12 #include <glog/logging.h>
17 size_t constexpr max_length
= 255;
20 // Normalization Form KC (NFKC) Compatibility Decomposition, followed
21 // by Canonical Composition, see <http://unicode.org/reports/tr15/>
23 std::string
nfkc(std::string_view str
)
25 size_t length
= max_length
;
27 CHECK_LE(str
.length(), max_length
);
28 auto udata
= reinterpret_cast<uint8_t const*>(str
.data());
29 auto ubfr
= reinterpret_cast<uint8_t*>(bfr
);
30 CHECK_NOTNULL(u8_normalize(UNINORM_NFKC
, udata
, str
.size(), ubfr
, &length
));
31 return std::string
{bfr
, length
};
34 bool Domain::validate(std::string_view dom
)
36 if (dom
.length() > max_length
) {
40 // Handle "bare" IP addresses, without the brackets.
41 if (IP::is_address(dom
)) {
45 if (IP::is_address_literal(dom
)) {
49 dom
= remove_trailing_dot(dom
);
51 auto const norm
= nfkc(dom
);
53 // idn2_to_ascii_8z() converts (ASCII) to lower case
56 auto code
= idn2_to_ascii_8z(norm
.c_str(), &ptr
, IDN2_TRANSITIONAL
);
59 std::string
ascii(ptr
);
63 code
= idn2_to_unicode_8z8z(ascii
.c_str(), &ptr
, IDN2_TRANSITIONAL
);
68 // FIXME: check syntax is dot-string?
73 void Domain::set(std::string_view dom
)
75 if (dom
.length() > max_length
) {
76 throw std::invalid_argument("domain name too long");
79 // Handle "bare" IP addresses, without the brackets.
80 if (IP::is_address(dom
)) {
81 ascii_
= IP::to_address_literal(dom
);
83 is_address_literal_
= true;
87 if (IP::is_address_literal(dom
)) {
88 ascii_
= std::string(dom
.data(), dom
.length());
90 is_address_literal_
= true;
94 is_address_literal_
= false;
96 // Since all Domains are fully qualified and not just some bag of
97 // labels, the trailing dot provides no real information and will
98 // mess up name matching on certs and stuff.
100 dom
= remove_trailing_dot(dom
);
102 auto const norm
= nfkc(dom
);
104 // idn2_to_ascii_8z() converts (ASCII) to lower case
107 auto code
= idn2_to_ascii_8z(norm
.c_str(), &ptr
, IDN2_TRANSITIONAL
);
109 throw std::invalid_argument(idn2_strerror(code
));
114 code
= idn2_to_unicode_8z8z(ascii_
.c_str(), &ptr
, IDN2_TRANSITIONAL
);
116 throw std::invalid_argument(idn2_strerror(code
));