blob: 557926761cf23074aa7d1ad60d2fef6002c1b29f [file] [log] [blame]
Ed Tanous7045c8d2017-04-03 10:04:37 -07001#pragma once
Ed Tanous1abe55e2018-09-05 08:30:59 -07002
Ed Tanous51dae672018-09-05 16:07:32 -07003#include <openssl/crypto.h>
4
Nan Zhou1d8782e2021-11-29 22:23:18 -08005#include <boost/date_time/posix_time/posix_time.hpp>
6
Ed Tanous9ea15c32022-01-04 14:18:22 -08007#include <array>
Ed Tanous74849be2021-02-05 09:47:47 -08008#include <chrono>
Ed Tanous7045c8d2017-04-03 10:04:37 -07009#include <cstdint>
Ed Tanous9ea15c32022-01-04 14:18:22 -080010#include <ctime>
Ed Tanous7045c8d2017-04-03 10:04:37 -070011#include <functional>
Ed Tanous9ea15c32022-01-04 14:18:22 -080012#include <limits>
Ed Tanous7045c8d2017-04-03 10:04:37 -070013#include <stdexcept>
14#include <string>
Ed Tanous9ea15c32022-01-04 14:18:22 -080015#include <string_view>
Ed Tanous7045c8d2017-04-03 10:04:37 -070016#include <tuple>
Ed Tanous9ea15c32022-01-04 14:18:22 -080017#include <type_traits>
18#include <utility>
Ed Tanous7045c8d2017-04-03 10:04:37 -070019
Ed Tanous1abe55e2018-09-05 08:30:59 -070020namespace crow
21{
22namespace black_magic
23{
Ed Tanous7045c8d2017-04-03 10:04:37 -070024
Ed Tanous988403c2020-08-24 11:29:49 -070025constexpr unsigned findClosingTag(std::string_view s, unsigned p)
Ed Tanous1abe55e2018-09-05 08:30:59 -070026{
27 return s[p] == '>' ? p : findClosingTag(s, p + 1);
Ed Tanous7045c8d2017-04-03 10:04:37 -070028}
29
Ed Tanous988403c2020-08-24 11:29:49 -070030constexpr bool isInt(std::string_view s, unsigned i)
Ed Tanous1abe55e2018-09-05 08:30:59 -070031{
Ed Tanous988403c2020-08-24 11:29:49 -070032 return s.substr(i, 5) == "<int>";
Ed Tanous7045c8d2017-04-03 10:04:37 -070033}
34
Ed Tanous988403c2020-08-24 11:29:49 -070035constexpr bool isUint(std::string_view s, unsigned i)
Ed Tanous1abe55e2018-09-05 08:30:59 -070036{
Ed Tanous988403c2020-08-24 11:29:49 -070037 return s.substr(i, 6) == "<uint>";
Ed Tanous7045c8d2017-04-03 10:04:37 -070038}
39
Ed Tanous988403c2020-08-24 11:29:49 -070040constexpr bool isFloat(std::string_view s, unsigned i)
Ed Tanous1abe55e2018-09-05 08:30:59 -070041{
Ed Tanous988403c2020-08-24 11:29:49 -070042 return s.substr(i, 7) == "<float>" || s.substr(i, 8) == "<double>";
Ed Tanous7045c8d2017-04-03 10:04:37 -070043}
44
Ed Tanous988403c2020-08-24 11:29:49 -070045constexpr bool isStr(std::string_view s, unsigned i)
Ed Tanous1abe55e2018-09-05 08:30:59 -070046{
Ed Tanous988403c2020-08-24 11:29:49 -070047 return s.substr(i, 5) == "<str>" || s.substr(i, 8) == "<string>";
Ed Tanous7045c8d2017-04-03 10:04:37 -070048}
49
Ed Tanous988403c2020-08-24 11:29:49 -070050constexpr bool isPath(std::string_view s, unsigned i)
Ed Tanous1abe55e2018-09-05 08:30:59 -070051{
Ed Tanous988403c2020-08-24 11:29:49 -070052 return s.substr(i, 6) == "<path>";
Ed Tanous7045c8d2017-04-03 10:04:37 -070053}
Ed Tanous3dac7492017-08-02 13:46:20 -070054
Gunnar Mills1214b7e2020-06-04 10:11:30 -050055template <typename T>
56constexpr int getParameterTag()
Ed Tanous1abe55e2018-09-05 08:30:59 -070057{
Ed Tanous69509012019-10-24 16:53:05 -070058 if constexpr (std::is_same_v<int, T>)
59 {
60 return 1;
Ed Tanous1abe55e2018-09-05 08:30:59 -070061 }
Ed Tanous69509012019-10-24 16:53:05 -070062 if constexpr (std::is_same_v<char, T>)
63 {
64 return 1;
65 }
66 if constexpr (std::is_same_v<short, T>)
67 {
68 return 1;
69 }
70 if constexpr (std::is_same_v<long, T>)
71 {
72 return 1;
73 }
74 if constexpr (std::is_same_v<long long, T>)
75 {
76 return 1;
77 }
78 if constexpr (std::is_same_v<unsigned int, T>)
79 {
80 return 2;
81 }
82 if constexpr (std::is_same_v<unsigned char, T>)
83 {
84 return 2;
85 }
86 if constexpr (std::is_same_v<unsigned short, T>)
87 {
88 return 2;
89 }
90 if constexpr (std::is_same_v<unsigned long, T>)
91 {
92 return 2;
93 }
94 if constexpr (std::is_same_v<unsigned long long, T>)
95 {
96 return 2;
97 }
98 if constexpr (std::is_same_v<double, T>)
99 {
100 return 3;
101 }
102 if constexpr (std::is_same_v<std::string, T>)
103 {
104 return 4;
105 }
106 return 0;
107}
108
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500109template <typename... Args>
Ed Tanous988403c2020-08-24 11:29:49 -0700110struct computeParameterTagFromArgsList;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700111
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500112template <>
Ed Tanous988403c2020-08-24 11:29:49 -0700113struct computeParameterTagFromArgsList<>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700114{
Ed Tanous69509012019-10-24 16:53:05 -0700115 static constexpr int value = 0;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700116};
117
118template <typename Arg, typename... Args>
Ed Tanous988403c2020-08-24 11:29:49 -0700119struct computeParameterTagFromArgsList<Arg, Args...>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700120{
Ed Tanous69509012019-10-24 16:53:05 -0700121 static constexpr int subValue =
Ed Tanous988403c2020-08-24 11:29:49 -0700122 computeParameterTagFromArgsList<Args...>::value;
Ed Tanous69509012019-10-24 16:53:05 -0700123 static constexpr int value =
124 getParameterTag<typename std::decay<Arg>::type>()
125 ? subValue * 6 + getParameterTag<typename std::decay<Arg>::type>()
Ed Tanous1abe55e2018-09-05 08:30:59 -0700126 : subValue;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700127};
128
Ed Tanous988403c2020-08-24 11:29:49 -0700129inline bool isParameterTagCompatible(uint64_t a, uint64_t b)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700130{
Ed Tanousb00dcc22021-02-23 12:52:50 -0800131
Ed Tanous1abe55e2018-09-05 08:30:59 -0700132 if (a == 0)
133 {
134 return b == 0;
135 }
136 if (b == 0)
137 {
138 return a == 0;
139 }
Ed Tanous271584a2019-07-09 16:24:22 -0700140 uint64_t sa = a % 6;
141 uint64_t sb = a % 6;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700142 if (sa == 5)
143 {
144 sa = 4;
145 }
146 if (sb == 5)
147 {
148 sb = 4;
149 }
150 if (sa != sb)
151 {
152 return false;
153 }
154 return isParameterTagCompatible(a / 6, b / 6);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700155}
156
Ed Tanous988403c2020-08-24 11:29:49 -0700157constexpr uint64_t getParameterTag(std::string_view s, unsigned p = 0)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700158{
Ed Tanousb00dcc22021-02-23 12:52:50 -0800159
Ed Tanous988403c2020-08-24 11:29:49 -0700160 if (p == s.size())
161 {
162 return 0;
163 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700164
Ed Tanous988403c2020-08-24 11:29:49 -0700165 if (s[p] != '<')
166 {
167 return getParameterTag(s, p + 1);
168 }
Ed Tanous3dac7492017-08-02 13:46:20 -0700169
Ed Tanous988403c2020-08-24 11:29:49 -0700170 if (isInt(s, p))
171 {
172 return getParameterTag(s, findClosingTag(s, p)) * 6 + 1;
173 }
174
175 if (isUint(s, p))
176 {
177 return getParameterTag(s, findClosingTag(s, p)) * 6 + 2;
178 }
179
180 if (isFloat(s, p))
181 {
182 return getParameterTag(s, findClosingTag(s, p)) * 6 + 3;
183 }
184
185 if (isStr(s, p))
186 {
187 return getParameterTag(s, findClosingTag(s, p)) * 6 + 4;
188 }
189
190 if (isPath(s, p))
191 {
192 return getParameterTag(s, findClosingTag(s, p)) * 6 + 5;
193 }
194
195 throw std::runtime_error("invalid parameter type");
Ed Tanous7045c8d2017-04-03 10:04:37 -0700196}
Ed Tanous7045c8d2017-04-03 10:04:37 -0700197
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500198template <typename... T>
199struct S
Ed Tanous1abe55e2018-09-05 08:30:59 -0700200{
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500201 template <typename U>
202 using push = S<U, T...>;
203 template <typename U>
204 using push_back = S<T..., U>;
205 template <template <typename... Args> class U>
206 using rebind = U<T...>;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700207};
Ed Tanous988403c2020-08-24 11:29:49 -0700208
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500209template <typename F, typename Set>
210struct CallHelper;
Ed Tanous988403c2020-08-24 11:29:49 -0700211
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500212template <typename F, typename... Args>
213struct CallHelper<F, S<Args...>>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700214{
215 template <typename F1, typename... Args1,
216 typename = decltype(std::declval<F1>()(std::declval<Args1>()...))>
Ed Tanous2c70f802020-09-28 14:29:23 -0700217 static char test(int);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700218
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500219 template <typename...>
Ed Tanous2c70f802020-09-28 14:29:23 -0700220 static int test(...);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700221
Ed Tanous2c70f802020-09-28 14:29:23 -0700222 static constexpr bool value = sizeof(test<F, Args...>(0)) == sizeof(char);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700223};
224
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500225template <uint64_t N>
226struct SingleTagToType
227{};
Ed Tanous7045c8d2017-04-03 10:04:37 -0700228
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500229template <>
230struct SingleTagToType<1>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700231{
232 using type = int64_t;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700233};
234
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500235template <>
236struct SingleTagToType<2>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700237{
238 using type = uint64_t;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700239};
240
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500241template <>
242struct SingleTagToType<3>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700243{
244 using type = double;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700245};
246
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500247template <>
248struct SingleTagToType<4>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700249{
250 using type = std::string;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700251};
252
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500253template <>
254struct SingleTagToType<5>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700255{
256 using type = std::string;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700257};
258
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500259template <uint64_t Tag>
260struct Arguments
Ed Tanous1abe55e2018-09-05 08:30:59 -0700261{
262 using subarguments = typename Arguments<Tag / 6>::type;
263 using type = typename subarguments::template push<
264 typename SingleTagToType<Tag % 6>::type>;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700265};
266
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500267template <>
268struct Arguments<0>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700269{
270 using type = S<>;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700271};
272
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500273template <typename T>
Ed Tanous988403c2020-08-24 11:29:49 -0700274struct Promote
Ed Tanous1abe55e2018-09-05 08:30:59 -0700275{
276 using type = T;
277};
278
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500279template <typename T>
Ed Tanous988403c2020-08-24 11:29:49 -0700280using PromoteT = typename Promote<T>::type;
281
282template <>
283struct Promote<char>
284{
285 using type = int64_t;
286};
287template <>
288struct Promote<short>
289{
290 using type = int64_t;
291};
292template <>
293struct Promote<int>
294{
295 using type = int64_t;
296};
297template <>
298struct Promote<long>
299{
300 using type = int64_t;
301};
302template <>
303struct Promote<long long>
304{
305 using type = int64_t;
306};
307template <>
308struct Promote<unsigned char>
309{
310 using type = uint64_t;
311};
312template <>
313struct Promote<unsigned short>
314{
315 using type = uint64_t;
316};
317template <>
318struct Promote<unsigned int>
319{
320 using type = uint64_t;
321};
322template <>
323struct Promote<unsigned long>
324{
325 using type = uint64_t;
326};
327template <>
328struct Promote<unsigned long long>
329{
330 using type = uint64_t;
331};
Ed Tanous7045c8d2017-04-03 10:04:37 -0700332
Ed Tanous1abe55e2018-09-05 08:30:59 -0700333} // namespace black_magic
Ed Tanous7045c8d2017-04-03 10:04:37 -0700334
Ed Tanous1abe55e2018-09-05 08:30:59 -0700335namespace detail
336{
Ed Tanous7045c8d2017-04-03 10:04:37 -0700337
338template <class T, std::size_t N, class... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700339struct GetIndexOfElementFromTupleByTypeImpl
340{
Ed Tanous271584a2019-07-09 16:24:22 -0700341 static constexpr std::size_t value = N;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700342};
343
344template <class T, std::size_t N, class... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700345struct GetIndexOfElementFromTupleByTypeImpl<T, N, T, Args...>
346{
Ed Tanous271584a2019-07-09 16:24:22 -0700347 static constexpr std::size_t value = N;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700348};
349
350template <class T, std::size_t N, class U, class... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700351struct GetIndexOfElementFromTupleByTypeImpl<T, N, U, Args...>
352{
Ed Tanous271584a2019-07-09 16:24:22 -0700353 static constexpr std::size_t value =
Ed Tanous1abe55e2018-09-05 08:30:59 -0700354 GetIndexOfElementFromTupleByTypeImpl<T, N + 1, Args...>::value;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700355};
356
Ed Tanous1abe55e2018-09-05 08:30:59 -0700357} // namespace detail
Ed Tanous7045c8d2017-04-03 10:04:37 -0700358
Ed Tanous1abe55e2018-09-05 08:30:59 -0700359namespace utility
360{
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500361template <class T, class... Args>
362T& getElementByType(std::tuple<Args...>& t)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700363{
364 return std::get<
365 detail::GetIndexOfElementFromTupleByTypeImpl<T, 0, Args...>::value>(t);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700366}
367
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500368template <typename T>
369struct function_traits;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700370
Ed Tanous7045c8d2017-04-03 10:04:37 -0700371template <typename T>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700372struct function_traits : public function_traits<decltype(&T::operator())>
373{
374 using parent_t = function_traits<decltype(&T::operator())>;
375 static const size_t arity = parent_t::arity;
376 using result_type = typename parent_t::result_type;
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500377 template <size_t i>
378 using arg = typename parent_t::template arg<i>;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700379};
Ed Tanous3dac7492017-08-02 13:46:20 -0700380
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700381template <typename ClassType, typename r, typename... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700382struct function_traits<r (ClassType::*)(Args...) const>
383{
384 static const size_t arity = sizeof...(Args);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700385
Ed Tanous1abe55e2018-09-05 08:30:59 -0700386 using result_type = r;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700387
Ed Tanous1abe55e2018-09-05 08:30:59 -0700388 template <size_t i>
389 using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700390};
391
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700392template <typename ClassType, typename r, typename... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700393struct function_traits<r (ClassType::*)(Args...)>
394{
395 static const size_t arity = sizeof...(Args);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700396
Ed Tanous1abe55e2018-09-05 08:30:59 -0700397 using result_type = r;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700398
Ed Tanous1abe55e2018-09-05 08:30:59 -0700399 template <size_t i>
400 using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700401};
402
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700403template <typename r, typename... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700404struct function_traits<std::function<r(Args...)>>
405{
406 static const size_t arity = sizeof...(Args);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700407
Ed Tanous1abe55e2018-09-05 08:30:59 -0700408 using result_type = r;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700409
Ed Tanous1abe55e2018-09-05 08:30:59 -0700410 template <size_t i>
411 using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700412};
413
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600414inline std::string base64encode(const std::string_view data)
415{
416 const std::array<char, 64> key = {
417 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
418 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
419 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
420 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
421 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
422
423 size_t size = data.size();
424 std::string ret;
425 ret.resize((size + 2) / 3 * 4);
426 auto it = ret.begin();
427
428 size_t i = 0;
429 while (i < size)
430 {
Ed Tanous543f4402022-01-06 13:12:53 -0800431 size_t keyIndex = 0;
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600432
433 keyIndex = static_cast<size_t>(data[i] & 0xFC) >> 2;
434 *it++ = key[keyIndex];
435
436 if (i + 1 < size)
437 {
438 keyIndex = static_cast<size_t>(data[i] & 0x03) << 4;
439 keyIndex += static_cast<size_t>(data[i + 1] & 0xF0) >> 4;
440 *it++ = key[keyIndex];
441
442 if (i + 2 < size)
443 {
444 keyIndex = static_cast<size_t>(data[i + 1] & 0x0F) << 2;
445 keyIndex += static_cast<size_t>(data[i + 2] & 0xC0) >> 6;
446 *it++ = key[keyIndex];
447
448 keyIndex = static_cast<size_t>(data[i + 2] & 0x3F);
449 *it++ = key[keyIndex];
450 }
451 else
452 {
453 keyIndex = static_cast<size_t>(data[i + 1] & 0x0F) << 2;
454 *it++ = key[keyIndex];
455 *it++ = '=';
456 }
457 }
458 else
459 {
460 keyIndex = static_cast<size_t>(data[i] & 0x03) << 4;
461 *it++ = key[keyIndex];
462 *it++ = '=';
463 *it++ = '=';
464 }
465
466 i += 3;
467 }
468
469 return ret;
470}
471
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100472// TODO this is temporary and should be deleted once base64 is refactored out of
473// crow
Ed Tanous39e77502019-03-04 17:35:53 -0800474inline bool base64Decode(const std::string_view input, std::string& output)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700475{
Ed Tanous271584a2019-07-09 16:24:22 -0700476 static const char nop = static_cast<char>(-1);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700477 // See note on encoding_data[] in above function
Jonathan Doman5beaf842020-08-14 11:23:33 -0700478 static const std::array<char, 256> decodingData = {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700479 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
480 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
481 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
482 nop, 62, nop, nop, nop, 63, 52, 53, 54, 55, 56, 57, 58, 59,
483 60, 61, nop, nop, nop, nop, nop, nop, nop, 0, 1, 2, 3, 4,
484 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
485 19, 20, 21, 22, 23, 24, 25, nop, nop, nop, nop, nop, nop, 26,
486 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
487 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, nop, nop, nop,
488 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
489 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
490 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
491 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
492 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
493 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
494 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
495 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
496 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
497 nop, nop, nop, nop};
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100498
Ed Tanous1abe55e2018-09-05 08:30:59 -0700499 size_t inputLength = input.size();
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100500
Ed Tanous1abe55e2018-09-05 08:30:59 -0700501 // allocate space for output string
502 output.clear();
503 output.reserve(((inputLength + 2) / 3) * 4);
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100504
Jonathan Doman5beaf842020-08-14 11:23:33 -0700505 auto getCodeValue = [](char c) {
506 auto code = static_cast<unsigned char>(c);
507 // Ensure we cannot index outside the bounds of the decoding array
508 static_assert(std::numeric_limits<decltype(code)>::max() <
509 decodingData.size());
510 return decodingData[code];
511 };
512
Ed Tanous1abe55e2018-09-05 08:30:59 -0700513 // for each 4-bytes sequence from the input, extract 4 6-bits sequences by
Gunnar Millscaa3ce32020-07-08 14:46:53 -0500514 // dropping first two bits
Ed Tanous1abe55e2018-09-05 08:30:59 -0700515 // and regenerate into 3 8-bits sequences
James Feist5a806642020-07-31 16:40:33 +0000516
Ed Tanous1abe55e2018-09-05 08:30:59 -0700517 for (size_t i = 0; i < inputLength; i++)
518 {
Ed Tanous543f4402022-01-06 13:12:53 -0800519 char base64code0 = 0;
520 char base64code1 = 0;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700521 char base64code2 = 0; // initialized to 0 to suppress warnings
Ed Tanous543f4402022-01-06 13:12:53 -0800522 char base64code3 = 0;
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100523
Jonathan Doman5beaf842020-08-14 11:23:33 -0700524 base64code0 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700525 if (base64code0 == nop)
526 { // non base64 character
527 return false;
528 }
529 if (!(++i < inputLength))
530 { // we need at least two input bytes for first
531 // byte output
532 return false;
533 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700534 base64code1 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700535 if (base64code1 == nop)
536 { // non base64 character
537 return false;
538 }
539 output +=
540 static_cast<char>((base64code0 << 2) | ((base64code1 >> 4) & 0x3));
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100541
Ed Tanous1abe55e2018-09-05 08:30:59 -0700542 if (++i < inputLength)
543 {
544 char c = input[i];
545 if (c == '=')
546 { // padding , end of input
547 return (base64code1 & 0x0f) == 0;
548 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700549 base64code2 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700550 if (base64code2 == nop)
551 { // non base64 character
552 return false;
553 }
554 output += static_cast<char>(((base64code1 << 4) & 0xf0) |
555 ((base64code2 >> 2) & 0x0f));
556 }
557
558 if (++i < inputLength)
559 {
560 char c = input[i];
561 if (c == '=')
562 { // padding , end of input
563 return (base64code2 & 0x03) == 0;
564 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700565 base64code3 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700566 if (base64code3 == nop)
567 { // non base64 character
568 return false;
569 }
570 output +=
571 static_cast<char>((((base64code2 << 6) & 0xc0) | base64code3));
572 }
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100573 }
574
Ed Tanous1abe55e2018-09-05 08:30:59 -0700575 return true;
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100576}
577
Krzysztof Grobelny45c367e2021-12-29 10:28:53 +0100578namespace details
579{
Ed Tanous22ce5452022-01-11 10:50:23 -0800580constexpr uint64_t maxMilliSeconds = 253402300799999;
581constexpr uint64_t maxSeconds = 253402300799;
Krzysztof Grobelny45c367e2021-12-29 10:28:53 +0100582inline std::string getDateTime(boost::posix_time::milliseconds timeSinceEpoch)
Andrew Geisslercb92c032018-08-17 07:56:14 -0700583{
Nan Zhou1d8782e2021-11-29 22:23:18 -0800584 boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1));
Krzysztof Grobelny45c367e2021-12-29 10:28:53 +0100585 boost::posix_time::ptime time = epoch + timeSinceEpoch;
Nan Zhou1d8782e2021-11-29 22:23:18 -0800586 // append zero offset to the end according to the Redfish spec for Date-Time
Nan Zhou5ae4b692021-12-14 13:30:37 -0800587 return boost::posix_time::to_iso_extended_string(time) + "+00:00";
Nan Zhou1d8782e2021-11-29 22:23:18 -0800588}
Krzysztof Grobelny45c367e2021-12-29 10:28:53 +0100589} // namespace details
Andrew Geisslercb92c032018-08-17 07:56:14 -0700590
Ed Tanous22ce5452022-01-11 10:50:23 -0800591// Returns the formatted date time string.
592// Note that the maximum supported date is 9999-12-31T23:59:59+00:00, if
593// the given |secondsSinceEpoch| is too large, we return the maximum supported
594// date. This behavior is to avoid exceptions throwed by Boost.
Nan Zhou1d8782e2021-11-29 22:23:18 -0800595inline std::string getDateTimeUint(uint64_t secondsSinceEpoch)
596{
Ed Tanous22ce5452022-01-11 10:50:23 -0800597
598 boost::posix_time::seconds boostSeconds(
599 std::min(secondsSinceEpoch, details::maxSeconds));
Krzysztof Grobelny45c367e2021-12-29 10:28:53 +0100600 return details::getDateTime(
601 boost::posix_time::milliseconds(boostSeconds.total_milliseconds()));
602}
603
Ed Tanous22ce5452022-01-11 10:50:23 -0800604// Returns the formatted date time string.
605// Note that the maximum supported date is 9999-12-31T23:59:59.999+00:00, if
606// the given |millisSecondsSinceEpoch| is too large, we return the maximum
607// supported date.
608inline std::string getDateTimeUintMs(uint64_t milliSecondsSinceEpoch)
Krzysztof Grobelny45c367e2021-12-29 10:28:53 +0100609{
Ed Tanous22ce5452022-01-11 10:50:23 -0800610 return details::getDateTime(boost::posix_time::milliseconds(
611 std::min(details::maxMilliSeconds, milliSecondsSinceEpoch)));
Nan Zhou1d8782e2021-11-29 22:23:18 -0800612}
Andrew Geisslercb92c032018-08-17 07:56:14 -0700613
Nan Zhou1d8782e2021-11-29 22:23:18 -0800614inline std::string getDateTimeStdtime(std::time_t secondsSinceEpoch)
615{
Ed Tanous22ce5452022-01-11 10:50:23 -0800616 boost::posix_time::ptime time = boost::posix_time::from_time_t(
617 std::min(secondsSinceEpoch, std::time_t{details::maxSeconds}));
Krzysztof Grobelny45c367e2021-12-29 10:28:53 +0100618 return boost::posix_time::to_iso_extended_string(time) + "+00:00";
Andrew Geisslercb92c032018-08-17 07:56:14 -0700619}
620
Tejas Patil7c8c4052021-06-04 17:43:14 +0530621/**
622 * Returns the current Date, Time & the local Time Offset
623 * infromation in a pair
624 *
625 * @param[in] None
626 *
627 * @return std::pair<std::string, std::string>, which consist
628 * of current DateTime & the TimeOffset strings respectively.
629 */
630inline std::pair<std::string, std::string> getDateTimeOffsetNow()
Andrew Geisslercb92c032018-08-17 07:56:14 -0700631{
632 std::time_t time = std::time(nullptr);
Nan Zhou1d8782e2021-11-29 22:23:18 -0800633 std::string dateTime = getDateTimeStdtime(time);
Tejas Patil7c8c4052021-06-04 17:43:14 +0530634
635 /* extract the local Time Offset value from the
636 * recevied dateTime string.
637 */
638 std::string timeOffset("Z00:00");
639 std::size_t lastPos = dateTime.size();
640 std::size_t len = timeOffset.size();
641 if (lastPos > len)
642 {
643 timeOffset = dateTime.substr(lastPos - len);
644 }
645
646 return std::make_pair(dateTime, timeOffset);
Andrew Geisslercb92c032018-08-17 07:56:14 -0700647}
648
Ed Tanous51dae672018-09-05 16:07:32 -0700649inline bool constantTimeStringCompare(const std::string_view a,
650 const std::string_view b)
651{
652 // Important note, this function is ONLY constant time if the two input
653 // sizes are the same
654 if (a.size() != b.size())
655 {
656 return false;
657 }
658 return CRYPTO_memcmp(a.data(), b.data(), a.size()) == 0;
659}
660
661struct ConstantTimeCompare
662{
663 bool operator()(const std::string_view a, const std::string_view b) const
664 {
665 return constantTimeStringCompare(a, b);
666 }
667};
668
George Liud139c232020-08-18 18:48:57 +0800669inline std::time_t getTimestamp(uint64_t millisTimeStamp)
670{
671 // Retrieve Created property with format:
672 // yyyy-mm-ddThh:mm:ss
673 std::chrono::milliseconds chronoTimeStamp(millisTimeStamp);
674 return std::chrono::duration_cast<std::chrono::duration<int>>(
675 chronoTimeStamp)
676 .count();
677}
678
Ed Tanous1abe55e2018-09-05 08:30:59 -0700679} // namespace utility
680} // namespace crow