diff options
author | nalpp <nalpp@yandex-team.ru> | 2022-02-10 16:46:45 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:46:45 +0300 |
commit | 87f3eb38999df2d3c1cb77f8ffb9c52ec9c516fb (patch) | |
tree | f4ab0734eecf35b22f21952d1aa15496f267a6a3 /contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source | |
parent | 198698b9c1e18958addc9682fbfba4576d604757 (diff) | |
download | ydb-87f3eb38999df2d3c1cb77f8ffb9c52ec9c516fb.tar.gz |
Restoring authorship annotation for <nalpp@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source')
80 files changed, 17131 insertions, 17131 deletions
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/AmazonSerializableWebServiceRequest.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/AmazonSerializableWebServiceRequest.cpp index 0c401b01b2..dc0f38b4dc 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/AmazonSerializableWebServiceRequest.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/AmazonSerializableWebServiceRequest.cpp @@ -2,23 +2,23 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/AmazonSerializableWebServiceRequest.h> -#include <aws/core/utils/memory/stl/AWSStringStream.h> - -using namespace Aws; - -std::shared_ptr<Aws::IOStream> AmazonSerializableWebServiceRequest::GetBody() const -{ - Aws::String&& payload = SerializePayload(); - std::shared_ptr<Aws::IOStream> payloadBody; - - if (!payload.empty()) - { - payloadBody = Aws::MakeShared<Aws::StringStream>("AmazonSerializableWebServiceRequest"); - *payloadBody << payload; - } - - return payloadBody; -} - + +#include <aws/core/AmazonSerializableWebServiceRequest.h> +#include <aws/core/utils/memory/stl/AWSStringStream.h> + +using namespace Aws; + +std::shared_ptr<Aws::IOStream> AmazonSerializableWebServiceRequest::GetBody() const +{ + Aws::String&& payload = SerializePayload(); + std::shared_ptr<Aws::IOStream> payloadBody; + + if (!payload.empty()) + { + payloadBody = Aws::MakeShared<Aws::StringStream>("AmazonSerializableWebServiceRequest"); + *payloadBody << payload; + } + + return payloadBody; +} + diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/AmazonStreamingWebServiceRequest.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/AmazonStreamingWebServiceRequest.cpp index 92e61c7ad4..fae0ea1c11 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/AmazonStreamingWebServiceRequest.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/AmazonStreamingWebServiceRequest.cpp @@ -2,11 +2,11 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/AmazonStreamingWebServiceRequest.h> -#include <aws/core/utils/memory/stl/AWSStringStream.h> - -using namespace Aws; - -AmazonStreamingWebServiceRequest::~AmazonStreamingWebServiceRequest() {} - + +#include <aws/core/AmazonStreamingWebServiceRequest.h> +#include <aws/core/utils/memory/stl/AWSStringStream.h> + +using namespace Aws; + +AmazonStreamingWebServiceRequest::~AmazonStreamingWebServiceRequest() {} + diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/AmazonWebServiceRequest.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/AmazonWebServiceRequest.cpp index a6b0406683..a0007c6d23 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/AmazonWebServiceRequest.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/AmazonWebServiceRequest.cpp @@ -2,19 +2,19 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/AmazonWebServiceRequest.h> -#include <aws/core/utils/memory/stl/AWSStringStream.h> - -using namespace Aws; - -AmazonWebServiceRequest::AmazonWebServiceRequest() : - m_responseStreamFactory(Aws::Utils::Stream::DefaultResponseStreamFactoryMethod), - m_onDataReceived(nullptr), + +#include <aws/core/AmazonWebServiceRequest.h> +#include <aws/core/utils/memory/stl/AWSStringStream.h> + +using namespace Aws; + +AmazonWebServiceRequest::AmazonWebServiceRequest() : + m_responseStreamFactory(Aws::Utils::Stream::DefaultResponseStreamFactoryMethod), + m_onDataReceived(nullptr), m_onDataSent(nullptr), m_continueRequest(nullptr), m_onRequestSigned(nullptr), m_requestRetryHandler(nullptr) -{ -} - +{ +} + diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Aws.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Aws.cpp index 1eaa477fca..16099d7123 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Aws.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Aws.cpp @@ -2,133 +2,133 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ -#include <aws/core/Version.h> -#include <aws/core/utils/logging/LogMacros.h> -#include <aws/core/Aws.h> +#include <aws/core/Version.h> +#include <aws/core/utils/logging/LogMacros.h> +#include <aws/core/Aws.h> #include <aws/core/client/CoreErrors.h> -#include <aws/core/utils/logging/AWSLogging.h> -#include <aws/core/utils/logging/DefaultLogSystem.h> -#include <aws/core/Globals.h> -#include <aws/core/external/cjson/cJSON.h> -#include <aws/core/monitoring/MonitoringManager.h> -#include <aws/core/net/Net.h> +#include <aws/core/utils/logging/AWSLogging.h> +#include <aws/core/utils/logging/DefaultLogSystem.h> +#include <aws/core/Globals.h> +#include <aws/core/external/cjson/cJSON.h> +#include <aws/core/monitoring/MonitoringManager.h> +#include <aws/core/net/Net.h> #include <aws/core/config/AWSProfileConfigLoader.h> #include <aws/core/internal/AWSHttpResourceClient.h> - -namespace Aws -{ - static const char* ALLOCATION_TAG = "Aws_Init_Cleanup"; - - void InitAPI(const SDKOptions &options) - { -#ifdef USE_AWS_MEMORY_MANAGEMENT - if(options.memoryManagementOptions.memoryManager) - { - Aws::Utils::Memory::InitializeAWSMemorySystem(*options.memoryManagementOptions.memoryManager); - } -#endif // USE_AWS_MEMORY_MANAGEMENT + +namespace Aws +{ + static const char* ALLOCATION_TAG = "Aws_Init_Cleanup"; + + void InitAPI(const SDKOptions &options) + { +#ifdef USE_AWS_MEMORY_MANAGEMENT + if(options.memoryManagementOptions.memoryManager) + { + Aws::Utils::Memory::InitializeAWSMemorySystem(*options.memoryManagementOptions.memoryManager); + } +#endif // USE_AWS_MEMORY_MANAGEMENT Aws::Client::CoreErrorsMapper::InitCoreErrorsMapper(); - if(options.loggingOptions.logLevel != Aws::Utils::Logging::LogLevel::Off) - { - if(options.loggingOptions.logger_create_fn) - { - Aws::Utils::Logging::InitializeAWSLogging(options.loggingOptions.logger_create_fn()); - } - else - { - Aws::Utils::Logging::InitializeAWSLogging( - Aws::MakeShared<Aws::Utils::Logging::DefaultLogSystem>(ALLOCATION_TAG, options.loggingOptions.logLevel, options.loggingOptions.defaultLogPrefix)); - } - // For users to better debugging in case multiple versions of SDK installed - AWS_LOGSTREAM_INFO(ALLOCATION_TAG, "Initiate AWS SDK for C++ with Version:" << Aws::String(Aws::Version::GetVersionString())); - } - + if(options.loggingOptions.logLevel != Aws::Utils::Logging::LogLevel::Off) + { + if(options.loggingOptions.logger_create_fn) + { + Aws::Utils::Logging::InitializeAWSLogging(options.loggingOptions.logger_create_fn()); + } + else + { + Aws::Utils::Logging::InitializeAWSLogging( + Aws::MakeShared<Aws::Utils::Logging::DefaultLogSystem>(ALLOCATION_TAG, options.loggingOptions.logLevel, options.loggingOptions.defaultLogPrefix)); + } + // For users to better debugging in case multiple versions of SDK installed + AWS_LOGSTREAM_INFO(ALLOCATION_TAG, "Initiate AWS SDK for C++ with Version:" << Aws::String(Aws::Version::GetVersionString())); + } + Aws::Config::InitConfigAndCredentialsCacheManager(); if (options.cryptoOptions.aes_CBCFactory_create_fn) - { - Aws::Utils::Crypto::SetAES_CBCFactory(options.cryptoOptions.aes_CBCFactory_create_fn()); - } - - if(options.cryptoOptions.aes_CTRFactory_create_fn) - { - Aws::Utils::Crypto::SetAES_CTRFactory(options.cryptoOptions.aes_CTRFactory_create_fn()); - } - - if(options.cryptoOptions.aes_GCMFactory_create_fn) - { - Aws::Utils::Crypto::SetAES_GCMFactory(options.cryptoOptions.aes_GCMFactory_create_fn()); - } - - if(options.cryptoOptions.md5Factory_create_fn) - { - Aws::Utils::Crypto::SetMD5Factory(options.cryptoOptions.md5Factory_create_fn()); - } - - if(options.cryptoOptions.sha256Factory_create_fn) - { - Aws::Utils::Crypto::SetSha256Factory(options.cryptoOptions.sha256Factory_create_fn()); - } - - if(options.cryptoOptions.sha256HMACFactory_create_fn) - { - Aws::Utils::Crypto::SetSha256HMACFactory(options.cryptoOptions.sha256HMACFactory_create_fn()); - } - - if (options.cryptoOptions.aes_KeyWrapFactory_create_fn) - { - Aws::Utils::Crypto::SetAES_KeyWrapFactory(options.cryptoOptions.aes_KeyWrapFactory_create_fn()); - } - - if(options.cryptoOptions.secureRandomFactory_create_fn) - { - Aws::Utils::Crypto::SetSecureRandomFactory(options.cryptoOptions.secureRandomFactory_create_fn()); - } - - Aws::Utils::Crypto::SetInitCleanupOpenSSLFlag(options.cryptoOptions.initAndCleanupOpenSSL); - Aws::Utils::Crypto::InitCrypto(); - - if(options.httpOptions.httpClientFactory_create_fn) - { - Aws::Http::SetHttpClientFactory(options.httpOptions.httpClientFactory_create_fn()); - } - - Aws::Http::SetInitCleanupCurlFlag(options.httpOptions.initAndCleanupCurl); - Aws::Http::SetInstallSigPipeHandlerFlag(options.httpOptions.installSigPipeHandler); - Aws::Http::InitHttp(); - Aws::InitializeEnumOverflowContainer(); - cJSON_Hooks hooks; - hooks.malloc_fn = [](size_t sz) { return Aws::Malloc("cJSON_Tag", sz); }; - hooks.free_fn = Aws::Free; - cJSON_InitHooks(&hooks); - Aws::Net::InitNetwork(); + { + Aws::Utils::Crypto::SetAES_CBCFactory(options.cryptoOptions.aes_CBCFactory_create_fn()); + } + + if(options.cryptoOptions.aes_CTRFactory_create_fn) + { + Aws::Utils::Crypto::SetAES_CTRFactory(options.cryptoOptions.aes_CTRFactory_create_fn()); + } + + if(options.cryptoOptions.aes_GCMFactory_create_fn) + { + Aws::Utils::Crypto::SetAES_GCMFactory(options.cryptoOptions.aes_GCMFactory_create_fn()); + } + + if(options.cryptoOptions.md5Factory_create_fn) + { + Aws::Utils::Crypto::SetMD5Factory(options.cryptoOptions.md5Factory_create_fn()); + } + + if(options.cryptoOptions.sha256Factory_create_fn) + { + Aws::Utils::Crypto::SetSha256Factory(options.cryptoOptions.sha256Factory_create_fn()); + } + + if(options.cryptoOptions.sha256HMACFactory_create_fn) + { + Aws::Utils::Crypto::SetSha256HMACFactory(options.cryptoOptions.sha256HMACFactory_create_fn()); + } + + if (options.cryptoOptions.aes_KeyWrapFactory_create_fn) + { + Aws::Utils::Crypto::SetAES_KeyWrapFactory(options.cryptoOptions.aes_KeyWrapFactory_create_fn()); + } + + if(options.cryptoOptions.secureRandomFactory_create_fn) + { + Aws::Utils::Crypto::SetSecureRandomFactory(options.cryptoOptions.secureRandomFactory_create_fn()); + } + + Aws::Utils::Crypto::SetInitCleanupOpenSSLFlag(options.cryptoOptions.initAndCleanupOpenSSL); + Aws::Utils::Crypto::InitCrypto(); + + if(options.httpOptions.httpClientFactory_create_fn) + { + Aws::Http::SetHttpClientFactory(options.httpOptions.httpClientFactory_create_fn()); + } + + Aws::Http::SetInitCleanupCurlFlag(options.httpOptions.initAndCleanupCurl); + Aws::Http::SetInstallSigPipeHandlerFlag(options.httpOptions.installSigPipeHandler); + Aws::Http::InitHttp(); + Aws::InitializeEnumOverflowContainer(); + cJSON_Hooks hooks; + hooks.malloc_fn = [](size_t sz) { return Aws::Malloc("cJSON_Tag", sz); }; + hooks.free_fn = Aws::Free; + cJSON_InitHooks(&hooks); + Aws::Net::InitNetwork(); Aws::Internal::InitEC2MetadataClient(); - Aws::Monitoring::InitMonitoring(options.monitoringOptions.customizedMonitoringFactory_create_fn); - } - - void ShutdownAPI(const SDKOptions& options) - { - Aws::Monitoring::CleanupMonitoring(); + Aws::Monitoring::InitMonitoring(options.monitoringOptions.customizedMonitoringFactory_create_fn); + } + + void ShutdownAPI(const SDKOptions& options) + { + Aws::Monitoring::CleanupMonitoring(); Aws::Internal::CleanupEC2MetadataClient(); - Aws::Net::CleanupNetwork(); - Aws::CleanupEnumOverflowContainer(); - Aws::Http::CleanupHttp(); - Aws::Utils::Crypto::CleanupCrypto(); - + Aws::Net::CleanupNetwork(); + Aws::CleanupEnumOverflowContainer(); + Aws::Http::CleanupHttp(); + Aws::Utils::Crypto::CleanupCrypto(); + Aws::Config::CleanupConfigAndCredentialsCacheManager(); - if(options.loggingOptions.logLevel != Aws::Utils::Logging::LogLevel::Off) - { - Aws::Utils::Logging::ShutdownAWSLogging(); - } + if(options.loggingOptions.logLevel != Aws::Utils::Logging::LogLevel::Off) + { + Aws::Utils::Logging::ShutdownAWSLogging(); + } Aws::Client::CoreErrorsMapper::CleanupCoreErrorsMapper(); - -#ifdef USE_AWS_MEMORY_MANAGEMENT - if(options.memoryManagementOptions.memoryManager) - { - Aws::Utils::Memory::ShutdownAWSMemorySystem(); - } -#endif // USE_AWS_MEMORY_MANAGEMENT - } -} + +#ifdef USE_AWS_MEMORY_MANAGEMENT + if(options.memoryManagementOptions.memoryManager) + { + Aws::Utils::Memory::ShutdownAWSMemorySystem(); + } +#endif // USE_AWS_MEMORY_MANAGEMENT + } +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Globals.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Globals.cpp index 55f2ee9220..6dc9ebd139 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Globals.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Globals.cpp @@ -2,27 +2,27 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ -#include <aws/core/Globals.h> -#include <aws/core/utils/EnumParseOverflowContainer.h> -#include <aws/core/utils/memory/AWSMemory.h> - -namespace Aws -{ - static const char TAG[] = "GlobalEnumOverflowContainer"; - static Utils::EnumParseOverflowContainer* g_enumOverflow; - - Utils::EnumParseOverflowContainer* GetEnumOverflowContainer() - { - return g_enumOverflow; - } - - void InitializeEnumOverflowContainer() - { - g_enumOverflow = Aws::New<Aws::Utils::EnumParseOverflowContainer>(TAG); - } - - void CleanupEnumOverflowContainer() - { - Aws::Delete(g_enumOverflow); - } -} +#include <aws/core/Globals.h> +#include <aws/core/utils/EnumParseOverflowContainer.h> +#include <aws/core/utils/memory/AWSMemory.h> + +namespace Aws +{ + static const char TAG[] = "GlobalEnumOverflowContainer"; + static Utils::EnumParseOverflowContainer* g_enumOverflow; + + Utils::EnumParseOverflowContainer* GetEnumOverflowContainer() + { + return g_enumOverflow; + } + + void InitializeEnumOverflowContainer() + { + g_enumOverflow = Aws::New<Aws::Utils::EnumParseOverflowContainer>(TAG); + } + + void CleanupEnumOverflowContainer() + { + Aws::Delete(g_enumOverflow); + } +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Version.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Version.cpp index 35291906b7..b379330738 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Version.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Version.cpp @@ -2,52 +2,52 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/Version.h> -#include <aws/core/VersionConfig.h> - -namespace Aws -{ -namespace Version -{ - const char* GetVersionString() - { - return AWS_SDK_VERSION_STRING; - } - - unsigned GetVersionMajor() - { - return AWS_SDK_VERSION_MAJOR; - } - - unsigned GetVersionMinor() - { - return AWS_SDK_VERSION_MINOR; - } - - unsigned GetVersionPatch() - { - return AWS_SDK_VERSION_PATCH; - } - - - const char* GetCompilerVersionString() - { -#define xstr(s) str(s) -#define str(s) #s -#if defined(_MSC_VER) - return "MSVC/" xstr(_MSC_VER); -#elif defined(__clang__) - return "Clang/" xstr(__clang_major__) "." xstr(__clang_minor__) "." xstr(__clang_patchlevel__); -#elif defined(__GNUC__) - return "GCC/" xstr(__GNUC__) "." xstr(__GNUC_MINOR__) "." xstr(__GNUC_PATCHLEVEL__); -#else - return "UnknownCompiler"; -#endif -#undef str -#undef xstr - } -} //namespace Version -} //namespace Aws - - + +#include <aws/core/Version.h> +#include <aws/core/VersionConfig.h> + +namespace Aws +{ +namespace Version +{ + const char* GetVersionString() + { + return AWS_SDK_VERSION_STRING; + } + + unsigned GetVersionMajor() + { + return AWS_SDK_VERSION_MAJOR; + } + + unsigned GetVersionMinor() + { + return AWS_SDK_VERSION_MINOR; + } + + unsigned GetVersionPatch() + { + return AWS_SDK_VERSION_PATCH; + } + + + const char* GetCompilerVersionString() + { +#define xstr(s) str(s) +#define str(s) #s +#if defined(_MSC_VER) + return "MSVC/" xstr(_MSC_VER); +#elif defined(__clang__) + return "Clang/" xstr(__clang_major__) "." xstr(__clang_minor__) "." xstr(__clang_patchlevel__); +#elif defined(__GNUC__) + return "GCC/" xstr(__GNUC__) "." xstr(__GNUC_MINOR__) "." xstr(__GNUC_PATCHLEVEL__); +#else + return "UnknownCompiler"; +#endif +#undef str +#undef xstr + } +} //namespace Version +} //namespace Aws + + diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSAuthSigner.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSAuthSigner.cpp index de4826fa5b..fa3f5583d5 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSAuthSigner.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSAuthSigner.cpp @@ -2,536 +2,536 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/auth/AWSAuthSigner.h> - -#include <aws/core/auth/AWSCredentialsProvider.h> -#include <aws/core/client/ClientConfiguration.h> -#include <aws/core/http/HttpRequest.h> -#include <aws/core/http/HttpResponse.h> -#include <aws/core/utils/DateTime.h> -#include <aws/core/utils/HashingUtils.h> -#include <aws/core/utils/Outcome.h> -#include <aws/core/utils/StringUtils.h> -#include <aws/core/utils/logging/LogMacros.h> -#include <aws/core/utils/memory/AWSMemory.h> -#include <aws/core/utils/crypto/Sha256.h> -#include <aws/core/utils/crypto/Sha256HMAC.h> + +#include <aws/core/auth/AWSAuthSigner.h> + +#include <aws/core/auth/AWSCredentialsProvider.h> +#include <aws/core/client/ClientConfiguration.h> +#include <aws/core/http/HttpRequest.h> +#include <aws/core/http/HttpResponse.h> +#include <aws/core/utils/DateTime.h> +#include <aws/core/utils/HashingUtils.h> +#include <aws/core/utils/Outcome.h> +#include <aws/core/utils/StringUtils.h> +#include <aws/core/utils/logging/LogMacros.h> +#include <aws/core/utils/memory/AWSMemory.h> +#include <aws/core/utils/crypto/Sha256.h> +#include <aws/core/utils/crypto/Sha256HMAC.h> #include <aws/core/utils/stream/PreallocatedStreamBuf.h> #include <aws/core/utils/event/EventMessage.h> #include <aws/core/utils/event/EventHeader.h> - -#include <cstdio> -#include <iomanip> -#include <math.h> + +#include <cstdio> +#include <iomanip> +#include <math.h> #include <cstring> - -using namespace Aws; -using namespace Aws::Client; -using namespace Aws::Auth; -using namespace Aws::Http; -using namespace Aws::Utils; -using namespace Aws::Utils::Logging; - -static const char* EQ = "="; -static const char* AWS_HMAC_SHA256 = "AWS4-HMAC-SHA256"; + +using namespace Aws; +using namespace Aws::Client; +using namespace Aws::Auth; +using namespace Aws::Http; +using namespace Aws::Utils; +using namespace Aws::Utils::Logging; + +static const char* EQ = "="; +static const char* AWS_HMAC_SHA256 = "AWS4-HMAC-SHA256"; static const char* EVENT_STREAM_CONTENT_SHA256 = "STREAMING-AWS4-HMAC-SHA256-EVENTS"; static const char* EVENT_STREAM_PAYLOAD = "AWS4-HMAC-SHA256-PAYLOAD"; -static const char* AWS4_REQUEST = "aws4_request"; -static const char* SIGNED_HEADERS = "SignedHeaders"; -static const char* CREDENTIAL = "Credential"; -static const char* NEWLINE = "\n"; -static const char* X_AMZ_SIGNED_HEADERS = "X-Amz-SignedHeaders"; -static const char* X_AMZ_ALGORITHM = "X-Amz-Algorithm"; -static const char* X_AMZ_CREDENTIAL = "X-Amz-Credential"; -static const char* UNSIGNED_PAYLOAD = "UNSIGNED-PAYLOAD"; -static const char* X_AMZ_SIGNATURE = "X-Amz-Signature"; +static const char* AWS4_REQUEST = "aws4_request"; +static const char* SIGNED_HEADERS = "SignedHeaders"; +static const char* CREDENTIAL = "Credential"; +static const char* NEWLINE = "\n"; +static const char* X_AMZ_SIGNED_HEADERS = "X-Amz-SignedHeaders"; +static const char* X_AMZ_ALGORITHM = "X-Amz-Algorithm"; +static const char* X_AMZ_CREDENTIAL = "X-Amz-Credential"; +static const char* UNSIGNED_PAYLOAD = "UNSIGNED-PAYLOAD"; +static const char* X_AMZ_SIGNATURE = "X-Amz-Signature"; static const char* X_AMZN_TRACE_ID = "x-amzn-trace-id"; static const char* X_AMZ_CONTENT_SHA256 = "x-amz-content-sha256"; static const char* USER_AGENT = "user-agent"; -static const char* SIGNING_KEY = "AWS4"; -static const char* SIMPLE_DATE_FORMAT_STR = "%Y%m%d"; -static const char* EMPTY_STRING_SHA256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"; - +static const char* SIGNING_KEY = "AWS4"; +static const char* SIMPLE_DATE_FORMAT_STR = "%Y%m%d"; +static const char* EMPTY_STRING_SHA256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"; + static const char v4LogTag[] = "AWSAuthV4Signer"; static const char v4StreamingLogTag[] = "AWSAuthEventStreamV4Signer"; - -namespace Aws -{ - namespace Auth - { + +namespace Aws +{ + namespace Auth + { const char SIGNATURE[] = "Signature"; - const char SIGV4_SIGNER[] = "SignatureV4"; + const char SIGV4_SIGNER[] = "SignatureV4"; const char EVENTSTREAM_SIGV4_SIGNER[] = "EventStreamSignatureV4"; const char EVENTSTREAM_SIGNATURE_HEADER[] = ":chunk-signature"; const char EVENTSTREAM_DATE_HEADER[] = ":date"; - const char NULL_SIGNER[] = "NullSigner"; - } -} - -static Aws::String CanonicalizeRequestSigningString(HttpRequest& request, bool urlEscapePath) -{ - request.CanonicalizeRequest(); - Aws::StringStream signingStringStream; - signingStringStream << HttpMethodMapper::GetNameForHttpMethod(request.GetMethod()); - - URI uriCpy = request.GetUri(); - // Many AWS services do not decode the URL before calculating SignatureV4 on their end. - // This results in the signature getting calculated with a double encoded URL. - // That means we have to double encode it here for the signature to match on the service side. - if(urlEscapePath) - { - // RFC3986 is how we encode the URL before sending it on the wire. - auto rfc3986EncodedPath = URI::URLEncodePathRFC3986(uriCpy.GetPath()); - uriCpy.SetPath(rfc3986EncodedPath); - // However, SignatureV4 uses this URL encoding scheme - signingStringStream << NEWLINE << uriCpy.GetURLEncodedPath() << NEWLINE; - } - else - { - // For the services that DO decode the URL first; we don't need to double encode it. - uriCpy.SetPath(uriCpy.GetURLEncodedPath()); - signingStringStream << NEWLINE << uriCpy.GetPath() << NEWLINE; - } - + const char NULL_SIGNER[] = "NullSigner"; + } +} + +static Aws::String CanonicalizeRequestSigningString(HttpRequest& request, bool urlEscapePath) +{ + request.CanonicalizeRequest(); + Aws::StringStream signingStringStream; + signingStringStream << HttpMethodMapper::GetNameForHttpMethod(request.GetMethod()); + + URI uriCpy = request.GetUri(); + // Many AWS services do not decode the URL before calculating SignatureV4 on their end. + // This results in the signature getting calculated with a double encoded URL. + // That means we have to double encode it here for the signature to match on the service side. + if(urlEscapePath) + { + // RFC3986 is how we encode the URL before sending it on the wire. + auto rfc3986EncodedPath = URI::URLEncodePathRFC3986(uriCpy.GetPath()); + uriCpy.SetPath(rfc3986EncodedPath); + // However, SignatureV4 uses this URL encoding scheme + signingStringStream << NEWLINE << uriCpy.GetURLEncodedPath() << NEWLINE; + } + else + { + // For the services that DO decode the URL first; we don't need to double encode it. + uriCpy.SetPath(uriCpy.GetURLEncodedPath()); + signingStringStream << NEWLINE << uriCpy.GetPath() << NEWLINE; + } + if (request.GetQueryString().find('=') != std::string::npos) - { - signingStringStream << request.GetQueryString().substr(1) << NEWLINE; - } - else if (request.GetQueryString().size() > 1) - { - signingStringStream << request.GetQueryString().substr(1) << "=" << NEWLINE; - } - else - { - signingStringStream << NEWLINE; - } - - return signingStringStream.str(); -} - -static Http::HeaderValueCollection CanonicalizeHeaders(Http::HeaderValueCollection&& headers) -{ - Http::HeaderValueCollection canonicalHeaders; - for (const auto& header : headers) - { - auto trimmedHeaderName = StringUtils::Trim(header.first.c_str()); - auto trimmedHeaderValue = StringUtils::Trim(header.second.c_str()); - - //multiline gets converted to line1,line2,etc... - auto headerMultiLine = StringUtils::SplitOnLine(trimmedHeaderValue); - Aws::String headerValue = headerMultiLine.size() == 0 ? "" : headerMultiLine[0]; - - if (headerMultiLine.size() > 1) - { - for(size_t i = 1; i < headerMultiLine.size(); ++i) - { - headerValue += ","; - headerValue += StringUtils::Trim(headerMultiLine[i].c_str()); - } - } - - //duplicate spaces need to be converted to one. - Aws::String::iterator new_end = - std::unique(headerValue.begin(), headerValue.end(), - [=](char lhs, char rhs) { return (lhs == rhs) && (lhs == ' '); } - ); - headerValue.erase(new_end, headerValue.end()); - + { + signingStringStream << request.GetQueryString().substr(1) << NEWLINE; + } + else if (request.GetQueryString().size() > 1) + { + signingStringStream << request.GetQueryString().substr(1) << "=" << NEWLINE; + } + else + { + signingStringStream << NEWLINE; + } + + return signingStringStream.str(); +} + +static Http::HeaderValueCollection CanonicalizeHeaders(Http::HeaderValueCollection&& headers) +{ + Http::HeaderValueCollection canonicalHeaders; + for (const auto& header : headers) + { + auto trimmedHeaderName = StringUtils::Trim(header.first.c_str()); + auto trimmedHeaderValue = StringUtils::Trim(header.second.c_str()); + + //multiline gets converted to line1,line2,etc... + auto headerMultiLine = StringUtils::SplitOnLine(trimmedHeaderValue); + Aws::String headerValue = headerMultiLine.size() == 0 ? "" : headerMultiLine[0]; + + if (headerMultiLine.size() > 1) + { + for(size_t i = 1; i < headerMultiLine.size(); ++i) + { + headerValue += ","; + headerValue += StringUtils::Trim(headerMultiLine[i].c_str()); + } + } + + //duplicate spaces need to be converted to one. + Aws::String::iterator new_end = + std::unique(headerValue.begin(), headerValue.end(), + [=](char lhs, char rhs) { return (lhs == rhs) && (lhs == ' '); } + ); + headerValue.erase(new_end, headerValue.end()); + canonicalHeaders[trimmedHeaderName] = headerValue; - } - - return canonicalHeaders; -} - -AWSAuthV4Signer::AWSAuthV4Signer(const std::shared_ptr<Auth::AWSCredentialsProvider>& credentialsProvider, - const char* serviceName, const Aws::String& region, PayloadSigningPolicy signingPolicy, bool urlEscapePath) : - m_includeSha256HashHeader(true), - m_credentialsProvider(credentialsProvider), - m_serviceName(serviceName), - m_region(region), - m_hash(Aws::MakeUnique<Aws::Utils::Crypto::Sha256>(v4LogTag)), - m_HMAC(Aws::MakeUnique<Aws::Utils::Crypto::Sha256HMAC>(v4LogTag)), + } + + return canonicalHeaders; +} + +AWSAuthV4Signer::AWSAuthV4Signer(const std::shared_ptr<Auth::AWSCredentialsProvider>& credentialsProvider, + const char* serviceName, const Aws::String& region, PayloadSigningPolicy signingPolicy, bool urlEscapePath) : + m_includeSha256HashHeader(true), + m_credentialsProvider(credentialsProvider), + m_serviceName(serviceName), + m_region(region), + m_hash(Aws::MakeUnique<Aws::Utils::Crypto::Sha256>(v4LogTag)), + m_HMAC(Aws::MakeUnique<Aws::Utils::Crypto::Sha256HMAC>(v4LogTag)), m_unsignedHeaders({USER_AGENT, X_AMZN_TRACE_ID}), - m_payloadSigningPolicy(signingPolicy), - m_urlEscapePath(urlEscapePath) -{ - //go ahead and warm up the signing cache. + m_payloadSigningPolicy(signingPolicy), + m_urlEscapePath(urlEscapePath) +{ + //go ahead and warm up the signing cache. ComputeHash(credentialsProvider->GetAWSCredentials().GetAWSSecretKey(), DateTime::CalculateGmtTimestampAsString(SIMPLE_DATE_FORMAT_STR), region, m_serviceName); -} - -AWSAuthV4Signer::~AWSAuthV4Signer() -{ +} + +AWSAuthV4Signer::~AWSAuthV4Signer() +{ // empty destructor in .cpp file to keep from needing the implementation of (AWSCredentialsProvider, Sha256, Sha256HMAC) in the header file -} - - -bool AWSAuthV4Signer::ShouldSignHeader(const Aws::String& header) const -{ - return m_unsignedHeaders.find(Aws::Utils::StringUtils::ToLower(header.c_str())) == m_unsignedHeaders.cend(); -} - +} + + +bool AWSAuthV4Signer::ShouldSignHeader(const Aws::String& header) const +{ + return m_unsignedHeaders.find(Aws::Utils::StringUtils::ToLower(header.c_str())) == m_unsignedHeaders.cend(); +} + bool AWSAuthV4Signer::SignRequest(Aws::Http::HttpRequest& request, const char* region, const char* serviceName, bool signBody) const -{ - AWSCredentials credentials = m_credentialsProvider->GetAWSCredentials(); - - //don't sign anonymous requests - if (credentials.GetAWSAccessKeyId().empty() || credentials.GetAWSSecretKey().empty()) - { - return true; - } - - if (!credentials.GetSessionToken().empty()) - { - request.SetAwsSessionToken(credentials.GetSessionToken()); - } - - Aws::String payloadHash(UNSIGNED_PAYLOAD); - switch(m_payloadSigningPolicy) - { - case PayloadSigningPolicy::Always: - signBody = true; - break; - case PayloadSigningPolicy::Never: - signBody = false; - break; - case PayloadSigningPolicy::RequestDependent: - // respect the request setting - default: - break; - } - - if(signBody || request.GetUri().GetScheme() != Http::Scheme::HTTPS) - { +{ + AWSCredentials credentials = m_credentialsProvider->GetAWSCredentials(); + + //don't sign anonymous requests + if (credentials.GetAWSAccessKeyId().empty() || credentials.GetAWSSecretKey().empty()) + { + return true; + } + + if (!credentials.GetSessionToken().empty()) + { + request.SetAwsSessionToken(credentials.GetSessionToken()); + } + + Aws::String payloadHash(UNSIGNED_PAYLOAD); + switch(m_payloadSigningPolicy) + { + case PayloadSigningPolicy::Always: + signBody = true; + break; + case PayloadSigningPolicy::Never: + signBody = false; + break; + case PayloadSigningPolicy::RequestDependent: + // respect the request setting + default: + break; + } + + if(signBody || request.GetUri().GetScheme() != Http::Scheme::HTTPS) + { payloadHash = ComputePayloadHash(request); - if (payloadHash.empty()) - { - return false; - } - } - else - { - AWS_LOGSTREAM_DEBUG(v4LogTag, "Note: Http payloads are not being signed. signPayloads=" << signBody - << " http scheme=" << Http::SchemeMapper::ToString(request.GetUri().GetScheme())); - } - - if(m_includeSha256HashHeader) - { + if (payloadHash.empty()) + { + return false; + } + } + else + { + AWS_LOGSTREAM_DEBUG(v4LogTag, "Note: Http payloads are not being signed. signPayloads=" << signBody + << " http scheme=" << Http::SchemeMapper::ToString(request.GetUri().GetScheme())); + } + + if(m_includeSha256HashHeader) + { request.SetHeaderValue(X_AMZ_CONTENT_SHA256, payloadHash); - } - - //calculate date header to use in internal signature (this also goes into date header). - DateTime now = GetSigningTimestamp(); + } + + //calculate date header to use in internal signature (this also goes into date header). + DateTime now = GetSigningTimestamp(); Aws::String dateHeaderValue = now.ToGmtString(DateFormat::ISO_8601_BASIC); - request.SetHeaderValue(AWS_DATE_HEADER, dateHeaderValue); - - Aws::StringStream headersStream; - Aws::StringStream signedHeadersStream; - - for (const auto& header : CanonicalizeHeaders(request.GetHeaders())) - { - if(ShouldSignHeader(header.first)) - { - headersStream << header.first.c_str() << ":" << header.second.c_str() << NEWLINE; - signedHeadersStream << header.first.c_str() << ";"; - } - } - - Aws::String canonicalHeadersString = headersStream.str(); - AWS_LOGSTREAM_DEBUG(v4LogTag, "Canonical Header String: " << canonicalHeadersString); - - //calculate signed headers parameter - Aws::String signedHeadersValue = signedHeadersStream.str(); - //remove that last semi-colon - if (!signedHeadersValue.empty()) - { + request.SetHeaderValue(AWS_DATE_HEADER, dateHeaderValue); + + Aws::StringStream headersStream; + Aws::StringStream signedHeadersStream; + + for (const auto& header : CanonicalizeHeaders(request.GetHeaders())) + { + if(ShouldSignHeader(header.first)) + { + headersStream << header.first.c_str() << ":" << header.second.c_str() << NEWLINE; + signedHeadersStream << header.first.c_str() << ";"; + } + } + + Aws::String canonicalHeadersString = headersStream.str(); + AWS_LOGSTREAM_DEBUG(v4LogTag, "Canonical Header String: " << canonicalHeadersString); + + //calculate signed headers parameter + Aws::String signedHeadersValue = signedHeadersStream.str(); + //remove that last semi-colon + if (!signedHeadersValue.empty()) + { signedHeadersValue.pop_back(); - } - - AWS_LOGSTREAM_DEBUG(v4LogTag, "Signed Headers value:" << signedHeadersValue); - - //generate generalized canonicalized request string. - Aws::String canonicalRequestString = CanonicalizeRequestSigningString(request, m_urlEscapePath); - - //append v4 stuff to the canonical request string. - canonicalRequestString.append(canonicalHeadersString); - canonicalRequestString.append(NEWLINE); - canonicalRequestString.append(signedHeadersValue); - canonicalRequestString.append(NEWLINE); - canonicalRequestString.append(payloadHash); - - AWS_LOGSTREAM_DEBUG(v4LogTag, "Canonical Request String: " << canonicalRequestString); - - //now compute sha256 on that request string - auto hashResult = m_hash->Calculate(canonicalRequestString); - if (!hashResult.IsSuccess()) - { - AWS_LOGSTREAM_ERROR(v4LogTag, "Failed to hash (sha256) request string"); - AWS_LOGSTREAM_DEBUG(v4LogTag, "The request string is: \"" << canonicalRequestString << "\""); - return false; - } - - auto sha256Digest = hashResult.GetResult(); + } + + AWS_LOGSTREAM_DEBUG(v4LogTag, "Signed Headers value:" << signedHeadersValue); + + //generate generalized canonicalized request string. + Aws::String canonicalRequestString = CanonicalizeRequestSigningString(request, m_urlEscapePath); + + //append v4 stuff to the canonical request string. + canonicalRequestString.append(canonicalHeadersString); + canonicalRequestString.append(NEWLINE); + canonicalRequestString.append(signedHeadersValue); + canonicalRequestString.append(NEWLINE); + canonicalRequestString.append(payloadHash); + + AWS_LOGSTREAM_DEBUG(v4LogTag, "Canonical Request String: " << canonicalRequestString); + + //now compute sha256 on that request string + auto hashResult = m_hash->Calculate(canonicalRequestString); + if (!hashResult.IsSuccess()) + { + AWS_LOGSTREAM_ERROR(v4LogTag, "Failed to hash (sha256) request string"); + AWS_LOGSTREAM_DEBUG(v4LogTag, "The request string is: \"" << canonicalRequestString << "\""); + return false; + } + + auto sha256Digest = hashResult.GetResult(); Aws::String canonicalRequestHash = HashingUtils::HexEncode(sha256Digest); - Aws::String simpleDate = now.ToGmtString(SIMPLE_DATE_FORMAT_STR); - + Aws::String simpleDate = now.ToGmtString(SIMPLE_DATE_FORMAT_STR); + Aws::String signingRegion = region ? region : m_region; Aws::String signingServiceName = serviceName ? serviceName : m_serviceName; Aws::String stringToSign = GenerateStringToSign(dateHeaderValue, simpleDate, canonicalRequestHash, signingRegion, signingServiceName); auto finalSignature = GenerateSignature(credentials, stringToSign, simpleDate, signingRegion, signingServiceName); - - Aws::StringStream ss; - ss << AWS_HMAC_SHA256 << " " << CREDENTIAL << EQ << credentials.GetAWSAccessKeyId() << "/" << simpleDate + + Aws::StringStream ss; + ss << AWS_HMAC_SHA256 << " " << CREDENTIAL << EQ << credentials.GetAWSAccessKeyId() << "/" << simpleDate << "/" << signingRegion << "/" << signingServiceName << "/" << AWS4_REQUEST << ", " << SIGNED_HEADERS << EQ - << signedHeadersValue << ", " << SIGNATURE << EQ << finalSignature; - - auto awsAuthString = ss.str(); - AWS_LOGSTREAM_DEBUG(v4LogTag, "Signing request with: " << awsAuthString); - request.SetAwsAuthorization(awsAuthString); - request.SetSigningAccessKey(credentials.GetAWSAccessKeyId()); + << signedHeadersValue << ", " << SIGNATURE << EQ << finalSignature; + + auto awsAuthString = ss.str(); + AWS_LOGSTREAM_DEBUG(v4LogTag, "Signing request with: " << awsAuthString); + request.SetAwsAuthorization(awsAuthString); + request.SetSigningAccessKey(credentials.GetAWSAccessKeyId()); request.SetSigningRegion(signingRegion); - return true; -} - -bool AWSAuthV4Signer::PresignRequest(Aws::Http::HttpRequest& request, long long expirationTimeInSeconds) const -{ - return PresignRequest(request, m_region.c_str(), expirationTimeInSeconds); -} - -bool AWSAuthV4Signer::PresignRequest(Aws::Http::HttpRequest& request, const char* region, long long expirationInSeconds) const -{ - return PresignRequest(request, region, m_serviceName.c_str(), expirationInSeconds); -} - -bool AWSAuthV4Signer::PresignRequest(Aws::Http::HttpRequest& request, const char* region, const char* serviceName, long long expirationTimeInSeconds) const -{ - AWSCredentials credentials = m_credentialsProvider->GetAWSCredentials(); - - //don't sign anonymous requests - if (credentials.GetAWSAccessKeyId().empty() || credentials.GetAWSSecretKey().empty()) - { - return true; - } - - Aws::StringStream intConversionStream; - intConversionStream << expirationTimeInSeconds; - request.AddQueryStringParameter(Http::X_AMZ_EXPIRES_HEADER, intConversionStream.str()); - - if (!credentials.GetSessionToken().empty()) - { - request.AddQueryStringParameter(Http::AWS_SECURITY_TOKEN, credentials.GetSessionToken()); - } - - //calculate date header to use in internal signature (this also goes into date header). - DateTime now = GetSigningTimestamp(); + return true; +} + +bool AWSAuthV4Signer::PresignRequest(Aws::Http::HttpRequest& request, long long expirationTimeInSeconds) const +{ + return PresignRequest(request, m_region.c_str(), expirationTimeInSeconds); +} + +bool AWSAuthV4Signer::PresignRequest(Aws::Http::HttpRequest& request, const char* region, long long expirationInSeconds) const +{ + return PresignRequest(request, region, m_serviceName.c_str(), expirationInSeconds); +} + +bool AWSAuthV4Signer::PresignRequest(Aws::Http::HttpRequest& request, const char* region, const char* serviceName, long long expirationTimeInSeconds) const +{ + AWSCredentials credentials = m_credentialsProvider->GetAWSCredentials(); + + //don't sign anonymous requests + if (credentials.GetAWSAccessKeyId().empty() || credentials.GetAWSSecretKey().empty()) + { + return true; + } + + Aws::StringStream intConversionStream; + intConversionStream << expirationTimeInSeconds; + request.AddQueryStringParameter(Http::X_AMZ_EXPIRES_HEADER, intConversionStream.str()); + + if (!credentials.GetSessionToken().empty()) + { + request.AddQueryStringParameter(Http::AWS_SECURITY_TOKEN, credentials.GetSessionToken()); + } + + //calculate date header to use in internal signature (this also goes into date header). + DateTime now = GetSigningTimestamp(); Aws::String dateQueryValue = now.ToGmtString(DateFormat::ISO_8601_BASIC); - request.AddQueryStringParameter(Http::AWS_DATE_HEADER, dateQueryValue); - - Aws::StringStream headersStream; - Aws::StringStream signedHeadersStream; - for (const auto& header : CanonicalizeHeaders(request.GetHeaders())) - { - if(ShouldSignHeader(header.first)) - { - headersStream << header.first.c_str() << ":" << header.second.c_str() << NEWLINE; - signedHeadersStream << header.first.c_str() << ";"; - } - } - - Aws::String canonicalHeadersString = headersStream.str(); - AWS_LOGSTREAM_DEBUG(v4LogTag, "Canonical Header String: " << canonicalHeadersString); - - //calculate signed headers parameter - Aws::String signedHeadersValue(signedHeadersStream.str()); - //remove that last semi-colon - if (!signedHeadersValue.empty()) - { - signedHeadersValue.pop_back(); - } - - request.AddQueryStringParameter(X_AMZ_SIGNED_HEADERS, signedHeadersValue); - AWS_LOGSTREAM_DEBUG(v4LogTag, "Signed Headers value: " << signedHeadersValue); - - Aws::StringStream ss; + request.AddQueryStringParameter(Http::AWS_DATE_HEADER, dateQueryValue); + + Aws::StringStream headersStream; + Aws::StringStream signedHeadersStream; + for (const auto& header : CanonicalizeHeaders(request.GetHeaders())) + { + if(ShouldSignHeader(header.first)) + { + headersStream << header.first.c_str() << ":" << header.second.c_str() << NEWLINE; + signedHeadersStream << header.first.c_str() << ";"; + } + } + + Aws::String canonicalHeadersString = headersStream.str(); + AWS_LOGSTREAM_DEBUG(v4LogTag, "Canonical Header String: " << canonicalHeadersString); + + //calculate signed headers parameter + Aws::String signedHeadersValue(signedHeadersStream.str()); + //remove that last semi-colon + if (!signedHeadersValue.empty()) + { + signedHeadersValue.pop_back(); + } + + request.AddQueryStringParameter(X_AMZ_SIGNED_HEADERS, signedHeadersValue); + AWS_LOGSTREAM_DEBUG(v4LogTag, "Signed Headers value: " << signedHeadersValue); + + Aws::StringStream ss; Aws::String signingRegion = region ? region : m_region; Aws::String signingServiceName = serviceName ? serviceName : m_serviceName; - Aws::String simpleDate = now.ToGmtString(SIMPLE_DATE_FORMAT_STR); - ss << credentials.GetAWSAccessKeyId() << "/" << simpleDate + Aws::String simpleDate = now.ToGmtString(SIMPLE_DATE_FORMAT_STR); + ss << credentials.GetAWSAccessKeyId() << "/" << simpleDate << "/" << signingRegion << "/" << signingServiceName << "/" << AWS4_REQUEST; - - request.AddQueryStringParameter(X_AMZ_ALGORITHM, AWS_HMAC_SHA256); - request.AddQueryStringParameter(X_AMZ_CREDENTIAL, ss.str()); - ss.str(""); - - request.SetSigningAccessKey(credentials.GetAWSAccessKeyId()); + + request.AddQueryStringParameter(X_AMZ_ALGORITHM, AWS_HMAC_SHA256); + request.AddQueryStringParameter(X_AMZ_CREDENTIAL, ss.str()); + ss.str(""); + + request.SetSigningAccessKey(credentials.GetAWSAccessKeyId()); request.SetSigningRegion(signingRegion); - - //generate generalized canonicalized request string. - Aws::String canonicalRequestString = CanonicalizeRequestSigningString(request, m_urlEscapePath); - - //append v4 stuff to the canonical request string. - canonicalRequestString.append(canonicalHeadersString); - canonicalRequestString.append(NEWLINE); - canonicalRequestString.append(signedHeadersValue); - canonicalRequestString.append(NEWLINE); + + //generate generalized canonicalized request string. + Aws::String canonicalRequestString = CanonicalizeRequestSigningString(request, m_urlEscapePath); + + //append v4 stuff to the canonical request string. + canonicalRequestString.append(canonicalHeadersString); + canonicalRequestString.append(NEWLINE); + canonicalRequestString.append(signedHeadersValue); + canonicalRequestString.append(NEWLINE); if (ServiceRequireUnsignedPayload(signingServiceName)) { - canonicalRequestString.append(UNSIGNED_PAYLOAD); + canonicalRequestString.append(UNSIGNED_PAYLOAD); } else { - canonicalRequestString.append(EMPTY_STRING_SHA256); - } - AWS_LOGSTREAM_DEBUG(v4LogTag, "Canonical Request String: " << canonicalRequestString); - - //now compute sha256 on that request string - auto hashResult = m_hash->Calculate(canonicalRequestString); - if (!hashResult.IsSuccess()) - { - AWS_LOGSTREAM_ERROR(v4LogTag, "Failed to hash (sha256) request string"); - AWS_LOGSTREAM_DEBUG(v4LogTag, "The request string is: \"" << canonicalRequestString << "\""); - return false; - } - - auto sha256Digest = hashResult.GetResult(); + canonicalRequestString.append(EMPTY_STRING_SHA256); + } + AWS_LOGSTREAM_DEBUG(v4LogTag, "Canonical Request String: " << canonicalRequestString); + + //now compute sha256 on that request string + auto hashResult = m_hash->Calculate(canonicalRequestString); + if (!hashResult.IsSuccess()) + { + AWS_LOGSTREAM_ERROR(v4LogTag, "Failed to hash (sha256) request string"); + AWS_LOGSTREAM_DEBUG(v4LogTag, "The request string is: \"" << canonicalRequestString << "\""); + return false; + } + + auto sha256Digest = hashResult.GetResult(); auto canonicalRequestHash = HashingUtils::HexEncode(sha256Digest); - + auto stringToSign = GenerateStringToSign(dateQueryValue, simpleDate, canonicalRequestHash, signingRegion, signingServiceName); auto finalSigningHash = GenerateSignature(credentials, stringToSign, simpleDate, signingRegion, signingServiceName); - if (finalSigningHash.empty()) - { - return false; - } - + if (finalSigningHash.empty()) + { + return false; + } + //add that the signature to the query string - request.AddQueryStringParameter(X_AMZ_SIGNATURE, finalSigningHash); - - return true; -} - -bool AWSAuthV4Signer::ServiceRequireUnsignedPayload(const Aws::String& serviceName) const -{ - // S3 uses a magic string (instead of the empty string) for its body hash for presigned URLs as outlined here: - // https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html - // this is true for PUT, POST, GET, DELETE and HEAD operations. - // However, other services (for example RDS) implement the specification as outlined here: - // https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html - // which states that body-less requests should use the empty-string SHA256 hash. - return "s3" == serviceName; -} - -Aws::String AWSAuthV4Signer::GenerateSignature(const AWSCredentials& credentials, const Aws::String& stringToSign, - const Aws::String& simpleDate, const Aws::String& region, const Aws::String& serviceName) const -{ - auto key = ComputeHash(credentials.GetAWSSecretKey(), simpleDate, region, serviceName); - return GenerateSignature(stringToSign, key); -} - -Aws::String AWSAuthV4Signer::GenerateSignature(const Aws::String& stringToSign, const ByteBuffer& key) const -{ - AWS_LOGSTREAM_DEBUG(v4LogTag, "Final String to sign: " << stringToSign); - - Aws::StringStream ss; - - auto hashResult = m_HMAC->Calculate(ByteBuffer((unsigned char*)stringToSign.c_str(), stringToSign.length()), key); - if (!hashResult.IsSuccess()) - { - AWS_LOGSTREAM_ERROR(v4LogTag, "Unable to hmac (sha256) final string"); - AWS_LOGSTREAM_DEBUG(v4LogTag, "The final string is: \"" << stringToSign << "\""); + request.AddQueryStringParameter(X_AMZ_SIGNATURE, finalSigningHash); + + return true; +} + +bool AWSAuthV4Signer::ServiceRequireUnsignedPayload(const Aws::String& serviceName) const +{ + // S3 uses a magic string (instead of the empty string) for its body hash for presigned URLs as outlined here: + // https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html + // this is true for PUT, POST, GET, DELETE and HEAD operations. + // However, other services (for example RDS) implement the specification as outlined here: + // https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html + // which states that body-less requests should use the empty-string SHA256 hash. + return "s3" == serviceName; +} + +Aws::String AWSAuthV4Signer::GenerateSignature(const AWSCredentials& credentials, const Aws::String& stringToSign, + const Aws::String& simpleDate, const Aws::String& region, const Aws::String& serviceName) const +{ + auto key = ComputeHash(credentials.GetAWSSecretKey(), simpleDate, region, serviceName); + return GenerateSignature(stringToSign, key); +} + +Aws::String AWSAuthV4Signer::GenerateSignature(const Aws::String& stringToSign, const ByteBuffer& key) const +{ + AWS_LOGSTREAM_DEBUG(v4LogTag, "Final String to sign: " << stringToSign); + + Aws::StringStream ss; + + auto hashResult = m_HMAC->Calculate(ByteBuffer((unsigned char*)stringToSign.c_str(), stringToSign.length()), key); + if (!hashResult.IsSuccess()) + { + AWS_LOGSTREAM_ERROR(v4LogTag, "Unable to hmac (sha256) final string"); + AWS_LOGSTREAM_DEBUG(v4LogTag, "The final string is: \"" << stringToSign << "\""); return {}; - } - - //now we finally sign our request string with our hex encoded derived hash. - auto finalSigningDigest = hashResult.GetResult(); - - auto finalSigningHash = HashingUtils::HexEncode(finalSigningDigest); - AWS_LOGSTREAM_DEBUG(v4LogTag, "Final computed signing hash: " << finalSigningHash); - - return finalSigningHash; -} - -Aws::String AWSAuthV4Signer::ComputePayloadHash(Aws::Http::HttpRequest& request) const -{ - if (!request.GetContentBody()) - { - AWS_LOGSTREAM_DEBUG(v4LogTag, "Using cached empty string sha256 " << EMPTY_STRING_SHA256 << " because payload is empty."); - return EMPTY_STRING_SHA256; - } - - //compute hash on payload if it exists. - auto hashResult = m_hash->Calculate(*request.GetContentBody()); - - if(request.GetContentBody()) - { - request.GetContentBody()->clear(); - request.GetContentBody()->seekg(0); - } - - if (!hashResult.IsSuccess()) - { - AWS_LOGSTREAM_ERROR(v4LogTag, "Unable to hash (sha256) request body"); + } + + //now we finally sign our request string with our hex encoded derived hash. + auto finalSigningDigest = hashResult.GetResult(); + + auto finalSigningHash = HashingUtils::HexEncode(finalSigningDigest); + AWS_LOGSTREAM_DEBUG(v4LogTag, "Final computed signing hash: " << finalSigningHash); + + return finalSigningHash; +} + +Aws::String AWSAuthV4Signer::ComputePayloadHash(Aws::Http::HttpRequest& request) const +{ + if (!request.GetContentBody()) + { + AWS_LOGSTREAM_DEBUG(v4LogTag, "Using cached empty string sha256 " << EMPTY_STRING_SHA256 << " because payload is empty."); + return EMPTY_STRING_SHA256; + } + + //compute hash on payload if it exists. + auto hashResult = m_hash->Calculate(*request.GetContentBody()); + + if(request.GetContentBody()) + { + request.GetContentBody()->clear(); + request.GetContentBody()->seekg(0); + } + + if (!hashResult.IsSuccess()) + { + AWS_LOGSTREAM_ERROR(v4LogTag, "Unable to hash (sha256) request body"); return {}; - } - - auto sha256Digest = hashResult.GetResult(); - - Aws::String payloadHash(HashingUtils::HexEncode(sha256Digest)); - AWS_LOGSTREAM_DEBUG(v4LogTag, "Calculated sha256 " << payloadHash << " for payload."); - return payloadHash; -} - -Aws::String AWSAuthV4Signer::GenerateStringToSign(const Aws::String& dateValue, const Aws::String& simpleDate, - const Aws::String& canonicalRequestHash, const Aws::String& region, const Aws::String& serviceName) const -{ - //generate the actual string we will use in signing the final request. - Aws::StringStream ss; - - ss << AWS_HMAC_SHA256 << NEWLINE << dateValue << NEWLINE << simpleDate << "/" << region << "/" - << serviceName << "/" << AWS4_REQUEST << NEWLINE << canonicalRequestHash; - - return ss.str(); -} - -Aws::Utils::ByteBuffer AWSAuthV4Signer::ComputeHash(const Aws::String& secretKey, - const Aws::String& simpleDate, const Aws::String& region, const Aws::String& serviceName) const -{ - Aws::String signingKey(SIGNING_KEY); - signingKey.append(secretKey); - auto hashResult = m_HMAC->Calculate(ByteBuffer((unsigned char*)simpleDate.c_str(), simpleDate.length()), - ByteBuffer((unsigned char*)signingKey.c_str(), signingKey.length())); - - if (!hashResult.IsSuccess()) - { - AWS_LOGSTREAM_ERROR(v4LogTag, "Failed to HMAC (SHA256) date string \"" << simpleDate << "\""); - return {}; - } - - auto kDate = hashResult.GetResult(); - hashResult = m_HMAC->Calculate(ByteBuffer((unsigned char*)region.c_str(), region.length()), kDate); - if (!hashResult.IsSuccess()) - { - AWS_LOGSTREAM_ERROR(v4LogTag, "Failed to HMAC (SHA256) region string \"" << region << "\""); - return {}; - } - - auto kRegion = hashResult.GetResult(); - hashResult = m_HMAC->Calculate(ByteBuffer((unsigned char*)serviceName.c_str(), serviceName.length()), kRegion); - if (!hashResult.IsSuccess()) - { - AWS_LOGSTREAM_ERROR(v4LogTag, "Failed to HMAC (SHA256) service string \"" << m_serviceName << "\""); - return {}; - } - - auto kService = hashResult.GetResult(); - hashResult = m_HMAC->Calculate(ByteBuffer((unsigned char*)AWS4_REQUEST, strlen(AWS4_REQUEST)), kService); - if (!hashResult.IsSuccess()) - { - AWS_LOGSTREAM_ERROR(v4LogTag, "Unable to HMAC (SHA256) request string"); - AWS_LOGSTREAM_DEBUG(v4LogTag, "The request string is: \"" << AWS4_REQUEST << "\""); - return {}; - } - return hashResult.GetResult(); -} + } + + auto sha256Digest = hashResult.GetResult(); + + Aws::String payloadHash(HashingUtils::HexEncode(sha256Digest)); + AWS_LOGSTREAM_DEBUG(v4LogTag, "Calculated sha256 " << payloadHash << " for payload."); + return payloadHash; +} + +Aws::String AWSAuthV4Signer::GenerateStringToSign(const Aws::String& dateValue, const Aws::String& simpleDate, + const Aws::String& canonicalRequestHash, const Aws::String& region, const Aws::String& serviceName) const +{ + //generate the actual string we will use in signing the final request. + Aws::StringStream ss; + + ss << AWS_HMAC_SHA256 << NEWLINE << dateValue << NEWLINE << simpleDate << "/" << region << "/" + << serviceName << "/" << AWS4_REQUEST << NEWLINE << canonicalRequestHash; + + return ss.str(); +} + +Aws::Utils::ByteBuffer AWSAuthV4Signer::ComputeHash(const Aws::String& secretKey, + const Aws::String& simpleDate, const Aws::String& region, const Aws::String& serviceName) const +{ + Aws::String signingKey(SIGNING_KEY); + signingKey.append(secretKey); + auto hashResult = m_HMAC->Calculate(ByteBuffer((unsigned char*)simpleDate.c_str(), simpleDate.length()), + ByteBuffer((unsigned char*)signingKey.c_str(), signingKey.length())); + + if (!hashResult.IsSuccess()) + { + AWS_LOGSTREAM_ERROR(v4LogTag, "Failed to HMAC (SHA256) date string \"" << simpleDate << "\""); + return {}; + } + + auto kDate = hashResult.GetResult(); + hashResult = m_HMAC->Calculate(ByteBuffer((unsigned char*)region.c_str(), region.length()), kDate); + if (!hashResult.IsSuccess()) + { + AWS_LOGSTREAM_ERROR(v4LogTag, "Failed to HMAC (SHA256) region string \"" << region << "\""); + return {}; + } + + auto kRegion = hashResult.GetResult(); + hashResult = m_HMAC->Calculate(ByteBuffer((unsigned char*)serviceName.c_str(), serviceName.length()), kRegion); + if (!hashResult.IsSuccess()) + { + AWS_LOGSTREAM_ERROR(v4LogTag, "Failed to HMAC (SHA256) service string \"" << m_serviceName << "\""); + return {}; + } + + auto kService = hashResult.GetResult(); + hashResult = m_HMAC->Calculate(ByteBuffer((unsigned char*)AWS4_REQUEST, strlen(AWS4_REQUEST)), kService); + if (!hashResult.IsSuccess()) + { + AWS_LOGSTREAM_ERROR(v4LogTag, "Unable to HMAC (SHA256) request string"); + AWS_LOGSTREAM_DEBUG(v4LogTag, "The request string is: \"" << AWS4_REQUEST << "\""); + return {}; + } + return hashResult.GetResult(); +} AWSAuthEventStreamV4Signer::AWSAuthEventStreamV4Signer(const std::shared_ptr<Auth::AWSCredentialsProvider>& credentialsProvider, const char* serviceName, const Aws::String& region) : diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSAuthSignerProvider.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSAuthSignerProvider.cpp index 31fd6c006b..bd005b73b7 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSAuthSignerProvider.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSAuthSignerProvider.cpp @@ -2,16 +2,16 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/utils/logging/LogMacros.h> -#include <aws/core/auth/AWSAuthSignerProvider.h> -#include <aws/core/auth/AWSAuthSigner.h> + +#include <aws/core/utils/logging/LogMacros.h> +#include <aws/core/auth/AWSAuthSignerProvider.h> +#include <aws/core/auth/AWSAuthSigner.h> #include <aws/core/auth/AWSCredentialsProvider.h> #include <aws/core/utils/memory/stl/AWSAllocator.h> - -const char CLASS_TAG[] = "AuthSignerProvider"; - -using namespace Aws::Auth; + +const char CLASS_TAG[] = "AuthSignerProvider"; + +using namespace Aws::Auth; DefaultAuthSignerProvider::DefaultAuthSignerProvider(const std::shared_ptr<AWSCredentialsProvider>& credentialsProvider, const Aws::String& serviceName, const Aws::String& region) @@ -21,28 +21,28 @@ DefaultAuthSignerProvider::DefaultAuthSignerProvider(const std::shared_ptr<AWSCr m_signers.emplace_back(Aws::MakeShared<Aws::Client::AWSNullSigner>(CLASS_TAG)); } -DefaultAuthSignerProvider::DefaultAuthSignerProvider(const std::shared_ptr<Aws::Client::AWSAuthSigner>& signer) -{ - m_signers.emplace_back(Aws::MakeShared<Aws::Client::AWSNullSigner>(CLASS_TAG)); - if(signer) - { - m_signers.emplace_back(signer); - } -} - -std::shared_ptr<Aws::Client::AWSAuthSigner> DefaultAuthSignerProvider::GetSigner(const Aws::String& signerName) const -{ - for(const auto& signer : m_signers) - { - if(signer->GetName() == signerName) - { - return signer; - } - } - AWS_LOGSTREAM_ERROR(CLASS_TAG, "Request's signer: '" << signerName << "' is not found in the signer's map."); - assert(false); - return nullptr; -} +DefaultAuthSignerProvider::DefaultAuthSignerProvider(const std::shared_ptr<Aws::Client::AWSAuthSigner>& signer) +{ + m_signers.emplace_back(Aws::MakeShared<Aws::Client::AWSNullSigner>(CLASS_TAG)); + if(signer) + { + m_signers.emplace_back(signer); + } +} + +std::shared_ptr<Aws::Client::AWSAuthSigner> DefaultAuthSignerProvider::GetSigner(const Aws::String& signerName) const +{ + for(const auto& signer : m_signers) + { + if(signer->GetName() == signerName) + { + return signer; + } + } + AWS_LOGSTREAM_ERROR(CLASS_TAG, "Request's signer: '" << signerName << "' is not found in the signer's map."); + assert(false); + return nullptr; +} void DefaultAuthSignerProvider::AddSigner(std::shared_ptr<Aws::Client::AWSAuthSigner>& signer) { diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSCredentialsProvider.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSCredentialsProvider.cpp index 31e28b996f..b7029eb832 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSCredentialsProvider.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSCredentialsProvider.cpp @@ -2,104 +2,104 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - - -#include <aws/core/auth/AWSCredentialsProvider.h> - -#include <aws/core/config/AWSProfileConfigLoader.h> -#include <aws/core/platform/Environment.h> -#include <aws/core/platform/FileSystem.h> + + +#include <aws/core/auth/AWSCredentialsProvider.h> + +#include <aws/core/config/AWSProfileConfigLoader.h> +#include <aws/core/platform/Environment.h> +#include <aws/core/platform/FileSystem.h> #include <aws/core/platform/OSVersionInfo.h> -#include <aws/core/utils/logging/LogMacros.h> -#include <aws/core/utils/StringUtils.h> -#include <aws/core/utils/json/JsonSerializer.h> -#include <aws/core/utils/FileSystemUtils.h> +#include <aws/core/utils/logging/LogMacros.h> +#include <aws/core/utils/StringUtils.h> +#include <aws/core/utils/json/JsonSerializer.h> +#include <aws/core/utils/FileSystemUtils.h> #include <aws/core/client/AWSError.h> #include <aws/core/utils/StringUtils.h> #include <aws/core/utils/xml/XmlSerializer.h> -#include <cstdlib> -#include <fstream> -#include <string.h> -#include <climits> - - -using namespace Aws::Utils; -using namespace Aws::Utils::Logging; -using namespace Aws::Auth; -using namespace Aws::Internal; +#include <cstdlib> +#include <fstream> +#include <string.h> +#include <climits> + + +using namespace Aws::Utils; +using namespace Aws::Utils::Logging; +using namespace Aws::Auth; +using namespace Aws::Internal; using namespace Aws::FileSystem; using namespace Aws::Utils::Xml; using namespace Aws::Client; -using Aws::Utils::Threading::ReaderLockGuard; -using Aws::Utils::Threading::WriterLockGuard; - -static const char ACCESS_KEY_ENV_VAR[] = "AWS_ACCESS_KEY_ID"; -static const char SECRET_KEY_ENV_VAR[] = "AWS_SECRET_ACCESS_KEY"; -static const char SESSION_TOKEN_ENV_VAR[] = "AWS_SESSION_TOKEN"; -static const char DEFAULT_PROFILE[] = "default"; -static const char AWS_PROFILE_ENV_VAR[] = "AWS_PROFILE"; -static const char AWS_PROFILE_DEFAULT_ENV_VAR[] = "AWS_DEFAULT_PROFILE"; - +using Aws::Utils::Threading::ReaderLockGuard; +using Aws::Utils::Threading::WriterLockGuard; + +static const char ACCESS_KEY_ENV_VAR[] = "AWS_ACCESS_KEY_ID"; +static const char SECRET_KEY_ENV_VAR[] = "AWS_SECRET_ACCESS_KEY"; +static const char SESSION_TOKEN_ENV_VAR[] = "AWS_SESSION_TOKEN"; +static const char DEFAULT_PROFILE[] = "default"; +static const char AWS_PROFILE_ENV_VAR[] = "AWS_PROFILE"; +static const char AWS_PROFILE_DEFAULT_ENV_VAR[] = "AWS_DEFAULT_PROFILE"; + static const char AWS_CREDENTIALS_FILE[] = "AWS_SHARED_CREDENTIALS_FILE"; extern const char AWS_CONFIG_FILE[] = "AWS_CONFIG_FILE"; - + extern const char PROFILE_DIRECTORY[] = ".aws"; static const char DEFAULT_CREDENTIALS_FILE[] = "credentials"; extern const char DEFAULT_CONFIG_FILE[] = "config"; - - -static const int EXPIRATION_GRACE_PERIOD = 5 * 1000; - -void AWSCredentialsProvider::Reload() -{ - m_lastLoadedMs = DateTime::Now().Millis(); -} - -bool AWSCredentialsProvider::IsTimeToRefresh(long reloadFrequency) -{ - if (DateTime::Now().Millis() - m_lastLoadedMs > reloadFrequency) - { - return true; - } - return false; -} - - -static const char* ENVIRONMENT_LOG_TAG = "EnvironmentAWSCredentialsProvider"; - - -AWSCredentials EnvironmentAWSCredentialsProvider::GetAWSCredentials() -{ - auto accessKey = Aws::Environment::GetEnv(ACCESS_KEY_ENV_VAR); + + +static const int EXPIRATION_GRACE_PERIOD = 5 * 1000; + +void AWSCredentialsProvider::Reload() +{ + m_lastLoadedMs = DateTime::Now().Millis(); +} + +bool AWSCredentialsProvider::IsTimeToRefresh(long reloadFrequency) +{ + if (DateTime::Now().Millis() - m_lastLoadedMs > reloadFrequency) + { + return true; + } + return false; +} + + +static const char* ENVIRONMENT_LOG_TAG = "EnvironmentAWSCredentialsProvider"; + + +AWSCredentials EnvironmentAWSCredentialsProvider::GetAWSCredentials() +{ + auto accessKey = Aws::Environment::GetEnv(ACCESS_KEY_ENV_VAR); AWSCredentials credentials; - - if (!accessKey.empty()) - { - credentials.SetAWSAccessKeyId(accessKey); - - AWS_LOGSTREAM_DEBUG(ENVIRONMENT_LOG_TAG, "Found credential in environment with access key id " << accessKey); - auto secretKey = Aws::Environment::GetEnv(SECRET_KEY_ENV_VAR); - - if (!secretKey.empty()) - { - credentials.SetAWSSecretKey(secretKey); - AWS_LOGSTREAM_INFO(ENVIRONMENT_LOG_TAG, "Found secret key"); - } - - auto sessionToken = Aws::Environment::GetEnv(SESSION_TOKEN_ENV_VAR); - - if(!sessionToken.empty()) - { - credentials.SetSessionToken(sessionToken); - AWS_LOGSTREAM_INFO(ENVIRONMENT_LOG_TAG, "Found sessionToken"); - } - } - - return credentials; -} - + + if (!accessKey.empty()) + { + credentials.SetAWSAccessKeyId(accessKey); + + AWS_LOGSTREAM_DEBUG(ENVIRONMENT_LOG_TAG, "Found credential in environment with access key id " << accessKey); + auto secretKey = Aws::Environment::GetEnv(SECRET_KEY_ENV_VAR); + + if (!secretKey.empty()) + { + credentials.SetAWSSecretKey(secretKey); + AWS_LOGSTREAM_INFO(ENVIRONMENT_LOG_TAG, "Found secret key"); + } + + auto sessionToken = Aws::Environment::GetEnv(SESSION_TOKEN_ENV_VAR); + + if(!sessionToken.empty()) + { + credentials.SetSessionToken(sessionToken); + AWS_LOGSTREAM_INFO(ENVIRONMENT_LOG_TAG, "Found sessionToken"); + } + } + + return credentials; +} + Aws::String Aws::Auth::GetConfigProfileFilename() -{ +{ auto configFileNameFromVar = Aws::Environment::GetEnv(AWS_CONFIG_FILE); if (!configFileNameFromVar.empty()) { @@ -109,8 +109,8 @@ Aws::String Aws::Auth::GetConfigProfileFilename() { return Aws::FileSystem::GetHomeDirectory() + PROFILE_DIRECTORY + PATH_DELIM + DEFAULT_CONFIG_FILE; } -} - +} + Aws::String Aws::Auth::GetConfigProfileName() { auto profileFromVar = Aws::Environment::GetEnv(AWS_PROFILE_DEFAULT_ENV_VAR); @@ -130,231 +130,231 @@ Aws::String Aws::Auth::GetConfigProfileName() } static const char* PROFILE_LOG_TAG = "ProfileConfigFileAWSCredentialsProvider"; - -Aws::String ProfileConfigFileAWSCredentialsProvider::GetCredentialsProfileFilename() -{ + +Aws::String ProfileConfigFileAWSCredentialsProvider::GetCredentialsProfileFilename() +{ auto credentialsFileNameFromVar = Aws::Environment::GetEnv(AWS_CREDENTIALS_FILE); - + if (credentialsFileNameFromVar.empty()) - { + { return Aws::FileSystem::GetHomeDirectory() + PROFILE_DIRECTORY + PATH_DELIM + DEFAULT_CREDENTIALS_FILE; - } - else - { + } + else + { return credentialsFileNameFromVar; - } -} - -Aws::String ProfileConfigFileAWSCredentialsProvider::GetProfileDirectory() -{ + } +} + +Aws::String ProfileConfigFileAWSCredentialsProvider::GetProfileDirectory() +{ Aws::String credentialsFileName = GetCredentialsProfileFilename(); auto lastSeparator = credentialsFileName.find_last_of(PATH_DELIM); - if (lastSeparator != std::string::npos) - { + if (lastSeparator != std::string::npos) + { return credentialsFileName.substr(0, lastSeparator); - } - else - { + } + else + { return {}; - } -} - -ProfileConfigFileAWSCredentialsProvider::ProfileConfigFileAWSCredentialsProvider(long refreshRateMs) : + } +} + +ProfileConfigFileAWSCredentialsProvider::ProfileConfigFileAWSCredentialsProvider(long refreshRateMs) : m_profileToUse(Aws::Auth::GetConfigProfileName()), m_credentialsFileLoader(GetCredentialsProfileFilename()), m_loadFrequencyMs(refreshRateMs) -{ - AWS_LOGSTREAM_INFO(PROFILE_LOG_TAG, "Setting provider to read credentials from " << GetCredentialsProfileFilename() << " for credentials file" - << " and " << GetConfigProfileFilename() << " for the config file " - << ", for use with profile " << m_profileToUse); -} - -ProfileConfigFileAWSCredentialsProvider::ProfileConfigFileAWSCredentialsProvider(const char* profile, long refreshRateMs) : +{ + AWS_LOGSTREAM_INFO(PROFILE_LOG_TAG, "Setting provider to read credentials from " << GetCredentialsProfileFilename() << " for credentials file" + << " and " << GetConfigProfileFilename() << " for the config file " + << ", for use with profile " << m_profileToUse); +} + +ProfileConfigFileAWSCredentialsProvider::ProfileConfigFileAWSCredentialsProvider(const char* profile, long refreshRateMs) : m_profileToUse(profile), m_credentialsFileLoader(GetCredentialsProfileFilename()), m_loadFrequencyMs(refreshRateMs) -{ - AWS_LOGSTREAM_INFO(PROFILE_LOG_TAG, "Setting provider to read credentials from " << GetCredentialsProfileFilename() << " for credentials file" - << " and " << GetConfigProfileFilename() << " for the config file " - << ", for use with profile " << m_profileToUse); -} - -AWSCredentials ProfileConfigFileAWSCredentialsProvider::GetAWSCredentials() -{ - RefreshIfExpired(); - ReaderLockGuard guard(m_reloadLock); +{ + AWS_LOGSTREAM_INFO(PROFILE_LOG_TAG, "Setting provider to read credentials from " << GetCredentialsProfileFilename() << " for credentials file" + << " and " << GetConfigProfileFilename() << " for the config file " + << ", for use with profile " << m_profileToUse); +} + +AWSCredentials ProfileConfigFileAWSCredentialsProvider::GetAWSCredentials() +{ + RefreshIfExpired(); + ReaderLockGuard guard(m_reloadLock); auto credsFileProfileIter = m_credentialsFileLoader.GetProfiles().find(m_profileToUse); - + if(credsFileProfileIter != m_credentialsFileLoader.GetProfiles().end()) - { - return credsFileProfileIter->second.GetCredentials(); - } - - return AWSCredentials(); -} - - -void ProfileConfigFileAWSCredentialsProvider::Reload() -{ + { + return credsFileProfileIter->second.GetCredentials(); + } + + return AWSCredentials(); +} + + +void ProfileConfigFileAWSCredentialsProvider::Reload() +{ m_credentialsFileLoader.Load(); - AWSCredentialsProvider::Reload(); -} - -void ProfileConfigFileAWSCredentialsProvider::RefreshIfExpired() -{ - ReaderLockGuard guard(m_reloadLock); - if (!IsTimeToRefresh(m_loadFrequencyMs)) - { - return; - } - - guard.UpgradeToWriterLock(); - if (!IsTimeToRefresh(m_loadFrequencyMs)) // double-checked lock to avoid refreshing twice - { - return; - } - - Reload(); -} - -static const char* INSTANCE_LOG_TAG = "InstanceProfileCredentialsProvider"; - -InstanceProfileCredentialsProvider::InstanceProfileCredentialsProvider(long refreshRateMs) : + AWSCredentialsProvider::Reload(); +} + +void ProfileConfigFileAWSCredentialsProvider::RefreshIfExpired() +{ + ReaderLockGuard guard(m_reloadLock); + if (!IsTimeToRefresh(m_loadFrequencyMs)) + { + return; + } + + guard.UpgradeToWriterLock(); + if (!IsTimeToRefresh(m_loadFrequencyMs)) // double-checked lock to avoid refreshing twice + { + return; + } + + Reload(); +} + +static const char* INSTANCE_LOG_TAG = "InstanceProfileCredentialsProvider"; + +InstanceProfileCredentialsProvider::InstanceProfileCredentialsProvider(long refreshRateMs) : m_ec2MetadataConfigLoader(Aws::MakeShared<Aws::Config::EC2InstanceProfileConfigLoader>(INSTANCE_LOG_TAG)), m_loadFrequencyMs(refreshRateMs) -{ - AWS_LOGSTREAM_INFO(INSTANCE_LOG_TAG, "Creating Instance with default EC2MetadataClient and refresh rate " << refreshRateMs); -} - - +{ + AWS_LOGSTREAM_INFO(INSTANCE_LOG_TAG, "Creating Instance with default EC2MetadataClient and refresh rate " << refreshRateMs); +} + + InstanceProfileCredentialsProvider::InstanceProfileCredentialsProvider(const std::shared_ptr<Aws::Config::EC2InstanceProfileConfigLoader>& loader, long refreshRateMs) : m_ec2MetadataConfigLoader(loader), m_loadFrequencyMs(refreshRateMs) -{ - AWS_LOGSTREAM_INFO(INSTANCE_LOG_TAG, "Creating Instance with injected EC2MetadataClient and refresh rate " << refreshRateMs); -} - - -AWSCredentials InstanceProfileCredentialsProvider::GetAWSCredentials() -{ - RefreshIfExpired(); - ReaderLockGuard guard(m_reloadLock); - auto profileIter = m_ec2MetadataConfigLoader->GetProfiles().find(Aws::Config::INSTANCE_PROFILE_KEY); - - if(profileIter != m_ec2MetadataConfigLoader->GetProfiles().end()) - { - return profileIter->second.GetCredentials(); - } - - return AWSCredentials(); -} - -void InstanceProfileCredentialsProvider::Reload() -{ - AWS_LOGSTREAM_INFO(INSTANCE_LOG_TAG, "Credentials have expired attempting to repull from EC2 Metadata Service."); - m_ec2MetadataConfigLoader->Load(); - AWSCredentialsProvider::Reload(); -} - -void InstanceProfileCredentialsProvider::RefreshIfExpired() -{ - AWS_LOGSTREAM_DEBUG(INSTANCE_LOG_TAG, "Checking if latest credential pull has expired."); - ReaderLockGuard guard(m_reloadLock); - if (!IsTimeToRefresh(m_loadFrequencyMs)) - { +{ + AWS_LOGSTREAM_INFO(INSTANCE_LOG_TAG, "Creating Instance with injected EC2MetadataClient and refresh rate " << refreshRateMs); +} + + +AWSCredentials InstanceProfileCredentialsProvider::GetAWSCredentials() +{ + RefreshIfExpired(); + ReaderLockGuard guard(m_reloadLock); + auto profileIter = m_ec2MetadataConfigLoader->GetProfiles().find(Aws::Config::INSTANCE_PROFILE_KEY); + + if(profileIter != m_ec2MetadataConfigLoader->GetProfiles().end()) + { + return profileIter->second.GetCredentials(); + } + + return AWSCredentials(); +} + +void InstanceProfileCredentialsProvider::Reload() +{ + AWS_LOGSTREAM_INFO(INSTANCE_LOG_TAG, "Credentials have expired attempting to repull from EC2 Metadata Service."); + m_ec2MetadataConfigLoader->Load(); + AWSCredentialsProvider::Reload(); +} + +void InstanceProfileCredentialsProvider::RefreshIfExpired() +{ + AWS_LOGSTREAM_DEBUG(INSTANCE_LOG_TAG, "Checking if latest credential pull has expired."); + ReaderLockGuard guard(m_reloadLock); + if (!IsTimeToRefresh(m_loadFrequencyMs)) + { + return; + } + + guard.UpgradeToWriterLock(); + if (!IsTimeToRefresh(m_loadFrequencyMs)) // double-checked lock to avoid refreshing twice + { return; - } - - guard.UpgradeToWriterLock(); - if (!IsTimeToRefresh(m_loadFrequencyMs)) // double-checked lock to avoid refreshing twice - { - return; - } - Reload(); -} - -static const char TASK_ROLE_LOG_TAG[] = "TaskRoleCredentialsProvider"; - -TaskRoleCredentialsProvider::TaskRoleCredentialsProvider(const char* URI, long refreshRateMs) : - m_ecsCredentialsClient(Aws::MakeShared<Aws::Internal::ECSCredentialsClient>(TASK_ROLE_LOG_TAG, URI)), + } + Reload(); +} + +static const char TASK_ROLE_LOG_TAG[] = "TaskRoleCredentialsProvider"; + +TaskRoleCredentialsProvider::TaskRoleCredentialsProvider(const char* URI, long refreshRateMs) : + m_ecsCredentialsClient(Aws::MakeShared<Aws::Internal::ECSCredentialsClient>(TASK_ROLE_LOG_TAG, URI)), m_loadFrequencyMs(refreshRateMs) -{ - AWS_LOGSTREAM_INFO(TASK_ROLE_LOG_TAG, "Creating TaskRole with default ECSCredentialsClient and refresh rate " << refreshRateMs); -} - -TaskRoleCredentialsProvider::TaskRoleCredentialsProvider(const char* endpoint, const char* token, long refreshRateMs) : +{ + AWS_LOGSTREAM_INFO(TASK_ROLE_LOG_TAG, "Creating TaskRole with default ECSCredentialsClient and refresh rate " << refreshRateMs); +} + +TaskRoleCredentialsProvider::TaskRoleCredentialsProvider(const char* endpoint, const char* token, long refreshRateMs) : m_ecsCredentialsClient(Aws::MakeShared<Aws::Internal::ECSCredentialsClient>(TASK_ROLE_LOG_TAG, ""/*resourcePath*/, endpoint, token)), m_loadFrequencyMs(refreshRateMs) -{ - AWS_LOGSTREAM_INFO(TASK_ROLE_LOG_TAG, "Creating TaskRole with default ECSCredentialsClient and refresh rate " << refreshRateMs); -} - -TaskRoleCredentialsProvider::TaskRoleCredentialsProvider( - const std::shared_ptr<Aws::Internal::ECSCredentialsClient>& client, long refreshRateMs) : - m_ecsCredentialsClient(client), +{ + AWS_LOGSTREAM_INFO(TASK_ROLE_LOG_TAG, "Creating TaskRole with default ECSCredentialsClient and refresh rate " << refreshRateMs); +} + +TaskRoleCredentialsProvider::TaskRoleCredentialsProvider( + const std::shared_ptr<Aws::Internal::ECSCredentialsClient>& client, long refreshRateMs) : + m_ecsCredentialsClient(client), m_loadFrequencyMs(refreshRateMs) -{ - AWS_LOGSTREAM_INFO(TASK_ROLE_LOG_TAG, "Creating TaskRole with default ECSCredentialsClient and refresh rate " << refreshRateMs); -} - -AWSCredentials TaskRoleCredentialsProvider::GetAWSCredentials() -{ - RefreshIfExpired(); - ReaderLockGuard guard(m_reloadLock); - return m_credentials; -} - -bool TaskRoleCredentialsProvider::ExpiresSoon() const -{ +{ + AWS_LOGSTREAM_INFO(TASK_ROLE_LOG_TAG, "Creating TaskRole with default ECSCredentialsClient and refresh rate " << refreshRateMs); +} + +AWSCredentials TaskRoleCredentialsProvider::GetAWSCredentials() +{ + RefreshIfExpired(); + ReaderLockGuard guard(m_reloadLock); + return m_credentials; +} + +bool TaskRoleCredentialsProvider::ExpiresSoon() const +{ return ((m_credentials.GetExpiration() - Aws::Utils::DateTime::Now()).count() < EXPIRATION_GRACE_PERIOD); -} - -void TaskRoleCredentialsProvider::Reload() -{ - AWS_LOGSTREAM_INFO(TASK_ROLE_LOG_TAG, "Credentials have expired or will expire, attempting to repull from ECS IAM Service."); - - auto credentialsStr = m_ecsCredentialsClient->GetECSCredentials(); - if (credentialsStr.empty()) return; - - Json::JsonValue credentialsDoc(credentialsStr); +} + +void TaskRoleCredentialsProvider::Reload() +{ + AWS_LOGSTREAM_INFO(TASK_ROLE_LOG_TAG, "Credentials have expired or will expire, attempting to repull from ECS IAM Service."); + + auto credentialsStr = m_ecsCredentialsClient->GetECSCredentials(); + if (credentialsStr.empty()) return; + + Json::JsonValue credentialsDoc(credentialsStr); if (!credentialsDoc.WasParseSuccessful()) - { + { AWS_LOGSTREAM_ERROR(TASK_ROLE_LOG_TAG, "Failed to parse output from ECSCredentialService."); - return; - } - - Aws::String accessKey, secretKey, token; - Utils::Json::JsonView credentialsView(credentialsDoc); - accessKey = credentialsView.GetString("AccessKeyId"); - secretKey = credentialsView.GetString("SecretAccessKey"); - token = credentialsView.GetString("Token"); - AWS_LOGSTREAM_DEBUG(TASK_ROLE_LOG_TAG, "Successfully pulled credentials from metadata service with access key " << accessKey); - - m_credentials.SetAWSAccessKeyId(accessKey); - m_credentials.SetAWSSecretKey(secretKey); - m_credentials.SetSessionToken(token); + return; + } + + Aws::String accessKey, secretKey, token; + Utils::Json::JsonView credentialsView(credentialsDoc); + accessKey = credentialsView.GetString("AccessKeyId"); + secretKey = credentialsView.GetString("SecretAccessKey"); + token = credentialsView.GetString("Token"); + AWS_LOGSTREAM_DEBUG(TASK_ROLE_LOG_TAG, "Successfully pulled credentials from metadata service with access key " << accessKey); + + m_credentials.SetAWSAccessKeyId(accessKey); + m_credentials.SetAWSSecretKey(secretKey); + m_credentials.SetSessionToken(token); m_credentials.SetExpiration(Aws::Utils::DateTime(credentialsView.GetString("Expiration"), DateFormat::ISO_8601)); - AWSCredentialsProvider::Reload(); -} - -void TaskRoleCredentialsProvider::RefreshIfExpired() -{ - AWS_LOGSTREAM_DEBUG(TASK_ROLE_LOG_TAG, "Checking if latest credential pull has expired."); - ReaderLockGuard guard(m_reloadLock); + AWSCredentialsProvider::Reload(); +} + +void TaskRoleCredentialsProvider::RefreshIfExpired() +{ + AWS_LOGSTREAM_DEBUG(TASK_ROLE_LOG_TAG, "Checking if latest credential pull has expired."); + ReaderLockGuard guard(m_reloadLock); if (!m_credentials.IsEmpty() && !IsTimeToRefresh(m_loadFrequencyMs) && !ExpiresSoon()) - { - return; - } - - guard.UpgradeToWriterLock(); - + { + return; + } + + guard.UpgradeToWriterLock(); + if (!m_credentials.IsEmpty() && !IsTimeToRefresh(m_loadFrequencyMs) && !ExpiresSoon()) - { - return; - } - - Reload(); -} + { + return; + } + + Reload(); +} static const char PROCESS_LOG_TAG[] = "ProcessCredentialsProvider"; ProcessCredentialsProvider::ProcessCredentialsProvider() : diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSCredentialsProviderChain.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSCredentialsProviderChain.cpp index 373136d96a..299f288210 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSCredentialsProviderChain.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSCredentialsProviderChain.cpp @@ -2,76 +2,76 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/auth/AWSCredentialsProviderChain.h> + +#include <aws/core/auth/AWSCredentialsProviderChain.h> #include <aws/core/auth/STSCredentialsProvider.h> -#include <aws/core/platform/Environment.h> -#include <aws/core/utils/memory/AWSMemory.h> -#include <aws/core/utils/StringUtils.h> -#include <aws/core/utils/logging/LogMacros.h> - -using namespace Aws::Auth; - -static const char AWS_ECS_CONTAINER_CREDENTIALS_RELATIVE_URI[] = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"; -static const char AWS_ECS_CONTAINER_CREDENTIALS_FULL_URI[] = "AWS_CONTAINER_CREDENTIALS_FULL_URI"; -static const char AWS_ECS_CONTAINER_AUTHORIZATION_TOKEN[] = "AWS_CONTAINER_AUTHORIZATION_TOKEN"; -static const char AWS_EC2_METADATA_DISABLED[] = "AWS_EC2_METADATA_DISABLED"; -static const char DefaultCredentialsProviderChainTag[] = "DefaultAWSCredentialsProviderChain"; - -AWSCredentials AWSCredentialsProviderChain::GetAWSCredentials() -{ +#include <aws/core/platform/Environment.h> +#include <aws/core/utils/memory/AWSMemory.h> +#include <aws/core/utils/StringUtils.h> +#include <aws/core/utils/logging/LogMacros.h> + +using namespace Aws::Auth; + +static const char AWS_ECS_CONTAINER_CREDENTIALS_RELATIVE_URI[] = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"; +static const char AWS_ECS_CONTAINER_CREDENTIALS_FULL_URI[] = "AWS_CONTAINER_CREDENTIALS_FULL_URI"; +static const char AWS_ECS_CONTAINER_AUTHORIZATION_TOKEN[] = "AWS_CONTAINER_AUTHORIZATION_TOKEN"; +static const char AWS_EC2_METADATA_DISABLED[] = "AWS_EC2_METADATA_DISABLED"; +static const char DefaultCredentialsProviderChainTag[] = "DefaultAWSCredentialsProviderChain"; + +AWSCredentials AWSCredentialsProviderChain::GetAWSCredentials() +{ for (auto&& credentialsProvider : m_providerChain) - { - AWSCredentials credentials = credentialsProvider->GetAWSCredentials(); - if (!credentials.GetAWSAccessKeyId().empty() && !credentials.GetAWSSecretKey().empty()) - { - return credentials; - } - } - + { + AWSCredentials credentials = credentialsProvider->GetAWSCredentials(); + if (!credentials.GetAWSAccessKeyId().empty() && !credentials.GetAWSSecretKey().empty()) + { + return credentials; + } + } + return AWSCredentials(); -} - -DefaultAWSCredentialsProviderChain::DefaultAWSCredentialsProviderChain() : AWSCredentialsProviderChain() -{ - AddProvider(Aws::MakeShared<EnvironmentAWSCredentialsProvider>(DefaultCredentialsProviderChainTag)); - AddProvider(Aws::MakeShared<ProfileConfigFileAWSCredentialsProvider>(DefaultCredentialsProviderChainTag)); +} + +DefaultAWSCredentialsProviderChain::DefaultAWSCredentialsProviderChain() : AWSCredentialsProviderChain() +{ + AddProvider(Aws::MakeShared<EnvironmentAWSCredentialsProvider>(DefaultCredentialsProviderChainTag)); + AddProvider(Aws::MakeShared<ProfileConfigFileAWSCredentialsProvider>(DefaultCredentialsProviderChainTag)); AddProvider(Aws::MakeShared<ProcessCredentialsProvider>(DefaultCredentialsProviderChainTag)); AddProvider(Aws::MakeShared<STSAssumeRoleWebIdentityCredentialsProvider>(DefaultCredentialsProviderChainTag)); - //ECS TaskRole Credentials only available when ENVIRONMENT VARIABLE is set - const auto relativeUri = Aws::Environment::GetEnv(AWS_ECS_CONTAINER_CREDENTIALS_RELATIVE_URI); - AWS_LOGSTREAM_DEBUG(DefaultCredentialsProviderChainTag, "The environment variable value " << AWS_ECS_CONTAINER_CREDENTIALS_RELATIVE_URI - << " is " << relativeUri); - - const auto absoluteUri = Aws::Environment::GetEnv(AWS_ECS_CONTAINER_CREDENTIALS_FULL_URI); - AWS_LOGSTREAM_DEBUG(DefaultCredentialsProviderChainTag, "The environment variable value " << AWS_ECS_CONTAINER_CREDENTIALS_FULL_URI - << " is " << absoluteUri); - - const auto ec2MetadataDisabled = Aws::Environment::GetEnv(AWS_EC2_METADATA_DISABLED); - AWS_LOGSTREAM_DEBUG(DefaultCredentialsProviderChainTag, "The environment variable value " << AWS_EC2_METADATA_DISABLED - << " is " << ec2MetadataDisabled); - - if (!relativeUri.empty()) - { - AddProvider(Aws::MakeShared<TaskRoleCredentialsProvider>(DefaultCredentialsProviderChainTag, relativeUri.c_str())); - AWS_LOGSTREAM_INFO(DefaultCredentialsProviderChainTag, "Added ECS metadata service credentials provider with relative path: [" - << relativeUri << "] to the provider chain."); - } - else if (!absoluteUri.empty()) - { - const auto token = Aws::Environment::GetEnv(AWS_ECS_CONTAINER_AUTHORIZATION_TOKEN); - AddProvider(Aws::MakeShared<TaskRoleCredentialsProvider>(DefaultCredentialsProviderChainTag, - absoluteUri.c_str(), token.c_str())); - - //DO NOT log the value of the authorization token for security purposes. - AWS_LOGSTREAM_INFO(DefaultCredentialsProviderChainTag, "Added ECS credentials provider with URI: [" - << absoluteUri << "] to the provider chain with a" << (token.empty() ? "n empty " : " non-empty ") - << "authorization token."); - } - else if (Aws::Utils::StringUtils::ToLower(ec2MetadataDisabled.c_str()) != "true") - { - AddProvider(Aws::MakeShared<InstanceProfileCredentialsProvider>(DefaultCredentialsProviderChainTag)); - AWS_LOGSTREAM_INFO(DefaultCredentialsProviderChainTag, "Added EC2 metadata service credentials provider to the provider chain."); - } -} + //ECS TaskRole Credentials only available when ENVIRONMENT VARIABLE is set + const auto relativeUri = Aws::Environment::GetEnv(AWS_ECS_CONTAINER_CREDENTIALS_RELATIVE_URI); + AWS_LOGSTREAM_DEBUG(DefaultCredentialsProviderChainTag, "The environment variable value " << AWS_ECS_CONTAINER_CREDENTIALS_RELATIVE_URI + << " is " << relativeUri); + + const auto absoluteUri = Aws::Environment::GetEnv(AWS_ECS_CONTAINER_CREDENTIALS_FULL_URI); + AWS_LOGSTREAM_DEBUG(DefaultCredentialsProviderChainTag, "The environment variable value " << AWS_ECS_CONTAINER_CREDENTIALS_FULL_URI + << " is " << absoluteUri); + + const auto ec2MetadataDisabled = Aws::Environment::GetEnv(AWS_EC2_METADATA_DISABLED); + AWS_LOGSTREAM_DEBUG(DefaultCredentialsProviderChainTag, "The environment variable value " << AWS_EC2_METADATA_DISABLED + << " is " << ec2MetadataDisabled); + + if (!relativeUri.empty()) + { + AddProvider(Aws::MakeShared<TaskRoleCredentialsProvider>(DefaultCredentialsProviderChainTag, relativeUri.c_str())); + AWS_LOGSTREAM_INFO(DefaultCredentialsProviderChainTag, "Added ECS metadata service credentials provider with relative path: [" + << relativeUri << "] to the provider chain."); + } + else if (!absoluteUri.empty()) + { + const auto token = Aws::Environment::GetEnv(AWS_ECS_CONTAINER_AUTHORIZATION_TOKEN); + AddProvider(Aws::MakeShared<TaskRoleCredentialsProvider>(DefaultCredentialsProviderChainTag, + absoluteUri.c_str(), token.c_str())); + + //DO NOT log the value of the authorization token for security purposes. + AWS_LOGSTREAM_INFO(DefaultCredentialsProviderChainTag, "Added ECS credentials provider with URI: [" + << absoluteUri << "] to the provider chain with a" << (token.empty() ? "n empty " : " non-empty ") + << "authorization token."); + } + else if (Aws::Utils::StringUtils::ToLower(ec2MetadataDisabled.c_str()) != "true") + { + AddProvider(Aws::MakeShared<InstanceProfileCredentialsProvider>(DefaultCredentialsProviderChainTag)); + AWS_LOGSTREAM_INFO(DefaultCredentialsProviderChainTag, "Added EC2 metadata service credentials provider to the provider chain."); + } +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSClient.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSClient.cpp index e1ff064840..0a1d9e6388 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSClient.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSClient.cpp @@ -1,75 +1,75 @@ /** * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. - */ - -#include <aws/core/client/AWSClient.h> -#include <aws/core/AmazonWebServiceRequest.h> -#include <aws/core/auth/AWSAuthSigner.h> -#include <aws/core/auth/AWSAuthSignerProvider.h> -#include <aws/core/client/AWSError.h> -#include <aws/core/client/AWSErrorMarshaller.h> -#include <aws/core/client/ClientConfiguration.h> -#include <aws/core/client/CoreErrors.h> -#include <aws/core/client/RetryStrategy.h> -#include <aws/core/http/HttpClient.h> -#include <aws/core/http/HttpClientFactory.h> -#include <aws/core/http/HttpResponse.h> -#include <aws/core/http/standard/StandardHttpResponse.h> + */ + +#include <aws/core/client/AWSClient.h> +#include <aws/core/AmazonWebServiceRequest.h> +#include <aws/core/auth/AWSAuthSigner.h> +#include <aws/core/auth/AWSAuthSignerProvider.h> +#include <aws/core/client/AWSError.h> +#include <aws/core/client/AWSErrorMarshaller.h> +#include <aws/core/client/ClientConfiguration.h> +#include <aws/core/client/CoreErrors.h> +#include <aws/core/client/RetryStrategy.h> +#include <aws/core/http/HttpClient.h> +#include <aws/core/http/HttpClientFactory.h> +#include <aws/core/http/HttpResponse.h> +#include <aws/core/http/standard/StandardHttpResponse.h> #include <aws/core/http/URI.h> -#include <aws/core/utils/stream/ResponseStream.h> -#include <aws/core/utils/json/JsonSerializer.h> -#include <aws/core/utils/Outcome.h> -#include <aws/core/utils/StringUtils.h> -#include <aws/core/utils/xml/XmlSerializer.h> -#include <aws/core/utils/memory/stl/AWSStringStream.h> -#include <aws/core/utils/logging/LogMacros.h> -#include <aws/core/Globals.h> -#include <aws/core/utils/EnumParseOverflowContainer.h> -#include <aws/core/utils/crypto/MD5.h> -#include <aws/core/utils/HashingUtils.h> -#include <aws/core/utils/crypto/Factories.h> +#include <aws/core/utils/stream/ResponseStream.h> +#include <aws/core/utils/json/JsonSerializer.h> +#include <aws/core/utils/Outcome.h> +#include <aws/core/utils/StringUtils.h> +#include <aws/core/utils/xml/XmlSerializer.h> +#include <aws/core/utils/memory/stl/AWSStringStream.h> +#include <aws/core/utils/logging/LogMacros.h> +#include <aws/core/Globals.h> +#include <aws/core/utils/EnumParseOverflowContainer.h> +#include <aws/core/utils/crypto/MD5.h> +#include <aws/core/utils/HashingUtils.h> +#include <aws/core/utils/crypto/Factories.h> #include <aws/core/utils/event/EventStream.h> #include <aws/core/utils/UUID.h> -#include <aws/core/monitoring/MonitoringManager.h> +#include <aws/core/monitoring/MonitoringManager.h> #include <aws/core/Region.h> #include <aws/core/utils/DNS.h> #include <aws/core/Version.h> #include <aws/core/platform/OSVersionInfo.h> - + #include <cstring> #include <cassert> -using namespace Aws; -using namespace Aws::Client; -using namespace Aws::Http; -using namespace Aws::Utils; -using namespace Aws::Utils::Json; -using namespace Aws::Utils::Xml; - -static const int SUCCESS_RESPONSE_MIN = 200; -static const int SUCCESS_RESPONSE_MAX = 299; - -static const char AWS_CLIENT_LOG_TAG[] = "AWSClient"; -//4 Minutes +using namespace Aws; +using namespace Aws::Client; +using namespace Aws::Http; +using namespace Aws::Utils; +using namespace Aws::Utils::Json; +using namespace Aws::Utils::Xml; + +static const int SUCCESS_RESPONSE_MIN = 200; +static const int SUCCESS_RESPONSE_MAX = 299; + +static const char AWS_CLIENT_LOG_TAG[] = "AWSClient"; +//4 Minutes static const std::chrono::milliseconds TIME_DIFF_MAX = std::chrono::minutes(4); -//-4 Minutes -static const std::chrono::milliseconds TIME_DIFF_MIN = std::chrono::minutes(-4); - -static CoreErrors GuessBodylessErrorType(Aws::Http::HttpResponseCode responseCode) -{ - switch (responseCode) - { - case HttpResponseCode::FORBIDDEN: - case HttpResponseCode::UNAUTHORIZED: - return CoreErrors::ACCESS_DENIED; - case HttpResponseCode::NOT_FOUND: - return CoreErrors::RESOURCE_NOT_FOUND; - default: - return CoreErrors::UNKNOWN; +//-4 Minutes +static const std::chrono::milliseconds TIME_DIFF_MIN = std::chrono::minutes(-4); + +static CoreErrors GuessBodylessErrorType(Aws::Http::HttpResponseCode responseCode) +{ + switch (responseCode) + { + case HttpResponseCode::FORBIDDEN: + case HttpResponseCode::UNAUTHORIZED: + return CoreErrors::ACCESS_DENIED; + case HttpResponseCode::NOT_FOUND: + return CoreErrors::RESOURCE_NOT_FOUND; + default: + return CoreErrors::UNKNOWN; } -} - +} + struct RequestInfo { Aws::Utils::DateTime ttl; @@ -93,44 +93,44 @@ struct RequestInfo } }; -AWSClient::AWSClient(const Aws::Client::ClientConfiguration& configuration, - const std::shared_ptr<Aws::Client::AWSAuthSigner>& signer, - const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) : +AWSClient::AWSClient(const Aws::Client::ClientConfiguration& configuration, + const std::shared_ptr<Aws::Client::AWSAuthSigner>& signer, + const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) : m_region(configuration.region), - m_httpClient(CreateHttpClient(configuration)), - m_signerProvider(Aws::MakeUnique<Aws::Auth::DefaultAuthSignerProvider>(AWS_CLIENT_LOG_TAG, signer)), - m_errorMarshaller(errorMarshaller), - m_retryStrategy(configuration.retryStrategy), - m_writeRateLimiter(configuration.writeRateLimiter), - m_readRateLimiter(configuration.readRateLimiter), - m_userAgent(configuration.userAgent), + m_httpClient(CreateHttpClient(configuration)), + m_signerProvider(Aws::MakeUnique<Aws::Auth::DefaultAuthSignerProvider>(AWS_CLIENT_LOG_TAG, signer)), + m_errorMarshaller(errorMarshaller), + m_retryStrategy(configuration.retryStrategy), + m_writeRateLimiter(configuration.writeRateLimiter), + m_readRateLimiter(configuration.readRateLimiter), + m_userAgent(configuration.userAgent), m_customizedUserAgent(!m_userAgent.empty()), - m_hash(Aws::Utils::Crypto::CreateMD5Implementation()), + m_hash(Aws::Utils::Crypto::CreateMD5Implementation()), m_requestTimeoutMs(configuration.requestTimeoutMs), - m_enableClockSkewAdjustment(configuration.enableClockSkewAdjustment) -{ + m_enableClockSkewAdjustment(configuration.enableClockSkewAdjustment) +{ SetServiceClientName("AWSBaseClient"); -} - -AWSClient::AWSClient(const Aws::Client::ClientConfiguration& configuration, - const std::shared_ptr<Aws::Auth::AWSAuthSignerProvider>& signerProvider, - const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) : +} + +AWSClient::AWSClient(const Aws::Client::ClientConfiguration& configuration, + const std::shared_ptr<Aws::Auth::AWSAuthSignerProvider>& signerProvider, + const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) : m_region(configuration.region), - m_httpClient(CreateHttpClient(configuration)), - m_signerProvider(signerProvider), - m_errorMarshaller(errorMarshaller), - m_retryStrategy(configuration.retryStrategy), - m_writeRateLimiter(configuration.writeRateLimiter), - m_readRateLimiter(configuration.readRateLimiter), - m_userAgent(configuration.userAgent), + m_httpClient(CreateHttpClient(configuration)), + m_signerProvider(signerProvider), + m_errorMarshaller(errorMarshaller), + m_retryStrategy(configuration.retryStrategy), + m_writeRateLimiter(configuration.writeRateLimiter), + m_readRateLimiter(configuration.readRateLimiter), + m_userAgent(configuration.userAgent), m_customizedUserAgent(!m_userAgent.empty()), - m_hash(Aws::Utils::Crypto::CreateMD5Implementation()), + m_hash(Aws::Utils::Crypto::CreateMD5Implementation()), m_requestTimeoutMs(configuration.requestTimeoutMs), - m_enableClockSkewAdjustment(configuration.enableClockSkewAdjustment) -{ + m_enableClockSkewAdjustment(configuration.enableClockSkewAdjustment) +{ SetServiceClientName("AWSBaseClient"); -} - +} + void AWSClient::SetServiceClientName(const Aws::String& name) { m_serviceName = name; @@ -141,8 +141,8 @@ void AWSClient::SetServiceClientName(const Aws::String& name) << " " << Version::GetCompilerVersionString(); m_userAgent = ss.str(); } -} - +} + void AWSClient::DisableRequestProcessing() { m_httpClient->DisableRequestProcessing(); @@ -150,15 +150,15 @@ void AWSClient::DisableRequestProcessing() void AWSClient::EnableRequestProcessing() { - m_httpClient->EnableRequestProcessing(); -} - -Aws::Client::AWSAuthSigner* AWSClient::GetSignerByName(const char* name) const -{ - const auto& signer = m_signerProvider->GetSigner(name); - return signer ? signer.get() : nullptr; -} - + m_httpClient->EnableRequestProcessing(); +} + +Aws::Client::AWSAuthSigner* AWSClient::GetSignerByName(const char* name) const +{ + const auto& signer = m_signerProvider->GetSigner(name); + return signer ? signer.get() : nullptr; +} + static DateTime GetServerTimeFromError(const AWSError<CoreErrors> error) { const Http::HeaderValueCollection& headers = error.GetResponseHeaders(); @@ -178,60 +178,60 @@ static DateTime GetServerTimeFromError(const AWSError<CoreErrors> error) } } -bool AWSClient::AdjustClockSkew(HttpResponseOutcome& outcome, const char* signerName) const -{ - if (m_enableClockSkewAdjustment) - { - auto signer = GetSignerByName(signerName); +bool AWSClient::AdjustClockSkew(HttpResponseOutcome& outcome, const char* signerName) const +{ + if (m_enableClockSkewAdjustment) + { + auto signer = GetSignerByName(signerName); //detect clock skew and try to correct. - AWS_LOGSTREAM_WARN(AWS_CLIENT_LOG_TAG, "If the signature check failed. This could be because of a time skew. Attempting to adjust the signer."); - + AWS_LOGSTREAM_WARN(AWS_CLIENT_LOG_TAG, "If the signature check failed. This could be because of a time skew. Attempting to adjust the signer."); + DateTime serverTime = GetServerTimeFromError(outcome.GetError()); - const auto signingTimestamp = signer->GetSigningTimestamp(); - if (!serverTime.WasParseSuccessful() || serverTime == DateTime()) - { - AWS_LOGSTREAM_DEBUG(AWS_CLIENT_LOG_TAG, "Date header was not found in the response, can't attempt to detect clock skew"); - return false; - } - - AWS_LOGSTREAM_DEBUG(AWS_CLIENT_LOG_TAG, "Server time is " << serverTime.ToGmtString(DateFormat::RFC822) << ", while client time is " << DateTime::Now().ToGmtString(DateFormat::RFC822)); - auto diff = DateTime::Diff(serverTime, signingTimestamp); - //only try again if clock skew was the cause of the error. - if (diff >= TIME_DIFF_MAX || diff <= TIME_DIFF_MIN) - { - diff = DateTime::Diff(serverTime, DateTime::Now()); - AWS_LOGSTREAM_INFO(AWS_CLIENT_LOG_TAG, "Computed time difference as " << diff.count() << " milliseconds. Adjusting signer with the skew."); - signer->SetClockSkew(diff); + const auto signingTimestamp = signer->GetSigningTimestamp(); + if (!serverTime.WasParseSuccessful() || serverTime == DateTime()) + { + AWS_LOGSTREAM_DEBUG(AWS_CLIENT_LOG_TAG, "Date header was not found in the response, can't attempt to detect clock skew"); + return false; + } + + AWS_LOGSTREAM_DEBUG(AWS_CLIENT_LOG_TAG, "Server time is " << serverTime.ToGmtString(DateFormat::RFC822) << ", while client time is " << DateTime::Now().ToGmtString(DateFormat::RFC822)); + auto diff = DateTime::Diff(serverTime, signingTimestamp); + //only try again if clock skew was the cause of the error. + if (diff >= TIME_DIFF_MAX || diff <= TIME_DIFF_MIN) + { + diff = DateTime::Diff(serverTime, DateTime::Now()); + AWS_LOGSTREAM_INFO(AWS_CLIENT_LOG_TAG, "Computed time difference as " << diff.count() << " milliseconds. Adjusting signer with the skew."); + signer->SetClockSkew(diff); AWSError<CoreErrors> newError( - outcome.GetError().GetErrorType(), outcome.GetError().GetExceptionName(), outcome.GetError().GetMessage(), true); - newError.SetResponseHeaders(outcome.GetError().GetResponseHeaders()); - newError.SetResponseCode(outcome.GetError().GetResponseCode()); + outcome.GetError().GetErrorType(), outcome.GetError().GetExceptionName(), outcome.GetError().GetMessage(), true); + newError.SetResponseHeaders(outcome.GetError().GetResponseHeaders()); + newError.SetResponseCode(outcome.GetError().GetResponseCode()); outcome = std::move(newError); - return true; - } - } - return false; -} - -HttpResponseOutcome AWSClient::AttemptExhaustively(const Aws::Http::URI& uri, - const Aws::AmazonWebServiceRequest& request, - HttpMethod method, + return true; + } + } + return false; +} + +HttpResponseOutcome AWSClient::AttemptExhaustively(const Aws::Http::URI& uri, + const Aws::AmazonWebServiceRequest& request, + HttpMethod method, const char* signerName, const char* signerRegionOverride, const char* signerServiceNameOverride) const -{ +{ if (!Aws::Utils::IsValidHost(uri.GetAuthority())) { return HttpResponseOutcome(AWSError<CoreErrors>(CoreErrors::VALIDATION, "", "Invalid DNS Label found in URI host", false/*retryable*/)); } - std::shared_ptr<HttpRequest> httpRequest(CreateHttpRequest(uri, method, request.GetResponseStreamFactory())); - HttpResponseOutcome outcome; + std::shared_ptr<HttpRequest> httpRequest(CreateHttpRequest(uri, method, request.GetResponseStreamFactory())); + HttpResponseOutcome outcome; AWSError<CoreErrors> lastError; - Aws::Monitoring::CoreMetricsCollection coreMetrics; - auto contexts = Aws::Monitoring::OnRequestStarted(this->GetServiceClientName(), request.GetServiceRequestName(), httpRequest); + Aws::Monitoring::CoreMetricsCollection coreMetrics; + auto contexts = Aws::Monitoring::OnRequestStarted(this->GetServiceClientName(), request.GetServiceRequestName(), httpRequest); const char* signerRegion = signerRegionOverride; Aws::String regionFromResponse; - + Aws::String invocationId = UUID::RandomUUID(); RequestInfo requestInfo; requestInfo.attempt = 1; @@ -239,8 +239,8 @@ HttpResponseOutcome AWSClient::AttemptExhaustively(const Aws::Http::URI& uri, httpRequest->SetHeaderValue(Http::SDK_INVOCATION_ID_HEADER, invocationId); httpRequest->SetHeaderValue(Http::SDK_REQUEST_HEADER, requestInfo); - for (long retries = 0;; retries++) - { + for (long retries = 0;; retries++) + { m_retryStrategy->GetSendToken(); httpRequest->SetEventStreamRequest(request.IsEventStreamRequest()); @@ -253,26 +253,26 @@ HttpResponseOutcome AWSClient::AttemptExhaustively(const Aws::Http::URI& uri, { m_retryStrategy->RequestBookkeeping(outcome, lastError); } - coreMetrics.httpClientMetrics = httpRequest->GetRequestMetrics(); - if (outcome.IsSuccess()) - { - Aws::Monitoring::OnRequestSucceeded(this->GetServiceClientName(), request.GetServiceRequestName(), httpRequest, outcome, coreMetrics, contexts); - AWS_LOGSTREAM_TRACE(AWS_CLIENT_LOG_TAG, "Request successful returning."); - break; - } + coreMetrics.httpClientMetrics = httpRequest->GetRequestMetrics(); + if (outcome.IsSuccess()) + { + Aws::Monitoring::OnRequestSucceeded(this->GetServiceClientName(), request.GetServiceRequestName(), httpRequest, outcome, coreMetrics, contexts); + AWS_LOGSTREAM_TRACE(AWS_CLIENT_LOG_TAG, "Request successful returning."); + break; + } lastError = outcome.GetError(); - + DateTime serverTime = GetServerTimeFromError(outcome.GetError()); auto clockSkew = DateTime::Diff(serverTime, DateTime::Now()); - Aws::Monitoring::OnRequestFailed(this->GetServiceClientName(), request.GetServiceRequestName(), httpRequest, outcome, coreMetrics, contexts); - - if (!m_httpClient->IsRequestProcessingEnabled()) - { - AWS_LOGSTREAM_TRACE(AWS_CLIENT_LOG_TAG, "Request was cancelled externally."); - break; - } - + Aws::Monitoring::OnRequestFailed(this->GetServiceClientName(), request.GetServiceRequestName(), httpRequest, outcome, coreMetrics, contexts); + + if (!m_httpClient->IsRequestProcessingEnabled()) + { + AWS_LOGSTREAM_TRACE(AWS_CLIENT_LOG_TAG, "Request was cancelled externally."); + break; + } + // Adjust region bool retryWithCorrectRegion = false; HttpResponseCode httpResponseCode = outcome.GetError().GetResponseCode(); @@ -289,32 +289,32 @@ HttpResponseOutcome AWSClient::AttemptExhaustively(const Aws::Http::URI& uri, } } - long sleepMillis = m_retryStrategy->CalculateDelayBeforeNextRetry(outcome.GetError(), retries); - //AdjustClockSkew returns true means clock skew was the problem and skew was adjusted, false otherwise. + long sleepMillis = m_retryStrategy->CalculateDelayBeforeNextRetry(outcome.GetError(), retries); + //AdjustClockSkew returns true means clock skew was the problem and skew was adjusted, false otherwise. //sleep if clock skew and region was NOT the problem. AdjustClockSkew may update error inside outcome. bool shouldSleep = !AdjustClockSkew(outcome, signerName) && !retryWithCorrectRegion; - + if (!retryWithCorrectRegion && !m_retryStrategy->ShouldRetry(outcome.GetError(), retries)) - { - break; - } - - AWS_LOGSTREAM_WARN(AWS_CLIENT_LOG_TAG, "Request failed, now waiting " << sleepMillis << " ms before attempting again."); - if(request.GetBody()) - { - request.GetBody()->clear(); - request.GetBody()->seekg(0); - } - - if (request.GetRequestRetryHandler()) - { - request.GetRequestRetryHandler()(request); - } - - if (shouldSleep) - { - m_httpClient->RetryRequestSleep(std::chrono::milliseconds(sleepMillis)); - } + { + break; + } + + AWS_LOGSTREAM_WARN(AWS_CLIENT_LOG_TAG, "Request failed, now waiting " << sleepMillis << " ms before attempting again."); + if(request.GetBody()) + { + request.GetBody()->clear(); + request.GetBody()->seekg(0); + } + + if (request.GetRequestRetryHandler()) + { + request.GetRequestRetryHandler()(request); + } + + if (shouldSleep) + { + m_httpClient->RetryRequestSleep(std::chrono::milliseconds(sleepMillis)); + } Aws::Http::URI newUri = uri; Aws::String newEndpoint = GetErrorMarshaller()->ExtractEndpoint(outcome.GetError()); @@ -332,32 +332,32 @@ HttpResponseOutcome AWSClient::AttemptExhaustively(const Aws::Http::URI& uri, requestInfo.attempt ++; requestInfo.maxAttempts = m_retryStrategy->GetMaxAttempts(); httpRequest->SetHeaderValue(Http::SDK_REQUEST_HEADER, requestInfo); - Aws::Monitoring::OnRequestRetry(this->GetServiceClientName(), request.GetServiceRequestName(), httpRequest, contexts); - } - Aws::Monitoring::OnFinish(this->GetServiceClientName(), request.GetServiceRequestName(), httpRequest, contexts); - return outcome; -} - + Aws::Monitoring::OnRequestRetry(this->GetServiceClientName(), request.GetServiceRequestName(), httpRequest, contexts); + } + Aws::Monitoring::OnFinish(this->GetServiceClientName(), request.GetServiceRequestName(), httpRequest, contexts); + return outcome; +} + HttpResponseOutcome AWSClient::AttemptExhaustively(const Aws::Http::URI& uri, HttpMethod method, const char* signerName, const char* requestName, const char* signerRegionOverride, const char* signerServiceNameOverride) const -{ +{ if (!Aws::Utils::IsValidHost(uri.GetAuthority())) { return HttpResponseOutcome(AWSError<CoreErrors>(CoreErrors::VALIDATION, "", "Invalid DNS Label found in URI host", false/*retryable*/)); } - std::shared_ptr<HttpRequest> httpRequest(CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod)); - HttpResponseOutcome outcome; + std::shared_ptr<HttpRequest> httpRequest(CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod)); + HttpResponseOutcome outcome; AWSError<CoreErrors> lastError; - Aws::Monitoring::CoreMetricsCollection coreMetrics; - auto contexts = Aws::Monitoring::OnRequestStarted(this->GetServiceClientName(), requestName, httpRequest); + Aws::Monitoring::CoreMetricsCollection coreMetrics; + auto contexts = Aws::Monitoring::OnRequestStarted(this->GetServiceClientName(), requestName, httpRequest); const char* signerRegion = signerRegionOverride; Aws::String regionFromResponse; - + Aws::String invocationId = UUID::RandomUUID(); RequestInfo requestInfo; requestInfo.attempt = 1; @@ -365,8 +365,8 @@ HttpResponseOutcome AWSClient::AttemptExhaustively(const Aws::Http::URI& uri, httpRequest->SetHeaderValue(Http::SDK_INVOCATION_ID_HEADER, invocationId); httpRequest->SetHeaderValue(Http::SDK_REQUEST_HEADER, requestInfo); - for (long retries = 0;; retries++) - { + for (long retries = 0;; retries++) + { m_retryStrategy->GetSendToken(); outcome = AttemptOneRequest(httpRequest, signerName, requestName, signerRegion, signerServiceNameOverride); if (retries == 0) @@ -377,26 +377,26 @@ HttpResponseOutcome AWSClient::AttemptExhaustively(const Aws::Http::URI& uri, { m_retryStrategy->RequestBookkeeping(outcome, lastError); } - coreMetrics.httpClientMetrics = httpRequest->GetRequestMetrics(); - if (outcome.IsSuccess()) - { - Aws::Monitoring::OnRequestSucceeded(this->GetServiceClientName(), requestName, httpRequest, outcome, coreMetrics, contexts); - AWS_LOGSTREAM_TRACE(AWS_CLIENT_LOG_TAG, "Request successful returning."); - break; - } + coreMetrics.httpClientMetrics = httpRequest->GetRequestMetrics(); + if (outcome.IsSuccess()) + { + Aws::Monitoring::OnRequestSucceeded(this->GetServiceClientName(), requestName, httpRequest, outcome, coreMetrics, contexts); + AWS_LOGSTREAM_TRACE(AWS_CLIENT_LOG_TAG, "Request successful returning."); + break; + } lastError = outcome.GetError(); - + DateTime serverTime = GetServerTimeFromError(outcome.GetError()); auto clockSkew = DateTime::Diff(serverTime, DateTime::Now()); - Aws::Monitoring::OnRequestFailed(this->GetServiceClientName(), requestName, httpRequest, outcome, coreMetrics, contexts); - - if (!m_httpClient->IsRequestProcessingEnabled()) - { - AWS_LOGSTREAM_TRACE(AWS_CLIENT_LOG_TAG, "Request was cancelled externally."); - break; - } - + Aws::Monitoring::OnRequestFailed(this->GetServiceClientName(), requestName, httpRequest, outcome, coreMetrics, contexts); + + if (!m_httpClient->IsRequestProcessingEnabled()) + { + AWS_LOGSTREAM_TRACE(AWS_CLIENT_LOG_TAG, "Request was cancelled externally."); + break; + } + // Adjust region bool retryWithCorrectRegion = false; HttpResponseCode httpResponseCode = outcome.GetError().GetResponseCode(); @@ -413,22 +413,22 @@ HttpResponseOutcome AWSClient::AttemptExhaustively(const Aws::Http::URI& uri, } } - long sleepMillis = m_retryStrategy->CalculateDelayBeforeNextRetry(outcome.GetError(), retries); - //AdjustClockSkew returns true means clock skew was the problem and skew was adjusted, false otherwise. + long sleepMillis = m_retryStrategy->CalculateDelayBeforeNextRetry(outcome.GetError(), retries); + //AdjustClockSkew returns true means clock skew was the problem and skew was adjusted, false otherwise. //sleep if clock skew and region was NOT the problem. AdjustClockSkew may update error inside outcome. bool shouldSleep = !AdjustClockSkew(outcome, signerName) && !retryWithCorrectRegion; - + if (!retryWithCorrectRegion && !m_retryStrategy->ShouldRetry(outcome.GetError(), retries)) - { - break; - } - - AWS_LOGSTREAM_WARN(AWS_CLIENT_LOG_TAG, "Request failed, now waiting " << sleepMillis << " ms before attempting again."); - - if (shouldSleep) - { - m_httpClient->RetryRequestSleep(std::chrono::milliseconds(sleepMillis)); - } + { + break; + } + + AWS_LOGSTREAM_WARN(AWS_CLIENT_LOG_TAG, "Request failed, now waiting " << sleepMillis << " ms before attempting again."); + + if (shouldSleep) + { + m_httpClient->RetryRequestSleep(std::chrono::milliseconds(sleepMillis)); + } Aws::Http::URI newUri = uri; Aws::String newEndpoint = GetErrorMarshaller()->ExtractEndpoint(outcome.GetError()); @@ -446,120 +446,120 @@ HttpResponseOutcome AWSClient::AttemptExhaustively(const Aws::Http::URI& uri, requestInfo.attempt ++; requestInfo.maxAttempts = m_retryStrategy->GetMaxAttempts(); httpRequest->SetHeaderValue(Http::SDK_REQUEST_HEADER, requestInfo); - Aws::Monitoring::OnRequestRetry(this->GetServiceClientName(), requestName, httpRequest, contexts); - } - Aws::Monitoring::OnFinish(this->GetServiceClientName(), requestName, httpRequest, contexts); - return outcome; -} - -static bool DoesResponseGenerateError(const std::shared_ptr<HttpResponse>& response) -{ + Aws::Monitoring::OnRequestRetry(this->GetServiceClientName(), requestName, httpRequest, contexts); + } + Aws::Monitoring::OnFinish(this->GetServiceClientName(), requestName, httpRequest, contexts); + return outcome; +} + +static bool DoesResponseGenerateError(const std::shared_ptr<HttpResponse>& response) +{ if (response->HasClientError()) return true; - - int responseCode = static_cast<int>(response->GetResponseCode()); - return responseCode < SUCCESS_RESPONSE_MIN || responseCode > SUCCESS_RESPONSE_MAX; - -} - + + int responseCode = static_cast<int>(response->GetResponseCode()); + return responseCode < SUCCESS_RESPONSE_MIN || responseCode > SUCCESS_RESPONSE_MAX; + +} + HttpResponseOutcome AWSClient::AttemptOneRequest(const std::shared_ptr<HttpRequest>& httpRequest, const Aws::AmazonWebServiceRequest& request, const char* signerName, const char* signerRegionOverride, const char* signerServiceNameOverride) const -{ - BuildHttpRequest(request, httpRequest); - auto signer = GetSignerByName(signerName); +{ + BuildHttpRequest(request, httpRequest); + auto signer = GetSignerByName(signerName); if (!signer->SignRequest(*httpRequest, signerRegionOverride, signerServiceNameOverride, request.SignBody())) - { - AWS_LOGSTREAM_ERROR(AWS_CLIENT_LOG_TAG, "Request signing failed. Returning error."); - return HttpResponseOutcome(AWSError<CoreErrors>(CoreErrors::CLIENT_SIGNING_FAILURE, "", "SDK failed to sign the request", false/*retryable*/)); - } - + { + AWS_LOGSTREAM_ERROR(AWS_CLIENT_LOG_TAG, "Request signing failed. Returning error."); + return HttpResponseOutcome(AWSError<CoreErrors>(CoreErrors::CLIENT_SIGNING_FAILURE, "", "SDK failed to sign the request", false/*retryable*/)); + } + if (request.GetRequestSignedHandler()) { request.GetRequestSignedHandler()(*httpRequest); } - AWS_LOGSTREAM_DEBUG(AWS_CLIENT_LOG_TAG, "Request Successfully signed"); - std::shared_ptr<HttpResponse> httpResponse( - m_httpClient->MakeRequest(httpRequest, m_readRateLimiter.get(), m_writeRateLimiter.get())); - - if (DoesResponseGenerateError(httpResponse)) - { - AWS_LOGSTREAM_DEBUG(AWS_CLIENT_LOG_TAG, "Request returned error. Attempting to generate appropriate error codes from response"); + AWS_LOGSTREAM_DEBUG(AWS_CLIENT_LOG_TAG, "Request Successfully signed"); + std::shared_ptr<HttpResponse> httpResponse( + m_httpClient->MakeRequest(httpRequest, m_readRateLimiter.get(), m_writeRateLimiter.get())); + + if (DoesResponseGenerateError(httpResponse)) + { + AWS_LOGSTREAM_DEBUG(AWS_CLIENT_LOG_TAG, "Request returned error. Attempting to generate appropriate error codes from response"); auto error = BuildAWSError(httpResponse); return HttpResponseOutcome(std::move(error)); - } - - AWS_LOGSTREAM_DEBUG(AWS_CLIENT_LOG_TAG, "Request returned successful response."); - + } + + AWS_LOGSTREAM_DEBUG(AWS_CLIENT_LOG_TAG, "Request returned successful response."); + return HttpResponseOutcome(std::move(httpResponse)); -} - +} + HttpResponseOutcome AWSClient::AttemptOneRequest(const std::shared_ptr<HttpRequest>& httpRequest, const char* signerName, const char* requestName, const char* signerRegionOverride, const char* signerServiceNameOverride) const -{ - AWS_UNREFERENCED_PARAM(requestName); - - auto signer = GetSignerByName(signerName); +{ + AWS_UNREFERENCED_PARAM(requestName); + + auto signer = GetSignerByName(signerName); if (!signer->SignRequest(*httpRequest, signerRegionOverride, signerServiceNameOverride, true)) - { - AWS_LOGSTREAM_ERROR(AWS_CLIENT_LOG_TAG, "Request signing failed. Returning error."); - return HttpResponseOutcome(AWSError<CoreErrors>(CoreErrors::CLIENT_SIGNING_FAILURE, "", "SDK failed to sign the request", false/*retryable*/)); - } - - //user agent and headers like that shouldn't be signed for the sake of compatibility with proxies which MAY mutate that header. - AddCommonHeaders(*httpRequest); - - AWS_LOGSTREAM_DEBUG(AWS_CLIENT_LOG_TAG, "Request Successfully signed"); - std::shared_ptr<HttpResponse> httpResponse( - m_httpClient->MakeRequest(httpRequest, m_readRateLimiter.get(), m_writeRateLimiter.get())); - - if (DoesResponseGenerateError(httpResponse)) - { - AWS_LOGSTREAM_DEBUG(AWS_CLIENT_LOG_TAG, "Request returned error. Attempting to generate appropriate error codes from response"); + { + AWS_LOGSTREAM_ERROR(AWS_CLIENT_LOG_TAG, "Request signing failed. Returning error."); + return HttpResponseOutcome(AWSError<CoreErrors>(CoreErrors::CLIENT_SIGNING_FAILURE, "", "SDK failed to sign the request", false/*retryable*/)); + } + + //user agent and headers like that shouldn't be signed for the sake of compatibility with proxies which MAY mutate that header. + AddCommonHeaders(*httpRequest); + + AWS_LOGSTREAM_DEBUG(AWS_CLIENT_LOG_TAG, "Request Successfully signed"); + std::shared_ptr<HttpResponse> httpResponse( + m_httpClient->MakeRequest(httpRequest, m_readRateLimiter.get(), m_writeRateLimiter.get())); + + if (DoesResponseGenerateError(httpResponse)) + { + AWS_LOGSTREAM_DEBUG(AWS_CLIENT_LOG_TAG, "Request returned error. Attempting to generate appropriate error codes from response"); auto error = BuildAWSError(httpResponse); return HttpResponseOutcome(std::move(error)); - } - - AWS_LOGSTREAM_DEBUG(AWS_CLIENT_LOG_TAG, "Request returned successful response."); - + } + + AWS_LOGSTREAM_DEBUG(AWS_CLIENT_LOG_TAG, "Request returned successful response."); + return HttpResponseOutcome(std::move(httpResponse)); -} - -StreamOutcome AWSClient::MakeRequestWithUnparsedResponse(const Aws::Http::URI& uri, - const Aws::AmazonWebServiceRequest& request, - Http::HttpMethod method, +} + +StreamOutcome AWSClient::MakeRequestWithUnparsedResponse(const Aws::Http::URI& uri, + const Aws::AmazonWebServiceRequest& request, + Http::HttpMethod method, const char* signerName, const char* signerRegionOverride, const char* signerServiceNameOverride) const -{ +{ HttpResponseOutcome httpResponseOutcome = AttemptExhaustively(uri, request, method, signerName, signerRegionOverride, signerServiceNameOverride); - if (httpResponseOutcome.IsSuccess()) - { - return StreamOutcome(AmazonWebServiceResult<Stream::ResponseStream>( - httpResponseOutcome.GetResult()->SwapResponseStreamOwnership(), - httpResponseOutcome.GetResult()->GetHeaders(), httpResponseOutcome.GetResult()->GetResponseCode())); - } - + if (httpResponseOutcome.IsSuccess()) + { + return StreamOutcome(AmazonWebServiceResult<Stream::ResponseStream>( + httpResponseOutcome.GetResult()->SwapResponseStreamOwnership(), + httpResponseOutcome.GetResult()->GetHeaders(), httpResponseOutcome.GetResult()->GetResponseCode())); + } + return StreamOutcome(std::move(httpResponseOutcome)); -} - +} + StreamOutcome AWSClient::MakeRequestWithUnparsedResponse(const Aws::Http::URI& uri, Http::HttpMethod method, const char* signerName, const char* requestName, const char* signerRegionOverride, const char* signerServiceNameOverride) const -{ +{ HttpResponseOutcome httpResponseOutcome = AttemptExhaustively(uri, method, signerName, requestName, signerRegionOverride, signerServiceNameOverride); - if (httpResponseOutcome.IsSuccess()) - { - return StreamOutcome(AmazonWebServiceResult<Stream::ResponseStream>( - httpResponseOutcome.GetResult()->SwapResponseStreamOwnership(), - httpResponseOutcome.GetResult()->GetHeaders(), httpResponseOutcome.GetResult()->GetResponseCode())); - } - + if (httpResponseOutcome.IsSuccess()) + { + return StreamOutcome(AmazonWebServiceResult<Stream::ResponseStream>( + httpResponseOutcome.GetResult()->SwapResponseStreamOwnership(), + httpResponseOutcome.GetResult()->GetHeaders(), httpResponseOutcome.GetResult()->GetResponseCode())); + } + return StreamOutcome(std::move(httpResponseOutcome)); -} - +} + XmlOutcome AWSXMLClient::MakeRequestWithEventStream(const Aws::Http::URI& uri, const Aws::AmazonWebServiceRequest& request, Http::HttpMethod method, @@ -592,80 +592,80 @@ XmlOutcome AWSXMLClient::MakeRequestWithEventStream(const Aws::Http::URI& uri, return XmlOutcome(std::move(httpOutcome)); } -void AWSClient::AddHeadersToRequest(const std::shared_ptr<Aws::Http::HttpRequest>& httpRequest, - const Http::HeaderValueCollection& headerValues) const -{ - for (auto const& headerValue : headerValues) - { - httpRequest->SetHeaderValue(headerValue.first, headerValue.second); - } - - AddCommonHeaders(*httpRequest); -} - -void AWSClient::AddContentBodyToRequest(const std::shared_ptr<Aws::Http::HttpRequest>& httpRequest, +void AWSClient::AddHeadersToRequest(const std::shared_ptr<Aws::Http::HttpRequest>& httpRequest, + const Http::HeaderValueCollection& headerValues) const +{ + for (auto const& headerValue : headerValues) + { + httpRequest->SetHeaderValue(headerValue.first, headerValue.second); + } + + AddCommonHeaders(*httpRequest); +} + +void AWSClient::AddContentBodyToRequest(const std::shared_ptr<Aws::Http::HttpRequest>& httpRequest, const std::shared_ptr<Aws::IOStream>& body, bool needsContentMd5, bool isChunked) const -{ - httpRequest->AddContentBody(body); - - //If there is no body, we have a content length of 0 - //note: we also used to remove content-type, but S3 actually needs content-type on InitiateMultipartUpload and it isn't - //forbiden by the spec. If we start getting weird errors related to this, make sure it isn't caused by this removal. - if (!body) - { - AWS_LOGSTREAM_TRACE(AWS_CLIENT_LOG_TAG, "No content body, content-length headers"); - - if(httpRequest->GetMethod() == HttpMethod::HTTP_POST || httpRequest->GetMethod() == HttpMethod::HTTP_PUT) +{ + httpRequest->AddContentBody(body); + + //If there is no body, we have a content length of 0 + //note: we also used to remove content-type, but S3 actually needs content-type on InitiateMultipartUpload and it isn't + //forbiden by the spec. If we start getting weird errors related to this, make sure it isn't caused by this removal. + if (!body) + { + AWS_LOGSTREAM_TRACE(AWS_CLIENT_LOG_TAG, "No content body, content-length headers"); + + if(httpRequest->GetMethod() == HttpMethod::HTTP_POST || httpRequest->GetMethod() == HttpMethod::HTTP_PUT) { httpRequest->SetHeaderValue(Http::CONTENT_LENGTH_HEADER, "0"); - } - else - { - httpRequest->DeleteHeader(Http::CONTENT_LENGTH_HEADER); - } - } - + } + else + { + httpRequest->DeleteHeader(Http::CONTENT_LENGTH_HEADER); + } + } + //Add transfer-encoding:chunked to header if (body && isChunked) { httpRequest->SetTransferEncoding(CHUNKED_VALUE); } - //in the scenario where we are adding a content body as a stream, the request object likely already - //has a content-length header set and we don't want to seek the stream just to find this information. + //in the scenario where we are adding a content body as a stream, the request object likely already + //has a content-length header set and we don't want to seek the stream just to find this information. else if (body && !httpRequest->HasHeader(Http::CONTENT_LENGTH_HEADER)) - { + { if (!m_httpClient->SupportsChunkedTransferEncoding()) { AWS_LOGSTREAM_WARN(AWS_CLIENT_LOG_TAG, "This http client doesn't support transfer-encoding:chunked. " << "The request may fail if it's not a seekable stream."); } - AWS_LOGSTREAM_TRACE(AWS_CLIENT_LOG_TAG, "Found body, but content-length has not been set, attempting to compute content-length"); - body->seekg(0, body->end); - auto streamSize = body->tellg(); - body->seekg(0, body->beg); - Aws::StringStream ss; - ss << streamSize; - httpRequest->SetContentLength(ss.str()); - } - - if (needsContentMd5 && body && !httpRequest->HasHeader(Http::CONTENT_MD5_HEADER)) - { - AWS_LOGSTREAM_TRACE(AWS_CLIENT_LOG_TAG, "Found body, and content-md5 needs to be set" << - ", attempting to compute content-md5"); - - //changing the internal state of the hash computation is not a logical state - //change as far as constness goes for this class. Due to the platform specificness - //of hash computations, we can't control the fact that computing a hash mutates - //state on some platforms such as windows (but that isn't a concern of this class. - auto md5HashResult = const_cast<AWSClient*>(this)->m_hash->Calculate(*body); - body->clear(); - if (md5HashResult.IsSuccess()) - { - httpRequest->SetHeaderValue(Http::CONTENT_MD5_HEADER, HashingUtils::Base64Encode(md5HashResult.GetResult())); - } - } -} - + AWS_LOGSTREAM_TRACE(AWS_CLIENT_LOG_TAG, "Found body, but content-length has not been set, attempting to compute content-length"); + body->seekg(0, body->end); + auto streamSize = body->tellg(); + body->seekg(0, body->beg); + Aws::StringStream ss; + ss << streamSize; + httpRequest->SetContentLength(ss.str()); + } + + if (needsContentMd5 && body && !httpRequest->HasHeader(Http::CONTENT_MD5_HEADER)) + { + AWS_LOGSTREAM_TRACE(AWS_CLIENT_LOG_TAG, "Found body, and content-md5 needs to be set" << + ", attempting to compute content-md5"); + + //changing the internal state of the hash computation is not a logical state + //change as far as constness goes for this class. Due to the platform specificness + //of hash computations, we can't control the fact that computing a hash mutates + //state on some platforms such as windows (but that isn't a concern of this class. + auto md5HashResult = const_cast<AWSClient*>(this)->m_hash->Calculate(*body); + body->clear(); + if (md5HashResult.IsSuccess()) + { + httpRequest->SetHeaderValue(Http::CONTENT_MD5_HEADER, HashingUtils::Base64Encode(md5HashResult.GetResult())); + } + } +} + Aws::String Aws::Client::GetAuthorizationHeader(const Aws::Http::HttpRequest& httpRequest) { // Extract the hex-encoded signature from the authorization header rather than recalculating it. @@ -697,47 +697,47 @@ void AWSClient::BuildHttpRequest(const Aws::AmazonWebServiceRequest& request, AddContentBodyToRequest(httpRequest, request.GetBody(), request.ShouldComputeContentMd5(), request.IsStreaming() && request.IsChunked() && m_httpClient->SupportsChunkedTransferEncoding()); } - // Pass along handlers for processing data sent/received in bytes - httpRequest->SetDataReceivedEventHandler(request.GetDataReceivedEventHandler()); - httpRequest->SetDataSentEventHandler(request.GetDataSentEventHandler()); - httpRequest->SetContinueRequestHandle(request.GetContinueRequestHandler()); - - request.AddQueryStringParameters(httpRequest->GetUri()); -} - -void AWSClient::AddCommonHeaders(HttpRequest& httpRequest) const -{ - httpRequest.SetUserAgent(m_userAgent); -} - -Aws::String AWSClient::GeneratePresignedUrl(URI& uri, HttpMethod method, long long expirationInSeconds) -{ - std::shared_ptr<HttpRequest> request = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod); - auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER); - if (signer->PresignRequest(*request, expirationInSeconds)) - { - return request->GetURIString(); - } - + // Pass along handlers for processing data sent/received in bytes + httpRequest->SetDataReceivedEventHandler(request.GetDataReceivedEventHandler()); + httpRequest->SetDataSentEventHandler(request.GetDataSentEventHandler()); + httpRequest->SetContinueRequestHandle(request.GetContinueRequestHandler()); + + request.AddQueryStringParameters(httpRequest->GetUri()); +} + +void AWSClient::AddCommonHeaders(HttpRequest& httpRequest) const +{ + httpRequest.SetUserAgent(m_userAgent); +} + +Aws::String AWSClient::GeneratePresignedUrl(URI& uri, HttpMethod method, long long expirationInSeconds) +{ + std::shared_ptr<HttpRequest> request = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod); + auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER); + if (signer->PresignRequest(*request, expirationInSeconds)) + { + return request->GetURIString(); + } + return {}; -} - -Aws::String AWSClient::GeneratePresignedUrl(URI& uri, HttpMethod method, const Aws::Http::HeaderValueCollection& customizedHeaders, long long expirationInSeconds) -{ - std::shared_ptr<HttpRequest> request = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod); - for (const auto& it: customizedHeaders) - { - request->SetHeaderValue(it.first.c_str(), it.second); - } - auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER); - if (signer->PresignRequest(*request, expirationInSeconds)) - { - return request->GetURIString(); - } - +} + +Aws::String AWSClient::GeneratePresignedUrl(URI& uri, HttpMethod method, const Aws::Http::HeaderValueCollection& customizedHeaders, long long expirationInSeconds) +{ + std::shared_ptr<HttpRequest> request = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod); + for (const auto& it: customizedHeaders) + { + request->SetHeaderValue(it.first.c_str(), it.second); + } + auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER); + if (signer->PresignRequest(*request, expirationInSeconds)) + { + return request->GetURIString(); + } + return {}; -} - +} + Aws::String AWSClient::GeneratePresignedUrl(URI& uri, HttpMethod method, const char* region, long long expirationInSeconds) const { std::shared_ptr<HttpRequest> request = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod); @@ -766,165 +766,165 @@ Aws::String AWSClient::GeneratePresignedUrl(URI& uri, HttpMethod method, const c return {}; } -Aws::String AWSClient::GeneratePresignedUrl(Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region, const char* serviceName, long long expirationInSeconds) const -{ - std::shared_ptr<HttpRequest> request = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod); - auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER); - if (signer->PresignRequest(*request, region, serviceName, expirationInSeconds)) - { - return request->GetURIString(); - } - +Aws::String AWSClient::GeneratePresignedUrl(Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region, const char* serviceName, long long expirationInSeconds) const +{ + std::shared_ptr<HttpRequest> request = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod); + auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER); + if (signer->PresignRequest(*request, region, serviceName, expirationInSeconds)) + { + return request->GetURIString(); + } + return {}; -} - +} + Aws::String AWSClient::GeneratePresignedUrl(Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region, const char* serviceName, const Aws::Http::HeaderValueCollection& customizedHeaders, long long expirationInSeconds) -{ - std::shared_ptr<HttpRequest> request = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod); +{ + std::shared_ptr<HttpRequest> request = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod); for (const auto& it: customizedHeaders) { request->SetHeaderValue(it.first.c_str(), it.second); } - auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER); + auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER); if (signer->PresignRequest(*request, region, serviceName, expirationInSeconds)) - { - return request->GetURIString(); - } - + { + return request->GetURIString(); + } + return {}; -} - -Aws::String AWSClient::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request, Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region, - const Aws::Http::QueryStringParameterCollection& extraParams, long long expirationInSeconds) const -{ - std::shared_ptr<HttpRequest> httpRequest = - ConvertToRequestForPresigning(request, uri, method, extraParams); - auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER); - if (signer->PresignRequest(*httpRequest, region, expirationInSeconds)) - { - return httpRequest->GetURIString(); - } - +} + +Aws::String AWSClient::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request, Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region, + const Aws::Http::QueryStringParameterCollection& extraParams, long long expirationInSeconds) const +{ + std::shared_ptr<HttpRequest> httpRequest = + ConvertToRequestForPresigning(request, uri, method, extraParams); + auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER); + if (signer->PresignRequest(*httpRequest, region, expirationInSeconds)) + { + return httpRequest->GetURIString(); + } + return {}; -} - -Aws::String AWSClient::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request, Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region, const char* serviceName, -const Aws::Http::QueryStringParameterCollection& extraParams, long long expirationInSeconds) const -{ - std::shared_ptr<HttpRequest> httpRequest = - ConvertToRequestForPresigning(request, uri, method, extraParams); - auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER); - if (signer->PresignRequest(*httpRequest, region, serviceName, expirationInSeconds)) - { - return httpRequest->GetURIString(); - } - +} + +Aws::String AWSClient::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request, Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region, const char* serviceName, +const Aws::Http::QueryStringParameterCollection& extraParams, long long expirationInSeconds) const +{ + std::shared_ptr<HttpRequest> httpRequest = + ConvertToRequestForPresigning(request, uri, method, extraParams); + auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER); + if (signer->PresignRequest(*httpRequest, region, serviceName, expirationInSeconds)) + { + return httpRequest->GetURIString(); + } + return {}; -} - -Aws::String AWSClient::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request, Aws::Http::URI& uri, Aws::Http::HttpMethod method, - const Aws::Http::QueryStringParameterCollection& extraParams, long long expirationInSeconds) const -{ - std::shared_ptr<HttpRequest> httpRequest = - ConvertToRequestForPresigning(request, uri, method, extraParams); - auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER); - if (signer->PresignRequest(*httpRequest, expirationInSeconds)) - { - return httpRequest->GetURIString(); - } - +} + +Aws::String AWSClient::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request, Aws::Http::URI& uri, Aws::Http::HttpMethod method, + const Aws::Http::QueryStringParameterCollection& extraParams, long long expirationInSeconds) const +{ + std::shared_ptr<HttpRequest> httpRequest = + ConvertToRequestForPresigning(request, uri, method, extraParams); + auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER); + if (signer->PresignRequest(*httpRequest, expirationInSeconds)) + { + return httpRequest->GetURIString(); + } + return {}; -} - -std::shared_ptr<Aws::Http::HttpRequest> AWSClient::ConvertToRequestForPresigning(const Aws::AmazonWebServiceRequest& request, Aws::Http::URI& uri, - Aws::Http::HttpMethod method, const Aws::Http::QueryStringParameterCollection& extraParams) const -{ - request.PutToPresignedUrl(uri); - std::shared_ptr<HttpRequest> httpRequest = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod); - - for (auto& param : extraParams) - { - httpRequest->AddQueryStringParameter(param.first.c_str(), param.second); - } - - return httpRequest; -} - +} + +std::shared_ptr<Aws::Http::HttpRequest> AWSClient::ConvertToRequestForPresigning(const Aws::AmazonWebServiceRequest& request, Aws::Http::URI& uri, + Aws::Http::HttpMethod method, const Aws::Http::QueryStringParameterCollection& extraParams) const +{ + request.PutToPresignedUrl(uri); + std::shared_ptr<HttpRequest> httpRequest = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod); + + for (auto& param : extraParams) + { + httpRequest->AddQueryStringParameter(param.first.c_str(), param.second); + } + + return httpRequest; +} + std::shared_ptr<Aws::Http::HttpResponse> AWSClient::MakeHttpRequest(std::shared_ptr<Aws::Http::HttpRequest>& request) const { return m_httpClient->MakeRequest(request, m_readRateLimiter.get(), m_writeRateLimiter.get()); } - - -//////////////////////////////////////////////////////////////////////////// -AWSJsonClient::AWSJsonClient(const Aws::Client::ClientConfiguration& configuration, - const std::shared_ptr<Aws::Client::AWSAuthSigner>& signer, - const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) : - BASECLASS(configuration, signer, errorMarshaller) -{ -} - -AWSJsonClient::AWSJsonClient(const Aws::Client::ClientConfiguration& configuration, - const std::shared_ptr<Aws::Auth::AWSAuthSignerProvider>& signerProvider, - const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) : - BASECLASS(configuration, signerProvider, errorMarshaller) -{ -} - - -JsonOutcome AWSJsonClient::MakeRequest(const Aws::Http::URI& uri, - const Aws::AmazonWebServiceRequest& request, - Http::HttpMethod method, + + +//////////////////////////////////////////////////////////////////////////// +AWSJsonClient::AWSJsonClient(const Aws::Client::ClientConfiguration& configuration, + const std::shared_ptr<Aws::Client::AWSAuthSigner>& signer, + const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) : + BASECLASS(configuration, signer, errorMarshaller) +{ +} + +AWSJsonClient::AWSJsonClient(const Aws::Client::ClientConfiguration& configuration, + const std::shared_ptr<Aws::Auth::AWSAuthSignerProvider>& signerProvider, + const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) : + BASECLASS(configuration, signerProvider, errorMarshaller) +{ +} + + +JsonOutcome AWSJsonClient::MakeRequest(const Aws::Http::URI& uri, + const Aws::AmazonWebServiceRequest& request, + Http::HttpMethod method, const char* signerName, const char* signerRegionOverride, const char* signerServiceNameOverride) const -{ +{ HttpResponseOutcome httpOutcome(BASECLASS::AttemptExhaustively(uri, request, method, signerName, signerRegionOverride, signerServiceNameOverride)); - if (!httpOutcome.IsSuccess()) - { + if (!httpOutcome.IsSuccess()) + { return JsonOutcome(std::move(httpOutcome)); - } - - if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0) - //this is stupid, but gcc doesn't pick up the covariant on the dereference so we have to give it a little hint. - return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(httpOutcome.GetResult()->GetResponseBody()), - httpOutcome.GetResult()->GetHeaders(), - httpOutcome.GetResult()->GetResponseCode())); - - else - return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(), httpOutcome.GetResult()->GetHeaders())); -} - -JsonOutcome AWSJsonClient::MakeRequest(const Aws::Http::URI& uri, - Http::HttpMethod method, - const char* signerName, + } + + if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0) + //this is stupid, but gcc doesn't pick up the covariant on the dereference so we have to give it a little hint. + return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(httpOutcome.GetResult()->GetResponseBody()), + httpOutcome.GetResult()->GetHeaders(), + httpOutcome.GetResult()->GetResponseCode())); + + else + return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(), httpOutcome.GetResult()->GetHeaders())); +} + +JsonOutcome AWSJsonClient::MakeRequest(const Aws::Http::URI& uri, + Http::HttpMethod method, + const char* signerName, const char* requestName, const char* signerRegionOverride, const char* signerServiceNameOverride) const -{ +{ HttpResponseOutcome httpOutcome(BASECLASS::AttemptExhaustively(uri, method, signerName, requestName, signerRegionOverride, signerServiceNameOverride)); - if (!httpOutcome.IsSuccess()) - { + if (!httpOutcome.IsSuccess()) + { return JsonOutcome(std::move(httpOutcome)); - } - - if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0) - { - JsonValue jsonValue(httpOutcome.GetResult()->GetResponseBody()); - if (!jsonValue.WasParseSuccessful()) - { - return JsonOutcome(AWSError<CoreErrors>(CoreErrors::UNKNOWN, "Json Parser Error", jsonValue.GetErrorMessage(), false)); - } - - //this is stupid, but gcc doesn't pick up the covariant on the dereference so we have to give it a little hint. - return JsonOutcome(AmazonWebServiceResult<JsonValue>(std::move(jsonValue), - httpOutcome.GetResult()->GetHeaders(), - httpOutcome.GetResult()->GetResponseCode())); - } - - return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(), httpOutcome.GetResult()->GetHeaders())); -} - + } + + if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0) + { + JsonValue jsonValue(httpOutcome.GetResult()->GetResponseBody()); + if (!jsonValue.WasParseSuccessful()) + { + return JsonOutcome(AWSError<CoreErrors>(CoreErrors::UNKNOWN, "Json Parser Error", jsonValue.GetErrorMessage(), false)); + } + + //this is stupid, but gcc doesn't pick up the covariant on the dereference so we have to give it a little hint. + return JsonOutcome(AmazonWebServiceResult<JsonValue>(std::move(jsonValue), + httpOutcome.GetResult()->GetHeaders(), + httpOutcome.GetResult()->GetResponseCode())); + } + + return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(), httpOutcome.GetResult()->GetHeaders())); +} + JsonOutcome AWSJsonClient::MakeEventStreamRequest(std::shared_ptr<Aws::Http::HttpRequest>& request) const { // request is assumed to be signed @@ -958,141 +958,141 @@ JsonOutcome AWSJsonClient::MakeEventStreamRequest(std::shared_ptr<Aws::Http::Htt return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(), httpOutcome.GetResult()->GetHeaders())); } -AWSError<CoreErrors> AWSJsonClient::BuildAWSError( - const std::shared_ptr<Aws::Http::HttpResponse>& httpResponse) const -{ - AWSError<CoreErrors> error; +AWSError<CoreErrors> AWSJsonClient::BuildAWSError( + const std::shared_ptr<Aws::Http::HttpResponse>& httpResponse) const +{ + AWSError<CoreErrors> error; if (httpResponse->HasClientError()) - { + { bool retryable = httpResponse->GetClientErrorType() == CoreErrors::NETWORK_CONNECTION ? true : false; error = AWSError<CoreErrors>(httpResponse->GetClientErrorType(), "", httpResponse->GetClientErrorMessage(), retryable); - } - else if (!httpResponse->GetResponseBody() || httpResponse->GetResponseBody().tellp() < 1) - { - auto responseCode = httpResponse->GetResponseCode(); - auto errorCode = GuessBodylessErrorType(responseCode); - - Aws::StringStream ss; - ss << "No response body."; - error = AWSError<CoreErrors>(errorCode, "", ss.str(), - IsRetryableHttpResponseCode(responseCode)); - } - else - { - assert(httpResponse->GetResponseCode() != HttpResponseCode::OK); - error = GetErrorMarshaller()->Marshall(*httpResponse); - } - - error.SetResponseHeaders(httpResponse->GetHeaders()); - error.SetResponseCode(httpResponse->GetResponseCode()); + } + else if (!httpResponse->GetResponseBody() || httpResponse->GetResponseBody().tellp() < 1) + { + auto responseCode = httpResponse->GetResponseCode(); + auto errorCode = GuessBodylessErrorType(responseCode); + + Aws::StringStream ss; + ss << "No response body."; + error = AWSError<CoreErrors>(errorCode, "", ss.str(), + IsRetryableHttpResponseCode(responseCode)); + } + else + { + assert(httpResponse->GetResponseCode() != HttpResponseCode::OK); + error = GetErrorMarshaller()->Marshall(*httpResponse); + } + + error.SetResponseHeaders(httpResponse->GetHeaders()); + error.SetResponseCode(httpResponse->GetResponseCode()); error.SetRemoteHostIpAddress(httpResponse->GetOriginatingRequest().GetResolvedRemoteHost()); - AWS_LOGSTREAM_ERROR(AWS_CLIENT_LOG_TAG, error); - return error; -} - -///////////////////////////////////////////////////////////////////////////////////////// -AWSXMLClient::AWSXMLClient(const Aws::Client::ClientConfiguration& configuration, - const std::shared_ptr<Aws::Client::AWSAuthSigner>& signer, - const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) : - BASECLASS(configuration, signer, errorMarshaller) -{ -} - -AWSXMLClient::AWSXMLClient(const Aws::Client::ClientConfiguration& configuration, - const std::shared_ptr<Aws::Auth::AWSAuthSignerProvider>& signerProvider, - const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) : - BASECLASS(configuration, signerProvider, errorMarshaller) -{ -} - -XmlOutcome AWSXMLClient::MakeRequest(const Aws::Http::URI& uri, - const Aws::AmazonWebServiceRequest& request, - Http::HttpMethod method, + AWS_LOGSTREAM_ERROR(AWS_CLIENT_LOG_TAG, error); + return error; +} + +///////////////////////////////////////////////////////////////////////////////////////// +AWSXMLClient::AWSXMLClient(const Aws::Client::ClientConfiguration& configuration, + const std::shared_ptr<Aws::Client::AWSAuthSigner>& signer, + const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) : + BASECLASS(configuration, signer, errorMarshaller) +{ +} + +AWSXMLClient::AWSXMLClient(const Aws::Client::ClientConfiguration& configuration, + const std::shared_ptr<Aws::Auth::AWSAuthSignerProvider>& signerProvider, + const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) : + BASECLASS(configuration, signerProvider, errorMarshaller) +{ +} + +XmlOutcome AWSXMLClient::MakeRequest(const Aws::Http::URI& uri, + const Aws::AmazonWebServiceRequest& request, + Http::HttpMethod method, const char* signerName, const char* signerRegionOverride, const char* signerServiceNameOverride) const -{ +{ HttpResponseOutcome httpOutcome(BASECLASS::AttemptExhaustively(uri, request, method, signerName, signerRegionOverride, signerServiceNameOverride)); - if (!httpOutcome.IsSuccess()) - { + if (!httpOutcome.IsSuccess()) + { return XmlOutcome(std::move(httpOutcome)); - } - - if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0) - { - XmlDocument xmlDoc = XmlDocument::CreateFromXmlStream(httpOutcome.GetResult()->GetResponseBody()); - - if (!xmlDoc.WasParseSuccessful()) - { - AWS_LOGSTREAM_ERROR(AWS_CLIENT_LOG_TAG, "Xml parsing for error failed with message " << xmlDoc.GetErrorMessage().c_str()); - return AWSError<CoreErrors>(CoreErrors::UNKNOWN, "Xml Parse Error", xmlDoc.GetErrorMessage(), false); - } - - return XmlOutcome(AmazonWebServiceResult<XmlDocument>(std::move(xmlDoc), - httpOutcome.GetResult()->GetHeaders(), httpOutcome.GetResult()->GetResponseCode())); - } - - return XmlOutcome(AmazonWebServiceResult<XmlDocument>(XmlDocument(), httpOutcome.GetResult()->GetHeaders())); -} - -XmlOutcome AWSXMLClient::MakeRequest(const Aws::Http::URI& uri, - Http::HttpMethod method, - const char* signerName, + } + + if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0) + { + XmlDocument xmlDoc = XmlDocument::CreateFromXmlStream(httpOutcome.GetResult()->GetResponseBody()); + + if (!xmlDoc.WasParseSuccessful()) + { + AWS_LOGSTREAM_ERROR(AWS_CLIENT_LOG_TAG, "Xml parsing for error failed with message " << xmlDoc.GetErrorMessage().c_str()); + return AWSError<CoreErrors>(CoreErrors::UNKNOWN, "Xml Parse Error", xmlDoc.GetErrorMessage(), false); + } + + return XmlOutcome(AmazonWebServiceResult<XmlDocument>(std::move(xmlDoc), + httpOutcome.GetResult()->GetHeaders(), httpOutcome.GetResult()->GetResponseCode())); + } + + return XmlOutcome(AmazonWebServiceResult<XmlDocument>(XmlDocument(), httpOutcome.GetResult()->GetHeaders())); +} + +XmlOutcome AWSXMLClient::MakeRequest(const Aws::Http::URI& uri, + Http::HttpMethod method, + const char* signerName, const char* requestName, const char* signerRegionOverride, const char* signerServiceNameOverride) const -{ +{ HttpResponseOutcome httpOutcome(BASECLASS::AttemptExhaustively(uri, method, signerName, requestName, signerRegionOverride, signerServiceNameOverride)); - if (!httpOutcome.IsSuccess()) - { + if (!httpOutcome.IsSuccess()) + { return XmlOutcome(std::move(httpOutcome)); - } - - if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0) - { - return XmlOutcome(AmazonWebServiceResult<XmlDocument>( - XmlDocument::CreateFromXmlStream(httpOutcome.GetResult()->GetResponseBody()), - httpOutcome.GetResult()->GetHeaders(), httpOutcome.GetResult()->GetResponseCode())); - } - - return XmlOutcome(AmazonWebServiceResult<XmlDocument>(XmlDocument(), httpOutcome.GetResult()->GetHeaders())); -} - -AWSError<CoreErrors> AWSXMLClient::BuildAWSError(const std::shared_ptr<Http::HttpResponse>& httpResponse) const -{ - AWSError<CoreErrors> error; + } + + if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0) + { + return XmlOutcome(AmazonWebServiceResult<XmlDocument>( + XmlDocument::CreateFromXmlStream(httpOutcome.GetResult()->GetResponseBody()), + httpOutcome.GetResult()->GetHeaders(), httpOutcome.GetResult()->GetResponseCode())); + } + + return XmlOutcome(AmazonWebServiceResult<XmlDocument>(XmlDocument(), httpOutcome.GetResult()->GetHeaders())); +} + +AWSError<CoreErrors> AWSXMLClient::BuildAWSError(const std::shared_ptr<Http::HttpResponse>& httpResponse) const +{ + AWSError<CoreErrors> error; if (httpResponse->HasClientError()) - { + { bool retryable = httpResponse->GetClientErrorType() == CoreErrors::NETWORK_CONNECTION ? true : false; error = AWSError<CoreErrors>(httpResponse->GetClientErrorType(), "", httpResponse->GetClientErrorMessage(), retryable); - } + } else if (!httpResponse->GetResponseBody() || httpResponse->GetResponseBody().tellp() < 1) - { - auto responseCode = httpResponse->GetResponseCode(); - auto errorCode = GuessBodylessErrorType(responseCode); - - Aws::StringStream ss; - ss << "No response body."; - error = AWSError<CoreErrors>(errorCode, "", ss.str(), IsRetryableHttpResponseCode(responseCode)); - } - else - { - assert(httpResponse->GetResponseCode() != HttpResponseCode::OK); - - // When trying to build an AWS Error from a response which is an FStream, we need to rewind the - // file pointer back to the beginning in order to correctly read the input using the XML string iterator - if ((httpResponse->GetResponseBody().tellp() > 0) - && (httpResponse->GetResponseBody().tellg() > 0)) - { - httpResponse->GetResponseBody().seekg(0); - } - - error = GetErrorMarshaller()->Marshall(*httpResponse); - } - - error.SetResponseHeaders(httpResponse->GetHeaders()); - error.SetResponseCode(httpResponse->GetResponseCode()); + { + auto responseCode = httpResponse->GetResponseCode(); + auto errorCode = GuessBodylessErrorType(responseCode); + + Aws::StringStream ss; + ss << "No response body."; + error = AWSError<CoreErrors>(errorCode, "", ss.str(), IsRetryableHttpResponseCode(responseCode)); + } + else + { + assert(httpResponse->GetResponseCode() != HttpResponseCode::OK); + + // When trying to build an AWS Error from a response which is an FStream, we need to rewind the + // file pointer back to the beginning in order to correctly read the input using the XML string iterator + if ((httpResponse->GetResponseBody().tellp() > 0) + && (httpResponse->GetResponseBody().tellg() > 0)) + { + httpResponse->GetResponseBody().seekg(0); + } + + error = GetErrorMarshaller()->Marshall(*httpResponse); + } + + error.SetResponseHeaders(httpResponse->GetHeaders()); + error.SetResponseCode(httpResponse->GetResponseCode()); error.SetRemoteHostIpAddress(httpResponse->GetOriginatingRequest().GetResolvedRemoteHost()); - AWS_LOGSTREAM_ERROR(AWS_CLIENT_LOG_TAG, error); - return error; -} + AWS_LOGSTREAM_ERROR(AWS_CLIENT_LOG_TAG, error); + return error; +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSErrorMarshaller.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSErrorMarshaller.cpp index f5fa676f98..061b3d9deb 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSErrorMarshaller.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSErrorMarshaller.cpp @@ -2,41 +2,41 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/client/AWSErrorMarshaller.h> -#include <aws/core/utils/logging/LogMacros.h> -#include <aws/core/utils/json/JsonSerializer.h> -#include <aws/core/utils/xml/XmlSerializer.h> -#include <aws/core/utils/StringUtils.h> -#include <aws/core/client/AWSError.h> -#include <aws/core/client/CoreErrors.h> - -using namespace Aws::Utils::Logging; -using namespace Aws::Utils::Json; -using namespace Aws::Utils::Xml; -using namespace Aws::Http; -using namespace Aws::Utils; -using namespace Aws::Client; - + +#include <aws/core/client/AWSErrorMarshaller.h> +#include <aws/core/utils/logging/LogMacros.h> +#include <aws/core/utils/json/JsonSerializer.h> +#include <aws/core/utils/xml/XmlSerializer.h> +#include <aws/core/utils/StringUtils.h> +#include <aws/core/client/AWSError.h> +#include <aws/core/client/CoreErrors.h> + +using namespace Aws::Utils::Logging; +using namespace Aws::Utils::Json; +using namespace Aws::Utils::Xml; +using namespace Aws::Http; +using namespace Aws::Utils; +using namespace Aws::Client; + static const char AWS_ERROR_MARSHALLER_LOG_TAG[] = "AWSErrorMarshaller"; AWS_CORE_API extern const char MESSAGE_LOWER_CASE[] = "message"; AWS_CORE_API extern const char MESSAGE_CAMEL_CASE[] = "Message"; AWS_CORE_API extern const char ERROR_TYPE_HEADER[] = "x-amzn-ErrorType"; AWS_CORE_API extern const char REQUEST_ID_HEADER[] = "x-amzn-RequestId"; AWS_CORE_API extern const char TYPE[] = "__type"; - -AWSError<CoreErrors> JsonErrorMarshaller::Marshall(const Aws::Http::HttpResponse& httpResponse) const -{ - JsonValue exceptionPayload(httpResponse.GetResponseBody()); - JsonView payloadView(exceptionPayload); + +AWSError<CoreErrors> JsonErrorMarshaller::Marshall(const Aws::Http::HttpResponse& httpResponse) const +{ + JsonValue exceptionPayload(httpResponse.GetResponseBody()); + JsonView payloadView(exceptionPayload); AWSError<CoreErrors> error; if (exceptionPayload.WasParseSuccessful()) - { + { AWS_LOGSTREAM_TRACE(AWS_ERROR_MARSHALLER_LOG_TAG, "Error response is " << payloadView.WriteReadable()); - + Aws::String message(payloadView.ValueExists(MESSAGE_CAMEL_CASE) ? payloadView.GetString(MESSAGE_CAMEL_CASE) : payloadView.ValueExists(MESSAGE_LOWER_CASE) ? payloadView.GetString(MESSAGE_LOWER_CASE) : ""); - + if (httpResponse.HasHeader(ERROR_TYPE_HEADER)) { error = Marshall(httpResponse.GetHeader(ERROR_TYPE_HEADER), message); @@ -50,131 +50,131 @@ AWSError<CoreErrors> JsonErrorMarshaller::Marshall(const Aws::Http::HttpResponse error = FindErrorByHttpResponseCode(httpResponse.GetResponseCode()); error.SetMessage(message); } - } - else - { + } + else + { error = AWSError<CoreErrors>(CoreErrors::UNKNOWN, "", "Failed to parse error payload", false); - } + } error.SetRequestId(httpResponse.HasHeader(REQUEST_ID_HEADER) ? httpResponse.GetHeader(REQUEST_ID_HEADER) : ""); error.SetJsonPayload(std::move(exceptionPayload)); return error; -} - +} + const JsonValue& JsonErrorMarshaller::GetJsonPayloadFromError(const AWSError<CoreErrors>& error) const { return error.GetJsonPayload(); } -AWSError<CoreErrors> XmlErrorMarshaller::Marshall(const Aws::Http::HttpResponse& httpResponse) const -{ - XmlDocument doc = XmlDocument::CreateFromXmlStream(httpResponse.GetResponseBody()); - AWS_LOGSTREAM_TRACE(AWS_ERROR_MARSHALLER_LOG_TAG, "Error response is " << doc.ConvertToString()); - bool errorParsed = false; - AWSError<CoreErrors> error; +AWSError<CoreErrors> XmlErrorMarshaller::Marshall(const Aws::Http::HttpResponse& httpResponse) const +{ + XmlDocument doc = XmlDocument::CreateFromXmlStream(httpResponse.GetResponseBody()); + AWS_LOGSTREAM_TRACE(AWS_ERROR_MARSHALLER_LOG_TAG, "Error response is " << doc.ConvertToString()); + bool errorParsed = false; + AWSError<CoreErrors> error; if (doc.WasParseSuccessful() && !doc.GetRootElement().IsNull()) - { - XmlNode errorNode = doc.GetRootElement(); + { + XmlNode errorNode = doc.GetRootElement(); Aws::String requestId(!errorNode.FirstChild("RequestId").IsNull() ? errorNode.FirstChild("RequestId").GetText() : !errorNode.FirstChild("RequestID").IsNull() ? errorNode.FirstChild("RequestID").GetText() : ""); - if (errorNode.GetName() != "Error") - { - errorNode = doc.GetRootElement().FirstChild("Error"); - } - if (errorNode.IsNull()) - { - errorNode = doc.GetRootElement().FirstChild("Errors"); - if(!errorNode.IsNull()) - { - errorNode = errorNode.FirstChild("Error"); - } - } - - if (!errorNode.IsNull()) - { + if (errorNode.GetName() != "Error") + { + errorNode = doc.GetRootElement().FirstChild("Error"); + } + if (errorNode.IsNull()) + { + errorNode = doc.GetRootElement().FirstChild("Errors"); + if(!errorNode.IsNull()) + { + errorNode = errorNode.FirstChild("Error"); + } + } + + if (!errorNode.IsNull()) + { requestId = !requestId.empty() ? requestId : !errorNode.FirstChild("RequestId").IsNull() ? errorNode.FirstChild("RequestId").GetText() : !errorNode.FirstChild("RequestID").IsNull() ? errorNode.FirstChild("RequestID").GetText() : ""; - XmlNode codeNode = errorNode.FirstChild("Code"); - XmlNode messageNode = errorNode.FirstChild("Message"); - - if (!codeNode.IsNull()) - { - error = Marshall(StringUtils::Trim(codeNode.GetText().c_str()), - StringUtils::Trim(messageNode.GetText().c_str())); - errorParsed = true; - } - } + XmlNode codeNode = errorNode.FirstChild("Code"); + XmlNode messageNode = errorNode.FirstChild("Message"); + + if (!codeNode.IsNull()) + { + error = Marshall(StringUtils::Trim(codeNode.GetText().c_str()), + StringUtils::Trim(messageNode.GetText().c_str())); + errorParsed = true; + } + } error.SetRequestId(requestId); - } - - if(!errorParsed) - { - // An error occurred attempting to parse the httpResponse as an XML stream, so we're just - // going to dump the XML parsing error and the http response code as a string - AWS_LOGSTREAM_WARN(AWS_ERROR_MARSHALLER_LOG_TAG, "Unable to generate a proper httpResponse from the response " - "stream. Response code: " << static_cast< uint32_t >(httpResponse.GetResponseCode())); - error = FindErrorByHttpResponseCode(httpResponse.GetResponseCode()); - } - + } + + if(!errorParsed) + { + // An error occurred attempting to parse the httpResponse as an XML stream, so we're just + // going to dump the XML parsing error and the http response code as a string + AWS_LOGSTREAM_WARN(AWS_ERROR_MARSHALLER_LOG_TAG, "Unable to generate a proper httpResponse from the response " + "stream. Response code: " << static_cast< uint32_t >(httpResponse.GetResponseCode())); + error = FindErrorByHttpResponseCode(httpResponse.GetResponseCode()); + } + error.SetXmlPayload(std::move(doc)); - return error; -} - + return error; +} + const XmlDocument& XmlErrorMarshaller::GetXmlPayloadFromError(const AWSError<CoreErrors>& error) const { return error.GetXmlPayload(); } -AWSError<CoreErrors> AWSErrorMarshaller::Marshall(const Aws::String& exceptionName, const Aws::String& message) const -{ - if(exceptionName.empty()) - { - return AWSError<CoreErrors>(CoreErrors::UNKNOWN, "", message, false); - } - - auto locationOfPound = exceptionName.find_first_of('#'); - auto locationOfColon = exceptionName.find_first_of(':'); - Aws::String formalExceptionName; - - if (locationOfPound != Aws::String::npos) - { +AWSError<CoreErrors> AWSErrorMarshaller::Marshall(const Aws::String& exceptionName, const Aws::String& message) const +{ + if(exceptionName.empty()) + { + return AWSError<CoreErrors>(CoreErrors::UNKNOWN, "", message, false); + } + + auto locationOfPound = exceptionName.find_first_of('#'); + auto locationOfColon = exceptionName.find_first_of(':'); + Aws::String formalExceptionName; + + if (locationOfPound != Aws::String::npos) + { formalExceptionName = exceptionName.substr(locationOfPound + 1); - } - else if (locationOfColon != Aws::String::npos) - { + } + else if (locationOfColon != Aws::String::npos) + { formalExceptionName = exceptionName.substr(0, locationOfColon); + } + else + { + formalExceptionName = exceptionName; + } + + AWSError<CoreErrors> error = FindErrorByName(formalExceptionName.c_str()); + if (error.GetErrorType() != CoreErrors::UNKNOWN) + { + AWS_LOGSTREAM_WARN(AWS_ERROR_MARSHALLER_LOG_TAG, "Encountered AWSError '" << formalExceptionName.c_str() << + "': " << message.c_str()); + error.SetExceptionName(formalExceptionName); + error.SetMessage(message); + return error; } - else - { - formalExceptionName = exceptionName; - } - - AWSError<CoreErrors> error = FindErrorByName(formalExceptionName.c_str()); - if (error.GetErrorType() != CoreErrors::UNKNOWN) - { - AWS_LOGSTREAM_WARN(AWS_ERROR_MARSHALLER_LOG_TAG, "Encountered AWSError '" << formalExceptionName.c_str() << - "': " << message.c_str()); - error.SetExceptionName(formalExceptionName); - error.SetMessage(message); - return error; - } - - AWS_LOGSTREAM_WARN(AWS_ERROR_MARSHALLER_LOG_TAG, "Encountered Unknown AWSError '" << exceptionName.c_str() << - "': " << message.c_str()); - - return AWSError<CoreErrors>(CoreErrors::UNKNOWN, exceptionName, "Unable to parse ExceptionName: " + exceptionName + " Message: " + message, false); -} - -AWSError<CoreErrors> AWSErrorMarshaller::FindErrorByName(const char* errorName) const -{ - return CoreErrorsMapper::GetErrorForName(errorName); -} - -AWSError<CoreErrors> AWSErrorMarshaller::FindErrorByHttpResponseCode(Aws::Http::HttpResponseCode code) const -{ - return CoreErrorsMapper::GetErrorForHttpResponseCode(code); -} + + AWS_LOGSTREAM_WARN(AWS_ERROR_MARSHALLER_LOG_TAG, "Encountered Unknown AWSError '" << exceptionName.c_str() << + "': " << message.c_str()); + + return AWSError<CoreErrors>(CoreErrors::UNKNOWN, exceptionName, "Unable to parse ExceptionName: " + exceptionName + " Message: " + message, false); +} + +AWSError<CoreErrors> AWSErrorMarshaller::FindErrorByName(const char* errorName) const +{ + return CoreErrorsMapper::GetErrorForName(errorName); +} + +AWSError<CoreErrors> AWSErrorMarshaller::FindErrorByHttpResponseCode(Aws::Http::HttpResponseCode code) const +{ + return CoreErrorsMapper::GetErrorForHttpResponseCode(code); +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AsyncCallerContext.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AsyncCallerContext.cpp index 4f9abdc9e4..5e0e12c8e0 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AsyncCallerContext.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AsyncCallerContext.cpp @@ -2,15 +2,15 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/client/AsyncCallerContext.h> -#include <aws/core/utils/UUID.h> - -namespace Aws -{ - namespace Client - { - AsyncCallerContext::AsyncCallerContext() : m_uuid(Aws::Utils::UUID::RandomUUID()) - {} - } -}
\ No newline at end of file + +#include <aws/core/client/AsyncCallerContext.h> +#include <aws/core/utils/UUID.h> + +namespace Aws +{ + namespace Client + { + AsyncCallerContext::AsyncCallerContext() : m_uuid(Aws::Utils::UUID::RandomUUID()) + {} + } +}
\ No newline at end of file diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/ClientConfiguration.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/ClientConfiguration.cpp index e517379a77..69e1742988 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/ClientConfiguration.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/ClientConfiguration.cpp @@ -2,63 +2,63 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/client/ClientConfiguration.h> + +#include <aws/core/client/ClientConfiguration.h> #include <aws/core/auth/AWSCredentialsProvider.h> -#include <aws/core/client/DefaultRetryStrategy.h> +#include <aws/core/client/DefaultRetryStrategy.h> #include <aws/core/platform/Environment.h> -#include <aws/core/platform/OSVersionInfo.h> -#include <aws/core/utils/memory/AWSMemory.h> +#include <aws/core/platform/OSVersionInfo.h> +#include <aws/core/utils/memory/AWSMemory.h> #include <aws/core/utils/StringUtils.h> -#include <aws/core/utils/threading/Executor.h> -#include <aws/core/utils/memory/stl/AWSStringStream.h> -#include <aws/core/Version.h> +#include <aws/core/utils/threading/Executor.h> +#include <aws/core/utils/memory/stl/AWSStringStream.h> +#include <aws/core/Version.h> #include <aws/core/config/AWSProfileConfigLoader.h> #include <aws/core/utils/logging/LogMacros.h> - -namespace Aws -{ + +namespace Aws +{ namespace Auth { AWS_CORE_API Aws::String GetConfigProfileFilename(); } -namespace Client -{ - +namespace Client +{ + static const char* CLIENT_CONFIG_TAG = "ClientConfiguration"; - + AWS_CORE_API Aws::String ComputeUserAgentString() -{ - Aws::StringStream ss; - ss << "aws-sdk-cpp/" << Version::GetVersionString() << " " << Aws::OSVersionInfo::ComputeOSVersionString() - << " " << Version::GetCompilerVersionString(); - return ss.str(); -} - +{ + Aws::StringStream ss; + ss << "aws-sdk-cpp/" << Version::GetVersionString() << " " << Aws::OSVersionInfo::ComputeOSVersionString() + << " " << Version::GetCompilerVersionString(); + return ss.str(); +} + ClientConfiguration::ClientConfiguration() : scheme(Aws::Http::Scheme::HTTPS), - useDualStack(false), + useDualStack(false), maxConnections(25), httpRequestTimeoutMs(0), requestTimeoutMs(3000), - connectTimeoutMs(1000), + connectTimeoutMs(1000), enableTcpKeepAlive(true), tcpKeepAliveIntervalMs(30000), lowSpeedLimit(1), - proxyScheme(Aws::Http::Scheme::HTTP), - proxyPort(0), + proxyScheme(Aws::Http::Scheme::HTTP), + proxyPort(0), executor(Aws::MakeShared<Aws::Utils::Threading::DefaultExecutor>(CLIENT_CONFIG_TAG)), - verifySSL(true), - writeRateLimiter(nullptr), - readRateLimiter(nullptr), - httpLibOverride(Aws::Http::TransferLibType::DEFAULT_CLIENT), + verifySSL(true), + writeRateLimiter(nullptr), + readRateLimiter(nullptr), + httpLibOverride(Aws::Http::TransferLibType::DEFAULT_CLIENT), followRedirects(FollowRedirectsPolicy::DEFAULT), - disableExpectHeader(false), + disableExpectHeader(false), enableClockSkewAdjustment(true), enableHostPrefixInjection(true), enableEndpointDiscovery(false), profileName(Aws::Auth::GetConfigProfileName()) -{ +{ AWS_LOGSTREAM_DEBUG(CLIENT_CONFIG_TAG, "ClientConfiguration will use SDK Auto Resolved profile: [" << profileName << "] if not specified by users."); // Initialize Retry Strategy @@ -138,8 +138,8 @@ ClientConfiguration::ClientConfiguration() : } region = Aws::String(Aws::Region::US_EAST_1); -} - +} + ClientConfiguration::ClientConfiguration(const char* profile) : ClientConfiguration() { if (profile && Aws::Config::HasCachedConfigProfile(profile)) @@ -156,5 +156,5 @@ ClientConfiguration::ClientConfiguration(const char* profile) : ClientConfigurat AWS_LOGSTREAM_WARN(CLIENT_CONFIG_TAG, "User specified profile: [" << profile << "] is not found, will use the SDK resolved one."); } -} // namespace Client -} // namespace Aws +} // namespace Client +} // namespace Aws diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/CoreErrors.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/CoreErrors.cpp index 8c2c288dcd..f9e1357c86 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/CoreErrors.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/CoreErrors.cpp @@ -2,22 +2,22 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/client/AWSError.h> -#include <aws/core/client/CoreErrors.h> + +#include <aws/core/client/AWSError.h> +#include <aws/core/client/CoreErrors.h> #include <aws/core/utils/memory/stl/AWSMap.h> -#include <aws/core/utils/HashingUtils.h> - -using namespace Aws::Client; -using namespace Aws::Utils; -using namespace Aws::Http; - +#include <aws/core/utils/HashingUtils.h> + +using namespace Aws::Client; +using namespace Aws::Utils; +using namespace Aws::Http; + #ifdef _MSC_VER #pragma warning(push) // VS2015 compiler's bug, warning s_CoreErrorsMapper: symbol will be dynamically initialized (implementation limitation) #pragma warning(disable : 4592) #endif - + static Aws::UniquePtr<Aws::Map<Aws::String, AWSError<CoreErrors> > > s_CoreErrorsMapper(nullptr); #ifdef _MSC_VER @@ -25,7 +25,7 @@ static Aws::UniquePtr<Aws::Map<Aws::String, AWSError<CoreErrors> > > s_CoreError #endif void CoreErrorsMapper::InitCoreErrorsMapper() -{ +{ if (s_CoreErrorsMapper) { return; @@ -89,7 +89,7 @@ void CoreErrorsMapper::InitCoreErrorsMapper() s_CoreErrorsMapper->emplace("RequestTimeoutException", AWSError<CoreErrors>(CoreErrors::REQUEST_TIMEOUT, true)); s_CoreErrorsMapper->emplace("RequestTimeout", AWSError<CoreErrors>(CoreErrors::REQUEST_TIMEOUT, true)); } - + void CoreErrorsMapper::CleanupCoreErrorsMapper() { if (s_CoreErrorsMapper) @@ -97,7 +97,7 @@ void CoreErrorsMapper::CleanupCoreErrorsMapper() s_CoreErrorsMapper = nullptr; } } - + AWSError<CoreErrors> CoreErrorsMapper::GetErrorForName(const char* errorName) { auto iter = s_CoreErrorsMapper->find(errorName); @@ -106,46 +106,46 @@ AWSError<CoreErrors> CoreErrorsMapper::GetErrorForName(const char* errorName) return iter->second; } return AWSError<CoreErrors>(CoreErrors::UNKNOWN, false); -} - -AWS_CORE_API AWSError<CoreErrors> CoreErrorsMapper::GetErrorForHttpResponseCode(HttpResponseCode code) -{ - // best effort attempt to map HTTP response codes to CoreErrors - bool retryable = IsRetryableHttpResponseCode(code); +} + +AWS_CORE_API AWSError<CoreErrors> CoreErrorsMapper::GetErrorForHttpResponseCode(HttpResponseCode code) +{ + // best effort attempt to map HTTP response codes to CoreErrors + bool retryable = IsRetryableHttpResponseCode(code); AWSError<CoreErrors> error; switch (code) - { - case HttpResponseCode::UNAUTHORIZED: - case HttpResponseCode::FORBIDDEN: + { + case HttpResponseCode::UNAUTHORIZED: + case HttpResponseCode::FORBIDDEN: error = AWSError<CoreErrors>(CoreErrors::ACCESS_DENIED, retryable); break; - case HttpResponseCode::NOT_FOUND: + case HttpResponseCode::NOT_FOUND: error = AWSError<CoreErrors>(CoreErrors::RESOURCE_NOT_FOUND, retryable); break; - case HttpResponseCode::TOO_MANY_REQUESTS: + case HttpResponseCode::TOO_MANY_REQUESTS: error = AWSError<CoreErrors>(CoreErrors::SLOW_DOWN, retryable); break; - case HttpResponseCode::INTERNAL_SERVER_ERROR: + case HttpResponseCode::INTERNAL_SERVER_ERROR: error = AWSError<CoreErrors>(CoreErrors::INTERNAL_FAILURE, retryable); break; - case HttpResponseCode::BANDWIDTH_LIMIT_EXCEEDED: + case HttpResponseCode::BANDWIDTH_LIMIT_EXCEEDED: error = AWSError<CoreErrors>(CoreErrors::THROTTLING, retryable); break; - case HttpResponseCode::SERVICE_UNAVAILABLE: + case HttpResponseCode::SERVICE_UNAVAILABLE: error = AWSError<CoreErrors>(CoreErrors::SERVICE_UNAVAILABLE, retryable); break; - case HttpResponseCode::REQUEST_TIMEOUT: - case HttpResponseCode::AUTHENTICATION_TIMEOUT: - case HttpResponseCode::LOGIN_TIMEOUT: - case HttpResponseCode::GATEWAY_TIMEOUT: - case HttpResponseCode::NETWORK_READ_TIMEOUT: - case HttpResponseCode::NETWORK_CONNECT_TIMEOUT: + case HttpResponseCode::REQUEST_TIMEOUT: + case HttpResponseCode::AUTHENTICATION_TIMEOUT: + case HttpResponseCode::LOGIN_TIMEOUT: + case HttpResponseCode::GATEWAY_TIMEOUT: + case HttpResponseCode::NETWORK_READ_TIMEOUT: + case HttpResponseCode::NETWORK_CONNECT_TIMEOUT: error = AWSError<CoreErrors>(CoreErrors::REQUEST_TIMEOUT, retryable); break; - default: - int codeValue = static_cast<int>(code); + default: + int codeValue = static_cast<int>(code); error = AWSError<CoreErrors>(CoreErrors::UNKNOWN, codeValue >= 500 && codeValue < 600); - } + } error.SetResponseCode(code); return error; -} +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/DefaultRetryStrategy.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/DefaultRetryStrategy.cpp index 7e57c79ffc..ad5c3d613f 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/DefaultRetryStrategy.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/DefaultRetryStrategy.cpp @@ -2,31 +2,31 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/client/DefaultRetryStrategy.h> - -#include <aws/core/client/AWSError.h> -#include <aws/core/utils/UnreferencedParam.h> - -using namespace Aws; -using namespace Aws::Client; - -bool DefaultRetryStrategy::ShouldRetry(const AWSError<CoreErrors>& error, long attemptedRetries) const -{ - if (attemptedRetries >= m_maxRetries) - return false; - - return error.ShouldRetry(); -} - -long DefaultRetryStrategy::CalculateDelayBeforeNextRetry(const AWSError<CoreErrors>& error, long attemptedRetries) const -{ - AWS_UNREFERENCED_PARAM(error); - - if (attemptedRetries == 0) - { - return 0; - } - - return (1 << attemptedRetries) * m_scaleFactor; -} + +#include <aws/core/client/DefaultRetryStrategy.h> + +#include <aws/core/client/AWSError.h> +#include <aws/core/utils/UnreferencedParam.h> + +using namespace Aws; +using namespace Aws::Client; + +bool DefaultRetryStrategy::ShouldRetry(const AWSError<CoreErrors>& error, long attemptedRetries) const +{ + if (attemptedRetries >= m_maxRetries) + return false; + + return error.ShouldRetry(); +} + +long DefaultRetryStrategy::CalculateDelayBeforeNextRetry(const AWSError<CoreErrors>& error, long attemptedRetries) const +{ + AWS_UNREFERENCED_PARAM(error); + + if (attemptedRetries == 0) + { + return 0; + } + + return (1 << attemptedRetries) * m_scaleFactor; +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/AWSProfileConfigLoader.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/AWSProfileConfigLoader.cpp index 9ec2e54f55..7d62866a63 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/AWSProfileConfigLoader.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/AWSProfileConfigLoader.cpp @@ -2,25 +2,25 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/config/AWSProfileConfigLoader.h> -#include <aws/core/internal/AWSHttpResourceClient.h> + +#include <aws/core/config/AWSProfileConfigLoader.h> +#include <aws/core/internal/AWSHttpResourceClient.h> #include <aws/core/auth/AWSCredentialsProvider.h> -#include <aws/core/utils/memory/stl/AWSList.h> -#include <aws/core/utils/memory/stl/AWSStreamFwd.h> -#include <aws/core/utils/StringUtils.h> -#include <aws/core/utils/logging/LogMacros.h> -#include <aws/core/utils/json/JsonSerializer.h> -#include <fstream> - -namespace Aws -{ - namespace Config - { - using namespace Aws::Utils; - using namespace Aws::Auth; - - static const char* const CONFIG_LOADER_TAG = "Aws::Config::AWSProfileConfigLoader"; +#include <aws/core/utils/memory/stl/AWSList.h> +#include <aws/core/utils/memory/stl/AWSStreamFwd.h> +#include <aws/core/utils/StringUtils.h> +#include <aws/core/utils/logging/LogMacros.h> +#include <aws/core/utils/json/JsonSerializer.h> +#include <fstream> + +namespace Aws +{ + namespace Config + { + using namespace Aws::Utils; + using namespace Aws::Auth; + + static const char* const CONFIG_LOADER_TAG = "Aws::Config::AWSProfileConfigLoader"; #ifdef _MSC_VER // VS2015 compiler's bug, warning s_CoreErrorsMapper: symbol will be dynamically initialized (implementation limitation) AWS_SUPPRESS_WARNING(4592, @@ -29,40 +29,40 @@ namespace Aws #else static Aws::UniquePtr<ConfigAndCredentialsCacheManager> s_configManager(nullptr); #endif - + static const char CONFIG_CREDENTIALS_CACHE_MANAGER_TAG[] = "ConfigAndCredentialsCacheManager"; - bool AWSProfileConfigLoader::Load() - { - if(LoadInternal()) - { - AWS_LOGSTREAM_INFO(CONFIG_LOADER_TAG, "Successfully reloaded configuration."); - m_lastLoadTime = DateTime::Now(); + bool AWSProfileConfigLoader::Load() + { + if(LoadInternal()) + { + AWS_LOGSTREAM_INFO(CONFIG_LOADER_TAG, "Successfully reloaded configuration."); + m_lastLoadTime = DateTime::Now(); AWS_LOGSTREAM_TRACE(CONFIG_LOADER_TAG, "reloaded config at " - << m_lastLoadTime.ToGmtString(DateFormat::ISO_8601)); - return true; - } - - AWS_LOGSTREAM_INFO(CONFIG_LOADER_TAG, "Failed to reload configuration."); - return false; - } - - bool AWSProfileConfigLoader::PersistProfiles(const Aws::Map<Aws::String, Profile>& profiles) - { - if(PersistInternal(profiles)) - { - AWS_LOGSTREAM_INFO(CONFIG_LOADER_TAG, "Successfully persisted configuration."); - m_profiles = profiles; - m_lastLoadTime = DateTime::Now(); + << m_lastLoadTime.ToGmtString(DateFormat::ISO_8601)); + return true; + } + + AWS_LOGSTREAM_INFO(CONFIG_LOADER_TAG, "Failed to reload configuration."); + return false; + } + + bool AWSProfileConfigLoader::PersistProfiles(const Aws::Map<Aws::String, Profile>& profiles) + { + if(PersistInternal(profiles)) + { + AWS_LOGSTREAM_INFO(CONFIG_LOADER_TAG, "Successfully persisted configuration."); + m_profiles = profiles; + m_lastLoadTime = DateTime::Now(); AWS_LOGSTREAM_TRACE(CONFIG_LOADER_TAG, "persisted config at " - << m_lastLoadTime.ToGmtString(DateFormat::ISO_8601)); - return true; - } - - AWS_LOGSTREAM_WARN(CONFIG_LOADER_TAG, "Failed to persist configuration."); - return false; - } - + << m_lastLoadTime.ToGmtString(DateFormat::ISO_8601)); + return true; + } + + AWS_LOGSTREAM_WARN(CONFIG_LOADER_TAG, "Failed to persist configuration."); + return false; + } + static const char REGION_KEY[] = "region"; static const char ACCESS_KEY_ID_KEY[] = "aws_access_key_id"; static const char SECRET_KEY_KEY[] = "aws_secret_access_key"; @@ -76,134 +76,134 @@ namespace Aws static const char LEFT_BRACKET = '['; static const char RIGHT_BRACKET = ']'; static const char PARSER_TAG[] = "Aws::Config::ConfigFileProfileFSM"; - - class ConfigFileProfileFSM - { - public: - ConfigFileProfileFSM() : m_parserState(START) {} - - const Aws::Map<String, Profile>& GetProfiles() const { return m_foundProfiles; } - - void ParseStream(Aws::IStream& stream) - { - static const size_t ASSUME_EMPTY_LEN = 3; - - Aws::String line; - while(std::getline(stream, line) && m_parserState != FAILURE) - { - if (line.empty() || line.length() < ASSUME_EMPTY_LEN) - { - continue; - } - - auto openPos = line.find(LEFT_BRACKET); - auto closePos = line.find(RIGHT_BRACKET); - - switch(m_parserState) - { - - case START: - if(openPos != std::string::npos && closePos != std::string::npos) - { - FlushProfileAndReset(line, openPos, closePos); - m_parserState = PROFILE_FOUND; - } - break; - - //fallthrough here is intentional to reduce duplicate logic - case PROFILE_KEY_VALUE_FOUND: - if(openPos != std::string::npos && closePos != std::string::npos) - { - m_parserState = PROFILE_FOUND; - FlushProfileAndReset(line, openPos, closePos); - break; - } - // fall through - case PROFILE_FOUND: - { - auto equalsPos = line.find(EQ); - if (equalsPos != std::string::npos) - { - auto key = line.substr(0, equalsPos); - auto value = line.substr(equalsPos + 1); - m_profileKeyValuePairs[StringUtils::Trim(key.c_str())] = - StringUtils::Trim(value.c_str()); - m_parserState = PROFILE_KEY_VALUE_FOUND; - } - - break; - } - default: - m_parserState = FAILURE; - break; - } - } - + + class ConfigFileProfileFSM + { + public: + ConfigFileProfileFSM() : m_parserState(START) {} + + const Aws::Map<String, Profile>& GetProfiles() const { return m_foundProfiles; } + + void ParseStream(Aws::IStream& stream) + { + static const size_t ASSUME_EMPTY_LEN = 3; + + Aws::String line; + while(std::getline(stream, line) && m_parserState != FAILURE) + { + if (line.empty() || line.length() < ASSUME_EMPTY_LEN) + { + continue; + } + + auto openPos = line.find(LEFT_BRACKET); + auto closePos = line.find(RIGHT_BRACKET); + + switch(m_parserState) + { + + case START: + if(openPos != std::string::npos && closePos != std::string::npos) + { + FlushProfileAndReset(line, openPos, closePos); + m_parserState = PROFILE_FOUND; + } + break; + + //fallthrough here is intentional to reduce duplicate logic + case PROFILE_KEY_VALUE_FOUND: + if(openPos != std::string::npos && closePos != std::string::npos) + { + m_parserState = PROFILE_FOUND; + FlushProfileAndReset(line, openPos, closePos); + break; + } + // fall through + case PROFILE_FOUND: + { + auto equalsPos = line.find(EQ); + if (equalsPos != std::string::npos) + { + auto key = line.substr(0, equalsPos); + auto value = line.substr(equalsPos + 1); + m_profileKeyValuePairs[StringUtils::Trim(key.c_str())] = + StringUtils::Trim(value.c_str()); + m_parserState = PROFILE_KEY_VALUE_FOUND; + } + + break; + } + default: + m_parserState = FAILURE; + break; + } + } + FlushProfileAndReset(line, std::string::npos, std::string::npos); - } - - private: - - void FlushProfileAndReset(Aws::String& line, size_t openPos, size_t closePos) - { - if(!m_currentWorkingProfile.empty() && !m_profileKeyValuePairs.empty()) - { - Profile profile; - profile.SetName(m_currentWorkingProfile); - - auto regionIter = m_profileKeyValuePairs.find(REGION_KEY); - if (regionIter != m_profileKeyValuePairs.end()) - { - AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found region " << regionIter->second); - profile.SetRegion(regionIter->second); - } - - auto accessKeyIdIter = m_profileKeyValuePairs.find(ACCESS_KEY_ID_KEY); - Aws::String accessKey, secretKey, sessionToken; - if (accessKeyIdIter != m_profileKeyValuePairs.end()) - { - accessKey = accessKeyIdIter->second; - AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found access key " << accessKey); - - auto secretAccessKeyIter = m_profileKeyValuePairs.find(SECRET_KEY_KEY); - auto sessionTokenIter = m_profileKeyValuePairs.find(SESSION_TOKEN_KEY); - if (secretAccessKeyIter != m_profileKeyValuePairs.end()) - { - secretKey = secretAccessKeyIter->second; - } - else - { - AWS_LOGSTREAM_ERROR(PARSER_TAG, "No secret access key found even though an access key was specified. This will cause all signed AWS calls to fail."); - } - - if (sessionTokenIter != m_profileKeyValuePairs.end()) - { - sessionToken = sessionTokenIter->second; + } + + private: + + void FlushProfileAndReset(Aws::String& line, size_t openPos, size_t closePos) + { + if(!m_currentWorkingProfile.empty() && !m_profileKeyValuePairs.empty()) + { + Profile profile; + profile.SetName(m_currentWorkingProfile); + + auto regionIter = m_profileKeyValuePairs.find(REGION_KEY); + if (regionIter != m_profileKeyValuePairs.end()) + { + AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found region " << regionIter->second); + profile.SetRegion(regionIter->second); + } + + auto accessKeyIdIter = m_profileKeyValuePairs.find(ACCESS_KEY_ID_KEY); + Aws::String accessKey, secretKey, sessionToken; + if (accessKeyIdIter != m_profileKeyValuePairs.end()) + { + accessKey = accessKeyIdIter->second; + AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found access key " << accessKey); + + auto secretAccessKeyIter = m_profileKeyValuePairs.find(SECRET_KEY_KEY); + auto sessionTokenIter = m_profileKeyValuePairs.find(SESSION_TOKEN_KEY); + if (secretAccessKeyIter != m_profileKeyValuePairs.end()) + { + secretKey = secretAccessKeyIter->second; + } + else + { + AWS_LOGSTREAM_ERROR(PARSER_TAG, "No secret access key found even though an access key was specified. This will cause all signed AWS calls to fail."); + } + + if (sessionTokenIter != m_profileKeyValuePairs.end()) + { + sessionToken = sessionTokenIter->second; } - - profile.SetCredentials(Aws::Auth::AWSCredentials(accessKey, secretKey, sessionToken)); - } - - auto assumeRoleArnIter = m_profileKeyValuePairs.find(ROLE_ARN_KEY); - if (assumeRoleArnIter != m_profileKeyValuePairs.end()) - { - AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found role arn " << assumeRoleArnIter->second); - profile.SetRoleArn(assumeRoleArnIter->second); - } - - auto externalIdIter = m_profileKeyValuePairs.find(EXTERNAL_ID_KEY); - if (externalIdIter != m_profileKeyValuePairs.end()) - { - AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found external id " << externalIdIter->second); - profile.SetExternalId(externalIdIter->second); - } - - auto sourceProfileIter = m_profileKeyValuePairs.find(SOURCE_PROFILE_KEY); - if (sourceProfileIter != m_profileKeyValuePairs.end()) - { - AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found source profile " << sourceProfileIter->second); - profile.SetSourceProfile(sourceProfileIter->second); - } + + profile.SetCredentials(Aws::Auth::AWSCredentials(accessKey, secretKey, sessionToken)); + } + + auto assumeRoleArnIter = m_profileKeyValuePairs.find(ROLE_ARN_KEY); + if (assumeRoleArnIter != m_profileKeyValuePairs.end()) + { + AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found role arn " << assumeRoleArnIter->second); + profile.SetRoleArn(assumeRoleArnIter->second); + } + + auto externalIdIter = m_profileKeyValuePairs.find(EXTERNAL_ID_KEY); + if (externalIdIter != m_profileKeyValuePairs.end()) + { + AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found external id " << externalIdIter->second); + profile.SetExternalId(externalIdIter->second); + } + + auto sourceProfileIter = m_profileKeyValuePairs.find(SOURCE_PROFILE_KEY); + if (sourceProfileIter != m_profileKeyValuePairs.end()) + { + AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found source profile " << sourceProfileIter->second); + profile.SetSourceProfile(sourceProfileIter->second); + } auto credentialProcessIter = m_profileKeyValuePairs.find(CREDENTIAL_PROCESS_COMMAND); if (credentialProcessIter != m_profileKeyValuePairs.end()) @@ -211,154 +211,154 @@ namespace Aws AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found credential process " << credentialProcessIter->second); profile.SetCredentialProcess(credentialProcessIter->second); } - profile.SetAllKeyValPairs(m_profileKeyValuePairs); - - m_foundProfiles[profile.GetName()] = std::move(profile); - m_currentWorkingProfile.clear(); - m_profileKeyValuePairs.clear(); - } - - if(!line.empty() && openPos != std::string::npos && closePos != std::string::npos) - { - m_currentWorkingProfile = StringUtils::Trim(line.substr(openPos + 1, closePos - openPos - 1).c_str()); - StringUtils::Replace(m_currentWorkingProfile, PROFILE_PREFIX, ""); - AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found profile " << m_currentWorkingProfile); - } - } - - enum State - { - START = 0, - PROFILE_FOUND, - PROFILE_KEY_VALUE_FOUND, - FAILURE - }; - - Aws::String m_currentWorkingProfile; - Aws::Map<String, String> m_profileKeyValuePairs; - State m_parserState; - Aws::Map<String, Profile> m_foundProfiles; - }; - - static const char* const CONFIG_FILE_LOADER = "Aws::Config::AWSConfigFileProfileConfigLoader"; - - AWSConfigFileProfileConfigLoader::AWSConfigFileProfileConfigLoader(const Aws::String& fileName, bool useProfilePrefix) : - m_fileName(fileName), m_useProfilePrefix(useProfilePrefix) - { + profile.SetAllKeyValPairs(m_profileKeyValuePairs); + + m_foundProfiles[profile.GetName()] = std::move(profile); + m_currentWorkingProfile.clear(); + m_profileKeyValuePairs.clear(); + } + + if(!line.empty() && openPos != std::string::npos && closePos != std::string::npos) + { + m_currentWorkingProfile = StringUtils::Trim(line.substr(openPos + 1, closePos - openPos - 1).c_str()); + StringUtils::Replace(m_currentWorkingProfile, PROFILE_PREFIX, ""); + AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found profile " << m_currentWorkingProfile); + } + } + + enum State + { + START = 0, + PROFILE_FOUND, + PROFILE_KEY_VALUE_FOUND, + FAILURE + }; + + Aws::String m_currentWorkingProfile; + Aws::Map<String, String> m_profileKeyValuePairs; + State m_parserState; + Aws::Map<String, Profile> m_foundProfiles; + }; + + static const char* const CONFIG_FILE_LOADER = "Aws::Config::AWSConfigFileProfileConfigLoader"; + + AWSConfigFileProfileConfigLoader::AWSConfigFileProfileConfigLoader(const Aws::String& fileName, bool useProfilePrefix) : + m_fileName(fileName), m_useProfilePrefix(useProfilePrefix) + { AWS_LOGSTREAM_INFO(CONFIG_FILE_LOADER, "Initializing config loader against fileName " - << fileName << " and using profilePrefix = " << useProfilePrefix); - } - - bool AWSConfigFileProfileConfigLoader::LoadInternal() - { - m_profiles.clear(); - - Aws::IFStream inputFile(m_fileName.c_str()); - if(inputFile) - { - ConfigFileProfileFSM parser; - parser.ParseStream(inputFile); - m_profiles = parser.GetProfiles(); - return m_profiles.size() > 0; - } - - AWS_LOGSTREAM_INFO(CONFIG_FILE_LOADER, "Unable to open config file " << m_fileName << " for reading."); - - return false; - } - - bool AWSConfigFileProfileConfigLoader::PersistInternal(const Aws::Map<Aws::String, Profile>& profiles) - { - Aws::OFStream outputFile(m_fileName.c_str(), std::ios_base::out | std::ios_base::trunc); - if(outputFile) - { - for(auto& profile : profiles) - { - Aws::String prefix = m_useProfilePrefix ? PROFILE_PREFIX : ""; - - AWS_LOGSTREAM_DEBUG(CONFIG_FILE_LOADER, "Writing profile " << profile.first << " to disk."); - - outputFile << LEFT_BRACKET << prefix << profile.second.GetName() << RIGHT_BRACKET << std::endl; - const Aws::Auth::AWSCredentials& credentials = profile.second.GetCredentials(); - outputFile << ACCESS_KEY_ID_KEY << EQ << credentials.GetAWSAccessKeyId() << std::endl; - outputFile << SECRET_KEY_KEY << EQ << credentials.GetAWSSecretKey() << std::endl; - - if(!credentials.GetSessionToken().empty()) - { - outputFile << SESSION_TOKEN_KEY << EQ << credentials.GetSessionToken() << std::endl; - } - - if(!profile.second.GetRegion().empty()) - { - outputFile << REGION_KEY << EQ << profile.second.GetRegion() << std::endl; - } - - if(!profile.second.GetRoleArn().empty()) - { - outputFile << ROLE_ARN_KEY << EQ << profile.second.GetRoleArn() << std::endl; - } - - if(!profile.second.GetSourceProfile().empty()) - { - outputFile << SOURCE_PROFILE_KEY << EQ << profile.second.GetSourceProfile() << std::endl; - } - - outputFile << std::endl; - } - - AWS_LOGSTREAM_INFO(CONFIG_FILE_LOADER, "Profiles written to config file " << m_fileName); - - return true; - } - - AWS_LOGSTREAM_WARN(CONFIG_FILE_LOADER, "Unable to open config file " << m_fileName << " for writing."); - - return false; - } - - static const char* const EC2_INSTANCE_PROFILE_LOG_TAG = "Aws::Config::EC2InstanceProfileConfigLoader"; - - EC2InstanceProfileConfigLoader::EC2InstanceProfileConfigLoader(const std::shared_ptr<Aws::Internal::EC2MetadataClient>& client) - : m_ec2metadataClient(client == nullptr ? Aws::MakeShared<Aws::Internal::EC2MetadataClient>(EC2_INSTANCE_PROFILE_LOG_TAG) : client) - { - } - - bool EC2InstanceProfileConfigLoader::LoadInternal() - { + << fileName << " and using profilePrefix = " << useProfilePrefix); + } + + bool AWSConfigFileProfileConfigLoader::LoadInternal() + { + m_profiles.clear(); + + Aws::IFStream inputFile(m_fileName.c_str()); + if(inputFile) + { + ConfigFileProfileFSM parser; + parser.ParseStream(inputFile); + m_profiles = parser.GetProfiles(); + return m_profiles.size() > 0; + } + + AWS_LOGSTREAM_INFO(CONFIG_FILE_LOADER, "Unable to open config file " << m_fileName << " for reading."); + + return false; + } + + bool AWSConfigFileProfileConfigLoader::PersistInternal(const Aws::Map<Aws::String, Profile>& profiles) + { + Aws::OFStream outputFile(m_fileName.c_str(), std::ios_base::out | std::ios_base::trunc); + if(outputFile) + { + for(auto& profile : profiles) + { + Aws::String prefix = m_useProfilePrefix ? PROFILE_PREFIX : ""; + + AWS_LOGSTREAM_DEBUG(CONFIG_FILE_LOADER, "Writing profile " << profile.first << " to disk."); + + outputFile << LEFT_BRACKET << prefix << profile.second.GetName() << RIGHT_BRACKET << std::endl; + const Aws::Auth::AWSCredentials& credentials = profile.second.GetCredentials(); + outputFile << ACCESS_KEY_ID_KEY << EQ << credentials.GetAWSAccessKeyId() << std::endl; + outputFile << SECRET_KEY_KEY << EQ << credentials.GetAWSSecretKey() << std::endl; + + if(!credentials.GetSessionToken().empty()) + { + outputFile << SESSION_TOKEN_KEY << EQ << credentials.GetSessionToken() << std::endl; + } + + if(!profile.second.GetRegion().empty()) + { + outputFile << REGION_KEY << EQ << profile.second.GetRegion() << std::endl; + } + + if(!profile.second.GetRoleArn().empty()) + { + outputFile << ROLE_ARN_KEY << EQ << profile.second.GetRoleArn() << std::endl; + } + + if(!profile.second.GetSourceProfile().empty()) + { + outputFile << SOURCE_PROFILE_KEY << EQ << profile.second.GetSourceProfile() << std::endl; + } + + outputFile << std::endl; + } + + AWS_LOGSTREAM_INFO(CONFIG_FILE_LOADER, "Profiles written to config file " << m_fileName); + + return true; + } + + AWS_LOGSTREAM_WARN(CONFIG_FILE_LOADER, "Unable to open config file " << m_fileName << " for writing."); + + return false; + } + + static const char* const EC2_INSTANCE_PROFILE_LOG_TAG = "Aws::Config::EC2InstanceProfileConfigLoader"; + + EC2InstanceProfileConfigLoader::EC2InstanceProfileConfigLoader(const std::shared_ptr<Aws::Internal::EC2MetadataClient>& client) + : m_ec2metadataClient(client == nullptr ? Aws::MakeShared<Aws::Internal::EC2MetadataClient>(EC2_INSTANCE_PROFILE_LOG_TAG) : client) + { + } + + bool EC2InstanceProfileConfigLoader::LoadInternal() + { auto credentialsStr = m_ec2metadataClient->GetDefaultCredentialsSecurely(); - if(credentialsStr.empty()) return false; - - Json::JsonValue credentialsDoc(credentialsStr); + if(credentialsStr.empty()) return false; + + Json::JsonValue credentialsDoc(credentialsStr); if (!credentialsDoc.WasParseSuccessful()) - { + { AWS_LOGSTREAM_ERROR(EC2_INSTANCE_PROFILE_LOG_TAG, "Failed to parse output from EC2MetadataService."); - return false; - } - const char* accessKeyId = "AccessKeyId"; - const char* secretAccessKey = "SecretAccessKey"; - Aws::String accessKey, secretKey, token; - - auto credentialsView = credentialsDoc.View(); - accessKey = credentialsView.GetString(accessKeyId); + return false; + } + const char* accessKeyId = "AccessKeyId"; + const char* secretAccessKey = "SecretAccessKey"; + Aws::String accessKey, secretKey, token; + + auto credentialsView = credentialsDoc.View(); + accessKey = credentialsView.GetString(accessKeyId); AWS_LOGSTREAM_INFO(EC2_INSTANCE_PROFILE_LOG_TAG, - "Successfully pulled credentials from metadata service with access key " << accessKey); - - secretKey = credentialsView.GetString(secretAccessKey); - token = credentialsView.GetString("Token"); - - auto region = m_ec2metadataClient->GetCurrentRegion(); - - Profile profile; - profile.SetCredentials(AWSCredentials(accessKey, secretKey, token)); - profile.SetRegion(region); - profile.SetName(INSTANCE_PROFILE_KEY); - - m_profiles[INSTANCE_PROFILE_KEY] = profile; - - return true; - } - + "Successfully pulled credentials from metadata service with access key " << accessKey); + + secretKey = credentialsView.GetString(secretAccessKey); + token = credentialsView.GetString("Token"); + + auto region = m_ec2metadataClient->GetCurrentRegion(); + + Profile profile; + profile.SetCredentials(AWSCredentials(accessKey, secretKey, token)); + profile.SetRegion(region); + profile.SetName(INSTANCE_PROFILE_KEY); + + m_profiles[INSTANCE_PROFILE_KEY] = profile; + + return true; + } + ConfigAndCredentialsCacheManager::ConfigAndCredentialsCacheManager() : m_credentialsFileLoader(Aws::Auth::ProfileConfigFileAWSCredentialsProvider::GetCredentialsProfileFilename()), m_configFileLoader(Aws::Auth::GetConfigProfileFilename(), true/*use profile prefix*/) @@ -536,5 +536,5 @@ namespace Aws assert(s_configManager); return s_configManager->GetCredentials(profileName); } - } // Config namespace -} // Aws namespace + } // Config namespace +} // Aws namespace diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/external/cjson/cJSON.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/external/cjson/cJSON.cpp index 2525976334..f7b1357d37 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/external/cjson/cJSON.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/external/cjson/cJSON.cpp @@ -1,2334 +1,2334 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -/* cJSON */ -/* JSON parser in C. */ - -/* disable warnings about old C89 functions in MSVC */ -#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) -#define _CRT_SECURE_NO_DEPRECATE -#endif - -#ifdef __GNUC__ -#pragma GCC visibility push(default) -#endif -#if defined(_MSC_VER) -#pragma warning (push) -/* disable warning about single line comments in system headers */ -#pragma warning (disable : 4001) -#endif - -#include <string.h> -#include <stdio.h> -#include <math.h> -#include <stdlib.h> -#include <limits.h> -#include <ctype.h> - -#ifdef ENABLE_LOCALES -#include <locale.h> -#endif - -#if defined(_MSC_VER) -#pragma warning (pop) -#endif -#ifdef __GNUC__ -#pragma GCC visibility pop -#endif - -#include <aws/core/external/cjson/cJSON.h> - -/* define our own boolean type */ -// #define true ((cJSON_bool)1) -// #define false ((cJSON_bool)0) - -typedef struct { - const unsigned char *json; - size_t position; -} error; -static error global_error = { NULL, 0 }; - -CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) -{ - return (const char*) (global_error.json + global_error.position); -} - -CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) { - if (!cJSON_IsString(item)) { - return NULL; - } - - return item->valuestring; -} - -/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ -#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 7) - #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. -#endif - -CJSON_PUBLIC(const char*) cJSON_Version(void) -{ - static char version[15]; - sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); - - return version; -} - -/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */ -static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) -{ - if ((string1 == NULL) || (string2 == NULL)) - { - return 1; - } - - if (string1 == string2) - { - return 0; - } - - for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++) - { - if (*string1 == '\0') - { - return 0; - } - } - - return tolower(*string1) - tolower(*string2); -} - -typedef struct internal_hooks -{ - void *(*allocate)(size_t size); - void (*deallocate)(void *pointer); - void *(*reallocate)(void *pointer, size_t size); -} internal_hooks; - -#if defined(_MSC_VER) -/* work around MSVC error C2322: '...' address of dillimport '...' is not static */ -static void *internal_malloc(size_t size) -{ - return malloc(size); -} -static void internal_free(void *pointer) -{ - free(pointer); -} -static void *internal_realloc(void *pointer, size_t size) -{ - return realloc(pointer, size); -} -#else -#define internal_malloc malloc -#define internal_free free -#define internal_realloc realloc -#endif - -static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc }; - -static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks) -{ - size_t length = 0; - unsigned char *copy = NULL; - - if (string == NULL) - { - return NULL; - } - - length = strlen((const char*)string) + sizeof(""); - copy = (unsigned char*)hooks->allocate(length); - if (copy == NULL) - { - return NULL; - } - memcpy(copy, string, length); - - return copy; -} - -CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) -{ - if (hooks == NULL) - { - /* Reset hooks */ - global_hooks.allocate = malloc; - global_hooks.deallocate = free; - global_hooks.reallocate = realloc; - return; - } - - global_hooks.allocate = malloc; - if (hooks->malloc_fn != NULL) - { - global_hooks.allocate = hooks->malloc_fn; - } - - global_hooks.deallocate = free; - if (hooks->free_fn != NULL) - { - global_hooks.deallocate = hooks->free_fn; - } - - /* use realloc only if both free and malloc are used */ - global_hooks.reallocate = NULL; - if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) - { - global_hooks.reallocate = realloc; - } -} - -/* Internal constructor. */ -static cJSON *cJSON_New_Item(const internal_hooks * const hooks) -{ - cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON)); - if (node) - { - memset(node, '\0', sizeof(cJSON)); - } - - return node; -} - -/* Delete a cJSON structure. */ -CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) -{ - cJSON *next = NULL; - while (item != NULL) - { - next = item->next; - if (!(item->type & cJSON_IsReference) && (item->child != NULL)) - { - cJSON_Delete(item->child); - } - if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) - { - global_hooks.deallocate(item->valuestring); - } - if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) - { - global_hooks.deallocate(item->string); - } - global_hooks.deallocate(item); - item = next; - } -} - -/* get the decimal point character of the current locale */ -static unsigned char get_decimal_point(void) -{ -#ifdef ENABLE_LOCALES - struct lconv *lconv = localeconv(); - return (unsigned char) lconv->decimal_point[0]; -#else - return '.'; -#endif -} - -typedef struct -{ - const unsigned char *content; - size_t length; - size_t offset; - size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */ - internal_hooks hooks; -} parse_buffer; - -/* check if the given size is left to read in a given parse buffer (starting with 1) */ -#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length)) -/* check if the buffer can be accessed at the given index (starting with 0) */ -#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length)) -#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index)) -/* get a pointer to the buffer at the position */ -#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) - -/* Parse the input text to generate a number, and populate the result into item. */ -static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer) -{ - double number = 0; - unsigned char *after_end = NULL; - unsigned char number_c_string[64]; - unsigned char decimal_point = get_decimal_point(); +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +/* cJSON */ +/* JSON parser in C. */ + +/* disable warnings about old C89 functions in MSVC */ +#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) +#define _CRT_SECURE_NO_DEPRECATE +#endif + +#ifdef __GNUC__ +#pragma GCC visibility push(default) +#endif +#if defined(_MSC_VER) +#pragma warning (push) +/* disable warning about single line comments in system headers */ +#pragma warning (disable : 4001) +#endif + +#include <string.h> +#include <stdio.h> +#include <math.h> +#include <stdlib.h> +#include <limits.h> +#include <ctype.h> + +#ifdef ENABLE_LOCALES +#include <locale.h> +#endif + +#if defined(_MSC_VER) +#pragma warning (pop) +#endif +#ifdef __GNUC__ +#pragma GCC visibility pop +#endif + +#include <aws/core/external/cjson/cJSON.h> + +/* define our own boolean type */ +// #define true ((cJSON_bool)1) +// #define false ((cJSON_bool)0) + +typedef struct { + const unsigned char *json; + size_t position; +} error; +static error global_error = { NULL, 0 }; + +CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) +{ + return (const char*) (global_error.json + global_error.position); +} + +CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) { + if (!cJSON_IsString(item)) { + return NULL; + } + + return item->valuestring; +} + +/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ +#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 7) + #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. +#endif + +CJSON_PUBLIC(const char*) cJSON_Version(void) +{ + static char version[15]; + sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); + + return version; +} + +/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */ +static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) +{ + if ((string1 == NULL) || (string2 == NULL)) + { + return 1; + } + + if (string1 == string2) + { + return 0; + } + + for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++) + { + if (*string1 == '\0') + { + return 0; + } + } + + return tolower(*string1) - tolower(*string2); +} + +typedef struct internal_hooks +{ + void *(*allocate)(size_t size); + void (*deallocate)(void *pointer); + void *(*reallocate)(void *pointer, size_t size); +} internal_hooks; + +#if defined(_MSC_VER) +/* work around MSVC error C2322: '...' address of dillimport '...' is not static */ +static void *internal_malloc(size_t size) +{ + return malloc(size); +} +static void internal_free(void *pointer) +{ + free(pointer); +} +static void *internal_realloc(void *pointer, size_t size) +{ + return realloc(pointer, size); +} +#else +#define internal_malloc malloc +#define internal_free free +#define internal_realloc realloc +#endif + +static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc }; + +static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks) +{ + size_t length = 0; + unsigned char *copy = NULL; + + if (string == NULL) + { + return NULL; + } + + length = strlen((const char*)string) + sizeof(""); + copy = (unsigned char*)hooks->allocate(length); + if (copy == NULL) + { + return NULL; + } + memcpy(copy, string, length); + + return copy; +} + +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) +{ + if (hooks == NULL) + { + /* Reset hooks */ + global_hooks.allocate = malloc; + global_hooks.deallocate = free; + global_hooks.reallocate = realloc; + return; + } + + global_hooks.allocate = malloc; + if (hooks->malloc_fn != NULL) + { + global_hooks.allocate = hooks->malloc_fn; + } + + global_hooks.deallocate = free; + if (hooks->free_fn != NULL) + { + global_hooks.deallocate = hooks->free_fn; + } + + /* use realloc only if both free and malloc are used */ + global_hooks.reallocate = NULL; + if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) + { + global_hooks.reallocate = realloc; + } +} + +/* Internal constructor. */ +static cJSON *cJSON_New_Item(const internal_hooks * const hooks) +{ + cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON)); + if (node) + { + memset(node, '\0', sizeof(cJSON)); + } + + return node; +} + +/* Delete a cJSON structure. */ +CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) +{ + cJSON *next = NULL; + while (item != NULL) + { + next = item->next; + if (!(item->type & cJSON_IsReference) && (item->child != NULL)) + { + cJSON_Delete(item->child); + } + if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) + { + global_hooks.deallocate(item->valuestring); + } + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) + { + global_hooks.deallocate(item->string); + } + global_hooks.deallocate(item); + item = next; + } +} + +/* get the decimal point character of the current locale */ +static unsigned char get_decimal_point(void) +{ +#ifdef ENABLE_LOCALES + struct lconv *lconv = localeconv(); + return (unsigned char) lconv->decimal_point[0]; +#else + return '.'; +#endif +} + +typedef struct +{ + const unsigned char *content; + size_t length; + size_t offset; + size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */ + internal_hooks hooks; +} parse_buffer; + +/* check if the given size is left to read in a given parse buffer (starting with 1) */ +#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length)) +/* check if the buffer can be accessed at the given index (starting with 0) */ +#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length)) +#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index)) +/* get a pointer to the buffer at the position */ +#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) + +/* Parse the input text to generate a number, and populate the result into item. */ +static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer) +{ + double number = 0; + unsigned char *after_end = NULL; + unsigned char number_c_string[64]; + unsigned char decimal_point = get_decimal_point(); bool isInteger = true; - size_t i = 0; - - if ((input_buffer == NULL) || (input_buffer->content == NULL)) - { - return false; - } - - /* copy the number into a temporary buffer and replace '.' with the decimal point - * of the current locale (for strtod) - * This also takes care of '\0' not necessarily being available for marking the end of the input */ - for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) - { - switch (buffer_at_offset(input_buffer)[i]) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '+': - case '-': + size_t i = 0; + + if ((input_buffer == NULL) || (input_buffer->content == NULL)) + { + return false; + } + + /* copy the number into a temporary buffer and replace '.' with the decimal point + * of the current locale (for strtod) + * This also takes care of '\0' not necessarily being available for marking the end of the input */ + for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) + { + switch (buffer_at_offset(input_buffer)[i]) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '+': + case '-': number_c_string[i] = buffer_at_offset(input_buffer)[i]; break; - case 'e': - case 'E': - number_c_string[i] = buffer_at_offset(input_buffer)[i]; + case 'e': + case 'E': + number_c_string[i] = buffer_at_offset(input_buffer)[i]; isInteger = false; - break; - - case '.': - number_c_string[i] = decimal_point; + break; + + case '.': + number_c_string[i] = decimal_point; isInteger = false; - break; - - default: - goto loop_end; - } - } -loop_end: - number_c_string[i] = '\0'; - - number = strtod((const char*)number_c_string, (char**)&after_end); - if (number_c_string == after_end) - { - return false; /* parse_error */ - } - - item->valuedouble = number; + break; + + default: + goto loop_end; + } + } +loop_end: + number_c_string[i] = '\0'; + + number = strtod((const char*)number_c_string, (char**)&after_end); + if (number_c_string == after_end) + { + return false; /* parse_error */ + } + + item->valuedouble = number; // For integer which is out of the range of [INT_MIN, INT_MAX], it may lose precision if we cast it to double. // Instead, we keep the integer literal as a string. if (isInteger && (number > INT_MAX || number < INT_MIN)) { item->valuestring = (char*)cJSON_strdup(number_c_string, &global_hooks); } - - /* use saturation in case of overflow */ - if (number >= INT_MAX) - { - item->valueint = INT_MAX; - } - else if (number <= INT_MIN) - { - item->valueint = INT_MIN; - } - else - { - item->valueint = (int)number; - } - - item->type = cJSON_Number; - - input_buffer->offset += (size_t)(after_end - number_c_string); - return true; -} - -/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */ -CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) -{ - if (number >= INT_MAX) - { - object->valueint = INT_MAX; - } - else if (number <= INT_MIN) - { - object->valueint = INT_MIN; - } - else - { - object->valueint = (int)number; - } - - return object->valuedouble = number; -} - -typedef struct -{ - unsigned char *buffer; - size_t length; - size_t offset; - size_t depth; /* current nesting depth (for formatted printing) */ - cJSON_bool noalloc; - cJSON_bool format; /* is this print a formatted print */ - internal_hooks hooks; -} printbuffer; - -/* realloc printbuffer if necessary to have at least "needed" bytes more */ -static unsigned char* ensure(printbuffer * const p, size_t needed) -{ - unsigned char *newbuffer = NULL; - size_t newsize = 0; - - if ((p == NULL) || (p->buffer == NULL)) - { - return NULL; - } - - if ((p->length > 0) && (p->offset >= p->length)) - { - /* make sure that offset is valid */ - return NULL; - } - - if (needed > INT_MAX) - { - /* sizes bigger than INT_MAX are currently not supported */ - return NULL; - } - - needed += p->offset + 1; - if (needed <= p->length) - { - return p->buffer + p->offset; - } - - if (p->noalloc) { - return NULL; - } - - /* calculate new buffer size */ - if (needed > (INT_MAX / 2)) - { - /* overflow of int, use INT_MAX if possible */ - if (needed <= INT_MAX) - { - newsize = INT_MAX; - } - else - { - return NULL; - } - } - else - { - newsize = needed * 2; - } - - if (p->hooks.reallocate != NULL) - { - /* reallocate with realloc if available */ - newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize); - if (newbuffer == NULL) - { - p->hooks.deallocate(p->buffer); - p->length = 0; - p->buffer = NULL; - - return NULL; - } - } - else - { - /* otherwise reallocate manually */ - newbuffer = (unsigned char*)p->hooks.allocate(newsize); - if (!newbuffer) - { - p->hooks.deallocate(p->buffer); - p->length = 0; - p->buffer = NULL; - - return NULL; - } - if (newbuffer) - { - memcpy(newbuffer, p->buffer, p->offset + 1); - } - p->hooks.deallocate(p->buffer); - } - p->length = newsize; - p->buffer = newbuffer; - - return newbuffer + p->offset; -} - -/* calculate the new length of the string in a printbuffer and update the offset */ -static void update_offset(printbuffer * const buffer) -{ - const unsigned char *buffer_pointer = NULL; - if ((buffer == NULL) || (buffer->buffer == NULL)) - { - return; - } - buffer_pointer = buffer->buffer + buffer->offset; - - buffer->offset += strlen((const char*)buffer_pointer); -} - -/* Render the number nicely from the given item into a string. */ -static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer) -{ - unsigned char *output_pointer = NULL; - double d = item->valuedouble; - int length = 0; - size_t i = 0; - unsigned char number_buffer[26]; /* temporary buffer to print the number into */ - unsigned char decimal_point = get_decimal_point(); - double test; - - if (output_buffer == NULL) - { - return false; - } - + + /* use saturation in case of overflow */ + if (number >= INT_MAX) + { + item->valueint = INT_MAX; + } + else if (number <= INT_MIN) + { + item->valueint = INT_MIN; + } + else + { + item->valueint = (int)number; + } + + item->type = cJSON_Number; + + input_buffer->offset += (size_t)(after_end - number_c_string); + return true; +} + +/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */ +CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) +{ + if (number >= INT_MAX) + { + object->valueint = INT_MAX; + } + else if (number <= INT_MIN) + { + object->valueint = INT_MIN; + } + else + { + object->valueint = (int)number; + } + + return object->valuedouble = number; +} + +typedef struct +{ + unsigned char *buffer; + size_t length; + size_t offset; + size_t depth; /* current nesting depth (for formatted printing) */ + cJSON_bool noalloc; + cJSON_bool format; /* is this print a formatted print */ + internal_hooks hooks; +} printbuffer; + +/* realloc printbuffer if necessary to have at least "needed" bytes more */ +static unsigned char* ensure(printbuffer * const p, size_t needed) +{ + unsigned char *newbuffer = NULL; + size_t newsize = 0; + + if ((p == NULL) || (p->buffer == NULL)) + { + return NULL; + } + + if ((p->length > 0) && (p->offset >= p->length)) + { + /* make sure that offset is valid */ + return NULL; + } + + if (needed > INT_MAX) + { + /* sizes bigger than INT_MAX are currently not supported */ + return NULL; + } + + needed += p->offset + 1; + if (needed <= p->length) + { + return p->buffer + p->offset; + } + + if (p->noalloc) { + return NULL; + } + + /* calculate new buffer size */ + if (needed > (INT_MAX / 2)) + { + /* overflow of int, use INT_MAX if possible */ + if (needed <= INT_MAX) + { + newsize = INT_MAX; + } + else + { + return NULL; + } + } + else + { + newsize = needed * 2; + } + + if (p->hooks.reallocate != NULL) + { + /* reallocate with realloc if available */ + newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize); + if (newbuffer == NULL) + { + p->hooks.deallocate(p->buffer); + p->length = 0; + p->buffer = NULL; + + return NULL; + } + } + else + { + /* otherwise reallocate manually */ + newbuffer = (unsigned char*)p->hooks.allocate(newsize); + if (!newbuffer) + { + p->hooks.deallocate(p->buffer); + p->length = 0; + p->buffer = NULL; + + return NULL; + } + if (newbuffer) + { + memcpy(newbuffer, p->buffer, p->offset + 1); + } + p->hooks.deallocate(p->buffer); + } + p->length = newsize; + p->buffer = newbuffer; + + return newbuffer + p->offset; +} + +/* calculate the new length of the string in a printbuffer and update the offset */ +static void update_offset(printbuffer * const buffer) +{ + const unsigned char *buffer_pointer = NULL; + if ((buffer == NULL) || (buffer->buffer == NULL)) + { + return; + } + buffer_pointer = buffer->buffer + buffer->offset; + + buffer->offset += strlen((const char*)buffer_pointer); +} + +/* Render the number nicely from the given item into a string. */ +static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + double d = item->valuedouble; + int length = 0; + size_t i = 0; + unsigned char number_buffer[26]; /* temporary buffer to print the number into */ + unsigned char decimal_point = get_decimal_point(); + double test; + + if (output_buffer == NULL) + { + return false; + } + /* For integer which is out of the range of [INT_MIN, INT_MAX], valuestring is an integer literal. */ if (item->valuestring) { length = sprintf((char*)number_buffer, "%s", item->valuestring); } - /* This checks for NaN and Infinity */ + /* This checks for NaN and Infinity */ else if ((d * 0) != 0) - { - length = sprintf((char*)number_buffer, "null"); - } - else - { - /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ - length = sprintf((char*)number_buffer, "%1.15g", d); - - /* Check whether the original double can be recovered */ - if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || ((double)test != d)) - { - /* If not, print with 17 decimal places of precision */ - length = sprintf((char*)number_buffer, "%1.17g", d); - } - } - + { + length = sprintf((char*)number_buffer, "null"); + } + else + { + /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ + length = sprintf((char*)number_buffer, "%1.15g", d); + + /* Check whether the original double can be recovered */ + if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || ((double)test != d)) + { + /* If not, print with 17 decimal places of precision */ + length = sprintf((char*)number_buffer, "%1.17g", d); + } + } + /* sprintf failed or buffer overrun occurred */ - if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) - { - return false; - } - - /* reserve appropriate space in the output */ - output_pointer = ensure(output_buffer, (size_t)length + sizeof("")); - if (output_pointer == NULL) - { - return false; - } - - /* copy the printed number to the output and replace locale - * dependent decimal point with '.' */ - for (i = 0; i < ((size_t)length); i++) - { - if (number_buffer[i] == decimal_point) - { - output_pointer[i] = '.'; - continue; - } - - output_pointer[i] = number_buffer[i]; - } - output_pointer[i] = '\0'; - - output_buffer->offset += (size_t)length; - - return true; -} - -/* parse 4 digit hexadecimal number */ -static unsigned parse_hex4(const unsigned char * const input) -{ - unsigned int h = 0; - size_t i = 0; - - for (i = 0; i < 4; i++) - { - /* parse digit */ - if ((input[i] >= '0') && (input[i] <= '9')) - { - h += (unsigned int) input[i] - '0'; - } - else if ((input[i] >= 'A') && (input[i] <= 'F')) - { - h += (unsigned int) 10 + input[i] - 'A'; - } - else if ((input[i] >= 'a') && (input[i] <= 'f')) - { - h += (unsigned int) 10 + input[i] - 'a'; - } - else /* invalid */ - { - return 0; - } - - if (i < 3) - { - /* shift left to make place for the next nibble */ - h = h << 4; - } - } - - return h; -} - -/* converts a UTF-16 literal to UTF-8 - * A literal can be one or two sequences of the form \uXXXX */ -static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer) -{ - long unsigned int codepoint = 0; - unsigned int first_code = 0; - const unsigned char *first_sequence = input_pointer; - unsigned char utf8_length = 0; - unsigned char utf8_position = 0; - unsigned char sequence_length = 0; - unsigned char first_byte_mark = 0; - - if ((input_end - first_sequence) < 6) - { - /* input ends unexpectedly */ - goto fail; - } - - /* get the first utf16 sequence */ - first_code = parse_hex4(first_sequence + 2); - - /* check that the code is valid */ - if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) - { - goto fail; - } - - /* UTF16 surrogate pair */ - if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) - { - const unsigned char *second_sequence = first_sequence + 6; - unsigned int second_code = 0; - sequence_length = 12; /* \uXXXX\uXXXX */ - - if ((input_end - second_sequence) < 6) - { - /* input ends unexpectedly */ - goto fail; - } - - if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) - { - /* missing second half of the surrogate pair */ - goto fail; - } - - /* get the second utf16 sequence */ - second_code = parse_hex4(second_sequence + 2); - /* check that the code is valid */ - if ((second_code < 0xDC00) || (second_code > 0xDFFF)) - { - /* invalid second half of the surrogate pair */ - goto fail; - } - - - /* calculate the unicode codepoint from the surrogate pair */ - codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); - } - else - { - sequence_length = 6; /* \uXXXX */ - codepoint = first_code; - } - - /* encode as UTF-8 - * takes at maximum 4 bytes to encode: - * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ - if (codepoint < 0x80) - { - /* normal ascii, encoding 0xxxxxxx */ - utf8_length = 1; - } - else if (codepoint < 0x800) - { - /* two bytes, encoding 110xxxxx 10xxxxxx */ - utf8_length = 2; - first_byte_mark = 0xC0; /* 11000000 */ - } - else if (codepoint < 0x10000) - { - /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ - utf8_length = 3; - first_byte_mark = 0xE0; /* 11100000 */ - } - else if (codepoint <= 0x10FFFF) - { - /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */ - utf8_length = 4; - first_byte_mark = 0xF0; /* 11110000 */ - } - else - { - /* invalid unicode codepoint */ - goto fail; - } - - /* encode as utf8 */ - for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) - { - /* 10xxxxxx */ - (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF); - codepoint >>= 6; - } - /* encode first byte */ - if (utf8_length > 1) - { - (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF); - } - else - { - (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); - } - - *output_pointer += utf8_length; - - return sequence_length; - -fail: - return 0; -} - -/* Parse the input text into an unescaped cinput, and populate item. */ -static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer) -{ - const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1; - const unsigned char *input_end = buffer_at_offset(input_buffer) + 1; - unsigned char *output_pointer = NULL; - unsigned char *output = NULL; - - /* not a string */ - if (buffer_at_offset(input_buffer)[0] != '\"') - { - goto fail; - } - - { - /* calculate approximate size of the output (overestimate) */ - size_t allocation_length = 0; - size_t skipped_bytes = 0; - while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) - { - /* is escape sequence */ - if (input_end[0] == '\\') - { - if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) - { - /* prevent buffer overflow when last input character is a backslash */ - goto fail; - } - skipped_bytes++; - input_end++; - } - input_end++; - } - if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) - { - goto fail; /* string ended unexpectedly */ - } - - /* This is at most how much we need for the output */ - allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes; - output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof("")); - if (output == NULL) - { - goto fail; /* allocation failure */ - } - } - - output_pointer = output; - /* loop through the string literal */ - while (input_pointer < input_end) - { - if (*input_pointer != '\\') - { - *output_pointer++ = *input_pointer++; - } - /* escape sequence */ - else - { - unsigned char sequence_length = 2; - if ((input_end - input_pointer) < 1) - { - goto fail; - } - - switch (input_pointer[1]) - { - case 'b': - *output_pointer++ = '\b'; - break; - case 'f': - *output_pointer++ = '\f'; - break; - case 'n': - *output_pointer++ = '\n'; - break; - case 'r': - *output_pointer++ = '\r'; - break; - case 't': - *output_pointer++ = '\t'; - break; - case '\"': - case '\\': - case '/': - *output_pointer++ = input_pointer[1]; - break; - - /* UTF-16 literal */ - case 'u': - sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); - if (sequence_length == 0) - { - /* failed to convert UTF16-literal to UTF-8 */ - goto fail; - } - break; - - default: - goto fail; - } - input_pointer += sequence_length; - } - } - - /* zero terminate the output */ - *output_pointer = '\0'; - - item->type = cJSON_String; - item->valuestring = (char*)output; - - input_buffer->offset = (size_t) (input_end - input_buffer->content); - input_buffer->offset++; - - return true; - -fail: - if (output != NULL) - { - input_buffer->hooks.deallocate(output); - } - - if (input_pointer != NULL) - { - input_buffer->offset = (size_t)(input_pointer - input_buffer->content); - } - - return false; -} - -/* Render the cstring provided to an escaped version that can be printed. */ -static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer) -{ - const unsigned char *input_pointer = NULL; - unsigned char *output = NULL; - unsigned char *output_pointer = NULL; - size_t output_length = 0; - /* numbers of additional characters needed for escaping */ - size_t escape_characters = 0; - - if (output_buffer == NULL) - { - return false; - } - - /* empty string */ - if (input == NULL) - { - output = ensure(output_buffer, sizeof("\"\"")); - if (output == NULL) - { - return false; - } - strcpy((char*)output, "\"\""); - - return true; - } - - /* set "flag" to 1 if something needs to be escaped */ - for (input_pointer = input; *input_pointer; input_pointer++) - { - switch (*input_pointer) - { - case '\"': - case '\\': - case '\b': - case '\f': - case '\n': - case '\r': - case '\t': - /* one character escape sequence */ - escape_characters++; - break; - default: - if (*input_pointer < 32) - { - /* UTF-16 escape sequence uXXXX */ - escape_characters += 5; - } - break; - } - } - output_length = (size_t)(input_pointer - input) + escape_characters; - - output = ensure(output_buffer, output_length + sizeof("\"\"")); - if (output == NULL) - { - return false; - } - - /* no characters have to be escaped */ - if (escape_characters == 0) - { - output[0] = '\"'; - memcpy(output + 1, input, output_length); - output[output_length + 1] = '\"'; - output[output_length + 2] = '\0'; - - return true; - } - - output[0] = '\"'; - output_pointer = output + 1; - /* copy the string */ - for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) - { - if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) - { - /* normal character, copy */ - *output_pointer = *input_pointer; - } - else - { - /* character needs to be escaped */ - *output_pointer++ = '\\'; - switch (*input_pointer) - { - case '\\': - *output_pointer = '\\'; - break; - case '\"': - *output_pointer = '\"'; - break; - case '\b': - *output_pointer = 'b'; - break; - case '\f': - *output_pointer = 'f'; - break; - case '\n': - *output_pointer = 'n'; - break; - case '\r': - *output_pointer = 'r'; - break; - case '\t': - *output_pointer = 't'; - break; - default: - /* escape and print as unicode codepoint */ - sprintf((char*)output_pointer, "u%04x", *input_pointer); - output_pointer += 4; - break; - } - } - } - output[output_length + 1] = '\"'; - output[output_length + 2] = '\0'; - - return true; -} - -/* Invoke print_string_ptr (which is useful) on an item. */ -static cJSON_bool print_string(const cJSON * const item, printbuffer * const p) -{ - return print_string_ptr((unsigned char*)item->valuestring, p); -} - -/* Predeclare these prototypes. */ -static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer); -static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer); -static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer); -static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer); -static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer); -static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer); - -/* Utility to jump whitespace and cr/lf */ -static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) -{ - if ((buffer == NULL) || (buffer->content == NULL)) - { - return NULL; - } - - while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) - { - buffer->offset++; - } - - if (buffer->offset == buffer->length) - { - buffer->offset--; - } - - return buffer; -} - -/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */ -static parse_buffer *skip_utf8_bom(parse_buffer * const buffer) -{ - if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) - { - return NULL; - } - - if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) - { - buffer->offset += 3; - } - - return buffer; -} - -/* Parse an object - create a new root, and populate. */ -CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) -{ - parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; - cJSON *item = NULL; - - /* reset error position */ - global_error.json = NULL; - global_error.position = 0; - - if (value == NULL) - { - goto fail; - } - - buffer.content = (const unsigned char*)value; - buffer.length = strlen((const char*)value) + sizeof(""); - buffer.offset = 0; - buffer.hooks = global_hooks; - - item = cJSON_New_Item(&global_hooks); - if (item == NULL) /* memory fail */ - { - goto fail; - } - - if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) - { - /* parse failure. ep is set. */ - goto fail; - } - - /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ - if (require_null_terminated) - { - buffer_skip_whitespace(&buffer); - if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') - { - goto fail; - } - } - if (return_parse_end) - { - *return_parse_end = (const char*)buffer_at_offset(&buffer); - } - - return item; - -fail: - if (item != NULL) - { - cJSON_Delete(item); - } - - if (value != NULL) - { - error local_error; - local_error.json = (const unsigned char*)value; - local_error.position = 0; - - if (buffer.offset < buffer.length) - { - local_error.position = buffer.offset; - } - else if (buffer.length > 0) - { - local_error.position = buffer.length - 1; - } - - if (return_parse_end != NULL) - { - *return_parse_end = (const char*)local_error.json + local_error.position; - } - - global_error = local_error; - } - - return NULL; -} - -/* Default options for cJSON_Parse */ -CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) -{ - return cJSON_ParseWithOpts(value, 0, 0); -} - -#define cjson_min(a, b) ((a < b) ? a : b) - -static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks) -{ - static const size_t default_buffer_size = 256; - printbuffer buffer[1]; - unsigned char *printed = NULL; - - memset(buffer, 0, sizeof(buffer)); - - /* create buffer */ - buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size); - buffer->length = default_buffer_size; - buffer->format = format; - buffer->hooks = *hooks; - if (buffer->buffer == NULL) - { - goto fail; - } - - /* print the value */ - if (!print_value(item, buffer)) - { - goto fail; - } - update_offset(buffer); - - /* check if reallocate is available */ - if (hooks->reallocate != NULL) - { - printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1); - if (printed == NULL) { - goto fail; - } - buffer->buffer = NULL; - } - else /* otherwise copy the JSON over to a new buffer */ - { - printed = (unsigned char*) hooks->allocate(buffer->offset + 1); - if (printed == NULL) - { - goto fail; - } - memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1)); - printed[buffer->offset] = '\0'; /* just to be sure */ - - /* free the buffer */ - hooks->deallocate(buffer->buffer); - } - - return printed; - -fail: - if (buffer->buffer != NULL) - { - hooks->deallocate(buffer->buffer); - } - - if (printed != NULL) - { - hooks->deallocate(printed); - } - - return NULL; -} - -/* Render a cJSON item/entity/structure to text. */ -CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) -{ - return (char*)print(item, true, &global_hooks); -} - -CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) -{ - return (char*)print(item, false, &global_hooks); -} - -CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) -{ - printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; - - if (prebuffer < 0) - { - return NULL; - } - - p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer); - if (!p.buffer) - { - return NULL; - } - - p.length = (size_t)prebuffer; - p.offset = 0; - p.noalloc = false; - p.format = fmt; - p.hooks = global_hooks; - - if (!print_value(item, &p)) - { - global_hooks.deallocate(p.buffer); - return NULL; - } - - return (char*)p.buffer; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt) -{ - printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; - - if ((len < 0) || (buf == NULL)) - { - return false; - } - - p.buffer = (unsigned char*)buf; - p.length = (size_t)len; - p.offset = 0; - p.noalloc = true; - p.format = fmt; - p.hooks = global_hooks; - - return print_value(item, &p); -} - -/* Parser core - when encountering text, process appropriately. */ -static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer) -{ - if ((input_buffer == NULL) || (input_buffer->content == NULL)) - { - return false; /* no input */ - } - - /* parse the different types of values */ - /* null */ - if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0)) - { - item->type = cJSON_NULL; - input_buffer->offset += 4; - return true; - } - /* false */ - if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0)) - { - item->type = cJSON_False; - input_buffer->offset += 5; - return true; - } - /* true */ - if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0)) - { - item->type = cJSON_True; - item->valueint = 1; - input_buffer->offset += 4; - return true; - } - /* string */ - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) - { - return parse_string(item, input_buffer); - } - /* number */ - if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) - { - return parse_number(item, input_buffer); - } - /* array */ - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) - { - return parse_array(item, input_buffer); - } - /* object */ - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) - { - return parse_object(item, input_buffer); - } - - return false; -} - -/* Render a value to text. */ -static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer) -{ - unsigned char *output = NULL; - - if ((item == NULL) || (output_buffer == NULL)) - { - return false; - } - - switch ((item->type) & 0xFF) - { - case cJSON_NULL: - output = ensure(output_buffer, 5); - if (output == NULL) - { - return false; - } - strcpy((char*)output, "null"); - return true; - - case cJSON_False: - output = ensure(output_buffer, 6); - if (output == NULL) - { - return false; - } - strcpy((char*)output, "false"); - return true; - - case cJSON_True: - output = ensure(output_buffer, 5); - if (output == NULL) - { - return false; - } - strcpy((char*)output, "true"); - return true; - - case cJSON_Number: - return print_number(item, output_buffer); - - case cJSON_Raw: - { - size_t raw_length = 0; - if (item->valuestring == NULL) - { - return false; - } - - raw_length = strlen(item->valuestring) + sizeof(""); - output = ensure(output_buffer, raw_length); - if (output == NULL) - { - return false; - } - memcpy(output, item->valuestring, raw_length); - return true; - } - - case cJSON_String: - return print_string(item, output_buffer); - - case cJSON_Array: - return print_array(item, output_buffer); - - case cJSON_Object: - return print_object(item, output_buffer); - - default: - return false; - } -} - -/* Build an array from input text. */ -static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer) -{ - cJSON *head = NULL; /* head of the linked list */ - cJSON *current_item = NULL; - - if (input_buffer->depth >= CJSON_NESTING_LIMIT) - { - return false; /* to deeply nested */ - } - input_buffer->depth++; - - if (buffer_at_offset(input_buffer)[0] != '[') - { - /* not an array */ - goto fail; - } - - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) - { - /* empty array */ - goto success; - } - - /* check if we skipped to the end of the buffer */ - if (cannot_access_at_index(input_buffer, 0)) - { - input_buffer->offset--; - goto fail; - } - - /* step back to character in front of the first element */ - input_buffer->offset--; - /* loop through the comma separated array elements */ - do - { - /* allocate next item */ - cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); - if (new_item == NULL) - { - goto fail; /* allocation failure */ - } - - /* attach next item to list */ - if (head == NULL) - { - /* start the linked list */ - current_item = head = new_item; - } - else - { - /* add to the end and advance */ - current_item->next = new_item; - new_item->prev = current_item; - current_item = new_item; - } - - /* parse next value */ - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (!parse_value(current_item, input_buffer)) - { - goto fail; /* failed to parse value */ - } - buffer_skip_whitespace(input_buffer); - } - while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); - - if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') - { - goto fail; /* expected end of array */ - } - -success: - input_buffer->depth--; - - item->type = cJSON_Array; - item->child = head; - - input_buffer->offset++; - - return true; - -fail: - if (head != NULL) - { - cJSON_Delete(head); - } - - return false; -} - -/* Render an array to text */ -static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer) -{ - unsigned char *output_pointer = NULL; - size_t length = 0; - cJSON *current_element = item->child; - - if (output_buffer == NULL) - { - return false; - } - - /* Compose the output array. */ - /* opening square bracket */ - output_pointer = ensure(output_buffer, 1); - if (output_pointer == NULL) - { - return false; - } - - *output_pointer = '['; - output_buffer->offset++; - output_buffer->depth++; - - while (current_element != NULL) - { - if (!print_value(current_element, output_buffer)) - { - return false; - } - update_offset(output_buffer); - if (current_element->next) - { - length = (size_t) (output_buffer->format ? 2 : 1); - output_pointer = ensure(output_buffer, length + 1); - if (output_pointer == NULL) - { - return false; - } - *output_pointer++ = ','; - if(output_buffer->format) - { - *output_pointer++ = ' '; - } - *output_pointer = '\0'; - output_buffer->offset += length; - } - current_element = current_element->next; - } - - output_pointer = ensure(output_buffer, 2); - if (output_pointer == NULL) - { - return false; - } - *output_pointer++ = ']'; - *output_pointer = '\0'; - output_buffer->depth--; - - return true; -} - -/* Build an object from the text. */ -static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer) -{ - cJSON *head = NULL; /* linked list head */ - cJSON *current_item = NULL; - - if (input_buffer->depth >= CJSON_NESTING_LIMIT) - { - return false; /* to deeply nested */ - } - input_buffer->depth++; - - if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) - { - goto fail; /* not an object */ - } - - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) - { - goto success; /* empty object */ - } - - /* check if we skipped to the end of the buffer */ - if (cannot_access_at_index(input_buffer, 0)) - { - input_buffer->offset--; - goto fail; - } - - /* step back to character in front of the first element */ - input_buffer->offset--; - /* loop through the comma separated array elements */ - do - { - /* allocate next item */ - cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); - if (new_item == NULL) - { - goto fail; /* allocation failure */ - } - - /* attach next item to list */ - if (head == NULL) - { - /* start the linked list */ - current_item = head = new_item; - } - else - { - /* add to the end and advance */ - current_item->next = new_item; - new_item->prev = current_item; - current_item = new_item; - } - - /* parse the name of the child */ - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (!parse_string(current_item, input_buffer)) - { + if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) + { + return false; + } + + /* reserve appropriate space in the output */ + output_pointer = ensure(output_buffer, (size_t)length + sizeof("")); + if (output_pointer == NULL) + { + return false; + } + + /* copy the printed number to the output and replace locale + * dependent decimal point with '.' */ + for (i = 0; i < ((size_t)length); i++) + { + if (number_buffer[i] == decimal_point) + { + output_pointer[i] = '.'; + continue; + } + + output_pointer[i] = number_buffer[i]; + } + output_pointer[i] = '\0'; + + output_buffer->offset += (size_t)length; + + return true; +} + +/* parse 4 digit hexadecimal number */ +static unsigned parse_hex4(const unsigned char * const input) +{ + unsigned int h = 0; + size_t i = 0; + + for (i = 0; i < 4; i++) + { + /* parse digit */ + if ((input[i] >= '0') && (input[i] <= '9')) + { + h += (unsigned int) input[i] - '0'; + } + else if ((input[i] >= 'A') && (input[i] <= 'F')) + { + h += (unsigned int) 10 + input[i] - 'A'; + } + else if ((input[i] >= 'a') && (input[i] <= 'f')) + { + h += (unsigned int) 10 + input[i] - 'a'; + } + else /* invalid */ + { + return 0; + } + + if (i < 3) + { + /* shift left to make place for the next nibble */ + h = h << 4; + } + } + + return h; +} + +/* converts a UTF-16 literal to UTF-8 + * A literal can be one or two sequences of the form \uXXXX */ +static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer) +{ + long unsigned int codepoint = 0; + unsigned int first_code = 0; + const unsigned char *first_sequence = input_pointer; + unsigned char utf8_length = 0; + unsigned char utf8_position = 0; + unsigned char sequence_length = 0; + unsigned char first_byte_mark = 0; + + if ((input_end - first_sequence) < 6) + { + /* input ends unexpectedly */ + goto fail; + } + + /* get the first utf16 sequence */ + first_code = parse_hex4(first_sequence + 2); + + /* check that the code is valid */ + if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) + { + goto fail; + } + + /* UTF16 surrogate pair */ + if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) + { + const unsigned char *second_sequence = first_sequence + 6; + unsigned int second_code = 0; + sequence_length = 12; /* \uXXXX\uXXXX */ + + if ((input_end - second_sequence) < 6) + { + /* input ends unexpectedly */ + goto fail; + } + + if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) + { + /* missing second half of the surrogate pair */ + goto fail; + } + + /* get the second utf16 sequence */ + second_code = parse_hex4(second_sequence + 2); + /* check that the code is valid */ + if ((second_code < 0xDC00) || (second_code > 0xDFFF)) + { + /* invalid second half of the surrogate pair */ + goto fail; + } + + + /* calculate the unicode codepoint from the surrogate pair */ + codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); + } + else + { + sequence_length = 6; /* \uXXXX */ + codepoint = first_code; + } + + /* encode as UTF-8 + * takes at maximum 4 bytes to encode: + * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ + if (codepoint < 0x80) + { + /* normal ascii, encoding 0xxxxxxx */ + utf8_length = 1; + } + else if (codepoint < 0x800) + { + /* two bytes, encoding 110xxxxx 10xxxxxx */ + utf8_length = 2; + first_byte_mark = 0xC0; /* 11000000 */ + } + else if (codepoint < 0x10000) + { + /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ + utf8_length = 3; + first_byte_mark = 0xE0; /* 11100000 */ + } + else if (codepoint <= 0x10FFFF) + { + /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */ + utf8_length = 4; + first_byte_mark = 0xF0; /* 11110000 */ + } + else + { + /* invalid unicode codepoint */ + goto fail; + } + + /* encode as utf8 */ + for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) + { + /* 10xxxxxx */ + (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF); + codepoint >>= 6; + } + /* encode first byte */ + if (utf8_length > 1) + { + (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF); + } + else + { + (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); + } + + *output_pointer += utf8_length; + + return sequence_length; + +fail: + return 0; +} + +/* Parse the input text into an unescaped cinput, and populate item. */ +static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer) +{ + const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1; + const unsigned char *input_end = buffer_at_offset(input_buffer) + 1; + unsigned char *output_pointer = NULL; + unsigned char *output = NULL; + + /* not a string */ + if (buffer_at_offset(input_buffer)[0] != '\"') + { + goto fail; + } + + { + /* calculate approximate size of the output (overestimate) */ + size_t allocation_length = 0; + size_t skipped_bytes = 0; + while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) + { + /* is escape sequence */ + if (input_end[0] == '\\') + { + if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) + { + /* prevent buffer overflow when last input character is a backslash */ + goto fail; + } + skipped_bytes++; + input_end++; + } + input_end++; + } + if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) + { + goto fail; /* string ended unexpectedly */ + } + + /* This is at most how much we need for the output */ + allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes; + output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof("")); + if (output == NULL) + { + goto fail; /* allocation failure */ + } + } + + output_pointer = output; + /* loop through the string literal */ + while (input_pointer < input_end) + { + if (*input_pointer != '\\') + { + *output_pointer++ = *input_pointer++; + } + /* escape sequence */ + else + { + unsigned char sequence_length = 2; + if ((input_end - input_pointer) < 1) + { + goto fail; + } + + switch (input_pointer[1]) + { + case 'b': + *output_pointer++ = '\b'; + break; + case 'f': + *output_pointer++ = '\f'; + break; + case 'n': + *output_pointer++ = '\n'; + break; + case 'r': + *output_pointer++ = '\r'; + break; + case 't': + *output_pointer++ = '\t'; + break; + case '\"': + case '\\': + case '/': + *output_pointer++ = input_pointer[1]; + break; + + /* UTF-16 literal */ + case 'u': + sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); + if (sequence_length == 0) + { + /* failed to convert UTF16-literal to UTF-8 */ + goto fail; + } + break; + + default: + goto fail; + } + input_pointer += sequence_length; + } + } + + /* zero terminate the output */ + *output_pointer = '\0'; + + item->type = cJSON_String; + item->valuestring = (char*)output; + + input_buffer->offset = (size_t) (input_end - input_buffer->content); + input_buffer->offset++; + + return true; + +fail: + if (output != NULL) + { + input_buffer->hooks.deallocate(output); + } + + if (input_pointer != NULL) + { + input_buffer->offset = (size_t)(input_pointer - input_buffer->content); + } + + return false; +} + +/* Render the cstring provided to an escaped version that can be printed. */ +static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer) +{ + const unsigned char *input_pointer = NULL; + unsigned char *output = NULL; + unsigned char *output_pointer = NULL; + size_t output_length = 0; + /* numbers of additional characters needed for escaping */ + size_t escape_characters = 0; + + if (output_buffer == NULL) + { + return false; + } + + /* empty string */ + if (input == NULL) + { + output = ensure(output_buffer, sizeof("\"\"")); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "\"\""); + + return true; + } + + /* set "flag" to 1 if something needs to be escaped */ + for (input_pointer = input; *input_pointer; input_pointer++) + { + switch (*input_pointer) + { + case '\"': + case '\\': + case '\b': + case '\f': + case '\n': + case '\r': + case '\t': + /* one character escape sequence */ + escape_characters++; + break; + default: + if (*input_pointer < 32) + { + /* UTF-16 escape sequence uXXXX */ + escape_characters += 5; + } + break; + } + } + output_length = (size_t)(input_pointer - input) + escape_characters; + + output = ensure(output_buffer, output_length + sizeof("\"\"")); + if (output == NULL) + { + return false; + } + + /* no characters have to be escaped */ + if (escape_characters == 0) + { + output[0] = '\"'; + memcpy(output + 1, input, output_length); + output[output_length + 1] = '\"'; + output[output_length + 2] = '\0'; + + return true; + } + + output[0] = '\"'; + output_pointer = output + 1; + /* copy the string */ + for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) + { + if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) + { + /* normal character, copy */ + *output_pointer = *input_pointer; + } + else + { + /* character needs to be escaped */ + *output_pointer++ = '\\'; + switch (*input_pointer) + { + case '\\': + *output_pointer = '\\'; + break; + case '\"': + *output_pointer = '\"'; + break; + case '\b': + *output_pointer = 'b'; + break; + case '\f': + *output_pointer = 'f'; + break; + case '\n': + *output_pointer = 'n'; + break; + case '\r': + *output_pointer = 'r'; + break; + case '\t': + *output_pointer = 't'; + break; + default: + /* escape and print as unicode codepoint */ + sprintf((char*)output_pointer, "u%04x", *input_pointer); + output_pointer += 4; + break; + } + } + } + output[output_length + 1] = '\"'; + output[output_length + 2] = '\0'; + + return true; +} + +/* Invoke print_string_ptr (which is useful) on an item. */ +static cJSON_bool print_string(const cJSON * const item, printbuffer * const p) +{ + return print_string_ptr((unsigned char*)item->valuestring, p); +} + +/* Predeclare these prototypes. */ +static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer); +static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer); +static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer); + +/* Utility to jump whitespace and cr/lf */ +static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) +{ + if ((buffer == NULL) || (buffer->content == NULL)) + { + return NULL; + } + + while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) + { + buffer->offset++; + } + + if (buffer->offset == buffer->length) + { + buffer->offset--; + } + + return buffer; +} + +/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */ +static parse_buffer *skip_utf8_bom(parse_buffer * const buffer) +{ + if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) + { + return NULL; + } + + if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) + { + buffer->offset += 3; + } + + return buffer; +} + +/* Parse an object - create a new root, and populate. */ +CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) +{ + parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; + cJSON *item = NULL; + + /* reset error position */ + global_error.json = NULL; + global_error.position = 0; + + if (value == NULL) + { + goto fail; + } + + buffer.content = (const unsigned char*)value; + buffer.length = strlen((const char*)value) + sizeof(""); + buffer.offset = 0; + buffer.hooks = global_hooks; + + item = cJSON_New_Item(&global_hooks); + if (item == NULL) /* memory fail */ + { + goto fail; + } + + if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) + { + /* parse failure. ep is set. */ + goto fail; + } + + /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ + if (require_null_terminated) + { + buffer_skip_whitespace(&buffer); + if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') + { + goto fail; + } + } + if (return_parse_end) + { + *return_parse_end = (const char*)buffer_at_offset(&buffer); + } + + return item; + +fail: + if (item != NULL) + { + cJSON_Delete(item); + } + + if (value != NULL) + { + error local_error; + local_error.json = (const unsigned char*)value; + local_error.position = 0; + + if (buffer.offset < buffer.length) + { + local_error.position = buffer.offset; + } + else if (buffer.length > 0) + { + local_error.position = buffer.length - 1; + } + + if (return_parse_end != NULL) + { + *return_parse_end = (const char*)local_error.json + local_error.position; + } + + global_error = local_error; + } + + return NULL; +} + +/* Default options for cJSON_Parse */ +CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) +{ + return cJSON_ParseWithOpts(value, 0, 0); +} + +#define cjson_min(a, b) ((a < b) ? a : b) + +static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks) +{ + static const size_t default_buffer_size = 256; + printbuffer buffer[1]; + unsigned char *printed = NULL; + + memset(buffer, 0, sizeof(buffer)); + + /* create buffer */ + buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size); + buffer->length = default_buffer_size; + buffer->format = format; + buffer->hooks = *hooks; + if (buffer->buffer == NULL) + { + goto fail; + } + + /* print the value */ + if (!print_value(item, buffer)) + { + goto fail; + } + update_offset(buffer); + + /* check if reallocate is available */ + if (hooks->reallocate != NULL) + { + printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1); + if (printed == NULL) { + goto fail; + } + buffer->buffer = NULL; + } + else /* otherwise copy the JSON over to a new buffer */ + { + printed = (unsigned char*) hooks->allocate(buffer->offset + 1); + if (printed == NULL) + { + goto fail; + } + memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1)); + printed[buffer->offset] = '\0'; /* just to be sure */ + + /* free the buffer */ + hooks->deallocate(buffer->buffer); + } + + return printed; + +fail: + if (buffer->buffer != NULL) + { + hooks->deallocate(buffer->buffer); + } + + if (printed != NULL) + { + hooks->deallocate(printed); + } + + return NULL; +} + +/* Render a cJSON item/entity/structure to text. */ +CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) +{ + return (char*)print(item, true, &global_hooks); +} + +CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) +{ + return (char*)print(item, false, &global_hooks); +} + +CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) +{ + printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; + + if (prebuffer < 0) + { + return NULL; + } + + p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer); + if (!p.buffer) + { + return NULL; + } + + p.length = (size_t)prebuffer; + p.offset = 0; + p.noalloc = false; + p.format = fmt; + p.hooks = global_hooks; + + if (!print_value(item, &p)) + { + global_hooks.deallocate(p.buffer); + return NULL; + } + + return (char*)p.buffer; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt) +{ + printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; + + if ((len < 0) || (buf == NULL)) + { + return false; + } + + p.buffer = (unsigned char*)buf; + p.length = (size_t)len; + p.offset = 0; + p.noalloc = true; + p.format = fmt; + p.hooks = global_hooks; + + return print_value(item, &p); +} + +/* Parser core - when encountering text, process appropriately. */ +static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer) +{ + if ((input_buffer == NULL) || (input_buffer->content == NULL)) + { + return false; /* no input */ + } + + /* parse the different types of values */ + /* null */ + if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0)) + { + item->type = cJSON_NULL; + input_buffer->offset += 4; + return true; + } + /* false */ + if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0)) + { + item->type = cJSON_False; + input_buffer->offset += 5; + return true; + } + /* true */ + if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0)) + { + item->type = cJSON_True; + item->valueint = 1; + input_buffer->offset += 4; + return true; + } + /* string */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) + { + return parse_string(item, input_buffer); + } + /* number */ + if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) + { + return parse_number(item, input_buffer); + } + /* array */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) + { + return parse_array(item, input_buffer); + } + /* object */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) + { + return parse_object(item, input_buffer); + } + + return false; +} + +/* Render a value to text. */ +static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output = NULL; + + if ((item == NULL) || (output_buffer == NULL)) + { + return false; + } + + switch ((item->type) & 0xFF) + { + case cJSON_NULL: + output = ensure(output_buffer, 5); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "null"); + return true; + + case cJSON_False: + output = ensure(output_buffer, 6); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "false"); + return true; + + case cJSON_True: + output = ensure(output_buffer, 5); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "true"); + return true; + + case cJSON_Number: + return print_number(item, output_buffer); + + case cJSON_Raw: + { + size_t raw_length = 0; + if (item->valuestring == NULL) + { + return false; + } + + raw_length = strlen(item->valuestring) + sizeof(""); + output = ensure(output_buffer, raw_length); + if (output == NULL) + { + return false; + } + memcpy(output, item->valuestring, raw_length); + return true; + } + + case cJSON_String: + return print_string(item, output_buffer); + + case cJSON_Array: + return print_array(item, output_buffer); + + case cJSON_Object: + return print_object(item, output_buffer); + + default: + return false; + } +} + +/* Build an array from input text. */ +static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer) +{ + cJSON *head = NULL; /* head of the linked list */ + cJSON *current_item = NULL; + + if (input_buffer->depth >= CJSON_NESTING_LIMIT) + { + return false; /* to deeply nested */ + } + input_buffer->depth++; + + if (buffer_at_offset(input_buffer)[0] != '[') + { + /* not an array */ + goto fail; + } + + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) + { + /* empty array */ + goto success; + } + + /* check if we skipped to the end of the buffer */ + if (cannot_access_at_index(input_buffer, 0)) + { + input_buffer->offset--; + goto fail; + } + + /* step back to character in front of the first element */ + input_buffer->offset--; + /* loop through the comma separated array elements */ + do + { + /* allocate next item */ + cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); + if (new_item == NULL) + { + goto fail; /* allocation failure */ + } + + /* attach next item to list */ + if (head == NULL) + { + /* start the linked list */ + current_item = head = new_item; + } + else + { + /* add to the end and advance */ + current_item->next = new_item; + new_item->prev = current_item; + current_item = new_item; + } + + /* parse next value */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_value(current_item, input_buffer)) + { + goto fail; /* failed to parse value */ + } + buffer_skip_whitespace(input_buffer); + } + while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + + if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') + { + goto fail; /* expected end of array */ + } + +success: + input_buffer->depth--; + + item->type = cJSON_Array; + item->child = head; + + input_buffer->offset++; + + return true; + +fail: + if (head != NULL) + { + cJSON_Delete(head); + } + + return false; +} + +/* Render an array to text */ +static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + size_t length = 0; + cJSON *current_element = item->child; + + if (output_buffer == NULL) + { + return false; + } + + /* Compose the output array. */ + /* opening square bracket */ + output_pointer = ensure(output_buffer, 1); + if (output_pointer == NULL) + { + return false; + } + + *output_pointer = '['; + output_buffer->offset++; + output_buffer->depth++; + + while (current_element != NULL) + { + if (!print_value(current_element, output_buffer)) + { + return false; + } + update_offset(output_buffer); + if (current_element->next) + { + length = (size_t) (output_buffer->format ? 2 : 1); + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ','; + if(output_buffer->format) + { + *output_pointer++ = ' '; + } + *output_pointer = '\0'; + output_buffer->offset += length; + } + current_element = current_element->next; + } + + output_pointer = ensure(output_buffer, 2); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ']'; + *output_pointer = '\0'; + output_buffer->depth--; + + return true; +} + +/* Build an object from the text. */ +static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer) +{ + cJSON *head = NULL; /* linked list head */ + cJSON *current_item = NULL; + + if (input_buffer->depth >= CJSON_NESTING_LIMIT) + { + return false; /* to deeply nested */ + } + input_buffer->depth++; + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) + { + goto fail; /* not an object */ + } + + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) + { + goto success; /* empty object */ + } + + /* check if we skipped to the end of the buffer */ + if (cannot_access_at_index(input_buffer, 0)) + { + input_buffer->offset--; + goto fail; + } + + /* step back to character in front of the first element */ + input_buffer->offset--; + /* loop through the comma separated array elements */ + do + { + /* allocate next item */ + cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); + if (new_item == NULL) + { + goto fail; /* allocation failure */ + } + + /* attach next item to list */ + if (head == NULL) + { + /* start the linked list */ + current_item = head = new_item; + } + else + { + /* add to the end and advance */ + current_item->next = new_item; + new_item->prev = current_item; + current_item = new_item; + } + + /* parse the name of the child */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_string(current_item, input_buffer)) + { goto fail; /* failed to parse name */ - } - buffer_skip_whitespace(input_buffer); - - /* swap valuestring and string, because we parsed the name */ - current_item->string = current_item->valuestring; - current_item->valuestring = NULL; - - if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) - { - goto fail; /* invalid object */ - } - - /* parse the value */ - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (!parse_value(current_item, input_buffer)) - { - goto fail; /* failed to parse value */ - } - buffer_skip_whitespace(input_buffer); - } - while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); - - if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) - { - goto fail; /* expected end of object */ - } - -success: - input_buffer->depth--; - - item->type = cJSON_Object; - item->child = head; - - input_buffer->offset++; - return true; - -fail: - if (head != NULL) - { - cJSON_Delete(head); - } - - return false; -} - -/* Render an object to text. */ -static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer) -{ - unsigned char *output_pointer = NULL; - size_t length = 0; - cJSON *current_item = item->child; - - if (output_buffer == NULL) - { - return false; - } - - /* Compose the output: */ - length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */ - output_pointer = ensure(output_buffer, length + 1); - if (output_pointer == NULL) - { - return false; - } - - *output_pointer++ = '{'; - output_buffer->depth++; - if (output_buffer->format) - { - *output_pointer++ = '\n'; - } - output_buffer->offset += length; - - while (current_item) - { - if (output_buffer->format) - { - size_t i; - output_pointer = ensure(output_buffer, output_buffer->depth); - if (output_pointer == NULL) - { - return false; - } - for (i = 0; i < output_buffer->depth; i++) - { - *output_pointer++ = '\t'; - } - output_buffer->offset += output_buffer->depth; - } - - /* print key */ - if (!print_string_ptr((unsigned char*)current_item->string, output_buffer)) - { - return false; - } - update_offset(output_buffer); - - length = (size_t) (output_buffer->format ? 2 : 1); - output_pointer = ensure(output_buffer, length); - if (output_pointer == NULL) - { - return false; - } - *output_pointer++ = ':'; - if (output_buffer->format) - { - *output_pointer++ = '\t'; - } - output_buffer->offset += length; - - /* print value */ - if (!print_value(current_item, output_buffer)) - { - return false; - } - update_offset(output_buffer); - - /* print comma if not last */ - length = (size_t) ((output_buffer->format ? 1 : 0) + (current_item->next ? 1 : 0)); - output_pointer = ensure(output_buffer, length + 1); - if (output_pointer == NULL) - { - return false; - } - if (current_item->next) - { - *output_pointer++ = ','; - } - - if (output_buffer->format) - { - *output_pointer++ = '\n'; - } - *output_pointer = '\0'; - output_buffer->offset += length; - - current_item = current_item->next; - } - - output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); - if (output_pointer == NULL) - { - return false; - } - if (output_buffer->format) - { - size_t i; - for (i = 0; i < (output_buffer->depth - 1); i++) - { - *output_pointer++ = '\t'; - } - } - *output_pointer++ = '}'; - *output_pointer = '\0'; - output_buffer->depth--; - - return true; -} - -/* Get Array size/item / object item. */ -CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) -{ - cJSON *child = NULL; - size_t size = 0; - - if (array == NULL) - { - return 0; - } - - child = array->child; - - while(child != NULL) - { - size++; - child = child->next; - } - - /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ - - return (int)size; -} - -static cJSON* get_array_item(const cJSON *array, size_t index) -{ - cJSON *current_child = NULL; - - if (array == NULL) - { - return NULL; - } - - current_child = array->child; - while ((current_child != NULL) && (index > 0)) - { - index--; - current_child = current_child->next; - } - - return current_child; -} - -CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) -{ - if (index < 0) - { - return NULL; - } - - return get_array_item(array, (size_t)index); -} - -static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive) -{ - cJSON *current_element = NULL; - - if ((object == NULL) || (name == NULL)) - { - return NULL; - } - - current_element = object->child; - if (case_sensitive) - { - while ((current_element != NULL) && (strcmp(name, current_element->string) != 0)) - { - current_element = current_element->next; - } - } - else - { - while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0)) - { - current_element = current_element->next; - } - } - - return current_element; -} - -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string) -{ - return get_object_item(object, string, false); -} - -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string) -{ - return get_object_item(object, string, true); -} - -CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string) -{ - return cJSON_GetObjectItem(object, string) ? 1 : 0; -} - -/* Utility for array list handling. */ -static void suffix_object(cJSON *prev, cJSON *item) -{ - prev->next = item; - item->prev = prev; -} - -/* Utility for handling references. */ -static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks) -{ - cJSON *reference = NULL; - if (item == NULL) - { - return NULL; - } - - reference = cJSON_New_Item(hooks); - if (reference == NULL) - { - return NULL; - } - - memcpy(reference, item, sizeof(cJSON)); - reference->string = NULL; - reference->type |= cJSON_IsReference; - reference->next = reference->prev = NULL; - return reference; -} - -static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) -{ - cJSON *child = NULL; - - if ((item == NULL) || (array == NULL)) - { - return false; - } - - child = array->child; - - if (child == NULL) - { - /* list is empty, start new one */ - array->child = item; - } - else - { - /* append to the end */ - while (child->next) - { - child = child->next; - } - suffix_object(child, item); - } - - return true; -} - -/* Add item to array/object. */ -CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item) -{ - add_item_to_array(array, item); -} - -#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) - #pragma GCC diagnostic push -#endif -#ifdef __GNUC__ -#pragma GCC diagnostic ignored "-Wcast-qual" -#endif -/* helper function to cast away const */ -static void* cast_away_const(const void* string) -{ - return (void*)string; -} -#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) - #pragma GCC diagnostic pop -#endif - - -static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key) -{ - char *new_key = NULL; - int new_type = cJSON_Invalid; - - if ((object == NULL) || (string == NULL) || (item == NULL)) - { - return false; - } - - if (constant_key) - { - new_key = (char*)cast_away_const(string); - new_type = item->type | cJSON_StringIsConst; - } - else - { - new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks); - if (new_key == NULL) - { - return false; - } - - new_type = item->type & ~cJSON_StringIsConst; - } - - if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) - { - hooks->deallocate(item->string); - } - - item->string = new_key; - item->type = new_type; - - return add_item_to_array(object, item); -} - -CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) -{ - add_item_to_object(object, string, item, &global_hooks, false); -} - -/* Add an item to an object with constant string as key */ -CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) -{ - add_item_to_object(object, string, item, &global_hooks, true); -} - -CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) -{ - if (array == NULL) - { - return; - } - - add_item_to_array(array, create_reference(item, &global_hooks)); -} - -CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) -{ - if ((object == NULL) || (string == NULL)) - { - return; - } - - add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false); -} - -CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name) -{ - cJSON *null = cJSON_CreateNull(); - if (add_item_to_object(object, name, null, &global_hooks, false)) - { - return null; - } - - cJSON_Delete(null); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name) -{ - cJSON *true_item = cJSON_CreateTrue(); - if (add_item_to_object(object, name, true_item, &global_hooks, false)) - { - return true_item; - } - - cJSON_Delete(true_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name) -{ - cJSON *false_item = cJSON_CreateFalse(); - if (add_item_to_object(object, name, false_item, &global_hooks, false)) - { - return false_item; - } - - cJSON_Delete(false_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean) -{ - cJSON *bool_item = cJSON_CreateBool(boolean); - if (add_item_to_object(object, name, bool_item, &global_hooks, false)) - { - return bool_item; - } - - cJSON_Delete(bool_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number) -{ - cJSON *number_item = cJSON_CreateNumber(number); - if (add_item_to_object(object, name, number_item, &global_hooks, false)) - { - return number_item; - } - - cJSON_Delete(number_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string) -{ - cJSON *string_item = cJSON_CreateString(string); - if (add_item_to_object(object, name, string_item, &global_hooks, false)) - { - return string_item; - } - - cJSON_Delete(string_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw) -{ - cJSON *raw_item = cJSON_CreateRaw(raw); - if (add_item_to_object(object, name, raw_item, &global_hooks, false)) - { - return raw_item; - } - - cJSON_Delete(raw_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name) -{ - cJSON *object_item = cJSON_CreateObject(); - if (add_item_to_object(object, name, object_item, &global_hooks, false)) - { - return object_item; - } - - cJSON_Delete(object_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name) -{ - cJSON *array = cJSON_CreateArray(); - if (add_item_to_object(object, name, array, &global_hooks, false)) - { - return array; - } - - cJSON_Delete(array); - return NULL; -} - -CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item) -{ - if ((parent == NULL) || (item == NULL)) - { - return NULL; - } - - if (item->prev != NULL) - { - /* not the first element */ - item->prev->next = item->next; - } - if (item->next != NULL) - { - /* not the last element */ - item->next->prev = item->prev; - } - - if (item == parent->child) - { - /* first element */ - parent->child = item->next; - } - /* make sure the detached item doesn't point anywhere anymore */ - item->prev = NULL; - item->next = NULL; - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which) -{ - if (which < 0) - { - return NULL; - } - - return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which)); -} - -CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which) -{ - cJSON_Delete(cJSON_DetachItemFromArray(array, which)); -} - -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string) -{ - cJSON *to_detach = cJSON_GetObjectItem(object, string); - - return cJSON_DetachItemViaPointer(object, to_detach); -} - -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string) -{ - cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string); - - return cJSON_DetachItemViaPointer(object, to_detach); -} - -CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string) -{ - cJSON_Delete(cJSON_DetachItemFromObject(object, string)); -} - -CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string) -{ - cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string)); -} - -/* Replace array/object items with new ones. */ -CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) -{ - cJSON *after_inserted = NULL; - - if (which < 0) - { - return; - } - - after_inserted = get_array_item(array, (size_t)which); - if (after_inserted == NULL) - { - add_item_to_array(array, newitem); - return; - } - - newitem->next = after_inserted; - newitem->prev = after_inserted->prev; - after_inserted->prev = newitem; - if (after_inserted == array->child) - { - array->child = newitem; - } - else - { - newitem->prev->next = newitem; - } -} - -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement) -{ - if ((parent == NULL) || (replacement == NULL) || (item == NULL)) - { - return false; - } - - if (replacement == item) - { - return true; - } - - replacement->next = item->next; - replacement->prev = item->prev; - - if (replacement->next != NULL) - { - replacement->next->prev = replacement; - } - if (replacement->prev != NULL) - { - replacement->prev->next = replacement; - } - if (parent->child == item) - { - parent->child = replacement; - } - - item->next = NULL; - item->prev = NULL; - cJSON_Delete(item); - - return true; -} - -CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) -{ - if (which < 0) - { - return; - } - - cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem); -} - -static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive) -{ - if ((replacement == NULL) || (string == NULL)) - { - return false; - } - - /* replace the name in the replacement */ - if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) - { - cJSON_free(replacement->string); - } - replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); - replacement->type &= ~cJSON_StringIsConst; - - cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement); - - return true; -} - -CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) -{ - replace_item_in_object(object, string, newitem, false); -} - -CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem) -{ - replace_item_in_object(object, string, newitem, true); -} - -/* Create basic types: */ -CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_NULL; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_True; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_False; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = b ? cJSON_True : cJSON_False; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_Number; - item->valuedouble = num; - - /* use saturation in case of overflow */ - if (num >= INT_MAX) - { - item->valueint = INT_MAX; - } - else if (num <= INT_MIN) - { - item->valueint = INT_MIN; - } - else - { - item->valueint = (int)num; - } - } - - return item; -} - + } + buffer_skip_whitespace(input_buffer); + + /* swap valuestring and string, because we parsed the name */ + current_item->string = current_item->valuestring; + current_item->valuestring = NULL; + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) + { + goto fail; /* invalid object */ + } + + /* parse the value */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_value(current_item, input_buffer)) + { + goto fail; /* failed to parse value */ + } + buffer_skip_whitespace(input_buffer); + } + while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) + { + goto fail; /* expected end of object */ + } + +success: + input_buffer->depth--; + + item->type = cJSON_Object; + item->child = head; + + input_buffer->offset++; + return true; + +fail: + if (head != NULL) + { + cJSON_Delete(head); + } + + return false; +} + +/* Render an object to text. */ +static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + size_t length = 0; + cJSON *current_item = item->child; + + if (output_buffer == NULL) + { + return false; + } + + /* Compose the output: */ + length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */ + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + + *output_pointer++ = '{'; + output_buffer->depth++; + if (output_buffer->format) + { + *output_pointer++ = '\n'; + } + output_buffer->offset += length; + + while (current_item) + { + if (output_buffer->format) + { + size_t i; + output_pointer = ensure(output_buffer, output_buffer->depth); + if (output_pointer == NULL) + { + return false; + } + for (i = 0; i < output_buffer->depth; i++) + { + *output_pointer++ = '\t'; + } + output_buffer->offset += output_buffer->depth; + } + + /* print key */ + if (!print_string_ptr((unsigned char*)current_item->string, output_buffer)) + { + return false; + } + update_offset(output_buffer); + + length = (size_t) (output_buffer->format ? 2 : 1); + output_pointer = ensure(output_buffer, length); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ':'; + if (output_buffer->format) + { + *output_pointer++ = '\t'; + } + output_buffer->offset += length; + + /* print value */ + if (!print_value(current_item, output_buffer)) + { + return false; + } + update_offset(output_buffer); + + /* print comma if not last */ + length = (size_t) ((output_buffer->format ? 1 : 0) + (current_item->next ? 1 : 0)); + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + if (current_item->next) + { + *output_pointer++ = ','; + } + + if (output_buffer->format) + { + *output_pointer++ = '\n'; + } + *output_pointer = '\0'; + output_buffer->offset += length; + + current_item = current_item->next; + } + + output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); + if (output_pointer == NULL) + { + return false; + } + if (output_buffer->format) + { + size_t i; + for (i = 0; i < (output_buffer->depth - 1); i++) + { + *output_pointer++ = '\t'; + } + } + *output_pointer++ = '}'; + *output_pointer = '\0'; + output_buffer->depth--; + + return true; +} + +/* Get Array size/item / object item. */ +CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) +{ + cJSON *child = NULL; + size_t size = 0; + + if (array == NULL) + { + return 0; + } + + child = array->child; + + while(child != NULL) + { + size++; + child = child->next; + } + + /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ + + return (int)size; +} + +static cJSON* get_array_item(const cJSON *array, size_t index) +{ + cJSON *current_child = NULL; + + if (array == NULL) + { + return NULL; + } + + current_child = array->child; + while ((current_child != NULL) && (index > 0)) + { + index--; + current_child = current_child->next; + } + + return current_child; +} + +CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) +{ + if (index < 0) + { + return NULL; + } + + return get_array_item(array, (size_t)index); +} + +static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive) +{ + cJSON *current_element = NULL; + + if ((object == NULL) || (name == NULL)) + { + return NULL; + } + + current_element = object->child; + if (case_sensitive) + { + while ((current_element != NULL) && (strcmp(name, current_element->string) != 0)) + { + current_element = current_element->next; + } + } + else + { + while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0)) + { + current_element = current_element->next; + } + } + + return current_element; +} + +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string) +{ + return get_object_item(object, string, false); +} + +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string) +{ + return get_object_item(object, string, true); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string) +{ + return cJSON_GetObjectItem(object, string) ? 1 : 0; +} + +/* Utility for array list handling. */ +static void suffix_object(cJSON *prev, cJSON *item) +{ + prev->next = item; + item->prev = prev; +} + +/* Utility for handling references. */ +static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks) +{ + cJSON *reference = NULL; + if (item == NULL) + { + return NULL; + } + + reference = cJSON_New_Item(hooks); + if (reference == NULL) + { + return NULL; + } + + memcpy(reference, item, sizeof(cJSON)); + reference->string = NULL; + reference->type |= cJSON_IsReference; + reference->next = reference->prev = NULL; + return reference; +} + +static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) +{ + cJSON *child = NULL; + + if ((item == NULL) || (array == NULL)) + { + return false; + } + + child = array->child; + + if (child == NULL) + { + /* list is empty, start new one */ + array->child = item; + } + else + { + /* append to the end */ + while (child->next) + { + child = child->next; + } + suffix_object(child, item); + } + + return true; +} + +/* Add item to array/object. */ +CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item) +{ + add_item_to_array(array, item); +} + +#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) + #pragma GCC diagnostic push +#endif +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif +/* helper function to cast away const */ +static void* cast_away_const(const void* string) +{ + return (void*)string; +} +#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) + #pragma GCC diagnostic pop +#endif + + +static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key) +{ + char *new_key = NULL; + int new_type = cJSON_Invalid; + + if ((object == NULL) || (string == NULL) || (item == NULL)) + { + return false; + } + + if (constant_key) + { + new_key = (char*)cast_away_const(string); + new_type = item->type | cJSON_StringIsConst; + } + else + { + new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks); + if (new_key == NULL) + { + return false; + } + + new_type = item->type & ~cJSON_StringIsConst; + } + + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) + { + hooks->deallocate(item->string); + } + + item->string = new_key; + item->type = new_type; + + return add_item_to_array(object, item); +} + +CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) +{ + add_item_to_object(object, string, item, &global_hooks, false); +} + +/* Add an item to an object with constant string as key */ +CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) +{ + add_item_to_object(object, string, item, &global_hooks, true); +} + +CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) +{ + if (array == NULL) + { + return; + } + + add_item_to_array(array, create_reference(item, &global_hooks)); +} + +CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) +{ + if ((object == NULL) || (string == NULL)) + { + return; + } + + add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false); +} + +CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name) +{ + cJSON *null = cJSON_CreateNull(); + if (add_item_to_object(object, name, null, &global_hooks, false)) + { + return null; + } + + cJSON_Delete(null); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name) +{ + cJSON *true_item = cJSON_CreateTrue(); + if (add_item_to_object(object, name, true_item, &global_hooks, false)) + { + return true_item; + } + + cJSON_Delete(true_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name) +{ + cJSON *false_item = cJSON_CreateFalse(); + if (add_item_to_object(object, name, false_item, &global_hooks, false)) + { + return false_item; + } + + cJSON_Delete(false_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean) +{ + cJSON *bool_item = cJSON_CreateBool(boolean); + if (add_item_to_object(object, name, bool_item, &global_hooks, false)) + { + return bool_item; + } + + cJSON_Delete(bool_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number) +{ + cJSON *number_item = cJSON_CreateNumber(number); + if (add_item_to_object(object, name, number_item, &global_hooks, false)) + { + return number_item; + } + + cJSON_Delete(number_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string) +{ + cJSON *string_item = cJSON_CreateString(string); + if (add_item_to_object(object, name, string_item, &global_hooks, false)) + { + return string_item; + } + + cJSON_Delete(string_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw) +{ + cJSON *raw_item = cJSON_CreateRaw(raw); + if (add_item_to_object(object, name, raw_item, &global_hooks, false)) + { + return raw_item; + } + + cJSON_Delete(raw_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name) +{ + cJSON *object_item = cJSON_CreateObject(); + if (add_item_to_object(object, name, object_item, &global_hooks, false)) + { + return object_item; + } + + cJSON_Delete(object_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name) +{ + cJSON *array = cJSON_CreateArray(); + if (add_item_to_object(object, name, array, &global_hooks, false)) + { + return array; + } + + cJSON_Delete(array); + return NULL; +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item) +{ + if ((parent == NULL) || (item == NULL)) + { + return NULL; + } + + if (item->prev != NULL) + { + /* not the first element */ + item->prev->next = item->next; + } + if (item->next != NULL) + { + /* not the last element */ + item->next->prev = item->prev; + } + + if (item == parent->child) + { + /* first element */ + parent->child = item->next; + } + /* make sure the detached item doesn't point anywhere anymore */ + item->prev = NULL; + item->next = NULL; + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which) +{ + if (which < 0) + { + return NULL; + } + + return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which)); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which) +{ + cJSON_Delete(cJSON_DetachItemFromArray(array, which)); +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string) +{ + cJSON *to_detach = cJSON_GetObjectItem(object, string); + + return cJSON_DetachItemViaPointer(object, to_detach); +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string) +{ + cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string); + + return cJSON_DetachItemViaPointer(object, to_detach); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string) +{ + cJSON_Delete(cJSON_DetachItemFromObject(object, string)); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string) +{ + cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string)); +} + +/* Replace array/object items with new ones. */ +CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) +{ + cJSON *after_inserted = NULL; + + if (which < 0) + { + return; + } + + after_inserted = get_array_item(array, (size_t)which); + if (after_inserted == NULL) + { + add_item_to_array(array, newitem); + return; + } + + newitem->next = after_inserted; + newitem->prev = after_inserted->prev; + after_inserted->prev = newitem; + if (after_inserted == array->child) + { + array->child = newitem; + } + else + { + newitem->prev->next = newitem; + } +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement) +{ + if ((parent == NULL) || (replacement == NULL) || (item == NULL)) + { + return false; + } + + if (replacement == item) + { + return true; + } + + replacement->next = item->next; + replacement->prev = item->prev; + + if (replacement->next != NULL) + { + replacement->next->prev = replacement; + } + if (replacement->prev != NULL) + { + replacement->prev->next = replacement; + } + if (parent->child == item) + { + parent->child = replacement; + } + + item->next = NULL; + item->prev = NULL; + cJSON_Delete(item); + + return true; +} + +CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) +{ + if (which < 0) + { + return; + } + + cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem); +} + +static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive) +{ + if ((replacement == NULL) || (string == NULL)) + { + return false; + } + + /* replace the name in the replacement */ + if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) + { + cJSON_free(replacement->string); + } + replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); + replacement->type &= ~cJSON_StringIsConst; + + cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement); + + return true; +} + +CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) +{ + replace_item_in_object(object, string, newitem, false); +} + +CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem) +{ + replace_item_in_object(object, string, newitem, true); +} + +/* Create basic types: */ +CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_NULL; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_True; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_False; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = b ? cJSON_True : cJSON_False; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_Number; + item->valuedouble = num; + + /* use saturation in case of overflow */ + if (num >= INT_MAX) + { + item->valueint = INT_MAX; + } + else if (num <= INT_MIN) + { + item->valueint = INT_MIN; + } + else + { + item->valueint = (int)num; + } + } + + return item; +} + CJSON_PUBLIC(cJSON *) cJSON_CreateInt64(long long num) { cJSON *item = cJSON_New_Item(&global_hooks); @@ -2364,620 +2364,620 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateInt64(long long num) return item; } -CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_String; - item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); - if(!item->valuestring) - { - cJSON_Delete(item); - return NULL; - } - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if (item != NULL) - { - item->type = cJSON_String | cJSON_IsReference; - item->valuestring = (char*)cast_away_const(string); - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if (item != NULL) { - item->type = cJSON_Object | cJSON_IsReference; - item->child = (cJSON*)cast_away_const(child); - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) { - cJSON *item = cJSON_New_Item(&global_hooks); - if (item != NULL) { - item->type = cJSON_Array | cJSON_IsReference; - item->child = (cJSON*)cast_away_const(child); - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_Raw; - item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks); - if(!item->valuestring) - { - cJSON_Delete(item); - return NULL; - } - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type=cJSON_Array; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if (item) - { - item->type = cJSON_Object; - } - - return item; -} - -/* Create Arrays: */ -CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) -{ - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; - - if ((count < 0) || (numbers == NULL)) - { - return NULL; - } - - a = cJSON_CreateArray(); - for(i = 0; a && (i < (size_t)count); i++) - { - n = cJSON_CreateNumber(numbers[i]); - if (!n) - { - cJSON_Delete(a); - return NULL; - } - if(!i) - { - a->child = n; - } - else - { - suffix_object(p, n); - } - p = n; - } - - return a; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) -{ - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; - - if ((count < 0) || (numbers == NULL)) - { - return NULL; - } - - a = cJSON_CreateArray(); - - for(i = 0; a && (i < (size_t)count); i++) - { - n = cJSON_CreateNumber((double)numbers[i]); - if(!n) - { - cJSON_Delete(a); - return NULL; - } - if(!i) - { - a->child = n; - } - else - { - suffix_object(p, n); - } - p = n; - } - - return a; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) -{ - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; - - if ((count < 0) || (numbers == NULL)) - { - return NULL; - } - - a = cJSON_CreateArray(); - - for(i = 0;a && (i < (size_t)count); i++) - { - n = cJSON_CreateNumber(numbers[i]); - if(!n) - { - cJSON_Delete(a); - return NULL; - } - if(!i) - { - a->child = n; - } - else - { - suffix_object(p, n); - } - p = n; - } - - return a; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count) -{ - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; - - if ((count < 0) || (strings == NULL)) - { - return NULL; - } - - a = cJSON_CreateArray(); - - for (i = 0; a && (i < (size_t)count); i++) - { - n = cJSON_CreateString(strings[i]); - if(!n) - { - cJSON_Delete(a); - return NULL; - } - if(!i) - { - a->child = n; - } - else - { - suffix_object(p,n); - } - p = n; - } - - return a; -} - -/* Duplication */ -CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) -{ - cJSON *newitem = NULL; - cJSON *child = NULL; - cJSON *next = NULL; - cJSON *newchild = NULL; - - /* Bail on bad ptr */ - if (!item) - { - goto fail; - } - /* Create new item */ - newitem = cJSON_New_Item(&global_hooks); - if (!newitem) - { - goto fail; - } - /* Copy over all vars */ - newitem->type = item->type & (~cJSON_IsReference); - newitem->valueint = item->valueint; - newitem->valuedouble = item->valuedouble; - if (item->valuestring) - { - newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks); - if (!newitem->valuestring) - { - goto fail; - } - } - if (item->string) - { - newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks); - if (!newitem->string) - { - goto fail; - } - } - /* If non-recursive, then we're done! */ - if (!recurse) - { - return newitem; - } - /* Walk the ->next chain for the child. */ - child = item->child; - while (child != NULL) - { - newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */ - if (!newchild) - { - goto fail; - } - if (next != NULL) - { - /* If newitem->child already set, then crosswire ->prev and ->next and move on */ - next->next = newchild; - newchild->prev = next; - next = newchild; - } - else - { - /* Set newitem->child and move to it */ - newitem->child = newchild; - next = newchild; - } - child = child->next; - } - - return newitem; - -fail: - if (newitem != NULL) - { - cJSON_Delete(newitem); - } - - return NULL; -} - -CJSON_PUBLIC(void) cJSON_Minify(char *json) -{ - unsigned char *into = (unsigned char*)json; - - if (json == NULL) - { - return; - } - - while (*json) - { - if (*json == ' ') - { - json++; - } - else if (*json == '\t') - { - /* Whitespace characters. */ - json++; - } - else if (*json == '\r') - { - json++; - } - else if (*json=='\n') - { - json++; - } - else if ((*json == '/') && (json[1] == '/')) - { - /* double-slash comments, to end of line. */ - while (*json && (*json != '\n')) - { - json++; - } - } - else if ((*json == '/') && (json[1] == '*')) - { - /* multiline comments. */ - while (*json && !((*json == '*') && (json[1] == '/'))) - { - json++; - } - json += 2; - } - else if (*json == '\"') - { - /* string literals, which are \" sensitive. */ - *into++ = (unsigned char)*json++; - while (*json && (*json != '\"')) - { - if (*json == '\\') - { - *into++ = (unsigned char)*json++; - } - *into++ = (unsigned char)*json++; - } - *into++ = (unsigned char)*json++; - } - else - { - /* All other characters. */ - *into++ = (unsigned char)*json++; - } - } - - /* and null-terminate. */ - *into = '\0'; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_Invalid; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_False; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xff) == cJSON_True; -} - - -CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & (cJSON_True | cJSON_False)) != 0; -} -CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_NULL; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_Number; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_String; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_Array; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_Object; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_Raw; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive) -{ - if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a)) - { - return false; - } - - /* check if type is valid */ - switch (a->type & 0xFF) - { - case cJSON_False: - case cJSON_True: - case cJSON_NULL: - case cJSON_Number: - case cJSON_String: - case cJSON_Raw: - case cJSON_Array: - case cJSON_Object: - break; - - default: - return false; - } - - /* identical objects are equal */ - if (a == b) - { - return true; - } - - switch (a->type & 0xFF) - { - /* in these cases and equal type is enough */ - case cJSON_False: - case cJSON_True: - case cJSON_NULL: - return true; - - case cJSON_Number: - if (a->valuedouble == b->valuedouble) - { - return true; - } - return false; - - case cJSON_String: - case cJSON_Raw: - if ((a->valuestring == NULL) || (b->valuestring == NULL)) - { - return false; - } - if (strcmp(a->valuestring, b->valuestring) == 0) - { - return true; - } - - return false; - - case cJSON_Array: - { - cJSON *a_element = a->child; - cJSON *b_element = b->child; - - for (; (a_element != NULL) && (b_element != NULL);) - { - if (!cJSON_Compare(a_element, b_element, case_sensitive)) - { - return false; - } - - a_element = a_element->next; - b_element = b_element->next; - } - - /* one of the arrays is longer than the other */ - if (a_element != b_element) { - return false; - } - - return true; - } - - case cJSON_Object: - { - cJSON *a_element = NULL; - cJSON *b_element = NULL; - cJSON_ArrayForEach(a_element, a) - { - /* TODO This has O(n^2) runtime, which is horrible! */ - b_element = get_object_item(b, a_element->string, case_sensitive); - if (b_element == NULL) - { - return false; - } - - if (!cJSON_Compare(a_element, b_element, case_sensitive)) - { - return false; - } - } - - /* doing this twice, once on a and b to prevent true comparison if a subset of b - * TODO: Do this the proper way, this is just a fix for now */ - cJSON_ArrayForEach(b_element, b) - { - a_element = get_object_item(a, b_element->string, case_sensitive); - if (a_element == NULL) - { - return false; - } - - if (!cJSON_Compare(b_element, a_element, case_sensitive)) - { - return false; - } - } - - return true; - } - - default: - return false; - } -} - -CJSON_PUBLIC(void *) cJSON_malloc(size_t size) -{ - return global_hooks.allocate(size); -} - -CJSON_PUBLIC(void) cJSON_free(void *object) -{ - global_hooks.deallocate(object); -} +CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_String; + item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); + if(!item->valuestring) + { + cJSON_Delete(item); + return NULL; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) + { + item->type = cJSON_String | cJSON_IsReference; + item->valuestring = (char*)cast_away_const(string); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) { + item->type = cJSON_Object | cJSON_IsReference; + item->child = (cJSON*)cast_away_const(child); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) { + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) { + item->type = cJSON_Array | cJSON_IsReference; + item->child = (cJSON*)cast_away_const(child); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_Raw; + item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks); + if(!item->valuestring) + { + cJSON_Delete(item); + return NULL; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type=cJSON_Array; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) + { + item->type = cJSON_Object; + } + + return item; +} + +/* Create Arrays: */ +CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + for(i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateNumber(numbers[i]); + if (!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for(i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateNumber((double)numbers[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for(i = 0;a && (i < (size_t)count); i++) + { + n = cJSON_CreateNumber(numbers[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (strings == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for (i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateString(strings[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p,n); + } + p = n; + } + + return a; +} + +/* Duplication */ +CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) +{ + cJSON *newitem = NULL; + cJSON *child = NULL; + cJSON *next = NULL; + cJSON *newchild = NULL; + + /* Bail on bad ptr */ + if (!item) + { + goto fail; + } + /* Create new item */ + newitem = cJSON_New_Item(&global_hooks); + if (!newitem) + { + goto fail; + } + /* Copy over all vars */ + newitem->type = item->type & (~cJSON_IsReference); + newitem->valueint = item->valueint; + newitem->valuedouble = item->valuedouble; + if (item->valuestring) + { + newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks); + if (!newitem->valuestring) + { + goto fail; + } + } + if (item->string) + { + newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks); + if (!newitem->string) + { + goto fail; + } + } + /* If non-recursive, then we're done! */ + if (!recurse) + { + return newitem; + } + /* Walk the ->next chain for the child. */ + child = item->child; + while (child != NULL) + { + newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */ + if (!newchild) + { + goto fail; + } + if (next != NULL) + { + /* If newitem->child already set, then crosswire ->prev and ->next and move on */ + next->next = newchild; + newchild->prev = next; + next = newchild; + } + else + { + /* Set newitem->child and move to it */ + newitem->child = newchild; + next = newchild; + } + child = child->next; + } + + return newitem; + +fail: + if (newitem != NULL) + { + cJSON_Delete(newitem); + } + + return NULL; +} + +CJSON_PUBLIC(void) cJSON_Minify(char *json) +{ + unsigned char *into = (unsigned char*)json; + + if (json == NULL) + { + return; + } + + while (*json) + { + if (*json == ' ') + { + json++; + } + else if (*json == '\t') + { + /* Whitespace characters. */ + json++; + } + else if (*json == '\r') + { + json++; + } + else if (*json=='\n') + { + json++; + } + else if ((*json == '/') && (json[1] == '/')) + { + /* double-slash comments, to end of line. */ + while (*json && (*json != '\n')) + { + json++; + } + } + else if ((*json == '/') && (json[1] == '*')) + { + /* multiline comments. */ + while (*json && !((*json == '*') && (json[1] == '/'))) + { + json++; + } + json += 2; + } + else if (*json == '\"') + { + /* string literals, which are \" sensitive. */ + *into++ = (unsigned char)*json++; + while (*json && (*json != '\"')) + { + if (*json == '\\') + { + *into++ = (unsigned char)*json++; + } + *into++ = (unsigned char)*json++; + } + *into++ = (unsigned char)*json++; + } + else + { + /* All other characters. */ + *into++ = (unsigned char)*json++; + } + } + + /* and null-terminate. */ + *into = '\0'; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Invalid; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_False; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xff) == cJSON_True; +} + + +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & (cJSON_True | cJSON_False)) != 0; +} +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_NULL; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Number; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_String; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Array; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Object; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Raw; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive) +{ + if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a)) + { + return false; + } + + /* check if type is valid */ + switch (a->type & 0xFF) + { + case cJSON_False: + case cJSON_True: + case cJSON_NULL: + case cJSON_Number: + case cJSON_String: + case cJSON_Raw: + case cJSON_Array: + case cJSON_Object: + break; + + default: + return false; + } + + /* identical objects are equal */ + if (a == b) + { + return true; + } + + switch (a->type & 0xFF) + { + /* in these cases and equal type is enough */ + case cJSON_False: + case cJSON_True: + case cJSON_NULL: + return true; + + case cJSON_Number: + if (a->valuedouble == b->valuedouble) + { + return true; + } + return false; + + case cJSON_String: + case cJSON_Raw: + if ((a->valuestring == NULL) || (b->valuestring == NULL)) + { + return false; + } + if (strcmp(a->valuestring, b->valuestring) == 0) + { + return true; + } + + return false; + + case cJSON_Array: + { + cJSON *a_element = a->child; + cJSON *b_element = b->child; + + for (; (a_element != NULL) && (b_element != NULL);) + { + if (!cJSON_Compare(a_element, b_element, case_sensitive)) + { + return false; + } + + a_element = a_element->next; + b_element = b_element->next; + } + + /* one of the arrays is longer than the other */ + if (a_element != b_element) { + return false; + } + + return true; + } + + case cJSON_Object: + { + cJSON *a_element = NULL; + cJSON *b_element = NULL; + cJSON_ArrayForEach(a_element, a) + { + /* TODO This has O(n^2) runtime, which is horrible! */ + b_element = get_object_item(b, a_element->string, case_sensitive); + if (b_element == NULL) + { + return false; + } + + if (!cJSON_Compare(a_element, b_element, case_sensitive)) + { + return false; + } + } + + /* doing this twice, once on a and b to prevent true comparison if a subset of b + * TODO: Do this the proper way, this is just a fix for now */ + cJSON_ArrayForEach(b_element, b) + { + a_element = get_object_item(a, b_element->string, case_sensitive); + if (a_element == NULL) + { + return false; + } + + if (!cJSON_Compare(b_element, a_element, case_sensitive)) + { + return false; + } + } + + return true; + } + + default: + return false; + } +} + +CJSON_PUBLIC(void *) cJSON_malloc(size_t size) +{ + return global_hooks.allocate(size); +} + +CJSON_PUBLIC(void) cJSON_free(void *object) +{ + global_hooks.deallocate(object); +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/external/tinyxml2/tinyxml2.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/external/tinyxml2/tinyxml2.cpp index ebe0fd9eec..b880ff007d 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/external/tinyxml2/tinyxml2.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/external/tinyxml2/tinyxml2.cpp @@ -1,2802 +1,2802 @@ -/* -Original code by Lee Thomason (www.grinninglizard.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -/* -This file has been modified from its original version by Amazon: - (1) Memory management operations use aws memory management api - (2) #includes all use <> -*/ - -#include <aws/core/external/tinyxml2/tinyxml2.h> - -#include <new> // yes, this one new style header, is in the Android SDK. -#if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__) -# include <stddef.h> -# include <stdarg.h> -#else -# include <cstddef> -# include <cstdarg> -#endif - -#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE) - // Microsoft Visual Studio, version 2005 and higher. Not WinCE. - /*int _snprintf_s( - char *buffer, - size_t sizeOfBuffer, - size_t count, - const char *format [, - argument] ... - );*/ - static inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... ) - { - va_list va; - va_start( va, format ); - int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va ); - va_end( va ); - return result; - } - - static inline int TIXML_VSNPRINTF( char* buffer, size_t size, const char* format, va_list va ) - { - int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va ); - return result; - } - - #define TIXML_VSCPRINTF _vscprintf - #define TIXML_SSCANF sscanf_s -#elif defined _MSC_VER - // Microsoft Visual Studio 2003 and earlier or WinCE - #define TIXML_SNPRINTF _snprintf - #define TIXML_VSNPRINTF _vsnprintf - #define TIXML_SSCANF sscanf - #if (_MSC_VER < 1400 ) && (!defined WINCE) - // Microsoft Visual Studio 2003 and not WinCE. - #define TIXML_VSCPRINTF _vscprintf // VS2003's C runtime has this, but VC6 C runtime or WinCE SDK doesn't have. - #else - // Microsoft Visual Studio 2003 and earlier or WinCE. - static inline int TIXML_VSCPRINTF( const char* format, va_list va ) - { - int len = 512; - for (;;) { - len = len*2; - char* str = Aws::NewArray<char>(len, ALLOCATION_TAG); - const int required = _vsnprintf(str, len, format, va); - Aws::DeleteArray(str); - if ( required != -1 ) { - TIXMLASSERT( required >= 0 ); - len = required; - break; - } - } - TIXMLASSERT( len >= 0 ); - return len; - } - #endif -#else - // GCC version 3 and higher - //#warning( "Using sn* functions." ) - #define TIXML_SNPRINTF snprintf - #define TIXML_VSNPRINTF vsnprintf - static inline int TIXML_VSCPRINTF( const char* format, va_list va ) - { - int len = vsnprintf( 0, 0, format, va ); - TIXMLASSERT( len >= 0 ); - return len; - } - #define TIXML_SSCANF sscanf -#endif - - -static const char LINE_FEED = (char)0x0a; // all line endings are normalized to LF -static const char LF = LINE_FEED; -static const char CARRIAGE_RETURN = (char)0x0d; // CR gets filtered out -static const char CR = CARRIAGE_RETURN; -static const char SINGLE_QUOTE = '\''; -static const char DOUBLE_QUOTE = '\"'; - -// Bunch of unicode info at: -// http://www.unicode.org/faq/utf_bom.html -// ef bb bf (Microsoft "lead bytes") - designates UTF-8 - -static const unsigned char TIXML_UTF_LEAD_0 = 0xefU; -static const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; -static const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; - -namespace Aws -{ -namespace External -{ -namespace tinyxml2 -{ - -struct Entity { - const char* pattern; - int length; - char value; -}; - -static const int NUM_ENTITIES = 5; -static const Entity entities[NUM_ENTITIES] = { - { "quot", 4, DOUBLE_QUOTE }, - { "amp", 3, '&' }, - { "apos", 4, SINGLE_QUOTE }, - { "lt", 2, '<' }, - { "gt", 2, '>' } -}; - - -StrPair::~StrPair() -{ - Reset(); -} - - -void StrPair::TransferTo( StrPair* other ) -{ - if ( this == other ) { - return; - } - // This in effect implements the assignment operator by "moving" - // ownership (as in auto_ptr). - - TIXMLASSERT( other != 0 ); - TIXMLASSERT( other->_flags == 0 ); - TIXMLASSERT( other->_start == 0 ); - TIXMLASSERT( other->_end == 0 ); - - other->Reset(); - - other->_flags = _flags; - other->_start = _start; - other->_end = _end; - - _flags = 0; - _start = 0; - _end = 0; -} - - -void StrPair::Reset() -{ - if ( _flags & NEEDS_DELETE ) { - Aws::DeleteArray(_start); - } - _flags = 0; - _start = 0; - _end = 0; -} - - -void StrPair::SetStr( const char* str, int flags ) -{ - TIXMLASSERT( str ); - Reset(); - size_t len = strlen( str ); - TIXMLASSERT( _start == 0 ); - _start = Aws::NewArray<char>(len+1, ALLOCATION_TAG); - memcpy( _start, str, len+1 ); - _end = _start + len; - _flags = flags | NEEDS_DELETE; -} - - -char* StrPair::ParseText( char* p, const char* endTag, int strFlags, int* curLineNumPtr ) -{ - TIXMLASSERT( p ); - TIXMLASSERT( endTag && *endTag ); - TIXMLASSERT(curLineNumPtr); - - char* start = p; - char endChar = *endTag; - size_t length = strlen( endTag ); - - // Inner loop of text parsing. - while ( *p ) { - if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) { - Set( start, p, strFlags ); - return p + length; - } else if (*p == '\n') { - ++(*curLineNumPtr); - } - ++p; - TIXMLASSERT( p ); - } - return 0; -} - - -char* StrPair::ParseName( char* p ) -{ - if ( !p || !(*p) ) { - return 0; - } - if ( !XMLUtil::IsNameStartChar( *p ) ) { - return 0; - } - - char* const start = p; - ++p; - while ( *p && XMLUtil::IsNameChar( *p ) ) { - ++p; - } - - Set( start, p, 0 ); - return p; -} - - -void StrPair::CollapseWhitespace() -{ - // Adjusting _start would cause undefined behavior on delete[] - TIXMLASSERT( ( _flags & NEEDS_DELETE ) == 0 ); - // Trim leading space. - _start = XMLUtil::SkipWhiteSpace( _start, 0 ); - - if ( *_start ) { - const char* p = _start; // the read pointer - char* q = _start; // the write pointer - - while( *p ) { - if ( XMLUtil::IsWhiteSpace( *p )) { - p = XMLUtil::SkipWhiteSpace( p, 0 ); - if ( *p == 0 ) { - break; // don't write to q; this trims the trailing space. - } - *q = ' '; - ++q; - } - *q = *p; - ++q; - ++p; - } - *q = 0; - } -} - - -const char* StrPair::GetStr() -{ - TIXMLASSERT( _start ); - TIXMLASSERT( _end ); - if ( _flags & NEEDS_FLUSH ) { - *_end = 0; - _flags ^= NEEDS_FLUSH; - - if ( _flags ) { - const char* p = _start; // the read pointer - char* q = _start; // the write pointer - - while( p < _end ) { - if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == CR ) { - // CR-LF pair becomes LF - // CR alone becomes LF - // LF-CR becomes LF - if ( *(p+1) == LF ) { - p += 2; - } - else { - ++p; - } - *q = LF; - ++q; - } - else if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) { - if ( *(p+1) == CR ) { - p += 2; - } - else { - ++p; - } - *q = LF; - ++q; - } - else if ( (_flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) { - // Entities handled by tinyXML2: - // - special entities in the entity table [in/out] - // - numeric character reference [in] - // 中 or 中 - - if ( *(p+1) == '#' ) { - const int buflen = 10; - char buf[buflen] = { 0 }; - int len = 0; - char* adjusted = const_cast<char*>( XMLUtil::GetCharacterRef( p, buf, &len ) ); - if ( adjusted == 0 ) { - *q = *p; - ++p; - ++q; - } - else { - TIXMLASSERT( 0 <= len && len <= buflen ); - TIXMLASSERT( q + len <= adjusted ); - p = adjusted; - memcpy( q, buf, len ); - q += len; - } - } - else { - bool entityFound = false; - for( int i = 0; i < NUM_ENTITIES; ++i ) { - const Entity& entity = entities[i]; - if ( strncmp( p + 1, entity.pattern, entity.length ) == 0 - && *( p + entity.length + 1 ) == ';' ) { - // Found an entity - convert. - *q = entity.value; - ++q; - p += entity.length + 2; - entityFound = true; - break; - } - } - if ( !entityFound ) { - // fixme: treat as error? - ++p; - ++q; - } - } - } - else { - *q = *p; - ++p; - ++q; - } - } - *q = 0; - } - // The loop below has plenty going on, and this - // is a less useful mode. Break it out. - if ( _flags & NEEDS_WHITESPACE_COLLAPSING ) { - CollapseWhitespace(); - } - _flags = (_flags & NEEDS_DELETE); - } - TIXMLASSERT( _start ); - return _start; -} - - - - -// --------- XMLUtil ----------- // - -const char* XMLUtil::writeBoolTrue = "true"; -const char* XMLUtil::writeBoolFalse = "false"; - -void XMLUtil::SetBoolSerialization(const char* writeTrue, const char* writeFalse) -{ - static const char* defTrue = "true"; - static const char* defFalse = "false"; - - writeBoolTrue = (writeTrue) ? writeTrue : defTrue; - writeBoolFalse = (writeFalse) ? writeFalse : defFalse; -} - - -const char* XMLUtil::ReadBOM( const char* p, bool* bom ) -{ - TIXMLASSERT( p ); - TIXMLASSERT( bom ); - *bom = false; - const unsigned char* pu = reinterpret_cast<const unsigned char*>(p); - // Check for BOM: - if ( *(pu+0) == TIXML_UTF_LEAD_0 - && *(pu+1) == TIXML_UTF_LEAD_1 - && *(pu+2) == TIXML_UTF_LEAD_2 ) { - *bom = true; - p += 3; - } - TIXMLASSERT( p ); - return p; -} - - -void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) -{ - const unsigned long BYTE_MASK = 0xBF; - const unsigned long BYTE_MARK = 0x80; - const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - - if (input < 0x80) { - *length = 1; - } - else if ( input < 0x800 ) { - *length = 2; - } - else if ( input < 0x10000 ) { - *length = 3; - } - else if ( input < 0x200000 ) { - *length = 4; - } - else { - *length = 0; // This code won't convert this correctly anyway. - return; - } - - output += *length; - - // Scary scary fall throughs are annotated with carefully designed comments - // to suppress compiler warnings such as -Wimplicit-fallthrough in gcc - switch (*length) { - case 4: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - //fall through - case 3: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - //fall through - case 2: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - //fall through - case 1: - --output; - *output = (char)(input | FIRST_BYTE_MARK[*length]); - break; - default: - TIXMLASSERT( false ); - } -} - - -const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length ) -{ - // Presume an entity, and pull it out. - *length = 0; - - if ( *(p+1) == '#' && *(p+2) ) { - unsigned long ucs = 0; - TIXMLASSERT( sizeof( ucs ) >= 4 ); - ptrdiff_t delta = 0; - unsigned mult = 1; - static const char SEMICOLON = ';'; - - if ( *(p+2) == 'x' ) { - // Hexadecimal. - const char* q = p+3; - if ( !(*q) ) { - return 0; - } - - q = strchr( q, SEMICOLON ); - - if ( !q ) { - return 0; - } - TIXMLASSERT( *q == SEMICOLON ); - - delta = q-p; - --q; - - while ( *q != 'x' ) { - unsigned int digit = 0; - - if ( *q >= '0' && *q <= '9' ) { - digit = *q - '0'; - } - else if ( *q >= 'a' && *q <= 'f' ) { - digit = *q - 'a' + 10; - } - else if ( *q >= 'A' && *q <= 'F' ) { - digit = *q - 'A' + 10; - } - else { - return 0; - } - TIXMLASSERT( digit < 16 ); - TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit ); - const unsigned int digitScaled = mult * digit; - TIXMLASSERT( ucs <= ULONG_MAX - digitScaled ); - ucs += digitScaled; - TIXMLASSERT( mult <= UINT_MAX / 16 ); - mult *= 16; - --q; - } - } - else { - // Decimal. - const char* q = p+2; - if ( !(*q) ) { - return 0; - } - - q = strchr( q, SEMICOLON ); - - if ( !q ) { - return 0; - } - TIXMLASSERT( *q == SEMICOLON ); - - delta = q-p; - --q; - - while ( *q != '#' ) { - if ( *q >= '0' && *q <= '9' ) { - const unsigned int digit = *q - '0'; - TIXMLASSERT( digit < 10 ); - TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit ); - const unsigned int digitScaled = mult * digit; - TIXMLASSERT( ucs <= ULONG_MAX - digitScaled ); - ucs += digitScaled; - } - else { - return 0; - } - TIXMLASSERT( mult <= UINT_MAX / 10 ); - mult *= 10; - --q; - } - } - // convert the UCS to UTF-8 - ConvertUTF32ToUTF8( ucs, value, length ); - return p + delta + 1; - } - return p+1; -} - - -void XMLUtil::ToStr( int v, char* buffer, int bufferSize ) -{ - TIXML_SNPRINTF( buffer, bufferSize, "%d", v ); -} - - -void XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize ) -{ - TIXML_SNPRINTF( buffer, bufferSize, "%u", v ); -} - - -void XMLUtil::ToStr( bool v, char* buffer, int bufferSize ) -{ - TIXML_SNPRINTF( buffer, bufferSize, "%s", v ? writeBoolTrue : writeBoolFalse); -} - -/* - ToStr() of a number is a very tricky topic. - https://github.com/leethomason/tinyxml2/issues/106 -*/ -void XMLUtil::ToStr( float v, char* buffer, int bufferSize ) -{ - TIXML_SNPRINTF( buffer, bufferSize, "%.8g", v ); -} - - -void XMLUtil::ToStr( double v, char* buffer, int bufferSize ) -{ - TIXML_SNPRINTF( buffer, bufferSize, "%.17g", v ); -} - - -void XMLUtil::ToStr(int64_t v, char* buffer, int bufferSize) -{ - // horrible syntax trick to make the compiler happy about %lld - TIXML_SNPRINTF(buffer, bufferSize, "%lld", (long long)v); -} - - -bool XMLUtil::ToInt( const char* str, int* value ) -{ - if ( TIXML_SSCANF( str, "%d", value ) == 1 ) { - return true; - } - return false; -} - -bool XMLUtil::ToUnsigned( const char* str, unsigned *value ) -{ - if ( TIXML_SSCANF( str, "%u", value ) == 1 ) { - return true; - } - return false; -} - -bool XMLUtil::ToBool( const char* str, bool* value ) -{ - int ival = 0; - if ( ToInt( str, &ival )) { - *value = (ival==0) ? false : true; - return true; - } - if ( StringEqual( str, "true" ) ) { - *value = true; - return true; - } - else if ( StringEqual( str, "false" ) ) { - *value = false; - return true; - } - return false; -} - - -bool XMLUtil::ToFloat( const char* str, float* value ) -{ - if ( TIXML_SSCANF( str, "%f", value ) == 1 ) { - return true; - } - return false; -} - - -bool XMLUtil::ToDouble( const char* str, double* value ) -{ - if ( TIXML_SSCANF( str, "%lf", value ) == 1 ) { - return true; - } - return false; -} - - -bool XMLUtil::ToInt64(const char* str, int64_t* value) -{ - long long v = 0; // horrible syntax trick to make the compiler happy about %lld - if (TIXML_SSCANF(str, "%lld", &v) == 1) { - *value = (int64_t)v; - return true; - } - return false; -} - - -char* XMLDocument::Identify( char* p, XMLNode** node ) -{ - TIXMLASSERT( node ); - TIXMLASSERT( p ); - char* const start = p; - int const startLine = _parseCurLineNum; - p = XMLUtil::SkipWhiteSpace( p, &_parseCurLineNum ); - if( !*p ) { - *node = 0; - TIXMLASSERT( p ); - return p; - } - - // These strings define the matching patterns: - static const char* xmlHeader = { "<?" }; - static const char* commentHeader = { "<!--" }; - static const char* cdataHeader = { "<![CDATA[" }; - static const char* dtdHeader = { "<!" }; - static const char* elementHeader = { "<" }; // and a header for everything else; check last. - - static const int xmlHeaderLen = 2; - static const int commentHeaderLen = 4; - static const int cdataHeaderLen = 9; - static const int dtdHeaderLen = 2; - static const int elementHeaderLen = 1; - - TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLUnknown ) ); // use same memory pool - TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLDeclaration ) ); // use same memory pool - XMLNode* returnNode = 0; - if ( XMLUtil::StringEqual( p, xmlHeader, xmlHeaderLen ) ) { - returnNode = CreateUnlinkedNode<XMLDeclaration>( _commentPool ); - returnNode->_parseLineNum = _parseCurLineNum; - p += xmlHeaderLen; - } - else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) { - returnNode = CreateUnlinkedNode<XMLComment>( _commentPool ); - returnNode->_parseLineNum = _parseCurLineNum; - p += commentHeaderLen; - } - else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) { - XMLText* text = CreateUnlinkedNode<XMLText>( _textPool ); - returnNode = text; - returnNode->_parseLineNum = _parseCurLineNum; - p += cdataHeaderLen; - text->SetCData( true ); - } - else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) { - returnNode = CreateUnlinkedNode<XMLUnknown>( _commentPool ); - returnNode->_parseLineNum = _parseCurLineNum; - p += dtdHeaderLen; - } - else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) { - returnNode = CreateUnlinkedNode<XMLElement>( _elementPool ); - returnNode->_parseLineNum = _parseCurLineNum; - p += elementHeaderLen; - } - else { - returnNode = CreateUnlinkedNode<XMLText>( _textPool ); - returnNode->_parseLineNum = _parseCurLineNum; // Report line of first non-whitespace character - p = start; // Back it up, all the text counts. - _parseCurLineNum = startLine; - } - - TIXMLASSERT( returnNode ); - TIXMLASSERT( p ); - *node = returnNode; - return p; -} - - -bool XMLDocument::Accept( XMLVisitor* visitor ) const -{ - TIXMLASSERT( visitor ); - if ( visitor->VisitEnter( *this ) ) { - for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) { - if ( !node->Accept( visitor ) ) { - break; - } - } - } - return visitor->VisitExit( *this ); -} - - -// --------- XMLNode ----------- // - -XMLNode::XMLNode( XMLDocument* doc ) : - _document( doc ), - _parent( 0 ), - _value(), - _parseLineNum( 0 ), - _firstChild( 0 ), _lastChild( 0 ), - _prev( 0 ), _next( 0 ), - _userData( 0 ), - _memPool( 0 ) -{ -} - - -XMLNode::~XMLNode() -{ - DeleteChildren(); - if ( _parent ) { - _parent->Unlink( this ); - } -} - +/* +Original code by Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +/* +This file has been modified from its original version by Amazon: + (1) Memory management operations use aws memory management api + (2) #includes all use <> +*/ + +#include <aws/core/external/tinyxml2/tinyxml2.h> + +#include <new> // yes, this one new style header, is in the Android SDK. +#if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__) +# include <stddef.h> +# include <stdarg.h> +#else +# include <cstddef> +# include <cstdarg> +#endif + +#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE) + // Microsoft Visual Studio, version 2005 and higher. Not WinCE. + /*int _snprintf_s( + char *buffer, + size_t sizeOfBuffer, + size_t count, + const char *format [, + argument] ... + );*/ + static inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... ) + { + va_list va; + va_start( va, format ); + int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va ); + va_end( va ); + return result; + } + + static inline int TIXML_VSNPRINTF( char* buffer, size_t size, const char* format, va_list va ) + { + int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va ); + return result; + } + + #define TIXML_VSCPRINTF _vscprintf + #define TIXML_SSCANF sscanf_s +#elif defined _MSC_VER + // Microsoft Visual Studio 2003 and earlier or WinCE + #define TIXML_SNPRINTF _snprintf + #define TIXML_VSNPRINTF _vsnprintf + #define TIXML_SSCANF sscanf + #if (_MSC_VER < 1400 ) && (!defined WINCE) + // Microsoft Visual Studio 2003 and not WinCE. + #define TIXML_VSCPRINTF _vscprintf // VS2003's C runtime has this, but VC6 C runtime or WinCE SDK doesn't have. + #else + // Microsoft Visual Studio 2003 and earlier or WinCE. + static inline int TIXML_VSCPRINTF( const char* format, va_list va ) + { + int len = 512; + for (;;) { + len = len*2; + char* str = Aws::NewArray<char>(len, ALLOCATION_TAG); + const int required = _vsnprintf(str, len, format, va); + Aws::DeleteArray(str); + if ( required != -1 ) { + TIXMLASSERT( required >= 0 ); + len = required; + break; + } + } + TIXMLASSERT( len >= 0 ); + return len; + } + #endif +#else + // GCC version 3 and higher + //#warning( "Using sn* functions." ) + #define TIXML_SNPRINTF snprintf + #define TIXML_VSNPRINTF vsnprintf + static inline int TIXML_VSCPRINTF( const char* format, va_list va ) + { + int len = vsnprintf( 0, 0, format, va ); + TIXMLASSERT( len >= 0 ); + return len; + } + #define TIXML_SSCANF sscanf +#endif + + +static const char LINE_FEED = (char)0x0a; // all line endings are normalized to LF +static const char LF = LINE_FEED; +static const char CARRIAGE_RETURN = (char)0x0d; // CR gets filtered out +static const char CR = CARRIAGE_RETURN; +static const char SINGLE_QUOTE = '\''; +static const char DOUBLE_QUOTE = '\"'; + +// Bunch of unicode info at: +// http://www.unicode.org/faq/utf_bom.html +// ef bb bf (Microsoft "lead bytes") - designates UTF-8 + +static const unsigned char TIXML_UTF_LEAD_0 = 0xefU; +static const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; +static const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; + +namespace Aws +{ +namespace External +{ +namespace tinyxml2 +{ + +struct Entity { + const char* pattern; + int length; + char value; +}; + +static const int NUM_ENTITIES = 5; +static const Entity entities[NUM_ENTITIES] = { + { "quot", 4, DOUBLE_QUOTE }, + { "amp", 3, '&' }, + { "apos", 4, SINGLE_QUOTE }, + { "lt", 2, '<' }, + { "gt", 2, '>' } +}; + + +StrPair::~StrPair() +{ + Reset(); +} + + +void StrPair::TransferTo( StrPair* other ) +{ + if ( this == other ) { + return; + } + // This in effect implements the assignment operator by "moving" + // ownership (as in auto_ptr). + + TIXMLASSERT( other != 0 ); + TIXMLASSERT( other->_flags == 0 ); + TIXMLASSERT( other->_start == 0 ); + TIXMLASSERT( other->_end == 0 ); + + other->Reset(); + + other->_flags = _flags; + other->_start = _start; + other->_end = _end; + + _flags = 0; + _start = 0; + _end = 0; +} + + +void StrPair::Reset() +{ + if ( _flags & NEEDS_DELETE ) { + Aws::DeleteArray(_start); + } + _flags = 0; + _start = 0; + _end = 0; +} + + +void StrPair::SetStr( const char* str, int flags ) +{ + TIXMLASSERT( str ); + Reset(); + size_t len = strlen( str ); + TIXMLASSERT( _start == 0 ); + _start = Aws::NewArray<char>(len+1, ALLOCATION_TAG); + memcpy( _start, str, len+1 ); + _end = _start + len; + _flags = flags | NEEDS_DELETE; +} + + +char* StrPair::ParseText( char* p, const char* endTag, int strFlags, int* curLineNumPtr ) +{ + TIXMLASSERT( p ); + TIXMLASSERT( endTag && *endTag ); + TIXMLASSERT(curLineNumPtr); + + char* start = p; + char endChar = *endTag; + size_t length = strlen( endTag ); + + // Inner loop of text parsing. + while ( *p ) { + if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) { + Set( start, p, strFlags ); + return p + length; + } else if (*p == '\n') { + ++(*curLineNumPtr); + } + ++p; + TIXMLASSERT( p ); + } + return 0; +} + + +char* StrPair::ParseName( char* p ) +{ + if ( !p || !(*p) ) { + return 0; + } + if ( !XMLUtil::IsNameStartChar( *p ) ) { + return 0; + } + + char* const start = p; + ++p; + while ( *p && XMLUtil::IsNameChar( *p ) ) { + ++p; + } + + Set( start, p, 0 ); + return p; +} + + +void StrPair::CollapseWhitespace() +{ + // Adjusting _start would cause undefined behavior on delete[] + TIXMLASSERT( ( _flags & NEEDS_DELETE ) == 0 ); + // Trim leading space. + _start = XMLUtil::SkipWhiteSpace( _start, 0 ); + + if ( *_start ) { + const char* p = _start; // the read pointer + char* q = _start; // the write pointer + + while( *p ) { + if ( XMLUtil::IsWhiteSpace( *p )) { + p = XMLUtil::SkipWhiteSpace( p, 0 ); + if ( *p == 0 ) { + break; // don't write to q; this trims the trailing space. + } + *q = ' '; + ++q; + } + *q = *p; + ++q; + ++p; + } + *q = 0; + } +} + + +const char* StrPair::GetStr() +{ + TIXMLASSERT( _start ); + TIXMLASSERT( _end ); + if ( _flags & NEEDS_FLUSH ) { + *_end = 0; + _flags ^= NEEDS_FLUSH; + + if ( _flags ) { + const char* p = _start; // the read pointer + char* q = _start; // the write pointer + + while( p < _end ) { + if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == CR ) { + // CR-LF pair becomes LF + // CR alone becomes LF + // LF-CR becomes LF + if ( *(p+1) == LF ) { + p += 2; + } + else { + ++p; + } + *q = LF; + ++q; + } + else if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) { + if ( *(p+1) == CR ) { + p += 2; + } + else { + ++p; + } + *q = LF; + ++q; + } + else if ( (_flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) { + // Entities handled by tinyXML2: + // - special entities in the entity table [in/out] + // - numeric character reference [in] + // 中 or 中 + + if ( *(p+1) == '#' ) { + const int buflen = 10; + char buf[buflen] = { 0 }; + int len = 0; + char* adjusted = const_cast<char*>( XMLUtil::GetCharacterRef( p, buf, &len ) ); + if ( adjusted == 0 ) { + *q = *p; + ++p; + ++q; + } + else { + TIXMLASSERT( 0 <= len && len <= buflen ); + TIXMLASSERT( q + len <= adjusted ); + p = adjusted; + memcpy( q, buf, len ); + q += len; + } + } + else { + bool entityFound = false; + for( int i = 0; i < NUM_ENTITIES; ++i ) { + const Entity& entity = entities[i]; + if ( strncmp( p + 1, entity.pattern, entity.length ) == 0 + && *( p + entity.length + 1 ) == ';' ) { + // Found an entity - convert. + *q = entity.value; + ++q; + p += entity.length + 2; + entityFound = true; + break; + } + } + if ( !entityFound ) { + // fixme: treat as error? + ++p; + ++q; + } + } + } + else { + *q = *p; + ++p; + ++q; + } + } + *q = 0; + } + // The loop below has plenty going on, and this + // is a less useful mode. Break it out. + if ( _flags & NEEDS_WHITESPACE_COLLAPSING ) { + CollapseWhitespace(); + } + _flags = (_flags & NEEDS_DELETE); + } + TIXMLASSERT( _start ); + return _start; +} + + + + +// --------- XMLUtil ----------- // + +const char* XMLUtil::writeBoolTrue = "true"; +const char* XMLUtil::writeBoolFalse = "false"; + +void XMLUtil::SetBoolSerialization(const char* writeTrue, const char* writeFalse) +{ + static const char* defTrue = "true"; + static const char* defFalse = "false"; + + writeBoolTrue = (writeTrue) ? writeTrue : defTrue; + writeBoolFalse = (writeFalse) ? writeFalse : defFalse; +} + + +const char* XMLUtil::ReadBOM( const char* p, bool* bom ) +{ + TIXMLASSERT( p ); + TIXMLASSERT( bom ); + *bom = false; + const unsigned char* pu = reinterpret_cast<const unsigned char*>(p); + // Check for BOM: + if ( *(pu+0) == TIXML_UTF_LEAD_0 + && *(pu+1) == TIXML_UTF_LEAD_1 + && *(pu+2) == TIXML_UTF_LEAD_2 ) { + *bom = true; + p += 3; + } + TIXMLASSERT( p ); + return p; +} + + +void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) +{ + const unsigned long BYTE_MASK = 0xBF; + const unsigned long BYTE_MARK = 0x80; + const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + + if (input < 0x80) { + *length = 1; + } + else if ( input < 0x800 ) { + *length = 2; + } + else if ( input < 0x10000 ) { + *length = 3; + } + else if ( input < 0x200000 ) { + *length = 4; + } + else { + *length = 0; // This code won't convert this correctly anyway. + return; + } + + output += *length; + + // Scary scary fall throughs are annotated with carefully designed comments + // to suppress compiler warnings such as -Wimplicit-fallthrough in gcc + switch (*length) { + case 4: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + //fall through + case 3: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + //fall through + case 2: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + //fall through + case 1: + --output; + *output = (char)(input | FIRST_BYTE_MARK[*length]); + break; + default: + TIXMLASSERT( false ); + } +} + + +const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length ) +{ + // Presume an entity, and pull it out. + *length = 0; + + if ( *(p+1) == '#' && *(p+2) ) { + unsigned long ucs = 0; + TIXMLASSERT( sizeof( ucs ) >= 4 ); + ptrdiff_t delta = 0; + unsigned mult = 1; + static const char SEMICOLON = ';'; + + if ( *(p+2) == 'x' ) { + // Hexadecimal. + const char* q = p+3; + if ( !(*q) ) { + return 0; + } + + q = strchr( q, SEMICOLON ); + + if ( !q ) { + return 0; + } + TIXMLASSERT( *q == SEMICOLON ); + + delta = q-p; + --q; + + while ( *q != 'x' ) { + unsigned int digit = 0; + + if ( *q >= '0' && *q <= '9' ) { + digit = *q - '0'; + } + else if ( *q >= 'a' && *q <= 'f' ) { + digit = *q - 'a' + 10; + } + else if ( *q >= 'A' && *q <= 'F' ) { + digit = *q - 'A' + 10; + } + else { + return 0; + } + TIXMLASSERT( digit < 16 ); + TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit ); + const unsigned int digitScaled = mult * digit; + TIXMLASSERT( ucs <= ULONG_MAX - digitScaled ); + ucs += digitScaled; + TIXMLASSERT( mult <= UINT_MAX / 16 ); + mult *= 16; + --q; + } + } + else { + // Decimal. + const char* q = p+2; + if ( !(*q) ) { + return 0; + } + + q = strchr( q, SEMICOLON ); + + if ( !q ) { + return 0; + } + TIXMLASSERT( *q == SEMICOLON ); + + delta = q-p; + --q; + + while ( *q != '#' ) { + if ( *q >= '0' && *q <= '9' ) { + const unsigned int digit = *q - '0'; + TIXMLASSERT( digit < 10 ); + TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit ); + const unsigned int digitScaled = mult * digit; + TIXMLASSERT( ucs <= ULONG_MAX - digitScaled ); + ucs += digitScaled; + } + else { + return 0; + } + TIXMLASSERT( mult <= UINT_MAX / 10 ); + mult *= 10; + --q; + } + } + // convert the UCS to UTF-8 + ConvertUTF32ToUTF8( ucs, value, length ); + return p + delta + 1; + } + return p+1; +} + + +void XMLUtil::ToStr( int v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%d", v ); +} + + +void XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%u", v ); +} + + +void XMLUtil::ToStr( bool v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%s", v ? writeBoolTrue : writeBoolFalse); +} + +/* + ToStr() of a number is a very tricky topic. + https://github.com/leethomason/tinyxml2/issues/106 +*/ +void XMLUtil::ToStr( float v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%.8g", v ); +} + + +void XMLUtil::ToStr( double v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%.17g", v ); +} + + +void XMLUtil::ToStr(int64_t v, char* buffer, int bufferSize) +{ + // horrible syntax trick to make the compiler happy about %lld + TIXML_SNPRINTF(buffer, bufferSize, "%lld", (long long)v); +} + + +bool XMLUtil::ToInt( const char* str, int* value ) +{ + if ( TIXML_SSCANF( str, "%d", value ) == 1 ) { + return true; + } + return false; +} + +bool XMLUtil::ToUnsigned( const char* str, unsigned *value ) +{ + if ( TIXML_SSCANF( str, "%u", value ) == 1 ) { + return true; + } + return false; +} + +bool XMLUtil::ToBool( const char* str, bool* value ) +{ + int ival = 0; + if ( ToInt( str, &ival )) { + *value = (ival==0) ? false : true; + return true; + } + if ( StringEqual( str, "true" ) ) { + *value = true; + return true; + } + else if ( StringEqual( str, "false" ) ) { + *value = false; + return true; + } + return false; +} + + +bool XMLUtil::ToFloat( const char* str, float* value ) +{ + if ( TIXML_SSCANF( str, "%f", value ) == 1 ) { + return true; + } + return false; +} + + +bool XMLUtil::ToDouble( const char* str, double* value ) +{ + if ( TIXML_SSCANF( str, "%lf", value ) == 1 ) { + return true; + } + return false; +} + + +bool XMLUtil::ToInt64(const char* str, int64_t* value) +{ + long long v = 0; // horrible syntax trick to make the compiler happy about %lld + if (TIXML_SSCANF(str, "%lld", &v) == 1) { + *value = (int64_t)v; + return true; + } + return false; +} + + +char* XMLDocument::Identify( char* p, XMLNode** node ) +{ + TIXMLASSERT( node ); + TIXMLASSERT( p ); + char* const start = p; + int const startLine = _parseCurLineNum; + p = XMLUtil::SkipWhiteSpace( p, &_parseCurLineNum ); + if( !*p ) { + *node = 0; + TIXMLASSERT( p ); + return p; + } + + // These strings define the matching patterns: + static const char* xmlHeader = { "<?" }; + static const char* commentHeader = { "<!--" }; + static const char* cdataHeader = { "<![CDATA[" }; + static const char* dtdHeader = { "<!" }; + static const char* elementHeader = { "<" }; // and a header for everything else; check last. + + static const int xmlHeaderLen = 2; + static const int commentHeaderLen = 4; + static const int cdataHeaderLen = 9; + static const int dtdHeaderLen = 2; + static const int elementHeaderLen = 1; + + TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLUnknown ) ); // use same memory pool + TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLDeclaration ) ); // use same memory pool + XMLNode* returnNode = 0; + if ( XMLUtil::StringEqual( p, xmlHeader, xmlHeaderLen ) ) { + returnNode = CreateUnlinkedNode<XMLDeclaration>( _commentPool ); + returnNode->_parseLineNum = _parseCurLineNum; + p += xmlHeaderLen; + } + else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) { + returnNode = CreateUnlinkedNode<XMLComment>( _commentPool ); + returnNode->_parseLineNum = _parseCurLineNum; + p += commentHeaderLen; + } + else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) { + XMLText* text = CreateUnlinkedNode<XMLText>( _textPool ); + returnNode = text; + returnNode->_parseLineNum = _parseCurLineNum; + p += cdataHeaderLen; + text->SetCData( true ); + } + else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) { + returnNode = CreateUnlinkedNode<XMLUnknown>( _commentPool ); + returnNode->_parseLineNum = _parseCurLineNum; + p += dtdHeaderLen; + } + else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) { + returnNode = CreateUnlinkedNode<XMLElement>( _elementPool ); + returnNode->_parseLineNum = _parseCurLineNum; + p += elementHeaderLen; + } + else { + returnNode = CreateUnlinkedNode<XMLText>( _textPool ); + returnNode->_parseLineNum = _parseCurLineNum; // Report line of first non-whitespace character + p = start; // Back it up, all the text counts. + _parseCurLineNum = startLine; + } + + TIXMLASSERT( returnNode ); + TIXMLASSERT( p ); + *node = returnNode; + return p; +} + + +bool XMLDocument::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + if ( visitor->VisitEnter( *this ) ) { + for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) { + if ( !node->Accept( visitor ) ) { + break; + } + } + } + return visitor->VisitExit( *this ); +} + + +// --------- XMLNode ----------- // + +XMLNode::XMLNode( XMLDocument* doc ) : + _document( doc ), + _parent( 0 ), + _value(), + _parseLineNum( 0 ), + _firstChild( 0 ), _lastChild( 0 ), + _prev( 0 ), _next( 0 ), + _userData( 0 ), + _memPool( 0 ) +{ +} + + +XMLNode::~XMLNode() +{ + DeleteChildren(); + if ( _parent ) { + _parent->Unlink( this ); + } +} + const char* XMLNode::Value() const -{ - // Edge case: XMLDocuments don't have a Value. Return null. - if ( this->ToDocument() ) - return 0; - return _value.GetStr(); -} - -void XMLNode::SetValue( const char* str, bool staticMem ) -{ - if ( staticMem ) { - _value.SetInternedStr( str ); - } - else { - _value.SetStr( str ); - } -} - -XMLNode* XMLNode::DeepClone(XMLDocument* target) const -{ - XMLNode* clone = this->ShallowClone(target); - if (!clone) return 0; - - for (const XMLNode* child = this->FirstChild(); child; child = child->NextSibling()) { - XMLNode* childClone = child->DeepClone(target); - TIXMLASSERT(childClone); - clone->InsertEndChild(childClone); - } - return clone; -} - -void XMLNode::DeleteChildren() -{ - while( _firstChild ) { - TIXMLASSERT( _lastChild ); - DeleteChild( _firstChild ); - } - _firstChild = _lastChild = 0; -} - - -void XMLNode::Unlink( XMLNode* child ) -{ - TIXMLASSERT( child ); - TIXMLASSERT( child->_document == _document ); - TIXMLASSERT( child->_parent == this ); - if ( child == _firstChild ) { - _firstChild = _firstChild->_next; - } - if ( child == _lastChild ) { - _lastChild = _lastChild->_prev; - } - - if ( child->_prev ) { - child->_prev->_next = child->_next; - } - if ( child->_next ) { - child->_next->_prev = child->_prev; - } - child->_next = 0; - child->_prev = 0; - child->_parent = 0; -} - - -void XMLNode::DeleteChild( XMLNode* node ) -{ - TIXMLASSERT( node ); - TIXMLASSERT( node->_document == _document ); - TIXMLASSERT( node->_parent == this ); - Unlink( node ); - TIXMLASSERT(node->_prev == 0); - TIXMLASSERT(node->_next == 0); - TIXMLASSERT(node->_parent == 0); - DeleteNode( node ); -} - - -XMLNode* XMLNode::InsertEndChild( XMLNode* addThis ) -{ - TIXMLASSERT( addThis ); - if ( addThis->_document != _document ) { - TIXMLASSERT( false ); - return 0; - } - InsertChildPreamble( addThis ); - - if ( _lastChild ) { - TIXMLASSERT( _firstChild ); - TIXMLASSERT( _lastChild->_next == 0 ); - _lastChild->_next = addThis; - addThis->_prev = _lastChild; - _lastChild = addThis; - - addThis->_next = 0; - } - else { - TIXMLASSERT( _firstChild == 0 ); - _firstChild = _lastChild = addThis; - - addThis->_prev = 0; - addThis->_next = 0; - } - addThis->_parent = this; - return addThis; -} - - -XMLNode* XMLNode::InsertFirstChild( XMLNode* addThis ) -{ - TIXMLASSERT( addThis ); - if ( addThis->_document != _document ) { - TIXMLASSERT( false ); - return 0; - } - InsertChildPreamble( addThis ); - - if ( _firstChild ) { - TIXMLASSERT( _lastChild ); - TIXMLASSERT( _firstChild->_prev == 0 ); - - _firstChild->_prev = addThis; - addThis->_next = _firstChild; - _firstChild = addThis; - - addThis->_prev = 0; - } - else { - TIXMLASSERT( _lastChild == 0 ); - _firstChild = _lastChild = addThis; - - addThis->_prev = 0; - addThis->_next = 0; - } - addThis->_parent = this; - return addThis; -} - - -XMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis ) -{ - TIXMLASSERT( addThis ); - if ( addThis->_document != _document ) { - TIXMLASSERT( false ); - return 0; - } - - TIXMLASSERT( afterThis ); - - if ( afterThis->_parent != this ) { - TIXMLASSERT( false ); - return 0; - } - if ( afterThis == addThis ) { - // Current state: BeforeThis -> AddThis -> OneAfterAddThis - // Now AddThis must disappear from it's location and then - // reappear between BeforeThis and OneAfterAddThis. - // So just leave it where it is. - return addThis; - } - - if ( afterThis->_next == 0 ) { - // The last node or the only node. - return InsertEndChild( addThis ); - } - InsertChildPreamble( addThis ); - addThis->_prev = afterThis; - addThis->_next = afterThis->_next; - afterThis->_next->_prev = addThis; - afterThis->_next = addThis; - addThis->_parent = this; - return addThis; -} - - - - -const XMLElement* XMLNode::FirstChildElement( const char* name ) const -{ - for( const XMLNode* node = _firstChild; node; node = node->_next ) { - const XMLElement* element = node->ToElementWithName( name ); - if ( element ) { - return element; - } - } - return 0; -} - - -const XMLElement* XMLNode::LastChildElement( const char* name ) const -{ - for( const XMLNode* node = _lastChild; node; node = node->_prev ) { - const XMLElement* element = node->ToElementWithName( name ); - if ( element ) { - return element; - } - } - return 0; -} - - -const XMLElement* XMLNode::NextSiblingElement( const char* name ) const -{ - for( const XMLNode* node = _next; node; node = node->_next ) { - const XMLElement* element = node->ToElementWithName( name ); - if ( element ) { - return element; - } - } - return 0; -} - - -const XMLElement* XMLNode::PreviousSiblingElement( const char* name ) const -{ - for( const XMLNode* node = _prev; node; node = node->_prev ) { - const XMLElement* element = node->ToElementWithName( name ); - if ( element ) { - return element; - } - } - return 0; -} - - -char* XMLNode::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) -{ - // This is a recursive method, but thinking about it "at the current level" - // it is a pretty simple flat list: - // <foo/> - // <!-- comment --> - // - // With a special case: - // <foo> - // </foo> - // <!-- comment --> - // - // Where the closing element (/foo) *must* be the next thing after the opening - // element, and the names must match. BUT the tricky bit is that the closing - // element will be read by the child. - // - // 'endTag' is the end tag for this node, it is returned by a call to a child. - // 'parentEnd' is the end tag for the parent, which is filled in and returned. - - while( p && *p ) { - XMLNode* node = 0; - - p = _document->Identify( p, &node ); - TIXMLASSERT( p ); - if ( node == 0 ) { - break; - } - - int initialLineNum = node->_parseLineNum; - - StrPair endTag; - p = node->ParseDeep( p, &endTag, curLineNumPtr ); - if ( !p ) { - DeleteNode( node ); - if ( !_document->Error() ) { - _document->SetError( XML_ERROR_PARSING, initialLineNum, 0); - } - break; - } - - XMLDeclaration* decl = node->ToDeclaration(); - if ( decl ) { - // Declarations are only allowed at document level - bool wellLocated = ( ToDocument() != 0 ); - if ( wellLocated ) { - // Multiple declarations are allowed but all declarations - // must occur before anything else - for ( const XMLNode* existingNode = _document->FirstChild(); existingNode; existingNode = existingNode->NextSibling() ) { - if ( !existingNode->ToDeclaration() ) { - wellLocated = false; - break; - } - } - } - if ( !wellLocated ) { - _document->SetError( XML_ERROR_PARSING_DECLARATION, initialLineNum, "XMLDeclaration value=%s", decl->Value()); - DeleteNode( node ); - break; - } - } - - XMLElement* ele = node->ToElement(); - if ( ele ) { - // We read the end tag. Return it to the parent. - if ( ele->ClosingType() == XMLElement::CLOSING ) { - if ( parentEndTag ) { - ele->_value.TransferTo( parentEndTag ); - } - node->_memPool->SetTracked(); // created and then immediately deleted. - DeleteNode( node ); - return p; - } - - // Handle an end tag returned to this level. - // And handle a bunch of annoying errors. - bool mismatch = false; - if ( endTag.Empty() ) { - if ( ele->ClosingType() == XMLElement::OPEN ) { - mismatch = true; - } - } - else { - if ( ele->ClosingType() != XMLElement::OPEN ) { - mismatch = true; - } - else if ( !XMLUtil::StringEqual( endTag.GetStr(), ele->Name() ) ) { - mismatch = true; - } - } - if ( mismatch ) { - _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, initialLineNum, "XMLElement name=%s", ele->Name()); - DeleteNode( node ); - break; - } - } - InsertEndChild( node ); - } - return 0; -} - -/*static*/ void XMLNode::DeleteNode( XMLNode* node ) -{ - if ( node == 0 ) { - return; - } - TIXMLASSERT(node->_document); - if (!node->ToDocument()) { - node->_document->MarkInUse(node); - } - - MemPool* pool = node->_memPool; - node->~XMLNode(); - pool->Free( node ); -} - -void XMLNode::InsertChildPreamble( XMLNode* insertThis ) const -{ - TIXMLASSERT( insertThis ); - TIXMLASSERT( insertThis->_document == _document ); - - if (insertThis->_parent) { - insertThis->_parent->Unlink( insertThis ); - } - else { - insertThis->_document->MarkInUse(insertThis); - insertThis->_memPool->SetTracked(); - } -} - -const XMLElement* XMLNode::ToElementWithName( const char* name ) const -{ - const XMLElement* element = this->ToElement(); - if ( element == 0 ) { - return 0; - } - if ( name == 0 ) { - return element; - } - if ( XMLUtil::StringEqual( element->Name(), name ) ) { - return element; - } - return 0; -} - -// --------- XMLText ---------- // -char* XMLText::ParseDeep( char* p, StrPair*, int* curLineNumPtr ) -{ - if ( this->CData() ) { - p = _value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr ); - if ( !p ) { - _document->SetError( XML_ERROR_PARSING_CDATA, _parseLineNum, 0 ); - } - return p; - } - else { - int flags = _document->ProcessEntities() ? StrPair::TEXT_ELEMENT : StrPair::TEXT_ELEMENT_LEAVE_ENTITIES; - if ( _document->WhitespaceMode() == COLLAPSE_WHITESPACE ) { - flags |= StrPair::NEEDS_WHITESPACE_COLLAPSING; - } - - p = _value.ParseText( p, "<", flags, curLineNumPtr ); - if ( p && *p ) { - return p-1; - } - if ( !p ) { - _document->SetError( XML_ERROR_PARSING_TEXT, _parseLineNum, 0 ); - } - } - return 0; -} - - -XMLNode* XMLText::ShallowClone( XMLDocument* doc ) const -{ - if ( !doc ) { - doc = _document; - } - XMLText* text = doc->NewText( Value() ); // fixme: this will always allocate memory. Intern? - text->SetCData( this->CData() ); - return text; -} - - -bool XMLText::ShallowEqual( const XMLNode* compare ) const -{ - TIXMLASSERT( compare ); - const XMLText* text = compare->ToText(); - return ( text && XMLUtil::StringEqual( text->Value(), Value() ) ); -} - - -bool XMLText::Accept( XMLVisitor* visitor ) const -{ - TIXMLASSERT( visitor ); - return visitor->Visit( *this ); -} - - -// --------- XMLComment ---------- // - -XMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc ) -{ -} - - -XMLComment::~XMLComment() -{ -} - - -char* XMLComment::ParseDeep( char* p, StrPair*, int* curLineNumPtr ) -{ - // Comment parses as text. - p = _value.ParseText( p, "-->", StrPair::COMMENT, curLineNumPtr ); - if ( p == 0 ) { - _document->SetError( XML_ERROR_PARSING_COMMENT, _parseLineNum, 0 ); - } - return p; -} - - -XMLNode* XMLComment::ShallowClone( XMLDocument* doc ) const -{ - if ( !doc ) { - doc = _document; - } - XMLComment* comment = doc->NewComment( Value() ); // fixme: this will always allocate memory. Intern? - return comment; -} - - -bool XMLComment::ShallowEqual( const XMLNode* compare ) const -{ - TIXMLASSERT( compare ); - const XMLComment* comment = compare->ToComment(); - return ( comment && XMLUtil::StringEqual( comment->Value(), Value() )); -} - - -bool XMLComment::Accept( XMLVisitor* visitor ) const -{ - TIXMLASSERT( visitor ); - return visitor->Visit( *this ); -} - - -// --------- XMLDeclaration ---------- // - -XMLDeclaration::XMLDeclaration( XMLDocument* doc ) : XMLNode( doc ) -{ -} - - -XMLDeclaration::~XMLDeclaration() -{ - //printf( "~XMLDeclaration\n" ); -} - - -char* XMLDeclaration::ParseDeep( char* p, StrPair*, int* curLineNumPtr ) -{ - // Declaration parses as text. - p = _value.ParseText( p, "?>", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr ); - if ( p == 0 ) { - _document->SetError( XML_ERROR_PARSING_DECLARATION, _parseLineNum, 0 ); - } - return p; -} - - -XMLNode* XMLDeclaration::ShallowClone( XMLDocument* doc ) const -{ - if ( !doc ) { - doc = _document; - } - XMLDeclaration* dec = doc->NewDeclaration( Value() ); // fixme: this will always allocate memory. Intern? - return dec; -} - - -bool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const -{ - TIXMLASSERT( compare ); - const XMLDeclaration* declaration = compare->ToDeclaration(); - return ( declaration && XMLUtil::StringEqual( declaration->Value(), Value() )); -} - - - -bool XMLDeclaration::Accept( XMLVisitor* visitor ) const -{ - TIXMLASSERT( visitor ); - return visitor->Visit( *this ); -} - -// --------- XMLUnknown ---------- // - -XMLUnknown::XMLUnknown( XMLDocument* doc ) : XMLNode( doc ) -{ -} - - -XMLUnknown::~XMLUnknown() -{ -} - - -char* XMLUnknown::ParseDeep( char* p, StrPair*, int* curLineNumPtr ) -{ - // Unknown parses as text. - p = _value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr ); - if ( !p ) { - _document->SetError( XML_ERROR_PARSING_UNKNOWN, _parseLineNum, 0 ); - } - return p; -} - - -XMLNode* XMLUnknown::ShallowClone( XMLDocument* doc ) const -{ - if ( !doc ) { - doc = _document; - } - XMLUnknown* text = doc->NewUnknown( Value() ); // fixme: this will always allocate memory. Intern? - return text; -} - - -bool XMLUnknown::ShallowEqual( const XMLNode* compare ) const -{ - TIXMLASSERT( compare ); - const XMLUnknown* unknown = compare->ToUnknown(); - return ( unknown && XMLUtil::StringEqual( unknown->Value(), Value() )); -} - - -bool XMLUnknown::Accept( XMLVisitor* visitor ) const -{ - TIXMLASSERT( visitor ); - return visitor->Visit( *this ); -} - -// --------- XMLAttribute ---------- // - +{ + // Edge case: XMLDocuments don't have a Value. Return null. + if ( this->ToDocument() ) + return 0; + return _value.GetStr(); +} + +void XMLNode::SetValue( const char* str, bool staticMem ) +{ + if ( staticMem ) { + _value.SetInternedStr( str ); + } + else { + _value.SetStr( str ); + } +} + +XMLNode* XMLNode::DeepClone(XMLDocument* target) const +{ + XMLNode* clone = this->ShallowClone(target); + if (!clone) return 0; + + for (const XMLNode* child = this->FirstChild(); child; child = child->NextSibling()) { + XMLNode* childClone = child->DeepClone(target); + TIXMLASSERT(childClone); + clone->InsertEndChild(childClone); + } + return clone; +} + +void XMLNode::DeleteChildren() +{ + while( _firstChild ) { + TIXMLASSERT( _lastChild ); + DeleteChild( _firstChild ); + } + _firstChild = _lastChild = 0; +} + + +void XMLNode::Unlink( XMLNode* child ) +{ + TIXMLASSERT( child ); + TIXMLASSERT( child->_document == _document ); + TIXMLASSERT( child->_parent == this ); + if ( child == _firstChild ) { + _firstChild = _firstChild->_next; + } + if ( child == _lastChild ) { + _lastChild = _lastChild->_prev; + } + + if ( child->_prev ) { + child->_prev->_next = child->_next; + } + if ( child->_next ) { + child->_next->_prev = child->_prev; + } + child->_next = 0; + child->_prev = 0; + child->_parent = 0; +} + + +void XMLNode::DeleteChild( XMLNode* node ) +{ + TIXMLASSERT( node ); + TIXMLASSERT( node->_document == _document ); + TIXMLASSERT( node->_parent == this ); + Unlink( node ); + TIXMLASSERT(node->_prev == 0); + TIXMLASSERT(node->_next == 0); + TIXMLASSERT(node->_parent == 0); + DeleteNode( node ); +} + + +XMLNode* XMLNode::InsertEndChild( XMLNode* addThis ) +{ + TIXMLASSERT( addThis ); + if ( addThis->_document != _document ) { + TIXMLASSERT( false ); + return 0; + } + InsertChildPreamble( addThis ); + + if ( _lastChild ) { + TIXMLASSERT( _firstChild ); + TIXMLASSERT( _lastChild->_next == 0 ); + _lastChild->_next = addThis; + addThis->_prev = _lastChild; + _lastChild = addThis; + + addThis->_next = 0; + } + else { + TIXMLASSERT( _firstChild == 0 ); + _firstChild = _lastChild = addThis; + + addThis->_prev = 0; + addThis->_next = 0; + } + addThis->_parent = this; + return addThis; +} + + +XMLNode* XMLNode::InsertFirstChild( XMLNode* addThis ) +{ + TIXMLASSERT( addThis ); + if ( addThis->_document != _document ) { + TIXMLASSERT( false ); + return 0; + } + InsertChildPreamble( addThis ); + + if ( _firstChild ) { + TIXMLASSERT( _lastChild ); + TIXMLASSERT( _firstChild->_prev == 0 ); + + _firstChild->_prev = addThis; + addThis->_next = _firstChild; + _firstChild = addThis; + + addThis->_prev = 0; + } + else { + TIXMLASSERT( _lastChild == 0 ); + _firstChild = _lastChild = addThis; + + addThis->_prev = 0; + addThis->_next = 0; + } + addThis->_parent = this; + return addThis; +} + + +XMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis ) +{ + TIXMLASSERT( addThis ); + if ( addThis->_document != _document ) { + TIXMLASSERT( false ); + return 0; + } + + TIXMLASSERT( afterThis ); + + if ( afterThis->_parent != this ) { + TIXMLASSERT( false ); + return 0; + } + if ( afterThis == addThis ) { + // Current state: BeforeThis -> AddThis -> OneAfterAddThis + // Now AddThis must disappear from it's location and then + // reappear between BeforeThis and OneAfterAddThis. + // So just leave it where it is. + return addThis; + } + + if ( afterThis->_next == 0 ) { + // The last node or the only node. + return InsertEndChild( addThis ); + } + InsertChildPreamble( addThis ); + addThis->_prev = afterThis; + addThis->_next = afterThis->_next; + afterThis->_next->_prev = addThis; + afterThis->_next = addThis; + addThis->_parent = this; + return addThis; +} + + + + +const XMLElement* XMLNode::FirstChildElement( const char* name ) const +{ + for( const XMLNode* node = _firstChild; node; node = node->_next ) { + const XMLElement* element = node->ToElementWithName( name ); + if ( element ) { + return element; + } + } + return 0; +} + + +const XMLElement* XMLNode::LastChildElement( const char* name ) const +{ + for( const XMLNode* node = _lastChild; node; node = node->_prev ) { + const XMLElement* element = node->ToElementWithName( name ); + if ( element ) { + return element; + } + } + return 0; +} + + +const XMLElement* XMLNode::NextSiblingElement( const char* name ) const +{ + for( const XMLNode* node = _next; node; node = node->_next ) { + const XMLElement* element = node->ToElementWithName( name ); + if ( element ) { + return element; + } + } + return 0; +} + + +const XMLElement* XMLNode::PreviousSiblingElement( const char* name ) const +{ + for( const XMLNode* node = _prev; node; node = node->_prev ) { + const XMLElement* element = node->ToElementWithName( name ); + if ( element ) { + return element; + } + } + return 0; +} + + +char* XMLNode::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) +{ + // This is a recursive method, but thinking about it "at the current level" + // it is a pretty simple flat list: + // <foo/> + // <!-- comment --> + // + // With a special case: + // <foo> + // </foo> + // <!-- comment --> + // + // Where the closing element (/foo) *must* be the next thing after the opening + // element, and the names must match. BUT the tricky bit is that the closing + // element will be read by the child. + // + // 'endTag' is the end tag for this node, it is returned by a call to a child. + // 'parentEnd' is the end tag for the parent, which is filled in and returned. + + while( p && *p ) { + XMLNode* node = 0; + + p = _document->Identify( p, &node ); + TIXMLASSERT( p ); + if ( node == 0 ) { + break; + } + + int initialLineNum = node->_parseLineNum; + + StrPair endTag; + p = node->ParseDeep( p, &endTag, curLineNumPtr ); + if ( !p ) { + DeleteNode( node ); + if ( !_document->Error() ) { + _document->SetError( XML_ERROR_PARSING, initialLineNum, 0); + } + break; + } + + XMLDeclaration* decl = node->ToDeclaration(); + if ( decl ) { + // Declarations are only allowed at document level + bool wellLocated = ( ToDocument() != 0 ); + if ( wellLocated ) { + // Multiple declarations are allowed but all declarations + // must occur before anything else + for ( const XMLNode* existingNode = _document->FirstChild(); existingNode; existingNode = existingNode->NextSibling() ) { + if ( !existingNode->ToDeclaration() ) { + wellLocated = false; + break; + } + } + } + if ( !wellLocated ) { + _document->SetError( XML_ERROR_PARSING_DECLARATION, initialLineNum, "XMLDeclaration value=%s", decl->Value()); + DeleteNode( node ); + break; + } + } + + XMLElement* ele = node->ToElement(); + if ( ele ) { + // We read the end tag. Return it to the parent. + if ( ele->ClosingType() == XMLElement::CLOSING ) { + if ( parentEndTag ) { + ele->_value.TransferTo( parentEndTag ); + } + node->_memPool->SetTracked(); // created and then immediately deleted. + DeleteNode( node ); + return p; + } + + // Handle an end tag returned to this level. + // And handle a bunch of annoying errors. + bool mismatch = false; + if ( endTag.Empty() ) { + if ( ele->ClosingType() == XMLElement::OPEN ) { + mismatch = true; + } + } + else { + if ( ele->ClosingType() != XMLElement::OPEN ) { + mismatch = true; + } + else if ( !XMLUtil::StringEqual( endTag.GetStr(), ele->Name() ) ) { + mismatch = true; + } + } + if ( mismatch ) { + _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, initialLineNum, "XMLElement name=%s", ele->Name()); + DeleteNode( node ); + break; + } + } + InsertEndChild( node ); + } + return 0; +} + +/*static*/ void XMLNode::DeleteNode( XMLNode* node ) +{ + if ( node == 0 ) { + return; + } + TIXMLASSERT(node->_document); + if (!node->ToDocument()) { + node->_document->MarkInUse(node); + } + + MemPool* pool = node->_memPool; + node->~XMLNode(); + pool->Free( node ); +} + +void XMLNode::InsertChildPreamble( XMLNode* insertThis ) const +{ + TIXMLASSERT( insertThis ); + TIXMLASSERT( insertThis->_document == _document ); + + if (insertThis->_parent) { + insertThis->_parent->Unlink( insertThis ); + } + else { + insertThis->_document->MarkInUse(insertThis); + insertThis->_memPool->SetTracked(); + } +} + +const XMLElement* XMLNode::ToElementWithName( const char* name ) const +{ + const XMLElement* element = this->ToElement(); + if ( element == 0 ) { + return 0; + } + if ( name == 0 ) { + return element; + } + if ( XMLUtil::StringEqual( element->Name(), name ) ) { + return element; + } + return 0; +} + +// --------- XMLText ---------- // +char* XMLText::ParseDeep( char* p, StrPair*, int* curLineNumPtr ) +{ + if ( this->CData() ) { + p = _value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr ); + if ( !p ) { + _document->SetError( XML_ERROR_PARSING_CDATA, _parseLineNum, 0 ); + } + return p; + } + else { + int flags = _document->ProcessEntities() ? StrPair::TEXT_ELEMENT : StrPair::TEXT_ELEMENT_LEAVE_ENTITIES; + if ( _document->WhitespaceMode() == COLLAPSE_WHITESPACE ) { + flags |= StrPair::NEEDS_WHITESPACE_COLLAPSING; + } + + p = _value.ParseText( p, "<", flags, curLineNumPtr ); + if ( p && *p ) { + return p-1; + } + if ( !p ) { + _document->SetError( XML_ERROR_PARSING_TEXT, _parseLineNum, 0 ); + } + } + return 0; +} + + +XMLNode* XMLText::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLText* text = doc->NewText( Value() ); // fixme: this will always allocate memory. Intern? + text->SetCData( this->CData() ); + return text; +} + + +bool XMLText::ShallowEqual( const XMLNode* compare ) const +{ + TIXMLASSERT( compare ); + const XMLText* text = compare->ToText(); + return ( text && XMLUtil::StringEqual( text->Value(), Value() ) ); +} + + +bool XMLText::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + return visitor->Visit( *this ); +} + + +// --------- XMLComment ---------- // + +XMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc ) +{ +} + + +XMLComment::~XMLComment() +{ +} + + +char* XMLComment::ParseDeep( char* p, StrPair*, int* curLineNumPtr ) +{ + // Comment parses as text. + p = _value.ParseText( p, "-->", StrPair::COMMENT, curLineNumPtr ); + if ( p == 0 ) { + _document->SetError( XML_ERROR_PARSING_COMMENT, _parseLineNum, 0 ); + } + return p; +} + + +XMLNode* XMLComment::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLComment* comment = doc->NewComment( Value() ); // fixme: this will always allocate memory. Intern? + return comment; +} + + +bool XMLComment::ShallowEqual( const XMLNode* compare ) const +{ + TIXMLASSERT( compare ); + const XMLComment* comment = compare->ToComment(); + return ( comment && XMLUtil::StringEqual( comment->Value(), Value() )); +} + + +bool XMLComment::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + return visitor->Visit( *this ); +} + + +// --------- XMLDeclaration ---------- // + +XMLDeclaration::XMLDeclaration( XMLDocument* doc ) : XMLNode( doc ) +{ +} + + +XMLDeclaration::~XMLDeclaration() +{ + //printf( "~XMLDeclaration\n" ); +} + + +char* XMLDeclaration::ParseDeep( char* p, StrPair*, int* curLineNumPtr ) +{ + // Declaration parses as text. + p = _value.ParseText( p, "?>", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr ); + if ( p == 0 ) { + _document->SetError( XML_ERROR_PARSING_DECLARATION, _parseLineNum, 0 ); + } + return p; +} + + +XMLNode* XMLDeclaration::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLDeclaration* dec = doc->NewDeclaration( Value() ); // fixme: this will always allocate memory. Intern? + return dec; +} + + +bool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const +{ + TIXMLASSERT( compare ); + const XMLDeclaration* declaration = compare->ToDeclaration(); + return ( declaration && XMLUtil::StringEqual( declaration->Value(), Value() )); +} + + + +bool XMLDeclaration::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + return visitor->Visit( *this ); +} + +// --------- XMLUnknown ---------- // + +XMLUnknown::XMLUnknown( XMLDocument* doc ) : XMLNode( doc ) +{ +} + + +XMLUnknown::~XMLUnknown() +{ +} + + +char* XMLUnknown::ParseDeep( char* p, StrPair*, int* curLineNumPtr ) +{ + // Unknown parses as text. + p = _value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr ); + if ( !p ) { + _document->SetError( XML_ERROR_PARSING_UNKNOWN, _parseLineNum, 0 ); + } + return p; +} + + +XMLNode* XMLUnknown::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLUnknown* text = doc->NewUnknown( Value() ); // fixme: this will always allocate memory. Intern? + return text; +} + + +bool XMLUnknown::ShallowEqual( const XMLNode* compare ) const +{ + TIXMLASSERT( compare ); + const XMLUnknown* unknown = compare->ToUnknown(); + return ( unknown && XMLUtil::StringEqual( unknown->Value(), Value() )); +} + + +bool XMLUnknown::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + return visitor->Visit( *this ); +} + +// --------- XMLAttribute ---------- // + const char* XMLAttribute::Name() const -{ - return _name.GetStr(); -} - +{ + return _name.GetStr(); +} + const char* XMLAttribute::Value() const -{ - return _value.GetStr(); -} - -char* XMLAttribute::ParseDeep( char* p, bool processEntities, int* curLineNumPtr ) -{ - // Parse using the name rules: bug fix, was using ParseText before - p = _name.ParseName( p ); - if ( !p || !*p ) { - return 0; - } - - // Skip white space before = - p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr ); - if ( *p != '=' ) { - return 0; - } - - ++p; // move up to opening quote - p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr ); - if ( *p != '\"' && *p != '\'' ) { - return 0; - } - - char endTag[2] = { *p, 0 }; - ++p; // move past opening quote - - p = _value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES, curLineNumPtr ); - return p; -} - - -void XMLAttribute::SetName( const char* n ) -{ - _name.SetStr( n ); -} - - -XMLError XMLAttribute::QueryIntValue( int* value ) const -{ - if ( XMLUtil::ToInt( Value(), value )) { - return XML_SUCCESS; - } - return XML_WRONG_ATTRIBUTE_TYPE; -} - - -XMLError XMLAttribute::QueryUnsignedValue( unsigned int* value ) const -{ - if ( XMLUtil::ToUnsigned( Value(), value )) { - return XML_SUCCESS; - } - return XML_WRONG_ATTRIBUTE_TYPE; -} - - -XMLError XMLAttribute::QueryInt64Value(int64_t* value) const -{ - if (XMLUtil::ToInt64(Value(), value)) { - return XML_SUCCESS; - } - return XML_WRONG_ATTRIBUTE_TYPE; -} - - -XMLError XMLAttribute::QueryBoolValue( bool* value ) const -{ - if ( XMLUtil::ToBool( Value(), value )) { - return XML_SUCCESS; - } - return XML_WRONG_ATTRIBUTE_TYPE; -} - - -XMLError XMLAttribute::QueryFloatValue( float* value ) const -{ - if ( XMLUtil::ToFloat( Value(), value )) { - return XML_SUCCESS; - } - return XML_WRONG_ATTRIBUTE_TYPE; -} - - -XMLError XMLAttribute::QueryDoubleValue( double* value ) const -{ - if ( XMLUtil::ToDouble( Value(), value )) { - return XML_SUCCESS; - } - return XML_WRONG_ATTRIBUTE_TYPE; -} - - -void XMLAttribute::SetAttribute( const char* v ) -{ - _value.SetStr( v ); -} - - -void XMLAttribute::SetAttribute( int v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - _value.SetStr( buf ); -} - - -void XMLAttribute::SetAttribute( unsigned v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - _value.SetStr( buf ); -} - - -void XMLAttribute::SetAttribute(int64_t v) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr(v, buf, BUF_SIZE); - _value.SetStr(buf); -} - - - -void XMLAttribute::SetAttribute( bool v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - _value.SetStr( buf ); -} - -void XMLAttribute::SetAttribute( double v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - _value.SetStr( buf ); -} - -void XMLAttribute::SetAttribute( float v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - _value.SetStr( buf ); -} - - -// --------- XMLElement ---------- // -XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ), - _closingType( OPEN ), - _rootAttribute( 0 ) -{ -} - - -XMLElement::~XMLElement() -{ - while( _rootAttribute ) { - XMLAttribute* next = _rootAttribute->_next; - DeleteAttribute( _rootAttribute ); - _rootAttribute = next; - } -} - - -const XMLAttribute* XMLElement::FindAttribute( const char* name ) const -{ - for( XMLAttribute* a = _rootAttribute; a; a = a->_next ) { - if ( XMLUtil::StringEqual( a->Name(), name ) ) { - return a; - } - } - return 0; -} - - -const char* XMLElement::Attribute( const char* name, const char* value ) const -{ - const XMLAttribute* a = FindAttribute( name ); - if ( !a ) { - return 0; - } - if ( !value || XMLUtil::StringEqual( a->Value(), value )) { - return a->Value(); - } - return 0; -} - +{ + return _value.GetStr(); +} + +char* XMLAttribute::ParseDeep( char* p, bool processEntities, int* curLineNumPtr ) +{ + // Parse using the name rules: bug fix, was using ParseText before + p = _name.ParseName( p ); + if ( !p || !*p ) { + return 0; + } + + // Skip white space before = + p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr ); + if ( *p != '=' ) { + return 0; + } + + ++p; // move up to opening quote + p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr ); + if ( *p != '\"' && *p != '\'' ) { + return 0; + } + + char endTag[2] = { *p, 0 }; + ++p; // move past opening quote + + p = _value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES, curLineNumPtr ); + return p; +} + + +void XMLAttribute::SetName( const char* n ) +{ + _name.SetStr( n ); +} + + +XMLError XMLAttribute::QueryIntValue( int* value ) const +{ + if ( XMLUtil::ToInt( Value(), value )) { + return XML_SUCCESS; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryUnsignedValue( unsigned int* value ) const +{ + if ( XMLUtil::ToUnsigned( Value(), value )) { + return XML_SUCCESS; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryInt64Value(int64_t* value) const +{ + if (XMLUtil::ToInt64(Value(), value)) { + return XML_SUCCESS; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryBoolValue( bool* value ) const +{ + if ( XMLUtil::ToBool( Value(), value )) { + return XML_SUCCESS; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryFloatValue( float* value ) const +{ + if ( XMLUtil::ToFloat( Value(), value )) { + return XML_SUCCESS; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryDoubleValue( double* value ) const +{ + if ( XMLUtil::ToDouble( Value(), value )) { + return XML_SUCCESS; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +void XMLAttribute::SetAttribute( const char* v ) +{ + _value.SetStr( v ); +} + + +void XMLAttribute::SetAttribute( int v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + + +void XMLAttribute::SetAttribute( unsigned v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + + +void XMLAttribute::SetAttribute(int64_t v) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr(v, buf, BUF_SIZE); + _value.SetStr(buf); +} + + + +void XMLAttribute::SetAttribute( bool v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + +void XMLAttribute::SetAttribute( double v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + +void XMLAttribute::SetAttribute( float v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + + +// --------- XMLElement ---------- // +XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ), + _closingType( OPEN ), + _rootAttribute( 0 ) +{ +} + + +XMLElement::~XMLElement() +{ + while( _rootAttribute ) { + XMLAttribute* next = _rootAttribute->_next; + DeleteAttribute( _rootAttribute ); + _rootAttribute = next; + } +} + + +const XMLAttribute* XMLElement::FindAttribute( const char* name ) const +{ + for( XMLAttribute* a = _rootAttribute; a; a = a->_next ) { + if ( XMLUtil::StringEqual( a->Name(), name ) ) { + return a; + } + } + return 0; +} + + +const char* XMLElement::Attribute( const char* name, const char* value ) const +{ + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return 0; + } + if ( !value || XMLUtil::StringEqual( a->Value(), value )) { + return a->Value(); + } + return 0; +} + int XMLElement::IntAttribute(const char* name, int defaultValue) const -{ - int i = defaultValue; - QueryIntAttribute(name, &i); - return i; -} - +{ + int i = defaultValue; + QueryIntAttribute(name, &i); + return i; +} + unsigned XMLElement::UnsignedAttribute(const char* name, unsigned defaultValue) const -{ - unsigned i = defaultValue; - QueryUnsignedAttribute(name, &i); - return i; -} - +{ + unsigned i = defaultValue; + QueryUnsignedAttribute(name, &i); + return i; +} + int64_t XMLElement::Int64Attribute(const char* name, int64_t defaultValue) const -{ - int64_t i = defaultValue; - QueryInt64Attribute(name, &i); - return i; -} - +{ + int64_t i = defaultValue; + QueryInt64Attribute(name, &i); + return i; +} + bool XMLElement::BoolAttribute(const char* name, bool defaultValue) const -{ - bool b = defaultValue; - QueryBoolAttribute(name, &b); - return b; -} - +{ + bool b = defaultValue; + QueryBoolAttribute(name, &b); + return b; +} + double XMLElement::DoubleAttribute(const char* name, double defaultValue) const -{ - double d = defaultValue; - QueryDoubleAttribute(name, &d); - return d; -} - +{ + double d = defaultValue; + QueryDoubleAttribute(name, &d); + return d; +} + float XMLElement::FloatAttribute(const char* name, float defaultValue) const -{ - float f = defaultValue; - QueryFloatAttribute(name, &f); - return f; -} - -const char* XMLElement::GetText() const -{ - if ( FirstChild() && FirstChild()->ToText() ) { - return FirstChild()->Value(); - } - return 0; -} - - -void XMLElement::SetText( const char* inText ) -{ - if ( FirstChild() && FirstChild()->ToText() ) - FirstChild()->SetValue( inText ); - else { - XMLText* theText = GetDocument()->NewText( inText ); - InsertFirstChild( theText ); - } -} - - +{ + float f = defaultValue; + QueryFloatAttribute(name, &f); + return f; +} + +const char* XMLElement::GetText() const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + return FirstChild()->Value(); + } + return 0; +} + + +void XMLElement::SetText( const char* inText ) +{ + if ( FirstChild() && FirstChild()->ToText() ) + FirstChild()->SetValue( inText ); + else { + XMLText* theText = GetDocument()->NewText( inText ); + InsertFirstChild( theText ); + } +} + + void XMLElement::SetText( int v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - SetText( buf ); -} - - +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + void XMLElement::SetText( unsigned v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - SetText( buf ); -} - - -void XMLElement::SetText(int64_t v) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr(v, buf, BUF_SIZE); - SetText(buf); -} - - -void XMLElement::SetText( bool v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - SetText( buf ); -} - - +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +void XMLElement::SetText(int64_t v) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr(v, buf, BUF_SIZE); + SetText(buf); +} + + +void XMLElement::SetText( bool v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + void XMLElement::SetText( float v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - SetText( buf ); -} - - +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + void XMLElement::SetText( double v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - SetText( buf ); -} - - -XMLError XMLElement::QueryIntText( int* ival ) const -{ - if ( FirstChild() && FirstChild()->ToText() ) { - const char* t = FirstChild()->Value(); - if ( XMLUtil::ToInt( t, ival ) ) { - return XML_SUCCESS; - } - return XML_CAN_NOT_CONVERT_TEXT; - } - return XML_NO_TEXT_NODE; -} - - -XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const -{ - if ( FirstChild() && FirstChild()->ToText() ) { - const char* t = FirstChild()->Value(); - if ( XMLUtil::ToUnsigned( t, uval ) ) { - return XML_SUCCESS; - } - return XML_CAN_NOT_CONVERT_TEXT; - } - return XML_NO_TEXT_NODE; -} - - -XMLError XMLElement::QueryInt64Text(int64_t* ival) const -{ - if (FirstChild() && FirstChild()->ToText()) { - const char* t = FirstChild()->Value(); - if (XMLUtil::ToInt64(t, ival)) { - return XML_SUCCESS; - } - return XML_CAN_NOT_CONVERT_TEXT; - } - return XML_NO_TEXT_NODE; -} - - -XMLError XMLElement::QueryBoolText( bool* bval ) const -{ - if ( FirstChild() && FirstChild()->ToText() ) { - const char* t = FirstChild()->Value(); - if ( XMLUtil::ToBool( t, bval ) ) { - return XML_SUCCESS; - } - return XML_CAN_NOT_CONVERT_TEXT; - } - return XML_NO_TEXT_NODE; -} - - -XMLError XMLElement::QueryDoubleText( double* dval ) const -{ - if ( FirstChild() && FirstChild()->ToText() ) { - const char* t = FirstChild()->Value(); - if ( XMLUtil::ToDouble( t, dval ) ) { - return XML_SUCCESS; - } - return XML_CAN_NOT_CONVERT_TEXT; - } - return XML_NO_TEXT_NODE; -} - - -XMLError XMLElement::QueryFloatText( float* fval ) const -{ - if ( FirstChild() && FirstChild()->ToText() ) { - const char* t = FirstChild()->Value(); - if ( XMLUtil::ToFloat( t, fval ) ) { - return XML_SUCCESS; - } - return XML_CAN_NOT_CONVERT_TEXT; - } - return XML_NO_TEXT_NODE; -} - -int XMLElement::IntText(int defaultValue) const -{ - int i = defaultValue; - QueryIntText(&i); - return i; -} - -unsigned XMLElement::UnsignedText(unsigned defaultValue) const -{ - unsigned i = defaultValue; - QueryUnsignedText(&i); - return i; -} - -int64_t XMLElement::Int64Text(int64_t defaultValue) const -{ - int64_t i = defaultValue; - QueryInt64Text(&i); - return i; -} - -bool XMLElement::BoolText(bool defaultValue) const -{ - bool b = defaultValue; - QueryBoolText(&b); - return b; -} - -double XMLElement::DoubleText(double defaultValue) const -{ - double d = defaultValue; - QueryDoubleText(&d); - return d; -} - -float XMLElement::FloatText(float defaultValue) const -{ - float f = defaultValue; - QueryFloatText(&f); - return f; -} - - -XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name ) -{ - XMLAttribute* last = 0; - XMLAttribute* attrib = 0; - for( attrib = _rootAttribute; - attrib; - last = attrib, attrib = attrib->_next ) { - if ( XMLUtil::StringEqual( attrib->Name(), name ) ) { - break; - } - } - if ( !attrib ) { - attrib = CreateAttribute(); - TIXMLASSERT( attrib ); - if ( last ) { - TIXMLASSERT( last->_next == 0 ); - last->_next = attrib; - } - else { - TIXMLASSERT( _rootAttribute == 0 ); - _rootAttribute = attrib; - } - attrib->SetName( name ); - } - return attrib; -} - - -void XMLElement::DeleteAttribute( const char* name ) -{ - XMLAttribute* prev = 0; - for( XMLAttribute* a=_rootAttribute; a; a=a->_next ) { - if ( XMLUtil::StringEqual( name, a->Name() ) ) { - if ( prev ) { - prev->_next = a->_next; - } - else { - _rootAttribute = a->_next; - } - DeleteAttribute( a ); - break; - } - prev = a; - } -} - - -char* XMLElement::ParseAttributes( char* p, int* curLineNumPtr ) -{ - XMLAttribute* prevAttribute = 0; - - // Read the attributes. - while( p ) { - p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr ); - if ( !(*p) ) { - _document->SetError( XML_ERROR_PARSING_ELEMENT, _parseLineNum, "XMLElement name=%s", Name() ); - return 0; - } - - // attribute. - if (XMLUtil::IsNameStartChar( *p ) ) { - XMLAttribute* attrib = CreateAttribute(); - TIXMLASSERT( attrib ); - attrib->_parseLineNum = _document->_parseCurLineNum; - - int attrLineNum = attrib->_parseLineNum; - - p = attrib->ParseDeep( p, _document->ProcessEntities(), curLineNumPtr ); - if ( !p || Attribute( attrib->Name() ) ) { - DeleteAttribute( attrib ); - _document->SetError( XML_ERROR_PARSING_ATTRIBUTE, attrLineNum, "XMLElement name=%s", Name() ); - return 0; - } - // There is a minor bug here: if the attribute in the source xml - // document is duplicated, it will not be detected and the - // attribute will be doubly added. However, tracking the 'prevAttribute' - // avoids re-scanning the attribute list. Preferring performance for - // now, may reconsider in the future. - if ( prevAttribute ) { - TIXMLASSERT( prevAttribute->_next == 0 ); - prevAttribute->_next = attrib; - } - else { - TIXMLASSERT( _rootAttribute == 0 ); - _rootAttribute = attrib; - } - prevAttribute = attrib; - } - // end of the tag - else if ( *p == '>' ) { - ++p; - break; - } - // end of the tag - else if ( *p == '/' && *(p+1) == '>' ) { - _closingType = CLOSED; - return p+2; // done; sealed element. - } - else { - _document->SetError( XML_ERROR_PARSING_ELEMENT, _parseLineNum, 0 ); - return 0; - } - } - return p; -} - -void XMLElement::DeleteAttribute( XMLAttribute* attribute ) -{ - if ( attribute == 0 ) { - return; - } - MemPool* pool = attribute->_memPool; - attribute->~XMLAttribute(); - pool->Free( attribute ); -} - -XMLAttribute* XMLElement::CreateAttribute() -{ - TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() ); - XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute(); - TIXMLASSERT( attrib ); - attrib->_memPool = &_document->_attributePool; - attrib->_memPool->SetTracked(); - return attrib; -} - -// -// <ele></ele> -// <ele>foo<b>bar</b></ele> -// -char* XMLElement::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) -{ - // Read the element name. - p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr ); - - // The closing element is the </element> form. It is - // parsed just like a regular element then deleted from - // the DOM. - if ( *p == '/' ) { - _closingType = CLOSING; - ++p; - } - - p = _value.ParseName( p ); - if ( _value.Empty() ) { - return 0; - } - - p = ParseAttributes( p, curLineNumPtr ); - if ( !p || !*p || _closingType != OPEN ) { - return p; - } - - p = XMLNode::ParseDeep( p, parentEndTag, curLineNumPtr ); - return p; -} - - - -XMLNode* XMLElement::ShallowClone( XMLDocument* doc ) const -{ - if ( !doc ) { - doc = _document; - } - XMLElement* element = doc->NewElement( Value() ); // fixme: this will always allocate memory. Intern? - for( const XMLAttribute* a=FirstAttribute(); a; a=a->Next() ) { - element->SetAttribute( a->Name(), a->Value() ); // fixme: this will always allocate memory. Intern? - } - return element; -} - - -bool XMLElement::ShallowEqual( const XMLNode* compare ) const -{ - TIXMLASSERT( compare ); - const XMLElement* other = compare->ToElement(); - if ( other && XMLUtil::StringEqual( other->Name(), Name() )) { - - const XMLAttribute* a=FirstAttribute(); - const XMLAttribute* b=other->FirstAttribute(); - - while ( a && b ) { - if ( !XMLUtil::StringEqual( a->Value(), b->Value() ) ) { - return false; - } - a = a->Next(); - b = b->Next(); - } - if ( a || b ) { - // different count - return false; - } - return true; - } - return false; -} - - -bool XMLElement::Accept( XMLVisitor* visitor ) const -{ - TIXMLASSERT( visitor ); - if ( visitor->VisitEnter( *this, _rootAttribute ) ) { - for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) { - if ( !node->Accept( visitor ) ) { - break; - } - } - } - return visitor->VisitExit( *this ); -} - - -// --------- XMLDocument ----------- // - -// Warning: List must match 'enum XMLError' -const char* XMLDocument::_errorNames[XML_ERROR_COUNT] = { - "XML_SUCCESS", - "XML_NO_ATTRIBUTE", - "XML_WRONG_ATTRIBUTE_TYPE", - "XML_ERROR_FILE_NOT_FOUND", - "XML_ERROR_FILE_COULD_NOT_BE_OPENED", - "XML_ERROR_FILE_READ_ERROR", - "UNUSED_XML_ERROR_ELEMENT_MISMATCH", - "XML_ERROR_PARSING_ELEMENT", - "XML_ERROR_PARSING_ATTRIBUTE", - "UNUSED_XML_ERROR_IDENTIFYING_TAG", - "XML_ERROR_PARSING_TEXT", - "XML_ERROR_PARSING_CDATA", - "XML_ERROR_PARSING_COMMENT", - "XML_ERROR_PARSING_DECLARATION", - "XML_ERROR_PARSING_UNKNOWN", - "XML_ERROR_EMPTY_DOCUMENT", - "XML_ERROR_MISMATCHED_ELEMENT", - "XML_ERROR_PARSING", - "XML_CAN_NOT_CONVERT_TEXT", - "XML_NO_TEXT_NODE" -}; - - -XMLDocument::XMLDocument( bool processEntities, Whitespace whitespaceMode ) : - XMLNode( 0 ), - _writeBOM( false ), - _processEntities( processEntities ), - _errorID(XML_SUCCESS), - _whitespaceMode( whitespaceMode ), - _errorStr(), - _errorLineNum( 0 ), - _charBuffer( 0 ), - _parseCurLineNum( 0 ), - _unlinked(), - _elementPool(), - _attributePool(), - _textPool(), - _commentPool() -{ - // avoid VC++ C4355 warning about 'this' in initializer list (C4355 is off by default in VS2012+) - _document = this; -} - - -XMLDocument::~XMLDocument() -{ - Clear(); -} - - -void XMLDocument::MarkInUse(XMLNode* node) -{ - TIXMLASSERT(node); - TIXMLASSERT(node->_parent == 0); - - for (int i = 0; i < _unlinked.Size(); ++i) { - if (node == _unlinked[i]) { - _unlinked.SwapRemove(i); - break; - } - } -} - -void XMLDocument::Clear() -{ - DeleteChildren(); - while( _unlinked.Size()) { - DeleteNode(_unlinked[0]); // Will remove from _unlinked as part of delete. - } - -#ifdef DEBUG - const bool hadError = Error(); -#endif - ClearError(); - - Aws::DeleteArray(_charBuffer); - _charBuffer = 0; - -#if 0 - _textPool.Trace( "text" ); - _elementPool.Trace( "element" ); - _commentPool.Trace( "comment" ); - _attributePool.Trace( "attribute" ); -#endif - -#ifdef DEBUG - if ( !hadError ) { - TIXMLASSERT( _elementPool.CurrentAllocs() == _elementPool.Untracked() ); - TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() ); - TIXMLASSERT( _textPool.CurrentAllocs() == _textPool.Untracked() ); - TIXMLASSERT( _commentPool.CurrentAllocs() == _commentPool.Untracked() ); - } -#endif -} - - -void XMLDocument::DeepCopy(XMLDocument* target) const -{ - TIXMLASSERT(target); - if (target == this) { - return; // technically success - a no-op. - } - - target->Clear(); - for (const XMLNode* node = this->FirstChild(); node; node = node->NextSibling()) { - target->InsertEndChild(node->DeepClone(target)); - } -} - -XMLElement* XMLDocument::NewElement( const char* name ) -{ - XMLElement* ele = CreateUnlinkedNode<XMLElement>( _elementPool ); - ele->SetName( name ); - return ele; -} - - -XMLComment* XMLDocument::NewComment( const char* str ) -{ - XMLComment* comment = CreateUnlinkedNode<XMLComment>( _commentPool ); - comment->SetValue( str ); - return comment; -} - - -XMLText* XMLDocument::NewText( const char* str ) -{ - XMLText* text = CreateUnlinkedNode<XMLText>( _textPool ); - text->SetValue( str ); - return text; -} - - -XMLDeclaration* XMLDocument::NewDeclaration( const char* str ) -{ - XMLDeclaration* dec = CreateUnlinkedNode<XMLDeclaration>( _commentPool ); - dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" ); - return dec; -} - - -XMLUnknown* XMLDocument::NewUnknown( const char* str ) -{ - XMLUnknown* unk = CreateUnlinkedNode<XMLUnknown>( _commentPool ); - unk->SetValue( str ); - return unk; -} - -static FILE* callfopen( const char* filepath, const char* mode ) -{ - TIXMLASSERT( filepath ); - TIXMLASSERT( mode ); -#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE) - FILE* fp = 0; - errno_t err = fopen_s( &fp, filepath, mode ); - if ( err ) { - return 0; - } -#else - FILE* fp = fopen( filepath, mode ); -#endif - return fp; -} - -void XMLDocument::DeleteNode( XMLNode* node ) { - TIXMLASSERT( node ); - TIXMLASSERT(node->_document == this ); - if (node->_parent) { - node->_parent->DeleteChild( node ); - } - else { - // Isn't in the tree. - // Use the parent delete. - // Also, we need to mark it tracked: we 'know' - // it was never used. - node->_memPool->SetTracked(); - // Call the static XMLNode version: - XMLNode::DeleteNode(node); - } -} - - -XMLError XMLDocument::LoadFile( const char* filename ) -{ - Clear(); - FILE* fp = callfopen( filename, "rb" ); - if ( !fp ) { - SetError( XML_ERROR_FILE_NOT_FOUND, 0, "filename=%s", filename ? filename : "<null>"); - return _errorID; - } - LoadFile( fp ); - fclose( fp ); - return _errorID; -} - -// This is likely overengineered template art to have a check that unsigned long value incremented -// by one still fits into size_t. If size_t type is larger than unsigned long type -// (x86_64-w64-mingw32 target) then the check is redundant and gcc and clang emit -// -Wtype-limits warning. This piece makes the compiler select code with a check when a check -// is useful and code with no check when a check is redundant depending on how size_t and unsigned long -// types sizes relate to each other. -template -<bool = (sizeof(unsigned long) >= sizeof(size_t))> -struct LongFitsIntoSizeTMinusOne { - static bool Fits( unsigned long value ) - { - return value < (size_t)-1; - } -}; - -template <> -struct LongFitsIntoSizeTMinusOne<false> { - static bool Fits( unsigned long ) - { - return true; - } -}; - -XMLError XMLDocument::LoadFile( FILE* fp ) -{ - Clear(); - - fseek( fp, 0, SEEK_SET ); - if ( fgetc( fp ) == EOF && ferror( fp ) != 0 ) { - SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); - return _errorID; - } - - fseek( fp, 0, SEEK_END ); - const long filelength = ftell( fp ); - fseek( fp, 0, SEEK_SET ); - if ( filelength == -1L ) { - SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); - return _errorID; - } - TIXMLASSERT( filelength >= 0 ); - - if ( !LongFitsIntoSizeTMinusOne<>::Fits( filelength ) ) { - // Cannot handle files which won't fit in buffer together with null terminator - SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); - return _errorID; - } - - if ( filelength == 0 ) { - SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); - return _errorID; - } - - const size_t size = filelength; - TIXMLASSERT( _charBuffer == 0 ); - _charBuffer = Aws::NewArray <char>(size+1, ALLOCATION_TAG); - size_t read = fread( _charBuffer, 1, size, fp ); - if ( read != size ) { - SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); - return _errorID; - } - - _charBuffer[size] = 0; - - Parse(); - return _errorID; -} - - -XMLError XMLDocument::SaveFile( const char* filename, bool compact ) -{ - FILE* fp = callfopen( filename, "w" ); - if ( !fp ) { - SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=%s", filename ? filename : "<null>"); - return _errorID; - } - SaveFile(fp, compact); - fclose( fp ); - return _errorID; -} - - -XMLError XMLDocument::SaveFile( FILE* fp, bool compact ) -{ - // Clear any error from the last save, otherwise it will get reported - // for *this* call. - ClearError(); - XMLPrinter stream( fp, compact ); - Print( &stream ); - return _errorID; -} - - -XMLError XMLDocument::Parse( const char* p, size_t len ) -{ - Clear(); - - if ( len == 0 || !p || !*p ) { - SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); - return _errorID; - } - if ( len == (size_t)(-1) ) { - len = strlen( p ); - } - TIXMLASSERT( _charBuffer == 0 ); - _charBuffer = Aws::NewArray<char>(len+1, ALLOCATION_TAG); - memcpy( _charBuffer, p, len ); - _charBuffer[len] = 0; - - Parse(); - if ( Error() ) { - // clean up now essentially dangling memory. - // and the parse fail can put objects in the - // pools that are dead and inaccessible. - DeleteChildren(); - _elementPool.Clear(); - _attributePool.Clear(); - _textPool.Clear(); - _commentPool.Clear(); - } - return _errorID; -} - - -void XMLDocument::Print( XMLPrinter* streamer ) const -{ - if ( streamer ) { - Accept( streamer ); - } - else { - XMLPrinter stdoutStreamer( stdout ); - Accept( &stdoutStreamer ); - } -} - - -void XMLDocument::SetError( XMLError error, int lineNum, const char* format, ... ) -{ - TIXMLASSERT( error >= 0 && error < XML_ERROR_COUNT ); - _errorID = error; - _errorLineNum = lineNum; - _errorStr.Reset(); - - if (format) { - size_t BUFFER_SIZE = 1000; - char* buffer = Aws::NewArray<char>(BUFFER_SIZE, ALLOCATION_TAG); - TIXML_SNPRINTF(buffer, BUFFER_SIZE, "Error=%s ErrorID=%d (0x%x) Line number=%d: ", ErrorIDToName(error), int(error), int(error), lineNum); - size_t len = strlen(buffer); - - va_list va; - va_start( va, format ); - TIXML_VSNPRINTF( buffer + len, BUFFER_SIZE - len, format, va ); - va_end( va ); - - _errorStr.SetStr(buffer); - Aws::DeleteArray(buffer); - } -} - - -/*static*/ const char* XMLDocument::ErrorIDToName(XMLError errorID) -{ - TIXMLASSERT( errorID >= 0 && errorID < XML_ERROR_COUNT ); - const char* errorName = _errorNames[errorID]; - TIXMLASSERT( errorName && errorName[0] ); - return errorName; -} - +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +XMLError XMLElement::QueryIntText( int* ival ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToInt( t, ival ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToUnsigned( t, uval ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryInt64Text(int64_t* ival) const +{ + if (FirstChild() && FirstChild()->ToText()) { + const char* t = FirstChild()->Value(); + if (XMLUtil::ToInt64(t, ival)) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryBoolText( bool* bval ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToBool( t, bval ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryDoubleText( double* dval ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToDouble( t, dval ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryFloatText( float* fval ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToFloat( t, fval ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + +int XMLElement::IntText(int defaultValue) const +{ + int i = defaultValue; + QueryIntText(&i); + return i; +} + +unsigned XMLElement::UnsignedText(unsigned defaultValue) const +{ + unsigned i = defaultValue; + QueryUnsignedText(&i); + return i; +} + +int64_t XMLElement::Int64Text(int64_t defaultValue) const +{ + int64_t i = defaultValue; + QueryInt64Text(&i); + return i; +} + +bool XMLElement::BoolText(bool defaultValue) const +{ + bool b = defaultValue; + QueryBoolText(&b); + return b; +} + +double XMLElement::DoubleText(double defaultValue) const +{ + double d = defaultValue; + QueryDoubleText(&d); + return d; +} + +float XMLElement::FloatText(float defaultValue) const +{ + float f = defaultValue; + QueryFloatText(&f); + return f; +} + + +XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name ) +{ + XMLAttribute* last = 0; + XMLAttribute* attrib = 0; + for( attrib = _rootAttribute; + attrib; + last = attrib, attrib = attrib->_next ) { + if ( XMLUtil::StringEqual( attrib->Name(), name ) ) { + break; + } + } + if ( !attrib ) { + attrib = CreateAttribute(); + TIXMLASSERT( attrib ); + if ( last ) { + TIXMLASSERT( last->_next == 0 ); + last->_next = attrib; + } + else { + TIXMLASSERT( _rootAttribute == 0 ); + _rootAttribute = attrib; + } + attrib->SetName( name ); + } + return attrib; +} + + +void XMLElement::DeleteAttribute( const char* name ) +{ + XMLAttribute* prev = 0; + for( XMLAttribute* a=_rootAttribute; a; a=a->_next ) { + if ( XMLUtil::StringEqual( name, a->Name() ) ) { + if ( prev ) { + prev->_next = a->_next; + } + else { + _rootAttribute = a->_next; + } + DeleteAttribute( a ); + break; + } + prev = a; + } +} + + +char* XMLElement::ParseAttributes( char* p, int* curLineNumPtr ) +{ + XMLAttribute* prevAttribute = 0; + + // Read the attributes. + while( p ) { + p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr ); + if ( !(*p) ) { + _document->SetError( XML_ERROR_PARSING_ELEMENT, _parseLineNum, "XMLElement name=%s", Name() ); + return 0; + } + + // attribute. + if (XMLUtil::IsNameStartChar( *p ) ) { + XMLAttribute* attrib = CreateAttribute(); + TIXMLASSERT( attrib ); + attrib->_parseLineNum = _document->_parseCurLineNum; + + int attrLineNum = attrib->_parseLineNum; + + p = attrib->ParseDeep( p, _document->ProcessEntities(), curLineNumPtr ); + if ( !p || Attribute( attrib->Name() ) ) { + DeleteAttribute( attrib ); + _document->SetError( XML_ERROR_PARSING_ATTRIBUTE, attrLineNum, "XMLElement name=%s", Name() ); + return 0; + } + // There is a minor bug here: if the attribute in the source xml + // document is duplicated, it will not be detected and the + // attribute will be doubly added. However, tracking the 'prevAttribute' + // avoids re-scanning the attribute list. Preferring performance for + // now, may reconsider in the future. + if ( prevAttribute ) { + TIXMLASSERT( prevAttribute->_next == 0 ); + prevAttribute->_next = attrib; + } + else { + TIXMLASSERT( _rootAttribute == 0 ); + _rootAttribute = attrib; + } + prevAttribute = attrib; + } + // end of the tag + else if ( *p == '>' ) { + ++p; + break; + } + // end of the tag + else if ( *p == '/' && *(p+1) == '>' ) { + _closingType = CLOSED; + return p+2; // done; sealed element. + } + else { + _document->SetError( XML_ERROR_PARSING_ELEMENT, _parseLineNum, 0 ); + return 0; + } + } + return p; +} + +void XMLElement::DeleteAttribute( XMLAttribute* attribute ) +{ + if ( attribute == 0 ) { + return; + } + MemPool* pool = attribute->_memPool; + attribute->~XMLAttribute(); + pool->Free( attribute ); +} + +XMLAttribute* XMLElement::CreateAttribute() +{ + TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() ); + XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute(); + TIXMLASSERT( attrib ); + attrib->_memPool = &_document->_attributePool; + attrib->_memPool->SetTracked(); + return attrib; +} + +// +// <ele></ele> +// <ele>foo<b>bar</b></ele> +// +char* XMLElement::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) +{ + // Read the element name. + p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr ); + + // The closing element is the </element> form. It is + // parsed just like a regular element then deleted from + // the DOM. + if ( *p == '/' ) { + _closingType = CLOSING; + ++p; + } + + p = _value.ParseName( p ); + if ( _value.Empty() ) { + return 0; + } + + p = ParseAttributes( p, curLineNumPtr ); + if ( !p || !*p || _closingType != OPEN ) { + return p; + } + + p = XMLNode::ParseDeep( p, parentEndTag, curLineNumPtr ); + return p; +} + + + +XMLNode* XMLElement::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLElement* element = doc->NewElement( Value() ); // fixme: this will always allocate memory. Intern? + for( const XMLAttribute* a=FirstAttribute(); a; a=a->Next() ) { + element->SetAttribute( a->Name(), a->Value() ); // fixme: this will always allocate memory. Intern? + } + return element; +} + + +bool XMLElement::ShallowEqual( const XMLNode* compare ) const +{ + TIXMLASSERT( compare ); + const XMLElement* other = compare->ToElement(); + if ( other && XMLUtil::StringEqual( other->Name(), Name() )) { + + const XMLAttribute* a=FirstAttribute(); + const XMLAttribute* b=other->FirstAttribute(); + + while ( a && b ) { + if ( !XMLUtil::StringEqual( a->Value(), b->Value() ) ) { + return false; + } + a = a->Next(); + b = b->Next(); + } + if ( a || b ) { + // different count + return false; + } + return true; + } + return false; +} + + +bool XMLElement::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + if ( visitor->VisitEnter( *this, _rootAttribute ) ) { + for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) { + if ( !node->Accept( visitor ) ) { + break; + } + } + } + return visitor->VisitExit( *this ); +} + + +// --------- XMLDocument ----------- // + +// Warning: List must match 'enum XMLError' +const char* XMLDocument::_errorNames[XML_ERROR_COUNT] = { + "XML_SUCCESS", + "XML_NO_ATTRIBUTE", + "XML_WRONG_ATTRIBUTE_TYPE", + "XML_ERROR_FILE_NOT_FOUND", + "XML_ERROR_FILE_COULD_NOT_BE_OPENED", + "XML_ERROR_FILE_READ_ERROR", + "UNUSED_XML_ERROR_ELEMENT_MISMATCH", + "XML_ERROR_PARSING_ELEMENT", + "XML_ERROR_PARSING_ATTRIBUTE", + "UNUSED_XML_ERROR_IDENTIFYING_TAG", + "XML_ERROR_PARSING_TEXT", + "XML_ERROR_PARSING_CDATA", + "XML_ERROR_PARSING_COMMENT", + "XML_ERROR_PARSING_DECLARATION", + "XML_ERROR_PARSING_UNKNOWN", + "XML_ERROR_EMPTY_DOCUMENT", + "XML_ERROR_MISMATCHED_ELEMENT", + "XML_ERROR_PARSING", + "XML_CAN_NOT_CONVERT_TEXT", + "XML_NO_TEXT_NODE" +}; + + +XMLDocument::XMLDocument( bool processEntities, Whitespace whitespaceMode ) : + XMLNode( 0 ), + _writeBOM( false ), + _processEntities( processEntities ), + _errorID(XML_SUCCESS), + _whitespaceMode( whitespaceMode ), + _errorStr(), + _errorLineNum( 0 ), + _charBuffer( 0 ), + _parseCurLineNum( 0 ), + _unlinked(), + _elementPool(), + _attributePool(), + _textPool(), + _commentPool() +{ + // avoid VC++ C4355 warning about 'this' in initializer list (C4355 is off by default in VS2012+) + _document = this; +} + + +XMLDocument::~XMLDocument() +{ + Clear(); +} + + +void XMLDocument::MarkInUse(XMLNode* node) +{ + TIXMLASSERT(node); + TIXMLASSERT(node->_parent == 0); + + for (int i = 0; i < _unlinked.Size(); ++i) { + if (node == _unlinked[i]) { + _unlinked.SwapRemove(i); + break; + } + } +} + +void XMLDocument::Clear() +{ + DeleteChildren(); + while( _unlinked.Size()) { + DeleteNode(_unlinked[0]); // Will remove from _unlinked as part of delete. + } + +#ifdef DEBUG + const bool hadError = Error(); +#endif + ClearError(); + + Aws::DeleteArray(_charBuffer); + _charBuffer = 0; + +#if 0 + _textPool.Trace( "text" ); + _elementPool.Trace( "element" ); + _commentPool.Trace( "comment" ); + _attributePool.Trace( "attribute" ); +#endif + +#ifdef DEBUG + if ( !hadError ) { + TIXMLASSERT( _elementPool.CurrentAllocs() == _elementPool.Untracked() ); + TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() ); + TIXMLASSERT( _textPool.CurrentAllocs() == _textPool.Untracked() ); + TIXMLASSERT( _commentPool.CurrentAllocs() == _commentPool.Untracked() ); + } +#endif +} + + +void XMLDocument::DeepCopy(XMLDocument* target) const +{ + TIXMLASSERT(target); + if (target == this) { + return; // technically success - a no-op. + } + + target->Clear(); + for (const XMLNode* node = this->FirstChild(); node; node = node->NextSibling()) { + target->InsertEndChild(node->DeepClone(target)); + } +} + +XMLElement* XMLDocument::NewElement( const char* name ) +{ + XMLElement* ele = CreateUnlinkedNode<XMLElement>( _elementPool ); + ele->SetName( name ); + return ele; +} + + +XMLComment* XMLDocument::NewComment( const char* str ) +{ + XMLComment* comment = CreateUnlinkedNode<XMLComment>( _commentPool ); + comment->SetValue( str ); + return comment; +} + + +XMLText* XMLDocument::NewText( const char* str ) +{ + XMLText* text = CreateUnlinkedNode<XMLText>( _textPool ); + text->SetValue( str ); + return text; +} + + +XMLDeclaration* XMLDocument::NewDeclaration( const char* str ) +{ + XMLDeclaration* dec = CreateUnlinkedNode<XMLDeclaration>( _commentPool ); + dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" ); + return dec; +} + + +XMLUnknown* XMLDocument::NewUnknown( const char* str ) +{ + XMLUnknown* unk = CreateUnlinkedNode<XMLUnknown>( _commentPool ); + unk->SetValue( str ); + return unk; +} + +static FILE* callfopen( const char* filepath, const char* mode ) +{ + TIXMLASSERT( filepath ); + TIXMLASSERT( mode ); +#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE) + FILE* fp = 0; + errno_t err = fopen_s( &fp, filepath, mode ); + if ( err ) { + return 0; + } +#else + FILE* fp = fopen( filepath, mode ); +#endif + return fp; +} + +void XMLDocument::DeleteNode( XMLNode* node ) { + TIXMLASSERT( node ); + TIXMLASSERT(node->_document == this ); + if (node->_parent) { + node->_parent->DeleteChild( node ); + } + else { + // Isn't in the tree. + // Use the parent delete. + // Also, we need to mark it tracked: we 'know' + // it was never used. + node->_memPool->SetTracked(); + // Call the static XMLNode version: + XMLNode::DeleteNode(node); + } +} + + +XMLError XMLDocument::LoadFile( const char* filename ) +{ + Clear(); + FILE* fp = callfopen( filename, "rb" ); + if ( !fp ) { + SetError( XML_ERROR_FILE_NOT_FOUND, 0, "filename=%s", filename ? filename : "<null>"); + return _errorID; + } + LoadFile( fp ); + fclose( fp ); + return _errorID; +} + +// This is likely overengineered template art to have a check that unsigned long value incremented +// by one still fits into size_t. If size_t type is larger than unsigned long type +// (x86_64-w64-mingw32 target) then the check is redundant and gcc and clang emit +// -Wtype-limits warning. This piece makes the compiler select code with a check when a check +// is useful and code with no check when a check is redundant depending on how size_t and unsigned long +// types sizes relate to each other. +template +<bool = (sizeof(unsigned long) >= sizeof(size_t))> +struct LongFitsIntoSizeTMinusOne { + static bool Fits( unsigned long value ) + { + return value < (size_t)-1; + } +}; + +template <> +struct LongFitsIntoSizeTMinusOne<false> { + static bool Fits( unsigned long ) + { + return true; + } +}; + +XMLError XMLDocument::LoadFile( FILE* fp ) +{ + Clear(); + + fseek( fp, 0, SEEK_SET ); + if ( fgetc( fp ) == EOF && ferror( fp ) != 0 ) { + SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); + return _errorID; + } + + fseek( fp, 0, SEEK_END ); + const long filelength = ftell( fp ); + fseek( fp, 0, SEEK_SET ); + if ( filelength == -1L ) { + SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); + return _errorID; + } + TIXMLASSERT( filelength >= 0 ); + + if ( !LongFitsIntoSizeTMinusOne<>::Fits( filelength ) ) { + // Cannot handle files which won't fit in buffer together with null terminator + SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); + return _errorID; + } + + if ( filelength == 0 ) { + SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); + return _errorID; + } + + const size_t size = filelength; + TIXMLASSERT( _charBuffer == 0 ); + _charBuffer = Aws::NewArray <char>(size+1, ALLOCATION_TAG); + size_t read = fread( _charBuffer, 1, size, fp ); + if ( read != size ) { + SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); + return _errorID; + } + + _charBuffer[size] = 0; + + Parse(); + return _errorID; +} + + +XMLError XMLDocument::SaveFile( const char* filename, bool compact ) +{ + FILE* fp = callfopen( filename, "w" ); + if ( !fp ) { + SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=%s", filename ? filename : "<null>"); + return _errorID; + } + SaveFile(fp, compact); + fclose( fp ); + return _errorID; +} + + +XMLError XMLDocument::SaveFile( FILE* fp, bool compact ) +{ + // Clear any error from the last save, otherwise it will get reported + // for *this* call. + ClearError(); + XMLPrinter stream( fp, compact ); + Print( &stream ); + return _errorID; +} + + +XMLError XMLDocument::Parse( const char* p, size_t len ) +{ + Clear(); + + if ( len == 0 || !p || !*p ) { + SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); + return _errorID; + } + if ( len == (size_t)(-1) ) { + len = strlen( p ); + } + TIXMLASSERT( _charBuffer == 0 ); + _charBuffer = Aws::NewArray<char>(len+1, ALLOCATION_TAG); + memcpy( _charBuffer, p, len ); + _charBuffer[len] = 0; + + Parse(); + if ( Error() ) { + // clean up now essentially dangling memory. + // and the parse fail can put objects in the + // pools that are dead and inaccessible. + DeleteChildren(); + _elementPool.Clear(); + _attributePool.Clear(); + _textPool.Clear(); + _commentPool.Clear(); + } + return _errorID; +} + + +void XMLDocument::Print( XMLPrinter* streamer ) const +{ + if ( streamer ) { + Accept( streamer ); + } + else { + XMLPrinter stdoutStreamer( stdout ); + Accept( &stdoutStreamer ); + } +} + + +void XMLDocument::SetError( XMLError error, int lineNum, const char* format, ... ) +{ + TIXMLASSERT( error >= 0 && error < XML_ERROR_COUNT ); + _errorID = error; + _errorLineNum = lineNum; + _errorStr.Reset(); + + if (format) { + size_t BUFFER_SIZE = 1000; + char* buffer = Aws::NewArray<char>(BUFFER_SIZE, ALLOCATION_TAG); + TIXML_SNPRINTF(buffer, BUFFER_SIZE, "Error=%s ErrorID=%d (0x%x) Line number=%d: ", ErrorIDToName(error), int(error), int(error), lineNum); + size_t len = strlen(buffer); + + va_list va; + va_start( va, format ); + TIXML_VSNPRINTF( buffer + len, BUFFER_SIZE - len, format, va ); + va_end( va ); + + _errorStr.SetStr(buffer); + Aws::DeleteArray(buffer); + } +} + + +/*static*/ const char* XMLDocument::ErrorIDToName(XMLError errorID) +{ + TIXMLASSERT( errorID >= 0 && errorID < XML_ERROR_COUNT ); + const char* errorName = _errorNames[errorID]; + TIXMLASSERT( errorName && errorName[0] ); + return errorName; +} + const char* XMLDocument::ErrorStr() const -{ - return _errorStr.Empty() ? "" : _errorStr.GetStr(); -} - - -void XMLDocument::PrintError() const -{ - printf("%s\n", ErrorStr()); -} - -const char* XMLDocument::ErrorName() const -{ - return ErrorIDToName(_errorID); -} - -void XMLDocument::Parse() -{ - TIXMLASSERT( NoChildren() ); // Clear() must have been called previously - TIXMLASSERT( _charBuffer ); - _parseCurLineNum = 1; - _parseLineNum = 1; - char* p = _charBuffer; - p = XMLUtil::SkipWhiteSpace( p, &_parseCurLineNum ); - p = const_cast<char*>( XMLUtil::ReadBOM( p, &_writeBOM ) ); - if ( !*p ) { - SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); - return; - } - ParseDeep(p, 0, &_parseCurLineNum ); -} - -XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) : - _elementJustOpened( false ), - _stack(), - _firstElement( true ), - _fp( file ), - _depth( depth ), - _textDepth( -1 ), - _processEntities( true ), - _compactMode( compact ), - _buffer() -{ - for( int i=0; i<ENTITY_RANGE; ++i ) { - _entityFlag[i] = false; - _restrictedEntityFlag[i] = false; - } - for( int i=0; i<NUM_ENTITIES; ++i ) { - const char entityValue = entities[i].value; - const unsigned char flagIndex = (unsigned char)entityValue; - TIXMLASSERT( flagIndex < ENTITY_RANGE ); - _entityFlag[flagIndex] = true; - } - _restrictedEntityFlag[(unsigned char)'&'] = true; - _restrictedEntityFlag[(unsigned char)'<'] = true; - _restrictedEntityFlag[(unsigned char)'>'] = true; // not required, but consistency is nice - _buffer.Push( 0 ); -} - - -void XMLPrinter::Print( const char* format, ... ) -{ - va_list va; - va_start( va, format ); - - if ( _fp ) { - vfprintf( _fp, format, va ); - } - else { - const int len = TIXML_VSCPRINTF( format, va ); - // Close out and re-start the va-args - va_end( va ); - TIXMLASSERT( len >= 0 ); - va_start( va, format ); - TIXMLASSERT( _buffer.Size() > 0 && _buffer[_buffer.Size() - 1] == 0 ); - char* p = _buffer.PushArr( len ) - 1; // back up over the null terminator. - TIXML_VSNPRINTF( p, len+1, format, va ); - } - va_end( va ); -} - - -void XMLPrinter::Write( const char* data, size_t size ) -{ - if ( _fp ) { - fwrite ( data , sizeof(char), size, _fp); - } - else { - char* p = _buffer.PushArr( static_cast<int>(size) ) - 1; // back up over the null terminator. - memcpy( p, data, size ); - p[size] = 0; - } -} - - -void XMLPrinter::Putc( char ch ) -{ - if ( _fp ) { - fputc ( ch, _fp); - } - else { - char* p = _buffer.PushArr( sizeof(char) ) - 1; // back up over the null terminator. - p[0] = ch; - p[1] = 0; - } -} - - -void XMLPrinter::PrintSpace( int depth ) -{ - for( int i=0; i<depth; ++i ) { - Write( " " ); - } -} - - -void XMLPrinter::PrintString( const char* p, bool restricted ) -{ - // Look for runs of bytes between entities to print. - const char* q = p; - - if ( _processEntities ) { - const bool* flag = restricted ? _restrictedEntityFlag : _entityFlag; - while ( *q ) { - TIXMLASSERT( p <= q ); - // Remember, char is sometimes signed. (How many times has that bitten me?) - if ( *q > 0 && *q < ENTITY_RANGE ) { - // Check for entities. If one is found, flush - // the stream up until the entity, write the - // entity, and keep looking. - if ( flag[(unsigned char)(*q)] ) { - while ( p < q ) { - const size_t delta = q - p; - const int toPrint = ( INT_MAX < delta ) ? INT_MAX : (int)delta; - Write( p, toPrint ); - p += toPrint; - } - bool entityPatternPrinted = false; - for( int i=0; i<NUM_ENTITIES; ++i ) { - if ( entities[i].value == *q ) { - Putc( '&' ); - Write( entities[i].pattern, entities[i].length ); - Putc( ';' ); - entityPatternPrinted = true; - break; - } - } - if ( !entityPatternPrinted ) { - // TIXMLASSERT( entityPatternPrinted ) causes gcc -Wunused-but-set-variable in release - TIXMLASSERT( false ); - } - ++p; - } - } - ++q; - TIXMLASSERT( p <= q ); - } - } - // Flush the remaining string. This will be the entire - // string if an entity wasn't found. - TIXMLASSERT( p <= q ); - if ( !_processEntities || ( p < q ) ) { - const size_t delta = q - p; - const int toPrint = ( INT_MAX < delta ) ? INT_MAX : (int)delta; - Write( p, toPrint ); - } -} - - -void XMLPrinter::PushHeader( bool writeBOM, bool writeDec ) -{ - if ( writeBOM ) { - static const unsigned char bom[] = { TIXML_UTF_LEAD_0, TIXML_UTF_LEAD_1, TIXML_UTF_LEAD_2, 0 }; - Write( reinterpret_cast< const char* >( bom ) ); - } - if ( writeDec ) { - PushDeclaration( "xml version=\"1.0\"" ); - } -} - - -void XMLPrinter::OpenElement( const char* name, bool compactMode ) -{ - SealElementIfJustOpened(); - _stack.Push( name ); - - if ( _textDepth < 0 && !_firstElement && !compactMode ) { - Putc( '\n' ); - } - if ( !compactMode ) { - PrintSpace( _depth ); - } - - Write ( "<" ); - Write ( name ); - - _elementJustOpened = true; - _firstElement = false; - ++_depth; -} - - -void XMLPrinter::PushAttribute( const char* name, const char* value ) -{ - TIXMLASSERT( _elementJustOpened ); - Putc ( ' ' ); - Write( name ); - Write( "=\"" ); - PrintString( value, false ); - Putc ( '\"' ); -} - - -void XMLPrinter::PushAttribute( const char* name, int v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - PushAttribute( name, buf ); -} - - -void XMLPrinter::PushAttribute( const char* name, unsigned v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - PushAttribute( name, buf ); -} - - -void XMLPrinter::PushAttribute(const char* name, int64_t v) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr(v, buf, BUF_SIZE); - PushAttribute(name, buf); -} - - -void XMLPrinter::PushAttribute( const char* name, bool v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - PushAttribute( name, buf ); -} - - -void XMLPrinter::PushAttribute( const char* name, double v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - PushAttribute( name, buf ); -} - - -void XMLPrinter::CloseElement( bool compactMode ) -{ - --_depth; - const char* name = _stack.Pop(); - - if ( _elementJustOpened ) { - Write( "/>" ); - } - else { - if ( _textDepth < 0 && !compactMode) { - Putc( '\n' ); - PrintSpace( _depth ); - } - Write ( "</" ); - Write ( name ); - Write ( ">" ); - } - - if ( _textDepth == _depth ) { - _textDepth = -1; - } - if ( _depth == 0 && !compactMode) { - Putc( '\n' ); - } - _elementJustOpened = false; -} - - -void XMLPrinter::SealElementIfJustOpened() -{ - if ( !_elementJustOpened ) { - return; - } - _elementJustOpened = false; - Putc( '>' ); -} - - -void XMLPrinter::PushText( const char* text, bool cdata ) -{ - _textDepth = _depth-1; - - SealElementIfJustOpened(); - if ( cdata ) { - Write( "<![CDATA[" ); - Write( text ); - Write( "]]>" ); - } - else { - PrintString( text, true ); - } -} - -void XMLPrinter::PushText( int64_t value ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( value, buf, BUF_SIZE ); - PushText( buf, false ); -} - -void XMLPrinter::PushText( int value ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( value, buf, BUF_SIZE ); - PushText( buf, false ); -} - - -void XMLPrinter::PushText( unsigned value ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( value, buf, BUF_SIZE ); - PushText( buf, false ); -} - - -void XMLPrinter::PushText( bool value ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( value, buf, BUF_SIZE ); - PushText( buf, false ); -} - - -void XMLPrinter::PushText( float value ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( value, buf, BUF_SIZE ); - PushText( buf, false ); -} - - -void XMLPrinter::PushText( double value ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( value, buf, BUF_SIZE ); - PushText( buf, false ); -} - - -void XMLPrinter::PushComment( const char* comment ) -{ - SealElementIfJustOpened(); - if ( _textDepth < 0 && !_firstElement && !_compactMode) { - Putc( '\n' ); - PrintSpace( _depth ); - } - _firstElement = false; - - Write( "<!--" ); - Write( comment ); - Write( "-->" ); -} - - -void XMLPrinter::PushDeclaration( const char* value ) -{ - SealElementIfJustOpened(); - if ( _textDepth < 0 && !_firstElement && !_compactMode) { - Putc( '\n' ); - PrintSpace( _depth ); - } - _firstElement = false; - - Write( "<?" ); - Write( value ); - Write( "?>" ); -} - - -void XMLPrinter::PushUnknown( const char* value ) -{ - SealElementIfJustOpened(); - if ( _textDepth < 0 && !_firstElement && !_compactMode) { - Putc( '\n' ); - PrintSpace( _depth ); - } - _firstElement = false; - - Write( "<!" ); - Write( value ); - Putc( '>' ); -} - - -bool XMLPrinter::VisitEnter( const XMLDocument& doc ) -{ - _processEntities = doc.ProcessEntities(); - if ( doc.HasBOM() ) { - PushHeader( true, false ); - } - return true; -} - - -bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute ) -{ - const XMLElement* parentElem = 0; - if ( element.Parent() ) { - parentElem = element.Parent()->ToElement(); - } - const bool compactMode = parentElem ? CompactMode( *parentElem ) : _compactMode; - OpenElement( element.Name(), compactMode ); - while ( attribute ) { - PushAttribute( attribute->Name(), attribute->Value() ); - attribute = attribute->Next(); - } - return true; -} - - -bool XMLPrinter::VisitExit( const XMLElement& element ) -{ - CloseElement( CompactMode(element) ); - return true; -} - - -bool XMLPrinter::Visit( const XMLText& text ) -{ - PushText( text.Value(), text.CData() ); - return true; -} - - -bool XMLPrinter::Visit( const XMLComment& comment ) -{ - PushComment( comment.Value() ); - return true; -} - -bool XMLPrinter::Visit( const XMLDeclaration& declaration ) -{ - PushDeclaration( declaration.Value() ); - return true; -} - - -bool XMLPrinter::Visit( const XMLUnknown& unknown ) -{ - PushUnknown( unknown.Value() ); - return true; -} - -} // namespace tinyxml2 +{ + return _errorStr.Empty() ? "" : _errorStr.GetStr(); +} + + +void XMLDocument::PrintError() const +{ + printf("%s\n", ErrorStr()); +} + +const char* XMLDocument::ErrorName() const +{ + return ErrorIDToName(_errorID); +} + +void XMLDocument::Parse() +{ + TIXMLASSERT( NoChildren() ); // Clear() must have been called previously + TIXMLASSERT( _charBuffer ); + _parseCurLineNum = 1; + _parseLineNum = 1; + char* p = _charBuffer; + p = XMLUtil::SkipWhiteSpace( p, &_parseCurLineNum ); + p = const_cast<char*>( XMLUtil::ReadBOM( p, &_writeBOM ) ); + if ( !*p ) { + SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); + return; + } + ParseDeep(p, 0, &_parseCurLineNum ); +} + +XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) : + _elementJustOpened( false ), + _stack(), + _firstElement( true ), + _fp( file ), + _depth( depth ), + _textDepth( -1 ), + _processEntities( true ), + _compactMode( compact ), + _buffer() +{ + for( int i=0; i<ENTITY_RANGE; ++i ) { + _entityFlag[i] = false; + _restrictedEntityFlag[i] = false; + } + for( int i=0; i<NUM_ENTITIES; ++i ) { + const char entityValue = entities[i].value; + const unsigned char flagIndex = (unsigned char)entityValue; + TIXMLASSERT( flagIndex < ENTITY_RANGE ); + _entityFlag[flagIndex] = true; + } + _restrictedEntityFlag[(unsigned char)'&'] = true; + _restrictedEntityFlag[(unsigned char)'<'] = true; + _restrictedEntityFlag[(unsigned char)'>'] = true; // not required, but consistency is nice + _buffer.Push( 0 ); +} + + +void XMLPrinter::Print( const char* format, ... ) +{ + va_list va; + va_start( va, format ); + + if ( _fp ) { + vfprintf( _fp, format, va ); + } + else { + const int len = TIXML_VSCPRINTF( format, va ); + // Close out and re-start the va-args + va_end( va ); + TIXMLASSERT( len >= 0 ); + va_start( va, format ); + TIXMLASSERT( _buffer.Size() > 0 && _buffer[_buffer.Size() - 1] == 0 ); + char* p = _buffer.PushArr( len ) - 1; // back up over the null terminator. + TIXML_VSNPRINTF( p, len+1, format, va ); + } + va_end( va ); +} + + +void XMLPrinter::Write( const char* data, size_t size ) +{ + if ( _fp ) { + fwrite ( data , sizeof(char), size, _fp); + } + else { + char* p = _buffer.PushArr( static_cast<int>(size) ) - 1; // back up over the null terminator. + memcpy( p, data, size ); + p[size] = 0; + } +} + + +void XMLPrinter::Putc( char ch ) +{ + if ( _fp ) { + fputc ( ch, _fp); + } + else { + char* p = _buffer.PushArr( sizeof(char) ) - 1; // back up over the null terminator. + p[0] = ch; + p[1] = 0; + } +} + + +void XMLPrinter::PrintSpace( int depth ) +{ + for( int i=0; i<depth; ++i ) { + Write( " " ); + } +} + + +void XMLPrinter::PrintString( const char* p, bool restricted ) +{ + // Look for runs of bytes between entities to print. + const char* q = p; + + if ( _processEntities ) { + const bool* flag = restricted ? _restrictedEntityFlag : _entityFlag; + while ( *q ) { + TIXMLASSERT( p <= q ); + // Remember, char is sometimes signed. (How many times has that bitten me?) + if ( *q > 0 && *q < ENTITY_RANGE ) { + // Check for entities. If one is found, flush + // the stream up until the entity, write the + // entity, and keep looking. + if ( flag[(unsigned char)(*q)] ) { + while ( p < q ) { + const size_t delta = q - p; + const int toPrint = ( INT_MAX < delta ) ? INT_MAX : (int)delta; + Write( p, toPrint ); + p += toPrint; + } + bool entityPatternPrinted = false; + for( int i=0; i<NUM_ENTITIES; ++i ) { + if ( entities[i].value == *q ) { + Putc( '&' ); + Write( entities[i].pattern, entities[i].length ); + Putc( ';' ); + entityPatternPrinted = true; + break; + } + } + if ( !entityPatternPrinted ) { + // TIXMLASSERT( entityPatternPrinted ) causes gcc -Wunused-but-set-variable in release + TIXMLASSERT( false ); + } + ++p; + } + } + ++q; + TIXMLASSERT( p <= q ); + } + } + // Flush the remaining string. This will be the entire + // string if an entity wasn't found. + TIXMLASSERT( p <= q ); + if ( !_processEntities || ( p < q ) ) { + const size_t delta = q - p; + const int toPrint = ( INT_MAX < delta ) ? INT_MAX : (int)delta; + Write( p, toPrint ); + } +} + + +void XMLPrinter::PushHeader( bool writeBOM, bool writeDec ) +{ + if ( writeBOM ) { + static const unsigned char bom[] = { TIXML_UTF_LEAD_0, TIXML_UTF_LEAD_1, TIXML_UTF_LEAD_2, 0 }; + Write( reinterpret_cast< const char* >( bom ) ); + } + if ( writeDec ) { + PushDeclaration( "xml version=\"1.0\"" ); + } +} + + +void XMLPrinter::OpenElement( const char* name, bool compactMode ) +{ + SealElementIfJustOpened(); + _stack.Push( name ); + + if ( _textDepth < 0 && !_firstElement && !compactMode ) { + Putc( '\n' ); + } + if ( !compactMode ) { + PrintSpace( _depth ); + } + + Write ( "<" ); + Write ( name ); + + _elementJustOpened = true; + _firstElement = false; + ++_depth; +} + + +void XMLPrinter::PushAttribute( const char* name, const char* value ) +{ + TIXMLASSERT( _elementJustOpened ); + Putc ( ' ' ); + Write( name ); + Write( "=\"" ); + PrintString( value, false ); + Putc ( '\"' ); +} + + +void XMLPrinter::PushAttribute( const char* name, int v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + PushAttribute( name, buf ); +} + + +void XMLPrinter::PushAttribute( const char* name, unsigned v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + PushAttribute( name, buf ); +} + + +void XMLPrinter::PushAttribute(const char* name, int64_t v) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr(v, buf, BUF_SIZE); + PushAttribute(name, buf); +} + + +void XMLPrinter::PushAttribute( const char* name, bool v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + PushAttribute( name, buf ); +} + + +void XMLPrinter::PushAttribute( const char* name, double v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + PushAttribute( name, buf ); +} + + +void XMLPrinter::CloseElement( bool compactMode ) +{ + --_depth; + const char* name = _stack.Pop(); + + if ( _elementJustOpened ) { + Write( "/>" ); + } + else { + if ( _textDepth < 0 && !compactMode) { + Putc( '\n' ); + PrintSpace( _depth ); + } + Write ( "</" ); + Write ( name ); + Write ( ">" ); + } + + if ( _textDepth == _depth ) { + _textDepth = -1; + } + if ( _depth == 0 && !compactMode) { + Putc( '\n' ); + } + _elementJustOpened = false; +} + + +void XMLPrinter::SealElementIfJustOpened() +{ + if ( !_elementJustOpened ) { + return; + } + _elementJustOpened = false; + Putc( '>' ); +} + + +void XMLPrinter::PushText( const char* text, bool cdata ) +{ + _textDepth = _depth-1; + + SealElementIfJustOpened(); + if ( cdata ) { + Write( "<![CDATA[" ); + Write( text ); + Write( "]]>" ); + } + else { + PrintString( text, true ); + } +} + +void XMLPrinter::PushText( int64_t value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + +void XMLPrinter::PushText( int value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushText( unsigned value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushText( bool value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushText( float value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushText( double value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushComment( const char* comment ) +{ + SealElementIfJustOpened(); + if ( _textDepth < 0 && !_firstElement && !_compactMode) { + Putc( '\n' ); + PrintSpace( _depth ); + } + _firstElement = false; + + Write( "<!--" ); + Write( comment ); + Write( "-->" ); +} + + +void XMLPrinter::PushDeclaration( const char* value ) +{ + SealElementIfJustOpened(); + if ( _textDepth < 0 && !_firstElement && !_compactMode) { + Putc( '\n' ); + PrintSpace( _depth ); + } + _firstElement = false; + + Write( "<?" ); + Write( value ); + Write( "?>" ); +} + + +void XMLPrinter::PushUnknown( const char* value ) +{ + SealElementIfJustOpened(); + if ( _textDepth < 0 && !_firstElement && !_compactMode) { + Putc( '\n' ); + PrintSpace( _depth ); + } + _firstElement = false; + + Write( "<!" ); + Write( value ); + Putc( '>' ); +} + + +bool XMLPrinter::VisitEnter( const XMLDocument& doc ) +{ + _processEntities = doc.ProcessEntities(); + if ( doc.HasBOM() ) { + PushHeader( true, false ); + } + return true; +} + + +bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute ) +{ + const XMLElement* parentElem = 0; + if ( element.Parent() ) { + parentElem = element.Parent()->ToElement(); + } + const bool compactMode = parentElem ? CompactMode( *parentElem ) : _compactMode; + OpenElement( element.Name(), compactMode ); + while ( attribute ) { + PushAttribute( attribute->Name(), attribute->Value() ); + attribute = attribute->Next(); + } + return true; +} + + +bool XMLPrinter::VisitExit( const XMLElement& element ) +{ + CloseElement( CompactMode(element) ); + return true; +} + + +bool XMLPrinter::Visit( const XMLText& text ) +{ + PushText( text.Value(), text.CData() ); + return true; +} + + +bool XMLPrinter::Visit( const XMLComment& comment ) +{ + PushComment( comment.Value() ); + return true; +} + +bool XMLPrinter::Visit( const XMLDeclaration& declaration ) +{ + PushDeclaration( declaration.Value() ); + return true; +} + + +bool XMLPrinter::Visit( const XMLUnknown& unknown ) +{ + PushUnknown( unknown.Value() ); + return true; +} + +} // namespace tinyxml2 } // namespace External -} // namespace Aws
\ No newline at end of file +} // namespace Aws
\ No newline at end of file diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpClient.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpClient.cpp index 8542023393..91a802c170 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpClient.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpClient.cpp @@ -2,48 +2,48 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/http/HttpClient.h> -#include <aws/core/http/HttpRequest.h> - -using namespace Aws; -using namespace Aws::Http; - -HttpClient::HttpClient() : - m_disableRequestProcessing( false ), - m_requestProcessingSignalLock(), - m_requestProcessingSignal() -{ -} - -void HttpClient::DisableRequestProcessing() + +#include <aws/core/http/HttpClient.h> +#include <aws/core/http/HttpRequest.h> + +using namespace Aws; +using namespace Aws::Http; + +HttpClient::HttpClient() : + m_disableRequestProcessing( false ), + m_requestProcessingSignalLock(), + m_requestProcessingSignal() { - m_disableRequestProcessing = true; - m_requestProcessingSignal.notify_all(); -} - -void HttpClient::EnableRequestProcessing() +} + +void HttpClient::DisableRequestProcessing() +{ + m_disableRequestProcessing = true; + m_requestProcessingSignal.notify_all(); +} + +void HttpClient::EnableRequestProcessing() +{ + m_disableRequestProcessing = false; +} + +bool HttpClient::IsRequestProcessingEnabled() const +{ + return m_disableRequestProcessing.load() == false; +} + +void HttpClient::RetryRequestSleep(std::chrono::milliseconds sleepTime) { - m_disableRequestProcessing = false; -} - -bool HttpClient::IsRequestProcessingEnabled() const + std::unique_lock< std::mutex > signalLocker(m_requestProcessingSignalLock); + m_requestProcessingSignal.wait_for(signalLocker, sleepTime, [this](){ return m_disableRequestProcessing.load() == true; }); +} + +bool HttpClient::ContinueRequest(const Aws::Http::HttpRequest& request) const { - return m_disableRequestProcessing.load() == false; -} - -void HttpClient::RetryRequestSleep(std::chrono::milliseconds sleepTime) -{ - std::unique_lock< std::mutex > signalLocker(m_requestProcessingSignalLock); - m_requestProcessingSignal.wait_for(signalLocker, sleepTime, [this](){ return m_disableRequestProcessing.load() == true; }); -} - -bool HttpClient::ContinueRequest(const Aws::Http::HttpRequest& request) const -{ - if (request.GetContinueRequestHandler()) - { - return request.GetContinueRequestHandler()(&request); - } - - return true; -} + if (request.GetContinueRequestHandler()) + { + return request.GetContinueRequestHandler()(&request); + } + + return true; +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpClientFactory.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpClientFactory.cpp index a556e39a5d..72287b1403 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpClientFactory.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpClientFactory.cpp @@ -3,201 +3,201 @@ * SPDX-License-Identifier: Apache-2.0. */ -#include <aws/core/http/HttpClientFactory.h> - -#if ENABLE_CURL_CLIENT -#include <aws/core/http/curl/CurlHttpClient.h> -#include <signal.h> - -#elif ENABLE_WINDOWS_CLIENT -#include <aws/core/client/ClientConfiguration.h> -#if ENABLE_WINDOWS_IXML_HTTP_REQUEST_2_CLIENT -#error #include <aws/core/http/windows/IXmlHttpRequest2HttpClient.h> -#if BYPASS_DEFAULT_PROXY -#error #include <aws/core/http/windows/WinHttpSyncHttpClient.h> -#endif -#else -#error #include <aws/core/http/windows/WinINetSyncHttpClient.h> -#error #include <aws/core/http/windows/WinHttpSyncHttpClient.h> -#endif -#endif - -#include <aws/core/http/standard/StandardHttpRequest.h> -#include <aws/core/utils/logging/LogMacros.h> -#include <cassert> - -using namespace Aws::Client; -using namespace Aws::Http; -using namespace Aws::Utils::Logging; - -namespace Aws -{ - namespace Http - { +#include <aws/core/http/HttpClientFactory.h> + +#if ENABLE_CURL_CLIENT +#include <aws/core/http/curl/CurlHttpClient.h> +#include <signal.h> + +#elif ENABLE_WINDOWS_CLIENT +#include <aws/core/client/ClientConfiguration.h> +#if ENABLE_WINDOWS_IXML_HTTP_REQUEST_2_CLIENT +#error #include <aws/core/http/windows/IXmlHttpRequest2HttpClient.h> +#if BYPASS_DEFAULT_PROXY +#error #include <aws/core/http/windows/WinHttpSyncHttpClient.h> +#endif +#else +#error #include <aws/core/http/windows/WinINetSyncHttpClient.h> +#error #include <aws/core/http/windows/WinHttpSyncHttpClient.h> +#endif +#endif + +#include <aws/core/http/standard/StandardHttpRequest.h> +#include <aws/core/utils/logging/LogMacros.h> +#include <cassert> + +using namespace Aws::Client; +using namespace Aws::Http; +using namespace Aws::Utils::Logging; + +namespace Aws +{ + namespace Http + { static std::shared_ptr<HttpClientFactory>& GetHttpClientFactory() { static std::shared_ptr<HttpClientFactory> s_HttpClientFactory(nullptr); return s_HttpClientFactory; } - static bool s_InitCleanupCurlFlag(false); - static bool s_InstallSigPipeHandler(false); - - static const char* HTTP_CLIENT_FACTORY_ALLOCATION_TAG = "HttpClientFactory"; - -#if ENABLE_CURL_CLIENT && !defined(_WIN32) - static void LogAndSwallowHandler(int signal) - { - switch(signal) - { - case SIGPIPE: - AWS_LOGSTREAM_ERROR(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "Received a SIGPIPE error"); - break; - default: - AWS_LOGSTREAM_ERROR(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "Unhandled system SIGNAL error" << signal); - } - } -#endif - - class DefaultHttpClientFactory : public HttpClientFactory - { - std::shared_ptr<HttpClient> CreateHttpClient(const ClientConfiguration& clientConfiguration) const override - { - // Figure out whether the selected option is available but fail gracefully and return a default of some type if not - // Windows clients: Http and Inet are always options, Curl MIGHT be an option if USE_CURL_CLIENT is on, and http is "default" - // Other clients: Curl is your default -#if ENABLE_WINDOWS_CLIENT -#if ENABLE_WINDOWS_IXML_HTTP_REQUEST_2_CLIENT -#if BYPASS_DEFAULT_PROXY - switch (clientConfiguration.httpLibOverride) - { - case TransferLibType::WIN_HTTP_CLIENT: - AWS_LOGSTREAM_INFO(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "Creating WinHTTP http client."); - return Aws::MakeShared<WinHttpSyncHttpClient>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, clientConfiguration); - case TransferLibType::WIN_INET_CLIENT: - AWS_LOGSTREAM_WARN(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "WinINet http client is not supported with the current build configuration."); - // fall-through - default: - AWS_LOGSTREAM_INFO(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "Creating IXMLHttpRequest http client."); - return Aws::MakeShared<IXmlHttpRequest2HttpClient>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, clientConfiguration); - } -#else - return Aws::MakeShared<IXmlHttpRequest2HttpClient>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, clientConfiguration); -#endif // BYPASS_DEFAULT_PROXY -#else - switch (clientConfiguration.httpLibOverride) - { - case TransferLibType::WIN_INET_CLIENT: - return Aws::MakeShared<WinINetSyncHttpClient>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, clientConfiguration); - - default: - return Aws::MakeShared<WinHttpSyncHttpClient>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, clientConfiguration); - } -#endif // ENABLE_WINDOWS_IXML_HTTP_REQUEST_2_CLIENT -#elif ENABLE_CURL_CLIENT - return Aws::MakeShared<CurlHttpClient>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, clientConfiguration); -#else - // When neither of these clients is enabled, gcc gives a warning (converted - // to error by -Werror) about the unused clientConfiguration parameter. We - // prevent that warning with AWS_UNREFERENCED_PARAM. - AWS_UNREFERENCED_PARAM(clientConfiguration); + static bool s_InitCleanupCurlFlag(false); + static bool s_InstallSigPipeHandler(false); + + static const char* HTTP_CLIENT_FACTORY_ALLOCATION_TAG = "HttpClientFactory"; + +#if ENABLE_CURL_CLIENT && !defined(_WIN32) + static void LogAndSwallowHandler(int signal) + { + switch(signal) + { + case SIGPIPE: + AWS_LOGSTREAM_ERROR(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "Received a SIGPIPE error"); + break; + default: + AWS_LOGSTREAM_ERROR(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "Unhandled system SIGNAL error" << signal); + } + } +#endif + + class DefaultHttpClientFactory : public HttpClientFactory + { + std::shared_ptr<HttpClient> CreateHttpClient(const ClientConfiguration& clientConfiguration) const override + { + // Figure out whether the selected option is available but fail gracefully and return a default of some type if not + // Windows clients: Http and Inet are always options, Curl MIGHT be an option if USE_CURL_CLIENT is on, and http is "default" + // Other clients: Curl is your default +#if ENABLE_WINDOWS_CLIENT +#if ENABLE_WINDOWS_IXML_HTTP_REQUEST_2_CLIENT +#if BYPASS_DEFAULT_PROXY + switch (clientConfiguration.httpLibOverride) + { + case TransferLibType::WIN_HTTP_CLIENT: + AWS_LOGSTREAM_INFO(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "Creating WinHTTP http client."); + return Aws::MakeShared<WinHttpSyncHttpClient>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, clientConfiguration); + case TransferLibType::WIN_INET_CLIENT: + AWS_LOGSTREAM_WARN(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "WinINet http client is not supported with the current build configuration."); + // fall-through + default: + AWS_LOGSTREAM_INFO(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "Creating IXMLHttpRequest http client."); + return Aws::MakeShared<IXmlHttpRequest2HttpClient>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, clientConfiguration); + } +#else + return Aws::MakeShared<IXmlHttpRequest2HttpClient>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, clientConfiguration); +#endif // BYPASS_DEFAULT_PROXY +#else + switch (clientConfiguration.httpLibOverride) + { + case TransferLibType::WIN_INET_CLIENT: + return Aws::MakeShared<WinINetSyncHttpClient>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, clientConfiguration); + + default: + return Aws::MakeShared<WinHttpSyncHttpClient>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, clientConfiguration); + } +#endif // ENABLE_WINDOWS_IXML_HTTP_REQUEST_2_CLIENT +#elif ENABLE_CURL_CLIENT + return Aws::MakeShared<CurlHttpClient>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, clientConfiguration); +#else + // When neither of these clients is enabled, gcc gives a warning (converted + // to error by -Werror) about the unused clientConfiguration parameter. We + // prevent that warning with AWS_UNREFERENCED_PARAM. + AWS_UNREFERENCED_PARAM(clientConfiguration); AWS_LOGSTREAM_WARN(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "SDK was built without an Http implementation, default http client factory can't create an Http client instance."); - return nullptr; -#endif - } - - std::shared_ptr<HttpRequest> CreateHttpRequest(const Aws::String &uri, HttpMethod method, - const Aws::IOStreamFactory &streamFactory) const override - { - return CreateHttpRequest(URI(uri), method, streamFactory); - } - - std::shared_ptr<HttpRequest> CreateHttpRequest(const URI& uri, HttpMethod method, const Aws::IOStreamFactory& streamFactory) const override - { - auto request = Aws::MakeShared<Standard::StandardHttpRequest>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, uri, method); - request->SetResponseStreamFactory(streamFactory); - - return request; - } - - void InitStaticState() override - { -#if ENABLE_CURL_CLIENT - if(s_InitCleanupCurlFlag) - { - CurlHttpClient::InitGlobalState(); - } -#if !defined (_WIN32) - if(s_InstallSigPipeHandler) - { - ::signal(SIGPIPE, LogAndSwallowHandler); - } -#endif -#elif ENABLE_WINDOWS_IXML_HTTP_REQUEST_2_CLIENT - IXmlHttpRequest2HttpClient::InitCOM(); -#endif - } - - virtual void CleanupStaticState() override - { -#if ENABLE_CURL_CLIENT - if(s_InitCleanupCurlFlag) - { - CurlHttpClient::CleanupGlobalState(); - } -#endif - } - }; - - void SetInitCleanupCurlFlag(bool initCleanupFlag) - { - s_InitCleanupCurlFlag = initCleanupFlag; - } - - void SetInstallSigPipeHandlerFlag(bool install) - { - s_InstallSigPipeHandler = install; - } - - void InitHttp() - { + return nullptr; +#endif + } + + std::shared_ptr<HttpRequest> CreateHttpRequest(const Aws::String &uri, HttpMethod method, + const Aws::IOStreamFactory &streamFactory) const override + { + return CreateHttpRequest(URI(uri), method, streamFactory); + } + + std::shared_ptr<HttpRequest> CreateHttpRequest(const URI& uri, HttpMethod method, const Aws::IOStreamFactory& streamFactory) const override + { + auto request = Aws::MakeShared<Standard::StandardHttpRequest>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, uri, method); + request->SetResponseStreamFactory(streamFactory); + + return request; + } + + void InitStaticState() override + { +#if ENABLE_CURL_CLIENT + if(s_InitCleanupCurlFlag) + { + CurlHttpClient::InitGlobalState(); + } +#if !defined (_WIN32) + if(s_InstallSigPipeHandler) + { + ::signal(SIGPIPE, LogAndSwallowHandler); + } +#endif +#elif ENABLE_WINDOWS_IXML_HTTP_REQUEST_2_CLIENT + IXmlHttpRequest2HttpClient::InitCOM(); +#endif + } + + virtual void CleanupStaticState() override + { +#if ENABLE_CURL_CLIENT + if(s_InitCleanupCurlFlag) + { + CurlHttpClient::CleanupGlobalState(); + } +#endif + } + }; + + void SetInitCleanupCurlFlag(bool initCleanupFlag) + { + s_InitCleanupCurlFlag = initCleanupFlag; + } + + void SetInstallSigPipeHandlerFlag(bool install) + { + s_InstallSigPipeHandler = install; + } + + void InitHttp() + { if(!GetHttpClientFactory()) - { + { GetHttpClientFactory() = Aws::MakeShared<DefaultHttpClientFactory>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG); - } + } GetHttpClientFactory()->InitStaticState(); - } - - void CleanupHttp() - { + } + + void CleanupHttp() + { if(GetHttpClientFactory()) - { + { GetHttpClientFactory()->CleanupStaticState(); GetHttpClientFactory() = nullptr; - } - } - - void SetHttpClientFactory(const std::shared_ptr<HttpClientFactory>& factory) - { - CleanupHttp(); + } + } + + void SetHttpClientFactory(const std::shared_ptr<HttpClientFactory>& factory) + { + CleanupHttp(); GetHttpClientFactory() = factory; - } - - std::shared_ptr<HttpClient> CreateHttpClient(const Aws::Client::ClientConfiguration& clientConfiguration) - { + } + + std::shared_ptr<HttpClient> CreateHttpClient(const Aws::Client::ClientConfiguration& clientConfiguration) + { assert(GetHttpClientFactory()); return GetHttpClientFactory()->CreateHttpClient(clientConfiguration); - } - - std::shared_ptr<HttpRequest> CreateHttpRequest(const Aws::String& uri, HttpMethod method, const Aws::IOStreamFactory& streamFactory) - { + } + + std::shared_ptr<HttpRequest> CreateHttpRequest(const Aws::String& uri, HttpMethod method, const Aws::IOStreamFactory& streamFactory) + { assert(GetHttpClientFactory()); return GetHttpClientFactory()->CreateHttpRequest(uri, method, streamFactory); - } - - std::shared_ptr<HttpRequest> CreateHttpRequest(const URI& uri, HttpMethod method, const Aws::IOStreamFactory& streamFactory) - { + } + + std::shared_ptr<HttpRequest> CreateHttpRequest(const URI& uri, HttpMethod method, const Aws::IOStreamFactory& streamFactory) + { assert(GetHttpClientFactory()); return GetHttpClientFactory()->CreateHttpRequest(uri, method, streamFactory); - } - } -} + } + } +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpRequest.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpRequest.cpp index 95cb626c22..2e20ba2ff5 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpRequest.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpRequest.cpp @@ -2,14 +2,14 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/http/HttpRequest.h> - -namespace Aws -{ -namespace Http -{ - + +#include <aws/core/http/HttpRequest.h> + +namespace Aws +{ +namespace Http +{ + const char DATE_HEADER[] = "date"; const char AWS_DATE_HEADER[] = "X-Amz-Date"; const char AWS_SECURITY_TOKEN[] = "X-Amz-Security-Token"; @@ -32,9 +32,9 @@ const char API_VERSION_HEADER[] = "x-amz-api-version"; const char SDK_INVOCATION_ID_HEADER[] = "amz-sdk-invocation-id"; const char SDK_REQUEST_HEADER[] = "amz-sdk-request"; const char CHUNKED_VALUE[] = "chunked"; - -} // Http -} // Aws - - - + +} // Http +} // Aws + + + diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpTypes.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpTypes.cpp index 4d313e52f3..02407c16d1 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpTypes.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpTypes.cpp @@ -2,41 +2,41 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/http/HttpTypes.h> -#include <cassert> - -using namespace Aws::Http; - -namespace Aws -{ -namespace Http -{ - -namespace HttpMethodMapper -{ -const char* GetNameForHttpMethod(HttpMethod httpMethod) -{ - switch (httpMethod) - { - case HttpMethod::HTTP_GET: - return "GET"; - case HttpMethod::HTTP_POST: - return "POST"; - case HttpMethod::HTTP_DELETE: - return "DELETE"; - case HttpMethod::HTTP_PUT: - return "PUT"; - case HttpMethod::HTTP_HEAD: - return "HEAD"; - case HttpMethod::HTTP_PATCH: - return "PATCH"; - default: - assert(0); - return "GET"; - } -} - -} // namespace HttpMethodMapper -} // namespace Http -} // namespace Aws + +#include <aws/core/http/HttpTypes.h> +#include <cassert> + +using namespace Aws::Http; + +namespace Aws +{ +namespace Http +{ + +namespace HttpMethodMapper +{ +const char* GetNameForHttpMethod(HttpMethod httpMethod) +{ + switch (httpMethod) + { + case HttpMethod::HTTP_GET: + return "GET"; + case HttpMethod::HTTP_POST: + return "POST"; + case HttpMethod::HTTP_DELETE: + return "DELETE"; + case HttpMethod::HTTP_PUT: + return "PUT"; + case HttpMethod::HTTP_HEAD: + return "HEAD"; + case HttpMethod::HTTP_PATCH: + return "PATCH"; + default: + assert(0); + return "GET"; + } +} + +} // namespace HttpMethodMapper +} // namespace Http +} // namespace Aws diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/Scheme.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/Scheme.cpp index 5dcea06aab..d75bb4a66d 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/Scheme.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/Scheme.cpp @@ -2,53 +2,53 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/http/Scheme.h> -#include <aws/core/utils/memory/stl/AWSString.h> -#include <aws/core/utils/StringUtils.h> - -using namespace Aws::Http; -using namespace Aws::Utils; - -namespace Aws -{ -namespace Http -{ -namespace SchemeMapper -{ - - const char* ToString(Scheme scheme) - { - switch (scheme) - { - case Scheme::HTTP: - return "http"; - case Scheme::HTTPS: - return "https"; - default: - return "http"; - } - } - - Scheme FromString(const char* name) - { - Aws::String trimmedString = StringUtils::Trim(name); - Aws::String loweredTrimmedString = StringUtils::ToLower(trimmedString.c_str()); - - if (loweredTrimmedString == "http") - { - return Scheme::HTTP; - } - //this branch is technically unneeded, but it is here so we don't have a subtle bug - //creep in as we extend this enum. - else if (loweredTrimmedString == "https") - { - return Scheme::HTTPS; - } - - return Scheme::HTTPS; - } - -} // namespace SchemeMapper -} // namespace Http -} // namespace Aws + +#include <aws/core/http/Scheme.h> +#include <aws/core/utils/memory/stl/AWSString.h> +#include <aws/core/utils/StringUtils.h> + +using namespace Aws::Http; +using namespace Aws::Utils; + +namespace Aws +{ +namespace Http +{ +namespace SchemeMapper +{ + + const char* ToString(Scheme scheme) + { + switch (scheme) + { + case Scheme::HTTP: + return "http"; + case Scheme::HTTPS: + return "https"; + default: + return "http"; + } + } + + Scheme FromString(const char* name) + { + Aws::String trimmedString = StringUtils::Trim(name); + Aws::String loweredTrimmedString = StringUtils::ToLower(trimmedString.c_str()); + + if (loweredTrimmedString == "http") + { + return Scheme::HTTP; + } + //this branch is technically unneeded, but it is here so we don't have a subtle bug + //creep in as we extend this enum. + else if (loweredTrimmedString == "https") + { + return Scheme::HTTPS; + } + + return Scheme::HTTPS; + } + +} // namespace SchemeMapper +} // namespace Http +} // namespace Aws diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/URI.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/URI.cpp index a2239df54b..e5a8e4cade 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/URI.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/URI.cpp @@ -2,170 +2,170 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/http/URI.h> - -#include <aws/core/utils/StringUtils.h> -#include <aws/core/utils/memory/stl/AWSStringStream.h> -#include <aws/core/utils/memory/stl/AWSSet.h> - -#include <cstdlib> -#include <cctype> -#include <cassert> -#include <algorithm> -#include <iomanip> - -using namespace Aws::Http; -using namespace Aws::Utils; - -namespace Aws -{ -namespace Http -{ - -const char* SEPARATOR = "://"; - -} // namespace Http -} // namespace Aws - -URI::URI() : m_scheme(Scheme::HTTP), m_port(HTTP_DEFAULT_PORT) -{ -} - -URI::URI(const Aws::String& uri) : m_scheme(Scheme::HTTP), m_port(HTTP_DEFAULT_PORT) -{ - ParseURIParts(uri); -} - -URI::URI(const char* uri) : m_scheme(Scheme::HTTP), m_port(HTTP_DEFAULT_PORT) -{ - ParseURIParts(uri); -} - -URI& URI::operator =(const Aws::String& uri) -{ - this->ParseURIParts(uri); - return *this; -} - -URI& URI::operator =(const char* uri) -{ - this->ParseURIParts(uri); - return *this; -} - -bool URI::operator ==(const URI& other) const -{ - return CompareURIParts(other); -} - -bool URI::operator ==(const Aws::String& other) const -{ - return CompareURIParts(other); -} - -bool URI::operator ==(const char* other) const -{ - return CompareURIParts(other); -} - -bool URI::operator !=(const URI& other) const -{ - return !(*this == other); -} - -bool URI::operator !=(const Aws::String& other) const -{ - return !(*this == other); -} - -bool URI::operator !=(const char* other) const -{ - return !(*this == other); -} - -void URI::SetScheme(Scheme value) -{ - assert(value == Scheme::HTTP || value == Scheme::HTTPS); - - if (value == Scheme::HTTP) - { - m_port = m_port == HTTPS_DEFAULT_PORT || m_port == 0 ? HTTP_DEFAULT_PORT : m_port; - m_scheme = value; - } - else if (value == Scheme::HTTPS) - { - m_port = m_port == HTTP_DEFAULT_PORT || m_port == 0 ? HTTPS_DEFAULT_PORT : m_port; - m_scheme = value; - } -} - -Aws::String URI::URLEncodePathRFC3986(const Aws::String& path) -{ - if(path.empty()) - { - return path; - } - - const Aws::Vector<Aws::String> pathParts = StringUtils::Split(path, '/'); - Aws::StringStream ss; - ss << std::hex << std::uppercase; - - // escape characters appearing in a URL path according to RFC 3986 - for (const auto& segment : pathParts) - { - ss << '/'; - for(unsigned char c : segment) // alnum results in UB if the value of c is not unsigned char & is not EOF - { + +#include <aws/core/http/URI.h> + +#include <aws/core/utils/StringUtils.h> +#include <aws/core/utils/memory/stl/AWSStringStream.h> +#include <aws/core/utils/memory/stl/AWSSet.h> + +#include <cstdlib> +#include <cctype> +#include <cassert> +#include <algorithm> +#include <iomanip> + +using namespace Aws::Http; +using namespace Aws::Utils; + +namespace Aws +{ +namespace Http +{ + +const char* SEPARATOR = "://"; + +} // namespace Http +} // namespace Aws + +URI::URI() : m_scheme(Scheme::HTTP), m_port(HTTP_DEFAULT_PORT) +{ +} + +URI::URI(const Aws::String& uri) : m_scheme(Scheme::HTTP), m_port(HTTP_DEFAULT_PORT) +{ + ParseURIParts(uri); +} + +URI::URI(const char* uri) : m_scheme(Scheme::HTTP), m_port(HTTP_DEFAULT_PORT) +{ + ParseURIParts(uri); +} + +URI& URI::operator =(const Aws::String& uri) +{ + this->ParseURIParts(uri); + return *this; +} + +URI& URI::operator =(const char* uri) +{ + this->ParseURIParts(uri); + return *this; +} + +bool URI::operator ==(const URI& other) const +{ + return CompareURIParts(other); +} + +bool URI::operator ==(const Aws::String& other) const +{ + return CompareURIParts(other); +} + +bool URI::operator ==(const char* other) const +{ + return CompareURIParts(other); +} + +bool URI::operator !=(const URI& other) const +{ + return !(*this == other); +} + +bool URI::operator !=(const Aws::String& other) const +{ + return !(*this == other); +} + +bool URI::operator !=(const char* other) const +{ + return !(*this == other); +} + +void URI::SetScheme(Scheme value) +{ + assert(value == Scheme::HTTP || value == Scheme::HTTPS); + + if (value == Scheme::HTTP) + { + m_port = m_port == HTTPS_DEFAULT_PORT || m_port == 0 ? HTTP_DEFAULT_PORT : m_port; + m_scheme = value; + } + else if (value == Scheme::HTTPS) + { + m_port = m_port == HTTP_DEFAULT_PORT || m_port == 0 ? HTTPS_DEFAULT_PORT : m_port; + m_scheme = value; + } +} + +Aws::String URI::URLEncodePathRFC3986(const Aws::String& path) +{ + if(path.empty()) + { + return path; + } + + const Aws::Vector<Aws::String> pathParts = StringUtils::Split(path, '/'); + Aws::StringStream ss; + ss << std::hex << std::uppercase; + + // escape characters appearing in a URL path according to RFC 3986 + for (const auto& segment : pathParts) + { + ss << '/'; + for(unsigned char c : segment) // alnum results in UB if the value of c is not unsigned char & is not EOF + { // §2.3 unreserved characters if (StringUtils::IsAlnum(c)) - { - ss << c; - continue; - } - switch(c) - { - // §2.3 unreserved characters - case '-': case '_': case '.': case '~': - // The path section of the URL allow reserved characters to appear unescaped - // RFC 3986 §2.2 Reserved characters - // NOTE: this implementation does not accurately implement the RFC on purpose to accommodate for - // discrepancies in the implementations of URL encoding between AWS services for legacy reasons. + { + ss << c; + continue; + } + switch(c) + { + // §2.3 unreserved characters + case '-': case '_': case '.': case '~': + // The path section of the URL allow reserved characters to appear unescaped + // RFC 3986 §2.2 Reserved characters + // NOTE: this implementation does not accurately implement the RFC on purpose to accommodate for + // discrepancies in the implementations of URL encoding between AWS services for legacy reasons. case '$': case '&': case ',': case ':': case '=': case '@': - ss << c; - break; - default: + ss << c; + break; + default: ss << '%' << std::setfill('0') << std::setw(2) << (int)((unsigned char)c) << std::setw(0); - } - } - } - - //if the last character was also a slash, then add that back here. - if (path.back() == '/') - { - ss << '/'; - } - - return ss.str(); -} - -Aws::String URI::URLEncodePath(const Aws::String& path) -{ - Aws::Vector<Aws::String> pathParts = StringUtils::Split(path, '/'); - Aws::StringStream ss; - - for (Aws::Vector<Aws::String>::iterator iter = pathParts.begin(); iter != pathParts.end(); ++iter) - { - ss << '/' << StringUtils::URLEncode(iter->c_str()); - } - - //if the last character was also a slash, then add that back here. + } + } + } + + //if the last character was also a slash, then add that back here. + if (path.back() == '/') + { + ss << '/'; + } + + return ss.str(); +} + +Aws::String URI::URLEncodePath(const Aws::String& path) +{ + Aws::Vector<Aws::String> pathParts = StringUtils::Split(path, '/'); + Aws::StringStream ss; + + for (Aws::Vector<Aws::String>::iterator iter = pathParts.begin(); iter != pathParts.end(); ++iter) + { + ss << '/' << StringUtils::URLEncode(iter->c_str()); + } + + //if the last character was also a slash, then add that back here. if (path.length() > 0 && path[path.length() - 1] == '/') - { - ss << '/'; - } - + { + ss << '/'; + } + if (path.length() > 0 && path[0] != '/') { return ss.str().substr(1); @@ -174,9 +174,9 @@ Aws::String URI::URLEncodePath(const Aws::String& path) { return ss.str(); } -} - -void URI::SetPath(const Aws::String& value) +} + +void URI::SetPath(const Aws::String& value) { const Aws::Vector<Aws::String> pathParts = StringUtils::Split(value, '/'); Aws::String path; @@ -193,318 +193,318 @@ void URI::SetPath(const Aws::String& value) path.push_back('/'); } m_path = std::move(path); -} - -//ugh, this isn't even part of the canonicalization spec. It is part of how our services have implemented their signers though.... +} + +//ugh, this isn't even part of the canonicalization spec. It is part of how our services have implemented their signers though.... //it doesn't really hurt anything to reorder it though, so go ahead and sort the values for parameters with the same key -void InsertValueOrderedParameter(QueryStringParameterCollection& queryParams, const Aws::String& key, const Aws::String& value) -{ - auto entriesAtKey = queryParams.equal_range(key); - for (auto& entry = entriesAtKey.first; entry != entriesAtKey.second; ++entry) - { - if (entry->second > value) - { +void InsertValueOrderedParameter(QueryStringParameterCollection& queryParams, const Aws::String& key, const Aws::String& value) +{ + auto entriesAtKey = queryParams.equal_range(key); + for (auto& entry = entriesAtKey.first; entry != entriesAtKey.second; ++entry) + { + if (entry->second > value) + { queryParams.emplace_hint(entry, key, value); - return; - } - } - - queryParams.emplace(key, value); -} - -QueryStringParameterCollection URI::GetQueryStringParameters(bool decode) const -{ - Aws::String queryString = GetQueryString(); - - QueryStringParameterCollection parameterCollection; - - //if we actually have a query string - if (queryString.size() > 0) - { - size_t currentPos = 1, locationOfNextDelimiter = 1; - - //while we have params left to parse - while (currentPos < queryString.size()) - { - //find next key/value pair - locationOfNextDelimiter = queryString.find('&', currentPos); - - Aws::String keyValuePair; - - //if this isn't the last parameter - if (locationOfNextDelimiter != Aws::String::npos) - { - keyValuePair = queryString.substr(currentPos, locationOfNextDelimiter - currentPos); - } - //if it is the last parameter - else - { - keyValuePair = queryString.substr(currentPos); - } - - //split on = - size_t locationOfEquals = keyValuePair.find('='); - Aws::String key = keyValuePair.substr(0, locationOfEquals); - Aws::String value = keyValuePair.substr(locationOfEquals + 1); - - if(decode) - { - InsertValueOrderedParameter(parameterCollection, StringUtils::URLDecode(key.c_str()), StringUtils::URLDecode(value.c_str())); - } - else - { - InsertValueOrderedParameter(parameterCollection, key, value); - } - - currentPos += keyValuePair.size() + 1; - } - } - - return parameterCollection; -} - -void URI::CanonicalizeQueryString() -{ - QueryStringParameterCollection sortedParameters = GetQueryStringParameters(false); - Aws::StringStream queryStringStream; - - bool first = true; - - if(sortedParameters.size() > 0) - { - queryStringStream << "?"; - } - + return; + } + } + + queryParams.emplace(key, value); +} + +QueryStringParameterCollection URI::GetQueryStringParameters(bool decode) const +{ + Aws::String queryString = GetQueryString(); + + QueryStringParameterCollection parameterCollection; + + //if we actually have a query string + if (queryString.size() > 0) + { + size_t currentPos = 1, locationOfNextDelimiter = 1; + + //while we have params left to parse + while (currentPos < queryString.size()) + { + //find next key/value pair + locationOfNextDelimiter = queryString.find('&', currentPos); + + Aws::String keyValuePair; + + //if this isn't the last parameter + if (locationOfNextDelimiter != Aws::String::npos) + { + keyValuePair = queryString.substr(currentPos, locationOfNextDelimiter - currentPos); + } + //if it is the last parameter + else + { + keyValuePair = queryString.substr(currentPos); + } + + //split on = + size_t locationOfEquals = keyValuePair.find('='); + Aws::String key = keyValuePair.substr(0, locationOfEquals); + Aws::String value = keyValuePair.substr(locationOfEquals + 1); + + if(decode) + { + InsertValueOrderedParameter(parameterCollection, StringUtils::URLDecode(key.c_str()), StringUtils::URLDecode(value.c_str())); + } + else + { + InsertValueOrderedParameter(parameterCollection, key, value); + } + + currentPos += keyValuePair.size() + 1; + } + } + + return parameterCollection; +} + +void URI::CanonicalizeQueryString() +{ + QueryStringParameterCollection sortedParameters = GetQueryStringParameters(false); + Aws::StringStream queryStringStream; + + bool first = true; + + if(sortedParameters.size() > 0) + { + queryStringStream << "?"; + } + if(m_queryString.find('=') != std::string::npos) - { - for (QueryStringParameterCollection::iterator iter = sortedParameters.begin(); - iter != sortedParameters.end(); ++iter) - { - if (!first) - { - queryStringStream << "&"; - } - - first = false; - queryStringStream << iter->first.c_str() << "=" << iter->second.c_str(); - } - - m_queryString = queryStringStream.str(); - } -} - -void URI::AddQueryStringParameter(const char* key, const Aws::String& value) -{ - if (m_queryString.size() <= 0) - { - m_queryString.append("?"); - } - else - { - m_queryString.append("&"); - } - - m_queryString.append(StringUtils::URLEncode(key) + "=" + StringUtils::URLEncode(value.c_str())); -} - -void URI::AddQueryStringParameter(const Aws::Map<Aws::String, Aws::String>& queryStringPairs) -{ - for(const auto& entry: queryStringPairs) - { - AddQueryStringParameter(entry.first.c_str(), entry.second); - } -} - -void URI::SetQueryString(const Aws::String& str) -{ - m_queryString = ""; - - if (str.empty()) return; - - if (str.front() != '?') - { - m_queryString.append("?").append(str); - } - else - { - m_queryString = str; - } -} - -Aws::String URI::GetURIString(bool includeQueryString) const -{ - assert(m_authority.size() > 0); - - Aws::StringStream ss; - ss << SchemeMapper::ToString(m_scheme) << SEPARATOR << m_authority; - - if (m_scheme == Scheme::HTTP && m_port != HTTP_DEFAULT_PORT) - { - ss << ":" << m_port; - } - else if (m_scheme == Scheme::HTTPS && m_port != HTTPS_DEFAULT_PORT) - { - ss << ":" << m_port; - } - - if(m_path != "/") - { - ss << URLEncodePathRFC3986(m_path); - } - - if(includeQueryString) - { - ss << m_queryString; - } - - return ss.str(); -} - -void URI::ParseURIParts(const Aws::String& uri) -{ - ExtractAndSetScheme(uri); - ExtractAndSetAuthority(uri); - ExtractAndSetPort(uri); - ExtractAndSetPath(uri); - ExtractAndSetQueryString(uri); -} - -void URI::ExtractAndSetScheme(const Aws::String& uri) -{ - size_t posOfSeparator = uri.find(SEPARATOR); - - if (posOfSeparator != Aws::String::npos) - { - Aws::String schemePortion = uri.substr(0, posOfSeparator); - SetScheme(SchemeMapper::FromString(schemePortion.c_str())); - } - else - { - SetScheme(Scheme::HTTP); - } -} - -void URI::ExtractAndSetAuthority(const Aws::String& uri) -{ - size_t authorityStart = uri.find(SEPARATOR); - - if (authorityStart == Aws::String::npos) - { - authorityStart = 0; - } - else - { - authorityStart += 3; - } - - size_t posOfEndOfAuthorityPort = uri.find(':', authorityStart); - size_t posOfEndOfAuthoritySlash = uri.find('/', authorityStart); - size_t posOfEndOfAuthorityQuery = uri.find('?', authorityStart); - size_t posEndOfAuthority = (std::min)({posOfEndOfAuthorityPort, posOfEndOfAuthoritySlash, posOfEndOfAuthorityQuery}); - if (posEndOfAuthority == Aws::String::npos) - { - posEndOfAuthority = uri.length(); - } - - SetAuthority(uri.substr(authorityStart, posEndOfAuthority - authorityStart)); -} - -void URI::ExtractAndSetPort(const Aws::String& uri) -{ - size_t authorityStart = uri.find(SEPARATOR); - - if(authorityStart == Aws::String::npos) - { - authorityStart = 0; - } - else - { - authorityStart += 3; - } - - size_t positionOfPortDelimiter = uri.find(':', authorityStart); - - bool hasPort = positionOfPortDelimiter != Aws::String::npos; - - if ((uri.find('/', authorityStart) < positionOfPortDelimiter) || (uri.find('?', authorityStart) < positionOfPortDelimiter)) - { - hasPort = false; - } - - if (hasPort) - { - Aws::String strPort; - - size_t i = positionOfPortDelimiter + 1; - char currentDigit = uri[i]; - - while (std::isdigit(currentDigit)) - { - strPort += currentDigit; - currentDigit = uri[++i]; - } - - SetPort(static_cast<uint16_t>(atoi(strPort.c_str()))); - } -} - -void URI::ExtractAndSetPath(const Aws::String& uri) -{ - size_t authorityStart = uri.find(SEPARATOR); - - if (authorityStart == Aws::String::npos) - { - authorityStart = 0; - } - else - { - authorityStart += 3; - } - - size_t pathEnd = uri.find('?'); - - if (pathEnd == Aws::String::npos) - { - pathEnd = uri.length(); - } - - Aws::String authorityAndPath = uri.substr(authorityStart, pathEnd - authorityStart); - - size_t pathStart = authorityAndPath.find('/'); - - if (pathStart != Aws::String::npos) - { - SetPath(authorityAndPath.substr(pathStart, pathEnd - pathStart)); - } - else - { - SetPath("/"); - } -} - -void URI::ExtractAndSetQueryString(const Aws::String& uri) -{ - size_t queryStart = uri.find('?'); - - if (queryStart != Aws::String::npos) - { - m_queryString = uri.substr(queryStart); - } -} - -Aws::String URI::GetFormParameters() const -{ - if(m_queryString.length() == 0) - { - return ""; - } - else - { - return m_queryString.substr(1); - } -} - -bool URI::CompareURIParts(const URI& other) const -{ - return m_scheme == other.m_scheme && m_authority == other.m_authority && m_path == other.m_path && m_queryString == other.m_queryString; -} + { + for (QueryStringParameterCollection::iterator iter = sortedParameters.begin(); + iter != sortedParameters.end(); ++iter) + { + if (!first) + { + queryStringStream << "&"; + } + + first = false; + queryStringStream << iter->first.c_str() << "=" << iter->second.c_str(); + } + + m_queryString = queryStringStream.str(); + } +} + +void URI::AddQueryStringParameter(const char* key, const Aws::String& value) +{ + if (m_queryString.size() <= 0) + { + m_queryString.append("?"); + } + else + { + m_queryString.append("&"); + } + + m_queryString.append(StringUtils::URLEncode(key) + "=" + StringUtils::URLEncode(value.c_str())); +} + +void URI::AddQueryStringParameter(const Aws::Map<Aws::String, Aws::String>& queryStringPairs) +{ + for(const auto& entry: queryStringPairs) + { + AddQueryStringParameter(entry.first.c_str(), entry.second); + } +} + +void URI::SetQueryString(const Aws::String& str) +{ + m_queryString = ""; + + if (str.empty()) return; + + if (str.front() != '?') + { + m_queryString.append("?").append(str); + } + else + { + m_queryString = str; + } +} + +Aws::String URI::GetURIString(bool includeQueryString) const +{ + assert(m_authority.size() > 0); + + Aws::StringStream ss; + ss << SchemeMapper::ToString(m_scheme) << SEPARATOR << m_authority; + + if (m_scheme == Scheme::HTTP && m_port != HTTP_DEFAULT_PORT) + { + ss << ":" << m_port; + } + else if (m_scheme == Scheme::HTTPS && m_port != HTTPS_DEFAULT_PORT) + { + ss << ":" << m_port; + } + + if(m_path != "/") + { + ss << URLEncodePathRFC3986(m_path); + } + + if(includeQueryString) + { + ss << m_queryString; + } + + return ss.str(); +} + +void URI::ParseURIParts(const Aws::String& uri) +{ + ExtractAndSetScheme(uri); + ExtractAndSetAuthority(uri); + ExtractAndSetPort(uri); + ExtractAndSetPath(uri); + ExtractAndSetQueryString(uri); +} + +void URI::ExtractAndSetScheme(const Aws::String& uri) +{ + size_t posOfSeparator = uri.find(SEPARATOR); + + if (posOfSeparator != Aws::String::npos) + { + Aws::String schemePortion = uri.substr(0, posOfSeparator); + SetScheme(SchemeMapper::FromString(schemePortion.c_str())); + } + else + { + SetScheme(Scheme::HTTP); + } +} + +void URI::ExtractAndSetAuthority(const Aws::String& uri) +{ + size_t authorityStart = uri.find(SEPARATOR); + + if (authorityStart == Aws::String::npos) + { + authorityStart = 0; + } + else + { + authorityStart += 3; + } + + size_t posOfEndOfAuthorityPort = uri.find(':', authorityStart); + size_t posOfEndOfAuthoritySlash = uri.find('/', authorityStart); + size_t posOfEndOfAuthorityQuery = uri.find('?', authorityStart); + size_t posEndOfAuthority = (std::min)({posOfEndOfAuthorityPort, posOfEndOfAuthoritySlash, posOfEndOfAuthorityQuery}); + if (posEndOfAuthority == Aws::String::npos) + { + posEndOfAuthority = uri.length(); + } + + SetAuthority(uri.substr(authorityStart, posEndOfAuthority - authorityStart)); +} + +void URI::ExtractAndSetPort(const Aws::String& uri) +{ + size_t authorityStart = uri.find(SEPARATOR); + + if(authorityStart == Aws::String::npos) + { + authorityStart = 0; + } + else + { + authorityStart += 3; + } + + size_t positionOfPortDelimiter = uri.find(':', authorityStart); + + bool hasPort = positionOfPortDelimiter != Aws::String::npos; + + if ((uri.find('/', authorityStart) < positionOfPortDelimiter) || (uri.find('?', authorityStart) < positionOfPortDelimiter)) + { + hasPort = false; + } + + if (hasPort) + { + Aws::String strPort; + + size_t i = positionOfPortDelimiter + 1; + char currentDigit = uri[i]; + + while (std::isdigit(currentDigit)) + { + strPort += currentDigit; + currentDigit = uri[++i]; + } + + SetPort(static_cast<uint16_t>(atoi(strPort.c_str()))); + } +} + +void URI::ExtractAndSetPath(const Aws::String& uri) +{ + size_t authorityStart = uri.find(SEPARATOR); + + if (authorityStart == Aws::String::npos) + { + authorityStart = 0; + } + else + { + authorityStart += 3; + } + + size_t pathEnd = uri.find('?'); + + if (pathEnd == Aws::String::npos) + { + pathEnd = uri.length(); + } + + Aws::String authorityAndPath = uri.substr(authorityStart, pathEnd - authorityStart); + + size_t pathStart = authorityAndPath.find('/'); + + if (pathStart != Aws::String::npos) + { + SetPath(authorityAndPath.substr(pathStart, pathEnd - pathStart)); + } + else + { + SetPath("/"); + } +} + +void URI::ExtractAndSetQueryString(const Aws::String& uri) +{ + size_t queryStart = uri.find('?'); + + if (queryStart != Aws::String::npos) + { + m_queryString = uri.substr(queryStart); + } +} + +Aws::String URI::GetFormParameters() const +{ + if(m_queryString.length() == 0) + { + return ""; + } + else + { + return m_queryString.substr(1); + } +} + +bool URI::CompareURIParts(const URI& other) const +{ + return m_scheme == other.m_scheme && m_authority == other.m_authority && m_path == other.m_path && m_queryString == other.m_queryString; +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHandleContainer.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHandleContainer.cpp index 1a965cd795..78f54b964d 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHandleContainer.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHandleContainer.cpp @@ -2,64 +2,64 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/http/curl/CurlHandleContainer.h> -#include <aws/core/utils/logging/LogMacros.h> - -#include <algorithm> - -using namespace Aws::Utils::Logging; -using namespace Aws::Http; - -static const char* CURL_HANDLE_CONTAINER_TAG = "CurlHandleContainer"; - - + +#include <aws/core/http/curl/CurlHandleContainer.h> +#include <aws/core/utils/logging/LogMacros.h> + +#include <algorithm> + +using namespace Aws::Utils::Logging; +using namespace Aws::Http; + +static const char* CURL_HANDLE_CONTAINER_TAG = "CurlHandleContainer"; + + CurlHandleContainer::CurlHandleContainer(unsigned maxSize, long httpRequestTimeout, long connectTimeout, bool enableTcpKeepAlive, unsigned long tcpKeepAliveIntervalMs, long lowSpeedTime, unsigned long lowSpeedLimit) : m_maxPoolSize(maxSize), m_httpRequestTimeout(httpRequestTimeout), m_connectTimeout(connectTimeout), m_enableTcpKeepAlive(enableTcpKeepAlive), m_tcpKeepAliveIntervalMs(tcpKeepAliveIntervalMs), m_lowSpeedTime(lowSpeedTime), m_lowSpeedLimit(lowSpeedLimit), m_poolSize(0) -{ - AWS_LOGSTREAM_INFO(CURL_HANDLE_CONTAINER_TAG, "Initializing CurlHandleContainer with size " << maxSize); -} - -CurlHandleContainer::~CurlHandleContainer() -{ - AWS_LOGSTREAM_INFO(CURL_HANDLE_CONTAINER_TAG, "Cleaning up CurlHandleContainer."); - for (CURL* handle : m_handleContainer.ShutdownAndWait(m_poolSize)) - { - AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "Cleaning up " << handle); - curl_easy_cleanup(handle); - } -} - -CURL* CurlHandleContainer::AcquireCurlHandle() -{ - AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "Attempting to acquire curl connection."); - - if(!m_handleContainer.HasResourcesAvailable()) - { - AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "No current connections available in pool. Attempting to create new connections."); - CheckAndGrowPool(); - } - - CURL* handle = m_handleContainer.Acquire(); - AWS_LOGSTREAM_INFO(CURL_HANDLE_CONTAINER_TAG, "Connection has been released. Continuing."); - AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "Returning connection handle " << handle); - return handle; -} - -void CurlHandleContainer::ReleaseCurlHandle(CURL* handle) -{ - if (handle) - { - curl_easy_reset(handle); - SetDefaultOptionsOnHandle(handle); - AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "Releasing curl handle " << handle); - m_handleContainer.Release(handle); - AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "Notified waiting threads."); - } -} - +{ + AWS_LOGSTREAM_INFO(CURL_HANDLE_CONTAINER_TAG, "Initializing CurlHandleContainer with size " << maxSize); +} + +CurlHandleContainer::~CurlHandleContainer() +{ + AWS_LOGSTREAM_INFO(CURL_HANDLE_CONTAINER_TAG, "Cleaning up CurlHandleContainer."); + for (CURL* handle : m_handleContainer.ShutdownAndWait(m_poolSize)) + { + AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "Cleaning up " << handle); + curl_easy_cleanup(handle); + } +} + +CURL* CurlHandleContainer::AcquireCurlHandle() +{ + AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "Attempting to acquire curl connection."); + + if(!m_handleContainer.HasResourcesAvailable()) + { + AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "No current connections available in pool. Attempting to create new connections."); + CheckAndGrowPool(); + } + + CURL* handle = m_handleContainer.Acquire(); + AWS_LOGSTREAM_INFO(CURL_HANDLE_CONTAINER_TAG, "Connection has been released. Continuing."); + AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "Returning connection handle " << handle); + return handle; +} + +void CurlHandleContainer::ReleaseCurlHandle(CURL* handle) +{ + if (handle) + { + curl_easy_reset(handle); + SetDefaultOptionsOnHandle(handle); + AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "Releasing curl handle " << handle); + m_handleContainer.Release(handle); + AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "Notified waiting threads."); + } +} + void CurlHandleContainer::DestroyCurlHandle(CURL* handle) { if (!handle) @@ -99,49 +99,49 @@ CURL* CurlHandleContainer::CreateCurlHandleInPool() return curlHandle; } -bool CurlHandleContainer::CheckAndGrowPool() -{ - std::lock_guard<std::mutex> locker(m_containerLock); - if (m_poolSize < m_maxPoolSize) - { - unsigned multiplier = m_poolSize > 0 ? m_poolSize : 1; - unsigned amountToAdd = (std::min)(multiplier * 2, m_maxPoolSize - m_poolSize); - AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "attempting to grow pool size by " << amountToAdd); - - unsigned actuallyAdded = 0; - for (unsigned i = 0; i < amountToAdd; ++i) - { +bool CurlHandleContainer::CheckAndGrowPool() +{ + std::lock_guard<std::mutex> locker(m_containerLock); + if (m_poolSize < m_maxPoolSize) + { + unsigned multiplier = m_poolSize > 0 ? m_poolSize : 1; + unsigned amountToAdd = (std::min)(multiplier * 2, m_maxPoolSize - m_poolSize); + AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "attempting to grow pool size by " << amountToAdd); + + unsigned actuallyAdded = 0; + for (unsigned i = 0; i < amountToAdd; ++i) + { CURL* curlHandle = CreateCurlHandleInPool(); - - if (curlHandle) - { - ++actuallyAdded; - } - else - { - break; - } - } - - AWS_LOGSTREAM_INFO(CURL_HANDLE_CONTAINER_TAG, "Pool grown by " << actuallyAdded); - m_poolSize += actuallyAdded; - - return actuallyAdded > 0; - } - - AWS_LOGSTREAM_INFO(CURL_HANDLE_CONTAINER_TAG, "Pool cannot be grown any further, already at max size."); - - return false; -} - -void CurlHandleContainer::SetDefaultOptionsOnHandle(CURL* handle) -{ - //for timeouts to work in a multi-threaded context, - //always turn signals off. This also forces dns queries to - //not be included in the timeout calculations. - curl_easy_setopt(handle, CURLOPT_NOSIGNAL, 1L); + + if (curlHandle) + { + ++actuallyAdded; + } + else + { + break; + } + } + + AWS_LOGSTREAM_INFO(CURL_HANDLE_CONTAINER_TAG, "Pool grown by " << actuallyAdded); + m_poolSize += actuallyAdded; + + return actuallyAdded > 0; + } + + AWS_LOGSTREAM_INFO(CURL_HANDLE_CONTAINER_TAG, "Pool cannot be grown any further, already at max size."); + + return false; +} + +void CurlHandleContainer::SetDefaultOptionsOnHandle(CURL* handle) +{ + //for timeouts to work in a multi-threaded context, + //always turn signals off. This also forces dns queries to + //not be included in the timeout calculations. + curl_easy_setopt(handle, CURLOPT_NOSIGNAL, 1L); curl_easy_setopt(handle, CURLOPT_TIMEOUT_MS, m_httpRequestTimeout); - curl_easy_setopt(handle, CURLOPT_CONNECTTIMEOUT_MS, m_connectTimeout); + curl_easy_setopt(handle, CURLOPT_CONNECTTIMEOUT_MS, m_connectTimeout); curl_easy_setopt(handle, CURLOPT_LOW_SPEED_LIMIT, m_lowSpeedLimit); curl_easy_setopt(handle, CURLOPT_LOW_SPEED_TIME, m_lowSpeedTime < 1000 ? (m_lowSpeedTime == 0 ? 0 : 1) : m_lowSpeedTime / 1000); curl_easy_setopt(handle, CURLOPT_TCP_KEEPALIVE, m_enableTcpKeepAlive ? 1L : 0L); @@ -150,4 +150,4 @@ void CurlHandleContainer::SetDefaultOptionsOnHandle(CURL* handle) #ifdef CURL_HAS_H2 curl_easy_setopt(handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); #endif -} +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp index 2fb9cc9643..dcebfc0302 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp @@ -2,164 +2,164 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/http/curl/CurlHttpClient.h> -#include <aws/core/http/HttpRequest.h> -#include <aws/core/http/standard/StandardHttpResponse.h> -#include <aws/core/utils/StringUtils.h> -#include <aws/core/utils/logging/LogMacros.h> -#include <aws/core/utils/ratelimiter/RateLimiterInterface.h> -#include <aws/core/utils/DateTime.h> -#include <aws/core/monitoring/HttpClientMetrics.h> -#include <cassert> -#include <algorithm> - - -using namespace Aws::Client; -using namespace Aws::Http; -using namespace Aws::Http::Standard; -using namespace Aws::Utils; -using namespace Aws::Utils::Logging; -using namespace Aws::Monitoring; - -#ifdef AWS_CUSTOM_MEMORY_MANAGEMENT - -static const char* MemTag = "libcurl"; -static size_t offset = sizeof(size_t); - -static void* malloc_callback(size_t size) -{ - char* newMem = reinterpret_cast<char*>(Aws::Malloc(MemTag, size + offset)); - std::size_t* pointerToSize = reinterpret_cast<std::size_t*>(newMem); - *pointerToSize = size; - return reinterpret_cast<void*>(newMem + offset); -} - -static void free_callback(void* ptr) -{ - if(ptr) - { - char* shiftedMemory = reinterpret_cast<char*>(ptr); - Aws::Free(shiftedMemory - offset); - } -} - -static void* realloc_callback(void* ptr, size_t size) -{ - if(!ptr) - { - return malloc_callback(size); - } - - - if(!size && ptr) - { - free_callback(ptr); - return nullptr; - } - - char* originalLenCharPtr = reinterpret_cast<char*>(ptr) - offset; - size_t originalLen = *reinterpret_cast<size_t*>(originalLenCharPtr); - - char* rawMemory = reinterpret_cast<char*>(Aws::Malloc(MemTag, size + offset)); - if(rawMemory) - { - std::size_t* pointerToSize = reinterpret_cast<std::size_t*>(rawMemory); - *pointerToSize = size; - - size_t copyLength = (std::min)(originalLen, size); -#ifdef _MSC_VER - memcpy_s(rawMemory + offset, size, ptr, copyLength); -#else - memcpy(rawMemory + offset, ptr, copyLength); -#endif - free_callback(ptr); - return reinterpret_cast<void*>(rawMemory + offset); - } - else - { - return ptr; - } - -} - -static void* calloc_callback(size_t nmemb, size_t size) -{ - size_t dataSize = nmemb * size; - char* newMem = reinterpret_cast<char*>(Aws::Malloc(MemTag, dataSize + offset)); - std::size_t* pointerToSize = reinterpret_cast<std::size_t*>(newMem); - *pointerToSize = dataSize; -#ifdef _MSC_VER - memset_s(newMem + offset, dataSize, 0, dataSize); -#else - memset(newMem + offset, 0, dataSize); -#endif - - return reinterpret_cast<void*>(newMem + offset); -} - -static char* strdup_callback(const char* str) -{ - size_t len = strlen(str) + 1; - size_t newLen = len + offset; - char* newMem = reinterpret_cast<char*>(Aws::Malloc(MemTag, newLen)); - - if(newMem) - { - std::size_t* pointerToSize = reinterpret_cast<std::size_t*>(newMem); - *pointerToSize = len; -#ifdef _MSC_VER - memcpy_s(newMem + offset, len, str, len); -#else - memcpy(newMem + offset, str, len); -#endif - return newMem + offset; - } - return nullptr; -} - -#endif - -struct CurlWriteCallbackContext -{ - CurlWriteCallbackContext(const CurlHttpClient* client, + +#include <aws/core/http/curl/CurlHttpClient.h> +#include <aws/core/http/HttpRequest.h> +#include <aws/core/http/standard/StandardHttpResponse.h> +#include <aws/core/utils/StringUtils.h> +#include <aws/core/utils/logging/LogMacros.h> +#include <aws/core/utils/ratelimiter/RateLimiterInterface.h> +#include <aws/core/utils/DateTime.h> +#include <aws/core/monitoring/HttpClientMetrics.h> +#include <cassert> +#include <algorithm> + + +using namespace Aws::Client; +using namespace Aws::Http; +using namespace Aws::Http::Standard; +using namespace Aws::Utils; +using namespace Aws::Utils::Logging; +using namespace Aws::Monitoring; + +#ifdef AWS_CUSTOM_MEMORY_MANAGEMENT + +static const char* MemTag = "libcurl"; +static size_t offset = sizeof(size_t); + +static void* malloc_callback(size_t size) +{ + char* newMem = reinterpret_cast<char*>(Aws::Malloc(MemTag, size + offset)); + std::size_t* pointerToSize = reinterpret_cast<std::size_t*>(newMem); + *pointerToSize = size; + return reinterpret_cast<void*>(newMem + offset); +} + +static void free_callback(void* ptr) +{ + if(ptr) + { + char* shiftedMemory = reinterpret_cast<char*>(ptr); + Aws::Free(shiftedMemory - offset); + } +} + +static void* realloc_callback(void* ptr, size_t size) +{ + if(!ptr) + { + return malloc_callback(size); + } + + + if(!size && ptr) + { + free_callback(ptr); + return nullptr; + } + + char* originalLenCharPtr = reinterpret_cast<char*>(ptr) - offset; + size_t originalLen = *reinterpret_cast<size_t*>(originalLenCharPtr); + + char* rawMemory = reinterpret_cast<char*>(Aws::Malloc(MemTag, size + offset)); + if(rawMemory) + { + std::size_t* pointerToSize = reinterpret_cast<std::size_t*>(rawMemory); + *pointerToSize = size; + + size_t copyLength = (std::min)(originalLen, size); +#ifdef _MSC_VER + memcpy_s(rawMemory + offset, size, ptr, copyLength); +#else + memcpy(rawMemory + offset, ptr, copyLength); +#endif + free_callback(ptr); + return reinterpret_cast<void*>(rawMemory + offset); + } + else + { + return ptr; + } + +} + +static void* calloc_callback(size_t nmemb, size_t size) +{ + size_t dataSize = nmemb * size; + char* newMem = reinterpret_cast<char*>(Aws::Malloc(MemTag, dataSize + offset)); + std::size_t* pointerToSize = reinterpret_cast<std::size_t*>(newMem); + *pointerToSize = dataSize; +#ifdef _MSC_VER + memset_s(newMem + offset, dataSize, 0, dataSize); +#else + memset(newMem + offset, 0, dataSize); +#endif + + return reinterpret_cast<void*>(newMem + offset); +} + +static char* strdup_callback(const char* str) +{ + size_t len = strlen(str) + 1; + size_t newLen = len + offset; + char* newMem = reinterpret_cast<char*>(Aws::Malloc(MemTag, newLen)); + + if(newMem) + { + std::size_t* pointerToSize = reinterpret_cast<std::size_t*>(newMem); + *pointerToSize = len; +#ifdef _MSC_VER + memcpy_s(newMem + offset, len, str, len); +#else + memcpy(newMem + offset, str, len); +#endif + return newMem + offset; + } + return nullptr; +} + +#endif + +struct CurlWriteCallbackContext +{ + CurlWriteCallbackContext(const CurlHttpClient* client, HttpRequest* request, HttpResponse* response, - Aws::Utils::RateLimits::RateLimiterInterface* rateLimiter) : - m_client(client), - m_request(request), - m_response(response), - m_rateLimiter(rateLimiter), - m_numBytesResponseReceived(0) - {} - - const CurlHttpClient* m_client; - HttpRequest* m_request; - HttpResponse* m_response; - Aws::Utils::RateLimits::RateLimiterInterface* m_rateLimiter; - int64_t m_numBytesResponseReceived; -}; - -struct CurlReadCallbackContext -{ - CurlReadCallbackContext(const CurlHttpClient* client, HttpRequest* request, Aws::Utils::RateLimits::RateLimiterInterface* limiter) : - m_client(client), - m_rateLimiter(limiter), - m_request(request) - {} - - const CurlHttpClient* m_client; + Aws::Utils::RateLimits::RateLimiterInterface* rateLimiter) : + m_client(client), + m_request(request), + m_response(response), + m_rateLimiter(rateLimiter), + m_numBytesResponseReceived(0) + {} + + const CurlHttpClient* m_client; + HttpRequest* m_request; + HttpResponse* m_response; + Aws::Utils::RateLimits::RateLimiterInterface* m_rateLimiter; + int64_t m_numBytesResponseReceived; +}; + +struct CurlReadCallbackContext +{ + CurlReadCallbackContext(const CurlHttpClient* client, HttpRequest* request, Aws::Utils::RateLimits::RateLimiterInterface* limiter) : + m_client(client), + m_rateLimiter(limiter), + m_request(request) + {} + + const CurlHttpClient* m_client; CURL* m_curlHandle; - Aws::Utils::RateLimits::RateLimiterInterface* m_rateLimiter; - HttpRequest* m_request; -}; - -static const char* CURL_HTTP_CLIENT_TAG = "CurlHttpClient"; - + Aws::Utils::RateLimits::RateLimiterInterface* m_rateLimiter; + HttpRequest* m_request; +}; + +static const char* CURL_HTTP_CLIENT_TAG = "CurlHttpClient"; + static size_t WriteData(char* ptr, size_t size, size_t nmemb, void* userdata) -{ +{ if (ptr) - { + { CurlWriteCallbackContext* context = reinterpret_cast<CurlWriteCallbackContext*>(userdata); const CurlHttpClient* client = context->m_client; @@ -309,144 +309,144 @@ void SetOptCodeForHttpMethod(CURL* requestHandle, const std::shared_ptr<HttpRequ { switch (request->GetMethod()) { - case HttpMethod::HTTP_GET: - curl_easy_setopt(requestHandle, CURLOPT_HTTPGET, 1L); - break; - case HttpMethod::HTTP_POST: + case HttpMethod::HTTP_GET: + curl_easy_setopt(requestHandle, CURLOPT_HTTPGET, 1L); + break; + case HttpMethod::HTTP_POST: if (request->HasHeader(Aws::Http::CONTENT_LENGTH_HEADER) && request->GetHeaderValue(Aws::Http::CONTENT_LENGTH_HEADER) == "0") - { - curl_easy_setopt(requestHandle, CURLOPT_CUSTOMREQUEST, "POST"); - } - else - { - curl_easy_setopt(requestHandle, CURLOPT_POST, 1L); - } - break; - case HttpMethod::HTTP_PUT: + { + curl_easy_setopt(requestHandle, CURLOPT_CUSTOMREQUEST, "POST"); + } + else + { + curl_easy_setopt(requestHandle, CURLOPT_POST, 1L); + } + break; + case HttpMethod::HTTP_PUT: if ((!request->HasHeader(Aws::Http::CONTENT_LENGTH_HEADER) || request->GetHeaderValue(Aws::Http::CONTENT_LENGTH_HEADER) == "0") && !request->HasHeader(Aws::Http::TRANSFER_ENCODING_HEADER)) - { - curl_easy_setopt(requestHandle, CURLOPT_CUSTOMREQUEST, "PUT"); - } - else - { - curl_easy_setopt(requestHandle, CURLOPT_PUT, 1L); - } - break; - case HttpMethod::HTTP_HEAD: - curl_easy_setopt(requestHandle, CURLOPT_HTTPGET, 1L); - curl_easy_setopt(requestHandle, CURLOPT_NOBODY, 1L); - break; - case HttpMethod::HTTP_PATCH: + { + curl_easy_setopt(requestHandle, CURLOPT_CUSTOMREQUEST, "PUT"); + } + else + { + curl_easy_setopt(requestHandle, CURLOPT_PUT, 1L); + } + break; + case HttpMethod::HTTP_HEAD: + curl_easy_setopt(requestHandle, CURLOPT_HTTPGET, 1L); + curl_easy_setopt(requestHandle, CURLOPT_NOBODY, 1L); + break; + case HttpMethod::HTTP_PATCH: if ((!request->HasHeader(Aws::Http::CONTENT_LENGTH_HEADER)|| request->GetHeaderValue(Aws::Http::CONTENT_LENGTH_HEADER) == "0") && !request->HasHeader(Aws::Http::TRANSFER_ENCODING_HEADER)) - { - curl_easy_setopt(requestHandle, CURLOPT_CUSTOMREQUEST, "PATCH"); - } - else - { - curl_easy_setopt(requestHandle, CURLOPT_POST, 1L); - curl_easy_setopt(requestHandle, CURLOPT_CUSTOMREQUEST, "PATCH"); - } - - break; - case HttpMethod::HTTP_DELETE: - curl_easy_setopt(requestHandle, CURLOPT_CUSTOMREQUEST, "DELETE"); - break; - default: - assert(0); - curl_easy_setopt(requestHandle, CURLOPT_CUSTOMREQUEST, "GET"); - break; - } -} - - -std::atomic<bool> CurlHttpClient::isInit(false); - -void CurlHttpClient::InitGlobalState() -{ - if (!isInit) - { + { + curl_easy_setopt(requestHandle, CURLOPT_CUSTOMREQUEST, "PATCH"); + } + else + { + curl_easy_setopt(requestHandle, CURLOPT_POST, 1L); + curl_easy_setopt(requestHandle, CURLOPT_CUSTOMREQUEST, "PATCH"); + } + + break; + case HttpMethod::HTTP_DELETE: + curl_easy_setopt(requestHandle, CURLOPT_CUSTOMREQUEST, "DELETE"); + break; + default: + assert(0); + curl_easy_setopt(requestHandle, CURLOPT_CUSTOMREQUEST, "GET"); + break; + } +} + + +std::atomic<bool> CurlHttpClient::isInit(false); + +void CurlHttpClient::InitGlobalState() +{ + if (!isInit) + { auto curlVersionData = curl_version_info(CURLVERSION_NOW); AWS_LOGSTREAM_INFO(CURL_HTTP_CLIENT_TAG, "Initializing Curl library with version: " << curlVersionData->version << ", ssl version: " << curlVersionData->ssl_version); - isInit = true; -#ifdef AWS_CUSTOM_MEMORY_MANAGEMENT - curl_global_init_mem(CURL_GLOBAL_ALL, &malloc_callback, &free_callback, &realloc_callback, &strdup_callback, &calloc_callback); -#else - curl_global_init(CURL_GLOBAL_ALL); -#endif - } -} - - -void CurlHttpClient::CleanupGlobalState() -{ - curl_global_cleanup(); -} - -Aws::String CurlInfoTypeToString(curl_infotype type) -{ - switch(type) - { - case CURLINFO_TEXT: - return "Text"; - - case CURLINFO_HEADER_IN: - return "HeaderIn"; - - case CURLINFO_HEADER_OUT: - return "HeaderOut"; - - case CURLINFO_DATA_IN: - return "DataIn"; - - case CURLINFO_DATA_OUT: - return "DataOut"; - - case CURLINFO_SSL_DATA_IN: - return "SSLDataIn"; - - case CURLINFO_SSL_DATA_OUT: - return "SSLDataOut"; - - default: - return "Unknown"; - } -} - -int CurlDebugCallback(CURL *handle, curl_infotype type, char *data, size_t size, void *userptr) -{ - AWS_UNREFERENCED_PARAM(handle); - AWS_UNREFERENCED_PARAM(userptr); - - if(type == CURLINFO_SSL_DATA_IN || type == CURLINFO_SSL_DATA_OUT) - { - AWS_LOGSTREAM_DEBUG("CURL", "(" << CurlInfoTypeToString(type) << ") " << size << "bytes"); - } - else - { - Aws::String debugString(data, size); - AWS_LOGSTREAM_DEBUG("CURL", "(" << CurlInfoTypeToString(type) << ") " << debugString); - } - - return 0; -} - - -CurlHttpClient::CurlHttpClient(const ClientConfiguration& clientConfig) : + isInit = true; +#ifdef AWS_CUSTOM_MEMORY_MANAGEMENT + curl_global_init_mem(CURL_GLOBAL_ALL, &malloc_callback, &free_callback, &realloc_callback, &strdup_callback, &calloc_callback); +#else + curl_global_init(CURL_GLOBAL_ALL); +#endif + } +} + + +void CurlHttpClient::CleanupGlobalState() +{ + curl_global_cleanup(); +} + +Aws::String CurlInfoTypeToString(curl_infotype type) +{ + switch(type) + { + case CURLINFO_TEXT: + return "Text"; + + case CURLINFO_HEADER_IN: + return "HeaderIn"; + + case CURLINFO_HEADER_OUT: + return "HeaderOut"; + + case CURLINFO_DATA_IN: + return "DataIn"; + + case CURLINFO_DATA_OUT: + return "DataOut"; + + case CURLINFO_SSL_DATA_IN: + return "SSLDataIn"; + + case CURLINFO_SSL_DATA_OUT: + return "SSLDataOut"; + + default: + return "Unknown"; + } +} + +int CurlDebugCallback(CURL *handle, curl_infotype type, char *data, size_t size, void *userptr) +{ + AWS_UNREFERENCED_PARAM(handle); + AWS_UNREFERENCED_PARAM(userptr); + + if(type == CURLINFO_SSL_DATA_IN || type == CURLINFO_SSL_DATA_OUT) + { + AWS_LOGSTREAM_DEBUG("CURL", "(" << CurlInfoTypeToString(type) << ") " << size << "bytes"); + } + else + { + Aws::String debugString(data, size); + AWS_LOGSTREAM_DEBUG("CURL", "(" << CurlInfoTypeToString(type) << ") " << debugString); + } + + return 0; +} + + +CurlHttpClient::CurlHttpClient(const ClientConfiguration& clientConfig) : Base(), m_curlHandleContainer(clientConfig.maxConnections, clientConfig.httpRequestTimeoutMs, clientConfig.connectTimeoutMs, clientConfig.enableTcpKeepAlive, clientConfig.tcpKeepAliveIntervalMs, clientConfig.requestTimeoutMs, clientConfig.lowSpeedLimit), - m_isUsingProxy(!clientConfig.proxyHost.empty()), m_proxyUserName(clientConfig.proxyUserName), - m_proxyPassword(clientConfig.proxyPassword), m_proxyScheme(SchemeMapper::ToString(clientConfig.proxyScheme)), m_proxyHost(clientConfig.proxyHost), + m_isUsingProxy(!clientConfig.proxyHost.empty()), m_proxyUserName(clientConfig.proxyUserName), + m_proxyPassword(clientConfig.proxyPassword), m_proxyScheme(SchemeMapper::ToString(clientConfig.proxyScheme)), m_proxyHost(clientConfig.proxyHost), m_proxySSLCertPath(clientConfig.proxySSLCertPath), m_proxySSLCertType(clientConfig.proxySSLCertType), m_proxySSLKeyPath(clientConfig.proxySSLKeyPath), m_proxySSLKeyType(clientConfig.proxySSLKeyType), m_proxyKeyPasswd(clientConfig.proxySSLKeyPassword), - m_proxyPort(clientConfig.proxyPort), m_verifySSL(clientConfig.verifySSL), m_caPath(clientConfig.caPath), + m_proxyPort(clientConfig.proxyPort), m_verifySSL(clientConfig.verifySSL), m_caPath(clientConfig.caPath), m_caFile(clientConfig.caFile), m_proxyCaPath(clientConfig.proxyCaPath), m_proxyCaFile(clientConfig.proxyCaFile), m_disableExpectHeader(clientConfig.disableExpectHeader) -{ +{ if (clientConfig.followRedirects == FollowRedirectsPolicy::NEVER || (clientConfig.followRedirects == FollowRedirectsPolicy::DEFAULT && clientConfig.region == Aws::Region::AWS_GLOBAL)) { @@ -456,132 +456,132 @@ CurlHttpClient::CurlHttpClient(const ClientConfiguration& clientConfig) : { m_allowRedirects = true; } -} - - +} + + std::shared_ptr<HttpResponse> CurlHttpClient::MakeRequest(const std::shared_ptr<HttpRequest>& request, Aws::Utils::RateLimits::RateLimiterInterface* readLimiter, Aws::Utils::RateLimits::RateLimiterInterface* writeLimiter) const -{ +{ URI uri = request->GetUri(); - Aws::String url = uri.GetURIString(); + Aws::String url = uri.GetURIString(); std::shared_ptr<HttpResponse> response = Aws::MakeShared<StandardHttpResponse>(CURL_HTTP_CLIENT_TAG, request); - - AWS_LOGSTREAM_TRACE(CURL_HTTP_CLIENT_TAG, "Making request to " << url); - struct curl_slist* headers = NULL; - - if (writeLimiter != nullptr) - { + + AWS_LOGSTREAM_TRACE(CURL_HTTP_CLIENT_TAG, "Making request to " << url); + struct curl_slist* headers = NULL; + + if (writeLimiter != nullptr) + { writeLimiter->ApplyAndPayForCost(request->GetSize()); - } - - Aws::StringStream headerStream; + } + + Aws::StringStream headerStream; HeaderValueCollection requestHeaders = request->GetHeaders(); - - AWS_LOGSTREAM_TRACE(CURL_HTTP_CLIENT_TAG, "Including headers:"); - for (auto& requestHeader : requestHeaders) - { - headerStream.str(""); - headerStream << requestHeader.first << ": " << requestHeader.second; - Aws::String headerString = headerStream.str(); - AWS_LOGSTREAM_TRACE(CURL_HTTP_CLIENT_TAG, headerString); - headers = curl_slist_append(headers, headerString.c_str()); - } - + + AWS_LOGSTREAM_TRACE(CURL_HTTP_CLIENT_TAG, "Including headers:"); + for (auto& requestHeader : requestHeaders) + { + headerStream.str(""); + headerStream << requestHeader.first << ": " << requestHeader.second; + Aws::String headerString = headerStream.str(); + AWS_LOGSTREAM_TRACE(CURL_HTTP_CLIENT_TAG, headerString); + headers = curl_slist_append(headers, headerString.c_str()); + } + if (!request->HasHeader(Http::TRANSFER_ENCODING_HEADER)) - { + { headers = curl_slist_append(headers, "transfer-encoding:"); } if (!request->HasHeader(Http::CONTENT_LENGTH_HEADER)) { - headers = curl_slist_append(headers, "content-length:"); - } - + headers = curl_slist_append(headers, "content-length:"); + } + if (!request->HasHeader(Http::CONTENT_TYPE_HEADER)) - { - headers = curl_slist_append(headers, "content-type:"); - } - - // Discard Expect header so as to avoid using multiple payloads to send a http request (header + body) - if (m_disableExpectHeader) - { - headers = curl_slist_append(headers, "Expect:"); - } - - CURL* connectionHandle = m_curlHandleContainer.AcquireCurlHandle(); - - if (connectionHandle) - { - AWS_LOGSTREAM_DEBUG(CURL_HTTP_CLIENT_TAG, "Obtained connection handle " << connectionHandle); - - if (headers) - { - curl_easy_setopt(connectionHandle, CURLOPT_HTTPHEADER, headers); - } - + { + headers = curl_slist_append(headers, "content-type:"); + } + + // Discard Expect header so as to avoid using multiple payloads to send a http request (header + body) + if (m_disableExpectHeader) + { + headers = curl_slist_append(headers, "Expect:"); + } + + CURL* connectionHandle = m_curlHandleContainer.AcquireCurlHandle(); + + if (connectionHandle) + { + AWS_LOGSTREAM_DEBUG(CURL_HTTP_CLIENT_TAG, "Obtained connection handle " << connectionHandle); + + if (headers) + { + curl_easy_setopt(connectionHandle, CURLOPT_HTTPHEADER, headers); + } + CurlWriteCallbackContext writeContext(this, request.get(), response.get(), readLimiter); CurlReadCallbackContext readContext(this, request.get(), writeLimiter); - - SetOptCodeForHttpMethod(connectionHandle, request); - - curl_easy_setopt(connectionHandle, CURLOPT_URL, url.c_str()); + + SetOptCodeForHttpMethod(connectionHandle, request); + + curl_easy_setopt(connectionHandle, CURLOPT_URL, url.c_str()); curl_easy_setopt(connectionHandle, CURLOPT_WRITEFUNCTION, WriteData); - curl_easy_setopt(connectionHandle, CURLOPT_WRITEDATA, &writeContext); + curl_easy_setopt(connectionHandle, CURLOPT_WRITEDATA, &writeContext); curl_easy_setopt(connectionHandle, CURLOPT_HEADERFUNCTION, WriteHeader); curl_easy_setopt(connectionHandle, CURLOPT_HEADERDATA, &writeContext); - - //we only want to override the default path if someone has explicitly told us to. - if(!m_caPath.empty()) - { - curl_easy_setopt(connectionHandle, CURLOPT_CAPATH, m_caPath.c_str()); - } - if(!m_caFile.empty()) - { - curl_easy_setopt(connectionHandle, CURLOPT_CAINFO, m_caFile.c_str()); - } - - // only set by android test builds because the emulator is missing a cert needed for aws services -#ifdef TEST_CERT_PATH - curl_easy_setopt(connectionHandle, CURLOPT_CAPATH, TEST_CERT_PATH); -#endif // TEST_CERT_PATH - - if (m_verifySSL) - { - curl_easy_setopt(connectionHandle, CURLOPT_SSL_VERIFYPEER, 1L); - curl_easy_setopt(connectionHandle, CURLOPT_SSL_VERIFYHOST, 2L); - -#if LIBCURL_VERSION_MAJOR >= 7 -#if LIBCURL_VERSION_MINOR >= 34 - curl_easy_setopt(connectionHandle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1); -#endif //LIBCURL_VERSION_MINOR -#endif //LIBCURL_VERSION_MAJOR - } - else - { - curl_easy_setopt(connectionHandle, CURLOPT_SSL_VERIFYPEER, 0L); - curl_easy_setopt(connectionHandle, CURLOPT_SSL_VERIFYHOST, 0L); - } - - if (m_allowRedirects) - { - curl_easy_setopt(connectionHandle, CURLOPT_FOLLOWLOCATION, 1L); - } - else - { - curl_easy_setopt(connectionHandle, CURLOPT_FOLLOWLOCATION, 0L); - } - + + //we only want to override the default path if someone has explicitly told us to. + if(!m_caPath.empty()) + { + curl_easy_setopt(connectionHandle, CURLOPT_CAPATH, m_caPath.c_str()); + } + if(!m_caFile.empty()) + { + curl_easy_setopt(connectionHandle, CURLOPT_CAINFO, m_caFile.c_str()); + } + + // only set by android test builds because the emulator is missing a cert needed for aws services +#ifdef TEST_CERT_PATH + curl_easy_setopt(connectionHandle, CURLOPT_CAPATH, TEST_CERT_PATH); +#endif // TEST_CERT_PATH + + if (m_verifySSL) + { + curl_easy_setopt(connectionHandle, CURLOPT_SSL_VERIFYPEER, 1L); + curl_easy_setopt(connectionHandle, CURLOPT_SSL_VERIFYHOST, 2L); + +#if LIBCURL_VERSION_MAJOR >= 7 +#if LIBCURL_VERSION_MINOR >= 34 + curl_easy_setopt(connectionHandle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1); +#endif //LIBCURL_VERSION_MINOR +#endif //LIBCURL_VERSION_MAJOR + } + else + { + curl_easy_setopt(connectionHandle, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(connectionHandle, CURLOPT_SSL_VERIFYHOST, 0L); + } + + if (m_allowRedirects) + { + curl_easy_setopt(connectionHandle, CURLOPT_FOLLOWLOCATION, 1L); + } + else + { + curl_easy_setopt(connectionHandle, CURLOPT_FOLLOWLOCATION, 0L); + } + #ifdef ENABLE_CURL_LOGGING curl_easy_setopt(connectionHandle, CURLOPT_VERBOSE, 1); curl_easy_setopt(connectionHandle, CURLOPT_DEBUGFUNCTION, CurlDebugCallback); #endif - if (m_isUsingProxy) - { - Aws::StringStream ss; - ss << m_proxyScheme << "://" << m_proxyHost; - curl_easy_setopt(connectionHandle, CURLOPT_PROXY, ss.str().c_str()); - curl_easy_setopt(connectionHandle, CURLOPT_PROXYPORT, (long) m_proxyPort); + if (m_isUsingProxy) + { + Aws::StringStream ss; + ss << m_proxyScheme << "://" << m_proxyHost; + curl_easy_setopt(connectionHandle, CURLOPT_PROXY, ss.str().c_str()); + curl_easy_setopt(connectionHandle, CURLOPT_PROXYPORT, (long) m_proxyPort); if(!m_proxyCaPath.empty()) { curl_easy_setopt(connectionHandle, CURLOPT_PROXY_CAPATH, m_proxyCaPath.c_str()); @@ -617,91 +617,91 @@ std::shared_ptr<HttpResponse> CurlHttpClient::MakeRequest(const std::shared_ptr< } } #endif //CURL_HAS_TLS_PROXY - } - else - { - curl_easy_setopt(connectionHandle, CURLOPT_PROXY, ""); - } - + } + else + { + curl_easy_setopt(connectionHandle, CURLOPT_PROXY, ""); + } + if (request->GetContentBody()) - { + { curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, ReadBody); - curl_easy_setopt(connectionHandle, CURLOPT_READDATA, &readContext); + curl_easy_setopt(connectionHandle, CURLOPT_READDATA, &readContext); curl_easy_setopt(connectionHandle, CURLOPT_SEEKFUNCTION, SeekBody); - curl_easy_setopt(connectionHandle, CURLOPT_SEEKDATA, &readContext); - } + curl_easy_setopt(connectionHandle, CURLOPT_SEEKDATA, &readContext); + } OverrideOptionsOnConnectionHandle(connectionHandle); - Aws::Utils::DateTime startTransmissionTime = Aws::Utils::DateTime::Now(); - CURLcode curlResponseCode = curl_easy_perform(connectionHandle); + Aws::Utils::DateTime startTransmissionTime = Aws::Utils::DateTime::Now(); + CURLcode curlResponseCode = curl_easy_perform(connectionHandle); bool shouldContinueRequest = ContinueRequest(*request); - if (curlResponseCode != CURLE_OK && shouldContinueRequest) - { + if (curlResponseCode != CURLE_OK && shouldContinueRequest) + { response->SetClientErrorType(CoreErrors::NETWORK_CONNECTION); Aws::StringStream ss; ss << "curlCode: " << curlResponseCode << ", " << curl_easy_strerror(curlResponseCode); response->SetClientErrorMessage(ss.str()); AWS_LOGSTREAM_ERROR(CURL_HTTP_CLIENT_TAG, "Curl returned error code " << curlResponseCode << " - " << curl_easy_strerror(curlResponseCode)); - } - else if(!shouldContinueRequest) - { + } + else if(!shouldContinueRequest) + { response->SetClientErrorType(CoreErrors::USER_CANCELLED); response->SetClientErrorMessage("Request cancelled by user's continuation handler"); - } - else - { - long responseCode; - curl_easy_getinfo(connectionHandle, CURLINFO_RESPONSE_CODE, &responseCode); - response->SetResponseCode(static_cast<HttpResponseCode>(responseCode)); - AWS_LOGSTREAM_DEBUG(CURL_HTTP_CLIENT_TAG, "Returned http response code " << responseCode); - - char* contentType = nullptr; - curl_easy_getinfo(connectionHandle, CURLINFO_CONTENT_TYPE, &contentType); - if (contentType) - { - response->SetContentType(contentType); - AWS_LOGSTREAM_DEBUG(CURL_HTTP_CLIENT_TAG, "Returned content type " << contentType); - } - + } + else + { + long responseCode; + curl_easy_getinfo(connectionHandle, CURLINFO_RESPONSE_CODE, &responseCode); + response->SetResponseCode(static_cast<HttpResponseCode>(responseCode)); + AWS_LOGSTREAM_DEBUG(CURL_HTTP_CLIENT_TAG, "Returned http response code " << responseCode); + + char* contentType = nullptr; + curl_easy_getinfo(connectionHandle, CURLINFO_CONTENT_TYPE, &contentType); + if (contentType) + { + response->SetContentType(contentType); + AWS_LOGSTREAM_DEBUG(CURL_HTTP_CLIENT_TAG, "Returned content type " << contentType); + } + if (request->GetMethod() != HttpMethod::HTTP_HEAD && - writeContext.m_client->IsRequestProcessingEnabled() && - response->HasHeader(Aws::Http::CONTENT_LENGTH_HEADER)) - { - const Aws::String& contentLength = response->GetHeader(Aws::Http::CONTENT_LENGTH_HEADER); - int64_t numBytesResponseReceived = writeContext.m_numBytesResponseReceived; - AWS_LOGSTREAM_TRACE(CURL_HTTP_CLIENT_TAG, "Response content-length header: " << contentLength); - AWS_LOGSTREAM_TRACE(CURL_HTTP_CLIENT_TAG, "Response body length: " << numBytesResponseReceived); - if (StringUtils::ConvertToInt64(contentLength.c_str()) != numBytesResponseReceived) - { + writeContext.m_client->IsRequestProcessingEnabled() && + response->HasHeader(Aws::Http::CONTENT_LENGTH_HEADER)) + { + const Aws::String& contentLength = response->GetHeader(Aws::Http::CONTENT_LENGTH_HEADER); + int64_t numBytesResponseReceived = writeContext.m_numBytesResponseReceived; + AWS_LOGSTREAM_TRACE(CURL_HTTP_CLIENT_TAG, "Response content-length header: " << contentLength); + AWS_LOGSTREAM_TRACE(CURL_HTTP_CLIENT_TAG, "Response body length: " << numBytesResponseReceived); + if (StringUtils::ConvertToInt64(contentLength.c_str()) != numBytesResponseReceived) + { response->SetClientErrorType(CoreErrors::NETWORK_CONNECTION); response->SetClientErrorMessage("Response body length doesn't match the content-length header."); - AWS_LOGSTREAM_ERROR(CURL_HTTP_CLIENT_TAG, "Response body length doesn't match the content-length header."); - } - } - - AWS_LOGSTREAM_DEBUG(CURL_HTTP_CLIENT_TAG, "Releasing curl handle " << connectionHandle); - } - - double timep; - CURLcode ret = curl_easy_getinfo(connectionHandle, CURLINFO_NAMELOOKUP_TIME, &timep); // DNS Resolve Latency, seconds. - if (ret == CURLE_OK) - { + AWS_LOGSTREAM_ERROR(CURL_HTTP_CLIENT_TAG, "Response body length doesn't match the content-length header."); + } + } + + AWS_LOGSTREAM_DEBUG(CURL_HTTP_CLIENT_TAG, "Releasing curl handle " << connectionHandle); + } + + double timep; + CURLcode ret = curl_easy_getinfo(connectionHandle, CURLINFO_NAMELOOKUP_TIME, &timep); // DNS Resolve Latency, seconds. + if (ret == CURLE_OK) + { request->AddRequestMetric(GetHttpClientMetricNameByType(HttpClientMetricsType::DnsLatency), static_cast<int64_t>(timep * 1000));// to milliseconds - } - + } + ret = curl_easy_getinfo(connectionHandle, CURLINFO_STARTTRANSFER_TIME, &timep); // Connect Latency - if (ret == CURLE_OK) - { + if (ret == CURLE_OK) + { request->AddRequestMetric(GetHttpClientMetricNameByType(HttpClientMetricsType::ConnectLatency), static_cast<int64_t>(timep * 1000)); - } - - ret = curl_easy_getinfo(connectionHandle, CURLINFO_APPCONNECT_TIME, &timep); // Ssl Latency - if (ret == CURLE_OK) - { + } + + ret = curl_easy_getinfo(connectionHandle, CURLINFO_APPCONNECT_TIME, &timep); // Ssl Latency + if (ret == CURLE_OK) + { request->AddRequestMetric(GetHttpClientMetricNameByType(HttpClientMetricsType::SslLatency), static_cast<int64_t>(timep * 1000)); - } - + } + const char* ip = nullptr; auto curlGetInfoResult = curl_easy_getinfo(connectionHandle, CURLINFO_PRIMARY_IP, &ip); // Get the IP address of the remote endpoint if (curlGetInfoResult == CURLE_OK && ip) @@ -709,9 +709,9 @@ std::shared_ptr<HttpResponse> CurlHttpClient::MakeRequest(const std::shared_ptr< request->SetResolvedRemoteHost(ip); } if (curlResponseCode != CURLE_OK) - { + { m_curlHandleContainer.DestroyCurlHandle(connectionHandle); - } + } else { m_curlHandleContainer.ReleaseCurlHandle(connectionHandle); @@ -719,12 +719,12 @@ std::shared_ptr<HttpResponse> CurlHttpClient::MakeRequest(const std::shared_ptr< //go ahead and flush the response body stream response->GetResponseBody().flush(); request->AddRequestMetric(GetHttpClientMetricNameByType(HttpClientMetricsType::RequestLatency), (DateTime::Now() - startTransmissionTime).count()); - } - - if (headers) - { - curl_slist_free_all(headers); - } - - return response; -} + } + + if (headers) + { + curl_slist_free_all(headers); + } + + return response; +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/standard/StandardHttpRequest.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/standard/StandardHttpRequest.cpp index 47a0ee4fac..1125eb57ce 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/standard/StandardHttpRequest.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/standard/StandardHttpRequest.cpp @@ -2,103 +2,103 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/http/standard/StandardHttpRequest.h> - -#include <aws/core/utils/StringUtils.h> - -#include <iostream> -#include <algorithm> -#include <cassert> - -using namespace Aws::Http; -using namespace Aws::Http::Standard; -using namespace Aws::Utils; - -static bool IsDefaultPort(const URI& uri) -{ - switch(uri.GetPort()) - { - case 80: - return uri.GetScheme() == Scheme::HTTP; - case 443: - return uri.GetScheme() == Scheme::HTTPS; - default: - return false; - } -} - -StandardHttpRequest::StandardHttpRequest(const URI& uri, HttpMethod method) : - HttpRequest(uri, method), - bodyStream(nullptr), - m_responseStreamFactory() -{ - if(IsDefaultPort(uri)) - { + +#include <aws/core/http/standard/StandardHttpRequest.h> + +#include <aws/core/utils/StringUtils.h> + +#include <iostream> +#include <algorithm> +#include <cassert> + +using namespace Aws::Http; +using namespace Aws::Http::Standard; +using namespace Aws::Utils; + +static bool IsDefaultPort(const URI& uri) +{ + switch(uri.GetPort()) + { + case 80: + return uri.GetScheme() == Scheme::HTTP; + case 443: + return uri.GetScheme() == Scheme::HTTPS; + default: + return false; + } +} + +StandardHttpRequest::StandardHttpRequest(const URI& uri, HttpMethod method) : + HttpRequest(uri, method), + bodyStream(nullptr), + m_responseStreamFactory() +{ + if(IsDefaultPort(uri)) + { StandardHttpRequest::SetHeaderValue(HOST_HEADER, uri.GetAuthority()); - } - else - { - Aws::StringStream host; - host << uri.GetAuthority() << ":" << uri.GetPort(); + } + else + { + Aws::StringStream host; + host << uri.GetAuthority() << ":" << uri.GetPort(); StandardHttpRequest::SetHeaderValue(HOST_HEADER, host.str()); - } -} - -HeaderValueCollection StandardHttpRequest::GetHeaders() const -{ - HeaderValueCollection headers; - - for (HeaderValueCollection::const_iterator iter = headerMap.begin(); iter != headerMap.end(); ++iter) - { - headers.emplace(HeaderValuePair(iter->first, iter->second)); - } - - return headers; -} - -const Aws::String& StandardHttpRequest::GetHeaderValue(const char* headerName) const -{ - auto iter = headerMap.find(headerName); - assert (iter != headerMap.end()); - return iter->second; -} - -void StandardHttpRequest::SetHeaderValue(const char* headerName, const Aws::String& headerValue) -{ - headerMap[StringUtils::ToLower(headerName)] = StringUtils::Trim(headerValue.c_str()); -} - -void StandardHttpRequest::SetHeaderValue(const Aws::String& headerName, const Aws::String& headerValue) -{ - headerMap[StringUtils::ToLower(headerName.c_str())] = StringUtils::Trim(headerValue.c_str()); -} - -void StandardHttpRequest::DeleteHeader(const char* headerName) -{ - headerMap.erase(StringUtils::ToLower(headerName)); -} - -bool StandardHttpRequest::HasHeader(const char* headerName) const -{ - return headerMap.find(StringUtils::ToLower(headerName)) != headerMap.end(); -} - -int64_t StandardHttpRequest::GetSize() const -{ - int64_t size = 0; - - std::for_each(headerMap.cbegin(), headerMap.cend(), [&](const HeaderValueCollection::value_type& kvPair){ size += kvPair.first.length(); size += kvPair.second.length(); }); - - return size; -} - -const Aws::IOStreamFactory& StandardHttpRequest::GetResponseStreamFactory() const + } +} + +HeaderValueCollection StandardHttpRequest::GetHeaders() const +{ + HeaderValueCollection headers; + + for (HeaderValueCollection::const_iterator iter = headerMap.begin(); iter != headerMap.end(); ++iter) + { + headers.emplace(HeaderValuePair(iter->first, iter->second)); + } + + return headers; +} + +const Aws::String& StandardHttpRequest::GetHeaderValue(const char* headerName) const +{ + auto iter = headerMap.find(headerName); + assert (iter != headerMap.end()); + return iter->second; +} + +void StandardHttpRequest::SetHeaderValue(const char* headerName, const Aws::String& headerValue) +{ + headerMap[StringUtils::ToLower(headerName)] = StringUtils::Trim(headerValue.c_str()); +} + +void StandardHttpRequest::SetHeaderValue(const Aws::String& headerName, const Aws::String& headerValue) +{ + headerMap[StringUtils::ToLower(headerName.c_str())] = StringUtils::Trim(headerValue.c_str()); +} + +void StandardHttpRequest::DeleteHeader(const char* headerName) +{ + headerMap.erase(StringUtils::ToLower(headerName)); +} + +bool StandardHttpRequest::HasHeader(const char* headerName) const { - return m_responseStreamFactory; -} - -void StandardHttpRequest::SetResponseStreamFactory(const Aws::IOStreamFactory& factory) + return headerMap.find(StringUtils::ToLower(headerName)) != headerMap.end(); +} + +int64_t StandardHttpRequest::GetSize() const { - m_responseStreamFactory = factory; -} + int64_t size = 0; + + std::for_each(headerMap.cbegin(), headerMap.cend(), [&](const HeaderValueCollection::value_type& kvPair){ size += kvPair.first.length(); size += kvPair.second.length(); }); + + return size; +} + +const Aws::IOStreamFactory& StandardHttpRequest::GetResponseStreamFactory() const +{ + return m_responseStreamFactory; +} + +void StandardHttpRequest::SetResponseStreamFactory(const Aws::IOStreamFactory& factory) +{ + m_responseStreamFactory = factory; +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/standard/StandardHttpResponse.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/standard/StandardHttpResponse.cpp index 92d7a062b6..2097a5efa4 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/standard/StandardHttpResponse.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/standard/StandardHttpResponse.cpp @@ -2,45 +2,45 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/http/standard/StandardHttpResponse.h> - -#include <aws/core/utils/StringUtils.h> -#include <aws/core/utils/memory/AWSMemory.h> - -#include <istream> - -using namespace Aws::Http; -using namespace Aws::Http::Standard; -using namespace Aws::Utils; - - -HeaderValueCollection StandardHttpResponse::GetHeaders() const -{ - HeaderValueCollection headerValueCollection; - - for (Aws::Map<Aws::String, Aws::String>::const_iterator iter = headerMap.begin(); iter != headerMap.end(); ++iter) - { - headerValueCollection.emplace(HeaderValuePair(iter->first, iter->second)); - } - - return headerValueCollection; -} - -bool StandardHttpResponse::HasHeader(const char* headerName) const -{ - return headerMap.find(StringUtils::ToLower(headerName)) != headerMap.end(); -} - -const Aws::String& StandardHttpResponse::GetHeader(const Aws::String& headerName) const -{ - Aws::Map<Aws::String, Aws::String>::const_iterator foundValue = headerMap.find(StringUtils::ToLower(headerName.c_str())); - return foundValue->second; -} - -void StandardHttpResponse::AddHeader(const Aws::String& headerName, const Aws::String& headerValue) -{ - headerMap[StringUtils::ToLower(headerName.c_str())] = headerValue; -} - - + +#include <aws/core/http/standard/StandardHttpResponse.h> + +#include <aws/core/utils/StringUtils.h> +#include <aws/core/utils/memory/AWSMemory.h> + +#include <istream> + +using namespace Aws::Http; +using namespace Aws::Http::Standard; +using namespace Aws::Utils; + + +HeaderValueCollection StandardHttpResponse::GetHeaders() const +{ + HeaderValueCollection headerValueCollection; + + for (Aws::Map<Aws::String, Aws::String>::const_iterator iter = headerMap.begin(); iter != headerMap.end(); ++iter) + { + headerValueCollection.emplace(HeaderValuePair(iter->first, iter->second)); + } + + return headerValueCollection; +} + +bool StandardHttpResponse::HasHeader(const char* headerName) const +{ + return headerMap.find(StringUtils::ToLower(headerName)) != headerMap.end(); +} + +const Aws::String& StandardHttpResponse::GetHeader(const Aws::String& headerName) const +{ + Aws::Map<Aws::String, Aws::String>::const_iterator foundValue = headerMap.find(StringUtils::ToLower(headerName.c_str())); + return foundValue->second; +} + +void StandardHttpResponse::AddHeader(const Aws::String& headerName, const Aws::String& headerValue) +{ + headerMap[StringUtils::ToLower(headerName.c_str())] = headerValue; +} + + diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/internal/AWSHttpResourceClient.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/internal/AWSHttpResourceClient.cpp index 24145e4d92..b69c7f5b5d 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/internal/AWSHttpResourceClient.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/internal/AWSHttpResourceClient.cpp @@ -2,30 +2,30 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/internal/AWSHttpResourceClient.h> -#include <aws/core/client/DefaultRetryStrategy.h> -#include <aws/core/http/HttpClient.h> -#include <aws/core/http/HttpClientFactory.h> -#include <aws/core/http/HttpResponse.h> -#include <aws/core/utils/logging/LogMacros.h> -#include <aws/core/utils/StringUtils.h> + +#include <aws/core/internal/AWSHttpResourceClient.h> +#include <aws/core/client/DefaultRetryStrategy.h> +#include <aws/core/http/HttpClient.h> +#include <aws/core/http/HttpClientFactory.h> +#include <aws/core/http/HttpResponse.h> +#include <aws/core/utils/logging/LogMacros.h> +#include <aws/core/utils/StringUtils.h> #include <aws/core/utils/HashingUtils.h> -#include <aws/core/platform/Environment.h> -#include <aws/core/client/AWSError.h> -#include <aws/core/client/CoreErrors.h> +#include <aws/core/platform/Environment.h> +#include <aws/core/client/AWSError.h> +#include <aws/core/client/CoreErrors.h> #include <aws/core/utils/xml/XmlSerializer.h> #include <mutex> -#include <sstream> - +#include <sstream> + using namespace Aws; -using namespace Aws::Utils; -using namespace Aws::Utils::Logging; +using namespace Aws::Utils; +using namespace Aws::Utils::Logging; using namespace Aws::Utils::Xml; -using namespace Aws::Http; -using namespace Aws::Client; -using namespace Aws::Internal; - +using namespace Aws::Http; +using namespace Aws::Client; +using namespace Aws::Internal; + static const char EC2_SECURITY_CREDENTIALS_RESOURCE[] = "/latest/meta-data/iam/security-credentials"; static const char EC2_REGION_RESOURCE[] = "/latest/meta-data/placement/availability-zone"; static const char EC2_IMDS_TOKEN_RESOURCE[] = "/latest/api/token"; @@ -35,7 +35,7 @@ static const char EC2_IMDS_TOKEN_HEADER[] = "x-aws-ec2-metadata-token"; static const char RESOURCE_CLIENT_CONFIGURATION_ALLOCATION_TAG[] = "AWSHttpResourceClient"; static const char EC2_METADATA_CLIENT_LOG_TAG[] = "EC2MetadataClient"; static const char ECS_CREDENTIALS_CLIENT_LOG_TAG[] = "ECSCredentialsClient"; - + namespace Aws { namespace Client @@ -48,10 +48,10 @@ namespace Aws static ClientConfiguration MakeDefaultHttpResourceClientConfiguration(const char *logtag) { ClientConfiguration res; - + res.maxConnections = 2; res.scheme = Scheme::HTTP; - + #if defined(WIN32) && defined(BYPASS_DEFAULT_PROXY) // For security reasons, we must bypass any proxy settings when fetching sensitive information, for example // user credentials. On Windows, IXMLHttpRequest2 does not support bypassing proxy settings, therefore, @@ -67,16 +67,16 @@ namespace Aws res.proxyUserName = ""; res.proxyPassword = ""; res.proxyPort = 0; - + // EC2MetadataService throttles by delaying the response so the service client should set a large read timeout. // EC2MetadataService delay is in order of seconds so it only make sense to retry after a couple of seconds. res.connectTimeoutMs = 1000; res.requestTimeoutMs = 1000; res.retryStrategy = Aws::MakeShared<DefaultRetryStrategy>(RESOURCE_CLIENT_CONFIGURATION_ALLOCATION_TAG, 1, 1000); - + return res; } - + AWSHttpResourceClient::AWSHttpResourceClient(const Aws::Client::ClientConfiguration& clientConfiguration, const char* logtag) : m_logtag(logtag), m_retryStrategy(clientConfiguration.retryStrategy), m_httpClient(nullptr) { @@ -85,24 +85,24 @@ namespace Aws << clientConfiguration.maxConnections << " and scheme " << SchemeMapper::ToString(clientConfiguration.scheme)); - + m_httpClient = CreateHttpClient(clientConfiguration); } - + AWSHttpResourceClient::AWSHttpResourceClient(const char* logtag) : AWSHttpResourceClient(MakeDefaultHttpResourceClientConfiguration(logtag), logtag) { } - + AWSHttpResourceClient::~AWSHttpResourceClient() { } - + Aws::String AWSHttpResourceClient::GetResource(const char* endpoint, const char* resource, const char* authToken) const { return GetResourceWithAWSWebServiceResult(endpoint, resource, authToken).GetPayload(); } - + AmazonWebServiceResult<Aws::String> AWSHttpResourceClient::GetResourceWithAWSWebServiceResult(const char *endpoint, const char *resource, const char *authToken) const { Aws::StringStream ss; @@ -113,7 +113,7 @@ namespace Aws } std::shared_ptr<HttpRequest> request(CreateHttpRequest(ss.str(), HttpMethod::HTTP_GET, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod)); - + request->SetUserAgent(ComputeUserAgentString()); if (authToken) @@ -125,7 +125,7 @@ namespace Aws } AmazonWebServiceResult<Aws::String> AWSHttpResourceClient::GetResourceWithAWSWebServiceResult(const std::shared_ptr<HttpRequest> &httpRequest) const - { + { AWS_LOGSTREAM_TRACE(m_logtag.c_str(), "Retrieving credentials from " << httpRequest->GetURIString()); for (long retries = 0;; retries++) @@ -167,18 +167,18 @@ namespace Aws AWS_LOGSTREAM_WARN(m_logtag.c_str(), "Request failed, now waiting " << sleepMillis << " ms before attempting again."); m_httpClient->RetryRequestSleep(std::chrono::milliseconds(sleepMillis)); } - } - + } + EC2MetadataClient::EC2MetadataClient(const char* endpoint) : AWSHttpResourceClient(EC2_METADATA_CLIENT_LOG_TAG), m_endpoint(endpoint), m_tokenRequired(true) { } - + EC2MetadataClient::EC2MetadataClient(const Aws::Client::ClientConfiguration &clientConfiguration, const char *endpoint) : AWSHttpResourceClient(clientConfiguration, EC2_METADATA_CLIENT_LOG_TAG), m_endpoint(endpoint), m_tokenRequired(true) - { - } - + { + } + EC2MetadataClient::~EC2MetadataClient() { @@ -193,9 +193,9 @@ namespace Aws { std::unique_lock<std::recursive_mutex> locker(m_tokenMutex); if (m_tokenRequired) - { + { return GetDefaultCredentialsSecurely(); - } + } AWS_LOGSTREAM_TRACE(m_logtag.c_str(), "Getting default credentials for ec2 instance"); auto result = GetResourceWithAWSWebServiceResult(m_endpoint.c_str(), EC2_SECURITY_CREDENTIALS_RESOURCE, nullptr); @@ -206,12 +206,12 @@ namespace Aws // then when we fall back to insecure call, it might return 401 ask for secure call, // Then, SDK might get into a recursive loop call situation between secure and insecure call. if (httpResponseCode == Http::HttpResponseCode::UNAUTHORIZED) - { + { m_tokenRequired = true; return {}; } locker.unlock(); - + Aws::String trimmedCredentialsString = StringUtils::Trim(credentialsString.c_str()); if (trimmedCredentialsString.empty()) return {}; @@ -224,8 +224,8 @@ namespace Aws { AWS_LOGSTREAM_WARN(m_logtag.c_str(), "Initial call to ec2Metadataservice to get credentials failed"); return {}; - } - + } + Aws::StringStream ss; ss << EC2_SECURITY_CREDENTIALS_RESOURCE << "/" << securityCredentials[0]; AWS_LOGSTREAM_DEBUG(m_logtag.c_str(), "Calling EC2MetadataService resource " << ss.str()); @@ -233,7 +233,7 @@ namespace Aws } Aws::String EC2MetadataClient::GetDefaultCredentialsSecurely() const - { + { std::unique_lock<std::recursive_mutex> locker(m_tokenMutex); if (!m_tokenRequired) { @@ -291,17 +291,17 @@ namespace Aws credentialsRequest->SetUserAgent(userAgentString); AWS_LOGSTREAM_DEBUG(m_logtag.c_str(), "Calling EC2MetadataService resource " << ss.str() << " with token."); return GetResourceWithAWSWebServiceResult(credentialsRequest).GetPayload(); - } - + } + Aws::String EC2MetadataClient::GetCurrentRegion() const { if (!m_region.empty()) { return m_region; } - + AWS_LOGSTREAM_TRACE(m_logtag.c_str(), "Getting current region for ec2 instance"); - + Aws::StringStream ss; ss << m_endpoint << EC2_REGION_RESOURCE; std::shared_ptr<HttpRequest> regionRequest(CreateHttpRequest(ss.str(), HttpMethod::HTTP_GET, @@ -315,21 +315,21 @@ namespace Aws } regionRequest->SetUserAgent(ComputeUserAgentString()); Aws::String azString = GetResourceWithAWSWebServiceResult(regionRequest).GetPayload(); - + if (azString.empty()) { AWS_LOGSTREAM_INFO(m_logtag.c_str() , "Unable to pull region from instance metadata service "); return {}; } - + Aws::String trimmedAZString = StringUtils::Trim(azString.c_str()); AWS_LOGSTREAM_DEBUG(m_logtag.c_str(), "Calling EC2MetadataService resource " << EC2_REGION_RESOURCE << " , returned credential string " << trimmedAZString); - + Aws::String region; region.reserve(trimmedAZString.length()); - + bool digitFound = false; for (auto character : trimmedAZString) { @@ -341,15 +341,15 @@ namespace Aws { digitFound = true; } - + region.append(1, character); } - + AWS_LOGSTREAM_INFO(m_logtag.c_str(), "Detected current region as " << region); m_region = region; return region; } - + #ifdef _MSC_VER // VS2015 compiler's bug, warning s_ec2metadataClient: symbol will be dynamically initialized (implementation limitation) AWS_SUPPRESS_WARNING(4592, @@ -358,7 +358,7 @@ namespace Aws #else static std::shared_ptr<EC2MetadataClient> s_ec2metadataClient(nullptr); #endif - + void InitEC2MetadataClient() { if (s_ec2metadataClient) @@ -367,7 +367,7 @@ namespace Aws } s_ec2metadataClient = Aws::MakeShared<EC2MetadataClient>(EC2_METADATA_CLIENT_LOG_TAG); } - + void CleanupEC2MetadataClient() { if (!s_ec2metadataClient) @@ -376,31 +376,31 @@ namespace Aws } s_ec2metadataClient = nullptr; } - + std::shared_ptr<EC2MetadataClient> GetEC2MetadataClient() { return s_ec2metadataClient; } - - + + ECSCredentialsClient::ECSCredentialsClient(const char* resourcePath, const char* endpoint, const char* token) : AWSHttpResourceClient(ECS_CREDENTIALS_CLIENT_LOG_TAG), m_resourcePath(resourcePath), m_endpoint(endpoint), m_token(token) - { - } + { + } ECSCredentialsClient::ECSCredentialsClient(const Aws::Client::ClientConfiguration& clientConfiguration, const char* resourcePath, const char* endpoint, const char* token) : AWSHttpResourceClient(clientConfiguration, ECS_CREDENTIALS_CLIENT_LOG_TAG), m_resourcePath(resourcePath), m_endpoint(endpoint), m_token(token) - { - } - + { + } + static const char STS_RESOURCE_CLIENT_LOG_TAG[] = "STSResourceClient"; STSCredentialsClient::STSCredentialsClient(const Aws::Client::ClientConfiguration& clientConfiguration) : AWSHttpResourceClient(clientConfiguration, STS_RESOURCE_CLIENT_LOG_TAG) { SetErrorMarshaller(Aws::MakeUnique<Aws::Client::XmlErrorMarshaller>(STS_RESOURCE_CLIENT_LOG_TAG)); - + Aws::StringStream ss; if (clientConfiguration.scheme == Aws::Http::Scheme::HTTP) { @@ -410,11 +410,11 @@ namespace Aws { ss << "https://"; } - + static const int CN_NORTH_1_HASH = Aws::Utils::HashingUtils::HashString(Aws::Region::CN_NORTH_1); static const int CN_NORTHWEST_1_HASH = Aws::Utils::HashingUtils::HashString(Aws::Region::CN_NORTHWEST_1); auto hash = Aws::Utils::HashingUtils::HashString(clientConfiguration.region.c_str()); - + ss << "sts." << clientConfiguration.region << ".amazonaws.com"; if (hash == CN_NORTH_1_HASH || hash == CN_NORTHWEST_1_HASH) { @@ -503,4 +503,4 @@ namespace Aws return result; } } -} +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/monitoring/DefaultMonitoring.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/monitoring/DefaultMonitoring.cpp index 9953004bc3..28b0cd97b9 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/monitoring/DefaultMonitoring.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/monitoring/DefaultMonitoring.cpp @@ -2,109 +2,109 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/utils/memory/AWSMemory.h> -#include <aws/core/monitoring/DefaultMonitoring.h> -#include <aws/core/utils/DateTime.h> -#include <aws/core/utils/json/JsonSerializer.h> -#include <aws/core/utils/Outcome.h> -#include <aws/core/client/AWSClient.h> -#include <aws/core/auth/AWSCredentialsProvider.h> -#include <aws/core/platform/Environment.h> -#include <aws/core/config/AWSProfileConfigLoader.h> -#include <aws/core/utils/logging/LogMacros.h> -using namespace Aws::Utils; - -namespace Aws -{ - namespace Monitoring - { - static const char DEFAULT_MONITORING_ALLOC_TAG[] = "DefaultMonitoringAllocTag"; - static const int CLIENT_ID_LENGTH_LIMIT = 256; + +#include <aws/core/utils/memory/AWSMemory.h> +#include <aws/core/monitoring/DefaultMonitoring.h> +#include <aws/core/utils/DateTime.h> +#include <aws/core/utils/json/JsonSerializer.h> +#include <aws/core/utils/Outcome.h> +#include <aws/core/client/AWSClient.h> +#include <aws/core/auth/AWSCredentialsProvider.h> +#include <aws/core/platform/Environment.h> +#include <aws/core/config/AWSProfileConfigLoader.h> +#include <aws/core/utils/logging/LogMacros.h> +using namespace Aws::Utils; + +namespace Aws +{ + namespace Monitoring + { + static const char DEFAULT_MONITORING_ALLOC_TAG[] = "DefaultMonitoringAllocTag"; + static const int CLIENT_ID_LENGTH_LIMIT = 256; static const int USER_AGENT_LENGTH_LIMIT = 256; - static const int ERROR_MESSAGE_LENGTH_LIMIT = 512; - - const char DEFAULT_MONITORING_CLIENT_ID[] = ""; // default to empty; + static const int ERROR_MESSAGE_LENGTH_LIMIT = 512; + + const char DEFAULT_MONITORING_CLIENT_ID[] = ""; // default to empty; const char DEFAULT_MONITORING_HOST[] = "127.0.0.1"; // default to loopback ip address instead of "localhost" based on design specification. - unsigned short DEFAULT_MONITORING_PORT = 31000; //default to 31000; - bool DEFAULT_MONITORING_ENABLE = false; //default to false; - - const int DefaultMonitoring::DEFAULT_MONITORING_VERSION = 1; - const char DefaultMonitoring::DEFAULT_CSM_CONFIG_ENABLED[] = "csm_enabled"; - const char DefaultMonitoring::DEFAULT_CSM_CONFIG_CLIENT_ID[] = "csm_client_id"; + unsigned short DEFAULT_MONITORING_PORT = 31000; //default to 31000; + bool DEFAULT_MONITORING_ENABLE = false; //default to false; + + const int DefaultMonitoring::DEFAULT_MONITORING_VERSION = 1; + const char DefaultMonitoring::DEFAULT_CSM_CONFIG_ENABLED[] = "csm_enabled"; + const char DefaultMonitoring::DEFAULT_CSM_CONFIG_CLIENT_ID[] = "csm_client_id"; const char DefaultMonitoring::DEFAULT_CSM_CONFIG_HOST[] = "csm_host"; - const char DefaultMonitoring::DEFAULT_CSM_CONFIG_PORT[] = "csm_port"; - const char DefaultMonitoring::DEFAULT_CSM_ENVIRONMENT_VAR_ENABLED[] = "AWS_CSM_ENABLED"; - const char DefaultMonitoring::DEFAULT_CSM_ENVIRONMENT_VAR_CLIENT_ID[] = "AWS_CSM_CLIENT_ID"; + const char DefaultMonitoring::DEFAULT_CSM_CONFIG_PORT[] = "csm_port"; + const char DefaultMonitoring::DEFAULT_CSM_ENVIRONMENT_VAR_ENABLED[] = "AWS_CSM_ENABLED"; + const char DefaultMonitoring::DEFAULT_CSM_ENVIRONMENT_VAR_CLIENT_ID[] = "AWS_CSM_CLIENT_ID"; const char DefaultMonitoring::DEFAULT_CSM_ENVIRONMENT_VAR_HOST[] = "AWS_CSM_HOST"; - const char DefaultMonitoring::DEFAULT_CSM_ENVIRONMENT_VAR_PORT[] = "AWS_CSM_PORT"; - - - struct DefaultContext - { - Aws::Utils::DateTime apiCallStartTime; - Aws::Utils::DateTime attemptStartTime; - int retryCount = 0; + const char DefaultMonitoring::DEFAULT_CSM_ENVIRONMENT_VAR_PORT[] = "AWS_CSM_PORT"; + + + struct DefaultContext + { + Aws::Utils::DateTime apiCallStartTime; + Aws::Utils::DateTime attemptStartTime; + int retryCount = 0; bool lastAttemptSucceeded = false; bool lastErrorRetryable = false; //doesn't apply if last attempt succeeded. const Aws::Client::HttpResponseOutcome* outcome = nullptr; - }; - + }; + static inline void FillRequiredFieldsToJson(Json::JsonValue& json, const Aws::String& type, - const Aws::String& service, - const Aws::String& api, - const Aws::String& clientId, - const DateTime& timestamp, + const Aws::String& service, + const Aws::String& api, + const Aws::String& clientId, + const DateTime& timestamp, int version, const Aws::String& userAgent) - { - json.WithString("Type", type) - .WithString("Service", service) - .WithString("Api", api) - .WithString("ClientId", clientId.substr(0, CLIENT_ID_LENGTH_LIMIT)) - .WithInt64("Timestamp", timestamp.Millis()) + { + json.WithString("Type", type) + .WithString("Service", service) + .WithString("Api", api) + .WithString("ClientId", clientId.substr(0, CLIENT_ID_LENGTH_LIMIT)) + .WithInt64("Timestamp", timestamp.Millis()) .WithInteger("Version", version) .WithString("UserAgent", userAgent.substr(0, USER_AGENT_LENGTH_LIMIT)); - } - - static inline void FillRequiredApiCallFieldsToJson(Json::JsonValue& json, - int attemptCount, + } + + static inline void FillRequiredApiCallFieldsToJson(Json::JsonValue& json, + int attemptCount, int64_t apiCallLatency, bool maxRetriesExceeded) - { - json.WithInteger("AttemptCount", attemptCount) + { + json.WithInteger("AttemptCount", attemptCount) .WithInt64("Latency", apiCallLatency) .WithInteger("MaxRetriesExceeded", maxRetriesExceeded ? 1 : 0); - } - - static inline void FillRequiredApiAttemptFieldsToJson(Json::JsonValue& json, - const Aws::String& domainName, - int64_t attemptLatency) - { - json.WithString("Fqdn", domainName) - .WithInt64("AttemptLatency", attemptLatency); - } - + } + + static inline void FillRequiredApiAttemptFieldsToJson(Json::JsonValue& json, + const Aws::String& domainName, + int64_t attemptLatency) + { + json.WithString("Fqdn", domainName) + .WithInt64("AttemptLatency", attemptLatency); + } + static inline void ExportResponseHeaderToJson(Json::JsonValue& json, const Aws::Http::HeaderValueCollection& headers, - const Aws::String& headerName, const Aws::String& targetName) - { - auto iter = headers.find(headerName); - if (iter != headers.end()) - { - json.WithString(targetName, iter->second); - } - } - - static inline void ExportHttpMetricsToJson(Json::JsonValue& json, const Aws::Monitoring::HttpClientMetricsCollection& httpMetrics, Aws::Monitoring::HttpClientMetricsType type) - { - auto iter = httpMetrics.find(GetHttpClientMetricNameByType(type)); - if (iter != httpMetrics.end()) - { - json.WithInt64(GetHttpClientMetricNameByType(type), iter->second); - } - } - + const Aws::String& headerName, const Aws::String& targetName) + { + auto iter = headers.find(headerName); + if (iter != headers.end()) + { + json.WithString(targetName, iter->second); + } + } + + static inline void ExportHttpMetricsToJson(Json::JsonValue& json, const Aws::Monitoring::HttpClientMetricsCollection& httpMetrics, Aws::Monitoring::HttpClientMetricsType type) + { + auto iter = httpMetrics.find(GetHttpClientMetricNameByType(type)); + if (iter != httpMetrics.end()) + { + json.WithInt64(GetHttpClientMetricNameByType(type), iter->second); + } + } + static inline void FillOptionalApiCallFieldsToJson(Json::JsonValue& json, const Aws::Http::HttpRequest* request, const Aws::Client::HttpResponseOutcome& outcome) @@ -132,155 +132,155 @@ namespace Aws } } - static inline void FillOptionalApiAttemptFieldsToJson(Json::JsonValue& json, + static inline void FillOptionalApiAttemptFieldsToJson(Json::JsonValue& json, const Aws::Http::HttpRequest* request, - const Aws::Client::HttpResponseOutcome& outcome, - const CoreMetricsCollection& metricsFromCore) - { - /** - *No matter request succeeded or not, these fields should be included as long as their requirements + const Aws::Client::HttpResponseOutcome& outcome, + const CoreMetricsCollection& metricsFromCore) + { + /** + *No matter request succeeded or not, these fields should be included as long as their requirements *are met. We should be able to access response (so as to access original request) if the response has error. - */ - if (request->HasAwsSessionToken() && !request->GetAwsSessionToken().empty()) - { - json.WithString("SessionToken", request->GetAwsSessionToken()); - } - if (!request->GetSigningRegion().empty()) - { - json.WithString("Region", request->GetSigningRegion()); - } - if (!request->GetSigningAccessKey().empty()) - { - json.WithString("AccessKey", request->GetSigningAccessKey()); - } - - const auto& headers = outcome.IsSuccess() ? outcome.GetResult()->GetHeaders() : outcome.GetError().GetResponseHeaders(); - - ExportResponseHeaderToJson(json, headers, StringUtils::ToLower("x-amzn-RequestId"), "XAmznRequestId"); - ExportResponseHeaderToJson(json, headers, StringUtils::ToLower("x-amz-request-id"), "XAmzRequestId"); - ExportResponseHeaderToJson(json, headers, StringUtils::ToLower("x-amz-id-2"), "XAmzId2"); - - if (!outcome.IsSuccess()) - { + */ + if (request->HasAwsSessionToken() && !request->GetAwsSessionToken().empty()) + { + json.WithString("SessionToken", request->GetAwsSessionToken()); + } + if (!request->GetSigningRegion().empty()) + { + json.WithString("Region", request->GetSigningRegion()); + } + if (!request->GetSigningAccessKey().empty()) + { + json.WithString("AccessKey", request->GetSigningAccessKey()); + } + + const auto& headers = outcome.IsSuccess() ? outcome.GetResult()->GetHeaders() : outcome.GetError().GetResponseHeaders(); + + ExportResponseHeaderToJson(json, headers, StringUtils::ToLower("x-amzn-RequestId"), "XAmznRequestId"); + ExportResponseHeaderToJson(json, headers, StringUtils::ToLower("x-amz-request-id"), "XAmzRequestId"); + ExportResponseHeaderToJson(json, headers, StringUtils::ToLower("x-amz-id-2"), "XAmzId2"); + + if (!outcome.IsSuccess()) + { if (outcome.GetError().GetExceptionName().empty()) // Not Aws Exception - { + { json.WithString("SdkExceptionMessage", outcome.GetError().GetMessage().substr(0, ERROR_MESSAGE_LENGTH_LIMIT)); - } - else // Aws Exception - { + } + else // Aws Exception + { json.WithString("AwsException", outcome.GetError().GetExceptionName()) .WithString("AwsExceptionMessage", outcome.GetError().GetMessage().substr(0, ERROR_MESSAGE_LENGTH_LIMIT)); - } + } json.WithInteger("HttpStatusCode", static_cast<int>(outcome.GetError().GetResponseCode())); - } + } else { json.WithInteger("HttpStatusCode", static_cast<int>(outcome.GetResult()->GetResponseCode())); } - - // Optional MetricsCollectedFromCore - ExportHttpMetricsToJson(json, metricsFromCore.httpClientMetrics, HttpClientMetricsType::AcquireConnectionLatency); - ExportHttpMetricsToJson(json, metricsFromCore.httpClientMetrics, HttpClientMetricsType::ConnectionReused); - ExportHttpMetricsToJson(json, metricsFromCore.httpClientMetrics, HttpClientMetricsType::ConnectLatency); - ExportHttpMetricsToJson(json, metricsFromCore.httpClientMetrics, HttpClientMetricsType::DestinationIp); - ExportHttpMetricsToJson(json, metricsFromCore.httpClientMetrics, HttpClientMetricsType::DnsLatency); - ExportHttpMetricsToJson(json, metricsFromCore.httpClientMetrics, HttpClientMetricsType::RequestLatency); - ExportHttpMetricsToJson(json, metricsFromCore.httpClientMetrics, HttpClientMetricsType::SslLatency); - ExportHttpMetricsToJson(json, metricsFromCore.httpClientMetrics, HttpClientMetricsType::TcpLatency); - } - + + // Optional MetricsCollectedFromCore + ExportHttpMetricsToJson(json, metricsFromCore.httpClientMetrics, HttpClientMetricsType::AcquireConnectionLatency); + ExportHttpMetricsToJson(json, metricsFromCore.httpClientMetrics, HttpClientMetricsType::ConnectionReused); + ExportHttpMetricsToJson(json, metricsFromCore.httpClientMetrics, HttpClientMetricsType::ConnectLatency); + ExportHttpMetricsToJson(json, metricsFromCore.httpClientMetrics, HttpClientMetricsType::DestinationIp); + ExportHttpMetricsToJson(json, metricsFromCore.httpClientMetrics, HttpClientMetricsType::DnsLatency); + ExportHttpMetricsToJson(json, metricsFromCore.httpClientMetrics, HttpClientMetricsType::RequestLatency); + ExportHttpMetricsToJson(json, metricsFromCore.httpClientMetrics, HttpClientMetricsType::SslLatency); + ExportHttpMetricsToJson(json, metricsFromCore.httpClientMetrics, HttpClientMetricsType::TcpLatency); + } + DefaultMonitoring::DefaultMonitoring(const Aws::String& clientId, const Aws::String& host, unsigned short port): m_udp(host.c_str(), port), m_clientId(clientId) - { - } - - void* DefaultMonitoring::OnRequestStarted(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr<const Aws::Http::HttpRequest>& request) const - { - AWS_UNREFERENCED_PARAM(request); - - AWS_LOGSTREAM_DEBUG(DEFAULT_MONITORING_ALLOC_TAG, "OnRequestStart Service: " << serviceName << "Request: " << requestName); - auto context = Aws::New<DefaultContext>(DEFAULT_MONITORING_ALLOC_TAG); - context->apiCallStartTime = Aws::Utils::DateTime::Now(); - context->attemptStartTime = context->apiCallStartTime; - context->retryCount = 0; - return context; - } - - - void DefaultMonitoring::OnRequestSucceeded(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr<const Aws::Http::HttpRequest>& request, - const Aws::Client::HttpResponseOutcome& outcome, const CoreMetricsCollection& metricsFromCore, void* context) const - { - AWS_LOGSTREAM_DEBUG(DEFAULT_MONITORING_ALLOC_TAG, "OnRequestSucceeded Service: " << serviceName << "Request: " << requestName); - CollectAndSendAttemptData(serviceName, requestName, request, outcome, metricsFromCore, context); - } - - void DefaultMonitoring::OnRequestFailed(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr<const Aws::Http::HttpRequest>& request, - const Aws::Client::HttpResponseOutcome& outcome, const CoreMetricsCollection& metricsFromCore, void* context) const - { - AWS_LOGSTREAM_DEBUG(DEFAULT_MONITORING_ALLOC_TAG, "OnRequestFailed Service: " << serviceName << "Request: " << requestName); - CollectAndSendAttemptData(serviceName, requestName, request, outcome, metricsFromCore, context); - } - + { + } + + void* DefaultMonitoring::OnRequestStarted(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr<const Aws::Http::HttpRequest>& request) const + { + AWS_UNREFERENCED_PARAM(request); + + AWS_LOGSTREAM_DEBUG(DEFAULT_MONITORING_ALLOC_TAG, "OnRequestStart Service: " << serviceName << "Request: " << requestName); + auto context = Aws::New<DefaultContext>(DEFAULT_MONITORING_ALLOC_TAG); + context->apiCallStartTime = Aws::Utils::DateTime::Now(); + context->attemptStartTime = context->apiCallStartTime; + context->retryCount = 0; + return context; + } + + + void DefaultMonitoring::OnRequestSucceeded(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr<const Aws::Http::HttpRequest>& request, + const Aws::Client::HttpResponseOutcome& outcome, const CoreMetricsCollection& metricsFromCore, void* context) const + { + AWS_LOGSTREAM_DEBUG(DEFAULT_MONITORING_ALLOC_TAG, "OnRequestSucceeded Service: " << serviceName << "Request: " << requestName); + CollectAndSendAttemptData(serviceName, requestName, request, outcome, metricsFromCore, context); + } + + void DefaultMonitoring::OnRequestFailed(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr<const Aws::Http::HttpRequest>& request, + const Aws::Client::HttpResponseOutcome& outcome, const CoreMetricsCollection& metricsFromCore, void* context) const + { + AWS_LOGSTREAM_DEBUG(DEFAULT_MONITORING_ALLOC_TAG, "OnRequestFailed Service: " << serviceName << "Request: " << requestName); + CollectAndSendAttemptData(serviceName, requestName, request, outcome, metricsFromCore, context); + } + void DefaultMonitoring::OnRequestRetry(const Aws::String& serviceName, const Aws::String& requestName, - const std::shared_ptr<const Aws::Http::HttpRequest>& request, void* context) const - { - AWS_UNREFERENCED_PARAM(request); - - DefaultContext* defaultContext = static_cast<DefaultContext*>(context); - defaultContext->retryCount++; - defaultContext->attemptStartTime = Aws::Utils::DateTime::Now(); - AWS_LOGSTREAM_DEBUG(DEFAULT_MONITORING_ALLOC_TAG, "OnRequestRetry Service: " << serviceName << "Request: " << requestName << " RetryCnt:" << defaultContext->retryCount); - } - + const std::shared_ptr<const Aws::Http::HttpRequest>& request, void* context) const + { + AWS_UNREFERENCED_PARAM(request); + + DefaultContext* defaultContext = static_cast<DefaultContext*>(context); + defaultContext->retryCount++; + defaultContext->attemptStartTime = Aws::Utils::DateTime::Now(); + AWS_LOGSTREAM_DEBUG(DEFAULT_MONITORING_ALLOC_TAG, "OnRequestRetry Service: " << serviceName << "Request: " << requestName << " RetryCnt:" << defaultContext->retryCount); + } + void DefaultMonitoring::OnFinish(const Aws::String& serviceName, const Aws::String& requestName, - const std::shared_ptr<const Aws::Http::HttpRequest>& request, void* context) const - { - AWS_UNREFERENCED_PARAM(request); - AWS_LOGSTREAM_DEBUG(DEFAULT_MONITORING_ALLOC_TAG, "OnRequestFinish Service: " << serviceName << "Request: " << requestName); - + const std::shared_ptr<const Aws::Http::HttpRequest>& request, void* context) const + { + AWS_UNREFERENCED_PARAM(request); + AWS_LOGSTREAM_DEBUG(DEFAULT_MONITORING_ALLOC_TAG, "OnRequestFinish Service: " << serviceName << "Request: " << requestName); + DefaultContext* defaultContext = static_cast<DefaultContext*>(context); - Aws::Utils::Json::JsonValue json; + Aws::Utils::Json::JsonValue json; FillRequiredFieldsToJson(json, "ApiCall", serviceName, requestName, m_clientId, defaultContext->apiCallStartTime, DEFAULT_MONITORING_VERSION, request->GetUserAgent()); FillRequiredApiCallFieldsToJson(json, defaultContext->retryCount + 1, (DateTime::Now() - defaultContext->apiCallStartTime).count(), (!defaultContext->lastAttemptSucceeded && defaultContext->lastErrorRetryable)); FillOptionalApiCallFieldsToJson(json, request.get(), *(defaultContext->outcome)); - Aws::String compactData = json.View().WriteCompact(); + Aws::String compactData = json.View().WriteCompact(); m_udp.SendData(reinterpret_cast<const uint8_t*>(compactData.c_str()), static_cast<int>(compactData.size())); - AWS_LOGSTREAM_DEBUG(DEFAULT_MONITORING_ALLOC_TAG, "Send API Metrics: \n" << json.View().WriteReadable()); - Aws::Delete(defaultContext); - } - - void DefaultMonitoring::CollectAndSendAttemptData(const Aws::String& serviceName, const Aws::String& requestName, + AWS_LOGSTREAM_DEBUG(DEFAULT_MONITORING_ALLOC_TAG, "Send API Metrics: \n" << json.View().WriteReadable()); + Aws::Delete(defaultContext); + } + + void DefaultMonitoring::CollectAndSendAttemptData(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr<const Aws::Http::HttpRequest>& request, const Aws::Client::HttpResponseOutcome& outcome, - const CoreMetricsCollection& metricsFromCore, void* context) const - { + const CoreMetricsCollection& metricsFromCore, void* context) const + { DefaultContext* defaultContext = static_cast<DefaultContext*>(context); defaultContext->outcome = &outcome; defaultContext->lastAttemptSucceeded = outcome.IsSuccess() ? true : false; defaultContext->lastErrorRetryable = (!outcome.IsSuccess() && outcome.GetError().ShouldRetry()) ? true : false; - Aws::Utils::Json::JsonValue json; + Aws::Utils::Json::JsonValue json; FillRequiredFieldsToJson(json, "ApiCallAttempt", serviceName, requestName, m_clientId, defaultContext->attemptStartTime, DEFAULT_MONITORING_VERSION, request->GetUserAgent()); FillRequiredApiAttemptFieldsToJson(json, request->GetUri().GetAuthority(), (DateTime::Now() - defaultContext->attemptStartTime).count()); FillOptionalApiAttemptFieldsToJson(json, request.get(), outcome, metricsFromCore); - Aws::String compactData = json.View().WriteCompact(); - AWS_LOGSTREAM_DEBUG(DEFAULT_MONITORING_ALLOC_TAG, "Send Attempt Metrics: \n" << json.View().WriteReadable()); + Aws::String compactData = json.View().WriteCompact(); + AWS_LOGSTREAM_DEBUG(DEFAULT_MONITORING_ALLOC_TAG, "Send Attempt Metrics: \n" << json.View().WriteReadable()); m_udp.SendData(reinterpret_cast<const uint8_t*>(compactData.c_str()), static_cast<int>(compactData.size())); - } - - Aws::UniquePtr<MonitoringInterface> DefaultMonitoringFactory::CreateMonitoringInstance() const + } + + Aws::UniquePtr<MonitoringInterface> DefaultMonitoringFactory::CreateMonitoringInstance() const { - Aws::String clientId(DEFAULT_MONITORING_CLIENT_ID); // default to empty + Aws::String clientId(DEFAULT_MONITORING_CLIENT_ID); // default to empty Aws::String host(DEFAULT_MONITORING_HOST); // default to 127.0.0.1 - unsigned short port = DEFAULT_MONITORING_PORT; // default to 31000 - bool enable = DEFAULT_MONITORING_ENABLE; //default to false; - - //check profile_config + unsigned short port = DEFAULT_MONITORING_PORT; // default to 31000 + bool enable = DEFAULT_MONITORING_ENABLE; //default to false; + + //check profile_config Aws::String tmpEnable = Aws::Config::GetCachedConfigValue(DefaultMonitoring::DEFAULT_CSM_CONFIG_ENABLED); Aws::String tmpClientId = Aws::Config::GetCachedConfigValue(DefaultMonitoring::DEFAULT_CSM_CONFIG_CLIENT_ID); Aws::String tmpHost = Aws::Config::GetCachedConfigValue(DefaultMonitoring::DEFAULT_CSM_CONFIG_HOST); Aws::String tmpPort = Aws::Config::GetCachedConfigValue(DefaultMonitoring::DEFAULT_CSM_CONFIG_PORT); - + if (!tmpEnable.empty()) - { + { enable = StringUtils::CaselessCompare(tmpEnable.c_str(), "true") ? true : false; AWS_LOGSTREAM_DEBUG(DEFAULT_MONITORING_ALLOC_TAG, "Resolved csm_enabled from profile_config to be " << enable); } @@ -289,52 +289,52 @@ namespace Aws clientId = tmpClientId; AWS_LOGSTREAM_DEBUG(DEFAULT_MONITORING_ALLOC_TAG, "Resolved csm_client_id from profile_config to be " << clientId); } - + if (!tmpHost.empty()) { host = tmpHost; AWS_LOGSTREAM_DEBUG(DEFAULT_MONITORING_ALLOC_TAG, "Resolved csm_host from profile_config to be " << host); - } - + } + if (!tmpPort.empty()) { port = static_cast<short>(StringUtils::ConvertToInt32(tmpPort.c_str())); AWS_LOGSTREAM_DEBUG(DEFAULT_MONITORING_ALLOC_TAG, "Resolved csm_port from profile_config to be " << port); } - // check environment variables + // check environment variables tmpEnable = Aws::Environment::GetEnv(DefaultMonitoring::DEFAULT_CSM_ENVIRONMENT_VAR_ENABLED); tmpClientId = Aws::Environment::GetEnv(DefaultMonitoring::DEFAULT_CSM_ENVIRONMENT_VAR_CLIENT_ID); tmpHost = Aws::Environment::GetEnv(DefaultMonitoring::DEFAULT_CSM_ENVIRONMENT_VAR_HOST); tmpPort = Aws::Environment::GetEnv(DefaultMonitoring::DEFAULT_CSM_ENVIRONMENT_VAR_PORT); - if (!tmpEnable.empty()) - { - enable = StringUtils::CaselessCompare(tmpEnable.c_str(), "true") ? true : false; - AWS_LOGSTREAM_DEBUG(DEFAULT_MONITORING_ALLOC_TAG, "Resolved AWS_CSM_ENABLED from Environment variable to be " << enable); - } - if (!tmpClientId.empty()) - { - clientId = tmpClientId; - AWS_LOGSTREAM_DEBUG(DEFAULT_MONITORING_ALLOC_TAG, "Resolved AWS_CSM_CLIENT_ID from Environment variable to be " << clientId); - - } + if (!tmpEnable.empty()) + { + enable = StringUtils::CaselessCompare(tmpEnable.c_str(), "true") ? true : false; + AWS_LOGSTREAM_DEBUG(DEFAULT_MONITORING_ALLOC_TAG, "Resolved AWS_CSM_ENABLED from Environment variable to be " << enable); + } + if (!tmpClientId.empty()) + { + clientId = tmpClientId; + AWS_LOGSTREAM_DEBUG(DEFAULT_MONITORING_ALLOC_TAG, "Resolved AWS_CSM_CLIENT_ID from Environment variable to be " << clientId); + + } if (!tmpHost.empty()) { host = tmpHost; AWS_LOGSTREAM_DEBUG(DEFAULT_MONITORING_ALLOC_TAG, "Resolved AWS_CSM_HOST from Environment variable to be " << host); } - if (!tmpPort.empty()) - { - port = static_cast<unsigned short>(StringUtils::ConvertToInt32(tmpPort.c_str())); - AWS_LOGSTREAM_DEBUG(DEFAULT_MONITORING_ALLOC_TAG, "Resolved AWS_CSM_PORT from Environment variable to be " << port); - } - - if (!enable) - { - return nullptr; - } + if (!tmpPort.empty()) + { + port = static_cast<unsigned short>(StringUtils::ConvertToInt32(tmpPort.c_str())); + AWS_LOGSTREAM_DEBUG(DEFAULT_MONITORING_ALLOC_TAG, "Resolved AWS_CSM_PORT from Environment variable to be " << port); + } + + if (!enable) + { + return nullptr; + } return Aws::MakeUnique<DefaultMonitoring>(DEFAULT_MONITORING_ALLOC_TAG, clientId, host, port); - } - - } -} + } + + } +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/monitoring/HttpClientMetrics.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/monitoring/HttpClientMetrics.cpp index f3ef582867..ce269c66fb 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/monitoring/HttpClientMetrics.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/monitoring/HttpClientMetrics.cpp @@ -1,71 +1,71 @@ /** * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. - */ - -#include <aws/core/utils/HashingUtils.h> -#include <aws/core/monitoring/HttpClientMetrics.h> - -namespace Aws -{ - namespace Monitoring - { + */ + +#include <aws/core/utils/HashingUtils.h> +#include <aws/core/monitoring/HttpClientMetrics.h> + +namespace Aws +{ + namespace Monitoring + { static const char HTTP_CLIENT_METRICS_DESTINATION_IP[] = "DestinationIp"; - static const char HTTP_CLIENT_METRICS_ACQUIRE_CONNECTION_LATENCY[] = "AcquireConnectionLatency"; - static const char HTTP_CLIENT_METRICS_CONNECTION_REUSED[] = "ConnectionReused"; - static const char HTTP_CLIENT_METRICS_CONNECTION_LATENCY[] = "ConnectLatency"; - static const char HTTP_CLIENT_METRICS_REQUEST_LATENCY[] = "RequestLatency"; - static const char HTTP_CLIENT_METRICS_DNS_LATENCY[] = "DnsLatency"; + static const char HTTP_CLIENT_METRICS_ACQUIRE_CONNECTION_LATENCY[] = "AcquireConnectionLatency"; + static const char HTTP_CLIENT_METRICS_CONNECTION_REUSED[] = "ConnectionReused"; + static const char HTTP_CLIENT_METRICS_CONNECTION_LATENCY[] = "ConnectLatency"; + static const char HTTP_CLIENT_METRICS_REQUEST_LATENCY[] = "RequestLatency"; + static const char HTTP_CLIENT_METRICS_DNS_LATENCY[] = "DnsLatency"; static const char HTTP_CLIENT_METRICS_TCP_LATENCY[] = "TcpLatency"; - static const char HTTP_CLIENT_METRICS_SSL_LATENCY[] = "SslLatency"; - static const char HTTP_CLIENT_METRICS_UNKNOWN[] = "Unknown"; - - using namespace Aws::Utils; - HttpClientMetricsType GetHttpClientMetricTypeByName(const Aws::String& name) - { + static const char HTTP_CLIENT_METRICS_SSL_LATENCY[] = "SslLatency"; + static const char HTTP_CLIENT_METRICS_UNKNOWN[] = "Unknown"; + + using namespace Aws::Utils; + HttpClientMetricsType GetHttpClientMetricTypeByName(const Aws::String& name) + { static std::map<int, HttpClientMetricsType> metricsNameHashToType = - { + { std::pair<int, HttpClientMetricsType>(HashingUtils::HashString(HTTP_CLIENT_METRICS_DESTINATION_IP), HttpClientMetricsType::DestinationIp), - std::pair<int, HttpClientMetricsType>(HashingUtils::HashString(HTTP_CLIENT_METRICS_ACQUIRE_CONNECTION_LATENCY), HttpClientMetricsType::AcquireConnectionLatency), - std::pair<int, HttpClientMetricsType>(HashingUtils::HashString(HTTP_CLIENT_METRICS_CONNECTION_REUSED), HttpClientMetricsType::ConnectionReused), - std::pair<int, HttpClientMetricsType>(HashingUtils::HashString(HTTP_CLIENT_METRICS_CONNECTION_LATENCY), HttpClientMetricsType::ConnectLatency), - std::pair<int, HttpClientMetricsType>(HashingUtils::HashString(HTTP_CLIENT_METRICS_REQUEST_LATENCY), HttpClientMetricsType::RequestLatency), - std::pair<int, HttpClientMetricsType>(HashingUtils::HashString(HTTP_CLIENT_METRICS_DNS_LATENCY), HttpClientMetricsType::DnsLatency), + std::pair<int, HttpClientMetricsType>(HashingUtils::HashString(HTTP_CLIENT_METRICS_ACQUIRE_CONNECTION_LATENCY), HttpClientMetricsType::AcquireConnectionLatency), + std::pair<int, HttpClientMetricsType>(HashingUtils::HashString(HTTP_CLIENT_METRICS_CONNECTION_REUSED), HttpClientMetricsType::ConnectionReused), + std::pair<int, HttpClientMetricsType>(HashingUtils::HashString(HTTP_CLIENT_METRICS_CONNECTION_LATENCY), HttpClientMetricsType::ConnectLatency), + std::pair<int, HttpClientMetricsType>(HashingUtils::HashString(HTTP_CLIENT_METRICS_REQUEST_LATENCY), HttpClientMetricsType::RequestLatency), + std::pair<int, HttpClientMetricsType>(HashingUtils::HashString(HTTP_CLIENT_METRICS_DNS_LATENCY), HttpClientMetricsType::DnsLatency), std::pair<int, HttpClientMetricsType>(HashingUtils::HashString(HTTP_CLIENT_METRICS_TCP_LATENCY), HttpClientMetricsType::TcpLatency), - std::pair<int, HttpClientMetricsType>(HashingUtils::HashString(HTTP_CLIENT_METRICS_SSL_LATENCY), HttpClientMetricsType::SslLatency) - }; - - int nameHash = HashingUtils::HashString(name.c_str()); - auto it = metricsNameHashToType.find(nameHash); - if (it == metricsNameHashToType.end()) - { - return HttpClientMetricsType::Unknown; - } - return it->second; - } - - Aws::String GetHttpClientMetricNameByType(HttpClientMetricsType type) - { + std::pair<int, HttpClientMetricsType>(HashingUtils::HashString(HTTP_CLIENT_METRICS_SSL_LATENCY), HttpClientMetricsType::SslLatency) + }; + + int nameHash = HashingUtils::HashString(name.c_str()); + auto it = metricsNameHashToType.find(nameHash); + if (it == metricsNameHashToType.end()) + { + return HttpClientMetricsType::Unknown; + } + return it->second; + } + + Aws::String GetHttpClientMetricNameByType(HttpClientMetricsType type) + { static std::map<int, std::string> metricsTypeToName = - { + { std::pair<int, std::string>(static_cast<int>(HttpClientMetricsType::DestinationIp), HTTP_CLIENT_METRICS_DESTINATION_IP), - std::pair<int, std::string>(static_cast<int>(HttpClientMetricsType::AcquireConnectionLatency), HTTP_CLIENT_METRICS_ACQUIRE_CONNECTION_LATENCY), - std::pair<int, std::string>(static_cast<int>(HttpClientMetricsType::ConnectionReused), HTTP_CLIENT_METRICS_CONNECTION_REUSED), - std::pair<int, std::string>(static_cast<int>(HttpClientMetricsType::ConnectLatency), HTTP_CLIENT_METRICS_CONNECTION_LATENCY), - std::pair<int, std::string>(static_cast<int>(HttpClientMetricsType::RequestLatency), HTTP_CLIENT_METRICS_REQUEST_LATENCY), - std::pair<int, std::string>(static_cast<int>(HttpClientMetricsType::DnsLatency), HTTP_CLIENT_METRICS_DNS_LATENCY), + std::pair<int, std::string>(static_cast<int>(HttpClientMetricsType::AcquireConnectionLatency), HTTP_CLIENT_METRICS_ACQUIRE_CONNECTION_LATENCY), + std::pair<int, std::string>(static_cast<int>(HttpClientMetricsType::ConnectionReused), HTTP_CLIENT_METRICS_CONNECTION_REUSED), + std::pair<int, std::string>(static_cast<int>(HttpClientMetricsType::ConnectLatency), HTTP_CLIENT_METRICS_CONNECTION_LATENCY), + std::pair<int, std::string>(static_cast<int>(HttpClientMetricsType::RequestLatency), HTTP_CLIENT_METRICS_REQUEST_LATENCY), + std::pair<int, std::string>(static_cast<int>(HttpClientMetricsType::DnsLatency), HTTP_CLIENT_METRICS_DNS_LATENCY), std::pair<int, std::string>(static_cast<int>(HttpClientMetricsType::TcpLatency), HTTP_CLIENT_METRICS_TCP_LATENCY), - std::pair<int, std::string>(static_cast<int>(HttpClientMetricsType::SslLatency), HTTP_CLIENT_METRICS_SSL_LATENCY), - std::pair<int, std::string>(static_cast<int>(HttpClientMetricsType::Unknown), HTTP_CLIENT_METRICS_UNKNOWN) - }; - - auto it = metricsTypeToName.find(static_cast<int>(type)); - if (it == metricsTypeToName.end()) - { - return HTTP_CLIENT_METRICS_UNKNOWN; - } - return Aws::String(it->second.c_str()); - } - - } -} + std::pair<int, std::string>(static_cast<int>(HttpClientMetricsType::SslLatency), HTTP_CLIENT_METRICS_SSL_LATENCY), + std::pair<int, std::string>(static_cast<int>(HttpClientMetricsType::Unknown), HTTP_CLIENT_METRICS_UNKNOWN) + }; + + auto it = metricsTypeToName.find(static_cast<int>(type)); + if (it == metricsTypeToName.end()) + { + return HTTP_CLIENT_METRICS_UNKNOWN; + } + return Aws::String(it->second.c_str()); + } + + } +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/monitoring/MonitoringManager.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/monitoring/MonitoringManager.cpp index 7a8d3adb41..38dccdec44 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/monitoring/MonitoringManager.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/monitoring/MonitoringManager.cpp @@ -1,129 +1,129 @@ /** * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. - */ - -#include <aws/core/utils/memory/AWSMemory.h> -#include <aws/core/monitoring/MonitoringInterface.h> -#include <aws/core/monitoring/MonitoringFactory.h> -#include <aws/core/monitoring/MonitoringManager.h> -#include <aws/core/monitoring/DefaultMonitoring.h> -#include <aws/core/Core_EXPORTS.h> - -#ifdef _MSC_VER -#pragma warning(disable : 4592) -#endif - -namespace Aws -{ - namespace Monitoring - { - typedef Aws::Vector<Aws::UniquePtr<MonitoringInterface>> Monitors; - - const char MonitoringTag[] = "MonitoringAllocTag"; - - /** + */ + +#include <aws/core/utils/memory/AWSMemory.h> +#include <aws/core/monitoring/MonitoringInterface.h> +#include <aws/core/monitoring/MonitoringFactory.h> +#include <aws/core/monitoring/MonitoringManager.h> +#include <aws/core/monitoring/DefaultMonitoring.h> +#include <aws/core/Core_EXPORTS.h> + +#ifdef _MSC_VER +#pragma warning(disable : 4592) +#endif + +namespace Aws +{ + namespace Monitoring + { + typedef Aws::Vector<Aws::UniquePtr<MonitoringInterface>> Monitors; + + const char MonitoringTag[] = "MonitoringAllocTag"; + + /** * Global factory to create global metrics instance. - */ - static Aws::UniquePtr<Monitors> s_monitors; - - Aws::Vector<void*> OnRequestStarted(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr<const Aws::Http::HttpRequest>& request) - { - assert(s_monitors); - Aws::Vector<void*> contexts; - contexts.reserve(s_monitors->size()); + */ + static Aws::UniquePtr<Monitors> s_monitors; + + Aws::Vector<void*> OnRequestStarted(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr<const Aws::Http::HttpRequest>& request) + { + assert(s_monitors); + Aws::Vector<void*> contexts; + contexts.reserve(s_monitors->size()); for (const auto& interface: *s_monitors) - { - contexts.emplace_back(interface->OnRequestStarted(serviceName, requestName, request)); - } - return contexts; - } - - void OnRequestSucceeded(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr<const Aws::Http::HttpRequest>& request, - const Aws::Client::HttpResponseOutcome& outcome, const CoreMetricsCollection& metricsFromCore, const Aws::Vector<void*>& contexts) - { - assert(s_monitors); - assert(contexts.size() == s_monitors->size()); - size_t index = 0; - for (const auto& interface: *s_monitors) - { - interface->OnRequestSucceeded(serviceName, requestName, request, outcome, metricsFromCore, contexts[index++]); - } - } - - void OnRequestFailed(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr<const Aws::Http::HttpRequest>& request, - const Aws::Client::HttpResponseOutcome& outcome, const CoreMetricsCollection& metricsFromCore, const Aws::Vector<void*>& contexts) - { - assert(s_monitors); - assert(contexts.size() == s_monitors->size()); - size_t index = 0; - for (const auto& interface: *s_monitors) - { - interface->OnRequestFailed(serviceName, requestName, request, outcome, metricsFromCore, contexts[index++]); - } - } - + { + contexts.emplace_back(interface->OnRequestStarted(serviceName, requestName, request)); + } + return contexts; + } + + void OnRequestSucceeded(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr<const Aws::Http::HttpRequest>& request, + const Aws::Client::HttpResponseOutcome& outcome, const CoreMetricsCollection& metricsFromCore, const Aws::Vector<void*>& contexts) + { + assert(s_monitors); + assert(contexts.size() == s_monitors->size()); + size_t index = 0; + for (const auto& interface: *s_monitors) + { + interface->OnRequestSucceeded(serviceName, requestName, request, outcome, metricsFromCore, contexts[index++]); + } + } + + void OnRequestFailed(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr<const Aws::Http::HttpRequest>& request, + const Aws::Client::HttpResponseOutcome& outcome, const CoreMetricsCollection& metricsFromCore, const Aws::Vector<void*>& contexts) + { + assert(s_monitors); + assert(contexts.size() == s_monitors->size()); + size_t index = 0; + for (const auto& interface: *s_monitors) + { + interface->OnRequestFailed(serviceName, requestName, request, outcome, metricsFromCore, contexts[index++]); + } + } + void OnRequestRetry(const Aws::String& serviceName, const Aws::String& requestName, - const std::shared_ptr<const Aws::Http::HttpRequest>& request, const Aws::Vector<void*>& contexts) - { - assert(s_monitors); - assert(contexts.size() == s_monitors->size()); - size_t index = 0; - for (const auto& interface: *s_monitors) - { - interface->OnRequestRetry(serviceName, requestName, request, contexts[index++]); - } - } - + const std::shared_ptr<const Aws::Http::HttpRequest>& request, const Aws::Vector<void*>& contexts) + { + assert(s_monitors); + assert(contexts.size() == s_monitors->size()); + size_t index = 0; + for (const auto& interface: *s_monitors) + { + interface->OnRequestRetry(serviceName, requestName, request, contexts[index++]); + } + } + void OnFinish(const Aws::String& serviceName, const Aws::String& requestName, - const std::shared_ptr<const Aws::Http::HttpRequest>& request, const Aws::Vector<void*>& contexts) - { - assert(s_monitors); - assert(contexts.size() == s_monitors->size()); - size_t index = 0; - for (const auto& interface: *s_monitors) - { - interface->OnFinish(serviceName, requestName, request, contexts[index++]); - } - } - - void InitMonitoring(const std::vector<MonitoringFactoryCreateFunction>& monitoringFactoryCreateFunctions) - { - if (s_monitors) - { - return; - } - s_monitors = Aws::MakeUnique<Monitors>(MonitoringTag); - for (const auto& function: monitoringFactoryCreateFunctions) - { - auto factory = function(); - if (factory) - { - auto instance = factory->CreateMonitoringInstance(); - if (instance) - { - s_monitors->emplace_back(std::move(instance)); - } - } - } - - auto defaultMonitoringFactory = Aws::MakeShared<DefaultMonitoringFactory>(MonitoringTag); - auto instance = defaultMonitoringFactory->CreateMonitoringInstance(); - if (instance) - { - s_monitors->emplace_back(std::move(instance)); - } - } - - void CleanupMonitoring() - { - if (!s_monitors) - { - return; - } - - s_monitors = nullptr; - } + const std::shared_ptr<const Aws::Http::HttpRequest>& request, const Aws::Vector<void*>& contexts) + { + assert(s_monitors); + assert(contexts.size() == s_monitors->size()); + size_t index = 0; + for (const auto& interface: *s_monitors) + { + interface->OnFinish(serviceName, requestName, request, contexts[index++]); + } + } + + void InitMonitoring(const std::vector<MonitoringFactoryCreateFunction>& monitoringFactoryCreateFunctions) + { + if (s_monitors) + { + return; + } + s_monitors = Aws::MakeUnique<Monitors>(MonitoringTag); + for (const auto& function: monitoringFactoryCreateFunctions) + { + auto factory = function(); + if (factory) + { + auto instance = factory->CreateMonitoringInstance(); + if (instance) + { + s_monitors->emplace_back(std::move(instance)); + } + } + } + + auto defaultMonitoringFactory = Aws::MakeShared<DefaultMonitoringFactory>(MonitoringTag); + auto instance = defaultMonitoringFactory->CreateMonitoringInstance(); + if (instance) + { + s_monitors->emplace_back(std::move(instance)); + } + } + + void CleanupMonitoring() + { + if (!s_monitors) + { + return; + } + + s_monitors = nullptr; + } } // namespace Monitoring - -} // namespace Aws + +} // namespace Aws diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/net/linux-shared/Net.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/net/linux-shared/Net.cpp index 244df21945..e39cb3dcf5 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/net/linux-shared/Net.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/net/linux-shared/Net.cpp @@ -2,27 +2,27 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/net/Net.h> - -namespace Aws -{ - namespace Net - { - // For Posix system, currently we don't need to do anything for network stack initialization. - // But we need to do initialization for WinSock on Windows and call them in Aws.cpp. So these functions - // also exist for Posix systems. - bool IsNetworkInitiated() - { - return true; - } - - void InitNetwork() - { - } - - void CleanupNetwork() - { - } - } -} + +#include <aws/core/net/Net.h> + +namespace Aws +{ + namespace Net + { + // For Posix system, currently we don't need to do anything for network stack initialization. + // But we need to do initialization for WinSock on Windows and call them in Aws.cpp. So these functions + // also exist for Posix systems. + bool IsNetworkInitiated() + { + return true; + } + + void InitNetwork() + { + } + + void CleanupNetwork() + { + } + } +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/net/linux-shared/SimpleUDP.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/net/linux-shared/SimpleUDP.cpp index d9e0c385fd..446de6689a 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/net/linux-shared/SimpleUDP.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/net/linux-shared/SimpleUDP.cpp @@ -2,35 +2,35 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <sys/types.h> -#include <sys/socket.h> + +#include <sys/types.h> +#include <sys/socket.h> #include <netdb.h> -#include <arpa/inet.h> -#include <netinet/in.h> -#include <unistd.h> -#include <fcntl.h> -#include <cassert> -#include <string.h> -#include <aws/core/net/SimpleUDP.h> -#include <aws/core/utils/logging/LogMacros.h> - -namespace Aws -{ - namespace Net - { - static const char ALLOC_TAG[] = "SimpleUDP"; +#include <arpa/inet.h> +#include <netinet/in.h> +#include <unistd.h> +#include <fcntl.h> +#include <cassert> +#include <string.h> +#include <aws/core/net/SimpleUDP.h> +#include <aws/core/utils/logging/LogMacros.h> + +namespace Aws +{ + namespace Net + { + static const char ALLOC_TAG[] = "SimpleUDP"; static const char IPV4_LOOP_BACK_ADDRESS[] = "127.0.0.1"; static const char IPV6_LOOP_BACK_ADDRESS[] = "::1"; static inline bool IsValidIPAddress(const char* ip, int addressFamily/*AF_INET or AF_INET6*/) - { + { char buffer[128]; return inet_pton(addressFamily, ip, (void*)buffer) == 1 ?true :false; - } - + } + static bool GetASockAddrFromHostName(const char* hostName, void* sockAddrBuffer, size_t& addrLength, int& addressFamily) - { + { struct addrinfo hints, *res; memset(&hints, 0, sizeof(hints)); @@ -47,8 +47,8 @@ namespace Aws addressFamily = res->ai_family; freeaddrinfo(res); return true; - } - + } + static sockaddr_in BuildAddrInfoIPV4(const char* hostIP, short port) { #if (__GNUC__ == 4) && !defined(__clang__) @@ -79,18 +79,18 @@ namespace Aws return addrinfo; } - SimpleUDP::SimpleUDP(int addressFamily, size_t sendBufSize, size_t receiveBufSize, bool nonBlocking): + SimpleUDP::SimpleUDP(int addressFamily, size_t sendBufSize, size_t receiveBufSize, bool nonBlocking): m_addressFamily(addressFamily), m_connected(false), m_socket(-1), m_port(0) - { - CreateSocket(addressFamily, sendBufSize, receiveBufSize, nonBlocking); - } - - SimpleUDP::SimpleUDP(bool IPV4, size_t sendBufSize, size_t receiveBufSize, bool nonBlocking) : + { + CreateSocket(addressFamily, sendBufSize, receiveBufSize, nonBlocking); + } + + SimpleUDP::SimpleUDP(bool IPV4, size_t sendBufSize, size_t receiveBufSize, bool nonBlocking) : m_addressFamily(IPV4 ? AF_INET : AF_INET6), m_connected(false), m_socket(-1), m_port(0) - { - CreateSocket(m_addressFamily, sendBufSize, receiveBufSize, nonBlocking); - } - + { + CreateSocket(m_addressFamily, sendBufSize, receiveBufSize, nonBlocking); + } + SimpleUDP::SimpleUDP(const char* host, unsigned short port, size_t sendBufSize, size_t receiveBufSize, bool nonBlocking) : m_addressFamily(AF_INET), m_connected(false), m_socket(-1), m_port(port) { @@ -131,76 +131,76 @@ namespace Aws CreateSocket(m_addressFamily, sendBufSize, receiveBufSize, nonBlocking); } - SimpleUDP::~SimpleUDP() - { - close(GetUnderlyingSocket()); - } - - void SimpleUDP::CreateSocket(int addressFamily, size_t sendBufSize, size_t receiveBufSize, bool nonBlocking) - { - int sock = socket(addressFamily, SOCK_DGRAM, IPPROTO_UDP); - assert(sock != -1); - - // Try to set sock to nonblocking mode. - if (nonBlocking) - { - int flags = fcntl(sock, F_GETFL, 0); - if (flags != -1) - { - flags |= O_NONBLOCK; - fcntl(sock, F_SETFL, flags); - } - } - - // if sendBufSize is not zero, try to set send buffer size - if (sendBufSize) - { - int ret = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sendBufSize, sizeof(sendBufSize)); - if (ret) - { - AWS_LOGSTREAM_WARN(ALLOC_TAG, "Failed to set UDP send buffer size to " << sendBufSize << " for socket " << sock << " error message: " << strerror(errno)); - } - assert(ret == 0); - } - - // if receiveBufSize is not zero, try to set receive buffer size - if (receiveBufSize) - { - int ret = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &receiveBufSize, sizeof(receiveBufSize)); - if (ret) - { - AWS_LOGSTREAM_WARN(ALLOC_TAG, "Failed to set UDP receive buffer size to " << receiveBufSize << " for socket " << sock << " error message: " << strerror(errno)); - } - assert(ret == 0); - } - - SetUnderlyingSocket(sock); - } - - int SimpleUDP::Connect(const sockaddr* address, size_t addressLength) - { - int ret = connect(GetUnderlyingSocket(), address, static_cast<socklen_t>(addressLength)); - m_connected = ret ? false : true; - return ret; - } - + SimpleUDP::~SimpleUDP() + { + close(GetUnderlyingSocket()); + } + + void SimpleUDP::CreateSocket(int addressFamily, size_t sendBufSize, size_t receiveBufSize, bool nonBlocking) + { + int sock = socket(addressFamily, SOCK_DGRAM, IPPROTO_UDP); + assert(sock != -1); + + // Try to set sock to nonblocking mode. + if (nonBlocking) + { + int flags = fcntl(sock, F_GETFL, 0); + if (flags != -1) + { + flags |= O_NONBLOCK; + fcntl(sock, F_SETFL, flags); + } + } + + // if sendBufSize is not zero, try to set send buffer size + if (sendBufSize) + { + int ret = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sendBufSize, sizeof(sendBufSize)); + if (ret) + { + AWS_LOGSTREAM_WARN(ALLOC_TAG, "Failed to set UDP send buffer size to " << sendBufSize << " for socket " << sock << " error message: " << strerror(errno)); + } + assert(ret == 0); + } + + // if receiveBufSize is not zero, try to set receive buffer size + if (receiveBufSize) + { + int ret = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &receiveBufSize, sizeof(receiveBufSize)); + if (ret) + { + AWS_LOGSTREAM_WARN(ALLOC_TAG, "Failed to set UDP receive buffer size to " << receiveBufSize << " for socket " << sock << " error message: " << strerror(errno)); + } + assert(ret == 0); + } + + SetUnderlyingSocket(sock); + } + + int SimpleUDP::Connect(const sockaddr* address, size_t addressLength) + { + int ret = connect(GetUnderlyingSocket(), address, static_cast<socklen_t>(addressLength)); + m_connected = ret ? false : true; + return ret; + } + int SimpleUDP::ConnectToHost(const char* hostIP, unsigned short port) const - { - int ret; - if (m_addressFamily == AF_INET6) - { + { + int ret; + if (m_addressFamily == AF_INET6) + { sockaddr_in6 addrinfo = BuildAddrInfoIPV6(hostIP, port); - ret = connect(GetUnderlyingSocket(), reinterpret_cast<sockaddr*>(&addrinfo), sizeof(sockaddr_in6)); - } - else - { + ret = connect(GetUnderlyingSocket(), reinterpret_cast<sockaddr*>(&addrinfo), sizeof(sockaddr_in6)); + } + else + { sockaddr_in addrinfo = BuildAddrInfoIPV4(hostIP, port); - ret = connect(GetUnderlyingSocket(), reinterpret_cast<sockaddr*>(&addrinfo), sizeof(sockaddr_in)); - } - m_connected = ret ? false : true; - return ret; - } - + ret = connect(GetUnderlyingSocket(), reinterpret_cast<sockaddr*>(&addrinfo), sizeof(sockaddr_in)); + } + m_connected = ret ? false : true; + return ret; + } + int SimpleUDP::ConnectToLocalHost(unsigned short port) const { if (m_addressFamily == AF_INET6) @@ -213,73 +213,73 @@ namespace Aws } } - int SimpleUDP::Bind(const sockaddr* address, size_t addressLength) const - { - return bind(GetUnderlyingSocket(), address, static_cast<socklen_t>(addressLength)); - } - - int SimpleUDP::BindToLocalHost(unsigned short port) const - { - if (m_addressFamily == AF_INET6) - { + int SimpleUDP::Bind(const sockaddr* address, size_t addressLength) const + { + return bind(GetUnderlyingSocket(), address, static_cast<socklen_t>(addressLength)); + } + + int SimpleUDP::BindToLocalHost(unsigned short port) const + { + if (m_addressFamily == AF_INET6) + { sockaddr_in6 addrinfo = BuildAddrInfoIPV6(IPV6_LOOP_BACK_ADDRESS, port); - return bind(GetUnderlyingSocket(), reinterpret_cast<sockaddr*>(&addrinfo), sizeof(sockaddr_in6)); - } - else - { + return bind(GetUnderlyingSocket(), reinterpret_cast<sockaddr*>(&addrinfo), sizeof(sockaddr_in6)); + } + else + { sockaddr_in addrinfo = BuildAddrInfoIPV4(IPV4_LOOP_BACK_ADDRESS, port); - return bind(GetUnderlyingSocket(), reinterpret_cast<sockaddr*>(&addrinfo), sizeof(sockaddr_in)); - } - } - - int SimpleUDP::SendData(const uint8_t* data, size_t dataLen) const - { + return bind(GetUnderlyingSocket(), reinterpret_cast<sockaddr*>(&addrinfo), sizeof(sockaddr_in)); + } + } + + int SimpleUDP::SendData(const uint8_t* data, size_t dataLen) const + { if (!m_connected) { ConnectToHost(m_hostIP.c_str(), m_port); } - return send(GetUnderlyingSocket(), data, dataLen, 0); - } - - int SimpleUDP::SendDataTo(const sockaddr* address, size_t addressLength, const uint8_t* data, size_t dataLen) const - { - if (m_connected) - { + return send(GetUnderlyingSocket(), data, dataLen, 0); + } + + int SimpleUDP::SendDataTo(const sockaddr* address, size_t addressLength, const uint8_t* data, size_t dataLen) const + { + if (m_connected) + { return send(GetUnderlyingSocket(), data, dataLen, 0); - } - else - { - return sendto(GetUnderlyingSocket(), data, dataLen, 0, address, static_cast<socklen_t>(addressLength)); - } - } - - int SimpleUDP::SendDataToLocalHost(const uint8_t* data, size_t dataLen, unsigned short port) const - { - if (m_connected) - { + } + else + { + return sendto(GetUnderlyingSocket(), data, dataLen, 0, address, static_cast<socklen_t>(addressLength)); + } + } + + int SimpleUDP::SendDataToLocalHost(const uint8_t* data, size_t dataLen, unsigned short port) const + { + if (m_connected) + { return send(GetUnderlyingSocket(), data, dataLen, 0); - } - else if (m_addressFamily == AF_INET6) - { + } + else if (m_addressFamily == AF_INET6) + { sockaddr_in6 addrinfo = BuildAddrInfoIPV6(IPV6_LOOP_BACK_ADDRESS, port); - return sendto(GetUnderlyingSocket(), data, dataLen, 0, reinterpret_cast<sockaddr*>(&addrinfo), sizeof(sockaddr_in6)); - } - else - { + return sendto(GetUnderlyingSocket(), data, dataLen, 0, reinterpret_cast<sockaddr*>(&addrinfo), sizeof(sockaddr_in6)); + } + else + { sockaddr_in addrinfo = BuildAddrInfoIPV4(IPV4_LOOP_BACK_ADDRESS, port); - return sendto(GetUnderlyingSocket(), data, dataLen, 0, reinterpret_cast<sockaddr*>(&addrinfo), sizeof(sockaddr_in)); - } - } - - int SimpleUDP::ReceiveData(uint8_t* buffer, size_t bufferLen) const - { - return recv(GetUnderlyingSocket(), buffer, static_cast<int>(bufferLen), 0); - } - - - int SimpleUDP::ReceiveDataFrom(sockaddr* address, size_t* addressLength, uint8_t* buffer, size_t bufferLen) const - { - return recvfrom(GetUnderlyingSocket(), buffer, static_cast<int>(bufferLen), 0, address, reinterpret_cast<socklen_t*>(addressLength)); - } - } -} + return sendto(GetUnderlyingSocket(), data, dataLen, 0, reinterpret_cast<sockaddr*>(&addrinfo), sizeof(sockaddr_in)); + } + } + + int SimpleUDP::ReceiveData(uint8_t* buffer, size_t bufferLen) const + { + return recv(GetUnderlyingSocket(), buffer, static_cast<int>(bufferLen), 0); + } + + + int SimpleUDP::ReceiveDataFrom(sockaddr* address, size_t* addressLength, uint8_t* buffer, size_t bufferLen) const + { + return recvfrom(GetUnderlyingSocket(), buffer, static_cast<int>(bufferLen), 0, address, reinterpret_cast<socklen_t*>(addressLength)); + } + } +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/linux-shared/Environment.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/linux-shared/Environment.cpp index ee627340bb..a582b80110 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/linux-shared/Environment.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/linux-shared/Environment.cpp @@ -2,22 +2,22 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/platform/Environment.h> - -//#include <aws/core/utils/memory/stl/AWSStringStream.h> -//#include <sys/utsname.h> - -namespace Aws -{ -namespace Environment -{ - -Aws::String GetEnv(const char* variableName) -{ - auto variableValue = std::getenv(variableName); - return Aws::String( variableValue ? variableValue : "" ); -} - -} // namespace Environment -} // namespace Aws + +#include <aws/core/platform/Environment.h> + +//#include <aws/core/utils/memory/stl/AWSStringStream.h> +//#include <sys/utsname.h> + +namespace Aws +{ +namespace Environment +{ + +Aws::String GetEnv(const char* variableName) +{ + auto variableValue = std::getenv(variableName); + return Aws::String( variableValue ? variableValue : "" ); +} + +} // namespace Environment +} // namespace Aws diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/linux-shared/FileSystem.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/linux-shared/FileSystem.cpp index c1ad818911..8c8dd49aad 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/linux-shared/FileSystem.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/linux-shared/FileSystem.cpp @@ -2,268 +2,268 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ -#include <aws/core/platform/FileSystem.h> - -#include <aws/core/platform/Environment.h> -#include <aws/core/platform/Platform.h> -#include <aws/core/utils/DateTime.h> -#include <aws/core/utils/logging/LogMacros.h> -#include <aws/core/utils/StringUtils.h> +#include <aws/core/platform/FileSystem.h> + +#include <aws/core/platform/Environment.h> +#include <aws/core/platform/Platform.h> +#include <aws/core/utils/DateTime.h> +#include <aws/core/utils/logging/LogMacros.h> +#include <aws/core/utils/StringUtils.h> #include <aws/core/utils/UUID.h> - -#include <unistd.h> -#include <pwd.h> -#include <sys/stat.h> -#include <dirent.h> -#include <errno.h> -#include <climits> - -#include <cassert> + +#include <unistd.h> +#include <pwd.h> +#include <sys/stat.h> +#include <dirent.h> +#include <errno.h> +#include <climits> + +#include <cassert> #ifdef __APPLE__ #include <mach-o/dyld.h> #endif -namespace Aws -{ -namespace FileSystem -{ - -static const char* FILE_SYSTEM_UTILS_LOG_TAG = "FileSystemUtils"; - - class PosixDirectory : public Directory - { - public: - PosixDirectory(const Aws::String& path, const Aws::String& relativePath) : Directory(path, relativePath), m_dir(nullptr) - { - m_dir = opendir(m_directoryEntry.path.c_str()); - AWS_LOGSTREAM_TRACE(FILE_SYSTEM_UTILS_LOG_TAG, "Entering directory " << m_directoryEntry.path); - - if(m_dir) - { - AWS_LOGSTREAM_TRACE(FILE_SYSTEM_UTILS_LOG_TAG, "Successfully opened directory " << m_directoryEntry.path); - m_directoryEntry.fileType = FileType::Directory; - } - else - { - AWS_LOGSTREAM_ERROR(FILE_SYSTEM_UTILS_LOG_TAG, "Could not load directory " << m_directoryEntry.path << " with error code " << errno); - } - } - - ~PosixDirectory() - { - if (m_dir) - { - closedir(m_dir); - } - } - - operator bool() const override { return m_directoryEntry.operator bool() && m_dir != nullptr; } - - DirectoryEntry Next() override - { - assert(m_dir); - DirectoryEntry entry; - - dirent* dirEntry; - bool invalidEntry(true); - - while(invalidEntry) - { - if ((dirEntry = readdir(m_dir))) - { - Aws::String entryName = dirEntry->d_name; - if(entryName != ".." && entryName != ".") - { - entry = ParseFileInfo(dirEntry, true); - invalidEntry = false; - } - else +namespace Aws +{ +namespace FileSystem +{ + +static const char* FILE_SYSTEM_UTILS_LOG_TAG = "FileSystemUtils"; + + class PosixDirectory : public Directory + { + public: + PosixDirectory(const Aws::String& path, const Aws::String& relativePath) : Directory(path, relativePath), m_dir(nullptr) + { + m_dir = opendir(m_directoryEntry.path.c_str()); + AWS_LOGSTREAM_TRACE(FILE_SYSTEM_UTILS_LOG_TAG, "Entering directory " << m_directoryEntry.path); + + if(m_dir) + { + AWS_LOGSTREAM_TRACE(FILE_SYSTEM_UTILS_LOG_TAG, "Successfully opened directory " << m_directoryEntry.path); + m_directoryEntry.fileType = FileType::Directory; + } + else + { + AWS_LOGSTREAM_ERROR(FILE_SYSTEM_UTILS_LOG_TAG, "Could not load directory " << m_directoryEntry.path << " with error code " << errno); + } + } + + ~PosixDirectory() + { + if (m_dir) + { + closedir(m_dir); + } + } + + operator bool() const override { return m_directoryEntry.operator bool() && m_dir != nullptr; } + + DirectoryEntry Next() override + { + assert(m_dir); + DirectoryEntry entry; + + dirent* dirEntry; + bool invalidEntry(true); + + while(invalidEntry) + { + if ((dirEntry = readdir(m_dir))) + { + Aws::String entryName = dirEntry->d_name; + if(entryName != ".." && entryName != ".") { - AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "skipping . or .."); - } - } - else - { - break; - } - } - - return entry; - } - - private: - DirectoryEntry ParseFileInfo(dirent* dirEnt, bool computePath) - { - DirectoryEntry entry; - - if(computePath) - { - Aws::StringStream ss; - ss << m_directoryEntry.path << PATH_DELIM << dirEnt->d_name; - entry.path = ss.str(); - - ss.str(""); - if(m_directoryEntry.relativePath.empty()) - { - ss << dirEnt->d_name; - } - else - { - ss << m_directoryEntry.relativePath << PATH_DELIM << dirEnt->d_name; - } - entry.relativePath = ss.str(); - } - else - { - entry.path = m_directoryEntry.path; - entry.relativePath = m_directoryEntry.relativePath; - } - - AWS_LOGSTREAM_TRACE(FILE_SYSTEM_UTILS_LOG_TAG, "Calling stat on path " << entry.path); - - struct stat dirInfo; - if(!lstat(entry.path.c_str(), &dirInfo)) - { - if(S_ISDIR(dirInfo.st_mode)) - { - AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "type directory detected"); - entry.fileType = FileType::Directory; - } - else if(S_ISLNK(dirInfo.st_mode)) - { - AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "type symlink detected"); - entry.fileType = FileType::Symlink; - } - else if(S_ISREG(dirInfo.st_mode)) - { - AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "type file detected"); - entry.fileType = FileType::File; - } - - entry.fileSize = static_cast<int64_t>(dirInfo.st_size); - AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "file size detected as " << entry.fileSize); - } - else - { - AWS_LOGSTREAM_ERROR(FILE_SYSTEM_UTILS_LOG_TAG, "Failed to stat file path " << entry.path << " with error code " << errno); - } - + entry = ParseFileInfo(dirEntry, true); + invalidEntry = false; + } + else + { + AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "skipping . or .."); + } + } + else + { + break; + } + } + + return entry; + } + + private: + DirectoryEntry ParseFileInfo(dirent* dirEnt, bool computePath) + { + DirectoryEntry entry; + + if(computePath) + { + Aws::StringStream ss; + ss << m_directoryEntry.path << PATH_DELIM << dirEnt->d_name; + entry.path = ss.str(); + + ss.str(""); + if(m_directoryEntry.relativePath.empty()) + { + ss << dirEnt->d_name; + } + else + { + ss << m_directoryEntry.relativePath << PATH_DELIM << dirEnt->d_name; + } + entry.relativePath = ss.str(); + } + else + { + entry.path = m_directoryEntry.path; + entry.relativePath = m_directoryEntry.relativePath; + } + + AWS_LOGSTREAM_TRACE(FILE_SYSTEM_UTILS_LOG_TAG, "Calling stat on path " << entry.path); + + struct stat dirInfo; + if(!lstat(entry.path.c_str(), &dirInfo)) + { + if(S_ISDIR(dirInfo.st_mode)) + { + AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "type directory detected"); + entry.fileType = FileType::Directory; + } + else if(S_ISLNK(dirInfo.st_mode)) + { + AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "type symlink detected"); + entry.fileType = FileType::Symlink; + } + else if(S_ISREG(dirInfo.st_mode)) + { + AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "type file detected"); + entry.fileType = FileType::File; + } + + entry.fileSize = static_cast<int64_t>(dirInfo.st_size); + AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "file size detected as " << entry.fileSize); + } + else + { + AWS_LOGSTREAM_ERROR(FILE_SYSTEM_UTILS_LOG_TAG, "Failed to stat file path " << entry.path << " with error code " << errno); + } + return entry; - } - - DIR* m_dir; - }; - -Aws::String GetHomeDirectory() -{ - static const char* HOME_DIR_ENV_VAR = "HOME"; - - AWS_LOGSTREAM_TRACE(FILE_SYSTEM_UTILS_LOG_TAG, "Checking " << HOME_DIR_ENV_VAR << " for the home directory."); - - Aws::String homeDir = Aws::Environment::GetEnv(HOME_DIR_ENV_VAR); - - AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "Environment value for variable " << HOME_DIR_ENV_VAR << " is " << homeDir); - - if(homeDir.empty()) - { - AWS_LOGSTREAM_WARN(FILE_SYSTEM_UTILS_LOG_TAG, "Home dir not stored in environment, trying to fetch manually from the OS."); - - passwd pw; - passwd *p_pw = nullptr; - char pw_buffer[4096]; - getpwuid_r(getuid(), &pw, pw_buffer, sizeof(pw_buffer), &p_pw); - if(p_pw && p_pw->pw_dir) - { - homeDir = p_pw->pw_dir; - } - - AWS_LOGSTREAM_INFO(FILE_SYSTEM_UTILS_LOG_TAG, "Pulled " << homeDir << " as home directory from the OS."); - } - - Aws::String retVal = homeDir.size() > 0 ? Aws::Utils::StringUtils::Trim(homeDir.c_str()) : ""; - if(!retVal.empty()) - { - if(retVal.at(retVal.length() - 1) != PATH_DELIM) - { - AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "Home directory is missing the final " << PATH_DELIM << " appending one to normalize"); - retVal += PATH_DELIM; - } - } - - AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "Final Home Directory is " << retVal); - - return retVal; -} - -bool CreateDirectoryIfNotExists(const char* path, bool createParentDirs) -{ - Aws::String directoryName = path; - AWS_LOGSTREAM_INFO(FILE_SYSTEM_UTILS_LOG_TAG, "Creating directory " << directoryName); - - for (size_t i = (createParentDirs ? 0 : directoryName.size() - 1); i < directoryName.size(); i++) - { - // Create the parent directory if we find a delimiter and the delimiter is not the first char, or if this is the target directory. - if (i != 0 && (directoryName[i] == FileSystem::PATH_DELIM || i == directoryName.size() - 1)) - { - if (directoryName[i] == FileSystem::PATH_DELIM) - { - directoryName[i] = '\0'; - } - int errorCode = mkdir(directoryName.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); - if (errorCode != 0 && errno != EEXIST) - { - AWS_LOGSTREAM_ERROR(FILE_SYSTEM_UTILS_LOG_TAG, "Creation of directory " << directoryName.c_str() << " returned code: " << errno); - return false; - } - AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "Creation of directory " << directoryName.c_str() << " returned code: " << errno); - directoryName[i] = FileSystem::PATH_DELIM; - } - } - return true; -} - -bool RemoveFileIfExists(const char* path) -{ - AWS_LOGSTREAM_INFO(FILE_SYSTEM_UTILS_LOG_TAG, "Deleting file: " << path); - - int errorCode = unlink(path); - AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "Deletion of file: " << path << " Returned error code: " << errno); - return errorCode == 0 || errno == ENOENT; -} - -bool RemoveDirectoryIfExists(const char* path) -{ - AWS_LOGSTREAM_INFO(FILE_SYSTEM_UTILS_LOG_TAG, "Deleting directory: " << path); - int errorCode = rmdir(path); - AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "Deletion of directory: " << path << " Returned error code: " << errno); - return errorCode == 0 || errno == ENOTDIR || errno == ENOENT; -} - -bool RelocateFileOrDirectory(const char* from, const char* to) -{ - AWS_LOGSTREAM_INFO(FILE_SYSTEM_UTILS_LOG_TAG, "Moving file at " << from << " to " << to); - - int errorCode = std::rename(from, to); - - AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "The moving operation of file at " << from << " to " << to << " Returned error code of " << errno); - return errorCode == 0; -} - -Aws::String CreateTempFilePath() -{ - Aws::StringStream ss; - auto dt = Aws::Utils::DateTime::Now(); + } + + DIR* m_dir; + }; + +Aws::String GetHomeDirectory() +{ + static const char* HOME_DIR_ENV_VAR = "HOME"; + + AWS_LOGSTREAM_TRACE(FILE_SYSTEM_UTILS_LOG_TAG, "Checking " << HOME_DIR_ENV_VAR << " for the home directory."); + + Aws::String homeDir = Aws::Environment::GetEnv(HOME_DIR_ENV_VAR); + + AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "Environment value for variable " << HOME_DIR_ENV_VAR << " is " << homeDir); + + if(homeDir.empty()) + { + AWS_LOGSTREAM_WARN(FILE_SYSTEM_UTILS_LOG_TAG, "Home dir not stored in environment, trying to fetch manually from the OS."); + + passwd pw; + passwd *p_pw = nullptr; + char pw_buffer[4096]; + getpwuid_r(getuid(), &pw, pw_buffer, sizeof(pw_buffer), &p_pw); + if(p_pw && p_pw->pw_dir) + { + homeDir = p_pw->pw_dir; + } + + AWS_LOGSTREAM_INFO(FILE_SYSTEM_UTILS_LOG_TAG, "Pulled " << homeDir << " as home directory from the OS."); + } + + Aws::String retVal = homeDir.size() > 0 ? Aws::Utils::StringUtils::Trim(homeDir.c_str()) : ""; + if(!retVal.empty()) + { + if(retVal.at(retVal.length() - 1) != PATH_DELIM) + { + AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "Home directory is missing the final " << PATH_DELIM << " appending one to normalize"); + retVal += PATH_DELIM; + } + } + + AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "Final Home Directory is " << retVal); + + return retVal; +} + +bool CreateDirectoryIfNotExists(const char* path, bool createParentDirs) +{ + Aws::String directoryName = path; + AWS_LOGSTREAM_INFO(FILE_SYSTEM_UTILS_LOG_TAG, "Creating directory " << directoryName); + + for (size_t i = (createParentDirs ? 0 : directoryName.size() - 1); i < directoryName.size(); i++) + { + // Create the parent directory if we find a delimiter and the delimiter is not the first char, or if this is the target directory. + if (i != 0 && (directoryName[i] == FileSystem::PATH_DELIM || i == directoryName.size() - 1)) + { + if (directoryName[i] == FileSystem::PATH_DELIM) + { + directoryName[i] = '\0'; + } + int errorCode = mkdir(directoryName.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); + if (errorCode != 0 && errno != EEXIST) + { + AWS_LOGSTREAM_ERROR(FILE_SYSTEM_UTILS_LOG_TAG, "Creation of directory " << directoryName.c_str() << " returned code: " << errno); + return false; + } + AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "Creation of directory " << directoryName.c_str() << " returned code: " << errno); + directoryName[i] = FileSystem::PATH_DELIM; + } + } + return true; +} + +bool RemoveFileIfExists(const char* path) +{ + AWS_LOGSTREAM_INFO(FILE_SYSTEM_UTILS_LOG_TAG, "Deleting file: " << path); + + int errorCode = unlink(path); + AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "Deletion of file: " << path << " Returned error code: " << errno); + return errorCode == 0 || errno == ENOENT; +} + +bool RemoveDirectoryIfExists(const char* path) +{ + AWS_LOGSTREAM_INFO(FILE_SYSTEM_UTILS_LOG_TAG, "Deleting directory: " << path); + int errorCode = rmdir(path); + AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "Deletion of directory: " << path << " Returned error code: " << errno); + return errorCode == 0 || errno == ENOTDIR || errno == ENOENT; +} + +bool RelocateFileOrDirectory(const char* from, const char* to) +{ + AWS_LOGSTREAM_INFO(FILE_SYSTEM_UTILS_LOG_TAG, "Moving file at " << from << " to " << to); + + int errorCode = std::rename(from, to); + + AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "The moving operation of file at " << from << " to " << to << " Returned error code of " << errno); + return errorCode == 0; +} + +Aws::String CreateTempFilePath() +{ + Aws::StringStream ss; + auto dt = Aws::Utils::DateTime::Now(); ss << dt.ToGmtString("%Y%m%dT%H%M%S") << dt.Millis() << Aws::String(Aws::Utils::UUID::RandomUUID()); - Aws::String tempFile(ss.str()); - - AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "CreateTempFilePath generated: " << tempFile); - - return tempFile; -} - -Aws::String GetExecutableDirectory() -{ - char dest[PATH_MAX]; + Aws::String tempFile(ss.str()); + + AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "CreateTempFilePath generated: " << tempFile); + + return tempFile; +} + +Aws::String GetExecutableDirectory() +{ + char dest[PATH_MAX]; memset(dest, 0, PATH_MAX); #ifdef __APPLE__ uint32_t destSize = PATH_MAX; @@ -272,21 +272,21 @@ Aws::String GetExecutableDirectory() size_t destSize = PATH_MAX; if (readlink("/proc/self/exe", dest, destSize)) #endif - { - Aws::String executablePath(dest); - auto lastSlash = executablePath.find_last_of('/'); - if(lastSlash != std::string::npos) - { - return executablePath.substr(0, lastSlash); + { + Aws::String executablePath(dest); + auto lastSlash = executablePath.find_last_of('/'); + if(lastSlash != std::string::npos) + { + return executablePath.substr(0, lastSlash); } } - return "./"; -} - -Aws::UniquePtr<Directory> OpenDirectory(const Aws::String& path, const Aws::String& relativePath) -{ - return Aws::MakeUnique<PosixDirectory>(FILE_SYSTEM_UTILS_LOG_TAG, path, relativePath); -} - -} // namespace FileSystem -} // namespace Aws + return "./"; +} + +Aws::UniquePtr<Directory> OpenDirectory(const Aws::String& path, const Aws::String& relativePath) +{ + return Aws::MakeUnique<PosixDirectory>(FILE_SYSTEM_UTILS_LOG_TAG, path, relativePath); +} + +} // namespace FileSystem +} // namespace Aws diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/linux-shared/OSVersionInfo.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/linux-shared/OSVersionInfo.cpp index 040173a2e5..507b374f36 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/linux-shared/OSVersionInfo.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/linux-shared/OSVersionInfo.cpp @@ -2,58 +2,58 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/platform/OSVersionInfo.h> -#include <aws/core/utils/memory/stl/AWSStringStream.h> -#include <aws/core/utils/StringUtils.h> -#include <sys/utsname.h> - -namespace Aws -{ -namespace OSVersionInfo -{ - -Aws::String GetSysCommandOutput(const char* command) -{ - Aws::String outputStr; - FILE* outputStream; - const int maxBufferSize = 256; - char outputBuffer[maxBufferSize]; - - outputStream = popen(command, "r"); - - if (outputStream) - { - while (!feof(outputStream)) - { - if (fgets(outputBuffer, maxBufferSize, outputStream) != nullptr) - { - outputStr.append(outputBuffer); - } - } - - pclose(outputStream); - - return Aws::Utils::StringUtils::Trim(outputStr.c_str()); - } - + +#include <aws/core/platform/OSVersionInfo.h> +#include <aws/core/utils/memory/stl/AWSStringStream.h> +#include <aws/core/utils/StringUtils.h> +#include <sys/utsname.h> + +namespace Aws +{ +namespace OSVersionInfo +{ + +Aws::String GetSysCommandOutput(const char* command) +{ + Aws::String outputStr; + FILE* outputStream; + const int maxBufferSize = 256; + char outputBuffer[maxBufferSize]; + + outputStream = popen(command, "r"); + + if (outputStream) + { + while (!feof(outputStream)) + { + if (fgets(outputBuffer, maxBufferSize, outputStream) != nullptr) + { + outputStr.append(outputBuffer); + } + } + + pclose(outputStream); + + return Aws::Utils::StringUtils::Trim(outputStr.c_str()); + } + return {}; -} - - -Aws::String ComputeOSVersionString() -{ - utsname name; - int32_t success = uname(&name); - if(success >= 0) - { - Aws::StringStream ss; - ss << name.sysname << "/" << name.release << " " << name.machine; - return ss.str(); - } - - return "non-windows/unknown"; -} - -} // namespace OSVersionInfo -} // namespace Aws +} + + +Aws::String ComputeOSVersionString() +{ + utsname name; + int32_t success = uname(&name); + if(success >= 0) + { + Aws::StringStream ss; + ss << name.sysname << "/" << name.release << " " << name.machine; + return ss.str(); + } + + return "non-windows/unknown"; +} + +} // namespace OSVersionInfo +} // namespace Aws diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/linux-shared/Security.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/linux-shared/Security.cpp index 286de1a948..b8012da068 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/linux-shared/Security.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/linux-shared/Security.cpp @@ -2,25 +2,25 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/platform/Security.h> - -#include <string.h> - -namespace Aws -{ -namespace Security -{ - -void SecureMemClear(unsigned char *data, size_t length) -{ -#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) - memset_s(data, length, 0, length); -#else - memset(data, 0, length); - asm volatile("" : "+m" (data)); -#endif -} - -} // namespace Security -} // namespace Aws + +#include <aws/core/platform/Security.h> + +#include <string.h> + +namespace Aws +{ +namespace Security +{ + +void SecureMemClear(unsigned char *data, size_t length) +{ +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) + memset_s(data, length, 0, length); +#else + memset(data, 0, length); + asm volatile("" : "+m" (data)); +#endif +} + +} // namespace Security +} // namespace Aws diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/linux-shared/Time.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/linux-shared/Time.cpp index 7a0d3d1c0a..6f2c3acf2e 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/linux-shared/Time.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/linux-shared/Time.cpp @@ -2,30 +2,30 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/platform/Time.h> - -#include <time.h> - -namespace Aws -{ -namespace Time -{ - -time_t TimeGM(struct tm* const t) -{ - return timegm(t); -} - -void LocalTime(tm* t, std::time_t time) -{ - localtime_r(&time, t); -} - -void GMTime(tm* t, std::time_t time) -{ - gmtime_r(&time, t); -} - -} // namespace Time -} // namespace Aws + +#include <aws/core/platform/Time.h> + +#include <time.h> + +namespace Aws +{ +namespace Time +{ + +time_t TimeGM(struct tm* const t) +{ + return timegm(t); +} + +void LocalTime(tm* t, std::time_t time) +{ + localtime_r(&time, t); +} + +void GMTime(tm* t, std::time_t time) +{ + gmtime_r(&time, t); +} + +} // namespace Time +} // namespace Aws diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/Array.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/Array.cpp index 43e7863421..39247ce3b1 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/Array.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/Array.cpp @@ -2,64 +2,64 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/utils/Array.h> - -#include <aws/core/platform/Security.h> - -namespace Aws -{ - namespace Utils - { - Array<CryptoBuffer> CryptoBuffer::Slice(size_t sizeOfSlice) const - { - assert(sizeOfSlice <= GetLength()); - - size_t numberOfSlices = (GetLength() + sizeOfSlice - 1) / sizeOfSlice; - size_t currentSliceIndex = 0; - Array<CryptoBuffer> slices(numberOfSlices); - - for (size_t i = 0; i < numberOfSlices - 1; ++i) - { - CryptoBuffer newArray(sizeOfSlice); - for (size_t cpyIdx = 0; cpyIdx < newArray.GetLength(); ++cpyIdx) - { - newArray[cpyIdx] = GetItem(cpyIdx + currentSliceIndex); - } - currentSliceIndex += sizeOfSlice; - slices[i] = std::move(newArray); - } - - CryptoBuffer lastArray(GetLength() % sizeOfSlice == 0 ? sizeOfSlice : GetLength() % sizeOfSlice ); - for (size_t cpyIdx = 0; cpyIdx < lastArray.GetLength(); ++cpyIdx) - { - lastArray[cpyIdx] = GetItem(cpyIdx + currentSliceIndex); - } - slices[slices.GetLength() - 1] = std::move(lastArray); - - return slices; - } - - CryptoBuffer& CryptoBuffer::operator^(const CryptoBuffer& operand) - { - size_t smallestSize = std::min<size_t>(GetLength(), operand.GetLength()); - for (size_t i = 0; i < smallestSize; ++i) - { - (*this)[i] ^= operand[i]; - } - - return *this; - } - - /** - * Zero out the array securely - */ - void CryptoBuffer::Zero() - { - if (GetUnderlyingData()) - { - Aws::Security::SecureMemClear(GetUnderlyingData(), GetLength()); - } - } - } -}
\ No newline at end of file + +#include <aws/core/utils/Array.h> + +#include <aws/core/platform/Security.h> + +namespace Aws +{ + namespace Utils + { + Array<CryptoBuffer> CryptoBuffer::Slice(size_t sizeOfSlice) const + { + assert(sizeOfSlice <= GetLength()); + + size_t numberOfSlices = (GetLength() + sizeOfSlice - 1) / sizeOfSlice; + size_t currentSliceIndex = 0; + Array<CryptoBuffer> slices(numberOfSlices); + + for (size_t i = 0; i < numberOfSlices - 1; ++i) + { + CryptoBuffer newArray(sizeOfSlice); + for (size_t cpyIdx = 0; cpyIdx < newArray.GetLength(); ++cpyIdx) + { + newArray[cpyIdx] = GetItem(cpyIdx + currentSliceIndex); + } + currentSliceIndex += sizeOfSlice; + slices[i] = std::move(newArray); + } + + CryptoBuffer lastArray(GetLength() % sizeOfSlice == 0 ? sizeOfSlice : GetLength() % sizeOfSlice ); + for (size_t cpyIdx = 0; cpyIdx < lastArray.GetLength(); ++cpyIdx) + { + lastArray[cpyIdx] = GetItem(cpyIdx + currentSliceIndex); + } + slices[slices.GetLength() - 1] = std::move(lastArray); + + return slices; + } + + CryptoBuffer& CryptoBuffer::operator^(const CryptoBuffer& operand) + { + size_t smallestSize = std::min<size_t>(GetLength(), operand.GetLength()); + for (size_t i = 0; i < smallestSize; ++i) + { + (*this)[i] ^= operand[i]; + } + + return *this; + } + + /** + * Zero out the array securely + */ + void CryptoBuffer::Zero() + { + if (GetUnderlyingData()) + { + Aws::Security::SecureMemClear(GetUnderlyingData(), GetLength()); + } + } + } +}
\ No newline at end of file diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/DNS.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/DNS.cpp index ce588150e2..66cc081b77 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/DNS.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/DNS.cpp @@ -2,43 +2,43 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/utils/DNS.h> + +#include <aws/core/utils/DNS.h> #include <aws/core/utils/StringUtils.h> - -namespace Aws -{ - namespace Utils - { - bool IsValidDnsLabel(const Aws::String& label) - { - // Valid DNS hostnames are composed of valid DNS labels separated by a period. - // Valid DNS labels are characterized by the following: - // 1- Only contains alphanumeric characters and/or dashes - // 2- Cannot start or end with a dash - // 3- Have a maximum length of 63 characters (the entirety of the domain name should be less than 255 bytes) - - if (label.empty()) - return false; - - if (label.size() > 63) - return false; - + +namespace Aws +{ + namespace Utils + { + bool IsValidDnsLabel(const Aws::String& label) + { + // Valid DNS hostnames are composed of valid DNS labels separated by a period. + // Valid DNS labels are characterized by the following: + // 1- Only contains alphanumeric characters and/or dashes + // 2- Cannot start or end with a dash + // 3- Have a maximum length of 63 characters (the entirety of the domain name should be less than 255 bytes) + + if (label.empty()) + return false; + + if (label.size() > 63) + return false; + if (!StringUtils::IsAlnum(label.front())) - return false; // '-' is not acceptable as the first character - + return false; // '-' is not acceptable as the first character + if (!StringUtils::IsAlnum(label.back())) - return false; // '-' is not acceptable as the last character - - for (size_t i = 1, e = label.size() - 1; i < e; ++i) - { - auto c = label[i]; + return false; // '-' is not acceptable as the last character + + for (size_t i = 1, e = label.size() - 1; i < e; ++i) + { + auto c = label[i]; if (c != '-' && !StringUtils::IsAlnum(c)) - return false; - } - - return true; - } + return false; + } + + return true; + } bool IsValidHost(const Aws::String& host) { @@ -51,5 +51,5 @@ namespace Aws return !std::any_of(labels.begin(), labels.end(), [](const Aws::String& label){ return !IsValidDnsLabel(label); }); } - } -} + } +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/DateTimeCommon.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/DateTimeCommon.cpp index b690c90c2d..f2ca5cb82b 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/DateTimeCommon.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/DateTimeCommon.cpp @@ -2,611 +2,611 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/utils/DateTime.h> - -#include <aws/core/platform/Time.h> -#include <aws/core/utils/memory/stl/AWSStringStream.h> -#include <aws/core/utils/logging/LogMacros.h> -#include <time.h> -#include <cassert> -#include <iostream> -#include <cstring> - -static const char* CLASS_TAG = "DateTime"; -static const char* RFC822_DATE_FORMAT_STR_MINUS_Z = "%a, %d %b %Y %H:%M:%S"; -static const char* RFC822_DATE_FORMAT_STR_WITH_Z = "%a, %d %b %Y %H:%M:%S %Z"; -static const char* ISO_8601_LONG_DATE_FORMAT_STR = "%Y-%m-%dT%H:%M:%SZ"; + +#include <aws/core/utils/DateTime.h> + +#include <aws/core/platform/Time.h> +#include <aws/core/utils/memory/stl/AWSStringStream.h> +#include <aws/core/utils/logging/LogMacros.h> +#include <time.h> +#include <cassert> +#include <iostream> +#include <cstring> + +static const char* CLASS_TAG = "DateTime"; +static const char* RFC822_DATE_FORMAT_STR_MINUS_Z = "%a, %d %b %Y %H:%M:%S"; +static const char* RFC822_DATE_FORMAT_STR_WITH_Z = "%a, %d %b %Y %H:%M:%S %Z"; +static const char* ISO_8601_LONG_DATE_FORMAT_STR = "%Y-%m-%dT%H:%M:%SZ"; static const char* ISO_8601_LONG_BASIC_DATE_FORMAT_STR = "%Y%m%dT%H%M%SZ"; - -using namespace Aws::Utils; - - -std::tm CreateZeroedTm() -{ - std::tm timeStruct; - timeStruct.tm_hour = 0; - timeStruct.tm_isdst = -1; - timeStruct.tm_mday = 0; - timeStruct.tm_min = 0; - timeStruct.tm_mon = 0; - timeStruct.tm_sec = 0; - timeStruct.tm_wday = 0; - timeStruct.tm_yday = 0; - timeStruct.tm_year = 0; - - return timeStruct; -} - -//Get the 0-6 week day number from a string representing WeekDay. Case insensitive and will stop on abbreviation -static int GetWeekDayNumberFromStr(const char* timeString, size_t startIndex, size_t stopIndex) -{ - if(stopIndex - startIndex < 3) - { - return -1; - } - - size_t index = startIndex; - - char c = timeString[index]; - char next = 0; - - //it's ugly but this should compile down to EXACTLY 3 comparisons and no memory allocations - switch(c) - { - case 'S': - case 's': - next = timeString[++index]; - switch(next) - { - case 'A': - case 'a': - next = timeString[++index]; - switch (next) - { - case 'T': - case 't': - return 6; - default: - return -1; - } - case 'U': - case 'u': - next = timeString[++index]; - switch (next) - { - case 'N': - case 'n': - return 0; - default: - return -1; - } - default: - return -1; - } - case 'T': - case 't': - next = timeString[++index]; - switch (next) - { - case 'H': - case 'h': - next = timeString[++index]; - switch(next) - { - case 'U': - case 'u': - return 4; - default: - return -1; - } - case 'U': - case 'u': - next = timeString[++index]; - switch(next) - { - case 'E': - case 'e': - return 2; - default: - return -1; - } - default: - return -1; - } - case 'M': - case 'm': - next = timeString[++index]; - switch(next) - { - case 'O': - case 'o': - next = timeString[++index]; - switch (next) - { - case 'N': - case 'n': - return 1; - default: - return -1; - } - default: - return -1; - } - case 'W': - case 'w': - next = timeString[++index]; - switch (next) - { - case 'E': - case 'e': - next = timeString[++index]; - switch (next) - { - case 'D': - case 'd': - return 3; - default: + +using namespace Aws::Utils; + + +std::tm CreateZeroedTm() +{ + std::tm timeStruct; + timeStruct.tm_hour = 0; + timeStruct.tm_isdst = -1; + timeStruct.tm_mday = 0; + timeStruct.tm_min = 0; + timeStruct.tm_mon = 0; + timeStruct.tm_sec = 0; + timeStruct.tm_wday = 0; + timeStruct.tm_yday = 0; + timeStruct.tm_year = 0; + + return timeStruct; +} + +//Get the 0-6 week day number from a string representing WeekDay. Case insensitive and will stop on abbreviation +static int GetWeekDayNumberFromStr(const char* timeString, size_t startIndex, size_t stopIndex) +{ + if(stopIndex - startIndex < 3) + { + return -1; + } + + size_t index = startIndex; + + char c = timeString[index]; + char next = 0; + + //it's ugly but this should compile down to EXACTLY 3 comparisons and no memory allocations + switch(c) + { + case 'S': + case 's': + next = timeString[++index]; + switch(next) + { + case 'A': + case 'a': + next = timeString[++index]; + switch (next) + { + case 'T': + case 't': + return 6; + default: + return -1; + } + case 'U': + case 'u': + next = timeString[++index]; + switch (next) + { + case 'N': + case 'n': + return 0; + default: return -1; + } + default: + return -1; + } + case 'T': + case 't': + next = timeString[++index]; + switch (next) + { + case 'H': + case 'h': + next = timeString[++index]; + switch(next) + { + case 'U': + case 'u': + return 4; + default: + return -1; + } + case 'U': + case 'u': + next = timeString[++index]; + switch(next) + { + case 'E': + case 'e': + return 2; + default: + return -1; + } + default: + return -1; + } + case 'M': + case 'm': + next = timeString[++index]; + switch(next) + { + case 'O': + case 'o': + next = timeString[++index]; + switch (next) + { + case 'N': + case 'n': + return 1; + default: + return -1; + } + default: + return -1; + } + case 'W': + case 'w': + next = timeString[++index]; + switch (next) + { + case 'E': + case 'e': + next = timeString[++index]; + switch (next) + { + case 'D': + case 'd': + return 3; + default: + return -1; + } + default: + return -1; + } + case 'F': + case 'f': + next = timeString[++index]; + switch (next) + { + case 'R': + case 'r': + next = timeString[++index]; + switch (next) + { + case 'I': + case 'i': + return 5; + default: + return -1; + } + default: + return -1; + } + default: + return -1; + } +} + +//Get the 0-11 monthy number from a string representing Month. Case insensitive and will stop on abbreviation +static int GetMonthNumberFromStr(const char* timeString, size_t startIndex, size_t stopIndex) +{ + if (stopIndex - startIndex < 3) + { + return -1; + } + + size_t index = startIndex; + + char c = timeString[index]; + char next = 0; + + //it's ugly but this should compile down to EXACTLY 3 comparisons and no memory allocations + switch (c) + { + case 'M': + case 'm': + next = timeString[++index]; + switch (next) + { + case 'A': + case 'a': + next = timeString[++index]; + switch (next) + { + case 'Y': + case 'y': + return 4; + case 'R': + case 'r': + return 2; + default: + return -1; } - default: - return -1; - } - case 'F': - case 'f': - next = timeString[++index]; - switch (next) - { - case 'R': - case 'r': - next = timeString[++index]; - switch (next) - { - case 'I': - case 'i': - return 5; - default: - return -1; - } - default: - return -1; - } - default: - return -1; - } -} - -//Get the 0-11 monthy number from a string representing Month. Case insensitive and will stop on abbreviation -static int GetMonthNumberFromStr(const char* timeString, size_t startIndex, size_t stopIndex) -{ - if (stopIndex - startIndex < 3) - { - return -1; - } - - size_t index = startIndex; - - char c = timeString[index]; - char next = 0; - - //it's ugly but this should compile down to EXACTLY 3 comparisons and no memory allocations - switch (c) - { - case 'M': - case 'm': - next = timeString[++index]; - switch (next) - { - case 'A': - case 'a': - next = timeString[++index]; - switch (next) - { - case 'Y': - case 'y': - return 4; - case 'R': - case 'r': - return 2; - default: - return -1; - } - default: - return -1; - } - case 'A': - case 'a': - next = timeString[++index]; - switch (next) - { - case 'P': - case 'p': - next = timeString[++index]; - switch (next) - { - case 'R': - case 'r': - return 3; - default: - return -1; - } - case 'U': - case 'u': - next = timeString[++index]; - switch (next) - { - case 'G': - case 'g': - return 7; - default: - return -1; - } - default: - return -1; - } - case 'J': - case 'j': - next = timeString[++index]; - switch (next) - { - case 'A': - case 'a': - next = timeString[++index]; - switch (next) - { - case 'N': - case 'n': - return 0; - default: - return -1; - } - case 'U': - case 'u': - next = timeString[++index]; - switch (next) - { - case 'N': - case 'n': - return 5; - case 'L': - case 'l': - return 6; - default: - return -1; - } - default: - return -1; - } - case 'F': - case 'f': - next = timeString[++index]; - switch (next) - { - case 'E': - case 'e': - next = timeString[++index]; - switch (next) - { - case 'B': - case 'b': - return 1; - default: - return -1; - } - default: - return -1; - } - case 'S': - case 's': - next = timeString[++index]; - switch (next) - { - case 'E': - case 'e': - next = timeString[++index]; - switch (next) - { - case 'P': - case 'p': - return 8; - default: - return -1; - } - default: - return -1; - } - case 'O': - case 'o': - next = timeString[++index]; - switch (next) - { - case 'C': - case 'c': - next = timeString[++index]; - switch (next) - { - case 'T': - case 't': - return 9; - default: - return -1; - } - default: - return -1; - } - case 'N': - case 'n': - next = timeString[++index]; - switch (next) - { - case 'O': - case 'o': - next = timeString[++index]; - switch (next) - { - case 'V': - case 'v': - return 10; - default: - return -1; - } - default: - return -1; - } - case 'D': - case 'd': - next = timeString[++index]; - switch (next) - { - case 'E': - case 'e': - next = timeString[++index]; - switch (next) - { - case 'C': - case 'c': - return 11; - default: - return -1; - } - default: - return -1; - } - default: - return -1; - } -} + default: + return -1; + } + case 'A': + case 'a': + next = timeString[++index]; + switch (next) + { + case 'P': + case 'p': + next = timeString[++index]; + switch (next) + { + case 'R': + case 'r': + return 3; + default: + return -1; + } + case 'U': + case 'u': + next = timeString[++index]; + switch (next) + { + case 'G': + case 'g': + return 7; + default: + return -1; + } + default: + return -1; + } + case 'J': + case 'j': + next = timeString[++index]; + switch (next) + { + case 'A': + case 'a': + next = timeString[++index]; + switch (next) + { + case 'N': + case 'n': + return 0; + default: + return -1; + } + case 'U': + case 'u': + next = timeString[++index]; + switch (next) + { + case 'N': + case 'n': + return 5; + case 'L': + case 'l': + return 6; + default: + return -1; + } + default: + return -1; + } + case 'F': + case 'f': + next = timeString[++index]; + switch (next) + { + case 'E': + case 'e': + next = timeString[++index]; + switch (next) + { + case 'B': + case 'b': + return 1; + default: + return -1; + } + default: + return -1; + } + case 'S': + case 's': + next = timeString[++index]; + switch (next) + { + case 'E': + case 'e': + next = timeString[++index]; + switch (next) + { + case 'P': + case 'p': + return 8; + default: + return -1; + } + default: + return -1; + } + case 'O': + case 'o': + next = timeString[++index]; + switch (next) + { + case 'C': + case 'c': + next = timeString[++index]; + switch (next) + { + case 'T': + case 't': + return 9; + default: + return -1; + } + default: + return -1; + } + case 'N': + case 'n': + next = timeString[++index]; + switch (next) + { + case 'O': + case 'o': + next = timeString[++index]; + switch (next) + { + case 'V': + case 'v': + return 10; + default: + return -1; + } + default: + return -1; + } + case 'D': + case 'd': + next = timeString[++index]; + switch (next) + { + case 'E': + case 'e': + next = timeString[++index]; + switch (next) + { + case 'C': + case 'c': + return 11; + default: + return -1; + } + default: + return -1; + } + default: + return -1; + } +} // Ensure local classes with generic names have internal linkage namespace { - -class DateParser -{ -public: - DateParser(const char* toParse) : m_error(false), m_toParse(toParse), m_utcAssumed(true) - { - m_parsedTimestamp = CreateZeroedTm(); + +class DateParser +{ +public: + DateParser(const char* toParse) : m_error(false), m_toParse(toParse), m_utcAssumed(true) + { + m_parsedTimestamp = CreateZeroedTm(); memset(m_tz, 0, 7); - } - - virtual ~DateParser() = default; - - virtual void Parse() = 0; - bool WasParseSuccessful() const { return !m_error; } - std::tm& GetParsedTimestamp() { return m_parsedTimestamp; } - bool ShouldIAssumeThisIsUTC() const { return m_utcAssumed; } - const char* GetParsedTimezone() const { return m_tz; } - -protected: - bool m_error; - const char* m_toParse; - std::tm m_parsedTimestamp; - bool m_utcAssumed; + } + + virtual ~DateParser() = default; + + virtual void Parse() = 0; + bool WasParseSuccessful() const { return !m_error; } + std::tm& GetParsedTimestamp() { return m_parsedTimestamp; } + bool ShouldIAssumeThisIsUTC() const { return m_utcAssumed; } + const char* GetParsedTimezone() const { return m_tz; } + +protected: + bool m_error; + const char* m_toParse; + std::tm m_parsedTimestamp; + bool m_utcAssumed; // The size should be at least one byte greater than the maximum possible size so that we could use the last char to indicate the end of the string. char m_tz[7]; -}; - -static const int MAX_LEN = 100; - -//Before you send me hate mail because I'm doing this manually, I encourage you to try using std::get_time on all platforms and getting -//uniform results. Timezone information doesn't parse on Windows and it hardly even works on GCC 4.9.x. This is the only way to make sure -//the standard is parsed correctly. strptime isn't available one Windows. This code gets hit pretty hard during http serialization/deserialization -//as a result I'm going for no dynamic allocations and linear complexity -class RFC822DateParser : public DateParser -{ -public: +}; + +static const int MAX_LEN = 100; + +//Before you send me hate mail because I'm doing this manually, I encourage you to try using std::get_time on all platforms and getting +//uniform results. Timezone information doesn't parse on Windows and it hardly even works on GCC 4.9.x. This is the only way to make sure +//the standard is parsed correctly. strptime isn't available one Windows. This code gets hit pretty hard during http serialization/deserialization +//as a result I'm going for no dynamic allocations and linear complexity +class RFC822DateParser : public DateParser +{ +public: RFC822DateParser(const char* toParse) : DateParser(toParse), m_state(0) { - } - - /** - * Really simple state machine for the format %a, %d %b %Y %H:%M:%S %Z - */ - void Parse() override - { + } + + /** + * Really simple state machine for the format %a, %d %b %Y %H:%M:%S %Z + */ + void Parse() override + { size_t len = strlen(m_toParse); - - //DOS check - if (len > MAX_LEN) - { + + //DOS check + if (len > MAX_LEN) + { AWS_LOGSTREAM_WARN(CLASS_TAG, "Incoming String to parse too long with length: " << len) m_error = true; - return; - } - - size_t index = 0; - size_t stateStartIndex = 0; - int finalState = 8; - - while(m_state <= finalState && !m_error && index < len) - { - char c = m_toParse[index]; - - switch (m_state) - { - case 0: - if(c == ',') - { - int weekNumber = GetWeekDayNumberFromStr(m_toParse, stateStartIndex, index + 1); - - if (weekNumber > -1) - { - m_state = 1; - stateStartIndex = index + 1; - m_parsedTimestamp.tm_wday = weekNumber; - } - else - { - m_error = true; - } - } - else if(!isalpha(c)) - { - m_error = true; - } - break; + return; + } + + size_t index = 0; + size_t stateStartIndex = 0; + int finalState = 8; + + while(m_state <= finalState && !m_error && index < len) + { + char c = m_toParse[index]; + + switch (m_state) + { + case 0: + if(c == ',') + { + int weekNumber = GetWeekDayNumberFromStr(m_toParse, stateStartIndex, index + 1); + + if (weekNumber > -1) + { + m_state = 1; + stateStartIndex = index + 1; + m_parsedTimestamp.tm_wday = weekNumber; + } + else + { + m_error = true; + } + } + else if(!isalpha(c)) + { + m_error = true; + } + break; case 1: - if (isspace(c)) - { + if (isspace(c)) + { m_state = 2; - stateStartIndex = index + 1; - } - else - { - m_error = true; - } - break; - case 2: - if (isdigit(c)) - { - m_parsedTimestamp.tm_mday = m_parsedTimestamp.tm_mday * 10 + (c - '0'); - } - else if(isspace(c)) - { - m_state = 3; - stateStartIndex = index + 1; - } - else - { - m_error = true; - } - break; - case 3: - if (isspace(c)) - { - int monthNumber = GetMonthNumberFromStr(m_toParse, stateStartIndex, index + 1); - - if (monthNumber > -1) - { - m_state = 4; - stateStartIndex = index + 1; - m_parsedTimestamp.tm_mon = monthNumber; - } - else - { - m_error = true; - } - } - else if (!isalpha(c)) - { - m_error = true; - } - break; - case 4: - if (isspace(c) && index - stateStartIndex == 4) - { - m_state = 5; - stateStartIndex = index + 1; - m_parsedTimestamp.tm_year -= 1900; - } - else if (isspace(c) && index - stateStartIndex == 2) - { - m_state = 5; - stateStartIndex = index + 1; - m_parsedTimestamp.tm_year += 2000 - 1900; - } - else if (isdigit(c)) - { - m_parsedTimestamp.tm_year = m_parsedTimestamp.tm_year * 10 + (c - '0'); - } - else - { - m_error = true; - } - break; - case 5: - if(c == ':' && index - stateStartIndex == 2) - { - m_state = 6; - stateStartIndex = index + 1; - } - else if (isdigit(c)) - { - m_parsedTimestamp.tm_hour = m_parsedTimestamp.tm_hour * 10 + (c - '0'); - } - else - { - m_error = true; - } - break; - case 6: - if (c == ':' && index - stateStartIndex == 2) - { - m_state = 7; - stateStartIndex = index + 1; - } - else if (isdigit(c)) - { - m_parsedTimestamp.tm_min = m_parsedTimestamp.tm_min * 10 + (c - '0'); - } - else - { - m_error = true; - } - break; - case 7: - if (isspace(c) && index - stateStartIndex == 2) - { - m_state = 8; - stateStartIndex = index + 1; - } - else if (isdigit(c)) - { - m_parsedTimestamp.tm_sec = m_parsedTimestamp.tm_sec * 10 + (c - '0'); - } - else - { - m_error = true; - } - break; - case 8: + stateStartIndex = index + 1; + } + else + { + m_error = true; + } + break; + case 2: + if (isdigit(c)) + { + m_parsedTimestamp.tm_mday = m_parsedTimestamp.tm_mday * 10 + (c - '0'); + } + else if(isspace(c)) + { + m_state = 3; + stateStartIndex = index + 1; + } + else + { + m_error = true; + } + break; + case 3: + if (isspace(c)) + { + int monthNumber = GetMonthNumberFromStr(m_toParse, stateStartIndex, index + 1); + + if (monthNumber > -1) + { + m_state = 4; + stateStartIndex = index + 1; + m_parsedTimestamp.tm_mon = monthNumber; + } + else + { + m_error = true; + } + } + else if (!isalpha(c)) + { + m_error = true; + } + break; + case 4: + if (isspace(c) && index - stateStartIndex == 4) + { + m_state = 5; + stateStartIndex = index + 1; + m_parsedTimestamp.tm_year -= 1900; + } + else if (isspace(c) && index - stateStartIndex == 2) + { + m_state = 5; + stateStartIndex = index + 1; + m_parsedTimestamp.tm_year += 2000 - 1900; + } + else if (isdigit(c)) + { + m_parsedTimestamp.tm_year = m_parsedTimestamp.tm_year * 10 + (c - '0'); + } + else + { + m_error = true; + } + break; + case 5: + if(c == ':' && index - stateStartIndex == 2) + { + m_state = 6; + stateStartIndex = index + 1; + } + else if (isdigit(c)) + { + m_parsedTimestamp.tm_hour = m_parsedTimestamp.tm_hour * 10 + (c - '0'); + } + else + { + m_error = true; + } + break; + case 6: + if (c == ':' && index - stateStartIndex == 2) + { + m_state = 7; + stateStartIndex = index + 1; + } + else if (isdigit(c)) + { + m_parsedTimestamp.tm_min = m_parsedTimestamp.tm_min * 10 + (c - '0'); + } + else + { + m_error = true; + } + break; + case 7: + if (isspace(c) && index - stateStartIndex == 2) + { + m_state = 8; + stateStartIndex = index + 1; + } + else if (isdigit(c)) + { + m_parsedTimestamp.tm_sec = m_parsedTimestamp.tm_sec * 10 + (c - '0'); + } + else + { + m_error = true; + } + break; + case 8: if ((isalnum(c) || c == '+' || c == '-') && (index - stateStartIndex < 5)) - { - m_tz[index - stateStartIndex] = c; + { + m_tz[index - stateStartIndex] = c; } else { m_error = true; } - break; + break; default: m_error = true; break; - } - - index++; - } - - if (m_tz[0] != 0) - { + } + + index++; + } + + if (m_tz[0] != 0) + { m_utcAssumed = IsUTCTimeZoneDesignator(m_tz); - } - - m_error = (m_error || m_state != finalState); - } - - int GetState() const { return m_state; } - -private: + } + + m_error = (m_error || m_state != finalState); + } + + int GetState() const { return m_state; } + +private: //Detects whether or not the passed in timezone string is a UTC zone. static bool IsUTCTimeZoneDesignator(const char* str) { @@ -702,157 +702,157 @@ private: } - int m_state; -}; - -//Before you send me hate mail because I'm doing this manually, I encourage you to try using std::get_time on all platforms and getting -//uniform results. Timezone information doesn't parse on Windows and it hardly even works on GCC 4.9.x. This is the only way to make sure -//the standard is parsed correctly. strptime isn't available one Windows. This code gets hit pretty hard during http serialization/deserialization -//as a result I'm going for no dynamic allocations and linear complexity -class ISO_8601DateParser : public DateParser -{ -public: - ISO_8601DateParser(const char* stringToParse) : DateParser(stringToParse), m_state(0) - { - } - - //parses "%Y-%m-%dT%H:%M:%SZ or "%Y-%m-%dT%H:%M:%S.000Z" - void Parse() override - { - size_t len = strlen(m_toParse); - - //DOS check - if (len > MAX_LEN) - { + int m_state; +}; + +//Before you send me hate mail because I'm doing this manually, I encourage you to try using std::get_time on all platforms and getting +//uniform results. Timezone information doesn't parse on Windows and it hardly even works on GCC 4.9.x. This is the only way to make sure +//the standard is parsed correctly. strptime isn't available one Windows. This code gets hit pretty hard during http serialization/deserialization +//as a result I'm going for no dynamic allocations and linear complexity +class ISO_8601DateParser : public DateParser +{ +public: + ISO_8601DateParser(const char* stringToParse) : DateParser(stringToParse), m_state(0) + { + } + + //parses "%Y-%m-%dT%H:%M:%SZ or "%Y-%m-%dT%H:%M:%S.000Z" + void Parse() override + { + size_t len = strlen(m_toParse); + + //DOS check + if (len > MAX_LEN) + { AWS_LOGSTREAM_WARN(CLASS_TAG, "Incoming String to parse too long with length: " << len) - m_error = true; - return; - } - - size_t index = 0; - size_t stateStartIndex = 0; - const int finalState = 7; - - while (m_state <= finalState && !m_error && index < len) - { - char c = m_toParse[index]; - switch (m_state) - { - case 0: - if (c == '-' && index - stateStartIndex == 4) - { - m_state = 1; - stateStartIndex = index + 1; - m_parsedTimestamp.tm_year -= 1900; - } - else if (isdigit(c)) - { - m_parsedTimestamp.tm_year = m_parsedTimestamp.tm_year * 10 + (c - '0'); - } - else - { - m_error = true; - } - break; - case 1: - if (c == '-' && index - stateStartIndex == 2) - { - m_state = 2; - stateStartIndex = index + 1; - m_parsedTimestamp.tm_mon -= 1; - } - else if (isdigit(c)) - { - m_parsedTimestamp.tm_mon = m_parsedTimestamp.tm_mon * 10 + (c - '0'); - } - else - { - m_error = true; - } - - break; - case 2: - if (c == 'T' && index - stateStartIndex == 2) - { - m_state = 3; - stateStartIndex = index + 1; - } - else if (isdigit(c)) - { - m_parsedTimestamp.tm_mday = m_parsedTimestamp.tm_mday * 10 + (c - '0'); - } - else - { - m_error = true; - } - - break; - case 3: - if (c == ':' && index - stateStartIndex == 2) - { - m_state = 4; - stateStartIndex = index + 1; - } - else if (isdigit(c)) - { - m_parsedTimestamp.tm_hour = m_parsedTimestamp.tm_hour * 10 + (c - '0'); - } - else - { - m_error = true; - } - - break; - case 4: - if (c == ':' && index - stateStartIndex == 2) - { - m_state = 5; - stateStartIndex = index + 1; - } - else if (isdigit(c)) - { - m_parsedTimestamp.tm_min = m_parsedTimestamp.tm_min * 10 + (c - '0'); - } - else - { - m_error = true; - } - - break; - case 5: + m_error = true; + return; + } + + size_t index = 0; + size_t stateStartIndex = 0; + const int finalState = 7; + + while (m_state <= finalState && !m_error && index < len) + { + char c = m_toParse[index]; + switch (m_state) + { + case 0: + if (c == '-' && index - stateStartIndex == 4) + { + m_state = 1; + stateStartIndex = index + 1; + m_parsedTimestamp.tm_year -= 1900; + } + else if (isdigit(c)) + { + m_parsedTimestamp.tm_year = m_parsedTimestamp.tm_year * 10 + (c - '0'); + } + else + { + m_error = true; + } + break; + case 1: + if (c == '-' && index - stateStartIndex == 2) + { + m_state = 2; + stateStartIndex = index + 1; + m_parsedTimestamp.tm_mon -= 1; + } + else if (isdigit(c)) + { + m_parsedTimestamp.tm_mon = m_parsedTimestamp.tm_mon * 10 + (c - '0'); + } + else + { + m_error = true; + } + + break; + case 2: + if (c == 'T' && index - stateStartIndex == 2) + { + m_state = 3; + stateStartIndex = index + 1; + } + else if (isdigit(c)) + { + m_parsedTimestamp.tm_mday = m_parsedTimestamp.tm_mday * 10 + (c - '0'); + } + else + { + m_error = true; + } + + break; + case 3: + if (c == ':' && index - stateStartIndex == 2) + { + m_state = 4; + stateStartIndex = index + 1; + } + else if (isdigit(c)) + { + m_parsedTimestamp.tm_hour = m_parsedTimestamp.tm_hour * 10 + (c - '0'); + } + else + { + m_error = true; + } + + break; + case 4: + if (c == ':' && index - stateStartIndex == 2) + { + m_state = 5; + stateStartIndex = index + 1; + } + else if (isdigit(c)) + { + m_parsedTimestamp.tm_min = m_parsedTimestamp.tm_min * 10 + (c - '0'); + } + else + { + m_error = true; + } + + break; + case 5: if ((c == 'Z' || c == '+' || c == '-' ) && (index - stateStartIndex == 2)) - { + { m_tz[0] = c; m_state = 7; - stateStartIndex = index + 1; - } - else if (c == '.' && index - stateStartIndex == 2) - { - m_state = 6; - stateStartIndex = index + 1; - } - else if (isdigit(c)) - { - m_parsedTimestamp.tm_sec = m_parsedTimestamp.tm_sec * 10 + (c - '0'); - } - else - { - m_error = true; - } - - break; - case 6: + stateStartIndex = index + 1; + } + else if (c == '.' && index - stateStartIndex == 2) + { + m_state = 6; + stateStartIndex = index + 1; + } + else if (isdigit(c)) + { + m_parsedTimestamp.tm_sec = m_parsedTimestamp.tm_sec * 10 + (c - '0'); + } + else + { + m_error = true; + } + + break; + case 6: if ((c == 'Z' || c == '+' || c == '-' ) && (index - stateStartIndex == 3)) - { + { m_tz[0] = c; m_state = 7; - stateStartIndex = index + 1; - } - else if(!isdigit(c)) - { - m_error = true; - } - break; + stateStartIndex = index + 1; + } + else if(!isdigit(c)) + { + m_error = true; + } + break; case 7: if ((isdigit(c) || c == ':') && (index - stateStartIndex < 5)) { @@ -866,24 +866,24 @@ public: default: m_error = true; break; - } - index++; - } - + } + index++; + } + if (m_tz[0] != 0) { m_utcAssumed = IsUTCTimeZoneDesignator(m_tz); } - m_error = (m_error || m_state != finalState); - } - + m_error = (m_error || m_state != finalState); + } + private: //Detects whether or not the passed in timezone string is a UTC zone. static bool IsUTCTimeZoneDesignator(const char* str) { size_t len = strlen(str); - + if (len > 0) { if (len == 1 && str[0] == 'Z') @@ -1075,7 +1075,7 @@ public: m_error = (m_error || m_state != finalState); } -private: +private: //Detects whether or not the passed in timezone string is a UTC zone. static bool IsUTCTimeZoneDesignator(const char* str) { @@ -1103,246 +1103,246 @@ private: return false; } - int m_state; -}; + int m_state; +}; } // namespace - -DateTime::DateTime(const std::chrono::system_clock::time_point& timepointToAssign) : m_time(timepointToAssign), m_valid(true) -{ -} - -DateTime::DateTime(int64_t millisSinceEpoch) : m_valid(true) -{ - std::chrono::duration<int64_t, std::chrono::milliseconds::period> timestamp(millisSinceEpoch); - m_time = std::chrono::system_clock::time_point(timestamp); -} - -DateTime::DateTime(double epoch_millis) : m_valid(true) -{ - std::chrono::duration<double, std::chrono::seconds::period> timestamp(epoch_millis); - m_time = std::chrono::system_clock::time_point(std::chrono::duration_cast<std::chrono::milliseconds>(timestamp)); -} - -DateTime::DateTime(const Aws::String& timestamp, DateFormat format) : m_valid(true) -{ - ConvertTimestampStringToTimePoint(timestamp.c_str(), format); -} - -DateTime::DateTime(const char* timestamp, DateFormat format) : m_valid(true) -{ - ConvertTimestampStringToTimePoint(timestamp, format); -} - -DateTime::DateTime() : m_valid(true) -{ - //init time_point to default by doing nothing. -} - -DateTime& DateTime::operator=(const Aws::String& timestamp) -{ - *this = DateTime(timestamp, DateFormat::AutoDetect); - return *this; -} - -DateTime& DateTime::operator=(double secondsMillis) -{ - *this = DateTime(secondsMillis); - return *this; -} - -DateTime& DateTime::operator=(int64_t millisSinceEpoch) + +DateTime::DateTime(const std::chrono::system_clock::time_point& timepointToAssign) : m_time(timepointToAssign), m_valid(true) { - *this = DateTime(millisSinceEpoch); - return *this; -} - -DateTime& DateTime::operator=(const std::chrono::system_clock::time_point& timepointToAssign) -{ - *this = DateTime(timepointToAssign); - return *this; -} - -bool DateTime::operator == (const DateTime& other) const -{ - return m_time == other.m_time; -} - -bool DateTime::operator < (const DateTime& other) const -{ - return m_time < other.m_time; -} - -bool DateTime::operator > (const DateTime& other) const -{ - return m_time > other.m_time; -} - -bool DateTime::operator != (const DateTime& other) const -{ - return m_time != other.m_time; -} - -bool DateTime::operator <= (const DateTime& other) const -{ - return m_time <= other.m_time; -} - -bool DateTime::operator >= (const DateTime& other) const -{ - return m_time >= other.m_time; -} - -DateTime DateTime::operator +(const std::chrono::milliseconds& a) const -{ - auto timepointCpy = m_time; - timepointCpy += a; - return DateTime(timepointCpy); -} - -DateTime DateTime::operator -(const std::chrono::milliseconds& a) const -{ - auto timepointCpy = m_time; - timepointCpy -= a; - return DateTime(timepointCpy); -} - -Aws::String DateTime::ToLocalTimeString(DateFormat format) const -{ - switch (format) - { - case DateFormat::ISO_8601: - return ToLocalTimeString(ISO_8601_LONG_DATE_FORMAT_STR); +} + +DateTime::DateTime(int64_t millisSinceEpoch) : m_valid(true) +{ + std::chrono::duration<int64_t, std::chrono::milliseconds::period> timestamp(millisSinceEpoch); + m_time = std::chrono::system_clock::time_point(timestamp); +} + +DateTime::DateTime(double epoch_millis) : m_valid(true) +{ + std::chrono::duration<double, std::chrono::seconds::period> timestamp(epoch_millis); + m_time = std::chrono::system_clock::time_point(std::chrono::duration_cast<std::chrono::milliseconds>(timestamp)); +} + +DateTime::DateTime(const Aws::String& timestamp, DateFormat format) : m_valid(true) +{ + ConvertTimestampStringToTimePoint(timestamp.c_str(), format); +} + +DateTime::DateTime(const char* timestamp, DateFormat format) : m_valid(true) +{ + ConvertTimestampStringToTimePoint(timestamp, format); +} + +DateTime::DateTime() : m_valid(true) +{ + //init time_point to default by doing nothing. +} + +DateTime& DateTime::operator=(const Aws::String& timestamp) +{ + *this = DateTime(timestamp, DateFormat::AutoDetect); + return *this; +} + +DateTime& DateTime::operator=(double secondsMillis) +{ + *this = DateTime(secondsMillis); + return *this; +} + +DateTime& DateTime::operator=(int64_t millisSinceEpoch) +{ + *this = DateTime(millisSinceEpoch); + return *this; +} + +DateTime& DateTime::operator=(const std::chrono::system_clock::time_point& timepointToAssign) +{ + *this = DateTime(timepointToAssign); + return *this; +} + +bool DateTime::operator == (const DateTime& other) const +{ + return m_time == other.m_time; +} + +bool DateTime::operator < (const DateTime& other) const +{ + return m_time < other.m_time; +} + +bool DateTime::operator > (const DateTime& other) const +{ + return m_time > other.m_time; +} + +bool DateTime::operator != (const DateTime& other) const +{ + return m_time != other.m_time; +} + +bool DateTime::operator <= (const DateTime& other) const +{ + return m_time <= other.m_time; +} + +bool DateTime::operator >= (const DateTime& other) const +{ + return m_time >= other.m_time; +} + +DateTime DateTime::operator +(const std::chrono::milliseconds& a) const +{ + auto timepointCpy = m_time; + timepointCpy += a; + return DateTime(timepointCpy); +} + +DateTime DateTime::operator -(const std::chrono::milliseconds& a) const +{ + auto timepointCpy = m_time; + timepointCpy -= a; + return DateTime(timepointCpy); +} + +Aws::String DateTime::ToLocalTimeString(DateFormat format) const +{ + switch (format) + { + case DateFormat::ISO_8601: + return ToLocalTimeString(ISO_8601_LONG_DATE_FORMAT_STR); case DateFormat::ISO_8601_BASIC: return ToLocalTimeString(ISO_8601_LONG_BASIC_DATE_FORMAT_STR); - case DateFormat::RFC822: + case DateFormat::RFC822: return ToLocalTimeString(RFC822_DATE_FORMAT_STR_WITH_Z); - default: - assert(0); - return ""; - } -} - -Aws::String DateTime::ToLocalTimeString(const char* formatStr) const -{ - struct tm localTimeStamp = ConvertTimestampToLocalTimeStruct(); - - char formattedString[100]; - std::strftime(formattedString, sizeof(formattedString), formatStr, &localTimeStamp); - return formattedString; -} - -Aws::String DateTime::ToGmtString(DateFormat format) const -{ - switch (format) - { - case DateFormat::ISO_8601: - return ToGmtString(ISO_8601_LONG_DATE_FORMAT_STR); + default: + assert(0); + return ""; + } +} + +Aws::String DateTime::ToLocalTimeString(const char* formatStr) const +{ + struct tm localTimeStamp = ConvertTimestampToLocalTimeStruct(); + + char formattedString[100]; + std::strftime(formattedString, sizeof(formattedString), formatStr, &localTimeStamp); + return formattedString; +} + +Aws::String DateTime::ToGmtString(DateFormat format) const +{ + switch (format) + { + case DateFormat::ISO_8601: + return ToGmtString(ISO_8601_LONG_DATE_FORMAT_STR); case DateFormat::ISO_8601_BASIC: return ToGmtString(ISO_8601_LONG_BASIC_DATE_FORMAT_STR); - case DateFormat::RFC822: - { + case DateFormat::RFC822: + { //Windows erroneously drops the local timezone in for %Z - Aws::String rfc822GmtString = ToGmtString(RFC822_DATE_FORMAT_STR_MINUS_Z); - rfc822GmtString += " GMT"; - return rfc822GmtString; - } - default: - assert(0); - return ""; - } -} - -Aws::String DateTime::ToGmtString(const char* formatStr) const -{ - struct tm gmtTimeStamp = ConvertTimestampToGmtStruct(); - - char formattedString[100]; - std::strftime(formattedString, sizeof(formattedString), formatStr, &gmtTimeStamp); - return formattedString; -} - -double DateTime::SecondsWithMSPrecision() const -{ - std::chrono::duration<double, std::chrono::seconds::period> timestamp(m_time.time_since_epoch()); - return timestamp.count(); -} - -int64_t DateTime::Millis() const -{ - auto timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(m_time.time_since_epoch()); - return timestamp.count(); -} - -std::chrono::system_clock::time_point DateTime::UnderlyingTimestamp() const -{ - return m_time; -} - -int DateTime::GetYear(bool localTime) const -{ - return GetTimeStruct(localTime).tm_year + 1900; -} - -Month DateTime::GetMonth(bool localTime) const -{ - return static_cast<Aws::Utils::Month>(GetTimeStruct(localTime).tm_mon); -} - -int DateTime::GetDay(bool localTime) const -{ - return GetTimeStruct(localTime).tm_mday; -} - -DayOfWeek DateTime::GetDayOfWeek(bool localTime) const -{ - return static_cast<Aws::Utils::DayOfWeek>(GetTimeStruct(localTime).tm_wday); -} - -int DateTime::GetHour(bool localTime) const -{ - return GetTimeStruct(localTime).tm_hour; -} - -int DateTime::GetMinute(bool localTime) const -{ - return GetTimeStruct(localTime).tm_min; -} - -int DateTime::GetSecond(bool localTime) const -{ - return GetTimeStruct(localTime).tm_sec; -} - -bool DateTime::IsDST(bool localTime) const -{ - return GetTimeStruct(localTime).tm_isdst == 0 ? false : true; -} - -DateTime DateTime::Now() -{ - DateTime dateTime; - dateTime.m_time = std::chrono::system_clock::now(); - return dateTime; -} - -int64_t DateTime::CurrentTimeMillis() -{ - return Now().Millis(); -} - -Aws::String DateTime::CalculateLocalTimestampAsString(const char* formatStr) -{ - DateTime now = Now(); - return now.ToLocalTimeString(formatStr); -} - -Aws::String DateTime::CalculateGmtTimestampAsString(const char* formatStr) + Aws::String rfc822GmtString = ToGmtString(RFC822_DATE_FORMAT_STR_MINUS_Z); + rfc822GmtString += " GMT"; + return rfc822GmtString; + } + default: + assert(0); + return ""; + } +} + +Aws::String DateTime::ToGmtString(const char* formatStr) const { - DateTime now = Now(); - return now.ToGmtString(formatStr); -} - + struct tm gmtTimeStamp = ConvertTimestampToGmtStruct(); + + char formattedString[100]; + std::strftime(formattedString, sizeof(formattedString), formatStr, &gmtTimeStamp); + return formattedString; +} + +double DateTime::SecondsWithMSPrecision() const +{ + std::chrono::duration<double, std::chrono::seconds::period> timestamp(m_time.time_since_epoch()); + return timestamp.count(); +} + +int64_t DateTime::Millis() const +{ + auto timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(m_time.time_since_epoch()); + return timestamp.count(); +} + +std::chrono::system_clock::time_point DateTime::UnderlyingTimestamp() const +{ + return m_time; +} + +int DateTime::GetYear(bool localTime) const +{ + return GetTimeStruct(localTime).tm_year + 1900; +} + +Month DateTime::GetMonth(bool localTime) const +{ + return static_cast<Aws::Utils::Month>(GetTimeStruct(localTime).tm_mon); +} + +int DateTime::GetDay(bool localTime) const +{ + return GetTimeStruct(localTime).tm_mday; +} + +DayOfWeek DateTime::GetDayOfWeek(bool localTime) const +{ + return static_cast<Aws::Utils::DayOfWeek>(GetTimeStruct(localTime).tm_wday); +} + +int DateTime::GetHour(bool localTime) const +{ + return GetTimeStruct(localTime).tm_hour; +} + +int DateTime::GetMinute(bool localTime) const +{ + return GetTimeStruct(localTime).tm_min; +} + +int DateTime::GetSecond(bool localTime) const +{ + return GetTimeStruct(localTime).tm_sec; +} + +bool DateTime::IsDST(bool localTime) const +{ + return GetTimeStruct(localTime).tm_isdst == 0 ? false : true; +} + +DateTime DateTime::Now() +{ + DateTime dateTime; + dateTime.m_time = std::chrono::system_clock::now(); + return dateTime; +} + +int64_t DateTime::CurrentTimeMillis() +{ + return Now().Millis(); +} + +Aws::String DateTime::CalculateLocalTimestampAsString(const char* formatStr) +{ + DateTime now = Now(); + return now.ToLocalTimeString(formatStr); +} + +Aws::String DateTime::CalculateGmtTimestampAsString(const char* formatStr) +{ + DateTime now = Now(); + return now.ToGmtString(formatStr); +} + Aws::String DateTime::CalculateGmtTimeWithMsPrecision() { auto now = DateTime::Now(); @@ -1368,53 +1368,53 @@ Aws::String DateTime::CalculateGmtTimeWithMsPrecision() return formattedString; } -int DateTime::CalculateCurrentHour() -{ - return Now().GetHour(true); -} - -double DateTime::ComputeCurrentTimestampInAmazonFormat() -{ - return Now().SecondsWithMSPrecision(); -} - -std::chrono::milliseconds DateTime::Diff(const DateTime& a, const DateTime& b) -{ - auto diff = a.m_time - b.m_time; - return std::chrono::duration_cast<std::chrono::milliseconds>(diff); -} - +int DateTime::CalculateCurrentHour() +{ + return Now().GetHour(true); +} + +double DateTime::ComputeCurrentTimestampInAmazonFormat() +{ + return Now().SecondsWithMSPrecision(); +} + +std::chrono::milliseconds DateTime::Diff(const DateTime& a, const DateTime& b) +{ + auto diff = a.m_time - b.m_time; + return std::chrono::duration_cast<std::chrono::milliseconds>(diff); +} + std::chrono::milliseconds DateTime::operator-(const DateTime& other) const +{ + auto diff = this->m_time - other.m_time; + return std::chrono::duration_cast<std::chrono::milliseconds>(diff); +} + +void DateTime::ConvertTimestampStringToTimePoint(const char* timestamp, DateFormat format) { - auto diff = this->m_time - other.m_time; - return std::chrono::duration_cast<std::chrono::milliseconds>(diff); -} - -void DateTime::ConvertTimestampStringToTimePoint(const char* timestamp, DateFormat format) -{ - std::tm timeStruct; - bool isUtc = true; - - switch (format) - { - case DateFormat::RFC822: - { - RFC822DateParser parser(timestamp); - parser.Parse(); - m_valid = parser.WasParseSuccessful(); - isUtc = parser.ShouldIAssumeThisIsUTC(); - timeStruct = parser.GetParsedTimestamp(); - break; - } - case DateFormat::ISO_8601: - { - ISO_8601DateParser parser(timestamp); - parser.Parse(); - m_valid = parser.WasParseSuccessful(); - isUtc = parser.ShouldIAssumeThisIsUTC(); - timeStruct = parser.GetParsedTimestamp(); + std::tm timeStruct; + bool isUtc = true; + + switch (format) + { + case DateFormat::RFC822: + { + RFC822DateParser parser(timestamp); + parser.Parse(); + m_valid = parser.WasParseSuccessful(); + isUtc = parser.ShouldIAssumeThisIsUTC(); + timeStruct = parser.GetParsedTimestamp(); + break; + } + case DateFormat::ISO_8601: + { + ISO_8601DateParser parser(timestamp); + parser.Parse(); + m_valid = parser.WasParseSuccessful(); + isUtc = parser.ShouldIAssumeThisIsUTC(); + timeStruct = parser.GetParsedTimestamp(); break; - } + } case DateFormat::ISO_8601_BASIC: { ISO_8601BasicDateParser parser(timestamp); @@ -1424,26 +1424,26 @@ void DateTime::ConvertTimestampStringToTimePoint(const char* timestamp, DateForm timeStruct = parser.GetParsedTimestamp(); break; } - case DateFormat::AutoDetect: - { - RFC822DateParser rfcParser(timestamp); - rfcParser.Parse(); - if(rfcParser.WasParseSuccessful()) - { - m_valid = true; - isUtc = rfcParser.ShouldIAssumeThisIsUTC(); - timeStruct = rfcParser.GetParsedTimestamp(); - break; - } - ISO_8601DateParser isoParser(timestamp); - isoParser.Parse(); - if (isoParser.WasParseSuccessful()) - { - m_valid = true; - isUtc = isoParser.ShouldIAssumeThisIsUTC(); - timeStruct = isoParser.GetParsedTimestamp(); - break; - } + case DateFormat::AutoDetect: + { + RFC822DateParser rfcParser(timestamp); + rfcParser.Parse(); + if(rfcParser.WasParseSuccessful()) + { + m_valid = true; + isUtc = rfcParser.ShouldIAssumeThisIsUTC(); + timeStruct = rfcParser.GetParsedTimestamp(); + break; + } + ISO_8601DateParser isoParser(timestamp); + isoParser.Parse(); + if (isoParser.WasParseSuccessful()) + { + m_valid = true; + isUtc = isoParser.ShouldIAssumeThisIsUTC(); + timeStruct = isoParser.GetParsedTimestamp(); + break; + } ISO_8601BasicDateParser isoBasicParser(timestamp); isoBasicParser.Parse(); if (isoBasicParser.WasParseSuccessful()) @@ -1453,50 +1453,50 @@ void DateTime::ConvertTimestampStringToTimePoint(const char* timestamp, DateForm timeStruct = isoBasicParser.GetParsedTimestamp(); break; } - m_valid = false; - break; - } + m_valid = false; + break; + } default: - assert(0); + assert(0); } - if (m_valid) + if (m_valid) { - std::time_t tt; - if(isUtc) - { - tt = Aws::Time::TimeGM(&timeStruct); - } - else - { - assert(0); - AWS_LOGSTREAM_WARN(CLASS_TAG, "Non-UTC timestamp detected. This is always a bug. Make the world a better place and fix whatever sent you this timestamp: " << timestamp) - tt = std::mktime(&timeStruct); - } - m_time = std::chrono::system_clock::from_time_t(tt); + std::time_t tt; + if(isUtc) + { + tt = Aws::Time::TimeGM(&timeStruct); + } + else + { + assert(0); + AWS_LOGSTREAM_WARN(CLASS_TAG, "Non-UTC timestamp detected. This is always a bug. Make the world a better place and fix whatever sent you this timestamp: " << timestamp) + tt = std::mktime(&timeStruct); + } + m_time = std::chrono::system_clock::from_time_t(tt); } -} - -tm DateTime::GetTimeStruct(bool localTime) const -{ - return localTime ? ConvertTimestampToLocalTimeStruct() : ConvertTimestampToGmtStruct(); -} - -tm DateTime::ConvertTimestampToLocalTimeStruct() const -{ - std::time_t time = std::chrono::system_clock::to_time_t(m_time); - struct tm localTimeStamp; - - Aws::Time::LocalTime(&localTimeStamp, time); - - return localTimeStamp; -} - -tm DateTime::ConvertTimestampToGmtStruct() const -{ - std::time_t time = std::chrono::system_clock::to_time_t(m_time); - struct tm gmtTimeStamp; - Aws::Time::GMTime(&gmtTimeStamp, time); - - return gmtTimeStamp; -} +} + +tm DateTime::GetTimeStruct(bool localTime) const +{ + return localTime ? ConvertTimestampToLocalTimeStruct() : ConvertTimestampToGmtStruct(); +} + +tm DateTime::ConvertTimestampToLocalTimeStruct() const +{ + std::time_t time = std::chrono::system_clock::to_time_t(m_time); + struct tm localTimeStamp; + + Aws::Time::LocalTime(&localTimeStamp, time); + + return localTimeStamp; +} + +tm DateTime::ConvertTimestampToGmtStruct() const +{ + std::time_t time = std::chrono::system_clock::to_time_t(m_time); + struct tm gmtTimeStamp; + Aws::Time::GMTime(&gmtTimeStamp, time); + + return gmtTimeStamp; +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/Directory.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/Directory.cpp index 49ca56b280..5423d38793 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/Directory.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/Directory.cpp @@ -2,322 +2,322 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/platform/FileSystem.h> -#include <aws/core/utils/memory/stl/AWSQueue.h> -#include <aws/core/utils/memory/stl/AWSStringStream.h> -#include <aws/core/utils/memory/stl/AWSStreamFwd.h> -#include <aws/core/utils/StringUtils.h> -#include <fstream> -#include <cassert> - -namespace Aws -{ - namespace FileSystem - { - Aws::String Join(const Aws::String& leftSegment, const Aws::String& rightSegment) - { - return Join(PATH_DELIM, leftSegment, rightSegment); - } - - Aws::String Join(char delimiter, const Aws::String& leftSegment, const Aws::String& rightSegment) - { - Aws::StringStream ss; - - if (!leftSegment.empty()) - { - if (leftSegment.back() == delimiter) - { - ss << leftSegment.substr(0, leftSegment.length() - 1); - } - else - { - ss << leftSegment; - } - } - - ss << delimiter; - - if (!rightSegment.empty()) - { - if (rightSegment.front() == delimiter) - { - ss << rightSegment.substr(1); - } - else - { - ss << rightSegment; - } - } - - return ss.str(); - } - - bool DeepCopyDirectory(const char* from, const char* to) - { - if (!from || !to) return false; - - DirectoryTree fromDir(from); - - if (!fromDir) return false; - - CreateDirectoryIfNotExists(to); - DirectoryTree toDir(to); - - if (!toDir) return false; - - bool success(true); - - auto visitor = [to,&success](const DirectoryTree*, const DirectoryEntry& entry) - { - auto newPath = Aws::FileSystem::Join(to, entry.relativePath); - - if (entry.fileType == Aws::FileSystem::FileType::File) - { - Aws::OFStream copyOutStream(newPath.c_str()); - Aws::IFStream originalStream(entry.path.c_str()); - - if(!copyOutStream.good() || !originalStream.good()) - { - success = false; - return false; - } - - std::copy(std::istreambuf_iterator<char>(originalStream), - std::istreambuf_iterator<char>(), std::ostreambuf_iterator<char>(copyOutStream)); - } - else if (entry.fileType == Aws::FileSystem::FileType::Directory) - { - success = CreateDirectoryIfNotExists(newPath.c_str()); - return success; - } - - return success; - }; - - fromDir.TraverseDepthFirst(visitor); - return success; - } - - bool DeepDeleteDirectory(const char* toDelete) - { - bool success(true); - - //scope this to a new stack frame, because we won't be able to delete the root directory - //unless the directory handle has closed. - { - DirectoryTree delDir(toDelete); - - if (!delDir) return false; - - auto visitor = [&success](const DirectoryTree*, const DirectoryEntry& entry) - { - if (entry.fileType == FileType::File) - { - success = RemoveFileIfExists(entry.path.c_str()); - } - else - { - success = RemoveDirectoryIfExists(entry.path.c_str()); - } - - return success; - }; - - delDir.TraverseDepthFirst(visitor, true); - } - - if (success) - { - success = RemoveDirectoryIfExists(toDelete); - } - - return success; - } - - Directory::Directory(const Aws::String& path, const Aws::String& relativePath) - { - auto trimmedPath = Utils::StringUtils::Trim(path.c_str()); - auto trimmedRelativePath = Utils::StringUtils::Trim(relativePath.c_str()); - - if (!trimmedPath.empty() && trimmedPath[trimmedPath.length() - 1] == PATH_DELIM) - { - m_directoryEntry.path = trimmedPath.substr(0, trimmedPath.length() - 1); - } - else - { - m_directoryEntry.path = trimmedPath; - } - - if (!trimmedRelativePath.empty() && trimmedRelativePath[trimmedRelativePath.length() - 1] == PATH_DELIM) - { - m_directoryEntry.relativePath = trimmedRelativePath.substr(0, trimmedRelativePath.length() - 1); - } - else - { - m_directoryEntry.relativePath = trimmedRelativePath; - } - } - - Aws::UniquePtr<Directory> Directory::Descend(const DirectoryEntry& directoryEntry) - { - assert(directoryEntry.fileType != FileType::File); - return OpenDirectory(directoryEntry.path, directoryEntry.relativePath); - } - - Aws::Vector<Aws::String> Directory::GetAllFilePathsInDirectory(const Aws::String& path) - { - Aws::FileSystem::DirectoryTree tree(path); - Aws::Vector<Aws::String> filesVector; - auto visitor = [&](const Aws::FileSystem::DirectoryTree*, const Aws::FileSystem::DirectoryEntry& entry) + +#include <aws/core/platform/FileSystem.h> +#include <aws/core/utils/memory/stl/AWSQueue.h> +#include <aws/core/utils/memory/stl/AWSStringStream.h> +#include <aws/core/utils/memory/stl/AWSStreamFwd.h> +#include <aws/core/utils/StringUtils.h> +#include <fstream> +#include <cassert> + +namespace Aws +{ + namespace FileSystem + { + Aws::String Join(const Aws::String& leftSegment, const Aws::String& rightSegment) + { + return Join(PATH_DELIM, leftSegment, rightSegment); + } + + Aws::String Join(char delimiter, const Aws::String& leftSegment, const Aws::String& rightSegment) + { + Aws::StringStream ss; + + if (!leftSegment.empty()) + { + if (leftSegment.back() == delimiter) + { + ss << leftSegment.substr(0, leftSegment.length() - 1); + } + else + { + ss << leftSegment; + } + } + + ss << delimiter; + + if (!rightSegment.empty()) + { + if (rightSegment.front() == delimiter) + { + ss << rightSegment.substr(1); + } + else + { + ss << rightSegment; + } + } + + return ss.str(); + } + + bool DeepCopyDirectory(const char* from, const char* to) + { + if (!from || !to) return false; + + DirectoryTree fromDir(from); + + if (!fromDir) return false; + + CreateDirectoryIfNotExists(to); + DirectoryTree toDir(to); + + if (!toDir) return false; + + bool success(true); + + auto visitor = [to,&success](const DirectoryTree*, const DirectoryEntry& entry) + { + auto newPath = Aws::FileSystem::Join(to, entry.relativePath); + + if (entry.fileType == Aws::FileSystem::FileType::File) + { + Aws::OFStream copyOutStream(newPath.c_str()); + Aws::IFStream originalStream(entry.path.c_str()); + + if(!copyOutStream.good() || !originalStream.good()) + { + success = false; + return false; + } + + std::copy(std::istreambuf_iterator<char>(originalStream), + std::istreambuf_iterator<char>(), std::ostreambuf_iterator<char>(copyOutStream)); + } + else if (entry.fileType == Aws::FileSystem::FileType::Directory) + { + success = CreateDirectoryIfNotExists(newPath.c_str()); + return success; + } + + return success; + }; + + fromDir.TraverseDepthFirst(visitor); + return success; + } + + bool DeepDeleteDirectory(const char* toDelete) + { + bool success(true); + + //scope this to a new stack frame, because we won't be able to delete the root directory + //unless the directory handle has closed. + { + DirectoryTree delDir(toDelete); + + if (!delDir) return false; + + auto visitor = [&success](const DirectoryTree*, const DirectoryEntry& entry) + { + if (entry.fileType == FileType::File) + { + success = RemoveFileIfExists(entry.path.c_str()); + } + else + { + success = RemoveDirectoryIfExists(entry.path.c_str()); + } + + return success; + }; + + delDir.TraverseDepthFirst(visitor, true); + } + + if (success) + { + success = RemoveDirectoryIfExists(toDelete); + } + + return success; + } + + Directory::Directory(const Aws::String& path, const Aws::String& relativePath) + { + auto trimmedPath = Utils::StringUtils::Trim(path.c_str()); + auto trimmedRelativePath = Utils::StringUtils::Trim(relativePath.c_str()); + + if (!trimmedPath.empty() && trimmedPath[trimmedPath.length() - 1] == PATH_DELIM) + { + m_directoryEntry.path = trimmedPath.substr(0, trimmedPath.length() - 1); + } + else + { + m_directoryEntry.path = trimmedPath; + } + + if (!trimmedRelativePath.empty() && trimmedRelativePath[trimmedRelativePath.length() - 1] == PATH_DELIM) + { + m_directoryEntry.relativePath = trimmedRelativePath.substr(0, trimmedRelativePath.length() - 1); + } + else { - if (entry.fileType == Aws::FileSystem::FileType::File) - { - filesVector.push_back(entry.path); - } - return true; - }; - tree.TraverseBreadthFirst(visitor); - return filesVector; - } - - DirectoryTree::DirectoryTree(const Aws::String& path) - { - m_dir = OpenDirectory(path); - } - - DirectoryTree::operator bool() const - { - return m_dir->operator bool(); - } - - bool DirectoryTree::operator==(DirectoryTree& other) - { - return Diff(other).size() == 0; - } - - bool DirectoryTree::operator==(const Aws::String& path) - { - return *this == DirectoryTree(path); - } - - Aws::Map<Aws::String, DirectoryEntry> DirectoryTree::Diff(DirectoryTree& other) - { - Aws::Map<Aws::String, DirectoryEntry> thisEntries; - auto thisTraversal = [&thisEntries](const DirectoryTree*, const DirectoryEntry& entry) - { - thisEntries[entry.relativePath] = entry; - return true; - }; - - Aws::Map<Aws::String, DirectoryEntry> otherEntries; - auto otherTraversal = [&thisEntries, &otherEntries](const DirectoryTree*, const DirectoryEntry& entry) - { - auto thisEntry = thisEntries.find(entry.relativePath); - if (thisEntry != thisEntries.end()) - { - thisEntries.erase(entry.relativePath); - } - else - { - otherEntries[entry.relativePath] = entry; - } - - return true; - }; - - TraverseDepthFirst(thisTraversal); - other.TraverseDepthFirst(otherTraversal); - - thisEntries.insert(otherEntries.begin(), otherEntries.end()); - return thisEntries; - } - - void DirectoryTree::TraverseDepthFirst(const DirectoryEntryVisitor& visitor, bool postOrderTraversal) - { - TraverseDepthFirst(*m_dir, visitor, postOrderTraversal); - m_dir = OpenDirectory(m_dir->GetPath()); - } - - void DirectoryTree::TraverseBreadthFirst(const DirectoryEntryVisitor& visitor) - { - TraverseBreadthFirst(*m_dir, visitor); - m_dir = OpenDirectory(m_dir->GetPath()); - } - - void DirectoryTree::TraverseBreadthFirst(Directory& dir, const DirectoryEntryVisitor& visitor) - { - if (!dir) - { - return; - } - - Aws::Queue<DirectoryEntry> queue; - while (DirectoryEntry&& entry = dir.Next()) - { - queue.push(std::move(entry)); - } - - while (queue.size() > 0) - { - auto entry = queue.front(); - queue.pop(); - if(visitor(this, entry)) - { - if(entry.fileType == FileType::Directory) - { - auto currentDir = dir.Descend(entry); - - while (DirectoryEntry&& dirEntry = currentDir->Next()) - { - queue.push(std::move(dirEntry)); - } - } - } - else - { - return; - } - } - } - - bool DirectoryTree::TraverseDepthFirst(Directory& dir, const DirectoryEntryVisitor& visitor, bool postOrder) - { - if (!dir) - { - return true; - } - - bool exitTraversal(false); - DirectoryEntry entry; - - while ((entry = dir.Next()) && !exitTraversal) - { - if(!postOrder) - { - if(!visitor(this, entry)) - { - return false; - } - } - - if (entry.fileType == FileType::Directory) - { - auto subDir = dir.Descend(entry); - exitTraversal = !TraverseDepthFirst(*subDir, visitor, postOrder); + m_directoryEntry.relativePath = trimmedRelativePath; + } + } + + Aws::UniquePtr<Directory> Directory::Descend(const DirectoryEntry& directoryEntry) + { + assert(directoryEntry.fileType != FileType::File); + return OpenDirectory(directoryEntry.path, directoryEntry.relativePath); + } + + Aws::Vector<Aws::String> Directory::GetAllFilePathsInDirectory(const Aws::String& path) + { + Aws::FileSystem::DirectoryTree tree(path); + Aws::Vector<Aws::String> filesVector; + auto visitor = [&](const Aws::FileSystem::DirectoryTree*, const Aws::FileSystem::DirectoryEntry& entry) + { + if (entry.fileType == Aws::FileSystem::FileType::File) + { + filesVector.push_back(entry.path); } - - if (postOrder) - { - if (!visitor(this, entry)) - { - return false; - } - } - } - - return !exitTraversal; - } - - } -} + return true; + }; + tree.TraverseBreadthFirst(visitor); + return filesVector; + } + + DirectoryTree::DirectoryTree(const Aws::String& path) + { + m_dir = OpenDirectory(path); + } + + DirectoryTree::operator bool() const + { + return m_dir->operator bool(); + } + + bool DirectoryTree::operator==(DirectoryTree& other) + { + return Diff(other).size() == 0; + } + + bool DirectoryTree::operator==(const Aws::String& path) + { + return *this == DirectoryTree(path); + } + + Aws::Map<Aws::String, DirectoryEntry> DirectoryTree::Diff(DirectoryTree& other) + { + Aws::Map<Aws::String, DirectoryEntry> thisEntries; + auto thisTraversal = [&thisEntries](const DirectoryTree*, const DirectoryEntry& entry) + { + thisEntries[entry.relativePath] = entry; + return true; + }; + + Aws::Map<Aws::String, DirectoryEntry> otherEntries; + auto otherTraversal = [&thisEntries, &otherEntries](const DirectoryTree*, const DirectoryEntry& entry) + { + auto thisEntry = thisEntries.find(entry.relativePath); + if (thisEntry != thisEntries.end()) + { + thisEntries.erase(entry.relativePath); + } + else + { + otherEntries[entry.relativePath] = entry; + } + + return true; + }; + + TraverseDepthFirst(thisTraversal); + other.TraverseDepthFirst(otherTraversal); + + thisEntries.insert(otherEntries.begin(), otherEntries.end()); + return thisEntries; + } + + void DirectoryTree::TraverseDepthFirst(const DirectoryEntryVisitor& visitor, bool postOrderTraversal) + { + TraverseDepthFirst(*m_dir, visitor, postOrderTraversal); + m_dir = OpenDirectory(m_dir->GetPath()); + } + + void DirectoryTree::TraverseBreadthFirst(const DirectoryEntryVisitor& visitor) + { + TraverseBreadthFirst(*m_dir, visitor); + m_dir = OpenDirectory(m_dir->GetPath()); + } + + void DirectoryTree::TraverseBreadthFirst(Directory& dir, const DirectoryEntryVisitor& visitor) + { + if (!dir) + { + return; + } + + Aws::Queue<DirectoryEntry> queue; + while (DirectoryEntry&& entry = dir.Next()) + { + queue.push(std::move(entry)); + } + + while (queue.size() > 0) + { + auto entry = queue.front(); + queue.pop(); + if(visitor(this, entry)) + { + if(entry.fileType == FileType::Directory) + { + auto currentDir = dir.Descend(entry); + + while (DirectoryEntry&& dirEntry = currentDir->Next()) + { + queue.push(std::move(dirEntry)); + } + } + } + else + { + return; + } + } + } + + bool DirectoryTree::TraverseDepthFirst(Directory& dir, const DirectoryEntryVisitor& visitor, bool postOrder) + { + if (!dir) + { + return true; + } + + bool exitTraversal(false); + DirectoryEntry entry; + + while ((entry = dir.Next()) && !exitTraversal) + { + if(!postOrder) + { + if(!visitor(this, entry)) + { + return false; + } + } + + if (entry.fileType == FileType::Directory) + { + auto subDir = dir.Descend(entry); + exitTraversal = !TraverseDepthFirst(*subDir, visitor, postOrder); + } + + if (postOrder) + { + if (!visitor(this, entry)) + { + return false; + } + } + } + + return !exitTraversal; + } + + } +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/EnumParseOverflowContainer.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/EnumParseOverflowContainer.cpp index eaeba1d910..3d93de1b97 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/EnumParseOverflowContainer.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/EnumParseOverflowContainer.cpp @@ -2,32 +2,32 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/utils/EnumParseOverflowContainer.h> -#include <aws/core/utils/logging/LogMacros.h> - -using namespace Aws::Utils; -using namespace Aws::Utils::Threading; - -static const char LOG_TAG[] = "EnumParseOverflowContainer"; - -const Aws::String& EnumParseOverflowContainer::RetrieveOverflow(int hashCode) const -{ - ReaderLockGuard guard(m_overflowLock); - auto foundIter = m_overflowMap.find(hashCode); - if (foundIter != m_overflowMap.end()) - { - AWS_LOGSTREAM_DEBUG(LOG_TAG, "Found value " << foundIter->second << " for hash " << hashCode << " from enum overflow container."); - return foundIter->second; - } - - AWS_LOGSTREAM_ERROR(LOG_TAG, "Could not find a previously stored overflow value for hash " << hashCode << ". This will likely break some requests."); - return m_emptyString; -} - -void EnumParseOverflowContainer::StoreOverflow(int hashCode, const Aws::String& value) -{ - WriterLockGuard guard(m_overflowLock); - AWS_LOGSTREAM_WARN(LOG_TAG, "Encountered enum member " << value << " which is not modeled in your clients. You should update your clients when you get a chance."); - m_overflowMap[hashCode] = value; -} + +#include <aws/core/utils/EnumParseOverflowContainer.h> +#include <aws/core/utils/logging/LogMacros.h> + +using namespace Aws::Utils; +using namespace Aws::Utils::Threading; + +static const char LOG_TAG[] = "EnumParseOverflowContainer"; + +const Aws::String& EnumParseOverflowContainer::RetrieveOverflow(int hashCode) const +{ + ReaderLockGuard guard(m_overflowLock); + auto foundIter = m_overflowMap.find(hashCode); + if (foundIter != m_overflowMap.end()) + { + AWS_LOGSTREAM_DEBUG(LOG_TAG, "Found value " << foundIter->second << " for hash " << hashCode << " from enum overflow container."); + return foundIter->second; + } + + AWS_LOGSTREAM_ERROR(LOG_TAG, "Could not find a previously stored overflow value for hash " << hashCode << ". This will likely break some requests."); + return m_emptyString; +} + +void EnumParseOverflowContainer::StoreOverflow(int hashCode, const Aws::String& value) +{ + WriterLockGuard guard(m_overflowLock); + AWS_LOGSTREAM_WARN(LOG_TAG, "Encountered enum member " << value << " which is not modeled in your clients. You should update your clients when you get a chance."); + m_overflowMap[hashCode] = value; +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/FileSystemUtils.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/FileSystemUtils.cpp index c47f750960..18e9f8dd28 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/FileSystemUtils.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/FileSystemUtils.cpp @@ -1,51 +1,51 @@ /** * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. - */ - -#include <aws/core/utils/FileSystemUtils.h> - -using namespace Aws::Utils; - -Aws::String PathUtils::GetFileNameFromPathWithoutExt(const Aws::String& path) -{ - Aws::String fileName = Aws::Utils::PathUtils::GetFileNameFromPathWithExt(path); - size_t endPos = fileName.find_last_of('.'); - if (endPos == std::string::npos) - { - return fileName; - } - if (endPos == 0) // fileName is "." - { + */ + +#include <aws/core/utils/FileSystemUtils.h> + +using namespace Aws::Utils; + +Aws::String PathUtils::GetFileNameFromPathWithoutExt(const Aws::String& path) +{ + Aws::String fileName = Aws::Utils::PathUtils::GetFileNameFromPathWithExt(path); + size_t endPos = fileName.find_last_of('.'); + if (endPos == std::string::npos) + { + return fileName; + } + if (endPos == 0) // fileName is "." + { return {}; - } - - return fileName.substr(0, endPos); -} - -Aws::String PathUtils::GetFileNameFromPathWithExt(const Aws::String& path) -{ - if (path.size() == 0) - { - return path; - } - - size_t startPos = path.find_last_of(Aws::FileSystem::PATH_DELIM); - if (startPos == path.size() - 1) - { + } + + return fileName.substr(0, endPos); +} + +Aws::String PathUtils::GetFileNameFromPathWithExt(const Aws::String& path) +{ + if (path.size() == 0) + { + return path; + } + + size_t startPos = path.find_last_of(Aws::FileSystem::PATH_DELIM); + if (startPos == path.size() - 1) + { return {}; - } - - if (startPos == std::string::npos) - { - startPos = 0; - } - else - { - startPos += 1; - } - - size_t endPos = path.size() - 1; - - return path.substr(startPos, endPos - startPos + 1); + } + + if (startPos == std::string::npos) + { + startPos = 0; + } + else + { + startPos += 1; + } + + size_t endPos = path.size() - 1; + + return path.substr(startPos, endPos - startPos + 1); } diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/GetTheLights.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/GetTheLights.cpp index 6e78b546ab..66f69a3b4b 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/GetTheLights.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/GetTheLights.cpp @@ -2,35 +2,35 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ -#include <aws/core/utils/GetTheLights.h> -#include <cassert> - -namespace Aws -{ - namespace Utils - { - GetTheLights::GetTheLights() : m_value(0) - { - } - - void GetTheLights::EnterRoom(std::function<void()> &&callable) - { - int cpy = ++m_value; - assert(cpy > 0); - if(cpy == 1) - { - callable(); - } - } - - void GetTheLights::LeaveRoom(std::function<void()> &&callable) - { - int cpy = --m_value; - assert(cpy >= 0); - if(cpy == 0) - { - callable(); - } - } - } -}
\ No newline at end of file +#include <aws/core/utils/GetTheLights.h> +#include <cassert> + +namespace Aws +{ + namespace Utils + { + GetTheLights::GetTheLights() : m_value(0) + { + } + + void GetTheLights::EnterRoom(std::function<void()> &&callable) + { + int cpy = ++m_value; + assert(cpy > 0); + if(cpy == 1) + { + callable(); + } + } + + void GetTheLights::LeaveRoom(std::function<void()> &&callable) + { + int cpy = --m_value; + assert(cpy >= 0); + if(cpy == 0) + { + callable(); + } + } + } +}
\ No newline at end of file diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/HashingUtils.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/HashingUtils.cpp index 147bddf33e..b656c72432 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/HashingUtils.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/HashingUtils.cpp @@ -2,235 +2,235 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/utils/logging/LogMacros.h> -#include <aws/core/utils/HashingUtils.h> + +#include <aws/core/utils/logging/LogMacros.h> +#include <aws/core/utils/HashingUtils.h> #include <aws/core/utils/StringUtils.h> -#include <aws/core/utils/base64/Base64.h> -#include <aws/core/utils/crypto/Sha256.h> -#include <aws/core/utils/crypto/Sha256HMAC.h> -#include <aws/core/utils/crypto/MD5.h> -#include <aws/core/utils/Outcome.h> -#include <aws/core/utils/memory/stl/AWSStringStream.h> -#include <aws/core/utils/memory/stl/AWSList.h> - -#include <iomanip> - -using namespace Aws::Utils; -using namespace Aws::Utils::Base64; -using namespace Aws::Utils::Crypto; - -// internal buffers are fixed-size arrays, so this is harmless memory-management wise -static Aws::Utils::Base64::Base64 s_base64; - -// Aws Glacier Tree Hash calculates hash value for each 1MB data -const static size_t TREE_HASH_ONE_MB = 1024 * 1024; - -Aws::String HashingUtils::Base64Encode(const ByteBuffer& message) -{ - return s_base64.Encode(message); -} - -ByteBuffer HashingUtils::Base64Decode(const Aws::String& encodedMessage) -{ - return s_base64.Decode(encodedMessage); -} - -ByteBuffer HashingUtils::CalculateSHA256HMAC(const ByteBuffer& toSign, const ByteBuffer& secret) -{ - Sha256HMAC hash; - return hash.Calculate(toSign, secret).GetResult(); -} - -ByteBuffer HashingUtils::CalculateSHA256(const Aws::String& str) -{ - Sha256 hash; - return hash.Calculate(str).GetResult(); -} - -ByteBuffer HashingUtils::CalculateSHA256(Aws::IOStream& stream) -{ - Sha256 hash; - return hash.Calculate(stream).GetResult(); -} - -/** - * This function is only used by HashingUtils::CalculateSHA256TreeHash() in this cpp file - * It's a helper function be used to compute the TreeHash defined at: - * http://docs.aws.amazon.com/amazonglacier/latest/dev/checksum-calculations.html - */ -static ByteBuffer TreeHashFinalCompute(Aws::List<ByteBuffer>& input) -{ - Sha256 hash; - assert(input.size() != 0); - - // O(n) time complexity of merging (n + n/2 + n/4 + n/8 +...+ 1) - while (input.size() > 1) - { - auto iter = input.begin(); - // if only one element left, just left it there - while (std::next(iter) != input.end()) - { - // if >= two elements - Aws::String str(reinterpret_cast<char*>(iter->GetUnderlyingData()), iter->GetLength()); - // list erase returns iterator of next element next to the erased element or end() if erased the last one - // list insert inserts element before pos, here we erase two elements, and insert a new element - iter = input.erase(iter); - str.append(reinterpret_cast<char*>(iter->GetUnderlyingData()), iter->GetLength()); - iter = input.erase(iter); - input.insert(iter, hash.Calculate(str).GetResult()); - - if (iter == input.end()) break; - } // while process to the last element - } // while the list has only one element left - - return *(input.begin()); -} - -ByteBuffer HashingUtils::CalculateSHA256TreeHash(const Aws::String& str) -{ - Sha256 hash; - if (str.size() == 0) - { - return hash.Calculate(str).GetResult(); - } - - Aws::List<ByteBuffer> input; - size_t pos = 0; - while (pos < str.size()) - { - input.push_back(hash.Calculate(Aws::String(str, pos, TREE_HASH_ONE_MB)).GetResult()); - pos += TREE_HASH_ONE_MB; - } - - return TreeHashFinalCompute(input); -} - -ByteBuffer HashingUtils::CalculateSHA256TreeHash(Aws::IOStream& stream) -{ - Sha256 hash; - Aws::List<ByteBuffer> input; - auto currentPos = stream.tellg(); - if (currentPos == std::ios::pos_type(-1)) - { - currentPos = 0; - stream.clear(); - } - stream.seekg(0, stream.beg); - Array<char> streamBuffer(TREE_HASH_ONE_MB); - while (stream.good()) - { - stream.read(streamBuffer.GetUnderlyingData(), TREE_HASH_ONE_MB); - auto bytesRead = stream.gcount(); - if (bytesRead > 0) - { - input.push_back(hash.Calculate(Aws::String(reinterpret_cast<char*>(streamBuffer.GetUnderlyingData()), static_cast<size_t>(bytesRead))).GetResult()); - } - } - stream.clear(); - stream.seekg(currentPos, stream.beg); - - if (input.size() == 0) - { - return hash.Calculate("").GetResult(); - } - return TreeHashFinalCompute(input); -} - -Aws::String HashingUtils::HexEncode(const ByteBuffer& message) -{ +#include <aws/core/utils/base64/Base64.h> +#include <aws/core/utils/crypto/Sha256.h> +#include <aws/core/utils/crypto/Sha256HMAC.h> +#include <aws/core/utils/crypto/MD5.h> +#include <aws/core/utils/Outcome.h> +#include <aws/core/utils/memory/stl/AWSStringStream.h> +#include <aws/core/utils/memory/stl/AWSList.h> + +#include <iomanip> + +using namespace Aws::Utils; +using namespace Aws::Utils::Base64; +using namespace Aws::Utils::Crypto; + +// internal buffers are fixed-size arrays, so this is harmless memory-management wise +static Aws::Utils::Base64::Base64 s_base64; + +// Aws Glacier Tree Hash calculates hash value for each 1MB data +const static size_t TREE_HASH_ONE_MB = 1024 * 1024; + +Aws::String HashingUtils::Base64Encode(const ByteBuffer& message) +{ + return s_base64.Encode(message); +} + +ByteBuffer HashingUtils::Base64Decode(const Aws::String& encodedMessage) +{ + return s_base64.Decode(encodedMessage); +} + +ByteBuffer HashingUtils::CalculateSHA256HMAC(const ByteBuffer& toSign, const ByteBuffer& secret) +{ + Sha256HMAC hash; + return hash.Calculate(toSign, secret).GetResult(); +} + +ByteBuffer HashingUtils::CalculateSHA256(const Aws::String& str) +{ + Sha256 hash; + return hash.Calculate(str).GetResult(); +} + +ByteBuffer HashingUtils::CalculateSHA256(Aws::IOStream& stream) +{ + Sha256 hash; + return hash.Calculate(stream).GetResult(); +} + +/** + * This function is only used by HashingUtils::CalculateSHA256TreeHash() in this cpp file + * It's a helper function be used to compute the TreeHash defined at: + * http://docs.aws.amazon.com/amazonglacier/latest/dev/checksum-calculations.html + */ +static ByteBuffer TreeHashFinalCompute(Aws::List<ByteBuffer>& input) +{ + Sha256 hash; + assert(input.size() != 0); + + // O(n) time complexity of merging (n + n/2 + n/4 + n/8 +...+ 1) + while (input.size() > 1) + { + auto iter = input.begin(); + // if only one element left, just left it there + while (std::next(iter) != input.end()) + { + // if >= two elements + Aws::String str(reinterpret_cast<char*>(iter->GetUnderlyingData()), iter->GetLength()); + // list erase returns iterator of next element next to the erased element or end() if erased the last one + // list insert inserts element before pos, here we erase two elements, and insert a new element + iter = input.erase(iter); + str.append(reinterpret_cast<char*>(iter->GetUnderlyingData()), iter->GetLength()); + iter = input.erase(iter); + input.insert(iter, hash.Calculate(str).GetResult()); + + if (iter == input.end()) break; + } // while process to the last element + } // while the list has only one element left + + return *(input.begin()); +} + +ByteBuffer HashingUtils::CalculateSHA256TreeHash(const Aws::String& str) +{ + Sha256 hash; + if (str.size() == 0) + { + return hash.Calculate(str).GetResult(); + } + + Aws::List<ByteBuffer> input; + size_t pos = 0; + while (pos < str.size()) + { + input.push_back(hash.Calculate(Aws::String(str, pos, TREE_HASH_ONE_MB)).GetResult()); + pos += TREE_HASH_ONE_MB; + } + + return TreeHashFinalCompute(input); +} + +ByteBuffer HashingUtils::CalculateSHA256TreeHash(Aws::IOStream& stream) +{ + Sha256 hash; + Aws::List<ByteBuffer> input; + auto currentPos = stream.tellg(); + if (currentPos == std::ios::pos_type(-1)) + { + currentPos = 0; + stream.clear(); + } + stream.seekg(0, stream.beg); + Array<char> streamBuffer(TREE_HASH_ONE_MB); + while (stream.good()) + { + stream.read(streamBuffer.GetUnderlyingData(), TREE_HASH_ONE_MB); + auto bytesRead = stream.gcount(); + if (bytesRead > 0) + { + input.push_back(hash.Calculate(Aws::String(reinterpret_cast<char*>(streamBuffer.GetUnderlyingData()), static_cast<size_t>(bytesRead))).GetResult()); + } + } + stream.clear(); + stream.seekg(currentPos, stream.beg); + + if (input.size() == 0) + { + return hash.Calculate("").GetResult(); + } + return TreeHashFinalCompute(input); +} + +Aws::String HashingUtils::HexEncode(const ByteBuffer& message) +{ Aws::String encoded; encoded.reserve(2 * message.GetLength()); - - for (unsigned i = 0; i < message.GetLength(); ++i) - { + + for (unsigned i = 0; i < message.GetLength(); ++i) + { encoded.push_back("0123456789abcdef"[message[i] >> 4]); encoded.push_back("0123456789abcdef"[message[i] & 0x0f]); - } - + } + return encoded; -} - -ByteBuffer HashingUtils::HexDecode(const Aws::String& str) -{ - //number of characters should be even - assert(str.length() % 2 == 0); - assert(str.length() >= 2); - - if(str.length() < 2 || str.length() % 2 != 0) - { - return ByteBuffer(); - } - - size_t strLength = str.length(); - size_t readIndex = 0; - - if(str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) - { - strLength -= 2; - readIndex = 2; - } - - ByteBuffer hexBuffer(strLength / 2); - size_t bufferIndex = 0; - - for (size_t i = readIndex; i < str.length(); i += 2) - { +} + +ByteBuffer HashingUtils::HexDecode(const Aws::String& str) +{ + //number of characters should be even + assert(str.length() % 2 == 0); + assert(str.length() >= 2); + + if(str.length() < 2 || str.length() % 2 != 0) + { + return ByteBuffer(); + } + + size_t strLength = str.length(); + size_t readIndex = 0; + + if(str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) + { + strLength -= 2; + readIndex = 2; + } + + ByteBuffer hexBuffer(strLength / 2); + size_t bufferIndex = 0; + + for (size_t i = readIndex; i < str.length(); i += 2) + { if(!StringUtils::IsAlnum(str[i]) || !StringUtils::IsAlnum(str[i + 1])) - { - //contains non-hex characters - assert(0); - } - - char firstChar = str[i]; - uint8_t distance = firstChar - '0'; - - if(isalpha(firstChar)) - { - firstChar = static_cast<char>(toupper(firstChar)); - distance = firstChar - 'A' + 10; - } - - unsigned char val = distance * 16; - - char secondChar = str[i + 1]; - distance = secondChar - '0'; - - if(isalpha(secondChar)) - { - secondChar = static_cast<char>(toupper(secondChar)); - distance = secondChar - 'A' + 10; - } - - val += distance; - hexBuffer[bufferIndex++] = val; - } - - return hexBuffer; -} - -ByteBuffer HashingUtils::CalculateMD5(const Aws::String& str) -{ - MD5 hash; - return hash.Calculate(str).GetResult(); -} - -ByteBuffer HashingUtils::CalculateMD5(Aws::IOStream& stream) -{ - MD5 hash; - return hash.Calculate(stream).GetResult(); -} - -int HashingUtils::HashString(const char* strToHash) -{ - if (!strToHash) - return 0; - + { + //contains non-hex characters + assert(0); + } + + char firstChar = str[i]; + uint8_t distance = firstChar - '0'; + + if(isalpha(firstChar)) + { + firstChar = static_cast<char>(toupper(firstChar)); + distance = firstChar - 'A' + 10; + } + + unsigned char val = distance * 16; + + char secondChar = str[i + 1]; + distance = secondChar - '0'; + + if(isalpha(secondChar)) + { + secondChar = static_cast<char>(toupper(secondChar)); + distance = secondChar - 'A' + 10; + } + + val += distance; + hexBuffer[bufferIndex++] = val; + } + + return hexBuffer; +} + +ByteBuffer HashingUtils::CalculateMD5(const Aws::String& str) +{ + MD5 hash; + return hash.Calculate(str).GetResult(); +} + +ByteBuffer HashingUtils::CalculateMD5(Aws::IOStream& stream) +{ + MD5 hash; + return hash.Calculate(stream).GetResult(); +} + +int HashingUtils::HashString(const char* strToHash) +{ + if (!strToHash) + return 0; + unsigned hash = 0; - while (char charValue = *strToHash++) - { - hash = charValue + 31 * hash; - } - - return hash; -} + while (char charValue = *strToHash++) + { + hash = charValue + 31 * hash; + } + + return hash; +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/StringUtils.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/StringUtils.cpp index e1deb3f046..f1b152b470 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/StringUtils.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/StringUtils.cpp @@ -2,108 +2,108 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - - -#include <aws/core/utils/StringUtils.h> -#include <aws/core/utils/memory/stl/AWSStringStream.h> -#include <algorithm> -#include <iomanip> -#include <cstdlib> -#include <cstdio> -#include <cstring> -#include <functional> - -#ifdef _WIN32 -#include <Windows.h> -#endif - -using namespace Aws::Utils; - -void StringUtils::Replace(Aws::String& s, const char* search, const char* replace) -{ - if(!search || !replace) - { - return; - } - - size_t replaceLength = strlen(replace); - size_t searchLength = strlen(search); - - for (std::size_t pos = 0;; pos += replaceLength) - { - pos = s.find(search, pos); - if (pos == Aws::String::npos) - break; - - s.erase(pos, searchLength); - s.insert(pos, replace); - } -} - - -Aws::String StringUtils::ToLower(const char* source) -{ - Aws::String copy; - size_t sourceLength = strlen(source); - copy.resize(sourceLength); - //appease the latest whims of the VC++ 2017 gods - std::transform(source, source + sourceLength, copy.begin(), [](unsigned char c) { return (char)::tolower(c); }); - - return copy; -} - - -Aws::String StringUtils::ToUpper(const char* source) -{ - Aws::String copy; - size_t sourceLength = strlen(source); - copy.resize(sourceLength); - //appease the latest whims of the VC++ 2017 gods - std::transform(source, source + sourceLength, copy.begin(), [](unsigned char c) { return (char)::toupper(c); }); - - return copy; -} - - -bool StringUtils::CaselessCompare(const char* value1, const char* value2) -{ - Aws::String value1Lower = ToLower(value1); - Aws::String value2Lower = ToLower(value2); - - return value1Lower == value2Lower; -} - -Aws::Vector<Aws::String> StringUtils::Split(const Aws::String& toSplit, char splitOn) -{ + + +#include <aws/core/utils/StringUtils.h> +#include <aws/core/utils/memory/stl/AWSStringStream.h> +#include <algorithm> +#include <iomanip> +#include <cstdlib> +#include <cstdio> +#include <cstring> +#include <functional> + +#ifdef _WIN32 +#include <Windows.h> +#endif + +using namespace Aws::Utils; + +void StringUtils::Replace(Aws::String& s, const char* search, const char* replace) +{ + if(!search || !replace) + { + return; + } + + size_t replaceLength = strlen(replace); + size_t searchLength = strlen(search); + + for (std::size_t pos = 0;; pos += replaceLength) + { + pos = s.find(search, pos); + if (pos == Aws::String::npos) + break; + + s.erase(pos, searchLength); + s.insert(pos, replace); + } +} + + +Aws::String StringUtils::ToLower(const char* source) +{ + Aws::String copy; + size_t sourceLength = strlen(source); + copy.resize(sourceLength); + //appease the latest whims of the VC++ 2017 gods + std::transform(source, source + sourceLength, copy.begin(), [](unsigned char c) { return (char)::tolower(c); }); + + return copy; +} + + +Aws::String StringUtils::ToUpper(const char* source) +{ + Aws::String copy; + size_t sourceLength = strlen(source); + copy.resize(sourceLength); + //appease the latest whims of the VC++ 2017 gods + std::transform(source, source + sourceLength, copy.begin(), [](unsigned char c) { return (char)::toupper(c); }); + + return copy; +} + + +bool StringUtils::CaselessCompare(const char* value1, const char* value2) +{ + Aws::String value1Lower = ToLower(value1); + Aws::String value2Lower = ToLower(value2); + + return value1Lower == value2Lower; +} + +Aws::Vector<Aws::String> StringUtils::Split(const Aws::String& toSplit, char splitOn) +{ return Split(toSplit, splitOn, SIZE_MAX, SplitOptions::NOT_SET); -} - +} + Aws::Vector<Aws::String> StringUtils::Split(const Aws::String& toSplit, char splitOn, SplitOptions option) { return Split(toSplit, splitOn, SIZE_MAX, option); } -Aws::Vector<Aws::String> StringUtils::Split(const Aws::String& toSplit, char splitOn, size_t numOfTargetParts) -{ +Aws::Vector<Aws::String> StringUtils::Split(const Aws::String& toSplit, char splitOn, size_t numOfTargetParts) +{ return Split(toSplit, splitOn, numOfTargetParts, SplitOptions::NOT_SET); } Aws::Vector<Aws::String> StringUtils::Split(const Aws::String& toSplit, char splitOn, size_t numOfTargetParts, SplitOptions option) { - Aws::Vector<Aws::String> returnValues; - Aws::StringStream input(toSplit); - Aws::String item; - - while(returnValues.size() < numOfTargetParts - 1 && std::getline(input, item, splitOn)) - { + Aws::Vector<Aws::String> returnValues; + Aws::StringStream input(toSplit); + Aws::String item; + + while(returnValues.size() < numOfTargetParts - 1 && std::getline(input, item, splitOn)) + { if (!item.empty() || option == SplitOptions::INCLUDE_EMPTY_ENTRIES) - { - returnValues.emplace_back(std::move(item)); - } - } - + { + returnValues.emplace_back(std::move(item)); + } + } + if (std::getline(input, item, static_cast<char>(EOF))) - { + { if (option != SplitOptions::INCLUDE_EMPTY_ENTRIES) { // Trim all leading delimiters. @@ -118,103 +118,103 @@ Aws::Vector<Aws::String> StringUtils::Split(const Aws::String& toSplit, char spl returnValues.emplace_back(std::move(item)); } - } + } // To handle the case when there are trailing delimiters. else if (!toSplit.empty() && toSplit.back() == splitOn && option == SplitOptions::INCLUDE_EMPTY_ENTRIES) { returnValues.emplace_back(); } - return returnValues; -} - -Aws::Vector<Aws::String> StringUtils::SplitOnLine(const Aws::String& toSplit) -{ - Aws::StringStream input(toSplit); - Aws::Vector<Aws::String> returnValues; - Aws::String item; - - while (std::getline(input, item)) - { - if (item.size() > 0) - { - returnValues.push_back(item); - } - } - - return returnValues; -} - - -Aws::String StringUtils::URLEncode(const char* unsafe) -{ - Aws::StringStream escaped; - escaped.fill('0'); - escaped << std::hex << std::uppercase; - - size_t unsafeLength = strlen(unsafe); - for (auto i = unsafe, n = unsafe + unsafeLength; i != n; ++i) - { + return returnValues; +} + +Aws::Vector<Aws::String> StringUtils::SplitOnLine(const Aws::String& toSplit) +{ + Aws::StringStream input(toSplit); + Aws::Vector<Aws::String> returnValues; + Aws::String item; + + while (std::getline(input, item)) + { + if (item.size() > 0) + { + returnValues.push_back(item); + } + } + + return returnValues; +} + + +Aws::String StringUtils::URLEncode(const char* unsafe) +{ + Aws::StringStream escaped; + escaped.fill('0'); + escaped << std::hex << std::uppercase; + + size_t unsafeLength = strlen(unsafe); + for (auto i = unsafe, n = unsafe + unsafeLength; i != n; ++i) + { char c = *i; if (IsAlnum(c) || c == '-' || c == '_' || c == '.' || c == '~') - { - escaped << (char)c; - } - else - { - //this unsigned char cast allows us to handle unicode characters. - escaped << '%' << std::setw(2) << int((unsigned char)c) << std::setw(0); - } - } - - return escaped.str(); -} - -Aws::String StringUtils::UTF8Escape(const char* unicodeString, const char* delimiter) -{ - Aws::StringStream escaped; - escaped.fill('0'); - escaped << std::hex << std::uppercase; - - size_t unsafeLength = strlen(unicodeString); - for (auto i = unicodeString, n = unicodeString + unsafeLength; i != n; ++i) - { - int c = *i; - if (c >= ' ' && c < 127 ) - { - escaped << (char)c; - } - else - { - //this unsigned char cast allows us to handle unicode characters. - escaped << delimiter << std::setw(2) << int((unsigned char)c) << std::setw(0); - } - } - - return escaped.str(); -} - -Aws::String StringUtils::URLEncode(double unsafe) -{ - char buffer[32]; -#if defined(_MSC_VER) && _MSC_VER < 1900 - _snprintf_s(buffer, sizeof(buffer), _TRUNCATE, "%g", unsafe); -#else - snprintf(buffer, sizeof(buffer), "%g", unsafe); -#endif - - return StringUtils::URLEncode(buffer); -} - - -Aws::String StringUtils::URLDecode(const char* safe) -{ + { + escaped << (char)c; + } + else + { + //this unsigned char cast allows us to handle unicode characters. + escaped << '%' << std::setw(2) << int((unsigned char)c) << std::setw(0); + } + } + + return escaped.str(); +} + +Aws::String StringUtils::UTF8Escape(const char* unicodeString, const char* delimiter) +{ + Aws::StringStream escaped; + escaped.fill('0'); + escaped << std::hex << std::uppercase; + + size_t unsafeLength = strlen(unicodeString); + for (auto i = unicodeString, n = unicodeString + unsafeLength; i != n; ++i) + { + int c = *i; + if (c >= ' ' && c < 127 ) + { + escaped << (char)c; + } + else + { + //this unsigned char cast allows us to handle unicode characters. + escaped << delimiter << std::setw(2) << int((unsigned char)c) << std::setw(0); + } + } + + return escaped.str(); +} + +Aws::String StringUtils::URLEncode(double unsafe) +{ + char buffer[32]; +#if defined(_MSC_VER) && _MSC_VER < 1900 + _snprintf_s(buffer, sizeof(buffer), _TRUNCATE, "%g", unsafe); +#else + snprintf(buffer, sizeof(buffer), "%g", unsafe); +#endif + + return StringUtils::URLEncode(buffer); +} + + +Aws::String StringUtils::URLDecode(const char* safe) +{ Aws::String unescaped; - + for (; *safe; safe++) - { + { switch(*safe) - { + { case '%': { int hex = 0; @@ -276,12 +276,12 @@ Aws::String StringUtils::URLDecode(const char* safe) default: unescaped.push_back(*safe); break; - } - } - + } + } + return unescaped; -} - +} + static bool IsSpace(int ch) { if (ch < -1 || ch > 255) @@ -292,130 +292,130 @@ static bool IsSpace(int ch) return ::isspace(ch) != 0; } -Aws::String StringUtils::LTrim(const char* source) -{ - Aws::String copy(source); +Aws::String StringUtils::LTrim(const char* source) +{ + Aws::String copy(source); copy.erase(copy.begin(), std::find_if(copy.begin(), copy.end(), [](int ch) { return !IsSpace(ch); })); - return copy; -} - -// trim from end -Aws::String StringUtils::RTrim(const char* source) -{ - Aws::String copy(source); + return copy; +} + +// trim from end +Aws::String StringUtils::RTrim(const char* source) +{ + Aws::String copy(source); copy.erase(std::find_if(copy.rbegin(), copy.rend(), [](int ch) { return !IsSpace(ch); }).base(), copy.end()); - return copy; -} - -// trim from both ends -Aws::String StringUtils::Trim(const char* source) -{ - return LTrim(RTrim(source).c_str()); -} - -long long StringUtils::ConvertToInt64(const char* source) -{ - if(!source) - { - return 0; - } - -#ifdef __ANDROID__ - return atoll(source); -#else - return std::atoll(source); -#endif // __ANDROID__ -} - - -long StringUtils::ConvertToInt32(const char* source) -{ - if (!source) - { - return 0; - } - - return std::atol(source); -} - - -bool StringUtils::ConvertToBool(const char* source) -{ - if(!source) - { - return false; - } - - Aws::String strValue = ToLower(source); - if(strValue == "true" || strValue == "1") - { - return true; - } - - return false; -} - - -double StringUtils::ConvertToDouble(const char* source) -{ - if(!source) - { - return 0.0; - } - - return std::strtod(source, NULL); -} - -#ifdef _WIN32 - -Aws::WString StringUtils::ToWString(const char* source) -{ - const auto len = static_cast<int>(std::strlen(source)); - Aws::WString outString; - outString.resize(len); // there is no way UTF-16 would require _more_ code-points than UTF-8 for the _same_ string - const auto result = MultiByteToWideChar(CP_UTF8 /*CodePage*/, - 0 /*dwFlags*/, - source /*lpMultiByteStr*/, - len /*cbMultiByte*/, - &outString[0] /*lpWideCharStr*/, - static_cast<int>(outString.length())/*cchWideChar*/); - if (!result) - { - return L""; - } - outString.resize(result); - return outString; -} - -Aws::String StringUtils::FromWString(const wchar_t* source) -{ - const auto len = static_cast<int>(std::wcslen(source)); - Aws::String output; - if (int requiredSizeInBytes = WideCharToMultiByte(CP_UTF8 /*CodePage*/, - 0 /*dwFlags*/, - source /*lpWideCharStr*/, - len /*cchWideChar*/, - nullptr /*lpMultiByteStr*/, - 0 /*cbMultiByte*/, - nullptr /*lpDefaultChar*/, - nullptr /*lpUsedDefaultChar*/)) - { - output.resize(requiredSizeInBytes); - } - const auto result = WideCharToMultiByte(CP_UTF8 /*CodePage*/, - 0 /*dwFlags*/, - source /*lpWideCharStr*/, - len /*cchWideChar*/, - &output[0] /*lpMultiByteStr*/, - static_cast<int>(output.length()) /*cbMultiByte*/, - nullptr /*lpDefaultChar*/, - nullptr /*lpUsedDefaultChar*/); - if (!result) - { - return ""; - } - output.resize(result); - return output; -} - -#endif + return copy; +} + +// trim from both ends +Aws::String StringUtils::Trim(const char* source) +{ + return LTrim(RTrim(source).c_str()); +} + +long long StringUtils::ConvertToInt64(const char* source) +{ + if(!source) + { + return 0; + } + +#ifdef __ANDROID__ + return atoll(source); +#else + return std::atoll(source); +#endif // __ANDROID__ +} + + +long StringUtils::ConvertToInt32(const char* source) +{ + if (!source) + { + return 0; + } + + return std::atol(source); +} + + +bool StringUtils::ConvertToBool(const char* source) +{ + if(!source) + { + return false; + } + + Aws::String strValue = ToLower(source); + if(strValue == "true" || strValue == "1") + { + return true; + } + + return false; +} + + +double StringUtils::ConvertToDouble(const char* source) +{ + if(!source) + { + return 0.0; + } + + return std::strtod(source, NULL); +} + +#ifdef _WIN32 + +Aws::WString StringUtils::ToWString(const char* source) +{ + const auto len = static_cast<int>(std::strlen(source)); + Aws::WString outString; + outString.resize(len); // there is no way UTF-16 would require _more_ code-points than UTF-8 for the _same_ string + const auto result = MultiByteToWideChar(CP_UTF8 /*CodePage*/, + 0 /*dwFlags*/, + source /*lpMultiByteStr*/, + len /*cbMultiByte*/, + &outString[0] /*lpWideCharStr*/, + static_cast<int>(outString.length())/*cchWideChar*/); + if (!result) + { + return L""; + } + outString.resize(result); + return outString; +} + +Aws::String StringUtils::FromWString(const wchar_t* source) +{ + const auto len = static_cast<int>(std::wcslen(source)); + Aws::String output; + if (int requiredSizeInBytes = WideCharToMultiByte(CP_UTF8 /*CodePage*/, + 0 /*dwFlags*/, + source /*lpWideCharStr*/, + len /*cchWideChar*/, + nullptr /*lpMultiByteStr*/, + 0 /*cbMultiByte*/, + nullptr /*lpDefaultChar*/, + nullptr /*lpUsedDefaultChar*/)) + { + output.resize(requiredSizeInBytes); + } + const auto result = WideCharToMultiByte(CP_UTF8 /*CodePage*/, + 0 /*dwFlags*/, + source /*lpWideCharStr*/, + len /*cchWideChar*/, + &output[0] /*lpMultiByteStr*/, + static_cast<int>(output.length()) /*cbMultiByte*/, + nullptr /*lpDefaultChar*/, + nullptr /*lpUsedDefaultChar*/); + if (!result) + { + return ""; + } + output.resize(result); + return output; +} + +#endif diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/TempFile.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/TempFile.cpp index 7bc07266c9..c1c569e29a 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/TempFile.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/TempFile.cpp @@ -2,53 +2,53 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/utils/FileSystemUtils.h> - -#include <aws/core/platform/FileSystem.h> - -namespace Aws -{ - namespace Utils - { - static Aws::String ComputeTempFileName(const char* prefix, const char* suffix) - { - Aws::String prefixStr; - - if (prefix) - { - prefixStr = prefix; - } - - Aws::String suffixStr; - - if (suffix) - { - suffixStr = suffix; - } - - return prefixStr + Aws::FileSystem::CreateTempFilePath() + suffixStr; - } - - TempFile::TempFile(const char* prefix, const char* suffix, std::ios_base::openmode openFlags) : - FStreamWithFileName(ComputeTempFileName(prefix, suffix).c_str(), openFlags) - { - } - - TempFile::TempFile(const char* prefix, std::ios_base::openmode openFlags) : - FStreamWithFileName(ComputeTempFileName(prefix, nullptr).c_str(), openFlags) - { - } - - TempFile::TempFile(std::ios_base::openmode openFlags) : - FStreamWithFileName(ComputeTempFileName(nullptr, nullptr).c_str(), openFlags) - { - } - - - TempFile::~TempFile() - { - Aws::FileSystem::RemoveFileIfExists(m_fileName.c_str()); - } - } -}
\ No newline at end of file + +#include <aws/core/utils/FileSystemUtils.h> + +#include <aws/core/platform/FileSystem.h> + +namespace Aws +{ + namespace Utils + { + static Aws::String ComputeTempFileName(const char* prefix, const char* suffix) + { + Aws::String prefixStr; + + if (prefix) + { + prefixStr = prefix; + } + + Aws::String suffixStr; + + if (suffix) + { + suffixStr = suffix; + } + + return prefixStr + Aws::FileSystem::CreateTempFilePath() + suffixStr; + } + + TempFile::TempFile(const char* prefix, const char* suffix, std::ios_base::openmode openFlags) : + FStreamWithFileName(ComputeTempFileName(prefix, suffix).c_str(), openFlags) + { + } + + TempFile::TempFile(const char* prefix, std::ios_base::openmode openFlags) : + FStreamWithFileName(ComputeTempFileName(prefix, nullptr).c_str(), openFlags) + { + } + + TempFile::TempFile(std::ios_base::openmode openFlags) : + FStreamWithFileName(ComputeTempFileName(nullptr, nullptr).c_str(), openFlags) + { + } + + + TempFile::~TempFile() + { + Aws::FileSystem::RemoveFileIfExists(m_fileName.c_str()); + } + } +}
\ No newline at end of file diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/UUID.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/UUID.cpp index 862f3eacdd..d170082178 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/UUID.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/UUID.cpp @@ -2,89 +2,89 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/utils/UUID.h> -#include <aws/core/utils/HashingUtils.h> -#include <aws/core/utils/StringUtils.h> -#include <aws/core/utils/crypto/Factories.h> -#include <aws/core/utils/crypto/SecureRandom.h> -#include <iomanip> - -namespace Aws -{ - namespace Utils - { + +#include <aws/core/utils/UUID.h> +#include <aws/core/utils/HashingUtils.h> +#include <aws/core/utils/StringUtils.h> +#include <aws/core/utils/crypto/Factories.h> +#include <aws/core/utils/crypto/SecureRandom.h> +#include <iomanip> + +namespace Aws +{ + namespace Utils + { static const size_t UUID_STR_SIZE = 0x24u; // 36 characters - static const size_t VERSION_LOCATION = 0x06u; - static const size_t VARIANT_LOCATION = 0x08u; - static const unsigned char VERSION = 0x40u; - static const unsigned char VERSION_MASK = 0x0Fu; - static const unsigned char VARIANT = 0x80u; - static const unsigned char VARIANT_MASK = 0x3Fu; - + static const size_t VERSION_LOCATION = 0x06u; + static const size_t VARIANT_LOCATION = 0x08u; + static const unsigned char VERSION = 0x40u; + static const unsigned char VERSION_MASK = 0x0Fu; + static const unsigned char VARIANT = 0x80u; + static const unsigned char VARIANT_MASK = 0x3Fu; + static void hexify(Aws::String& ss, const unsigned char* toWrite, size_t min, size_t max) - { - for (size_t i = min; i < max; ++i) - { + { + for (size_t i = min; i < max; ++i) + { ss.push_back("0123456789ABCDEF"[toWrite[i] >> 4]); ss.push_back("0123456789ABCDEF"[toWrite[i] & 0x0F]); - } - } - - UUID::UUID(const Aws::String& uuidToConvert) - { - //GUID has 2 characters per byte + 4 dashes = 36 bytes - assert(uuidToConvert.length() == UUID_STR_SIZE); - memset(m_uuid, 0, sizeof(m_uuid)); - Aws::String escapedHexStr(uuidToConvert); - StringUtils::Replace(escapedHexStr, "-", ""); - assert(escapedHexStr.length() == UUID_BINARY_SIZE * 2); - ByteBuffer&& rawUuid = HashingUtils::HexDecode(escapedHexStr); - memcpy(m_uuid, rawUuid.GetUnderlyingData(), rawUuid.GetLength()); - } - - UUID::UUID(const unsigned char toCopy[UUID_BINARY_SIZE]) - { - memcpy(m_uuid, toCopy, sizeof(m_uuid)); - } - - UUID::operator Aws::String() const - { + } + } + + UUID::UUID(const Aws::String& uuidToConvert) + { + //GUID has 2 characters per byte + 4 dashes = 36 bytes + assert(uuidToConvert.length() == UUID_STR_SIZE); + memset(m_uuid, 0, sizeof(m_uuid)); + Aws::String escapedHexStr(uuidToConvert); + StringUtils::Replace(escapedHexStr, "-", ""); + assert(escapedHexStr.length() == UUID_BINARY_SIZE * 2); + ByteBuffer&& rawUuid = HashingUtils::HexDecode(escapedHexStr); + memcpy(m_uuid, rawUuid.GetUnderlyingData(), rawUuid.GetLength()); + } + + UUID::UUID(const unsigned char toCopy[UUID_BINARY_SIZE]) + { + memcpy(m_uuid, toCopy, sizeof(m_uuid)); + } + + UUID::operator Aws::String() const + { Aws::String ss; ss.reserve(UUID_STR_SIZE); hexify(ss, m_uuid, 0, 4); ss.push_back('-'); - + hexify(ss, m_uuid, 4, 6); ss.push_back('-'); - + hexify(ss, m_uuid, 6, 8); ss.push_back('-'); - + hexify(ss, m_uuid, 8, 10); ss.push_back('-'); - + hexify(ss, m_uuid, 10, 16); - + return ss; - } - - UUID UUID::RandomUUID() - { - auto secureRandom = Crypto::CreateSecureRandomBytesImplementation(); - assert(secureRandom); - - unsigned char randomBytes[UUID_BINARY_SIZE]; - memset(randomBytes, 0, UUID_BINARY_SIZE); - secureRandom->GetBytes(randomBytes, UUID_BINARY_SIZE); - //Set version bits to 0100 - //https://tools.ietf.org/html/rfc4122#section-4.1.3 - randomBytes[VERSION_LOCATION] = (randomBytes[VERSION_LOCATION] & VERSION_MASK) | VERSION; - //set variant bits to 10 - //https://tools.ietf.org/html/rfc4122#section-4.1.1 - randomBytes[VARIANT_LOCATION] = (randomBytes[VARIANT_LOCATION] & VARIANT_MASK) | VARIANT; - - return UUID(randomBytes); - } - } -} + } + + UUID UUID::RandomUUID() + { + auto secureRandom = Crypto::CreateSecureRandomBytesImplementation(); + assert(secureRandom); + + unsigned char randomBytes[UUID_BINARY_SIZE]; + memset(randomBytes, 0, UUID_BINARY_SIZE); + secureRandom->GetBytes(randomBytes, UUID_BINARY_SIZE); + //Set version bits to 0100 + //https://tools.ietf.org/html/rfc4122#section-4.1.3 + randomBytes[VERSION_LOCATION] = (randomBytes[VERSION_LOCATION] & VERSION_MASK) | VERSION; + //set variant bits to 10 + //https://tools.ietf.org/html/rfc4122#section-4.1.1 + randomBytes[VARIANT_LOCATION] = (randomBytes[VARIANT_LOCATION] & VARIANT_MASK) | VARIANT; + + return UUID(randomBytes); + } + } +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/base64/Base64.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/base64/Base64.cpp index 2103d6d5a6..a6a777164d 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/base64/Base64.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/base64/Base64.cpp @@ -2,147 +2,147 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/utils/base64/Base64.h> -#include <cstring> - -using namespace Aws::Utils::Base64; - -static const uint8_t SENTINEL_VALUE = 255; -static const char BASE64_ENCODING_TABLE_MIME[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -namespace Aws -{ -namespace Utils -{ -namespace Base64 -{ - -Base64::Base64(const char *encodingTable) -{ - if(encodingTable == nullptr) - { - encodingTable = BASE64_ENCODING_TABLE_MIME; - } - - size_t encodingTableLength = strlen(encodingTable); - if(encodingTableLength != 64) - { - encodingTable = BASE64_ENCODING_TABLE_MIME; - encodingTableLength = 64; - } - - memcpy(m_mimeBase64EncodingTable, encodingTable, encodingTableLength); - - memset((void *)m_mimeBase64DecodingTable, 0, 256); - - for(uint32_t i = 0; i < encodingTableLength; ++i) - { - uint32_t index = static_cast<uint32_t>(m_mimeBase64EncodingTable[i]); - m_mimeBase64DecodingTable[index] = static_cast<uint8_t>(i); - } - - m_mimeBase64DecodingTable[(uint32_t)'='] = SENTINEL_VALUE; -} - -Aws::String Base64::Encode(const Aws::Utils::ByteBuffer& buffer) const -{ - size_t bufferLength = buffer.GetLength(); - size_t blockCount = (bufferLength + 2) / 3; - size_t remainderCount = (bufferLength % 3); - - Aws::String outputString; - outputString.reserve(CalculateBase64EncodedLength(buffer)); - - for(size_t i = 0; i < bufferLength; i += 3 ) - { - uint32_t block = buffer[ i ]; - - block <<= 8; - if (i + 1 < bufferLength) - { - block = block | buffer[ i + 1 ]; - } - - block <<= 8; - if (i + 2 < bufferLength) - { - block = block | buffer[ i + 2 ]; - } - - outputString.push_back(m_mimeBase64EncodingTable[(block >> 18) & 0x3F]); - outputString.push_back(m_mimeBase64EncodingTable[(block >> 12) & 0x3F]); - outputString.push_back(m_mimeBase64EncodingTable[(block >> 6) & 0x3F]); - outputString.push_back(m_mimeBase64EncodingTable[block & 0x3F]); - } - - if(remainderCount > 0) - { - outputString[blockCount * 4 - 1] = '='; - if(remainderCount == 1) - { - outputString[blockCount * 4 - 2] = '='; - } - } - - return outputString; -} - -Aws::Utils::ByteBuffer Base64::Decode(const Aws::String& str) const -{ - size_t decodedLength = CalculateBase64DecodedLength(str); - - Aws::Utils::ByteBuffer buffer(decodedLength); - - const char* rawString = str.c_str(); - size_t blockCount = str.length() / 4; - for(size_t i = 0; i < blockCount; ++i) - { - size_t stringIndex = i * 4; - - uint32_t value1 = m_mimeBase64DecodingTable[uint32_t(rawString[stringIndex])]; - uint32_t value2 = m_mimeBase64DecodingTable[uint32_t(rawString[++stringIndex])]; - uint32_t value3 = m_mimeBase64DecodingTable[uint32_t(rawString[++stringIndex])]; - uint32_t value4 = m_mimeBase64DecodingTable[uint32_t(rawString[++stringIndex])]; - - size_t bufferIndex = i * 3; - buffer[bufferIndex] = static_cast<uint8_t>((value1 << 2) | ((value2 >> 4) & 0x03)); - if(value3 != SENTINEL_VALUE) - { - buffer[++bufferIndex] = static_cast<uint8_t>(((value2 << 4) & 0xF0) | ((value3 >> 2) & 0x0F)); - if(value4 != SENTINEL_VALUE) - { - buffer[++bufferIndex] = static_cast<uint8_t>((value3 & 0x03) << 6 | value4); - } - } - } - - return buffer; -} - -size_t Base64::CalculateBase64DecodedLength(const Aws::String& b64input) -{ + +#include <aws/core/utils/base64/Base64.h> +#include <cstring> + +using namespace Aws::Utils::Base64; + +static const uint8_t SENTINEL_VALUE = 255; +static const char BASE64_ENCODING_TABLE_MIME[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +namespace Aws +{ +namespace Utils +{ +namespace Base64 +{ + +Base64::Base64(const char *encodingTable) +{ + if(encodingTable == nullptr) + { + encodingTable = BASE64_ENCODING_TABLE_MIME; + } + + size_t encodingTableLength = strlen(encodingTable); + if(encodingTableLength != 64) + { + encodingTable = BASE64_ENCODING_TABLE_MIME; + encodingTableLength = 64; + } + + memcpy(m_mimeBase64EncodingTable, encodingTable, encodingTableLength); + + memset((void *)m_mimeBase64DecodingTable, 0, 256); + + for(uint32_t i = 0; i < encodingTableLength; ++i) + { + uint32_t index = static_cast<uint32_t>(m_mimeBase64EncodingTable[i]); + m_mimeBase64DecodingTable[index] = static_cast<uint8_t>(i); + } + + m_mimeBase64DecodingTable[(uint32_t)'='] = SENTINEL_VALUE; +} + +Aws::String Base64::Encode(const Aws::Utils::ByteBuffer& buffer) const +{ + size_t bufferLength = buffer.GetLength(); + size_t blockCount = (bufferLength + 2) / 3; + size_t remainderCount = (bufferLength % 3); + + Aws::String outputString; + outputString.reserve(CalculateBase64EncodedLength(buffer)); + + for(size_t i = 0; i < bufferLength; i += 3 ) + { + uint32_t block = buffer[ i ]; + + block <<= 8; + if (i + 1 < bufferLength) + { + block = block | buffer[ i + 1 ]; + } + + block <<= 8; + if (i + 2 < bufferLength) + { + block = block | buffer[ i + 2 ]; + } + + outputString.push_back(m_mimeBase64EncodingTable[(block >> 18) & 0x3F]); + outputString.push_back(m_mimeBase64EncodingTable[(block >> 12) & 0x3F]); + outputString.push_back(m_mimeBase64EncodingTable[(block >> 6) & 0x3F]); + outputString.push_back(m_mimeBase64EncodingTable[block & 0x3F]); + } + + if(remainderCount > 0) + { + outputString[blockCount * 4 - 1] = '='; + if(remainderCount == 1) + { + outputString[blockCount * 4 - 2] = '='; + } + } + + return outputString; +} + +Aws::Utils::ByteBuffer Base64::Decode(const Aws::String& str) const +{ + size_t decodedLength = CalculateBase64DecodedLength(str); + + Aws::Utils::ByteBuffer buffer(decodedLength); + + const char* rawString = str.c_str(); + size_t blockCount = str.length() / 4; + for(size_t i = 0; i < blockCount; ++i) + { + size_t stringIndex = i * 4; + + uint32_t value1 = m_mimeBase64DecodingTable[uint32_t(rawString[stringIndex])]; + uint32_t value2 = m_mimeBase64DecodingTable[uint32_t(rawString[++stringIndex])]; + uint32_t value3 = m_mimeBase64DecodingTable[uint32_t(rawString[++stringIndex])]; + uint32_t value4 = m_mimeBase64DecodingTable[uint32_t(rawString[++stringIndex])]; + + size_t bufferIndex = i * 3; + buffer[bufferIndex] = static_cast<uint8_t>((value1 << 2) | ((value2 >> 4) & 0x03)); + if(value3 != SENTINEL_VALUE) + { + buffer[++bufferIndex] = static_cast<uint8_t>(((value2 << 4) & 0xF0) | ((value3 >> 2) & 0x0F)); + if(value4 != SENTINEL_VALUE) + { + buffer[++bufferIndex] = static_cast<uint8_t>((value3 & 0x03) << 6 | value4); + } + } + } + + return buffer; +} + +size_t Base64::CalculateBase64DecodedLength(const Aws::String& b64input) +{ const size_t len = b64input.length(); if(len < 2) - { - return 0; - } - - size_t padding = 0; - - if (b64input[len - 1] == '=' && b64input[len - 2] == '=') //last two chars are = - padding = 2; - else if (b64input[len - 1] == '=') //last char is = - padding = 1; - - return (len * 3 / 4 - padding); -} - -size_t Base64::CalculateBase64EncodedLength(const Aws::Utils::ByteBuffer& buffer) -{ - return 4 * ((buffer.GetLength() + 2) / 3); -} - -} // namespace Base64 -} // namespace Utils -} // namespace Aws
\ No newline at end of file + { + return 0; + } + + size_t padding = 0; + + if (b64input[len - 1] == '=' && b64input[len - 2] == '=') //last two chars are = + padding = 2; + else if (b64input[len - 1] == '=') //last char is = + padding = 1; + + return (len * 3 / 4 - padding); +} + +size_t Base64::CalculateBase64EncodedLength(const Aws::Utils::ByteBuffer& buffer) +{ + return 4 * ((buffer.GetLength() + 2) / 3); +} + +} // namespace Base64 +} // namespace Utils +} // namespace Aws
\ No newline at end of file diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Cipher.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Cipher.cpp index 1c844273f4..128a2cb60a 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Cipher.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Cipher.cpp @@ -2,122 +2,122 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/utils/crypto/Cipher.h> -#include <aws/core/utils/crypto/Factories.h> -#include <aws/core/utils/crypto/SecureRandom.h> -#include <aws/core/utils/logging/LogMacros.h> -#include <cstdlib> -#include <climits> - -//if you are reading this, you are witnessing pure brilliance. -#define IS_BIG_ENDIAN (*(uint16_t*)"\0\xff" < 0x100) - -using namespace Aws::Utils::Crypto; -using namespace Aws::Utils; - -namespace Aws -{ - namespace Utils - { - namespace Crypto - { - static const char* LOG_TAG = "Cipher"; - - //swap byte ordering - template<class T> - typename std::enable_if<std::is_unsigned<T>::value, T>::type + +#include <aws/core/utils/crypto/Cipher.h> +#include <aws/core/utils/crypto/Factories.h> +#include <aws/core/utils/crypto/SecureRandom.h> +#include <aws/core/utils/logging/LogMacros.h> +#include <cstdlib> +#include <climits> + +//if you are reading this, you are witnessing pure brilliance. +#define IS_BIG_ENDIAN (*(uint16_t*)"\0\xff" < 0x100) + +using namespace Aws::Utils::Crypto; +using namespace Aws::Utils; + +namespace Aws +{ + namespace Utils + { + namespace Crypto + { + static const char* LOG_TAG = "Cipher"; + + //swap byte ordering + template<class T> + typename std::enable_if<std::is_unsigned<T>::value, T>::type bswap(T i, T j = 0u, std::size_t n = 0u) + { + return n == sizeof(T) ? j : + bswap<T>(i >> CHAR_BIT, (j << CHAR_BIT) | (i & (T)(unsigned char)(-1)), n + 1); + } + + CryptoBuffer IncrementCTRCounter(const CryptoBuffer& counter, uint32_t numberOfBlocks) { - return n == sizeof(T) ? j : - bswap<T>(i >> CHAR_BIT, (j << CHAR_BIT) | (i & (T)(unsigned char)(-1)), n + 1); - } - - CryptoBuffer IncrementCTRCounter(const CryptoBuffer& counter, uint32_t numberOfBlocks) - { - // minium counter size is 12 bytes. This isn't a variable because some compilers - // are stupid and thing that variable is unused. - assert(counter.GetLength() >= 12); - + // minium counter size is 12 bytes. This isn't a variable because some compilers + // are stupid and thing that variable is unused. + assert(counter.GetLength() >= 12); + CryptoBuffer incrementedCounter(counter); - - //get the last 4 bytes and manipulate them as an integer. + + //get the last 4 bytes and manipulate them as an integer. uint32_t* ctrPtr = (uint32_t*)(incrementedCounter.GetUnderlyingData() + incrementedCounter.GetLength() - sizeof(int32_t)); - if(IS_BIG_ENDIAN) - { - //you likely are not Big Endian, but - //if it's big endian, just go ahead and increment it... done + if(IS_BIG_ENDIAN) + { + //you likely are not Big Endian, but + //if it's big endian, just go ahead and increment it... done *ctrPtr += numberOfBlocks; - } - else - { + } + else + { //otherwise, swap the byte ordering of the integer we loaded from the buffer (because it is backwards). However, the number of blocks is already properly - //aligned. Once we compute the new value, swap it back so that the mirroring operation goes back to the actual buffer. - *ctrPtr = bswap<uint32_t>(bswap<uint32_t>(*ctrPtr) + numberOfBlocks); - } - - return incrementedCounter; - } - - CryptoBuffer GenerateXRandomBytes(size_t lengthBytes, bool ctrMode) - { - std::shared_ptr<SecureRandomBytes> rng = CreateSecureRandomBytesImplementation(); - - CryptoBuffer bytes(lengthBytes); - size_t lengthToGenerate = ctrMode ? (3 * bytes.GetLength()) / 4 : bytes.GetLength(); - - rng->GetBytes(bytes.GetUnderlyingData(), lengthToGenerate); - - if(!*rng) - { - AWS_LOGSTREAM_FATAL(LOG_TAG, "Random Number generation failed. Abort all crypto operations."); - assert(false); + //aligned. Once we compute the new value, swap it back so that the mirroring operation goes back to the actual buffer. + *ctrPtr = bswap<uint32_t>(bswap<uint32_t>(*ctrPtr) + numberOfBlocks); + } + + return incrementedCounter; + } + + CryptoBuffer GenerateXRandomBytes(size_t lengthBytes, bool ctrMode) + { + std::shared_ptr<SecureRandomBytes> rng = CreateSecureRandomBytesImplementation(); + + CryptoBuffer bytes(lengthBytes); + size_t lengthToGenerate = ctrMode ? (3 * bytes.GetLength()) / 4 : bytes.GetLength(); + + rng->GetBytes(bytes.GetUnderlyingData(), lengthToGenerate); + + if(!*rng) + { + AWS_LOGSTREAM_FATAL(LOG_TAG, "Random Number generation failed. Abort all crypto operations."); + assert(false); abort(); - } - - return bytes; - } - - /** - * Generate random number per 4 bytes and use each byte for the byte in the iv - */ - CryptoBuffer SymmetricCipher::GenerateIV(size_t ivLengthBytes, bool ctrMode) - { - CryptoBuffer iv(GenerateXRandomBytes(ivLengthBytes, ctrMode)); - - if(iv.GetLength() == 0) - { - AWS_LOGSTREAM_ERROR(LOG_TAG, "Unable to generate iv of length " << ivLengthBytes); - return iv; - } - - if(ctrMode) - { - //init the counter - size_t length = iv.GetLength(); - //[ nonce 1/4] [ iv 1/2 ] [ ctr 1/4 ] - size_t ctrStart = (length / 2) + (length / 4); - for(; ctrStart < iv.GetLength() - 1; ++ ctrStart) - { - iv[ctrStart] = 0; - } - iv[length - 1] = 1; - } - - return iv; - } - - CryptoBuffer SymmetricCipher::GenerateKey(size_t keyLengthBytes) - { - CryptoBuffer const& key = GenerateXRandomBytes(keyLengthBytes, false); - - if(key.GetLength() == 0) - { - AWS_LOGSTREAM_ERROR(LOG_TAG, "Unable to generate key of length " << keyLengthBytes); - } - - return key; - } - } - } -} + } + + return bytes; + } + + /** + * Generate random number per 4 bytes and use each byte for the byte in the iv + */ + CryptoBuffer SymmetricCipher::GenerateIV(size_t ivLengthBytes, bool ctrMode) + { + CryptoBuffer iv(GenerateXRandomBytes(ivLengthBytes, ctrMode)); + + if(iv.GetLength() == 0) + { + AWS_LOGSTREAM_ERROR(LOG_TAG, "Unable to generate iv of length " << ivLengthBytes); + return iv; + } + + if(ctrMode) + { + //init the counter + size_t length = iv.GetLength(); + //[ nonce 1/4] [ iv 1/2 ] [ ctr 1/4 ] + size_t ctrStart = (length / 2) + (length / 4); + for(; ctrStart < iv.GetLength() - 1; ++ ctrStart) + { + iv[ctrStart] = 0; + } + iv[length - 1] = 1; + } + + return iv; + } + + CryptoBuffer SymmetricCipher::GenerateKey(size_t keyLengthBytes) + { + CryptoBuffer const& key = GenerateXRandomBytes(keyLengthBytes, false); + + if(key.GetLength() == 0) + { + AWS_LOGSTREAM_ERROR(LOG_TAG, "Unable to generate key of length " << keyLengthBytes); + } + + return key; + } + } + } +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/ContentCryptoMaterial.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/ContentCryptoMaterial.cpp index 3036bd70eb..3d484f680b 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/ContentCryptoMaterial.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/ContentCryptoMaterial.cpp @@ -2,33 +2,33 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ -#include <aws/core/utils/crypto/ContentCryptoMaterial.h> -#include <aws/core/utils/crypto/Cipher.h> - -using namespace Aws::Utils::Crypto; - -namespace Aws -{ - namespace Utils - { - namespace Crypto - { - ContentCryptoMaterial::ContentCryptoMaterial() : - m_cryptoTagLength(0), m_keyWrapAlgorithm(KeyWrapAlgorithm::NONE), m_contentCryptoScheme(ContentCryptoScheme::NONE) - { - } - - ContentCryptoMaterial::ContentCryptoMaterial(ContentCryptoScheme contentCryptoScheme) : - m_contentEncryptionKey(SymmetricCipher::GenerateKey()), m_cryptoTagLength(0), m_keyWrapAlgorithm(KeyWrapAlgorithm::NONE), m_contentCryptoScheme(contentCryptoScheme) - { - - } - - ContentCryptoMaterial::ContentCryptoMaterial(const Aws::Utils::CryptoBuffer & cek, ContentCryptoScheme contentCryptoScheme) : - m_contentEncryptionKey(cek), m_cryptoTagLength(0), m_keyWrapAlgorithm(KeyWrapAlgorithm::NONE), m_contentCryptoScheme(contentCryptoScheme) - { - - } - } - } -} +#include <aws/core/utils/crypto/ContentCryptoMaterial.h> +#include <aws/core/utils/crypto/Cipher.h> + +using namespace Aws::Utils::Crypto; + +namespace Aws +{ + namespace Utils + { + namespace Crypto + { + ContentCryptoMaterial::ContentCryptoMaterial() : + m_cryptoTagLength(0), m_keyWrapAlgorithm(KeyWrapAlgorithm::NONE), m_contentCryptoScheme(ContentCryptoScheme::NONE) + { + } + + ContentCryptoMaterial::ContentCryptoMaterial(ContentCryptoScheme contentCryptoScheme) : + m_contentEncryptionKey(SymmetricCipher::GenerateKey()), m_cryptoTagLength(0), m_keyWrapAlgorithm(KeyWrapAlgorithm::NONE), m_contentCryptoScheme(contentCryptoScheme) + { + + } + + ContentCryptoMaterial::ContentCryptoMaterial(const Aws::Utils::CryptoBuffer & cek, ContentCryptoScheme contentCryptoScheme) : + m_contentEncryptionKey(cek), m_cryptoTagLength(0), m_keyWrapAlgorithm(KeyWrapAlgorithm::NONE), m_contentCryptoScheme(contentCryptoScheme) + { + + } + } + } +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/ContentCryptoScheme.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/ContentCryptoScheme.cpp index f39a75df2c..c32df35939 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/ContentCryptoScheme.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/ContentCryptoScheme.cpp @@ -2,60 +2,60 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ -#include <aws/core/utils/crypto/ContentCryptoScheme.h> -#include <aws/core/utils/HashingUtils.h> -#include <aws/core/utils/EnumParseOverflowContainer.h> -#include <aws/core/Globals.h> - -using namespace Aws::Utils; - -namespace Aws -{ - namespace Utils - { - namespace Crypto - { - namespace ContentCryptoSchemeMapper - { - static const int cryptoScheme_CBC_HASH = HashingUtils::HashString("AES/CBC/PKCS5Padding"); - static const int cryptoScheme_CTR_HASH = HashingUtils::HashString("AES/CTR/NoPadding"); - static const int cryptoScheme_GCM_HASH = HashingUtils::HashString("AES/GCM/NoPadding"); - - ContentCryptoScheme GetContentCryptoSchemeForName(const Aws::String& name) - { - int hashcode = HashingUtils::HashString(name.c_str()); - if (hashcode == cryptoScheme_CBC_HASH) - { - return ContentCryptoScheme::CBC; - } - else if (hashcode == cryptoScheme_CTR_HASH) - { - return ContentCryptoScheme::CTR; - } - else if (hashcode == cryptoScheme_GCM_HASH) - { - return ContentCryptoScheme::GCM; - } - assert(0); - return ContentCryptoScheme::NONE; - } - - Aws::String GetNameForContentCryptoScheme(ContentCryptoScheme enumValue) - { - switch (enumValue) - { - case ContentCryptoScheme::CBC: - return "AES/CBC/PKCS5Padding"; - case ContentCryptoScheme::CTR: - return "AES/CTR/NoPadding"; - case ContentCryptoScheme::GCM: - return "AES/GCM/NoPadding"; - default: - assert(0); - return ""; - } - } - }//namespace ContentCryptoSchemeMapper - } //namespace Crypto - }//namespace Utils -}//namespace Aws
\ No newline at end of file +#include <aws/core/utils/crypto/ContentCryptoScheme.h> +#include <aws/core/utils/HashingUtils.h> +#include <aws/core/utils/EnumParseOverflowContainer.h> +#include <aws/core/Globals.h> + +using namespace Aws::Utils; + +namespace Aws +{ + namespace Utils + { + namespace Crypto + { + namespace ContentCryptoSchemeMapper + { + static const int cryptoScheme_CBC_HASH = HashingUtils::HashString("AES/CBC/PKCS5Padding"); + static const int cryptoScheme_CTR_HASH = HashingUtils::HashString("AES/CTR/NoPadding"); + static const int cryptoScheme_GCM_HASH = HashingUtils::HashString("AES/GCM/NoPadding"); + + ContentCryptoScheme GetContentCryptoSchemeForName(const Aws::String& name) + { + int hashcode = HashingUtils::HashString(name.c_str()); + if (hashcode == cryptoScheme_CBC_HASH) + { + return ContentCryptoScheme::CBC; + } + else if (hashcode == cryptoScheme_CTR_HASH) + { + return ContentCryptoScheme::CTR; + } + else if (hashcode == cryptoScheme_GCM_HASH) + { + return ContentCryptoScheme::GCM; + } + assert(0); + return ContentCryptoScheme::NONE; + } + + Aws::String GetNameForContentCryptoScheme(ContentCryptoScheme enumValue) + { + switch (enumValue) + { + case ContentCryptoScheme::CBC: + return "AES/CBC/PKCS5Padding"; + case ContentCryptoScheme::CTR: + return "AES/CTR/NoPadding"; + case ContentCryptoScheme::GCM: + return "AES/GCM/NoPadding"; + default: + assert(0); + return ""; + } + } + }//namespace ContentCryptoSchemeMapper + } //namespace Crypto + }//namespace Utils +}//namespace Aws
\ No newline at end of file diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/CryptoBuf.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/CryptoBuf.cpp index 2b47097679..7f433ce368 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/CryptoBuf.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/CryptoBuf.cpp @@ -2,300 +2,300 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/utils/crypto/CryptoBuf.h> - -namespace Aws -{ - namespace Utils - { - namespace Crypto - { - SymmetricCryptoBufSrc::SymmetricCryptoBufSrc(Aws::IStream& stream, SymmetricCipher& cipher, CipherMode cipherMode, size_t bufferSize) - : - m_isBuf(PUT_BACK_SIZE), m_cipher(cipher), m_stream(stream), m_cipherMode(cipherMode), m_isFinalized(false), - m_bufferSize(bufferSize), m_putBack(PUT_BACK_SIZE) - { - char* end = reinterpret_cast<char*>(m_isBuf.GetUnderlyingData() + m_isBuf.GetLength()); - setg(end, end, end); - } - - SymmetricCryptoBufSrc::pos_type SymmetricCryptoBufSrc::seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which) - { - if(which == std::ios_base::in) - { - auto curPos = m_stream.tellg(); - //error on seek we may have read past the end already. Try resetting and seeking to the end first - if (curPos == pos_type(-1)) - { - m_stream.clear(); - m_stream.seekg(0, std::ios_base::end); - curPos = m_stream.tellg(); - } - - auto absPosition = ComputeAbsSeekPosition(off, dir, curPos); - size_t seekTo = static_cast<size_t>(absPosition); - size_t index = static_cast<size_t>(curPos); - - if(index == seekTo) - { - return curPos; - } - else if (seekTo < index) - { - m_cipher.Reset(); - m_stream.clear(); - m_stream.seekg(0); - m_isFinalized = false; - index = 0; - } - - CryptoBuffer cryptoBuffer; - while (m_cipher && index < seekTo && !m_isFinalized) - { - size_t max_read = std::min<size_t>(static_cast<size_t>(seekTo - index), m_bufferSize); - - Aws::Utils::Array<char> buf(max_read); - size_t readSize(0); - if(m_stream) - { - m_stream.read(buf.GetUnderlyingData(), max_read); - readSize = static_cast<size_t>(m_stream.gcount()); - } - - if (readSize > 0) - { - if (m_cipherMode == CipherMode::Encrypt) - { - cryptoBuffer = m_cipher.EncryptBuffer(CryptoBuffer(reinterpret_cast<unsigned char*>(buf.GetUnderlyingData()), readSize)); - } - else - { - cryptoBuffer = m_cipher.DecryptBuffer(CryptoBuffer(reinterpret_cast<unsigned char*>(buf.GetUnderlyingData()), readSize)); - } - } - else - { - if (m_cipherMode == CipherMode::Encrypt) - { - cryptoBuffer = m_cipher.FinalizeEncryption(); - } - else - { - cryptoBuffer = m_cipher.FinalizeDecryption(); - } - - m_isFinalized = true; - } - - index += cryptoBuffer.GetLength(); - } - - if (cryptoBuffer.GetLength() && m_cipher) - { - CryptoBuffer putBackArea(m_putBack); - - m_isBuf = CryptoBuffer({&putBackArea, &cryptoBuffer}); - //in the very unlikely case that the cipher had less output than the source stream. - assert(seekTo <= index); - size_t newBufferPos = index > seekTo ? cryptoBuffer.GetLength() - (index - seekTo) : cryptoBuffer.GetLength(); - char* baseBufPtr = reinterpret_cast<char*>(m_isBuf.GetUnderlyingData()); - setg(baseBufPtr, baseBufPtr + m_putBack + newBufferPos, baseBufPtr + m_isBuf.GetLength()); - - return pos_type(seekTo); - } - else if (seekTo == 0) - { - m_isBuf = CryptoBuffer(m_putBack); - char* end = reinterpret_cast<char*>(m_isBuf.GetUnderlyingData() + m_isBuf.GetLength()); - setg(end, end, end); - return pos_type(seekTo); - } - } - - return pos_type(off_type(-1)); - } - - SymmetricCryptoBufSrc::pos_type SymmetricCryptoBufSrc::seekpos(pos_type pos, std::ios_base::openmode which) - { - return seekoff(pos, std::ios_base::beg, which); - } - - SymmetricCryptoBufSrc::int_type SymmetricCryptoBufSrc::underflow() - { - if (!m_cipher || (m_isFinalized && gptr() >= egptr())) - { - return traits_type::eof(); - } - - if (gptr() < egptr()) - { - return traits_type::to_int_type(*gptr()); - } - - char* baseBufPtr = reinterpret_cast<char*>(m_isBuf.GetUnderlyingData()); - CryptoBuffer putBackArea(m_putBack); - - //eback is properly set after the first fill. So this guarantees we are on the second or later fill. - if (eback() == baseBufPtr) - { - //just fill in the last bit of the previous buffer into the put back area so that it has some data in it - memcpy(putBackArea.GetUnderlyingData(), egptr() - m_putBack, m_putBack); - } - - CryptoBuffer newDataBuf; - - while(!newDataBuf.GetLength() && !m_isFinalized) - { - Aws::Utils::Array<char> buf(m_bufferSize); - m_stream.read(buf.GetUnderlyingData(), m_bufferSize); - size_t readSize = static_cast<size_t>(m_stream.gcount()); - - if (readSize > 0) - { - if (m_cipherMode == CipherMode::Encrypt) - { - newDataBuf = m_cipher.EncryptBuffer(CryptoBuffer(reinterpret_cast<unsigned char*>(buf.GetUnderlyingData()), readSize)); - } - else - { - newDataBuf = m_cipher.DecryptBuffer(CryptoBuffer(reinterpret_cast<unsigned char*>(buf.GetUnderlyingData()), readSize)); - } - } - else - { - if (m_cipherMode == CipherMode::Encrypt) - { - newDataBuf = m_cipher.FinalizeEncryption(); - } - else - { - newDataBuf = m_cipher.FinalizeDecryption(); - } - - m_isFinalized = true; - } - } - - - if(newDataBuf.GetLength() > 0) - { - m_isBuf = CryptoBuffer({&putBackArea, &newDataBuf}); - - baseBufPtr = reinterpret_cast<char*>(m_isBuf.GetUnderlyingData()); - setg(baseBufPtr, baseBufPtr + m_putBack, baseBufPtr + m_isBuf.GetLength()); - - return traits_type::to_int_type(*gptr()); - } - - return traits_type::eof(); - } - - SymmetricCryptoBufSrc::off_type SymmetricCryptoBufSrc::ComputeAbsSeekPosition(off_type pos, std::ios_base::seekdir dir, std::fpos<FPOS_TYPE> curPos) - { - switch(dir) - { - case std::ios_base::beg: - return pos; - case std::ios_base::cur: - return m_stream.tellg() + pos; - case std::ios_base::end: - { - off_type absPos = m_stream.seekg(0, std::ios_base::end).tellg() - pos; - m_stream.seekg(curPos); - return absPos; - } - default: - assert(0); - return off_type(-1); - } - } - - void SymmetricCryptoBufSrc::FinalizeCipher() - { - if(m_cipher && !m_isFinalized) - { - if(m_cipherMode == CipherMode::Encrypt) - { - m_cipher.FinalizeEncryption(); - } - else - { - m_cipher.FinalizeDecryption(); - } - } - } - - SymmetricCryptoBufSink::SymmetricCryptoBufSink(Aws::OStream& stream, SymmetricCipher& cipher, CipherMode cipherMode, size_t bufferSize, int16_t blockOffset) - : - m_osBuf(bufferSize), m_cipher(cipher), m_stream(stream), m_cipherMode(cipherMode), m_isFinalized(false), m_blockOffset(blockOffset) - { - assert(m_blockOffset < 16 && m_blockOffset >= 0); - char* outputBase = reinterpret_cast<char*>(m_osBuf.GetUnderlyingData()); - setp(outputBase, outputBase + bufferSize - 1); - } - - SymmetricCryptoBufSink::~SymmetricCryptoBufSink() - { - FinalizeCiphersAndFlushSink(); - } - - void SymmetricCryptoBufSink::FinalizeCiphersAndFlushSink() - { - if(m_cipher && !m_isFinalized) - { - writeOutput(true); - } - } - - bool SymmetricCryptoBufSink::writeOutput(bool finalize) - { - if(!m_isFinalized) - { - CryptoBuffer cryptoBuf; - if (pptr() > pbase()) - { - if (m_cipherMode == CipherMode::Encrypt) - { - cryptoBuf = m_cipher.EncryptBuffer(CryptoBuffer(reinterpret_cast<unsigned char*>(pbase()), pptr() - pbase())); - } - else - { - cryptoBuf = m_cipher.DecryptBuffer(CryptoBuffer(reinterpret_cast<unsigned char*>(pbase()), pptr() - pbase())); - } - - pbump(-(static_cast<int>(pptr() - pbase()))); - } - if(finalize) - { - CryptoBuffer finalBuffer; - if (m_cipherMode == CipherMode::Encrypt) - { - finalBuffer = m_cipher.FinalizeEncryption(); - } - else - { - finalBuffer = m_cipher.FinalizeDecryption(); - } - if(cryptoBuf.GetLength()) - { - cryptoBuf = CryptoBuffer({&cryptoBuf, &finalBuffer}); - } - else - { - cryptoBuf = std::move(finalBuffer); - } - - m_isFinalized = true; - } - - if (m_cipher) - { - if(cryptoBuf.GetLength()) - { - //allow mid block decryption. We have to decrypt it, but we don't have to write it to the stream. + +#include <aws/core/utils/crypto/CryptoBuf.h> + +namespace Aws +{ + namespace Utils + { + namespace Crypto + { + SymmetricCryptoBufSrc::SymmetricCryptoBufSrc(Aws::IStream& stream, SymmetricCipher& cipher, CipherMode cipherMode, size_t bufferSize) + : + m_isBuf(PUT_BACK_SIZE), m_cipher(cipher), m_stream(stream), m_cipherMode(cipherMode), m_isFinalized(false), + m_bufferSize(bufferSize), m_putBack(PUT_BACK_SIZE) + { + char* end = reinterpret_cast<char*>(m_isBuf.GetUnderlyingData() + m_isBuf.GetLength()); + setg(end, end, end); + } + + SymmetricCryptoBufSrc::pos_type SymmetricCryptoBufSrc::seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which) + { + if(which == std::ios_base::in) + { + auto curPos = m_stream.tellg(); + //error on seek we may have read past the end already. Try resetting and seeking to the end first + if (curPos == pos_type(-1)) + { + m_stream.clear(); + m_stream.seekg(0, std::ios_base::end); + curPos = m_stream.tellg(); + } + + auto absPosition = ComputeAbsSeekPosition(off, dir, curPos); + size_t seekTo = static_cast<size_t>(absPosition); + size_t index = static_cast<size_t>(curPos); + + if(index == seekTo) + { + return curPos; + } + else if (seekTo < index) + { + m_cipher.Reset(); + m_stream.clear(); + m_stream.seekg(0); + m_isFinalized = false; + index = 0; + } + + CryptoBuffer cryptoBuffer; + while (m_cipher && index < seekTo && !m_isFinalized) + { + size_t max_read = std::min<size_t>(static_cast<size_t>(seekTo - index), m_bufferSize); + + Aws::Utils::Array<char> buf(max_read); + size_t readSize(0); + if(m_stream) + { + m_stream.read(buf.GetUnderlyingData(), max_read); + readSize = static_cast<size_t>(m_stream.gcount()); + } + + if (readSize > 0) + { + if (m_cipherMode == CipherMode::Encrypt) + { + cryptoBuffer = m_cipher.EncryptBuffer(CryptoBuffer(reinterpret_cast<unsigned char*>(buf.GetUnderlyingData()), readSize)); + } + else + { + cryptoBuffer = m_cipher.DecryptBuffer(CryptoBuffer(reinterpret_cast<unsigned char*>(buf.GetUnderlyingData()), readSize)); + } + } + else + { + if (m_cipherMode == CipherMode::Encrypt) + { + cryptoBuffer = m_cipher.FinalizeEncryption(); + } + else + { + cryptoBuffer = m_cipher.FinalizeDecryption(); + } + + m_isFinalized = true; + } + + index += cryptoBuffer.GetLength(); + } + + if (cryptoBuffer.GetLength() && m_cipher) + { + CryptoBuffer putBackArea(m_putBack); + + m_isBuf = CryptoBuffer({&putBackArea, &cryptoBuffer}); + //in the very unlikely case that the cipher had less output than the source stream. + assert(seekTo <= index); + size_t newBufferPos = index > seekTo ? cryptoBuffer.GetLength() - (index - seekTo) : cryptoBuffer.GetLength(); + char* baseBufPtr = reinterpret_cast<char*>(m_isBuf.GetUnderlyingData()); + setg(baseBufPtr, baseBufPtr + m_putBack + newBufferPos, baseBufPtr + m_isBuf.GetLength()); + + return pos_type(seekTo); + } + else if (seekTo == 0) + { + m_isBuf = CryptoBuffer(m_putBack); + char* end = reinterpret_cast<char*>(m_isBuf.GetUnderlyingData() + m_isBuf.GetLength()); + setg(end, end, end); + return pos_type(seekTo); + } + } + + return pos_type(off_type(-1)); + } + + SymmetricCryptoBufSrc::pos_type SymmetricCryptoBufSrc::seekpos(pos_type pos, std::ios_base::openmode which) + { + return seekoff(pos, std::ios_base::beg, which); + } + + SymmetricCryptoBufSrc::int_type SymmetricCryptoBufSrc::underflow() + { + if (!m_cipher || (m_isFinalized && gptr() >= egptr())) + { + return traits_type::eof(); + } + + if (gptr() < egptr()) + { + return traits_type::to_int_type(*gptr()); + } + + char* baseBufPtr = reinterpret_cast<char*>(m_isBuf.GetUnderlyingData()); + CryptoBuffer putBackArea(m_putBack); + + //eback is properly set after the first fill. So this guarantees we are on the second or later fill. + if (eback() == baseBufPtr) + { + //just fill in the last bit of the previous buffer into the put back area so that it has some data in it + memcpy(putBackArea.GetUnderlyingData(), egptr() - m_putBack, m_putBack); + } + + CryptoBuffer newDataBuf; + + while(!newDataBuf.GetLength() && !m_isFinalized) + { + Aws::Utils::Array<char> buf(m_bufferSize); + m_stream.read(buf.GetUnderlyingData(), m_bufferSize); + size_t readSize = static_cast<size_t>(m_stream.gcount()); + + if (readSize > 0) + { + if (m_cipherMode == CipherMode::Encrypt) + { + newDataBuf = m_cipher.EncryptBuffer(CryptoBuffer(reinterpret_cast<unsigned char*>(buf.GetUnderlyingData()), readSize)); + } + else + { + newDataBuf = m_cipher.DecryptBuffer(CryptoBuffer(reinterpret_cast<unsigned char*>(buf.GetUnderlyingData()), readSize)); + } + } + else + { + if (m_cipherMode == CipherMode::Encrypt) + { + newDataBuf = m_cipher.FinalizeEncryption(); + } + else + { + newDataBuf = m_cipher.FinalizeDecryption(); + } + + m_isFinalized = true; + } + } + + + if(newDataBuf.GetLength() > 0) + { + m_isBuf = CryptoBuffer({&putBackArea, &newDataBuf}); + + baseBufPtr = reinterpret_cast<char*>(m_isBuf.GetUnderlyingData()); + setg(baseBufPtr, baseBufPtr + m_putBack, baseBufPtr + m_isBuf.GetLength()); + + return traits_type::to_int_type(*gptr()); + } + + return traits_type::eof(); + } + + SymmetricCryptoBufSrc::off_type SymmetricCryptoBufSrc::ComputeAbsSeekPosition(off_type pos, std::ios_base::seekdir dir, std::fpos<FPOS_TYPE> curPos) + { + switch(dir) + { + case std::ios_base::beg: + return pos; + case std::ios_base::cur: + return m_stream.tellg() + pos; + case std::ios_base::end: + { + off_type absPos = m_stream.seekg(0, std::ios_base::end).tellg() - pos; + m_stream.seekg(curPos); + return absPos; + } + default: + assert(0); + return off_type(-1); + } + } + + void SymmetricCryptoBufSrc::FinalizeCipher() + { + if(m_cipher && !m_isFinalized) + { + if(m_cipherMode == CipherMode::Encrypt) + { + m_cipher.FinalizeEncryption(); + } + else + { + m_cipher.FinalizeDecryption(); + } + } + } + + SymmetricCryptoBufSink::SymmetricCryptoBufSink(Aws::OStream& stream, SymmetricCipher& cipher, CipherMode cipherMode, size_t bufferSize, int16_t blockOffset) + : + m_osBuf(bufferSize), m_cipher(cipher), m_stream(stream), m_cipherMode(cipherMode), m_isFinalized(false), m_blockOffset(blockOffset) + { + assert(m_blockOffset < 16 && m_blockOffset >= 0); + char* outputBase = reinterpret_cast<char*>(m_osBuf.GetUnderlyingData()); + setp(outputBase, outputBase + bufferSize - 1); + } + + SymmetricCryptoBufSink::~SymmetricCryptoBufSink() + { + FinalizeCiphersAndFlushSink(); + } + + void SymmetricCryptoBufSink::FinalizeCiphersAndFlushSink() + { + if(m_cipher && !m_isFinalized) + { + writeOutput(true); + } + } + + bool SymmetricCryptoBufSink::writeOutput(bool finalize) + { + if(!m_isFinalized) + { + CryptoBuffer cryptoBuf; + if (pptr() > pbase()) + { + if (m_cipherMode == CipherMode::Encrypt) + { + cryptoBuf = m_cipher.EncryptBuffer(CryptoBuffer(reinterpret_cast<unsigned char*>(pbase()), pptr() - pbase())); + } + else + { + cryptoBuf = m_cipher.DecryptBuffer(CryptoBuffer(reinterpret_cast<unsigned char*>(pbase()), pptr() - pbase())); + } + + pbump(-(static_cast<int>(pptr() - pbase()))); + } + if(finalize) + { + CryptoBuffer finalBuffer; + if (m_cipherMode == CipherMode::Encrypt) + { + finalBuffer = m_cipher.FinalizeEncryption(); + } + else + { + finalBuffer = m_cipher.FinalizeDecryption(); + } + if(cryptoBuf.GetLength()) + { + cryptoBuf = CryptoBuffer({&cryptoBuf, &finalBuffer}); + } + else + { + cryptoBuf = std::move(finalBuffer); + } + + m_isFinalized = true; + } + + if (m_cipher) + { + if(cryptoBuf.GetLength()) + { + //allow mid block decryption. We have to decrypt it, but we don't have to write it to the stream. //the assumption here is that tellp() will always be 0 or >= 16 bytes. The block offset should only - //be the offset of the first block read. + //be the offset of the first block read. size_t len = cryptoBuf.GetLength(); size_t blockOffset = m_stream.tellp() > m_blockOffset ? 0 : m_blockOffset; if (len > blockOffset) @@ -307,42 +307,42 @@ namespace Aws { m_blockOffset -= static_cast<int16_t>(len); } - } - return true; - } - } - - return false; - } - - SymmetricCryptoBufSink::int_type SymmetricCryptoBufSink::overflow(int_type ch) - { - if(m_cipher && m_stream) - { - if(ch != traits_type::eof()) - { - *pptr() = (char)ch; - pbump(1); - } - - if(writeOutput(ch == traits_type::eof())) - { - return ch; - } - } - - return traits_type::eof(); - } - - int SymmetricCryptoBufSink::sync() - { - if(m_cipher && m_stream) - { - return writeOutput(false) ? 0 : -1; - } - - return -1; - } - } - } -} + } + return true; + } + } + + return false; + } + + SymmetricCryptoBufSink::int_type SymmetricCryptoBufSink::overflow(int_type ch) + { + if(m_cipher && m_stream) + { + if(ch != traits_type::eof()) + { + *pptr() = (char)ch; + pbump(1); + } + + if(writeOutput(ch == traits_type::eof())) + { + return ch; + } + } + + return traits_type::eof(); + } + + int SymmetricCryptoBufSink::sync() + { + if(m_cipher && m_stream) + { + return writeOutput(false) ? 0 : -1; + } + + return -1; + } + } + } +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/CryptoStream.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/CryptoStream.cpp index 2d645f7427..aa0ebba128 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/CryptoStream.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/CryptoStream.cpp @@ -2,51 +2,51 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ -#include <aws/core/utils/crypto/CryptoStream.h> - -namespace Aws -{ - namespace Utils - { - namespace Crypto - { - static const char* CLASS_TAG = "Aws::Utils::Crypto::SymmetricCryptoStream"; - - SymmetricCryptoStream::SymmetricCryptoStream(Aws::IStream& src, CipherMode mode, SymmetricCipher& cipher, size_t bufSize) : - Aws::IOStream(m_cryptoBuf = Aws::New<SymmetricCryptoBufSrc>(CLASS_TAG, src, cipher, mode, bufSize)), m_hasOwnership(true) - { - } - - SymmetricCryptoStream::SymmetricCryptoStream(Aws::OStream& sink, CipherMode mode, SymmetricCipher& cipher, size_t bufSize, int16_t blockOffset) : - Aws::IOStream(m_cryptoBuf = Aws::New<SymmetricCryptoBufSink>(CLASS_TAG, sink, cipher, mode, bufSize, blockOffset)), m_hasOwnership(true) - { - } - - SymmetricCryptoStream::SymmetricCryptoStream(Aws::Utils::Crypto::SymmetricCryptoBufSrc& bufSrc) : - Aws::IOStream(&bufSrc), m_cryptoBuf(&bufSrc), m_hasOwnership(false) - { - } - - SymmetricCryptoStream::SymmetricCryptoStream(Aws::Utils::Crypto::SymmetricCryptoBufSink& bufSink) : - Aws::IOStream(&bufSink), m_cryptoBuf(&bufSink), m_hasOwnership(false) - { - } - - SymmetricCryptoStream::~SymmetricCryptoStream() - { - Finalize(); - - if(m_hasOwnership && m_cryptoBuf) - { - Aws::Delete(m_cryptoBuf); - } - } - - void SymmetricCryptoStream::Finalize() - { +#include <aws/core/utils/crypto/CryptoStream.h> + +namespace Aws +{ + namespace Utils + { + namespace Crypto + { + static const char* CLASS_TAG = "Aws::Utils::Crypto::SymmetricCryptoStream"; + + SymmetricCryptoStream::SymmetricCryptoStream(Aws::IStream& src, CipherMode mode, SymmetricCipher& cipher, size_t bufSize) : + Aws::IOStream(m_cryptoBuf = Aws::New<SymmetricCryptoBufSrc>(CLASS_TAG, src, cipher, mode, bufSize)), m_hasOwnership(true) + { + } + + SymmetricCryptoStream::SymmetricCryptoStream(Aws::OStream& sink, CipherMode mode, SymmetricCipher& cipher, size_t bufSize, int16_t blockOffset) : + Aws::IOStream(m_cryptoBuf = Aws::New<SymmetricCryptoBufSink>(CLASS_TAG, sink, cipher, mode, bufSize, blockOffset)), m_hasOwnership(true) + { + } + + SymmetricCryptoStream::SymmetricCryptoStream(Aws::Utils::Crypto::SymmetricCryptoBufSrc& bufSrc) : + Aws::IOStream(&bufSrc), m_cryptoBuf(&bufSrc), m_hasOwnership(false) + { + } + + SymmetricCryptoStream::SymmetricCryptoStream(Aws::Utils::Crypto::SymmetricCryptoBufSink& bufSink) : + Aws::IOStream(&bufSink), m_cryptoBuf(&bufSink), m_hasOwnership(false) + { + } + + SymmetricCryptoStream::~SymmetricCryptoStream() + { + Finalize(); + + if(m_hasOwnership && m_cryptoBuf) + { + Aws::Delete(m_cryptoBuf); + } + } + + void SymmetricCryptoStream::Finalize() + { assert(m_cryptoBuf); - m_cryptoBuf->Finalize(); - } - } - } -}
\ No newline at end of file + m_cryptoBuf->Finalize(); + } + } + } +}
\ No newline at end of file diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/EncryptionMaterials.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/EncryptionMaterials.cpp index d000c86baa..09cd9c0cf7 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/EncryptionMaterials.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/EncryptionMaterials.cpp @@ -2,18 +2,18 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ -#include <aws/core/utils/crypto/EncryptionMaterials.h> - -namespace Aws -{ - namespace Utils - { - namespace Crypto - { - //this is here to force the linker to behave correctly since this is an interface that will need to cross the dll - //boundary. - EncryptionMaterials::~EncryptionMaterials() - {} - } - } -}
\ No newline at end of file +#include <aws/core/utils/crypto/EncryptionMaterials.h> + +namespace Aws +{ + namespace Utils + { + namespace Crypto + { + //this is here to force the linker to behave correctly since this is an interface that will need to cross the dll + //boundary. + EncryptionMaterials::~EncryptionMaterials() + {} + } + } +}
\ No newline at end of file diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/KeyWrapAlgorithm.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/KeyWrapAlgorithm.cpp index b9e098775c..fbe11626f1 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/KeyWrapAlgorithm.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/KeyWrapAlgorithm.cpp @@ -2,67 +2,67 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ -#include <aws/core/utils/crypto/KeyWrapAlgorithm.h> -#include <aws/core/utils/HashingUtils.h> -#include <aws/core/utils/EnumParseOverflowContainer.h> -#include <aws/core/Globals.h> - -using namespace Aws::Utils; - -namespace Aws -{ - namespace Utils - { - namespace Crypto - { - namespace KeyWrapAlgorithmMapper - { - static const int keyWrapAlgorithm_KMS_HASH = HashingUtils::HashString("kms"); +#include <aws/core/utils/crypto/KeyWrapAlgorithm.h> +#include <aws/core/utils/HashingUtils.h> +#include <aws/core/utils/EnumParseOverflowContainer.h> +#include <aws/core/Globals.h> + +using namespace Aws::Utils; + +namespace Aws +{ + namespace Utils + { + namespace Crypto + { + namespace KeyWrapAlgorithmMapper + { + static const int keyWrapAlgorithm_KMS_HASH = HashingUtils::HashString("kms"); static const int keyWrapAlgorithm_KMS_CONTEXT_HASH = HashingUtils::HashString("kms+context"); - static const int keyWrapAlgorithm_KeyWrap_HASH = HashingUtils::HashString("AESWrap"); + static const int keyWrapAlgorithm_KeyWrap_HASH = HashingUtils::HashString("AESWrap"); static const int keyWrapAlgorithm_AES_GCM_HASH = HashingUtils::HashString("AES/GCM"); - - KeyWrapAlgorithm GetKeyWrapAlgorithmForName(const Aws::String& name) - { - int hashcode = HashingUtils::HashString(name.c_str()); - if (hashcode == keyWrapAlgorithm_KMS_HASH) - { - return KeyWrapAlgorithm::KMS; - } + + KeyWrapAlgorithm GetKeyWrapAlgorithmForName(const Aws::String& name) + { + int hashcode = HashingUtils::HashString(name.c_str()); + if (hashcode == keyWrapAlgorithm_KMS_HASH) + { + return KeyWrapAlgorithm::KMS; + } else if (hashcode == keyWrapAlgorithm_KMS_CONTEXT_HASH) { return KeyWrapAlgorithm::KMS_CONTEXT; } - else if (hashcode == keyWrapAlgorithm_KeyWrap_HASH) - { - return KeyWrapAlgorithm::AES_KEY_WRAP; + else if (hashcode == keyWrapAlgorithm_KeyWrap_HASH) + { + return KeyWrapAlgorithm::AES_KEY_WRAP; } else if (hashcode == keyWrapAlgorithm_AES_GCM_HASH) { return KeyWrapAlgorithm::AES_GCM; - } - assert(0); - return KeyWrapAlgorithm::NONE; - } - - Aws::String GetNameForKeyWrapAlgorithm(KeyWrapAlgorithm enumValue) - { - switch (enumValue) - { - case KeyWrapAlgorithm::KMS: - return "kms"; + } + assert(0); + return KeyWrapAlgorithm::NONE; + } + + Aws::String GetNameForKeyWrapAlgorithm(KeyWrapAlgorithm enumValue) + { + switch (enumValue) + { + case KeyWrapAlgorithm::KMS: + return "kms"; case KeyWrapAlgorithm::KMS_CONTEXT: return "kms+context"; - case KeyWrapAlgorithm::AES_KEY_WRAP: - return "AESWrap"; + case KeyWrapAlgorithm::AES_KEY_WRAP: + return "AESWrap"; case KeyWrapAlgorithm::AES_GCM: return "AES/GCM"; - default: - assert(0); - } - return ""; - } - }//namespace KeyWrapAlgorithmMapper - }//namespace Crypto - }//namespace Utils + default: + assert(0); + } + return ""; + } + }//namespace KeyWrapAlgorithmMapper + }//namespace Crypto + }//namespace Utils }//namespace Aws diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/MD5.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/MD5.cpp index bf14ace1ad..177947b743 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/MD5.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/MD5.cpp @@ -2,30 +2,30 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - - -#include <aws/core/utils/crypto/MD5.h> -#include <aws/core/utils/Outcome.h> -#include <aws/core/utils/crypto/Factories.h> - -using namespace Aws::Utils::Crypto; - - -MD5::MD5() : - m_hashImpl(CreateMD5Implementation()) -{ -} - -MD5::~MD5() -{ -} - -HashResult MD5::Calculate(const Aws::String& str) -{ - return m_hashImpl->Calculate(str); -} - -HashResult MD5::Calculate(Aws::IStream& stream) -{ - return m_hashImpl->Calculate(stream); -}
\ No newline at end of file + + +#include <aws/core/utils/crypto/MD5.h> +#include <aws/core/utils/Outcome.h> +#include <aws/core/utils/crypto/Factories.h> + +using namespace Aws::Utils::Crypto; + + +MD5::MD5() : + m_hashImpl(CreateMD5Implementation()) +{ +} + +MD5::~MD5() +{ +} + +HashResult MD5::Calculate(const Aws::String& str) +{ + return m_hashImpl->Calculate(str); +} + +HashResult MD5::Calculate(Aws::IStream& stream) +{ + return m_hashImpl->Calculate(stream); +}
\ No newline at end of file diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Sha256.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Sha256.cpp index 178df00d37..47fbab0207 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Sha256.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Sha256.cpp @@ -2,29 +2,29 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - - -#include <aws/core/utils/crypto/Sha256.h> -#include <aws/core/utils/Outcome.h> -#include <aws/core/utils/crypto/Factories.h> - -using namespace Aws::Utils::Crypto; - -Sha256::Sha256() : - m_hashImpl(CreateSha256Implementation()) -{ -} - -Sha256::~Sha256() -{ -} - -HashResult Sha256::Calculate(const Aws::String& str) -{ - return m_hashImpl->Calculate(str); -} - -HashResult Sha256::Calculate(Aws::IStream& stream) -{ - return m_hashImpl->Calculate(stream); -}
\ No newline at end of file + + +#include <aws/core/utils/crypto/Sha256.h> +#include <aws/core/utils/Outcome.h> +#include <aws/core/utils/crypto/Factories.h> + +using namespace Aws::Utils::Crypto; + +Sha256::Sha256() : + m_hashImpl(CreateSha256Implementation()) +{ +} + +Sha256::~Sha256() +{ +} + +HashResult Sha256::Calculate(const Aws::String& str) +{ + return m_hashImpl->Calculate(str); +} + +HashResult Sha256::Calculate(Aws::IStream& stream) +{ + return m_hashImpl->Calculate(stream); +}
\ No newline at end of file diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Sha256HMAC.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Sha256HMAC.cpp index ecc1f06529..6b16757f77 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Sha256HMAC.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Sha256HMAC.cpp @@ -2,33 +2,33 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - - -#include <aws/core/utils/crypto/Sha256HMAC.h> -#include <aws/core/utils/crypto/Factories.h> -#include <aws/core/utils/Outcome.h> - -namespace Aws -{ -namespace Utils -{ -namespace Crypto -{ - -Sha256HMAC::Sha256HMAC() : - m_hmacImpl(CreateSha256HMACImplementation()) -{ -} - -Sha256HMAC::~Sha256HMAC() -{ -} - -HashResult Sha256HMAC::Calculate(const Aws::Utils::ByteBuffer& toSign, const Aws::Utils::ByteBuffer& secret) -{ - return m_hmacImpl->Calculate(toSign, secret); -} - -} // namespace Crypto -} // namespace Utils -} // namespace Aws
\ No newline at end of file + + +#include <aws/core/utils/crypto/Sha256HMAC.h> +#include <aws/core/utils/crypto/Factories.h> +#include <aws/core/utils/Outcome.h> + +namespace Aws +{ +namespace Utils +{ +namespace Crypto +{ + +Sha256HMAC::Sha256HMAC() : + m_hmacImpl(CreateSha256HMACImplementation()) +{ +} + +Sha256HMAC::~Sha256HMAC() +{ +} + +HashResult Sha256HMAC::Calculate(const Aws::Utils::ByteBuffer& toSign, const Aws::Utils::ByteBuffer& secret) +{ + return m_hmacImpl->Calculate(toSign, secret); +} + +} // namespace Crypto +} // namespace Utils +} // namespace Aws
\ No newline at end of file diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/factory/Factories.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/factory/Factories.cpp index bff0382241..fcecdd1c40 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/factory/Factories.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/factory/Factories.cpp @@ -2,51 +2,51 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - - -#include <aws/core/utils/crypto/Factories.h> -#include <aws/core/utils/crypto/Hash.h> -#include <aws/core/utils/crypto/HMAC.h> - -#if ENABLE_BCRYPT_ENCRYPTION + + +#include <aws/core/utils/crypto/Factories.h> +#include <aws/core/utils/crypto/Hash.h> +#include <aws/core/utils/crypto/HMAC.h> + +#if ENABLE_BCRYPT_ENCRYPTION #error #include <aws/core/utils/crypto/bcrypt/CryptoImpl.h> -#elif ENABLE_OPENSSL_ENCRYPTION - #include <aws/core/utils/crypto/openssl/CryptoImpl.h> -#elif ENABLE_COMMONCRYPTO_ENCRYPTION +#elif ENABLE_OPENSSL_ENCRYPTION + #include <aws/core/utils/crypto/openssl/CryptoImpl.h> +#elif ENABLE_COMMONCRYPTO_ENCRYPTION #error #include <aws/core/utils/crypto/commoncrypto/CryptoImpl.h> - #include <aws/core/utils/logging/LogMacros.h> -#else - // if you don't have any encryption you still need to pull in the interface definitions - #include <aws/core/utils/crypto/Hash.h> - #include <aws/core/utils/crypto/HMAC.h> - #include <aws/core/utils/crypto/Cipher.h> - #include <aws/core/utils/crypto/SecureRandom.h> - #define NO_ENCRYPTION -#endif - -using namespace Aws::Utils; -using namespace Aws::Utils::Crypto; - -static const char *s_allocationTag = "CryptoFactory"; - + #include <aws/core/utils/logging/LogMacros.h> +#else + // if you don't have any encryption you still need to pull in the interface definitions + #include <aws/core/utils/crypto/Hash.h> + #include <aws/core/utils/crypto/HMAC.h> + #include <aws/core/utils/crypto/Cipher.h> + #include <aws/core/utils/crypto/SecureRandom.h> + #define NO_ENCRYPTION +#endif + +using namespace Aws::Utils; +using namespace Aws::Utils::Crypto; + +static const char *s_allocationTag = "CryptoFactory"; + static std::shared_ptr<HashFactory>& GetMD5Factory() { static std::shared_ptr<HashFactory> s_MD5Factory(nullptr); return s_MD5Factory; } - + static std::shared_ptr<HashFactory>& GetSha256Factory() { static std::shared_ptr<HashFactory> s_Sha256Factory(nullptr); return s_Sha256Factory; } - + static std::shared_ptr<HMACFactory>& GetSha256HMACFactory() { static std::shared_ptr<HMACFactory> s_Sha256HMACFactory(nullptr); return s_Sha256HMACFactory; } - + static std::shared_ptr<SymmetricCipherFactory>& GetAES_CBCFactory() { static std::shared_ptr<SymmetricCipherFactory> s_AES_CBCFactory(nullptr); @@ -83,323 +83,323 @@ static std::shared_ptr<SecureRandomBytes>& GetSecureRandom() return s_SecureRandom; } -static bool s_InitCleanupOpenSSLFlag(false); - -class DefaultMD5Factory : public HashFactory -{ -public: - std::shared_ptr<Hash> CreateImplementation() const override - { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared<MD5BcryptImpl>(s_allocationTag); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared<MD5OpenSSLImpl>(s_allocationTag); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared<MD5CommonCryptoImpl>(s_allocationTag); -#else - return nullptr; -#endif - } - - /** - * Opportunity to make any static initialization calls you need to make. - * Will only be called once. - */ - void InitStaticState() override - { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state); - } -#endif - } - - /** - * Opportunity to make any static cleanup calls you need to make. - * will only be called at the end of the application. - */ - void CleanupStaticState() override - { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state); - } -#endif - } -}; - -class DefaultSHA256Factory : public HashFactory -{ -public: - std::shared_ptr<Hash> CreateImplementation() const override - { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared<Sha256BcryptImpl>(s_allocationTag); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared<Sha256OpenSSLImpl>(s_allocationTag); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared<Sha256CommonCryptoImpl>(s_allocationTag); -#else - return nullptr; -#endif - } - - /** - * Opportunity to make any static initialization calls you need to make. - * Will only be called once. - */ - void InitStaticState() override - { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state); - } -#endif - } - - /** - * Opportunity to make any static cleanup calls you need to make. - * will only be called at the end of the application. - */ - void CleanupStaticState() override - { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state); - } -#endif - } -}; - -class DefaultSHA256HmacFactory : public HMACFactory -{ -public: - std::shared_ptr<Aws::Utils::Crypto::HMAC> CreateImplementation() const override - { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared<Sha256HMACBcryptImpl>(s_allocationTag); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared<Sha256HMACOpenSSLImpl>(s_allocationTag); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared<Sha256HMACCommonCryptoImpl>(s_allocationTag); -#else - return nullptr; -#endif - } - - /** - * Opportunity to make any static initialization calls you need to make. - * Will only be called once. - */ - void InitStaticState() override - { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state); - } -#endif - } - - /** - * Opportunity to make any static cleanup calls you need to make. - * will only be called at the end of the application. - */ - void CleanupStaticState() override - { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state); - } -#endif - } -}; - - -class DefaultAES_CBCFactory : public SymmetricCipherFactory -{ -public: - std::shared_ptr<SymmetricCipher> CreateImplementation(const CryptoBuffer& key) const override - { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared<AES_CBC_Cipher_BCrypt>(s_allocationTag, key); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared<AES_CBC_Cipher_OpenSSL>(s_allocationTag, key); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared<AES_CBC_Cipher_CommonCrypto>(s_allocationTag, key); -#else - AWS_UNREFERENCED_PARAM(key); - return nullptr; -#endif - } - /** - * Factory method. Returns cipher implementation. See the SymmetricCipher class for more details. - */ +static bool s_InitCleanupOpenSSLFlag(false); + +class DefaultMD5Factory : public HashFactory +{ +public: + std::shared_ptr<Hash> CreateImplementation() const override + { +#if ENABLE_BCRYPT_ENCRYPTION + return Aws::MakeShared<MD5BcryptImpl>(s_allocationTag); +#elif ENABLE_OPENSSL_ENCRYPTION + return Aws::MakeShared<MD5OpenSSLImpl>(s_allocationTag); +#elif ENABLE_COMMONCRYPTO_ENCRYPTION + return Aws::MakeShared<MD5CommonCryptoImpl>(s_allocationTag); +#else + return nullptr; +#endif + } + + /** + * Opportunity to make any static initialization calls you need to make. + * Will only be called once. + */ + void InitStaticState() override + { +#if ENABLE_OPENSSL_ENCRYPTION + if(s_InitCleanupOpenSSLFlag) + { + OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state); + } +#endif + } + + /** + * Opportunity to make any static cleanup calls you need to make. + * will only be called at the end of the application. + */ + void CleanupStaticState() override + { +#if ENABLE_OPENSSL_ENCRYPTION + if(s_InitCleanupOpenSSLFlag) + { + OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state); + } +#endif + } +}; + +class DefaultSHA256Factory : public HashFactory +{ +public: + std::shared_ptr<Hash> CreateImplementation() const override + { +#if ENABLE_BCRYPT_ENCRYPTION + return Aws::MakeShared<Sha256BcryptImpl>(s_allocationTag); +#elif ENABLE_OPENSSL_ENCRYPTION + return Aws::MakeShared<Sha256OpenSSLImpl>(s_allocationTag); +#elif ENABLE_COMMONCRYPTO_ENCRYPTION + return Aws::MakeShared<Sha256CommonCryptoImpl>(s_allocationTag); +#else + return nullptr; +#endif + } + + /** + * Opportunity to make any static initialization calls you need to make. + * Will only be called once. + */ + void InitStaticState() override + { +#if ENABLE_OPENSSL_ENCRYPTION + if(s_InitCleanupOpenSSLFlag) + { + OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state); + } +#endif + } + + /** + * Opportunity to make any static cleanup calls you need to make. + * will only be called at the end of the application. + */ + void CleanupStaticState() override + { +#if ENABLE_OPENSSL_ENCRYPTION + if(s_InitCleanupOpenSSLFlag) + { + OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state); + } +#endif + } +}; + +class DefaultSHA256HmacFactory : public HMACFactory +{ +public: + std::shared_ptr<Aws::Utils::Crypto::HMAC> CreateImplementation() const override + { +#if ENABLE_BCRYPT_ENCRYPTION + return Aws::MakeShared<Sha256HMACBcryptImpl>(s_allocationTag); +#elif ENABLE_OPENSSL_ENCRYPTION + return Aws::MakeShared<Sha256HMACOpenSSLImpl>(s_allocationTag); +#elif ENABLE_COMMONCRYPTO_ENCRYPTION + return Aws::MakeShared<Sha256HMACCommonCryptoImpl>(s_allocationTag); +#else + return nullptr; +#endif + } + + /** + * Opportunity to make any static initialization calls you need to make. + * Will only be called once. + */ + void InitStaticState() override + { +#if ENABLE_OPENSSL_ENCRYPTION + if(s_InitCleanupOpenSSLFlag) + { + OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state); + } +#endif + } + + /** + * Opportunity to make any static cleanup calls you need to make. + * will only be called at the end of the application. + */ + void CleanupStaticState() override + { +#if ENABLE_OPENSSL_ENCRYPTION + if(s_InitCleanupOpenSSLFlag) + { + OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state); + } +#endif + } +}; + + +class DefaultAES_CBCFactory : public SymmetricCipherFactory +{ +public: + std::shared_ptr<SymmetricCipher> CreateImplementation(const CryptoBuffer& key) const override + { +#if ENABLE_BCRYPT_ENCRYPTION + return Aws::MakeShared<AES_CBC_Cipher_BCrypt>(s_allocationTag, key); +#elif ENABLE_OPENSSL_ENCRYPTION + return Aws::MakeShared<AES_CBC_Cipher_OpenSSL>(s_allocationTag, key); +#elif ENABLE_COMMONCRYPTO_ENCRYPTION + return Aws::MakeShared<AES_CBC_Cipher_CommonCrypto>(s_allocationTag, key); +#else + AWS_UNREFERENCED_PARAM(key); + return nullptr; +#endif + } + /** + * Factory method. Returns cipher implementation. See the SymmetricCipher class for more details. + */ std::shared_ptr<SymmetricCipher> CreateImplementation(const CryptoBuffer& key, const CryptoBuffer& iv, const CryptoBuffer&, const CryptoBuffer&) const override - { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared<AES_CBC_Cipher_BCrypt>(s_allocationTag, key, iv); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared<AES_CBC_Cipher_OpenSSL>(s_allocationTag, key, iv); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared<AES_CBC_Cipher_CommonCrypto>(s_allocationTag, key, iv); -#else - AWS_UNREFERENCED_PARAM(key); - AWS_UNREFERENCED_PARAM(iv); - - return nullptr; -#endif - } - /** - * Factory method. Returns cipher implementation. See the SymmetricCipher class for more details. - */ + { +#if ENABLE_BCRYPT_ENCRYPTION + return Aws::MakeShared<AES_CBC_Cipher_BCrypt>(s_allocationTag, key, iv); +#elif ENABLE_OPENSSL_ENCRYPTION + return Aws::MakeShared<AES_CBC_Cipher_OpenSSL>(s_allocationTag, key, iv); +#elif ENABLE_COMMONCRYPTO_ENCRYPTION + return Aws::MakeShared<AES_CBC_Cipher_CommonCrypto>(s_allocationTag, key, iv); +#else + AWS_UNREFERENCED_PARAM(key); + AWS_UNREFERENCED_PARAM(iv); + + return nullptr; +#endif + } + /** + * Factory method. Returns cipher implementation. See the SymmetricCipher class for more details. + */ std::shared_ptr<SymmetricCipher> CreateImplementation(CryptoBuffer&& key, CryptoBuffer&& iv, CryptoBuffer&&, CryptoBuffer&&) const override - { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared<AES_CBC_Cipher_BCrypt>(s_allocationTag, key, iv); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared<AES_CBC_Cipher_OpenSSL>(s_allocationTag, key, iv); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared<AES_CBC_Cipher_CommonCrypto>(s_allocationTag, key, iv); -#else - AWS_UNREFERENCED_PARAM(key); - AWS_UNREFERENCED_PARAM(iv); - - return nullptr; -#endif - } - - /** - * Opportunity to make any static initialization calls you need to make. - * Will only be called once. - */ - void InitStaticState() override - { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state); - } -#endif - } - - /** - * Opportunity to make any static cleanup calls you need to make. - * will only be called at the end of the application. - */ - void CleanupStaticState() override - { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state); - } -#endif - } -}; - -class DefaultAES_CTRFactory : public SymmetricCipherFactory -{ -public: - std::shared_ptr<SymmetricCipher> CreateImplementation(const CryptoBuffer& key) const override - { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared<AES_CTR_Cipher_BCrypt>(s_allocationTag, key); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared<AES_CTR_Cipher_OpenSSL>(s_allocationTag, key); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared<AES_CTR_Cipher_CommonCrypto>(s_allocationTag, key); -#else - AWS_UNREFERENCED_PARAM(key); - return nullptr; -#endif - } - /** - * Factory method. Returns cipher implementation. See the SymmetricCipher class for more details. - */ + { +#if ENABLE_BCRYPT_ENCRYPTION + return Aws::MakeShared<AES_CBC_Cipher_BCrypt>(s_allocationTag, key, iv); +#elif ENABLE_OPENSSL_ENCRYPTION + return Aws::MakeShared<AES_CBC_Cipher_OpenSSL>(s_allocationTag, key, iv); +#elif ENABLE_COMMONCRYPTO_ENCRYPTION + return Aws::MakeShared<AES_CBC_Cipher_CommonCrypto>(s_allocationTag, key, iv); +#else + AWS_UNREFERENCED_PARAM(key); + AWS_UNREFERENCED_PARAM(iv); + + return nullptr; +#endif + } + + /** + * Opportunity to make any static initialization calls you need to make. + * Will only be called once. + */ + void InitStaticState() override + { +#if ENABLE_OPENSSL_ENCRYPTION + if(s_InitCleanupOpenSSLFlag) + { + OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state); + } +#endif + } + + /** + * Opportunity to make any static cleanup calls you need to make. + * will only be called at the end of the application. + */ + void CleanupStaticState() override + { +#if ENABLE_OPENSSL_ENCRYPTION + if(s_InitCleanupOpenSSLFlag) + { + OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state); + } +#endif + } +}; + +class DefaultAES_CTRFactory : public SymmetricCipherFactory +{ +public: + std::shared_ptr<SymmetricCipher> CreateImplementation(const CryptoBuffer& key) const override + { +#if ENABLE_BCRYPT_ENCRYPTION + return Aws::MakeShared<AES_CTR_Cipher_BCrypt>(s_allocationTag, key); +#elif ENABLE_OPENSSL_ENCRYPTION + return Aws::MakeShared<AES_CTR_Cipher_OpenSSL>(s_allocationTag, key); +#elif ENABLE_COMMONCRYPTO_ENCRYPTION + return Aws::MakeShared<AES_CTR_Cipher_CommonCrypto>(s_allocationTag, key); +#else + AWS_UNREFERENCED_PARAM(key); + return nullptr; +#endif + } + /** + * Factory method. Returns cipher implementation. See the SymmetricCipher class for more details. + */ std::shared_ptr<SymmetricCipher> CreateImplementation(const CryptoBuffer& key, const CryptoBuffer& iv, const CryptoBuffer&, const CryptoBuffer&) const override - { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared<AES_CTR_Cipher_BCrypt>(s_allocationTag, key, iv); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared<AES_CTR_Cipher_OpenSSL>(s_allocationTag, key, iv); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared<AES_CTR_Cipher_CommonCrypto>(s_allocationTag, key, iv); -#else - AWS_UNREFERENCED_PARAM(key); - AWS_UNREFERENCED_PARAM(iv); - - return nullptr; -#endif - } - /** - * Factory method. Returns cipher implementation. See the SymmetricCipher class for more details. - */ + { +#if ENABLE_BCRYPT_ENCRYPTION + return Aws::MakeShared<AES_CTR_Cipher_BCrypt>(s_allocationTag, key, iv); +#elif ENABLE_OPENSSL_ENCRYPTION + return Aws::MakeShared<AES_CTR_Cipher_OpenSSL>(s_allocationTag, key, iv); +#elif ENABLE_COMMONCRYPTO_ENCRYPTION + return Aws::MakeShared<AES_CTR_Cipher_CommonCrypto>(s_allocationTag, key, iv); +#else + AWS_UNREFERENCED_PARAM(key); + AWS_UNREFERENCED_PARAM(iv); + + return nullptr; +#endif + } + /** + * Factory method. Returns cipher implementation. See the SymmetricCipher class for more details. + */ std::shared_ptr<SymmetricCipher> CreateImplementation(CryptoBuffer&& key, CryptoBuffer&& iv, CryptoBuffer&&, CryptoBuffer&&) const override - { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared<AES_CTR_Cipher_BCrypt>(s_allocationTag, key, iv); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared<AES_CTR_Cipher_OpenSSL>(s_allocationTag, key, iv); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared<AES_CTR_Cipher_CommonCrypto>(s_allocationTag, key, iv); -#else - AWS_UNREFERENCED_PARAM(key); - AWS_UNREFERENCED_PARAM(iv); - - return nullptr; -#endif - } - - /** - * Opportunity to make any static initialization calls you need to make. - * Will only be called once. - */ - void InitStaticState() override - { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state); - } -#endif - } - - /** - * Opportunity to make any static cleanup calls you need to make. - * will only be called at the end of the application. - */ - void CleanupStaticState() override - { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state); - } -#endif - } -}; - -class DefaultAES_GCMFactory : public SymmetricCipherFactory -{ -public: - std::shared_ptr<SymmetricCipher> CreateImplementation(const CryptoBuffer& key) const override - { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared<AES_GCM_Cipher_BCrypt>(s_allocationTag, key); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared<AES_GCM_Cipher_OpenSSL>(s_allocationTag, key); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION + { +#if ENABLE_BCRYPT_ENCRYPTION + return Aws::MakeShared<AES_CTR_Cipher_BCrypt>(s_allocationTag, key, iv); +#elif ENABLE_OPENSSL_ENCRYPTION + return Aws::MakeShared<AES_CTR_Cipher_OpenSSL>(s_allocationTag, key, iv); +#elif ENABLE_COMMONCRYPTO_ENCRYPTION + return Aws::MakeShared<AES_CTR_Cipher_CommonCrypto>(s_allocationTag, key, iv); +#else + AWS_UNREFERENCED_PARAM(key); + AWS_UNREFERENCED_PARAM(iv); + + return nullptr; +#endif + } + + /** + * Opportunity to make any static initialization calls you need to make. + * Will only be called once. + */ + void InitStaticState() override + { +#if ENABLE_OPENSSL_ENCRYPTION + if(s_InitCleanupOpenSSLFlag) + { + OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state); + } +#endif + } + + /** + * Opportunity to make any static cleanup calls you need to make. + * will only be called at the end of the application. + */ + void CleanupStaticState() override + { +#if ENABLE_OPENSSL_ENCRYPTION + if(s_InitCleanupOpenSSLFlag) + { + OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state); + } +#endif + } +}; + +class DefaultAES_GCMFactory : public SymmetricCipherFactory +{ +public: + std::shared_ptr<SymmetricCipher> CreateImplementation(const CryptoBuffer& key) const override + { +#if ENABLE_BCRYPT_ENCRYPTION + return Aws::MakeShared<AES_GCM_Cipher_BCrypt>(s_allocationTag, key); +#elif ENABLE_OPENSSL_ENCRYPTION + return Aws::MakeShared<AES_GCM_Cipher_OpenSSL>(s_allocationTag, key); +#elif ENABLE_COMMONCRYPTO_ENCRYPTION return Aws::MakeShared<AES_GCM_Cipher_CommonCrypto>(s_allocationTag, key); #else - AWS_UNREFERENCED_PARAM(key); + AWS_UNREFERENCED_PARAM(key); - return nullptr; + return nullptr; #endif } @@ -411,464 +411,464 @@ public: return Aws::MakeShared<AES_GCM_Cipher_OpenSSL>(s_allocationTag, key, aad); #elif ENABLE_COMMONCRYPTO_ENCRYPTION return Aws::MakeShared<AES_GCM_Cipher_CommonCrypto>(s_allocationTag, key, aad); -#else - AWS_UNREFERENCED_PARAM(key); +#else + AWS_UNREFERENCED_PARAM(key); AWS_UNREFERENCED_PARAM(aad); - return nullptr; -#endif - } + return nullptr; +#endif + } - /** - * Factory method. Returns cipher implementation. See the SymmetricCipher class for more details. - */ + /** + * Factory method. Returns cipher implementation. See the SymmetricCipher class for more details. + */ std::shared_ptr<SymmetricCipher> CreateImplementation(const CryptoBuffer& key, const CryptoBuffer& iv, const CryptoBuffer& tag, const CryptoBuffer& aad) const override - { -#if ENABLE_BCRYPT_ENCRYPTION + { +#if ENABLE_BCRYPT_ENCRYPTION return Aws::MakeShared<AES_GCM_Cipher_BCrypt>(s_allocationTag, key, iv, tag, aad); -#elif ENABLE_OPENSSL_ENCRYPTION +#elif ENABLE_OPENSSL_ENCRYPTION return Aws::MakeShared<AES_GCM_Cipher_OpenSSL>(s_allocationTag, key, iv, tag, aad); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION +#elif ENABLE_COMMONCRYPTO_ENCRYPTION return Aws::MakeShared<AES_GCM_Cipher_CommonCrypto>(s_allocationTag, key, iv, tag, aad); -#else - AWS_UNREFERENCED_PARAM(key); - AWS_UNREFERENCED_PARAM(iv); - AWS_UNREFERENCED_PARAM(tag); +#else + AWS_UNREFERENCED_PARAM(key); + AWS_UNREFERENCED_PARAM(iv); + AWS_UNREFERENCED_PARAM(tag); AWS_UNREFERENCED_PARAM(aad); - return nullptr; -#endif - } - /** - * Factory method. Returns cipher implementation. See the SymmetricCipher class for more details. - */ + return nullptr; +#endif + } + /** + * Factory method. Returns cipher implementation. See the SymmetricCipher class for more details. + */ std::shared_ptr<SymmetricCipher> CreateImplementation(CryptoBuffer&& key, CryptoBuffer&& iv, CryptoBuffer&& tag, CryptoBuffer&& aad) const override - { -#if ENABLE_BCRYPT_ENCRYPTION + { +#if ENABLE_BCRYPT_ENCRYPTION return Aws::MakeShared<AES_GCM_Cipher_BCrypt>(s_allocationTag, std::move(key), std::move(iv), std::move(tag), std::move(aad)); -#elif ENABLE_OPENSSL_ENCRYPTION +#elif ENABLE_OPENSSL_ENCRYPTION return Aws::MakeShared<AES_GCM_Cipher_OpenSSL>(s_allocationTag, std::move(key), std::move(iv), std::move(tag), std::move(aad)); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION +#elif ENABLE_COMMONCRYPTO_ENCRYPTION return Aws::MakeShared<AES_GCM_Cipher_CommonCrypto>(s_allocationTag, std::move(key), std::move(iv), std::move(tag), std::move(aad)); -#else - AWS_UNREFERENCED_PARAM(key); - AWS_UNREFERENCED_PARAM(iv); - AWS_UNREFERENCED_PARAM(tag); +#else + AWS_UNREFERENCED_PARAM(key); + AWS_UNREFERENCED_PARAM(iv); + AWS_UNREFERENCED_PARAM(tag); AWS_UNREFERENCED_PARAM(aad); - return nullptr; -#endif - } - - /** - * Opportunity to make any static initialization calls you need to make. - * Will only be called once. - */ - void InitStaticState() override - { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state); - } -#endif - } - - /** - * Opportunity to make any static cleanup calls you need to make. - * will only be called at the end of the application. - */ - void CleanupStaticState() override - { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state); - } -#endif - } -}; - -class DefaultAES_KeyWrapFactory : public SymmetricCipherFactory -{ -public: - std::shared_ptr<SymmetricCipher> CreateImplementation(const CryptoBuffer& key) const override - { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared<AES_KeyWrap_Cipher_BCrypt>(s_allocationTag, key); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared<AES_KeyWrap_Cipher_OpenSSL>(s_allocationTag, key); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared<AES_KeyWrap_Cipher_CommonCrypto>(s_allocationTag, key); -#else - AWS_UNREFERENCED_PARAM(key); - return nullptr; -#endif - } - /** - * Factory method. Returns cipher implementation. See the SymmetricCipher class for more details. - */ + return nullptr; +#endif + } + + /** + * Opportunity to make any static initialization calls you need to make. + * Will only be called once. + */ + void InitStaticState() override + { +#if ENABLE_OPENSSL_ENCRYPTION + if(s_InitCleanupOpenSSLFlag) + { + OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state); + } +#endif + } + + /** + * Opportunity to make any static cleanup calls you need to make. + * will only be called at the end of the application. + */ + void CleanupStaticState() override + { +#if ENABLE_OPENSSL_ENCRYPTION + if(s_InitCleanupOpenSSLFlag) + { + OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state); + } +#endif + } +}; + +class DefaultAES_KeyWrapFactory : public SymmetricCipherFactory +{ +public: + std::shared_ptr<SymmetricCipher> CreateImplementation(const CryptoBuffer& key) const override + { +#if ENABLE_BCRYPT_ENCRYPTION + return Aws::MakeShared<AES_KeyWrap_Cipher_BCrypt>(s_allocationTag, key); +#elif ENABLE_OPENSSL_ENCRYPTION + return Aws::MakeShared<AES_KeyWrap_Cipher_OpenSSL>(s_allocationTag, key); +#elif ENABLE_COMMONCRYPTO_ENCRYPTION + return Aws::MakeShared<AES_KeyWrap_Cipher_CommonCrypto>(s_allocationTag, key); +#else + AWS_UNREFERENCED_PARAM(key); + return nullptr; +#endif + } + /** + * Factory method. Returns cipher implementation. See the SymmetricCipher class for more details. + */ std::shared_ptr<SymmetricCipher> CreateImplementation(const CryptoBuffer& key, const CryptoBuffer& iv, const CryptoBuffer& tag, const CryptoBuffer&) const override - { - AWS_UNREFERENCED_PARAM(key); - AWS_UNREFERENCED_PARAM(iv); - AWS_UNREFERENCED_PARAM(tag); - return nullptr; - } - /** - * Factory method. Returns cipher implementation. See the SymmetricCipher class for more details. - */ + { + AWS_UNREFERENCED_PARAM(key); + AWS_UNREFERENCED_PARAM(iv); + AWS_UNREFERENCED_PARAM(tag); + return nullptr; + } + /** + * Factory method. Returns cipher implementation. See the SymmetricCipher class for more details. + */ std::shared_ptr<SymmetricCipher> CreateImplementation(CryptoBuffer&& key, CryptoBuffer&& iv, CryptoBuffer&& tag, CryptoBuffer&&) const override - { - AWS_UNREFERENCED_PARAM(key); - AWS_UNREFERENCED_PARAM(iv); - AWS_UNREFERENCED_PARAM(tag); - return nullptr; - } - - /** - * Opportunity to make any static initialization calls you need to make. - * Will only be called once. - */ - void InitStaticState() override - { -#if ENABLE_OPENSSL_ENCRYPTION - if (s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state); - } -#endif - } - - /** - * Opportunity to make any static cleanup calls you need to make. - * will only be called at the end of the application. - */ - void CleanupStaticState() override - { -#if ENABLE_OPENSSL_ENCRYPTION - if (s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state); - } -#endif - } -}; - -class DefaultSecureRandFactory : public SecureRandomFactory -{ - /** - * Factory method. Returns SecureRandom implementation. - */ - std::shared_ptr<SecureRandomBytes> CreateImplementation() const override - { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared<SecureRandomBytes_BCrypt>(s_allocationTag); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared<SecureRandomBytes_OpenSSLImpl>(s_allocationTag); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared<SecureRandomBytes_CommonCrypto>(s_allocationTag); -#else - return nullptr; -#endif - } - - /** - * Opportunity to make any static initialization calls you need to make. - * Will only be called once. - */ - void InitStaticState() override - { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state); - } -#endif - } - - /** - * Opportunity to make any static cleanup calls you need to make. - * will only be called at the end of the application. - */ - void CleanupStaticState() override - { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state); - } -#endif - } -}; - -void Aws::Utils::Crypto::SetInitCleanupOpenSSLFlag(bool initCleanupFlag) -{ - s_InitCleanupOpenSSLFlag = initCleanupFlag; -} - -void Aws::Utils::Crypto::InitCrypto() -{ + { + AWS_UNREFERENCED_PARAM(key); + AWS_UNREFERENCED_PARAM(iv); + AWS_UNREFERENCED_PARAM(tag); + return nullptr; + } + + /** + * Opportunity to make any static initialization calls you need to make. + * Will only be called once. + */ + void InitStaticState() override + { +#if ENABLE_OPENSSL_ENCRYPTION + if (s_InitCleanupOpenSSLFlag) + { + OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state); + } +#endif + } + + /** + * Opportunity to make any static cleanup calls you need to make. + * will only be called at the end of the application. + */ + void CleanupStaticState() override + { +#if ENABLE_OPENSSL_ENCRYPTION + if (s_InitCleanupOpenSSLFlag) + { + OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state); + } +#endif + } +}; + +class DefaultSecureRandFactory : public SecureRandomFactory +{ + /** + * Factory method. Returns SecureRandom implementation. + */ + std::shared_ptr<SecureRandomBytes> CreateImplementation() const override + { +#if ENABLE_BCRYPT_ENCRYPTION + return Aws::MakeShared<SecureRandomBytes_BCrypt>(s_allocationTag); +#elif ENABLE_OPENSSL_ENCRYPTION + return Aws::MakeShared<SecureRandomBytes_OpenSSLImpl>(s_allocationTag); +#elif ENABLE_COMMONCRYPTO_ENCRYPTION + return Aws::MakeShared<SecureRandomBytes_CommonCrypto>(s_allocationTag); +#else + return nullptr; +#endif + } + + /** + * Opportunity to make any static initialization calls you need to make. + * Will only be called once. + */ + void InitStaticState() override + { +#if ENABLE_OPENSSL_ENCRYPTION + if(s_InitCleanupOpenSSLFlag) + { + OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state); + } +#endif + } + + /** + * Opportunity to make any static cleanup calls you need to make. + * will only be called at the end of the application. + */ + void CleanupStaticState() override + { +#if ENABLE_OPENSSL_ENCRYPTION + if(s_InitCleanupOpenSSLFlag) + { + OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state); + } +#endif + } +}; + +void Aws::Utils::Crypto::SetInitCleanupOpenSSLFlag(bool initCleanupFlag) +{ + s_InitCleanupOpenSSLFlag = initCleanupFlag; +} + +void Aws::Utils::Crypto::InitCrypto() +{ if(GetMD5Factory()) - { + { GetMD5Factory()->InitStaticState(); - } - else - { + } + else + { GetMD5Factory() = Aws::MakeShared<DefaultMD5Factory>(s_allocationTag); GetMD5Factory()->InitStaticState(); - } - + } + if(GetSha256Factory()) - { + { GetSha256Factory()->InitStaticState(); - } - else - { + } + else + { GetSha256Factory() = Aws::MakeShared<DefaultSHA256Factory>(s_allocationTag); GetSha256Factory()->InitStaticState(); - } - + } + if(GetSha256HMACFactory()) - { + { GetSha256HMACFactory()->InitStaticState(); - } - else - { + } + else + { GetSha256HMACFactory() = Aws::MakeShared<DefaultSHA256HmacFactory>(s_allocationTag); GetSha256HMACFactory()->InitStaticState(); - } - + } + if(GetAES_CBCFactory()) - { + { GetAES_CBCFactory()->InitStaticState(); - } - else - { + } + else + { GetAES_CBCFactory() = Aws::MakeShared<DefaultAES_CBCFactory>(s_allocationTag); GetAES_CBCFactory()->InitStaticState(); - } - + } + if(GetAES_CTRFactory()) - { + { GetAES_CTRFactory()->InitStaticState(); - } - else - { + } + else + { GetAES_CTRFactory() = Aws::MakeShared<DefaultAES_CTRFactory>(s_allocationTag); GetAES_CTRFactory()->InitStaticState(); - } - + } + if(GetAES_GCMFactory()) - { + { GetAES_GCMFactory()->InitStaticState(); - } - else - { + } + else + { GetAES_GCMFactory() = Aws::MakeShared<DefaultAES_GCMFactory>(s_allocationTag); GetAES_GCMFactory()->InitStaticState(); - } - + } + if (!GetAES_KeyWrapFactory()) - { + { GetAES_KeyWrapFactory() = Aws::MakeShared<DefaultAES_KeyWrapFactory>(s_allocationTag); - } + } GetAES_KeyWrapFactory()->InitStaticState(); - + if(GetSecureRandomFactory()) - { + { GetSecureRandomFactory()->InitStaticState(); - } - else - { + } + else + { GetSecureRandomFactory() = Aws::MakeShared<DefaultSecureRandFactory>(s_allocationTag); GetSecureRandomFactory()->InitStaticState(); } GetSecureRandom() = GetSecureRandomFactory()->CreateImplementation(); -} - -void Aws::Utils::Crypto::CleanupCrypto() -{ +} + +void Aws::Utils::Crypto::CleanupCrypto() +{ if(GetMD5Factory()) - { + { GetMD5Factory()->CleanupStaticState(); GetMD5Factory() = nullptr; - } - + } + if(GetSha256Factory()) - { + { GetSha256Factory()->CleanupStaticState(); GetSha256Factory() = nullptr; - } - + } + if(GetSha256HMACFactory()) - { + { GetSha256HMACFactory()->CleanupStaticState(); GetSha256HMACFactory() = nullptr; - } - + } + if(GetAES_CBCFactory()) - { + { GetAES_CBCFactory()->CleanupStaticState(); GetAES_CBCFactory() = nullptr; - } - + } + if(GetAES_CTRFactory()) - { + { GetAES_CTRFactory()->CleanupStaticState(); GetAES_CTRFactory() = nullptr; - } - + } + if(GetAES_GCMFactory()) - { + { GetAES_GCMFactory()->CleanupStaticState(); GetAES_GCMFactory() = nullptr; - } - + } + if(GetAES_KeyWrapFactory()) - { + { GetAES_KeyWrapFactory()->CleanupStaticState(); GetAES_KeyWrapFactory() = nullptr; - } - + } + if(GetSecureRandomFactory()) - { + { GetSecureRandom() = nullptr; GetSecureRandomFactory()->CleanupStaticState(); GetSecureRandomFactory() = nullptr; } -} - -void Aws::Utils::Crypto::SetMD5Factory(const std::shared_ptr<HashFactory>& factory) -{ +} + +void Aws::Utils::Crypto::SetMD5Factory(const std::shared_ptr<HashFactory>& factory) +{ GetMD5Factory() = factory; -} - -void Aws::Utils::Crypto::SetSha256Factory(const std::shared_ptr<HashFactory>& factory) -{ +} + +void Aws::Utils::Crypto::SetSha256Factory(const std::shared_ptr<HashFactory>& factory) +{ GetSha256Factory() = factory; -} - -void Aws::Utils::Crypto::SetSha256HMACFactory(const std::shared_ptr<HMACFactory>& factory) -{ +} + +void Aws::Utils::Crypto::SetSha256HMACFactory(const std::shared_ptr<HMACFactory>& factory) +{ GetSha256HMACFactory() = factory; -} - -void Aws::Utils::Crypto::SetAES_CBCFactory(const std::shared_ptr<SymmetricCipherFactory>& factory) -{ +} + +void Aws::Utils::Crypto::SetAES_CBCFactory(const std::shared_ptr<SymmetricCipherFactory>& factory) +{ GetAES_CBCFactory() = factory; -} - -void Aws::Utils::Crypto::SetAES_CTRFactory(const std::shared_ptr<SymmetricCipherFactory>& factory) -{ +} + +void Aws::Utils::Crypto::SetAES_CTRFactory(const std::shared_ptr<SymmetricCipherFactory>& factory) +{ GetAES_CTRFactory() = factory; -} - -void Aws::Utils::Crypto::SetAES_GCMFactory(const std::shared_ptr<SymmetricCipherFactory>& factory) -{ +} + +void Aws::Utils::Crypto::SetAES_GCMFactory(const std::shared_ptr<SymmetricCipherFactory>& factory) +{ GetAES_GCMFactory() = factory; -} - -void Aws::Utils::Crypto::SetAES_KeyWrapFactory(const std::shared_ptr<SymmetricCipherFactory>& factory) -{ +} + +void Aws::Utils::Crypto::SetAES_KeyWrapFactory(const std::shared_ptr<SymmetricCipherFactory>& factory) +{ GetAES_KeyWrapFactory() = factory; -} - -void Aws::Utils::Crypto::SetSecureRandomFactory(const std::shared_ptr<SecureRandomFactory>& factory) -{ +} + +void Aws::Utils::Crypto::SetSecureRandomFactory(const std::shared_ptr<SecureRandomFactory>& factory) +{ GetSecureRandomFactory() = factory; -} - -std::shared_ptr<Hash> Aws::Utils::Crypto::CreateMD5Implementation() -{ +} + +std::shared_ptr<Hash> Aws::Utils::Crypto::CreateMD5Implementation() +{ return GetMD5Factory()->CreateImplementation(); -} - -std::shared_ptr<Hash> Aws::Utils::Crypto::CreateSha256Implementation() -{ +} + +std::shared_ptr<Hash> Aws::Utils::Crypto::CreateSha256Implementation() +{ return GetSha256Factory()->CreateImplementation(); -} - -std::shared_ptr<Aws::Utils::Crypto::HMAC> Aws::Utils::Crypto::CreateSha256HMACImplementation() -{ +} + +std::shared_ptr<Aws::Utils::Crypto::HMAC> Aws::Utils::Crypto::CreateSha256HMACImplementation() +{ return GetSha256HMACFactory()->CreateImplementation(); -} - -#ifdef _WIN32 -#pragma warning( push ) -#pragma warning( disable : 4702 ) -#endif - -std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_CBCImplementation(const CryptoBuffer& key) -{ -#ifdef NO_SYMMETRIC_ENCRYPTION - return nullptr; -#endif +} + +#ifdef _WIN32 +#pragma warning( push ) +#pragma warning( disable : 4702 ) +#endif + +std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_CBCImplementation(const CryptoBuffer& key) +{ +#ifdef NO_SYMMETRIC_ENCRYPTION + return nullptr; +#endif return GetAES_CBCFactory()->CreateImplementation(key); -} - -std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_CBCImplementation(const CryptoBuffer& key, const CryptoBuffer& iv) -{ -#ifdef NO_SYMMETRIC_ENCRYPTION - return nullptr; -#endif +} + +std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_CBCImplementation(const CryptoBuffer& key, const CryptoBuffer& iv) +{ +#ifdef NO_SYMMETRIC_ENCRYPTION + return nullptr; +#endif return GetAES_CBCFactory()->CreateImplementation(key, iv); -} - -std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_CBCImplementation(CryptoBuffer&& key, CryptoBuffer&& iv) -{ -#ifdef NO_SYMMETRIC_ENCRYPTION - return nullptr; -#endif +} + +std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_CBCImplementation(CryptoBuffer&& key, CryptoBuffer&& iv) +{ +#ifdef NO_SYMMETRIC_ENCRYPTION + return nullptr; +#endif return GetAES_CBCFactory()->CreateImplementation(std::move(key), std::move(iv)); -} - -std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_CTRImplementation(const CryptoBuffer& key) -{ -#ifdef NO_SYMMETRIC_ENCRYPTION - return nullptr; -#endif +} + +std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_CTRImplementation(const CryptoBuffer& key) +{ +#ifdef NO_SYMMETRIC_ENCRYPTION + return nullptr; +#endif return GetAES_CTRFactory()->CreateImplementation(key); -} - -std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_CTRImplementation(const CryptoBuffer& key, const CryptoBuffer& iv) -{ -#ifdef NO_SYMMETRIC_ENCRYPTION - return nullptr; -#endif +} + +std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_CTRImplementation(const CryptoBuffer& key, const CryptoBuffer& iv) +{ +#ifdef NO_SYMMETRIC_ENCRYPTION + return nullptr; +#endif return GetAES_CTRFactory()->CreateImplementation(key, iv); -} - -std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_CTRImplementation(CryptoBuffer&& key, CryptoBuffer&& iv) -{ -#ifdef NO_SYMMETRIC_ENCRYPTION - return nullptr; -#endif +} + +std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_CTRImplementation(CryptoBuffer&& key, CryptoBuffer&& iv) +{ +#ifdef NO_SYMMETRIC_ENCRYPTION + return nullptr; +#endif return GetAES_CTRFactory()->CreateImplementation(std::move(key), std::move(iv)); -} - -std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_GCMImplementation(const CryptoBuffer& key) -{ -#ifdef NO_SYMMETRIC_ENCRYPTION - return nullptr; -#endif +} + +std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_GCMImplementation(const CryptoBuffer& key) +{ +#ifdef NO_SYMMETRIC_ENCRYPTION + return nullptr; +#endif return GetAES_GCMFactory()->CreateImplementation(key); -} - +} + std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_GCMImplementation(const CryptoBuffer& key, const CryptoBuffer* aad) -{ -#ifdef NO_SYMMETRIC_ENCRYPTION - return nullptr; -#endif +{ +#ifdef NO_SYMMETRIC_ENCRYPTION + return nullptr; +#endif return GetAES_GCMFactory()->CreateImplementation(key, aad); -} - +} + std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_GCMImplementation(const CryptoBuffer& key, const CryptoBuffer& iv, const CryptoBuffer& tag, const CryptoBuffer& aad) -{ -#ifdef NO_SYMMETRIC_ENCRYPTION - return nullptr; -#endif +{ +#ifdef NO_SYMMETRIC_ENCRYPTION + return nullptr; +#endif return GetAES_GCMFactory()->CreateImplementation(key, iv, tag, aad); -} - +} + std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_GCMImplementation(CryptoBuffer&& key, CryptoBuffer&& iv, CryptoBuffer&& tag, CryptoBuffer&& aad) { #ifdef NO_SYMMETRIC_ENCRYPTION @@ -877,19 +877,19 @@ std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_GCMImplementation return GetAES_GCMFactory()->CreateImplementation(std::move(key), std::move(iv), std::move(tag), std::move(aad)); } -std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_KeyWrapImplementation(const CryptoBuffer& key) -{ -#ifdef NO_SYMMETRIC_ENCRYPTION - return nullptr; -#endif +std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_KeyWrapImplementation(const CryptoBuffer& key) +{ +#ifdef NO_SYMMETRIC_ENCRYPTION + return nullptr; +#endif return GetAES_KeyWrapFactory()->CreateImplementation(key); -} - -#ifdef _WIN32 -#pragma warning(pop) -#endif - -std::shared_ptr<SecureRandomBytes> Aws::Utils::Crypto::CreateSecureRandomBytesImplementation() -{ +} + +#ifdef _WIN32 +#pragma warning(pop) +#endif + +std::shared_ptr<SecureRandomBytes> Aws::Utils::Crypto::CreateSecureRandomBytesImplementation() +{ return GetSecureRandom(); -} +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/openssl/CryptoImpl.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/openssl/CryptoImpl.cpp index 911838864b..49a95e524b 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/openssl/CryptoImpl.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/openssl/CryptoImpl.cpp @@ -2,13 +2,13 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <cstring> - -#include <aws/core/utils/memory/AWSMemory.h> -#include <aws/core/utils/crypto/openssl/CryptoImpl.h> -#include <aws/core/utils/Outcome.h> -#include <openssl/md5.h> + +#include <cstring> + +#include <aws/core/utils/memory/AWSMemory.h> +#include <aws/core/utils/crypto/openssl/CryptoImpl.h> +#include <aws/core/utils/Outcome.h> +#include <openssl/md5.h> #ifdef OPENSSL_IS_BORINGSSL #ifdef _MSC_VER @@ -18,119 +18,119 @@ AWS_SUPPRESS_WARNING_PUSH("-Wpedantic") #endif #endif -#include <openssl/sha.h> +#include <openssl/sha.h> #ifdef OPENSSL_IS_BORINGSSL AWS_SUPPRESS_WARNING_POP #endif -#include <openssl/err.h> -#include <aws/core/utils/logging/LogMacros.h> -#include <thread> - -using namespace Aws::Utils; -using namespace Aws::Utils::Crypto; - -namespace Aws -{ - namespace Utils - { - namespace Crypto - { - namespace OpenSSL - { -/** - * openssl with OPENSSL_VERSION_NUMBER < 0x10100003L made data type details unavailable +#include <openssl/err.h> +#include <aws/core/utils/logging/LogMacros.h> +#include <thread> + +using namespace Aws::Utils; +using namespace Aws::Utils::Crypto; + +namespace Aws +{ + namespace Utils + { + namespace Crypto + { + namespace OpenSSL + { +/** + * openssl with OPENSSL_VERSION_NUMBER < 0x10100003L made data type details unavailable * libressl use openssl with data type details available, but mandatorily set - * OPENSSL_VERSION_NUMBER = 0x20000000L, insane! - * https://github.com/aws/aws-sdk-cpp/pull/507/commits/2c99f1fe0c4b4683280caeb161538d4724d6a179 - */ -#if defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER == 0x20000000L) -#undef OPENSSL_VERSION_NUMBER -#define OPENSSL_VERSION_NUMBER 0x1000107fL -#endif -#define OPENSSL_VERSION_LESS_1_1 (OPENSSL_VERSION_NUMBER < 0x10100003L) - -#if OPENSSL_VERSION_LESS_1_1 - static const char* OPENSSL_INTERNALS_TAG = "OpenSSLCallbackState"; - static std::mutex* locks(nullptr); -#endif - - GetTheLights getTheLights; - - void init_static_state() - { + * OPENSSL_VERSION_NUMBER = 0x20000000L, insane! + * https://github.com/aws/aws-sdk-cpp/pull/507/commits/2c99f1fe0c4b4683280caeb161538d4724d6a179 + */ +#if defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER == 0x20000000L) +#undef OPENSSL_VERSION_NUMBER +#define OPENSSL_VERSION_NUMBER 0x1000107fL +#endif +#define OPENSSL_VERSION_LESS_1_1 (OPENSSL_VERSION_NUMBER < 0x10100003L) + +#if OPENSSL_VERSION_LESS_1_1 + static const char* OPENSSL_INTERNALS_TAG = "OpenSSLCallbackState"; + static std::mutex* locks(nullptr); +#endif + + GetTheLights getTheLights; + + void init_static_state() + { #if OPENSSL_VERSION_LESS_1_1 || defined(OPENSSL_IS_BORINGSSL) ERR_load_crypto_strings(); #else OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS /*options*/ ,NULL /* OpenSSL init settings*/ ); #endif #if !defined(OPENSSL_IS_BORINGSSL) - OPENSSL_add_all_algorithms_noconf(); -#endif -#if OPENSSL_VERSION_LESS_1_1 - if (!CRYPTO_get_locking_callback()) - { - locks = Aws::NewArray<std::mutex>(static_cast<size_t>(CRYPTO_num_locks()), - OPENSSL_INTERNALS_TAG); - CRYPTO_set_locking_callback(&locking_fn); - } - - if (!CRYPTO_get_id_callback()) - { - CRYPTO_set_id_callback(&id_fn); - } -#endif - RAND_poll(); - } - - void cleanup_static_state() - { -#if OPENSSL_VERSION_LESS_1_1 - if (CRYPTO_get_locking_callback() == &locking_fn) - { - CRYPTO_set_locking_callback(nullptr); - assert(locks); - Aws::DeleteArray(locks); - locks = nullptr; - } - - if (CRYPTO_get_id_callback() == &id_fn) - { - CRYPTO_set_id_callback(nullptr); - } + OPENSSL_add_all_algorithms_noconf(); #endif - } - -#if OPENSSL_VERSION_LESS_1_1 - void locking_fn(int mode, int n, const char*, int) - { - if (mode & CRYPTO_LOCK) - { - locks[n].lock(); - } - else - { - locks[n].unlock(); - } - } - - unsigned long id_fn() - { - return static_cast<unsigned long>(std::hash<std::thread::id>()(std::this_thread::get_id())); - } -#endif - } - +#if OPENSSL_VERSION_LESS_1_1 + if (!CRYPTO_get_locking_callback()) + { + locks = Aws::NewArray<std::mutex>(static_cast<size_t>(CRYPTO_num_locks()), + OPENSSL_INTERNALS_TAG); + CRYPTO_set_locking_callback(&locking_fn); + } + + if (!CRYPTO_get_id_callback()) + { + CRYPTO_set_id_callback(&id_fn); + } +#endif + RAND_poll(); + } + + void cleanup_static_state() + { +#if OPENSSL_VERSION_LESS_1_1 + if (CRYPTO_get_locking_callback() == &locking_fn) + { + CRYPTO_set_locking_callback(nullptr); + assert(locks); + Aws::DeleteArray(locks); + locks = nullptr; + } + + if (CRYPTO_get_id_callback() == &id_fn) + { + CRYPTO_set_id_callback(nullptr); + } +#endif + } + +#if OPENSSL_VERSION_LESS_1_1 + void locking_fn(int mode, int n, const char*, int) + { + if (mode & CRYPTO_LOCK) + { + locks[n].lock(); + } + else + { + locks[n].unlock(); + } + } + + unsigned long id_fn() + { + return static_cast<unsigned long>(std::hash<std::thread::id>()(std::this_thread::get_id())); + } +#endif + } + static const char* OPENSSL_LOG_TAG = "OpenSSLCipher"; - void SecureRandomBytes_OpenSSLImpl::GetBytes(unsigned char* buffer, size_t bufferSize) - { + void SecureRandomBytes_OpenSSLImpl::GetBytes(unsigned char* buffer, size_t bufferSize) + { if (!bufferSize) { return; } - + if (!buffer) { AWS_LOGSTREAM_FATAL(OPENSSL_LOG_TAG, "Secure Random Bytes generator can't generate: " << bufferSize << " bytes with nullptr buffer."); @@ -138,391 +138,391 @@ namespace Aws return; } - int success = RAND_bytes(buffer, static_cast<int>(bufferSize)); - if (success != 1) - { - m_failure = true; - } - } - + int success = RAND_bytes(buffer, static_cast<int>(bufferSize)); + if (success != 1) + { + m_failure = true; + } + } + class OpensslCtxRAIIGuard - { + { public: OpensslCtxRAIIGuard() - { - m_ctx = EVP_MD_CTX_create(); - assert(m_ctx != nullptr); - } - + { + m_ctx = EVP_MD_CTX_create(); + assert(m_ctx != nullptr); + } + ~OpensslCtxRAIIGuard() - { - EVP_MD_CTX_destroy(m_ctx); - m_ctx = nullptr; - } - + { + EVP_MD_CTX_destroy(m_ctx); + m_ctx = nullptr; + } + EVP_MD_CTX* getResource() - { - return m_ctx; - } - private: - EVP_MD_CTX *m_ctx; - }; - - HashResult MD5OpenSSLImpl::Calculate(const Aws::String& str) - { - OpensslCtxRAIIGuard guard; - auto ctx = guard.getResource(); + { + return m_ctx; + } + private: + EVP_MD_CTX *m_ctx; + }; + + HashResult MD5OpenSSLImpl::Calculate(const Aws::String& str) + { + OpensslCtxRAIIGuard guard; + auto ctx = guard.getResource(); #if !defined(OPENSSL_IS_BORINGSSL) - EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); + EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); #endif - EVP_DigestInit_ex(ctx, EVP_md5(), nullptr); - EVP_DigestUpdate(ctx, str.c_str(), str.size()); - - ByteBuffer hash(EVP_MD_size(EVP_md5())); - EVP_DigestFinal(ctx, hash.GetUnderlyingData(), nullptr); - - return HashResult(std::move(hash)); - } - - HashResult MD5OpenSSLImpl::Calculate(Aws::IStream& stream) - { - OpensslCtxRAIIGuard guard; - auto ctx = guard.getResource(); + EVP_DigestInit_ex(ctx, EVP_md5(), nullptr); + EVP_DigestUpdate(ctx, str.c_str(), str.size()); + + ByteBuffer hash(EVP_MD_size(EVP_md5())); + EVP_DigestFinal(ctx, hash.GetUnderlyingData(), nullptr); + + return HashResult(std::move(hash)); + } + + HashResult MD5OpenSSLImpl::Calculate(Aws::IStream& stream) + { + OpensslCtxRAIIGuard guard; + auto ctx = guard.getResource(); #if !defined(OPENSSL_IS_BORINGSSL) - EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); + EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); #endif - EVP_DigestInit_ex(ctx, EVP_md5(), nullptr); - - auto currentPos = stream.tellg(); - if (currentPos == -1) - { - currentPos = 0; - stream.clear(); - } - stream.seekg(0, stream.beg); - - char streamBuffer[Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE]; - while (stream.good()) - { - stream.read(streamBuffer, Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE); - auto bytesRead = stream.gcount(); - - if (bytesRead > 0) - { - EVP_DigestUpdate(ctx, streamBuffer, static_cast<size_t>(bytesRead)); - } - } - - stream.clear(); - stream.seekg(currentPos, stream.beg); - - ByteBuffer hash(EVP_MD_size(EVP_md5())); - EVP_DigestFinal(ctx, hash.GetUnderlyingData(), nullptr); - - return HashResult(std::move(hash)); - } - - HashResult Sha256OpenSSLImpl::Calculate(const Aws::String& str) - { - OpensslCtxRAIIGuard guard; - auto ctx = guard.getResource(); - EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr); - EVP_DigestUpdate(ctx, str.c_str(), str.size()); - - ByteBuffer hash(EVP_MD_size(EVP_sha256())); - EVP_DigestFinal(ctx, hash.GetUnderlyingData(), nullptr); - - return HashResult(std::move(hash)); - } - - HashResult Sha256OpenSSLImpl::Calculate(Aws::IStream& stream) - { - OpensslCtxRAIIGuard guard; - auto ctx = guard.getResource(); - - EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr); - - auto currentPos = stream.tellg(); - if (currentPos == -1) - { - currentPos = 0; - stream.clear(); - } - - stream.seekg(0, stream.beg); - - char streamBuffer[Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE]; - while (stream.good()) - { - stream.read(streamBuffer, Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE); - auto bytesRead = stream.gcount(); - - if (bytesRead > 0) - { - EVP_DigestUpdate(ctx, streamBuffer, static_cast<size_t>(bytesRead)); - } - } - - stream.clear(); - stream.seekg(currentPos, stream.beg); - - ByteBuffer hash(EVP_MD_size(EVP_sha256())); - EVP_DigestFinal(ctx, hash.GetUnderlyingData(), nullptr); - - return HashResult(std::move(hash)); - } - - class HMACRAIIGuard { - public: - HMACRAIIGuard() { -#if OPENSSL_VERSION_LESS_1_1 - m_ctx = Aws::New<HMAC_CTX>("AllocSha256HAMCOpenSSLContext"); -#else - m_ctx = HMAC_CTX_new(); -#endif - assert(m_ctx != nullptr); - } - - ~HMACRAIIGuard() { -#if OPENSSL_VERSION_LESS_1_1 - Aws::Delete<HMAC_CTX>(m_ctx); -#else - HMAC_CTX_free(m_ctx); -#endif - m_ctx = nullptr; - } - - HMAC_CTX* getResource() { - return m_ctx; - } - private: - HMAC_CTX *m_ctx; - }; - - HashResult Sha256HMACOpenSSLImpl::Calculate(const ByteBuffer& toSign, const ByteBuffer& secret) - { - unsigned int length = SHA256_DIGEST_LENGTH; - ByteBuffer digest(length); - memset(digest.GetUnderlyingData(), 0, length); - - HMACRAIIGuard guard; - HMAC_CTX* m_ctx = guard.getResource(); - -#if OPENSSL_VERSION_LESS_1_1 - HMAC_CTX_init(m_ctx); -#endif - - HMAC_Init_ex(m_ctx, secret.GetUnderlyingData(), static_cast<int>(secret.GetLength()), EVP_sha256(), - NULL); - HMAC_Update(m_ctx, toSign.GetUnderlyingData(), toSign.GetLength()); - HMAC_Final(m_ctx, digest.GetUnderlyingData(), &length); - -#if OPENSSL_VERSION_LESS_1_1 - HMAC_CTX_cleanup(m_ctx); -#else - HMAC_CTX_reset(m_ctx); -#endif - return HashResult(std::move(digest)); - } - - void LogErrors(const char* logTag = OPENSSL_LOG_TAG) - { - unsigned long errorCode = ERR_get_error(); - char errStr[256]; - ERR_error_string_n(errorCode, errStr, 256); - - AWS_LOGSTREAM_ERROR(logTag, errStr); - } - - OpenSSLCipher::OpenSSLCipher(const CryptoBuffer& key, size_t blockSizeBytes, bool ctrMode) : - SymmetricCipher(key, blockSizeBytes, ctrMode), m_encryptor_ctx(nullptr), m_decryptor_ctx(nullptr) - { - Init(); - } - - OpenSSLCipher::OpenSSLCipher(OpenSSLCipher&& toMove) : SymmetricCipher(std::move(toMove)), - m_encryptor_ctx(nullptr), m_decryptor_ctx(nullptr) - { - Init(); - EVP_CIPHER_CTX_copy(m_encryptor_ctx, toMove.m_encryptor_ctx); - EVP_CIPHER_CTX_copy(m_decryptor_ctx, toMove.m_decryptor_ctx); - EVP_CIPHER_CTX_cleanup(toMove.m_encryptor_ctx); - EVP_CIPHER_CTX_cleanup(toMove.m_decryptor_ctx); - } - - OpenSSLCipher::OpenSSLCipher(CryptoBuffer&& key, CryptoBuffer&& initializationVector, CryptoBuffer&& tag) : - SymmetricCipher(std::move(key), std::move(initializationVector), std::move(tag)), - m_encryptor_ctx(nullptr), m_decryptor_ctx(nullptr) - { - Init(); - } - - OpenSSLCipher::OpenSSLCipher(const CryptoBuffer& key, const CryptoBuffer& initializationVector, - const CryptoBuffer& tag) : - SymmetricCipher(key, initializationVector, tag), m_encryptor_ctx(nullptr), m_decryptor_ctx(nullptr) - { - Init(); - } - - OpenSSLCipher::~OpenSSLCipher() - { - Cleanup(); - if (m_encryptor_ctx) - { - EVP_CIPHER_CTX_free(m_encryptor_ctx); - m_encryptor_ctx = nullptr; - } - if (m_decryptor_ctx) - { - EVP_CIPHER_CTX_free(m_decryptor_ctx); - m_decryptor_ctx = nullptr; - } - } - - void OpenSSLCipher::Init() - { + EVP_DigestInit_ex(ctx, EVP_md5(), nullptr); + + auto currentPos = stream.tellg(); + if (currentPos == -1) + { + currentPos = 0; + stream.clear(); + } + stream.seekg(0, stream.beg); + + char streamBuffer[Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE]; + while (stream.good()) + { + stream.read(streamBuffer, Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE); + auto bytesRead = stream.gcount(); + + if (bytesRead > 0) + { + EVP_DigestUpdate(ctx, streamBuffer, static_cast<size_t>(bytesRead)); + } + } + + stream.clear(); + stream.seekg(currentPos, stream.beg); + + ByteBuffer hash(EVP_MD_size(EVP_md5())); + EVP_DigestFinal(ctx, hash.GetUnderlyingData(), nullptr); + + return HashResult(std::move(hash)); + } + + HashResult Sha256OpenSSLImpl::Calculate(const Aws::String& str) + { + OpensslCtxRAIIGuard guard; + auto ctx = guard.getResource(); + EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr); + EVP_DigestUpdate(ctx, str.c_str(), str.size()); + + ByteBuffer hash(EVP_MD_size(EVP_sha256())); + EVP_DigestFinal(ctx, hash.GetUnderlyingData(), nullptr); + + return HashResult(std::move(hash)); + } + + HashResult Sha256OpenSSLImpl::Calculate(Aws::IStream& stream) + { + OpensslCtxRAIIGuard guard; + auto ctx = guard.getResource(); + + EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr); + + auto currentPos = stream.tellg(); + if (currentPos == -1) + { + currentPos = 0; + stream.clear(); + } + + stream.seekg(0, stream.beg); + + char streamBuffer[Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE]; + while (stream.good()) + { + stream.read(streamBuffer, Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE); + auto bytesRead = stream.gcount(); + + if (bytesRead > 0) + { + EVP_DigestUpdate(ctx, streamBuffer, static_cast<size_t>(bytesRead)); + } + } + + stream.clear(); + stream.seekg(currentPos, stream.beg); + + ByteBuffer hash(EVP_MD_size(EVP_sha256())); + EVP_DigestFinal(ctx, hash.GetUnderlyingData(), nullptr); + + return HashResult(std::move(hash)); + } + + class HMACRAIIGuard { + public: + HMACRAIIGuard() { +#if OPENSSL_VERSION_LESS_1_1 + m_ctx = Aws::New<HMAC_CTX>("AllocSha256HAMCOpenSSLContext"); +#else + m_ctx = HMAC_CTX_new(); +#endif + assert(m_ctx != nullptr); + } + + ~HMACRAIIGuard() { +#if OPENSSL_VERSION_LESS_1_1 + Aws::Delete<HMAC_CTX>(m_ctx); +#else + HMAC_CTX_free(m_ctx); +#endif + m_ctx = nullptr; + } + + HMAC_CTX* getResource() { + return m_ctx; + } + private: + HMAC_CTX *m_ctx; + }; + + HashResult Sha256HMACOpenSSLImpl::Calculate(const ByteBuffer& toSign, const ByteBuffer& secret) + { + unsigned int length = SHA256_DIGEST_LENGTH; + ByteBuffer digest(length); + memset(digest.GetUnderlyingData(), 0, length); + + HMACRAIIGuard guard; + HMAC_CTX* m_ctx = guard.getResource(); + +#if OPENSSL_VERSION_LESS_1_1 + HMAC_CTX_init(m_ctx); +#endif + + HMAC_Init_ex(m_ctx, secret.GetUnderlyingData(), static_cast<int>(secret.GetLength()), EVP_sha256(), + NULL); + HMAC_Update(m_ctx, toSign.GetUnderlyingData(), toSign.GetLength()); + HMAC_Final(m_ctx, digest.GetUnderlyingData(), &length); + +#if OPENSSL_VERSION_LESS_1_1 + HMAC_CTX_cleanup(m_ctx); +#else + HMAC_CTX_reset(m_ctx); +#endif + return HashResult(std::move(digest)); + } + + void LogErrors(const char* logTag = OPENSSL_LOG_TAG) + { + unsigned long errorCode = ERR_get_error(); + char errStr[256]; + ERR_error_string_n(errorCode, errStr, 256); + + AWS_LOGSTREAM_ERROR(logTag, errStr); + } + + OpenSSLCipher::OpenSSLCipher(const CryptoBuffer& key, size_t blockSizeBytes, bool ctrMode) : + SymmetricCipher(key, blockSizeBytes, ctrMode), m_encryptor_ctx(nullptr), m_decryptor_ctx(nullptr) + { + Init(); + } + + OpenSSLCipher::OpenSSLCipher(OpenSSLCipher&& toMove) : SymmetricCipher(std::move(toMove)), + m_encryptor_ctx(nullptr), m_decryptor_ctx(nullptr) + { + Init(); + EVP_CIPHER_CTX_copy(m_encryptor_ctx, toMove.m_encryptor_ctx); + EVP_CIPHER_CTX_copy(m_decryptor_ctx, toMove.m_decryptor_ctx); + EVP_CIPHER_CTX_cleanup(toMove.m_encryptor_ctx); + EVP_CIPHER_CTX_cleanup(toMove.m_decryptor_ctx); + } + + OpenSSLCipher::OpenSSLCipher(CryptoBuffer&& key, CryptoBuffer&& initializationVector, CryptoBuffer&& tag) : + SymmetricCipher(std::move(key), std::move(initializationVector), std::move(tag)), + m_encryptor_ctx(nullptr), m_decryptor_ctx(nullptr) + { + Init(); + } + + OpenSSLCipher::OpenSSLCipher(const CryptoBuffer& key, const CryptoBuffer& initializationVector, + const CryptoBuffer& tag) : + SymmetricCipher(key, initializationVector, tag), m_encryptor_ctx(nullptr), m_decryptor_ctx(nullptr) + { + Init(); + } + + OpenSSLCipher::~OpenSSLCipher() + { + Cleanup(); + if (m_encryptor_ctx) + { + EVP_CIPHER_CTX_free(m_encryptor_ctx); + m_encryptor_ctx = nullptr; + } + if (m_decryptor_ctx) + { + EVP_CIPHER_CTX_free(m_decryptor_ctx); + m_decryptor_ctx = nullptr; + } + } + + void OpenSSLCipher::Init() + { if (m_failure) { return; } - if (!m_encryptor_ctx) - { - // EVP_CIPHER_CTX_init() will be called inside EVP_CIPHER_CTX_new(). - m_encryptor_ctx = EVP_CIPHER_CTX_new(); - assert(m_encryptor_ctx != nullptr); - } - else - { // _init is the same as _reset after openssl 1.1 - EVP_CIPHER_CTX_init(m_encryptor_ctx); - } - if (!m_decryptor_ctx) - { - // EVP_CIPHER_CTX_init() will be called inside EVP_CIPHER_CTX_new(). - m_decryptor_ctx = EVP_CIPHER_CTX_new(); - assert(m_decryptor_ctx != nullptr); - } - else - { // _init is the same as _reset after openssl 1.1 - EVP_CIPHER_CTX_init(m_decryptor_ctx); - } + if (!m_encryptor_ctx) + { + // EVP_CIPHER_CTX_init() will be called inside EVP_CIPHER_CTX_new(). + m_encryptor_ctx = EVP_CIPHER_CTX_new(); + assert(m_encryptor_ctx != nullptr); + } + else + { // _init is the same as _reset after openssl 1.1 + EVP_CIPHER_CTX_init(m_encryptor_ctx); + } + if (!m_decryptor_ctx) + { + // EVP_CIPHER_CTX_init() will be called inside EVP_CIPHER_CTX_new(). + m_decryptor_ctx = EVP_CIPHER_CTX_new(); + assert(m_decryptor_ctx != nullptr); + } + else + { // _init is the same as _reset after openssl 1.1 + EVP_CIPHER_CTX_init(m_decryptor_ctx); + } m_emptyPlaintext = false; - } - - CryptoBuffer OpenSSLCipher::EncryptBuffer(const CryptoBuffer& unEncryptedData) - { - if (m_failure) - { - AWS_LOGSTREAM_FATAL(OPENSSL_LOG_TAG, "Cipher not properly initialized for encryption. Aborting"); - return CryptoBuffer(); - } - - int lengthWritten = static_cast<int>(unEncryptedData.GetLength() + (GetBlockSizeBytes() - 1)); - CryptoBuffer encryptedText(static_cast<size_t>( lengthWritten + (GetBlockSizeBytes() - 1))); - - if (!EVP_EncryptUpdate(m_encryptor_ctx, encryptedText.GetUnderlyingData(), &lengthWritten, - unEncryptedData.GetUnderlyingData(), - static_cast<int>(unEncryptedData.GetLength()))) - { - m_failure = true; - LogErrors(); - return CryptoBuffer(); - } - - if (static_cast<size_t>(lengthWritten) < encryptedText.GetLength()) - { - return CryptoBuffer(encryptedText.GetUnderlyingData(), static_cast<size_t>(lengthWritten)); - } - return encryptedText; - } - - CryptoBuffer OpenSSLCipher::FinalizeEncryption() - { - if (m_failure) - { + } + + CryptoBuffer OpenSSLCipher::EncryptBuffer(const CryptoBuffer& unEncryptedData) + { + if (m_failure) + { + AWS_LOGSTREAM_FATAL(OPENSSL_LOG_TAG, "Cipher not properly initialized for encryption. Aborting"); + return CryptoBuffer(); + } + + int lengthWritten = static_cast<int>(unEncryptedData.GetLength() + (GetBlockSizeBytes() - 1)); + CryptoBuffer encryptedText(static_cast<size_t>( lengthWritten + (GetBlockSizeBytes() - 1))); + + if (!EVP_EncryptUpdate(m_encryptor_ctx, encryptedText.GetUnderlyingData(), &lengthWritten, + unEncryptedData.GetUnderlyingData(), + static_cast<int>(unEncryptedData.GetLength()))) + { + m_failure = true; + LogErrors(); + return CryptoBuffer(); + } + + if (static_cast<size_t>(lengthWritten) < encryptedText.GetLength()) + { + return CryptoBuffer(encryptedText.GetUnderlyingData(), static_cast<size_t>(lengthWritten)); + } + return encryptedText; + } + + CryptoBuffer OpenSSLCipher::FinalizeEncryption() + { + if (m_failure) + { AWS_LOGSTREAM_FATAL(OPENSSL_LOG_TAG, "Cipher not properly initialized for encryption finalization. Aborting"); - return CryptoBuffer(); - } - - CryptoBuffer finalBlock(GetBlockSizeBytes()); - int writtenSize = 0; - if (!EVP_EncryptFinal_ex(m_encryptor_ctx, finalBlock.GetUnderlyingData(), &writtenSize)) - { - m_failure = true; - LogErrors(); - return CryptoBuffer(); - } - return CryptoBuffer(finalBlock.GetUnderlyingData(), static_cast<size_t>(writtenSize)); - } - - CryptoBuffer OpenSSLCipher::DecryptBuffer(const CryptoBuffer& encryptedData) - { - if (m_failure) - { - AWS_LOGSTREAM_FATAL(OPENSSL_LOG_TAG, "Cipher not properly initialized for decryption. Aborting"); - return CryptoBuffer(); - } - - int lengthWritten = static_cast<int>(encryptedData.GetLength() + (GetBlockSizeBytes() - 1)); - CryptoBuffer decryptedText(static_cast<size_t>(lengthWritten)); - - if (!EVP_DecryptUpdate(m_decryptor_ctx, decryptedText.GetUnderlyingData(), &lengthWritten, - encryptedData.GetUnderlyingData(), - static_cast<int>(encryptedData.GetLength()))) - { - m_failure = true; - LogErrors(); - return CryptoBuffer(); - } - + return CryptoBuffer(); + } + + CryptoBuffer finalBlock(GetBlockSizeBytes()); + int writtenSize = 0; + if (!EVP_EncryptFinal_ex(m_encryptor_ctx, finalBlock.GetUnderlyingData(), &writtenSize)) + { + m_failure = true; + LogErrors(); + return CryptoBuffer(); + } + return CryptoBuffer(finalBlock.GetUnderlyingData(), static_cast<size_t>(writtenSize)); + } + + CryptoBuffer OpenSSLCipher::DecryptBuffer(const CryptoBuffer& encryptedData) + { + if (m_failure) + { + AWS_LOGSTREAM_FATAL(OPENSSL_LOG_TAG, "Cipher not properly initialized for decryption. Aborting"); + return CryptoBuffer(); + } + + int lengthWritten = static_cast<int>(encryptedData.GetLength() + (GetBlockSizeBytes() - 1)); + CryptoBuffer decryptedText(static_cast<size_t>(lengthWritten)); + + if (!EVP_DecryptUpdate(m_decryptor_ctx, decryptedText.GetUnderlyingData(), &lengthWritten, + encryptedData.GetUnderlyingData(), + static_cast<int>(encryptedData.GetLength()))) + { + m_failure = true; + LogErrors(); + return CryptoBuffer(); + } + if (lengthWritten == 0) { m_emptyPlaintext = true; } - if (static_cast<size_t>(lengthWritten) < decryptedText.GetLength()) - { - return CryptoBuffer(decryptedText.GetUnderlyingData(), static_cast<size_t>(lengthWritten)); - } - return decryptedText; - } - - CryptoBuffer OpenSSLCipher::FinalizeDecryption() - { - if (m_failure) - { + if (static_cast<size_t>(lengthWritten) < decryptedText.GetLength()) + { + return CryptoBuffer(decryptedText.GetUnderlyingData(), static_cast<size_t>(lengthWritten)); + } + return decryptedText; + } + + CryptoBuffer OpenSSLCipher::FinalizeDecryption() + { + if (m_failure) + { AWS_LOGSTREAM_FATAL(OPENSSL_LOG_TAG, "Cipher not properly initialized for decryption finalization. Aborting"); - return CryptoBuffer(); - } - - CryptoBuffer finalBlock(GetBlockSizeBytes()); - int writtenSize = static_cast<int>(finalBlock.GetLength()); + return CryptoBuffer(); + } + + CryptoBuffer finalBlock(GetBlockSizeBytes()); + int writtenSize = static_cast<int>(finalBlock.GetLength()); int ret = EVP_DecryptFinal_ex(m_decryptor_ctx, finalBlock.GetUnderlyingData(), &writtenSize); #if OPENSSL_VERSION_NUMBER > 0x1010104fL //1.1.1d if (ret <= 0) #else if (ret <= 0 && !m_emptyPlaintext) // see details why making exception for empty string at: https://github.com/aws/aws-sdk-cpp/issues/1413 #endif - { - m_failure = true; - LogErrors(); - return CryptoBuffer(); - } - return CryptoBuffer(finalBlock.GetUnderlyingData(), static_cast<size_t>(writtenSize)); - } - - void OpenSSLCipher::Reset() - { - Cleanup(); - Init(); - } - - void OpenSSLCipher::Cleanup() - { - m_failure = false; + { + m_failure = true; + LogErrors(); + return CryptoBuffer(); + } + return CryptoBuffer(finalBlock.GetUnderlyingData(), static_cast<size_t>(writtenSize)); + } + + void OpenSSLCipher::Reset() + { + Cleanup(); + Init(); + } + + void OpenSSLCipher::Cleanup() + { + m_failure = false; if (m_encryptor_ctx) EVP_CIPHER_CTX_cleanup(m_encryptor_ctx); if (m_decryptor_ctx) EVP_CIPHER_CTX_cleanup(m_decryptor_ctx); } - + bool OpenSSLCipher::CheckKeyAndIVLength(size_t expectedKeyLength, size_t expectedIVLength) { if (!m_failure && ((m_key.GetLength() != expectedKeyLength) || m_initializationVector.GetLength() != expectedIVLength)) @@ -531,156 +531,156 @@ namespace Aws m_failure = true; } return !m_failure; - } - - size_t AES_CBC_Cipher_OpenSSL::BlockSizeBytes = 16; - size_t AES_CBC_Cipher_OpenSSL::KeyLengthBits = 256; - static const char* CBC_LOG_TAG = "AES_CBC_Cipher_OpenSSL"; - - AES_CBC_Cipher_OpenSSL::AES_CBC_Cipher_OpenSSL(const CryptoBuffer& key) : OpenSSLCipher(key, BlockSizeBytes) - { - InitCipher(); - } - - AES_CBC_Cipher_OpenSSL::AES_CBC_Cipher_OpenSSL(CryptoBuffer&& key, CryptoBuffer&& initializationVector) : - OpenSSLCipher(std::move(key), std::move(initializationVector)) - { - InitCipher(); - } - - AES_CBC_Cipher_OpenSSL::AES_CBC_Cipher_OpenSSL(const CryptoBuffer& key, - const CryptoBuffer& initializationVector) : - OpenSSLCipher(key, initializationVector) - { - InitCipher(); - } - - void AES_CBC_Cipher_OpenSSL::InitCipher() - { + } + + size_t AES_CBC_Cipher_OpenSSL::BlockSizeBytes = 16; + size_t AES_CBC_Cipher_OpenSSL::KeyLengthBits = 256; + static const char* CBC_LOG_TAG = "AES_CBC_Cipher_OpenSSL"; + + AES_CBC_Cipher_OpenSSL::AES_CBC_Cipher_OpenSSL(const CryptoBuffer& key) : OpenSSLCipher(key, BlockSizeBytes) + { + InitCipher(); + } + + AES_CBC_Cipher_OpenSSL::AES_CBC_Cipher_OpenSSL(CryptoBuffer&& key, CryptoBuffer&& initializationVector) : + OpenSSLCipher(std::move(key), std::move(initializationVector)) + { + InitCipher(); + } + + AES_CBC_Cipher_OpenSSL::AES_CBC_Cipher_OpenSSL(const CryptoBuffer& key, + const CryptoBuffer& initializationVector) : + OpenSSLCipher(key, initializationVector) + { + InitCipher(); + } + + void AES_CBC_Cipher_OpenSSL::InitCipher() + { if (m_failure || !CheckKeyAndIVLength(KeyLengthBits/8, BlockSizeBytes)) { return; } - if (!EVP_EncryptInit_ex(m_encryptor_ctx, EVP_aes_256_cbc(), nullptr, m_key.GetUnderlyingData(), - m_initializationVector.GetUnderlyingData()) || - !EVP_DecryptInit_ex(m_decryptor_ctx, EVP_aes_256_cbc(), nullptr, m_key.GetUnderlyingData(), - m_initializationVector.GetUnderlyingData())) - { - m_failure = true; - LogErrors(CBC_LOG_TAG); - } - } - - size_t AES_CBC_Cipher_OpenSSL::GetBlockSizeBytes() const - { - return BlockSizeBytes; - } - - size_t AES_CBC_Cipher_OpenSSL::GetKeyLengthBits() const - { - return KeyLengthBits; - } - + if (!EVP_EncryptInit_ex(m_encryptor_ctx, EVP_aes_256_cbc(), nullptr, m_key.GetUnderlyingData(), + m_initializationVector.GetUnderlyingData()) || + !EVP_DecryptInit_ex(m_decryptor_ctx, EVP_aes_256_cbc(), nullptr, m_key.GetUnderlyingData(), + m_initializationVector.GetUnderlyingData())) + { + m_failure = true; + LogErrors(CBC_LOG_TAG); + } + } + + size_t AES_CBC_Cipher_OpenSSL::GetBlockSizeBytes() const + { + return BlockSizeBytes; + } + + size_t AES_CBC_Cipher_OpenSSL::GetKeyLengthBits() const + { + return KeyLengthBits; + } + void AES_CBC_Cipher_OpenSSL::Reset() { OpenSSLCipher::Reset(); InitCipher(); } - size_t AES_CTR_Cipher_OpenSSL::BlockSizeBytes = 16; - size_t AES_CTR_Cipher_OpenSSL::KeyLengthBits = 256; - static const char* CTR_LOG_TAG = "AES_CTR_Cipher_OpenSSL"; - - AES_CTR_Cipher_OpenSSL::AES_CTR_Cipher_OpenSSL(const CryptoBuffer& key) : OpenSSLCipher(key, BlockSizeBytes, - true) - { - InitCipher(); - } - - AES_CTR_Cipher_OpenSSL::AES_CTR_Cipher_OpenSSL(CryptoBuffer&& key, CryptoBuffer&& initializationVector) : - OpenSSLCipher(std::move(key), std::move(initializationVector)) - { - InitCipher(); - } - - AES_CTR_Cipher_OpenSSL::AES_CTR_Cipher_OpenSSL(const CryptoBuffer& key, - const CryptoBuffer& initializationVector) : - OpenSSLCipher(key, initializationVector) - { - InitCipher(); - } - - void AES_CTR_Cipher_OpenSSL::InitCipher() - { + size_t AES_CTR_Cipher_OpenSSL::BlockSizeBytes = 16; + size_t AES_CTR_Cipher_OpenSSL::KeyLengthBits = 256; + static const char* CTR_LOG_TAG = "AES_CTR_Cipher_OpenSSL"; + + AES_CTR_Cipher_OpenSSL::AES_CTR_Cipher_OpenSSL(const CryptoBuffer& key) : OpenSSLCipher(key, BlockSizeBytes, + true) + { + InitCipher(); + } + + AES_CTR_Cipher_OpenSSL::AES_CTR_Cipher_OpenSSL(CryptoBuffer&& key, CryptoBuffer&& initializationVector) : + OpenSSLCipher(std::move(key), std::move(initializationVector)) + { + InitCipher(); + } + + AES_CTR_Cipher_OpenSSL::AES_CTR_Cipher_OpenSSL(const CryptoBuffer& key, + const CryptoBuffer& initializationVector) : + OpenSSLCipher(key, initializationVector) + { + InitCipher(); + } + + void AES_CTR_Cipher_OpenSSL::InitCipher() + { if (m_failure || !CheckKeyAndIVLength(KeyLengthBits/8, BlockSizeBytes)) { return; } - if (!(EVP_EncryptInit_ex(m_encryptor_ctx, EVP_aes_256_ctr(), nullptr, m_key.GetUnderlyingData(), - m_initializationVector.GetUnderlyingData()) - && EVP_CIPHER_CTX_set_padding(m_encryptor_ctx, 0)) || - !(EVP_DecryptInit_ex(m_decryptor_ctx, EVP_aes_256_ctr(), nullptr, m_key.GetUnderlyingData(), - m_initializationVector.GetUnderlyingData()) - && EVP_CIPHER_CTX_set_padding(m_decryptor_ctx, 0))) - { - m_failure = true; - LogErrors(CTR_LOG_TAG); - } - } - - size_t AES_CTR_Cipher_OpenSSL::GetBlockSizeBytes() const - { - return BlockSizeBytes; - } - - size_t AES_CTR_Cipher_OpenSSL::GetKeyLengthBits() const - { - return KeyLengthBits; - } - + if (!(EVP_EncryptInit_ex(m_encryptor_ctx, EVP_aes_256_ctr(), nullptr, m_key.GetUnderlyingData(), + m_initializationVector.GetUnderlyingData()) + && EVP_CIPHER_CTX_set_padding(m_encryptor_ctx, 0)) || + !(EVP_DecryptInit_ex(m_decryptor_ctx, EVP_aes_256_ctr(), nullptr, m_key.GetUnderlyingData(), + m_initializationVector.GetUnderlyingData()) + && EVP_CIPHER_CTX_set_padding(m_decryptor_ctx, 0))) + { + m_failure = true; + LogErrors(CTR_LOG_TAG); + } + } + + size_t AES_CTR_Cipher_OpenSSL::GetBlockSizeBytes() const + { + return BlockSizeBytes; + } + + size_t AES_CTR_Cipher_OpenSSL::GetKeyLengthBits() const + { + return KeyLengthBits; + } + void AES_CTR_Cipher_OpenSSL::Reset() { OpenSSLCipher::Reset(); InitCipher(); } - size_t AES_GCM_Cipher_OpenSSL::BlockSizeBytes = 16; - size_t AES_GCM_Cipher_OpenSSL::KeyLengthBits = 256; - size_t AES_GCM_Cipher_OpenSSL::IVLengthBytes = 12; - size_t AES_GCM_Cipher_OpenSSL::TagLengthBytes = 16; - - static const char* GCM_LOG_TAG = "AES_GCM_Cipher_OpenSSL"; - + size_t AES_GCM_Cipher_OpenSSL::BlockSizeBytes = 16; + size_t AES_GCM_Cipher_OpenSSL::KeyLengthBits = 256; + size_t AES_GCM_Cipher_OpenSSL::IVLengthBytes = 12; + size_t AES_GCM_Cipher_OpenSSL::TagLengthBytes = 16; + + static const char* GCM_LOG_TAG = "AES_GCM_Cipher_OpenSSL"; + AES_GCM_Cipher_OpenSSL::AES_GCM_Cipher_OpenSSL(const CryptoBuffer& key) : OpenSSLCipher(key, IVLengthBytes) - { - InitCipher(); - } - + { + InitCipher(); + } + AES_GCM_Cipher_OpenSSL::AES_GCM_Cipher_OpenSSL(const CryptoBuffer& key, const CryptoBuffer* aad) : OpenSSLCipher(key, IVLengthBytes), m_aad(*aad) { InitCipher(); } - AES_GCM_Cipher_OpenSSL::AES_GCM_Cipher_OpenSSL(CryptoBuffer&& key, CryptoBuffer&& initializationVector, + AES_GCM_Cipher_OpenSSL::AES_GCM_Cipher_OpenSSL(CryptoBuffer&& key, CryptoBuffer&& initializationVector, CryptoBuffer&& tag, CryptoBuffer&& aad) : OpenSSLCipher(std::move(key), std::move(initializationVector), std::move(tag)), m_aad(std::move(aad)) - { - InitCipher(); - } - + { + InitCipher(); + } + AES_GCM_Cipher_OpenSSL::AES_GCM_Cipher_OpenSSL(const CryptoBuffer& key, const CryptoBuffer& initializationVector, const CryptoBuffer& tag, const CryptoBuffer& aad) : OpenSSLCipher(key, initializationVector, tag), m_aad(std::move(aad)) - { - InitCipher(); - } - - CryptoBuffer AES_GCM_Cipher_OpenSSL::FinalizeEncryption() - { + { + InitCipher(); + } + + CryptoBuffer AES_GCM_Cipher_OpenSSL::FinalizeEncryption() + { if (m_failure) { AWS_LOGSTREAM_FATAL(GCM_LOG_TAG, "Cipher not properly initialized for encryption finalization. Aborting"); @@ -691,38 +691,38 @@ namespace Aws CryptoBuffer finalBlock(GetBlockSizeBytes()); EVP_EncryptFinal_ex(m_encryptor_ctx, finalBlock.GetUnderlyingData(), &writtenSize); - m_tag = CryptoBuffer(TagLengthBytes); + m_tag = CryptoBuffer(TagLengthBytes); if (!EVP_CIPHER_CTX_ctrl(m_encryptor_ctx, EVP_CTRL_GCM_GET_TAG, static_cast<int>(m_tag.GetLength()), - m_tag.GetUnderlyingData())) - { - m_failure = true; - LogErrors(GCM_LOG_TAG); - } - + m_tag.GetUnderlyingData())) + { + m_failure = true; + LogErrors(GCM_LOG_TAG); + } + return CryptoBuffer(); - } - - void AES_GCM_Cipher_OpenSSL::InitCipher() - { + } + + void AES_GCM_Cipher_OpenSSL::InitCipher() + { if (m_failure || !CheckKeyAndIVLength(KeyLengthBits/8, IVLengthBytes)) { return; } - if (!(EVP_EncryptInit_ex(m_encryptor_ctx, EVP_aes_256_gcm(), nullptr, nullptr, nullptr) && - EVP_EncryptInit_ex(m_encryptor_ctx, nullptr, nullptr, m_key.GetUnderlyingData(), - m_initializationVector.GetUnderlyingData()) && - EVP_CIPHER_CTX_set_padding(m_encryptor_ctx, 0)) || - !(EVP_DecryptInit_ex(m_decryptor_ctx, EVP_aes_256_gcm(), nullptr, nullptr, nullptr) && - EVP_DecryptInit_ex(m_decryptor_ctx, nullptr, nullptr, m_key.GetUnderlyingData(), - m_initializationVector.GetUnderlyingData()) && - EVP_CIPHER_CTX_set_padding(m_decryptor_ctx, 0))) - { - m_failure = true; - LogErrors(GCM_LOG_TAG); - return; - } - + if (!(EVP_EncryptInit_ex(m_encryptor_ctx, EVP_aes_256_gcm(), nullptr, nullptr, nullptr) && + EVP_EncryptInit_ex(m_encryptor_ctx, nullptr, nullptr, m_key.GetUnderlyingData(), + m_initializationVector.GetUnderlyingData()) && + EVP_CIPHER_CTX_set_padding(m_encryptor_ctx, 0)) || + !(EVP_DecryptInit_ex(m_decryptor_ctx, EVP_aes_256_gcm(), nullptr, nullptr, nullptr) && + EVP_DecryptInit_ex(m_decryptor_ctx, nullptr, nullptr, m_key.GetUnderlyingData(), + m_initializationVector.GetUnderlyingData()) && + EVP_CIPHER_CTX_set_padding(m_decryptor_ctx, 0))) + { + m_failure = true; + LogErrors(GCM_LOG_TAG); + return; + } + if (m_aad.GetLength() > 0) { int outLen = 0; @@ -735,246 +735,246 @@ namespace Aws } } - //tag should always be set in GCM decrypt mode - if (m_tag.GetLength() > 0) - { - if (m_tag.GetLength() < TagLengthBytes) - { + //tag should always be set in GCM decrypt mode + if (m_tag.GetLength() > 0) + { + if (m_tag.GetLength() < TagLengthBytes) + { AWS_LOGSTREAM_ERROR(GCM_LOG_TAG, "Illegal attempt to decrypt an AES GCM payload without a valid tag set: tag length=" << m_tag.GetLength()); - m_failure = true; - return; - } - + m_failure = true; + return; + } + if (!EVP_CIPHER_CTX_ctrl(m_decryptor_ctx, EVP_CTRL_GCM_SET_TAG, static_cast<int>(m_tag.GetLength()), m_tag.GetUnderlyingData())) - { - m_failure = true; - LogErrors(GCM_LOG_TAG); - } - } - } - - size_t AES_GCM_Cipher_OpenSSL::GetBlockSizeBytes() const - { - return BlockSizeBytes; - } - - size_t AES_GCM_Cipher_OpenSSL::GetKeyLengthBits() const - { - return KeyLengthBits; - } - - size_t AES_GCM_Cipher_OpenSSL::GetTagLengthBytes() const - { - return TagLengthBytes; - } - + { + m_failure = true; + LogErrors(GCM_LOG_TAG); + } + } + } + + size_t AES_GCM_Cipher_OpenSSL::GetBlockSizeBytes() const + { + return BlockSizeBytes; + } + + size_t AES_GCM_Cipher_OpenSSL::GetKeyLengthBits() const + { + return KeyLengthBits; + } + + size_t AES_GCM_Cipher_OpenSSL::GetTagLengthBytes() const + { + return TagLengthBytes; + } + void AES_GCM_Cipher_OpenSSL::Reset() { OpenSSLCipher::Reset(); InitCipher(); } - size_t AES_KeyWrap_Cipher_OpenSSL::KeyLengthBits = 256; - size_t AES_KeyWrap_Cipher_OpenSSL::BlockSizeBytes = 8; - static const unsigned char INTEGRITY_VALUE = 0xA6; - static const size_t MIN_CEK_LENGTH_BYTES = 128 / 8; - - static const char* KEY_WRAP_TAG = "AES_KeyWrap_Cipher_OpenSSL"; - - AES_KeyWrap_Cipher_OpenSSL::AES_KeyWrap_Cipher_OpenSSL(const CryptoBuffer& key) : OpenSSLCipher(key, 0) - { - InitCipher(); - } - - CryptoBuffer AES_KeyWrap_Cipher_OpenSSL::EncryptBuffer(const CryptoBuffer& plainText) - { + size_t AES_KeyWrap_Cipher_OpenSSL::KeyLengthBits = 256; + size_t AES_KeyWrap_Cipher_OpenSSL::BlockSizeBytes = 8; + static const unsigned char INTEGRITY_VALUE = 0xA6; + static const size_t MIN_CEK_LENGTH_BYTES = 128 / 8; + + static const char* KEY_WRAP_TAG = "AES_KeyWrap_Cipher_OpenSSL"; + + AES_KeyWrap_Cipher_OpenSSL::AES_KeyWrap_Cipher_OpenSSL(const CryptoBuffer& key) : OpenSSLCipher(key, 0) + { + InitCipher(); + } + + CryptoBuffer AES_KeyWrap_Cipher_OpenSSL::EncryptBuffer(const CryptoBuffer& plainText) + { if (!m_failure) { m_workingKeyBuffer = CryptoBuffer({&m_workingKeyBuffer, (CryptoBuffer*) &plainText}); } - return CryptoBuffer(); - } - - CryptoBuffer AES_KeyWrap_Cipher_OpenSSL::FinalizeEncryption() - { - if (m_failure) - { - AWS_LOGSTREAM_FATAL(KEY_WRAP_TAG, "Cipher not properly initialized for encryption finalization. Aborting"); - return CryptoBuffer(); - } - - if (m_workingKeyBuffer.GetLength() < MIN_CEK_LENGTH_BYTES) - { - AWS_LOGSTREAM_ERROR(KEY_WRAP_TAG, "Incorrect input length of " << m_workingKeyBuffer.GetLength()); - m_failure = true; - return CryptoBuffer(); - } - - //the following is an in place implementation of + return CryptoBuffer(); + } + + CryptoBuffer AES_KeyWrap_Cipher_OpenSSL::FinalizeEncryption() + { + if (m_failure) + { + AWS_LOGSTREAM_FATAL(KEY_WRAP_TAG, "Cipher not properly initialized for encryption finalization. Aborting"); + return CryptoBuffer(); + } + + if (m_workingKeyBuffer.GetLength() < MIN_CEK_LENGTH_BYTES) + { + AWS_LOGSTREAM_ERROR(KEY_WRAP_TAG, "Incorrect input length of " << m_workingKeyBuffer.GetLength()); + m_failure = true; + return CryptoBuffer(); + } + + //the following is an in place implementation of //RFC 3394 using the alternate in-place implementation. - //we use one in-place buffer instead of the copy at the end. - //the one letter variable names are meant to directly reflect the variables in the RFC - CryptoBuffer cipherText(m_workingKeyBuffer.GetLength() + BlockSizeBytes); - - //put the integrity check register in the first 8 bytes of the final buffer. - memset(cipherText.GetUnderlyingData(), INTEGRITY_VALUE, BlockSizeBytes); - unsigned char* a = cipherText.GetUnderlyingData(); - - //put the register buffer after the integrity check register - memcpy(cipherText.GetUnderlyingData() + BlockSizeBytes, m_workingKeyBuffer.GetUnderlyingData(), - m_workingKeyBuffer.GetLength()); - unsigned char* r = cipherText.GetUnderlyingData() + BlockSizeBytes; - - int n = static_cast<int>(m_workingKeyBuffer.GetLength() / BlockSizeBytes); - - //temporary encryption buffer - CryptoBuffer b(BlockSizeBytes * 2); - int outLen = static_cast<int>(b.GetLength()); - - //concatenation buffer - CryptoBuffer tempInput(BlockSizeBytes * 2); - - for (int j = 0; j <= 5; ++j) - { - for (int i = 1; i <= n; ++i) - { - //concat A and R[i], A should be most significant and then R[i] should be least significant. - memcpy(tempInput.GetUnderlyingData(), a, BlockSizeBytes); - memcpy(tempInput.GetUnderlyingData() + BlockSizeBytes, r, BlockSizeBytes); - - //encrypt the concatenated A and R[I] and store it in B - if (!EVP_EncryptUpdate(m_encryptor_ctx, b.GetUnderlyingData(), &outLen, - tempInput.GetUnderlyingData(), static_cast<int>(tempInput.GetLength()))) - { - LogErrors(KEY_WRAP_TAG); - m_failure = true; - return CryptoBuffer(); - } - - unsigned char t = static_cast<unsigned char>((n * j) + i); - //put the 64 MSB ^ T into A - memcpy(a, b.GetUnderlyingData(), BlockSizeBytes); - a[7] ^= t; - //put the 64 LSB into R[i] - memcpy(r, b.GetUnderlyingData() + BlockSizeBytes, BlockSizeBytes); - //increment i -> R[i] - r += BlockSizeBytes; - } - //reset R - r = cipherText.GetUnderlyingData() + BlockSizeBytes; - } - - return cipherText; - } - - CryptoBuffer AES_KeyWrap_Cipher_OpenSSL::DecryptBuffer(const CryptoBuffer& cipherText) - { + //we use one in-place buffer instead of the copy at the end. + //the one letter variable names are meant to directly reflect the variables in the RFC + CryptoBuffer cipherText(m_workingKeyBuffer.GetLength() + BlockSizeBytes); + + //put the integrity check register in the first 8 bytes of the final buffer. + memset(cipherText.GetUnderlyingData(), INTEGRITY_VALUE, BlockSizeBytes); + unsigned char* a = cipherText.GetUnderlyingData(); + + //put the register buffer after the integrity check register + memcpy(cipherText.GetUnderlyingData() + BlockSizeBytes, m_workingKeyBuffer.GetUnderlyingData(), + m_workingKeyBuffer.GetLength()); + unsigned char* r = cipherText.GetUnderlyingData() + BlockSizeBytes; + + int n = static_cast<int>(m_workingKeyBuffer.GetLength() / BlockSizeBytes); + + //temporary encryption buffer + CryptoBuffer b(BlockSizeBytes * 2); + int outLen = static_cast<int>(b.GetLength()); + + //concatenation buffer + CryptoBuffer tempInput(BlockSizeBytes * 2); + + for (int j = 0; j <= 5; ++j) + { + for (int i = 1; i <= n; ++i) + { + //concat A and R[i], A should be most significant and then R[i] should be least significant. + memcpy(tempInput.GetUnderlyingData(), a, BlockSizeBytes); + memcpy(tempInput.GetUnderlyingData() + BlockSizeBytes, r, BlockSizeBytes); + + //encrypt the concatenated A and R[I] and store it in B + if (!EVP_EncryptUpdate(m_encryptor_ctx, b.GetUnderlyingData(), &outLen, + tempInput.GetUnderlyingData(), static_cast<int>(tempInput.GetLength()))) + { + LogErrors(KEY_WRAP_TAG); + m_failure = true; + return CryptoBuffer(); + } + + unsigned char t = static_cast<unsigned char>((n * j) + i); + //put the 64 MSB ^ T into A + memcpy(a, b.GetUnderlyingData(), BlockSizeBytes); + a[7] ^= t; + //put the 64 LSB into R[i] + memcpy(r, b.GetUnderlyingData() + BlockSizeBytes, BlockSizeBytes); + //increment i -> R[i] + r += BlockSizeBytes; + } + //reset R + r = cipherText.GetUnderlyingData() + BlockSizeBytes; + } + + return cipherText; + } + + CryptoBuffer AES_KeyWrap_Cipher_OpenSSL::DecryptBuffer(const CryptoBuffer& cipherText) + { if (!m_failure) { m_workingKeyBuffer = CryptoBuffer({&m_workingKeyBuffer, (CryptoBuffer*)&cipherText}); } - return CryptoBuffer(); - } - - CryptoBuffer AES_KeyWrap_Cipher_OpenSSL::FinalizeDecryption() - { - if (m_failure) - { - AWS_LOGSTREAM_FATAL(KEY_WRAP_TAG, "Cipher not properly initialized for decryption finalization. Aborting"); - return CryptoBuffer(); - } - - if (m_workingKeyBuffer.GetLength() < MIN_CEK_LENGTH_BYTES + BlockSizeBytes) - { - AWS_LOGSTREAM_ERROR(KEY_WRAP_TAG, "Incorrect input length of " << m_workingKeyBuffer.GetLength()); - m_failure = true; - return CryptoBuffer(); - } - - //the following is an in place implementation of - //RFC 3394 using the alternate in-place implementation. - //we use one in-place buffer instead of the copy at the end. - //the one letter variable names are meant to directly reflect the variables in the RFC - CryptoBuffer plainText(m_workingKeyBuffer.GetLength() - BlockSizeBytes); - memcpy(plainText.GetUnderlyingData(), m_workingKeyBuffer.GetUnderlyingData() + BlockSizeBytes, plainText.GetLength()); - - //integrity register should be the first 8 bytes of the cipher text - unsigned char* a = m_workingKeyBuffer.GetUnderlyingData(); - - //in-place register is the plaintext. For decryption, start at the last array position (8 bytes before the end); - unsigned char* r = plainText.GetUnderlyingData() + plainText.GetLength() - BlockSizeBytes; - - int n = static_cast<int>(plainText.GetLength() / BlockSizeBytes); - - //temporary encryption buffer - CryptoBuffer b(BlockSizeBytes * 10); - int outLen = static_cast<int>(b.GetLength()); - - //concatenation buffer - CryptoBuffer tempInput(BlockSizeBytes * 2); - - for(int j = 5; j >= 0; --j) - { - for(int i = n; i >= 1; --i) - { - //concat - //A ^ t - memcpy(tempInput.GetUnderlyingData(), a, BlockSizeBytes); - unsigned char t = static_cast<unsigned char>((n * j) + i); - tempInput[7] ^= t; - //R[i] - memcpy(tempInput.GetUnderlyingData() + BlockSizeBytes, r, BlockSizeBytes); - - //Decrypt the concatenated buffer - if(!EVP_DecryptUpdate(m_decryptor_ctx, b.GetUnderlyingData(), &outLen, - tempInput.GetUnderlyingData(), static_cast<int>(tempInput.GetLength()))) - { - m_failure = true; - LogErrors(KEY_WRAP_TAG); - return CryptoBuffer(); - } - - //set A to MSB 64 bits of decrypted result - memcpy(a, b.GetUnderlyingData(), BlockSizeBytes); - //set R[i] to LSB 64 bits of decrypted result - memcpy(r, b.GetUnderlyingData() + BlockSizeBytes, BlockSizeBytes); - //decrement i -> R[i] - r -= BlockSizeBytes; - } - - r = plainText.GetUnderlyingData() + plainText.GetLength() - BlockSizeBytes; - } - - //here we perform the integrity check to make sure A == 0xA6A6A6A6A6A6A6A6 - for(size_t i = 0; i < BlockSizeBytes; ++i) - { - if(a[i] != INTEGRITY_VALUE) - { - m_failure = true; - AWS_LOGSTREAM_ERROR(KEY_WRAP_TAG, "Integrity check failed for key wrap decryption."); - return CryptoBuffer(); - } - } - - return plainText; - } - - void AES_KeyWrap_Cipher_OpenSSL::InitCipher() - { + return CryptoBuffer(); + } + + CryptoBuffer AES_KeyWrap_Cipher_OpenSSL::FinalizeDecryption() + { + if (m_failure) + { + AWS_LOGSTREAM_FATAL(KEY_WRAP_TAG, "Cipher not properly initialized for decryption finalization. Aborting"); + return CryptoBuffer(); + } + + if (m_workingKeyBuffer.GetLength() < MIN_CEK_LENGTH_BYTES + BlockSizeBytes) + { + AWS_LOGSTREAM_ERROR(KEY_WRAP_TAG, "Incorrect input length of " << m_workingKeyBuffer.GetLength()); + m_failure = true; + return CryptoBuffer(); + } + + //the following is an in place implementation of + //RFC 3394 using the alternate in-place implementation. + //we use one in-place buffer instead of the copy at the end. + //the one letter variable names are meant to directly reflect the variables in the RFC + CryptoBuffer plainText(m_workingKeyBuffer.GetLength() - BlockSizeBytes); + memcpy(plainText.GetUnderlyingData(), m_workingKeyBuffer.GetUnderlyingData() + BlockSizeBytes, plainText.GetLength()); + + //integrity register should be the first 8 bytes of the cipher text + unsigned char* a = m_workingKeyBuffer.GetUnderlyingData(); + + //in-place register is the plaintext. For decryption, start at the last array position (8 bytes before the end); + unsigned char* r = plainText.GetUnderlyingData() + plainText.GetLength() - BlockSizeBytes; + + int n = static_cast<int>(plainText.GetLength() / BlockSizeBytes); + + //temporary encryption buffer + CryptoBuffer b(BlockSizeBytes * 10); + int outLen = static_cast<int>(b.GetLength()); + + //concatenation buffer + CryptoBuffer tempInput(BlockSizeBytes * 2); + + for(int j = 5; j >= 0; --j) + { + for(int i = n; i >= 1; --i) + { + //concat + //A ^ t + memcpy(tempInput.GetUnderlyingData(), a, BlockSizeBytes); + unsigned char t = static_cast<unsigned char>((n * j) + i); + tempInput[7] ^= t; + //R[i] + memcpy(tempInput.GetUnderlyingData() + BlockSizeBytes, r, BlockSizeBytes); + + //Decrypt the concatenated buffer + if(!EVP_DecryptUpdate(m_decryptor_ctx, b.GetUnderlyingData(), &outLen, + tempInput.GetUnderlyingData(), static_cast<int>(tempInput.GetLength()))) + { + m_failure = true; + LogErrors(KEY_WRAP_TAG); + return CryptoBuffer(); + } + + //set A to MSB 64 bits of decrypted result + memcpy(a, b.GetUnderlyingData(), BlockSizeBytes); + //set R[i] to LSB 64 bits of decrypted result + memcpy(r, b.GetUnderlyingData() + BlockSizeBytes, BlockSizeBytes); + //decrement i -> R[i] + r -= BlockSizeBytes; + } + + r = plainText.GetUnderlyingData() + plainText.GetLength() - BlockSizeBytes; + } + + //here we perform the integrity check to make sure A == 0xA6A6A6A6A6A6A6A6 + for(size_t i = 0; i < BlockSizeBytes; ++i) + { + if(a[i] != INTEGRITY_VALUE) + { + m_failure = true; + AWS_LOGSTREAM_ERROR(KEY_WRAP_TAG, "Integrity check failed for key wrap decryption."); + return CryptoBuffer(); + } + } + + return plainText; + } + + void AES_KeyWrap_Cipher_OpenSSL::InitCipher() + { if (m_failure || !CheckKeyAndIVLength(KeyLengthBits/8, 0)) { return; } - if (!(EVP_EncryptInit_ex(m_encryptor_ctx, EVP_aes_256_ecb(), nullptr, m_key.GetUnderlyingData(), nullptr) && - EVP_CIPHER_CTX_set_padding(m_encryptor_ctx, 0)) || - !(EVP_DecryptInit_ex(m_decryptor_ctx, EVP_aes_256_ecb(), nullptr, m_key.GetUnderlyingData(), nullptr) && - EVP_CIPHER_CTX_set_padding(m_decryptor_ctx, 0))) - { - m_failure = true; - LogErrors(KEY_WRAP_TAG); - } - } + if (!(EVP_EncryptInit_ex(m_encryptor_ctx, EVP_aes_256_ecb(), nullptr, m_key.GetUnderlyingData(), nullptr) && + EVP_CIPHER_CTX_set_padding(m_encryptor_ctx, 0)) || + !(EVP_DecryptInit_ex(m_decryptor_ctx, EVP_aes_256_ecb(), nullptr, m_key.GetUnderlyingData(), nullptr) && + EVP_CIPHER_CTX_set_padding(m_decryptor_ctx, 0))) + { + m_failure = true; + LogErrors(KEY_WRAP_TAG); + } + } void AES_KeyWrap_Cipher_OpenSSL::Reset() { @@ -982,6 +982,6 @@ namespace Aws OpenSSLCipher::Reset(); InitCipher(); } - } - } -} + } + } +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/json/JsonSerializer.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/json/JsonSerializer.cpp index 9b785d1995..cbf7d01678 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/json/JsonSerializer.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/json/JsonSerializer.cpp @@ -2,190 +2,190 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/utils/json/JsonSerializer.h> - -#include <iterator> -#include <algorithm> -#include <aws/core/utils/memory/stl/AWSStringStream.h> + +#include <aws/core/utils/json/JsonSerializer.h> + +#include <iterator> +#include <algorithm> +#include <aws/core/utils/memory/stl/AWSStringStream.h> #include <aws/core/utils/StringUtils.h> - -using namespace Aws::Utils; -using namespace Aws::Utils::Json; - -JsonValue::JsonValue() : m_wasParseSuccessful(true) -{ - m_value = nullptr; -} - -JsonValue::JsonValue(cJSON* value) : - m_value(cJSON_Duplicate(value, true /* recurse */)), - m_wasParseSuccessful(true) -{ -} - -JsonValue::JsonValue(const Aws::String& value) : m_wasParseSuccessful(true) -{ - const char* return_parse_end; - m_value = cJSON_ParseWithOpts(value.c_str(), &return_parse_end, 1/*require_null_terminated*/); - - if (!m_value || cJSON_IsInvalid(m_value)) - { - m_wasParseSuccessful = false; - m_errorMessage = "Failed to parse JSON at: "; - m_errorMessage += return_parse_end; - } -} - -JsonValue::JsonValue(Aws::IStream& istream) : m_wasParseSuccessful(true) -{ - Aws::StringStream memoryStream; - std::copy(std::istreambuf_iterator<char>(istream), std::istreambuf_iterator<char>(), std::ostreambuf_iterator<char>(memoryStream)); - const char* return_parse_end; - const auto input = memoryStream.str(); - m_value = cJSON_ParseWithOpts(input.c_str(), &return_parse_end, 1/*require_null_terminated*/); - - if (!m_value || cJSON_IsInvalid(m_value)) - { - m_wasParseSuccessful = false; - m_errorMessage = "Failed to parse JSON. Invalid input at: "; - m_errorMessage += return_parse_end; - } -} - -JsonValue::JsonValue(const JsonValue& value) : - m_value(cJSON_Duplicate(value.m_value, true/*recurse*/)), - m_wasParseSuccessful(value.m_wasParseSuccessful), - m_errorMessage(value.m_errorMessage) -{ -} - -JsonValue::JsonValue(JsonValue&& value) : - m_value(value.m_value), - m_wasParseSuccessful(value.m_wasParseSuccessful), - m_errorMessage(std::move(value.m_errorMessage)) -{ - value.m_value = nullptr; -} - -void JsonValue::Destroy() -{ - cJSON_Delete(m_value); -} - -JsonValue::~JsonValue() -{ - Destroy(); -} - -JsonValue& JsonValue::operator=(const JsonValue& other) -{ - if (this == &other) - { - return *this; - } - - Destroy(); - m_value = cJSON_Duplicate(other.m_value, true /*recurse*/); - m_wasParseSuccessful = other.m_wasParseSuccessful; - m_errorMessage = other.m_errorMessage; - return *this; -} - -JsonValue& JsonValue::operator=(JsonValue&& other) -{ - if (this == &other) - { - return *this; - } - - using std::swap; - swap(m_value, other.m_value); - swap(m_errorMessage, other.m_errorMessage); - m_wasParseSuccessful = other.m_wasParseSuccessful; - return *this; -} - -static void AddOrReplace(cJSON* root, const char* key, cJSON* value) -{ - const auto existing = cJSON_GetObjectItemCaseSensitive(root, key); - if (existing) - { - cJSON_ReplaceItemInObjectCaseSensitive(root, key, value); - } - else - { - cJSON_AddItemToObject(root, key, value); - } -} - -JsonValue& JsonValue::WithString(const char* key, const Aws::String& value) -{ - if (!m_value) - { - m_value = cJSON_CreateObject(); - } - - const auto val = cJSON_CreateString(value.c_str()); - AddOrReplace(m_value, key, val); - return *this; -} - -JsonValue& JsonValue::WithString(const Aws::String& key, const Aws::String& value) -{ - return WithString(key.c_str(), value); -} - -JsonValue& JsonValue::AsString(const Aws::String& value) -{ - Destroy(); - m_value = cJSON_CreateString(value.c_str()); - return *this; -} - -JsonValue& JsonValue::WithBool(const char* key, bool value) -{ - if (!m_value) - { - m_value = cJSON_CreateObject(); - } - - const auto val = cJSON_CreateBool(value); - AddOrReplace(m_value, key, val); - return *this; -} - -JsonValue& JsonValue::WithBool(const Aws::String& key, bool value) -{ - return WithBool(key.c_str(), value); -} - -JsonValue& JsonValue::AsBool(bool value) -{ - Destroy(); - m_value = cJSON_CreateBool(value); - return *this; -} - -JsonValue& JsonValue::WithInteger(const char* key, int value) -{ - return WithDouble(key, static_cast<double>(value)); -} - -JsonValue& JsonValue::WithInteger(const Aws::String& key, int value) -{ - return WithDouble(key.c_str(), static_cast<double>(value)); -} - -JsonValue& JsonValue::AsInteger(int value) -{ - Destroy(); - m_value = cJSON_CreateNumber(static_cast<double>(value)); - return *this; -} - -JsonValue& JsonValue::WithInt64(const char* key, long long value) -{ + +using namespace Aws::Utils; +using namespace Aws::Utils::Json; + +JsonValue::JsonValue() : m_wasParseSuccessful(true) +{ + m_value = nullptr; +} + +JsonValue::JsonValue(cJSON* value) : + m_value(cJSON_Duplicate(value, true /* recurse */)), + m_wasParseSuccessful(true) +{ +} + +JsonValue::JsonValue(const Aws::String& value) : m_wasParseSuccessful(true) +{ + const char* return_parse_end; + m_value = cJSON_ParseWithOpts(value.c_str(), &return_parse_end, 1/*require_null_terminated*/); + + if (!m_value || cJSON_IsInvalid(m_value)) + { + m_wasParseSuccessful = false; + m_errorMessage = "Failed to parse JSON at: "; + m_errorMessage += return_parse_end; + } +} + +JsonValue::JsonValue(Aws::IStream& istream) : m_wasParseSuccessful(true) +{ + Aws::StringStream memoryStream; + std::copy(std::istreambuf_iterator<char>(istream), std::istreambuf_iterator<char>(), std::ostreambuf_iterator<char>(memoryStream)); + const char* return_parse_end; + const auto input = memoryStream.str(); + m_value = cJSON_ParseWithOpts(input.c_str(), &return_parse_end, 1/*require_null_terminated*/); + + if (!m_value || cJSON_IsInvalid(m_value)) + { + m_wasParseSuccessful = false; + m_errorMessage = "Failed to parse JSON. Invalid input at: "; + m_errorMessage += return_parse_end; + } +} + +JsonValue::JsonValue(const JsonValue& value) : + m_value(cJSON_Duplicate(value.m_value, true/*recurse*/)), + m_wasParseSuccessful(value.m_wasParseSuccessful), + m_errorMessage(value.m_errorMessage) +{ +} + +JsonValue::JsonValue(JsonValue&& value) : + m_value(value.m_value), + m_wasParseSuccessful(value.m_wasParseSuccessful), + m_errorMessage(std::move(value.m_errorMessage)) +{ + value.m_value = nullptr; +} + +void JsonValue::Destroy() +{ + cJSON_Delete(m_value); +} + +JsonValue::~JsonValue() +{ + Destroy(); +} + +JsonValue& JsonValue::operator=(const JsonValue& other) +{ + if (this == &other) + { + return *this; + } + + Destroy(); + m_value = cJSON_Duplicate(other.m_value, true /*recurse*/); + m_wasParseSuccessful = other.m_wasParseSuccessful; + m_errorMessage = other.m_errorMessage; + return *this; +} + +JsonValue& JsonValue::operator=(JsonValue&& other) +{ + if (this == &other) + { + return *this; + } + + using std::swap; + swap(m_value, other.m_value); + swap(m_errorMessage, other.m_errorMessage); + m_wasParseSuccessful = other.m_wasParseSuccessful; + return *this; +} + +static void AddOrReplace(cJSON* root, const char* key, cJSON* value) +{ + const auto existing = cJSON_GetObjectItemCaseSensitive(root, key); + if (existing) + { + cJSON_ReplaceItemInObjectCaseSensitive(root, key, value); + } + else + { + cJSON_AddItemToObject(root, key, value); + } +} + +JsonValue& JsonValue::WithString(const char* key, const Aws::String& value) +{ + if (!m_value) + { + m_value = cJSON_CreateObject(); + } + + const auto val = cJSON_CreateString(value.c_str()); + AddOrReplace(m_value, key, val); + return *this; +} + +JsonValue& JsonValue::WithString(const Aws::String& key, const Aws::String& value) +{ + return WithString(key.c_str(), value); +} + +JsonValue& JsonValue::AsString(const Aws::String& value) +{ + Destroy(); + m_value = cJSON_CreateString(value.c_str()); + return *this; +} + +JsonValue& JsonValue::WithBool(const char* key, bool value) +{ + if (!m_value) + { + m_value = cJSON_CreateObject(); + } + + const auto val = cJSON_CreateBool(value); + AddOrReplace(m_value, key, val); + return *this; +} + +JsonValue& JsonValue::WithBool(const Aws::String& key, bool value) +{ + return WithBool(key.c_str(), value); +} + +JsonValue& JsonValue::AsBool(bool value) +{ + Destroy(); + m_value = cJSON_CreateBool(value); + return *this; +} + +JsonValue& JsonValue::WithInteger(const char* key, int value) +{ + return WithDouble(key, static_cast<double>(value)); +} + +JsonValue& JsonValue::WithInteger(const Aws::String& key, int value) +{ + return WithDouble(key.c_str(), static_cast<double>(value)); +} + +JsonValue& JsonValue::AsInteger(int value) +{ + Destroy(); + m_value = cJSON_CreateNumber(static_cast<double>(value)); + return *this; +} + +JsonValue& JsonValue::WithInt64(const char* key, long long value) +{ if (!m_value) { m_value = cJSON_CreateObject(); @@ -194,261 +194,261 @@ JsonValue& JsonValue::WithInt64(const char* key, long long value) const auto val = cJSON_CreateInt64(value); AddOrReplace(m_value, key, val); return *this; -} - -JsonValue& JsonValue::WithInt64(const Aws::String& key, long long value) -{ +} + +JsonValue& JsonValue::WithInt64(const Aws::String& key, long long value) +{ return WithInt64(key.c_str(), value); -} - -JsonValue& JsonValue::AsInt64(long long value) -{ +} + +JsonValue& JsonValue::AsInt64(long long value) +{ Destroy(); m_value = cJSON_CreateInt64(value); return *this; -} - -JsonValue& JsonValue::WithDouble(const char* key, double value) -{ - if (!m_value) - { - m_value = cJSON_CreateObject(); - } - - const auto val = cJSON_CreateNumber(value); - AddOrReplace(m_value, key, val); - return *this; -} - -JsonValue& JsonValue::WithDouble(const Aws::String& key, double value) -{ - return WithDouble(key.c_str(), value); -} - -JsonValue& JsonValue::AsDouble(double value) -{ - Destroy(); - m_value = cJSON_CreateNumber(value); - return *this; -} - -JsonValue& JsonValue::WithArray(const char* key, const Array<Aws::String>& array) -{ - if (!m_value) - { - m_value = cJSON_CreateObject(); - } - - auto arrayValue = cJSON_CreateArray(); - for (unsigned i = 0; i < array.GetLength(); ++i) - { - cJSON_AddItemToArray(arrayValue, cJSON_CreateString(array[i].c_str())); - } - - AddOrReplace(m_value, key, arrayValue); - return *this; -} - -JsonValue& JsonValue::WithArray(const Aws::String& key, const Array<Aws::String>& array) -{ - return WithArray(key.c_str(), array); -} - -JsonValue& JsonValue::WithArray(const Aws::String& key, const Array<JsonValue>& array) -{ - if (!m_value) - { - m_value = cJSON_CreateObject(); - } - - auto arrayValue = cJSON_CreateArray(); - for (unsigned i = 0; i < array.GetLength(); ++i) - { - cJSON_AddItemToArray(arrayValue, cJSON_Duplicate(array[i].m_value, true /*recurse*/)); - } - - AddOrReplace(m_value, key.c_str(), arrayValue); - return *this; -} - -JsonValue& JsonValue::WithArray(const Aws::String& key, Array<JsonValue>&& array) -{ - if (!m_value) - { - m_value = cJSON_CreateObject(); - } - - auto arrayValue = cJSON_CreateArray(); - for (unsigned i = 0; i < array.GetLength(); ++i) - { - cJSON_AddItemToArray(arrayValue, array[i].m_value); - array[i].m_value = nullptr; - } - - AddOrReplace(m_value, key.c_str(), arrayValue); - return *this; -} - -JsonValue& JsonValue::AsArray(const Array<JsonValue>& array) -{ - auto arrayValue = cJSON_CreateArray(); - for (unsigned i = 0; i < array.GetLength(); ++i) - { - cJSON_AddItemToArray(arrayValue, cJSON_Duplicate(array[i].m_value, true /*recurse*/)); - } - - Destroy(); - m_value = arrayValue; - return *this; -} - -JsonValue& JsonValue::AsArray(Array<JsonValue>&& array) -{ - auto arrayValue = cJSON_CreateArray(); - for (unsigned i = 0; i < array.GetLength(); ++i) - { - cJSON_AddItemToArray(arrayValue, array[i].m_value); - array[i].m_value = nullptr; - } - - Destroy(); - m_value = arrayValue; - return *this; -} - -JsonValue& JsonValue::WithObject(const char* key, const JsonValue& value) -{ - if (!m_value) - { - m_value = cJSON_CreateObject(); - } - - const auto copy = value.m_value == nullptr ? cJSON_CreateObject() : cJSON_Duplicate(value.m_value, true /*recurse*/); - AddOrReplace(m_value, key, copy); - return *this; -} - -JsonValue& JsonValue::WithObject(const Aws::String& key, const JsonValue& value) -{ - return WithObject(key.c_str(), value); -} - -JsonValue& JsonValue::WithObject(const char* key, JsonValue&& value) -{ - if (!m_value) - { - m_value = cJSON_CreateObject(); - } - - AddOrReplace(m_value, key, value.m_value == nullptr ? cJSON_CreateObject() : value.m_value); - value.m_value = nullptr; - return *this; -} - -JsonValue& JsonValue::WithObject(const Aws::String& key, JsonValue&& value) -{ - return WithObject(key.c_str(), std::move(value)); -} - -JsonValue& JsonValue::AsObject(const JsonValue& value) -{ - *this = value; - return *this; -} - -JsonValue& JsonValue::AsObject(JsonValue && value) -{ - *this = std::move(value); - return *this; -} - -bool JsonValue::operator==(const JsonValue& other) const -{ - return cJSON_Compare(m_value, other.m_value, true /*case-sensitive*/) != 0; -} - -bool JsonValue::operator!=(const JsonValue& other) const -{ - return !(*this == other); -} - -JsonView JsonValue::View() const -{ - return *this; -} - -JsonView::JsonView() : m_value(nullptr) -{ -} - -JsonView::JsonView(const JsonValue& val) : m_value(val.m_value) -{ -} - -JsonView::JsonView(cJSON* val) : m_value(val) -{ -} - -JsonView& JsonView::operator=(const JsonValue& v) -{ - m_value = v.m_value; - return *this; -} - -JsonView& JsonView::operator=(cJSON* val) -{ - m_value = val; - return *this; -} - -Aws::String JsonView::GetString(const Aws::String& key) const -{ - assert(m_value); - auto item = cJSON_GetObjectItemCaseSensitive(m_value, key.c_str()); - auto str = cJSON_GetStringValue(item); - return str ? str : ""; -} - -Aws::String JsonView::AsString() const -{ - const char* str = cJSON_GetStringValue(m_value); - if (str == nullptr) - { - return {}; - } - return str; -} - -bool JsonView::GetBool(const Aws::String& key) const -{ - assert(m_value); - auto item = cJSON_GetObjectItemCaseSensitive(m_value, key.c_str()); - assert(item); - return item->valueint != 0; -} - -bool JsonView::AsBool() const -{ - assert(cJSON_IsBool(m_value)); - return cJSON_IsTrue(m_value) != 0; -} - -int JsonView::GetInteger(const Aws::String& key) const -{ - assert(m_value); - auto item = cJSON_GetObjectItemCaseSensitive(m_value, key.c_str()); - assert(item); - return item->valueint; -} - -int JsonView::AsInteger() const -{ - assert(cJSON_IsNumber(m_value)); // can be double or value larger than int_max, but at least not UB - return m_value->valueint; -} - -int64_t JsonView::GetInt64(const Aws::String& key) const -{ +} + +JsonValue& JsonValue::WithDouble(const char* key, double value) +{ + if (!m_value) + { + m_value = cJSON_CreateObject(); + } + + const auto val = cJSON_CreateNumber(value); + AddOrReplace(m_value, key, val); + return *this; +} + +JsonValue& JsonValue::WithDouble(const Aws::String& key, double value) +{ + return WithDouble(key.c_str(), value); +} + +JsonValue& JsonValue::AsDouble(double value) +{ + Destroy(); + m_value = cJSON_CreateNumber(value); + return *this; +} + +JsonValue& JsonValue::WithArray(const char* key, const Array<Aws::String>& array) +{ + if (!m_value) + { + m_value = cJSON_CreateObject(); + } + + auto arrayValue = cJSON_CreateArray(); + for (unsigned i = 0; i < array.GetLength(); ++i) + { + cJSON_AddItemToArray(arrayValue, cJSON_CreateString(array[i].c_str())); + } + + AddOrReplace(m_value, key, arrayValue); + return *this; +} + +JsonValue& JsonValue::WithArray(const Aws::String& key, const Array<Aws::String>& array) +{ + return WithArray(key.c_str(), array); +} + +JsonValue& JsonValue::WithArray(const Aws::String& key, const Array<JsonValue>& array) +{ + if (!m_value) + { + m_value = cJSON_CreateObject(); + } + + auto arrayValue = cJSON_CreateArray(); + for (unsigned i = 0; i < array.GetLength(); ++i) + { + cJSON_AddItemToArray(arrayValue, cJSON_Duplicate(array[i].m_value, true /*recurse*/)); + } + + AddOrReplace(m_value, key.c_str(), arrayValue); + return *this; +} + +JsonValue& JsonValue::WithArray(const Aws::String& key, Array<JsonValue>&& array) +{ + if (!m_value) + { + m_value = cJSON_CreateObject(); + } + + auto arrayValue = cJSON_CreateArray(); + for (unsigned i = 0; i < array.GetLength(); ++i) + { + cJSON_AddItemToArray(arrayValue, array[i].m_value); + array[i].m_value = nullptr; + } + + AddOrReplace(m_value, key.c_str(), arrayValue); + return *this; +} + +JsonValue& JsonValue::AsArray(const Array<JsonValue>& array) +{ + auto arrayValue = cJSON_CreateArray(); + for (unsigned i = 0; i < array.GetLength(); ++i) + { + cJSON_AddItemToArray(arrayValue, cJSON_Duplicate(array[i].m_value, true /*recurse*/)); + } + + Destroy(); + m_value = arrayValue; + return *this; +} + +JsonValue& JsonValue::AsArray(Array<JsonValue>&& array) +{ + auto arrayValue = cJSON_CreateArray(); + for (unsigned i = 0; i < array.GetLength(); ++i) + { + cJSON_AddItemToArray(arrayValue, array[i].m_value); + array[i].m_value = nullptr; + } + + Destroy(); + m_value = arrayValue; + return *this; +} + +JsonValue& JsonValue::WithObject(const char* key, const JsonValue& value) +{ + if (!m_value) + { + m_value = cJSON_CreateObject(); + } + + const auto copy = value.m_value == nullptr ? cJSON_CreateObject() : cJSON_Duplicate(value.m_value, true /*recurse*/); + AddOrReplace(m_value, key, copy); + return *this; +} + +JsonValue& JsonValue::WithObject(const Aws::String& key, const JsonValue& value) +{ + return WithObject(key.c_str(), value); +} + +JsonValue& JsonValue::WithObject(const char* key, JsonValue&& value) +{ + if (!m_value) + { + m_value = cJSON_CreateObject(); + } + + AddOrReplace(m_value, key, value.m_value == nullptr ? cJSON_CreateObject() : value.m_value); + value.m_value = nullptr; + return *this; +} + +JsonValue& JsonValue::WithObject(const Aws::String& key, JsonValue&& value) +{ + return WithObject(key.c_str(), std::move(value)); +} + +JsonValue& JsonValue::AsObject(const JsonValue& value) +{ + *this = value; + return *this; +} + +JsonValue& JsonValue::AsObject(JsonValue && value) +{ + *this = std::move(value); + return *this; +} + +bool JsonValue::operator==(const JsonValue& other) const +{ + return cJSON_Compare(m_value, other.m_value, true /*case-sensitive*/) != 0; +} + +bool JsonValue::operator!=(const JsonValue& other) const +{ + return !(*this == other); +} + +JsonView JsonValue::View() const +{ + return *this; +} + +JsonView::JsonView() : m_value(nullptr) +{ +} + +JsonView::JsonView(const JsonValue& val) : m_value(val.m_value) +{ +} + +JsonView::JsonView(cJSON* val) : m_value(val) +{ +} + +JsonView& JsonView::operator=(const JsonValue& v) +{ + m_value = v.m_value; + return *this; +} + +JsonView& JsonView::operator=(cJSON* val) +{ + m_value = val; + return *this; +} + +Aws::String JsonView::GetString(const Aws::String& key) const +{ + assert(m_value); + auto item = cJSON_GetObjectItemCaseSensitive(m_value, key.c_str()); + auto str = cJSON_GetStringValue(item); + return str ? str : ""; +} + +Aws::String JsonView::AsString() const +{ + const char* str = cJSON_GetStringValue(m_value); + if (str == nullptr) + { + return {}; + } + return str; +} + +bool JsonView::GetBool(const Aws::String& key) const +{ + assert(m_value); + auto item = cJSON_GetObjectItemCaseSensitive(m_value, key.c_str()); + assert(item); + return item->valueint != 0; +} + +bool JsonView::AsBool() const +{ + assert(cJSON_IsBool(m_value)); + return cJSON_IsTrue(m_value) != 0; +} + +int JsonView::GetInteger(const Aws::String& key) const +{ + assert(m_value); + auto item = cJSON_GetObjectItemCaseSensitive(m_value, key.c_str()); + assert(item); + return item->valueint; +} + +int JsonView::AsInteger() const +{ + assert(cJSON_IsNumber(m_value)); // can be double or value larger than int_max, but at least not UB + return m_value->valueint; +} + +int64_t JsonView::GetInt64(const Aws::String& key) const +{ assert(m_value); auto item = cJSON_GetObjectItemCaseSensitive(m_value, key.c_str()); assert(item); @@ -460,11 +460,11 @@ int64_t JsonView::GetInt64(const Aws::String& key) const { return static_cast<int64_t>(item->valuedouble); } -} - -int64_t JsonView::AsInt64() const -{ - assert(cJSON_IsNumber(m_value)); +} + +int64_t JsonView::AsInt64() const +{ + assert(cJSON_IsNumber(m_value)); if (m_value->valuestring) { return Aws::Utils::StringUtils::ConvertToInt64(m_value->valuestring); @@ -473,193 +473,193 @@ int64_t JsonView::AsInt64() const { return static_cast<int64_t>(m_value->valuedouble); } -} - -double JsonView::GetDouble(const Aws::String& key) const -{ - assert(m_value); - auto item = cJSON_GetObjectItemCaseSensitive(m_value, key.c_str()); - assert(item); - return item->valuedouble; -} - -double JsonView::AsDouble() const -{ - assert(cJSON_IsNumber(m_value)); - return m_value->valuedouble; -} - -JsonView JsonView::GetObject(const Aws::String& key) const -{ - assert(m_value); - auto item = cJSON_GetObjectItemCaseSensitive(m_value, key.c_str()); - return item; -} - -JsonView JsonView::AsObject() const -{ +} + +double JsonView::GetDouble(const Aws::String& key) const +{ + assert(m_value); + auto item = cJSON_GetObjectItemCaseSensitive(m_value, key.c_str()); + assert(item); + return item->valuedouble; +} + +double JsonView::AsDouble() const +{ + assert(cJSON_IsNumber(m_value)); + return m_value->valuedouble; +} + +JsonView JsonView::GetObject(const Aws::String& key) const +{ + assert(m_value); + auto item = cJSON_GetObjectItemCaseSensitive(m_value, key.c_str()); + return item; +} + +JsonView JsonView::AsObject() const +{ assert(cJSON_IsObject(m_value) || cJSON_IsNull(m_value)); - return m_value; -} - -Array<JsonView> JsonView::GetArray(const Aws::String& key) const -{ - assert(m_value); - auto array = cJSON_GetObjectItemCaseSensitive(m_value, key.c_str()); - assert(cJSON_IsArray(array)); - Array<JsonView> returnArray(cJSON_GetArraySize(array)); - - auto element = array->child; - for (unsigned i = 0; element && i < returnArray.GetLength(); ++i, element = element->next) - { - returnArray[i] = element; - } - - return returnArray; -} - -Array<JsonView> JsonView::AsArray() const -{ - assert(cJSON_IsArray(m_value)); - Array<JsonView> returnArray(cJSON_GetArraySize(m_value)); - - auto element = m_value->child; - - for (unsigned i = 0; element && i < returnArray.GetLength(); ++i, element = element->next) - { - returnArray[i] = element; - } - - return returnArray; -} - -Aws::Map<Aws::String, JsonView> JsonView::GetAllObjects() const -{ - Aws::Map<Aws::String, JsonView> valueMap; - if (!m_value) - { - return valueMap; - } - - for (auto iter = m_value->child; iter; iter = iter->next) - { - valueMap.emplace(std::make_pair(Aws::String(iter->string), JsonView(iter))); - } - - return valueMap; -} - -bool JsonView::ValueExists(const Aws::String& key) const -{ - if (!cJSON_IsObject(m_value)) - { - return false; - } - - auto item = cJSON_GetObjectItemCaseSensitive(m_value, key.c_str()); - return !(item == nullptr || cJSON_IsNull(item)); -} - -bool JsonView::KeyExists(const Aws::String& key) const -{ - if (!cJSON_IsObject(m_value)) - { - return false; - } - - return cJSON_GetObjectItemCaseSensitive(m_value, key.c_str()) != nullptr;; -} - -bool JsonView::IsObject() const -{ - return cJSON_IsObject(m_value) != 0; -} - -bool JsonView::IsBool() const -{ - return cJSON_IsBool(m_value) != 0; -} - -bool JsonView::IsString() const -{ - return cJSON_IsString(m_value) != 0; -} - -bool JsonView::IsIntegerType() const -{ - if (!cJSON_IsNumber(m_value)) - { - return false; - } - + return m_value; +} + +Array<JsonView> JsonView::GetArray(const Aws::String& key) const +{ + assert(m_value); + auto array = cJSON_GetObjectItemCaseSensitive(m_value, key.c_str()); + assert(cJSON_IsArray(array)); + Array<JsonView> returnArray(cJSON_GetArraySize(array)); + + auto element = array->child; + for (unsigned i = 0; element && i < returnArray.GetLength(); ++i, element = element->next) + { + returnArray[i] = element; + } + + return returnArray; +} + +Array<JsonView> JsonView::AsArray() const +{ + assert(cJSON_IsArray(m_value)); + Array<JsonView> returnArray(cJSON_GetArraySize(m_value)); + + auto element = m_value->child; + + for (unsigned i = 0; element && i < returnArray.GetLength(); ++i, element = element->next) + { + returnArray[i] = element; + } + + return returnArray; +} + +Aws::Map<Aws::String, JsonView> JsonView::GetAllObjects() const +{ + Aws::Map<Aws::String, JsonView> valueMap; + if (!m_value) + { + return valueMap; + } + + for (auto iter = m_value->child; iter; iter = iter->next) + { + valueMap.emplace(std::make_pair(Aws::String(iter->string), JsonView(iter))); + } + + return valueMap; +} + +bool JsonView::ValueExists(const Aws::String& key) const +{ + if (!cJSON_IsObject(m_value)) + { + return false; + } + + auto item = cJSON_GetObjectItemCaseSensitive(m_value, key.c_str()); + return !(item == nullptr || cJSON_IsNull(item)); +} + +bool JsonView::KeyExists(const Aws::String& key) const +{ + if (!cJSON_IsObject(m_value)) + { + return false; + } + + return cJSON_GetObjectItemCaseSensitive(m_value, key.c_str()) != nullptr;; +} + +bool JsonView::IsObject() const +{ + return cJSON_IsObject(m_value) != 0; +} + +bool JsonView::IsBool() const +{ + return cJSON_IsBool(m_value) != 0; +} + +bool JsonView::IsString() const +{ + return cJSON_IsString(m_value) != 0; +} + +bool JsonView::IsIntegerType() const +{ + if (!cJSON_IsNumber(m_value)) + { + return false; + } + if (m_value->valuestring) { Aws::String valueString = m_value->valuestring; return std::all_of(valueString.begin(), valueString.end(), [](unsigned char c){ return ::isdigit(c) || c == '+' || c == '-'; }); } - return m_value->valuedouble == static_cast<long long>(m_value->valuedouble); -} - -bool JsonView::IsFloatingPointType() const -{ - if (!cJSON_IsNumber(m_value)) - { - return false; - } - + return m_value->valuedouble == static_cast<long long>(m_value->valuedouble); +} + +bool JsonView::IsFloatingPointType() const +{ + if (!cJSON_IsNumber(m_value)) + { + return false; + } + if (m_value->valuestring) { Aws::String valueString = m_value->valuestring; return std::any_of(valueString.begin(), valueString.end(), [](unsigned char c){ return !::isdigit(c) && c != '+' && c != '-'; }); } - return m_value->valuedouble != static_cast<long long>(m_value->valuedouble); -} - -bool JsonView::IsListType() const -{ - return cJSON_IsArray(m_value) != 0; -} - -bool JsonView::IsNull() const -{ - return cJSON_IsNull(m_value) != 0; -} - -Aws::String JsonView::WriteCompact(bool treatAsObject) const -{ - if (!m_value) - { - if (treatAsObject) - { - return "{}"; - } + return m_value->valuedouble != static_cast<long long>(m_value->valuedouble); +} + +bool JsonView::IsListType() const +{ + return cJSON_IsArray(m_value) != 0; +} + +bool JsonView::IsNull() const +{ + return cJSON_IsNull(m_value) != 0; +} + +Aws::String JsonView::WriteCompact(bool treatAsObject) const +{ + if (!m_value) + { + if (treatAsObject) + { + return "{}"; + } return {}; - } - - auto temp = cJSON_PrintUnformatted(m_value); - Aws::String out(temp); - cJSON_free(temp); - return out; -} - -Aws::String JsonView::WriteReadable(bool treatAsObject) const -{ - if (!m_value) - { - if (treatAsObject) - { - return "{\n}\n"; - } + } + + auto temp = cJSON_PrintUnformatted(m_value); + Aws::String out(temp); + cJSON_free(temp); + return out; +} + +Aws::String JsonView::WriteReadable(bool treatAsObject) const +{ + if (!m_value) + { + if (treatAsObject) + { + return "{\n}\n"; + } return {}; - } - - auto temp = cJSON_Print(m_value); - Aws::String out(temp); - cJSON_free(temp); - return out; -} - -JsonValue JsonView::Materialize() const -{ - return m_value; -} + } + + auto temp = cJSON_Print(m_value); + Aws::String out(temp); + cJSON_free(temp); + return out; +} + +JsonValue JsonView::Materialize() const +{ + return m_value; +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/AWSLogging.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/AWSLogging.cpp index fc1b9fcc2e..82a49da4fb 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/AWSLogging.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/AWSLogging.cpp @@ -2,50 +2,50 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - - -#include <aws/core/utils/logging/AWSLogging.h> -#include <aws/core/utils/logging/LogSystemInterface.h> -#include <aws/core/utils/memory/stl/AWSStack.h> - -#include <memory> - -using namespace Aws::Utils; -using namespace Aws::Utils::Logging; - -static std::shared_ptr<LogSystemInterface> AWSLogSystem(nullptr); -static std::shared_ptr<LogSystemInterface> OldLogger(nullptr); - -namespace Aws -{ -namespace Utils -{ -namespace Logging { - -void InitializeAWSLogging(const std::shared_ptr<LogSystemInterface> &logSystem) { - AWSLogSystem = logSystem; -} - -void ShutdownAWSLogging(void) { - InitializeAWSLogging(nullptr); -} - -LogSystemInterface *GetLogSystem() { - return AWSLogSystem.get(); -} - -void PushLogger(const std::shared_ptr<LogSystemInterface> &logSystem) -{ - OldLogger = AWSLogSystem; - AWSLogSystem = logSystem; -} - -void PopLogger() -{ - AWSLogSystem = OldLogger; - OldLogger = nullptr; -} - -} // namespace Logging -} // namespace Utils -} // namespace Aws
\ No newline at end of file + + +#include <aws/core/utils/logging/AWSLogging.h> +#include <aws/core/utils/logging/LogSystemInterface.h> +#include <aws/core/utils/memory/stl/AWSStack.h> + +#include <memory> + +using namespace Aws::Utils; +using namespace Aws::Utils::Logging; + +static std::shared_ptr<LogSystemInterface> AWSLogSystem(nullptr); +static std::shared_ptr<LogSystemInterface> OldLogger(nullptr); + +namespace Aws +{ +namespace Utils +{ +namespace Logging { + +void InitializeAWSLogging(const std::shared_ptr<LogSystemInterface> &logSystem) { + AWSLogSystem = logSystem; +} + +void ShutdownAWSLogging(void) { + InitializeAWSLogging(nullptr); +} + +LogSystemInterface *GetLogSystem() { + return AWSLogSystem.get(); +} + +void PushLogger(const std::shared_ptr<LogSystemInterface> &logSystem) +{ + OldLogger = AWSLogSystem; + AWSLogSystem = logSystem; +} + +void PopLogger() +{ + AWSLogSystem = OldLogger; + OldLogger = nullptr; +} + +} // namespace Logging +} // namespace Utils +} // namespace Aws
\ No newline at end of file diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/ConsoleLogSystem.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/ConsoleLogSystem.cpp index dec7cef82f..ac7cbba8c0 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/ConsoleLogSystem.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/ConsoleLogSystem.cpp @@ -2,19 +2,19 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - - -#include <aws/core/utils/logging/ConsoleLogSystem.h> - -#include <iostream> - -using namespace Aws::Utils; -using namespace Aws::Utils::Logging; - -void ConsoleLogSystem::ProcessFormattedStatement(Aws::String&& statement) -{ - std::cout << statement; -} + + +#include <aws/core/utils/logging/ConsoleLogSystem.h> + +#include <iostream> + +using namespace Aws::Utils; +using namespace Aws::Utils::Logging; + +void ConsoleLogSystem::ProcessFormattedStatement(Aws::String&& statement) +{ + std::cout << statement; +} void ConsoleLogSystem::Flush() { diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/DefaultLogSystem.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/DefaultLogSystem.cpp index 7286bb6378..065dc9b037 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/DefaultLogSystem.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/DefaultLogSystem.cpp @@ -2,114 +2,114 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - - -#include <aws/core/utils/logging/DefaultLogSystem.h> - -#include <aws/core/utils/DateTime.h> -#include <aws/core/utils/memory/stl/AWSVector.h> - -#include <fstream> - -using namespace Aws::Utils; -using namespace Aws::Utils::Logging; - -static const char* AllocationTag = "DefaultLogSystem"; -static const int BUFFERED_MSG_COUNT = 100; - + + +#include <aws/core/utils/logging/DefaultLogSystem.h> + +#include <aws/core/utils/DateTime.h> +#include <aws/core/utils/memory/stl/AWSVector.h> + +#include <fstream> + +using namespace Aws::Utils; +using namespace Aws::Utils::Logging; + +static const char* AllocationTag = "DefaultLogSystem"; +static const int BUFFERED_MSG_COUNT = 100; + static std::shared_ptr<Aws::OFStream> MakeDefaultLogFile(const Aws::String& filenamePrefix) -{ - Aws::String newFileName = filenamePrefix + DateTime::CalculateGmtTimestampAsString("%Y-%m-%d-%H") + ".log"; - return Aws::MakeShared<Aws::OFStream>(AllocationTag, newFileName.c_str(), Aws::OFStream::out | Aws::OFStream::app); -} - -static void LogThread(DefaultLogSystem::LogSynchronizationData* syncData, const std::shared_ptr<Aws::OStream>& logFile, const Aws::String& filenamePrefix, bool rollLog) -{ - // localtime requires access to env. variables to get Timezone, which is not thread-safe - int32_t lastRolledHour = DateTime::Now().GetHour(false /*localtime*/); - std::shared_ptr<Aws::OStream> log = logFile; - - for(;;) - { - std::unique_lock<std::mutex> locker(syncData->m_logQueueMutex); +{ + Aws::String newFileName = filenamePrefix + DateTime::CalculateGmtTimestampAsString("%Y-%m-%d-%H") + ".log"; + return Aws::MakeShared<Aws::OFStream>(AllocationTag, newFileName.c_str(), Aws::OFStream::out | Aws::OFStream::app); +} + +static void LogThread(DefaultLogSystem::LogSynchronizationData* syncData, const std::shared_ptr<Aws::OStream>& logFile, const Aws::String& filenamePrefix, bool rollLog) +{ + // localtime requires access to env. variables to get Timezone, which is not thread-safe + int32_t lastRolledHour = DateTime::Now().GetHour(false /*localtime*/); + std::shared_ptr<Aws::OStream> log = logFile; + + for(;;) + { + std::unique_lock<std::mutex> locker(syncData->m_logQueueMutex); syncData->m_queueSignal.wait(locker, [&](){ return syncData->m_stopLogging == true || syncData->m_queuedLogMessages.size() > 0; } ); - - if (syncData->m_stopLogging && syncData->m_queuedLogMessages.size() == 0) - { - break; - } - - Aws::Vector<Aws::String> messages(std::move(syncData->m_queuedLogMessages)); - syncData->m_queuedLogMessages.reserve(BUFFERED_MSG_COUNT); - - locker.unlock(); - - if (messages.size() > 0) - { - if (rollLog) - { - // localtime requires access to env. variables to get Timezone, which is not thread-safe - int32_t currentHour = DateTime::Now().GetHour(false /*localtime*/); - if (currentHour != lastRolledHour) - { - log = MakeDefaultLogFile(filenamePrefix); - lastRolledHour = currentHour; - } - } - - for (const auto& msg : messages) - { - (*log) << msg; - } - - log->flush(); - } - } -} - -DefaultLogSystem::DefaultLogSystem(LogLevel logLevel, const std::shared_ptr<Aws::OStream>& logFile) : - Base(logLevel), - m_syncData(), - m_loggingThread() -{ - m_loggingThread = std::thread(LogThread, &m_syncData, logFile, "", false); -} - -DefaultLogSystem::DefaultLogSystem(LogLevel logLevel, const Aws::String& filenamePrefix) : - Base(logLevel), - m_syncData(), - m_loggingThread() -{ - m_loggingThread = std::thread(LogThread, &m_syncData, MakeDefaultLogFile(filenamePrefix), filenamePrefix, true); -} - -DefaultLogSystem::~DefaultLogSystem() -{ - { - std::lock_guard<std::mutex> locker(m_syncData.m_logQueueMutex); + + if (syncData->m_stopLogging && syncData->m_queuedLogMessages.size() == 0) + { + break; + } + + Aws::Vector<Aws::String> messages(std::move(syncData->m_queuedLogMessages)); + syncData->m_queuedLogMessages.reserve(BUFFERED_MSG_COUNT); + + locker.unlock(); + + if (messages.size() > 0) + { + if (rollLog) + { + // localtime requires access to env. variables to get Timezone, which is not thread-safe + int32_t currentHour = DateTime::Now().GetHour(false /*localtime*/); + if (currentHour != lastRolledHour) + { + log = MakeDefaultLogFile(filenamePrefix); + lastRolledHour = currentHour; + } + } + + for (const auto& msg : messages) + { + (*log) << msg; + } + + log->flush(); + } + } +} + +DefaultLogSystem::DefaultLogSystem(LogLevel logLevel, const std::shared_ptr<Aws::OStream>& logFile) : + Base(logLevel), + m_syncData(), + m_loggingThread() +{ + m_loggingThread = std::thread(LogThread, &m_syncData, logFile, "", false); +} + +DefaultLogSystem::DefaultLogSystem(LogLevel logLevel, const Aws::String& filenamePrefix) : + Base(logLevel), + m_syncData(), + m_loggingThread() +{ + m_loggingThread = std::thread(LogThread, &m_syncData, MakeDefaultLogFile(filenamePrefix), filenamePrefix, true); +} + +DefaultLogSystem::~DefaultLogSystem() +{ + { + std::lock_guard<std::mutex> locker(m_syncData.m_logQueueMutex); m_syncData.m_stopLogging = true; - } - - m_syncData.m_queueSignal.notify_one(); - - m_loggingThread.join(); -} - -void DefaultLogSystem::ProcessFormattedStatement(Aws::String&& statement) -{ - std::unique_lock<std::mutex> locker(m_syncData.m_logQueueMutex); - m_syncData.m_queuedLogMessages.emplace_back(std::move(statement)); - if(m_syncData.m_queuedLogMessages.size() >= BUFFERED_MSG_COUNT) - { - locker.unlock(); - m_syncData.m_queueSignal.notify_one(); - } - else - { - locker.unlock(); - } -} - + } + + m_syncData.m_queueSignal.notify_one(); + + m_loggingThread.join(); +} + +void DefaultLogSystem::ProcessFormattedStatement(Aws::String&& statement) +{ + std::unique_lock<std::mutex> locker(m_syncData.m_logQueueMutex); + m_syncData.m_queuedLogMessages.emplace_back(std::move(statement)); + if(m_syncData.m_queuedLogMessages.size() >= BUFFERED_MSG_COUNT) + { + locker.unlock(); + m_syncData.m_queueSignal.notify_one(); + } + else + { + locker.unlock(); + } +} + void DefaultLogSystem::Flush() { m_syncData.m_queueSignal.notify_one(); diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/FormattedLogSystem.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/FormattedLogSystem.cpp index 41c4d7e09c..8cca6d89a8 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/FormattedLogSystem.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/FormattedLogSystem.cpp @@ -2,98 +2,98 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - - -#include <aws/core/utils/logging/FormattedLogSystem.h> - -#include <aws/core/utils/DateTime.h> -#include <aws/core/utils/Array.h> - -#include <fstream> -#include <cstdarg> -#include <stdio.h> -#include <thread> - -using namespace Aws::Utils; -using namespace Aws::Utils::Logging; - -static Aws::String CreateLogPrefixLine(LogLevel logLevel, const char* tag) -{ - Aws::StringStream ss; - - switch(logLevel) - { - case LogLevel::Error: - ss << "[ERROR] "; - break; - - case LogLevel::Fatal: - ss << "[FATAL] "; - break; - - case LogLevel::Warn: - ss << "[WARN] "; - break; - - case LogLevel::Info: - ss << "[INFO] "; - break; - - case LogLevel::Debug: - ss << "[DEBUG] "; - break; - - case LogLevel::Trace: - ss << "[TRACE] "; - break; - - default: - ss << "[UNKOWN] "; - break; - } - + + +#include <aws/core/utils/logging/FormattedLogSystem.h> + +#include <aws/core/utils/DateTime.h> +#include <aws/core/utils/Array.h> + +#include <fstream> +#include <cstdarg> +#include <stdio.h> +#include <thread> + +using namespace Aws::Utils; +using namespace Aws::Utils::Logging; + +static Aws::String CreateLogPrefixLine(LogLevel logLevel, const char* tag) +{ + Aws::StringStream ss; + + switch(logLevel) + { + case LogLevel::Error: + ss << "[ERROR] "; + break; + + case LogLevel::Fatal: + ss << "[FATAL] "; + break; + + case LogLevel::Warn: + ss << "[WARN] "; + break; + + case LogLevel::Info: + ss << "[INFO] "; + break; + + case LogLevel::Debug: + ss << "[DEBUG] "; + break; + + case LogLevel::Trace: + ss << "[TRACE] "; + break; + + default: + ss << "[UNKOWN] "; + break; + } + ss << DateTime::Now().CalculateGmtTimeWithMsPrecision() << " " << tag << " [" << std::this_thread::get_id() << "] "; - - return ss.str(); -} - -FormattedLogSystem::FormattedLogSystem(LogLevel logLevel) : - m_logLevel(logLevel) -{ -} - -void FormattedLogSystem::Log(LogLevel logLevel, const char* tag, const char* formatStr, ...) -{ - Aws::StringStream ss; - ss << CreateLogPrefixLine(logLevel, tag); - - std::va_list args; - va_start(args, formatStr); - - va_list tmp_args; //unfortunately you cannot consume a va_list twice - va_copy(tmp_args, args); //so we have to copy it - #ifdef WIN32 - const int requiredLength = _vscprintf(formatStr, tmp_args) + 1; - #else - const int requiredLength = vsnprintf(nullptr, 0, formatStr, tmp_args) + 1; - #endif - va_end(tmp_args); - - Array<char> outputBuff(requiredLength); - #ifdef WIN32 - vsnprintf_s(outputBuff.GetUnderlyingData(), requiredLength, _TRUNCATE, formatStr, args); - #else - vsnprintf(outputBuff.GetUnderlyingData(), requiredLength, formatStr, args); - #endif // WIN32 - - ss << outputBuff.GetUnderlyingData() << std::endl; - - ProcessFormattedStatement(ss.str()); - - va_end(args); -} - -void FormattedLogSystem::LogStream(LogLevel logLevel, const char* tag, const Aws::OStringStream &message_stream) -{ + + return ss.str(); +} + +FormattedLogSystem::FormattedLogSystem(LogLevel logLevel) : + m_logLevel(logLevel) +{ +} + +void FormattedLogSystem::Log(LogLevel logLevel, const char* tag, const char* formatStr, ...) +{ + Aws::StringStream ss; + ss << CreateLogPrefixLine(logLevel, tag); + + std::va_list args; + va_start(args, formatStr); + + va_list tmp_args; //unfortunately you cannot consume a va_list twice + va_copy(tmp_args, args); //so we have to copy it + #ifdef WIN32 + const int requiredLength = _vscprintf(formatStr, tmp_args) + 1; + #else + const int requiredLength = vsnprintf(nullptr, 0, formatStr, tmp_args) + 1; + #endif + va_end(tmp_args); + + Array<char> outputBuff(requiredLength); + #ifdef WIN32 + vsnprintf_s(outputBuff.GetUnderlyingData(), requiredLength, _TRUNCATE, formatStr, args); + #else + vsnprintf(outputBuff.GetUnderlyingData(), requiredLength, formatStr, args); + #endif // WIN32 + + ss << outputBuff.GetUnderlyingData() << std::endl; + + ProcessFormattedStatement(ss.str()); + + va_end(args); +} + +void FormattedLogSystem::LogStream(LogLevel logLevel, const char* tag, const Aws::OStringStream &message_stream) +{ ProcessFormattedStatement(CreateLogPrefixLine(logLevel, tag) + message_stream.str() + "\n"); -} +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/LogLevel.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/LogLevel.cpp index 9ff1bf3126..643985bd14 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/LogLevel.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/LogLevel.cpp @@ -2,44 +2,44 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/utils/logging/LogLevel.h> - -#include <aws/core/utils/memory/stl/AWSMap.h> -#include <aws/core/utils/memory/stl/AWSString.h> -#include <cassert> - -using namespace Aws::Utils::Logging; - -namespace Aws -{ -namespace Utils -{ -namespace Logging -{ - -Aws::String GetLogLevelName(LogLevel logLevel) + +#include <aws/core/utils/logging/LogLevel.h> + +#include <aws/core/utils/memory/stl/AWSMap.h> +#include <aws/core/utils/memory/stl/AWSString.h> +#include <cassert> + +using namespace Aws::Utils::Logging; + +namespace Aws { - switch (logLevel) - { - case LogLevel::Fatal: - return "FATAL"; - case LogLevel::Error: - return "ERROR"; - case LogLevel::Warn: - return "WARN"; - case LogLevel::Info: - return "INFO"; - case LogLevel::Debug: - return "DEBUG"; - case LogLevel::Trace: - return "TRACE"; - default: - assert(0); - return ""; - } -} - -} // namespace Logging -} // namespace Utils -} // namespace Aws +namespace Utils +{ +namespace Logging +{ + +Aws::String GetLogLevelName(LogLevel logLevel) +{ + switch (logLevel) + { + case LogLevel::Fatal: + return "FATAL"; + case LogLevel::Error: + return "ERROR"; + case LogLevel::Warn: + return "WARN"; + case LogLevel::Info: + return "INFO"; + case LogLevel::Debug: + return "DEBUG"; + case LogLevel::Trace: + return "TRACE"; + default: + assert(0); + return ""; + } +} + +} // namespace Logging +} // namespace Utils +} // namespace Aws diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/memory/AWSMemory.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/memory/AWSMemory.cpp index 96d339d385..361cdc95fc 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/memory/AWSMemory.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/memory/AWSMemory.cpp @@ -2,102 +2,102 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/utils/memory/AWSMemory.h> - -#include <aws/core/utils/memory/MemorySystemInterface.h> + +#include <aws/core/utils/memory/AWSMemory.h> + +#include <aws/core/utils/memory/MemorySystemInterface.h> #include <aws/common/common.h> - -#include <atomic> - -using namespace Aws::Utils; -using namespace Aws::Utils::Memory; - -#ifdef USE_AWS_MEMORY_MANAGEMENT - static MemorySystemInterface* AWSMemorySystem(nullptr); -#endif // USE_AWS_MEMORY_MANAGEMENT - -namespace Aws -{ -namespace Utils -{ -namespace Memory -{ - -void InitializeAWSMemorySystem(MemorySystemInterface& memorySystem) -{ - #ifdef USE_AWS_MEMORY_MANAGEMENT - if(AWSMemorySystem != nullptr) - { - AWSMemorySystem->End(); - } - - AWSMemorySystem = &memorySystem; - AWSMemorySystem->Begin(); - #else - AWS_UNREFERENCED_PARAM(memorySystem); - #endif // USE_AWS_MEMORY_MANAGEMENT -} - -void ShutdownAWSMemorySystem(void) -{ - #ifdef USE_AWS_MEMORY_MANAGEMENT - if(AWSMemorySystem != nullptr) - { - AWSMemorySystem->End(); - } - AWSMemorySystem = nullptr; - #endif // USE_AWS_MEMORY_MANAGEMENT -} - -MemorySystemInterface* GetMemorySystem() -{ - #ifdef USE_AWS_MEMORY_MANAGEMENT - return AWSMemorySystem; - #else - return nullptr; - #endif // USE_AWS_MEMORY_MANAGEMENT -} - -} // namespace Memory -} // namespace Utils - -void* Malloc(const char* allocationTag, size_t allocationSize) -{ - Aws::Utils::Memory::MemorySystemInterface* memorySystem = Aws::Utils::Memory::GetMemorySystem(); - - void* rawMemory = nullptr; - if(memorySystem != nullptr) - { - rawMemory = memorySystem->AllocateMemory(allocationSize, 1, allocationTag); - } - else - { - rawMemory = malloc(allocationSize); - } - - return rawMemory; -} - - -void Free(void* memoryPtr) -{ - if(memoryPtr == nullptr) - { - return; - } - - Aws::Utils::Memory::MemorySystemInterface* memorySystem = Aws::Utils::Memory::GetMemorySystem(); - if(memorySystem != nullptr) - { - memorySystem->FreeMemory(memoryPtr); - } - else - { - free(memoryPtr); - } -} - + +#include <atomic> + +using namespace Aws::Utils; +using namespace Aws::Utils::Memory; + +#ifdef USE_AWS_MEMORY_MANAGEMENT + static MemorySystemInterface* AWSMemorySystem(nullptr); +#endif // USE_AWS_MEMORY_MANAGEMENT + +namespace Aws +{ +namespace Utils +{ +namespace Memory +{ + +void InitializeAWSMemorySystem(MemorySystemInterface& memorySystem) +{ + #ifdef USE_AWS_MEMORY_MANAGEMENT + if(AWSMemorySystem != nullptr) + { + AWSMemorySystem->End(); + } + + AWSMemorySystem = &memorySystem; + AWSMemorySystem->Begin(); + #else + AWS_UNREFERENCED_PARAM(memorySystem); + #endif // USE_AWS_MEMORY_MANAGEMENT +} + +void ShutdownAWSMemorySystem(void) +{ + #ifdef USE_AWS_MEMORY_MANAGEMENT + if(AWSMemorySystem != nullptr) + { + AWSMemorySystem->End(); + } + AWSMemorySystem = nullptr; + #endif // USE_AWS_MEMORY_MANAGEMENT +} + +MemorySystemInterface* GetMemorySystem() +{ + #ifdef USE_AWS_MEMORY_MANAGEMENT + return AWSMemorySystem; + #else + return nullptr; + #endif // USE_AWS_MEMORY_MANAGEMENT +} + +} // namespace Memory +} // namespace Utils + +void* Malloc(const char* allocationTag, size_t allocationSize) +{ + Aws::Utils::Memory::MemorySystemInterface* memorySystem = Aws::Utils::Memory::GetMemorySystem(); + + void* rawMemory = nullptr; + if(memorySystem != nullptr) + { + rawMemory = memorySystem->AllocateMemory(allocationSize, 1, allocationTag); + } + else + { + rawMemory = malloc(allocationSize); + } + + return rawMemory; +} + + +void Free(void* memoryPtr) +{ + if(memoryPtr == nullptr) + { + return; + } + + Aws::Utils::Memory::MemorySystemInterface* memorySystem = Aws::Utils::Memory::GetMemorySystem(); + if(memorySystem != nullptr) + { + memorySystem->FreeMemory(memoryPtr); + } + else + { + free(memoryPtr); + } +} + static void* MemAcquire(aws_allocator* allocator, size_t size) { (void)allocator; // unused; @@ -129,6 +129,6 @@ aws_allocator* get_aws_allocator() return &wrapper; } -} // namespace Aws - - +} // namespace Aws + + diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/memory/stl/SimpleStringStream.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/memory/stl/SimpleStringStream.cpp index 4662749872..faee8777a8 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/memory/stl/SimpleStringStream.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/memory/stl/SimpleStringStream.cpp @@ -2,65 +2,65 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/utils/memory/stl/SimpleStringStream.h> - -namespace Aws -{ - -SimpleStringStream::SimpleStringStream() : - base(&m_streamBuffer), - m_streamBuffer() -{ -} - -SimpleStringStream::SimpleStringStream(const Aws::String& value) : - base(&m_streamBuffer), - m_streamBuffer(value) -{ -} - + +#include <aws/core/utils/memory/stl/SimpleStringStream.h> + +namespace Aws +{ + +SimpleStringStream::SimpleStringStream() : + base(&m_streamBuffer), + m_streamBuffer() +{ +} + +SimpleStringStream::SimpleStringStream(const Aws::String& value) : + base(&m_streamBuffer), + m_streamBuffer(value) +{ +} + void SimpleStringStream::str(const Aws::String& value) -{ - m_streamBuffer.str(value); -} - -// - -SimpleIStringStream::SimpleIStringStream() : - base(&m_streamBuffer), - m_streamBuffer() -{ -} - -SimpleIStringStream::SimpleIStringStream(const Aws::String& value) : - base(&m_streamBuffer), - m_streamBuffer(value) -{ -} - +{ + m_streamBuffer.str(value); +} + +// + +SimpleIStringStream::SimpleIStringStream() : + base(&m_streamBuffer), + m_streamBuffer() +{ +} + +SimpleIStringStream::SimpleIStringStream(const Aws::String& value) : + base(&m_streamBuffer), + m_streamBuffer(value) +{ +} + void SimpleIStringStream::str(const Aws::String& value) -{ - m_streamBuffer.str(value); -} - -// - -SimpleOStringStream::SimpleOStringStream() : - base(&m_streamBuffer), - m_streamBuffer() -{ -} - -SimpleOStringStream::SimpleOStringStream(const Aws::String& value) : - base(&m_streamBuffer), - m_streamBuffer(value) -{ -} - +{ + m_streamBuffer.str(value); +} + +// + +SimpleOStringStream::SimpleOStringStream() : + base(&m_streamBuffer), + m_streamBuffer() +{ +} + +SimpleOStringStream::SimpleOStringStream(const Aws::String& value) : + base(&m_streamBuffer), + m_streamBuffer(value) +{ +} + void SimpleOStringStream::str(const Aws::String& value) -{ - m_streamBuffer.str(value); -} - +{ + m_streamBuffer.str(value); +} + } // namespace Aws diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/stream/PreallocatedStreamBuf.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/stream/PreallocatedStreamBuf.cpp index f656fc8613..a91903a0f3 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/stream/PreallocatedStreamBuf.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/stream/PreallocatedStreamBuf.cpp @@ -1,75 +1,75 @@ - + /** * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/utils/stream/PreallocatedStreamBuf.h> -#include <cassert> - -namespace Aws -{ - namespace Utils - { - namespace Stream - { + +#include <aws/core/utils/stream/PreallocatedStreamBuf.h> +#include <cassert> + +namespace Aws +{ + namespace Utils + { + namespace Stream + { PreallocatedStreamBuf::PreallocatedStreamBuf(unsigned char* buffer, uint64_t lengthToRead) : - m_underlyingBuffer(buffer), m_lengthToRead(lengthToRead) - { + m_underlyingBuffer(buffer), m_lengthToRead(lengthToRead) + { char* end = reinterpret_cast<char*>(m_underlyingBuffer + m_lengthToRead); char* begin = reinterpret_cast<char*>(m_underlyingBuffer); - setp(begin, end); - setg(begin, begin, end); - } - - PreallocatedStreamBuf::pos_type PreallocatedStreamBuf::seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which) - { - if (dir == std::ios_base::beg) - { - return seekpos(off, which); - } - else if (dir == std::ios_base::end) - { - return seekpos(m_lengthToRead - off, which); - } - else if (dir == std::ios_base::cur) - { - if(which == std::ios_base::in) - { + setp(begin, end); + setg(begin, begin, end); + } + + PreallocatedStreamBuf::pos_type PreallocatedStreamBuf::seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which) + { + if (dir == std::ios_base::beg) + { + return seekpos(off, which); + } + else if (dir == std::ios_base::end) + { + return seekpos(m_lengthToRead - off, which); + } + else if (dir == std::ios_base::cur) + { + if(which == std::ios_base::in) + { return seekpos((gptr() - reinterpret_cast<char*>(m_underlyingBuffer)) + off, which); - } - else - { + } + else + { return seekpos((pptr() - reinterpret_cast<char*>(m_underlyingBuffer)) + off, which); - } - } - - return off_type(-1); - } - - PreallocatedStreamBuf::pos_type PreallocatedStreamBuf::seekpos(pos_type pos, std::ios_base::openmode which) - { - assert(static_cast<size_t>(pos) <= m_lengthToRead); - if (static_cast<size_t>(pos) > m_lengthToRead) - { - return pos_type(off_type(-1)); - } - + } + } + + return off_type(-1); + } + + PreallocatedStreamBuf::pos_type PreallocatedStreamBuf::seekpos(pos_type pos, std::ios_base::openmode which) + { + assert(static_cast<size_t>(pos) <= m_lengthToRead); + if (static_cast<size_t>(pos) > m_lengthToRead) + { + return pos_type(off_type(-1)); + } + char* end = reinterpret_cast<char*>(m_underlyingBuffer + m_lengthToRead); char* begin = reinterpret_cast<char*>(m_underlyingBuffer); - - if (which == std::ios_base::in) - { + + if (which == std::ios_base::in) + { setg(begin, begin + static_cast<size_t>(pos), end); - } - - if (which == std::ios_base::out) - { - setp(begin + static_cast<size_t>(pos), end); - } - - return pos; - } - } - } + } + + if (which == std::ios_base::out) + { + setp(begin + static_cast<size_t>(pos), end); + } + + return pos; + } + } + } } diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/stream/ResponseStream.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/stream/ResponseStream.cpp index 6d1f90ed12..afba5ee828 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/stream/ResponseStream.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/stream/ResponseStream.cpp @@ -2,90 +2,90 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/utils/stream/ResponseStream.h> -#include <aws/core/utils/memory/stl/AWSStringStream.h> - -#if defined(_GLIBCXX_FULLY_DYNAMIC_STRING) && _GLIBCXX_FULLY_DYNAMIC_STRING == 0 && defined(__ANDROID__) -#include <aws/core/utils/stream/SimpleStreamBuf.h> -using DefaultStreamBufType = Aws::Utils::Stream::SimpleStreamBuf; -#else -using DefaultStreamBufType = Aws::StringBuf; -#endif - -using namespace Aws::Utils::Stream; - -ResponseStream::ResponseStream(void) : - m_underlyingStream(nullptr) -{ -} - -ResponseStream::ResponseStream(Aws::IOStream* underlyingStreamToManage) : - m_underlyingStream(underlyingStreamToManage) -{ -} - -ResponseStream::ResponseStream(const Aws::IOStreamFactory& factory) : - m_underlyingStream(factory()) -{ -} - -ResponseStream::ResponseStream(ResponseStream&& toMove) : m_underlyingStream(toMove.m_underlyingStream) -{ - toMove.m_underlyingStream = nullptr; -} - -ResponseStream& ResponseStream::operator=(ResponseStream&& toMove) -{ - if(m_underlyingStream == toMove.m_underlyingStream) - { - return *this; - } - - ReleaseStream(); - m_underlyingStream = toMove.m_underlyingStream; - toMove.m_underlyingStream = nullptr; - - return *this; -} - -ResponseStream::~ResponseStream() -{ - ReleaseStream(); -} - -void ResponseStream::ReleaseStream() -{ - if (m_underlyingStream) - { - m_underlyingStream->flush(); - Aws::Delete(m_underlyingStream); - } - - m_underlyingStream = nullptr; -} - -static const char *DEFAULT_STREAM_TAG = "DefaultUnderlyingStream"; - -DefaultUnderlyingStream::DefaultUnderlyingStream() : - Base( Aws::New< DefaultStreamBufType >( DEFAULT_STREAM_TAG ) ) -{} - -DefaultUnderlyingStream::DefaultUnderlyingStream(Aws::UniquePtr<std::streambuf> buf) : - Base(buf.release()) -{} - -DefaultUnderlyingStream::~DefaultUnderlyingStream() -{ - if( rdbuf() ) - { - Aws::Delete( rdbuf() ); - } -} - -static const char* RESPONSE_STREAM_FACTORY_TAG = "ResponseStreamFactory"; - -Aws::IOStream* Aws::Utils::Stream::DefaultResponseStreamFactoryMethod() -{ - return Aws::New<Aws::Utils::Stream::DefaultUnderlyingStream>(RESPONSE_STREAM_FACTORY_TAG); -} + +#include <aws/core/utils/stream/ResponseStream.h> +#include <aws/core/utils/memory/stl/AWSStringStream.h> + +#if defined(_GLIBCXX_FULLY_DYNAMIC_STRING) && _GLIBCXX_FULLY_DYNAMIC_STRING == 0 && defined(__ANDROID__) +#include <aws/core/utils/stream/SimpleStreamBuf.h> +using DefaultStreamBufType = Aws::Utils::Stream::SimpleStreamBuf; +#else +using DefaultStreamBufType = Aws::StringBuf; +#endif + +using namespace Aws::Utils::Stream; + +ResponseStream::ResponseStream(void) : + m_underlyingStream(nullptr) +{ +} + +ResponseStream::ResponseStream(Aws::IOStream* underlyingStreamToManage) : + m_underlyingStream(underlyingStreamToManage) +{ +} + +ResponseStream::ResponseStream(const Aws::IOStreamFactory& factory) : + m_underlyingStream(factory()) +{ +} + +ResponseStream::ResponseStream(ResponseStream&& toMove) : m_underlyingStream(toMove.m_underlyingStream) +{ + toMove.m_underlyingStream = nullptr; +} + +ResponseStream& ResponseStream::operator=(ResponseStream&& toMove) +{ + if(m_underlyingStream == toMove.m_underlyingStream) + { + return *this; + } + + ReleaseStream(); + m_underlyingStream = toMove.m_underlyingStream; + toMove.m_underlyingStream = nullptr; + + return *this; +} + +ResponseStream::~ResponseStream() +{ + ReleaseStream(); +} + +void ResponseStream::ReleaseStream() +{ + if (m_underlyingStream) + { + m_underlyingStream->flush(); + Aws::Delete(m_underlyingStream); + } + + m_underlyingStream = nullptr; +} + +static const char *DEFAULT_STREAM_TAG = "DefaultUnderlyingStream"; + +DefaultUnderlyingStream::DefaultUnderlyingStream() : + Base( Aws::New< DefaultStreamBufType >( DEFAULT_STREAM_TAG ) ) +{} + +DefaultUnderlyingStream::DefaultUnderlyingStream(Aws::UniquePtr<std::streambuf> buf) : + Base(buf.release()) +{} + +DefaultUnderlyingStream::~DefaultUnderlyingStream() +{ + if( rdbuf() ) + { + Aws::Delete( rdbuf() ); + } +} + +static const char* RESPONSE_STREAM_FACTORY_TAG = "ResponseStreamFactory"; + +Aws::IOStream* Aws::Utils::Stream::DefaultResponseStreamFactoryMethod() +{ + return Aws::New<Aws::Utils::Stream::DefaultUnderlyingStream>(RESPONSE_STREAM_FACTORY_TAG); +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/stream/SimpleStreamBuf.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/stream/SimpleStreamBuf.cpp index 6e42994744..06ce057a36 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/stream/SimpleStreamBuf.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/stream/SimpleStreamBuf.cpp @@ -1,239 +1,239 @@ - + /** * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/utils/stream/SimpleStreamBuf.h> - -#include <algorithm> -#include <cassert> -#include <cstring> - -namespace Aws -{ -namespace Utils -{ -namespace Stream -{ - -static const uint32_t DEFAULT_BUFFER_SIZE = 100; -static const char* SIMPLE_STREAMBUF_ALLOCATION_TAG = "SimpleStreamBufTag"; - -SimpleStreamBuf::SimpleStreamBuf() : - m_buffer(nullptr), - m_bufferSize(0) -{ - m_buffer = Aws::NewArray<char>(DEFAULT_BUFFER_SIZE, SIMPLE_STREAMBUF_ALLOCATION_TAG); - m_bufferSize = DEFAULT_BUFFER_SIZE; - - char* begin = m_buffer; - char* end = begin + m_bufferSize; - - setp(begin, end); - setg(begin, begin, begin); -} - -SimpleStreamBuf::SimpleStreamBuf(const Aws::String& value) : - m_buffer(nullptr), - m_bufferSize(0) -{ - size_t baseSize = (std::max)(value.size(), static_cast<std::size_t>(DEFAULT_BUFFER_SIZE)); - - m_buffer = Aws::NewArray<char>(baseSize, SIMPLE_STREAMBUF_ALLOCATION_TAG); - m_bufferSize = baseSize; - - std::memcpy(m_buffer, value.c_str(), value.size()); - - char* begin = m_buffer; - char* end = begin + m_bufferSize; - - setp(begin + value.size(), end); - setg(begin, begin, begin); -} - -SimpleStreamBuf::~SimpleStreamBuf() -{ - if(m_buffer) - { - Aws::DeleteArray<char>(m_buffer); - m_buffer = nullptr; - } - - m_bufferSize = 0; -} - -std::streampos SimpleStreamBuf::seekoff(std::streamoff off, std::ios_base::seekdir dir, std::ios_base::openmode which) -{ - if (dir == std::ios_base::beg) - { - return seekpos(off, which); - } - else if (dir == std::ios_base::end) - { - return seekpos((pptr() - m_buffer) - off, which); - } - else if (dir == std::ios_base::cur) - { - if(which == std::ios_base::in) + +#include <aws/core/utils/stream/SimpleStreamBuf.h> + +#include <algorithm> +#include <cassert> +#include <cstring> + +namespace Aws +{ +namespace Utils +{ +namespace Stream +{ + +static const uint32_t DEFAULT_BUFFER_SIZE = 100; +static const char* SIMPLE_STREAMBUF_ALLOCATION_TAG = "SimpleStreamBufTag"; + +SimpleStreamBuf::SimpleStreamBuf() : + m_buffer(nullptr), + m_bufferSize(0) +{ + m_buffer = Aws::NewArray<char>(DEFAULT_BUFFER_SIZE, SIMPLE_STREAMBUF_ALLOCATION_TAG); + m_bufferSize = DEFAULT_BUFFER_SIZE; + + char* begin = m_buffer; + char* end = begin + m_bufferSize; + + setp(begin, end); + setg(begin, begin, begin); +} + +SimpleStreamBuf::SimpleStreamBuf(const Aws::String& value) : + m_buffer(nullptr), + m_bufferSize(0) +{ + size_t baseSize = (std::max)(value.size(), static_cast<std::size_t>(DEFAULT_BUFFER_SIZE)); + + m_buffer = Aws::NewArray<char>(baseSize, SIMPLE_STREAMBUF_ALLOCATION_TAG); + m_bufferSize = baseSize; + + std::memcpy(m_buffer, value.c_str(), value.size()); + + char* begin = m_buffer; + char* end = begin + m_bufferSize; + + setp(begin + value.size(), end); + setg(begin, begin, begin); +} + +SimpleStreamBuf::~SimpleStreamBuf() +{ + if(m_buffer) + { + Aws::DeleteArray<char>(m_buffer); + m_buffer = nullptr; + } + + m_bufferSize = 0; +} + +std::streampos SimpleStreamBuf::seekoff(std::streamoff off, std::ios_base::seekdir dir, std::ios_base::openmode which) +{ + if (dir == std::ios_base::beg) + { + return seekpos(off, which); + } + else if (dir == std::ios_base::end) + { + return seekpos((pptr() - m_buffer) - off, which); + } + else if (dir == std::ios_base::cur) + { + if(which == std::ios_base::in) + { + return seekpos((gptr() - m_buffer) + off, which); + } + else { - return seekpos((gptr() - m_buffer) + off, which); - } - else - { - return seekpos((pptr() - m_buffer) + off, which); - } - } - - return off_type(-1); -} - -std::streampos SimpleStreamBuf::seekpos(std::streampos pos, std::ios_base::openmode which) -{ - size_t maxSeek = pptr() - m_buffer; - assert(static_cast<size_t>(pos) <= maxSeek); - if (static_cast<size_t>(pos) > maxSeek) - { - return pos_type(off_type(-1)); - } - - if (which == std::ios_base::in) - { - setg(m_buffer, m_buffer + static_cast<size_t>(pos), pptr()); - } - - if (which == std::ios_base::out) - { - setp(m_buffer + static_cast<size_t>(pos), epptr()); - } - - return pos; -} - -bool SimpleStreamBuf::GrowBuffer() -{ - size_t currentSize = m_bufferSize; - size_t newSize = currentSize * 2; - - char* newBuffer = Aws::NewArray<char>(newSize, SIMPLE_STREAMBUF_ALLOCATION_TAG); - if(newBuffer == nullptr) - { - return false; - } - - if(currentSize > 0) - { - std::memcpy(newBuffer, m_buffer, currentSize); - } - - if(m_buffer) - { - Aws::DeleteArray<char>(m_buffer); - } - - m_buffer = newBuffer; - m_bufferSize = newSize; - - return true; -} - -int SimpleStreamBuf::overflow (int c) -{ - auto endOfFile = std::char_traits< char >::eof(); - if(c == endOfFile) - { - return endOfFile; - } - - char* old_begin = m_buffer; - - char *old_pptr = pptr(); - char *old_gptr = gptr(); - char *old_egptr = egptr(); - - size_t currentWritePosition = m_bufferSize; - - if(!GrowBuffer()) - { - return endOfFile; - } - - char* new_begin = m_buffer; - char* new_end = new_begin + m_bufferSize; - - setp(new_begin + (old_pptr - old_begin) + 1, new_end); - setg(new_begin, new_begin + (old_gptr - old_begin), new_begin + (old_egptr - old_begin)); - - auto val = std::char_traits< char >::to_char_type(c); - *(new_begin + currentWritePosition) = val; - - return c; -} - -std::streamsize SimpleStreamBuf::xsputn(const char* s, std::streamsize n) -{ - std::streamsize writeCount = 0; - while(writeCount < n) - { - char* current_pptr = pptr(); - char* current_epptr = epptr(); - - if (current_pptr < current_epptr) - { - std::size_t copySize = (std::min)(static_cast< std::size_t >(n - writeCount), - static_cast< std::size_t >(current_epptr - current_pptr)); - - std::memcpy(current_pptr, s + writeCount, copySize); - writeCount += copySize; - setp(current_pptr + copySize, current_epptr); - setg(m_buffer, gptr(), pptr()); - } - else if (overflow(std::char_traits< char >::to_int_type(*(s + writeCount))) != std::char_traits<char>::eof()) - { - writeCount++; - } - else - { - return writeCount; - } - } - - return writeCount; -} - + return seekpos((pptr() - m_buffer) + off, which); + } + } + + return off_type(-1); +} + +std::streampos SimpleStreamBuf::seekpos(std::streampos pos, std::ios_base::openmode which) +{ + size_t maxSeek = pptr() - m_buffer; + assert(static_cast<size_t>(pos) <= maxSeek); + if (static_cast<size_t>(pos) > maxSeek) + { + return pos_type(off_type(-1)); + } + + if (which == std::ios_base::in) + { + setg(m_buffer, m_buffer + static_cast<size_t>(pos), pptr()); + } + + if (which == std::ios_base::out) + { + setp(m_buffer + static_cast<size_t>(pos), epptr()); + } + + return pos; +} + +bool SimpleStreamBuf::GrowBuffer() +{ + size_t currentSize = m_bufferSize; + size_t newSize = currentSize * 2; + + char* newBuffer = Aws::NewArray<char>(newSize, SIMPLE_STREAMBUF_ALLOCATION_TAG); + if(newBuffer == nullptr) + { + return false; + } + + if(currentSize > 0) + { + std::memcpy(newBuffer, m_buffer, currentSize); + } + + if(m_buffer) + { + Aws::DeleteArray<char>(m_buffer); + } + + m_buffer = newBuffer; + m_bufferSize = newSize; + + return true; +} + +int SimpleStreamBuf::overflow (int c) +{ + auto endOfFile = std::char_traits< char >::eof(); + if(c == endOfFile) + { + return endOfFile; + } + + char* old_begin = m_buffer; + + char *old_pptr = pptr(); + char *old_gptr = gptr(); + char *old_egptr = egptr(); + + size_t currentWritePosition = m_bufferSize; + + if(!GrowBuffer()) + { + return endOfFile; + } + + char* new_begin = m_buffer; + char* new_end = new_begin + m_bufferSize; + + setp(new_begin + (old_pptr - old_begin) + 1, new_end); + setg(new_begin, new_begin + (old_gptr - old_begin), new_begin + (old_egptr - old_begin)); + + auto val = std::char_traits< char >::to_char_type(c); + *(new_begin + currentWritePosition) = val; + + return c; +} + +std::streamsize SimpleStreamBuf::xsputn(const char* s, std::streamsize n) +{ + std::streamsize writeCount = 0; + while(writeCount < n) + { + char* current_pptr = pptr(); + char* current_epptr = epptr(); + + if (current_pptr < current_epptr) + { + std::size_t copySize = (std::min)(static_cast< std::size_t >(n - writeCount), + static_cast< std::size_t >(current_epptr - current_pptr)); + + std::memcpy(current_pptr, s + writeCount, copySize); + writeCount += copySize; + setp(current_pptr + copySize, current_epptr); + setg(m_buffer, gptr(), pptr()); + } + else if (overflow(std::char_traits< char >::to_int_type(*(s + writeCount))) != std::char_traits<char>::eof()) + { + writeCount++; + } + else + { + return writeCount; + } + } + + return writeCount; +} + Aws::String SimpleStreamBuf::str() const -{ - return Aws::String(m_buffer, pptr()); -} - -int SimpleStreamBuf::underflow() -{ - if(egptr() != pptr()) - { - setg(m_buffer, gptr(), pptr()); - } - - if(gptr() != egptr()) - { - return std::char_traits< char >::to_int_type(*gptr()); - } - else - { - return std::char_traits< char >::eof(); - } -} - -void SimpleStreamBuf::str(const Aws::String& value) -{ - char* begin = m_buffer; - char* end = begin + m_bufferSize; - - setp(begin, end); - setg(begin, begin, begin); - - xsputn(value.c_str(), value.size()); -} - -} -} +{ + return Aws::String(m_buffer, pptr()); +} + +int SimpleStreamBuf::underflow() +{ + if(egptr() != pptr()) + { + setg(m_buffer, gptr(), pptr()); + } + + if(gptr() != egptr()) + { + return std::char_traits< char >::to_int_type(*gptr()); + } + else + { + return std::char_traits< char >::eof(); + } +} + +void SimpleStreamBuf::str(const Aws::String& value) +{ + char* begin = m_buffer; + char* end = begin + m_bufferSize; + + setp(begin, end); + setg(begin, begin, begin); + + xsputn(value.c_str(), value.size()); +} + +} +} } diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/threading/Executor.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/threading/Executor.cpp index 4a3c4209c4..d63c66c884 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/threading/Executor.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/threading/Executor.cpp @@ -2,154 +2,154 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/utils/threading/Executor.h> -#include <aws/core/utils/threading/ThreadTask.h> -#include <thread> -#include <cassert> - -static const char* POOLED_CLASS_TAG = "PooledThreadExecutor"; - -using namespace Aws::Utils::Threading; - -bool DefaultExecutor::SubmitToThread(std::function<void()>&& fx) -{ - auto main = [fx, this] { - fx(); - Detach(std::this_thread::get_id()); - }; - - State expected; - do - { - expected = State::Free; - if(m_state.compare_exchange_strong(expected, State::Locked)) - { - std::thread t(main); - const auto id = t.get_id(); // copy the id before we std::move the thread - m_threads.emplace(id, std::move(t)); - m_state = State::Free; - return true; - } - } - while(expected != State::Shutdown); - return false; -} - -void DefaultExecutor::Detach(std::thread::id id) -{ - State expected; - do - { - expected = State::Free; - if(m_state.compare_exchange_strong(expected, State::Locked)) - { - auto it = m_threads.find(id); - assert(it != m_threads.end()); - it->second.detach(); - m_threads.erase(it); - m_state = State::Free; - return; - } + +#include <aws/core/utils/threading/Executor.h> +#include <aws/core/utils/threading/ThreadTask.h> +#include <thread> +#include <cassert> + +static const char* POOLED_CLASS_TAG = "PooledThreadExecutor"; + +using namespace Aws::Utils::Threading; + +bool DefaultExecutor::SubmitToThread(std::function<void()>&& fx) +{ + auto main = [fx, this] { + fx(); + Detach(std::this_thread::get_id()); + }; + + State expected; + do + { + expected = State::Free; + if(m_state.compare_exchange_strong(expected, State::Locked)) + { + std::thread t(main); + const auto id = t.get_id(); // copy the id before we std::move the thread + m_threads.emplace(id, std::move(t)); + m_state = State::Free; + return true; + } } - while(expected != State::Shutdown); -} - -DefaultExecutor::~DefaultExecutor() -{ - auto expected = State::Free; - while(!m_state.compare_exchange_strong(expected, State::Shutdown)) - { - //spin while currently detaching threads finish - assert(expected == State::Locked); + while(expected != State::Shutdown); + return false; +} + +void DefaultExecutor::Detach(std::thread::id id) +{ + State expected; + do + { expected = State::Free; - } - - auto it = m_threads.begin(); - while(!m_threads.empty()) - { - it->second.join(); - it = m_threads.erase(it); - } -} - -PooledThreadExecutor::PooledThreadExecutor(size_t poolSize, OverflowPolicy overflowPolicy) : - m_sync(0, poolSize), m_poolSize(poolSize), m_overflowPolicy(overflowPolicy) -{ - for (size_t index = 0; index < m_poolSize; ++index) - { - m_threadTaskHandles.push_back(Aws::New<ThreadTask>(POOLED_CLASS_TAG, *this)); - } -} - -PooledThreadExecutor::~PooledThreadExecutor() -{ - for(auto threadTask : m_threadTaskHandles) - { - threadTask->StopProcessingWork(); - } - - m_sync.ReleaseAll(); - - for (auto threadTask : m_threadTaskHandles) - { - Aws::Delete(threadTask); - } - - while(m_tasks.size() > 0) - { - std::function<void()>* fn = m_tasks.front(); - m_tasks.pop(); - - if(fn) - { - Aws::Delete(fn); - } - } - -} - -bool PooledThreadExecutor::SubmitToThread(std::function<void()>&& fn) -{ - //avoid the need to do copies inside the lock. Instead lets do a pointer push. - std::function<void()>* fnCpy = Aws::New<std::function<void()>>(POOLED_CLASS_TAG, std::forward<std::function<void()>>(fn)); - - { - std::lock_guard<std::mutex> locker(m_queueLock); - - if (m_overflowPolicy == OverflowPolicy::REJECT_IMMEDIATELY && m_tasks.size() >= m_poolSize) - { - Aws::Delete(fnCpy); - return false; - } - - m_tasks.push(fnCpy); - } - - m_sync.Release(); - - return true; -} - -std::function<void()>* PooledThreadExecutor::PopTask() -{ - std::lock_guard<std::mutex> locker(m_queueLock); - - if (m_tasks.size() > 0) - { - std::function<void()>* fn = m_tasks.front(); - if (fn) - { - m_tasks.pop(); - return fn; - } - } - - return nullptr; -} - -bool PooledThreadExecutor::HasTasks() -{ - std::lock_guard<std::mutex> locker(m_queueLock); - return m_tasks.size() > 0; -} + if(m_state.compare_exchange_strong(expected, State::Locked)) + { + auto it = m_threads.find(id); + assert(it != m_threads.end()); + it->second.detach(); + m_threads.erase(it); + m_state = State::Free; + return; + } + } + while(expected != State::Shutdown); +} + +DefaultExecutor::~DefaultExecutor() +{ + auto expected = State::Free; + while(!m_state.compare_exchange_strong(expected, State::Shutdown)) + { + //spin while currently detaching threads finish + assert(expected == State::Locked); + expected = State::Free; + } + + auto it = m_threads.begin(); + while(!m_threads.empty()) + { + it->second.join(); + it = m_threads.erase(it); + } +} + +PooledThreadExecutor::PooledThreadExecutor(size_t poolSize, OverflowPolicy overflowPolicy) : + m_sync(0, poolSize), m_poolSize(poolSize), m_overflowPolicy(overflowPolicy) +{ + for (size_t index = 0; index < m_poolSize; ++index) + { + m_threadTaskHandles.push_back(Aws::New<ThreadTask>(POOLED_CLASS_TAG, *this)); + } +} + +PooledThreadExecutor::~PooledThreadExecutor() +{ + for(auto threadTask : m_threadTaskHandles) + { + threadTask->StopProcessingWork(); + } + + m_sync.ReleaseAll(); + + for (auto threadTask : m_threadTaskHandles) + { + Aws::Delete(threadTask); + } + + while(m_tasks.size() > 0) + { + std::function<void()>* fn = m_tasks.front(); + m_tasks.pop(); + + if(fn) + { + Aws::Delete(fn); + } + } + +} + +bool PooledThreadExecutor::SubmitToThread(std::function<void()>&& fn) +{ + //avoid the need to do copies inside the lock. Instead lets do a pointer push. + std::function<void()>* fnCpy = Aws::New<std::function<void()>>(POOLED_CLASS_TAG, std::forward<std::function<void()>>(fn)); + + { + std::lock_guard<std::mutex> locker(m_queueLock); + + if (m_overflowPolicy == OverflowPolicy::REJECT_IMMEDIATELY && m_tasks.size() >= m_poolSize) + { + Aws::Delete(fnCpy); + return false; + } + + m_tasks.push(fnCpy); + } + + m_sync.Release(); + + return true; +} + +std::function<void()>* PooledThreadExecutor::PopTask() +{ + std::lock_guard<std::mutex> locker(m_queueLock); + + if (m_tasks.size() > 0) + { + std::function<void()>* fn = m_tasks.front(); + if (fn) + { + m_tasks.pop(); + return fn; + } + } + + return nullptr; +} + +bool PooledThreadExecutor::HasTasks() +{ + std::lock_guard<std::mutex> locker(m_queueLock); + return m_tasks.size() > 0; +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/threading/ReaderWriterLock.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/threading/ReaderWriterLock.cpp index ddb5860563..9daad445d8 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/threading/ReaderWriterLock.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/threading/ReaderWriterLock.cpp @@ -1,64 +1,64 @@ /** * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. - */ - -#include <aws/core/utils/threading/ReaderWriterLock.h> -#include <cstdint> -#include <limits> -#include <cassert> - -using namespace Aws::Utils::Threading; - + */ + +#include <aws/core/utils/threading/ReaderWriterLock.h> +#include <cstdint> +#include <limits> +#include <cassert> + +using namespace Aws::Utils::Threading; + static const int64_t MaxReaders = (std::numeric_limits<std::int32_t>::max)(); - -ReaderWriterLock::ReaderWriterLock() : - m_readers(0), - m_holdouts(0), - m_readerSem(0, static_cast<size_t>(MaxReaders)), - m_writerSem(0, 1) -{ -} - -void ReaderWriterLock::LockReader() -{ - if (++m_readers < 0) - { - m_readerSem.WaitOne(); - } -} - -void ReaderWriterLock::UnlockReader() -{ - if (--m_readers < 0 && --m_holdouts == 0) - { - m_writerSem.Release(); - } -} - -void ReaderWriterLock::LockWriter() -{ - m_writerLock.lock(); - if(const auto current = m_readers.fetch_sub(MaxReaders)) - { - assert(current > 0); - const auto holdouts = m_holdouts.fetch_add(current) + current; - assert(holdouts >= 0); - if(holdouts > 0) - { - m_writerSem.WaitOne(); - } - } -} - -void ReaderWriterLock::UnlockWriter() -{ - assert(m_holdouts == 0); - const auto current = m_readers.fetch_add(MaxReaders) + MaxReaders; - assert(current >= 0); - for(int64_t r = 0; r < current; r++) - { - m_readerSem.Release(); - } - m_writerLock.unlock(); -} + +ReaderWriterLock::ReaderWriterLock() : + m_readers(0), + m_holdouts(0), + m_readerSem(0, static_cast<size_t>(MaxReaders)), + m_writerSem(0, 1) +{ +} + +void ReaderWriterLock::LockReader() +{ + if (++m_readers < 0) + { + m_readerSem.WaitOne(); + } +} + +void ReaderWriterLock::UnlockReader() +{ + if (--m_readers < 0 && --m_holdouts == 0) + { + m_writerSem.Release(); + } +} + +void ReaderWriterLock::LockWriter() +{ + m_writerLock.lock(); + if(const auto current = m_readers.fetch_sub(MaxReaders)) + { + assert(current > 0); + const auto holdouts = m_holdouts.fetch_add(current) + current; + assert(holdouts >= 0); + if(holdouts > 0) + { + m_writerSem.WaitOne(); + } + } +} + +void ReaderWriterLock::UnlockWriter() +{ + assert(m_holdouts == 0); + const auto current = m_readers.fetch_add(MaxReaders) + MaxReaders; + assert(current >= 0); + for(int64_t r = 0; r < current; r++) + { + m_readerSem.Release(); + } + m_writerLock.unlock(); +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/threading/Semaphore.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/threading/Semaphore.cpp index 86dabc9acf..dfc7d1a1f6 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/threading/Semaphore.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/threading/Semaphore.cpp @@ -1,39 +1,39 @@ /** * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. - */ - -#include <aws/core/utils/threading/Semaphore.h> -#include <algorithm> - -using namespace Aws::Utils::Threading; - -Semaphore::Semaphore(size_t initialCount, size_t maxCount) - : m_count(initialCount), m_maxCount(maxCount) -{ -} - -void Semaphore::WaitOne() -{ - std::unique_lock<std::mutex> locker(m_mutex); - if(0 == m_count) - { - m_syncPoint.wait(locker, [this] { return m_count > 0; }); - } - --m_count; -} - -void Semaphore::Release() -{ - std::lock_guard<std::mutex> locker(m_mutex); - m_count = (std::min)(m_maxCount, m_count + 1); - m_syncPoint.notify_one(); -} - -void Semaphore::ReleaseAll() -{ - std::lock_guard<std::mutex> locker(m_mutex); - m_count = m_maxCount; - m_syncPoint.notify_all(); -} - + */ + +#include <aws/core/utils/threading/Semaphore.h> +#include <algorithm> + +using namespace Aws::Utils::Threading; + +Semaphore::Semaphore(size_t initialCount, size_t maxCount) + : m_count(initialCount), m_maxCount(maxCount) +{ +} + +void Semaphore::WaitOne() +{ + std::unique_lock<std::mutex> locker(m_mutex); + if(0 == m_count) + { + m_syncPoint.wait(locker, [this] { return m_count > 0; }); + } + --m_count; +} + +void Semaphore::Release() +{ + std::lock_guard<std::mutex> locker(m_mutex); + m_count = (std::min)(m_maxCount, m_count + 1); + m_syncPoint.notify_one(); +} + +void Semaphore::ReleaseAll() +{ + std::lock_guard<std::mutex> locker(m_mutex); + m_count = m_maxCount; + m_syncPoint.notify_all(); +} + diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/threading/ThreadTask.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/threading/ThreadTask.cpp index a899fe045d..3f32ca2583 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/threading/ThreadTask.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/threading/ThreadTask.cpp @@ -2,45 +2,45 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/utils/threading/ThreadTask.h> -#include <aws/core/utils/threading/Executor.h> - -using namespace Aws::Utils; -using namespace Aws::Utils::Threading; - -ThreadTask::ThreadTask(PooledThreadExecutor& executor) : m_continue(true), m_executor(executor), m_thread(std::bind(&ThreadTask::MainTaskRunner, this)) -{ -} - -ThreadTask::~ThreadTask() -{ - StopProcessingWork(); - m_thread.join(); -} - -void ThreadTask::MainTaskRunner() -{ - while (m_continue) - { - while (m_continue && m_executor.HasTasks()) - { - auto fn = m_executor.PopTask(); - if(fn) - { - (*fn)(); - Aws::Delete(fn); - } - } - - if(m_continue) - { - m_executor.m_sync.WaitOne(); - } - } -} - -void ThreadTask::StopProcessingWork() -{ - m_continue = false; -} + +#include <aws/core/utils/threading/ThreadTask.h> +#include <aws/core/utils/threading/Executor.h> + +using namespace Aws::Utils; +using namespace Aws::Utils::Threading; + +ThreadTask::ThreadTask(PooledThreadExecutor& executor) : m_continue(true), m_executor(executor), m_thread(std::bind(&ThreadTask::MainTaskRunner, this)) +{ +} + +ThreadTask::~ThreadTask() +{ + StopProcessingWork(); + m_thread.join(); +} + +void ThreadTask::MainTaskRunner() +{ + while (m_continue) + { + while (m_continue && m_executor.HasTasks()) + { + auto fn = m_executor.PopTask(); + if(fn) + { + (*fn)(); + Aws::Delete(fn); + } + } + + if(m_continue) + { + m_executor.m_sync.WaitOne(); + } + } +} + +void ThreadTask::StopProcessingWork() +{ + m_continue = false; +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/xml/XmlSerializer.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/xml/XmlSerializer.cpp index c06befaf9b..912ac7c3a3 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/xml/XmlSerializer.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/xml/XmlSerializer.cpp @@ -2,165 +2,165 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ - -#include <aws/core/utils/xml/XmlSerializer.h> - -#include <aws/core/utils/StringUtils.h> -#include <aws/core/external/tinyxml2/tinyxml2.h> - -#include <utility> -#include <algorithm> -#include <iostream> - -using namespace Aws::Utils::Xml; -using namespace Aws::Utils; - -Aws::String Aws::Utils::Xml::DecodeEscapedXmlText(const Aws::String& textToDecode) -{ - Aws::String decodedString = textToDecode; - StringUtils::Replace(decodedString, """, "\""); - StringUtils::Replace(decodedString, "'", "'"); - StringUtils::Replace(decodedString, "<", "<"); - StringUtils::Replace(decodedString, ">", ">"); - StringUtils::Replace(decodedString, "&", "&"); - - return decodedString; -} - -XmlNode::XmlNode(const XmlNode& other) : m_node(other.m_node), m_doc(other.m_doc) -{ -} - -XmlNode& XmlNode::operator=(const XmlNode& other) -{ - if(this == &other) - { - return *this; - } - - m_node = other.m_node; - m_doc = other.m_doc; - - return *this; -} - -const Aws::String XmlNode::GetName() const -{ - return m_node->Value(); -} - -void XmlNode::SetName(const Aws::String& name) -{ - m_node->SetValue(name.c_str(), false); -} - -const Aws::String XmlNode::GetAttributeValue(const Aws::String& name) const -{ + +#include <aws/core/utils/xml/XmlSerializer.h> + +#include <aws/core/utils/StringUtils.h> +#include <aws/core/external/tinyxml2/tinyxml2.h> + +#include <utility> +#include <algorithm> +#include <iostream> + +using namespace Aws::Utils::Xml; +using namespace Aws::Utils; + +Aws::String Aws::Utils::Xml::DecodeEscapedXmlText(const Aws::String& textToDecode) +{ + Aws::String decodedString = textToDecode; + StringUtils::Replace(decodedString, """, "\""); + StringUtils::Replace(decodedString, "'", "'"); + StringUtils::Replace(decodedString, "<", "<"); + StringUtils::Replace(decodedString, ">", ">"); + StringUtils::Replace(decodedString, "&", "&"); + + return decodedString; +} + +XmlNode::XmlNode(const XmlNode& other) : m_node(other.m_node), m_doc(other.m_doc) +{ +} + +XmlNode& XmlNode::operator=(const XmlNode& other) +{ + if(this == &other) + { + return *this; + } + + m_node = other.m_node; + m_doc = other.m_doc; + + return *this; +} + +const Aws::String XmlNode::GetName() const +{ + return m_node->Value(); +} + +void XmlNode::SetName(const Aws::String& name) +{ + m_node->SetValue(name.c_str(), false); +} + +const Aws::String XmlNode::GetAttributeValue(const Aws::String& name) const +{ auto pointer = m_node->ToElement()->Attribute(name.c_str(), nullptr); return pointer ? pointer : ""; -} - -void XmlNode::SetAttributeValue(const Aws::String& name, const Aws::String& value) -{ - m_node->ToElement()->SetAttribute(name.c_str(), value.c_str()); -} - -bool XmlNode::HasNextNode() const -{ - return m_node->NextSibling() != nullptr; -} - -XmlNode XmlNode::NextNode() const -{ - return XmlNode(m_node->NextSiblingElement(), *m_doc); -} - -XmlNode XmlNode::NextNode(const char* name) const -{ - return XmlNode(m_node->NextSiblingElement(name), *m_doc); -} - -XmlNode XmlNode::NextNode(const Aws::String& name) const -{ - return NextNode(name.c_str()); -} - -XmlNode XmlNode::FirstChild() const -{ - return XmlNode(m_node->FirstChildElement(), *m_doc); -} - -XmlNode XmlNode::FirstChild(const char* name) const -{ - return XmlNode(m_node->FirstChildElement(name), *m_doc); -} - -XmlNode XmlNode::FirstChild(const Aws::String& name) const -{ - return FirstChild(name.c_str()); -} - -bool XmlNode::HasChildren() const -{ - return !m_node->NoChildren(); -} - -XmlNode XmlNode::Parent() const -{ - return XmlNode(m_node->Parent()->ToElement(), *m_doc); -} - -Aws::String XmlNode::GetText() const -{ - if (m_node != nullptr) - { - Aws::External::tinyxml2::XMLPrinter printer; - Aws::External::tinyxml2::XMLNode* node = m_node->FirstChild(); - while (node != nullptr) - { - node->Accept(&printer); - node = node->NextSibling(); - } - - return printer.CStr(); - } - +} + +void XmlNode::SetAttributeValue(const Aws::String& name, const Aws::String& value) +{ + m_node->ToElement()->SetAttribute(name.c_str(), value.c_str()); +} + +bool XmlNode::HasNextNode() const +{ + return m_node->NextSibling() != nullptr; +} + +XmlNode XmlNode::NextNode() const +{ + return XmlNode(m_node->NextSiblingElement(), *m_doc); +} + +XmlNode XmlNode::NextNode(const char* name) const +{ + return XmlNode(m_node->NextSiblingElement(name), *m_doc); +} + +XmlNode XmlNode::NextNode(const Aws::String& name) const +{ + return NextNode(name.c_str()); +} + +XmlNode XmlNode::FirstChild() const +{ + return XmlNode(m_node->FirstChildElement(), *m_doc); +} + +XmlNode XmlNode::FirstChild(const char* name) const +{ + return XmlNode(m_node->FirstChildElement(name), *m_doc); +} + +XmlNode XmlNode::FirstChild(const Aws::String& name) const +{ + return FirstChild(name.c_str()); +} + +bool XmlNode::HasChildren() const +{ + return !m_node->NoChildren(); +} + +XmlNode XmlNode::Parent() const +{ + return XmlNode(m_node->Parent()->ToElement(), *m_doc); +} + +Aws::String XmlNode::GetText() const +{ + if (m_node != nullptr) + { + Aws::External::tinyxml2::XMLPrinter printer; + Aws::External::tinyxml2::XMLNode* node = m_node->FirstChild(); + while (node != nullptr) + { + node->Accept(&printer); + node = node->NextSibling(); + } + + return printer.CStr(); + } + return {}; -} - -void XmlNode::SetText(const Aws::String& textValue) -{ - if (m_node != nullptr) - { - Aws::External::tinyxml2::XMLText* text = m_doc->m_doc->NewText(textValue.c_str()); - m_node->InsertEndChild(text); - } -} - -XmlNode XmlNode::CreateChildElement(const Aws::String& name) -{ - Aws::External::tinyxml2::XMLElement* element = m_doc->m_doc->NewElement(name.c_str()); - return XmlNode(m_node->InsertEndChild(element), *m_doc); -} - -XmlNode XmlNode::CreateSiblingElement(const Aws::String& name) -{ - Aws::External::tinyxml2::XMLElement* element = m_doc->m_doc->NewElement(name.c_str()); - return XmlNode(m_node->Parent()->InsertEndChild(element), *m_doc); -} - -bool XmlNode::IsNull() -{ - return m_node == nullptr; -} - -static const char* XML_SERIALIZER_ALLOCATION_TAG = "XmlDocument"; - -XmlDocument::XmlDocument() -{ +} + +void XmlNode::SetText(const Aws::String& textValue) +{ + if (m_node != nullptr) + { + Aws::External::tinyxml2::XMLText* text = m_doc->m_doc->NewText(textValue.c_str()); + m_node->InsertEndChild(text); + } +} + +XmlNode XmlNode::CreateChildElement(const Aws::String& name) +{ + Aws::External::tinyxml2::XMLElement* element = m_doc->m_doc->NewElement(name.c_str()); + return XmlNode(m_node->InsertEndChild(element), *m_doc); +} + +XmlNode XmlNode::CreateSiblingElement(const Aws::String& name) +{ + Aws::External::tinyxml2::XMLElement* element = m_doc->m_doc->NewElement(name.c_str()); + return XmlNode(m_node->Parent()->InsertEndChild(element), *m_doc); +} + +bool XmlNode::IsNull() +{ + return m_node == nullptr; +} + +static const char* XML_SERIALIZER_ALLOCATION_TAG = "XmlDocument"; + +XmlDocument::XmlDocument() +{ m_doc = nullptr; -} - +} + XmlDocument::XmlDocument(const XmlDocument& doc) { if (doc.m_doc == nullptr) @@ -175,10 +175,10 @@ XmlDocument::XmlDocument(const XmlDocument& doc) } XmlDocument::XmlDocument(XmlDocument&& doc) : m_doc{ doc.m_doc } // take the innards -{ - doc.m_doc = nullptr; // leave nothing behind -} - +{ + doc.m_doc = nullptr; // leave nothing behind +} + XmlDocument& XmlDocument::operator=(const XmlDocument& other) { if (this == &other) @@ -221,21 +221,21 @@ XmlDocument& XmlDocument::operator=(XmlDocument&& other) return *this; } -XmlDocument::~XmlDocument() -{ +XmlDocument::~XmlDocument() +{ if (m_doc) { Aws::Delete(m_doc); } -} - +} + void XmlDocument::InitDoc() { m_doc = Aws::New<Aws::External::tinyxml2::XMLDocument>(XML_SERIALIZER_ALLOCATION_TAG, true, Aws::External::tinyxml2::Whitespace::PRESERVE_WHITESPACE); } -XmlNode XmlDocument::GetRootElement() const -{ +XmlNode XmlDocument::GetRootElement() const +{ if (m_doc) { return XmlNode(m_doc->FirstChildElement(), *this); @@ -245,10 +245,10 @@ XmlNode XmlDocument::GetRootElement() const return XmlNode(nullptr, *this); } -} - -bool XmlDocument::WasParseSuccessful() const -{ +} + +bool XmlDocument::WasParseSuccessful() const +{ if (m_doc) { return !m_doc->Error(); @@ -258,45 +258,45 @@ bool XmlDocument::WasParseSuccessful() const return true; } -} - -Aws::String XmlDocument::GetErrorMessage() const -{ - return !WasParseSuccessful() ? m_doc->ErrorName() : ""; -} - -Aws::String XmlDocument::ConvertToString() const -{ +} + +Aws::String XmlDocument::GetErrorMessage() const +{ + return !WasParseSuccessful() ? m_doc->ErrorName() : ""; +} + +Aws::String XmlDocument::ConvertToString() const +{ if (!m_doc) return ""; - Aws::External::tinyxml2::XMLPrinter printer; - printer.PushHeader(false, true); - m_doc->Accept(&printer); - - return printer.CStr(); -} - -XmlDocument XmlDocument::CreateFromXmlStream(Aws::IOStream& xmlStream) -{ - Aws::String xmlString((Aws::IStreamBufIterator(xmlStream)), Aws::IStreamBufIterator()); - return CreateFromXmlString(xmlString); -} - -XmlDocument XmlDocument::CreateFromXmlString(const Aws::String& xmlText) -{ - XmlDocument xmlDocument; + Aws::External::tinyxml2::XMLPrinter printer; + printer.PushHeader(false, true); + m_doc->Accept(&printer); + + return printer.CStr(); +} + +XmlDocument XmlDocument::CreateFromXmlStream(Aws::IOStream& xmlStream) +{ + Aws::String xmlString((Aws::IStreamBufIterator(xmlStream)), Aws::IStreamBufIterator()); + return CreateFromXmlString(xmlString); +} + +XmlDocument XmlDocument::CreateFromXmlString(const Aws::String& xmlText) +{ + XmlDocument xmlDocument; xmlDocument.InitDoc(); - xmlDocument.m_doc->Parse(xmlText.c_str(), xmlText.size()); - return xmlDocument; -} - -XmlDocument XmlDocument::CreateWithRootNode(const Aws::String& rootNodeName) -{ - XmlDocument xmlDocument; + xmlDocument.m_doc->Parse(xmlText.c_str(), xmlText.size()); + return xmlDocument; +} + +XmlDocument XmlDocument::CreateWithRootNode(const Aws::String& rootNodeName) +{ + XmlDocument xmlDocument; xmlDocument.InitDoc(); - Aws::External::tinyxml2::XMLElement* rootNode = xmlDocument.m_doc->NewElement(rootNodeName.c_str()); - xmlDocument.m_doc->LinkEndChild(rootNode); - - return xmlDocument; -} - + Aws::External::tinyxml2::XMLElement* rootNode = xmlDocument.m_doc->NewElement(rootNodeName.c_str()); + xmlDocument.m_doc->LinkEndChild(rootNode); + + return xmlDocument; +} + |