blob: 0cddb1c34aea6ba6cf75ccbfef7f5357b501fa81 [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 Tanousc867a832022-03-10 14:17:00 -08005#include <boost/callable_traits.hpp>
Ed Tanous079360a2022-06-29 10:05:19 -07006#include <boost/url/parse.hpp>
Ed Tanouseae855c2021-10-26 11:26:02 -07007#include <boost/url/url.hpp>
Ed Tanous079360a2022-06-29 10:05:19 -07008#include <boost/url/url_view.hpp>
Ed Tanous4a7fbef2024-04-06 16:03:49 -07009#include <boost/url/url_view_base.hpp>
Ed Tanous71f2db72022-05-25 12:28:09 -070010#include <nlohmann/json.hpp>
Nan Zhou1d8782e2021-11-29 22:23:18 -080011
Ed Tanous9ea15c32022-01-04 14:18:22 -080012#include <array>
Ed Tanous74849be2021-02-05 09:47:47 -080013#include <chrono>
Ed Tanousc715ec22022-03-10 15:38:01 -080014#include <cstddef>
Ed Tanous7045c8d2017-04-03 10:04:37 -070015#include <cstdint>
Ed Tanous9ea15c32022-01-04 14:18:22 -080016#include <ctime>
Ed Tanous7045c8d2017-04-03 10:04:37 -070017#include <functional>
Ed Tanous9896eae2022-07-23 15:07:33 -070018#include <iomanip>
Ed Tanous9ea15c32022-01-04 14:18:22 -080019#include <limits>
Ed Tanous7045c8d2017-04-03 10:04:37 -070020#include <stdexcept>
21#include <string>
Ed Tanous9ea15c32022-01-04 14:18:22 -080022#include <string_view>
Ed Tanous7045c8d2017-04-03 10:04:37 -070023#include <tuple>
Ed Tanous9ea15c32022-01-04 14:18:22 -080024#include <type_traits>
25#include <utility>
Szymon Dompkeca1600c2022-03-03 14:42:52 +010026#include <variant>
Ed Tanous7045c8d2017-04-03 10:04:37 -070027
Ed Tanous1abe55e2018-09-05 08:30:59 -070028namespace crow
29{
Ed Tanous47488a92023-06-26 18:19:33 -070030namespace utility
Ed Tanous1abe55e2018-09-05 08:30:59 -070031{
Ed Tanous7045c8d2017-04-03 10:04:37 -070032
Ed Tanous9de65b32024-03-27 13:34:40 -070033constexpr uint64_t getParameterTag(std::string_view url)
Ed Tanous1abe55e2018-09-05 08:30:59 -070034{
Ed Tanous1c30e502022-03-08 18:02:24 -080035 uint64_t tagValue = 0;
36 size_t urlSegmentIndex = std::string_view::npos;
Ed Tanousb00dcc22021-02-23 12:52:50 -080037
Ed Tanous1c30e502022-03-08 18:02:24 -080038 for (size_t urlIndex = 0; urlIndex < url.size(); urlIndex++)
39 {
40 char character = url[urlIndex];
41 if (character == '<')
42 {
43 if (urlSegmentIndex != std::string_view::npos)
44 {
45 return 0;
46 }
47 urlSegmentIndex = urlIndex;
48 }
49 if (character == '>')
50 {
51 if (urlSegmentIndex == std::string_view::npos)
52 {
53 return 0;
54 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -040055 std::string_view tag =
56 url.substr(urlSegmentIndex, urlIndex + 1 - urlSegmentIndex);
Ed Tanous1c30e502022-03-08 18:02:24 -080057
Ed Tanous1c30e502022-03-08 18:02:24 -080058 if (tag == "<str>" || tag == "<string>")
59 {
Ed Tanousd9e89df2024-03-27 14:08:59 -070060 tagValue++;
Ed Tanous1c30e502022-03-08 18:02:24 -080061 }
62 if (tag == "<path>")
63 {
Ed Tanousd9e89df2024-03-27 14:08:59 -070064 tagValue++;
Ed Tanous1c30e502022-03-08 18:02:24 -080065 }
Ed Tanous1c30e502022-03-08 18:02:24 -080066 urlSegmentIndex = std::string_view::npos;
67 }
68 }
69 if (urlSegmentIndex != std::string_view::npos)
Ed Tanous988403c2020-08-24 11:29:49 -070070 {
71 return 0;
72 }
Ed Tanous1c30e502022-03-08 18:02:24 -080073 return tagValue;
Ed Tanous7045c8d2017-04-03 10:04:37 -070074}
Ed Tanous7045c8d2017-04-03 10:04:37 -070075
Ed Tanousee192c02023-12-13 10:49:58 -080076class Base64Encoder
Adriana Kobylakd830ff52021-01-27 14:15:27 -060077{
Ed Tanousee192c02023-12-13 10:49:58 -080078 char overflow1 = '\0';
79 char overflow2 = '\0';
80 uint8_t overflowCount = 0;
81
82 constexpr static std::array<char, 64> key = {
Adriana Kobylakd830ff52021-01-27 14:15:27 -060083 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
84 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
85 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
86 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
87 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
88
Ed Tanousee192c02023-12-13 10:49:58 -080089 // Takes 3 ascii chars, and encodes them as 4 base64 chars
90 static void encodeTriple(char first, char second, char third,
91 std::string& output)
Adriana Kobylakd830ff52021-01-27 14:15:27 -060092 {
Ed Tanous543f4402022-01-06 13:12:53 -080093 size_t keyIndex = 0;
Adriana Kobylakd830ff52021-01-27 14:15:27 -060094
Ed Tanousee192c02023-12-13 10:49:58 -080095 keyIndex = static_cast<size_t>(first & 0xFC) >> 2;
96 output += key[keyIndex];
Adriana Kobylakd830ff52021-01-27 14:15:27 -060097
Ed Tanousee192c02023-12-13 10:49:58 -080098 keyIndex = static_cast<size_t>(first & 0x03) << 4;
99 keyIndex += static_cast<size_t>(second & 0xF0) >> 4;
100 output += key[keyIndex];
101
102 keyIndex = static_cast<size_t>(second & 0x0F) << 2;
103 keyIndex += static_cast<size_t>(third & 0xC0) >> 6;
104 output += key[keyIndex];
105
106 keyIndex = static_cast<size_t>(third & 0x3F);
107 output += key[keyIndex];
108 }
109
110 public:
111 // Accepts a partial string to encode, and writes the encoded characters to
112 // the output stream. requires subsequently calling finalize to complete
113 // stream.
114 void encode(std::string_view data, std::string& output)
115 {
116 // Encode the last round of overflow chars first
117 if (overflowCount == 2)
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600118 {
Ed Tanousee192c02023-12-13 10:49:58 -0800119 if (!data.empty())
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600120 {
Ed Tanousee192c02023-12-13 10:49:58 -0800121 encodeTriple(overflow1, overflow2, data[0], output);
122 overflowCount = 0;
123 data.remove_prefix(1);
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600124 }
Ed Tanousee192c02023-12-13 10:49:58 -0800125 }
126 else if (overflowCount == 1)
127 {
128 if (data.size() >= 2)
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600129 {
Ed Tanousee192c02023-12-13 10:49:58 -0800130 encodeTriple(overflow1, data[0], data[1], output);
131 overflowCount = 0;
132 data.remove_prefix(2);
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600133 }
134 }
Ed Tanousee192c02023-12-13 10:49:58 -0800135
136 while (data.size() >= 3)
137 {
138 encodeTriple(data[0], data[1], data[2], output);
139 data.remove_prefix(3);
140 }
141
142 if (!data.empty() && overflowCount == 0)
143 {
144 overflow1 = data[0];
145 overflowCount++;
146 data.remove_prefix(1);
147 }
148
149 if (!data.empty() && overflowCount == 1)
150 {
151 overflow2 = data[0];
152 overflowCount++;
153 data.remove_prefix(1);
154 }
155 }
156
157 // Completes a base64 output, by writing any MOD(3) characters to the
158 // output, as well as any required trailing =
159 void finalize(std::string& output)
160 {
161 if (overflowCount == 0)
162 {
163 return;
164 }
165 size_t keyIndex = static_cast<size_t>(overflow1 & 0xFC) >> 2;
166 output += key[keyIndex];
167
168 keyIndex = static_cast<size_t>(overflow1 & 0x03) << 4;
169 if (overflowCount == 2)
170 {
171 keyIndex += static_cast<size_t>(overflow2 & 0xF0) >> 4;
172 output += key[keyIndex];
173 keyIndex = static_cast<size_t>(overflow2 & 0x0F) << 2;
174 output += key[keyIndex];
175 }
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600176 else
177 {
Ed Tanousee192c02023-12-13 10:49:58 -0800178 output += key[keyIndex];
179 output += '=';
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600180 }
Ed Tanousee192c02023-12-13 10:49:58 -0800181 output += '=';
182 overflowCount = 0;
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600183 }
184
Ed Tanousee192c02023-12-13 10:49:58 -0800185 // Returns the required output buffer in characters for an input of size
186 // inputSize
187 static size_t constexpr encodedSize(size_t inputSize)
188 {
189 // Base64 encodes 3 character blocks as 4 character blocks
190 // With a possibility of 2 trailing = characters
191 return (inputSize + 2) / 3 * 4;
192 }
193};
194
195inline std::string base64encode(std::string_view data)
196{
197 // Encodes a 3 character stream into a 4 character stream
198 std::string out;
199 Base64Encoder base64;
200 out.reserve(Base64Encoder::encodedSize(data.size()));
201 base64.encode(data, out);
202 base64.finalize(out);
203 return out;
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600204}
205
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100206// TODO this is temporary and should be deleted once base64 is refactored out of
207// crow
Ed Tanous26ccae32023-02-16 10:28:44 -0800208inline bool base64Decode(std::string_view input, std::string& output)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700209{
Ed Tanous271584a2019-07-09 16:24:22 -0700210 static const char nop = static_cast<char>(-1);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700211 // See note on encoding_data[] in above function
Jonathan Doman5beaf842020-08-14 11:23:33 -0700212 static const std::array<char, 256> decodingData = {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700213 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
214 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
215 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
216 nop, 62, nop, nop, nop, 63, 52, 53, 54, 55, 56, 57, 58, 59,
217 60, 61, nop, nop, nop, nop, nop, nop, nop, 0, 1, 2, 3, 4,
218 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
219 19, 20, 21, 22, 23, 24, 25, nop, nop, nop, nop, nop, nop, 26,
220 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
221 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, nop, nop, nop,
222 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
223 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
224 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
225 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
226 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, 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};
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100232
Ed Tanous1abe55e2018-09-05 08:30:59 -0700233 size_t inputLength = input.size();
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100234
Ed Tanous1abe55e2018-09-05 08:30:59 -0700235 // allocate space for output string
236 output.clear();
237 output.reserve(((inputLength + 2) / 3) * 4);
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100238
Jonathan Doman5beaf842020-08-14 11:23:33 -0700239 auto getCodeValue = [](char c) {
240 auto code = static_cast<unsigned char>(c);
241 // Ensure we cannot index outside the bounds of the decoding array
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400242 static_assert(
243 std::numeric_limits<decltype(code)>::max() < decodingData.size());
Jonathan Doman5beaf842020-08-14 11:23:33 -0700244 return decodingData[code];
245 };
246
Ed Tanous1abe55e2018-09-05 08:30:59 -0700247 // for each 4-bytes sequence from the input, extract 4 6-bits sequences by
Gunnar Millscaa3ce32020-07-08 14:46:53 -0500248 // dropping first two bits
Ed Tanous1abe55e2018-09-05 08:30:59 -0700249 // and regenerate into 3 8-bits sequences
James Feist5a806642020-07-31 16:40:33 +0000250
Ed Tanous1abe55e2018-09-05 08:30:59 -0700251 for (size_t i = 0; i < inputLength; i++)
252 {
Ed Tanous543f4402022-01-06 13:12:53 -0800253 char base64code0 = 0;
254 char base64code1 = 0;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700255 char base64code2 = 0; // initialized to 0 to suppress warnings
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100256
Jonathan Doman5beaf842020-08-14 11:23:33 -0700257 base64code0 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700258 if (base64code0 == nop)
Myung Bae41868c62024-10-09 16:36:49 -0700259 {
260 // non base64 character
Ed Tanous1abe55e2018-09-05 08:30:59 -0700261 return false;
262 }
263 if (!(++i < inputLength))
Myung Bae41868c62024-10-09 16:36:49 -0700264 {
265 // we need at least two input bytes for first byte output
Ed Tanous1abe55e2018-09-05 08:30:59 -0700266 return false;
267 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700268 base64code1 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700269 if (base64code1 == nop)
Myung Bae41868c62024-10-09 16:36:49 -0700270 {
271 // non base64 character
Ed Tanous1abe55e2018-09-05 08:30:59 -0700272 return false;
273 }
274 output +=
275 static_cast<char>((base64code0 << 2) | ((base64code1 >> 4) & 0x3));
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100276
Ed Tanous1abe55e2018-09-05 08:30:59 -0700277 if (++i < inputLength)
278 {
279 char c = input[i];
280 if (c == '=')
Myung Bae41868c62024-10-09 16:36:49 -0700281 {
282 // padding , end of input
Ed Tanous1abe55e2018-09-05 08:30:59 -0700283 return (base64code1 & 0x0f) == 0;
284 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700285 base64code2 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700286 if (base64code2 == nop)
Myung Bae41868c62024-10-09 16:36:49 -0700287 {
288 // non base64 character
Ed Tanous1abe55e2018-09-05 08:30:59 -0700289 return false;
290 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400291 output += static_cast<char>(
292 ((base64code1 << 4) & 0xf0) | ((base64code2 >> 2) & 0x0f));
Ed Tanous1abe55e2018-09-05 08:30:59 -0700293 }
294
295 if (++i < inputLength)
296 {
297 char c = input[i];
298 if (c == '=')
Myung Bae41868c62024-10-09 16:36:49 -0700299 {
300 // padding , end of input
Ed Tanous1abe55e2018-09-05 08:30:59 -0700301 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)
Myung Bae41868c62024-10-09 16:36:49 -0700305 {
306 // non base64 character
Ed Tanous1abe55e2018-09-05 08:30:59 -0700307 return false;
308 }
309 output +=
310 static_cast<char>((((base64code2 << 6) & 0xc0) | base64code3));
311 }
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100312 }
313
Ed Tanous1abe55e2018-09-05 08:30:59 -0700314 return true;
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100315}
316
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700317class OrMorePaths
318{};
319
Ed Tanouseae855c2021-10-26 11:26:02 -0700320template <typename... AV>
Ed Tanousdaadfb22024-12-20 09:25:54 -0800321inline void appendUrlPieces(boost::urls::url& url, AV&&... args)
Willy Tuc6bcedc2022-09-27 05:36:59 +0000322{
Ed Tanousdaadfb22024-12-20 09:25:54 -0800323 // Unclear the correct fix here.
324 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
325 for (const std::string_view arg : {args...})
326 {
327 url.segments().push_back(arg);
328 }
Willy Tuc6bcedc2022-09-27 05:36:59 +0000329}
330
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100331namespace details
332{
333
334// std::reference_wrapper<std::string> - extracts segment to variable
335// std::string_view - checks if segment is equal to variable
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700336using UrlSegment = std::variant<std::reference_wrapper<std::string>,
337 std::string_view, OrMorePaths>;
338
339enum class UrlParseResult
340{
341 Continue,
342 Fail,
343 Done,
344};
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100345
346class UrlSegmentMatcherVisitor
347{
348 public:
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700349 UrlParseResult operator()(std::string& output)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100350 {
Ed Tanous079360a2022-06-29 10:05:19 -0700351 output = segment;
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700352 return UrlParseResult::Continue;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100353 }
354
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700355 UrlParseResult operator()(std::string_view expected)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100356 {
Ed Tanous079360a2022-06-29 10:05:19 -0700357 if (segment == expected)
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700358 {
359 return UrlParseResult::Continue;
360 }
361 return UrlParseResult::Fail;
362 }
363
364 UrlParseResult operator()(OrMorePaths /*unused*/)
365 {
366 return UrlParseResult::Done;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100367 }
368
Ed Tanous079360a2022-06-29 10:05:19 -0700369 explicit UrlSegmentMatcherVisitor(std::string_view segmentIn) :
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100370 segment(segmentIn)
371 {}
372
373 private:
Ed Tanous079360a2022-06-29 10:05:19 -0700374 std::string_view segment;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100375};
376
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700377inline bool readUrlSegments(const boost::urls::url_view_base& url,
Ed Tanous5be2b142024-03-27 15:27:04 -0700378 std::initializer_list<UrlSegment> segments)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100379{
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700380 const boost::urls::segments_view& urlSegments = url.segments();
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100381
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700382 if (!urlSegments.is_absolute())
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100383 {
384 return false;
385 }
386
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700387 boost::urls::segments_view::const_iterator it = urlSegments.begin();
388 boost::urls::segments_view::const_iterator end = urlSegments.end();
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100389
390 for (const auto& segment : segments)
391 {
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700392 if (it == end)
393 {
394 // If the request ends with an "any" path, this was successful
395 return std::holds_alternative<OrMorePaths>(segment);
396 }
397 UrlParseResult res = std::visit(UrlSegmentMatcherVisitor(*it), segment);
398 if (res == UrlParseResult::Done)
399 {
400 return true;
401 }
402 if (res == UrlParseResult::Fail)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100403 {
404 return false;
405 }
406 it++;
407 }
Carson Labrado4c30e222022-06-24 22:16:00 +0000408
409 // There will be an empty segment at the end if the URI ends with a "/"
410 // e.g. /redfish/v1/Chassis/
411 if ((it != end) && urlSegments.back().empty())
412 {
413 it++;
414 }
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700415 return it == end;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100416}
417
418} // namespace details
419
420template <typename... Args>
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700421inline bool readUrlSegments(const boost::urls::url_view_base& url,
422 Args&&... args)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100423{
Ed Tanous39662a32023-02-06 15:09:46 -0800424 return details::readUrlSegments(url, {std::forward<Args>(args)...});
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100425}
426
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700427inline boost::urls::url
428 replaceUrlSegment(const boost::urls::url_view_base& urlView,
429 const uint replaceLoc, std::string_view newSegment)
Carson Labrado1c0bb5c2022-05-18 00:12:52 +0000430{
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700431 const boost::urls::segments_view& urlSegments = urlView.segments();
Carson Labrado1c0bb5c2022-05-18 00:12:52 +0000432 boost::urls::url url("/");
433
434 if (!urlSegments.is_absolute())
435 {
436 return url;
437 }
438
439 boost::urls::segments_view::iterator it = urlSegments.begin();
440 boost::urls::segments_view::iterator end = urlSegments.end();
441
442 for (uint idx = 0; it != end; it++, idx++)
443 {
444 if (idx == replaceLoc)
445 {
446 url.segments().push_back(newSegment);
447 }
448 else
449 {
450 url.segments().push_back(*it);
451 }
452 }
453
454 return url;
455}
456
Ed Tanousa716aa72023-08-01 11:35:53 -0700457inline void setProtocolDefaults(boost::urls::url& url,
458 std::string_view protocol)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800459{
Ed Tanousa716aa72023-08-01 11:35:53 -0700460 if (url.has_scheme())
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800461 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700462 return;
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800463 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700464 if (protocol == "Redfish" || protocol.empty())
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800465 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700466 if (url.port_number() == 443)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800467 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700468 url.set_scheme("https");
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800469 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700470 if (url.port_number() == 80)
471 {
Ed Tanous25b54db2024-04-17 15:40:31 -0700472 if constexpr (BMCWEB_INSECURE_PUSH_STYLE_NOTIFICATION)
Ed Tanousa716aa72023-08-01 11:35:53 -0700473 {
474 url.set_scheme("http");
475 }
476 }
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800477 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700478 else if (protocol == "SNMPv2c")
Chicago Duan3d307082020-11-26 14:12:12 +0800479 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700480 url.set_scheme("snmp");
Chicago Duan3d307082020-11-26 14:12:12 +0800481 }
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800482}
483
Ed Tanousa716aa72023-08-01 11:35:53 -0700484inline void setPortDefaults(boost::urls::url& url)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800485{
486 uint16_t port = url.port_number();
487 if (port != 0)
488 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700489 return;
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800490 }
491
492 // If the user hasn't explicitly stated a port, pick one explicitly for them
493 // based on the protocol defaults
494 if (url.scheme() == "http")
495 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700496 url.set_port_number(80);
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800497 }
498 if (url.scheme() == "https")
499 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700500 url.set_port_number(443);
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800501 }
Chicago Duan3d307082020-11-26 14:12:12 +0800502 if (url.scheme() == "snmp")
503 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700504 url.set_port_number(162);
Chicago Duan3d307082020-11-26 14:12:12 +0800505 }
Ed Tanous11baefe2022-02-09 12:14:12 -0800506}
507
Ed Tanous1abe55e2018-09-05 08:30:59 -0700508} // namespace utility
509} // namespace crow
Ed Tanous71f2db72022-05-25 12:28:09 -0700510
511namespace nlohmann
512{
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700513template <std::derived_from<boost::urls::url_view_base> URL>
514struct adl_serializer<URL>
Ed Tanous71f2db72022-05-25 12:28:09 -0700515{
516 // NOLINTNEXTLINE(readability-identifier-naming)
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700517 static void to_json(json& j, const URL& url)
Ed Tanous71f2db72022-05-25 12:28:09 -0700518 {
Ed Tanous079360a2022-06-29 10:05:19 -0700519 j = url.buffer();
Ed Tanous71f2db72022-05-25 12:28:09 -0700520 }
521};
522} // namespace nlohmann