blob: 5a184cce1883c1aa3fdd97350d74128f70f9a243 [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
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100407// TODO this is temporary and should be deleted once base64 is refactored out of
408// crow
Ed Tanous39e77502019-03-04 17:35:53 -0800409inline bool base64Decode(const std::string_view input, std::string& output)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700410{
Ed Tanous271584a2019-07-09 16:24:22 -0700411 static const char nop = static_cast<char>(-1);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700412 // See note on encoding_data[] in above function
Jonathan Doman5beaf842020-08-14 11:23:33 -0700413 static const std::array<char, 256> decodingData = {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700414 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
415 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
416 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
417 nop, 62, nop, nop, nop, 63, 52, 53, 54, 55, 56, 57, 58, 59,
418 60, 61, nop, nop, nop, nop, nop, nop, nop, 0, 1, 2, 3, 4,
419 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
420 19, 20, 21, 22, 23, 24, 25, nop, nop, nop, nop, nop, nop, 26,
421 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
422 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, nop, nop, nop,
423 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
424 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
425 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
426 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
427 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
428 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
429 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
430 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
431 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
432 nop, nop, nop, nop};
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100433
Ed Tanous1abe55e2018-09-05 08:30:59 -0700434 size_t inputLength = input.size();
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100435
Ed Tanous1abe55e2018-09-05 08:30:59 -0700436 // allocate space for output string
437 output.clear();
438 output.reserve(((inputLength + 2) / 3) * 4);
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100439
Jonathan Doman5beaf842020-08-14 11:23:33 -0700440 auto getCodeValue = [](char c) {
441 auto code = static_cast<unsigned char>(c);
442 // Ensure we cannot index outside the bounds of the decoding array
443 static_assert(std::numeric_limits<decltype(code)>::max() <
444 decodingData.size());
445 return decodingData[code];
446 };
447
Ed Tanous1abe55e2018-09-05 08:30:59 -0700448 // for each 4-bytes sequence from the input, extract 4 6-bits sequences by
Gunnar Millscaa3ce32020-07-08 14:46:53 -0500449 // dropping first two bits
Ed Tanous1abe55e2018-09-05 08:30:59 -0700450 // and regenerate into 3 8-bits sequences
James Feist5a806642020-07-31 16:40:33 +0000451
Ed Tanous1abe55e2018-09-05 08:30:59 -0700452 for (size_t i = 0; i < inputLength; i++)
453 {
454 char base64code0;
455 char base64code1;
456 char base64code2 = 0; // initialized to 0 to suppress warnings
457 char base64code3;
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100458
Jonathan Doman5beaf842020-08-14 11:23:33 -0700459 base64code0 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700460 if (base64code0 == nop)
461 { // non base64 character
462 return false;
463 }
464 if (!(++i < inputLength))
465 { // we need at least two input bytes for first
466 // byte output
467 return false;
468 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700469 base64code1 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700470 if (base64code1 == nop)
471 { // non base64 character
472 return false;
473 }
474 output +=
475 static_cast<char>((base64code0 << 2) | ((base64code1 >> 4) & 0x3));
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100476
Ed Tanous1abe55e2018-09-05 08:30:59 -0700477 if (++i < inputLength)
478 {
479 char c = input[i];
480 if (c == '=')
481 { // padding , end of input
482 return (base64code1 & 0x0f) == 0;
483 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700484 base64code2 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700485 if (base64code2 == nop)
486 { // non base64 character
487 return false;
488 }
489 output += static_cast<char>(((base64code1 << 4) & 0xf0) |
490 ((base64code2 >> 2) & 0x0f));
491 }
492
493 if (++i < inputLength)
494 {
495 char c = input[i];
496 if (c == '=')
497 { // padding , end of input
498 return (base64code2 & 0x03) == 0;
499 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700500 base64code3 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700501 if (base64code3 == nop)
502 { // non base64 character
503 return false;
504 }
505 output +=
506 static_cast<char>((((base64code2 << 6) & 0xc0) | base64code3));
507 }
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100508 }
509
Ed Tanous1abe55e2018-09-05 08:30:59 -0700510 return true;
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100511}
512
Andrew Geisslercb92c032018-08-17 07:56:14 -0700513/**
514 * Method returns Date Time information according to requested format
515 *
516 * @param[in] time time in second since the Epoch
517 *
518 * @return Date Time according to requested format
519 */
520inline std::string getDateTime(const std::time_t& time)
521{
522 std::array<char, 128> dateTime;
523 std::string redfishDateTime("0000-00-00T00:00:00Z00:00");
524
525 if (std::strftime(dateTime.begin(), dateTime.size(), "%FT%T%z",
526 std::localtime(&time)))
527 {
528 // insert the colon required by the ISO 8601 standard
529 redfishDateTime = std::string(dateTime.data());
530 redfishDateTime.insert(redfishDateTime.end() - 2, ':');
531 }
532
533 return redfishDateTime;
534}
535
536inline std::string dateTimeNow()
537{
538 std::time_t time = std::time(nullptr);
539 return getDateTime(time);
540}
541
Ed Tanous51dae672018-09-05 16:07:32 -0700542inline bool constantTimeStringCompare(const std::string_view a,
543 const std::string_view b)
544{
545 // Important note, this function is ONLY constant time if the two input
546 // sizes are the same
547 if (a.size() != b.size())
548 {
549 return false;
550 }
551 return CRYPTO_memcmp(a.data(), b.data(), a.size()) == 0;
552}
553
554struct ConstantTimeCompare
555{
556 bool operator()(const std::string_view a, const std::string_view b) const
557 {
558 return constantTimeStringCompare(a, b);
559 }
560};
561
George Liud139c232020-08-18 18:48:57 +0800562inline std::time_t getTimestamp(uint64_t millisTimeStamp)
563{
564 // Retrieve Created property with format:
565 // yyyy-mm-ddThh:mm:ss
566 std::chrono::milliseconds chronoTimeStamp(millisTimeStamp);
567 return std::chrono::duration_cast<std::chrono::duration<int>>(
568 chronoTimeStamp)
569 .count();
570}
571
Ed Tanous1abe55e2018-09-05 08:30:59 -0700572} // namespace utility
573} // namespace crow