27
27
#include < limits>
28
28
#include < optional>
29
29
#include < iostream>
30
+ #include < ranges>
30
31
#include < string>
31
32
#include < vector>
32
33
#include < algorithm>
33
34
#include < charconv>
34
35
35
36
#include < fmt/core.h>
36
37
38
+ namespace {
39
+
40
+ bool parseQValue (std::string_view param, double &qValue) {
41
+ #if !defined(__APPLE__)
42
+ auto [ptr, ec] = std::from_chars (param.begin (), param.end (), qValue,
43
+ std::chars_format::fixed);
44
+ return (ec == std::errc () && ptr == param.end ());
45
+ #else
46
+ std::string p (param);
47
+ for (char ch : p) {
48
+ if (!(std::isdigit (ch) || ch == ' .' )) {
49
+ return false ; // Invalid character found
50
+ }
51
+ }
52
+ size_t pos;
53
+ try {
54
+ qValue = std::stod (p, &pos);
55
+ return (pos == p.size ()); // Check if the entire string was consumed
56
+ } catch (const std::exception &) {
57
+ return false ; // Invalid value
58
+ }
59
+ #endif
60
+ }
61
+
62
+ } // namespace
63
+
37
64
AcceptHeader::AcceptHeader (const std::string &header) {
38
65
39
66
acceptedTypes = parse (header);
40
67
41
- std::sort (acceptedTypes. begin (), acceptedTypes. end () ,
68
+ std::ranges:: sort (acceptedTypes,
42
69
[](const AcceptElement &a, const AcceptElement &b) {
43
70
return std::tie (a.q , a.type , a.subtype ) >
44
71
std::tie (b.q , b.type , b.subtype );
@@ -49,8 +76,7 @@ AcceptHeader::AcceptHeader(const std::string &header) {
49
76
}
50
77
51
78
[[nodiscard]] bool AcceptHeader::is_acceptable (mime::type mt) const {
52
- return mapping.find (mt) != mapping.end () ||
53
- mapping.find (mime::type::any_type) != mapping.end ();
79
+ return mapping.contains (mt) || mapping.contains (mime::type::any_type);
54
80
}
55
81
56
82
[[nodiscard]] mime::type AcceptHeader::most_acceptable_of (
@@ -135,17 +161,15 @@ std::vector<AcceptHeader::AcceptElement> AcceptHeader::parse(const std::string &
135
161
}
136
162
137
163
if (param_parts[0 ] == " q" ) {
138
- auto [ptr, ec] = std::from_chars (param_parts[1 ].begin (),
139
- param_parts[1 ].end (),
140
- acceptElement.q ,
141
- std::chars_format::fixed);
142
- if (ec != std::errc () ||
143
- ptr != param_parts[1 ].end () ||
144
- !std::isfinite (acceptElement.q ) ||
145
- acceptElement.q < 0 ||
146
- acceptElement.q > 1 ) {
164
+ if (!parseQValue (param_parts[1 ], acceptElement.q )) {
147
165
throw http::bad_request (" Invalid q parameter value in accept header" );
148
166
}
167
+
168
+ // Check if q is within the valid range [0, 1]
169
+ if (!std::isfinite (acceptElement.q ) || acceptElement.q < 0.0 || acceptElement.q > 1.0 ) {
170
+ throw http::bad_request (" Invalid q parameter value in accept header" );
171
+ }
172
+
149
173
} else {
150
174
acceptElement.params [std::string{param_parts[0 ]}] = std::string{param_parts[1 ]};
151
175
}
0 commit comments