| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 1 | #pragma once | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 2 |  | 
| Ed Tanous | 51dae67 | 2018-09-05 16:07:32 -0700 | [diff] [blame] | 3 | #include <openssl/crypto.h> | 
 | 4 |  | 
| Nan Zhou | 1d8782e | 2021-11-29 22:23:18 -0800 | [diff] [blame] | 5 | #include <boost/date_time/posix_time/posix_time.hpp> | 
| Ed Tanous | eae855c | 2021-10-26 11:26:02 -0700 | [diff] [blame] | 6 | #include <boost/url/url.hpp> | 
| Nan Zhou | 1d8782e | 2021-11-29 22:23:18 -0800 | [diff] [blame] | 7 |  | 
| Ed Tanous | 9ea15c3 | 2022-01-04 14:18:22 -0800 | [diff] [blame] | 8 | #include <array> | 
| Ed Tanous | 74849be | 2021-02-05 09:47:47 -0800 | [diff] [blame] | 9 | #include <chrono> | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 10 | #include <cstdint> | 
| Ed Tanous | 9ea15c3 | 2022-01-04 14:18:22 -0800 | [diff] [blame] | 11 | #include <ctime> | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 12 | #include <functional> | 
| Ed Tanous | 9ea15c3 | 2022-01-04 14:18:22 -0800 | [diff] [blame] | 13 | #include <limits> | 
| Ed Tanous | 11baefe | 2022-02-09 12:14:12 -0800 | [diff] [blame] | 14 | #include <regex> | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 15 | #include <stdexcept> | 
 | 16 | #include <string> | 
| Ed Tanous | 9ea15c3 | 2022-01-04 14:18:22 -0800 | [diff] [blame] | 17 | #include <string_view> | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 18 | #include <tuple> | 
| Ed Tanous | 9ea15c3 | 2022-01-04 14:18:22 -0800 | [diff] [blame] | 19 | #include <type_traits> | 
 | 20 | #include <utility> | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 21 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 22 | namespace crow | 
 | 23 | { | 
 | 24 | namespace black_magic | 
 | 25 | { | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 26 |  | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 27 | constexpr unsigned findClosingTag(std::string_view s, unsigned p) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 28 | { | 
 | 29 |     return s[p] == '>' ? p : findClosingTag(s, p + 1); | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 30 | } | 
 | 31 |  | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 32 | constexpr bool isInt(std::string_view s, unsigned i) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 33 | { | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 34 |     return s.substr(i, 5) == "<int>"; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 35 | } | 
 | 36 |  | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 37 | constexpr bool isUint(std::string_view s, unsigned i) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 38 | { | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 39 |     return s.substr(i, 6) == "<uint>"; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 40 | } | 
 | 41 |  | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 42 | constexpr bool isFloat(std::string_view s, unsigned i) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 43 | { | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 44 |     return s.substr(i, 7) == "<float>" || s.substr(i, 8) == "<double>"; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 45 | } | 
 | 46 |  | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 47 | constexpr bool isStr(std::string_view s, unsigned i) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 48 | { | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 49 |     return s.substr(i, 5) == "<str>" || s.substr(i, 8) == "<string>"; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 50 | } | 
 | 51 |  | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 52 | constexpr bool isPath(std::string_view s, unsigned i) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 53 | { | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 54 |     return s.substr(i, 6) == "<path>"; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 55 | } | 
| Ed Tanous | 3dac749 | 2017-08-02 13:46:20 -0700 | [diff] [blame] | 56 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 57 | template <typename T> | 
 | 58 | constexpr int getParameterTag() | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 59 | { | 
| Ed Tanous | 6950901 | 2019-10-24 16:53:05 -0700 | [diff] [blame] | 60 |     if constexpr (std::is_same_v<int, T>) | 
 | 61 |     { | 
 | 62 |         return 1; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 63 |     } | 
| Ed Tanous | 6950901 | 2019-10-24 16:53:05 -0700 | [diff] [blame] | 64 |     if constexpr (std::is_same_v<char, T>) | 
 | 65 |     { | 
 | 66 |         return 1; | 
 | 67 |     } | 
 | 68 |     if constexpr (std::is_same_v<short, T>) | 
 | 69 |     { | 
 | 70 |         return 1; | 
 | 71 |     } | 
 | 72 |     if constexpr (std::is_same_v<long, T>) | 
 | 73 |     { | 
 | 74 |         return 1; | 
 | 75 |     } | 
 | 76 |     if constexpr (std::is_same_v<long long, T>) | 
 | 77 |     { | 
 | 78 |         return 1; | 
 | 79 |     } | 
 | 80 |     if constexpr (std::is_same_v<unsigned int, T>) | 
 | 81 |     { | 
 | 82 |         return 2; | 
 | 83 |     } | 
 | 84 |     if constexpr (std::is_same_v<unsigned char, T>) | 
 | 85 |     { | 
 | 86 |         return 2; | 
 | 87 |     } | 
 | 88 |     if constexpr (std::is_same_v<unsigned short, T>) | 
 | 89 |     { | 
 | 90 |         return 2; | 
 | 91 |     } | 
 | 92 |     if constexpr (std::is_same_v<unsigned long, T>) | 
 | 93 |     { | 
 | 94 |         return 2; | 
 | 95 |     } | 
 | 96 |     if constexpr (std::is_same_v<unsigned long long, T>) | 
 | 97 |     { | 
 | 98 |         return 2; | 
 | 99 |     } | 
 | 100 |     if constexpr (std::is_same_v<double, T>) | 
 | 101 |     { | 
 | 102 |         return 3; | 
 | 103 |     } | 
 | 104 |     if constexpr (std::is_same_v<std::string, T>) | 
 | 105 |     { | 
 | 106 |         return 4; | 
 | 107 |     } | 
 | 108 |     return 0; | 
 | 109 | } | 
 | 110 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 111 | template <typename... Args> | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 112 | struct computeParameterTagFromArgsList; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 113 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 114 | template <> | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 115 | struct computeParameterTagFromArgsList<> | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 116 | { | 
| Ed Tanous | 6950901 | 2019-10-24 16:53:05 -0700 | [diff] [blame] | 117 |     static constexpr int value = 0; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 118 | }; | 
 | 119 |  | 
 | 120 | template <typename Arg, typename... Args> | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 121 | struct computeParameterTagFromArgsList<Arg, Args...> | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 122 | { | 
| Ed Tanous | 6950901 | 2019-10-24 16:53:05 -0700 | [diff] [blame] | 123 |     static constexpr int subValue = | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 124 |         computeParameterTagFromArgsList<Args...>::value; | 
| Ed Tanous | 6950901 | 2019-10-24 16:53:05 -0700 | [diff] [blame] | 125 |     static constexpr int value = | 
 | 126 |         getParameterTag<typename std::decay<Arg>::type>() | 
 | 127 |             ? subValue * 6 + getParameterTag<typename std::decay<Arg>::type>() | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 128 |             : subValue; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 129 | }; | 
 | 130 |  | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 131 | inline bool isParameterTagCompatible(uint64_t a, uint64_t b) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 132 | { | 
| Ed Tanous | b00dcc2 | 2021-02-23 12:52:50 -0800 | [diff] [blame] | 133 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 134 |     if (a == 0) | 
 | 135 |     { | 
 | 136 |         return b == 0; | 
 | 137 |     } | 
 | 138 |     if (b == 0) | 
 | 139 |     { | 
 | 140 |         return a == 0; | 
 | 141 |     } | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 142 |     uint64_t sa = a % 6; | 
 | 143 |     uint64_t sb = a % 6; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 144 |     if (sa == 5) | 
 | 145 |     { | 
 | 146 |         sa = 4; | 
 | 147 |     } | 
 | 148 |     if (sb == 5) | 
 | 149 |     { | 
 | 150 |         sb = 4; | 
 | 151 |     } | 
 | 152 |     if (sa != sb) | 
 | 153 |     { | 
 | 154 |         return false; | 
 | 155 |     } | 
 | 156 |     return isParameterTagCompatible(a / 6, b / 6); | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 157 | } | 
 | 158 |  | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 159 | constexpr uint64_t getParameterTag(std::string_view s, unsigned p = 0) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 160 | { | 
| Ed Tanous | b00dcc2 | 2021-02-23 12:52:50 -0800 | [diff] [blame] | 161 |  | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 162 |     if (p == s.size()) | 
 | 163 |     { | 
 | 164 |         return 0; | 
 | 165 |     } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 166 |  | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 167 |     if (s[p] != '<') | 
 | 168 |     { | 
 | 169 |         return getParameterTag(s, p + 1); | 
 | 170 |     } | 
| Ed Tanous | 3dac749 | 2017-08-02 13:46:20 -0700 | [diff] [blame] | 171 |  | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 172 |     if (isInt(s, p)) | 
 | 173 |     { | 
 | 174 |         return getParameterTag(s, findClosingTag(s, p)) * 6 + 1; | 
 | 175 |     } | 
 | 176 |  | 
 | 177 |     if (isUint(s, p)) | 
 | 178 |     { | 
 | 179 |         return getParameterTag(s, findClosingTag(s, p)) * 6 + 2; | 
 | 180 |     } | 
 | 181 |  | 
 | 182 |     if (isFloat(s, p)) | 
 | 183 |     { | 
 | 184 |         return getParameterTag(s, findClosingTag(s, p)) * 6 + 3; | 
 | 185 |     } | 
 | 186 |  | 
 | 187 |     if (isStr(s, p)) | 
 | 188 |     { | 
 | 189 |         return getParameterTag(s, findClosingTag(s, p)) * 6 + 4; | 
 | 190 |     } | 
 | 191 |  | 
 | 192 |     if (isPath(s, p)) | 
 | 193 |     { | 
 | 194 |         return getParameterTag(s, findClosingTag(s, p)) * 6 + 5; | 
 | 195 |     } | 
 | 196 |  | 
 | 197 |     throw std::runtime_error("invalid parameter type"); | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 198 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 199 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 200 | template <typename... T> | 
 | 201 | struct S | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 202 | { | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 203 |     template <typename U> | 
 | 204 |     using push = S<U, T...>; | 
 | 205 |     template <typename U> | 
 | 206 |     using push_back = S<T..., U>; | 
 | 207 |     template <template <typename... Args> class U> | 
 | 208 |     using rebind = U<T...>; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 209 | }; | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 210 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 211 | template <typename F, typename Set> | 
 | 212 | struct CallHelper; | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 213 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 214 | template <typename F, typename... Args> | 
 | 215 | struct CallHelper<F, S<Args...>> | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 216 | { | 
 | 217 |     template <typename F1, typename... Args1, | 
 | 218 |               typename = decltype(std::declval<F1>()(std::declval<Args1>()...))> | 
| Ed Tanous | 2c70f80 | 2020-09-28 14:29:23 -0700 | [diff] [blame] | 219 |     static char test(int); | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 220 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 221 |     template <typename...> | 
| Ed Tanous | 2c70f80 | 2020-09-28 14:29:23 -0700 | [diff] [blame] | 222 |     static int test(...); | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 223 |  | 
| Ed Tanous | 2c70f80 | 2020-09-28 14:29:23 -0700 | [diff] [blame] | 224 |     static constexpr bool value = sizeof(test<F, Args...>(0)) == sizeof(char); | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 225 | }; | 
 | 226 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 227 | template <uint64_t N> | 
 | 228 | struct SingleTagToType | 
 | 229 | {}; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 230 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 231 | template <> | 
 | 232 | struct SingleTagToType<1> | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 233 | { | 
 | 234 |     using type = int64_t; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 235 | }; | 
 | 236 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 237 | template <> | 
 | 238 | struct SingleTagToType<2> | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 239 | { | 
 | 240 |     using type = uint64_t; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 241 | }; | 
 | 242 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 243 | template <> | 
 | 244 | struct SingleTagToType<3> | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 245 | { | 
 | 246 |     using type = double; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 247 | }; | 
 | 248 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 249 | template <> | 
 | 250 | struct SingleTagToType<4> | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 251 | { | 
 | 252 |     using type = std::string; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 253 | }; | 
 | 254 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 255 | template <> | 
 | 256 | struct SingleTagToType<5> | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 257 | { | 
 | 258 |     using type = std::string; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 259 | }; | 
 | 260 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 261 | template <uint64_t Tag> | 
 | 262 | struct Arguments | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 263 | { | 
 | 264 |     using subarguments = typename Arguments<Tag / 6>::type; | 
 | 265 |     using type = typename subarguments::template push< | 
 | 266 |         typename SingleTagToType<Tag % 6>::type>; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 267 | }; | 
 | 268 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 269 | template <> | 
 | 270 | struct Arguments<0> | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 271 | { | 
 | 272 |     using type = S<>; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 273 | }; | 
 | 274 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 275 | template <typename T> | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 276 | struct Promote | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 277 | { | 
 | 278 |     using type = T; | 
 | 279 | }; | 
 | 280 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 281 | template <typename T> | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 282 | using PromoteT = typename Promote<T>::type; | 
 | 283 |  | 
 | 284 | template <> | 
 | 285 | struct Promote<char> | 
 | 286 | { | 
 | 287 |     using type = int64_t; | 
 | 288 | }; | 
 | 289 | template <> | 
 | 290 | struct Promote<short> | 
 | 291 | { | 
 | 292 |     using type = int64_t; | 
 | 293 | }; | 
 | 294 | template <> | 
 | 295 | struct Promote<int> | 
 | 296 | { | 
 | 297 |     using type = int64_t; | 
 | 298 | }; | 
 | 299 | template <> | 
 | 300 | struct Promote<long> | 
 | 301 | { | 
 | 302 |     using type = int64_t; | 
 | 303 | }; | 
 | 304 | template <> | 
 | 305 | struct Promote<long long> | 
 | 306 | { | 
 | 307 |     using type = int64_t; | 
 | 308 | }; | 
 | 309 | template <> | 
 | 310 | struct Promote<unsigned char> | 
 | 311 | { | 
 | 312 |     using type = uint64_t; | 
 | 313 | }; | 
 | 314 | template <> | 
 | 315 | struct Promote<unsigned short> | 
 | 316 | { | 
 | 317 |     using type = uint64_t; | 
 | 318 | }; | 
 | 319 | template <> | 
 | 320 | struct Promote<unsigned int> | 
 | 321 | { | 
 | 322 |     using type = uint64_t; | 
 | 323 | }; | 
 | 324 | template <> | 
 | 325 | struct Promote<unsigned long> | 
 | 326 | { | 
 | 327 |     using type = uint64_t; | 
 | 328 | }; | 
 | 329 | template <> | 
 | 330 | struct Promote<unsigned long long> | 
 | 331 | { | 
 | 332 |     using type = uint64_t; | 
 | 333 | }; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 334 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 335 | } // namespace black_magic | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 336 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 337 | namespace detail | 
 | 338 | { | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 339 |  | 
 | 340 | template <class T, std::size_t N, class... Args> | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 341 | struct GetIndexOfElementFromTupleByTypeImpl | 
 | 342 | { | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 343 |     static constexpr std::size_t value = N; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 344 | }; | 
 | 345 |  | 
 | 346 | template <class T, std::size_t N, class... Args> | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 347 | struct GetIndexOfElementFromTupleByTypeImpl<T, N, T, Args...> | 
 | 348 | { | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 349 |     static constexpr std::size_t value = N; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 350 | }; | 
 | 351 |  | 
 | 352 | template <class T, std::size_t N, class U, class... Args> | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 353 | struct GetIndexOfElementFromTupleByTypeImpl<T, N, U, Args...> | 
 | 354 | { | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 355 |     static constexpr std::size_t value = | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 356 |         GetIndexOfElementFromTupleByTypeImpl<T, N + 1, Args...>::value; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 357 | }; | 
 | 358 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 359 | } // namespace detail | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 360 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 361 | namespace utility | 
 | 362 | { | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 363 | template <class T, class... Args> | 
 | 364 | T& getElementByType(std::tuple<Args...>& t) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 365 | { | 
 | 366 |     return std::get< | 
 | 367 |         detail::GetIndexOfElementFromTupleByTypeImpl<T, 0, Args...>::value>(t); | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 368 | } | 
 | 369 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 370 | template <typename T> | 
 | 371 | struct function_traits; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 372 |  | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 373 | template <typename T> | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 374 | struct function_traits : public function_traits<decltype(&T::operator())> | 
 | 375 | { | 
 | 376 |     using parent_t = function_traits<decltype(&T::operator())>; | 
 | 377 |     static const size_t arity = parent_t::arity; | 
 | 378 |     using result_type = typename parent_t::result_type; | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 379 |     template <size_t i> | 
 | 380 |     using arg = typename parent_t::template arg<i>; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 381 | }; | 
| Ed Tanous | 3dac749 | 2017-08-02 13:46:20 -0700 | [diff] [blame] | 382 |  | 
| Ed Tanous | 55c7b7a | 2018-05-22 15:27:24 -0700 | [diff] [blame] | 383 | template <typename ClassType, typename r, typename... Args> | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 384 | struct function_traits<r (ClassType::*)(Args...) const> | 
 | 385 | { | 
 | 386 |     static const size_t arity = sizeof...(Args); | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 387 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 388 |     using result_type = r; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 389 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 390 |     template <size_t i> | 
 | 391 |     using arg = typename std::tuple_element<i, std::tuple<Args...>>::type; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 392 | }; | 
 | 393 |  | 
| Ed Tanous | 55c7b7a | 2018-05-22 15:27:24 -0700 | [diff] [blame] | 394 | template <typename ClassType, typename r, typename... Args> | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 395 | struct function_traits<r (ClassType::*)(Args...)> | 
 | 396 | { | 
 | 397 |     static const size_t arity = sizeof...(Args); | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 398 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 399 |     using result_type = r; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 400 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 401 |     template <size_t i> | 
 | 402 |     using arg = typename std::tuple_element<i, std::tuple<Args...>>::type; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 403 | }; | 
 | 404 |  | 
| Ed Tanous | 55c7b7a | 2018-05-22 15:27:24 -0700 | [diff] [blame] | 405 | template <typename r, typename... Args> | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 406 | struct function_traits<std::function<r(Args...)>> | 
 | 407 | { | 
 | 408 |     static const size_t arity = sizeof...(Args); | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 409 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 410 |     using result_type = r; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 411 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 412 |     template <size_t i> | 
 | 413 |     using arg = typename std::tuple_element<i, std::tuple<Args...>>::type; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 414 | }; | 
 | 415 |  | 
| Adriana Kobylak | d830ff5 | 2021-01-27 14:15:27 -0600 | [diff] [blame] | 416 | inline std::string base64encode(const std::string_view data) | 
 | 417 | { | 
 | 418 |     const std::array<char, 64> key = { | 
 | 419 |         'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', | 
 | 420 |         'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', | 
 | 421 |         'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', | 
 | 422 |         'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', | 
 | 423 |         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'}; | 
 | 424 |  | 
 | 425 |     size_t size = data.size(); | 
 | 426 |     std::string ret; | 
 | 427 |     ret.resize((size + 2) / 3 * 4); | 
 | 428 |     auto it = ret.begin(); | 
 | 429 |  | 
 | 430 |     size_t i = 0; | 
 | 431 |     while (i < size) | 
 | 432 |     { | 
| Ed Tanous | 543f440 | 2022-01-06 13:12:53 -0800 | [diff] [blame] | 433 |         size_t keyIndex = 0; | 
| Adriana Kobylak | d830ff5 | 2021-01-27 14:15:27 -0600 | [diff] [blame] | 434 |  | 
 | 435 |         keyIndex = static_cast<size_t>(data[i] & 0xFC) >> 2; | 
 | 436 |         *it++ = key[keyIndex]; | 
 | 437 |  | 
 | 438 |         if (i + 1 < size) | 
 | 439 |         { | 
 | 440 |             keyIndex = static_cast<size_t>(data[i] & 0x03) << 4; | 
 | 441 |             keyIndex += static_cast<size_t>(data[i + 1] & 0xF0) >> 4; | 
 | 442 |             *it++ = key[keyIndex]; | 
 | 443 |  | 
 | 444 |             if (i + 2 < size) | 
 | 445 |             { | 
 | 446 |                 keyIndex = static_cast<size_t>(data[i + 1] & 0x0F) << 2; | 
 | 447 |                 keyIndex += static_cast<size_t>(data[i + 2] & 0xC0) >> 6; | 
 | 448 |                 *it++ = key[keyIndex]; | 
 | 449 |  | 
 | 450 |                 keyIndex = static_cast<size_t>(data[i + 2] & 0x3F); | 
 | 451 |                 *it++ = key[keyIndex]; | 
 | 452 |             } | 
 | 453 |             else | 
 | 454 |             { | 
 | 455 |                 keyIndex = static_cast<size_t>(data[i + 1] & 0x0F) << 2; | 
 | 456 |                 *it++ = key[keyIndex]; | 
 | 457 |                 *it++ = '='; | 
 | 458 |             } | 
 | 459 |         } | 
 | 460 |         else | 
 | 461 |         { | 
 | 462 |             keyIndex = static_cast<size_t>(data[i] & 0x03) << 4; | 
 | 463 |             *it++ = key[keyIndex]; | 
 | 464 |             *it++ = '='; | 
 | 465 |             *it++ = '='; | 
 | 466 |         } | 
 | 467 |  | 
 | 468 |         i += 3; | 
 | 469 |     } | 
 | 470 |  | 
 | 471 |     return ret; | 
 | 472 | } | 
 | 473 |  | 
| Borawski.Lukasz | 9d8fd30 | 2018-01-05 14:56:09 +0100 | [diff] [blame] | 474 | // TODO this is temporary and should be deleted once base64 is refactored out of | 
 | 475 | // crow | 
| Ed Tanous | 39e7750 | 2019-03-04 17:35:53 -0800 | [diff] [blame] | 476 | inline bool base64Decode(const std::string_view input, std::string& output) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 477 | { | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 478 |     static const char nop = static_cast<char>(-1); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 479 |     // See note on encoding_data[] in above function | 
| Jonathan Doman | 5beaf84 | 2020-08-14 11:23:33 -0700 | [diff] [blame] | 480 |     static const std::array<char, 256> decodingData = { | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 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, 62,  nop, nop, nop, 63,  52,  53,  54,  55,  56,  57,  58,  59, | 
 | 485 |         60,  61,  nop, nop, nop, nop, nop, nop, nop, 0,   1,   2,   3,   4, | 
 | 486 |         5,   6,   7,   8,   9,   10,  11,  12,  13,  14,  15,  16,  17,  18, | 
 | 487 |         19,  20,  21,  22,  23,  24,  25,  nop, nop, nop, nop, nop, nop, 26, | 
 | 488 |         27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40, | 
 | 489 |         41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  nop, nop, nop, | 
 | 490 |         nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, | 
 | 491 |         nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, | 
 | 492 |         nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, | 
 | 493 |         nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, | 
 | 494 |         nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, | 
 | 495 |         nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, | 
 | 496 |         nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, | 
 | 497 |         nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, | 
 | 498 |         nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, | 
 | 499 |         nop, nop, nop, nop}; | 
| Borawski.Lukasz | 9d8fd30 | 2018-01-05 14:56:09 +0100 | [diff] [blame] | 500 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 501 |     size_t inputLength = input.size(); | 
| Borawski.Lukasz | 9d8fd30 | 2018-01-05 14:56:09 +0100 | [diff] [blame] | 502 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 503 |     // allocate space for output string | 
 | 504 |     output.clear(); | 
 | 505 |     output.reserve(((inputLength + 2) / 3) * 4); | 
| Borawski.Lukasz | 9d8fd30 | 2018-01-05 14:56:09 +0100 | [diff] [blame] | 506 |  | 
| Jonathan Doman | 5beaf84 | 2020-08-14 11:23:33 -0700 | [diff] [blame] | 507 |     auto getCodeValue = [](char c) { | 
 | 508 |         auto code = static_cast<unsigned char>(c); | 
 | 509 |         // Ensure we cannot index outside the bounds of the decoding array | 
 | 510 |         static_assert(std::numeric_limits<decltype(code)>::max() < | 
 | 511 |                       decodingData.size()); | 
 | 512 |         return decodingData[code]; | 
 | 513 |     }; | 
 | 514 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 515 |     // for each 4-bytes sequence from the input, extract 4 6-bits sequences by | 
| Gunnar Mills | caa3ce3 | 2020-07-08 14:46:53 -0500 | [diff] [blame] | 516 |     // dropping first two bits | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 517 |     // and regenerate into 3 8-bits sequences | 
| James Feist | 5a80664 | 2020-07-31 16:40:33 +0000 | [diff] [blame] | 518 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 519 |     for (size_t i = 0; i < inputLength; i++) | 
 | 520 |     { | 
| Ed Tanous | 543f440 | 2022-01-06 13:12:53 -0800 | [diff] [blame] | 521 |         char base64code0 = 0; | 
 | 522 |         char base64code1 = 0; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 523 |         char base64code2 = 0; // initialized to 0 to suppress warnings | 
| Ed Tanous | 543f440 | 2022-01-06 13:12:53 -0800 | [diff] [blame] | 524 |         char base64code3 = 0; | 
| Borawski.Lukasz | 9d8fd30 | 2018-01-05 14:56:09 +0100 | [diff] [blame] | 525 |  | 
| Jonathan Doman | 5beaf84 | 2020-08-14 11:23:33 -0700 | [diff] [blame] | 526 |         base64code0 = getCodeValue(input[i]); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 527 |         if (base64code0 == nop) | 
 | 528 |         { // non base64 character | 
 | 529 |             return false; | 
 | 530 |         } | 
 | 531 |         if (!(++i < inputLength)) | 
 | 532 |         { // we need at least two input bytes for first | 
 | 533 |           // byte output | 
 | 534 |             return false; | 
 | 535 |         } | 
| Jonathan Doman | 5beaf84 | 2020-08-14 11:23:33 -0700 | [diff] [blame] | 536 |         base64code1 = getCodeValue(input[i]); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 537 |         if (base64code1 == nop) | 
 | 538 |         { // non base64 character | 
 | 539 |             return false; | 
 | 540 |         } | 
 | 541 |         output += | 
 | 542 |             static_cast<char>((base64code0 << 2) | ((base64code1 >> 4) & 0x3)); | 
| Borawski.Lukasz | 9d8fd30 | 2018-01-05 14:56:09 +0100 | [diff] [blame] | 543 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 544 |         if (++i < inputLength) | 
 | 545 |         { | 
 | 546 |             char c = input[i]; | 
 | 547 |             if (c == '=') | 
 | 548 |             { // padding , end of input | 
 | 549 |                 return (base64code1 & 0x0f) == 0; | 
 | 550 |             } | 
| Jonathan Doman | 5beaf84 | 2020-08-14 11:23:33 -0700 | [diff] [blame] | 551 |             base64code2 = getCodeValue(input[i]); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 552 |             if (base64code2 == nop) | 
 | 553 |             { // non base64 character | 
 | 554 |                 return false; | 
 | 555 |             } | 
 | 556 |             output += static_cast<char>(((base64code1 << 4) & 0xf0) | | 
 | 557 |                                         ((base64code2 >> 2) & 0x0f)); | 
 | 558 |         } | 
 | 559 |  | 
 | 560 |         if (++i < inputLength) | 
 | 561 |         { | 
 | 562 |             char c = input[i]; | 
 | 563 |             if (c == '=') | 
 | 564 |             { // padding , end of input | 
 | 565 |                 return (base64code2 & 0x03) == 0; | 
 | 566 |             } | 
| Jonathan Doman | 5beaf84 | 2020-08-14 11:23:33 -0700 | [diff] [blame] | 567 |             base64code3 = getCodeValue(input[i]); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 568 |             if (base64code3 == nop) | 
 | 569 |             { // non base64 character | 
 | 570 |                 return false; | 
 | 571 |             } | 
 | 572 |             output += | 
 | 573 |                 static_cast<char>((((base64code2 << 6) & 0xc0) | base64code3)); | 
 | 574 |         } | 
| Borawski.Lukasz | 9d8fd30 | 2018-01-05 14:56:09 +0100 | [diff] [blame] | 575 |     } | 
 | 576 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 577 |     return true; | 
| Borawski.Lukasz | 9d8fd30 | 2018-01-05 14:56:09 +0100 | [diff] [blame] | 578 | } | 
 | 579 |  | 
| Krzysztof Grobelny | 45c367e | 2021-12-29 10:28:53 +0100 | [diff] [blame] | 580 | namespace details | 
 | 581 | { | 
| Ed Tanous | 22ce545 | 2022-01-11 10:50:23 -0800 | [diff] [blame] | 582 | constexpr uint64_t maxMilliSeconds = 253402300799999; | 
 | 583 | constexpr uint64_t maxSeconds = 253402300799; | 
| Krzysztof Grobelny | 45c367e | 2021-12-29 10:28:53 +0100 | [diff] [blame] | 584 | inline std::string getDateTime(boost::posix_time::milliseconds timeSinceEpoch) | 
| Andrew Geissler | cb92c03 | 2018-08-17 07:56:14 -0700 | [diff] [blame] | 585 | { | 
| Nan Zhou | 1d8782e | 2021-11-29 22:23:18 -0800 | [diff] [blame] | 586 |     boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1)); | 
| Krzysztof Grobelny | 45c367e | 2021-12-29 10:28:53 +0100 | [diff] [blame] | 587 |     boost::posix_time::ptime time = epoch + timeSinceEpoch; | 
| Nan Zhou | 1d8782e | 2021-11-29 22:23:18 -0800 | [diff] [blame] | 588 |     // append zero offset to the end according to the Redfish spec for Date-Time | 
| Nan Zhou | 5ae4b69 | 2021-12-14 13:30:37 -0800 | [diff] [blame] | 589 |     return boost::posix_time::to_iso_extended_string(time) + "+00:00"; | 
| Nan Zhou | 1d8782e | 2021-11-29 22:23:18 -0800 | [diff] [blame] | 590 | } | 
| Krzysztof Grobelny | 45c367e | 2021-12-29 10:28:53 +0100 | [diff] [blame] | 591 | } // namespace details | 
| Andrew Geissler | cb92c03 | 2018-08-17 07:56:14 -0700 | [diff] [blame] | 592 |  | 
| Ed Tanous | 22ce545 | 2022-01-11 10:50:23 -0800 | [diff] [blame] | 593 | // Returns the formatted date time string. | 
 | 594 | // Note that the maximum supported date is 9999-12-31T23:59:59+00:00, if | 
 | 595 | // the given |secondsSinceEpoch| is too large, we return the maximum supported | 
 | 596 | // date. This behavior is to avoid exceptions throwed by Boost. | 
| Nan Zhou | 1d8782e | 2021-11-29 22:23:18 -0800 | [diff] [blame] | 597 | inline std::string getDateTimeUint(uint64_t secondsSinceEpoch) | 
 | 598 | { | 
| Nan Zhou | 665479d | 2022-01-26 12:12:59 -0800 | [diff] [blame] | 599 |     secondsSinceEpoch = std::min(secondsSinceEpoch, details::maxSeconds); | 
 | 600 |     boost::posix_time::seconds boostSeconds(secondsSinceEpoch); | 
| Krzysztof Grobelny | 45c367e | 2021-12-29 10:28:53 +0100 | [diff] [blame] | 601 |     return details::getDateTime( | 
 | 602 |         boost::posix_time::milliseconds(boostSeconds.total_milliseconds())); | 
 | 603 | } | 
 | 604 |  | 
| Ed Tanous | 22ce545 | 2022-01-11 10:50:23 -0800 | [diff] [blame] | 605 | // Returns the formatted date time string. | 
 | 606 | // Note that the maximum supported date is 9999-12-31T23:59:59.999+00:00, if | 
 | 607 | // the given |millisSecondsSinceEpoch| is too large, we return the maximum | 
 | 608 | // supported date. | 
 | 609 | inline std::string getDateTimeUintMs(uint64_t milliSecondsSinceEpoch) | 
| Krzysztof Grobelny | 45c367e | 2021-12-29 10:28:53 +0100 | [diff] [blame] | 610 | { | 
| Nan Zhou | 665479d | 2022-01-26 12:12:59 -0800 | [diff] [blame] | 611 |     milliSecondsSinceEpoch = | 
 | 612 |         std::min(details::maxMilliSeconds, milliSecondsSinceEpoch); | 
 | 613 |     return details::getDateTime( | 
 | 614 |         boost::posix_time::milliseconds(milliSecondsSinceEpoch)); | 
| Nan Zhou | 1d8782e | 2021-11-29 22:23:18 -0800 | [diff] [blame] | 615 | } | 
| Andrew Geissler | cb92c03 | 2018-08-17 07:56:14 -0700 | [diff] [blame] | 616 |  | 
| Nan Zhou | 1d8782e | 2021-11-29 22:23:18 -0800 | [diff] [blame] | 617 | inline std::string getDateTimeStdtime(std::time_t secondsSinceEpoch) | 
 | 618 | { | 
| Nan Zhou | 665479d | 2022-01-26 12:12:59 -0800 | [diff] [blame] | 619 |     if (secondsSinceEpoch > static_cast<int64_t>(details::maxSeconds)) | 
 | 620 |     { | 
 | 621 |         secondsSinceEpoch = static_cast<std::time_t>(details::maxSeconds); | 
 | 622 |     } | 
 | 623 |     boost::posix_time::ptime time = | 
 | 624 |         boost::posix_time::from_time_t(secondsSinceEpoch); | 
| Krzysztof Grobelny | 45c367e | 2021-12-29 10:28:53 +0100 | [diff] [blame] | 625 |     return boost::posix_time::to_iso_extended_string(time) + "+00:00"; | 
| Andrew Geissler | cb92c03 | 2018-08-17 07:56:14 -0700 | [diff] [blame] | 626 | } | 
 | 627 |  | 
| Tejas Patil | 7c8c405 | 2021-06-04 17:43:14 +0530 | [diff] [blame] | 628 | /** | 
 | 629 |  * Returns the current Date, Time & the local Time Offset | 
 | 630 |  * infromation in a pair | 
 | 631 |  * | 
 | 632 |  * @param[in] None | 
 | 633 |  * | 
 | 634 |  * @return std::pair<std::string, std::string>, which consist | 
 | 635 |  * of current DateTime & the TimeOffset strings respectively. | 
 | 636 |  */ | 
 | 637 | inline std::pair<std::string, std::string> getDateTimeOffsetNow() | 
| Andrew Geissler | cb92c03 | 2018-08-17 07:56:14 -0700 | [diff] [blame] | 638 | { | 
 | 639 |     std::time_t time = std::time(nullptr); | 
| Nan Zhou | 1d8782e | 2021-11-29 22:23:18 -0800 | [diff] [blame] | 640 |     std::string dateTime = getDateTimeStdtime(time); | 
| Tejas Patil | 7c8c405 | 2021-06-04 17:43:14 +0530 | [diff] [blame] | 641 |  | 
 | 642 |     /* extract the local Time Offset value from the | 
 | 643 |      * recevied dateTime string. | 
 | 644 |      */ | 
 | 645 |     std::string timeOffset("Z00:00"); | 
 | 646 |     std::size_t lastPos = dateTime.size(); | 
 | 647 |     std::size_t len = timeOffset.size(); | 
 | 648 |     if (lastPos > len) | 
 | 649 |     { | 
 | 650 |         timeOffset = dateTime.substr(lastPos - len); | 
 | 651 |     } | 
 | 652 |  | 
 | 653 |     return std::make_pair(dateTime, timeOffset); | 
| Andrew Geissler | cb92c03 | 2018-08-17 07:56:14 -0700 | [diff] [blame] | 654 | } | 
 | 655 |  | 
| Ed Tanous | 51dae67 | 2018-09-05 16:07:32 -0700 | [diff] [blame] | 656 | inline bool constantTimeStringCompare(const std::string_view a, | 
 | 657 |                                       const std::string_view b) | 
 | 658 | { | 
 | 659 |     // Important note, this function is ONLY constant time if the two input | 
 | 660 |     // sizes are the same | 
 | 661 |     if (a.size() != b.size()) | 
 | 662 |     { | 
 | 663 |         return false; | 
 | 664 |     } | 
 | 665 |     return CRYPTO_memcmp(a.data(), b.data(), a.size()) == 0; | 
 | 666 | } | 
 | 667 |  | 
 | 668 | struct ConstantTimeCompare | 
 | 669 | { | 
 | 670 |     bool operator()(const std::string_view a, const std::string_view b) const | 
 | 671 |     { | 
 | 672 |         return constantTimeStringCompare(a, b); | 
 | 673 |     } | 
 | 674 | }; | 
 | 675 |  | 
| Ed Tanous | eae855c | 2021-10-26 11:26:02 -0700 | [diff] [blame] | 676 | namespace details | 
 | 677 | { | 
 | 678 | inline boost::urls::url | 
 | 679 |     urlFromPiecesDetail(const std::initializer_list<std::string_view> args) | 
 | 680 | { | 
 | 681 |     boost::urls::url url("/"); | 
 | 682 |     for (const std::string_view& arg : args) | 
 | 683 |     { | 
 | 684 |         url.segments().push_back(arg); | 
 | 685 |     } | 
 | 686 |     return url; | 
 | 687 | } | 
 | 688 | } // namespace details | 
 | 689 |  | 
 | 690 | template <typename... AV> | 
 | 691 | inline boost::urls::url urlFromPieces(const AV... args) | 
 | 692 | { | 
 | 693 |     return details::urlFromPiecesDetail({args...}); | 
 | 694 | } | 
 | 695 |  | 
| Ed Tanous | 11baefe | 2022-02-09 12:14:12 -0800 | [diff] [blame] | 696 | inline bool validateAndSplitUrl(std::string_view destUrl, std::string& urlProto, | 
 | 697 |                                 std::string& host, std::string& port, | 
 | 698 |                                 std::string& path) | 
 | 699 | { | 
 | 700 |     // Validate URL using regex expression | 
 | 701 |     // Format: <protocol>://<host>:<port>/<path> | 
 | 702 |     // protocol: http/https | 
 | 703 |     const std::regex urlRegex( | 
 | 704 |         "(http|https)://([^/\\x20\\x3f\\x23\\x3a]+):?([0-9]*)(/" | 
 | 705 |         "([^\\x20\\x23\\x3f]*\\x3f?([^\\x20\\x23\\x3f])*)?)"); | 
 | 706 |     std::cmatch match; | 
 | 707 |     if (!std::regex_match(destUrl.begin(), destUrl.end(), match, urlRegex)) | 
 | 708 |     { | 
 | 709 |         return false; | 
 | 710 |     } | 
 | 711 |  | 
 | 712 |     urlProto = std::string(match[1].first, match[1].second); | 
 | 713 |     if (urlProto == "http") | 
 | 714 |     { | 
 | 715 | #ifndef BMCWEB_INSECURE_ENABLE_HTTP_PUSH_STYLE_EVENTING | 
 | 716 |         return false; | 
 | 717 | #endif | 
 | 718 |     } | 
 | 719 |  | 
 | 720 |     host = std::string(match[2].first, match[2].second); | 
 | 721 |     port = std::string(match[3].first, match[3].second); | 
 | 722 |     path = std::string(match[4].first, match[4].second); | 
 | 723 |     if (port.empty()) | 
 | 724 |     { | 
 | 725 |         if (urlProto == "http") | 
 | 726 |         { | 
 | 727 |             port = "80"; | 
 | 728 |         } | 
 | 729 |         else | 
 | 730 |         { | 
 | 731 |             port = "443"; | 
 | 732 |         } | 
 | 733 |     } | 
 | 734 |     if (path.empty()) | 
 | 735 |     { | 
 | 736 |         path = "/"; | 
 | 737 |     } | 
 | 738 |     return true; | 
 | 739 | } | 
 | 740 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 741 | } // namespace utility | 
 | 742 | } // namespace crow |