blob: 494b73453be9487ea66d57047a66c0718d8e47f8 [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 Tanouseae855c2021-10-26 11:26:02 -0700317namespace details
318{
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400319inline boost::urls::url appendUrlPieces(
320 boost::urls::url& url, const std::initializer_list<std::string_view> args)
Ed Tanouseae855c2021-10-26 11:26:02 -0700321{
Ed Tanous26ccae32023-02-16 10:28:44 -0800322 for (std::string_view arg : args)
Ed Tanouseae855c2021-10-26 11:26:02 -0700323 {
324 url.segments().push_back(arg);
325 }
326 return url;
327}
Willy Tuc6bcedc2022-09-27 05:36:59 +0000328
Ed Tanouseae855c2021-10-26 11:26:02 -0700329} // namespace details
330
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700331class OrMorePaths
332{};
333
Ed Tanouseae855c2021-10-26 11:26:02 -0700334template <typename... AV>
Willy Tuc6bcedc2022-09-27 05:36:59 +0000335inline void appendUrlPieces(boost::urls::url& url, const AV... args)
336{
337 details::appendUrlPieces(url, {args...});
338}
339
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100340namespace details
341{
342
343// std::reference_wrapper<std::string> - extracts segment to variable
344// std::string_view - checks if segment is equal to variable
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700345using UrlSegment = std::variant<std::reference_wrapper<std::string>,
346 std::string_view, OrMorePaths>;
347
348enum class UrlParseResult
349{
350 Continue,
351 Fail,
352 Done,
353};
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100354
355class UrlSegmentMatcherVisitor
356{
357 public:
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700358 UrlParseResult operator()(std::string& output)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100359 {
Ed Tanous079360a2022-06-29 10:05:19 -0700360 output = segment;
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700361 return UrlParseResult::Continue;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100362 }
363
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700364 UrlParseResult operator()(std::string_view expected)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100365 {
Ed Tanous079360a2022-06-29 10:05:19 -0700366 if (segment == expected)
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700367 {
368 return UrlParseResult::Continue;
369 }
370 return UrlParseResult::Fail;
371 }
372
373 UrlParseResult operator()(OrMorePaths /*unused*/)
374 {
375 return UrlParseResult::Done;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100376 }
377
Ed Tanous079360a2022-06-29 10:05:19 -0700378 explicit UrlSegmentMatcherVisitor(std::string_view segmentIn) :
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100379 segment(segmentIn)
380 {}
381
382 private:
Ed Tanous079360a2022-06-29 10:05:19 -0700383 std::string_view segment;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100384};
385
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700386inline bool readUrlSegments(const boost::urls::url_view_base& url,
Ed Tanous5be2b142024-03-27 15:27:04 -0700387 std::initializer_list<UrlSegment> segments)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100388{
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700389 const boost::urls::segments_view& urlSegments = url.segments();
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100390
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700391 if (!urlSegments.is_absolute())
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100392 {
393 return false;
394 }
395
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700396 boost::urls::segments_view::const_iterator it = urlSegments.begin();
397 boost::urls::segments_view::const_iterator end = urlSegments.end();
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100398
399 for (const auto& segment : segments)
400 {
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700401 if (it == end)
402 {
403 // If the request ends with an "any" path, this was successful
404 return std::holds_alternative<OrMorePaths>(segment);
405 }
406 UrlParseResult res = std::visit(UrlSegmentMatcherVisitor(*it), segment);
407 if (res == UrlParseResult::Done)
408 {
409 return true;
410 }
411 if (res == UrlParseResult::Fail)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100412 {
413 return false;
414 }
415 it++;
416 }
Carson Labrado4c30e222022-06-24 22:16:00 +0000417
418 // There will be an empty segment at the end if the URI ends with a "/"
419 // e.g. /redfish/v1/Chassis/
420 if ((it != end) && urlSegments.back().empty())
421 {
422 it++;
423 }
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700424 return it == end;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100425}
426
427} // namespace details
428
429template <typename... Args>
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700430inline bool readUrlSegments(const boost::urls::url_view_base& url,
431 Args&&... args)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100432{
Ed Tanous39662a32023-02-06 15:09:46 -0800433 return details::readUrlSegments(url, {std::forward<Args>(args)...});
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100434}
435
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700436inline boost::urls::url
437 replaceUrlSegment(const boost::urls::url_view_base& urlView,
438 const uint replaceLoc, std::string_view newSegment)
Carson Labrado1c0bb5c2022-05-18 00:12:52 +0000439{
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700440 const boost::urls::segments_view& urlSegments = urlView.segments();
Carson Labrado1c0bb5c2022-05-18 00:12:52 +0000441 boost::urls::url url("/");
442
443 if (!urlSegments.is_absolute())
444 {
445 return url;
446 }
447
448 boost::urls::segments_view::iterator it = urlSegments.begin();
449 boost::urls::segments_view::iterator end = urlSegments.end();
450
451 for (uint idx = 0; it != end; it++, idx++)
452 {
453 if (idx == replaceLoc)
454 {
455 url.segments().push_back(newSegment);
456 }
457 else
458 {
459 url.segments().push_back(*it);
460 }
461 }
462
463 return url;
464}
465
Ed Tanousa716aa72023-08-01 11:35:53 -0700466inline void setProtocolDefaults(boost::urls::url& url,
467 std::string_view protocol)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800468{
Ed Tanousa716aa72023-08-01 11:35:53 -0700469 if (url.has_scheme())
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800470 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700471 return;
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800472 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700473 if (protocol == "Redfish" || protocol.empty())
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800474 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700475 if (url.port_number() == 443)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800476 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700477 url.set_scheme("https");
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800478 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700479 if (url.port_number() == 80)
480 {
Ed Tanous25b54db2024-04-17 15:40:31 -0700481 if constexpr (BMCWEB_INSECURE_PUSH_STYLE_NOTIFICATION)
Ed Tanousa716aa72023-08-01 11:35:53 -0700482 {
483 url.set_scheme("http");
484 }
485 }
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800486 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700487 else if (protocol == "SNMPv2c")
Chicago Duan3d307082020-11-26 14:12:12 +0800488 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700489 url.set_scheme("snmp");
Chicago Duan3d307082020-11-26 14:12:12 +0800490 }
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800491}
492
Ed Tanousa716aa72023-08-01 11:35:53 -0700493inline void setPortDefaults(boost::urls::url& url)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800494{
495 uint16_t port = url.port_number();
496 if (port != 0)
497 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700498 return;
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800499 }
500
501 // If the user hasn't explicitly stated a port, pick one explicitly for them
502 // based on the protocol defaults
503 if (url.scheme() == "http")
504 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700505 url.set_port_number(80);
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800506 }
507 if (url.scheme() == "https")
508 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700509 url.set_port_number(443);
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800510 }
Chicago Duan3d307082020-11-26 14:12:12 +0800511 if (url.scheme() == "snmp")
512 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700513 url.set_port_number(162);
Chicago Duan3d307082020-11-26 14:12:12 +0800514 }
Ed Tanous11baefe2022-02-09 12:14:12 -0800515}
516
Ed Tanous1abe55e2018-09-05 08:30:59 -0700517} // namespace utility
518} // namespace crow
Ed Tanous71f2db72022-05-25 12:28:09 -0700519
520namespace nlohmann
521{
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700522template <std::derived_from<boost::urls::url_view_base> URL>
523struct adl_serializer<URL>
Ed Tanous71f2db72022-05-25 12:28:09 -0700524{
525 // NOLINTNEXTLINE(readability-identifier-naming)
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700526 static void to_json(json& j, const URL& url)
Ed Tanous71f2db72022-05-25 12:28:09 -0700527 {
Ed Tanous079360a2022-06-29 10:05:19 -0700528 j = url.buffer();
Ed Tanous71f2db72022-05-25 12:28:09 -0700529 }
530};
531} // namespace nlohmann