blob: 033755e273912760bd61a5b22d99b6d5a07dc56f [file] [log] [blame]
Ed Tanous7045c8d2017-04-03 10:04:37 -07001#pragma once
Ed Tanous1abe55e2018-09-05 08:30:59 -07002#include "nlohmann/json.hpp"
3
Ed Tanous51dae672018-09-05 16:07:32 -07004#include <openssl/crypto.h>
5
Nan Zhou1d8782e2021-11-29 22:23:18 -08006#include <boost/date_time/posix_time/posix_time.hpp>
7
Ed Tanous74849be2021-02-05 09:47:47 -08008#include <chrono>
Ed Tanous7045c8d2017-04-03 10:04:37 -07009#include <cstdint>
10#include <cstring>
11#include <functional>
Ed Tanousa29c9972018-11-29 15:54:32 -080012#include <regex>
Ed Tanous7045c8d2017-04-03 10:04:37 -070013#include <stdexcept>
14#include <string>
15#include <tuple>
Ed Tanous7045c8d2017-04-03 10:04:37 -070016
Ed Tanous1abe55e2018-09-05 08:30:59 -070017namespace crow
18{
19namespace black_magic
20{
Ed Tanous7045c8d2017-04-03 10:04:37 -070021
Ed Tanous988403c2020-08-24 11:29:49 -070022constexpr unsigned findClosingTag(std::string_view s, unsigned p)
Ed Tanous1abe55e2018-09-05 08:30:59 -070023{
24 return s[p] == '>' ? p : findClosingTag(s, p + 1);
Ed Tanous7045c8d2017-04-03 10:04:37 -070025}
26
Ed Tanous988403c2020-08-24 11:29:49 -070027constexpr bool isInt(std::string_view s, unsigned i)
Ed Tanous1abe55e2018-09-05 08:30:59 -070028{
Ed Tanous988403c2020-08-24 11:29:49 -070029 return s.substr(i, 5) == "<int>";
Ed Tanous7045c8d2017-04-03 10:04:37 -070030}
31
Ed Tanous988403c2020-08-24 11:29:49 -070032constexpr bool isUint(std::string_view s, unsigned i)
Ed Tanous1abe55e2018-09-05 08:30:59 -070033{
Ed Tanous988403c2020-08-24 11:29:49 -070034 return s.substr(i, 6) == "<uint>";
Ed Tanous7045c8d2017-04-03 10:04:37 -070035}
36
Ed Tanous988403c2020-08-24 11:29:49 -070037constexpr bool isFloat(std::string_view s, unsigned i)
Ed Tanous1abe55e2018-09-05 08:30:59 -070038{
Ed Tanous988403c2020-08-24 11:29:49 -070039 return s.substr(i, 7) == "<float>" || s.substr(i, 8) == "<double>";
Ed Tanous7045c8d2017-04-03 10:04:37 -070040}
41
Ed Tanous988403c2020-08-24 11:29:49 -070042constexpr bool isStr(std::string_view s, unsigned i)
Ed Tanous1abe55e2018-09-05 08:30:59 -070043{
Ed Tanous988403c2020-08-24 11:29:49 -070044 return s.substr(i, 5) == "<str>" || s.substr(i, 8) == "<string>";
Ed Tanous7045c8d2017-04-03 10:04:37 -070045}
46
Ed Tanous988403c2020-08-24 11:29:49 -070047constexpr bool isPath(std::string_view s, unsigned i)
Ed Tanous1abe55e2018-09-05 08:30:59 -070048{
Ed Tanous988403c2020-08-24 11:29:49 -070049 return s.substr(i, 6) == "<path>";
Ed Tanous7045c8d2017-04-03 10:04:37 -070050}
Ed Tanous3dac7492017-08-02 13:46:20 -070051
Gunnar Mills1214b7e2020-06-04 10:11:30 -050052template <typename T>
53constexpr int getParameterTag()
Ed Tanous1abe55e2018-09-05 08:30:59 -070054{
Ed Tanous69509012019-10-24 16:53:05 -070055 if constexpr (std::is_same_v<int, T>)
56 {
57 return 1;
Ed Tanous1abe55e2018-09-05 08:30:59 -070058 }
Ed Tanous69509012019-10-24 16:53:05 -070059 if constexpr (std::is_same_v<char, T>)
60 {
61 return 1;
62 }
63 if constexpr (std::is_same_v<short, T>)
64 {
65 return 1;
66 }
67 if constexpr (std::is_same_v<long, T>)
68 {
69 return 1;
70 }
71 if constexpr (std::is_same_v<long long, T>)
72 {
73 return 1;
74 }
75 if constexpr (std::is_same_v<unsigned int, T>)
76 {
77 return 2;
78 }
79 if constexpr (std::is_same_v<unsigned char, T>)
80 {
81 return 2;
82 }
83 if constexpr (std::is_same_v<unsigned short, T>)
84 {
85 return 2;
86 }
87 if constexpr (std::is_same_v<unsigned long, T>)
88 {
89 return 2;
90 }
91 if constexpr (std::is_same_v<unsigned long long, T>)
92 {
93 return 2;
94 }
95 if constexpr (std::is_same_v<double, T>)
96 {
97 return 3;
98 }
99 if constexpr (std::is_same_v<std::string, T>)
100 {
101 return 4;
102 }
103 return 0;
104}
105
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500106template <typename... Args>
Ed Tanous988403c2020-08-24 11:29:49 -0700107struct computeParameterTagFromArgsList;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700108
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500109template <>
Ed Tanous988403c2020-08-24 11:29:49 -0700110struct computeParameterTagFromArgsList<>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700111{
Ed Tanous69509012019-10-24 16:53:05 -0700112 static constexpr int value = 0;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700113};
114
115template <typename Arg, typename... Args>
Ed Tanous988403c2020-08-24 11:29:49 -0700116struct computeParameterTagFromArgsList<Arg, Args...>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700117{
Ed Tanous69509012019-10-24 16:53:05 -0700118 static constexpr int subValue =
Ed Tanous988403c2020-08-24 11:29:49 -0700119 computeParameterTagFromArgsList<Args...>::value;
Ed Tanous69509012019-10-24 16:53:05 -0700120 static constexpr int value =
121 getParameterTag<typename std::decay<Arg>::type>()
122 ? subValue * 6 + getParameterTag<typename std::decay<Arg>::type>()
Ed Tanous1abe55e2018-09-05 08:30:59 -0700123 : subValue;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700124};
125
Ed Tanous988403c2020-08-24 11:29:49 -0700126inline bool isParameterTagCompatible(uint64_t a, uint64_t b)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700127{
Ed Tanousb00dcc22021-02-23 12:52:50 -0800128
Ed Tanous1abe55e2018-09-05 08:30:59 -0700129 if (a == 0)
130 {
131 return b == 0;
132 }
133 if (b == 0)
134 {
135 return a == 0;
136 }
Ed Tanous271584a2019-07-09 16:24:22 -0700137 uint64_t sa = a % 6;
138 uint64_t sb = a % 6;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700139 if (sa == 5)
140 {
141 sa = 4;
142 }
143 if (sb == 5)
144 {
145 sb = 4;
146 }
147 if (sa != sb)
148 {
149 return false;
150 }
151 return isParameterTagCompatible(a / 6, b / 6);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700152}
153
Ed Tanous988403c2020-08-24 11:29:49 -0700154constexpr uint64_t getParameterTag(std::string_view s, unsigned p = 0)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700155{
Ed Tanousb00dcc22021-02-23 12:52:50 -0800156
Ed Tanous988403c2020-08-24 11:29:49 -0700157 if (p == s.size())
158 {
159 return 0;
160 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700161
Ed Tanous988403c2020-08-24 11:29:49 -0700162 if (s[p] != '<')
163 {
164 return getParameterTag(s, p + 1);
165 }
Ed Tanous3dac7492017-08-02 13:46:20 -0700166
Ed Tanous988403c2020-08-24 11:29:49 -0700167 if (isInt(s, p))
168 {
169 return getParameterTag(s, findClosingTag(s, p)) * 6 + 1;
170 }
171
172 if (isUint(s, p))
173 {
174 return getParameterTag(s, findClosingTag(s, p)) * 6 + 2;
175 }
176
177 if (isFloat(s, p))
178 {
179 return getParameterTag(s, findClosingTag(s, p)) * 6 + 3;
180 }
181
182 if (isStr(s, p))
183 {
184 return getParameterTag(s, findClosingTag(s, p)) * 6 + 4;
185 }
186
187 if (isPath(s, p))
188 {
189 return getParameterTag(s, findClosingTag(s, p)) * 6 + 5;
190 }
191
192 throw std::runtime_error("invalid parameter type");
Ed Tanous7045c8d2017-04-03 10:04:37 -0700193}
Ed Tanous7045c8d2017-04-03 10:04:37 -0700194
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500195template <typename... T>
196struct S
Ed Tanous1abe55e2018-09-05 08:30:59 -0700197{
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500198 template <typename U>
199 using push = S<U, T...>;
200 template <typename U>
201 using push_back = S<T..., U>;
202 template <template <typename... Args> class U>
203 using rebind = U<T...>;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700204};
Ed Tanous988403c2020-08-24 11:29:49 -0700205
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500206template <typename F, typename Set>
207struct CallHelper;
Ed Tanous988403c2020-08-24 11:29:49 -0700208
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500209template <typename F, typename... Args>
210struct CallHelper<F, S<Args...>>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700211{
212 template <typename F1, typename... Args1,
213 typename = decltype(std::declval<F1>()(std::declval<Args1>()...))>
Ed Tanous2c70f802020-09-28 14:29:23 -0700214 static char test(int);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700215
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500216 template <typename...>
Ed Tanous2c70f802020-09-28 14:29:23 -0700217 static int test(...);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700218
Ed Tanous2c70f802020-09-28 14:29:23 -0700219 static constexpr bool value = sizeof(test<F, Args...>(0)) == sizeof(char);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700220};
221
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500222template <uint64_t N>
223struct SingleTagToType
224{};
Ed Tanous7045c8d2017-04-03 10:04:37 -0700225
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500226template <>
227struct SingleTagToType<1>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700228{
229 using type = int64_t;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700230};
231
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500232template <>
233struct SingleTagToType<2>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700234{
235 using type = uint64_t;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700236};
237
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500238template <>
239struct SingleTagToType<3>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700240{
241 using type = double;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700242};
243
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500244template <>
245struct SingleTagToType<4>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700246{
247 using type = std::string;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700248};
249
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500250template <>
251struct SingleTagToType<5>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700252{
253 using type = std::string;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700254};
255
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500256template <uint64_t Tag>
257struct Arguments
Ed Tanous1abe55e2018-09-05 08:30:59 -0700258{
259 using subarguments = typename Arguments<Tag / 6>::type;
260 using type = typename subarguments::template push<
261 typename SingleTagToType<Tag % 6>::type>;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700262};
263
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500264template <>
265struct Arguments<0>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700266{
267 using type = S<>;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700268};
269
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500270template <typename T>
Ed Tanous988403c2020-08-24 11:29:49 -0700271struct Promote
Ed Tanous1abe55e2018-09-05 08:30:59 -0700272{
273 using type = T;
274};
275
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500276template <typename T>
Ed Tanous988403c2020-08-24 11:29:49 -0700277using PromoteT = typename Promote<T>::type;
278
279template <>
280struct Promote<char>
281{
282 using type = int64_t;
283};
284template <>
285struct Promote<short>
286{
287 using type = int64_t;
288};
289template <>
290struct Promote<int>
291{
292 using type = int64_t;
293};
294template <>
295struct Promote<long>
296{
297 using type = int64_t;
298};
299template <>
300struct Promote<long long>
301{
302 using type = int64_t;
303};
304template <>
305struct Promote<unsigned char>
306{
307 using type = uint64_t;
308};
309template <>
310struct Promote<unsigned short>
311{
312 using type = uint64_t;
313};
314template <>
315struct Promote<unsigned int>
316{
317 using type = uint64_t;
318};
319template <>
320struct Promote<unsigned long>
321{
322 using type = uint64_t;
323};
324template <>
325struct Promote<unsigned long long>
326{
327 using type = uint64_t;
328};
Ed Tanous7045c8d2017-04-03 10:04:37 -0700329
Ed Tanous1abe55e2018-09-05 08:30:59 -0700330} // namespace black_magic
Ed Tanous7045c8d2017-04-03 10:04:37 -0700331
Ed Tanous1abe55e2018-09-05 08:30:59 -0700332namespace detail
333{
Ed Tanous7045c8d2017-04-03 10:04:37 -0700334
335template <class T, std::size_t N, class... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700336struct GetIndexOfElementFromTupleByTypeImpl
337{
Ed Tanous271584a2019-07-09 16:24:22 -0700338 static constexpr std::size_t value = N;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700339};
340
341template <class T, std::size_t N, class... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700342struct GetIndexOfElementFromTupleByTypeImpl<T, N, T, Args...>
343{
Ed Tanous271584a2019-07-09 16:24:22 -0700344 static constexpr std::size_t value = N;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700345};
346
347template <class T, std::size_t N, class U, class... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700348struct GetIndexOfElementFromTupleByTypeImpl<T, N, U, Args...>
349{
Ed Tanous271584a2019-07-09 16:24:22 -0700350 static constexpr std::size_t value =
Ed Tanous1abe55e2018-09-05 08:30:59 -0700351 GetIndexOfElementFromTupleByTypeImpl<T, N + 1, Args...>::value;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700352};
353
Ed Tanous1abe55e2018-09-05 08:30:59 -0700354} // namespace detail
Ed Tanous7045c8d2017-04-03 10:04:37 -0700355
Ed Tanous1abe55e2018-09-05 08:30:59 -0700356namespace utility
357{
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500358template <class T, class... Args>
359T& getElementByType(std::tuple<Args...>& t)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700360{
361 return std::get<
362 detail::GetIndexOfElementFromTupleByTypeImpl<T, 0, Args...>::value>(t);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700363}
364
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500365template <typename T>
366struct function_traits;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700367
Ed Tanous7045c8d2017-04-03 10:04:37 -0700368template <typename T>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700369struct function_traits : public function_traits<decltype(&T::operator())>
370{
371 using parent_t = function_traits<decltype(&T::operator())>;
372 static const size_t arity = parent_t::arity;
373 using result_type = typename parent_t::result_type;
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500374 template <size_t i>
375 using arg = typename parent_t::template arg<i>;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700376};
Ed Tanous3dac7492017-08-02 13:46:20 -0700377
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700378template <typename ClassType, typename r, typename... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700379struct function_traits<r (ClassType::*)(Args...) const>
380{
381 static const size_t arity = sizeof...(Args);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700382
Ed Tanous1abe55e2018-09-05 08:30:59 -0700383 using result_type = r;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700384
Ed Tanous1abe55e2018-09-05 08:30:59 -0700385 template <size_t i>
386 using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700387};
388
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700389template <typename ClassType, typename r, typename... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700390struct function_traits<r (ClassType::*)(Args...)>
391{
392 static const size_t arity = sizeof...(Args);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700393
Ed Tanous1abe55e2018-09-05 08:30:59 -0700394 using result_type = r;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700395
Ed Tanous1abe55e2018-09-05 08:30:59 -0700396 template <size_t i>
397 using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700398};
399
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700400template <typename r, typename... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700401struct function_traits<std::function<r(Args...)>>
402{
403 static const size_t arity = sizeof...(Args);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700404
Ed Tanous1abe55e2018-09-05 08:30:59 -0700405 using result_type = r;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700406
Ed Tanous1abe55e2018-09-05 08:30:59 -0700407 template <size_t i>
408 using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700409};
410
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600411inline std::string base64encode(const std::string_view data)
412{
413 const std::array<char, 64> key = {
414 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
415 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
416 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
417 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
418 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
419
420 size_t size = data.size();
421 std::string ret;
422 ret.resize((size + 2) / 3 * 4);
423 auto it = ret.begin();
424
425 size_t i = 0;
426 while (i < size)
427 {
428 size_t keyIndex;
429
430 keyIndex = static_cast<size_t>(data[i] & 0xFC) >> 2;
431 *it++ = key[keyIndex];
432
433 if (i + 1 < size)
434 {
435 keyIndex = static_cast<size_t>(data[i] & 0x03) << 4;
436 keyIndex += static_cast<size_t>(data[i + 1] & 0xF0) >> 4;
437 *it++ = key[keyIndex];
438
439 if (i + 2 < size)
440 {
441 keyIndex = static_cast<size_t>(data[i + 1] & 0x0F) << 2;
442 keyIndex += static_cast<size_t>(data[i + 2] & 0xC0) >> 6;
443 *it++ = key[keyIndex];
444
445 keyIndex = static_cast<size_t>(data[i + 2] & 0x3F);
446 *it++ = key[keyIndex];
447 }
448 else
449 {
450 keyIndex = static_cast<size_t>(data[i + 1] & 0x0F) << 2;
451 *it++ = key[keyIndex];
452 *it++ = '=';
453 }
454 }
455 else
456 {
457 keyIndex = static_cast<size_t>(data[i] & 0x03) << 4;
458 *it++ = key[keyIndex];
459 *it++ = '=';
460 *it++ = '=';
461 }
462
463 i += 3;
464 }
465
466 return ret;
467}
468
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100469// TODO this is temporary and should be deleted once base64 is refactored out of
470// crow
Ed Tanous39e77502019-03-04 17:35:53 -0800471inline bool base64Decode(const std::string_view input, std::string& output)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700472{
Ed Tanous271584a2019-07-09 16:24:22 -0700473 static const char nop = static_cast<char>(-1);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700474 // See note on encoding_data[] in above function
Jonathan Doman5beaf842020-08-14 11:23:33 -0700475 static const std::array<char, 256> decodingData = {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700476 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
477 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
478 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
479 nop, 62, nop, nop, nop, 63, 52, 53, 54, 55, 56, 57, 58, 59,
480 60, 61, nop, nop, nop, nop, nop, nop, nop, 0, 1, 2, 3, 4,
481 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
482 19, 20, 21, 22, 23, 24, 25, nop, nop, nop, nop, nop, nop, 26,
483 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
484 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, nop, nop, nop,
485 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
486 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
487 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, 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};
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100495
Ed Tanous1abe55e2018-09-05 08:30:59 -0700496 size_t inputLength = input.size();
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100497
Ed Tanous1abe55e2018-09-05 08:30:59 -0700498 // allocate space for output string
499 output.clear();
500 output.reserve(((inputLength + 2) / 3) * 4);
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100501
Jonathan Doman5beaf842020-08-14 11:23:33 -0700502 auto getCodeValue = [](char c) {
503 auto code = static_cast<unsigned char>(c);
504 // Ensure we cannot index outside the bounds of the decoding array
505 static_assert(std::numeric_limits<decltype(code)>::max() <
506 decodingData.size());
507 return decodingData[code];
508 };
509
Ed Tanous1abe55e2018-09-05 08:30:59 -0700510 // for each 4-bytes sequence from the input, extract 4 6-bits sequences by
Gunnar Millscaa3ce32020-07-08 14:46:53 -0500511 // dropping first two bits
Ed Tanous1abe55e2018-09-05 08:30:59 -0700512 // and regenerate into 3 8-bits sequences
James Feist5a806642020-07-31 16:40:33 +0000513
Ed Tanous1abe55e2018-09-05 08:30:59 -0700514 for (size_t i = 0; i < inputLength; i++)
515 {
516 char base64code0;
517 char base64code1;
518 char base64code2 = 0; // initialized to 0 to suppress warnings
519 char base64code3;
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100520
Jonathan Doman5beaf842020-08-14 11:23:33 -0700521 base64code0 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700522 if (base64code0 == nop)
523 { // non base64 character
524 return false;
525 }
526 if (!(++i < inputLength))
527 { // we need at least two input bytes for first
528 // byte output
529 return false;
530 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700531 base64code1 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700532 if (base64code1 == nop)
533 { // non base64 character
534 return false;
535 }
536 output +=
537 static_cast<char>((base64code0 << 2) | ((base64code1 >> 4) & 0x3));
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100538
Ed Tanous1abe55e2018-09-05 08:30:59 -0700539 if (++i < inputLength)
540 {
541 char c = input[i];
542 if (c == '=')
543 { // padding , end of input
544 return (base64code1 & 0x0f) == 0;
545 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700546 base64code2 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700547 if (base64code2 == nop)
548 { // non base64 character
549 return false;
550 }
551 output += static_cast<char>(((base64code1 << 4) & 0xf0) |
552 ((base64code2 >> 2) & 0x0f));
553 }
554
555 if (++i < inputLength)
556 {
557 char c = input[i];
558 if (c == '=')
559 { // padding , end of input
560 return (base64code2 & 0x03) == 0;
561 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700562 base64code3 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700563 if (base64code3 == nop)
564 { // non base64 character
565 return false;
566 }
567 output +=
568 static_cast<char>((((base64code2 << 6) & 0xc0) | base64code3));
569 }
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100570 }
571
Ed Tanous1abe55e2018-09-05 08:30:59 -0700572 return true;
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100573}
574
Andrew Geisslercb92c032018-08-17 07:56:14 -0700575/**
Nan Zhou1d8782e2021-11-29 22:23:18 -0800576 * Method returns Date Time information in the ISO extended format
Andrew Geisslercb92c032018-08-17 07:56:14 -0700577 *
Nan Zhou1d8782e2021-11-29 22:23:18 -0800578 * @param[in] timestamp in second since the Epoch; it can be negative
Andrew Geisslercb92c032018-08-17 07:56:14 -0700579 *
Nan Zhou1d8782e2021-11-29 22:23:18 -0800580 * @return Date Time in the ISO extended format
Andrew Geisslercb92c032018-08-17 07:56:14 -0700581 */
Nan Zhou1d8782e2021-11-29 22:23:18 -0800582inline std::string getDateTime(boost::posix_time::seconds secondsSinceEpoch)
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));
585 boost::posix_time::ptime time = epoch + secondsSinceEpoch;
586 // 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}
Andrew Geisslercb92c032018-08-17 07:56:14 -0700589
Nan Zhou1d8782e2021-11-29 22:23:18 -0800590inline std::string getDateTimeUint(uint64_t secondsSinceEpoch)
591{
592 return getDateTime(boost::posix_time::seconds(secondsSinceEpoch));
593}
Andrew Geisslercb92c032018-08-17 07:56:14 -0700594
Nan Zhou1d8782e2021-11-29 22:23:18 -0800595inline std::string getDateTimeStdtime(std::time_t secondsSinceEpoch)
596{
597 return getDateTime(boost::posix_time::seconds(secondsSinceEpoch));
Andrew Geisslercb92c032018-08-17 07:56:14 -0700598}
599
Tejas Patil7c8c4052021-06-04 17:43:14 +0530600/**
601 * Returns the current Date, Time & the local Time Offset
602 * infromation in a pair
603 *
604 * @param[in] None
605 *
606 * @return std::pair<std::string, std::string>, which consist
607 * of current DateTime & the TimeOffset strings respectively.
608 */
609inline std::pair<std::string, std::string> getDateTimeOffsetNow()
Andrew Geisslercb92c032018-08-17 07:56:14 -0700610{
611 std::time_t time = std::time(nullptr);
Nan Zhou1d8782e2021-11-29 22:23:18 -0800612 std::string dateTime = getDateTimeStdtime(time);
Tejas Patil7c8c4052021-06-04 17:43:14 +0530613
614 /* extract the local Time Offset value from the
615 * recevied dateTime string.
616 */
617 std::string timeOffset("Z00:00");
618 std::size_t lastPos = dateTime.size();
619 std::size_t len = timeOffset.size();
620 if (lastPos > len)
621 {
622 timeOffset = dateTime.substr(lastPos - len);
623 }
624
625 return std::make_pair(dateTime, timeOffset);
Andrew Geisslercb92c032018-08-17 07:56:14 -0700626}
627
Ed Tanous51dae672018-09-05 16:07:32 -0700628inline bool constantTimeStringCompare(const std::string_view a,
629 const std::string_view b)
630{
631 // Important note, this function is ONLY constant time if the two input
632 // sizes are the same
633 if (a.size() != b.size())
634 {
635 return false;
636 }
637 return CRYPTO_memcmp(a.data(), b.data(), a.size()) == 0;
638}
639
640struct ConstantTimeCompare
641{
642 bool operator()(const std::string_view a, const std::string_view b) const
643 {
644 return constantTimeStringCompare(a, b);
645 }
646};
647
George Liud139c232020-08-18 18:48:57 +0800648inline std::time_t getTimestamp(uint64_t millisTimeStamp)
649{
650 // Retrieve Created property with format:
651 // yyyy-mm-ddThh:mm:ss
652 std::chrono::milliseconds chronoTimeStamp(millisTimeStamp);
653 return std::chrono::duration_cast<std::chrono::duration<int>>(
654 chronoTimeStamp)
655 .count();
656}
657
Ed Tanous1abe55e2018-09-05 08:30:59 -0700658} // namespace utility
659} // namespace crow