mirror of
https://github.com/pocoproject/poco.git
synced 2025-01-19 00:46:03 +01:00
IDN testsuite and fixes
This commit is contained in:
parent
c74af100b5
commit
c17c569d13
@ -32,7 +32,17 @@ class Net_API DNS
|
||||
/// This class provides an interface to the
|
||||
/// domain name service.
|
||||
///
|
||||
/// An internal DNS cache is used to speed up name lookups.
|
||||
/// Starting with POCO C++ Libraries release 1.9.0,
|
||||
/// this class also supports Internationalized Domain Names (IDNs).
|
||||
///
|
||||
/// Regarding IDNs, the following rules apply:
|
||||
///
|
||||
/// * An IDN passed to hostByName() must be encoded manually, by calling
|
||||
/// encodeIDN() (after testing with isIDN() first).
|
||||
/// * An UTF-8 IDN passed to resolve() or resolveOne() is automatically encoded.
|
||||
/// * IDNs returned in HostEntry objects are never decoded. They can be
|
||||
/// decoded by calling decodeIDN() (after testing for an encoded IDN by
|
||||
/// calling isEncodedIDN()).
|
||||
{
|
||||
public:
|
||||
enum HintFlag
|
||||
@ -60,6 +70,9 @@ public:
|
||||
/// for the host with the given name. HintFlag argument is only
|
||||
/// used on platforms that have getaddrinfo().
|
||||
///
|
||||
/// Note that Internationalized Domain Names must be encoded
|
||||
/// using Punycode (see encodeIDN()) before calling this method.
|
||||
///
|
||||
/// Throws a HostNotFoundException if a host with the given
|
||||
/// name cannot be found.
|
||||
///
|
||||
@ -93,8 +106,8 @@ public:
|
||||
/// for the host with the given IP address or host name.
|
||||
///
|
||||
/// If address contains a UTF-8 encoded IDN (internationalized
|
||||
/// domain name), the domain name will be encoded first according
|
||||
/// to Punycode.
|
||||
/// domain name), the domain name will be encoded first using
|
||||
/// Punycode.
|
||||
///
|
||||
/// Throws a HostNotFoundException if a host with the given
|
||||
/// name cannot be found.
|
||||
|
@ -164,9 +164,18 @@ HostEntry DNS::resolve(const std::string& address)
|
||||
{
|
||||
IPAddress ip;
|
||||
if (IPAddress::tryParse(address, ip))
|
||||
{
|
||||
return hostByAddress(ip);
|
||||
}
|
||||
else if (isIDN(address))
|
||||
{
|
||||
std::string encoded = encodeIDN(address);
|
||||
return hostByName(encoded);
|
||||
}
|
||||
else
|
||||
{
|
||||
return hostByName(address);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -235,11 +244,16 @@ std::string DNS::encodeIDN(const std::string& idn)
|
||||
while (it != end)
|
||||
{
|
||||
std::string label;
|
||||
bool mustEncode = false;
|
||||
while (it != end && *it != '.')
|
||||
{
|
||||
if (static_cast<unsigned char>(*it) >= 0x80) mustEncode = true;
|
||||
label += *it++;
|
||||
}
|
||||
encoded += encodeIDNLabel(label);
|
||||
if (mustEncode)
|
||||
encoded += encodeIDNLabel(label);
|
||||
else
|
||||
encoded += label;
|
||||
if (it != end) encoded += *it++;
|
||||
}
|
||||
return encoded;
|
||||
@ -258,10 +272,7 @@ std::string DNS::decodeIDN(const std::string& encodedIDN)
|
||||
{
|
||||
label += *it++;
|
||||
}
|
||||
if (label.compare(0, 4, "xn--") == 0)
|
||||
decoded += decodeIDNLabel(label);
|
||||
else
|
||||
decoded += label;
|
||||
decoded += decodeIDNLabel(label);
|
||||
if (it != end) decoded += *it++;
|
||||
}
|
||||
return decoded;
|
||||
@ -289,8 +300,8 @@ std::string DNS::encodeIDNLabel(const std::string& label)
|
||||
char buffer[64];
|
||||
std::size_t size = 64;
|
||||
int rc = punycode_encode(uniLabel.size(), &uniLabel[0], &size, buffer);
|
||||
if (rc > 0)
|
||||
return encoded.append(buffer, size);
|
||||
if (rc == punycode_success)
|
||||
encoded.append(buffer, size);
|
||||
else
|
||||
throw DNSException("Failed to encode IDN label", label);
|
||||
return encoded;
|
||||
@ -305,12 +316,12 @@ std::string DNS::decodeIDNLabel(const std::string& encodedIDN)
|
||||
std::size_t size = 64;
|
||||
punycode_uint buffer[64];
|
||||
int rc = punycode_decode(encodedIDN.size() - 4, encodedIDN.data() + 4, &size, buffer);
|
||||
if (rc > 0)
|
||||
if (rc == punycode_success)
|
||||
{
|
||||
Poco::UTF32Encoding utf32;
|
||||
Poco::UTF8Encoding utf8;
|
||||
Poco::TextConverter converter(utf32, utf8);
|
||||
converter.convert(buffer, size*rc, decoded);
|
||||
converter.convert(buffer, size*sizeof(punycode_uint), decoded);
|
||||
}
|
||||
else throw DNSException("Failed to decode IDN label: ", encodedIDN);
|
||||
}
|
||||
@ -394,7 +405,7 @@ void DNS::aierror(int code, const std::string& arg)
|
||||
2018-02-17 with SHA-1 a966a8017f6be579d74a50a226accc7607c40133
|
||||
labeled punycode-spec 1.0.3 (2006-Mar-23-Thu).
|
||||
|
||||
Modified for POCO C++ Libraries by Günter Obiltschnig.
|
||||
Modified for POCO C++ Libraries by Guenter Obiltschnig.
|
||||
|
||||
License on the original code:
|
||||
|
||||
@ -526,8 +537,8 @@ int punycode_encode(size_t input_length_orig, const punycode_uint input[], size_
|
||||
if (max_out - out < 2) return punycode_big_output;
|
||||
output[out++] = (char) input[j];
|
||||
}
|
||||
/* else if (input[j] < n) return punycode_bad_input; */
|
||||
/* (not needed for Punycode with unsigned code points) */
|
||||
/* else if (input[j] < n) return punycode_bad_input; */
|
||||
/* (not needed for Punycode with unsigned code points) */
|
||||
}
|
||||
|
||||
h = b = (punycode_uint) out;
|
||||
|
@ -93,14 +93,89 @@ void DNSTest::testResolve()
|
||||
|
||||
void DNSTest::testEncodeIDN()
|
||||
{
|
||||
std::string idn("d\xc3\xb6m\xc3\xa4in.example"); // domain.example with umlauts
|
||||
std::string idn("d\xc3\xb6m\xc3\xa4in.example"); // d"om"ain.example
|
||||
assert (DNS::isIDN(idn));
|
||||
assert (DNS::encodeIDN(idn) == "xn--dmin-moa0i.example");
|
||||
|
||||
idn = ".d\xc3\xb6m\xc3\xa4in.example"; // .d"om"ain.example
|
||||
assert(DNS::isIDN(idn));
|
||||
assert(DNS::encodeIDN(idn) == ".xn--dmin-moa0i.example");
|
||||
|
||||
idn = "d\xc3\xb6m\xc3\xa4in.example."; // .d"om"ain.example.
|
||||
assert(DNS::isIDN(idn));
|
||||
assert(DNS::encodeIDN(idn) == "xn--dmin-moa0i.example.");
|
||||
|
||||
idn = "d\xc3\xb6m\xc3\xa4in"; // d"om"ain
|
||||
assert(DNS::isIDN(idn));
|
||||
assert(DNS::encodeIDN(idn) == "xn--dmin-moa0i");
|
||||
|
||||
idn = "\xc3\xa4""aaa.example"; // "aaaa.example
|
||||
assert (DNS::isIDN(idn));
|
||||
assert (DNS::encodeIDN(idn) == "xn--aaa-pla.example");
|
||||
|
||||
idn = "a\xc3\xa4""aa.example"; // a"aaa.example
|
||||
assert(DNS::isIDN(idn));
|
||||
assert(DNS::encodeIDN(idn) == "xn--aaa-qla.example");
|
||||
|
||||
idn = "foo.\xc3\xa2""bcd\xc3\xa9""f.example"; // foo.^abcd'ef.example
|
||||
assert(DNS::isIDN(idn));
|
||||
assert(DNS::encodeIDN(idn) == "foo.xn--bcdf-9na9b.example");
|
||||
|
||||
idn = "\xe2\x98\x83.example"; // <snowman>.example
|
||||
assert(DNS::isIDN(idn));
|
||||
assert(DNS::encodeIDN(idn) == "xn--n3h.example");
|
||||
|
||||
idn = "\xe2\x98\x83."; // <snowman>.
|
||||
assert(DNS::isIDN(idn));
|
||||
assert(DNS::encodeIDN(idn) == "xn--n3h.");
|
||||
|
||||
idn = "\xe2\x98\x83"; // <snowman>
|
||||
assert(DNS::isIDN(idn));
|
||||
assert(DNS::encodeIDN(idn) == "xn--n3h");
|
||||
|
||||
std::string dn = "www.pocoproject.org";
|
||||
assert (!DNS::isIDN(dn));
|
||||
assert (DNS::encodeIDN(dn) == "www.pocoproject.org");
|
||||
}
|
||||
|
||||
|
||||
void DNSTest::testDecodeIDN()
|
||||
{
|
||||
std::string enc("xn--dmin-moa0i.example");
|
||||
assert (DNS::isEncodedIDN(enc));
|
||||
assert (DNS::decodeIDN(enc) == "d\xc3\xb6m\xc3\xa4in.example"); // d"om"ain.example
|
||||
|
||||
enc = ".xn--dmin-moa0i.example";
|
||||
assert(DNS::isEncodedIDN(enc));
|
||||
assert(DNS::decodeIDN(enc) == ".d\xc3\xb6m\xc3\xa4in.example"); // .d"om"ain.example
|
||||
|
||||
enc = "xn--dmin-moa0i.example.";
|
||||
assert(DNS::isEncodedIDN(enc));
|
||||
assert(DNS::decodeIDN(enc) == "d\xc3\xb6m\xc3\xa4in.example."); // d"om"ain.example.
|
||||
|
||||
enc = "xn--dmin-moa0i";
|
||||
assert(DNS::isEncodedIDN(enc));
|
||||
assert(DNS::decodeIDN(enc) == "d\xc3\xb6m\xc3\xa4in"); // d"om"ain
|
||||
|
||||
enc = "foo.xn--bcdf-9na9b.example";
|
||||
assert (DNS::isEncodedIDN(enc));
|
||||
assert (DNS::decodeIDN(enc) == "foo.\xc3\xa2""bcd\xc3\xa9""f.example"); // foo.^abcd'ef.example
|
||||
|
||||
enc = "xn--n3h.example";
|
||||
assert (DNS::isEncodedIDN(enc));
|
||||
assert (DNS::decodeIDN(enc) == "\xe2\x98\x83.example"); // <snowman>.example
|
||||
|
||||
enc = "xn--n3h.";
|
||||
assert(DNS::isEncodedIDN(enc));
|
||||
assert(DNS::decodeIDN(enc) == "\xe2\x98\x83."); // <snowman>.
|
||||
|
||||
enc = "xn--n3h";
|
||||
assert(DNS::isEncodedIDN(enc));
|
||||
assert(DNS::decodeIDN(enc) == "\xe2\x98\x83"); // <snowman>
|
||||
|
||||
std::string dn = "www.pocoproject.org";
|
||||
assert (!DNS::isEncodedIDN(dn));
|
||||
assert (DNS::decodeIDN(dn) == "www.pocoproject.org");
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user