Line | Branch | Exec | Source |
---|---|---|---|
1 | // | ||
2 | // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) | ||
3 | // | ||
4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
6 | // | ||
7 | // Official repository: https://github.com/boostorg/url | ||
8 | // | ||
9 | |||
10 | |||
11 | #include <boost/url/detail/config.hpp> | ||
12 | #include <boost/url/authority_view.hpp> | ||
13 | #include "detail/normalize.hpp" | ||
14 | #include <boost/url/grammar/parse.hpp> | ||
15 | #include <boost/url/rfc/authority_rule.hpp> | ||
16 | #include <boost/url/rfc/pct_encoded_rule.hpp> | ||
17 | #include <array> | ||
18 | #include <ostream> | ||
19 | |||
20 | namespace boost { | ||
21 | namespace urls { | ||
22 | |||
23 | //------------------------------------------------ | ||
24 | |||
25 | namespace detail { | ||
26 | |||
27 | authority_view | ||
28 | 2341 | url_impl:: | |
29 | construct_authority() const noexcept | ||
30 | { | ||
31 | 2341 | return authority_view(*this); | |
32 | } | ||
33 | |||
34 | } // detail | ||
35 | |||
36 | //------------------------------------------------ | ||
37 | |||
38 | 2341 | authority_view:: | |
39 | authority_view( | ||
40 | 2341 | detail::url_impl const& u) noexcept | |
41 | 2341 | : u_(u) | |
42 | { | ||
43 | 2341 | } | |
44 | |||
45 | //------------------------------------------------ | ||
46 | |||
47 | 23290 | authority_view:: | |
48 | 23290 | ~authority_view() | |
49 | { | ||
50 | 23290 | } | |
51 | |||
52 | 3605 | authority_view:: | |
53 | 3605 | authority_view() noexcept | |
54 | 3605 | : u_(from::authority) | |
55 | { | ||
56 | 3605 | } | |
57 | |||
58 | 1 | authority_view:: | |
59 | authority_view( | ||
60 | 1 | core::string_view s) | |
61 | : authority_view( | ||
62 | 1 | parse_authority(s | |
63 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | ).value(BOOST_URL_POS)) |
64 | { | ||
65 | 1 | } | |
66 | |||
67 | authority_view:: | ||
68 | authority_view( | ||
69 | authority_view const&) noexcept = default; | ||
70 | |||
71 | authority_view& | ||
72 | authority_view:: | ||
73 | operator=( | ||
74 | authority_view const&) noexcept = default; | ||
75 | |||
76 | //------------------------------------------------ | ||
77 | // | ||
78 | // Userinfo | ||
79 | // | ||
80 | //------------------------------------------------ | ||
81 | |||
82 | bool | ||
83 | 567 | authority_view:: | |
84 | has_userinfo() const noexcept | ||
85 | { | ||
86 | 567 | auto n = u_.len(id_pass); | |
87 |
2/2✓ Branch 0 taken 475 times.
✓ Branch 1 taken 92 times.
|
567 | if(n == 0) |
88 | 475 | return false; | |
89 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 92 times.
|
92 | BOOST_ASSERT(u_.get( |
90 | id_pass).ends_with('@')); | ||
91 | 92 | return true; | |
92 | } | ||
93 | |||
94 | pct_string_view | ||
95 | 50 | authority_view:: | |
96 | encoded_userinfo() const noexcept | ||
97 | { | ||
98 | auto s = u_.get( | ||
99 | 50 | id_user, id_host); | |
100 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
|
50 | if(s.empty()) |
101 | ✗ | return s; | |
102 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
|
50 | BOOST_ASSERT( |
103 | s.ends_with('@')); | ||
104 | 50 | s.remove_suffix(1); | |
105 | return make_pct_string_view_unsafe( | ||
106 | s.data(), | ||
107 | s.size(), | ||
108 | 50 | u_.decoded_[id_user] + | |
109 | 50 | u_.decoded_[id_pass] + | |
110 | 50 | has_password()); | |
111 | } | ||
112 | |||
113 | pct_string_view | ||
114 | 73 | authority_view:: | |
115 | encoded_user() const noexcept | ||
116 | { | ||
117 | 73 | auto s = u_.get(id_user); | |
118 | return make_pct_string_view_unsafe( | ||
119 | s.data(), | ||
120 | s.size(), | ||
121 | 73 | u_.decoded_[id_user]); | |
122 | } | ||
123 | |||
124 | bool | ||
125 | 112 | authority_view:: | |
126 | has_password() const noexcept | ||
127 | { | ||
128 | 112 | auto const n = u_.len(id_pass); | |
129 |
2/2✓ Branch 0 taken 79 times.
✓ Branch 1 taken 33 times.
|
112 | if(n > 1) |
130 | { | ||
131 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 79 times.
|
79 | BOOST_ASSERT(u_.get(id_pass |
132 | ).starts_with(':')); | ||
133 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 79 times.
|
79 | BOOST_ASSERT(u_.get(id_pass |
134 | ).ends_with('@')); | ||
135 | 79 | return true; | |
136 | } | ||
137 |
2/4✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 33 times.
|
33 | BOOST_ASSERT(n == 0 || u_.get( |
138 | id_pass).ends_with('@')); | ||
139 | 33 | return false; | |
140 | } | ||
141 | |||
142 | pct_string_view | ||
143 | 57 | authority_view:: | |
144 | encoded_password() const noexcept | ||
145 | { | ||
146 | 57 | auto s = u_.get(id_pass); | |
147 |
2/3✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
|
57 | switch(s.size()) |
148 | { | ||
149 | 8 | case 1: | |
150 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | BOOST_ASSERT( |
151 | s.starts_with('@')); | ||
152 | 8 | s.remove_prefix(1); | |
153 | BOOST_FALLTHROUGH; | ||
154 | 8 | case 0: | |
155 | return make_pct_string_view_unsafe( | ||
156 | 8 | s.data(), s.size(), 0); | |
157 | 49 | default: | |
158 | 49 | break; | |
159 | } | ||
160 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
|
49 | BOOST_ASSERT(s.ends_with('@')); |
161 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
|
49 | BOOST_ASSERT(s.starts_with(':')); |
162 | return make_pct_string_view_unsafe( | ||
163 | 49 | s.data() + 1, | |
164 | 49 | s.size() - 2, | |
165 | 49 | u_.decoded_[id_pass]); | |
166 | } | ||
167 | |||
168 | //------------------------------------------------ | ||
169 | // | ||
170 | // Host | ||
171 | // | ||
172 | //------------------------------------------------ | ||
173 | /* | ||
174 | host_type host_type() // ipv4, ipv6, ipvfuture, name | ||
175 | |||
176 | std::string host() // return encoded_host().decode() | ||
177 | pct_string_view encoded_host() // return host part, as-is | ||
178 | std::string host_address() // return encoded_host_address().decode() | ||
179 | pct_string_view encoded_host_address() // ipv4, ipv6, ipvfut, or encoded name, no brackets | ||
180 | |||
181 | ipv4_address host_ipv4_address() // return ipv4_address or {} | ||
182 | ipv6_address host_ipv6_address() // return ipv6_address or {} | ||
183 | core::string_view host_ipvfuture() // return ipvfuture or {} | ||
184 | std::string host_name() // return decoded name or "" | ||
185 | pct_string_view encoded_host_name() // return encoded host name or "" | ||
186 | */ | ||
187 | |||
188 | pct_string_view | ||
189 | 330 | authority_view:: | |
190 | encoded_host() const noexcept | ||
191 | { | ||
192 | 330 | return u_.pct_get(id_host); | |
193 | } | ||
194 | |||
195 | pct_string_view | ||
196 | ✗ | authority_view:: | |
197 | encoded_host_address() const noexcept | ||
198 | { | ||
199 | ✗ | core::string_view s = u_.get(id_host); | |
200 | std::size_t n; | ||
201 | ✗ | switch(u_.host_type_) | |
202 | { | ||
203 | ✗ | default: | |
204 | case urls::host_type::none: | ||
205 | ✗ | BOOST_ASSERT(s.empty()); | |
206 | ✗ | n = 0; | |
207 | ✗ | break; | |
208 | |||
209 | ✗ | case urls::host_type::name: | |
210 | case urls::host_type::ipv4: | ||
211 | ✗ | n = u_.decoded_[id_host]; | |
212 | ✗ | break; | |
213 | |||
214 | ✗ | case urls::host_type::ipv6: | |
215 | case urls::host_type::ipvfuture: | ||
216 | { | ||
217 | ✗ | BOOST_ASSERT( | |
218 | u_.decoded_[id_host] == | ||
219 | s.size()); | ||
220 | ✗ | BOOST_ASSERT(s.size() >= 2); | |
221 | ✗ | BOOST_ASSERT(s.front() == '['); | |
222 | ✗ | BOOST_ASSERT(s.back() == ']'); | |
223 | ✗ | s = s.substr(1, s.size() - 2); | |
224 | ✗ | n = u_.decoded_[id_host] - 2; | |
225 | ✗ | break; | |
226 | } | ||
227 | } | ||
228 | return make_pct_string_view_unsafe( | ||
229 | ✗ | s.data(), s.size(), n); | |
230 | } | ||
231 | |||
232 | urls::ipv4_address | ||
233 | 2 | authority_view:: | |
234 | host_ipv4_address() const noexcept | ||
235 | { | ||
236 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if(u_.host_type_ != |
237 | urls::host_type::ipv4) | ||
238 | 1 | return {}; | |
239 | 1 | ipv4_address::bytes_type b{{}}; | |
240 | 1 | std::memcpy( | |
241 | 1 | &b[0], &u_.ip_addr_[0], b.size()); | |
242 | 1 | return urls::ipv4_address(b); | |
243 | } | ||
244 | |||
245 | urls::ipv6_address | ||
246 | 2 | authority_view:: | |
247 | host_ipv6_address() const noexcept | ||
248 | { | ||
249 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if(u_.host_type_ != |
250 | urls::host_type::ipv6) | ||
251 | 1 | return {}; | |
252 | 1 | ipv6_address::bytes_type b{{}}; | |
253 | 1 | std::memcpy( | |
254 | 1 | &b[0], &u_.ip_addr_[0], b.size()); | |
255 | 1 | return urls::ipv6_address(b); | |
256 | } | ||
257 | |||
258 | core::string_view | ||
259 | 2 | authority_view:: | |
260 | host_ipvfuture() const noexcept | ||
261 | { | ||
262 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if(u_.host_type_ != |
263 | urls::host_type::ipvfuture) | ||
264 | 1 | return {}; | |
265 | 1 | core::string_view s = u_.get(id_host); | |
266 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | BOOST_ASSERT(s.size() >= 6); |
267 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | BOOST_ASSERT(s.front() == '['); |
268 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | BOOST_ASSERT(s.back() == ']'); |
269 | 1 | s = s.substr(1, s.size() - 2); | |
270 | 1 | return s; | |
271 | } | ||
272 | |||
273 | pct_string_view | ||
274 | ✗ | authority_view:: | |
275 | encoded_host_name() const noexcept | ||
276 | { | ||
277 | ✗ | if(u_.host_type_ != | |
278 | urls::host_type::name) | ||
279 | ✗ | return {}; | |
280 | ✗ | return u_.pct_get(id_host); | |
281 | } | ||
282 | |||
283 | //------------------------------------------------ | ||
284 | // | ||
285 | // Port | ||
286 | // | ||
287 | //------------------------------------------------ | ||
288 | |||
289 | bool | ||
290 | 567 | authority_view:: | |
291 | has_port() const noexcept | ||
292 | { | ||
293 | 567 | auto const n = u_.len(id_port); | |
294 |
2/2✓ Branch 0 taken 282 times.
✓ Branch 1 taken 285 times.
|
567 | if(n == 0) |
295 | 282 | return false; | |
296 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 285 times.
|
285 | BOOST_ASSERT( |
297 | u_.get(id_port).starts_with(':')); | ||
298 | 285 | return true; | |
299 | } | ||
300 | |||
301 | core::string_view | ||
302 | 112 | authority_view:: | |
303 | port() const noexcept | ||
304 | { | ||
305 | 112 | auto s = u_.get(id_port); | |
306 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 108 times.
|
112 | if(s.empty()) |
307 | 4 | return s; | |
308 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 108 times.
|
108 | BOOST_ASSERT(has_port()); |
309 | 108 | return s.substr(1); | |
310 | } | ||
311 | |||
312 | std::uint16_t | ||
313 | 20 | authority_view:: | |
314 | port_number() const noexcept | ||
315 | { | ||
316 |
3/4✓ Branch 1 taken 4 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
|
20 | BOOST_ASSERT( |
317 | has_port() || | ||
318 | u_.port_number_ == 0); | ||
319 | 20 | return u_.port_number_; | |
320 | } | ||
321 | |||
322 | pct_string_view | ||
323 | 10 | authority_view:: | |
324 | encoded_host_and_port() const noexcept | ||
325 | { | ||
326 | 10 | return u_.get(id_host, id_end); | |
327 | } | ||
328 | |||
329 | //------------------------------------------------ | ||
330 | // | ||
331 | // Parsing | ||
332 | // | ||
333 | //------------------------------------------------ | ||
334 | |||
335 | system::result<authority_view> | ||
336 | 42 | parse_authority( | |
337 | core::string_view s) noexcept | ||
338 | { | ||
339 | 42 | return grammar::parse(s, authority_rule); | |
340 | } | ||
341 | |||
342 | //------------------------------------------------ | ||
343 | // | ||
344 | // Comparisons | ||
345 | // | ||
346 | //------------------------------------------------ | ||
347 | |||
348 | int | ||
349 | 182 | authority_view:: | |
350 | compare(const authority_view& other) const noexcept | ||
351 | { | ||
352 | 182 | auto comp = static_cast<int>(has_userinfo()) - | |
353 | 182 | static_cast<int>(other.has_userinfo()); | |
354 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 181 times.
|
182 | if ( comp != 0 ) |
355 | 1 | return comp; | |
356 | |||
357 |
2/2✓ Branch 1 taken 23 times.
✓ Branch 2 taken 158 times.
|
181 | if (has_userinfo()) |
358 | { | ||
359 | 46 | comp = detail::compare_encoded( | |
360 | 23 | encoded_user(), | |
361 | 23 | other.encoded_user()); | |
362 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 16 times.
|
23 | if ( comp != 0 ) |
363 | 7 | return comp; | |
364 | |||
365 | 16 | comp = static_cast<int>(has_password()) - | |
366 | 16 | static_cast<int>(other.has_password()); | |
367 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 15 times.
|
16 | if ( comp != 0 ) |
368 | 1 | return comp; | |
369 | |||
370 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
15 | if (has_password()) |
371 | { | ||
372 | 30 | comp = detail::compare_encoded( | |
373 | 15 | encoded_password(), | |
374 | 15 | other.encoded_password()); | |
375 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1 times.
|
15 | if ( comp != 0 ) |
376 | 14 | return comp; | |
377 | } | ||
378 | } | ||
379 | |||
380 | 318 | comp = detail::ci_compare_encoded( | |
381 | 159 | encoded_host(), | |
382 | 159 | other.encoded_host()); | |
383 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 142 times.
|
159 | if ( comp != 0 ) |
384 | 17 | return comp; | |
385 | |||
386 | 142 | comp = static_cast<int>(has_port()) - | |
387 | 142 | static_cast<int>(other.has_port()); | |
388 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 135 times.
|
142 | if ( comp != 0 ) |
389 | 7 | return comp; | |
390 | |||
391 |
2/2✓ Branch 1 taken 46 times.
✓ Branch 2 taken 89 times.
|
135 | if (has_port()) |
392 | { | ||
393 | 46 | comp = detail::compare( | |
394 | port(), | ||
395 | other.port()); | ||
396 |
2/2✓ Branch 0 taken 42 times.
✓ Branch 1 taken 4 times.
|
46 | if ( comp != 0 ) |
397 | 42 | return comp; | |
398 | } | ||
399 | |||
400 | 93 | return 0; | |
401 | } | ||
402 | |||
403 | } // urls | ||
404 | } // boost | ||
405 | |||
406 |