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 | 2349 | url_impl:: | |
29 | construct_authority() const noexcept | ||
30 | { | ||
31 | 2349 | return authority_view(*this); | |
32 | } | ||
33 | |||
34 | } // detail | ||
35 | |||
36 | //------------------------------------------------ | ||
37 | |||
38 | 2349 | authority_view:: | |
39 | authority_view( | ||
40 | 2349 | detail::url_impl const& u) noexcept | |
41 | 2349 | : u_(u) | |
42 | { | ||
43 | 2349 | } | |
44 | |||
45 | //------------------------------------------------ | ||
46 | |||
47 | 23358 | authority_view:: | |
48 | 23358 | ~authority_view() | |
49 | { | ||
50 | 23358 | } | |
51 | |||
52 | 3612 | authority_view:: | |
53 | 3612 | authority_view() noexcept | |
54 | 3612 | : u_(from::authority) | |
55 | { | ||
56 | 3612 | } | |
57 | |||
58 | 2 | authority_view:: | |
59 | authority_view( | ||
60 | 2 | core::string_view s) | |
61 | : authority_view( | ||
62 | 2 | parse_authority(s | |
63 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | ).value(BOOST_URL_POS)) |
64 | { | ||
65 | 2 | } | |
66 | |||
67 | 5718 | authority_view:: | |
68 | authority_view( | ||
69 | authority_view const&) noexcept = default; | ||
70 | |||
71 | authority_view& | ||
72 | 1708 | authority_view:: | |
73 | operator=( | ||
74 | authority_view const&) noexcept = default; | ||
75 | |||
76 | //------------------------------------------------ | ||
77 | // | ||
78 | // Userinfo | ||
79 | // | ||
80 | //------------------------------------------------ | ||
81 | |||
82 | bool | ||
83 | 568 | authority_view:: | |
84 | has_userinfo() const noexcept | ||
85 | { | ||
86 | 568 | auto n = u_.len(id_pass); | |
87 |
2/2✓ Branch 0 taken 476 times.
✓ Branch 1 taken 92 times.
|
568 | if(n == 0) |
88 | 476 | 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 | 52 | authority_view:: | |
96 | encoded_userinfo() const noexcept | ||
97 | { | ||
98 | 52 | auto s = u_.get( | |
99 | id_user, id_host); | ||
100 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 50 times.
|
52 | if(s.empty()) |
101 | 2 | 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 | 50 | 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 | 100 | 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 | 73 | return make_pct_string_view_unsafe( | |
119 | s.data(), | ||
120 | s.size(), | ||
121 | 146 | 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 | 8 | 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 | 49 | return make_pct_string_view_unsafe( | |
163 | 49 | s.data() + 1, | |
164 | 49 | s.size() - 2, | |
165 | 98 | 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 | 7 | authority_view:: | |
197 | encoded_host_address() const noexcept | ||
198 | { | ||
199 | 7 | core::string_view s = u_.get(id_host); | |
200 | std::size_t n; | ||
201 |
2/3✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
7 | switch(u_.host_type_) |
202 | { | ||
203 | 5 | case urls::host_type::name: | |
204 | case urls::host_type::ipv4: | ||
205 | 5 | n = u_.decoded_[id_host]; | |
206 | 5 | break; | |
207 | |||
208 | 2 | case urls::host_type::ipv6: | |
209 | case urls::host_type::ipvfuture: | ||
210 | { | ||
211 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | BOOST_ASSERT( |
212 | u_.decoded_[id_host] == | ||
213 | s.size()); | ||
214 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | BOOST_ASSERT(s.size() >= 2); |
215 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | BOOST_ASSERT(s.front() == '['); |
216 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | BOOST_ASSERT(s.back() == ']'); |
217 | 2 | s = s.substr(1, s.size() - 2); | |
218 | 2 | n = u_.decoded_[id_host] - 2; | |
219 | 2 | break; | |
220 | } | ||
221 | // LCOV_EXCL_START | ||
222 | − | default: | |
223 | case urls::host_type::none: | ||
224 | /* | ||
225 | * This condition is for correctness | ||
226 | * only. | ||
227 | * This should never happen, because | ||
228 | * the `host_rule` will set the host | ||
229 | * type to `name` when it's empty. | ||
230 | * This is correct because `reg-name` | ||
231 | * accepts empty strings. | ||
232 | */ | ||
233 | − | BOOST_ASSERT(s.empty()); | |
234 | − | n = 0; | |
235 | − | break; | |
236 | // LCOV_EXCL_STOP | ||
237 | } | ||
238 | 7 | return make_pct_string_view_unsafe( | |
239 | 7 | s.data(), s.size(), n); | |
240 | } | ||
241 | |||
242 | urls::ipv4_address | ||
243 | 2 | authority_view:: | |
244 | host_ipv4_address() const noexcept | ||
245 | { | ||
246 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if(u_.host_type_ != |
247 | urls::host_type::ipv4) | ||
248 | 1 | return {}; | |
249 | 1 | ipv4_address::bytes_type b{{}}; | |
250 | 1 | std::memcpy( | |
251 | 1 | &b[0], &u_.ip_addr_[0], b.size()); | |
252 | 1 | return urls::ipv4_address(b); | |
253 | } | ||
254 | |||
255 | urls::ipv6_address | ||
256 | 2 | authority_view:: | |
257 | host_ipv6_address() const noexcept | ||
258 | { | ||
259 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if(u_.host_type_ != |
260 | urls::host_type::ipv6) | ||
261 | 1 | return {}; | |
262 | 1 | ipv6_address::bytes_type b{{}}; | |
263 | 1 | std::memcpy( | |
264 | 1 | &b[0], &u_.ip_addr_[0], b.size()); | |
265 | 1 | return urls::ipv6_address(b); | |
266 | } | ||
267 | |||
268 | core::string_view | ||
269 | 2 | authority_view:: | |
270 | host_ipvfuture() const noexcept | ||
271 | { | ||
272 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if(u_.host_type_ != |
273 | urls::host_type::ipvfuture) | ||
274 | 1 | return {}; | |
275 | 1 | core::string_view s = u_.get(id_host); | |
276 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | BOOST_ASSERT(s.size() >= 6); |
277 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | BOOST_ASSERT(s.front() == '['); |
278 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | BOOST_ASSERT(s.back() == ']'); |
279 | 1 | s = s.substr(1, s.size() - 2); | |
280 | 1 | return s; | |
281 | } | ||
282 | |||
283 | pct_string_view | ||
284 | 3 | authority_view:: | |
285 | encoded_host_name() const noexcept | ||
286 | { | ||
287 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
|
3 | if(u_.host_type_ != |
288 | urls::host_type::name) | ||
289 | 1 | return {}; | |
290 | 2 | return u_.pct_get(id_host); | |
291 | } | ||
292 | |||
293 | //------------------------------------------------ | ||
294 | // | ||
295 | // Port | ||
296 | // | ||
297 | //------------------------------------------------ | ||
298 | |||
299 | bool | ||
300 | 567 | authority_view:: | |
301 | has_port() const noexcept | ||
302 | { | ||
303 | 567 | auto const n = u_.len(id_port); | |
304 |
2/2✓ Branch 0 taken 282 times.
✓ Branch 1 taken 285 times.
|
567 | if(n == 0) |
305 | 282 | return false; | |
306 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 285 times.
|
285 | BOOST_ASSERT( |
307 | u_.get(id_port).starts_with(':')); | ||
308 | 285 | return true; | |
309 | } | ||
310 | |||
311 | core::string_view | ||
312 | 112 | authority_view:: | |
313 | port() const noexcept | ||
314 | { | ||
315 | 112 | auto s = u_.get(id_port); | |
316 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 108 times.
|
112 | if(s.empty()) |
317 | 4 | return s; | |
318 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 108 times.
|
108 | BOOST_ASSERT(has_port()); |
319 | 108 | return s.substr(1); | |
320 | } | ||
321 | |||
322 | std::uint16_t | ||
323 | 20 | authority_view:: | |
324 | port_number() const noexcept | ||
325 | { | ||
326 |
3/4✓ Branch 1 taken 4 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
|
20 | BOOST_ASSERT( |
327 | has_port() || | ||
328 | u_.port_number_ == 0); | ||
329 | 20 | return u_.port_number_; | |
330 | } | ||
331 | |||
332 | pct_string_view | ||
333 | 10 | authority_view:: | |
334 | encoded_host_and_port() const noexcept | ||
335 | { | ||
336 | 10 | return u_.get(id_host, id_end); | |
337 | } | ||
338 | |||
339 | //------------------------------------------------ | ||
340 | // | ||
341 | // Parsing | ||
342 | // | ||
343 | //------------------------------------------------ | ||
344 | |||
345 | system::result<authority_view> | ||
346 | 44 | parse_authority( | |
347 | core::string_view s) noexcept | ||
348 | { | ||
349 | 44 | return grammar::parse(s, authority_rule); | |
350 | } | ||
351 | |||
352 | //------------------------------------------------ | ||
353 | // | ||
354 | // Comparisons | ||
355 | // | ||
356 | //------------------------------------------------ | ||
357 | |||
358 | int | ||
359 | 182 | authority_view:: | |
360 | compare(const authority_view& other) const noexcept | ||
361 | { | ||
362 | 182 | auto comp = static_cast<int>(has_userinfo()) - | |
363 | 182 | static_cast<int>(other.has_userinfo()); | |
364 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 181 times.
|
182 | if ( comp != 0 ) |
365 | 1 | return comp; | |
366 | |||
367 |
2/2✓ Branch 1 taken 23 times.
✓ Branch 2 taken 158 times.
|
181 | if (has_userinfo()) |
368 | { | ||
369 | 46 | comp = detail::compare_encoded( | |
370 | 23 | encoded_user(), | |
371 | 23 | other.encoded_user()); | |
372 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 16 times.
|
23 | if ( comp != 0 ) |
373 | 7 | return comp; | |
374 | |||
375 | 16 | comp = static_cast<int>(has_password()) - | |
376 | 16 | static_cast<int>(other.has_password()); | |
377 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 15 times.
|
16 | if ( comp != 0 ) |
378 | 1 | return comp; | |
379 | |||
380 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
15 | if (has_password()) |
381 | { | ||
382 | 30 | comp = detail::compare_encoded( | |
383 | 15 | encoded_password(), | |
384 | 15 | other.encoded_password()); | |
385 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1 times.
|
15 | if ( comp != 0 ) |
386 | 14 | return comp; | |
387 | } | ||
388 | } | ||
389 | |||
390 | 318 | comp = detail::ci_compare_encoded( | |
391 | 159 | encoded_host(), | |
392 | 159 | other.encoded_host()); | |
393 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 142 times.
|
159 | if ( comp != 0 ) |
394 | 17 | return comp; | |
395 | |||
396 | 142 | comp = static_cast<int>(has_port()) - | |
397 | 142 | static_cast<int>(other.has_port()); | |
398 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 135 times.
|
142 | if ( comp != 0 ) |
399 | 7 | return comp; | |
400 | |||
401 |
2/2✓ Branch 1 taken 46 times.
✓ Branch 2 taken 89 times.
|
135 | if (has_port()) |
402 | { | ||
403 | 46 | comp = detail::compare( | |
404 | port(), | ||
405 | other.port()); | ||
406 |
2/2✓ Branch 0 taken 42 times.
✓ Branch 1 taken 4 times.
|
46 | if ( comp != 0 ) |
407 | 42 | return comp; | |
408 | } | ||
409 | |||
410 | 93 | return 0; | |
411 | } | ||
412 | |||
413 | } // urls | ||
414 | } // boost | ||
415 | |||
416 |