/* * Validates the syntax of hostnames, ipv4-, and ipv6-addresses. * Returns an empty string on success, non-empty on failure. * * TODO: Implement support for internationalized domain names. */ const std::string util::valid_addr(const std::experimental::string_view &addr) { if (!valid_ipv46_addr(addr)) { if (string_contains(addr, ipv6_sep)) return "invalid ipv6 address."; if (addr.length() > addr_max_length) return "the address is too long; it's illegal to exceed 255 characters."; /* * Split the hostname into its multiple sub-domains * (seperated by periods) and check them. */ std::vector<std::string> tokens = split_string(addr, period); for (const std::experimental::string_view &s: tokens) { /* * In case of "irc..hostname.tld", where the token between '..', * would be empty. */ if (s.empty()) return "a token is empty; does the address contain \"..\" somewhere?"; /* Also as per RFC 1035. */ if (s.front() == hyphen || s.back() == hyphen) { std::string element = s.data(); return "first or last character in the element \"" + element + "\" is a hyphen; that's not allowed."; } /* * O̶n̶l̶y̶ ̶[̶A̶-̶Z̶a̶-̶z̶0̶-̶9̶]̶ ̶a̶r̶e̶ ̶a̶l̶l̶o̶w̶e̶d̶.̶ * Okey, no. International domain names is a thing: * <https://en.wikipedia.org/wiki/Domain_name> * * s[first] and s[last] are checked again, but they * must be checked for non-[A-Za-z0-9], anyway. A check for * periods could be implemented here, but then we'd lose a specified * error message and we'd need more checks than what we remove. */ if (std::find_if(s.begin(), s.end(), [](char c) { return !std::isdigit(c) && !std::isalpha(c) && c != hyphen; }) != s.end()) { std::string element = s.data(); return "the element \"" + element + "\" contains an illegal character (not a [A-Za-z0-9\\-])."; } } } return ""; }