resolved add dns_name_apply_idna() to convert a domain name into its IDNA equivalent
This commit is contained in:
@@ -1303,3 +1303,55 @@ int dns_name_common_suffix(const char *a, const char *b, const char **ret) {
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
int dns_name_apply_idna(const char *name, char **ret) {
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
size_t n = 0, allocated = 0;
|
||||
bool first = true;
|
||||
int r, q;
|
||||
|
||||
assert(name);
|
||||
assert(ret);
|
||||
|
||||
for (;;) {
|
||||
char label[DNS_LABEL_MAX];
|
||||
|
||||
r = dns_label_unescape(&name, label, sizeof(label));
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
q = dns_label_apply_idna(label, r, label, sizeof(label));
|
||||
if (q < 0)
|
||||
return q;
|
||||
if (q > 0)
|
||||
r = q;
|
||||
|
||||
if (!GREEDY_REALLOC(buf, allocated, n + !first + DNS_LABEL_ESCAPED_MAX))
|
||||
return -ENOMEM;
|
||||
|
||||
r = dns_label_escape(label, r, buf + n + !first, DNS_LABEL_ESCAPED_MAX);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
buf[n++] = '.';
|
||||
|
||||
n +=r;
|
||||
}
|
||||
|
||||
if (n > DNS_HOSTNAME_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
if (!GREEDY_REALLOC(buf, allocated, n + 1))
|
||||
return -ENOMEM;
|
||||
|
||||
buf[n] = 0;
|
||||
*ret = buf;
|
||||
buf = NULL;
|
||||
|
||||
return (int) n;
|
||||
}
|
||||
|
||||
@@ -108,3 +108,5 @@ int dns_name_skip(const char *a, unsigned n_labels, const char **ret);
|
||||
int dns_name_equal_skip(const char *a, unsigned n_labels, const char *b);
|
||||
|
||||
int dns_name_common_suffix(const char *a, const char *b, const char **ret);
|
||||
|
||||
int dns_name_apply_idna(const char *name, char **ret);
|
||||
|
||||
@@ -598,6 +598,26 @@ static void test_dns_name_common_suffix(void) {
|
||||
test_dns_name_common_suffix_one("FOO.BAR", "tEST.bAR", "BAR");
|
||||
}
|
||||
|
||||
static void test_dns_name_apply_idna_one(const char *s, const char *result) {
|
||||
#ifdef HAVE_LIBIDN
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
assert_se(dns_name_apply_idna(s, &buf) >= 0);
|
||||
assert_se(dns_name_equal(buf, result) > 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void test_dns_name_apply_idna(void) {
|
||||
test_dns_name_apply_idna_one("", "");
|
||||
test_dns_name_apply_idna_one("foo", "foo");
|
||||
test_dns_name_apply_idna_one("foo.", "foo");
|
||||
test_dns_name_apply_idna_one("foo.bar", "foo.bar");
|
||||
test_dns_name_apply_idna_one("foo.bar.", "foo.bar");
|
||||
test_dns_name_apply_idna_one("föö", "xn--f-1gaa");
|
||||
test_dns_name_apply_idna_one("föö.", "xn--f-1gaa");
|
||||
test_dns_name_apply_idna_one("föö.bär", "xn--f-1gaa.xn--br-via");
|
||||
test_dns_name_apply_idna_one("föö.bär.", "xn--f-1gaa.xn--br-via");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
test_dns_label_unescape();
|
||||
@@ -624,6 +644,7 @@ int main(int argc, char *argv[]) {
|
||||
test_dns_name_equal_skip();
|
||||
test_dns_name_compare_func();
|
||||
test_dns_name_common_suffix();
|
||||
test_dns_name_apply_idna();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user