blob: da174e538f27be1129532f761ba21d73a31e66a7 [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 Tanous6dbe9be2024-04-14 10:24:20 -07005extern "C"
6{
Ed Tanous51dae672018-09-05 16:07:32 -07007#include <openssl/crypto.h>
Ed Tanous6dbe9be2024-04-14 10:24:20 -07008}
Ed Tanous51dae672018-09-05 16:07:32 -07009
Ed Tanousc867a832022-03-10 14:17:00 -080010#include <boost/callable_traits.hpp>
Ed Tanous079360a2022-06-29 10:05:19 -070011#include <boost/url/parse.hpp>
Ed Tanouseae855c2021-10-26 11:26:02 -070012#include <boost/url/url.hpp>
Ed Tanous079360a2022-06-29 10:05:19 -070013#include <boost/url/url_view.hpp>
Ed Tanous4a7fbef2024-04-06 16:03:49 -070014#include <boost/url/url_view_base.hpp>
Ed Tanous71f2db72022-05-25 12:28:09 -070015#include <nlohmann/json.hpp>
Nan Zhou1d8782e2021-11-29 22:23:18 -080016
Ed Tanous9ea15c32022-01-04 14:18:22 -080017#include <array>
Ed Tanous74849be2021-02-05 09:47:47 -080018#include <chrono>
Ed Tanousc715ec22022-03-10 15:38:01 -080019#include <cstddef>
Ed Tanous7045c8d2017-04-03 10:04:37 -070020#include <cstdint>
Ed Tanous9ea15c32022-01-04 14:18:22 -080021#include <ctime>
Ed Tanous7045c8d2017-04-03 10:04:37 -070022#include <functional>
Ed Tanous9896eae2022-07-23 15:07:33 -070023#include <iomanip>
Ed Tanous9ea15c32022-01-04 14:18:22 -080024#include <limits>
Ed Tanous7045c8d2017-04-03 10:04:37 -070025#include <stdexcept>
26#include <string>
Ed Tanous9ea15c32022-01-04 14:18:22 -080027#include <string_view>
Ed Tanous7045c8d2017-04-03 10:04:37 -070028#include <tuple>
Ed Tanous9ea15c32022-01-04 14:18:22 -080029#include <type_traits>
30#include <utility>
Szymon Dompkeca1600c2022-03-03 14:42:52 +010031#include <variant>
Ed Tanous7045c8d2017-04-03 10:04:37 -070032
Ed Tanous1abe55e2018-09-05 08:30:59 -070033namespace crow
34{
Ed Tanous47488a92023-06-26 18:19:33 -070035namespace utility
Ed Tanous1abe55e2018-09-05 08:30:59 -070036{
Ed Tanous7045c8d2017-04-03 10:04:37 -070037
Ed Tanous9de65b32024-03-27 13:34:40 -070038constexpr uint64_t getParameterTag(std::string_view url)
Ed Tanous1abe55e2018-09-05 08:30:59 -070039{
Ed Tanous1c30e502022-03-08 18:02:24 -080040 uint64_t tagValue = 0;
41 size_t urlSegmentIndex = std::string_view::npos;
Ed Tanousb00dcc22021-02-23 12:52:50 -080042
Ed Tanous1c30e502022-03-08 18:02:24 -080043 for (size_t urlIndex = 0; urlIndex < url.size(); urlIndex++)
44 {
45 char character = url[urlIndex];
46 if (character == '<')
47 {
48 if (urlSegmentIndex != std::string_view::npos)
49 {
50 return 0;
51 }
52 urlSegmentIndex = urlIndex;
53 }
54 if (character == '>')
55 {
56 if (urlSegmentIndex == std::string_view::npos)
57 {
58 return 0;
59 }
Patrick Williams89492a12023-05-10 07:51:34 -050060 std::string_view tag = url.substr(urlSegmentIndex,
61 urlIndex + 1 - urlSegmentIndex);
Ed Tanous1c30e502022-03-08 18:02:24 -080062
Ed Tanous1c30e502022-03-08 18:02:24 -080063 if (tag == "<str>" || tag == "<string>")
64 {
Ed Tanousd9e89df2024-03-27 14:08:59 -070065 tagValue++;
Ed Tanous1c30e502022-03-08 18:02:24 -080066 }
67 if (tag == "<path>")
68 {
Ed Tanousd9e89df2024-03-27 14:08:59 -070069 tagValue++;
Ed Tanous1c30e502022-03-08 18:02:24 -080070 }
Ed Tanous1c30e502022-03-08 18:02:24 -080071 urlSegmentIndex = std::string_view::npos;
72 }
73 }
74 if (urlSegmentIndex != std::string_view::npos)
Ed Tanous988403c2020-08-24 11:29:49 -070075 {
76 return 0;
77 }
Ed Tanous1c30e502022-03-08 18:02:24 -080078 return tagValue;
Ed Tanous7045c8d2017-04-03 10:04:37 -070079}
Ed Tanous7045c8d2017-04-03 10:04:37 -070080
Ed Tanousee192c02023-12-13 10:49:58 -080081class Base64Encoder
Adriana Kobylakd830ff52021-01-27 14:15:27 -060082{
Ed Tanousee192c02023-12-13 10:49:58 -080083 char overflow1 = '\0';
84 char overflow2 = '\0';
85 uint8_t overflowCount = 0;
86
87 constexpr static std::array<char, 64> key = {
Adriana Kobylakd830ff52021-01-27 14:15:27 -060088 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
89 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
90 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
91 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
92 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
93
Ed Tanousee192c02023-12-13 10:49:58 -080094 // Takes 3 ascii chars, and encodes them as 4 base64 chars
95 static void encodeTriple(char first, char second, char third,
96 std::string& output)
Adriana Kobylakd830ff52021-01-27 14:15:27 -060097 {
Ed Tanous543f4402022-01-06 13:12:53 -080098 size_t keyIndex = 0;
Adriana Kobylakd830ff52021-01-27 14:15:27 -060099
Ed Tanousee192c02023-12-13 10:49:58 -0800100 keyIndex = static_cast<size_t>(first & 0xFC) >> 2;
101 output += key[keyIndex];
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600102
Ed Tanousee192c02023-12-13 10:49:58 -0800103 keyIndex = static_cast<size_t>(first & 0x03) << 4;
104 keyIndex += static_cast<size_t>(second & 0xF0) >> 4;
105 output += key[keyIndex];
106
107 keyIndex = static_cast<size_t>(second & 0x0F) << 2;
108 keyIndex += static_cast<size_t>(third & 0xC0) >> 6;
109 output += key[keyIndex];
110
111 keyIndex = static_cast<size_t>(third & 0x3F);
112 output += key[keyIndex];
113 }
114
115 public:
116 // Accepts a partial string to encode, and writes the encoded characters to
117 // the output stream. requires subsequently calling finalize to complete
118 // stream.
119 void encode(std::string_view data, std::string& output)
120 {
121 // Encode the last round of overflow chars first
122 if (overflowCount == 2)
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600123 {
Ed Tanousee192c02023-12-13 10:49:58 -0800124 if (!data.empty())
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600125 {
Ed Tanousee192c02023-12-13 10:49:58 -0800126 encodeTriple(overflow1, overflow2, data[0], output);
127 overflowCount = 0;
128 data.remove_prefix(1);
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600129 }
Ed Tanousee192c02023-12-13 10:49:58 -0800130 }
131 else if (overflowCount == 1)
132 {
133 if (data.size() >= 2)
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600134 {
Ed Tanousee192c02023-12-13 10:49:58 -0800135 encodeTriple(overflow1, data[0], data[1], output);
136 overflowCount = 0;
137 data.remove_prefix(2);
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600138 }
139 }
Ed Tanousee192c02023-12-13 10:49:58 -0800140
141 while (data.size() >= 3)
142 {
143 encodeTriple(data[0], data[1], data[2], output);
144 data.remove_prefix(3);
145 }
146
147 if (!data.empty() && overflowCount == 0)
148 {
149 overflow1 = data[0];
150 overflowCount++;
151 data.remove_prefix(1);
152 }
153
154 if (!data.empty() && overflowCount == 1)
155 {
156 overflow2 = data[0];
157 overflowCount++;
158 data.remove_prefix(1);
159 }
160 }
161
162 // Completes a base64 output, by writing any MOD(3) characters to the
163 // output, as well as any required trailing =
164 void finalize(std::string& output)
165 {
166 if (overflowCount == 0)
167 {
168 return;
169 }
170 size_t keyIndex = static_cast<size_t>(overflow1 & 0xFC) >> 2;
171 output += key[keyIndex];
172
173 keyIndex = static_cast<size_t>(overflow1 & 0x03) << 4;
174 if (overflowCount == 2)
175 {
176 keyIndex += static_cast<size_t>(overflow2 & 0xF0) >> 4;
177 output += key[keyIndex];
178 keyIndex = static_cast<size_t>(overflow2 & 0x0F) << 2;
179 output += key[keyIndex];
180 }
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600181 else
182 {
Ed Tanousee192c02023-12-13 10:49:58 -0800183 output += key[keyIndex];
184 output += '=';
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600185 }
Ed Tanousee192c02023-12-13 10:49:58 -0800186 output += '=';
187 overflowCount = 0;
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600188 }
189
Ed Tanousee192c02023-12-13 10:49:58 -0800190 // Returns the required output buffer in characters for an input of size
191 // inputSize
192 static size_t constexpr encodedSize(size_t inputSize)
193 {
194 // Base64 encodes 3 character blocks as 4 character blocks
195 // With a possibility of 2 trailing = characters
196 return (inputSize + 2) / 3 * 4;
197 }
198};
199
200inline std::string base64encode(std::string_view data)
201{
202 // Encodes a 3 character stream into a 4 character stream
203 std::string out;
204 Base64Encoder base64;
205 out.reserve(Base64Encoder::encodedSize(data.size()));
206 base64.encode(data, out);
207 base64.finalize(out);
208 return out;
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600209}
210
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100211// TODO this is temporary and should be deleted once base64 is refactored out of
212// crow
Ed Tanous26ccae32023-02-16 10:28:44 -0800213inline bool base64Decode(std::string_view input, std::string& output)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700214{
Ed Tanous271584a2019-07-09 16:24:22 -0700215 static const char nop = static_cast<char>(-1);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700216 // See note on encoding_data[] in above function
Jonathan Doman5beaf842020-08-14 11:23:33 -0700217 static const std::array<char, 256> decodingData = {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700218 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
219 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
220 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
221 nop, 62, nop, nop, nop, 63, 52, 53, 54, 55, 56, 57, 58, 59,
222 60, 61, nop, nop, nop, nop, nop, nop, nop, 0, 1, 2, 3, 4,
223 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
224 19, 20, 21, 22, 23, 24, 25, nop, nop, nop, nop, nop, nop, 26,
225 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
226 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, nop, nop, nop,
227 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
228 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
229 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
230 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
231 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
232 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
233 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
234 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
235 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
236 nop, nop, nop, nop};
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100237
Ed Tanous1abe55e2018-09-05 08:30:59 -0700238 size_t inputLength = input.size();
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100239
Ed Tanous1abe55e2018-09-05 08:30:59 -0700240 // allocate space for output string
241 output.clear();
242 output.reserve(((inputLength + 2) / 3) * 4);
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100243
Jonathan Doman5beaf842020-08-14 11:23:33 -0700244 auto getCodeValue = [](char c) {
245 auto code = static_cast<unsigned char>(c);
246 // Ensure we cannot index outside the bounds of the decoding array
247 static_assert(std::numeric_limits<decltype(code)>::max() <
248 decodingData.size());
249 return decodingData[code];
250 };
251
Ed Tanous1abe55e2018-09-05 08:30:59 -0700252 // for each 4-bytes sequence from the input, extract 4 6-bits sequences by
Gunnar Millscaa3ce32020-07-08 14:46:53 -0500253 // dropping first two bits
Ed Tanous1abe55e2018-09-05 08:30:59 -0700254 // and regenerate into 3 8-bits sequences
James Feist5a806642020-07-31 16:40:33 +0000255
Ed Tanous1abe55e2018-09-05 08:30:59 -0700256 for (size_t i = 0; i < inputLength; i++)
257 {
Ed Tanous543f4402022-01-06 13:12:53 -0800258 char base64code0 = 0;
259 char base64code1 = 0;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700260 char base64code2 = 0; // initialized to 0 to suppress warnings
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100261
Jonathan Doman5beaf842020-08-14 11:23:33 -0700262 base64code0 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700263 if (base64code0 == nop)
264 { // non base64 character
265 return false;
266 }
267 if (!(++i < inputLength))
268 { // we need at least two input bytes for first
269 // byte output
270 return false;
271 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700272 base64code1 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700273 if (base64code1 == nop)
274 { // non base64 character
275 return false;
276 }
277 output +=
278 static_cast<char>((base64code0 << 2) | ((base64code1 >> 4) & 0x3));
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100279
Ed Tanous1abe55e2018-09-05 08:30:59 -0700280 if (++i < inputLength)
281 {
282 char c = input[i];
283 if (c == '=')
284 { // padding , end of input
285 return (base64code1 & 0x0f) == 0;
286 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700287 base64code2 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700288 if (base64code2 == nop)
289 { // non base64 character
290 return false;
291 }
292 output += static_cast<char>(((base64code1 << 4) & 0xf0) |
293 ((base64code2 >> 2) & 0x0f));
294 }
295
296 if (++i < inputLength)
297 {
298 char c = input[i];
299 if (c == '=')
300 { // padding , end of input
301 return (base64code2 & 0x03) == 0;
302 }
Ed Tanousf8fe53e2022-06-30 15:55:45 -0700303 char base64code3 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700304 if (base64code3 == nop)
305 { // non base64 character
306 return false;
307 }
308 output +=
309 static_cast<char>((((base64code2 << 6) & 0xc0) | base64code3));
310 }
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100311 }
312
Ed Tanous1abe55e2018-09-05 08:30:59 -0700313 return true;
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100314}
315
Ed Tanous26ccae32023-02-16 10:28:44 -0800316inline bool constantTimeStringCompare(std::string_view a, std::string_view b)
Ed Tanous51dae672018-09-05 16:07:32 -0700317{
318 // Important note, this function is ONLY constant time if the two input
319 // sizes are the same
320 if (a.size() != b.size())
321 {
322 return false;
323 }
324 return CRYPTO_memcmp(a.data(), b.data(), a.size()) == 0;
325}
326
327struct ConstantTimeCompare
328{
Ed Tanous26ccae32023-02-16 10:28:44 -0800329 bool operator()(std::string_view a, std::string_view b) const
Ed Tanous51dae672018-09-05 16:07:32 -0700330 {
331 return constantTimeStringCompare(a, b);
332 }
333};
334
Ed Tanouseae855c2021-10-26 11:26:02 -0700335namespace details
336{
337inline boost::urls::url
Willy Tuc6bcedc2022-09-27 05:36:59 +0000338 appendUrlPieces(boost::urls::url& url,
339 const std::initializer_list<std::string_view> args)
Ed Tanouseae855c2021-10-26 11:26:02 -0700340{
Ed Tanous26ccae32023-02-16 10:28:44 -0800341 for (std::string_view arg : args)
Ed Tanouseae855c2021-10-26 11:26:02 -0700342 {
343 url.segments().push_back(arg);
344 }
345 return url;
346}
Willy Tuc6bcedc2022-09-27 05:36:59 +0000347
Ed Tanouseae855c2021-10-26 11:26:02 -0700348} // namespace details
349
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700350class OrMorePaths
351{};
352
Ed Tanouseae855c2021-10-26 11:26:02 -0700353template <typename... AV>
Willy Tuc6bcedc2022-09-27 05:36:59 +0000354inline void appendUrlPieces(boost::urls::url& url, const AV... args)
355{
356 details::appendUrlPieces(url, {args...});
357}
358
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100359namespace details
360{
361
362// std::reference_wrapper<std::string> - extracts segment to variable
363// std::string_view - checks if segment is equal to variable
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700364using UrlSegment = std::variant<std::reference_wrapper<std::string>,
365 std::string_view, OrMorePaths>;
366
367enum class UrlParseResult
368{
369 Continue,
370 Fail,
371 Done,
372};
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100373
374class UrlSegmentMatcherVisitor
375{
376 public:
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700377 UrlParseResult operator()(std::string& output)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100378 {
Ed Tanous079360a2022-06-29 10:05:19 -0700379 output = segment;
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700380 return UrlParseResult::Continue;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100381 }
382
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700383 UrlParseResult operator()(std::string_view expected)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100384 {
Ed Tanous079360a2022-06-29 10:05:19 -0700385 if (segment == expected)
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700386 {
387 return UrlParseResult::Continue;
388 }
389 return UrlParseResult::Fail;
390 }
391
392 UrlParseResult operator()(OrMorePaths /*unused*/)
393 {
394 return UrlParseResult::Done;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100395 }
396
Ed Tanous079360a2022-06-29 10:05:19 -0700397 explicit UrlSegmentMatcherVisitor(std::string_view segmentIn) :
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100398 segment(segmentIn)
399 {}
400
401 private:
Ed Tanous079360a2022-06-29 10:05:19 -0700402 std::string_view segment;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100403};
404
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700405inline bool readUrlSegments(const boost::urls::url_view_base& url,
Ed Tanous5be2b142024-03-27 15:27:04 -0700406 std::initializer_list<UrlSegment> segments)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100407{
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700408 const boost::urls::segments_view& urlSegments = url.segments();
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100409
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700410 if (!urlSegments.is_absolute())
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100411 {
412 return false;
413 }
414
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700415 boost::urls::segments_view::const_iterator it = urlSegments.begin();
416 boost::urls::segments_view::const_iterator end = urlSegments.end();
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100417
418 for (const auto& segment : segments)
419 {
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700420 if (it == end)
421 {
422 // If the request ends with an "any" path, this was successful
423 return std::holds_alternative<OrMorePaths>(segment);
424 }
425 UrlParseResult res = std::visit(UrlSegmentMatcherVisitor(*it), segment);
426 if (res == UrlParseResult::Done)
427 {
428 return true;
429 }
430 if (res == UrlParseResult::Fail)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100431 {
432 return false;
433 }
434 it++;
435 }
Carson Labrado4c30e222022-06-24 22:16:00 +0000436
437 // There will be an empty segment at the end if the URI ends with a "/"
438 // e.g. /redfish/v1/Chassis/
439 if ((it != end) && urlSegments.back().empty())
440 {
441 it++;
442 }
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700443 return it == end;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100444}
445
446} // namespace details
447
448template <typename... Args>
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700449inline bool readUrlSegments(const boost::urls::url_view_base& url,
450 Args&&... args)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100451{
Ed Tanous39662a32023-02-06 15:09:46 -0800452 return details::readUrlSegments(url, {std::forward<Args>(args)...});
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100453}
454
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700455inline boost::urls::url
456 replaceUrlSegment(const boost::urls::url_view_base& urlView,
457 const uint replaceLoc, std::string_view newSegment)
Carson Labrado1c0bb5c2022-05-18 00:12:52 +0000458{
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700459 const boost::urls::segments_view& urlSegments = urlView.segments();
Carson Labrado1c0bb5c2022-05-18 00:12:52 +0000460 boost::urls::url url("/");
461
462 if (!urlSegments.is_absolute())
463 {
464 return url;
465 }
466
467 boost::urls::segments_view::iterator it = urlSegments.begin();
468 boost::urls::segments_view::iterator end = urlSegments.end();
469
470 for (uint idx = 0; it != end; it++, idx++)
471 {
472 if (idx == replaceLoc)
473 {
474 url.segments().push_back(newSegment);
475 }
476 else
477 {
478 url.segments().push_back(*it);
479 }
480 }
481
482 return url;
483}
484
Ed Tanousa716aa72023-08-01 11:35:53 -0700485inline void setProtocolDefaults(boost::urls::url& url,
486 std::string_view protocol)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800487{
Ed Tanousa716aa72023-08-01 11:35:53 -0700488 if (url.has_scheme())
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800489 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700490 return;
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800491 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700492 if (protocol == "Redfish" || protocol.empty())
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800493 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700494 if (url.port_number() == 443)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800495 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700496 url.set_scheme("https");
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800497 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700498 if (url.port_number() == 80)
499 {
Ed Tanous25b54db2024-04-17 15:40:31 -0700500 if constexpr (BMCWEB_INSECURE_PUSH_STYLE_NOTIFICATION)
Ed Tanousa716aa72023-08-01 11:35:53 -0700501 {
502 url.set_scheme("http");
503 }
504 }
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800505 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700506 else if (protocol == "SNMPv2c")
Chicago Duan3d307082020-11-26 14:12:12 +0800507 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700508 url.set_scheme("snmp");
Chicago Duan3d307082020-11-26 14:12:12 +0800509 }
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800510}
511
Ed Tanousa716aa72023-08-01 11:35:53 -0700512inline void setPortDefaults(boost::urls::url& url)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800513{
514 uint16_t port = url.port_number();
515 if (port != 0)
516 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700517 return;
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800518 }
519
520 // If the user hasn't explicitly stated a port, pick one explicitly for them
521 // based on the protocol defaults
522 if (url.scheme() == "http")
523 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700524 url.set_port_number(80);
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800525 }
526 if (url.scheme() == "https")
527 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700528 url.set_port_number(443);
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800529 }
Chicago Duan3d307082020-11-26 14:12:12 +0800530 if (url.scheme() == "snmp")
531 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700532 url.set_port_number(162);
Chicago Duan3d307082020-11-26 14:12:12 +0800533 }
Ed Tanous11baefe2022-02-09 12:14:12 -0800534}
535
Ed Tanous1abe55e2018-09-05 08:30:59 -0700536} // namespace utility
537} // namespace crow
Ed Tanous71f2db72022-05-25 12:28:09 -0700538
539namespace nlohmann
540{
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700541template <std::derived_from<boost::urls::url_view_base> URL>
542struct adl_serializer<URL>
Ed Tanous71f2db72022-05-25 12:28:09 -0700543{
544 // NOLINTNEXTLINE(readability-identifier-naming)
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700545 static void to_json(json& j, const URL& url)
Ed Tanous71f2db72022-05-25 12:28:09 -0700546 {
Ed Tanous079360a2022-06-29 10:05:19 -0700547 j = url.buffer();
Ed Tanous71f2db72022-05-25 12:28:09 -0700548 }
549};
550} // namespace nlohmann