Skip to content

Commit 6c7ec07

Browse files
Custom implementation of RFC1123 Parser
Signed-off-by: Mykhailo Diachenko <ext-mykhailo.z.diachenko@here.com>
1 parent 4863a44 commit 6c7ec07

File tree

5 files changed

+479
-96
lines changed

5 files changed

+479
-96
lines changed

olp-cpp-sdk-authentication/src/AuthenticationClientUtils.cpp

Lines changed: 2 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,8 @@
3030
#include <rapidjson/istreamwrapper.h>
3131
#include <rapidjson/stringbuffer.h>
3232
#include <rapidjson/writer.h>
33-
#include <boost/date_time/gregorian/gregorian.hpp>
34-
#include <boost/date_time/posix_time/posix_time.hpp>
35-
#include <boost/date_time/time_facet.hpp>
3633
#include "Constants.h"
34+
#include "Rfc1123Helper.h"
3735
#include "ResponseFromJsonBuilder.h"
3836
#include "olp/core/http/NetworkResponse.h"
3937
#include "olp/core/http/NetworkUtils.h"
@@ -61,19 +59,6 @@ constexpr auto kOauthTimestamp = "oauth_timestamp";
6159
constexpr auto kOauthSignatureMethod = "oauth_signature_method";
6260
constexpr auto kVersion = "1.0";
6361
constexpr auto kHmac = "HMAC-SHA256";
64-
constexpr auto kLogTag = "AuthenticationClientUtils";
65-
// %e: day with optional leading space/zero.
66-
// %H remains strict two-digit hour in input facet.
67-
constexpr auto kRfc1123GmtFormat = "%a, %e %b %Y %H:%M:%S GMT";
68-
69-
std::string TrimDateHeaderValue(const std::string& value) {
70-
const auto begin = value.find_first_not_of(" \t\r\n");
71-
if (begin == std::string::npos) {
72-
return {};
73-
}
74-
const auto end = value.find_last_not_of(" \t\r\n");
75-
return value.substr(begin, end - begin + 1);
76-
}
7762

7863
std::string Base64Encode(const Crypto::Sha256Digest& digest) {
7964
std::string ret = olp::utils::Base64Encode(digest.data(), digest.size());
@@ -113,89 +98,10 @@ namespace client = olp::client;
11398

11499
constexpr auto kDate = "date";
115100

116-
#ifdef _WIN32
117-
// Windows does not have ::strptime and ::timegm
118101
std::time_t ParseTime(const std::string& value) {
119-
std::tm tm = {};
120-
std::istringstream ss(value);
121-
ss >> std::get_time(&tm, "%a, %d %b %Y %H:%M:%S %z");
122-
return _mkgmtime(&tm);
102+
return internal::ParseRfc1123GmtNoExceptions(value);
123103
}
124104

125-
#else
126-
127-
std::time_t ParseTime(const std::string& value) {
128-
const auto trimmed_value = TrimDateHeaderValue(value);
129-
if (trimmed_value.empty()) {
130-
OLP_SDK_LOG_WARNING_F(kLogTag,
131-
"Failed to parse Date header '%s': value is empty "
132-
"after trimming whitespace",
133-
value.c_str());
134-
return static_cast<std::time_t>(-1);
135-
}
136-
137-
std::istringstream stream(trimmed_value);
138-
139-
// Facet has internal counter, which is incremented by the std::locale.
140-
// When last locale pointing to the facet is destroyed, the counter is
141-
// decremented and the facet is destroyed.
142-
stream.imbue(
143-
std::locale(std::locale::classic(),
144-
new boost::posix_time::time_input_facet(kRfc1123GmtFormat)));
145-
146-
boost::posix_time::ptime parsed_time;
147-
stream >> parsed_time;
148-
if (stream.fail()) {
149-
OLP_SDK_LOG_WARNING_F(kLogTag,
150-
"Failed to parse Date header '%s': format mismatch "
151-
"for RFC1123 timestamp",
152-
value.c_str());
153-
return static_cast<std::time_t>(-1);
154-
}
155-
156-
if (parsed_time.is_not_a_date_time()) {
157-
OLP_SDK_LOG_WARNING_F(kLogTag,
158-
"Failed to parse Date header '%s': parsed value is "
159-
"not a valid date/time",
160-
value.c_str());
161-
return static_cast<std::time_t>(-1);
162-
}
163-
164-
stream >> std::ws;
165-
if (!stream.eof()) {
166-
OLP_SDK_LOG_WARNING_F(kLogTag,
167-
"Failed to parse Date header '%s': unexpected "
168-
"trailing characters after timestamp",
169-
value.c_str());
170-
return static_cast<std::time_t>(-1);
171-
}
172-
173-
const auto epoch =
174-
boost::posix_time::ptime(boost::gregorian::date(1970, 1, 1));
175-
if (parsed_time < epoch) {
176-
OLP_SDK_LOG_WARNING_F(
177-
kLogTag,
178-
"Failed to parse Date header '%s': timestamp is before Unix epoch",
179-
value.c_str());
180-
return static_cast<std::time_t>(-1);
181-
}
182-
183-
const auto seconds_since_epoch = (parsed_time - epoch).total_seconds();
184-
using SecondsType = boost::remove_cv_t<decltype(seconds_since_epoch)>;
185-
if (seconds_since_epoch >
186-
static_cast<SecondsType>(std::numeric_limits<std::time_t>::max())) {
187-
OLP_SDK_LOG_WARNING_F(
188-
kLogTag,
189-
"Failed to parse Date header '%s': timestamp exceeds std::time_t range",
190-
value.c_str());
191-
return static_cast<std::time_t>(-1);
192-
}
193-
194-
return static_cast<std::time_t>(seconds_since_epoch);
195-
}
196-
197-
#endif
198-
199105
porting::optional<std::time_t> GetTimestampFromHeaders(
200106
const olp::http::Headers& headers) {
201107
auto it =

0 commit comments

Comments
 (0)