blob: 6f81be8b2602ee41dbb4c58601725253abfbb467 [file] [log] [blame]
Ed Tanous7045c8d2017-04-03 10:04:37 -07001#pragma once
2
Ed Tanous1abe55e2018-09-05 08:30:59 -07003#include "nlohmann/json.hpp"
4
Ed Tanous51dae672018-09-05 16:07:32 -07005#include <openssl/crypto.h>
6
Ed Tanous74849be2021-02-05 09:47:47 -08007#include <chrono>
Ed Tanous7045c8d2017-04-03 10:04:37 -07008#include <cstdint>
9#include <cstring>
10#include <functional>
Ed Tanousa29c9972018-11-29 15:54:32 -080011#include <regex>
Ed Tanous7045c8d2017-04-03 10:04:37 -070012#include <stdexcept>
13#include <string>
14#include <tuple>
Ed Tanous7045c8d2017-04-03 10:04:37 -070015
Ed Tanous1abe55e2018-09-05 08:30:59 -070016namespace crow
17{
18namespace black_magic
19{
Ed Tanous7045c8d2017-04-03 10:04:37 -070020
Ed Tanous988403c2020-08-24 11:29:49 -070021constexpr unsigned findClosingTag(std::string_view s, unsigned p)
Ed Tanous1abe55e2018-09-05 08:30:59 -070022{
23 return s[p] == '>' ? p : findClosingTag(s, p + 1);
Ed Tanous7045c8d2017-04-03 10:04:37 -070024}
25
Ed Tanous988403c2020-08-24 11:29:49 -070026constexpr bool isInt(std::string_view s, unsigned i)
Ed Tanous1abe55e2018-09-05 08:30:59 -070027{
Ed Tanous988403c2020-08-24 11:29:49 -070028 return s.substr(i, 5) == "<int>";
Ed Tanous7045c8d2017-04-03 10:04:37 -070029}
30
Ed Tanous988403c2020-08-24 11:29:49 -070031constexpr bool isUint(std::string_view s, unsigned i)
Ed Tanous1abe55e2018-09-05 08:30:59 -070032{
Ed Tanous988403c2020-08-24 11:29:49 -070033 return s.substr(i, 6) == "<uint>";
Ed Tanous7045c8d2017-04-03 10:04:37 -070034}
35
Ed Tanous988403c2020-08-24 11:29:49 -070036constexpr bool isFloat(std::string_view s, unsigned i)
Ed Tanous1abe55e2018-09-05 08:30:59 -070037{
Ed Tanous988403c2020-08-24 11:29:49 -070038 return s.substr(i, 7) == "<float>" || s.substr(i, 8) == "<double>";
Ed Tanous7045c8d2017-04-03 10:04:37 -070039}
40
Ed Tanous988403c2020-08-24 11:29:49 -070041constexpr bool isStr(std::string_view s, unsigned i)
Ed Tanous1abe55e2018-09-05 08:30:59 -070042{
Ed Tanous988403c2020-08-24 11:29:49 -070043 return s.substr(i, 5) == "<str>" || s.substr(i, 8) == "<string>";
Ed Tanous7045c8d2017-04-03 10:04:37 -070044}
45
Ed Tanous988403c2020-08-24 11:29:49 -070046constexpr bool isPath(std::string_view s, unsigned i)
Ed Tanous1abe55e2018-09-05 08:30:59 -070047{
Ed Tanous988403c2020-08-24 11:29:49 -070048 return s.substr(i, 6) == "<path>";
Ed Tanous7045c8d2017-04-03 10:04:37 -070049}
Ed Tanous3dac7492017-08-02 13:46:20 -070050
Gunnar Mills1214b7e2020-06-04 10:11:30 -050051template <typename T>
52constexpr int getParameterTag()
Ed Tanous1abe55e2018-09-05 08:30:59 -070053{
Ed Tanous69509012019-10-24 16:53:05 -070054 if constexpr (std::is_same_v<int, T>)
55 {
56 return 1;
Ed Tanous1abe55e2018-09-05 08:30:59 -070057 }
Ed Tanous69509012019-10-24 16:53:05 -070058 if constexpr (std::is_same_v<char, T>)
59 {
60 return 1;
61 }
62 if constexpr (std::is_same_v<short, T>)
63 {
64 return 1;
65 }
66 if constexpr (std::is_same_v<long, T>)
67 {
68 return 1;
69 }
70 if constexpr (std::is_same_v<long long, T>)
71 {
72 return 1;
73 }
74 if constexpr (std::is_same_v<unsigned int, T>)
75 {
76 return 2;
77 }
78 if constexpr (std::is_same_v<unsigned char, T>)
79 {
80 return 2;
81 }
82 if constexpr (std::is_same_v<unsigned short, T>)
83 {
84 return 2;
85 }
86 if constexpr (std::is_same_v<unsigned long, T>)
87 {
88 return 2;
89 }
90 if constexpr (std::is_same_v<unsigned long long, T>)
91 {
92 return 2;
93 }
94 if constexpr (std::is_same_v<double, T>)
95 {
96 return 3;
97 }
98 if constexpr (std::is_same_v<std::string, T>)
99 {
100 return 4;
101 }
102 return 0;
103}
104
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500105template <typename... Args>
Ed Tanous988403c2020-08-24 11:29:49 -0700106struct computeParameterTagFromArgsList;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700107
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500108template <>
Ed Tanous988403c2020-08-24 11:29:49 -0700109struct computeParameterTagFromArgsList<>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700110{
Ed Tanous69509012019-10-24 16:53:05 -0700111 static constexpr int value = 0;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700112};
113
114template <typename Arg, typename... Args>
Ed Tanous988403c2020-08-24 11:29:49 -0700115struct computeParameterTagFromArgsList<Arg, Args...>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700116{
Ed Tanous69509012019-10-24 16:53:05 -0700117 static constexpr int subValue =
Ed Tanous988403c2020-08-24 11:29:49 -0700118 computeParameterTagFromArgsList<Args...>::value;
Ed Tanous69509012019-10-24 16:53:05 -0700119 static constexpr int value =
120 getParameterTag<typename std::decay<Arg>::type>()
121 ? subValue * 6 + getParameterTag<typename std::decay<Arg>::type>()
Ed Tanous1abe55e2018-09-05 08:30:59 -0700122 : subValue;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700123};
124
Ed Tanous988403c2020-08-24 11:29:49 -0700125inline bool isParameterTagCompatible(uint64_t a, uint64_t b)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700126{
Ed Tanousb00dcc22021-02-23 12:52:50 -0800127
Ed Tanous1abe55e2018-09-05 08:30:59 -0700128 if (a == 0)
129 {
130 return b == 0;
131 }
132 if (b == 0)
133 {
134 return a == 0;
135 }
Ed Tanous271584a2019-07-09 16:24:22 -0700136 uint64_t sa = a % 6;
137 uint64_t sb = a % 6;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700138 if (sa == 5)
139 {
140 sa = 4;
141 }
142 if (sb == 5)
143 {
144 sb = 4;
145 }
146 if (sa != sb)
147 {
148 return false;
149 }
150 return isParameterTagCompatible(a / 6, b / 6);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700151}
152
Ed Tanous988403c2020-08-24 11:29:49 -0700153constexpr uint64_t getParameterTag(std::string_view s, unsigned p = 0)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700154{
Ed Tanousb00dcc22021-02-23 12:52:50 -0800155
Ed Tanous988403c2020-08-24 11:29:49 -0700156 if (p == s.size())
157 {
158 return 0;
159 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700160
Ed Tanous988403c2020-08-24 11:29:49 -0700161 if (s[p] != '<')
162 {
163 return getParameterTag(s, p + 1);
164 }
Ed Tanous3dac7492017-08-02 13:46:20 -0700165
Ed Tanous988403c2020-08-24 11:29:49 -0700166 if (isInt(s, p))
167 {
168 return getParameterTag(s, findClosingTag(s, p)) * 6 + 1;
169 }
170
171 if (isUint(s, p))
172 {
173 return getParameterTag(s, findClosingTag(s, p)) * 6 + 2;
174 }
175
176 if (isFloat(s, p))
177 {
178 return getParameterTag(s, findClosingTag(s, p)) * 6 + 3;
179 }
180
181 if (isStr(s, p))
182 {
183 return getParameterTag(s, findClosingTag(s, p)) * 6 + 4;
184 }
185
186 if (isPath(s, p))
187 {
188 return getParameterTag(s, findClosingTag(s, p)) * 6 + 5;
189 }
190
191 throw std::runtime_error("invalid parameter type");
Ed Tanous7045c8d2017-04-03 10:04:37 -0700192}
Ed Tanous7045c8d2017-04-03 10:04:37 -0700193
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500194template <typename... T>
195struct S
Ed Tanous1abe55e2018-09-05 08:30:59 -0700196{
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500197 template <typename U>
198 using push = S<U, T...>;
199 template <typename U>
200 using push_back = S<T..., U>;
201 template <template <typename... Args> class U>
202 using rebind = U<T...>;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700203};
Ed Tanous988403c2020-08-24 11:29:49 -0700204
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500205template <typename F, typename Set>
206struct CallHelper;
Ed Tanous988403c2020-08-24 11:29:49 -0700207
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500208template <typename F, typename... Args>
209struct CallHelper<F, S<Args...>>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700210{
211 template <typename F1, typename... Args1,
212 typename = decltype(std::declval<F1>()(std::declval<Args1>()...))>
Ed Tanous2c70f802020-09-28 14:29:23 -0700213 static char test(int);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700214
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500215 template <typename...>
Ed Tanous2c70f802020-09-28 14:29:23 -0700216 static int test(...);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700217
Ed Tanous2c70f802020-09-28 14:29:23 -0700218 static constexpr bool value = sizeof(test<F, Args...>(0)) == sizeof(char);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700219};
220
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500221template <uint64_t N>
222struct SingleTagToType
223{};
Ed Tanous7045c8d2017-04-03 10:04:37 -0700224
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500225template <>
226struct SingleTagToType<1>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700227{
228 using type = int64_t;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700229};
230
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500231template <>
232struct SingleTagToType<2>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700233{
234 using type = uint64_t;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700235};
236
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500237template <>
238struct SingleTagToType<3>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700239{
240 using type = double;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700241};
242
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500243template <>
244struct SingleTagToType<4>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700245{
246 using type = std::string;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700247};
248
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500249template <>
250struct SingleTagToType<5>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700251{
252 using type = std::string;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700253};
254
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500255template <uint64_t Tag>
256struct Arguments
Ed Tanous1abe55e2018-09-05 08:30:59 -0700257{
258 using subarguments = typename Arguments<Tag / 6>::type;
259 using type = typename subarguments::template push<
260 typename SingleTagToType<Tag % 6>::type>;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700261};
262
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500263template <>
264struct Arguments<0>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700265{
266 using type = S<>;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700267};
268
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500269template <typename T>
Ed Tanous988403c2020-08-24 11:29:49 -0700270struct Promote
Ed Tanous1abe55e2018-09-05 08:30:59 -0700271{
272 using type = T;
273};
274
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500275template <typename T>
Ed Tanous988403c2020-08-24 11:29:49 -0700276using PromoteT = typename Promote<T>::type;
277
278template <>
279struct Promote<char>
280{
281 using type = int64_t;
282};
283template <>
284struct Promote<short>
285{
286 using type = int64_t;
287};
288template <>
289struct Promote<int>
290{
291 using type = int64_t;
292};
293template <>
294struct Promote<long>
295{
296 using type = int64_t;
297};
298template <>
299struct Promote<long long>
300{
301 using type = int64_t;
302};
303template <>
304struct Promote<unsigned char>
305{
306 using type = uint64_t;
307};
308template <>
309struct Promote<unsigned short>
310{
311 using type = uint64_t;
312};
313template <>
314struct Promote<unsigned int>
315{
316 using type = uint64_t;
317};
318template <>
319struct Promote<unsigned long>
320{
321 using type = uint64_t;
322};
323template <>
324struct Promote<unsigned long long>
325{
326 using type = uint64_t;
327};
Ed Tanous7045c8d2017-04-03 10:04:37 -0700328
Ed Tanous1abe55e2018-09-05 08:30:59 -0700329} // namespace black_magic
Ed Tanous7045c8d2017-04-03 10:04:37 -0700330
Ed Tanous1abe55e2018-09-05 08:30:59 -0700331namespace detail
332{
Ed Tanous7045c8d2017-04-03 10:04:37 -0700333
334template <class T, std::size_t N, class... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700335struct GetIndexOfElementFromTupleByTypeImpl
336{
Ed Tanous271584a2019-07-09 16:24:22 -0700337 static constexpr std::size_t value = N;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700338};
339
340template <class T, std::size_t N, class... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700341struct GetIndexOfElementFromTupleByTypeImpl<T, N, T, Args...>
342{
Ed Tanous271584a2019-07-09 16:24:22 -0700343 static constexpr std::size_t value = N;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700344};
345
346template <class T, std::size_t N, class U, class... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700347struct GetIndexOfElementFromTupleByTypeImpl<T, N, U, Args...>
348{
Ed Tanous271584a2019-07-09 16:24:22 -0700349 static constexpr std::size_t value =
Ed Tanous1abe55e2018-09-05 08:30:59 -0700350 GetIndexOfElementFromTupleByTypeImpl<T, N + 1, Args...>::value;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700351};
352
Ed Tanous1abe55e2018-09-05 08:30:59 -0700353} // namespace detail
Ed Tanous7045c8d2017-04-03 10:04:37 -0700354
Ed Tanous1abe55e2018-09-05 08:30:59 -0700355namespace utility
356{
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500357template <class T, class... Args>
358T& getElementByType(std::tuple<Args...>& t)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700359{
360 return std::get<
361 detail::GetIndexOfElementFromTupleByTypeImpl<T, 0, Args...>::value>(t);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700362}
363
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500364template <typename T>
365struct function_traits;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700366
Ed Tanous7045c8d2017-04-03 10:04:37 -0700367template <typename T>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700368struct function_traits : public function_traits<decltype(&T::operator())>
369{
370 using parent_t = function_traits<decltype(&T::operator())>;
371 static const size_t arity = parent_t::arity;
372 using result_type = typename parent_t::result_type;
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500373 template <size_t i>
374 using arg = typename parent_t::template arg<i>;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700375};
Ed Tanous3dac7492017-08-02 13:46:20 -0700376
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700377template <typename ClassType, typename r, typename... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700378struct function_traits<r (ClassType::*)(Args...) const>
379{
380 static const size_t arity = sizeof...(Args);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700381
Ed Tanous1abe55e2018-09-05 08:30:59 -0700382 using result_type = r;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700383
Ed Tanous1abe55e2018-09-05 08:30:59 -0700384 template <size_t i>
385 using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700386};
387
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700388template <typename ClassType, typename r, typename... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700389struct function_traits<r (ClassType::*)(Args...)>
390{
391 static const size_t arity = sizeof...(Args);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700392
Ed Tanous1abe55e2018-09-05 08:30:59 -0700393 using result_type = r;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700394
Ed Tanous1abe55e2018-09-05 08:30:59 -0700395 template <size_t i>
396 using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700397};
398
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700399template <typename r, typename... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700400struct function_traits<std::function<r(Args...)>>
401{
402 static const size_t arity = sizeof...(Args);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700403
Ed Tanous1abe55e2018-09-05 08:30:59 -0700404 using result_type = r;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700405
Ed Tanous1abe55e2018-09-05 08:30:59 -0700406 template <size_t i>
407 using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700408};
409
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600410inline std::string base64encode(const std::string_view data)
411{
412 const std::array<char, 64> key = {
413 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
414 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
415 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
416 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
417 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
418
419 size_t size = data.size();
420 std::string ret;
421 ret.resize((size + 2) / 3 * 4);
422 auto it = ret.begin();
423
424 size_t i = 0;
425 while (i < size)
426 {
427 size_t keyIndex;
428
429 keyIndex = static_cast<size_t>(data[i] & 0xFC) >> 2;
430 *it++ = key[keyIndex];
431
432 if (i + 1 < size)
433 {
434 keyIndex = static_cast<size_t>(data[i] & 0x03) << 4;
435 keyIndex += static_cast<size_t>(data[i + 1] & 0xF0) >> 4;
436 *it++ = key[keyIndex];
437
438 if (i + 2 < size)
439 {
440 keyIndex = static_cast<size_t>(data[i + 1] & 0x0F) << 2;
441 keyIndex += static_cast<size_t>(data[i + 2] & 0xC0) >> 6;
442 *it++ = key[keyIndex];
443
444 keyIndex = static_cast<size_t>(data[i + 2] & 0x3F);
445 *it++ = key[keyIndex];
446 }
447 else
448 {
449 keyIndex = static_cast<size_t>(data[i + 1] & 0x0F) << 2;
450 *it++ = key[keyIndex];
451 *it++ = '=';
452 }
453 }
454 else
455 {
456 keyIndex = static_cast<size_t>(data[i] & 0x03) << 4;
457 *it++ = key[keyIndex];
458 *it++ = '=';
459 *it++ = '=';
460 }
461
462 i += 3;
463 }
464
465 return ret;
466}
467
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100468// TODO this is temporary and should be deleted once base64 is refactored out of
469// crow
Ed Tanous39e77502019-03-04 17:35:53 -0800470inline bool base64Decode(const std::string_view input, std::string& output)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700471{
Ed Tanous271584a2019-07-09 16:24:22 -0700472 static const char nop = static_cast<char>(-1);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700473 // See note on encoding_data[] in above function
Jonathan Doman5beaf842020-08-14 11:23:33 -0700474 static const std::array<char, 256> decodingData = {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700475 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
476 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, 62, nop, nop, nop, 63, 52, 53, 54, 55, 56, 57, 58, 59,
479 60, 61, nop, nop, nop, nop, nop, nop, nop, 0, 1, 2, 3, 4,
480 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
481 19, 20, 21, 22, 23, 24, 25, nop, nop, nop, nop, nop, nop, 26,
482 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
483 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, nop, nop, nop,
484 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, 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};
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100494
Ed Tanous1abe55e2018-09-05 08:30:59 -0700495 size_t inputLength = input.size();
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100496
Ed Tanous1abe55e2018-09-05 08:30:59 -0700497 // allocate space for output string
498 output.clear();
499 output.reserve(((inputLength + 2) / 3) * 4);
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100500
Jonathan Doman5beaf842020-08-14 11:23:33 -0700501 auto getCodeValue = [](char c) {
502 auto code = static_cast<unsigned char>(c);
503 // Ensure we cannot index outside the bounds of the decoding array
504 static_assert(std::numeric_limits<decltype(code)>::max() <
505 decodingData.size());
506 return decodingData[code];
507 };
508
Ed Tanous1abe55e2018-09-05 08:30:59 -0700509 // for each 4-bytes sequence from the input, extract 4 6-bits sequences by
Gunnar Millscaa3ce32020-07-08 14:46:53 -0500510 // dropping first two bits
Ed Tanous1abe55e2018-09-05 08:30:59 -0700511 // and regenerate into 3 8-bits sequences
James Feist5a806642020-07-31 16:40:33 +0000512
Ed Tanous1abe55e2018-09-05 08:30:59 -0700513 for (size_t i = 0; i < inputLength; i++)
514 {
515 char base64code0;
516 char base64code1;
517 char base64code2 = 0; // initialized to 0 to suppress warnings
518 char base64code3;
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100519
Jonathan Doman5beaf842020-08-14 11:23:33 -0700520 base64code0 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700521 if (base64code0 == nop)
522 { // non base64 character
523 return false;
524 }
525 if (!(++i < inputLength))
526 { // we need at least two input bytes for first
527 // byte output
528 return false;
529 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700530 base64code1 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700531 if (base64code1 == nop)
532 { // non base64 character
533 return false;
534 }
535 output +=
536 static_cast<char>((base64code0 << 2) | ((base64code1 >> 4) & 0x3));
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100537
Ed Tanous1abe55e2018-09-05 08:30:59 -0700538 if (++i < inputLength)
539 {
540 char c = input[i];
541 if (c == '=')
542 { // padding , end of input
543 return (base64code1 & 0x0f) == 0;
544 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700545 base64code2 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700546 if (base64code2 == nop)
547 { // non base64 character
548 return false;
549 }
550 output += static_cast<char>(((base64code1 << 4) & 0xf0) |
551 ((base64code2 >> 2) & 0x0f));
552 }
553
554 if (++i < inputLength)
555 {
556 char c = input[i];
557 if (c == '=')
558 { // padding , end of input
559 return (base64code2 & 0x03) == 0;
560 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700561 base64code3 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700562 if (base64code3 == nop)
563 { // non base64 character
564 return false;
565 }
566 output +=
567 static_cast<char>((((base64code2 << 6) & 0xc0) | base64code3));
568 }
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100569 }
570
Ed Tanous1abe55e2018-09-05 08:30:59 -0700571 return true;
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100572}
573
Andrew Geisslercb92c032018-08-17 07:56:14 -0700574/**
575 * Method returns Date Time information according to requested format
576 *
577 * @param[in] time time in second since the Epoch
578 *
579 * @return Date Time according to requested format
580 */
581inline std::string getDateTime(const std::time_t& time)
582{
583 std::array<char, 128> dateTime;
584 std::string redfishDateTime("0000-00-00T00:00:00Z00:00");
585
586 if (std::strftime(dateTime.begin(), dateTime.size(), "%FT%T%z",
587 std::localtime(&time)))
588 {
589 // insert the colon required by the ISO 8601 standard
590 redfishDateTime = std::string(dateTime.data());
591 redfishDateTime.insert(redfishDateTime.end() - 2, ':');
592 }
593
594 return redfishDateTime;
595}
596
Tejas Patil7c8c4052021-06-04 17:43:14 +0530597/**
598 * Returns the current Date, Time & the local Time Offset
599 * infromation in a pair
600 *
601 * @param[in] None
602 *
603 * @return std::pair<std::string, std::string>, which consist
604 * of current DateTime & the TimeOffset strings respectively.
605 */
606inline std::pair<std::string, std::string> getDateTimeOffsetNow()
Andrew Geisslercb92c032018-08-17 07:56:14 -0700607{
608 std::time_t time = std::time(nullptr);
Tejas Patil7c8c4052021-06-04 17:43:14 +0530609 std::string dateTime = getDateTime(time);
610
611 /* extract the local Time Offset value from the
612 * recevied dateTime string.
613 */
614 std::string timeOffset("Z00:00");
615 std::size_t lastPos = dateTime.size();
616 std::size_t len = timeOffset.size();
617 if (lastPos > len)
618 {
619 timeOffset = dateTime.substr(lastPos - len);
620 }
621
622 return std::make_pair(dateTime, timeOffset);
Andrew Geisslercb92c032018-08-17 07:56:14 -0700623}
624
Ed Tanous51dae672018-09-05 16:07:32 -0700625inline bool constantTimeStringCompare(const std::string_view a,
626 const std::string_view b)
627{
628 // Important note, this function is ONLY constant time if the two input
629 // sizes are the same
630 if (a.size() != b.size())
631 {
632 return false;
633 }
634 return CRYPTO_memcmp(a.data(), b.data(), a.size()) == 0;
635}
636
637struct ConstantTimeCompare
638{
639 bool operator()(const std::string_view a, const std::string_view b) const
640 {
641 return constantTimeStringCompare(a, b);
642 }
643};
644
George Liud139c232020-08-18 18:48:57 +0800645inline std::time_t getTimestamp(uint64_t millisTimeStamp)
646{
647 // Retrieve Created property with format:
648 // yyyy-mm-ddThh:mm:ss
649 std::chrono::milliseconds chronoTimeStamp(millisTimeStamp);
650 return std::chrono::duration_cast<std::chrono::duration<int>>(
651 chronoTimeStamp)
652 .count();
653}
654
Ed Tanous1abe55e2018-09-05 08:30:59 -0700655} // namespace utility
656} // namespace crow