blob: a059723ad7a2c546efc0c78ebd4d722520db0d0d [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>
Ed Tanous71f2db72022-05-25 12:28:09 -070012#include <nlohmann/json.hpp>
Nan Zhou1d8782e2021-11-29 22:23:18 -080013
Ed Tanous9ea15c32022-01-04 14:18:22 -080014#include <array>
Ed Tanous80d2ef32025-02-04 09:29:02 -080015#include <bit>
Ed Tanousd7857202025-01-28 15:32:26 -080016#include <concepts>
Ed Tanousc715ec22022-03-10 15:38:01 -080017#include <cstddef>
Ed Tanous7045c8d2017-04-03 10:04:37 -070018#include <cstdint>
Ed Tanous9ea15c32022-01-04 14:18:22 -080019#include <ctime>
Ed Tanous7045c8d2017-04-03 10:04:37 -070020#include <functional>
Ed Tanousd7857202025-01-28 15:32:26 -080021#include <initializer_list>
Ed Tanous9ea15c32022-01-04 14:18:22 -080022#include <limits>
Ed Tanous7045c8d2017-04-03 10:04:37 -070023#include <string>
Ed Tanous9ea15c32022-01-04 14:18:22 -080024#include <string_view>
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 Tanous9de65b32024-03-27 13:34:40 -070034constexpr uint64_t getParameterTag(std::string_view url)
Ed Tanous1abe55e2018-09-05 08:30:59 -070035{
Ed Tanous1c30e502022-03-08 18:02:24 -080036 uint64_t tagValue = 0;
37 size_t urlSegmentIndex = std::string_view::npos;
Ed Tanousb00dcc22021-02-23 12:52:50 -080038
Ed Tanous1c30e502022-03-08 18:02:24 -080039 for (size_t urlIndex = 0; urlIndex < url.size(); urlIndex++)
40 {
41 char character = url[urlIndex];
42 if (character == '<')
43 {
44 if (urlSegmentIndex != std::string_view::npos)
45 {
46 return 0;
47 }
48 urlSegmentIndex = urlIndex;
49 }
50 if (character == '>')
51 {
52 if (urlSegmentIndex == std::string_view::npos)
53 {
54 return 0;
55 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -040056 std::string_view tag =
57 url.substr(urlSegmentIndex, urlIndex + 1 - urlSegmentIndex);
Ed Tanous1c30e502022-03-08 18:02:24 -080058
Ed Tanous1c30e502022-03-08 18:02:24 -080059 if (tag == "<str>" || tag == "<string>")
60 {
Ed Tanousd9e89df2024-03-27 14:08:59 -070061 tagValue++;
Ed Tanous1c30e502022-03-08 18:02:24 -080062 }
63 if (tag == "<path>")
64 {
Ed Tanousd9e89df2024-03-27 14:08:59 -070065 tagValue++;
Ed Tanous1c30e502022-03-08 18:02:24 -080066 }
Ed Tanous1c30e502022-03-08 18:02:24 -080067 urlSegmentIndex = std::string_view::npos;
68 }
69 }
70 if (urlSegmentIndex != std::string_view::npos)
Ed Tanous988403c2020-08-24 11:29:49 -070071 {
72 return 0;
73 }
Ed Tanous1c30e502022-03-08 18:02:24 -080074 return tagValue;
Ed Tanous7045c8d2017-04-03 10:04:37 -070075}
Ed Tanous7045c8d2017-04-03 10:04:37 -070076
Ed Tanous80d2ef32025-02-04 09:29:02 -080077constexpr static std::array<char, 64> base64key = {
78 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
79 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
80 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
81 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
82 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
83
84static constexpr char nop = static_cast<char>(-1);
85constexpr std::array<char, 256> getDecodeTable(bool urlSafe)
86{
87 std::array<char, 256> decodeTable{};
88 decodeTable.fill(nop);
89
90 for (size_t index = 0; index < base64key.size(); index++)
91 {
92 char character = base64key[index];
93 decodeTable[std::bit_cast<uint8_t>(character)] =
94 static_cast<char>(index);
95 }
96
97 if (urlSafe)
98 {
99 // Urlsafe decode tables replace the last two characters with - and _
100 decodeTable['+'] = nop;
101 decodeTable['/'] = nop;
102 decodeTable['-'] = 62;
103 decodeTable['_'] = 63;
104 }
105
106 return decodeTable;
107}
108
Ed Tanousee192c02023-12-13 10:49:58 -0800109class Base64Encoder
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600110{
Ed Tanousee192c02023-12-13 10:49:58 -0800111 char overflow1 = '\0';
112 char overflow2 = '\0';
113 uint8_t overflowCount = 0;
114
Ed Tanousee192c02023-12-13 10:49:58 -0800115 // Takes 3 ascii chars, and encodes them as 4 base64 chars
116 static void encodeTriple(char first, char second, char third,
117 std::string& output)
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600118 {
Ed Tanous543f4402022-01-06 13:12:53 -0800119 size_t keyIndex = 0;
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600120
Ed Tanousee192c02023-12-13 10:49:58 -0800121 keyIndex = static_cast<size_t>(first & 0xFC) >> 2;
Ed Tanous80d2ef32025-02-04 09:29:02 -0800122 output += base64key[keyIndex];
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600123
Ed Tanousee192c02023-12-13 10:49:58 -0800124 keyIndex = static_cast<size_t>(first & 0x03) << 4;
125 keyIndex += static_cast<size_t>(second & 0xF0) >> 4;
Ed Tanous80d2ef32025-02-04 09:29:02 -0800126 output += base64key[keyIndex];
Ed Tanousee192c02023-12-13 10:49:58 -0800127
128 keyIndex = static_cast<size_t>(second & 0x0F) << 2;
129 keyIndex += static_cast<size_t>(third & 0xC0) >> 6;
Ed Tanous80d2ef32025-02-04 09:29:02 -0800130 output += base64key[keyIndex];
Ed Tanousee192c02023-12-13 10:49:58 -0800131
132 keyIndex = static_cast<size_t>(third & 0x3F);
Ed Tanous80d2ef32025-02-04 09:29:02 -0800133 output += base64key[keyIndex];
Ed Tanousee192c02023-12-13 10:49:58 -0800134 }
135
136 public:
137 // Accepts a partial string to encode, and writes the encoded characters to
138 // the output stream. requires subsequently calling finalize to complete
139 // stream.
140 void encode(std::string_view data, std::string& output)
141 {
142 // Encode the last round of overflow chars first
143 if (overflowCount == 2)
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600144 {
Ed Tanousee192c02023-12-13 10:49:58 -0800145 if (!data.empty())
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600146 {
Ed Tanousee192c02023-12-13 10:49:58 -0800147 encodeTriple(overflow1, overflow2, data[0], output);
148 overflowCount = 0;
149 data.remove_prefix(1);
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600150 }
Ed Tanousee192c02023-12-13 10:49:58 -0800151 }
152 else if (overflowCount == 1)
153 {
154 if (data.size() >= 2)
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600155 {
Ed Tanousee192c02023-12-13 10:49:58 -0800156 encodeTriple(overflow1, data[0], data[1], output);
157 overflowCount = 0;
158 data.remove_prefix(2);
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600159 }
160 }
Ed Tanousee192c02023-12-13 10:49:58 -0800161
162 while (data.size() >= 3)
163 {
164 encodeTriple(data[0], data[1], data[2], output);
165 data.remove_prefix(3);
166 }
167
168 if (!data.empty() && overflowCount == 0)
169 {
170 overflow1 = data[0];
171 overflowCount++;
172 data.remove_prefix(1);
173 }
174
175 if (!data.empty() && overflowCount == 1)
176 {
177 overflow2 = data[0];
178 overflowCount++;
179 data.remove_prefix(1);
180 }
181 }
182
183 // Completes a base64 output, by writing any MOD(3) characters to the
184 // output, as well as any required trailing =
185 void finalize(std::string& output)
186 {
187 if (overflowCount == 0)
188 {
189 return;
190 }
191 size_t keyIndex = static_cast<size_t>(overflow1 & 0xFC) >> 2;
Ed Tanous80d2ef32025-02-04 09:29:02 -0800192 output += base64key[keyIndex];
Ed Tanousee192c02023-12-13 10:49:58 -0800193
194 keyIndex = static_cast<size_t>(overflow1 & 0x03) << 4;
195 if (overflowCount == 2)
196 {
197 keyIndex += static_cast<size_t>(overflow2 & 0xF0) >> 4;
Ed Tanous80d2ef32025-02-04 09:29:02 -0800198 output += base64key[keyIndex];
Ed Tanousee192c02023-12-13 10:49:58 -0800199 keyIndex = static_cast<size_t>(overflow2 & 0x0F) << 2;
Ed Tanous80d2ef32025-02-04 09:29:02 -0800200 output += base64key[keyIndex];
Ed Tanousee192c02023-12-13 10:49:58 -0800201 }
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600202 else
203 {
Ed Tanous80d2ef32025-02-04 09:29:02 -0800204 output += base64key[keyIndex];
Ed Tanousee192c02023-12-13 10:49:58 -0800205 output += '=';
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600206 }
Ed Tanousee192c02023-12-13 10:49:58 -0800207 output += '=';
208 overflowCount = 0;
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600209 }
210
Ed Tanousee192c02023-12-13 10:49:58 -0800211 // Returns the required output buffer in characters for an input of size
212 // inputSize
213 static size_t constexpr encodedSize(size_t inputSize)
214 {
215 // Base64 encodes 3 character blocks as 4 character blocks
216 // With a possibility of 2 trailing = characters
217 return (inputSize + 2) / 3 * 4;
218 }
219};
220
221inline std::string base64encode(std::string_view data)
222{
223 // Encodes a 3 character stream into a 4 character stream
224 std::string out;
225 Base64Encoder base64;
226 out.reserve(Base64Encoder::encodedSize(data.size()));
227 base64.encode(data, out);
228 base64.finalize(out);
229 return out;
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600230}
231
Ed Tanous80d2ef32025-02-04 09:29:02 -0800232template <bool urlsafe = false>
Ed Tanous26ccae32023-02-16 10:28:44 -0800233inline bool base64Decode(std::string_view input, std::string& output)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700234{
Ed Tanous1abe55e2018-09-05 08:30:59 -0700235 size_t inputLength = input.size();
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100236
Ed Tanous1abe55e2018-09-05 08:30:59 -0700237 // allocate space for output string
238 output.clear();
239 output.reserve(((inputLength + 2) / 3) * 4);
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100240
Ed Tanous80d2ef32025-02-04 09:29:02 -0800241 static constexpr auto decodingData = getDecodeTable(urlsafe);
242
Jonathan Doman5beaf842020-08-14 11:23:33 -0700243 auto getCodeValue = [](char c) {
244 auto code = static_cast<unsigned char>(c);
245 // Ensure we cannot index outside the bounds of the decoding array
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400246 static_assert(
247 std::numeric_limits<decltype(code)>::max() < decodingData.size());
Jonathan Doman5beaf842020-08-14 11:23:33 -0700248 return decodingData[code];
249 };
250
Ed Tanous1abe55e2018-09-05 08:30:59 -0700251 // for each 4-bytes sequence from the input, extract 4 6-bits sequences by
Gunnar Millscaa3ce32020-07-08 14:46:53 -0500252 // dropping first two bits
Ed Tanous1abe55e2018-09-05 08:30:59 -0700253 // and regenerate into 3 8-bits sequences
James Feist5a806642020-07-31 16:40:33 +0000254
Ed Tanous1abe55e2018-09-05 08:30:59 -0700255 for (size_t i = 0; i < inputLength; i++)
256 {
Ed Tanous543f4402022-01-06 13:12:53 -0800257 char base64code0 = 0;
258 char base64code1 = 0;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700259 char base64code2 = 0; // initialized to 0 to suppress warnings
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100260
Jonathan Doman5beaf842020-08-14 11:23:33 -0700261 base64code0 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700262 if (base64code0 == nop)
Myung Bae41868c62024-10-09 16:36:49 -0700263 {
264 // non base64 character
Ed Tanous1abe55e2018-09-05 08:30:59 -0700265 return false;
266 }
267 if (!(++i < inputLength))
Myung Bae41868c62024-10-09 16:36:49 -0700268 {
269 // we need at least two input bytes for first byte output
Ed Tanous1abe55e2018-09-05 08:30:59 -0700270 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)
Myung Bae41868c62024-10-09 16:36:49 -0700274 {
275 // non base64 character
Ed Tanous1abe55e2018-09-05 08:30:59 -0700276 return false;
277 }
278 output +=
279 static_cast<char>((base64code0 << 2) | ((base64code1 >> 4) & 0x3));
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100280
Ed Tanous1abe55e2018-09-05 08:30:59 -0700281 if (++i < inputLength)
282 {
283 char c = input[i];
284 if (c == '=')
Myung Bae41868c62024-10-09 16:36:49 -0700285 {
286 // padding , end of input
Ed Tanous1abe55e2018-09-05 08:30:59 -0700287 return (base64code1 & 0x0f) == 0;
288 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700289 base64code2 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700290 if (base64code2 == nop)
Myung Bae41868c62024-10-09 16:36:49 -0700291 {
292 // non base64 character
Ed Tanous1abe55e2018-09-05 08:30:59 -0700293 return false;
294 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400295 output += static_cast<char>(
296 ((base64code1 << 4) & 0xf0) | ((base64code2 >> 2) & 0x0f));
Ed Tanous1abe55e2018-09-05 08:30:59 -0700297 }
298
299 if (++i < inputLength)
300 {
301 char c = input[i];
302 if (c == '=')
Myung Bae41868c62024-10-09 16:36:49 -0700303 {
304 // padding , end of input
Ed Tanous1abe55e2018-09-05 08:30:59 -0700305 return (base64code2 & 0x03) == 0;
306 }
Ed Tanousf8fe53e2022-06-30 15:55:45 -0700307 char base64code3 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700308 if (base64code3 == nop)
Myung Bae41868c62024-10-09 16:36:49 -0700309 {
310 // non base64 character
Ed Tanous1abe55e2018-09-05 08:30:59 -0700311 return false;
312 }
313 output +=
314 static_cast<char>((((base64code2 << 6) & 0xc0) | base64code3));
315 }
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100316 }
317
Ed Tanous1abe55e2018-09-05 08:30:59 -0700318 return true;
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100319}
320
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700321class OrMorePaths
322{};
323
Ed Tanouseae855c2021-10-26 11:26:02 -0700324template <typename... AV>
Ed Tanousdaadfb22024-12-20 09:25:54 -0800325inline void appendUrlPieces(boost::urls::url& url, AV&&... args)
Willy Tuc6bcedc2022-09-27 05:36:59 +0000326{
Ed Tanousdaadfb22024-12-20 09:25:54 -0800327 // Unclear the correct fix here.
328 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
329 for (const std::string_view arg : {args...})
330 {
331 url.segments().push_back(arg);
332 }
Willy Tuc6bcedc2022-09-27 05:36:59 +0000333}
334
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100335namespace details
336{
337
338// std::reference_wrapper<std::string> - extracts segment to variable
339// std::string_view - checks if segment is equal to variable
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700340using UrlSegment = std::variant<std::reference_wrapper<std::string>,
341 std::string_view, OrMorePaths>;
342
343enum class UrlParseResult
344{
345 Continue,
346 Fail,
347 Done,
348};
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100349
350class UrlSegmentMatcherVisitor
351{
352 public:
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700353 UrlParseResult operator()(std::string& output)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100354 {
Ed Tanous079360a2022-06-29 10:05:19 -0700355 output = segment;
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700356 return UrlParseResult::Continue;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100357 }
358
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700359 UrlParseResult operator()(std::string_view expected)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100360 {
Ed Tanous079360a2022-06-29 10:05:19 -0700361 if (segment == expected)
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700362 {
363 return UrlParseResult::Continue;
364 }
365 return UrlParseResult::Fail;
366 }
367
368 UrlParseResult operator()(OrMorePaths /*unused*/)
369 {
370 return UrlParseResult::Done;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100371 }
372
Ed Tanous079360a2022-06-29 10:05:19 -0700373 explicit UrlSegmentMatcherVisitor(std::string_view segmentIn) :
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100374 segment(segmentIn)
375 {}
376
377 private:
Ed Tanous079360a2022-06-29 10:05:19 -0700378 std::string_view segment;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100379};
380
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700381inline bool readUrlSegments(const boost::urls::url_view_base& url,
Ed Tanous5be2b142024-03-27 15:27:04 -0700382 std::initializer_list<UrlSegment> segments)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100383{
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700384 const boost::urls::segments_view& urlSegments = url.segments();
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100385
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700386 if (!urlSegments.is_absolute())
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100387 {
388 return false;
389 }
390
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700391 boost::urls::segments_view::const_iterator it = urlSegments.begin();
392 boost::urls::segments_view::const_iterator end = urlSegments.end();
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100393
394 for (const auto& segment : segments)
395 {
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700396 if (it == end)
397 {
398 // If the request ends with an "any" path, this was successful
399 return std::holds_alternative<OrMorePaths>(segment);
400 }
401 UrlParseResult res = std::visit(UrlSegmentMatcherVisitor(*it), segment);
402 if (res == UrlParseResult::Done)
403 {
404 return true;
405 }
406 if (res == UrlParseResult::Fail)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100407 {
408 return false;
409 }
410 it++;
411 }
Carson Labrado4c30e222022-06-24 22:16:00 +0000412
413 // There will be an empty segment at the end if the URI ends with a "/"
414 // e.g. /redfish/v1/Chassis/
415 if ((it != end) && urlSegments.back().empty())
416 {
417 it++;
418 }
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700419 return it == end;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100420}
421
422} // namespace details
423
424template <typename... Args>
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700425inline bool readUrlSegments(const boost::urls::url_view_base& url,
426 Args&&... args)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100427{
Ed Tanous39662a32023-02-06 15:09:46 -0800428 return details::readUrlSegments(url, {std::forward<Args>(args)...});
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100429}
430
Patrick Williams504af5a2025-02-03 14:29:03 -0500431inline boost::urls::url replaceUrlSegment(
432 const boost::urls::url_view_base& urlView, const uint replaceLoc,
433 std::string_view newSegment)
Carson Labrado1c0bb5c2022-05-18 00:12:52 +0000434{
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700435 const boost::urls::segments_view& urlSegments = urlView.segments();
Carson Labrado1c0bb5c2022-05-18 00:12:52 +0000436 boost::urls::url url("/");
437
438 if (!urlSegments.is_absolute())
439 {
440 return url;
441 }
442
443 boost::urls::segments_view::iterator it = urlSegments.begin();
444 boost::urls::segments_view::iterator end = urlSegments.end();
445
446 for (uint idx = 0; it != end; it++, idx++)
447 {
448 if (idx == replaceLoc)
449 {
450 url.segments().push_back(newSegment);
451 }
452 else
453 {
454 url.segments().push_back(*it);
455 }
456 }
457
458 return url;
459}
460
Ed Tanousa716aa72023-08-01 11:35:53 -0700461inline void setProtocolDefaults(boost::urls::url& url,
462 std::string_view protocol)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800463{
Ed Tanousa716aa72023-08-01 11:35:53 -0700464 if (url.has_scheme())
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800465 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700466 return;
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800467 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700468 if (protocol == "Redfish" || protocol.empty())
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800469 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700470 if (url.port_number() == 443)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800471 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700472 url.set_scheme("https");
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800473 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700474 if (url.port_number() == 80)
475 {
Ed Tanous25b54db2024-04-17 15:40:31 -0700476 if constexpr (BMCWEB_INSECURE_PUSH_STYLE_NOTIFICATION)
Ed Tanousa716aa72023-08-01 11:35:53 -0700477 {
478 url.set_scheme("http");
479 }
480 }
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800481 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700482 else if (protocol == "SNMPv2c")
Chicago Duan3d307082020-11-26 14:12:12 +0800483 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700484 url.set_scheme("snmp");
Chicago Duan3d307082020-11-26 14:12:12 +0800485 }
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800486}
487
Ed Tanousa716aa72023-08-01 11:35:53 -0700488inline void setPortDefaults(boost::urls::url& url)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800489{
490 uint16_t port = url.port_number();
491 if (port != 0)
492 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700493 return;
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800494 }
495
496 // If the user hasn't explicitly stated a port, pick one explicitly for them
497 // based on the protocol defaults
498 if (url.scheme() == "http")
499 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700500 url.set_port_number(80);
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800501 }
502 if (url.scheme() == "https")
503 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700504 url.set_port_number(443);
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800505 }
Chicago Duan3d307082020-11-26 14:12:12 +0800506 if (url.scheme() == "snmp")
507 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700508 url.set_port_number(162);
Chicago Duan3d307082020-11-26 14:12:12 +0800509 }
Ed Tanous11baefe2022-02-09 12:14:12 -0800510}
511
Ed Tanous1abe55e2018-09-05 08:30:59 -0700512} // namespace utility
513} // namespace crow
Ed Tanous71f2db72022-05-25 12:28:09 -0700514
515namespace nlohmann
516{
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700517template <std::derived_from<boost::urls::url_view_base> URL>
518struct adl_serializer<URL>
Ed Tanous71f2db72022-05-25 12:28:09 -0700519{
520 // NOLINTNEXTLINE(readability-identifier-naming)
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700521 static void to_json(json& j, const URL& url)
Ed Tanous71f2db72022-05-25 12:28:09 -0700522 {
Ed Tanous079360a2022-06-29 10:05:19 -0700523 j = url.buffer();
Ed Tanous71f2db72022-05-25 12:28:09 -0700524 }
525};
526} // namespace nlohmann