blob: be506367cace8b8ab7ca9dd040eeee4cb400ced3 [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{
127 if (a == 0)
128 {
129 return b == 0;
130 }
131 if (b == 0)
132 {
133 return a == 0;
134 }
Ed Tanous271584a2019-07-09 16:24:22 -0700135 uint64_t sa = a % 6;
136 uint64_t sb = a % 6;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700137 if (sa == 5)
138 {
139 sa = 4;
140 }
141 if (sb == 5)
142 {
143 sb = 4;
144 }
145 if (sa != sb)
146 {
147 return false;
148 }
149 return isParameterTagCompatible(a / 6, b / 6);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700150}
151
Ed Tanous988403c2020-08-24 11:29:49 -0700152constexpr uint64_t getParameterTag(std::string_view s, unsigned p = 0)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700153{
Ed Tanous988403c2020-08-24 11:29:49 -0700154 if (p == s.size())
155 {
156 return 0;
157 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700158
Ed Tanous988403c2020-08-24 11:29:49 -0700159 if (s[p] != '<')
160 {
161 return getParameterTag(s, p + 1);
162 }
Ed Tanous3dac7492017-08-02 13:46:20 -0700163
Ed Tanous988403c2020-08-24 11:29:49 -0700164 if (isInt(s, p))
165 {
166 return getParameterTag(s, findClosingTag(s, p)) * 6 + 1;
167 }
168
169 if (isUint(s, p))
170 {
171 return getParameterTag(s, findClosingTag(s, p)) * 6 + 2;
172 }
173
174 if (isFloat(s, p))
175 {
176 return getParameterTag(s, findClosingTag(s, p)) * 6 + 3;
177 }
178
179 if (isStr(s, p))
180 {
181 return getParameterTag(s, findClosingTag(s, p)) * 6 + 4;
182 }
183
184 if (isPath(s, p))
185 {
186 return getParameterTag(s, findClosingTag(s, p)) * 6 + 5;
187 }
188
189 throw std::runtime_error("invalid parameter type");
Ed Tanous7045c8d2017-04-03 10:04:37 -0700190}
Ed Tanous7045c8d2017-04-03 10:04:37 -0700191
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500192template <typename... T>
193struct S
Ed Tanous1abe55e2018-09-05 08:30:59 -0700194{
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500195 template <typename U>
196 using push = S<U, T...>;
197 template <typename U>
198 using push_back = S<T..., U>;
199 template <template <typename... Args> class U>
200 using rebind = U<T...>;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700201};
Ed Tanous988403c2020-08-24 11:29:49 -0700202
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500203template <typename F, typename Set>
204struct CallHelper;
Ed Tanous988403c2020-08-24 11:29:49 -0700205
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500206template <typename F, typename... Args>
207struct CallHelper<F, S<Args...>>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700208{
209 template <typename F1, typename... Args1,
210 typename = decltype(std::declval<F1>()(std::declval<Args1>()...))>
Ed Tanous2c70f802020-09-28 14:29:23 -0700211 static char test(int);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700212
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500213 template <typename...>
Ed Tanous2c70f802020-09-28 14:29:23 -0700214 static int test(...);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700215
Ed Tanous2c70f802020-09-28 14:29:23 -0700216 static constexpr bool value = sizeof(test<F, Args...>(0)) == sizeof(char);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700217};
218
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500219template <uint64_t N>
220struct SingleTagToType
221{};
Ed Tanous7045c8d2017-04-03 10:04:37 -0700222
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500223template <>
224struct SingleTagToType<1>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700225{
226 using type = int64_t;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700227};
228
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500229template <>
230struct SingleTagToType<2>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700231{
232 using type = uint64_t;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700233};
234
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500235template <>
236struct SingleTagToType<3>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700237{
238 using type = double;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700239};
240
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500241template <>
242struct SingleTagToType<4>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700243{
244 using type = std::string;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700245};
246
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500247template <>
248struct SingleTagToType<5>
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 <uint64_t Tag>
254struct Arguments
Ed Tanous1abe55e2018-09-05 08:30:59 -0700255{
256 using subarguments = typename Arguments<Tag / 6>::type;
257 using type = typename subarguments::template push<
258 typename SingleTagToType<Tag % 6>::type>;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700259};
260
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500261template <>
262struct Arguments<0>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700263{
264 using type = S<>;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700265};
266
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500267template <typename T>
Ed Tanous988403c2020-08-24 11:29:49 -0700268struct Promote
Ed Tanous1abe55e2018-09-05 08:30:59 -0700269{
270 using type = T;
271};
272
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500273template <typename T>
Ed Tanous988403c2020-08-24 11:29:49 -0700274using PromoteT = typename Promote<T>::type;
275
276template <>
277struct Promote<char>
278{
279 using type = int64_t;
280};
281template <>
282struct Promote<short>
283{
284 using type = int64_t;
285};
286template <>
287struct Promote<int>
288{
289 using type = int64_t;
290};
291template <>
292struct Promote<long>
293{
294 using type = int64_t;
295};
296template <>
297struct Promote<long long>
298{
299 using type = int64_t;
300};
301template <>
302struct Promote<unsigned char>
303{
304 using type = uint64_t;
305};
306template <>
307struct Promote<unsigned short>
308{
309 using type = uint64_t;
310};
311template <>
312struct Promote<unsigned int>
313{
314 using type = uint64_t;
315};
316template <>
317struct Promote<unsigned long>
318{
319 using type = uint64_t;
320};
321template <>
322struct Promote<unsigned long long>
323{
324 using type = uint64_t;
325};
Ed Tanous7045c8d2017-04-03 10:04:37 -0700326
Ed Tanous1abe55e2018-09-05 08:30:59 -0700327} // namespace black_magic
Ed Tanous7045c8d2017-04-03 10:04:37 -0700328
Ed Tanous1abe55e2018-09-05 08:30:59 -0700329namespace detail
330{
Ed Tanous7045c8d2017-04-03 10:04:37 -0700331
332template <class T, std::size_t N, class... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700333struct GetIndexOfElementFromTupleByTypeImpl
334{
Ed Tanous271584a2019-07-09 16:24:22 -0700335 static constexpr std::size_t value = N;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700336};
337
338template <class T, std::size_t N, class... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700339struct GetIndexOfElementFromTupleByTypeImpl<T, N, T, Args...>
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 U, class... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700345struct GetIndexOfElementFromTupleByTypeImpl<T, N, U, Args...>
346{
Ed Tanous271584a2019-07-09 16:24:22 -0700347 static constexpr std::size_t value =
Ed Tanous1abe55e2018-09-05 08:30:59 -0700348 GetIndexOfElementFromTupleByTypeImpl<T, N + 1, Args...>::value;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700349};
350
Ed Tanous1abe55e2018-09-05 08:30:59 -0700351} // namespace detail
Ed Tanous7045c8d2017-04-03 10:04:37 -0700352
Ed Tanous1abe55e2018-09-05 08:30:59 -0700353namespace utility
354{
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500355template <class T, class... Args>
356T& getElementByType(std::tuple<Args...>& t)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700357{
358 return std::get<
359 detail::GetIndexOfElementFromTupleByTypeImpl<T, 0, Args...>::value>(t);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700360}
361
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500362template <typename T>
363struct function_traits;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700364
Ed Tanous7045c8d2017-04-03 10:04:37 -0700365template <typename T>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700366struct function_traits : public function_traits<decltype(&T::operator())>
367{
368 using parent_t = function_traits<decltype(&T::operator())>;
369 static const size_t arity = parent_t::arity;
370 using result_type = typename parent_t::result_type;
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500371 template <size_t i>
372 using arg = typename parent_t::template arg<i>;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700373};
Ed Tanous3dac7492017-08-02 13:46:20 -0700374
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700375template <typename ClassType, typename r, typename... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700376struct function_traits<r (ClassType::*)(Args...) const>
377{
378 static const size_t arity = sizeof...(Args);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700379
Ed Tanous1abe55e2018-09-05 08:30:59 -0700380 using result_type = r;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700381
Ed Tanous1abe55e2018-09-05 08:30:59 -0700382 template <size_t i>
383 using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700384};
385
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700386template <typename ClassType, typename r, typename... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700387struct function_traits<r (ClassType::*)(Args...)>
388{
389 static const size_t arity = sizeof...(Args);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700390
Ed Tanous1abe55e2018-09-05 08:30:59 -0700391 using result_type = r;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700392
Ed Tanous1abe55e2018-09-05 08:30:59 -0700393 template <size_t i>
394 using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700395};
396
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700397template <typename r, typename... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700398struct function_traits<std::function<r(Args...)>>
399{
400 static const size_t arity = sizeof...(Args);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700401
Ed Tanous1abe55e2018-09-05 08:30:59 -0700402 using result_type = r;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700403
Ed Tanous1abe55e2018-09-05 08:30:59 -0700404 template <size_t i>
405 using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700406};
407
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600408inline std::string base64encode(const std::string_view data)
409{
410 const std::array<char, 64> key = {
411 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
412 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
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 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
416
417 size_t size = data.size();
418 std::string ret;
419 ret.resize((size + 2) / 3 * 4);
420 auto it = ret.begin();
421
422 size_t i = 0;
423 while (i < size)
424 {
425 size_t keyIndex;
426
427 keyIndex = static_cast<size_t>(data[i] & 0xFC) >> 2;
428 *it++ = key[keyIndex];
429
430 if (i + 1 < size)
431 {
432 keyIndex = static_cast<size_t>(data[i] & 0x03) << 4;
433 keyIndex += static_cast<size_t>(data[i + 1] & 0xF0) >> 4;
434 *it++ = key[keyIndex];
435
436 if (i + 2 < size)
437 {
438 keyIndex = static_cast<size_t>(data[i + 1] & 0x0F) << 2;
439 keyIndex += static_cast<size_t>(data[i + 2] & 0xC0) >> 6;
440 *it++ = key[keyIndex];
441
442 keyIndex = static_cast<size_t>(data[i + 2] & 0x3F);
443 *it++ = key[keyIndex];
444 }
445 else
446 {
447 keyIndex = static_cast<size_t>(data[i + 1] & 0x0F) << 2;
448 *it++ = key[keyIndex];
449 *it++ = '=';
450 }
451 }
452 else
453 {
454 keyIndex = static_cast<size_t>(data[i] & 0x03) << 4;
455 *it++ = key[keyIndex];
456 *it++ = '=';
457 *it++ = '=';
458 }
459
460 i += 3;
461 }
462
463 return ret;
464}
465
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100466// TODO this is temporary and should be deleted once base64 is refactored out of
467// crow
Ed Tanous39e77502019-03-04 17:35:53 -0800468inline bool base64Decode(const std::string_view input, std::string& output)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700469{
Ed Tanous271584a2019-07-09 16:24:22 -0700470 static const char nop = static_cast<char>(-1);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700471 // See note on encoding_data[] in above function
Jonathan Doman5beaf842020-08-14 11:23:33 -0700472 static const std::array<char, 256> decodingData = {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700473 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
474 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
475 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
476 nop, 62, nop, nop, nop, 63, 52, 53, 54, 55, 56, 57, 58, 59,
477 60, 61, nop, nop, nop, nop, nop, nop, nop, 0, 1, 2, 3, 4,
478 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
479 19, 20, 21, 22, 23, 24, 25, nop, nop, nop, nop, nop, nop, 26,
480 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
481 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, nop, nop, nop,
482 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
483 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, 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};
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100492
Ed Tanous1abe55e2018-09-05 08:30:59 -0700493 size_t inputLength = input.size();
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100494
Ed Tanous1abe55e2018-09-05 08:30:59 -0700495 // allocate space for output string
496 output.clear();
497 output.reserve(((inputLength + 2) / 3) * 4);
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100498
Jonathan Doman5beaf842020-08-14 11:23:33 -0700499 auto getCodeValue = [](char c) {
500 auto code = static_cast<unsigned char>(c);
501 // Ensure we cannot index outside the bounds of the decoding array
502 static_assert(std::numeric_limits<decltype(code)>::max() <
503 decodingData.size());
504 return decodingData[code];
505 };
506
Ed Tanous1abe55e2018-09-05 08:30:59 -0700507 // for each 4-bytes sequence from the input, extract 4 6-bits sequences by
Gunnar Millscaa3ce32020-07-08 14:46:53 -0500508 // dropping first two bits
Ed Tanous1abe55e2018-09-05 08:30:59 -0700509 // and regenerate into 3 8-bits sequences
James Feist5a806642020-07-31 16:40:33 +0000510
Ed Tanous1abe55e2018-09-05 08:30:59 -0700511 for (size_t i = 0; i < inputLength; i++)
512 {
513 char base64code0;
514 char base64code1;
515 char base64code2 = 0; // initialized to 0 to suppress warnings
516 char base64code3;
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100517
Jonathan Doman5beaf842020-08-14 11:23:33 -0700518 base64code0 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700519 if (base64code0 == nop)
520 { // non base64 character
521 return false;
522 }
523 if (!(++i < inputLength))
524 { // we need at least two input bytes for first
525 // byte output
526 return false;
527 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700528 base64code1 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700529 if (base64code1 == nop)
530 { // non base64 character
531 return false;
532 }
533 output +=
534 static_cast<char>((base64code0 << 2) | ((base64code1 >> 4) & 0x3));
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100535
Ed Tanous1abe55e2018-09-05 08:30:59 -0700536 if (++i < inputLength)
537 {
538 char c = input[i];
539 if (c == '=')
540 { // padding , end of input
541 return (base64code1 & 0x0f) == 0;
542 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700543 base64code2 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700544 if (base64code2 == nop)
545 { // non base64 character
546 return false;
547 }
548 output += static_cast<char>(((base64code1 << 4) & 0xf0) |
549 ((base64code2 >> 2) & 0x0f));
550 }
551
552 if (++i < inputLength)
553 {
554 char c = input[i];
555 if (c == '=')
556 { // padding , end of input
557 return (base64code2 & 0x03) == 0;
558 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700559 base64code3 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700560 if (base64code3 == nop)
561 { // non base64 character
562 return false;
563 }
564 output +=
565 static_cast<char>((((base64code2 << 6) & 0xc0) | base64code3));
566 }
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100567 }
568
Ed Tanous1abe55e2018-09-05 08:30:59 -0700569 return true;
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100570}
571
Andrew Geisslercb92c032018-08-17 07:56:14 -0700572/**
573 * Method returns Date Time information according to requested format
574 *
575 * @param[in] time time in second since the Epoch
576 *
577 * @return Date Time according to requested format
578 */
579inline std::string getDateTime(const std::time_t& time)
580{
581 std::array<char, 128> dateTime;
582 std::string redfishDateTime("0000-00-00T00:00:00Z00:00");
583
584 if (std::strftime(dateTime.begin(), dateTime.size(), "%FT%T%z",
585 std::localtime(&time)))
586 {
587 // insert the colon required by the ISO 8601 standard
588 redfishDateTime = std::string(dateTime.data());
589 redfishDateTime.insert(redfishDateTime.end() - 2, ':');
590 }
591
592 return redfishDateTime;
593}
594
595inline std::string dateTimeNow()
596{
597 std::time_t time = std::time(nullptr);
598 return getDateTime(time);
599}
600
Ed Tanous51dae672018-09-05 16:07:32 -0700601inline bool constantTimeStringCompare(const std::string_view a,
602 const std::string_view b)
603{
604 // Important note, this function is ONLY constant time if the two input
605 // sizes are the same
606 if (a.size() != b.size())
607 {
608 return false;
609 }
610 return CRYPTO_memcmp(a.data(), b.data(), a.size()) == 0;
611}
612
613struct ConstantTimeCompare
614{
615 bool operator()(const std::string_view a, const std::string_view b) const
616 {
617 return constantTimeStringCompare(a, b);
618 }
619};
620
George Liud139c232020-08-18 18:48:57 +0800621inline std::time_t getTimestamp(uint64_t millisTimeStamp)
622{
623 // Retrieve Created property with format:
624 // yyyy-mm-ddThh:mm:ss
625 std::chrono::milliseconds chronoTimeStamp(millisTimeStamp);
626 return std::chrono::duration_cast<std::chrono::duration<int>>(
627 chronoTimeStamp)
628 .count();
629}
630
Ed Tanous1abe55e2018-09-05 08:30:59 -0700631} // namespace utility
632} // namespace crow