From ab589d4673768e5cc17a4c35f1909668780032f8 Mon Sep 17 00:00:00 2001 From: Mykhailo Diachenko Date: Fri, 19 Apr 2024 18:30:15 +0300 Subject: [PATCH] Fix parsing of server DateTime std::get_time does not claim support of time zones in the string parameter, and seems to be subject of locale set on the system. An example is a following result on linux: ParseTime(Thu, 1 Jan 1970 0:00:00 GMT)=-2209075200 ::strptime is also a subject to the time zones of locale, but it also claim support for parsing a time zone from the passed string. Thus, additional logic incorporated to offset parsed DataTime to the local timezone. Relates-To: IOTSDK-24021 Signed-off-by: Mykhailo Diachenko --- .../src/AuthenticationClientUtils.cpp | 33 ++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/olp-cpp-sdk-authentication/src/AuthenticationClientUtils.cpp b/olp-cpp-sdk-authentication/src/AuthenticationClientUtils.cpp index 9cb50f269..d069b3ec2 100644 --- a/olp-cpp-sdk-authentication/src/AuthenticationClientUtils.cpp +++ b/olp-cpp-sdk-authentication/src/AuthenticationClientUtils.cpp @@ -32,6 +32,7 @@ #include "ResponseFromJsonBuilder.h" #include "olp/core/http/NetworkResponse.h" #include "olp/core/http/NetworkUtils.h" +#include "olp/core/logging/Log.h" #include "olp/core/utils/Base64.h" #include "olp/core/utils/Url.h" @@ -55,6 +56,7 @@ constexpr auto kOauthTimestamp = "oauth_timestamp"; constexpr auto kOauthSignatureMethod = "oauth_signature_method"; constexpr auto kVersion = "1.0"; constexpr auto kHmac = "HMAC-SHA256"; +constexpr auto kLogTag = "AuthenticationClientUtils"; std::string Base64Encode(const Crypto::Sha256Digest& digest) { std::string ret = olp::utils::Base64Encode(digest.data(), digest.size()); @@ -95,16 +97,39 @@ namespace client = olp::client; constexpr auto kDate = "date"; #ifdef _WIN32 -#define timegm _mkgmtime -#endif - -std::time_t ParseTime(const std::string& value) { +// Windows does not have ::strptime and ::timegm +std::time_t DoParseTime(const std::string& value) { std::tm tm = {}; std::istringstream ss(value); ss >> std::get_time(&tm, "%a, %d %b %Y %H:%M:%S %z"); + return _mkgmtime(&tm); +} + +#else + +std::time_t DoParseTime(const std::string& value) { + std::tm tm = {}; + const auto format = "%a, %d %b %Y %H:%M:%S %Z"; + const auto parsed_until = ::strptime(value.c_str(), format, &tm); + if (parsed_until != value.c_str() + value.size()) { + OLP_SDK_LOG_WARNING(kLogTag, "Timestamp is not fully parsed" << value); + } return timegm(&tm); } +#endif + +std::time_t GmtEpochOffset() { + const auto epoch_as_date_time = "Thu, 1 Jan 1970 0:00:00 GMT"; + return DoParseTime(epoch_as_date_time); +} + +std::time_t ParseTime(const std::string& value) { + const auto time = DoParseTime(value); + const auto offset = GmtEpochOffset(); + return time - offset; +} + boost::optional GetTimestampFromHeaders( const olp::http::Headers& headers) { auto it =