s/g_strncasecmp/strncasecmp/g
authorJeffrey Stedfast <fejj@ximian.com>
Thu, 6 Mar 2003 21:42:11 +0000 (21:42 +0000)
committerJeffrey Stedfast <fejj@src.gnome.org>
Thu, 6 Mar 2003 21:42:11 +0000 (21:42 +0000)
2003-03-06  Jeffrey Stedfast  <fejj@ximian.com>

* providers/imap/camel-imap-utils.c (imap_next_word):
s/g_strncasecmp/strncasecmp/g

* camel-iconv.c: Updated to be an exact copy of e-iconv (except
names changed). We don't use this yet, but we may in the future.

* camel-url.c (camel_url_new_with_base): Here too.

* camel-sasl-kerberos4.c (krb4_challenge): Use camel_strdown()
here instead of g_strdown() since the latter has been deprecated.

* providers/imap/camel-imap-utils.c (imap_parse_body): Use
camel_strdown() since g_ascii_strdown() does not do what we
thought.

* providers/imap/camel-imap-store.c:
s/strstrcase/camel_strstrcase/g

* providers/imap/camel-imap-folder.c (do_append):
s/strstrcase/camel_strstrcase/
(handle_copyuid): Same.

* string-utils.c (camel_strdown): New function because the
g_ascii_strdown interface sucks.
(camel_strstrcase): Renamed from strstrcase.

camel/ChangeLog
camel/camel-iconv.c
camel/camel-iconv.h
camel/camel-sasl-kerberos4.c
camel/camel-url.c
camel/providers/imap/camel-imap-folder.c
camel/providers/imap/camel-imap-store.c
camel/providers/imap/camel-imap-utils.c
camel/string-utils.c
camel/string-utils.h

index ac301df..d37731e 100644 (file)
@@ -1,5 +1,33 @@
 2003-03-06  Jeffrey Stedfast  <fejj@ximian.com>
 
+       * providers/imap/camel-imap-utils.c (imap_next_word):
+       s/g_strncasecmp/strncasecmp/g
+
+       * camel-iconv.c: Updated to be an exact copy of e-iconv (except
+       names changed). We don't use this yet, but we may in the future.
+
+       * camel-url.c (camel_url_new_with_base): Here too.
+
+       * camel-sasl-kerberos4.c (krb4_challenge): Use camel_strdown()
+       here instead of g_strdown() since the latter has been deprecated.
+
+       * providers/imap/camel-imap-utils.c (imap_parse_body): Use
+       camel_strdown() since g_ascii_strdown() does not do what we
+       thought.
+
+       * providers/imap/camel-imap-store.c:
+       s/strstrcase/camel_strstrcase/g
+
+       * providers/imap/camel-imap-folder.c (do_append):
+       s/strstrcase/camel_strstrcase/
+       (handle_copyuid): Same.
+
+       * string-utils.c (camel_strdown): New function because the
+       g_ascii_strdown interface sucks.
+       (camel_strstrcase): Renamed from strstrcase.
+
+2003-03-06  Jeffrey Stedfast  <fejj@ximian.com>
+
        * camel-text-index.c (camel_utf8_next): Same as below.
 
        * camel-search-private.c (camel_utf8_getc): Updated since not all
@@ -45,6 +73,7 @@
        convert any CRLF sequences into plain old line-feeds to work
        around a bug in some local transport programs.
 
+>>>>>>> 1.1757
 2003-03-04  Jeffrey Stedfast  <fejj@ximian.com>
 
        * camel-object.h: s/class/klass in one place so that the header is
index 9bf614d..3f1708c 100644 (file)
@@ -1,6 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
  *  Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *           Michael Zucchi <notzed@ximian.com>
  *
  *  Copyright 2003 Ximian, Inc. (www.ximian.com)
  *
 #include <string.h>
 #include <errno.h>
 
+#include <locale.h>
+
+#ifdef HAVE_CODESET
+#include <langinfo.h>
+#endif
+
 #include "e-util/e-memory.h"
-#include "camel/camel-charset-map.h"
+#include "camel-charset-map.h"
+#include "string-utils.h"
 #include "camel-iconv.h"
 
+#define d(x)
 
-#define ICONV_CACHE_SIZE   (16)
+#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
+
+
+struct _iconv_cache_node {
+       struct _iconv_cache_node *next;
+       struct _iconv_cache_node *prev;
+
+       struct _iconv_cache *parent;
 
-struct _iconv_cache_bucket {
-       struct _iconv_cache_bucket *next;
-       struct _iconv_cache_bucket *prev;
-       guint32 refcount:31;
-       guint32 used:1;
+       int busy;
        iconv_t cd;
-       char *key;
 };
 
+struct _iconv_cache {
+       struct _iconv_cache *next;
+       struct _iconv_cache *prev;
+
+       char *conv;
+
+       EDList open;            /* stores iconv_cache_nodes, busy ones up front */
+};
+
+#define ICONV_CACHE_SIZE   (16)
 
-/* a useful website on charset alaises:
- * http://www.li18nux.org/subgroups/sa/locnameguide/v1.1draft/CodesetAliasTable-V11.html */
+static EDList iconv_cache_list;
+static GHashTable *iconv_cache;
+static GHashTable *iconv_cache_open;
+static unsigned int iconv_cache_size = 0;
+
+static GHashTable *iconv_charsets = NULL;
+static char *locale_charset = NULL;
+static char *locale_lang = NULL;
 
 struct {
        char *charset;
@@ -113,190 +147,82 @@ struct {
 };
 
 
-static GHashTable *iconv_charsets;
-
-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;
-static GStaticMutex iconv_charset_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)
-#define ICONV_CHARSET_LOCK() g_static_mutex_lock (&iconv_charset_lock)
-#define ICONV_CHARSET_UNLOCK() g_static_mutex_unlock (&iconv_charset_lock)
-#else
-#define ICONV_CACHE_LOCK()
-#define ICONV_CACHE_UNLOCK()
-#define ICONV_CHARSET_LOCK()
-#define ICONV_CHARSET_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);
-       g_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;
-       }
-}
-
-
-static void
-iconv_charset_free (char *name, char *iname, gpointer user_data)
-{
-       g_free (name);
-       g_free (iname);
-}
-
-void
-camel_iconv_shutdown (void)
-{
-       struct _iconv_cache_bucket *bucket, *next;
-       
-       g_hash_table_foreach (iconv_charsets, (GHFunc) iconv_charset_free, NULL);
-       g_hash_table_destroy (iconv_charsets);
-       
-       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 void
+camel_iconv_init (int keep)
 {
-       static int initialized = FALSE;
        char *from, *to;
        int i;
        
-       if (initialized)
+       LOCK ();
+       
+       if (iconv_charsets != NULL) {
+               if (!keep)
+                       UNLOCK();
                return;
+       }
        
        iconv_charsets = g_hash_table_new (g_str_hash, g_str_equal);
        
        for (i = 0; known_iconv_charsets[i].charset != NULL; i++) {
                from = g_strdup (known_iconv_charsets[i].charset);
                to = g_strdup (known_iconv_charsets[i].iconv_name);
-               g_ascii_strdown (from, -1);
-               
+               e_strdown (from);
                g_hash_table_insert (iconv_charsets, from, to);
        }
        
-       iconv_cache_buckets = NULL;
+       e_dlist_init (&iconv_cache_list);
        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);
+       iconv_cache_open = g_hash_table_new (NULL, NULL);
+       
+       locale = setlocale (LC_ALL, NULL);
        
-       cache_chunk = e_memchunk_new (ICONV_CACHE_SIZE, sizeof (struct _iconv_cache_bucket));
+       if (!locale || !strcmp (locale, "C") || !strcmp (locale, "POSIX")) {
+               /* The locale "C"  or  "POSIX"  is  a  portable  locale;  its
+                * LC_CTYPE  part  corresponds  to  the 7-bit ASCII character
+                * set.
+                */
+               
+               locale_charset = NULL;
+               locale_lang = NULL;
+       } else {
+#ifdef HAVE_CODESET
+               locale_charset = g_strdup (nl_langinfo (CODESET));
+               camel_strdown (locale_charset);
+#else
+               /* A locale name is typically of  the  form  language[_terri-
+                * tory][.codeset][@modifier],  where  language is an ISO 639
+                * language code, territory is an ISO 3166 country code,  and
+                * codeset  is  a  character  set or encoding identifier like
+                * ISO-8859-1 or UTF-8.
+                */
+               char *codeset, *p;
+               
+               codeset = strchr (locale, '.');
+               if (codeset) {
+                       codeset++;
+                       
+                       /* ; is a hack for debian systems and / is a hack for Solaris systems */
+                       for (p = codeset; *p && !strchr ("@;/", *p); p++);
+                       locale_charset = g_strndup (codeset, p - codeset);
+                       camel_strdown (locale_charset);
+               } else {
+                       /* charset unknown */
+                       locale_charset = NULL;
+               }
+#endif         
+               
+               /* parse the locale lang */
+               locale_parse_lang (locale);
+       }
        
-       initialized = TRUE;
+       if (!keep)
+               UNLOCK ();
 }
 
 
@@ -319,19 +245,43 @@ camel_iconv_charset_name (const char *charset)
        
        name = g_alloca (strlen (charset) + 1);
        strcpy (name, charset);
-       g_ascii_strdown (name, -1);
+       camel_strdown (name);
        
-       ICONV_CHARSET_LOCK ();
+       camel_iconv_init (TRUE);
        if ((iname = g_hash_table_lookup (iconv_charsets, name)) != NULL) {
-               ICONV_CHARSET_UNLOCK ();
+               UNLOCK ();
                return iname;
        }
        
        /* Unknown, try to convert some basic charset types to something that should work */
        if (!strncmp (name, "iso", 3)) {
-               /* camel_charset_canonical_name() can handle this case */
-               ICONV_CHARSET_UNLOCK ();
-               return camel_charset_canonical_name (charset);
+               /* Convert iso-####-# or iso####-# or iso_####-# into the canonical form: iso-####-# */
+               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 */
+                       ret = g_strdup ("iso-10646");
+               } else {
+                       tmp = p;
+                       if (*tmp == '-' || *tmp == '_')
+                               tmp++;
+                       
+                       codepage = strtoul (tmp, &p, 10);
+                       
+                       if (p > tmp) {
+                               /* codepage is numeric */
+                               ret = g_strdup_printf ("iso-%d-%d", iso, codepage);
+                       } else {
+                               /* codepage is a string - probably iso-2022-jp or something */
+                               ret = g_strdup_printf ("iso-%d-%s", iso, p);
+                       }
+               }
        } else if (strncmp (name, "windows-", 8) == 0) {
                /* Convert windows-#### or windows-cp#### to cp#### */
                tmp = name + 8;
@@ -350,11 +300,31 @@ camel_iconv_charset_name (const char *charset)
        }
        
        g_hash_table_insert (iconv_charsets, g_strdup (name), iname);
-       ICONV_CHARSET_UNLOCK ();
+       UNLOCK ();
        
        return iname;
 }
 
+static void
+flush_entry (struct _iconv_cache *ic)
+{
+       struct _iconv_cache_node *in, *nn;
+
+       in = (struct _iconv_cache_node *) ic->open.head;
+       nn = in->next;
+       while (nn) {
+               if (in->cd != (iconv_t) -1) {
+                       g_hash_table_remove (iconv_cache_open, in->cd);
+                       g_iconv_close (in->cd);
+               }
+               g_free (in);
+               in = nn;
+               nn = in->next;
+       }
+       g_free (ic->conv);
+       g_free (ic);
+}
+
 
 /**
  * camel_iconv_open:
@@ -373,7 +343,8 @@ camel_iconv_charset_name (const char *charset)
 iconv_t
 camel_iconv_open (const char *to, const char *from)
 {
-       struct _iconv_cache_bucket *bucket;
+       struct _iconv_cache_node *in;
+       struct _iconv_cache *ic;
        iconv_t cd;
        char *key;
        
@@ -383,7 +354,7 @@ camel_iconv_open (const char *to, const char *from)
        }
        
        if (!strcasecmp (from, "x-unknown"))
-               from = camel_charset_locale_name ();
+               from = camel_iconv_locale_charset ();
        
        /* Even tho g_iconv_open will find the appropriate charset
         * format(s) for the to/from charset strings (hahaha, yea
@@ -394,55 +365,78 @@ camel_iconv_open (const char *to, const char *from)
        key = g_alloca (strlen (from) + strlen (to) + 2);
        sprintf (key, "%s:%s", from, to);
        
-       ICONV_CACHE_LOCK ();
+       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);
+       ic = g_hash_table_lookup (iconv_cache, key);
+       if (ic) {
+               e_dlist_remove ((EDListNode *) ic);
+       } else {
+               struct _iconv_cache *last = (struct _iconv_cache *)iconv_cache_list.tailpred;
+               struct _iconv_cache *prev;
+               
+               prev = last->prev;
+               while (prev && iconv_cache_size > ICONV_CACHE_SIZE) {
+                       in = (struct _iconv_cache_node *) last->open.head;
+                       if (in->next && !in->busy) {
+                               d(printf ("Flushing iconv converter '%s'\n", last->conv));
+                               e_dlist_remove ((EDListNode *)last);
+                               g_hash_table_remove (iconv_cache, last->conv);
+                               flush_entry (last);
+                               iconv_cache_size--;
+                       }
+                       last = prev;
+                       prev = last->prev;
                }
                
-               bucket->refcount++;
-       } else {
-               cd = g_iconv_open (to, from);
-               if (cd == (iconv_t) -1)
-                       goto exception;
+               iconv_cache_size++;
                
-               iconv_cache_expire_unused ();
+               ic = g_new (struct _iconv_cache, 1);
+               e_dlist_init (&ic->open);
+               ic->conv = g_strdup (tofrom);
+               g_hash_table_insert (iconv_cache, ic->conv, ic);
                
-               bucket = iconv_cache_bucket_new (key, cd);
+               cd(printf ("Creating iconv converter '%s'\n", ic->conv));
        }
        
-       g_hash_table_insert (iconv_open_hash, cd, bucket->key);
-       
-       ICONV_CACHE_UNLOCK ();
-       
-       return cd;
-       
- exception:
+       e_dlist_addhead (&iconv_cache_list, (EDListNode *) ic);
        
-       ICONV_CACHE_UNLOCK ();
+       /* If we have a free iconv, use it */
+       in = (struct _iconv_cache_node *) ic->open.tailpred;
+       if (in->prev && !in->busy) {
+               cd(printf ("using existing iconv converter '%s'\n", ic->conv));
+               cd = in->cd;
+               if (cd != (iconv_t) -1) {
+                       /* work around some broken iconv implementations 
+                        * that die if the length arguments are NULL 
+                        */
+                       size_t buggy_iconv_len = 0;
+                       char *buggy_iconv_buf = NULL;
+                       
+                       /* resets the converter */
+                       g_iconv (cd, &buggy_iconv_buf, &buggy_iconv_len, &buggy_iconv_buf, &buggy_iconv_len);
+                       in->busy = TRUE;
+                       e_dlist_remove ((EDListNode *) in);
+                       e_dlist_addhead (&ic->open, (EDListNode *) in);
+               }
+       } else {
+               d(printf ("creating new iconv converter '%s'\n", ic->conv));
+               cd = g_iconv_open (to, from);
+               in = g_new (struct _iconv_cache_node, 1);
+               in->cd = cd;
+               in->parent = ic;
+               e_dlist_addhead (&ic->open, (EDListNode *) in);
+               if (cd != (iconv_t) -1) {
+                       g_hash_table_insert (iconv_cache_open, cd, in);
+                       in->busy = TRUE;
+               } else {
+                       errnosav = errno;
+                       g_warning ("Could not open converter for '%s' to '%s' charset", from, to);
+                       in->busy = FALSE;
+                       errno = errnosav;
+               }
+       }
        
-       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));
+       UNLOCK();
        
        return cd;
 }
@@ -477,41 +471,81 @@ camel_iconv (iconv_t cd, const char **inbuf, size_t *inleft, char **outbuf, size
 int
 camel_iconv_close (iconv_t cd)
 {
-       struct _iconv_cache_bucket *bucket;
-       const char *key;
+       struct _iconv_cache_node *in;
        
-       if (cd == (iconv_t) -1)
-               return 0;
-       
-       ICONV_CACHE_LOCK ();
+       if (cd == (iconv_t)-1)
+               return;
        
-       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);
-               }
+       LOCK ();
+       in = g_hash_table_lookup (iconv_cache_open, cd);
+       if (in) {
+               d(printf ("closing iconv converter '%s'\n", in->parent->conv));
+               e_dlist_remove ((EDListNode *) in);
+               in->busy = FALSE;
+               e_dlist_addtail (&in->parent->open, (EDListNode *) in);
        } else {
-               ICONV_CACHE_UNLOCK ();
-               
-               g_warning ("This iconv context wasn't opened using camel_iconv_open()");
-               
-               return g_iconv_close (cd);
+               g_warning ("trying to close iconv i dont know about: %p", cd);
+               g_iconv_close (cd);
        }
+       UNLOCK ();
+}
+
+const char *
+camel_iconv_locale_charset (void)
+{
+       camel_iconv_init (FALSE);
+       
+       return locale_charset;
+}
+
+
+const char *
+camel_iconv_locale_language (void)
+{
+       camel_iconv_init (FALSE);
+       
+       return locale_lang;
+}
+
+/* map CJKR charsets to their language code */
+/* NOTE: only support charset names that will be returned by
+ * e_iconv_charset_name() so that we don't have to keep track of all
+ * the aliases too. */
+static struct {
+       char *charset;
+       char *lang;
+} cjkr_lang_map[] = {
+       { "Big5",        "zh" },
+       { "BIG5HKCS",    "zh" },
+       { "gb2312",      "zh" },
+       { "gb18030",     "zh" },
+       { "gbk",         "zh" },
+       { "euc-tw",      "zh" },
+       { "iso-2022-jp", "ja" },
+       { "sjis",        "ja" },
+       { "ujis",        "ja" },
+       { "eucJP",       "ja" },
+       { "euc-jp",      "ja" },
+       { "euc-kr",      "ko" },
+       { "koi8-r",      "ru" },
+       { "koi8-u",      "uk" }
+};
+
+#define NUM_CJKR_LANGS (sizeof (cjkr_lang_map) / sizeof (cjkr_lang_map[0]))
+
+const char *
+camel_iconv_charset_language (const char *charset)
+{
+       int i;
        
-       ICONV_CACHE_UNLOCK ();
+       if (!charset)
+               return NULL;
+       
+       charset = camel_iconv_charset_name (charset);
+       for (i = 0; i < NUM_CJKR_LANGS; i++) {
+               if (!strcasecmp (cjkr_lang_map[i].charset, charset))
+                       return cjkr_lang_map[i].lang;
+       }
        
-       return 0;
+       return NULL;
 }
index 9fccc55..09f0a5c 100644 (file)
@@ -32,15 +32,15 @@ extern "C" {
 #include <sys/types.h>
 #include <iconv.h>
 
-void camel_iconv_init (void);
-void camel_iconv_shutdown (void);
+const char *camel_iconv_locale_charset (void);
+const char *camel_iconv_locale_language (void);
 
 const char *camel_iconv_charset_name (const char *charset);
 
-iconv_t camel_iconv_open (const char *to, const char *from);
+const char *camel_iconv_charset_language (const char *charset);
 
+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
index 50b4581..8bf1571 100644 (file)
@@ -33,6 +33,7 @@
 #undef _
 
 #include <string.h>
+#include "string-utils.h"
 #include "camel-sasl-kerberos4.h"
 #include "camel-service.h"
 
@@ -144,7 +145,7 @@ krb4_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex)
                /* Our response is an authenticator including that number. */
                h = camel_service_gethost (sasl->service, ex);
                inst = g_strndup (h->h_name, strcspn (h->h_name, "."));
-               g_strdown (inst);
+               camel_strdown (inst);
                realm = g_strdup (krb_realmofhost (h->h_name));
                camel_free_host(h);
                status = krb_mk_req (&authenticator, sasl->service_name, inst, realm, priv->nonce_h);
index c0544dd..a78ba44 100644 (file)
@@ -34,6 +34,7 @@
 #include <string.h>
 
 #include "camel-url.h"
+#include "string-utils.h"
 #include "camel-exception.h"
 #include "camel-mime-utils.h"
 #include "camel-object.h"
@@ -79,7 +80,7 @@ camel_url_new_with_base (CamelURL *base, const char *url_string)
 
        if (p > url_string && *p == ':') {
                url->protocol = g_strndup (url_string, p - url_string);
-               g_ascii_strdown (url->protocol, -1);
+               camel_strdown (url->protocol);
                url_string = p + 1;
        }
 
index a97cc8f..e7c51bf 100644 (file)
@@ -1179,7 +1179,7 @@ do_append (CamelFolder *folder, CamelMimeMessage *message,
                return response;
        
        if (store->capabilities & IMAP_CAPABILITY_UIDPLUS) {
-               *uid = strstrcase (response->status, "[APPENDUID ");
+               *uid = camel_strstrcase (response->status, "[APPENDUID ");
                if (*uid)
                        *uid = strchr (*uid + 11, ' ');
                if (*uid) {
@@ -1351,7 +1351,7 @@ handle_copyuid (CamelImapResponse *response, CamelFolder *source,
        GPtrArray *src, *dest;
        int i;
 
-       validity = strstrcase (response->status, "[COPYUID ");
+       validity = camel_strstrcase (response->status, "[COPYUID ");
        if (!validity)
                return;
        validity += 9;
index b947516..9b7ddaf 100644 (file)
@@ -1202,7 +1202,7 @@ imap_connect_online (CamelService *service, CamelException *ex)
                imap_namespaces_destroy (namespaces);
                /* end new code */
                
-               name = strstrcase (result, "NAMESPACE ((");
+               name = camel_strstrcase (result, "NAMESPACE ((");
                if (name) {
                        char *sep;
                        
@@ -1528,7 +1528,7 @@ get_folder_status (CamelImapStore *imap_store, const char *folder_name, const ch
        if (!status)
                return -1;
 
-       p = strstrcase (status, type);
+       p = camel_strstrcase (status, type);
        if (p)
                out = strtoul (p + strlen (type), NULL, 10);
        else
index 181ca3e..7ec152a 100644 (file)
@@ -35,6 +35,7 @@
 #include "camel-imap-summary.h"
 #include "camel-imap-store.h"
 #include "camel-folder.h"
+#include "string-utils.h"
 #include "camel-utf8.h"
 
 #define d(x) x
@@ -240,7 +241,7 @@ imap_parse_namespace_response (const char *response)
                return NULL;
        
        inptr = imap_next_word (response);
-       if (g_strncasecmp (inptr, "NAMESPACE", 9) != 0)
+       if (strncasecmp (inptr, "NAMESPACE", 9) != 0)
                return NULL;
        
        inptr = imap_next_word (inptr);
@@ -306,7 +307,7 @@ imap_parse_list_response (CamelImapStore *store, const char *buf, int *flags, ch
                return FALSE;
        
        word = imap_next_word (buf);
-       if (g_strncasecmp (word, "LIST", 4) && g_strncasecmp (word, "LSUB", 4))
+       if (strncasecmp (word, "LIST", 4) && strncasecmp (word, "LSUB", 4))
                return FALSE;
        
        /* check if we are looking at an LSUB response */
@@ -325,17 +326,17 @@ imap_parse_list_response (CamelImapStore *store, const char *buf, int *flags, ch
        while (*word != ')') {
                len = strcspn (word, " )");
                if (flags) {
-                       if (!g_strncasecmp (word, "\\NoInferiors", len))
+                       if (!strncasecmp (word, "\\NoInferiors", len))
                                *flags |= CAMEL_FOLDER_NOINFERIORS;
-                       else if (!g_strncasecmp (word, "\\NoSelect", len))
+                       else if (!strncasecmp (word, "\\NoSelect", len))
                                *flags |= CAMEL_FOLDER_NOSELECT;
-                       else if (!g_strncasecmp (word, "\\Marked", len))
+                       else if (!strncasecmp (word, "\\Marked", len))
                                *flags |= CAMEL_IMAP_FOLDER_MARKED;
-                       else if (!g_strncasecmp (word, "\\Unmarked", len))
+                       else if (!strncasecmp (word, "\\Unmarked", len))
                                *flags |= CAMEL_IMAP_FOLDER_UNMARKED;
-                       else if (!g_strncasecmp (word, "\\HasChildren", len))
+                       else if (!strncasecmp (word, "\\HasChildren", len))
                                *flags |= CAMEL_FOLDER_CHILDREN;
-                       else if (!g_strncasecmp (word, "\\HasNoChildren", len))
+                       else if (!strncasecmp (word, "\\HasNoChildren", len))
                                *flags |= CAMEL_IMAP_FOLDER_NOCHILDREN;
                }
                
@@ -491,17 +492,17 @@ imap_parse_flag_list (char **flag_list_p)
        
        while (*flag_list && *flag_list != ')') {
                len = strcspn (flag_list, " )");
-               if (!g_strncasecmp (flag_list, "\\Answered", len))
+               if (!strncasecmp (flag_list, "\\Answered", len))
                        flags |= CAMEL_MESSAGE_ANSWERED;
-               else if (!g_strncasecmp (flag_list, "\\Deleted", len))
+               else if (!strncasecmp (flag_list, "\\Deleted", len))
                        flags |= CAMEL_MESSAGE_DELETED;
-               else if (!g_strncasecmp (flag_list, "\\Draft", len))
+               else if (!strncasecmp (flag_list, "\\Draft", len))
                        flags |= CAMEL_MESSAGE_DRAFT;
-               else if (!g_strncasecmp (flag_list, "\\Flagged", len))
+               else if (!strncasecmp (flag_list, "\\Flagged", len))
                        flags |= CAMEL_MESSAGE_FLAGGED;
-               else if (!g_strncasecmp (flag_list, "\\Seen", len))
+               else if (!strncasecmp (flag_list, "\\Seen", len))
                        flags |= CAMEL_MESSAGE_SEEN;
-               else if (!g_strncasecmp (flag_list, "\\Recent", len))
+               else if (!strncasecmp (flag_list, "\\Recent", len))
                        flags |= CAMEL_IMAP_MESSAGE_RECENT;
                
                flag_list += len;
@@ -643,7 +644,7 @@ imap_parse_string_generic (const char **str_p, size_t *len, int type)
                out = g_strndup (str, *len);
                *str_p = str + *len;
                return out;
-       } else if (type == IMAP_NSTRING && !g_strncasecmp (str, "nil", 3)) {
+       } else if (type == IMAP_NSTRING && !strncasecmp (str, "nil", 3)) {
                *str_p += 3;
                *len = 0;
                return NULL;
@@ -732,7 +733,7 @@ parse_params (const char **parms_p, CamelContentType *type)
        char *name, *value;
        int len;
        
-       if (!g_strncasecmp (parms, "nil", 3)) {
+       if (!strncasecmp (parms, "nil", 3)) {
                *parms_p += 3;
                return;
        }
@@ -819,7 +820,7 @@ imap_parse_body (const char **body_p, CamelFolder *folder,
                        return;
                }
                
-               g_ascii_strdown (subtype, -1);
+               camel_strdown (subtype);
                ci->type = header_content_type_new ("multipart", subtype);
                g_free (subtype);
                
@@ -848,8 +849,9 @@ imap_parse_body (const char **body_p, CamelFolder *folder,
                        *body_p = NULL;
                        return;
                }
-               g_ascii_strdown (main_type, -1);
-               g_ascii_strdown (subtype, -1);
+               
+               camel_strdown (main_type);
+               camel_strdown (subtype);
                type = header_content_type_new (main_type, subtype);
                g_free (main_type);
                g_free (subtype);
index 8fa82ed..d87d506 100644 (file)
@@ -72,7 +72,7 @@ string_list_free (GList *string_list)
 }
 
 char *
-strstrcase (const char *haystack, const char *needle)
+camel_strstrcase (const char *haystack, const char *needle)
 {
        /* find the needle in the haystack neglecting case */
        const char *ptr;
@@ -94,3 +94,18 @@ strstrcase (const char *haystack, const char *needle)
        
        return NULL;
 }
+
+
+const char *
+camel_strdown (char *str)
+{
+       register char *s = str;
+       
+       while (*s) {
+               if (*s >= 'A' && *s <= 'Z')
+                       *s += 0x20;
+               s++;
+       }
+       
+       return str;
+}
index ab881a0..ddfbda8 100644 (file)
@@ -36,7 +36,9 @@ guint g_strcase_hash  (gconstpointer v);
 
 void string_list_free (GList *string_list);
 
-char *strstrcase (const char *haystack, const char *needle);
+char *camel_strstrcase (const char *haystack, const char *needle);
+
+const char *camel_strdown (char *str);
 
 #ifdef __cplusplus
 }