static void locale_parse_lang (const char *locale) { char *codeset, *lang; if ((codeset = strchr (locale, '.'))) lang = g_strndup (locale, codeset - locale); else lang = g_strdup (locale); /* validate the language */ if (strlen (lang) >= 2) { if (lang[2] == '-' || lang[2] == '_') { /* canonicalise the lang */ e_strdown (lang); /* validate the country code */ if (strlen (lang + 3) > 2) { /* invalid country code */ lang[2] = '\0'; } else { lang[2] = '-'; e_strup (lang + 3); } } else if (lang[2] != '\0') { /* invalid language */ g_free (lang); lang = NULL; } locale_lang = lang; } else { /* invalid language */ locale_lang = NULL; g_free (lang); } }
const char *e_iconv_charset_name(const char *charset) { char *name, *ret, *tmp; if (charset == NULL) return NULL; /* The current longest charsetname in http://www.iana.org/assignments/character-sets is 45, so 80 should be more than enough to avoid SIGSEVS caused by specially huge malformed charset names */ if (strlen (charset) > 80) return NULL; name = g_alloca (strlen (charset) + 1); strcpy (name, charset); e_strdown (name); e_iconv_init(TRUE); ret = g_hash_table_lookup(iconv_charsets, name); if (ret != NULL) { UNLOCK(); return ret; } /* Unknown, try canonicalise some basic charset types to something that should work */ if (strncmp(name, "iso", 3) == 0) { /* Convert iso-nnnn-n or isonnnn-n or iso_nnnn-n to iso-nnnn-n or isonnnn-n */ int iso, codepage; char *p; tmp = name + 3; if (*tmp == '-' || *tmp == '_') tmp++; iso = strtoul (tmp, &p, 10); if (iso == 10646) { /* they all become ICONV_10646 */ ret = g_strdup (ICONV_10646); } else { tmp = p; if (*tmp == '-' || *tmp == '_') tmp++; codepage = strtoul (tmp, &p, 10); if (p > tmp) { /* codepage is numeric */ #ifdef __aix__ if (codepage == 13) ret = g_strdup ("IBM-921"); else #endif /* __aix__ */ ret = g_strdup_printf (ICONV_ISO_D_FORMAT, iso, codepage); } else { /* codepage is a string - probably iso-2022-jp or something */ ret = g_strdup_printf (ICONV_ISO_S_FORMAT, iso, p); } } } else if (strncmp(name, "windows-", 8) == 0) { /* Convert windows-nnnnn or windows-cpnnnnn to cpnnnn */ tmp = name+8; if (!strncmp(tmp, "cp", 2)) tmp+=2; ret = g_strdup_printf("CP%s", tmp); } else if (strncmp(name, "microsoft-", 10) == 0) { /* Convert microsoft-nnnnn or microsoft-cpnnnnn to cpnnnn */ tmp = name+10; if (!strncmp(tmp, "cp", 2)) tmp+=2; ret = g_strdup_printf("CP%s", tmp); } else { /* Just assume its ok enough as is, case and all */ ret = g_strdup(charset); } g_hash_table_insert(iconv_charsets, g_strdup(name), ret); UNLOCK(); return ret; }
/* NOTE: Owns the lock on return if keep is TRUE ! */ static void e_iconv_init(int keep) { char *from, *to, *locale; int i; LOCK(); if (iconv_charsets != NULL) { if (!keep) UNLOCK(); return; } iconv_charsets = g_hash_table_new(g_str_hash, g_str_equal); for (i = 0; known_iconv_charsets[i].charset != NULL; i++) { from = g_strdup(known_iconv_charsets[i].charset); to = g_strdup(known_iconv_charsets[i].iconv_name); e_strdown (from); g_hash_table_insert(iconv_charsets, from, to); } e_dlist_init(&iconv_cache_list); iconv_cache = g_hash_table_new(g_str_hash, g_str_equal); iconv_cache_open = g_hash_table_new(NULL, NULL); #ifndef G_OS_WIN32 locale = setlocale (LC_ALL, NULL); #else locale = g_win32_getlocale (); #endif if (!locale || !strcmp (locale, "C") || !strcmp (locale, "POSIX")) { /* The locale "C" or "POSIX" is a portable locale; its * LC_CTYPE part corresponds to the 7-bit ASCII character * set. */ locale_charset = NULL; locale_lang = NULL; } else { #ifdef G_OS_WIN32 g_get_charset (&locale_charset); locale_charset = g_strdup (locale_charset); e_strdown (locale_charset); #else #ifdef HAVE_CODESET locale_charset = g_strdup (nl_langinfo (CODESET)); e_strdown (locale_charset); #else /* A locale name is typically of the form language[_terri- * tory][.codeset][@modifier], where language is an ISO 639 * language code, territory is an ISO 3166 country code, and * codeset is a character set or encoding identifier like * ISO-8859-1 or UTF-8. */ char *codeset, *p; codeset = strchr (locale, '.'); if (codeset) { codeset++; /* ; is a hack for debian systems and / is a hack for Solaris systems */ for (p = codeset; *p && !strchr ("@;/", *p); p++); locale_charset = g_strndup (codeset, p - codeset); e_strdown (locale_charset); } else { /* charset unknown */ locale_charset = NULL; } #endif #endif /* !G_OS_WIN32 */ /* parse the locale lang */ locale_parse_lang (locale); } #ifdef G_OS_WIN32 g_free (locale); #endif if (!keep) UNLOCK(); }
const gchar * camel_iconv_charset_name (const gchar *charset) { gchar *name, *ret, *tmp; if (charset == NULL) return NULL; name = g_alloca (strlen (charset) + 1); strcpy (name, charset); e_strdown (name); iconv_init (TRUE); ret = g_hash_table_lookup (iconv_charsets, name); if (ret != NULL) { G_UNLOCK (iconv); return ret; } /* Unknown, try canonicalise some basic charset types to something that should work */ if (strncmp (name, "iso", 3) == 0) { /* Convert iso-nnnn-n or isonnnn-n or iso_nnnn-n to iso-nnnn-n or isonnnn-n */ gint iso, codepage; gchar *p; tmp = name + 3; if (*tmp == '-' || *tmp == '_') tmp++; iso = strtoul (tmp, &p, 10); if (iso == 10646) { /* they all become ICONV_10646 */ ret = g_strdup (ICONV_10646); } else { tmp = p; if (*tmp == '-' || *tmp == '_') tmp++; codepage = strtoul (tmp, &p, 10); if (p > tmp) { /* codepage is numeric */ #ifdef __aix__ if (codepage == 13) ret = g_strdup ("IBM-921"); else #endif /* __aix__ */ ret = g_strdup_printf (ICONV_ISO_D_FORMAT, iso, codepage); } else { /* codepage is a string - probably iso-2022-jp or something */ ret = g_strdup_printf (ICONV_ISO_S_FORMAT, iso, p); } } } else if (strncmp (name, "windows-", 8) == 0) { /* Convert windows-nnnnn or windows-cpnnnnn to cpnnnn */ tmp = name + 8; if (!strncmp (tmp, "cp", 2)) tmp+=2; ret = g_strdup_printf ("CP%s", tmp); } else if (strncmp (name, "microsoft-", 10) == 0) { /* Convert microsoft-nnnnn or microsoft-cpnnnnn to cpnnnn */ tmp = name + 10; if (!strncmp (tmp, "cp", 2)) tmp+=2; ret = g_strdup_printf ("CP%s", tmp); } else { /* Just assume its ok enough as is, case and all */ ret = g_strdup (charset); } g_hash_table_insert (iconv_charsets, g_strdup (name), ret); G_UNLOCK (iconv); return ret; }