Call camel_iconv_init(). (camel_shutdown): Call camel_iconv_shutdown().
authorJeffrey Stedfast <fejj@ximian.com>
Thu, 20 Feb 2003 21:04:19 +0000 (21:04 +0000)
committerJeffrey Stedfast <fejj@src.gnome.org>
Thu, 20 Feb 2003 21:04:19 +0000 (21:04 +0000)
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).

16 files changed:
camel/ChangeLog
camel/Makefile.am
camel/camel-charset-map.c
camel/camel-charset-map.h
camel/camel-filter-search.c
camel/camel-folder-summary.c
camel/camel-iconv.c [new file with mode: 0644]
camel/camel-iconv.h [new file with mode: 0644]
camel/camel-mime-filter-charset.c
camel/camel-mime-message.c
camel/camel-mime-part-utils.c
camel/camel-mime-part.c
camel/camel-mime-utils.c
camel/camel-sasl-digest-md5.c
camel/camel-search-private.c
camel/camel.c

index 54763b7..63ef0af 100644 (file)
@@ -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
 
index 119798b..7192e5e 100644 (file)
@@ -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                            \
index be57d88..5fcd490 100644 (file)
@@ -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 
  * 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 */
-
index ab60ef5..d18f782 100644 (file)
@@ -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);
index e0e3853..2439a9b 100644 (file)
 #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);
+                               }
                        }
                }
                
index 337342a..ee3fc16 100644 (file)
 #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 (file)
index 0000000..29e90cd
--- /dev/null
@@ -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 (file)
index 0000000..77052b4
--- /dev/null
@@ -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__ */
index f8eafa9..0e1c111 100644 (file)
  */
 
 
-#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);
index 428cfd0..6bd1f73 100644 (file)
 #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;
index c6fbd65..c7c0d15 100644 (file)
 #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);
index eb65dea..765a9af 100644 (file)
 #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;
index 83120e3..b12c116 100644 (file)
@@ -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;
index d7219f6..be67d32 100644 (file)
 #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);
index 80152e7..8b0879f 100644 (file)
@@ -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;
index c62656d..0a3974a 100644 (file)
@@ -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) {