blob: fe7384e6c876bfaab86c7416d00707b107d21a24 [file] [log] [blame]
/*-
* Copyright (c) 2000, Boris Popov. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Boris Popov
* and its contributors.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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 DAMAGE.
*
*/
#define ICONV_INTERNAL
#include "iconv.h"
#include "apr_file_io.h"
#include "apr_file_info.h"
#include "apr_pools.h"
#include "apr_dso.h"
#include "apr_env.h"
#include "apr_strings.h"
#include "apr_tables.h"
#include "apr_lib.h"
#include "api_version.h"
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef API_USE_BUILTIN_ALIASES
#include "charset_alias.h"
#endif
#define APR_ICONV_PATH "APR_ICONV" API_STRINGIFY(API_MAJOR_VERSION) "_PATH"
API_IMPORT_MODULE(_tbl_simple);
API_IMPORT_MODULE(adobe_stdenc);
API_IMPORT_MODULE(adobe_symbol);
API_IMPORT_MODULE(adobe_zdingbats);
API_IMPORT_MODULE(big5);
API_IMPORT_MODULE(cns11643_plane1);
API_IMPORT_MODULE(cns11643_plane14);
API_IMPORT_MODULE(cns11643_plane2);
API_IMPORT_MODULE(cp037);
API_IMPORT_MODULE(cp038);
API_IMPORT_MODULE(cp10000);
API_IMPORT_MODULE(cp10006);
API_IMPORT_MODULE(cp10007);
API_IMPORT_MODULE(cp10029);
API_IMPORT_MODULE(cp1006);
API_IMPORT_MODULE(cp10079);
API_IMPORT_MODULE(cp10081);
API_IMPORT_MODULE(cp1026);
API_IMPORT_MODULE(cp273);
API_IMPORT_MODULE(cp274);
API_IMPORT_MODULE(cp275);
API_IMPORT_MODULE(cp277);
API_IMPORT_MODULE(cp278);
API_IMPORT_MODULE(cp280);
API_IMPORT_MODULE(cp281);
API_IMPORT_MODULE(cp284);
API_IMPORT_MODULE(cp285);
API_IMPORT_MODULE(cp290);
API_IMPORT_MODULE(cp297);
API_IMPORT_MODULE(cp420);
API_IMPORT_MODULE(cp423);
API_IMPORT_MODULE(cp424);
API_IMPORT_MODULE(cp437);
API_IMPORT_MODULE(cp500);
API_IMPORT_MODULE(cp737);
API_IMPORT_MODULE(cp775);
API_IMPORT_MODULE(cp850);
API_IMPORT_MODULE(cp851);
API_IMPORT_MODULE(cp852);
API_IMPORT_MODULE(cp855);
API_IMPORT_MODULE(cp856);
API_IMPORT_MODULE(cp857);
API_IMPORT_MODULE(cp860);
API_IMPORT_MODULE(cp861);
API_IMPORT_MODULE(cp862);
API_IMPORT_MODULE(cp863);
API_IMPORT_MODULE(cp864);
API_IMPORT_MODULE(cp865);
API_IMPORT_MODULE(cp866);
API_IMPORT_MODULE(cp868);
API_IMPORT_MODULE(cp869);
API_IMPORT_MODULE(cp870);
API_IMPORT_MODULE(cp871);
API_IMPORT_MODULE(cp874);
API_IMPORT_MODULE(cp875);
API_IMPORT_MODULE(cp880);
API_IMPORT_MODULE(cp891);
API_IMPORT_MODULE(cp903);
API_IMPORT_MODULE(cp904);
API_IMPORT_MODULE(cp905);
API_IMPORT_MODULE(cp918);
API_IMPORT_MODULE(cp932);
API_IMPORT_MODULE(cp936);
API_IMPORT_MODULE(cp949);
API_IMPORT_MODULE(cp950);
API_IMPORT_MODULE(dec_mcs);
API_IMPORT_MODULE(ebcdic_at_de);
API_IMPORT_MODULE(ebcdic_at_de_a);
API_IMPORT_MODULE(ebcdic_ca_fr);
API_IMPORT_MODULE(ebcdic_dk_no);
API_IMPORT_MODULE(ebcdic_dk_no_a);
API_IMPORT_MODULE(ebcdic_es);
API_IMPORT_MODULE(ebcdic_es_a);
API_IMPORT_MODULE(ebcdic_es_s);
API_IMPORT_MODULE(ebcdic_fi_se);
API_IMPORT_MODULE(ebcdic_fi_se_a);
API_IMPORT_MODULE(ebcdic_fr);
API_IMPORT_MODULE(ebcdic_it);
API_IMPORT_MODULE(ebcdic_pt);
API_IMPORT_MODULE(ebcdic_uk);
API_IMPORT_MODULE(ebcdic_us);
API_IMPORT_MODULE(euc_jp);
API_IMPORT_MODULE(euc_kr);
API_IMPORT_MODULE(euc_tw);
API_IMPORT_MODULE(gb12345);
API_IMPORT_MODULE(gb2312);
API_IMPORT_MODULE(gb_2312_80);
API_IMPORT_MODULE(hp_roman8);
API_IMPORT_MODULE(iso646_dk);
API_IMPORT_MODULE(iso646_kr);
API_IMPORT_MODULE(iso_10646_ucs_2);
API_IMPORT_MODULE(iso_10646_ucs_4);
API_IMPORT_MODULE(iso_2022_cn);
API_IMPORT_MODULE(iso_2022_jp);
API_IMPORT_MODULE(iso_2022_jp_2);
API_IMPORT_MODULE(iso_2022_kr);
API_IMPORT_MODULE(iso_8859_1);
API_IMPORT_MODULE(iso_8859_10);
API_IMPORT_MODULE(iso_8859_13);
API_IMPORT_MODULE(iso_8859_14);
API_IMPORT_MODULE(iso_8859_15);
API_IMPORT_MODULE(iso_8859_2);
API_IMPORT_MODULE(iso_8859_3);
API_IMPORT_MODULE(iso_8859_4);
API_IMPORT_MODULE(iso_8859_5);
API_IMPORT_MODULE(iso_8859_6);
API_IMPORT_MODULE(iso_8859_7);
API_IMPORT_MODULE(iso_8859_8);
API_IMPORT_MODULE(iso_8859_9);
API_IMPORT_MODULE(iso_ir_10);
API_IMPORT_MODULE(iso_ir_102);
API_IMPORT_MODULE(iso_ir_103);
API_IMPORT_MODULE(iso_ir_11);
API_IMPORT_MODULE(iso_ir_111);
API_IMPORT_MODULE(iso_ir_121);
API_IMPORT_MODULE(iso_ir_122);
API_IMPORT_MODULE(iso_ir_123);
API_IMPORT_MODULE(iso_ir_128);
API_IMPORT_MODULE(iso_ir_13);
API_IMPORT_MODULE(iso_ir_139);
API_IMPORT_MODULE(iso_ir_14);
API_IMPORT_MODULE(iso_ir_141);
API_IMPORT_MODULE(iso_ir_142);
API_IMPORT_MODULE(iso_ir_143);
API_IMPORT_MODULE(iso_ir_146);
API_IMPORT_MODULE(iso_ir_147);
API_IMPORT_MODULE(iso_ir_15);
API_IMPORT_MODULE(iso_ir_150);
API_IMPORT_MODULE(iso_ir_151);
API_IMPORT_MODULE(iso_ir_152);
API_IMPORT_MODULE(iso_ir_153);
API_IMPORT_MODULE(iso_ir_154);
API_IMPORT_MODULE(iso_ir_155);
API_IMPORT_MODULE(iso_ir_158);
API_IMPORT_MODULE(iso_ir_16);
API_IMPORT_MODULE(iso_ir_17);
API_IMPORT_MODULE(iso_ir_18);
API_IMPORT_MODULE(iso_ir_19);
API_IMPORT_MODULE(iso_ir_2);
API_IMPORT_MODULE(iso_ir_21);
API_IMPORT_MODULE(iso_ir_25);
API_IMPORT_MODULE(iso_ir_27);
API_IMPORT_MODULE(iso_ir_37);
API_IMPORT_MODULE(iso_ir_4);
API_IMPORT_MODULE(iso_ir_47);
API_IMPORT_MODULE(iso_ir_49);
API_IMPORT_MODULE(iso_ir_50);
API_IMPORT_MODULE(iso_ir_51);
API_IMPORT_MODULE(iso_ir_54);
API_IMPORT_MODULE(iso_ir_55);
API_IMPORT_MODULE(iso_ir_57);
API_IMPORT_MODULE(iso_ir_60);
API_IMPORT_MODULE(iso_ir_61);
API_IMPORT_MODULE(iso_ir_69);
API_IMPORT_MODULE(iso_ir_70);
API_IMPORT_MODULE(iso_ir_84);
API_IMPORT_MODULE(iso_ir_85);
API_IMPORT_MODULE(iso_ir_86);
API_IMPORT_MODULE(iso_ir_88);
API_IMPORT_MODULE(iso_ir_89);
API_IMPORT_MODULE(iso_ir_8_1);
API_IMPORT_MODULE(iso_ir_8_2);
API_IMPORT_MODULE(iso_ir_90);
API_IMPORT_MODULE(iso_ir_91);
API_IMPORT_MODULE(iso_ir_92);
API_IMPORT_MODULE(iso_ir_93);
API_IMPORT_MODULE(iso_ir_94);
API_IMPORT_MODULE(iso_ir_95);
API_IMPORT_MODULE(iso_ir_96);
API_IMPORT_MODULE(iso_ir_98);
API_IMPORT_MODULE(iso_ir_99);
API_IMPORT_MODULE(iso_ir_9_1);
API_IMPORT_MODULE(iso_ir_9_2);
API_IMPORT_MODULE(jis_x0201);
API_IMPORT_MODULE(jis_x0208_1983);
API_IMPORT_MODULE(jis_x0212_1990);
API_IMPORT_MODULE(johab);
API_IMPORT_MODULE(koi8_r);
API_IMPORT_MODULE(koi8_ru);
API_IMPORT_MODULE(koi8_u);
API_IMPORT_MODULE(ksx1001);
API_IMPORT_MODULE(mac_ce);
API_IMPORT_MODULE(mac_croatian);
API_IMPORT_MODULE(mac_cyrillic);
API_IMPORT_MODULE(mac_dingbats);
API_IMPORT_MODULE(mac_greek);
API_IMPORT_MODULE(mac_iceland);
API_IMPORT_MODULE(mac_japan);
API_IMPORT_MODULE(mac_roman);
API_IMPORT_MODULE(mac_romania);
API_IMPORT_MODULE(mac_thai);
API_IMPORT_MODULE(mac_turkish);
API_IMPORT_MODULE(mac_ukraine);
API_IMPORT_MODULE(macintosh);
API_IMPORT_MODULE(osd_ebcdic_df04_1);
API_IMPORT_MODULE(osd_ebcdic_df04_15);
API_IMPORT_MODULE(shift_jis);
API_IMPORT_MODULE(ucs2_internal);
API_IMPORT_MODULE(ucs4_internal);
API_IMPORT_MODULE(unicode_1_1_utf_7);
API_IMPORT_MODULE(us_ascii);
API_IMPORT_MODULE(utf_16);
API_IMPORT_MODULE(utf_8);
API_IMPORT_MODULE(windows_1250);
API_IMPORT_MODULE(windows_1251);
API_IMPORT_MODULE(windows_1252);
API_IMPORT_MODULE(windows_1253);
API_IMPORT_MODULE(windows_1254);
API_IMPORT_MODULE(windows_1255);
API_IMPORT_MODULE(windows_1256);
API_IMPORT_MODULE(windows_1257);
API_IMPORT_MODULE(windows_1258);
static struct static_iconv_module {
const char *name;
int present;
iconv_module_desc_t *module;
} const static_iconv_modules[] = {
{ "_tbl_simple", API_USE_MODULE(_tbl_simple) },
{ "adobe-stdenc", API_USE_MODULE(adobe_stdenc) },
{ "adobe-symbol", API_USE_MODULE(adobe_symbol) },
{ "adobe-zdingbats", API_USE_MODULE(adobe_zdingbats) },
{ "big5", API_USE_MODULE(big5) },
{ "cns11643-plane1", API_USE_MODULE(cns11643_plane1) },
{ "cns11643-plane14", API_USE_MODULE(cns11643_plane14) },
{ "cns11643-plane2", API_USE_MODULE(cns11643_plane2) },
{ "cp037", API_USE_MODULE(cp037) },
{ "cp038", API_USE_MODULE(cp038) },
{ "cp10000", API_USE_MODULE(cp10000) },
{ "cp10006", API_USE_MODULE(cp10006) },
{ "cp10007", API_USE_MODULE(cp10007) },
{ "cp10029", API_USE_MODULE(cp10029) },
{ "cp1006", API_USE_MODULE(cp1006) },
{ "cp10079", API_USE_MODULE(cp10079) },
{ "cp10081", API_USE_MODULE(cp10081) },
{ "cp1026", API_USE_MODULE(cp1026) },
{ "cp273", API_USE_MODULE(cp273) },
{ "cp274", API_USE_MODULE(cp274) },
{ "cp275", API_USE_MODULE(cp275) },
{ "cp277", API_USE_MODULE(cp277) },
{ "cp278", API_USE_MODULE(cp278) },
{ "cp280", API_USE_MODULE(cp280) },
{ "cp281", API_USE_MODULE(cp281) },
{ "cp284", API_USE_MODULE(cp284) },
{ "cp285", API_USE_MODULE(cp285) },
{ "cp290", API_USE_MODULE(cp290) },
{ "cp297", API_USE_MODULE(cp297) },
{ "cp420", API_USE_MODULE(cp420) },
{ "cp423", API_USE_MODULE(cp423) },
{ "cp424", API_USE_MODULE(cp424) },
{ "cp437", API_USE_MODULE(cp437) },
{ "cp500", API_USE_MODULE(cp500) },
{ "cp737", API_USE_MODULE(cp737) },
{ "cp775", API_USE_MODULE(cp775) },
{ "cp850", API_USE_MODULE(cp850) },
{ "cp851", API_USE_MODULE(cp851) },
{ "cp852", API_USE_MODULE(cp852) },
{ "cp855", API_USE_MODULE(cp855) },
{ "cp856", API_USE_MODULE(cp856) },
{ "cp857", API_USE_MODULE(cp857) },
{ "cp860", API_USE_MODULE(cp860) },
{ "cp861", API_USE_MODULE(cp861) },
{ "cp862", API_USE_MODULE(cp862) },
{ "cp863", API_USE_MODULE(cp863) },
{ "cp864", API_USE_MODULE(cp864) },
{ "cp865", API_USE_MODULE(cp865) },
{ "cp866", API_USE_MODULE(cp866) },
{ "cp868", API_USE_MODULE(cp868) },
{ "cp869", API_USE_MODULE(cp869) },
{ "cp870", API_USE_MODULE(cp870) },
{ "cp871", API_USE_MODULE(cp871) },
{ "cp874", API_USE_MODULE(cp874) },
{ "cp875", API_USE_MODULE(cp875) },
{ "cp880", API_USE_MODULE(cp880) },
{ "cp891", API_USE_MODULE(cp891) },
{ "cp903", API_USE_MODULE(cp903) },
{ "cp904", API_USE_MODULE(cp904) },
{ "cp905", API_USE_MODULE(cp905) },
{ "cp918", API_USE_MODULE(cp918) },
{ "cp932", API_USE_MODULE(cp932) },
{ "cp936", API_USE_MODULE(cp936) },
{ "cp949", API_USE_MODULE(cp949) },
{ "cp950", API_USE_MODULE(cp950) },
{ "dec-mcs", API_USE_MODULE(dec_mcs) },
{ "ebcdic-at-de", API_USE_MODULE(ebcdic_at_de) },
{ "ebcdic-at-de-a", API_USE_MODULE(ebcdic_at_de_a) },
{ "ebcdic-ca-fr", API_USE_MODULE(ebcdic_ca_fr) },
{ "ebcdic-dk-no", API_USE_MODULE(ebcdic_dk_no) },
{ "ebcdic-dk-no-a", API_USE_MODULE(ebcdic_dk_no_a) },
{ "ebcdic-es", API_USE_MODULE(ebcdic_es) },
{ "ebcdic-es-a", API_USE_MODULE(ebcdic_es_a) },
{ "ebcdic-es-s", API_USE_MODULE(ebcdic_es_s) },
{ "ebcdic-fi-se", API_USE_MODULE(ebcdic_fi_se) },
{ "ebcdic-fi-se-a", API_USE_MODULE(ebcdic_fi_se_a) },
{ "ebcdic-fr", API_USE_MODULE(ebcdic_fr) },
{ "ebcdic-it", API_USE_MODULE(ebcdic_it) },
{ "ebcdic-pt", API_USE_MODULE(ebcdic_pt) },
{ "ebcdic-uk", API_USE_MODULE(ebcdic_uk) },
{ "ebcdic-us", API_USE_MODULE(ebcdic_us) },
{ "euc-jp", API_USE_MODULE(euc_jp) },
{ "euc-kr", API_USE_MODULE(euc_kr) },
{ "euc-tw", API_USE_MODULE(euc_tw) },
{ "gb12345", API_USE_MODULE(gb12345) },
{ "gb2312", API_USE_MODULE(gb2312) },
{ "gb_2312-80", API_USE_MODULE(gb_2312_80) },
{ "hp-roman8", API_USE_MODULE(hp_roman8) },
{ "iso646-dk", API_USE_MODULE(iso646_dk) },
{ "iso646-kr", API_USE_MODULE(iso646_kr) },
{ "iso-10646-ucs-2", API_USE_MODULE(iso_10646_ucs_2) },
{ "iso-10646-ucs-4", API_USE_MODULE(iso_10646_ucs_4) },
{ "iso-2022-cn", API_USE_MODULE(iso_2022_cn) },
{ "iso-2022-jp", API_USE_MODULE(iso_2022_jp) },
{ "iso-2022-jp-2", API_USE_MODULE(iso_2022_jp_2) },
{ "iso-2022-kr", API_USE_MODULE(iso_2022_kr) },
{ "iso-8859-1", API_USE_MODULE(iso_8859_1) },
{ "iso-8859-10", API_USE_MODULE(iso_8859_10) },
{ "iso-8859-13", API_USE_MODULE(iso_8859_13) },
{ "iso-8859-14", API_USE_MODULE(iso_8859_14) },
{ "iso-8859-15", API_USE_MODULE(iso_8859_15) },
{ "iso-8859-2", API_USE_MODULE(iso_8859_2) },
{ "iso-8859-3", API_USE_MODULE(iso_8859_3) },
{ "iso-8859-4", API_USE_MODULE(iso_8859_4) },
{ "iso-8859-5", API_USE_MODULE(iso_8859_5) },
{ "iso-8859-6", API_USE_MODULE(iso_8859_6) },
{ "iso-8859-7", API_USE_MODULE(iso_8859_7) },
{ "iso-8859-8", API_USE_MODULE(iso_8859_8) },
{ "iso-8859-9", API_USE_MODULE(iso_8859_9) },
{ "iso-ir-10", API_USE_MODULE(iso_ir_10) },
{ "iso-ir-102", API_USE_MODULE(iso_ir_102) },
{ "iso-ir-103", API_USE_MODULE(iso_ir_103) },
{ "iso-ir-11", API_USE_MODULE(iso_ir_11) },
{ "iso-ir-111", API_USE_MODULE(iso_ir_111) },
{ "iso-ir-121", API_USE_MODULE(iso_ir_121) },
{ "iso-ir-122", API_USE_MODULE(iso_ir_122) },
{ "iso-ir-123", API_USE_MODULE(iso_ir_123) },
{ "iso-ir-128", API_USE_MODULE(iso_ir_128) },
{ "iso-ir-13", API_USE_MODULE(iso_ir_13) },
{ "iso-ir-139", API_USE_MODULE(iso_ir_139) },
{ "iso-ir-14", API_USE_MODULE(iso_ir_14) },
{ "iso-ir-141", API_USE_MODULE(iso_ir_141) },
{ "iso-ir-142", API_USE_MODULE(iso_ir_142) },
{ "iso-ir-143", API_USE_MODULE(iso_ir_143) },
{ "iso-ir-146", API_USE_MODULE(iso_ir_146) },
{ "iso-ir-147", API_USE_MODULE(iso_ir_147) },
{ "iso-ir-15", API_USE_MODULE(iso_ir_15) },
{ "iso-ir-150", API_USE_MODULE(iso_ir_150) },
{ "iso-ir-151", API_USE_MODULE(iso_ir_151) },
{ "iso-ir-152", API_USE_MODULE(iso_ir_152) },
{ "iso-ir-153", API_USE_MODULE(iso_ir_153) },
{ "iso-ir-154", API_USE_MODULE(iso_ir_154) },
{ "iso-ir-155", API_USE_MODULE(iso_ir_155) },
{ "iso-ir-158", API_USE_MODULE(iso_ir_158) },
{ "iso-ir-16", API_USE_MODULE(iso_ir_16) },
{ "iso-ir-17", API_USE_MODULE(iso_ir_17) },
{ "iso-ir-18", API_USE_MODULE(iso_ir_18) },
{ "iso-ir-19", API_USE_MODULE(iso_ir_19) },
{ "iso-ir-2", API_USE_MODULE(iso_ir_2) },
{ "iso-ir-21", API_USE_MODULE(iso_ir_21) },
{ "iso-ir-25", API_USE_MODULE(iso_ir_25) },
{ "iso-ir-27", API_USE_MODULE(iso_ir_27) },
{ "iso-ir-37", API_USE_MODULE(iso_ir_37) },
{ "iso-ir-4", API_USE_MODULE(iso_ir_4) },
{ "iso-ir-47", API_USE_MODULE(iso_ir_47) },
{ "iso-ir-49", API_USE_MODULE(iso_ir_49) },
{ "iso-ir-50", API_USE_MODULE(iso_ir_50) },
{ "iso-ir-51", API_USE_MODULE(iso_ir_51) },
{ "iso-ir-54", API_USE_MODULE(iso_ir_54) },
{ "iso-ir-55", API_USE_MODULE(iso_ir_55) },
{ "iso-ir-57", API_USE_MODULE(iso_ir_57) },
{ "iso-ir-60", API_USE_MODULE(iso_ir_60) },
{ "iso-ir-61", API_USE_MODULE(iso_ir_61) },
{ "iso-ir-69", API_USE_MODULE(iso_ir_69) },
{ "iso-ir-70", API_USE_MODULE(iso_ir_70) },
{ "iso-ir-84", API_USE_MODULE(iso_ir_84) },
{ "iso-ir-85", API_USE_MODULE(iso_ir_85) },
{ "iso-ir-86", API_USE_MODULE(iso_ir_86) },
{ "iso-ir-88", API_USE_MODULE(iso_ir_88) },
{ "iso-ir-89", API_USE_MODULE(iso_ir_89) },
{ "iso-ir-8-1", API_USE_MODULE(iso_ir_8_1) },
{ "iso-ir-8-2", API_USE_MODULE(iso_ir_8_2) },
{ "iso-ir-90", API_USE_MODULE(iso_ir_90) },
{ "iso-ir-91", API_USE_MODULE(iso_ir_91) },
{ "iso-ir-92", API_USE_MODULE(iso_ir_92) },
{ "iso-ir-93", API_USE_MODULE(iso_ir_93) },
{ "iso-ir-94", API_USE_MODULE(iso_ir_94) },
{ "iso-ir-95", API_USE_MODULE(iso_ir_95) },
{ "iso-ir-96", API_USE_MODULE(iso_ir_96) },
{ "iso-ir-98", API_USE_MODULE(iso_ir_98) },
{ "iso-ir-99", API_USE_MODULE(iso_ir_99) },
{ "iso-ir-9-1", API_USE_MODULE(iso_ir_9_1) },
{ "iso-ir-9-2", API_USE_MODULE(iso_ir_9_2) },
{ "jis_x0201", API_USE_MODULE(jis_x0201) },
{ "jis_x0208-1983", API_USE_MODULE(jis_x0208_1983) },
{ "jis_x0212-1990", API_USE_MODULE(jis_x0212_1990) },
{ "johab", API_USE_MODULE(johab) },
{ "koi8-r", API_USE_MODULE(koi8_r) },
{ "koi8-ru", API_USE_MODULE(koi8_ru) },
{ "koi8-u", API_USE_MODULE(koi8_u) },
{ "ksx1001", API_USE_MODULE(ksx1001) },
{ "mac-ce", API_USE_MODULE(mac_ce) },
{ "mac-croatian", API_USE_MODULE(mac_croatian) },
{ "mac-cyrillic", API_USE_MODULE(mac_cyrillic) },
{ "mac-dingbats", API_USE_MODULE(mac_dingbats) },
{ "mac-greek", API_USE_MODULE(mac_greek) },
{ "mac-iceland", API_USE_MODULE(mac_iceland) },
{ "mac-japan", API_USE_MODULE(mac_japan) },
{ "mac-roman", API_USE_MODULE(mac_roman) },
{ "mac-romania", API_USE_MODULE(mac_romania) },
{ "mac-thai", API_USE_MODULE(mac_thai) },
{ "mac-turkish", API_USE_MODULE(mac_turkish) },
{ "mac-ukraine", API_USE_MODULE(mac_ukraine) },
{ "macintosh", API_USE_MODULE(macintosh) },
{ "osd_ebcdic_df04_1", API_USE_MODULE(osd_ebcdic_df04_1) },
{ "osd_ebcdic_df04_15", API_USE_MODULE(osd_ebcdic_df04_15) },
{ "shift_jis", API_USE_MODULE(shift_jis) },
{ "ucs2-internal", API_USE_MODULE(ucs2_internal) },
{ "ucs4-internal", API_USE_MODULE(ucs4_internal) },
{ "unicode-1-1-utf-7", API_USE_MODULE(unicode_1_1_utf_7) },
{ "us-ascii", API_USE_MODULE(us_ascii) },
{ "utf-16", API_USE_MODULE(utf_16) },
{ "utf-8", API_USE_MODULE(utf_8) },
{ "windows-1250", API_USE_MODULE(windows_1250) },
{ "windows-1251", API_USE_MODULE(windows_1251) },
{ "windows-1252", API_USE_MODULE(windows_1252) },
{ "windows-1253", API_USE_MODULE(windows_1253) },
{ "windows-1254", API_USE_MODULE(windows_1254) },
{ "windows-1255", API_USE_MODULE(windows_1255) },
{ "windows-1256", API_USE_MODULE(windows_1256) },
{ "windows-1257", API_USE_MODULE(windows_1257) },
{ "windows-1258", API_USE_MODULE(windows_1258) },
{ NULL, 0, NULL}
};
static const size_t static_iconv_modules_count =
sizeof(static_iconv_modules)/sizeof(static_iconv_modules[0]) - 1;
/* Compare two static modules. */
static int static_iconv_module_compare (const void *u, const void *v)
{
const struct static_iconv_module *const a = u;
const struct static_iconv_module *const b = v;
return strcmp(a->name, b->name);
}
static iconv_module_desc_t *static_iconv_module_find(const char *name)
{
struct static_iconv_module key;
struct static_iconv_module *val;
#if 'A' == '\xC1' /* if EBCDIC host */
/* The table is sorted in ASCII collation order, not in EBCDIC order.
* At the first access, we sort it automatically
* Criterion for the 1st time initialization is the fact that the
* 1st name in the list starts with a digit (in ASCII, numbers
* have a lower ordinal value than alphabetic characters; while
* in EBCDIC, their ordinal value is higher)
*/
if (isdigit(static_iconv_modules[0].name[0])) {
qsort((void *)static_iconv_modules, static_iconv_modules_count,
sizeof(static_iconv_modules[0]),
static_iconv_module_compare);
}
#endif
key.name = name;
val = bsearch(&key, static_iconv_modules, static_iconv_modules_count,
sizeof(static_iconv_modules[0]),
static_iconv_module_compare);
if (val)
return val->module;
else
return NULL;
}
static int
iconv_smopen(const char *name, void **dpp)
{
char buffer[APR_PATH_MAX];
char *ptr;
iconv_module_desc_t *module;
if (apr_tolower(name[0]) == 'x' && name[1] == '-')
name += 2;
ptr = buffer;
while (0 != (*ptr++ = apr_tolower(*name++)))
module = static_iconv_module_find(buffer);
if (!module) {
const char *alias = charset_alias_find(buffer);
if (alias) {
if ((module = static_iconv_module_find(alias))) {
*dpp = module;
return 0;
}
}
}
else {
*dpp = module;
return 0;
}
return EINVAL;
}
static apr_status_t
iconv_getpathname(char *buffer, const char *dir, const char *name, apr_pool_t *ctx)
{
apr_status_t rv;
apr_finfo_t sb;
apr_snprintf(buffer, APR_PATH_MAX, "%s/%s.so", dir, name);
rv = apr_stat(&sb, buffer, APR_FINFO_TYPE, ctx);
#ifdef API_HAVE_CHARSET_ALIAS_TABLE
/* If we didn't find the file, try again after looking in
the charset alias mapping table. */
if (rv || sb.filetype != APR_REG) {
const char *alias = charset_alias_find(name);
if (alias) {
apr_snprintf(buffer, APR_PATH_MAX, "%s/%s.so", dir, alias);
rv = apr_stat(&sb, buffer, APR_FINFO_TYPE, ctx);
}
}
#endif /* API_HAVE_CHARSET_ALIAS_TABLE */
if (!rv && sb.filetype != APR_REG)
rv = APR_EINVAL;
return rv;
}
static apr_status_t
iconv_getpath(char *buf, const char *name, apr_pool_t *ctx)
{
char buffer[APR_PATH_MAX];
apr_array_header_t *pathelts;
apr_pool_t *subpool;
apr_status_t status;
char *ptr;
status = apr_pool_create(&subpool, ctx);
if (status)
return status;
if (apr_tolower(name[0]) == 'x' && name[1] == '-')
name += 2;
ptr = buffer;
while (0 != (*ptr++ = apr_tolower(*name++)))
;
/* Fall back on APR_ICONV_PATH if APR_ICONVn_PATH isn't set...
* TODO: Drop support for "APR_ICONV_PATH" in apr-iconv 2.0
*/
if ((!apr_env_get(&ptr, APR_ICONV_PATH, subpool)
|| (!apr_env_get(&ptr, "APR_ICONV_PATH", subpool)))
&& !apr_filepath_list_split(&pathelts, ptr, subpool))
{
int i;
char **elts = (char **)pathelts->elts;
for (i = 0; i < pathelts->nelts; ++i)
{
if (iconv_getpathname(buf, elts[i], buffer, subpool) == 0)
{
apr_pool_destroy(subpool);
return APR_SUCCESS;
}
}
}
status = iconv_getpathname(buf, ICONV_DEFAULT_PATH, buffer, subpool);
apr_pool_destroy(subpool);
return status;
}
static int
iconv_dlopen(const char *name, const char *symbol, void **hpp, void **dpp, apr_pool_t *ctx)
{
apr_dso_handle_t *handle;
void *data;
/* dlopen */
if (apr_dso_load(&handle, name, ctx) != APR_SUCCESS) {
return EINVAL;
}
/* dlsym */
if ( apr_dso_sym(&data, handle, symbol) == APR_SUCCESS) {
*hpp = handle;
*dpp = data;
return 0;
}
apr_dso_unload(handle);
return EINVAL;
}
API_DECLARE_NONSTD(int)
apr_iconv_mod_load(const char *modname, int modtype, const void *args,
struct iconv_module **modpp, apr_pool_t *ctx)
{
struct iconv_module_desc *mdesc;
struct iconv_module *mod, *depmod;
const struct iconv_module_depend *depend;
char buffer[APR_PATH_MAX];
void *handle = NULL;
int error;
/* Try to load the built-in modules first */
error = iconv_smopen(modname, (void**)&mdesc);
if (error) {
if (iconv_getpath(buffer, modname, ctx) != 0)
return EINVAL;
error = iconv_dlopen(buffer, "iconv_module", &handle, (void**)&mdesc, ctx);
}
if (error)
return error;
if (modtype != ICMOD_ANY && mdesc->imd_type != modtype) {
if (handle)
apr_dso_unload(handle);
return APR_EFTYPE;
}
mod = malloc(sizeof(*mod));
if (mod == NULL) {
if (handle)
apr_dso_unload(handle);
return ENOMEM;
}
memset(mod, 0, sizeof(*mod));
mod->im_handle = handle;
mod->im_desc = mdesc;
mod->im_args = args;
depend = mdesc->imd_depend;
if (depend) {
while (depend->md_name) {
error = apr_iconv_mod_load(depend->md_name,
depend->md_type, NULL, &depmod, ctx);
if (error)
goto bad;
depmod->im_depdata = depend->md_data;
depmod->im_next = mod->im_deplist;
mod->im_deplist = depmod;
depend++;
}
}
error = ICONV_MOD_DYN_LOAD(mod,ctx);
if (error)
goto bad;
depmod = mod->im_deplist;
while (depmod) {
mod->im_depcnt++;
depmod = depmod->im_next;
}
error = ICONV_MOD_LOAD(mod,ctx);
if (error)
goto bad;
mod->im_flags |= ICMODF_LOADED;
*modpp = mod;
return 0;
bad:
apr_iconv_mod_unload(mod,ctx);
return error;
}
API_DECLARE_NONSTD(int)
apr_iconv_mod_unload(struct iconv_module *mod, apr_pool_t *ctx)
{
struct iconv_module *deplist, *tmp;
int error = 0;
if (mod == NULL)
return -1;
if (mod->im_flags & ICMODF_LOADED)
error = ICONV_MOD_UNLOAD(mod,ctx);
error = ICONV_MOD_DYN_UNLOAD(mod,ctx);
deplist = mod->im_deplist;
while (deplist) {
tmp = deplist->im_next;
apr_iconv_mod_unload(deplist,ctx);
deplist = tmp;
}
if (mod->im_handle != NULL)
if (apr_dso_unload(mod->im_handle) != APR_SUCCESS)
error = APR_EINVAL;
free(mod);
return error;
}
API_DECLARE_NONSTD(int)
apr_iconv_mod_noevent(struct iconv_module *mod, int event, apr_pool_t *ctx)
{
switch (event) {
case ICMODEV_LOAD:
case ICMODEV_UNLOAD:
case ICMODEV_DYN_LOAD:
case ICMODEV_DYN_UNLOAD:
break;
default:
return APR_EINVAL;
}
return 0;
}