Line data Source code
1 : /**********************************************************************
2 : * Project: CPL - Common Portability Library
3 : * Purpose: OpenStack Swift Object Storage routines
4 : * Author: Even Rouault <even.rouault at spatialys.com>
5 : *
6 : **********************************************************************
7 : * Copyright (c) 2018, Even Rouault <even.rouault at spatialys.com>
8 : *
9 : * Permission is hereby granted, free of charge, to any person obtaining a
10 : * copy of this software and associated documentation files (the "Software"),
11 : * to deal in the Software without restriction, including without limitation
12 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 : * and/or sell copies of the Software, and to permit persons to whom the
14 : * Software is furnished to do so, subject to the following conditions:
15 : *
16 : * The above copyright notice and this permission notice shall be included
17 : * in all copies or substantial portions of the Software.
18 : *
19 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 : * DEALINSwift IN THE SOFTWARE.
26 : ****************************************************************************/
27 :
28 : #include "cpl_swift.h"
29 : #include "cpl_vsi_error.h"
30 : #include "cpl_http.h"
31 : #include "cpl_multiproc.h"
32 : #include "cpl_json.h"
33 :
34 : // HOWTO setup a Docker-based SWIFT server:
35 : // https://github.com/MorrisJobke/docker-swift-onlyone
36 :
37 : //! @cond Doxygen_Suppress
38 :
39 : #ifdef HAVE_CURL
40 :
41 : static CPLMutex *g_hMutex = nullptr;
42 : static std::string g_osLastAuthURL;
43 : static std::string g_osLastUser;
44 : static std::string g_osLastKey;
45 : static std::string g_osLastStorageURL;
46 : static std::string g_osLastAuthToken;
47 :
48 : /************************************************************************/
49 : /* GetSwiftHeaders() */
50 : /************************************************************************/
51 :
52 41 : static struct curl_slist *GetSwiftHeaders(const std::string &osAuthToken)
53 : {
54 41 : struct curl_slist *headers = nullptr;
55 41 : headers = curl_slist_append(headers, "Accept: application/json");
56 41 : headers = curl_slist_append(
57 : headers, CPLSPrintf("x-auth-token: %s", osAuthToken.c_str()));
58 41 : return headers;
59 : }
60 :
61 : /************************************************************************/
62 : /* VSISwiftHandleHelper() */
63 : /************************************************************************/
64 68 : VSISwiftHandleHelper::VSISwiftHandleHelper(const std::string &osStorageURL,
65 : const std::string &osAuthToken,
66 : const std::string &osBucket,
67 68 : const std::string &osObjectKey)
68 : : m_osURL(BuildURL(osStorageURL, osBucket, osObjectKey)),
69 : m_osStorageURL(osStorageURL), m_osAuthToken(osAuthToken),
70 68 : m_osBucket(osBucket), m_osObjectKey(osObjectKey)
71 : {
72 68 : }
73 :
74 : /************************************************************************/
75 : /* ~VSISwiftHandleHelper() */
76 : /************************************************************************/
77 :
78 136 : VSISwiftHandleHelper::~VSISwiftHandleHelper()
79 : {
80 136 : }
81 :
82 : /************************************************************************/
83 : /* GetConfiguration() */
84 : /************************************************************************/
85 :
86 71 : bool VSISwiftHandleHelper::GetConfiguration(const std::string &osPathForOption,
87 : std::string &osStorageURL,
88 : std::string &osAuthToken)
89 : {
90 : osStorageURL = VSIGetPathSpecificOption(osPathForOption.c_str(),
91 71 : "SWIFT_STORAGE_URL", "");
92 71 : if (!osStorageURL.empty())
93 : {
94 : osAuthToken = VSIGetPathSpecificOption(osPathForOption.c_str(),
95 65 : "SWIFT_AUTH_TOKEN", "");
96 65 : if (osAuthToken.empty())
97 : {
98 1 : const char *pszMsg = "Missing SWIFT_AUTH_TOKEN";
99 1 : CPLDebug("SWIFT", "%s", pszMsg);
100 1 : VSIError(VSIE_AWSInvalidCredentials, "%s", pszMsg);
101 1 : return false;
102 : }
103 64 : return true;
104 : }
105 :
106 : const std::string osAuthVersion = VSIGetPathSpecificOption(
107 12 : osPathForOption.c_str(), "OS_IDENTITY_API_VERSION", "");
108 6 : if (osAuthVersion == "3")
109 : {
110 : const std::string osAuthType = VSIGetPathSpecificOption(
111 2 : osPathForOption.c_str(), "OS_AUTH_TYPE", "");
112 2 : if (!CheckCredentialsV3(osPathForOption, osAuthType))
113 0 : return false;
114 2 : if (osAuthType == "v3applicationcredential")
115 : {
116 1 : if (GetCached(osPathForOption, "OS_AUTH_URL",
117 : "OS_APPLICATION_CREDENTIAL_ID",
118 : "OS_APPLICATION_CREDENTIAL_SECRET", osStorageURL,
119 : osAuthToken))
120 0 : return true;
121 : }
122 : else
123 : {
124 1 : if (GetCached(osPathForOption, "OS_AUTH_URL", "OS_USERNAME",
125 : "OS_PASSWORD", osStorageURL, osAuthToken))
126 0 : return true;
127 : }
128 2 : if (AuthV3(osPathForOption, osAuthType, osStorageURL, osAuthToken))
129 2 : return true;
130 : }
131 : else
132 : {
133 : const std::string osAuthV1URL = VSIGetPathSpecificOption(
134 4 : osPathForOption.c_str(), "SWIFT_AUTH_V1_URL", "");
135 4 : if (!osAuthV1URL.empty())
136 : {
137 2 : if (!CheckCredentialsV1(osPathForOption))
138 0 : return false;
139 2 : if (GetCached(osPathForOption, "SWIFT_AUTH_V1_URL", "SWIFT_USER",
140 : "SWIFT_KEY", osStorageURL, osAuthToken))
141 1 : return true;
142 1 : if (AuthV1(osPathForOption, osStorageURL, osAuthToken))
143 1 : return true;
144 : }
145 : }
146 :
147 2 : const char *pszMsg = "Missing SWIFT_STORAGE_URL+SWIFT_AUTH_TOKEN or "
148 : "appropriate authentication options";
149 2 : CPLDebug("SWIFT", "%s", pszMsg);
150 2 : VSIError(VSIE_AWSInvalidCredentials, "%s", pszMsg);
151 :
152 2 : return false;
153 : }
154 :
155 : /************************************************************************/
156 : /* AuthV1() */
157 : /************************************************************************/
158 :
159 1 : bool VSISwiftHandleHelper::AuthV1(const std::string &osPathForOption,
160 : std::string &osStorageURL,
161 : std::string &osAuthToken)
162 : {
163 : std::string osAuthURL = VSIGetPathSpecificOption(osPathForOption.c_str(),
164 2 : "SWIFT_AUTH_V1_URL", "");
165 : std::string osUser =
166 2 : VSIGetPathSpecificOption(osPathForOption.c_str(), "SWIFT_USER", "");
167 : std::string osKey =
168 2 : VSIGetPathSpecificOption(osPathForOption.c_str(), "SWIFT_KEY", "");
169 : char **papszHeaders =
170 1 : CSLSetNameValue(nullptr, "HEADERS",
171 : CPLSPrintf("X-Auth-User: %s\r\n"
172 : "X-Auth-Key: %s",
173 : osUser.c_str(), osKey.c_str()));
174 1 : CPLHTTPResult *psResult = CPLHTTPFetch(osAuthURL.c_str(), papszHeaders);
175 1 : CSLDestroy(papszHeaders);
176 1 : if (psResult == nullptr)
177 0 : return false;
178 : osStorageURL =
179 1 : CSLFetchNameValueDef(psResult->papszHeaders, "X-Storage-Url", "");
180 : osAuthToken =
181 1 : CSLFetchNameValueDef(psResult->papszHeaders, "X-Auth-Token", "");
182 : std::string osErrorMsg =
183 1 : psResult->pabyData ? reinterpret_cast<const char *>(psResult->pabyData)
184 2 : : "";
185 1 : CPLHTTPDestroyResult(psResult);
186 1 : if (osStorageURL.empty() || osAuthToken.empty())
187 : {
188 0 : CPLDebug("SWIFT", "Authentication failed: %s", osErrorMsg.c_str());
189 0 : VSIError(VSIE_AWSInvalidCredentials, "Authentication failed: %s",
190 : osErrorMsg.c_str());
191 0 : return false;
192 : }
193 :
194 : // Cache credentials
195 : {
196 2 : CPLMutexHolder oHolder(&g_hMutex);
197 1 : g_osLastAuthURL = std::move(osAuthURL);
198 1 : g_osLastUser = std::move(osUser);
199 1 : g_osLastKey = std::move(osKey);
200 1 : g_osLastStorageURL = osStorageURL;
201 1 : g_osLastAuthToken = osAuthToken;
202 : }
203 :
204 1 : return true;
205 : }
206 :
207 : /************************************************************************/
208 : /* CreateAuthV3RequestObject() */
209 : /************************************************************************/
210 :
211 2 : CPLJSONObject VSISwiftHandleHelper::CreateAuthV3RequestObject(
212 : const std::string &osPathForOption, const std::string &osAuthType)
213 : {
214 4 : CPLJSONArray methods;
215 4 : CPLJSONObject identity;
216 4 : CPLJSONObject scope;
217 2 : if (osAuthType == "v3applicationcredential")
218 : {
219 : std::string osApplicationCredentialID = VSIGetPathSpecificOption(
220 2 : osPathForOption.c_str(), "OS_APPLICATION_CREDENTIAL_ID", "");
221 : std::string osApplicationCredentialSecret = VSIGetPathSpecificOption(
222 2 : osPathForOption.c_str(), "OS_APPLICATION_CREDENTIAL_SECRET", "");
223 1 : CPLJSONObject applicationCredential;
224 1 : applicationCredential.Add("id", osApplicationCredentialID);
225 1 : applicationCredential.Add("secret", osApplicationCredentialSecret);
226 1 : methods.Add("application_credential");
227 1 : identity.Add("application_credential", applicationCredential);
228 : // Application credentials cannot request a scope.
229 : }
230 : else
231 : {
232 : std::string osUser = VSIGetPathSpecificOption(osPathForOption.c_str(),
233 2 : "OS_USERNAME", "");
234 : std::string osPassword = VSIGetPathSpecificOption(
235 2 : osPathForOption.c_str(), "OS_PASSWORD", "");
236 :
237 2 : CPLJSONObject user;
238 1 : user.Add("name", osUser);
239 1 : user.Add("password", osPassword);
240 :
241 : std::string osUserDomainName = VSIGetPathSpecificOption(
242 2 : osPathForOption.c_str(), "OS_USER_DOMAIN_NAME", "");
243 1 : if (!osUserDomainName.empty())
244 : {
245 1 : CPLJSONObject userDomain;
246 1 : userDomain.Add("name", osUserDomainName);
247 1 : user.Add("domain", userDomain);
248 : }
249 :
250 2 : CPLJSONObject password;
251 1 : password.Add("user", user);
252 1 : methods.Add("password");
253 1 : identity.Add("password", password);
254 :
255 : // Request a scope if one is specified in the configuration
256 : std::string osProjectName = VSIGetPathSpecificOption(
257 2 : osPathForOption.c_str(), "OS_PROJECT_NAME", "");
258 1 : if (!osProjectName.empty())
259 : {
260 2 : CPLJSONObject project;
261 1 : project.Add("name", osProjectName);
262 :
263 : std::string osProjectDomainName = VSIGetPathSpecificOption(
264 1 : osPathForOption.c_str(), "OS_PROJECT_DOMAIN_NAME", "");
265 1 : if (!osProjectDomainName.empty())
266 : {
267 1 : CPLJSONObject projectDomain;
268 1 : projectDomain.Add("name", osProjectDomainName);
269 1 : project.Add("domain", projectDomain);
270 : }
271 :
272 1 : scope.Add("project", project);
273 : }
274 : }
275 :
276 2 : identity.Add("methods", methods);
277 :
278 4 : CPLJSONObject auth;
279 2 : auth.Add("identity", identity);
280 2 : if (!scope.GetChildren().empty())
281 1 : auth.Add("scope", scope);
282 :
283 2 : CPLJSONObject obj;
284 2 : obj.Add("auth", auth);
285 4 : return obj;
286 : }
287 :
288 : /************************************************************************/
289 : /* GetAuthV3StorageURL() */
290 : /************************************************************************/
291 :
292 2 : bool VSISwiftHandleHelper::GetAuthV3StorageURL(
293 : const std::string &osPathForOption, const CPLHTTPResult *psResult,
294 : std::string &storageURL)
295 : {
296 2 : if (psResult->pabyData == nullptr)
297 0 : return false;
298 :
299 4 : CPLJSONDocument resultJson;
300 2 : resultJson.LoadMemory(psResult->pabyData);
301 4 : CPLJSONObject result(resultJson.GetRoot());
302 :
303 6 : CPLJSONObject token(result.GetObj("token"));
304 2 : if (!token.IsValid())
305 0 : return false;
306 :
307 6 : CPLJSONArray catalog(token.GetArray("catalog"));
308 2 : if (!catalog.IsValid())
309 0 : return false;
310 :
311 4 : CPLJSONArray endpoints;
312 2 : for (int i = 0; i < catalog.Size(); ++i)
313 : {
314 2 : CPLJSONObject item(catalog[i]);
315 2 : if (item.GetString("type") == "object-store")
316 : {
317 2 : endpoints = item.GetArray("endpoints");
318 2 : break;
319 : }
320 : }
321 :
322 2 : if (endpoints.Size() == 0)
323 0 : return false;
324 :
325 : std::string osRegionName =
326 4 : VSIGetPathSpecificOption(osPathForOption.c_str(), "OS_REGION_NAME", "");
327 2 : if (osRegionName.empty())
328 : {
329 0 : for (int i = 0; i < endpoints.Size(); ++i)
330 : {
331 0 : CPLJSONObject endpoint(endpoints[i]);
332 : std::string interfaceType =
333 0 : endpoint.GetString("interface", ""); // internal, admin, public
334 0 : if (interfaceType.empty() || interfaceType == "public")
335 : {
336 0 : storageURL = endpoint.GetString("url");
337 0 : return true;
338 : }
339 : }
340 0 : return false;
341 : }
342 :
343 6 : for (int i = 0; i < endpoints.Size(); ++i)
344 : {
345 6 : CPLJSONObject endpoint(endpoints[i]);
346 6 : if (endpoint.GetString("region") == osRegionName)
347 : {
348 : std::string interfaceType =
349 12 : endpoint.GetString("interface", ""); // internal, admin, public
350 6 : if (interfaceType.empty() || interfaceType == "public")
351 : {
352 2 : storageURL = endpoint.GetString("url");
353 2 : CPLDebug("SWIFT", "Storage URL '%s' for region '%s'",
354 : storageURL.c_str(), osRegionName.c_str());
355 2 : return true;
356 : }
357 : }
358 : }
359 :
360 0 : return false;
361 : }
362 :
363 : /************************************************************************/
364 : /* AuthV3() */
365 : /************************************************************************/
366 :
367 2 : bool VSISwiftHandleHelper::AuthV3(const std::string &osPathForOption,
368 : const std::string &osAuthType,
369 : std::string &osStorageURL,
370 : std::string &osAuthToken)
371 : {
372 4 : std::string osAuthID;
373 4 : std::string osAuthKey;
374 2 : if (osAuthType.empty() || osAuthType == "password")
375 : {
376 : osAuthID = VSIGetPathSpecificOption(osPathForOption.c_str(),
377 1 : "OS_USERNAME", "");
378 : osAuthKey = VSIGetPathSpecificOption(osPathForOption.c_str(),
379 1 : "OS_PASSWORD", "");
380 : }
381 1 : else if (osAuthType == "v3applicationcredential")
382 : {
383 : osAuthID = VSIGetPathSpecificOption(osPathForOption.c_str(),
384 1 : "OS_APPLICATION_CREDENTIAL_ID", "");
385 : osAuthKey = VSIGetPathSpecificOption(
386 1 : osPathForOption.c_str(), "OS_APPLICATION_CREDENTIAL_SECRET", "");
387 : }
388 : else
389 : {
390 0 : CPLDebug("SWIFT", "Unsupported OS SWIFT Auth Type: %s",
391 : osAuthType.c_str());
392 0 : VSIError(VSIE_AWSInvalidCredentials, "%s", osAuthType.c_str());
393 0 : return false;
394 : }
395 : CPLJSONObject postObject(
396 4 : CreateAuthV3RequestObject(osPathForOption, osAuthType));
397 4 : std::string post = postObject.Format(CPLJSONObject::PrettyFormat::Plain);
398 :
399 : // coverity[tainted_data]
400 : std::string osAuthURL =
401 4 : VSIGetPathSpecificOption(osPathForOption.c_str(), "OS_AUTH_URL", "");
402 4 : std::string url = osAuthURL;
403 2 : if (!url.empty() && url.back() != '/')
404 2 : url += '/';
405 2 : url += "auth/tokens";
406 :
407 2 : char **papszOptions = CSLSetNameValue(nullptr, "POSTFIELDS", post.data());
408 2 : papszOptions = CSLSetNameValue(papszOptions, "HEADERS",
409 : "Content-Type: application/json");
410 2 : CPLHTTPResult *psResult = CPLHTTPFetchEx(url.c_str(), papszOptions, nullptr,
411 : nullptr, nullptr, nullptr);
412 2 : CSLDestroy(papszOptions);
413 :
414 2 : if (psResult == nullptr)
415 0 : return false;
416 :
417 : osAuthToken =
418 2 : CSLFetchNameValueDef(psResult->papszHeaders, "X-Subject-Token", "");
419 :
420 2 : if (!GetAuthV3StorageURL(osPathForOption, psResult, osStorageURL))
421 : {
422 0 : CPLHTTPDestroyResult(psResult);
423 0 : return false;
424 : }
425 :
426 2 : if (osStorageURL.empty() || osAuthToken.empty())
427 : {
428 : std::string osErrorMsg =
429 0 : reinterpret_cast<const char *>(psResult->pabyData);
430 0 : CPLDebug("SWIFT", "Authentication failed: %s", osErrorMsg.c_str());
431 0 : VSIError(VSIE_AWSInvalidCredentials, "Authentication failed: %s",
432 : osErrorMsg.c_str());
433 0 : CPLHTTPDestroyResult(psResult);
434 0 : return false;
435 : }
436 :
437 2 : CPLHTTPDestroyResult(psResult);
438 :
439 : // Cache credentials
440 : {
441 4 : CPLMutexHolder oHolder(&g_hMutex);
442 2 : g_osLastAuthURL = std::move(osAuthURL);
443 2 : g_osLastUser = std::move(osAuthID);
444 2 : g_osLastKey = std::move(osAuthKey);
445 2 : g_osLastStorageURL = osStorageURL;
446 2 : g_osLastAuthToken = osAuthToken;
447 : }
448 2 : return true;
449 : }
450 :
451 : /************************************************************************/
452 : /* Authenticate() */
453 : /************************************************************************/
454 :
455 0 : bool VSISwiftHandleHelper::Authenticate(const std::string &osPathForOption)
456 : {
457 : std::string osAuthV1URL = VSIGetPathSpecificOption(osPathForOption.c_str(),
458 0 : "SWIFT_AUTH_V1_URL", "");
459 0 : if (!osAuthV1URL.empty() &&
460 0 : AuthV1(osPathForOption, m_osStorageURL, m_osAuthToken))
461 : {
462 0 : RebuildURL();
463 0 : return true;
464 : }
465 :
466 : const std::string osAuthVersion = VSIGetPathSpecificOption(
467 0 : osPathForOption.c_str(), "OS_IDENTITY_API_VERSION", "");
468 : const std::string osAuthType =
469 0 : VSIGetPathSpecificOption(osPathForOption.c_str(), "OS_AUTH_TYPE", "");
470 0 : if (osAuthVersion == "3" &&
471 0 : AuthV3(osPathForOption, osAuthType, m_osStorageURL, m_osAuthToken))
472 : {
473 0 : RebuildURL();
474 0 : return true;
475 : }
476 :
477 0 : return false;
478 : }
479 :
480 : /************************************************************************/
481 : /* CheckCredentialsV1() */
482 : /************************************************************************/
483 :
484 2 : bool VSISwiftHandleHelper::CheckCredentialsV1(
485 : const std::string &osPathForOption)
486 : {
487 2 : const char *pszMissingKey = nullptr;
488 : std::string osUser =
489 4 : VSIGetPathSpecificOption(osPathForOption.c_str(), "SWIFT_USER", "");
490 : std::string osKey =
491 4 : VSIGetPathSpecificOption(osPathForOption.c_str(), "SWIFT_KEY", "");
492 2 : if (osUser.empty())
493 : {
494 0 : pszMissingKey = "SWIFT_USER";
495 : }
496 2 : else if (osKey.empty())
497 : {
498 0 : pszMissingKey = "SWIFT_KEY";
499 : }
500 :
501 2 : if (pszMissingKey)
502 : {
503 0 : CPLDebug("SWIFT", "Missing %s configuration option", pszMissingKey);
504 0 : VSIError(VSIE_AWSInvalidCredentials, "%s", pszMissingKey);
505 0 : return false;
506 : }
507 :
508 2 : return true;
509 : }
510 :
511 : /************************************************************************/
512 : /* CheckCredentialsV3() */
513 : /************************************************************************/
514 :
515 2 : bool VSISwiftHandleHelper::CheckCredentialsV3(
516 : const std::string &osPathForOption, const std::string &osAuthType)
517 : {
518 2 : const char *papszMandatoryOptionKeys[3] = {
519 : "OS_AUTH_URL",
520 : "",
521 : "",
522 : };
523 2 : if (osAuthType.empty() || osAuthType == "password")
524 : {
525 1 : papszMandatoryOptionKeys[1] = "OS_USERNAME";
526 1 : papszMandatoryOptionKeys[2] = "OS_PASSWORD";
527 : }
528 1 : else if (osAuthType == "v3applicationcredential")
529 : {
530 1 : papszMandatoryOptionKeys[1] = "OS_APPLICATION_CREDENTIAL_ID";
531 1 : papszMandatoryOptionKeys[2] = "OS_APPLICATION_CREDENTIAL_SECRET";
532 : }
533 : else
534 : {
535 0 : CPLDebug("SWIFT", "Unsupported OS SWIFT Auth Type: %s",
536 : osAuthType.c_str());
537 0 : VSIError(VSIE_AWSInvalidCredentials, "%s", osAuthType.c_str());
538 0 : return false;
539 : }
540 8 : for (auto const *pszOptionKey : papszMandatoryOptionKeys)
541 : {
542 : std::string option =
543 6 : VSIGetPathSpecificOption(osPathForOption.c_str(), pszOptionKey, "");
544 6 : if (option.empty())
545 : {
546 0 : CPLDebug("SWIFT", "Missing %s configuration option", pszOptionKey);
547 0 : VSIError(VSIE_AWSInvalidCredentials, "%s", pszOptionKey);
548 0 : return false;
549 : }
550 : }
551 2 : return true;
552 : }
553 :
554 : /************************************************************************/
555 : /* GetCached() */
556 : /************************************************************************/
557 :
558 4 : bool VSISwiftHandleHelper::GetCached(const std::string &osPathForOption,
559 : const char *pszURLKey,
560 : const char *pszUserKey,
561 : const char *pszPasswordKey,
562 : std::string &osStorageURL,
563 : std::string &osAuthToken)
564 : {
565 : std::string osAuthURL =
566 8 : VSIGetPathSpecificOption(osPathForOption.c_str(), pszURLKey, "");
567 : std::string osUser =
568 8 : VSIGetPathSpecificOption(osPathForOption.c_str(), pszUserKey, "");
569 : std::string osKey =
570 8 : VSIGetPathSpecificOption(osPathForOption.c_str(), pszPasswordKey, "");
571 :
572 8 : CPLMutexHolder oHolder(&g_hMutex);
573 : // Re-use cached credentials if available
574 : // coverity[tainted_data]
575 5 : if (osAuthURL == g_osLastAuthURL && osUser == g_osLastUser &&
576 1 : osKey == g_osLastKey)
577 : {
578 1 : osStorageURL = g_osLastStorageURL;
579 1 : osAuthToken = g_osLastAuthToken;
580 1 : return true;
581 : }
582 3 : return false;
583 : }
584 :
585 : /************************************************************************/
586 : /* BuildFromURI() */
587 : /************************************************************************/
588 :
589 : VSISwiftHandleHelper *
590 71 : VSISwiftHandleHelper::BuildFromURI(const char *pszURI,
591 : const char * /*pszFSPrefix*/)
592 : {
593 142 : std::string osPathForOption("/vsiswift/");
594 71 : osPathForOption += pszURI;
595 :
596 142 : std::string osStorageURL;
597 142 : std::string osAuthToken;
598 :
599 71 : if (!GetConfiguration(osPathForOption, osStorageURL, osAuthToken))
600 : {
601 3 : return nullptr;
602 : }
603 :
604 : // pszURI == bucket/object
605 136 : const std::string osBucketObject(pszURI);
606 136 : std::string osBucket(osBucketObject);
607 68 : std::string osObjectKey;
608 68 : size_t nSlashPos = osBucketObject.find('/');
609 68 : if (nSlashPos != std::string::npos)
610 : {
611 37 : osBucket = osBucketObject.substr(0, nSlashPos);
612 37 : osObjectKey = osBucketObject.substr(nSlashPos + 1);
613 : }
614 :
615 : return new VSISwiftHandleHelper(osStorageURL, osAuthToken, osBucket,
616 68 : osObjectKey);
617 : }
618 :
619 : /************************************************************************/
620 : /* BuildURL() */
621 : /************************************************************************/
622 :
623 120 : std::string VSISwiftHandleHelper::BuildURL(const std::string &osStorageURL,
624 : const std::string &osBucket,
625 : const std::string &osObjectKey)
626 : {
627 120 : std::string osURL = osStorageURL;
628 120 : if (!osBucket.empty())
629 111 : osURL += "/" + CPLAWSURLEncode(osBucket, false);
630 120 : if (!osObjectKey.empty())
631 42 : osURL += "/" + CPLAWSURLEncode(osObjectKey, false);
632 120 : return osURL;
633 : }
634 :
635 : /************************************************************************/
636 : /* RebuildURL() */
637 : /************************************************************************/
638 :
639 52 : void VSISwiftHandleHelper::RebuildURL()
640 : {
641 52 : m_osURL = BuildURL(m_osStorageURL, m_osBucket, m_osObjectKey);
642 52 : m_osURL += GetQueryString(false);
643 52 : }
644 :
645 : /************************************************************************/
646 : /* GetCurlHeaders() */
647 : /************************************************************************/
648 :
649 41 : struct curl_slist *VSISwiftHandleHelper::GetCurlHeaders(
650 : const std::string &, const struct curl_slist *, const void *, size_t) const
651 : {
652 41 : return GetSwiftHeaders(m_osAuthToken);
653 : }
654 :
655 : /************************************************************************/
656 : /* CleanMutex() */
657 : /************************************************************************/
658 :
659 933 : void VSISwiftHandleHelper::CleanMutex()
660 : {
661 933 : if (g_hMutex != nullptr)
662 933 : CPLDestroyMutex(g_hMutex);
663 933 : g_hMutex = nullptr;
664 933 : }
665 :
666 : /************************************************************************/
667 : /* ClearCache() */
668 : /************************************************************************/
669 :
670 1232 : void VSISwiftHandleHelper::ClearCache()
671 : {
672 2464 : CPLMutexHolder oHolder(&g_hMutex);
673 1232 : g_osLastAuthURL.clear();
674 1232 : g_osLastUser.clear();
675 1232 : g_osLastKey.clear();
676 1232 : g_osLastStorageURL.clear();
677 1232 : g_osLastAuthToken.clear();
678 1232 : }
679 :
680 : #endif
681 :
682 : //! @endcond
|