blob: 5be9ac50c444c8c65343c8a80c8d7549164fbb31 [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
Ed Tanous7045c8d2017-04-03 10:04:37 -07003#pragma once
Ed Tanous1abe55e2018-09-05 08:30:59 -07004
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08005#include "bmcweb_config.h"
6
Ed Tanousd7857202025-01-28 15:32:26 -08007#include <sys/types.h>
8
9#include <boost/url/segments_view.hpp>
Ed Tanouseae855c2021-10-26 11:26:02 -070010#include <boost/url/url.hpp>
Ed Tanous4a7fbef2024-04-06 16:03:49 -070011#include <boost/url/url_view_base.hpp>
Myung Bae8873f322025-03-17 18:24:13 -050012#include <nlohmann/adl_serializer.hpp>
Ed Tanous71f2db72022-05-25 12:28:09 -070013#include <nlohmann/json.hpp>
Nan Zhou1d8782e2021-11-29 22:23:18 -080014
Ed Tanous9ea15c32022-01-04 14:18:22 -080015#include <array>
Ed Tanous80d2ef32025-02-04 09:29:02 -080016#include <bit>
Ed Tanousd7857202025-01-28 15:32:26 -080017#include <concepts>
Ed Tanousc715ec22022-03-10 15:38:01 -080018#include <cstddef>
Ed Tanous7045c8d2017-04-03 10:04:37 -070019#include <cstdint>
Ed Tanous9ea15c32022-01-04 14:18:22 -080020#include <ctime>
Ed Tanous7045c8d2017-04-03 10:04:37 -070021#include <functional>
Ed Tanousd7857202025-01-28 15:32:26 -080022#include <initializer_list>
Ed Tanous9ea15c32022-01-04 14:18:22 -080023#include <limits>
Ed Tanous7045c8d2017-04-03 10:04:37 -070024#include <string>
Ed Tanous9ea15c32022-01-04 14:18:22 -080025#include <string_view>
Ed Tanous9ea15c32022-01-04 14:18:22 -080026#include <type_traits>
27#include <utility>
Szymon Dompkeca1600c2022-03-03 14:42:52 +010028#include <variant>
Ed Tanous7045c8d2017-04-03 10:04:37 -070029
Ed Tanous1abe55e2018-09-05 08:30:59 -070030namespace crow
31{
Ed Tanous47488a92023-06-26 18:19:33 -070032namespace utility
Ed Tanous1abe55e2018-09-05 08:30:59 -070033{
Ed Tanous7045c8d2017-04-03 10:04:37 -070034
Ed Tanous9de65b32024-03-27 13:34:40 -070035constexpr uint64_t getParameterTag(std::string_view url)
Ed Tanous1abe55e2018-09-05 08:30:59 -070036{
Ed Tanous1c30e502022-03-08 18:02:24 -080037 uint64_t tagValue = 0;
38 size_t urlSegmentIndex = std::string_view::npos;
Ed Tanousb00dcc22021-02-23 12:52:50 -080039
Ed Tanous1c30e502022-03-08 18:02:24 -080040 for (size_t urlIndex = 0; urlIndex < url.size(); urlIndex++)
41 {
42 char character = url[urlIndex];
43 if (character == '<')
44 {
45 if (urlSegmentIndex != std::string_view::npos)
46 {
47 return 0;
48 }
49 urlSegmentIndex = urlIndex;
50 }
51 if (character == '>')
52 {
53 if (urlSegmentIndex == std::string_view::npos)
54 {
55 return 0;
56 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -040057 std::string_view tag =
58 url.substr(urlSegmentIndex, urlIndex + 1 - urlSegmentIndex);
Ed Tanous1c30e502022-03-08 18:02:24 -080059
Ed Tanous1c30e502022-03-08 18:02:24 -080060 if (tag == "<str>" || tag == "<string>")
61 {
Ed Tanousd9e89df2024-03-27 14:08:59 -070062 tagValue++;
Ed Tanous1c30e502022-03-08 18:02:24 -080063 }
64 if (tag == "<path>")
65 {
Ed Tanousd9e89df2024-03-27 14:08:59 -070066 tagValue++;
Ed Tanous1c30e502022-03-08 18:02:24 -080067 }
Ed Tanous1c30e502022-03-08 18:02:24 -080068 urlSegmentIndex = std::string_view::npos;
69 }
70 }
71 if (urlSegmentIndex != std::string_view::npos)
Ed Tanous988403c2020-08-24 11:29:49 -070072 {
73 return 0;
74 }
Ed Tanous1c30e502022-03-08 18:02:24 -080075 return tagValue;
Ed Tanous7045c8d2017-04-03 10:04:37 -070076}
Ed Tanous7045c8d2017-04-03 10:04:37 -070077
Ed Tanous80d2ef32025-02-04 09:29:02 -080078constexpr static std::array<char, 64> base64key = {
79 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
80 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
81 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
82 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
83 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
84
85static constexpr char nop = static_cast<char>(-1);
86constexpr std::array<char, 256> getDecodeTable(bool urlSafe)
87{
88 std::array<char, 256> decodeTable{};
89 decodeTable.fill(nop);
90
91 for (size_t index = 0; index < base64key.size(); index++)
92 {
93 char character = base64key[index];
94 decodeTable[std::bit_cast<uint8_t>(character)] =
95 static_cast<char>(index);
96 }
97
98 if (urlSafe)
99 {
100 // Urlsafe decode tables replace the last two characters with - and _
101 decodeTable['+'] = nop;
102 decodeTable['/'] = nop;
103 decodeTable['-'] = 62;
104 decodeTable['_'] = 63;
105 }
106
107 return decodeTable;
108}
109
Ed Tanousee192c02023-12-13 10:49:58 -0800110class Base64Encoder
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600111{
Ed Tanousee192c02023-12-13 10:49:58 -0800112 char overflow1 = '\0';
113 char overflow2 = '\0';
114 uint8_t overflowCount = 0;
115
Ed Tanousee192c02023-12-13 10:49:58 -0800116 // Takes 3 ascii chars, and encodes them as 4 base64 chars
117 static void encodeTriple(char first, char second, char third,
118 std::string& output)
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600119 {
Ed Tanous543f4402022-01-06 13:12:53 -0800120 size_t keyIndex = 0;
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600121
Ed Tanousee192c02023-12-13 10:49:58 -0800122 keyIndex = static_cast<size_t>(first & 0xFC) >> 2;
Ed Tanous80d2ef32025-02-04 09:29:02 -0800123 output += base64key[keyIndex];
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600124
Ed Tanousee192c02023-12-13 10:49:58 -0800125 keyIndex = static_cast<size_t>(first & 0x03) << 4;
126 keyIndex += static_cast<size_t>(second & 0xF0) >> 4;
Ed Tanous80d2ef32025-02-04 09:29:02 -0800127 output += base64key[keyIndex];
Ed Tanousee192c02023-12-13 10:49:58 -0800128
129 keyIndex = static_cast<size_t>(second & 0x0F) << 2;
130 keyIndex += static_cast<size_t>(third & 0xC0) >> 6;
Ed Tanous80d2ef32025-02-04 09:29:02 -0800131 output += base64key[keyIndex];
Ed Tanousee192c02023-12-13 10:49:58 -0800132
133 keyIndex = static_cast<size_t>(third & 0x3F);
Ed Tanous80d2ef32025-02-04 09:29:02 -0800134 output += base64key[keyIndex];
Ed Tanousee192c02023-12-13 10:49:58 -0800135 }
136
137 public:
138 // Accepts a partial string to encode, and writes the encoded characters to
139 // the output stream. requires subsequently calling finalize to complete
140 // stream.
141 void encode(std::string_view data, std::string& output)
142 {
143 // Encode the last round of overflow chars first
144 if (overflowCount == 2)
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600145 {
Ed Tanousee192c02023-12-13 10:49:58 -0800146 if (!data.empty())
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600147 {
Ed Tanousee192c02023-12-13 10:49:58 -0800148 encodeTriple(overflow1, overflow2, data[0], output);
149 overflowCount = 0;
150 data.remove_prefix(1);
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600151 }
Ed Tanousee192c02023-12-13 10:49:58 -0800152 }
153 else if (overflowCount == 1)
154 {
155 if (data.size() >= 2)
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600156 {
Ed Tanousee192c02023-12-13 10:49:58 -0800157 encodeTriple(overflow1, data[0], data[1], output);
158 overflowCount = 0;
159 data.remove_prefix(2);
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600160 }
161 }
Ed Tanousee192c02023-12-13 10:49:58 -0800162
163 while (data.size() >= 3)
164 {
165 encodeTriple(data[0], data[1], data[2], output);
166 data.remove_prefix(3);
167 }
168
169 if (!data.empty() && overflowCount == 0)
170 {
171 overflow1 = data[0];
172 overflowCount++;
173 data.remove_prefix(1);
174 }
175
176 if (!data.empty() && overflowCount == 1)
177 {
178 overflow2 = data[0];
179 overflowCount++;
180 data.remove_prefix(1);
181 }
182 }
183
184 // Completes a base64 output, by writing any MOD(3) characters to the
185 // output, as well as any required trailing =
186 void finalize(std::string& output)
187 {
188 if (overflowCount == 0)
189 {
190 return;
191 }
192 size_t keyIndex = static_cast<size_t>(overflow1 & 0xFC) >> 2;
Ed Tanous80d2ef32025-02-04 09:29:02 -0800193 output += base64key[keyIndex];
Ed Tanousee192c02023-12-13 10:49:58 -0800194
195 keyIndex = static_cast<size_t>(overflow1 & 0x03) << 4;
196 if (overflowCount == 2)
197 {
198 keyIndex += static_cast<size_t>(overflow2 & 0xF0) >> 4;
Ed Tanous80d2ef32025-02-04 09:29:02 -0800199 output += base64key[keyIndex];
Ed Tanousee192c02023-12-13 10:49:58 -0800200 keyIndex = static_cast<size_t>(overflow2 & 0x0F) << 2;
Ed Tanous80d2ef32025-02-04 09:29:02 -0800201 output += base64key[keyIndex];
Ed Tanousee192c02023-12-13 10:49:58 -0800202 }
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600203 else
204 {
Ed Tanous80d2ef32025-02-04 09:29:02 -0800205 output += base64key[keyIndex];
Ed Tanousee192c02023-12-13 10:49:58 -0800206 output += '=';
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600207 }
Ed Tanousee192c02023-12-13 10:49:58 -0800208 output += '=';
209 overflowCount = 0;
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600210 }
211
Ed Tanousee192c02023-12-13 10:49:58 -0800212 // Returns the required output buffer in characters for an input of size
213 // inputSize
214 static size_t constexpr encodedSize(size_t inputSize)
215 {
216 // Base64 encodes 3 character blocks as 4 character blocks
217 // With a possibility of 2 trailing = characters
218 return (inputSize + 2) / 3 * 4;
219 }
220};
221
222inline std::string base64encode(std::string_view data)
223{
224 // Encodes a 3 character stream into a 4 character stream
225 std::string out;
226 Base64Encoder base64;
227 out.reserve(Base64Encoder::encodedSize(data.size()));
228 base64.encode(data, out);
229 base64.finalize(out);
230 return out;
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600231}
232
Ed Tanous80d2ef32025-02-04 09:29:02 -0800233template <bool urlsafe = false>
Ed Tanous26ccae32023-02-16 10:28:44 -0800234inline bool base64Decode(std::string_view input, std::string& output)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700235{
Ed Tanous1abe55e2018-09-05 08:30:59 -0700236 size_t inputLength = input.size();
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100237
Ed Tanous1abe55e2018-09-05 08:30:59 -0700238 // allocate space for output string
239 output.clear();
240 output.reserve(((inputLength + 2) / 3) * 4);
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100241
Ed Tanous80d2ef32025-02-04 09:29:02 -0800242 static constexpr auto decodingData = getDecodeTable(urlsafe);
243
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
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400247 static_assert(
248 std::numeric_limits<decltype(code)>::max() < decodingData.size());
Jonathan Doman5beaf842020-08-14 11:23:33 -0700249 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)
Myung Bae41868c62024-10-09 16:36:49 -0700264 {
265 // non base64 character
Ed Tanous1abe55e2018-09-05 08:30:59 -0700266 return false;
267 }
268 if (!(++i < inputLength))
Myung Bae41868c62024-10-09 16:36:49 -0700269 {
270 // we need at least two input bytes for first byte output
Ed Tanous1abe55e2018-09-05 08:30:59 -0700271 return false;
272 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700273 base64code1 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700274 if (base64code1 == nop)
Myung Bae41868c62024-10-09 16:36:49 -0700275 {
276 // non base64 character
Ed Tanous1abe55e2018-09-05 08:30:59 -0700277 return false;
278 }
279 output +=
280 static_cast<char>((base64code0 << 2) | ((base64code1 >> 4) & 0x3));
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100281
Ed Tanous1abe55e2018-09-05 08:30:59 -0700282 if (++i < inputLength)
283 {
284 char c = input[i];
285 if (c == '=')
Myung Bae41868c62024-10-09 16:36:49 -0700286 {
287 // padding , end of input
Ed Tanous1abe55e2018-09-05 08:30:59 -0700288 return (base64code1 & 0x0f) == 0;
289 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700290 base64code2 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700291 if (base64code2 == nop)
Myung Bae41868c62024-10-09 16:36:49 -0700292 {
293 // non base64 character
Ed Tanous1abe55e2018-09-05 08:30:59 -0700294 return false;
295 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400296 output += static_cast<char>(
297 ((base64code1 << 4) & 0xf0) | ((base64code2 >> 2) & 0x0f));
Ed Tanous1abe55e2018-09-05 08:30:59 -0700298 }
299
300 if (++i < inputLength)
301 {
302 char c = input[i];
303 if (c == '=')
Myung Bae41868c62024-10-09 16:36:49 -0700304 {
305 // padding , end of input
Ed Tanous1abe55e2018-09-05 08:30:59 -0700306 return (base64code2 & 0x03) == 0;
307 }
Ed Tanousf8fe53e2022-06-30 15:55:45 -0700308 char base64code3 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700309 if (base64code3 == nop)
Myung Bae41868c62024-10-09 16:36:49 -0700310 {
311 // non base64 character
Ed Tanous1abe55e2018-09-05 08:30:59 -0700312 return false;
313 }
314 output +=
315 static_cast<char>((((base64code2 << 6) & 0xc0) | base64code3));
316 }
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100317 }
318
Ed Tanous1abe55e2018-09-05 08:30:59 -0700319 return true;
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100320}
321
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700322class OrMorePaths
323{};
324
Ed Tanouseae855c2021-10-26 11:26:02 -0700325template <typename... AV>
Ed Tanousdaadfb22024-12-20 09:25:54 -0800326inline void appendUrlPieces(boost::urls::url& url, AV&&... args)
Willy Tuc6bcedc2022-09-27 05:36:59 +0000327{
Ed Tanousdaadfb22024-12-20 09:25:54 -0800328 // Unclear the correct fix here.
329 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
330 for (const std::string_view arg : {args...})
331 {
332 url.segments().push_back(arg);
333 }
Willy Tuc6bcedc2022-09-27 05:36:59 +0000334}
335
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100336namespace details
337{
338
339// std::reference_wrapper<std::string> - extracts segment to variable
340// std::string_view - checks if segment is equal to variable
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700341using UrlSegment = std::variant<std::reference_wrapper<std::string>,
342 std::string_view, OrMorePaths>;
343
344enum class UrlParseResult
345{
346 Continue,
347 Fail,
348 Done,
349};
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100350
351class UrlSegmentMatcherVisitor
352{
353 public:
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700354 UrlParseResult operator()(std::string& output)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100355 {
Ed Tanous079360a2022-06-29 10:05:19 -0700356 output = segment;
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700357 return UrlParseResult::Continue;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100358 }
359
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700360 UrlParseResult operator()(std::string_view expected)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100361 {
Ed Tanous079360a2022-06-29 10:05:19 -0700362 if (segment == expected)
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700363 {
364 return UrlParseResult::Continue;
365 }
366 return UrlParseResult::Fail;
367 }
368
369 UrlParseResult operator()(OrMorePaths /*unused*/)
370 {
371 return UrlParseResult::Done;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100372 }
373
Ed Tanous079360a2022-06-29 10:05:19 -0700374 explicit UrlSegmentMatcherVisitor(std::string_view segmentIn) :
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100375 segment(segmentIn)
376 {}
377
378 private:
Ed Tanous079360a2022-06-29 10:05:19 -0700379 std::string_view segment;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100380};
381
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700382inline bool readUrlSegments(const boost::urls::url_view_base& url,
Ed Tanous5be2b142024-03-27 15:27:04 -0700383 std::initializer_list<UrlSegment> segments)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100384{
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700385 const boost::urls::segments_view& urlSegments = url.segments();
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100386
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700387 if (!urlSegments.is_absolute())
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100388 {
389 return false;
390 }
391
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700392 boost::urls::segments_view::const_iterator it = urlSegments.begin();
393 boost::urls::segments_view::const_iterator end = urlSegments.end();
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100394
395 for (const auto& segment : segments)
396 {
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700397 if (it == end)
398 {
399 // If the request ends with an "any" path, this was successful
400 return std::holds_alternative<OrMorePaths>(segment);
401 }
402 UrlParseResult res = std::visit(UrlSegmentMatcherVisitor(*it), segment);
403 if (res == UrlParseResult::Done)
404 {
405 return true;
406 }
407 if (res == UrlParseResult::Fail)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100408 {
409 return false;
410 }
411 it++;
412 }
Carson Labrado4c30e222022-06-24 22:16:00 +0000413
414 // There will be an empty segment at the end if the URI ends with a "/"
415 // e.g. /redfish/v1/Chassis/
416 if ((it != end) && urlSegments.back().empty())
417 {
418 it++;
419 }
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700420 return it == end;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100421}
422
423} // namespace details
424
425template <typename... Args>
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700426inline bool readUrlSegments(const boost::urls::url_view_base& url,
427 Args&&... args)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100428{
Ed Tanous39662a32023-02-06 15:09:46 -0800429 return details::readUrlSegments(url, {std::forward<Args>(args)...});
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100430}
431
Patrick Williams504af5a2025-02-03 14:29:03 -0500432inline boost::urls::url replaceUrlSegment(
433 const boost::urls::url_view_base& urlView, const uint replaceLoc,
434 std::string_view newSegment)
Carson Labrado1c0bb5c2022-05-18 00:12:52 +0000435{
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700436 const boost::urls::segments_view& urlSegments = urlView.segments();
Carson Labrado1c0bb5c2022-05-18 00:12:52 +0000437 boost::urls::url url("/");
438
439 if (!urlSegments.is_absolute())
440 {
441 return url;
442 }
443
444 boost::urls::segments_view::iterator it = urlSegments.begin();
445 boost::urls::segments_view::iterator end = urlSegments.end();
446
447 for (uint idx = 0; it != end; it++, idx++)
448 {
449 if (idx == replaceLoc)
450 {
451 url.segments().push_back(newSegment);
452 }
453 else
454 {
455 url.segments().push_back(*it);
456 }
457 }
458
459 return url;
460}
461
Ed Tanousa716aa72023-08-01 11:35:53 -0700462inline void setProtocolDefaults(boost::urls::url& url,
463 std::string_view protocol)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800464{
Ed Tanousa716aa72023-08-01 11:35:53 -0700465 if (url.has_scheme())
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800466 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700467 return;
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800468 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700469 if (protocol == "Redfish" || protocol.empty())
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800470 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700471 if (url.port_number() == 443)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800472 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700473 url.set_scheme("https");
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800474 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700475 if (url.port_number() == 80)
476 {
Ed Tanous25b54db2024-04-17 15:40:31 -0700477 if constexpr (BMCWEB_INSECURE_PUSH_STYLE_NOTIFICATION)
Ed Tanousa716aa72023-08-01 11:35:53 -0700478 {
479 url.set_scheme("http");
480 }
481 }
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800482 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700483 else if (protocol == "SNMPv2c")
Chicago Duan3d307082020-11-26 14:12:12 +0800484 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700485 url.set_scheme("snmp");
Chicago Duan3d307082020-11-26 14:12:12 +0800486 }
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800487}
488
Ed Tanousa716aa72023-08-01 11:35:53 -0700489inline void setPortDefaults(boost::urls::url& url)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800490{
491 uint16_t port = url.port_number();
492 if (port != 0)
493 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700494 return;
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800495 }
496
497 // If the user hasn't explicitly stated a port, pick one explicitly for them
498 // based on the protocol defaults
499 if (url.scheme() == "http")
500 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700501 url.set_port_number(80);
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800502 }
503 if (url.scheme() == "https")
504 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700505 url.set_port_number(443);
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800506 }
Chicago Duan3d307082020-11-26 14:12:12 +0800507 if (url.scheme() == "snmp")
508 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700509 url.set_port_number(162);
Chicago Duan3d307082020-11-26 14:12:12 +0800510 }
Ed Tanous11baefe2022-02-09 12:14:12 -0800511}
512
Ed Tanous1abe55e2018-09-05 08:30:59 -0700513} // namespace utility
514} // namespace crow
Ed Tanous71f2db72022-05-25 12:28:09 -0700515
516namespace nlohmann
517{
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700518template <std::derived_from<boost::urls::url_view_base> URL>
519struct adl_serializer<URL>
Ed Tanous71f2db72022-05-25 12:28:09 -0700520{
521 // NOLINTNEXTLINE(readability-identifier-naming)
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700522 static void to_json(json& j, const URL& url)
Ed Tanous71f2db72022-05-25 12:28:09 -0700523 {
Ed Tanous079360a2022-06-29 10:05:19 -0700524 j = url.buffer();
Ed Tanous71f2db72022-05-25 12:28:09 -0700525 }
526};
527} // namespace nlohmann