idn_converter_t idn_resconf_getalternateconverter(idn_resconf_t ctx) { assert(ctx != NULL); TRACE(("idn_resconf_getalternateconverter()\n")); return (idn_resconf_getidnconverter(ctx)); }
static idn_result_t label_lencheck_nonace(idn_resconf_t ctx, labellist_t label) { idn_converter_t idn_converter; const unsigned long *from; size_t to_length; idn_result_t r; char *buffer = NULL; size_t buffer_length; from = labellist_getname(label); TRACE(("res lencheck(label=\"%s\")\n", idn__debug_ucs4xstring(from, 50))); buffer_length = idn_ucs4_strlen(from) * 4 + 16; /* 16 for margin */ idn_converter = idn_resconf_getidnconverter(ctx); for (;;) { void *new_buffer; new_buffer = realloc(buffer, sizeof(*buffer) * buffer_length); if (new_buffer == NULL) { r = idn_nomemory; goto ret; } buffer = (char *)new_buffer; if (idn_converter != NULL) { r = idn_converter_convfromucs4(idn_converter, from, buffer, buffer_length); } else { r = idn_ucs4_ucs4toutf8(from, buffer, buffer_length); } if (r == idn_success) break; else if (r != idn_buffer_overflow) goto ret; buffer_length *= 2; } to_length = strlen(buffer); if (to_length == 0 || to_length > MAX_LABEL_LENGTH) { r = idn_invalid_length; goto ret; } r = idn_success; ret: TRACE(("res lencheck(): %s\n", idn_result_tostring(r))); if (idn_converter != NULL) idn_converter_destroy(idn_converter); free(buffer); return (r); }
static int decode_file (idn_resconf_t conf1, idn_resconf_t conf2, FILE * fp, int flags) { idn_result_t r; idnconv_strbuf_t buf1, buf2; idn_action_t actions1, actions2; int nl_trimmed; int local_ace_hack, idn_ace_hack; idn_converter_t conv; /* * See if the input codeset is an ACE. */ conv = idn_resconf_getidnconverter (conf1); if (conv != NULL && idn_converter_isasciicompatible (conv) && (flags & FLAG_SELECTIVE)) idn_ace_hack = 1; else idn_ace_hack = 0; if (conv != NULL) idn_converter_destroy (conv); conv = idn_resconf_getlocalconverter (conf1); if (conv != NULL && idn_converter_isasciicompatible (conv) && (flags & FLAG_SELECTIVE)) local_ace_hack = 1; else local_ace_hack = 0; if (conv != NULL) idn_converter_destroy (conv); actions1 = IDN_IDNCONV; if (local_ace_hack) { actions2 = IDN_IDNCONV; if (flags & FLAG_MAP) actions2 |= IDN_MAP; if (flags & FLAG_NORMALIZE) actions2 |= IDN_NORMALIZE; if (flags & FLAG_PROHIBITCHECK) actions2 |= IDN_PROHCHECK; if (flags & FLAG_UNASSIGNCHECK) actions2 |= IDN_UNASCHECK; if (flags & FLAG_BIDICHECK) actions2 |= IDN_BIDICHECK; if (flags & FLAG_ASCIICHECK) actions2 |= IDN_ASCCHECK; if (flags & FLAG_LENGTHCHECK) actions2 |= IDN_LENCHECK; } else { actions2 = IDN_LOCALCONV; } if (flags & FLAG_DELIMMAP) actions1 |= IDN_DELIMMAP; if (flags & FLAG_MAP) actions1 |= IDN_MAP; if (flags & FLAG_NORMALIZE) actions1 |= IDN_NORMALIZE; if (flags & FLAG_NORMALIZE) actions1 |= IDN_NORMALIZE; if (flags & FLAG_PROHIBITCHECK) actions1 |= IDN_PROHCHECK; if (flags & FLAG_UNASSIGNCHECK) actions1 |= IDN_UNASCHECK; if (flags & FLAG_BIDICHECK) actions1 |= IDN_BIDICHECK; if (flags & FLAG_ASCIICHECK) actions1 |= IDN_ASCCHECK; if (flags & FLAG_ROUNDTRIPCHECK) actions1 |= IDN_RTCHECK; strbuf_init (&buf1); strbuf_init (&buf2); line_number = 1; while (strbuf_getline (&buf1, fp) != NULL) { /* * Trim newline at the end. This is needed for * those ascii-comatible encodings such as UTF-5 or RACE * not to try converting newlines, which will result * in `invalid encoding' error. */ nl_trimmed = trim_newline (&buf1); /* * Treat input line as the string encoded in local * encoding and convert it to UTF-8 encoded string. */ if (local_ace_hack) { if (strbuf_copy (&buf2, strbuf_get (&buf1)) == NULL) r = idn_nomemory; else r = idn_success; } else { r = convert_line (&buf1, &buf2, conf1, IDN_LOCALCONV, 0); } if (r != idn_success) { errormsg ("conversion failed at line %d: %s\n", line_number, idn_result_tostring (r)); goto error; } /* * Convert internationalized domain names in the line. */ if (idn_ace_hack) { r = convert_line (&buf2, &buf1, conf1, actions1, FLAG_REVERSE | FLAG_SELECTIVE); } else { r = convert_line (&buf2, &buf1, conf1, actions1, FLAG_REVERSE); } if (r != idn_success) { errormsg ("conversion failed at line %d: %s\n", line_number, idn_result_tostring (r)); goto error; } if (!idn_utf8_isvalidstring (strbuf_get (&buf1))) { errormsg ("conversion to utf-8 failed at line %d\n", line_number); goto error; } /* * Perform round trip check and convert to the output * codeset. */ if (local_ace_hack) { r = convert_line (&buf1, &buf2, conf2, actions2, FLAG_SELECTIVE); } else { r = convert_line (&buf1, &buf2, conf1, actions2, FLAG_REVERSE); } if (r != idn_success) { errormsg ("error in nameprep or output conversion " "at line %d: %s\n", line_number, idn_result_tostring (r)); goto error; } fputs (strbuf_get (&buf2), stdout); if (nl_trimmed) putc ('\n', stdout); if (flush_every_line) fflush (stdout); line_number++; } strbuf_reset (&buf1); strbuf_reset (&buf2); return (0); error: strbuf_reset (&buf1); strbuf_reset (&buf2); return (1); }
int main (int ac, char **av) { char *cmd = *av; char *cname; unsigned long delimiters[MAX_DELIMITER]; char *localmappers[MAX_LOCALMAPPER]; char *nameprep_version = NULL; int ndelimiters = 0; int nlocalmappers = 0; char *in_code = NULL; char *out_code = NULL; char *resconf_file = NULL; int no_resconf = 0; char *encoding_alias = NULL; int flags = DEFAULT_FLAGS; FILE *fp; idn_result_t r; idn_resconf_t resconf1, resconf2; idn_converter_t conv; int exit_value; #ifdef HAVE_SETLOCALE (void) setlocale (LC_ALL, ""); #endif /* * If the command name begins with 'r', reverse mode is assumed. */ if ((cname = strrchr (cmd, '/')) != NULL) cname++; else cname = cmd; if (cname[0] == 'r') flags |= FLAG_REVERSE; ac--; av++; while (ac > 0 && **av == '-') { #define OPT_MATCH(opt) (strcmp(*av, opt) == 0) #define MUST_HAVE_ARG if (ac < 2) print_usage(cmd) #define APPEND_LIST(array, size, item, what) \ if (size >= (sizeof(array) / sizeof(array[0]))) { \ errormsg("too many " what "\n"); \ exit(1); \ } \ array[size++] = item; \ ac--; av++ if (OPT_MATCH ("-in") || OPT_MATCH ("-i")) { MUST_HAVE_ARG; in_code = av[1]; ac--; av++; } else if (OPT_MATCH ("-out") || OPT_MATCH ("-o")) { MUST_HAVE_ARG; out_code = av[1]; ac--; av++; } else if (OPT_MATCH ("-conf") || OPT_MATCH ("-c")) { MUST_HAVE_ARG; resconf_file = av[1]; ac--; av++; } else if (OPT_MATCH ("-nameprep") || OPT_MATCH ("-n")) { MUST_HAVE_ARG; nameprep_version = av[1]; ac--; av++; } else if (OPT_MATCH ("-noconf") || OPT_MATCH ("-C")) { no_resconf = 1; } else if (OPT_MATCH ("-reverse") || OPT_MATCH ("-r")) { flags |= FLAG_REVERSE; } else if (OPT_MATCH ("-nolocalmap") || OPT_MATCH ("-L")) { flags &= ~FLAG_LOCALMAP; } else if (OPT_MATCH ("-nonameprep") || OPT_MATCH ("-N")) { flags &= ~FLAG_NAMEPREP; } else if (OPT_MATCH ("-unassigncheck") || OPT_MATCH ("-u")) { flags |= FLAG_UNASSIGNCHECK; } else if (OPT_MATCH ("-nounassigncheck") || OPT_MATCH ("-U")) { flags &= ~FLAG_UNASSIGNCHECK; } else if (OPT_MATCH ("-nobidicheck") || OPT_MATCH ("-B")) { flags &= ~FLAG_BIDICHECK; } else if (OPT_MATCH ("-noasciicheck") || OPT_MATCH ("-A")) { flags &= ~FLAG_ASCIICHECK; } else if (OPT_MATCH ("-nolengthcheck")) { flags &= ~FLAG_LENGTHCHECK; } else if (OPT_MATCH ("-noroundtripcheck")) { flags &= ~FLAG_ROUNDTRIPCHECK; } else if (OPT_MATCH ("-whole") || OPT_MATCH ("-w")) { flags &= ~FLAG_SELECTIVE; } else if (OPT_MATCH ("-localmap")) { MUST_HAVE_ARG; APPEND_LIST (localmappers, nlocalmappers, av[1], "local maps"); } else if (OPT_MATCH ("-delimiter")) { unsigned long v; MUST_HAVE_ARG; v = get_ucs (av[1]); APPEND_LIST (delimiters, ndelimiters, v, "delimiter maps"); } else if (OPT_MATCH ("-alias") || OPT_MATCH ("-a")) { MUST_HAVE_ARG; encoding_alias = av[1]; ac--; av++; } else if (OPT_MATCH ("-flush")) { flush_every_line = 1; } else if (OPT_MATCH ("-version") || OPT_MATCH ("-v")) { print_version (); } else { print_usage (cmd); } #undef OPT_MATCH #undef MUST_HAVE_ARG #undef APPEND_LIST ac--; av++; } if (ac > 1) print_usage (cmd); /* Initialize. */ if ((r = idn_resconf_initialize ()) != idn_success) { errormsg ("error initializing library\n"); return (1); } /* * Create resource contexts. * `resconf1' and `resconf2' are almost the same but local and * IDN encodings are reversed. */ resconf1 = NULL; resconf2 = NULL; if (idn_resconf_create (&resconf1) != idn_success || idn_resconf_create (&resconf2) != idn_success) { errormsg ("error initializing configuration contexts\n"); return (1); } /* Load configuration file. */ if (no_resconf) { set_defaults (resconf1); set_defaults (resconf2); } else { load_conf_file (resconf1, resconf_file); load_conf_file (resconf2, resconf_file); } /* Set encoding alias file. */ if (encoding_alias != NULL) set_encoding_alias (encoding_alias); /* Set input codeset. */ if (flags & FLAG_REVERSE) { if (in_code == NULL) { conv = idn_resconf_getidnconverter (resconf1); if (conv == NULL) { errormsg ("cannot get the IDN encoding.\n" "please specify an appropriate one " "with `-in' option.\n"); exit (1); } idn_resconf_setlocalconverter (resconf2, conv); idn_converter_destroy (conv); } else { set_idncode (resconf1, in_code); set_localcode (resconf2, in_code); } } else { if (in_code == NULL) { conv = idn_resconf_getlocalconverter (resconf1); if (conv == NULL) { errormsg ("cannot get the local encoding.\n" "please specify an appropriate one " "with `-in' option.\n"); exit (1); } idn_resconf_setidnconverter (resconf2, conv); idn_converter_destroy (conv); } else { set_localcode (resconf1, in_code); set_idncode (resconf2, in_code); } } /* Set output codeset. */ if (flags & FLAG_REVERSE) { if (out_code == NULL) { conv = idn_resconf_getlocalconverter (resconf1); if (conv == NULL) { errormsg ("cannot get the local encoding.\n" "please specify an appropriate one " "with `-out' option.\n"); exit (1); } idn_resconf_setidnconverter (resconf2, conv); idn_converter_destroy (conv); } else { set_localcode (resconf1, out_code); set_idncode (resconf2, out_code); } } else { if (out_code == NULL) { conv = idn_resconf_getidnconverter (resconf1); if (conv == NULL) { errormsg ("cannot get the IDN encoding.\n" "please specify an appropriate one " "with `-out' option.\n"); exit (1); } idn_resconf_setlocalconverter (resconf2, conv); idn_converter_destroy (conv); } else { set_idncode (resconf1, out_code); set_localcode (resconf2, out_code); } } /* Set delimiter map(s). */ if (ndelimiters > 0) { set_delimitermapper (resconf1, delimiters, ndelimiters); set_delimitermapper (resconf2, delimiters, ndelimiters); } /* Set local map(s). */ if (nlocalmappers > 0) { set_localmapper (resconf1, localmappers, nlocalmappers); set_localmapper (resconf2, localmappers, nlocalmappers); } /* Set NAMEPREP version. */ if (nameprep_version != NULL) { set_nameprep (resconf1, nameprep_version); set_nameprep (resconf2, nameprep_version); } idn_res_enable (1); /* Open input file. */ if (ac > 0) { if ((fp = fopen (av[0], "r")) == NULL) { errormsg ("cannot open file %s: %s\n", av[0], strerror (errno)); return (1); } } else { fp = stdin; } /* Do the conversion. */ if (flags & FLAG_REVERSE) exit_value = decode_file (resconf1, resconf2, fp, flags); else exit_value = encode_file (resconf1, resconf2, fp, flags); idn_resconf_destroy (resconf1); idn_resconf_destroy (resconf2); return exit_value; }
idn_result_t idn_res_decodename(idn_resconf_t ctx, idn_action_t actions, const char *from, char *to, size_t tolen) { idn_converter_t local_converter = NULL; idn_converter_t idn_converter = NULL; idn_delimitermap_t delimiter_mapper; idn_result_t r; labellist_t labels = NULL, l; unsigned long *buffer = NULL; unsigned long *saved_name = NULL; size_t buffer_length; int idn_is_ace; assert(ctx != NULL && from != NULL && to != NULL); TRACE(("idn_res_decodename(actions=%s, from=\"%s\", tolen=%d)\n", idn__res_actionstostring(actions), idn__debug_xstring(from, 50), (int)tolen)); if (actions & ~DECODE_MASK) { WARNING(("idn_res_decodename: invalid actions 0x%x\n", actions)); r = idn_invalid_action; goto ret; } if (!initialized) idn_res_initialize(); if (!enabled || actions == 0) { r = copy_verbatim(from, to, tolen); goto ret; } else if (tolen <= 0) { r = idn_buffer_overflow; goto ret; } if (actions & IDN_DECODE_QUERY) { #ifndef WITHOUT_ICONV actions |= (IDN_DELIMMAP | IDN_MAP | IDN_NORMALIZE | \ IDN_PROHCHECK | IDN_BIDICHECK | IDN_IDNCONV | \ IDN_RTCHECK | IDN_LOCALCONV); #else actions |= (IDN_DELIMMAP | IDN_MAP | IDN_NORMALIZE | \ IDN_PROHCHECK | IDN_BIDICHECK | IDN_IDNCONV | \ IDN_RTCHECK); #endif } /* * Convert `from' to UCS4. */ local_converter = idn_resconf_getlocalconverter(ctx); #ifndef WITHOUT_ICONV if (local_converter == NULL) { r = idn_invalid_name; goto ret; } #endif idn_converter = idn_resconf_getidnconverter(ctx); if (idn_converter != NULL && idn_converter_isasciicompatible(idn_converter)) idn_is_ace = 1; else idn_is_ace = 0; buffer_length = tolen * 2; TRACE(("res idndecode(name=\"%s\")\n", idn__debug_xstring(from, 50))); for (;;) { void *new_buffer; new_buffer = realloc(buffer, sizeof(*buffer) * buffer_length); if (new_buffer == NULL) { r = idn_nomemory; goto ret; } buffer = (unsigned long *)new_buffer; if ((actions & IDN_IDNCONV) && idn_converter != NULL && !idn_is_ace) { r = idn_converter_convtoucs4(idn_converter, from, buffer, buffer_length); } else { r = idn_ucs4_utf8toucs4(from, buffer, buffer_length); } if (r == idn_success) break; else if (r != idn_buffer_overflow) goto ret; buffer_length *= 2; } if (*buffer == '\0') { if (tolen <= 0) { r = idn_buffer_overflow; goto ret; } *to = '\0'; r = idn_success; goto ret; } /* * Delimiter map. */ if (actions & IDN_DELIMMAP) { TRACE(("res delimitermap(name=\"%s\")\n", idn__debug_ucs4xstring(buffer, 50))); delimiter_mapper = idn_resconf_getdelimitermap(ctx); if (delimiter_mapper != NULL) { r = idn_delimitermap_map(delimiter_mapper, buffer, buffer, buffer_length); idn_delimitermap_destroy(delimiter_mapper); if (r != idn_success) goto ret; } TRACE(("res delimitermap(): success (name=\"%s\")\n", idn__debug_ucs4xstring(buffer, 50))); } /* * Split the name into a list of labels. */ r = labellist_create(buffer, &labels); if (r != idn_success) goto ret; /* * Perform conversions and tests. */ for (l = labellist_tail(labels); l != NULL; l = labellist_previous(l)) { free(saved_name); saved_name = NULL; if (!idn__util_ucs4isasciirange(labellist_getname(l))) { if (actions & IDN_MAP) { r = label_map(ctx, l); if (r != idn_success) goto ret; } if (actions & IDN_NORMALIZE) { r = label_normalize(ctx, l); if (r != idn_success) goto ret; } if (actions & IDN_PROHCHECK) { r = label_prohcheck(ctx, l); if (r == idn_prohibited) { labellist_undo(l); continue; } else if (r != idn_success) { goto ret; } } if (actions & IDN_UNASCHECK) { r = label_unascheck(ctx, l); if (r == idn_prohibited) { labellist_undo(l); continue; } else if (r != idn_success) { goto ret; } } if (actions & IDN_BIDICHECK) { r = label_bidicheck(ctx, l); if (r == idn_prohibited) { labellist_undo(l); continue; } else if (r != idn_success) { goto ret; } } } if ((actions & IDN_IDNCONV) && idn_is_ace) { saved_name = idn_ucs4_strdup(labellist_getname(l)); if (saved_name == NULL) { r = idn_nomemory; goto ret; } r = label_idndecode(ctx, l); if (r == idn_invalid_encoding) { labellist_undo(l); continue; } else if (r != idn_success) { goto ret; } } if ((actions & IDN_RTCHECK) && saved_name != NULL) { r = label_rtcheck(ctx, actions, l, saved_name); if (r == idn_invalid_encoding) { labellist_undo(l); continue; } else if (r != idn_success) { goto ret; } } #ifndef WITHOUT_ICONV if (actions & IDN_LOCALCONV) { r = label_localdecodecheck(ctx, l); if (r != idn_success) goto ret; } #endif } /* * Concat a list of labels to a name. */ for (;;) { void *new_buffer; new_buffer = realloc(buffer, sizeof(*buffer) * buffer_length); if (new_buffer == NULL) { r = idn_nomemory; goto ret; } buffer = (unsigned long *)new_buffer; r = labellist_getnamelist(labels, buffer, buffer_length); if (r == idn_success) break; else if (r != idn_buffer_overflow) goto ret; buffer_length *= 2; } if (actions & IDN_LOCALCONV) { r = idn_converter_convfromucs4(local_converter, buffer, to, tolen); } else { r = idn_ucs4_ucs4toutf8(buffer, to, tolen); } ret: if (r == idn_success) { TRACE(("idn_res_decodename(): success (to=\"%s\")\n", idn__debug_xstring(to, 50))); } else { TRACE(("idn_res_decodename(): %s\n", idn_result_tostring(r))); } free(saved_name); free(buffer); if (local_converter != NULL) idn_converter_destroy(local_converter); if (idn_converter != NULL) idn_converter_destroy(idn_converter); if (labels != NULL) labellist_destroy(labels); return (r); }
static idn_result_t label_idnencode_ace(idn_resconf_t ctx, labellist_t label) { idn_converter_t idn_converter = NULL; const unsigned long *from; char *ascii_to = NULL; unsigned long *to = NULL; size_t to_length; idn_result_t r; from = labellist_getname(label); TRACE(("res ucs4toidn(label=\"%s\")\n", idn__debug_ucs4xstring(from, 50))); idn_converter = idn_resconf_getidnconverter(ctx); if (idn_converter == NULL) { r = idn_success; goto ret; } ascii_to = NULL; to_length = idn_ucs4_strlen(from) * 4 + 16; /* add mergin */ for (;;) { char *new_buffer; new_buffer = (char *) realloc(ascii_to, to_length); if (new_buffer == NULL) { r = idn_nomemory; goto ret; } ascii_to = new_buffer; r = idn_converter_convfromucs4(idn_converter, from, ascii_to, to_length); if (r == idn_success) break; else if (r != idn_buffer_overflow) goto ret; to_length *= 2; } for (;;) { unsigned long *new_buffer; new_buffer = (unsigned long *) realloc(to, sizeof(long) * to_length); if (new_buffer == NULL) { r = idn_nomemory; goto ret; } to = new_buffer; r = idn_ucs4_utf8toucs4(ascii_to, to, to_length); if (r == idn_success) break; else if (r != idn_buffer_overflow) goto ret; to_length *= 2; } if (r != idn_success) goto ret; r = labellist_setname(label, to); ret: if (r == idn_success) { TRACE(("res ucs4toidn(): success (label=\"%s\")\n", idn__debug_ucs4xstring(labellist_getname(label), 50))); } else { TRACE(("res ucs4toidn(): %s\n", idn_result_tostring(r))); } if (idn_converter != NULL) idn_converter_destroy(idn_converter); free(to); free(ascii_to); return (r); }