aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog17
-rw-r--r--camel/camel-iconv.c161
-rw-r--r--camel/camel-iconv.h2
-rw-r--r--camel/providers/pop3/camel-pop3-engine.c14
-rw-r--r--camel/providers/pop3/camel-pop3-store.c7
5 files changed, 194 insertions, 7 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index 5d50e60964..73f13758fa 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,3 +1,20 @@
+2003-02-21 Jeffrey Stedfast <fejj@ximian.com>
+
+ * camel-iconv.c (camel_iconv_charset_name): New function...back
+ from the depths of hell from whence it came originally. Turns out
+ that g_iconv_open() is lame and can't handle all the stuff we used
+ to handle in e_iconv_charset_name().
+ (camel_iconv_open): Use camel_iconv_charset_name() on the to/from
+ charsets rather than camel_charset_canonical_name(). Now maybe
+ g_iconv_open will work for charsets such as "ks_c_5601-1987".
+
+ * providers/pop3/camel-pop3-store.c (pop3_connect): Reget the
+ capabilities after a successful authentication.
+
+ * providers/pop3/camel-pop3-engine.c (get_capabilities): If we are
+ in the TRANSACTION state and CAPA did not list UIDL as a supported
+ command, try checking for it the hard way.
+
2003-02-23 Jeffrey Stedfast <fejj@ximian.com>
* providers/smtp/camel-smtp-transport.c (smtp_data): Do it the
diff --git a/camel/camel-iconv.c b/camel/camel-iconv.c
index e2798a16e1..439adf2df2 100644
--- a/camel/camel-iconv.c
+++ b/camel/camel-iconv.c
@@ -27,6 +27,7 @@
#include <glib.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <errno.h>
@@ -47,6 +48,73 @@ struct _iconv_cache_bucket {
};
+/* a useful website on charset alaises:
+ * http://www.li18nux.org/subgroups/sa/locnameguide/v1.1draft/CodesetAliasTable-V11.html */
+
+struct {
+ char *charset;
+ char *iconv_name;
+} known_iconv_charsets[] = {
+#if 0
+ /* charset name, iconv-friendly charset name */
+ { "iso-8859-1", "iso-8859-1" },
+ { "iso8859-1", "iso-8859-1" },
+ /* the above mostly serves as an example for iso-style charsets,
+ but we have code that will populate the iso-*'s if/when they
+ show up in camel_iconv_charset_name() so I'm
+ not going to bother putting them all in here... */
+ { "windows-cp1251", "cp1251" },
+ { "windows-1251", "cp1251" },
+ { "cp1251", "cp1251" },
+ /* the above mostly serves as an example for windows-style
+ charsets, but we have code that will parse and convert them
+ to their cp#### equivalents if/when they show up in
+ camel_iconv_charset_name() so I'm not going to bother
+ putting them all in here either... */
+#endif
+ /* charset name (lowercase!), iconv-friendly name (sometimes case sensitive) */
+ { "utf-8", "UTF-8" },
+ { "utf8", "UTF-8" },
+
+ /* 10646 is a special case, its usually UCS-2 big endian */
+ /* This might need some checking but should be ok for solaris/linux */
+ { "iso-10646-1", "UCS-2BE" },
+ { "iso_10646-1", "UCS-2BE" },
+ { "iso10646-1", "UCS-2BE" },
+ { "iso-10646", "UCS-2BE" },
+ { "iso_10646", "UCS-2BE" },
+ { "iso10646", "UCS-2BE" },
+
+ /* "ks_c_5601-1987" seems to be the most common of this lot */
+ { "ks_c_5601-1987", "EUC-KR" },
+ { "5601", "EUC-KR" },
+ { "ksc-5601", "EUC-KR" },
+ { "ksc-5601-1987", "EUC-KR" },
+ { "ksc-5601_1987", "EUC-KR" },
+
+ /* FIXME: Japanese/Korean/Chinese stuff needs checking */
+ { "euckr-0", "EUC-KR" },
+ { "5601", "EUC-KR" },
+ { "big5-0", "BIG5" },
+ { "big5.eten-0", "BIG5" },
+ { "big5hkscs-0", "BIG5HKCS" },
+ { "gb2312-0", "gb2312" },
+ { "gb2312.1980-0", "gb2312" },
+ { "euc-cn", "gb2312" },
+ { "gb18030-0", "gb18030" },
+ { "gbk-0", "GBK" },
+
+ { "eucjp-0", "eucJP" }, /* should this map to "EUC-JP" instead? */
+ { "ujis-0", "ujis" }, /* we might want to map this to EUC-JP */
+ { "jisx0208.1983-0", "SJIS" },
+ { "jisx0212.1990-0", "SJIS" },
+ { "pck", "SJIS" },
+ { NULL, NULL }
+};
+
+
+static GHashTable *iconv_charsets;
+
static EMemChunk *cache_chunk;
static struct _iconv_cache_bucket *iconv_cache_buckets;
static GHashTable *iconv_cache;
@@ -55,11 +123,16 @@ 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 */
@@ -158,11 +231,21 @@ iconv_cache_expire_unused (void)
}
+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;
@@ -191,10 +274,22 @@ void
camel_iconv_init (void)
{
static int initialized = FALSE;
+ char *from, *to;
+ int i;
if (initialized)
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);
+
+ g_hash_table_insert (iconv_charsets, from, to);
+ }
+
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);
@@ -206,6 +301,62 @@ camel_iconv_init (void)
/**
+ * camel_iconv_charset_name:
+ * @charset: charset name
+ *
+ * Maps charset names to the names that glib's g_iconv_open() is more
+ * likely able to handle.
+ *
+ * Returns an iconv-friendly name for @charset.
+ **/
+const char *
+camel_iconv_charset_name (const char *charset)
+{
+ char *name, *iname, *tmp;
+
+ if (charset == NULL)
+ return NULL;
+
+ name = g_alloca (strlen (charset) + 1);
+ strcpy (name, charset);
+ g_ascii_strdown (name, -1);
+
+ ICONV_CHARSET_LOCK ();
+ if ((iname = g_hash_table_lookup (iconv_charsets, name)) != NULL) {
+ ICONV_CHARSET_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);
+ } else if (strncmp (name, "windows-", 8) == 0) {
+ /* Convert windows-#### or windows-cp#### to cp#### */
+ tmp = name + 8;
+ if (!strncmp (tmp, "cp", 2))
+ tmp += 2;
+ iname = g_strdup_printf ("CP%s", tmp);
+ } else if (strncmp (name, "microsoft-", 10) == 0) {
+ /* Convert microsoft-#### or microsoft-cp#### to cp#### */
+ tmp = name + 10;
+ if (!strncmp (tmp, "cp", 2))
+ tmp += 2;
+ iname = g_strdup_printf ("CP%s", tmp);
+ } else {
+ /* Just assume its ok enough as is, case and all - let g_iconv_open() handle this */
+ iname = g_strdup (charset);
+ }
+
+ g_hash_table_insert (iconv_charsets, g_strdup (name), iname);
+ ICONV_CHARSET_UNLOCK ();
+
+ return iname;
+}
+
+
+/**
* camel_iconv_open:
* @to: charset to convert to
* @from: charset to convert from
@@ -235,11 +386,11 @@ camel_iconv_open (const char *to, const char *from)
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);
+ * format(s) for the to/from charset strings (hahaha, yea
+ * right), we still convert them to their canonical format
+ * here so that our key is in a standard format */
+ from = camel_iconv_charset_name (from);
+ to = camel_iconv_charset_name (to);
key = g_alloca (strlen (from) + strlen (to) + 2);
sprintf (key, "%s:%s", from, to);
diff --git a/camel/camel-iconv.h b/camel/camel-iconv.h
index 77052b469b..9fccc55752 100644
--- a/camel/camel-iconv.h
+++ b/camel/camel-iconv.h
@@ -35,6 +35,8 @@ extern "C" {
void camel_iconv_init (void);
void camel_iconv_shutdown (void);
+const char *camel_iconv_charset_name (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);
diff --git a/camel/providers/pop3/camel-pop3-engine.c b/camel/providers/pop3/camel-pop3-engine.c
index a76df8f9bc..6ea3704667 100644
--- a/camel/providers/pop3/camel-pop3-engine.c
+++ b/camel/providers/pop3/camel-pop3-engine.c
@@ -217,6 +217,18 @@ get_capabilities(CamelPOP3Engine *pe, int read_greeting)
while (camel_pop3_engine_iterate(pe, pc) > 0)
;
camel_pop3_engine_command_free(pe, pc);
+
+ if (pe->state == CAMEL_POP3_ENGINE_TRANSACTION && !(pe->capa & CAMEL_POP3_CAP_UIDL)) {
+ /* check for UIDL support manually */
+ pc = camel_pop3_engine_command_new (pe, CAMEL_POP3_COMMAND_SIMPLE, NULL, NULL, "UIDL 1\r\n");
+ while (camel_pop3_engine_iterate (pe, pc) > 0)
+ ;
+
+ if (pc->state == CAMEL_POP3_COMMAND_OK)
+ pe->capa |= CAMEL_POP3_CAP_UIDL;
+
+ camel_pop3_engine_command_free (pe, pc);
+ }
}
/* returns true if the command was sent, false if it was just queued */
@@ -350,7 +362,7 @@ camel_pop3_engine_command_new(CamelPOP3Engine *pe, guint32 flags, CamelPOP3Comma
pc->data = g_strdup_vprintf(fmt, ap);
pc->state = CAMEL_POP3_COMMAND_IDLE;
- /* TODO: what abou write errors? */
+ /* TODO: what about write errors? */
engine_command_queue(pe, pc);
return pc;
diff --git a/camel/providers/pop3/camel-pop3-store.c b/camel/providers/pop3/camel-pop3-store.c
index 566d57c9ba..f0928ea4cc 100644
--- a/camel/providers/pop3/camel-pop3-store.c
+++ b/camel/providers/pop3/camel-pop3-store.c
@@ -484,7 +484,8 @@ pop3_try_authenticate (CamelService *service, gboolean reprompt, const char *err
for (s = md5sum, d = md5asc; d < md5asc + 32; s++, d += 2)
sprintf (d, "%.2x", *s);
- pcp = camel_pop3_engine_command_new(store->engine, 0, NULL, NULL, "APOP %s %s\r\n", service->url->user, md5asc);
+ pcp = camel_pop3_engine_command_new(store->engine, 0, NULL, NULL, "APOP %s %s\r\n",
+ service->url->user, md5asc);
} else {
CamelServiceAuthType *auth;
GList *l;
@@ -581,6 +582,10 @@ pop3_connect (CamelService *service, CamelException *ex)
return FALSE;
}
+ /* Now that we are in the TRANSACTION state, try regetting the capabilities */
+ store->engine->state = CAMEL_POP3_ENGINE_TRANSACTION;
+ camel_pop3_engine_reget_capabilities (store->engine);
+
return TRUE;
}