Sync with TP.
[libidn.git] / src / idn.c
blob5297f563b71fbba014231bf27aa64d820158cbc8
1 /* idn.c --- Command line interface to libidn.
2 * Copyright (C) 2003, 2004, 2005, 2006, 2007 Simon Josefsson
4 * This file is part of GNU Libidn.
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <locale.h>
31 /* Gnulib headers. */
32 #include "error.h"
33 #include "gettext.h"
34 #define _(String) dgettext (PACKAGE, String)
36 /* Libidn headers. */
37 #include <stringprep.h>
38 #include <punycode.h>
39 #include <idna.h>
40 #ifdef WITH_TLD
41 # include <tld.h>
42 #endif
44 #include "idn_cmd.h"
46 #define GREETING \
47 "Copyright 2002, 2003, 2004, 2005, 2006, 2007 Simon Josefsson.\n" \
48 "GNU Libidn comes with NO WARRANTY, to the extent permitted by law.\n" \
49 "You may redistribute copies of GNU Libidn under the terms of\n" \
50 "the GNU Lesser General Public License. For more information\n" \
51 "about these matters, see the file named COPYING.LIB.\n"
53 /* For error.c */
54 char *program_name;
56 int
57 main (int argc, char *argv[])
59 struct gengetopt_args_info args_info;
60 char readbuf[BUFSIZ];
61 char *p, *r;
62 uint32_t *q;
63 unsigned cmdn = 0;
64 int rc;
66 setlocale (LC_ALL, "");
67 program_name = argv[0];
68 bindtextdomain (PACKAGE, LOCALEDIR);
69 textdomain (PACKAGE);
71 if (cmdline_parser (argc, argv, &args_info) != 0)
72 return EXIT_FAILURE;
74 if (!args_info.stringprep_given &&
75 !args_info.punycode_encode_given && !args_info.punycode_decode_given &&
76 !args_info.idna_to_ascii_given && !args_info.idna_to_unicode_given)
77 args_info.idna_to_ascii_given = 1;
79 if ((args_info.stringprep_given ? 1 : 0) +
80 (args_info.punycode_encode_given ? 1 : 0) +
81 (args_info.punycode_decode_given ? 1 : 0) +
82 (args_info.idna_to_ascii_given ? 1 : 0) +
83 (args_info.idna_to_unicode_given ? 1 : 0) != 1)
85 error (0, 0, _("Only one of -s, -e, -d, -a or -u can be specified."));
86 cmdline_parser_print_help ();
87 return EXIT_FAILURE;
90 if (!args_info.quiet_given)
91 fprintf (stderr, "%s %s\n" GREETING, PACKAGE, VERSION);
93 if (args_info.debug_given)
94 fprintf (stderr, _("Charset `%s'.\n"), stringprep_locale_charset ());
96 if (!args_info.quiet_given && args_info.inputs_num == 0)
97 fprintf (stderr, _("Type each input string on a line by itself, "
98 "terminated by a newline character.\n"));
102 if (cmdn < args_info.inputs_num)
104 strncpy (readbuf, args_info.inputs[cmdn++], BUFSIZ - 1);
105 readbuf[BUFSIZ - 1] = '\0';
107 else if (fgets (readbuf, BUFSIZ, stdin) == NULL)
109 if (feof (stdin))
110 break;
112 error (EXIT_FAILURE, errno, _("Input error"));
115 if (readbuf[strlen (readbuf) - 1] == '\n')
116 readbuf[strlen (readbuf) - 1] = '\0';
118 if (args_info.stringprep_given)
120 p = stringprep_locale_to_utf8 (readbuf);
121 if (!p)
122 error (EXIT_FAILURE, 0, _("Could not convert from %s to UTF-8."),
123 stringprep_locale_charset ());
125 q = stringprep_utf8_to_ucs4 (p, -1, NULL);
126 if (!q)
128 free (p);
129 error (EXIT_FAILURE, 0,
130 _("Could not convert from UTF-8 to UCS-4."));
133 if (args_info.debug_given)
135 size_t i;
136 for (i = 0; q[i]; i++)
137 fprintf (stderr, _("input[%lu] = U+%04x\n"),
138 (unsigned long) i, q[i]);
140 free (q);
142 rc = stringprep_profile (p, &r,
143 args_info.profile_given ?
144 args_info.profile_arg : "Nameprep", 0);
145 free (p);
146 if (rc != STRINGPREP_OK)
147 error (EXIT_FAILURE, 0, _("stringprep_profile: %s"),
148 stringprep_strerror (rc));
150 q = stringprep_utf8_to_ucs4 (r, -1, NULL);
151 if (!q)
153 free (r);
154 error (EXIT_FAILURE, 0,
155 _("Could not convert from UTF-8 to UCS-4."));
158 if (args_info.debug_given)
160 size_t i;
161 for (i = 0; q[i]; i++)
162 fprintf (stderr, _("output[%lu] = U+%04x\n"),
163 (unsigned long) i, q[i]);
165 free (q);
167 p = stringprep_utf8_to_locale (r);
168 free (r);
169 if (!p)
170 error (EXIT_FAILURE, 0, _("Could not convert from UTF-8 to %s."),
171 stringprep_locale_charset ());
173 fprintf (stdout, "%s\n", p);
175 free (p);
178 if (args_info.punycode_encode_given)
180 size_t len, len2;
182 p = stringprep_locale_to_utf8 (readbuf);
183 if (!p)
184 error (EXIT_FAILURE, 0, _("Could not convert from %s to UTF-8."),
185 stringprep_locale_charset ());
187 q = stringprep_utf8_to_ucs4 (p, -1, &len);
188 free (p);
189 if (!q)
190 error (EXIT_FAILURE, 0,
191 _("Could not convert from UTF-8 to UCS-4."));
193 if (args_info.debug_given)
195 size_t i;
196 for (i = 0; i < len; i++)
197 fprintf (stderr, _("input[%lu] = U+%04x\n"),
198 (unsigned long) i, q[i]);
201 len2 = BUFSIZ - 1;
202 rc = punycode_encode (len, q, NULL, &len2, readbuf);
203 free (q);
204 if (rc != PUNYCODE_SUCCESS)
205 error (EXIT_FAILURE, 0, _("punycode_encode: %s"),
206 punycode_strerror (rc));
208 readbuf[len2] = '\0';
210 p = stringprep_utf8_to_locale (readbuf);
211 if (!p)
212 error (EXIT_FAILURE, 0, _("Could not convert from UTF-8 to %s."),
213 stringprep_locale_charset ());
215 fprintf (stdout, "%s\n", p);
217 free (p);
220 if (args_info.punycode_decode_given)
222 size_t len;
224 len = BUFSIZ;
225 q = (uint32_t *) malloc (len * sizeof (q[0]));
226 if (!q)
227 error (EXIT_FAILURE, ENOMEM, _("malloc"));
229 rc = punycode_decode (strlen (readbuf), readbuf, &len, q, NULL);
230 if (rc != PUNYCODE_SUCCESS)
232 free (q);
233 error (EXIT_FAILURE, 0, _("punycode_decode: %s"),
234 punycode_strerror (rc));
237 if (args_info.debug_given)
239 size_t i;
240 for (i = 0; i < len; i++)
241 fprintf (stderr, _("output[%lu] = U+%04x\n"),
242 (unsigned long) i, q[i]);
245 q[len] = 0;
246 r = stringprep_ucs4_to_utf8 (q, -1, NULL, NULL);
247 free (q);
248 if (!r)
249 error (EXIT_FAILURE, 0,
250 _("Could not convert from UCS-4 to UTF-8."));
252 p = stringprep_utf8_to_locale (r);
253 free (r);
254 if (!r)
255 error (EXIT_FAILURE, 0, _("Could not convert from UTF-8 to %s."),
256 stringprep_locale_charset ());
258 fprintf (stdout, "%s\n", p);
260 free (p);
263 if (args_info.idna_to_ascii_given)
265 p = stringprep_locale_to_utf8 (readbuf);
266 if (!p)
267 error (EXIT_FAILURE, 0, _("Could not convert from %s to UTF-8."),
268 stringprep_locale_charset ());
270 q = stringprep_utf8_to_ucs4 (p, -1, NULL);
271 free (p);
272 if (!q)
273 error (EXIT_FAILURE, 0,
274 _("Could not convert from UCS-4 to UTF-8."));
276 if (args_info.debug_given)
278 size_t i;
279 for (i = 0; q[i]; i++)
280 fprintf (stderr, _("input[%lu] = U+%04x\n"),
281 (unsigned long) i, q[i]);
284 rc = idna_to_ascii_4z (q, &p,
285 (args_info.allow_unassigned_given ?
286 IDNA_ALLOW_UNASSIGNED : 0) |
287 (args_info.usestd3asciirules_given ?
288 IDNA_USE_STD3_ASCII_RULES : 0));
289 free (q);
290 if (rc != IDNA_SUCCESS)
291 error (EXIT_FAILURE, 0, _("idna_to_ascii_4z: %s"),
292 idna_strerror (rc));
294 #ifdef WITH_TLD
295 if (args_info.tld_flag)
297 size_t errpos;
299 rc = idna_to_unicode_8z4z (p, &q,
300 (args_info.allow_unassigned_given ?
301 IDNA_ALLOW_UNASSIGNED : 0) |
302 (args_info.usestd3asciirules_given ?
303 IDNA_USE_STD3_ASCII_RULES : 0));
304 if (rc != IDNA_SUCCESS)
305 error (EXIT_FAILURE, 0, _("idna_to_unicode_8z4z (TLD): %s"),
306 idna_strerror (rc));
308 if (args_info.debug_given)
310 size_t i;
311 for (i = 0; q[i]; i++)
312 fprintf (stderr, _("tld[%lu] = U+%04x\n"),
313 (unsigned long) i, q[i]);
316 rc = tld_check_4z (q, &errpos, NULL);
317 free (q);
318 if (rc == TLD_INVALID)
319 error (EXIT_FAILURE, 0, _("tld_check_4z (position %lu): %s"),
320 (unsigned long) errpos, tld_strerror (rc));
321 if (rc != TLD_SUCCESS)
322 error (EXIT_FAILURE, 0, _("tld_check_4z: %s"),
323 tld_strerror (rc));
325 #endif
327 if (args_info.debug_given)
329 size_t i;
330 for (i = 0; p[i]; i++)
331 fprintf (stderr, _("output[%lu] = U+%04x\n"),
332 (unsigned long) i, p[i]);
335 fprintf (stdout, "%s\n", p);
337 free (p);
340 if (args_info.idna_to_unicode_given)
342 p = stringprep_locale_to_utf8 (readbuf);
343 if (!p)
344 error (EXIT_FAILURE, 0, _("Could not convert from %s to UTF-8."),
345 stringprep_locale_charset ());
347 q = stringprep_utf8_to_ucs4 (p, -1, NULL);
348 if (!q)
350 free (p);
351 error (EXIT_FAILURE, 0,
352 _("Could not convert from UCS-4 to UTF-8."));
355 if (args_info.debug_given)
357 size_t i;
358 for (i = 0; q[i]; i++)
359 fprintf (stderr, _("input[%lu] = U+%04x\n"),
360 (unsigned long) i, q[i]);
362 free (q);
364 rc = idna_to_unicode_8z4z (p, &q,
365 (args_info.allow_unassigned_given ?
366 IDNA_ALLOW_UNASSIGNED : 0) |
367 (args_info.usestd3asciirules_given ?
368 IDNA_USE_STD3_ASCII_RULES : 0));
369 free (p);
370 if (rc != IDNA_SUCCESS)
371 error (EXIT_FAILURE, 0, _("idna_to_unicode_8z4z: %s"),
372 idna_strerror (rc));
374 if (args_info.debug_given)
376 size_t i;
377 for (i = 0; q[i]; i++)
378 fprintf (stderr, _("output[%lu] = U+%04x\n"),
379 (unsigned long) i, q[i]);
382 #ifdef WITH_TLD
383 if (args_info.tld_flag)
385 size_t errpos;
387 rc = tld_check_4z (q, &errpos, NULL);
388 if (rc == TLD_INVALID)
390 free (q);
391 error (EXIT_FAILURE, 0, _("tld_check_4z (position %lu): %s"),
392 (unsigned long) errpos, tld_strerror (rc));
394 if (rc != TLD_SUCCESS)
396 free (q);
397 error (EXIT_FAILURE, 0, _("tld_check_4z: %s"),
398 tld_strerror (rc));
401 #endif
403 r = stringprep_ucs4_to_utf8 (q, -1, NULL, NULL);
404 free (q);
405 if (!r)
406 error (EXIT_FAILURE, 0,
407 _("Could not convert from UTF-8 to UCS-4."));
409 p = stringprep_utf8_to_locale (r);
410 free (r);
411 if (!r)
412 error (EXIT_FAILURE, 0, _("Could not convert from UTF-8 to %s."),
413 stringprep_locale_charset ());
415 fprintf (stdout, "%s\n", p);
417 free (p);
420 while (!feof (stdin) && !ferror (stdin) && (args_info.inputs_num == 0 ||
421 cmdn < args_info.inputs_num));
423 return EXIT_SUCCESS;