7#include <botan/internal/uri.h>
9#include <botan/exceptn.h>
13#if defined(BOTAN_TARGET_OS_HAS_SOCKETS)
14 #include <arpa/inet.h>
15 #include <netinet/in.h>
16 #include <sys/socket.h>
17#elif defined(BOTAN_TARGET_OS_HAS_WINSOCK2)
21#if defined(BOTAN_TARGET_OS_HAS_SOCKETS) || defined(BOTAN_TARGET_OS_HAS_WINSOCK2)
25constexpr bool isdigit(
char ch) {
26 return ch >=
'0' && ch <=
'9';
29bool isDomain(std::string_view domain) {
30 std::string domain_str(domain);
32 R
"(^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$)");
34 return std::regex_match(domain_str.c_str(), m, re);
37bool isIPv4(std::string_view ip) {
38 std::string ip_str(ip);
39 sockaddr_storage inaddr;
40 return !!inet_pton(AF_INET, ip_str.c_str(), &inaddr);
43bool isIPv6(std::string_view ip) {
44 std::string ip_str(ip);
45 sockaddr_storage in6addr;
46 return !!inet_pton(AF_INET6, ip_str.c_str(), &in6addr);
54 const auto port_pos = uri.find(
':');
55 if(port_pos != std::string::npos) {
56 for(
char c : uri.substr(port_pos + 1)) {
58 throw Invalid_Argument(
"invalid");
62 throw Invalid_Argument(
"invalid");
66 const auto domain = uri.substr(0, port_pos);
68 throw Invalid_Argument(
"invalid");
70 if(!isDomain(domain)) {
71 throw Invalid_Argument(
"invalid");
78 const auto port_pos = uri.find(
':');
79 if(port_pos != std::string::npos) {
80 for(
char c : uri.substr(port_pos + 1)) {
82 throw Invalid_Argument(
"invalid");
86 throw Invalid_Argument(
"invalid");
90 const auto ip = uri.substr(0, port_pos);
92 throw Invalid_Argument(
"invalid");
99 const auto port_pos = uri.find(
']');
100 const bool with_braces = (port_pos != std::string::npos);
101 if((uri[0] ==
'[') != with_braces) {
102 throw Invalid_Argument(
"invalid");
105 if(with_braces && (uri.size() > port_pos + 1)) {
106 if(uri[port_pos + 1] !=
':') {
107 throw Invalid_Argument(
"invalid");
109 for(
char c : uri.substr(port_pos + 2)) {
111 throw Invalid_Argument(
"invalid");
115 throw Invalid_Argument(
"invalid");
119 const auto ip = uri.substr((with_braces ? 1 : 0), port_pos - with_braces);
121 throw Invalid_Argument(
"invalid");
127 bool colon_seen =
false;
128 bool non_number =
false;
139 }
else if(!isdigit(c) && c !=
'.') {
144 if(isIPv4(uri.substr(0, uri.find(
':')))) {
153 throw Invalid_Argument(
"not set");
158 return "[" +
host +
"]:" + std::to_string(
port);
160 return host +
":" + std::to_string(
port);
static URI fromIPv4(std::string_view uri)
static URI fromIPv6(std::string_view uri)
static URI fromDomain(std::string_view uri)
std::string to_string() const
static URI fromAny(std::string_view uri)