blob: 0a61f3f5c5284433145c29bae24f83612443d2a2 [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 Tanous7045c8d2017-04-03 10:04:37 -07007#include <cstdint>
8#include <cstring>
9#include <functional>
Ed Tanousa29c9972018-11-29 15:54:32 -080010#include <regex>
Ed Tanous7045c8d2017-04-03 10:04:37 -070011#include <stdexcept>
12#include <string>
13#include <tuple>
Ed Tanous7045c8d2017-04-03 10:04:37 -070014
Ed Tanous1abe55e2018-09-05 08:30:59 -070015namespace crow
16{
17namespace black_magic
18{
Ed Tanous7045c8d2017-04-03 10:04:37 -070019
Ed Tanous988403c2020-08-24 11:29:49 -070020constexpr unsigned findClosingTag(std::string_view s, unsigned p)
Ed Tanous1abe55e2018-09-05 08:30:59 -070021{
22 return s[p] == '>' ? p : findClosingTag(s, p + 1);
Ed Tanous7045c8d2017-04-03 10:04:37 -070023}
24
Ed Tanous988403c2020-08-24 11:29:49 -070025constexpr bool isInt(std::string_view s, unsigned i)
Ed Tanous1abe55e2018-09-05 08:30:59 -070026{
Ed Tanous988403c2020-08-24 11:29:49 -070027 return s.substr(i, 5) == "<int>";
Ed Tanous7045c8d2017-04-03 10:04:37 -070028}
29
Ed Tanous988403c2020-08-24 11:29:49 -070030constexpr bool isUint(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, 6) == "<uint>";
Ed Tanous7045c8d2017-04-03 10:04:37 -070033}
34
Ed Tanous988403c2020-08-24 11:29:49 -070035constexpr bool isFloat(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, 7) == "<float>" || s.substr(i, 8) == "<double>";
Ed Tanous7045c8d2017-04-03 10:04:37 -070038}
39
Ed Tanous988403c2020-08-24 11:29:49 -070040constexpr bool isStr(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, 5) == "<str>" || s.substr(i, 8) == "<string>";
Ed Tanous7045c8d2017-04-03 10:04:37 -070043}
44
Ed Tanous988403c2020-08-24 11:29:49 -070045constexpr bool isPath(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, 6) == "<path>";
Ed Tanous7045c8d2017-04-03 10:04:37 -070048}
Ed Tanous3dac7492017-08-02 13:46:20 -070049
Gunnar Mills1214b7e2020-06-04 10:11:30 -050050template <typename T>
51constexpr int getParameterTag()
Ed Tanous1abe55e2018-09-05 08:30:59 -070052{
Ed Tanous69509012019-10-24 16:53:05 -070053 if constexpr (std::is_same_v<int, T>)
54 {
55 return 1;
Ed Tanous1abe55e2018-09-05 08:30:59 -070056 }
Ed Tanous69509012019-10-24 16:53:05 -070057 if constexpr (std::is_same_v<char, T>)
58 {
59 return 1;
60 }
61 if constexpr (std::is_same_v<short, T>)
62 {
63 return 1;
64 }
65 if constexpr (std::is_same_v<long, T>)
66 {
67 return 1;
68 }
69 if constexpr (std::is_same_v<long long, T>)
70 {
71 return 1;
72 }
73 if constexpr (std::is_same_v<unsigned int, T>)
74 {
75 return 2;
76 }
77 if constexpr (std::is_same_v<unsigned char, T>)
78 {
79 return 2;
80 }
81 if constexpr (std::is_same_v<unsigned short, T>)
82 {
83 return 2;
84 }
85 if constexpr (std::is_same_v<unsigned long, T>)
86 {
87 return 2;
88 }
89 if constexpr (std::is_same_v<unsigned long long, T>)
90 {
91 return 2;
92 }
93 if constexpr (std::is_same_v<double, T>)
94 {
95 return 3;
96 }
97 if constexpr (std::is_same_v<std::string, T>)
98 {
99 return 4;
100 }
101 return 0;
102}
103
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500104template <typename... Args>
Ed Tanous988403c2020-08-24 11:29:49 -0700105struct computeParameterTagFromArgsList;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700106
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500107template <>
Ed Tanous988403c2020-08-24 11:29:49 -0700108struct computeParameterTagFromArgsList<>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700109{
Ed Tanous69509012019-10-24 16:53:05 -0700110 static constexpr int value = 0;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700111};
112
113template <typename Arg, typename... Args>
Ed Tanous988403c2020-08-24 11:29:49 -0700114struct computeParameterTagFromArgsList<Arg, Args...>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700115{
Ed Tanous69509012019-10-24 16:53:05 -0700116 static constexpr int subValue =
Ed Tanous988403c2020-08-24 11:29:49 -0700117 computeParameterTagFromArgsList<Args...>::value;
Ed Tanous69509012019-10-24 16:53:05 -0700118 static constexpr int value =
119 getParameterTag<typename std::decay<Arg>::type>()
120 ? subValue * 6 + getParameterTag<typename std::decay<Arg>::type>()
Ed Tanous1abe55e2018-09-05 08:30:59 -0700121 : subValue;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700122};
123
Ed Tanous988403c2020-08-24 11:29:49 -0700124inline bool isParameterTagCompatible(uint64_t a, uint64_t b)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700125{
126 if (a == 0)
127 {
128 return b == 0;
129 }
130 if (b == 0)
131 {
132 return a == 0;
133 }
Ed Tanous271584a2019-07-09 16:24:22 -0700134 uint64_t sa = a % 6;
135 uint64_t sb = a % 6;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700136 if (sa == 5)
137 {
138 sa = 4;
139 }
140 if (sb == 5)
141 {
142 sb = 4;
143 }
144 if (sa != sb)
145 {
146 return false;
147 }
148 return isParameterTagCompatible(a / 6, b / 6);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700149}
150
Ed Tanous988403c2020-08-24 11:29:49 -0700151constexpr uint64_t getParameterTag(std::string_view s, unsigned p = 0)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700152{
Ed Tanous988403c2020-08-24 11:29:49 -0700153 if (p == s.size())
154 {
155 return 0;
156 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700157
Ed Tanous988403c2020-08-24 11:29:49 -0700158 if (s[p] != '<')
159 {
160 return getParameterTag(s, p + 1);
161 }
Ed Tanous3dac7492017-08-02 13:46:20 -0700162
Ed Tanous988403c2020-08-24 11:29:49 -0700163 if (isInt(s, p))
164 {
165 return getParameterTag(s, findClosingTag(s, p)) * 6 + 1;
166 }
167
168 if (isUint(s, p))
169 {
170 return getParameterTag(s, findClosingTag(s, p)) * 6 + 2;
171 }
172
173 if (isFloat(s, p))
174 {
175 return getParameterTag(s, findClosingTag(s, p)) * 6 + 3;
176 }
177
178 if (isStr(s, p))
179 {
180 return getParameterTag(s, findClosingTag(s, p)) * 6 + 4;
181 }
182
183 if (isPath(s, p))
184 {
185 return getParameterTag(s, findClosingTag(s, p)) * 6 + 5;
186 }
187
188 throw std::runtime_error("invalid parameter type");
Ed Tanous7045c8d2017-04-03 10:04:37 -0700189}
Ed Tanous7045c8d2017-04-03 10:04:37 -0700190
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500191template <typename... T>
192struct S
Ed Tanous1abe55e2018-09-05 08:30:59 -0700193{
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500194 template <typename U>
195 using push = S<U, T...>;
196 template <typename U>
197 using push_back = S<T..., U>;
198 template <template <typename... Args> class U>
199 using rebind = U<T...>;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700200};
Ed Tanous988403c2020-08-24 11:29:49 -0700201
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500202template <typename F, typename Set>
203struct CallHelper;
Ed Tanous988403c2020-08-24 11:29:49 -0700204
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500205template <typename F, typename... Args>
206struct CallHelper<F, S<Args...>>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700207{
208 template <typename F1, typename... Args1,
209 typename = decltype(std::declval<F1>()(std::declval<Args1>()...))>
Ed Tanous2c70f802020-09-28 14:29:23 -0700210 static char test(int);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700211
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500212 template <typename...>
Ed Tanous2c70f802020-09-28 14:29:23 -0700213 static int test(...);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700214
Ed Tanous2c70f802020-09-28 14:29:23 -0700215 static constexpr bool value = sizeof(test<F, Args...>(0)) == sizeof(char);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700216};
217
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500218template <uint64_t N>
219struct SingleTagToType
220{};
Ed Tanous7045c8d2017-04-03 10:04:37 -0700221
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500222template <>
223struct SingleTagToType<1>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700224{
225 using type = int64_t;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700226};
227
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500228template <>
229struct SingleTagToType<2>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700230{
231 using type = uint64_t;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700232};
233
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500234template <>
235struct SingleTagToType<3>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700236{
237 using type = double;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700238};
239
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500240template <>
241struct SingleTagToType<4>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700242{
243 using type = std::string;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700244};
245
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500246template <>
247struct SingleTagToType<5>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700248{
249 using type = std::string;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700250};
251
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500252template <uint64_t Tag>
253struct Arguments
Ed Tanous1abe55e2018-09-05 08:30:59 -0700254{
255 using subarguments = typename Arguments<Tag / 6>::type;
256 using type = typename subarguments::template push<
257 typename SingleTagToType<Tag % 6>::type>;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700258};
259
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500260template <>
261struct Arguments<0>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700262{
263 using type = S<>;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700264};
265
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500266template <typename T>
Ed Tanous988403c2020-08-24 11:29:49 -0700267struct Promote
Ed Tanous1abe55e2018-09-05 08:30:59 -0700268{
269 using type = T;
270};
271
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500272template <typename T>
Ed Tanous988403c2020-08-24 11:29:49 -0700273using PromoteT = typename Promote<T>::type;
274
275template <>
276struct Promote<char>
277{
278 using type = int64_t;
279};
280template <>
281struct Promote<short>
282{
283 using type = int64_t;
284};
285template <>
286struct Promote<int>
287{
288 using type = int64_t;
289};
290template <>
291struct Promote<long>
292{
293 using type = int64_t;
294};
295template <>
296struct Promote<long long>
297{
298 using type = int64_t;
299};
300template <>
301struct Promote<unsigned char>
302{
303 using type = uint64_t;
304};
305template <>
306struct Promote<unsigned short>
307{
308 using type = uint64_t;
309};
310template <>
311struct Promote<unsigned int>
312{
313 using type = uint64_t;
314};
315template <>
316struct Promote<unsigned long>
317{
318 using type = uint64_t;
319};
320template <>
321struct Promote<unsigned long long>
322{
323 using type = uint64_t;
324};
Ed Tanous7045c8d2017-04-03 10:04:37 -0700325
Ed Tanous1abe55e2018-09-05 08:30:59 -0700326} // namespace black_magic
Ed Tanous7045c8d2017-04-03 10:04:37 -0700327
Ed Tanous1abe55e2018-09-05 08:30:59 -0700328namespace detail
329{
Ed Tanous7045c8d2017-04-03 10:04:37 -0700330
331template <class T, std::size_t N, class... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700332struct GetIndexOfElementFromTupleByTypeImpl
333{
Ed Tanous271584a2019-07-09 16:24:22 -0700334 static constexpr std::size_t value = N;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700335};
336
337template <class T, std::size_t N, class... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700338struct GetIndexOfElementFromTupleByTypeImpl<T, N, T, Args...>
339{
Ed Tanous271584a2019-07-09 16:24:22 -0700340 static constexpr std::size_t value = N;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700341};
342
343template <class T, std::size_t N, class U, class... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700344struct GetIndexOfElementFromTupleByTypeImpl<T, N, U, Args...>
345{
Ed Tanous271584a2019-07-09 16:24:22 -0700346 static constexpr std::size_t value =
Ed Tanous1abe55e2018-09-05 08:30:59 -0700347 GetIndexOfElementFromTupleByTypeImpl<T, N + 1, Args...>::value;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700348};
349
Ed Tanous1abe55e2018-09-05 08:30:59 -0700350} // namespace detail
Ed Tanous7045c8d2017-04-03 10:04:37 -0700351
Ed Tanous1abe55e2018-09-05 08:30:59 -0700352namespace utility
353{
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500354template <class T, class... Args>
355T& getElementByType(std::tuple<Args...>& t)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700356{
357 return std::get<
358 detail::GetIndexOfElementFromTupleByTypeImpl<T, 0, Args...>::value>(t);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700359}
360
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500361template <typename T>
362struct function_traits;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700363
Ed Tanous7045c8d2017-04-03 10:04:37 -0700364template <typename T>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700365struct function_traits : public function_traits<decltype(&T::operator())>
366{
367 using parent_t = function_traits<decltype(&T::operator())>;
368 static const size_t arity = parent_t::arity;
369 using result_type = typename parent_t::result_type;
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500370 template <size_t i>
371 using arg = typename parent_t::template arg<i>;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700372};
Ed Tanous3dac7492017-08-02 13:46:20 -0700373
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700374template <typename ClassType, typename r, typename... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700375struct function_traits<r (ClassType::*)(Args...) const>
376{
377 static const size_t arity = sizeof...(Args);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700378
Ed Tanous1abe55e2018-09-05 08:30:59 -0700379 using result_type = r;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700380
Ed Tanous1abe55e2018-09-05 08:30:59 -0700381 template <size_t i>
382 using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700383};
384
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700385template <typename ClassType, typename r, typename... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700386struct function_traits<r (ClassType::*)(Args...)>
387{
388 static const size_t arity = sizeof...(Args);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700389
Ed Tanous1abe55e2018-09-05 08:30:59 -0700390 using result_type = r;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700391
Ed Tanous1abe55e2018-09-05 08:30:59 -0700392 template <size_t i>
393 using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700394};
395
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700396template <typename r, typename... Args>
Ed Tanous1abe55e2018-09-05 08:30:59 -0700397struct function_traits<std::function<r(Args...)>>
398{
399 static const size_t arity = sizeof...(Args);
Ed Tanous7045c8d2017-04-03 10:04:37 -0700400
Ed Tanous1abe55e2018-09-05 08:30:59 -0700401 using result_type = r;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700402
Ed Tanous1abe55e2018-09-05 08:30:59 -0700403 template <size_t i>
404 using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700405};
406
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600407inline std::string base64encode(const std::string_view data)
408{
409 const std::array<char, 64> key = {
410 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
411 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
412 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
413 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
414 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
415
416 size_t size = data.size();
417 std::string ret;
418 ret.resize((size + 2) / 3 * 4);
419 auto it = ret.begin();
420
421 size_t i = 0;
422 while (i < size)
423 {
424 size_t keyIndex;
425
426 keyIndex = static_cast<size_t>(data[i] & 0xFC) >> 2;
427 *it++ = key[keyIndex];
428
429 if (i + 1 < size)
430 {
431 keyIndex = static_cast<size_t>(data[i] & 0x03) << 4;
432 keyIndex += static_cast<size_t>(data[i + 1] & 0xF0) >> 4;
433 *it++ = key[keyIndex];
434
435 if (i + 2 < size)
436 {
437 keyIndex = static_cast<size_t>(data[i + 1] & 0x0F) << 2;
438 keyIndex += static_cast<size_t>(data[i + 2] & 0xC0) >> 6;
439 *it++ = key[keyIndex];
440
441 keyIndex = static_cast<size_t>(data[i + 2] & 0x3F);
442 *it++ = key[keyIndex];
443 }
444 else
445 {
446 keyIndex = static_cast<size_t>(data[i + 1] & 0x0F) << 2;
447 *it++ = key[keyIndex];
448 *it++ = '=';
449 }
450 }
451 else
452 {
453 keyIndex = static_cast<size_t>(data[i] & 0x03) << 4;
454 *it++ = key[keyIndex];
455 *it++ = '=';
456 *it++ = '=';
457 }
458
459 i += 3;
460 }
461
462 return ret;
463}
464
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100465// TODO this is temporary and should be deleted once base64 is refactored out of
466// crow
Ed Tanous39e77502019-03-04 17:35:53 -0800467inline bool base64Decode(const std::string_view input, std::string& output)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700468{
Ed Tanous271584a2019-07-09 16:24:22 -0700469 static const char nop = static_cast<char>(-1);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700470 // See note on encoding_data[] in above function
Jonathan Doman5beaf842020-08-14 11:23:33 -0700471 static const std::array<char, 256> decodingData = {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700472 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
473 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, 62, nop, nop, nop, 63, 52, 53, 54, 55, 56, 57, 58, 59,
476 60, 61, nop, nop, nop, nop, nop, nop, nop, 0, 1, 2, 3, 4,
477 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
478 19, 20, 21, 22, 23, 24, 25, nop, nop, nop, nop, nop, nop, 26,
479 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
480 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, nop, nop, nop,
481 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, 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};
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100491
Ed Tanous1abe55e2018-09-05 08:30:59 -0700492 size_t inputLength = input.size();
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100493
Ed Tanous1abe55e2018-09-05 08:30:59 -0700494 // allocate space for output string
495 output.clear();
496 output.reserve(((inputLength + 2) / 3) * 4);
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100497
Jonathan Doman5beaf842020-08-14 11:23:33 -0700498 auto getCodeValue = [](char c) {
499 auto code = static_cast<unsigned char>(c);
500 // Ensure we cannot index outside the bounds of the decoding array
501 static_assert(std::numeric_limits<decltype(code)>::max() <
502 decodingData.size());
503 return decodingData[code];
504 };
505
Ed Tanous1abe55e2018-09-05 08:30:59 -0700506 // for each 4-bytes sequence from the input, extract 4 6-bits sequences by
Gunnar Millscaa3ce32020-07-08 14:46:53 -0500507 // dropping first two bits
Ed Tanous1abe55e2018-09-05 08:30:59 -0700508 // and regenerate into 3 8-bits sequences
James Feist5a806642020-07-31 16:40:33 +0000509
Ed Tanous1abe55e2018-09-05 08:30:59 -0700510 for (size_t i = 0; i < inputLength; i++)
511 {
512 char base64code0;
513 char base64code1;
514 char base64code2 = 0; // initialized to 0 to suppress warnings
515 char base64code3;
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100516
Jonathan Doman5beaf842020-08-14 11:23:33 -0700517 base64code0 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700518 if (base64code0 == nop)
519 { // non base64 character
520 return false;
521 }
522 if (!(++i < inputLength))
523 { // we need at least two input bytes for first
524 // byte output
525 return false;
526 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700527 base64code1 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700528 if (base64code1 == nop)
529 { // non base64 character
530 return false;
531 }
532 output +=
533 static_cast<char>((base64code0 << 2) | ((base64code1 >> 4) & 0x3));
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100534
Ed Tanous1abe55e2018-09-05 08:30:59 -0700535 if (++i < inputLength)
536 {
537 char c = input[i];
538 if (c == '=')
539 { // padding , end of input
540 return (base64code1 & 0x0f) == 0;
541 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700542 base64code2 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700543 if (base64code2 == nop)
544 { // non base64 character
545 return false;
546 }
547 output += static_cast<char>(((base64code1 << 4) & 0xf0) |
548 ((base64code2 >> 2) & 0x0f));
549 }
550
551 if (++i < inputLength)
552 {
553 char c = input[i];
554 if (c == '=')
555 { // padding , end of input
556 return (base64code2 & 0x03) == 0;
557 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700558 base64code3 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700559 if (base64code3 == nop)
560 { // non base64 character
561 return false;
562 }
563 output +=
564 static_cast<char>((((base64code2 << 6) & 0xc0) | base64code3));
565 }
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100566 }
567
Ed Tanous1abe55e2018-09-05 08:30:59 -0700568 return true;
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100569}
570
Andrew Geisslercb92c032018-08-17 07:56:14 -0700571/**
572 * Method returns Date Time information according to requested format
573 *
574 * @param[in] time time in second since the Epoch
575 *
576 * @return Date Time according to requested format
577 */
578inline std::string getDateTime(const std::time_t& time)
579{
580 std::array<char, 128> dateTime;
581 std::string redfishDateTime("0000-00-00T00:00:00Z00:00");
582
583 if (std::strftime(dateTime.begin(), dateTime.size(), "%FT%T%z",
584 std::localtime(&time)))
585 {
586 // insert the colon required by the ISO 8601 standard
587 redfishDateTime = std::string(dateTime.data());
588 redfishDateTime.insert(redfishDateTime.end() - 2, ':');
589 }
590
591 return redfishDateTime;
592}
593
594inline std::string dateTimeNow()
595{
596 std::time_t time = std::time(nullptr);
597 return getDateTime(time);
598}
599
Ed Tanous51dae672018-09-05 16:07:32 -0700600inline bool constantTimeStringCompare(const std::string_view a,
601 const std::string_view b)
602{
603 // Important note, this function is ONLY constant time if the two input
604 // sizes are the same
605 if (a.size() != b.size())
606 {
607 return false;
608 }
609 return CRYPTO_memcmp(a.data(), b.data(), a.size()) == 0;
610}
611
612struct ConstantTimeCompare
613{
614 bool operator()(const std::string_view a, const std::string_view b) const
615 {
616 return constantTimeStringCompare(a, b);
617 }
618};
619
George Liud139c232020-08-18 18:48:57 +0800620inline std::time_t getTimestamp(uint64_t millisTimeStamp)
621{
622 // Retrieve Created property with format:
623 // yyyy-mm-ddThh:mm:ss
624 std::chrono::milliseconds chronoTimeStamp(millisTimeStamp);
625 return std::chrono::duration_cast<std::chrono::duration<int>>(
626 chronoTimeStamp)
627 .count();
628}
629
Ed Tanous1abe55e2018-09-05 08:30:59 -0700630} // namespace utility
631} // namespace crow