blob: 7633c395afae45eb736f616767bf3c541fb93e2b [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 Tanous51dae672018-09-05 16:07:32 -07005#include <openssl/crypto.h>
6
Ed Tanousc867a832022-03-10 14:17:00 -08007#include <boost/callable_traits.hpp>
Ed Tanous079360a2022-06-29 10:05:19 -07008#include <boost/url/parse.hpp>
Ed Tanouseae855c2021-10-26 11:26:02 -07009#include <boost/url/url.hpp>
Ed Tanous079360a2022-06-29 10:05:19 -070010#include <boost/url/url_view.hpp>
Ed Tanous71f2db72022-05-25 12:28:09 -070011#include <nlohmann/json.hpp>
Nan Zhou1d8782e2021-11-29 22:23:18 -080012
Ed Tanous9ea15c32022-01-04 14:18:22 -080013#include <array>
Ed Tanous74849be2021-02-05 09:47:47 -080014#include <chrono>
Ed Tanousc715ec22022-03-10 15:38:01 -080015#include <cstddef>
Ed Tanous7045c8d2017-04-03 10:04:37 -070016#include <cstdint>
Ed Tanous9ea15c32022-01-04 14:18:22 -080017#include <ctime>
Ed Tanous7045c8d2017-04-03 10:04:37 -070018#include <functional>
Ed Tanous9896eae2022-07-23 15:07:33 -070019#include <iomanip>
Ed Tanous9ea15c32022-01-04 14:18:22 -080020#include <limits>
Ed Tanous7045c8d2017-04-03 10:04:37 -070021#include <stdexcept>
22#include <string>
Ed Tanous9ea15c32022-01-04 14:18:22 -080023#include <string_view>
Ed Tanous7045c8d2017-04-03 10:04:37 -070024#include <tuple>
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 Williams89492a12023-05-10 07:51:34 -050056 std::string_view tag = url.substr(urlSegmentIndex,
57 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 Tanousee192c02023-12-13 10:49:58 -080077class Base64Encoder
Adriana Kobylakd830ff52021-01-27 14:15:27 -060078{
Ed Tanousee192c02023-12-13 10:49:58 -080079 char overflow1 = '\0';
80 char overflow2 = '\0';
81 uint8_t overflowCount = 0;
82
83 constexpr static std::array<char, 64> key = {
Adriana Kobylakd830ff52021-01-27 14:15:27 -060084 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
85 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
86 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
87 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
88 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
89
Ed Tanousee192c02023-12-13 10:49:58 -080090 // Takes 3 ascii chars, and encodes them as 4 base64 chars
91 static void encodeTriple(char first, char second, char third,
92 std::string& output)
Adriana Kobylakd830ff52021-01-27 14:15:27 -060093 {
Ed Tanous543f4402022-01-06 13:12:53 -080094 size_t keyIndex = 0;
Adriana Kobylakd830ff52021-01-27 14:15:27 -060095
Ed Tanousee192c02023-12-13 10:49:58 -080096 keyIndex = static_cast<size_t>(first & 0xFC) >> 2;
97 output += key[keyIndex];
Adriana Kobylakd830ff52021-01-27 14:15:27 -060098
Ed Tanousee192c02023-12-13 10:49:58 -080099 keyIndex = static_cast<size_t>(first & 0x03) << 4;
100 keyIndex += static_cast<size_t>(second & 0xF0) >> 4;
101 output += key[keyIndex];
102
103 keyIndex = static_cast<size_t>(second & 0x0F) << 2;
104 keyIndex += static_cast<size_t>(third & 0xC0) >> 6;
105 output += key[keyIndex];
106
107 keyIndex = static_cast<size_t>(third & 0x3F);
108 output += key[keyIndex];
109 }
110
111 public:
112 // Accepts a partial string to encode, and writes the encoded characters to
113 // the output stream. requires subsequently calling finalize to complete
114 // stream.
115 void encode(std::string_view data, std::string& output)
116 {
117 // Encode the last round of overflow chars first
118 if (overflowCount == 2)
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600119 {
Ed Tanousee192c02023-12-13 10:49:58 -0800120 if (!data.empty())
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600121 {
Ed Tanousee192c02023-12-13 10:49:58 -0800122 encodeTriple(overflow1, overflow2, data[0], output);
123 overflowCount = 0;
124 data.remove_prefix(1);
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600125 }
Ed Tanousee192c02023-12-13 10:49:58 -0800126 }
127 else if (overflowCount == 1)
128 {
129 if (data.size() >= 2)
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600130 {
Ed Tanousee192c02023-12-13 10:49:58 -0800131 encodeTriple(overflow1, data[0], data[1], output);
132 overflowCount = 0;
133 data.remove_prefix(2);
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600134 }
135 }
Ed Tanousee192c02023-12-13 10:49:58 -0800136
137 while (data.size() >= 3)
138 {
139 encodeTriple(data[0], data[1], data[2], output);
140 data.remove_prefix(3);
141 }
142
143 if (!data.empty() && overflowCount == 0)
144 {
145 overflow1 = data[0];
146 overflowCount++;
147 data.remove_prefix(1);
148 }
149
150 if (!data.empty() && overflowCount == 1)
151 {
152 overflow2 = data[0];
153 overflowCount++;
154 data.remove_prefix(1);
155 }
156 }
157
158 // Completes a base64 output, by writing any MOD(3) characters to the
159 // output, as well as any required trailing =
160 void finalize(std::string& output)
161 {
162 if (overflowCount == 0)
163 {
164 return;
165 }
166 size_t keyIndex = static_cast<size_t>(overflow1 & 0xFC) >> 2;
167 output += key[keyIndex];
168
169 keyIndex = static_cast<size_t>(overflow1 & 0x03) << 4;
170 if (overflowCount == 2)
171 {
172 keyIndex += static_cast<size_t>(overflow2 & 0xF0) >> 4;
173 output += key[keyIndex];
174 keyIndex = static_cast<size_t>(overflow2 & 0x0F) << 2;
175 output += key[keyIndex];
176 }
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600177 else
178 {
Ed Tanousee192c02023-12-13 10:49:58 -0800179 output += key[keyIndex];
180 output += '=';
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600181 }
Ed Tanousee192c02023-12-13 10:49:58 -0800182 output += '=';
183 overflowCount = 0;
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600184 }
185
Ed Tanousee192c02023-12-13 10:49:58 -0800186 // Returns the required output buffer in characters for an input of size
187 // inputSize
188 static size_t constexpr encodedSize(size_t inputSize)
189 {
190 // Base64 encodes 3 character blocks as 4 character blocks
191 // With a possibility of 2 trailing = characters
192 return (inputSize + 2) / 3 * 4;
193 }
194};
195
196inline std::string base64encode(std::string_view data)
197{
198 // Encodes a 3 character stream into a 4 character stream
199 std::string out;
200 Base64Encoder base64;
201 out.reserve(Base64Encoder::encodedSize(data.size()));
202 base64.encode(data, out);
203 base64.finalize(out);
204 return out;
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600205}
206
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100207// TODO this is temporary and should be deleted once base64 is refactored out of
208// crow
Ed Tanous26ccae32023-02-16 10:28:44 -0800209inline bool base64Decode(std::string_view input, std::string& output)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700210{
Ed Tanous271584a2019-07-09 16:24:22 -0700211 static const char nop = static_cast<char>(-1);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700212 // See note on encoding_data[] in above function
Jonathan Doman5beaf842020-08-14 11:23:33 -0700213 static const std::array<char, 256> decodingData = {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700214 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, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
217 nop, 62, nop, nop, nop, 63, 52, 53, 54, 55, 56, 57, 58, 59,
218 60, 61, nop, nop, nop, nop, nop, nop, nop, 0, 1, 2, 3, 4,
219 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
220 19, 20, 21, 22, 23, 24, 25, nop, nop, nop, nop, nop, nop, 26,
221 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
222 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 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, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
232 nop, nop, nop, nop};
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100233
Ed Tanous1abe55e2018-09-05 08:30:59 -0700234 size_t inputLength = input.size();
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100235
Ed Tanous1abe55e2018-09-05 08:30:59 -0700236 // allocate space for output string
237 output.clear();
238 output.reserve(((inputLength + 2) / 3) * 4);
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100239
Jonathan Doman5beaf842020-08-14 11:23:33 -0700240 auto getCodeValue = [](char c) {
241 auto code = static_cast<unsigned char>(c);
242 // Ensure we cannot index outside the bounds of the decoding array
243 static_assert(std::numeric_limits<decltype(code)>::max() <
244 decodingData.size());
245 return decodingData[code];
246 };
247
Ed Tanous1abe55e2018-09-05 08:30:59 -0700248 // for each 4-bytes sequence from the input, extract 4 6-bits sequences by
Gunnar Millscaa3ce32020-07-08 14:46:53 -0500249 // dropping first two bits
Ed Tanous1abe55e2018-09-05 08:30:59 -0700250 // and regenerate into 3 8-bits sequences
James Feist5a806642020-07-31 16:40:33 +0000251
Ed Tanous1abe55e2018-09-05 08:30:59 -0700252 for (size_t i = 0; i < inputLength; i++)
253 {
Ed Tanous543f4402022-01-06 13:12:53 -0800254 char base64code0 = 0;
255 char base64code1 = 0;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700256 char base64code2 = 0; // initialized to 0 to suppress warnings
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100257
Jonathan Doman5beaf842020-08-14 11:23:33 -0700258 base64code0 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700259 if (base64code0 == nop)
260 { // non base64 character
261 return false;
262 }
263 if (!(++i < inputLength))
264 { // we need at least two input bytes for first
265 // byte output
266 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)
270 { // non base64 character
271 return false;
272 }
273 output +=
274 static_cast<char>((base64code0 << 2) | ((base64code1 >> 4) & 0x3));
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100275
Ed Tanous1abe55e2018-09-05 08:30:59 -0700276 if (++i < inputLength)
277 {
278 char c = input[i];
279 if (c == '=')
280 { // padding , end of input
281 return (base64code1 & 0x0f) == 0;
282 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700283 base64code2 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700284 if (base64code2 == nop)
285 { // non base64 character
286 return false;
287 }
288 output += static_cast<char>(((base64code1 << 4) & 0xf0) |
289 ((base64code2 >> 2) & 0x0f));
290 }
291
292 if (++i < inputLength)
293 {
294 char c = input[i];
295 if (c == '=')
296 { // padding , end of input
297 return (base64code2 & 0x03) == 0;
298 }
Ed Tanousf8fe53e2022-06-30 15:55:45 -0700299 char base64code3 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700300 if (base64code3 == nop)
301 { // non base64 character
302 return false;
303 }
304 output +=
305 static_cast<char>((((base64code2 << 6) & 0xc0) | base64code3));
306 }
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100307 }
308
Ed Tanous1abe55e2018-09-05 08:30:59 -0700309 return true;
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100310}
311
Ed Tanous26ccae32023-02-16 10:28:44 -0800312inline bool constantTimeStringCompare(std::string_view a, std::string_view b)
Ed Tanous51dae672018-09-05 16:07:32 -0700313{
314 // Important note, this function is ONLY constant time if the two input
315 // sizes are the same
316 if (a.size() != b.size())
317 {
318 return false;
319 }
320 return CRYPTO_memcmp(a.data(), b.data(), a.size()) == 0;
321}
322
323struct ConstantTimeCompare
324{
Ed Tanous26ccae32023-02-16 10:28:44 -0800325 bool operator()(std::string_view a, std::string_view b) const
Ed Tanous51dae672018-09-05 16:07:32 -0700326 {
327 return constantTimeStringCompare(a, b);
328 }
329};
330
Ed Tanouseae855c2021-10-26 11:26:02 -0700331namespace details
332{
333inline boost::urls::url
Willy Tuc6bcedc2022-09-27 05:36:59 +0000334 appendUrlPieces(boost::urls::url& url,
335 const std::initializer_list<std::string_view> args)
Ed Tanouseae855c2021-10-26 11:26:02 -0700336{
Ed Tanous26ccae32023-02-16 10:28:44 -0800337 for (std::string_view arg : args)
Ed Tanouseae855c2021-10-26 11:26:02 -0700338 {
339 url.segments().push_back(arg);
340 }
341 return url;
342}
Willy Tuc6bcedc2022-09-27 05:36:59 +0000343
Ed Tanouseae855c2021-10-26 11:26:02 -0700344} // namespace details
345
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700346class OrMorePaths
347{};
348
Ed Tanouseae855c2021-10-26 11:26:02 -0700349template <typename... AV>
Willy Tuc6bcedc2022-09-27 05:36:59 +0000350inline void appendUrlPieces(boost::urls::url& url, const AV... args)
351{
352 details::appendUrlPieces(url, {args...});
353}
354
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100355namespace details
356{
357
358// std::reference_wrapper<std::string> - extracts segment to variable
359// std::string_view - checks if segment is equal to variable
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700360using UrlSegment = std::variant<std::reference_wrapper<std::string>,
361 std::string_view, OrMorePaths>;
362
363enum class UrlParseResult
364{
365 Continue,
366 Fail,
367 Done,
368};
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100369
370class UrlSegmentMatcherVisitor
371{
372 public:
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700373 UrlParseResult operator()(std::string& output)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100374 {
Ed Tanous079360a2022-06-29 10:05:19 -0700375 output = segment;
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700376 return UrlParseResult::Continue;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100377 }
378
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700379 UrlParseResult operator()(std::string_view expected)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100380 {
Ed Tanous079360a2022-06-29 10:05:19 -0700381 if (segment == expected)
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700382 {
383 return UrlParseResult::Continue;
384 }
385 return UrlParseResult::Fail;
386 }
387
388 UrlParseResult operator()(OrMorePaths /*unused*/)
389 {
390 return UrlParseResult::Done;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100391 }
392
Ed Tanous079360a2022-06-29 10:05:19 -0700393 explicit UrlSegmentMatcherVisitor(std::string_view segmentIn) :
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100394 segment(segmentIn)
395 {}
396
397 private:
Ed Tanous079360a2022-06-29 10:05:19 -0700398 std::string_view segment;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100399};
400
Ed Tanousd9f466b2023-03-06 15:04:25 -0800401inline bool readUrlSegments(boost::urls::url_view url,
Ed Tanous5be2b142024-03-27 15:27:04 -0700402 std::initializer_list<UrlSegment> segments)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100403{
Ed Tanousd9f466b2023-03-06 15:04:25 -0800404 boost::urls::segments_view urlSegments = url.segments();
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100405
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700406 if (!urlSegments.is_absolute())
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100407 {
408 return false;
409 }
410
411 boost::urls::segments_view::iterator it = urlSegments.begin();
412 boost::urls::segments_view::iterator end = urlSegments.end();
413
414 for (const auto& segment : segments)
415 {
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700416 if (it == end)
417 {
418 // If the request ends with an "any" path, this was successful
419 return std::holds_alternative<OrMorePaths>(segment);
420 }
421 UrlParseResult res = std::visit(UrlSegmentMatcherVisitor(*it), segment);
422 if (res == UrlParseResult::Done)
423 {
424 return true;
425 }
426 if (res == UrlParseResult::Fail)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100427 {
428 return false;
429 }
430 it++;
431 }
Carson Labrado4c30e222022-06-24 22:16:00 +0000432
433 // There will be an empty segment at the end if the URI ends with a "/"
434 // e.g. /redfish/v1/Chassis/
435 if ((it != end) && urlSegments.back().empty())
436 {
437 it++;
438 }
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700439 return it == end;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100440}
441
442} // namespace details
443
444template <typename... Args>
Ed Tanousd9f466b2023-03-06 15:04:25 -0800445inline bool readUrlSegments(boost::urls::url_view url, Args&&... args)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100446{
Ed Tanous39662a32023-02-06 15:09:46 -0800447 return details::readUrlSegments(url, {std::forward<Args>(args)...});
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100448}
449
Ed Tanousd9f466b2023-03-06 15:04:25 -0800450inline boost::urls::url replaceUrlSegment(boost::urls::url_view urlView,
Carson Labrado1c0bb5c2022-05-18 00:12:52 +0000451 const uint replaceLoc,
Ed Tanous26ccae32023-02-16 10:28:44 -0800452 std::string_view newSegment)
Carson Labrado1c0bb5c2022-05-18 00:12:52 +0000453{
Ed Tanousd9f466b2023-03-06 15:04:25 -0800454 boost::urls::segments_view urlSegments = urlView.segments();
Carson Labrado1c0bb5c2022-05-18 00:12:52 +0000455 boost::urls::url url("/");
456
457 if (!urlSegments.is_absolute())
458 {
459 return url;
460 }
461
462 boost::urls::segments_view::iterator it = urlSegments.begin();
463 boost::urls::segments_view::iterator end = urlSegments.end();
464
465 for (uint idx = 0; it != end; it++, idx++)
466 {
467 if (idx == replaceLoc)
468 {
469 url.segments().push_back(newSegment);
470 }
471 else
472 {
473 url.segments().push_back(*it);
474 }
475 }
476
477 return url;
478}
479
Ed Tanousa716aa72023-08-01 11:35:53 -0700480inline void setProtocolDefaults(boost::urls::url& url,
481 std::string_view protocol)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800482{
Ed Tanousa716aa72023-08-01 11:35:53 -0700483 if (url.has_scheme())
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800484 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700485 return;
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800486 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700487 if (protocol == "Redfish" || protocol.empty())
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800488 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700489 if (url.port_number() == 443)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800490 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700491 url.set_scheme("https");
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800492 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700493 if (url.port_number() == 80)
494 {
495 if (bmcwebInsecureEnableHttpPushStyleEventing)
496 {
497 url.set_scheme("http");
498 }
499 }
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800500 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700501 else if (protocol == "SNMPv2c")
Chicago Duan3d307082020-11-26 14:12:12 +0800502 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700503 url.set_scheme("snmp");
Chicago Duan3d307082020-11-26 14:12:12 +0800504 }
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800505}
506
Ed Tanousa716aa72023-08-01 11:35:53 -0700507inline void setPortDefaults(boost::urls::url& url)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800508{
509 uint16_t port = url.port_number();
510 if (port != 0)
511 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700512 return;
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800513 }
514
515 // If the user hasn't explicitly stated a port, pick one explicitly for them
516 // based on the protocol defaults
517 if (url.scheme() == "http")
518 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700519 url.set_port_number(80);
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800520 }
521 if (url.scheme() == "https")
522 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700523 url.set_port_number(443);
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800524 }
Chicago Duan3d307082020-11-26 14:12:12 +0800525 if (url.scheme() == "snmp")
526 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700527 url.set_port_number(162);
Chicago Duan3d307082020-11-26 14:12:12 +0800528 }
Ed Tanous11baefe2022-02-09 12:14:12 -0800529}
530
Ed Tanous1abe55e2018-09-05 08:30:59 -0700531} // namespace utility
532} // namespace crow
Ed Tanous71f2db72022-05-25 12:28:09 -0700533
534namespace nlohmann
535{
536template <>
537struct adl_serializer<boost::urls::url>
538{
539 // nlohmann requires a specific casing to look these up in adl
540 // NOLINTNEXTLINE(readability-identifier-naming)
541 static void to_json(json& j, const boost::urls::url& url)
542 {
Ed Tanous079360a2022-06-29 10:05:19 -0700543 j = url.buffer();
Ed Tanous71f2db72022-05-25 12:28:09 -0700544 }
545};
546
547template <>
548struct adl_serializer<boost::urls::url_view>
549{
550 // NOLINTNEXTLINE(readability-identifier-naming)
Ed Tanousd9f466b2023-03-06 15:04:25 -0800551 static void to_json(json& j, boost::urls::url_view url)
Ed Tanous71f2db72022-05-25 12:28:09 -0700552 {
Ed Tanous079360a2022-06-29 10:05:19 -0700553 j = url.buffer();
Ed Tanous71f2db72022-05-25 12:28:09 -0700554 }
555};
556} // namespace nlohmann