2 * Copyright (C) 2008 Red Hat, Inc
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General
15 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 #include <glib/glib.h>
25 const gchar
*ascii_name
, *unicode_name
;
26 } idn_test_domains
[] = {
27 /* "example.test" in various languages */
28 { "xn--mgbh0fb.xn--kgbechtv", "\xd9\x85\xd8\xab\xd8\xa7\xd9\x84.\xd8\xa5\xd8\xae\xd8\xaa\xd8\xa8\xd8\xa7\xd8\xb1" },
29 { "xn--fsqu00a.xn--0zwm56d", "\xe4\xbe\x8b\xe5\xad\x90.\xe6\xb5\x8b\xe8\xaf\x95" },
30 { "xn--fsqu00a.xn--g6w251d", "\xe4\xbe\x8b\xe5\xad\x90.\xe6\xb8\xac\xe8\xa9\xa6" },
31 { "xn--hxajbheg2az3al.xn--jxalpdlp", "\xcf\x80\xce\xb1\xcf\x81\xce\xac\xce\xb4\xce\xb5\xce\xb9\xce\xb3\xce\xbc\xce\xb1.\xce\xb4\xce\xbf\xce\xba\xce\xb9\xce\xbc\xce\xae" },
32 { "xn--p1b6ci4b4b3a.xn--11b5bs3a9aj6g", "\xe0\xa4\x89\xe0\xa4\xa6\xe0\xa4\xbe\xe0\xa4\xb9\xe0\xa4\xb0\xe0\xa4\xa3.\xe0\xa4\xaa\xe0\xa4\xb0\xe0\xa5\x80\xe0\xa4\x95\xe0\xa5\x8d\xe0\xa4\xb7\xe0\xa4\xbe" },
33 { "xn--r8jz45g.xn--zckzah", "\xe4\xbe\x8b\xe3\x81\x88.\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88" },
34 { "xn--9n2bp8q.xn--9t4b11yi5a", "\xec\x8b\xa4\xeb\xa1\x80.\xed\x85\x8c\xec\x8a\xa4\xed\x8a\xb8" },
35 { "xn--mgbh0fb.xn--hgbk6aj7f53bba", "\xd9\x85\xd8\xab\xd8\xa7\xd9\x84.\xd8\xa2\xd8\xb2\xd9\x85\xd8\xa7\xdb\x8c\xd8\xb4\xdb\x8c" },
36 { "xn--e1afmkfd.xn--80akhbyknj4f", "\xd0\xbf\xd1\x80\xd0\xb8\xd0\xbc\xd0\xb5\xd1\x80.\xd0\xb8\xd1\x81\xd0\xbf\xd1\x8b\xd1\x82\xd0\xb0\xd0\xbd\xd0\xb8\xd0\xb5" },
37 { "xn--zkc6cc5bi7f6e.xn--hlcj6aya9esc7a", "\xe0\xae\x89\xe0\xae\xa4\xe0\xae\xbe\xe0\xae\xb0\xe0\xae\xa3\xe0\xae\xae\xe0\xaf\x8d.\xe0\xae\xaa\xe0\xae\xb0\xe0\xae\xbf\xe0\xae\x9f\xe0\xaf\x8d\xe0\xae\x9a\xe0\xaf\x88" },
38 { "xn--fdbk5d8ap9b8a8d.xn--deba0ad", "\xd7\x91\xd7\xb2\xd6\xb7\xd7\xa9\xd7\xa4\xd6\xbc\xd7\x99\xd7\x9c.\xd7\x98\xd7\xa2\xd7\xa1\xd7\x98" },
40 /* further examples without their own IDN-ized TLD */
41 { "xn--1xd0bwwra.idn.icann.org", "\xe1\x8a\xa0\xe1\x88\x9b\xe1\x88\xad\xe1\x8a\x9b.idn.icann.org" },
42 { "xn--54b7fta0cc.idn.icann.org", "\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa6\x82\xe0\xa6\xb2\xe0\xa6\xbe.idn.icann.org" },
43 { "xn--5dbqzzl.idn.icann.org", "\xd7\xa2\xd7\x91\xd7\xa8\xd7\x99\xd7\xaa.idn.icann.org" },
44 { "xn--j2e7beiw1lb2hqg.idn.icann.org", "\xe1\x9e\x97\xe1\x9e\xb6\xe1\x9e\x9f\xe1\x9e\xb6\xe1\x9e\x81\xe1\x9f\x92\xe1\x9e\x98\xe1\x9f\x82\xe1\x9e\x9a.idn.icann.org" },
45 { "xn--o3cw4h.idn.icann.org", "\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2.idn.icann.org" },
46 { "xn--mgbqf7g.idn.icann.org", "\xd8\xa7\xd8\xb1\xd8\xaf\xd9\x88.idn.icann.org" }
48 static const gint num_idn_test_domains
= G_N_ELEMENTS (idn_test_domains
);
51 const gchar
*orig_name
, *ascii_name
;
52 gboolean orig_is_unicode
, ascii_is_encoded
;
53 } non_round_trip_names
[] = {
54 /* uppercase characters */
55 { "EXAMPLE.COM", "example.com", FALSE
, FALSE
},
56 { "\xc3\x89XAMPLE.COM", "xn--xample-9ua.com", TRUE
, TRUE
},
58 /* unicode that decodes to ascii */
59 { "\xe2\x93\x94\xe2\x93\xa7\xe2\x93\x90\xe2\x93\x9c\xe2\x93\x9f\xe2\x93\x9b\xe2\x93\x94.com", "example.com", TRUE
, FALSE
},
61 /* non-standard dot characters */
62 { "example\xe3\x80\x82" "com", "example.com", TRUE
, FALSE
},
63 { "\xc3\xa9xample\xe3\x80\x82" "com", "xn--xample-9ua.com", TRUE
, TRUE
},
64 { "Å.idn.icann.org", "xn--5ca.idn.icann.org", TRUE
, TRUE
},
65 { "ℵℶℷ\xcd\x8f.idn.icann.org", "xn--4dbcd.idn.icann.org", TRUE
, TRUE
}
67 static const gint num_non_round_trip_names
= G_N_ELEMENTS (non_round_trip_names
);
69 static const gchar
*bad_names
[] = {
70 "disallowed\xef\xbf\xbd" "character",
74 static const gint num_bad_names
= G_N_ELEMENTS (bad_names
);
82 for (i
= 0; i
< num_idn_test_domains
; i
++)
84 g_assert (g_hostname_is_non_ascii (idn_test_domains
[i
].unicode_name
));
85 ascii
= g_hostname_to_ascii (idn_test_domains
[i
].unicode_name
);
86 g_assert_cmpstr (idn_test_domains
[i
].ascii_name
, ==, ascii
);
89 ascii
= g_hostname_to_ascii (idn_test_domains
[i
].ascii_name
);
90 g_assert_cmpstr (idn_test_domains
[i
].ascii_name
, ==, ascii
);
94 for (i
= 0; i
< num_non_round_trip_names
; i
++)
96 if (non_round_trip_names
[i
].orig_is_unicode
)
97 g_assert (g_hostname_is_non_ascii (non_round_trip_names
[i
].orig_name
));
99 g_assert (!g_hostname_is_non_ascii (non_round_trip_names
[i
].orig_name
));
101 if (non_round_trip_names
[i
].ascii_is_encoded
)
102 g_assert (g_hostname_is_ascii_encoded (non_round_trip_names
[i
].ascii_name
));
104 g_assert (!g_hostname_is_ascii_encoded (non_round_trip_names
[i
].ascii_name
));
106 ascii
= g_hostname_to_ascii (non_round_trip_names
[i
].orig_name
);
107 g_assert_cmpstr (non_round_trip_names
[i
].ascii_name
, ==, ascii
);
110 ascii
= g_hostname_to_ascii (non_round_trip_names
[i
].ascii_name
);
111 g_assert_cmpstr (non_round_trip_names
[i
].ascii_name
, ==, ascii
);
115 for (i
= 0; i
< num_bad_names
; i
++)
117 ascii
= g_hostname_to_ascii (bad_names
[i
]);
118 g_assert_cmpstr (ascii
, ==, NULL
);
123 test_to_unicode (void)
128 for (i
= 0; i
< num_idn_test_domains
; i
++)
130 g_assert (g_hostname_is_ascii_encoded (idn_test_domains
[i
].ascii_name
));
131 unicode
= g_hostname_to_unicode (idn_test_domains
[i
].ascii_name
);
132 g_assert_cmpstr (idn_test_domains
[i
].unicode_name
, ==, unicode
);
135 unicode
= g_hostname_to_unicode (idn_test_domains
[i
].unicode_name
);
136 g_assert_cmpstr (idn_test_domains
[i
].unicode_name
, ==, unicode
);
140 for (i
= 0; i
< num_bad_names
; i
++)
142 unicode
= g_hostname_to_unicode (bad_names
[i
]);
143 g_assert_cmpstr (unicode
, ==, NULL
);
147 static const struct {
150 } ip_addr_tests
[] = {
153 { "0123:4567:89AB:cdef:3210:7654:ba98:FeDc", TRUE
},
155 { "0123:4567:89AB:cdef:3210:7654:ba98::", TRUE
},
156 { "0123:4567:89AB:cdef:3210:7654::", TRUE
},
157 { "0123:4567:89AB:cdef:3210::", TRUE
},
158 { "0123:4567:89AB:cdef::", TRUE
},
159 { "0123:4567:89AB::", TRUE
},
160 { "0123:4567::", TRUE
},
163 { "::4567:89AB:cdef:3210:7654:ba98:FeDc", TRUE
},
164 { "::89AB:cdef:3210:7654:ba98:FeDc", TRUE
},
165 { "::cdef:3210:7654:ba98:FeDc", TRUE
},
166 { "::3210:7654:ba98:FeDc", TRUE
},
167 { "::7654:ba98:FeDc", TRUE
},
168 { "::ba98:FeDc", TRUE
},
171 { "0123::89AB:cdef:3210:7654:ba98:FeDc", TRUE
},
172 { "0123:4567::cdef:3210:7654:ba98:FeDc", TRUE
},
173 { "0123:4567:89AB::3210:7654:ba98:FeDc", TRUE
},
174 { "0123:4567:89AB:cdef::7654:ba98:FeDc", TRUE
},
175 { "0123:4567:89AB:cdef:3210::ba98:FeDc", TRUE
},
176 { "0123:4567:89AB:cdef:3210:7654::FeDc", TRUE
},
178 { "0123::cdef:3210:7654:ba98:FeDc", TRUE
},
179 { "0123:4567::3210:7654:ba98:FeDc", TRUE
},
180 { "0123:4567:89AB::7654:ba98:FeDc", TRUE
},
181 { "0123:4567:89AB:cdef::ba98:FeDc", TRUE
},
182 { "0123:4567:89AB:cdef:3210::FeDc", TRUE
},
184 { "0123::3210:7654:ba98:FeDc", TRUE
},
185 { "0123:4567::7654:ba98:FeDc", TRUE
},
186 { "0123:4567:89AB::ba98:FeDc", TRUE
},
187 { "0123:4567:89AB:cdef::FeDc", TRUE
},
189 { "0123::7654:ba98:FeDc", TRUE
},
190 { "0123:4567::ba98:FeDc", TRUE
},
191 { "0123:4567:89AB::FeDc", TRUE
},
193 { "0123::ba98:FeDc", TRUE
},
194 { "0123:4567::FeDc", TRUE
},
196 { "0123::FeDc", TRUE
},
200 { "0:12:345:6789:a:bc:def::", TRUE
},
202 { "0123:4567:89AB:cdef:3210:7654:123.45.67.89", TRUE
},
203 { "0123:4567:89AB:cdef:3210::123.45.67.89", TRUE
},
204 { "0123:4567:89AB:cdef::123.45.67.89", TRUE
},
205 { "0123:4567:89AB::123.45.67.89", TRUE
},
206 { "0123:4567::123.45.67.89", TRUE
},
207 { "0123::123.45.67.89", TRUE
},
208 { "::123.45.67.89", TRUE
},
210 /* Contain non-hex chars */
211 { "012x:4567:89AB:cdef:3210:7654:ba98:FeDc", FALSE
},
212 { "0123:45x7:89AB:cdef:3210:7654:ba98:FeDc", FALSE
},
213 { "0123:4567:8xAB:cdef:3210:7654:ba98:FeDc", FALSE
},
214 { "0123:4567:89AB:xdef:3210:7654:ba98:FeDc", FALSE
},
215 { "0123:4567:89AB:cdef:321;:7654:ba98:FeDc", FALSE
},
216 { "0123:4567:89AB:cdef:3210:76*4:ba98:FeDc", FALSE
},
217 { "0123:4567:89AB:cdef:3210:7654:b-98:FeDc", FALSE
},
218 { "0123:4567:89AB:cdef:3210:7654:ba98:+eDc", FALSE
},
219 { "0123:4567:89AB:cdef:3210:7654:ba98:FeDc and some trailing junk", FALSE
},
220 { " 123:4567:89AB:cdef:3210:7654:ba98:FeDc", FALSE
},
221 { "012 :4567:89AB:cdef:3210:7654:ba98:FeDc", FALSE
},
222 { "0123: 567:89AB:cdef:3210:7654:ba98:FeDc", FALSE
},
223 { "0123:4567:89AB:cdef:3210:7654:ba98:FeD ", FALSE
},
225 /* Contains too-long/out-of-range segments */
226 { "00123:4567:89AB:cdef:3210:7654:ba98:FeDc", FALSE
},
227 { "0123:04567:89AB:cdef:3210:7654:ba98:FeDc", FALSE
},
228 { "0123:4567:189AB:cdef:3210:7654:ba98:FeDc", FALSE
},
231 { "0123:4567:89AB:cdef:3210:7654:ba98", FALSE
},
232 { "0123:4567:89AB:cdef:3210:7654", FALSE
},
233 { "0123:4567:89AB:cdef:3210", FALSE
},
238 { "0123:4567:89AB:cdef:3210:7654:ba98:FeDc:9999", FALSE
},
239 { "0123::4567:89AB:cdef:3210:7654:ba98:FeDc", FALSE
},
240 { "0123:4567::89AB:cdef:3210:7654:ba98:FeDc", FALSE
},
241 { "0123:4567:89AB::cdef:3210:7654:ba98:FeDc", FALSE
},
242 { "0123:4567:89AB:cdef::3210:7654:ba98:FeDc", FALSE
},
243 { "0123:4567:89AB:cdef:3210::7654:ba98:FeDc", FALSE
},
244 { "0123:4567:89AB:cdef:3210:7654::ba98:FeDc", FALSE
},
245 { "0123:4567:89AB:cdef:3210:7654:ba98::FeDc", FALSE
},
247 /* Invalid use of ":"s */
248 { "0123::89AB::3210:7654:ba98:FeDc", FALSE
},
249 { "::4567:89AB:cdef:3210:7654::FeDc", FALSE
},
250 { "0123::89AB:cdef:3210:7654:ba98::", FALSE
},
251 { ":4567:89AB:cdef:3210:7654:ba98:FeDc", FALSE
},
252 { "0123:4567:89AB:cdef:3210:7654:ba98:", FALSE
},
253 { "0123:::cdef:3210:7654:ba98:FeDc", FALSE
},
254 { "0123:4567:89AB:cdef:3210:7654:ba98:FeDc:", FALSE
},
255 { ":0123:4567:89AB:cdef:3210:7654:ba98:FeDc", FALSE
},
258 /* IPv4 address at wrong place */
259 { "0123:4567:89AB:cdef:3210:123.45.67.89", FALSE
},
260 { "0123:4567:89AB:cdef:3210:7654::123.45.67.89", FALSE
},
261 { "0123:4567:89AB:cdef:123.45.67.89", FALSE
},
262 { "0123:4567:89AB:cdef:3210:123.45.67.89:FeDc", FALSE
},
267 { "123.45.67.89", TRUE
},
271 { "023.045.067.089", FALSE
},
272 { "1234.5.67.89", FALSE
},
273 { "123.45.67.00", FALSE
},
274 { " 1.2.3.4", FALSE
},
275 { "1 .2.3.4", FALSE
},
276 { "1. 2.3.4", FALSE
},
277 { "1.2.3.4 ", FALSE
},
279 { "1.2.3.4.5", FALSE
},
280 { "1.b.3.4", FALSE
},
281 { "1.2.3:4", FALSE
},
282 { "1.2.3.4, etc", FALSE
},
283 { "1,2,3,4", FALSE
},
284 { "1.2.3.com", FALSE
},
285 { "1.2.3.4.", FALSE
},
287 { ".1.2.3.4", FALSE
},
289 { "1..2.3.4", FALSE
},
292 static const gint num_ip_addr_tests
= G_N_ELEMENTS (ip_addr_tests
);
295 test_is_ip_addr (void)
299 for (i
= 0; i
< num_ip_addr_tests
; i
++)
301 if (g_hostname_is_ip_address (ip_addr_tests
[i
].addr
) != ip_addr_tests
[i
].is_addr
)
303 char *msg
= g_strdup_printf ("g_hostname_is_ip_address (\"%s\") == %s",
304 ip_addr_tests
[i
].addr
,
305 ip_addr_tests
[i
].is_addr
? "TRUE" : "FALSE");
306 g_assertion_message (G_LOG_DOMAIN
, __FILE__
, __LINE__
, G_STRFUNC
, msg
);
311 /* FIXME: test names with both unicode and ACE-encoded labels */
312 /* FIXME: test invalid unicode names */
318 g_test_init (&argc
, &argv
, NULL
);
320 if (argc
== 2 && argv
[1][0] != '-')
322 const gchar
*hostname
= argv
[1];
325 if (g_hostname_is_non_ascii (hostname
))
327 converted
= g_hostname_to_ascii (hostname
);
328 printf ("to_ascii: %s\n", converted
);
331 else if (g_hostname_is_ascii_encoded (hostname
))
333 converted
= g_hostname_to_unicode (hostname
);
334 printf ("to_unicode: %s\n", converted
);
338 printf ("hostname is neither unicode nor ACE encoded\n");
342 g_test_add_func ("/hostutils/to_ascii", test_to_ascii
);
343 g_test_add_func ("/hostutils/to_unicode", test_to_unicode
);
344 g_test_add_func ("/hostutils/is_ip_addr", test_is_ip_addr
);
346 return g_test_run ();