LCOV - code coverage report
Current view: top level - port - cpl_swift.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 237 290 81.7 %
Date: 2026-09-09 22:24:20 Functions: 18 19 94.7 %

          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

Generated by: LCOV version 1.14