|
@@ -484,7 +484,7 @@ inline bool duration(std::string_view dur) {
|
|
|
template <typename CharT>
|
|
template <typename CharT>
|
|
|
bool is_invalid_size_or_boundary_hostname(std::basic_string_view<CharT> name) {
|
|
bool is_invalid_size_or_boundary_hostname(std::basic_string_view<CharT> name) {
|
|
|
using delim = detail::char_delimiters<CharT>;
|
|
using delim = detail::char_delimiters<CharT>;
|
|
|
- return (name.empty() || detail::length_u8(name) >= 64 ||
|
|
|
|
|
|
|
+ return (name.empty() || name.length() >= 64 ||
|
|
|
(name.size() >= 4 && name.substr(2).starts_with(delim::illegal_dashes_ulabel)) ||
|
|
(name.size() >= 4 && name.substr(2).starts_with(delim::illegal_dashes_ulabel)) ||
|
|
|
name[0] == '-' || name.back() == '-');
|
|
name[0] == '-' || name.back() == '-');
|
|
|
}
|
|
}
|
|
@@ -508,9 +508,19 @@ template <typename CharT> inline bool hostname_part(std::basic_string_view<CharT
|
|
|
return (decoded != detail::to_u32(name)) && hostname_part<char32_t>(decoded);
|
|
return (decoded != detail::to_u32(name)) && hostname_part<char32_t>(decoded);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // Unfortunately, the ada-idna library does not validate things like
|
|
|
|
|
+ // "is there a HEBREW character after the HEBREW COMMA".
|
|
|
|
|
+ if (not detail::is_special_case_ok(name)) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (name.find_first_of(delim::illegal_hostname_chars) != name.npos) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// An INVALID hostname part is one of the following:
|
|
// An INVALID hostname part is one of the following:
|
|
|
// - empty
|
|
// - empty
|
|
|
- // - more than 63 UTF-8 characters long
|
|
|
|
|
|
|
+ // - more than 63 characters long
|
|
|
// - starts or ends with a '-'
|
|
// - starts or ends with a '-'
|
|
|
// - matches the regular expression /^..--.*$/
|
|
// - matches the regular expression /^..--.*$/
|
|
|
if (is_invalid_size_or_boundary_hostname(name)) {
|
|
if (is_invalid_size_or_boundary_hostname(name)) {
|
|
@@ -529,34 +539,22 @@ template <typename CharT> inline bool hostname_part(std::basic_string_view<CharT
|
|
|
|
|
|
|
|
template <typename CharT> inline bool hostname(std::basic_string_view<CharT> name) {
|
|
template <typename CharT> inline bool hostname(std::basic_string_view<CharT> name) {
|
|
|
using delim = detail::char_delimiters<CharT>;
|
|
using delim = detail::char_delimiters<CharT>;
|
|
|
- if (name.find_first_of(delim::illegal_hostname_chars) != name.npos) {
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // In general, the maximum length of a hostname is 253 UTF-8 characters.
|
|
|
|
|
- if (detail::to_u8(name).size() > (name.back() == '.' ? 254 : 253)) {
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Unfortunately, the ada-idna library does not validate things like
|
|
|
|
|
- // "is there a HEBREW character after the HEBREW COMMA".
|
|
|
|
|
- if (not std::ranges::all_of(delim::special_cases,
|
|
|
|
|
- [name](auto & sc) { return sc.accepts(name); })) {
|
|
|
|
|
|
|
+ // In general, the maximum length of a hostname is 253 characters.
|
|
|
|
|
+ if (name.empty() || name.length() > 253) {
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// We validate each sub-section of the hostname in parts, delimited by '.'
|
|
// We validate each sub-section of the hostname in parts, delimited by '.'
|
|
|
- for (size_t n = name.find('.'); n != std::string::npos;
|
|
|
|
|
- name.remove_prefix(n + 1), n = name.find('.')) {
|
|
|
|
|
|
|
+ for (size_t n = name.find_first_of(delim::hostname_part_delims); n != std::string::npos;
|
|
|
|
|
+ name.remove_prefix(n + 1), n = name.find_first_of(delim::hostname_part_delims)) {
|
|
|
if (not hostname_part(name.substr(0, n))) {
|
|
if (not hostname_part(name.substr(0, n))) {
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // name.empty() would be true only if the final character in the input name
|
|
|
|
|
- // was '.', this is the only empty hostname part that we allow. Otherwise, we
|
|
|
|
|
- // have a trailing hostname_part.
|
|
|
|
|
- return name.empty() || hostname_part(name);
|
|
|
|
|
|
|
+ // Previous test versions allowed for a hostname to end with '.', but this is
|
|
|
|
|
+ // not permitted in the latest test specification.
|
|
|
|
|
+ return hostname_part(name);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
inline bool ipv4(std::string_view ip) {
|
|
inline bool ipv4(std::string_view ip) {
|
|
@@ -669,6 +667,10 @@ template <typename CharT> inline bool email(std::basic_string_view<CharT> em) {
|
|
|
return false;
|
|
return false;
|
|
|
} else if (em.substr(0, n).find(delim::dotdot) != em.npos) {
|
|
} else if (em.substr(0, n).find(delim::dotdot) != em.npos) {
|
|
|
return false;
|
|
return false;
|
|
|
|
|
+ } else if (who.find('@') != em.npos) {
|
|
|
|
|
+ // This will catch multiple emails, but will gracefully ignore quote-escaped
|
|
|
|
|
+ // '@' characters in the name element.
|
|
|
|
|
+ return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// The DOMAIN section of an email address MAY be either a HOSTNAME, or an
|
|
// The DOMAIN section of an email address MAY be either a HOSTNAME, or an
|