/** * Initialize iconv conversion descriptors. * * This is called the first time it is needed, and also called again * every time the configuration is reloaded, because the charset or * codepage might have changed. **/ void init_iconv(void) { int c1, c2; BOOL did_reload = False; /* so that charset_name() works we need to get the UNIX<->UCS2 going first */ if (!conv_handles[CH_UNIX][CH_UTF16LE]) conv_handles[CH_UNIX][CH_UTF16LE] = smb_iconv_open(charset_name(CH_UTF16LE), "ASCII"); if (!conv_handles[CH_UTF16LE][CH_UNIX]) conv_handles[CH_UTF16LE][CH_UNIX] = smb_iconv_open("ASCII", charset_name(CH_UTF16LE)); for (c1=0;c1<NUM_CHARSETS;c1++) { for (c2=0;c2<NUM_CHARSETS;c2++) { const char *n1 = charset_name((charset_t)c1); const char *n2 = charset_name((charset_t)c2); if (conv_handles[c1][c2] && strcmp(n1, conv_handles[c1][c2]->from_name) == 0 && strcmp(n2, conv_handles[c1][c2]->to_name) == 0) continue; did_reload = True; if (conv_handles[c1][c2]) smb_iconv_close(conv_handles[c1][c2]); conv_handles[c1][c2] = smb_iconv_open(n2,n1); if (conv_handles[c1][c2] == (smb_iconv_t)-1) { DEBUG(0,("init_iconv: Conversion from %s to %s not supported\n", charset_name((charset_t)c1), charset_name((charset_t)c2))); if (c1 != CH_UTF16LE && c1 != CH_UTF16BE) { n1 = "ASCII"; } if (c2 != CH_UTF16LE && c2 != CH_UTF16BE) { n2 = "ASCII"; } DEBUG(0,("init_iconv: Attempting to replace with conversion from %s to %s\n", n1, n2 )); conv_handles[c1][c2] = smb_iconv_open(n2,n1); if (!conv_handles[c1][c2]) { DEBUG(0,("init_iconv: Conversion from %s to %s failed", n1, n2)); smb_panic("init_iconv: conv_handle initialization failed."); } } } } if (did_reload) { /* XXX: Does this really get called every time the dos * codepage changes? */ /* XXX: Is the did_reload test too strict? */ conv_silent = True; init_doschar_table(); init_valid_table(); conv_silent = False; } }
/** * Destroy global objects allocated by init_iconv() **/ void gfree_charcnv(void) { int c1, c2; for (c1=0;c1<NUM_CHARSETS;c1++) { for (c2=0;c2<NUM_CHARSETS;c2++) { if ( conv_handles[c1][c2] ) { smb_iconv_close( conv_handles[c1][c2] ); conv_handles[c1][c2] = 0; } } } }
bool set_iconv(smb_iconv_t* t, const char* to, const char* from) { smb_iconv_t cd = (smb_iconv_t)-1; if (to && from) { to = get_charset(to); from = get_charset(from); cd = smb_iconv_open(to, from); if (cd == ((smb_iconv_t)-1)) { return false; } } if ((*t != (smb_iconv_t)NULL) && (*t != (smb_iconv_t)-1)) { smb_iconv_close(*t); } *t = cd; return true; }
/** * Return the name of a charset to give to iconv(). **/ static const char *charset_name(charset_t ch) { const char *ret = NULL; if (ch == CH_UTF16LE) ret = "UTF-16LE"; else if (ch == CH_UTF16BE) ret = "UTF-16BE"; else if (ch == CH_UNIX) ret = lp_unix_charset(); else if (ch == CH_DOS) ret = lp_dos_charset(); else if (ch == CH_DISPLAY) ret = lp_display_charset(); else if (ch == CH_UTF8) ret = "UTF8"; #if defined(HAVE_NL_LANGINFO) && defined(CODESET) if (ret && !strcmp(ret, "LOCALE")) { const char *ln = NULL; #ifdef HAVE_SETLOCALE setlocale(LC_ALL, ""); #endif ln = nl_langinfo(CODESET); if (ln) { /* Check whether the charset name is supported by iconv */ smb_iconv_t handle = smb_iconv_open(ln,"UCS-2LE"); if (handle == (smb_iconv_t) -1) { DEBUG(5,("Locale charset '%s' unsupported, using ASCII instead\n", ln)); ln = NULL; } else { DEBUG(5,("Substituting charset '%s' for LOCALE\n", ln)); smb_iconv_close(handle); } } ret = ln; } #endif if (!ret || !*ret) ret = "ASCII"; return ret; }