diff options
author | Jeffrey Stedfast <fejj@ximian.com> | 2002-01-19 08:03:05 +0800 |
---|---|---|
committer | Jeffrey Stedfast <fejj@src.gnome.org> | 2002-01-19 08:03:05 +0800 |
commit | da5d9e6dc27ff04ba3a571cdfbad6856297556cb (patch) | |
tree | 40ed654b0b93dac68571020a19e6813905350a57 /camel/providers | |
parent | 695a0a631bd4fae44f5e3427d0ed166cd0a80f52 (diff) | |
download | gsoc2013-evolution-da5d9e6dc27ff04ba3a571cdfbad6856297556cb.tar.gz gsoc2013-evolution-da5d9e6dc27ff04ba3a571cdfbad6856297556cb.tar.zst gsoc2013-evolution-da5d9e6dc27ff04ba3a571cdfbad6856297556cb.zip |
New function to decode an IMAP mailbox name from modified UTF-7 encoding
2002-01-18 Jeffrey Stedfast <fejj@ximian.com>
* providers/imap/camel-imap-utils.c (imap_mailbox_decode): New
function to decode an IMAP mailbox name from modified UTF-7
encoding to UTF-8.
(imap_mailbox_encode): New function to convert a mailbox name from
UTF-8 to IMAP's modified UTF-7 encoding.
svn path=/trunk/; revision=15361
Diffstat (limited to 'camel/providers')
-rw-r--r-- | camel/providers/imap/camel-imap-utils.c | 264 | ||||
-rw-r--r-- | camel/providers/imap/camel-imap-utils.h | 3 |
2 files changed, 266 insertions, 1 deletions
diff --git a/camel/providers/imap/camel-imap-utils.c b/camel/providers/imap/camel-imap-utils.c index 7d2073142b..746aec2167 100644 --- a/camel/providers/imap/camel-imap-utils.c +++ b/camel/providers/imap/camel-imap-utils.c @@ -24,6 +24,7 @@ #include <stdio.h> #include <string.h> #include <time.h> +#include <iconv.h> #include "camel-imap-utils.h" #include "camel-imap-summary.h" @@ -173,8 +174,10 @@ imap_parse_folder_name (CamelImapStore *store, const char *folder_name) continue; } - if (*p == store->dir_sep) + if (*p == store->dir_sep) { + /* FIXME: decode mailbox */ g_ptr_array_add (heirarchy, g_strndup (folder_name, p - folder_name)); + } p++; } @@ -841,3 +844,262 @@ imap_namespace_concat (CamelImapStore *store, const char *name) return imap_concat (store, store->namespace, name); } + + +#define UTF8_TO_UTF7_LEN(len) ((len * 3) + 8) +#define UTF7_TO_UTF8_LEN(len) (len) + +enum { + MODE_USASCII, + MODE_AMPERSAND, + MODE_MODUTF7 +}; + +#define is_usascii(c) (((c) >= 0x20 && (c) <= 0x25) || ((c) >= 0x27 && (c) <= 0x7e)) +#define encode_mode(c) (is_usascii (c) ? MODE_USASCII : (c) == '&' ? MODE_AMPERSAND : MODE_MODUTF7) + +char * +imap_mailbox_encode (const unsigned char *in, int inlen) +{ + const unsigned char *start, *inptr, *inend; + unsigned char *mailbox, *m, *mend; + size_t inleft, outleft, conv; + char *inbuf, *outbuf; + iconv_t cd; + int mode; + + cd = (iconv_t) -1; + m = mailbox = g_malloc (UTF8_TO_UTF7_LEN (inlen) + 1); + mend = mailbox + UTF8_TO_UTF7_LEN (inlen); + + start = inptr = in; + inend = in + inlen; + mode = MODE_USASCII; + + while (inptr < inend) { + int new_mode; + + new_mode = encode_mode (*inptr); + + if (new_mode != mode) { + switch (mode) { + case MODE_USASCII: + memcpy (m, start, inptr - start); + m += (inptr - start); + break; + case MODE_AMPERSAND: + while (start < inptr) { + *m++ = '&'; + *m++ = '-'; + start++; + } + break; + case MODE_MODUTF7: + inbuf = (char *) start; + inleft = inptr - start; + outbuf = (char *) m; + outleft = mend - m; + + if (cd == (iconv_t) -1) + cd = iconv_open ("UTF-7", "UTF-8"); + + conv = iconv (cd, &inbuf, &inleft, &outbuf, &outleft); + if (conv == (size_t) -1) { + g_warning ("error converting mailbox to UTF-7!"); + } + iconv (cd, NULL, NULL, &outbuf, &outleft); + + /* shift into modified UTF-7 mode (overwrite UTF-7's '+' shift)... */ + *m++ = '&'; + + while (m < (unsigned char *) outbuf) { + /* replace '/' with ',' */ + if (*m == '/') + *m = ','; + + m++; + } + + break; + } + + mode = new_mode; + start = inptr; + } + + inptr++; + } + + switch (mode) { + case MODE_USASCII: + memcpy (m, start, inptr - start); + m += (inptr - start); + break; + case MODE_AMPERSAND: + while (start < inptr) { + *m++ = '&'; + *m++ = '-'; + start++; + } + break; + case MODE_MODUTF7: + inbuf = (char *) start; + inleft = inptr - start; + outbuf = (char *) m; + outleft = mend - m; + + if (cd == (iconv_t) -1) + cd = iconv_open ("UTF-7", "UTF-8"); + + conv = iconv (cd, &inbuf, &inleft, &outbuf, &outleft); + if (conv == (size_t) -1) { + g_warning ("error converting mailbox to UTF-7!"); + } + iconv (cd, NULL, NULL, &outbuf, &outleft); + + /* shift into modified UTF-7 mode (overwrite UTF-7's '+' shift)... */ + *m++ = '&'; + + while (m < (unsigned char *) outbuf) { + /* replace '/' with ',' */ + if (*m == '/') + *m = ','; + + m++; + } + + break; + } + + *m = '\0'; + + if (cd != (iconv_t) -1) + iconv_close (cd); + + return mailbox; +} + + +char * +imap_mailbox_decode (const unsigned char *in, int inlen) +{ + const unsigned char *start, *inptr, *inend; + unsigned char *mailbox, *m, *mend; + unsigned char mode_switch; + iconv_t cd; + + cd = (iconv_t) -1; + m = mailbox = g_malloc (UTF7_TO_UTF8_LEN (inlen) + 1); + mend = mailbox + UTF7_TO_UTF8_LEN (inlen); + + start = inptr = in; + inend = in + inlen; + mode_switch = '&'; + + while (inptr < inend) { + if (*inptr == mode_switch) { + if (mode_switch == '&') { + /* mode switch from US-ASCII to UTF-7 */ + mode_switch = '-'; + memcpy (m, start, inptr - start); + m += (inptr - start); + start = inptr; + } else if (mode_switch == '-') { + /* mode switch from UTF-7 to US-ASCII or an ampersand (&) */ + mode_switch = '&'; + start++; + if (start == inptr) { + /* we had the sequence "&-" which becomes "&" when decoded */ + *m++ = '&'; + } else { + char *buffer, *inbuf, *outbuf; + size_t buflen, outleft, conv; + + buflen = (inptr - start) + 2; + inbuf = buffer = alloca (buflen); + *inbuf++ = '+'; + while (start < inptr) { + *inbuf++ = *start == ',' ? '/' : *start; + start++; + } + *inbuf = '-'; + + inbuf = buffer; + outbuf = (char *) m; + outleft = mend - m; + + if (cd == (iconv_t) -1) + cd = iconv_open ("UTF-8", "UTF-7"); + + conv = iconv (cd, &inbuf, &buflen, &outbuf, &outleft); + if (conv == (size_t) -1) { + g_warning ("error decoding mailbox from UTF-7!"); + } + iconv (cd, NULL, NULL, NULL, NULL); + + m = (unsigned char *) outbuf; + } + + /* point to the char after the '-' */ + start = inptr + 1; + } + } + + inptr++; + } + + if (*inptr == mode_switch) { + if (mode_switch == '&') { + /* the remaining text is US-ASCII */ + memcpy (m, start, inptr - start); + m += (inptr - start); + start = inptr; + } else if (mode_switch == '-') { + /* We've got encoded UTF-7 or else an ampersand */ + start++; + if (start == inptr) { + /* we had the sequence "&-" which becomes "&" when decoded */ + *m++ = '&'; + } else { + char *buffer, *inbuf, *outbuf; + size_t buflen, outleft, conv; + + buflen = (inptr - start) + 2; + inbuf = buffer = alloca (buflen); + *inbuf++ = '+'; + while (start < inptr) { + *inbuf++ = *start == ',' ? '/' : *start; + start++; + } + *inbuf = '-'; + + inbuf = buffer; + outbuf = (char *) m; + outleft = mend - m; + + if (cd == (iconv_t) -1) + cd = iconv_open ("UTF-8", "UTF-7"); + + conv = iconv (cd, &inbuf, &buflen, &outbuf, &outleft); + if (conv == (size_t) -1) { + g_warning ("error decoding mailbox from UTF-7!"); + } + iconv (cd, NULL, NULL, NULL, NULL); + + m = (unsigned char *) outbuf; + } + } + } else { + /* illegal encoded mailbox... */ + g_warning ("illegal mailbox name encountered!"); + memcpy (m, start, inptr - start); + m += (inptr - start); + } + + *m = '\0'; + + if (cd != (iconv_t) -1) + iconv_close (cd); + + return mailbox; +} diff --git a/camel/providers/imap/camel-imap-utils.h b/camel/providers/imap/camel-imap-utils.h index f64d56743a..bedc604116 100644 --- a/camel/providers/imap/camel-imap-utils.h +++ b/camel/providers/imap/camel-imap-utils.h @@ -72,6 +72,9 @@ void imap_uid_array_free (GPtrArray *arr); char *imap_concat (CamelImapStore *imap_store, const char *prefix, const char *suffix); char *imap_namespace_concat (CamelImapStore *store, const char *name); +char *imap_mailbox_encode (const unsigned char *in, int inlen); +char *imap_mailbox_decode (const unsigned char *in, int inlen); + #ifdef __cplusplus } #endif /* __cplusplus */ |