/* idn2.c - command line interface to libidn2 Copyright (C) 2011-2019 Simon Josefsson, Tim Ruehsen This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* Gnulib headers. */ #include "error.h" #include "gettext.h" #define _(String) dgettext (PACKAGE, String) #include "progname.h" #include "version-etc.h" #include "idn2_cmd.h" #include "blurbs.h" #ifdef __cplusplus extern // define a global const variable in C++, C doesn't need it. #endif const char version_etc_copyright[] = /* Do *not* mark this string for translation. %s is a copyright symbol suitable for this locale, and %d is the copyright year. */ "Copyright 2011-%s %d Simon Josefsson, Tim Ruehsen."; static void usage (int status) { if (status != EXIT_SUCCESS) fprintf (stderr, _("Try `%s --help' for more information.\n"), program_name); else { printf (_("\ Usage: %s [OPTION]... [STRINGS]...\n\ "), program_name); fputs (_("\ Internationalized Domain Name (IDNA2008) convert STRINGS, or standard input.\n\ \n\ "), stdout); fputs (_("\ Command line interface to the Libidn2 implementation of IDNA2008.\n\ \n\ All strings are expected to be encoded in the locale charset.\n\ \n\ To process a string that starts with `-', for example `-foo', use `--'\n\ to signal the end of parameters, as in `idn2 --quiet -- -foo'.\n\ \n\ Mandatory arguments to long options are mandatory for short options too.\n\ "), stdout); fputs (_("\ -h, --help Print help and exit\n\ -V, --version Print version and exit\n\ "), stdout); fputs (_("\ -d, --decode Decode (punycode) domain name\n\ -l, --lookup Lookup domain name (default)\n\ -r, --register Register label\n\ "), stdout); fputs (_("\ -T, --tr46t Enable TR46 transitional processing\n\ -N, --tr46nt Enable TR46 non-transitional processing\n\ --no-tr46 Disable TR46 processing\n\ "), stdout); fputs (_("\ --usestd3asciirules Enable STD3 ASCII rules\n\ --no-alabelroundtrip Disable ALabel rountrip for lookups\n\ --debug Print debugging information\n\ --quiet Silent operation\n\ "), stdout); emit_bug_reporting_address (); } exit (status); } static void hexdump (const char *prefix, const char *str) { uint8_t *u8; uint32_t *u32 = NULL; size_t u32len; size_t i; const char *encoding = locale_charset (); u8 = u8_strconv_from_encoding (str, encoding, iconveh_error); if (u8) u32 = u8_to_u32 (u8, strlen ((char *) u8), NULL, &u32len); for (i = 0; i < strlen (str); i++) fprintf (stderr, "%s[%lu] = 0x%02x\n", prefix, (unsigned long) i, (unsigned) (str[i] & 0xFF)); if (u8 && strcmp (str, (char *) u8) != 0) for (i = 0; i < strlen ((char *) u8); i++) fprintf (stderr, "UTF-8 %s[%lu] = 0x%02x\n", prefix, (unsigned long) i, u8[i] & 0xFF); if (u8 && u32) for (i = 0; i < u32len; i++) fprintf (stderr, "UCS-4 %s[%lu] = U+%04x\n", prefix, (unsigned long) i, u32[i]); } static struct gengetopt_args_info args_info; static void process_input (char *readbuf, int flags) { size_t len = strlen (readbuf); char *output; const char *tag; int rc; if (len && readbuf[len - 1] == '\n') readbuf[len - 1] = '\0'; if (strcmp (readbuf, "show w") == 0) { puts (WARRANTY); return; } else if (strcmp (readbuf, "show c") == 0) { puts (CONDITIONS); return; } if (args_info.debug_given) hexdump ("input", readbuf); if (args_info.register_given) { rc = idn2_register_ul(readbuf, NULL, &output, flags); tag = "register"; } else if (args_info.decode_given) { rc = idn2_to_unicode_lzlz (readbuf, &output, 0); tag = "decode"; } else { rc = idn2_to_ascii_lz (readbuf, &output, flags); tag = "toAscii"; } if (rc == IDN2_OK) { if (args_info.debug_given) hexdump ("output", readbuf); printf ("%s\n", output); free (output); } else error (EXIT_FAILURE, 0, "%s: %s", tag, idn2_strerror (rc)); } int main (int argc, char *argv[]) { unsigned cmdn; int flags = IDN2_NONTRANSITIONAL; setlocale (LC_ALL, ""); set_program_name (argv[0]); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); if (cmdline_parser (argc, argv, &args_info) != 0) return EXIT_FAILURE; if (args_info.version_given) { version_etc (stdout, "idn2", PACKAGE_NAME, VERSION, "Simon Josefsson, Tim Ruehsen", (char *) NULL); return EXIT_SUCCESS; } if (args_info.help_given) usage (EXIT_SUCCESS); if (!args_info.quiet_given && args_info.inputs_num == 0 && isatty (fileno (stdin))) fprintf (stderr, "%s %s\n" GREETING, PACKAGE, VERSION); if (args_info.debug_given) fprintf (stderr, _("Charset: %s\n"), locale_charset ()); if (!args_info.quiet_given && args_info.inputs_num == 0 && isatty (fileno (stdin))) fprintf (stderr, "%s", _("Type each input string on a line by itself, " "terminated by a newline character.\n")); if (args_info.tr46t_given) flags = IDN2_TRANSITIONAL; else if (args_info.tr46nt_given) flags = IDN2_NONTRANSITIONAL; else if (args_info.no_tr46_given) flags = IDN2_NO_TR46; if (flags && args_info.usestd3asciirules_given) flags |= IDN2_USE_STD3_ASCII_RULES; if (flags && args_info.no_alabelroundtrip_given) flags |= IDN2_NO_ALABEL_ROUNDTRIP; for (cmdn = 0; cmdn < args_info.inputs_num; cmdn++) process_input (args_info.inputs[cmdn], flags | IDN2_NFC_INPUT); if (!cmdn) { char *buf = NULL; size_t bufsize = 0; while (getline (&buf, &bufsize, stdin) > 0) process_input (buf, flags); free (buf); } if (ferror (stdin)) error (EXIT_FAILURE, errno, "%s", _("input error")); cmdline_parser_free (&args_info); return EXIT_SUCCESS; }