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