diff options
Diffstat (limited to 'camel')
-rw-r--r-- | camel/ChangeLog | 48 | ||||
-rw-r--r-- | camel/Makefile.am | 2 | ||||
-rw-r--r-- | camel/camel-charset-map.c | 189 | ||||
-rw-r--r-- | camel/camel-charset-map.h | 6 | ||||
-rw-r--r-- | camel/camel-filter-search.c | 14 | ||||
-rw-r--r-- | camel/camel-folder-summary.c | 15 | ||||
-rw-r--r-- | camel/camel-iconv.c | 365 | ||||
-rw-r--r-- | camel/camel-iconv.h | 48 | ||||
-rw-r--r-- | camel/camel-mime-filter-charset.c | 35 | ||||
-rw-r--r-- | camel/camel-mime-message.c | 11 | ||||
-rw-r--r-- | camel/camel-mime-part-utils.c | 30 | ||||
-rw-r--r-- | camel/camel-mime-part.c | 10 | ||||
-rw-r--r-- | camel/camel-mime-utils.c | 66 | ||||
-rw-r--r-- | camel/camel-sasl-digest-md5.c | 23 | ||||
-rw-r--r-- | camel/camel-search-private.c | 7 | ||||
-rw-r--r-- | camel/camel.c | 7 |
16 files changed, 757 insertions, 119 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog index 54763b7388..63ef0afb14 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,5 +1,53 @@ 2003-02-20 Jeffrey Stedfast <fejj@ximian.com> + * camel.c (camel_init): Call camel_iconv_init(). + (camel_shutdown): Call camel_iconv_shutdown(). + + * camel-sasl-digest-md5.c (digest_response): Updated to use + camel-iconv and the new camel-charset-map functions. + + * camel-mime-utils.c: Updated to use camel-iconv and the new + camel-charset-map functions. + + * camel-mime-part-utils.c (check_html_charset): Use + camel_charset_canonical_name() instead of e_iconv_charset_name() + which is longer available. + (convert_buffer): Use camel-iconv. + (simple_data_wrapper_construct_from_parser): Since + camel_charset_iso_to_windows() returns the charset in it's + canonical format, no need to re-canonicalise it. + + * camel-mime-part.c (process_header): Use + camel_charset_canonical_name() instead of e_iconv_charset_name() + which is longer available. + + * camel-mime-message.c (process_header): Use + camel_charset_canonical_name() instead of e_iconv_charset_name() + which is longer available. + + * camel-mime-filter-charset.c: Use camel-iconv. + + * camel-folder-summary.c (message_info_new): Use + camel_charset_canonical_name() instead of e_iconv_charset_name() + which is longer available. + (content_info_new): Use camel_charset_locale_name(). + (camel_message_info_new_from_header): Same as message_info_new(). + + * camel-search-private.c: Use g_alloca() instead of alloca(). + + * camel-filter-search.c (check_header): Use + camel_charset_canonical_name() instead of e_iconv_charset_name() + which is longer available. + + * camel-charset-map.c (camel_charset_locale_name): New function, + replaces e_iconv_locale_charset(). + (camel_charset_canonical_name): New function, similar to + e_iconv_charset_name() but instead of returning the iconv-friendly + name, it returns the canonical name. (g_iconv will do the + iconv-friendly name conversions for us). + +2003-02-20 Jeffrey Stedfast <fejj@ximian.com> + * camel-filter-search.c (run_command): Redirect program's stdout and stderr to /dev/null diff --git a/camel/Makefile.am b/camel/Makefile.am index 119798b233..7192e5e48a 100644 --- a/camel/Makefile.am +++ b/camel/Makefile.am @@ -47,6 +47,7 @@ libcamel_la_SOURCES = \ camel-gpg-context.c \ camel-html-parser.c \ camel-http-stream.c \ + camel-iconv.c \ camel-index.c \ camel-internet-address.c \ camel-lock.c \ @@ -148,6 +149,7 @@ libcamelinclude_HEADERS = \ camel-folder.h \ camel-gpg-context.h \ camel-http-stream.h \ + camel-iconv.h \ camel-index.h \ camel-internet-address.h \ camel-i18n.h \ diff --git a/camel/camel-charset-map.c b/camel/camel-charset-map.c index be57d882e8..5fcd490dde 100644 --- a/camel/camel-charset-map.c +++ b/camel/camel-charset-map.c @@ -3,9 +3,10 @@ /* * Authors: * Michael Zucchi <notzed@ximian.com> + * Jeffrey Stedfast <fejj@ximian.com> * Dan Winship <danw@ximian.com> * - * Copyright 2000, 2001 Ximian, Inc. (www.ximian.com) + * Copyright 2000, 2003 Ximian, Inc. (www.ximian.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public @@ -22,12 +23,15 @@ * USA */ + #ifdef HAVE_CONFIG_H #include <config.h> #endif -#include <errno.h> #include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> /* if you want to build the charset map, compile this with something like: @@ -200,16 +204,16 @@ int main (void) #include "camel-charset-map.h" #include "camel-charset-map-private.h" #include "string-utils.h" + +#include <glib.h> #include <glib/gunicode.h> #include <locale.h> -#include <string.h> #include <ctype.h> -#include <glib.h> #ifdef ENABLE_THREADS #include <pthread.h> #endif -#ifdef HAVE_ALLOCA_H -#include <alloca.h> +#ifdef HAVE_CODESET +#include <langinfo.h> #endif void @@ -295,9 +299,179 @@ camel_charset_best (const char *in, int len) } +#ifdef G_THREADS_ENABLED +static GStaticMutex lock = G_STATIC_MUTEX_INIT; +#define LOCK() g_static_mutex_lock(&lock) +#define UNLOCK() g_static_mutex_unlock(&lock) +#else +#define LOCK() +#define UNLOCK() +#endif + +static char *locale_charset = NULL; +static GHashTable *canon_charsets = NULL; + +static void +canon_charsets_init (int keep) +{ + char *locale; + + LOCK (); + + if (canon_charsets != NULL) { + if (!keep) + UNLOCK (); + return; + } + + canon_charsets = g_hash_table_new (g_str_hash, g_str_equal); + + locale = setlocale (LC_ALL, NULL); + + 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; + } else { +#ifdef HAVE_CODESET + locale_charset = g_strdup (nl_langinfo (CODESET)); + g_ascii_strdown (locale_charset, -1); +#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); + g_ascii_strdown (locale_charset, -1); + } else { + /* charset unknown */ + locale_charset = NULL; + } +#endif + } + + if (!keep) + UNLOCK (); +} + + +/** + * camel_charset_locale_name: + * + * Returns the name of the system's locale charset. + **/ +const char * +camel_charset_locale_name (void) +{ + canon_charsets_init (FALSE); + + return locale_charset; +} + + +/** + * camel_charset_canonical_name: + * @charset: charset to canonicalise + * + * Returns the charset in its canonical format. This is currently only + * needed for iso charsets but also handles canonicalisation of + * windows charsets. May need to expand this to handle canincalisation + * of more charsets in the future? + **/ +const char * +camel_charset_canonical_name (const char *charset) +{ + char *name, *canon, *tmp; + + if (charset == NULL) + return NULL; + + name = g_alloca (strlen (charset)); + strcpy (name, charset); + g_ascii_strdown (name, -1); + + canon_charsets_init (TRUE); + canon = g_hash_table_lookup (canon_charsets, name); + if (canon != NULL) { + UNLOCK (); + return canon; + } + + /* 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 iso-10646 */ + canon = g_strdup ("iso-10646"); + } else { + /* iso-8859-# */ + tmp = p; + if (*tmp == '-' || *tmp == '_') + tmp++; + + codepage = strtoul (tmp, &p, 10); + + if (p > tmp) { + /* codepage is numeric */ + canon = g_strdup_printf ("iso-%d-%d", iso, codepage); + } else { + /* codepage is a string - probably iso-2022-jp or something */ + canon = g_strdup_printf ("iso-%d-%s", iso, p); + } + } + } else if (strncmp (name, "windows-", 8) == 0) { + /* Convert windows-#### and windows-cp#### to windows-cp#### */ + tmp = name + 8; + if (!strncmp (tmp, "cp", 2)) + tmp += 2; + canon = g_strdup_printf ("windows-cp%s", tmp); + } else if (strncmp (name, "microsoft-", 10) == 0) { + /* Convert microsoft-#### or microsoft-cp#### to windows-cp#### */ + tmp = name + 10; + if (!strncmp (tmp, "cp", 2)) + tmp += 2; + canon = g_strdup_printf ("windows-cp%s", tmp); + } else if (strncmp (name, "cp125", 5) == 0) { + /* Convert cp125# to windows-cp#### */ + canon = g_strdup_printf ("windows-%s", name); + } else { + /* Just assume its ok enough as is, case and all */ + canon = g_strdup (charset); + } + + g_hash_table_insert (canon_charsets, g_strdup (name), canon); + UNLOCK (); + + return canon; +} + + /** * camel_charset_iso_to_windows: - * @isocharset: an ISO charset + * @isocharset: a canonicalised ISO charset * * Returns the equivalent Windows charset. **/ @@ -351,4 +525,3 @@ camel_charset_iso_to_windows (const char *isocharset) } #endif /* !BUILD_MAP */ - diff --git a/camel/camel-charset-map.h b/camel/camel-charset-map.h index ab60ef5bf5..d18f782ea0 100644 --- a/camel/camel-charset-map.h +++ b/camel/camel-charset-map.h @@ -37,7 +37,11 @@ struct _CamelCharset { void camel_charset_init(CamelCharset *); void camel_charset_step(CamelCharset *, const char *in, int len); -const char *camel_charset_best_name(CamelCharset *); + +const char *camel_charset_locale_name (void); +const char *camel_charset_canonical_name (const char *charset); + +const char *camel_charset_best_name (CamelCharset *); /* helper function */ const char *camel_charset_best(const char *in, int len); diff --git a/camel/camel-filter-search.c b/camel/camel-filter-search.c index e0e385346b..2439a9b23d 100644 --- a/camel/camel-filter-search.c +++ b/camel/camel-filter-search.c @@ -42,15 +42,9 @@ #include <signal.h> #include <sys/wait.h> - -#ifdef HAVE_ALLOCA_H -#include <alloca.h> -#endif - -#include <gal/util/e-iconv.h> - #include "e-util/e-sexp.h" +#include "camel-charset-map.h" #include "camel-mime-message.h" #include "camel-provider.h" #include "camel-session.h" @@ -167,8 +161,10 @@ check_header (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMess type = CAMEL_SEARCH_TYPE_ADDRESS_ENCODED; else { ct = camel_mime_part_get_content_type (CAMEL_MIME_PART (message)); - if (ct) - charset = e_iconv_charset_name(header_content_type_param(ct, "charset")); + if (ct) { + charset = header_content_type_param (ct, "charset"); + charset = camel_charset_canonical_name (charset); + } } } diff --git a/camel/camel-folder-summary.c b/camel/camel-folder-summary.c index 337342acd6..ee3fc16882 100644 --- a/camel/camel-folder-summary.c +++ b/camel/camel-folder-summary.c @@ -33,10 +33,9 @@ #include <errno.h> #include <stdlib.h> -#include <gal/util/e-iconv.h> - #include "camel-folder-summary.h" +#include <camel/camel-charset-map.h> #include <camel/camel-file-utils.h> #include <camel/camel-mime-filter.h> #include <camel/camel-mime-filter-index.h> @@ -1575,9 +1574,9 @@ message_info_new(CamelFolderSummary *s, struct _header_raw *h) && (charset = header_content_type_param(ct, "charset")) && (strcasecmp(charset, "us-ascii") == 0)) charset = NULL; - - charset = e_iconv_charset_name(charset); - + + charset = camel_charset_canonicalname (charset); + subject = summary_format_string(h, "subject", charset); from = summary_format_address(h, "from"); to = summary_format_address(h, "to"); @@ -1837,7 +1836,7 @@ content_info_new (CamelFolderSummary *s, struct _header_raw *h) ci = camel_folder_summary_content_info_new (s); - charset = e_iconv_locale_charset(); + charset = camel_charset_locale_name (); ci->id = header_msgid_decode (header_raw_find (&h, "content-id", NULL)); ci->description = header_decode_string (header_raw_find (&h, "content-description", NULL), NULL); ci->encoding = header_content_encoding_decode (header_raw_find (&h, "content-transfer-encoding", NULL)); @@ -2562,8 +2561,8 @@ camel_message_info_new_from_header (struct _header_raw *header) && (charset = header_content_type_param(ct, "charset")) && (strcasecmp(charset, "us-ascii") == 0)) charset = NULL; - - charset = e_iconv_charset_name(charset); + + charset = camel_charset_canonical_name (charset); subject = summary_format_string(header, "subject", charset); from = summary_format_address(header, "from"); diff --git a/camel/camel-iconv.c b/camel/camel-iconv.c new file mode 100644 index 0000000000..29e90cd1e7 --- /dev/null +++ b/camel/camel-iconv.c @@ -0,0 +1,365 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * + * Copyright 2003 Ximian, Inc. (www.ximian.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * + */ + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <glib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include "e-util/e-memory.h" +#include "camel/camel-charset-map.h" + + +#define ICONV_CACHE_SIZE (16) + +struct _iconv_cache_bucket { + struct _iconv_cache_bucket *next; + struct _iconv_cache_bucket *prev; + guint32 refcount; + gboolean used; + iconv_t cd; + char *key; +}; + + +static EMemChunk *cache_chunk; +static struct _iconv_cache_bucket *iconv_cache_buckets; +static GHashTable *iconv_cache; +static GHashTable *iconv_open_hash; +static unsigned int iconv_cache_size = 0; + +#ifdef G_THREADS_ENABLED +static GStaticMutex iconv_cache_lock = G_STATIC_MUTEX_INIT; +#define ICONV_CACHE_LOCK() g_static_mutex_lock (&iconv_cache_lock) +#define ICONV_CACHE_UNLOCK() g_static_mutex_unlock (&iconv_cache_lock) +#else +#define ICONV_CACHE_LOCK() +#define ICONV_CACHE_UNLOCK() +#endif /* G_THREADS_ENABLED */ + + +/* caller *must* hold the iconv_cache_lock to call any of the following functions */ + + +/** + * iconv_cache_bucket_new: + * @key: cache key + * @cd: iconv descriptor + * + * Creates a new cache bucket, inserts it into the cache and + * increments the cache size. + * + * Returns a pointer to the newly allocated cache bucket. + **/ +static struct _iconv_cache_bucket * +iconv_cache_bucket_new (const char *key, iconv_t cd) +{ + struct _iconv_cache_bucket *bucket; + + bucket = e_memchunk_alloc (cache_chunk); + bucket->next = NULL; + bucket->prev = NULL; + bucket->key = g_strdup (key); + bucket->refcount = 1; + bucket->used = TRUE; + bucket->cd = cd; + + g_hash_table_insert (iconv_cache, bucket->key, bucket); + + /* FIXME: Since iconv_cache_expire_unused() traverses the list + from head to tail, perhaps it might be better to append new + nodes rather than prepending? This way older cache buckets + expire first? */ + bucket->next = iconv_cache_buckets; + iconv_cache_buckets = bucket; + + iconv_cache_size++; + + return bucket; +} + + +/** + * iconv_cache_bucket_expire: + * @bucket: cache bucket + * + * Expires a single cache bucket @bucket. This should only ever be + * called on a bucket that currently has no used iconv descriptors + * open. + **/ +static void +iconv_cache_bucket_expire (struct _iconv_cache_bucket *bucket) +{ + g_hash_table_remove (iconv_cache, bucket->key); + + if (bucket->prev) { + bucket->prev->next = bucket->next; + if (bucket->next) + bucket->next->prev = bucket->prev; + } else { + iconv_cache_buckets = bucket->next; + if (bucket->next) + bucket->next->prev = NULL; + } + + g_free (bucket->key); + iconv_close (bucket->cd); + e_memchunk_free (cache_chunk, bucket); + + iconv_cache_size--; +} + + +/** + * iconv_cache_expire_unused: + * + * Expires as many unused cache buckets as it needs to in order to get + * the total number of buckets < ICONV_CACHE_SIZE. + **/ +static void +iconv_cache_expire_unused (void) +{ + struct _iconv_cache_bucket *bucket, *next; + + bucket = iconv_cache_buckets; + while (bucket && iconv_cache_size >= ICONV_CACHE_SIZE) { + next = bucket->next; + + if (bucket->refcount == 0) + iconv_cache_bucket_expire (bucket); + + bucket = next; + } +} + + +void +camel_iconv_shutdown (void) +{ + struct _iconv_cache_bucket *bucket, *next; + + bucket = iconv_cache_buckets; + while (bucket) { + next = bucket->next; + + g_free (bucket->key); + g_iconv_close (bucket->cd); + e_memchunk_free (cache_chunk, bucket); + + bucket = next; + } + + g_hash_table_destroy (iconv_cache); + g_hash_table_destroy (iconv_open_hash); + + e_memchunk_destroy (cache_chunk); +} + + +/** + * camel_iconv_init: + * + * Initialize Camel's iconv cache. This *MUST* be called before any + * camel-iconv interfaces will work correctly. + **/ +void +camel_iconv_init (void) +{ + static int initialized = FALSE; + + if (initialized) + return; + + iconv_cache_buckets = NULL; + iconv_cache = g_hash_table_new (g_str_hash, g_str_equal); + iconv_open_hash = g_hash_table_new (g_direct_hash, g_direct_equal); + + cache_chunk = e_memchunk_new (ICONV_CACHE_SIZE, sizeof (struct _iconv_cache_bucket)); + + initialized = TRUE; +} + + +/** + * camel_iconv_open: + * @to: charset to convert to + * @from: charset to convert from + * + * Allocates a coversion descriptor suitable for converting byte + * sequences from charset @from to charset @to. The resulting + * descriptor can be used with iconv (or the camel_iconv wrapper) any + * number of times until closed using camel_iconv_close. + * + * Returns a new conversion descriptor for use with iconv on success + * or (iconv_t) -1 on fail as well as setting an appropriate errno + * value. + **/ +iconv_t +camel_iconv_open (const char *to, const char *from) +{ + struct _iconv_cache_bucket *bucket; + iconv_t cd; + char *key; + + if (from == NULL || to == NULL) { + errno = EINVAL; + return (iconv_t) -1; + } + + if (!strcasecmp (from, "x-unknown")) + from = camel_charset_locale_name (); + + /* Even tho g_iconv_open will find the appropriate charset + * format(s) for the to/from charset strings, we still convert + * them to their canonical format here so that our key is in a + * standard format */ + from = camel_charset_canonical_name (from); + to = camel_charset_canonical_name (to); + key = g_alloca (strlen (from) + strlen (to) + 2); + sprintf (key, "%s:%s", from, to); + + ICONV_CACHE_LOCK (); + + bucket = g_hash_table_lookup (iconv_cache, key); + if (bucket) { + if (bucket->used) { + cd = g_iconv_open (to, from); + if (cd == (iconv_t) -1) + goto exception; + } else { + /* Apparently iconv on Solaris <= 7 segfaults if you pass in + * NULL for anything but inbuf; work around that. (NULL outbuf + * or NULL *outbuf is allowed by Unix98.) + */ + size_t inleft = 0, outleft = 0; + char *outbuf = NULL; + + cd = bucket->cd; + bucket->used = TRUE; + + /* reset the descriptor */ + g_iconv (cd, NULL, &inleft, &outbuf, &outleft); + } + + bucket->refcount++; + } else { + cd = g_iconv_open (to, from); + if (cd == (iconv_t) -1) + goto exception; + + iconv_cache_expire_unused (); + + bucket = iconv_cache_bucket_new (key, cd); + } + + g_hash_table_insert (iconv_open_hash, cd, bucket->key); + + ICONV_CACHE_UNLOCK (); + + return cd; + + exception: + + ICONV_CACHE_UNLOCK (); + + if (errno == EINVAL) + g_warning ("Conversion from '%s' to '%s' is not supported", from, to); + else + g_warning ("Could not open converter from '%s' to '%s': %s", + from, to, g_strerror (errno)); + + return cd; +} + + +/** + * camel_iconv: + * @cd: conversion descriptor + * @inbuf: address of input buffer + * @inleft: input bytes left + * @outbuf: address of output buffer + * @outleft: output bytes left + * + * Read `man 3 iconv` + **/ +size_t +camel_iconv (iconv_t cd, const char **inbuf, size_t *inleft, char **outbuf, size_t *outleft) +{ + return iconv (cd, (ICONV_CONST char **) inbuf, inleft, outbuf, outleft); +} + + +/** + * camel_iconv_close: + * @cd: iconv conversion descriptor + * + * Closes the iconv descriptor @cd. + * + * Returns 0 on success or -1 on fail as well as setting an + * appropriate errno value. + **/ +int +camel_iconv_close (iconv_t cd) +{ + struct _iconv_cache_bucket *bucket; + const char *key; + + if (cd == (iconv_t) -1) + return 0; + + ICONV_CACHE_LOCK (); + + key = g_hash_table_lookup (iconv_open_hash, cd); + if (key) { + g_hash_table_remove (iconv_open_hash, cd); + + bucket = g_hash_table_lookup (iconv_cache, key); + g_assert (bucket); + + bucket->refcount--; + + if (cd == bucket->cd) + bucket->used = FALSE; + else + g_iconv_close (cd); + + if (!bucket->refcount && iconv_cache_size > ICONV_CACHE_SIZE) { + /* expire this cache bucket */ + iconv_cache_bucket_expire (bucket); + } + } else { + ICONV_CACHE_UNLOCK (); + + g_warning ("This iconv context wasn't opened using camel_iconv_open()"); + + return g_iconv_close (cd); + } + + ICONV_CACHE_UNLOCK (); + + return 0; +} diff --git a/camel/camel-iconv.h b/camel/camel-iconv.h new file mode 100644 index 0000000000..77052b469b --- /dev/null +++ b/camel/camel-iconv.h @@ -0,0 +1,48 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * + * Copyright 2003 Ximian, Inc. (www.ximian.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * + */ + + +#ifndef __CAMEL_ICONV_H__ +#define __CAMEL_ICONV_H__ + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#include <sys/types.h> +#include <iconv.h> + +void camel_iconv_init (void); +void camel_iconv_shutdown (void); + +iconv_t camel_iconv_open (const char *to, const char *from); + +size_t camel_iconv (iconv_t cd, const char **inbuf, size_t *inleft, char **outbuf, size_t *outleft); + +int camel_iconv_close (iconv_t cd); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __CAMEL_ICONV_H__ */ diff --git a/camel/camel-mime-filter-charset.c b/camel/camel-mime-filter-charset.c index f8eafa9633..0e1c111786 100644 --- a/camel/camel-mime-filter-charset.c +++ b/camel/camel-mime-filter-charset.c @@ -20,15 +20,16 @@ */ -#include <iconv.h> +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif #include <string.h> #include <errno.h> -#include <gal/util/e-iconv.h> - #include "camel-mime-filter-charset.h" #include "camel-charset-map.h" +#include "camel-iconv.h" #define d(x) @@ -63,8 +64,8 @@ camel_mime_filter_charset_finalize(CamelObject *o) g_free(f->from); g_free(f->to); - if (f->ic != (iconv_t)-1) { - e_iconv_close(f->ic); + if (f->ic != (iconv_t) -1) { + camel_iconv_close (f->ic); f->ic = (iconv_t) -1; } } @@ -76,11 +77,11 @@ reset(CamelMimeFilter *mf) char buf[16]; char *buffer; size_t outlen = 16; - + /* what happens with the output bytes if this resets the state? */ if (f->ic != (iconv_t) -1) { buffer = buf; - e_iconv(f->ic, NULL, 0, &buffer, &outlen); + camel_iconv (f->ic, NULL, 0, &buffer, &outlen); } } @@ -104,7 +105,7 @@ complete(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, if (inleft > 0) { do { - converted = e_iconv (charset->ic, &inbuf, &inleft, &outbuf, &outleft); + converted = camel_iconv (charset->ic, &inbuf, &inleft, &outbuf, &outleft); if (converted == (size_t) -1) { if (errno == E2BIG) { /* @@ -144,7 +145,7 @@ complete(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, } /* flush the iconv conversion */ - e_iconv (charset->ic, NULL, NULL, &outbuf, &outleft); + camel_iconv (charset->ic, NULL, NULL, &outbuf, &outleft); *out = mf->outbuf; *outlen = mf->outsize - outleft; @@ -178,7 +179,7 @@ filter(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, s inleft = len; do { - converted = e_iconv (charset->ic, &inbuf, &inleft, &outbuf, &outleft); + converted = camel_iconv (charset->ic, &inbuf, &inleft, &outbuf, &outleft); if (converted == (size_t) -1) { if (errno == E2BIG || errno == EINVAL) break; @@ -248,19 +249,21 @@ camel_mime_filter_charset_init (CamelMimeFilterCharset *obj) CamelMimeFilterCharset * camel_mime_filter_charset_new (void) { - CamelMimeFilterCharset *new = CAMEL_MIME_FILTER_CHARSET (camel_object_new (camel_mime_filter_charset_get_type ())); - return new; + return CAMEL_MIME_FILTER_CHARSET (camel_object_new (camel_mime_filter_charset_get_type ())); } CamelMimeFilterCharset * camel_mime_filter_charset_new_convert (const char *from_charset, const char *to_charset) { - CamelMimeFilterCharset *new = CAMEL_MIME_FILTER_CHARSET (camel_object_new (camel_mime_filter_charset_get_type ())); + CamelMimeFilterCharset *new; + + new = CAMEL_MIME_FILTER_CHARSET (camel_object_new (camel_mime_filter_charset_get_type ())); - new->ic = e_iconv_open (to_charset, from_charset); + new->ic = camel_iconv_open (to_charset, from_charset); if (new->ic == (iconv_t) -1) { - g_warning ("Cannot create charset conversion from %s to %s: %s", from_charset, to_charset, strerror (errno)); - camel_object_unref ((CamelObject *)new); + g_warning ("Cannot create charset conversion from %s to %s: %s", + from_charset, to_charset, g_strerror (errno)); + camel_object_unref (new); new = NULL; } else { new->from = g_strdup (from_charset); diff --git a/camel/camel-mime-message.c b/camel/camel-mime-message.c index 428cfd061d..6bd1f7360e 100644 --- a/camel/camel-mime-message.c +++ b/camel/camel-mime-message.c @@ -30,11 +30,9 @@ #include <ctype.h> #include <stdio.h> #include <string.h> - -#include <gal/util/e-iconv.h> - #include <errno.h> +#include "camel-charset-map.h" #include "camel-mime-message.h" #include "camel-multipart.h" #include "camel-stream-mem.h" @@ -544,9 +542,10 @@ process_header (CamelMedium *medium, const char *header_name, const char *header break; case HEADER_SUBJECT: g_free (message->subject); - if (((CamelMimePart *)message)->content_type) - charset = e_iconv_charset_name(header_content_type_param(((CamelMimePart *)message)->content_type, "charset")); - else + if (((CamelMimePart *) message)->content_type) { + charset = header_content_type_param (((CamelMimePart *) message)->content_type, "charset"); + charset = camel_charset_canonical_name (charset); + } else charset = NULL; message->subject = g_strstrip (header_decode_string (header_value, charset)); break; diff --git a/camel/camel-mime-part-utils.c b/camel/camel-mime-part-utils.c index c6fbd65404..c7c0d15907 100644 --- a/camel/camel-mime-part-utils.c +++ b/camel/camel-mime-part-utils.c @@ -31,10 +31,11 @@ #include <unistd.h> #include <errno.h> -#include <gal/util/e-iconv.h> #include <glib/gunicode.h> #include "string-utils.h" +#include "camel-iconv.h" +#include "camel-charset-map.h" #include "camel-mime-part-utils.h" #include "camel-mime-message.h" #include "camel-multipart.h" @@ -49,7 +50,6 @@ #include "camel-mime-filter-crlf.h" #include "camel-mime-filter-save.h" #include "camel-html-parser.h" -#include "camel-charset-map.h" #define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x)) #include <stdio.h>*/ @@ -87,7 +87,7 @@ check_html_charset(char *buffer, int length) && (val = camel_html_parser_attr(hp, "content")) && (ct = header_content_type_decode(val))) { charset = header_content_type_param(ct, "charset"); - charset = e_iconv_charset_name (charset); + charset = camel_charset_canonical_name (charset); header_content_type_unref(ct); } break; @@ -97,7 +97,7 @@ check_html_charset(char *buffer, int length) } } while (charset == NULL && state != CAMEL_HTML_PARSER_EOF); - camel_object_unref((CamelObject *)hp); + camel_object_unref (hp); return charset; } @@ -113,12 +113,12 @@ convert_buffer (GByteArray *in, const char *to, const char *from) if (in->len == 0) return g_byte_array_new(); - + d(printf("converting buffer from %s to %s:\n", from, to)); d(fwrite(in->data, 1, (int)in->len, stdout)); d(printf("\n")); - cd = e_iconv_open(to, from); + cd = camel_iconv_open(to, from); if (cd == (iconv_t) -1) { g_warning ("Cannot convert from '%s' to '%s': %s", from, to, strerror (errno)); return NULL; @@ -135,7 +135,7 @@ convert_buffer (GByteArray *in, const char *to, const char *from) outbuf = out->data + converted; outleft = outlen - converted; - converted = e_iconv (cd, &inbuf, &inleft, &outbuf, &outleft); + converted = camel_iconv (cd, &inbuf, &inleft, &outbuf, &outleft); if (converted == (size_t) -1) { if (errno != E2BIG && errno != EINVAL) goto fail; @@ -164,17 +164,17 @@ convert_buffer (GByteArray *in, const char *to, const char *from) */ /* flush the iconv conversion */ - e_iconv (cd, NULL, NULL, &outbuf, &outleft); + camel_iconv (cd, NULL, NULL, &outbuf, &outleft); /* now set the true length on the GByteArray */ converted = outbuf - (char *)out->data; g_byte_array_set_size (out, converted); - + d(printf("converted data:\n")); d(fwrite(out->data, 1, (int)out->len, stdout)); d(printf("\n")); - - e_iconv_close (cd); + + camel_iconv_close (cd); return out; @@ -183,7 +183,7 @@ convert_buffer (GByteArray *in, const char *to, const char *from) g_byte_array_free (out, TRUE); - e_iconv_close (cd); + camel_iconv_close (cd); return NULL; } @@ -262,7 +262,7 @@ simple_data_wrapper_construct_from_parser (CamelDataWrapper *dw, CamelMimeParser ct = camel_mime_parser_content_type (mp); if (header_content_type_is (ct, "text", "*")) { charset = header_content_type_param (ct, "charset"); - charset = e_iconv_charset_name (charset); + charset = camel_charset_canonical_name (charset); if (fdec) { d(printf ("Adding CRLF conversion filter\n")); @@ -313,10 +313,8 @@ simple_data_wrapper_construct_from_parser (CamelDataWrapper *dw, CamelMimeParser */ if (!strncasecmp (charset, "iso-8859", 8)) { /* check for Windows-specific chars... */ - if (broken_windows_charset (buffer, charset)) { + if (broken_windows_charset (buffer, charset)) charset = camel_charset_iso_to_windows (charset); - charset = e_iconv_charset_name (charset); - } } out = convert_buffer (buffer, "UTF-8", charset); diff --git a/camel/camel-mime-part.c b/camel/camel-mime-part.c index eb65dead4e..765a9af5b5 100644 --- a/camel/camel-mime-part.c +++ b/camel/camel-mime-part.c @@ -29,11 +29,8 @@ #include <string.h> #include <stdio.h> #include <ctype.h> - #include <errno.h> -#include <gal/util/e-iconv.h> - #include "camel-mime-parser.h" #include "camel-stream-mem.h" #include "camel-stream-filter.h" @@ -223,9 +220,10 @@ process_header(CamelMedium *medium, const char *header_name, const char *header_ switch (header_type) { case HEADER_DESCRIPTION: /* raw header->utf8 conversion */ g_free (mime_part->description); - if (mime_part->content_type) - charset = e_iconv_charset_name(header_content_type_param(mime_part->content_type, "charset")); - else + if (mime_part->content_type) { + charset = header_content_type_param (mime_part->content_type, "charset"); + charset = camel_charset_canonical_name (charset); + } else charset = NULL; mime_part->description = g_strstrip (header_decode_string (header_value, charset)); break; diff --git a/camel/camel-mime-utils.c b/camel/camel-mime-utils.c index 83120e35a8..b12c116b28 100644 --- a/camel/camel-mime-utils.c +++ b/camel/camel-mime-utils.c @@ -39,8 +39,6 @@ #define MAXHOSTNAMELEN 1024 #endif -#include <iconv.h> - #include <time.h> #include <ctype.h> @@ -49,9 +47,9 @@ #include <glib.h> #include <glib/gunicode.h> -#include <gal/util/e-iconv.h> #include "e-time-utils.h" +#include "camel-iconv.h" #include "camel-mime-utils.h" #include "camel-charset-map.h" #include "camel-service.h" /* for camel_gethostbyname() */ @@ -1051,7 +1049,7 @@ rfc2047_decode_word(const char *in, size_t len) if (p) *p = '\0'; - charset = e_iconv_charset_name (encname); + charset = camel_charset_canonical_name (encname); inbuf = decword; @@ -1060,21 +1058,21 @@ rfc2047_decode_word(const char *in, size_t len) outbuf = outbase; retry: - ic = e_iconv_open ("UTF-8", charset); + ic = camel_iconv_open ("UTF-8", charset); if (ic != (iconv_t) -1) { - ret = e_iconv (ic, &inbuf, &inlen, &outbuf, &outlen); + ret = camel_iconv (ic, &inbuf, &inlen, &outbuf, &outlen); if (ret != (size_t) -1) { - e_iconv (ic, NULL, 0, &outbuf, &outlen); + camel_iconv (ic, NULL, 0, &outbuf, &outlen); *outbuf = 0; decoded = g_strdup (outbase); } - e_iconv_close (ic); + camel_iconv_close (ic); } else { w(g_warning ("Cannot decode charset, header display may be corrupt: %s: %s", charset, strerror (errno))); if (!retried) { - charset = e_iconv_locale_charset (); + charset = camel_charset_locale_name (); if (!charset) charset = "iso-8859-1"; @@ -1122,24 +1120,24 @@ append_8bit (GString *out, const char *inbuf, size_t inlen, const char *charset) size_t outlen; iconv_t ic; - ic = e_iconv_open ("UTF-8", charset); + ic = camel_iconv_open ("UTF-8", charset); if (ic == (iconv_t) -1) return FALSE; outlen = inlen * 6 + 16; outbuf = outbase = g_malloc(outlen); - if (e_iconv(ic, &inbuf, &inlen, &outbuf, &outlen) == (size_t) -1) { + if (camel_iconv (ic, &inbuf, &inlen, &outbuf, &outlen) == (size_t) -1) { w(g_warning("Conversion to '%s' failed: %s", charset, strerror (errno))); g_free(outbase); - e_iconv_close(ic); + camel_iconv_close (ic); return FALSE; } *outbuf = 0; g_string_append(out, outbase); g_free(outbase); - e_iconv_close(ic); + camel_iconv_close (ic); return TRUE; @@ -1152,9 +1150,9 @@ header_decode_text (const char *in, size_t inlen, const char *default_charset) GString *out; const char *inptr, *inend, *start, *chunk, *locale_charset; char *dword = NULL; - - locale_charset = e_iconv_locale_charset(); - + + locale_charset = camel_charset_locale_name (); + out = g_string_new(""); inptr = in; inend = inptr + inlen; @@ -1233,7 +1231,7 @@ rfc2047_encode_word(GString *outstring, const char *in, size_t len, const char * ascii = alloca (bufflen); if (strcasecmp (type, "UTF-8") != 0) - ic = e_iconv_open (type, "UTF-8"); + ic = camel_iconv_open (type, "UTF-8"); while (inlen) { size_t convlen, proclen; @@ -1281,13 +1279,13 @@ rfc2047_encode_word(GString *outstring, const char *in, size_t len, const char * hopefully-small-enough chunks, and leave it at that */ convlen = MIN(inlen, CAMEL_FOLD_PREENCODED); p = inptr; - if (e_iconv (ic, &inptr, &convlen, &out, &outlen) == (size_t) -1) { + if (camel_iconv (ic, &inptr, &convlen, &out, &outlen) == (size_t) -1) { w(g_warning("Conversion problem: conversion truncated: %s", strerror (errno))); /* blah, we include it anyway, better than infinite loop ... */ inptr = p + convlen; } else { /* make sure we flush out any shift state */ - e_iconv(ic, NULL, 0, &out, &outlen); + camel_iconv (ic, NULL, 0, &out, &outlen); } inlen -= (inptr - p); } @@ -1312,7 +1310,7 @@ rfc2047_encode_word(GString *outstring, const char *in, size_t len, const char * } if (ic != (iconv_t) -1) - e_iconv_close(ic); + camel_iconv_close (ic); } @@ -1869,7 +1867,7 @@ rfc2184_decode (const char *in, size_t len) return NULL; encoding = g_strndup (in, inptr - in); - charset = e_iconv_charset_name (encoding); + charset = camel_charset_canonical_name (encoding); g_free (encoding); inptr = memchr (inptr + 1, '\'', inend - inptr - 1); @@ -1886,22 +1884,22 @@ rfc2184_decode (const char *in, size_t len) inbuf = decword = hex_decode (inptr, inend - inptr); inlen = strlen (inbuf); - ic = e_iconv_open ("UTF-8", charset); + ic = camel_iconv_open ("UTF-8", charset); if (ic != (iconv_t) -1) { size_t ret; outlen = inlen * 6 + 16; outbuf = outbase = g_malloc (outlen); - ret = e_iconv (ic, &inbuf, &inlen, &outbuf, &outlen); + ret = camel_iconv (ic, &inbuf, &inlen, &outbuf, &outlen); if (ret != (size_t) -1) { - e_iconv (ic, NULL, 0, &outbuf, &outlen); + camel_iconv (ic, NULL, 0, &outbuf, &outlen); *outbuf = '\0'; g_free (decoded); decoded = outbase; } - e_iconv_close (ic); + camel_iconv_close (ic); } else { decoded = decword; } @@ -2041,21 +2039,21 @@ header_decode_param (const char **in, char **paramp, char **valuep, int *is_rfc2 inbuf = value; inlen = strlen (inbuf); - charset = e_iconv_locale_charset (); - ic = e_iconv_open ("UTF-8", charset ? charset : "ISO-8859-1"); + charset = camel_charset_locale_name (); + ic = camel_iconv_open ("UTF-8", charset ? charset : "ISO-8859-1"); if (ic != (iconv_t) -1) { size_t ret; outlen = inlen * 6 + 16; outbuf = outbase = g_malloc (outlen); - ret = e_iconv (ic, &inbuf, &inlen, &outbuf, &outlen); + ret = camel_iconv (ic, &inbuf, &inlen, &outbuf, &outlen); if (ret != (size_t) -1) { - e_iconv (ic, NULL, 0, &outbuf, &outlen); + camel_iconv (ic, NULL, 0, &outbuf, &outlen); *outbuf = '\0'; } - e_iconv_close (ic); + camel_iconv_close (ic); g_free (value); value = outbase; @@ -2970,7 +2968,7 @@ header_encode_param (const unsigned char *in, gboolean *encoded) charset = "iso-8859-1"; if (strcasecmp (charset, "UTF-8") != 0) - cd = e_iconv_open (charset, "UTF-8"); + cd = camel_iconv_open (charset, "UTF-8"); if (cd == (iconv_t) -1) { charset = "UTF-8"; @@ -2986,13 +2984,13 @@ header_encode_param (const unsigned char *in, gboolean *encoded) outptr = outbuf = g_malloc (outleft); inbuf = in; - if (e_iconv (cd, &inbuf, &inleft, &outptr, &outleft) == (size_t) -1) { + if (camel_iconv (cd, &inbuf, &inleft, &outptr, &outleft) == (size_t) -1) { w(g_warning ("Conversion problem: conversion truncated: %s", strerror (errno))); } else { - e_iconv (cd, NULL, 0, &outptr, &outleft); + camel_iconv (cd, NULL, 0, &outptr, &outleft); } - e_iconv_close (cd); + camel_iconv_close (cd); inptr = outbuf; inend = outptr; diff --git a/camel/camel-sasl-digest-md5.c b/camel/camel-sasl-digest-md5.c index d7219f6779..be67d32163 100644 --- a/camel/camel-sasl-digest-md5.c +++ b/camel/camel-sasl-digest-md5.c @@ -28,12 +28,13 @@ #include <string.h> #include <ctype.h> #include <unistd.h> -#include <iconv.h> -#include "camel-sasl-digest-md5.h" -#include "camel-mime-utils.h" -#include "camel-charset-map.h" + #include <e-util/md5-utils.h> -#include <gal/util/e-iconv.h> + +#include "camel-iconv.h" +#include "camel-charset-map.h" +#include "camel-mime-utils.h" +#include "camel-sasl-digest-md5.h" #define d(x) @@ -695,21 +696,21 @@ digest_response (struct _DigestResponse *resp) char *username, *outbuf; const char *charset; size_t len, outlen; - const char *buf; + const char *inbuf; iconv_t cd; - charset = e_iconv_locale_charset(); + charset = camel_charset_locale_name (); if (!charset) charset = "iso-8859-1"; - cd = e_iconv_open (resp->charset, charset); + cd = camel_iconv_open (resp->charset, charset); len = strlen (resp->username); outlen = 2 * len; /* plenty of space */ outbuf = username = g_malloc0 (outlen + 1); - buf = resp->username; - if (cd == (iconv_t) -1 || e_iconv (cd, &buf, &len, &outbuf, &outlen) == (size_t) -1) { + inbuf = resp->username; + if (cd == (iconv_t) -1 || camel_iconv (cd, &inbuf, &len, &outbuf, &outlen) == (size_t) -1) { /* We can't convert to UTF-8 - pretend we never got a charset param? */ g_free (resp->charset); resp->charset = NULL; @@ -720,7 +721,7 @@ digest_response (struct _DigestResponse *resp) } if (cd != (iconv_t) -1) - e_iconv_close (cd); + camel_iconv_close (cd); g_byte_array_append (buffer, username, strlen (username)); g_free (username); diff --git a/camel/camel-search-private.c b/camel/camel-search-private.c index 80152e7410..8b0879f7ed 100644 --- a/camel/camel-search-private.c +++ b/camel/camel-search-private.c @@ -29,6 +29,7 @@ #include <config.h> #endif +#include <glib.h> #include <sys/types.h> #include <regex.h> #include <string.h> @@ -225,7 +226,7 @@ camel_ustrstrcase (const char *haystack, const char *needle) if (strlen (haystack) == 0) return NULL; - puni = nuni = alloca (sizeof (gunichar) * strlen (needle)); + puni = nuni = g_alloca (sizeof (gunichar) * strlen (needle)); p = needle; while ((u = utf8_get (&p))) @@ -419,12 +420,12 @@ camel_search_header_match (const char *value, const char *match, camel_search_ma vdom = strchr(value, '@'); mdom = strchr(match, '@'); if (mdom == NULL && vdom != NULL) { - v = alloca(vdom-value+1); + v = g_alloca(vdom-value+1); memcpy(v, value, vdom-value); v[vdom-value] = 0; value = (char *)v; } else if (mdom != NULL && vdom == NULL) { - v = alloca(mdom-match+1); + v = g_alloca(mdom-match+1); memcpy(v, match, mdom-match); v[mdom-match] = 0; match = (char *)v; diff --git a/camel/camel.c b/camel/camel.c index c62656de42..0a3974a913 100644 --- a/camel/camel.c +++ b/camel/camel.c @@ -36,6 +36,7 @@ #endif /* HAVE_NSS */ #include "camel.h" +#include "camel-iconv.h" #include "camel-certdb.h" #include "camel-mime-utils.h" @@ -57,6 +58,8 @@ camel_shutdown (void) camel_certdb_save (certdb); camel_object_unref (certdb); } + + camel_iconv_shutdown (); } gint @@ -79,7 +82,9 @@ camel_init (const char *configdir, gboolean nss_init) /* initialise global camel_object_type */ camel_object_get_type(); - camel_mime_utils_init(); + camel_iconv_init (); + + camel_mime_utils_init (); #ifdef HAVE_NSS if (nss_init) { |