Botan 3.13.0
Crypto and TLS for C&
Botan::URI::Authority Class Referencefinal

#include <uri.h>

Public Types

using Host = std::variant<DNSName, IPv4Address, IPv6Address>
enum class  HostKind : uint8_t { DNS = 0 , IPv4 = 1 , IPv6 = 2 }

Public Member Functions

const Hosthost () const
HostKind host_kind () const
std::string host_to_string () const
std::strong_ordering operator<=> (const Authority &other) const
bool operator== (const Authority &other) const
const std::string & original_input () const
std::optional< uint16_t > port () const
const std::optional< std::string > & userinfo () const

Static Public Member Functions

static std::optional< Authority > from_string (std::string_view raw)

Detailed Description

The optional authority component of a URI: a validated DNS name, IPv4 literal, or IPv6 literal, with an optional port.

Definition at line 31 of file uri.h.

Member Typedef Documentation

◆ Host

A validated DNS name, or a literal IPv4 or IPv6 address.

Definition at line 36 of file uri.h.

Member Enumeration Documentation

◆ HostKind

enum class Botan::URI::Authority::HostKind : uint8_t
strong

Tag for the alternative held by Host.

Enumerator
DNS 
IPv4 
IPv6 

Definition at line 41 of file uri.h.

41 : uint8_t {
42 DNS = 0,
43 IPv4 = 1,
44 IPv6 = 2,
45 };

Member Function Documentation

◆ from_string()

std::optional< URI::Authority > Botan::URI::Authority::from_string ( std::string_view raw)
static

Parse a bare authority "host[:port]" or "[ipv6][:port]". Returns nullopt for any parse failure.

Definition at line 248 of file uri.cpp.

248 {
249 if(raw.empty()) {
250 return {};
251 }
252
253 // Capture the full input now; the userinfo prefix is stripped from
254 // `raw` below, and m_raw must reflect the original
255 const std::string original_input(raw);
256
257 /*
258 RFC 3986
259 userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
260
261 Thus a unencoded '@' is not allowed inside userinfo, and the single '@' splits the
262 username from the authority. The @ being present at all is significant; an empty
263 userinfo ("https://@example.com/") is distinct from no userinfo at all.
264 */
265 std::optional<std::string> userinfo;
266 const auto first_at = raw.find('@');
267 if(first_at != std::string_view::npos) {
268 if(raw.find('@', first_at + 1) != std::string_view::npos) {
269 return {};
270 }
271 const auto userinfo_view = raw.substr(0, first_at);
272 if(!validate_userinfo(userinfo_view)) {
273 return {};
274 }
275 userinfo = std::string(userinfo_view);
276 raw.remove_prefix(first_at + 1);
277 }
278
279 std::string_view host_view;
280 std::string_view port_str;
281 std::optional<Host> host;
282
283 if(!raw.empty() && raw.front() == '[') {
284 // Bracketed IPv6 literal.
285 const auto close = raw.find(']');
286 if(close == std::string_view::npos) {
287 return {};
288 }
289 host_view = raw.substr(1, close - 1);
290 if(host_view.empty()) {
291 return {};
292 }
293 const auto after = raw.substr(close + 1);
294 if(!after.empty()) {
295 if(after.front() != ':') {
296 return {};
297 }
298 port_str = after.substr(1);
299 }
300 auto ipv6 = IPv6Address::from_string(host_view);
301 if(!ipv6.has_value()) {
302 return {};
303 }
304 host = *ipv6;
305 } else {
306 // host[:port] with no brackets. Only one ':' is allowed (port).
307 const auto colon = raw.find(':');
308 if(colon == std::string_view::npos) {
309 host_view = raw;
310 } else {
311 host_view = raw.substr(0, colon);
312 port_str = raw.substr(colon + 1);
313
314 // Verify the `:` char is the only one that appears
315 if(port_str.find(':') != std::string::npos) {
316 return {};
317 }
318 }
319
320 if(host_view.empty()) {
321 return {};
322 }
323
324 // Technically valid per RFC 3986 but likely not something we want to support
325 if(host_view.ends_with('.')) {
326 return {};
327 }
328
329 if(auto ipv4 = IPv4Address::from_string(host_view)) {
330 host = *ipv4;
331 } else if(auto dns = DNSName::from_string(host_view)) {
332 host = std::move(*dns);
333 } else {
334 return {};
335 }
336 }
337
338 std::optional<uint16_t> port;
339
340 if(!port_str.empty()) {
341 port = parse_port(port_str);
342 if(!port.has_value()) {
343 return {};
344 }
345 }
346
347 return Authority(original_input, std::move(userinfo), std::move(*host), port);
348}
static std::optional< DNSName > from_string(std::string_view name)
Definition dns_name.cpp:136
static std::optional< IPv4Address > from_string(std::string_view str)
static std::optional< IPv6Address > from_string(std::string_view str)
const std::optional< std::string > & userinfo() const
Definition uri.h:87
const Host & host() const
Definition uri.h:56
std::optional< uint16_t > port() const
Definition uri.h:74
const std::string & original_input() const
Definition uri.h:79

References Botan::DNSName::from_string(), Botan::IPv4Address::from_string(), Botan::IPv6Address::from_string(), host(), original_input(), Botan::URI::original_input(), port(), and userinfo().

Referenced by Botan::URI::from_string(), and Botan::OS::open_socket_udp().

◆ host()

const Host & Botan::URI::Authority::host ( ) const
inline

Parsed host: a DNS name, an IPv4 literal, or an IPv6 literal.

Definition at line 56 of file uri.h.

56{ return m_host; }

Referenced by from_string().

◆ host_kind()

URI::Authority::HostKind Botan::URI::Authority::host_kind ( ) const

Which alternative of host() is held.

Definition at line 354 of file uri.cpp.

354 {
355 if(std::holds_alternative<DNSName>(m_host)) {
356 return HostKind::DNS;
357 } else if(std::holds_alternative<IPv4Address>(m_host)) {
358 return HostKind::IPv4;
359 } else if(std::holds_alternative<IPv6Address>(m_host)) {
360 return HostKind::IPv6;
361 } else {
363 }
364}
#define BOTAN_ASSERT_UNREACHABLE()
Definition assert.h:166

References BOTAN_ASSERT_UNREACHABLE.

◆ host_to_string()

std::string Botan::URI::Authority::host_to_string ( ) const

The host as a string: DNS names and dotted-IPv4 literals are returned verbatim; IPv6 literals are returned without surrounding brackets. Lowercased for DNS / IPv4; the IPv6 form is whatever IPv6Address::to_string produces.

Definition at line 350 of file uri.cpp.

350 {
351 return std::visit([](const auto& h) -> std::string { return h.to_string(); }, m_host);
352}

◆ operator<=>()

std::strong_ordering Botan::URI::Authority::operator<=> ( const Authority & other) const

Order two authorities

Parameters
otherthe authority to compare against
Returns
the ordering of this authority relative to other

Definition at line 146 of file uri.cpp.

146 =>(const URI::Authority& other) const {
147 /*
148 Userinfo is compared without normalization; RFC 3986 6.2.2.1:
149 When a URI uses components of the generic syntax, the component
150 syntax equivalence rules always apply; namely, that the scheme
151 and host are case-insensitive and therefore should be normalized
152 to lowercase. ... The other generic syntax components are assumed
153 to be case-sensitive unless specifically defined otherwise by the
154 scheme.
155 */
156 return std::tie(m_userinfo, m_host, m_port) <=> std::tie(other.m_userinfo, other.m_host, other.m_port);
157}

◆ operator==()

bool Botan::URI::Authority::operator== ( const Authority & other) const

Compare two authorities

Parameters
otherthe authority to compare against
Returns
true if the two authorities are equal

Definition at line 159 of file uri.cpp.

159 {
160 return m_userinfo == other.m_userinfo && m_host == other.m_host && m_port == other.m_port;
161}

◆ original_input()

const std::string & Botan::URI::Authority::original_input ( ) const
inline

The original input that was parsed

Definition at line 79 of file uri.h.

79{ return m_raw; }

Referenced by from_string().

◆ port()

std::optional< uint16_t > Botan::URI::Authority::port ( ) const
inline

Port if present; nullopt otherwise.

Definition at line 74 of file uri.h.

74{ return m_port; }

Referenced by from_string().

◆ userinfo()

const std::optional< std::string > & Botan::URI::Authority::userinfo ( ) const
inline

The userinfo component, preserved verbatim (no case normalization or pct-decoding) and compared verbatim for identity. nullopt if no "@" was present; present-but-empty (e.g. "https://@example.com/") is distinguished from absent.

Definition at line 87 of file uri.h.

87{ return m_userinfo; }

Referenced by from_string().


The documentation for this class was generated from the following files: