📄 converter.c
字号:
#ifndef lintstatic char *rcsid = "$Id: converter.c,v 1.1.1.1 2003/06/04 00:25:51 marka Exp $";#endif/* * Copyright (c) 2000,2002 Japan Network Information Center. * All rights reserved. * * By using this file, you agree to the terms and conditions set forth bellow. * * LICENSE TERMS AND CONDITIONS * * The following License Terms and Conditions apply, unless a different * license is obtained from Japan Network Information Center ("JPNIC"), * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda, * Chiyoda-ku, Tokyo 101-0047, Japan. * * 1. Use, Modification and Redistribution (including distribution of any * modified or derived work) in source and/or binary forms is permitted * under this License Terms and Conditions. * * 2. Redistribution of source code must retain the copyright notices as they * appear in each source code file, this License Terms and Conditions. * * 3. Redistribution in binary form must reproduce the Copyright Notice, * this License Terms and Conditions, in the documentation and/or other * materials provided with the distribution. For the purposes of binary * distribution the "Copyright Notice" refers to the following language: * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved." * * 4. The name of JPNIC may not be used to endorse or promote products * derived from this Software without specific prior written approval of * JPNIC. * * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */#include <config.h>#include <stddef.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <ctype.h>#include <errno.h>#ifndef WITHOUT_ICONV#include <iconv.h>#endif#include <idn/result.h>#include <idn/assert.h>#include <idn/logmacro.h>#include <idn/converter.h>#include <idn/aliaslist.h>#include <idn/strhash.h>#include <idn/debug.h>#include <idn/ucs4.h>#include <idn/punycode.h>#include <idn/race.h>#include <idn/util.h>#ifndef IDN_UTF8_ENCODING_NAME#define IDN_UTF8_ENCODING_NAME "UTF-8" /* by IANA */#endif#ifndef IDN_RACE_ENCODING_NAME#define IDN_RACE_ENCODING_NAME "RACE"#endif#ifndef IDN_AMCACEZ_ENCODING_NAME#define IDN_AMCACEZ_ENCODING_NAME "AMC-ACE-Z"#endif#ifndef IDN_PUNYCODE_ENCODING_NAME#define IDN_PUNYCODE_ENCODING_NAME "Punycode"#endif#define MAX_RECURSE 20#ifdef WIN32#define IDNKEY_IDNKIT "Software\\JPNIC\\IDN"#define IDNVAL_ALIASFILE "AliasFile"#else /* WIN32 */#ifndef IDN_RESCONF_DIR#define IDN_RESCONF_DIR "/etc"#endif#define IDN_ALIAS_FILE IDN_RESCONF_DIR "/idnalias.conf"#endif /* WIN32 */typedef struct { idn_converter_openproc_t openfromucs4; idn_converter_openproc_t opentoucs4; idn_converter_convfromucs4proc_t convfromucs4; idn_converter_convtoucs4proc_t convtoucs4; idn_converter_closeproc_t close; int encoding_type;} converter_ops_t;struct idn_converter { char *local_encoding_name; converter_ops_t *ops; int flags; int opened_convfromucs4; int opened_convtoucs4; int reference_count; void *private_data;};static idn__strhash_t encoding_name_hash;static idn__aliaslist_t encoding_alias_list;static idn_result_t register_standard_encoding(void);static idn_result_t roundtrip_check(idn_converter_t ctx, const unsigned long *from, const char *to);static idn_result_t converter_none_open(idn_converter_t ctx, void **privdata);static idn_result_t converter_none_close(idn_converter_t ctx, void *privdata);static idn_result_t converter_none_convfromucs4(idn_converter_t ctx, void *privdata, const unsigned long *from, char *to, size_t tolen);static idn_result_t converter_none_convtoucs4(idn_converter_t ctx, void *privdata, const char *from, unsigned long *to, size_t tolen);#ifndef WITHOUT_ICONVstatic idn_result_t converter_iconv_openfromucs4(idn_converter_t ctx, void **privdata);static idn_result_t converter_iconv_opentoucs4(idn_converter_t ctx, void **privdata);static idn_result_t converter_iconv_close(idn_converter_t ctx, void *privdata);static idn_result_t converter_iconv_convfromucs4(idn_converter_t ctx, void *privdata, const unsigned long *from, char *to, size_t tolen);static idn_result_t converter_iconv_convtoucs4(idn_converter_t ctx, void *privdata, const char *from, unsigned long *to, size_t tolen);static idn_result_ticonv_initialize_privdata(void **privdata);static voidiconv_finalize_privdata(void *privdata);static char * get_system_aliasfile(void);static int file_exist(const char *filename);#endif /* !WITHOUT_ICONV */#ifdef DEBUGstatic idn_result_t converter_uescape_convfromucs4(idn_converter_t ctx, void *privdata, const unsigned long *from, char *to, size_t tolen);static idn_result_t converter_uescape_convtoucs4(idn_converter_t ctx, void *privdata, const char *from, unsigned long *to, size_t tolen);#endif /* DEBUG */static converter_ops_t none_converter_ops = { converter_none_open, converter_none_open, converter_none_convfromucs4, converter_none_convtoucs4, converter_none_close, IDN_NONACE,};#ifndef WITHOUT_ICONVstatic converter_ops_t iconv_converter_ops = { converter_iconv_openfromucs4, converter_iconv_opentoucs4, converter_iconv_convfromucs4, converter_iconv_convtoucs4, converter_iconv_close, IDN_NONACE,};#endif/* * Initialize. */idn_result_tidn_converter_initialize(void) { idn_result_t r; idn__strhash_t hash; idn__aliaslist_t list;#ifndef WITHOUT_ICONV const char *fname;#endif TRACE(("idn_converter_initialize()\n")); if (encoding_name_hash == NULL) { if ((r = idn__strhash_create(&hash)) != idn_success) goto ret; encoding_name_hash = hash; r = register_standard_encoding(); } if (encoding_alias_list == NULL) { if ((r = idn__aliaslist_create(&list)) != idn_success) goto ret; encoding_alias_list = list;#ifndef WITHOUT_ICONV fname = get_system_aliasfile(); if (fname != NULL && file_exist(fname)) idn_converter_aliasfile(fname);#endif } r = idn_success;ret: TRACE(("idn_converter_initialize(): %s\n", idn_result_tostring(r))); return (r);}#ifndef WITHOUT_ICONVstatic char *get_system_aliasfile() {#ifdef WIN32 static char alias_path[500]; /* a good longer than MAX_PATH */ if (idn__util_getregistrystring(idn__util_hkey_localmachine, IDNVAL_ALIASFILE, alias_path, sizeof(alias_path))) { return (alias_path); } else { return (NULL); }#else return (IDN_ALIAS_FILE);#endif}static intfile_exist(const char *filename) { FILE *fp; if ((fp = fopen(filename, "r")) == NULL) return (0); fclose(fp); return (1);}#endifidn_result_tidn_converter_create(const char *name, idn_converter_t *ctxp, int flags) { const char *realname; idn_converter_t ctx; idn_result_t r; void *v; assert(name != NULL && ctxp != NULL); TRACE(("idn_converter_create(%s)\n", name)); realname = idn_converter_getrealname(name);#ifdef DEBUG if (strcmp(name, realname) != 0) { TRACE(("idn_converter_create: realname=%s\n", realname)); }#endif *ctxp = NULL; /* Allocate memory for a converter context and the name. */ ctx = malloc(sizeof(struct idn_converter) + strlen(realname) + 1); if (ctx == NULL) { r = idn_nomemory; goto ret; } ctx->local_encoding_name = (char *)(ctx + 1); (void)strcpy(ctx->local_encoding_name, realname); ctx->flags = flags; ctx->reference_count = 1; ctx->opened_convfromucs4 = 0; ctx->opened_convtoucs4 = 0; ctx->private_data = NULL; assert(encoding_name_hash != NULL); if (strcmp(realname, IDN_UTF8_ENCODING_NAME) == 0) { /* No conversion needed */ ctx->ops = &none_converter_ops; } else if ((r = idn__strhash_get(encoding_name_hash, realname, &v)) == idn_success) { /* Special converter found */ ctx->ops = (converter_ops_t *)v; } else { /* General case */#ifdef WITHOUT_ICONV free(ctx); *ctxp = NULL; r = idn_invalid_name; goto ret;#else ctx->ops = &iconv_converter_ops;#endif } if ((flags & IDN_CONVERTER_DELAYEDOPEN) == 0) { r = (ctx->ops->openfromucs4)(ctx, &(ctx->private_data)); if (r != idn_success) { WARNING(("idn_converter_create(): open failed " "(ucs4->local)\n")); free(ctx); *ctxp = NULL; goto ret; } ctx->opened_convfromucs4 = 1; r = (*ctx->ops->opentoucs4)(ctx, &(ctx->private_data)); if (r != idn_success) { WARNING(("idn_converter_create(): open failed " "(local->ucs4)\n")); free(ctx); *ctxp = NULL; goto ret; } ctx->opened_convtoucs4 = 1; } *ctxp = ctx; r = idn_success;ret: TRACE(("idn_converter_create(): %s\n", idn_result_tostring(r))); return (r);}voididn_converter_destroy(idn_converter_t ctx) { assert(ctx != NULL); TRACE(("idn_converter_destroy(ctx=%s)\n", ctx->local_encoding_name)); ctx->reference_count--; if (ctx->reference_count <= 0) { TRACE(("idn_converter_destroy(): the object is destroyed\n")); (void)(*ctx->ops->close)(ctx, ctx->private_data); free(ctx); } else { TRACE(("idn_converter_destroy(): " "update reference count (%d->%d)\n", ctx->reference_count + 1, ctx->reference_count)); }}voididn_converter_incrref(idn_converter_t ctx) { assert(ctx != NULL); TRACE(("idn_converter_incrref(ctx=%s)\n", ctx->local_encoding_name)); TRACE(("idn_converter_incrref: update reference count (%d->%d)\n", ctx->reference_count, ctx->reference_count + 1)); ctx->reference_count++;}char *idn_converter_localencoding(idn_converter_t ctx) { assert(ctx != NULL); TRACE(("idn_converter_localencoding(ctx=%s)\n", ctx->local_encoding_name)); return (ctx->local_encoding_name);} intidn_converter_encodingtype(idn_converter_t ctx) { int encoding_type; assert(ctx != NULL); TRACE(("idn_converter_encodingtype(ctx=%s)\n", ctx->local_encoding_name)); encoding_type = ctx->ops->encoding_type; TRACE(("idn_converter_encodingtype(): %d\n", encoding_type)); return (encoding_type);}intidn_converter_isasciicompatible(idn_converter_t ctx) { int iscompat; assert(ctx != NULL); TRACE(("idn_converter_isasciicompatible(ctx=%s)\n", ctx->local_encoding_name)); iscompat = (ctx->ops->encoding_type != IDN_NONACE); TRACE(("idn_converter_isasciicompatible(): %d\n", iscompat)); return (iscompat);}idn_result_tidn_converter_convfromucs4(idn_converter_t ctx, const unsigned long *from, char *to, size_t tolen) { idn_result_t r; assert(ctx != NULL && from != NULL && to != NULL); TRACE(("idn_converter_convfromucs4(ctx=%s, from=\"%s\", tolen=%d)\n", ctx->local_encoding_name, idn__debug_ucs4xstring(from, 50), (int)tolen)); if (!ctx->opened_convfromucs4) { r = (*ctx->ops->openfromucs4)(ctx, &(ctx->private_data)); if (r != idn_success) goto ret; ctx->opened_convfromucs4 = 1; } r = (*ctx->ops->convfromucs4)(ctx, ctx->private_data, from, to, tolen); if (r != idn_success) goto ret; if ((ctx->flags & IDN_CONVERTER_RTCHECK) != 0) { r = roundtrip_check(ctx, from, to); if (r != idn_success) goto ret; } r = idn_success;ret: if (r == idn_success) { TRACE(("idn_converter_convfromucs4(): success (to=\"%s\")\n", idn__debug_xstring(to, 50))); } else { TRACE(("idn_converter_convfromucs4(): %s\n", idn_result_tostring(r))); } return (r);}idn_result_tidn_converter_convtoucs4(idn_converter_t ctx, const char *from, unsigned long *to, size_t tolen) { idn_result_t r; assert(ctx != NULL && from != NULL && to != NULL); TRACE(("idn_converter_convtoucs4(ctx=%s, from=\"%s\", tolen=%d)\n", ctx->local_encoding_name, idn__debug_xstring(from, 50), (int)tolen)); if (!ctx->opened_convtoucs4) { r = (*ctx->ops->opentoucs4)(ctx, &(ctx->private_data)); if (r != idn_success) goto ret; ctx->opened_convtoucs4 = 1; } r = (*ctx->ops->convtoucs4)(ctx, ctx->private_data, from, to, tolen);ret: if (r == idn_success) { TRACE(("idn_converter_convtoucs4(): success (to=\"%s\")\n", idn__debug_ucs4xstring(to, 50))); } else { TRACE(("idn_converter_convtoucs4(): %s\n", idn_result_tostring(r))); } return (r);}/* * Encoding registration. */idn_result_tidn_converter_register(const char *name, idn_converter_openproc_t openfromucs4, idn_converter_openproc_t opentoucs4, idn_converter_convfromucs4proc_t convfromucs4, idn_converter_convtoucs4proc_t convtoucs4, idn_converter_closeproc_t close, int encoding_type) { converter_ops_t *ops; idn_result_t r; assert(name != NULL && convfromucs4 != NULL && convtoucs4 != NULL); TRACE(("idn_converter_register(name=%s)\n", name)); if ((ops = malloc(sizeof(*ops))) == NULL) { r = idn_nomemory; goto ret; } if (openfromucs4 == NULL) openfromucs4 = converter_none_open; if (opentoucs4 == NULL) opentoucs4 = converter_none_open; if (close == NULL) close = converter_none_close; ops->openfromucs4 = openfromucs4; ops->opentoucs4 = opentoucs4; ops->convfromucs4 = convfromucs4; ops->convtoucs4 = convtoucs4; ops->close = close; ops->encoding_type = encoding_type; r = idn__strhash_put(encoding_name_hash, name, ops); if (r != idn_success) { free(ops); goto ret; } r = idn_success;ret: TRACE(("idn_converter_register(): %s\n", idn_result_tostring(r))); return (r);}static idn_result_tregister_standard_encoding(void) { idn_result_t r; r = idn_converter_register(IDN_PUNYCODE_ENCODING_NAME, NULL, NULL, idn__punycode_encode, idn__punycode_decode, converter_none_close, IDN_ACE_STRICTCASE); if (r != idn_success) return (r);#ifdef IDN_EXTRA_ACE r = idn_converter_register(IDN_AMCACEZ_ENCODING_NAME, NULL, NULL, idn__punycode_encode, idn__punycode_decode, converter_none_close, IDN_ACE_STRICTCASE); if (r != idn_success) return (r); r = idn_converter_register(IDN_RACE_ENCODING_NAME, NULL, NULL, idn__race_encode, idn__race_decode, converter_none_close, IDN_ACE_LOOSECASE); if (r != idn_success) return (r);#endif /* IDN_EXTRA_ACE */#ifdef DEBUG /* This is convenient for debug. Not useful for other purposes. */ r = idn_converter_register("U-escape", NULL, NULL, converter_uescape_convfromucs4, converter_uescape_convtoucs4, NULL, IDN_NONACE); if (r != idn_success) return (r);#endif /* DEBUG */ return (r);}/* * Encoding alias support. */idn_result_tidn_converter_addalias(const char *alias_name, const char *real_name, int first_item) { idn_result_t r; assert(alias_name != NULL && real_name != NULL); TRACE(("idn_converter_addalias(alias_name=%s,real_name=%s)\n", alias_name, real_name)); if (strlen(alias_name) == 0 || strlen(real_name) == 0) { return idn_invalid_syntax; } if (strcmp(alias_name, real_name) == 0) { r = idn_success; goto ret; } if (encoding_alias_list == NULL) { WARNING(("idn_converter_addalias(): the module is not " "initialized\n")); r = idn_failure; goto ret; } r = idn__aliaslist_additem(encoding_alias_list, alias_name, real_name, first_item);ret: TRACE(("idn_converter_addalias(): %s\n", idn_result_tostring(r))); return (r);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -