blob: dc7ea7f1b27329af6c72c569acbe9c19a8f0875e [file] [log] [blame]
Ed Tanous7045c8d2017-04-03 10:04:37 -07001#pragma once
Ed Tanous1abe55e2018-09-05 08:30:59 -07002
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08003#include "bmcweb_config.h"
4
Ed Tanous51dae672018-09-05 16:07:32 -07005#include <openssl/crypto.h>
6
Ed Tanousc867a832022-03-10 14:17:00 -08007#include <boost/callable_traits.hpp>
Ed Tanous079360a2022-06-29 10:05:19 -07008#include <boost/url/parse.hpp>
Ed Tanouseae855c2021-10-26 11:26:02 -07009#include <boost/url/url.hpp>
Ed Tanous079360a2022-06-29 10:05:19 -070010#include <boost/url/url_view.hpp>
Ed Tanous71f2db72022-05-25 12:28:09 -070011#include <nlohmann/json.hpp>
Nan Zhou1d8782e2021-11-29 22:23:18 -080012
Ed Tanous9ea15c32022-01-04 14:18:22 -080013#include <array>
Ed Tanous74849be2021-02-05 09:47:47 -080014#include <chrono>
Ed Tanousc715ec22022-03-10 15:38:01 -080015#include <cstddef>
Ed Tanous7045c8d2017-04-03 10:04:37 -070016#include <cstdint>
Ed Tanous9ea15c32022-01-04 14:18:22 -080017#include <ctime>
Ed Tanous7045c8d2017-04-03 10:04:37 -070018#include <functional>
Ed Tanous9896eae2022-07-23 15:07:33 -070019#include <iomanip>
Ed Tanous9ea15c32022-01-04 14:18:22 -080020#include <limits>
Ed Tanous7045c8d2017-04-03 10:04:37 -070021#include <stdexcept>
22#include <string>
Ed Tanous9ea15c32022-01-04 14:18:22 -080023#include <string_view>
Ed Tanous7045c8d2017-04-03 10:04:37 -070024#include <tuple>
Ed Tanous9ea15c32022-01-04 14:18:22 -080025#include <type_traits>
26#include <utility>
Szymon Dompkeca1600c2022-03-03 14:42:52 +010027#include <variant>
Ed Tanous7045c8d2017-04-03 10:04:37 -070028
Ed Tanous1abe55e2018-09-05 08:30:59 -070029namespace crow
30{
Ed Tanous47488a92023-06-26 18:19:33 -070031namespace utility
Ed Tanous1abe55e2018-09-05 08:30:59 -070032{
Ed Tanous7045c8d2017-04-03 10:04:37 -070033
Ed Tanousc715ec22022-03-10 15:38:01 -080034enum class TypeCode : uint8_t
35{
36 Unspecified = 0,
Ed Tanous15a42df2023-02-09 18:08:23 -080037 String = 1,
38 Path = 2,
39 Max = 3,
Ed Tanousc715ec22022-03-10 15:38:01 -080040};
41
42// Remove when we have c++23
43template <typename E>
44constexpr typename std::underlying_type<E>::type toUnderlying(E e) noexcept
45{
46 return static_cast<typename std::underlying_type<E>::type>(e);
47}
48
Ed Tanous1c30e502022-03-08 18:02:24 -080049constexpr inline uint64_t getParameterTag(std::string_view url)
Ed Tanous1abe55e2018-09-05 08:30:59 -070050{
Ed Tanous1c30e502022-03-08 18:02:24 -080051 uint64_t tagValue = 0;
52 size_t urlSegmentIndex = std::string_view::npos;
Ed Tanousb00dcc22021-02-23 12:52:50 -080053
Ed Tanous1c30e502022-03-08 18:02:24 -080054 size_t paramIndex = 0;
55
56 for (size_t urlIndex = 0; urlIndex < url.size(); urlIndex++)
57 {
58 char character = url[urlIndex];
59 if (character == '<')
60 {
61 if (urlSegmentIndex != std::string_view::npos)
62 {
63 return 0;
64 }
65 urlSegmentIndex = urlIndex;
66 }
67 if (character == '>')
68 {
69 if (urlSegmentIndex == std::string_view::npos)
70 {
71 return 0;
72 }
Patrick Williams89492a12023-05-10 07:51:34 -050073 std::string_view tag = url.substr(urlSegmentIndex,
74 urlIndex + 1 - urlSegmentIndex);
Ed Tanous1c30e502022-03-08 18:02:24 -080075
76 // Note, this is a really lame way to do std::pow(6, paramIndex)
77 // std::pow doesn't work in constexpr in clang.
78 // Ideally in the future we'd move this to use a power of 2 packing
79 // (probably 8 instead of 6) so that these just become bit shifts
80 uint64_t insertIndex = 1;
81 for (size_t unused = 0; unused < paramIndex; unused++)
82 {
Ed Tanous15a42df2023-02-09 18:08:23 -080083 insertIndex *= 3;
Ed Tanous1c30e502022-03-08 18:02:24 -080084 }
85
Ed Tanous1c30e502022-03-08 18:02:24 -080086 if (tag == "<str>" || tag == "<string>")
87 {
Ed Tanousc715ec22022-03-10 15:38:01 -080088 tagValue += insertIndex * toUnderlying(TypeCode::String);
Ed Tanous1c30e502022-03-08 18:02:24 -080089 }
90 if (tag == "<path>")
91 {
Ed Tanousc715ec22022-03-10 15:38:01 -080092 tagValue += insertIndex * toUnderlying(TypeCode::Path);
Ed Tanous1c30e502022-03-08 18:02:24 -080093 }
94 paramIndex++;
95 urlSegmentIndex = std::string_view::npos;
96 }
97 }
98 if (urlSegmentIndex != std::string_view::npos)
Ed Tanous988403c2020-08-24 11:29:49 -070099 {
100 return 0;
101 }
Ed Tanous1c30e502022-03-08 18:02:24 -0800102 return tagValue;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700103}
Ed Tanous7045c8d2017-04-03 10:04:37 -0700104
Ed Tanouscfe3bc02023-06-26 12:47:24 -0700105constexpr size_t numArgsFromTag(int tag)
106{
107 size_t ret = 0;
108 while (tag > 0)
109 {
110 // Move to the next tag by removing the bottom bits from the number
Ed Tanous47488a92023-06-26 18:19:33 -0700111 tag /= toUnderlying(TypeCode::Max);
Ed Tanouscfe3bc02023-06-26 12:47:24 -0700112 ret++;
113 }
114 return ret;
115};
116
Ed Tanous26ccae32023-02-16 10:28:44 -0800117inline std::string base64encode(std::string_view data)
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600118{
119 const std::array<char, 64> key = {
120 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
121 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
122 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
123 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
124 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
125
126 size_t size = data.size();
127 std::string ret;
128 ret.resize((size + 2) / 3 * 4);
129 auto it = ret.begin();
130
131 size_t i = 0;
132 while (i < size)
133 {
Ed Tanous543f4402022-01-06 13:12:53 -0800134 size_t keyIndex = 0;
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600135
136 keyIndex = static_cast<size_t>(data[i] & 0xFC) >> 2;
137 *it++ = key[keyIndex];
138
139 if (i + 1 < size)
140 {
141 keyIndex = static_cast<size_t>(data[i] & 0x03) << 4;
142 keyIndex += static_cast<size_t>(data[i + 1] & 0xF0) >> 4;
143 *it++ = key[keyIndex];
144
145 if (i + 2 < size)
146 {
147 keyIndex = static_cast<size_t>(data[i + 1] & 0x0F) << 2;
148 keyIndex += static_cast<size_t>(data[i + 2] & 0xC0) >> 6;
149 *it++ = key[keyIndex];
150
151 keyIndex = static_cast<size_t>(data[i + 2] & 0x3F);
152 *it++ = key[keyIndex];
153 }
154 else
155 {
156 keyIndex = static_cast<size_t>(data[i + 1] & 0x0F) << 2;
157 *it++ = key[keyIndex];
158 *it++ = '=';
159 }
160 }
161 else
162 {
163 keyIndex = static_cast<size_t>(data[i] & 0x03) << 4;
164 *it++ = key[keyIndex];
165 *it++ = '=';
166 *it++ = '=';
167 }
168
169 i += 3;
170 }
171
172 return ret;
173}
174
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100175// TODO this is temporary and should be deleted once base64 is refactored out of
176// crow
Ed Tanous26ccae32023-02-16 10:28:44 -0800177inline bool base64Decode(std::string_view input, std::string& output)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700178{
Ed Tanous271584a2019-07-09 16:24:22 -0700179 static const char nop = static_cast<char>(-1);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700180 // See note on encoding_data[] in above function
Jonathan Doman5beaf842020-08-14 11:23:33 -0700181 static const std::array<char, 256> decodingData = {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700182 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
183 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
184 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
185 nop, 62, nop, nop, nop, 63, 52, 53, 54, 55, 56, 57, 58, 59,
186 60, 61, nop, nop, nop, nop, nop, nop, nop, 0, 1, 2, 3, 4,
187 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
188 19, 20, 21, 22, 23, 24, 25, nop, nop, nop, nop, nop, nop, 26,
189 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
190 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, nop, nop, nop,
191 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
192 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
193 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
194 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
195 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
196 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
197 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
198 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
199 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
200 nop, nop, nop, nop};
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100201
Ed Tanous1abe55e2018-09-05 08:30:59 -0700202 size_t inputLength = input.size();
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100203
Ed Tanous1abe55e2018-09-05 08:30:59 -0700204 // allocate space for output string
205 output.clear();
206 output.reserve(((inputLength + 2) / 3) * 4);
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100207
Jonathan Doman5beaf842020-08-14 11:23:33 -0700208 auto getCodeValue = [](char c) {
209 auto code = static_cast<unsigned char>(c);
210 // Ensure we cannot index outside the bounds of the decoding array
211 static_assert(std::numeric_limits<decltype(code)>::max() <
212 decodingData.size());
213 return decodingData[code];
214 };
215
Ed Tanous1abe55e2018-09-05 08:30:59 -0700216 // for each 4-bytes sequence from the input, extract 4 6-bits sequences by
Gunnar Millscaa3ce32020-07-08 14:46:53 -0500217 // dropping first two bits
Ed Tanous1abe55e2018-09-05 08:30:59 -0700218 // and regenerate into 3 8-bits sequences
James Feist5a806642020-07-31 16:40:33 +0000219
Ed Tanous1abe55e2018-09-05 08:30:59 -0700220 for (size_t i = 0; i < inputLength; i++)
221 {
Ed Tanous543f4402022-01-06 13:12:53 -0800222 char base64code0 = 0;
223 char base64code1 = 0;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700224 char base64code2 = 0; // initialized to 0 to suppress warnings
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100225
Jonathan Doman5beaf842020-08-14 11:23:33 -0700226 base64code0 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700227 if (base64code0 == nop)
228 { // non base64 character
229 return false;
230 }
231 if (!(++i < inputLength))
232 { // we need at least two input bytes for first
233 // byte output
234 return false;
235 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700236 base64code1 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700237 if (base64code1 == nop)
238 { // non base64 character
239 return false;
240 }
241 output +=
242 static_cast<char>((base64code0 << 2) | ((base64code1 >> 4) & 0x3));
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100243
Ed Tanous1abe55e2018-09-05 08:30:59 -0700244 if (++i < inputLength)
245 {
246 char c = input[i];
247 if (c == '=')
248 { // padding , end of input
249 return (base64code1 & 0x0f) == 0;
250 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700251 base64code2 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700252 if (base64code2 == nop)
253 { // non base64 character
254 return false;
255 }
256 output += static_cast<char>(((base64code1 << 4) & 0xf0) |
257 ((base64code2 >> 2) & 0x0f));
258 }
259
260 if (++i < inputLength)
261 {
262 char c = input[i];
263 if (c == '=')
264 { // padding , end of input
265 return (base64code2 & 0x03) == 0;
266 }
Ed Tanousf8fe53e2022-06-30 15:55:45 -0700267 char base64code3 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700268 if (base64code3 == nop)
269 { // non base64 character
270 return false;
271 }
272 output +=
273 static_cast<char>((((base64code2 << 6) & 0xc0) | base64code3));
274 }
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100275 }
276
Ed Tanous1abe55e2018-09-05 08:30:59 -0700277 return true;
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100278}
279
Ed Tanous26ccae32023-02-16 10:28:44 -0800280inline bool constantTimeStringCompare(std::string_view a, std::string_view b)
Ed Tanous51dae672018-09-05 16:07:32 -0700281{
282 // Important note, this function is ONLY constant time if the two input
283 // sizes are the same
284 if (a.size() != b.size())
285 {
286 return false;
287 }
288 return CRYPTO_memcmp(a.data(), b.data(), a.size()) == 0;
289}
290
291struct ConstantTimeCompare
292{
Ed Tanous26ccae32023-02-16 10:28:44 -0800293 bool operator()(std::string_view a, std::string_view b) const
Ed Tanous51dae672018-09-05 16:07:32 -0700294 {
295 return constantTimeStringCompare(a, b);
296 }
297};
298
Ed Tanouseae855c2021-10-26 11:26:02 -0700299namespace details
300{
301inline boost::urls::url
Willy Tuc6bcedc2022-09-27 05:36:59 +0000302 appendUrlPieces(boost::urls::url& url,
303 const std::initializer_list<std::string_view> args)
Ed Tanouseae855c2021-10-26 11:26:02 -0700304{
Ed Tanous26ccae32023-02-16 10:28:44 -0800305 for (std::string_view arg : args)
Ed Tanouseae855c2021-10-26 11:26:02 -0700306 {
307 url.segments().push_back(arg);
308 }
309 return url;
310}
Willy Tuc6bcedc2022-09-27 05:36:59 +0000311
Ed Tanouseae855c2021-10-26 11:26:02 -0700312} // namespace details
313
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700314class OrMorePaths
315{};
316
Ed Tanouseae855c2021-10-26 11:26:02 -0700317template <typename... AV>
Willy Tuc6bcedc2022-09-27 05:36:59 +0000318inline void appendUrlPieces(boost::urls::url& url, const AV... args)
319{
320 details::appendUrlPieces(url, {args...});
321}
322
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100323namespace details
324{
325
326// std::reference_wrapper<std::string> - extracts segment to variable
327// std::string_view - checks if segment is equal to variable
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700328using UrlSegment = std::variant<std::reference_wrapper<std::string>,
329 std::string_view, OrMorePaths>;
330
331enum class UrlParseResult
332{
333 Continue,
334 Fail,
335 Done,
336};
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100337
338class UrlSegmentMatcherVisitor
339{
340 public:
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700341 UrlParseResult operator()(std::string& output)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100342 {
Ed Tanous079360a2022-06-29 10:05:19 -0700343 output = segment;
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700344 return UrlParseResult::Continue;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100345 }
346
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700347 UrlParseResult operator()(std::string_view expected)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100348 {
Ed Tanous079360a2022-06-29 10:05:19 -0700349 if (segment == expected)
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700350 {
351 return UrlParseResult::Continue;
352 }
353 return UrlParseResult::Fail;
354 }
355
356 UrlParseResult operator()(OrMorePaths /*unused*/)
357 {
358 return UrlParseResult::Done;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100359 }
360
Ed Tanous079360a2022-06-29 10:05:19 -0700361 explicit UrlSegmentMatcherVisitor(std::string_view segmentIn) :
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100362 segment(segmentIn)
363 {}
364
365 private:
Ed Tanous079360a2022-06-29 10:05:19 -0700366 std::string_view segment;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100367};
368
Ed Tanousd9f466b2023-03-06 15:04:25 -0800369inline bool readUrlSegments(boost::urls::url_view url,
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100370 std::initializer_list<UrlSegment>&& segments)
371{
Ed Tanousd9f466b2023-03-06 15:04:25 -0800372 boost::urls::segments_view urlSegments = url.segments();
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100373
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700374 if (!urlSegments.is_absolute())
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100375 {
376 return false;
377 }
378
379 boost::urls::segments_view::iterator it = urlSegments.begin();
380 boost::urls::segments_view::iterator end = urlSegments.end();
381
382 for (const auto& segment : segments)
383 {
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700384 if (it == end)
385 {
386 // If the request ends with an "any" path, this was successful
387 return std::holds_alternative<OrMorePaths>(segment);
388 }
389 UrlParseResult res = std::visit(UrlSegmentMatcherVisitor(*it), segment);
390 if (res == UrlParseResult::Done)
391 {
392 return true;
393 }
394 if (res == UrlParseResult::Fail)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100395 {
396 return false;
397 }
398 it++;
399 }
Carson Labrado4c30e222022-06-24 22:16:00 +0000400
401 // There will be an empty segment at the end if the URI ends with a "/"
402 // e.g. /redfish/v1/Chassis/
403 if ((it != end) && urlSegments.back().empty())
404 {
405 it++;
406 }
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700407 return it == end;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100408}
409
410} // namespace details
411
412template <typename... Args>
Ed Tanousd9f466b2023-03-06 15:04:25 -0800413inline bool readUrlSegments(boost::urls::url_view url, Args&&... args)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100414{
Ed Tanous39662a32023-02-06 15:09:46 -0800415 return details::readUrlSegments(url, {std::forward<Args>(args)...});
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100416}
417
Ed Tanousd9f466b2023-03-06 15:04:25 -0800418inline boost::urls::url replaceUrlSegment(boost::urls::url_view urlView,
Carson Labrado1c0bb5c2022-05-18 00:12:52 +0000419 const uint replaceLoc,
Ed Tanous26ccae32023-02-16 10:28:44 -0800420 std::string_view newSegment)
Carson Labrado1c0bb5c2022-05-18 00:12:52 +0000421{
Ed Tanousd9f466b2023-03-06 15:04:25 -0800422 boost::urls::segments_view urlSegments = urlView.segments();
Carson Labrado1c0bb5c2022-05-18 00:12:52 +0000423 boost::urls::url url("/");
424
425 if (!urlSegments.is_absolute())
426 {
427 return url;
428 }
429
430 boost::urls::segments_view::iterator it = urlSegments.begin();
431 boost::urls::segments_view::iterator end = urlSegments.end();
432
433 for (uint idx = 0; it != end; it++, idx++)
434 {
435 if (idx == replaceLoc)
436 {
437 url.segments().push_back(newSegment);
438 }
439 else
440 {
441 url.segments().push_back(*it);
442 }
443 }
444
445 return url;
446}
447
Ed Tanousa716aa72023-08-01 11:35:53 -0700448inline void setProtocolDefaults(boost::urls::url& url,
449 std::string_view protocol)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800450{
Ed Tanousa716aa72023-08-01 11:35:53 -0700451 if (url.has_scheme())
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800452 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700453 return;
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800454 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700455 if (protocol == "Redfish" || protocol.empty())
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800456 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700457 if (url.port_number() == 443)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800458 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700459 url.set_scheme("https");
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800460 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700461 if (url.port_number() == 80)
462 {
463 if (bmcwebInsecureEnableHttpPushStyleEventing)
464 {
465 url.set_scheme("http");
466 }
467 }
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800468 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700469 else if (protocol == "SNMPv2c")
Chicago Duan3d307082020-11-26 14:12:12 +0800470 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700471 url.set_scheme("snmp");
Chicago Duan3d307082020-11-26 14:12:12 +0800472 }
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800473}
474
Ed Tanousa716aa72023-08-01 11:35:53 -0700475inline void setPortDefaults(boost::urls::url& url)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800476{
477 uint16_t port = url.port_number();
478 if (port != 0)
479 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700480 return;
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800481 }
482
483 // If the user hasn't explicitly stated a port, pick one explicitly for them
484 // based on the protocol defaults
485 if (url.scheme() == "http")
486 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700487 url.set_port_number(80);
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800488 }
489 if (url.scheme() == "https")
490 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700491 url.set_port_number(443);
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800492 }
Chicago Duan3d307082020-11-26 14:12:12 +0800493 if (url.scheme() == "snmp")
494 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700495 url.set_port_number(162);
Chicago Duan3d307082020-11-26 14:12:12 +0800496 }
Ed Tanous11baefe2022-02-09 12:14:12 -0800497}
498
Ed Tanous1abe55e2018-09-05 08:30:59 -0700499} // namespace utility
500} // namespace crow
Ed Tanous71f2db72022-05-25 12:28:09 -0700501
502namespace nlohmann
503{
504template <>
505struct adl_serializer<boost::urls::url>
506{
507 // nlohmann requires a specific casing to look these up in adl
508 // NOLINTNEXTLINE(readability-identifier-naming)
509 static void to_json(json& j, const boost::urls::url& url)
510 {
Ed Tanous079360a2022-06-29 10:05:19 -0700511 j = url.buffer();
Ed Tanous71f2db72022-05-25 12:28:09 -0700512 }
513};
514
515template <>
516struct adl_serializer<boost::urls::url_view>
517{
518 // NOLINTNEXTLINE(readability-identifier-naming)
Ed Tanousd9f466b2023-03-06 15:04:25 -0800519 static void to_json(json& j, boost::urls::url_view url)
Ed Tanous71f2db72022-05-25 12:28:09 -0700520 {
Ed Tanous079360a2022-06-29 10:05:19 -0700521 j = url.buffer();
Ed Tanous71f2db72022-05-25 12:28:09 -0700522 }
523};
524} // namespace nlohmann