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