Re: ANNOUNCE: development balsa-2.1.1 released
- From: Pawel Salek <pawsa theochem kth se>
- To: "J.A. Magallon" <jamagallon able es>
- Cc: balsa-list gnome org
- Subject: Re: ANNOUNCE: development balsa-2.1.1 released
- Date: Tue, 02 Mar 2004 23:22:59 +0000
On 03/02/2004 12:19:24 AM, J.A. Magallon wrote:
>
> On 02.29, Pawel Salek wrote:
> > Hello,
> >
> > Balsa team would like to officially announce balsa-2.1.1 release
> > available at http://balsa.gnome.org/
> >
>
> Uh, how did this pass your compiler ?
>
> imap-handle.c:286: error: conflicting types for
> 'imap_mbox_handle_reconnect'
gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5) seems to be very
forgiving. I have just fixed it in cvs (and few more, too). The patch
contains the fixes (+implementation of UTF7 for mailbox names - it cannot
hurt). Thanks for pointing this out!
Pawel
Index: libbalsa/imap/imap-auth.c
===================================================================
RCS file: /cvs/gnome/balsa/libbalsa/imap/imap-auth.c,v
retrieving revision 1.9
diff -u -r1.9 imap-auth.c
--- libbalsa/imap/imap-auth.c 29 Feb 2004 16:40:37 -0000 1.9
+++ libbalsa/imap/imap-auth.c 2 Mar 2004 23:13:22 -0000
@@ -30,7 +30,7 @@
#include "imap_private.h"
/* ordered from strongest to weakest */
-ImapAuthenticator imap_authenticators_arr[] = {
+static ImapAuthenticator imap_authenticators_arr[] = {
imap_auth_cram,
imap_auth_login,
NULL
Index: libbalsa/imap/imap-commands.c
===================================================================
RCS file: /cvs/gnome/balsa/libbalsa/imap/imap-commands.c,v
retrieving revision 1.33
diff -u -r1.33 imap-commands.c
--- libbalsa/imap/imap-commands.c 2 Mar 2004 10:57:56 -0000 1.33
+++ libbalsa/imap/imap-commands.c 2 Mar 2004 23:13:23 -0000
@@ -23,6 +23,7 @@
#include "imap-commands.h"
#include "imap_private.h"
#include "siobuf.h"
+#include "util.h"
#define ELEMENTS(x) (sizeof (x) / sizeof(x[0]))
struct msg_set {
@@ -50,11 +51,11 @@
if(seq<=hi && (num=incl(seq, data)) != 0) {
switch(mode) {
case BEGIN:
- sprintf(buf, "%d", num); g_string_append(res, buf);
+ sprintf(buf, "%u", num); g_string_append(res, buf);
mode = LASTIN; break;
case RANGE:
if(num!=prev+1) {
- sprintf(buf, ":%d,%d", prev, num); g_string_append(res, buf);
+ sprintf(buf, ":%u,%u", prev, num); g_string_append(res, buf);
mode = LASTIN;
}
break;
@@ -64,7 +65,7 @@
break;
} /* else fall through */
case LASTOUT:
- sprintf(buf, ",%d", num); g_string_append(res, buf);
+ sprintf(buf, ",%u", num); g_string_append(res, buf);
mode = LASTIN; break;
}
} else {
@@ -73,7 +74,7 @@
case LASTOUT: break;
case LASTIN: mode = LASTOUT; break;
case RANGE:
- sprintf(buf, ":%d", prev); g_string_append(res, buf);
+ sprintf(buf, ":%u", prev); g_string_append(res, buf);
mode = LASTOUT;
break;
}
@@ -203,7 +204,7 @@
imap_mbox_select(ImapMboxHandle* handle, const char *mbox,
gboolean *readonly_mbox)
{
- gchar* cmd;
+ gchar* cmd, *mbx7;
ImapResponse rc;
if (handle->state == IMHS_SELECTED && strcmp(handle->mbox, mbox) == 0)
@@ -213,7 +214,10 @@
mbox_view_dispose(&handle->mbox_view);
handle->unseen = 0;
- cmd = g_strdup_printf("SELECT \"%s\"", mbox);
+ mbx7 = imap_utf8_to_mailbox(mbox);
+
+ cmd = g_strdup_printf("SELECT \"%s\"", mbx7);
+ g_free(mbx7);
rc= imap_cmd_exec(handle, cmd);
g_free(cmd);
if(rc == IMR_OK) {
@@ -234,9 +238,10 @@
ImapResponse
imap_mbox_examine(ImapMboxHandle* handle, const char* mbox)
{
- gchar* cmd = g_strdup_printf("EXAMINE %s", mbox);
+ gchar *mbx7 = imap_utf8_to_mailbox(mbox);
+ gchar* cmd = g_strdup_printf("EXAMINE \"%s\"", mbx7);
ImapResponse rc = imap_cmd_exec(handle, cmd);
- g_free(cmd);
+ g_free(mbx7); g_free(cmd);
if(rc == IMR_OK) {
g_free(handle->mbox);
handle->mbox = g_strdup(mbox);
@@ -248,11 +253,12 @@
/* 6.3.3 CREATE Command */
ImapResponse
-imap_mbox_create(ImapMboxHandle* handle, const char* new_mbox)
+imap_mbox_create(ImapMboxHandle* handle, const char* mbox)
{
- gchar* cmd = g_strdup_printf("CREATE \"%s\"", new_mbox);
+ gchar *mbx7 = imap_utf8_to_mailbox(mbox);
+ gchar* cmd = g_strdup_printf("CREATE \"%s\"", mbx7);
ImapResponse rc = imap_cmd_exec(handle, cmd);
- g_free(cmd);
+ g_free(mbx7); g_free(cmd);
return rc;
}
@@ -261,7 +267,8 @@
ImapResponse
imap_mbox_delete(ImapMboxHandle* handle, const char* mbox)
{
- gchar* cmd = g_strdup_printf("DELETE \"%s\"", mbox);
+ gchar *mbx7 = imap_utf8_to_mailbox(mbox);
+ gchar* cmd = g_strdup_printf("DELETE \"%s\"", mbx7);
ImapResponse rc = imap_cmd_exec(handle, cmd);
g_free(cmd);
return rc;
@@ -274,7 +281,10 @@
const char* old_mbox,
const char* new_mbox)
{
- gchar* cmd = g_strdup_printf("RENAME \"%s\" \"%s\"", old_mbox, new_mbox);
+ gchar *mbx7o = imap_utf8_to_mailbox(old_mbox);
+ gchar *mbx7n = imap_utf8_to_mailbox(old_mbox);
+
+ gchar* cmd = g_strdup_printf("RENAME \"%s\" \"%s\"", mbx7o, mbx7n);
ImapResponse rc = imap_cmd_exec(handle, cmd);
g_free(cmd);
return rc;
@@ -287,11 +297,12 @@
imap_mbox_subscribe(ImapMboxHandle* handle,
const char* mbox, gboolean subscribe)
{
+ gchar *mbx7 = imap_utf8_to_mailbox(mbox);
gchar* cmd = g_strdup_printf("%s \"%s\"",
subscribe ? "SUBSCRIBE" : "UNSUBSCRIBE",
- mbox);
+ mbx7);
ImapResponse rc = imap_cmd_exec(handle, cmd);
- g_free(cmd);
+ g_free(mbx7); g_free(cmd);
return rc;
}
@@ -300,7 +311,8 @@
ImapResponse
imap_mbox_list(ImapMboxHandle *handle, const char* what)
{
- gchar * cmd = g_strdup_printf("LIST \"%s\" \"%%\"", what);
+ gchar *mbx7 = imap_utf8_to_mailbox(what);
+ gchar *cmd = g_strdup_printf("LIST \"%s\" \"%%\"", mbx7);
ImapResponse rc = imap_cmd_exec(handle, cmd);
g_free(cmd);
return rc;
@@ -311,9 +323,10 @@
ImapResponse
imap_mbox_lsub(ImapMboxHandle *handle, const char* what)
{
- gchar * cmd = g_strdup_printf("LSUB \"%s\" \"%%\"", what);
+ gchar *mbx7 = imap_utf8_to_mailbox(what);
+ gchar *cmd = g_strdup_printf("LSUB \"%s\" \"%%\"", mbx7);
ImapResponse rc = imap_cmd_exec(handle, cmd);
- g_free(cmd);
+ g_free(mbx7); g_free(cmd);
return rc;
}
@@ -324,7 +337,7 @@
/* 6.3.11 APPEND Command */
static gchar*
-enum_flag_to_str(ImapMsgFlag flg)
+enum_flag_to_str(ImapMsgFlags flg)
{
GString *flags_str = g_string_new("");
unsigned idx;
@@ -343,62 +356,61 @@
ImapMsgFlags flags, size_t sz,
ImapAppendFunc dump_cb, void *arg)
{
+ int use_literal = imap_mbox_handle_can_do(handle, IMCAP_LITERAL);
unsigned cmdno;
ImapResponse rc;
- /* FIXME: quoting */
+ gchar *mbx7 = imap_utf8_to_mailbox(mbox);
gchar *cmd;
+ char *litstr = use_literal ? "+" : "";
+ char buf[4096];
+ size_t s, delta;
+ int c;
if(flags) {
gchar *str = enum_flag_to_str(flags);
- cmd = g_strdup_printf("APPEND \"%s\" (%s) {%d}", mbox, str, sz);
+ cmd = g_strdup_printf("APPEND \"%s\" (%s) {%u%s}", mbx7, str, sz, litstr);
g_free(str);
} else
- cmd = g_strdup_printf("APPEND \"%s\" {%d}", mbox, sz);
+ cmd = g_strdup_printf("APPEND \"%s\" {%u%s}", mbx7, sz, litstr);
- rc = imap_cmd_start(handle, cmd, &cmdno);
- g_free(cmd);
- if (rc<0) /* irrecoverable connection error. */
+ c = imap_cmd_start(handle, cmd, &cmdno);
+ g_free(mbx7); g_free(cmd);
+ if (c<0) /* irrecoverable connection error. */
return IMR_SEVERED;
+ if(use_literal)
+ rc = IMR_RESPOND; /* we do it without flushing */
+ else {
+ sio_flush(handle->sio);
+ do {
+ rc = imap_cmd_step (handle, cmdno);
+ } while (rc == IMR_UNTAGGED);
+ if(rc != IMR_RESPOND) return rc;
+ while( (c=sio_getc(handle->sio)) != -1 && c != '\n');
+ }
+ for(s=0; s<sz; s+= delta) {
+ delta = dump_cb(buf, sizeof(buf), arg);
+ if(s+delta>sz) delta = sz-s;
+ sio_write(handle->sio, buf, delta);
+ }
+
+ /* It has been though observed that "Cyrus IMAP4 v2.0.16-p1
+ * server" can hang if the flush isn't done under following conditions:
+ * a). TLS is enabled, b). message contains NUL characters. NUL
+ * characters are forbidden (RFC3501, sect. 4.3.1) and we probably
+ * should make sure on a higher level that they are not sent.
+ */
+ /* sio_flush(handle->sio); */
+ sio_write(handle->sio, "\r\n", 2);
sio_flush(handle->sio);
do {
rc = imap_cmd_step (handle, cmdno);
} while (rc == IMR_UNTAGGED);
-
- if (rc == IMR_RESPOND) {
- char buf[4096];
- size_t s, delta;
- int c;
- while( (c=sio_getc(handle->sio)) != -1 && c != '\n');
- for(s=0; s<sz; s+= delta) {
- delta = dump_cb(buf, sizeof(buf), arg);
- if(s+delta>sz) delta = sz-s;
- sio_write(handle->sio, buf, delta);
- }
- /* It has been though observed that "Cyrus IMAP4 v2.0.16-p1
- * server" can hang if this isn't done under following conditions:
- * a). TLS is enabled, b). message contains NUL characters. NUL
- * characters are forbidden (RFC3501, sect. 4.3.1) and we probably
- * should make sure on a higher level that they are not sent.
- */
- sio_flush(handle->sio);
- sio_write(handle->sio, "\r\n", 2);
- sio_flush(handle->sio);
- do {
- rc = imap_cmd_step (handle, cmdno);
- } while (rc == IMR_UNTAGGED);
- } /* FIXME: else unexpected response */
return rc;
}
-#if USE_STRING_BUF /* not used currently */
-struct string_buf {
- char *string;
- unsigned pos;
-};
-#endif
-#if USE_IMAP_APPEND_STR /* not used currently */
+#ifdef USE_IMAP_APPEND_STR /* not used currently */
static size_t
pass_str(char* buf, size_t sz, void*arg)
{
@@ -461,40 +473,6 @@
return handle->unseen;
}
-static void
-find_next_cb(ImapMboxHandle* handle, unsigned seqno, unsigned *res)
-{
- if(!*res)
- *res = seqno;
-}
-
-
-/* should chain up the callbacks */
-unsigned
-imap_mbox_find_next(ImapMboxHandle* handle, unsigned start,
- const char *search_str)
-{
- ImapResponse rc;
- unsigned seqno = 0;
- void *arg;
- ImapSearchCb cb;
- const char *filter_str = mbox_view_get_str(&handle->mbox_view);
-
- cb = handle->search_cb; handle->search_cb = (ImapSearchCb)find_next_cb;
- arg = handle->search_arg; handle->search_arg = &seqno;
- while(seqno==0 && start<=handle->exists) {
- unsigned top = start+3000>handle->exists ? handle->exists : start+3000;
- gchar * cmd = g_strdup_printf("SEARCH %d:%d (FROM \"%s\"%s%s)",
- start, top, search_str,
- *filter_str?" ":"", filter_str);
- rc = imap_cmd_exec(handle, cmd);
- g_free(cmd);
- start = top+1;
- }
- handle->search_cb = cb; handle->search_arg = arg;
- return seqno;
-}
-
struct find_all_data {
unsigned *seqno;
unsigned msgcnt, allocated;
@@ -667,7 +645,7 @@
char cmd[40];
handle->body_cb = body_cb;
handle->body_arg = arg;
- snprintf(cmd, sizeof(cmd), "FETCH %d BODY[%s]", seqno, section);
+ snprintf(cmd, sizeof(cmd), "FETCH %u BODY[%s]", seqno, section);
return imap_cmd_exec(handle, cmd);
}
@@ -727,7 +705,7 @@
gchar* cmd, *str;
str = enum_flag_to_str(flg);
- cmd = g_strdup_printf("STORE %d %cFLAGS (%s)", seq,
+ cmd = g_strdup_printf("STORE %u %cFLAGS (%s)", seq,
state ? '+' : '-', str);
g_free(str);
rc = imap_cmd_exec(h, cmd);
@@ -743,9 +721,10 @@
imap_mbox_handle_copy(ImapMboxHandle* handle, unsigned seqno,
const gchar *dest)
{
- gchar *cmd = g_strdup_printf("COPY %u \"%s\"", seqno, dest);
+ gchar *mbx7 = imap_utf8_to_mailbox(dest);
+ gchar *cmd = g_strdup_printf("COPY %u \"%s\"", seqno, mbx7);
ImapResponse rc = imap_cmd_exec(handle, cmd);
- g_free(cmd);
+ g_free(mbx7); g_free(cmd);
return rc;
}
Index: libbalsa/imap/imap-commands.h
===================================================================
RCS file: /cvs/gnome/balsa/libbalsa/imap/imap-commands.h,v
retrieving revision 1.17
diff -u -r1.17 imap-commands.h
--- libbalsa/imap/imap-commands.h 29 Feb 2004 16:40:37 -0000 1.17
+++ libbalsa/imap/imap-commands.h 2 Mar 2004 23:13:23 -0000
@@ -45,7 +45,7 @@
ImapResponse imap_mbox_append(ImapMboxHandle *handle, const char *mbox,
ImapMsgFlags flags, size_t sz,
ImapAppendFunc dump_cb, void* arg);
-#if USE_IMAP_APPEND_STR /* not used currently */
+#ifdef USE_IMAP_APPEND_STR /* not used currently */
ImapResponse imap_mbox_append_str(ImapMboxHandle *handle, const char *mbox,
ImapMsgFlags flags, size_t sz, char *txt);
#endif
Index: libbalsa/imap/imap-handle.c
===================================================================
RCS file: /cvs/gnome/balsa/libbalsa/imap/imap-handle.c,v
retrieving revision 1.43
diff -u -r1.43 imap-handle.c
--- libbalsa/imap/imap-handle.c 2 Mar 2004 10:57:56 -0000 1.43
+++ libbalsa/imap/imap-handle.c 2 Mar 2004 23:13:23 -0000
@@ -46,8 +46,6 @@
#include "siobuf.h"
#include "util.h"
-FILE *debug_stream = NULL;
-
#define LONG_STRING 512
#define ELEMENTS(x) (sizeof (x) / sizeof(x[0]))
@@ -572,6 +570,8 @@
mbox_view_dispose(&handle->mbox_view);
imap_mbox_resize_cache(handle, 0);
+
+ G_OBJECT_CLASS(parent_class)->finalize(gobject);
}
typedef void (*ImapTasklet)(ImapMboxHandle*, void*);
@@ -714,7 +714,7 @@
rc = imap_cmd_exec(h, cmd);
g_free(cmd);
h->search_cb = cb; h->search_arg = arg;
- return 1;
+ return rc == IMR_OK;
}
const char*
@@ -1084,9 +1084,8 @@
return IMR_SEVERED;
/* create sequence for command */
- rc = imap_cmd_start(handle, cmd, &cmdno);
- if (rc<0) /* irrecoverable connection error. */
- return IMR_SEVERED;
+ if (imap_cmd_start(handle, cmd, &cmdno)<0)
+ return IMR_SEVERED; /* irrecoverable connection error. */
sio_flush(handle->sio);
do {
@@ -1239,8 +1238,6 @@
#include "imap-handle.h"
-ImapResponse (*handler)(ImapMboxHandle *h);
-
static void
ignore_bad_charset(struct siobuf *sio, int c)
{
@@ -1432,7 +1429,7 @@
"HasChildren", "HasNoChildren"
};
int flags = 0;
- char buf[LONG_STRING], *s;
+ char buf[LONG_STRING], *s, *mbx;
int c, delim;
ImapResponse rc;
@@ -1464,10 +1461,12 @@
if(sio_getc(h->sio) != ' ') return IMR_PROTOCOL;
/* mailbox */
s = imap_get_astring(h->sio, &c);
+ mbx = imap_mailbox_to_utf8(s);
rc = ir_check_crlf(h, c);
g_signal_emit(G_OBJECT(h), imap_mbox_handle_signals[signal],
- 0, delim, &flags, s);
+ 0, delim, &flags, mbx);
g_free(s);
+ g_free(mbx);
return rc;
}
Index: libbalsa/imap/imap-handle.h
===================================================================
RCS file: /cvs/gnome/balsa/libbalsa/imap/imap-handle.h,v
retrieving revision 1.20
diff -u -r1.20 imap-handle.h
--- libbalsa/imap/imap-handle.h 29 Feb 2004 16:40:37 -0000 1.20
+++ libbalsa/imap/imap-handle.h 2 Mar 2004 23:13:23 -0000
@@ -138,8 +138,8 @@
ImapResult imap_mbox_handle_connect(ImapMboxHandle* r, const char *hst,
int over_ssl);
-ImapResponse imap_mbox_handle_reconnect(ImapMboxHandle* r,
- gboolean *readonly);
+ImapResult imap_mbox_handle_reconnect(ImapMboxHandle* r,
+ gboolean *readonly);
unsigned imap_mbox_handle_require_tls(ImapMboxHandle* r, unsigned state);
/* int below is a boolean */
Index: libbalsa/imap/util.c
===================================================================
RCS file: /cvs/gnome/balsa/libbalsa/imap/util.c,v
retrieving revision 1.4
diff -u -r1.4 util.c
--- libbalsa/imap/util.c 29 Feb 2004 16:40:37 -0000 1.4
+++ libbalsa/imap/util.c 2 Mar 2004 23:13:23 -0000
@@ -24,6 +24,7 @@
#include <stdio.h>
#include <ctype.h>
#include <string.h>
+#include <stdlib.h>
#include "util.h"
#define SKIPWS(c) while (*(c) && isspace ((unsigned char) *(c))) c++;
@@ -136,7 +137,7 @@
#define BAD -1
#define base64val(c) Index_64[(unsigned int)(c)]
-char B64Chars[64] = {
+static char B64Chars[64] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
@@ -144,7 +145,7 @@
'8', '9', '+', '/'
};
-int Index_64[128] = {
+static int Index_64[128] = {
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
@@ -229,3 +230,233 @@
return len;
}
+
+
+/* ===================================================================
+ * UTF-7 conversion routines as in RFC 2192
+ * =================================================================== */
+/* UTF7 modified base64 alphabet */
+static char base64chars[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
+#define UNDEFINED 64
+
+/* UTF16 definitions */
+#define UTF16MASK 0x03FFUL
+#define UTF16SHIFT 10
+#define UTF16BASE 0x10000UL
+#define UTF16HIGHSTART 0xD800UL
+#define UTF16HIGHEND 0xDBFFUL
+#define UTF16LOSTART 0xDC00UL
+#define UTF16LOEND 0xDFFFUL
+
+
+/* Convert an IMAP mailbox to a UTF-8 string.
+ * dst needs to have roughly 4 times the storage space of src
+ * Hex encoding can triple the size of the input
+ * UTF-7 can be slightly denser than UTF-8
+ * (worst case: 8 octets UTF-7 becomes 9 octets UTF-8)
+ */
+char*
+imap_mailbox_to_utf8(const unsigned char *mbox)
+{
+ unsigned c, i, bitcount;
+ unsigned long ucs4, utf16, bitbuf;
+ unsigned char base64[256];
+ const unsigned char *src;
+ char *dst, *res = malloc(2*strlen(mbox)+1);
+
+ bitbuf = 0;
+ dst = res;
+ src = mbox;
+ if(!dst) return NULL;
+ /* initialize modified base64 decoding table */
+ memset(base64, UNDEFINED, sizeof (base64));
+ for (i = 0; i < sizeof (base64chars); ++i) {
+ base64[(unsigned)base64chars[i]] = i;
+ }
+
+ /* loop until end of string */
+ while (*src != '\0') {
+ c = *src++;
+ /* deal with literal characters and &- */
+ if (c != '&' || *src == '-') {
+ /* encode literally */
+ *dst++ = c;
+ /* skip over the '-' if this is an &- sequence */
+ if (c == '&') ++src;
+ } else {
+ /* convert modified UTF-7 -> UTF-16 -> UCS-4 -> UTF-8 -> HEX */
+ bitbuf = 0;
+ bitcount = 0;
+ ucs4 = 0;
+ while ((c = base64[(unsigned char) *src]) != UNDEFINED) {
+ ++src;
+ bitbuf = (bitbuf << 6) | c;
+ bitcount += 6;
+ /* enough bits for a UTF-16 character? */
+ if (bitcount >= 16) {
+ bitcount -= 16;
+ utf16 = (bitcount ? bitbuf >> bitcount
+ : bitbuf) & 0xffff;
+ /* convert UTF16 to UCS4 */
+ if
+ (utf16 >= UTF16HIGHSTART && utf16 <= UTF16HIGHEND) {
+ ucs4 = (utf16 - UTF16HIGHSTART) << UTF16SHIFT;
+ continue;
+ } else if
+ (utf16 >= UTF16LOSTART && utf16 <= UTF16LOEND) {
+ ucs4 += utf16 - UTF16LOSTART + UTF16BASE;
+ } else {
+ ucs4 = utf16;
+ }
+
+ /* convert UTF-16 range of UCS4 to UTF-8 */
+ if (ucs4 <= 0x7fUL) {
+ dst[0] = ucs4;
+ dst += 1;
+ } else if (ucs4 <= 0x7ffUL) {
+ dst[0] = 0xc0 | (ucs4 >> 6);
+ dst[1] = 0x80 | (ucs4 & 0x3f);
+ dst += 2;
+ } else if (ucs4 <= 0xffffUL) {
+ dst[0] = 0xe0 | (ucs4 >> 12);
+ dst[1] = 0x80 | ((ucs4 >> 6) & 0x3f);
+ dst[2] = 0x80 | (ucs4 & 0x3f);
+ dst += 3;
+ } else {
+ dst[0] = 0xf0 | (ucs4 >> 18);
+ dst[1] = 0x80 | ((ucs4 >> 12) & 0x3f);
+ dst[2] = 0x80 | ((ucs4 >> 6) & 0x3f);
+ dst[3] = 0x80 | (ucs4 & 0x3f);
+ dst += 4;
+ }
+ }
+ }
+ /* skip over trailing '-' in modified UTF-7 encoding */
+ if (*src == '-') ++src;
+ }
+ }
+ /* terminate destination string */
+ *dst = '\0';
+ return res;
+}
+
+/* Convert hex coded UTF-8 string to modified UTF-7 IMAP mailbox
+ * dst should be about twice the length of src to deal with non-hex
+ * coded URLs
+ */
+char*
+imap_utf8_to_mailbox(const unsigned char *src)
+{
+ unsigned int utf8pos, utf8total, c, utf7mode, bitstogo, utf16flag;
+ unsigned long ucs4 = 0, bitbuf = 0;
+
+ /* initialize hex lookup table */
+ unsigned char *dst, *res = malloc(2*strlen(src)+1);
+ dst = res;
+ if(!dst) return NULL;
+
+ utf7mode = 0;
+ utf8total = 0;
+ bitstogo = 0;
+ utf8pos = 0;
+ while ((c = *src) != '\0') {
+ ++src;
+ /* normal character? */
+ if (c >= ' ' && c <= '~') {
+ /* switch out of UTF-7 mode */
+ if (utf7mode) {
+ if (bitstogo) {
+ *dst++ = base64chars[(bitbuf << (6 - bitstogo)) & 0x3F];
+ }
+ *dst++ = '-';
+ utf7mode = 0;
+ utf8pos = 0;
+ bitstogo = 0;
+ utf8total= 0;
+ }
+ *dst++ = c;
+ /* encode '&' as '&-' */
+ if (c == '&') {
+ *dst++ = '-';
+ }
+ continue;
+ }
+ /* switch to UTF-7 mode */
+ if (!utf7mode) {
+ *dst++ = '&';
+ utf7mode = 1;
+ }
+ /* Encode US-ASCII characters as themselves */
+ if (c < 0x80) {
+ ucs4 = c;
+ utf8total = 1;
+ } else if (utf8total) {
+ /* save UTF8 bits into UCS4 */
+ ucs4 = (ucs4 << 6) | (c & 0x3FUL);
+ if (++utf8pos < utf8total) {
+ continue;
+ }
+ } else {
+ utf8pos = 1;
+ if (c < 0xE0) {
+ utf8total = 2;
+ ucs4 = c & 0x1F;
+ } else if (c < 0xF0) {
+ utf8total = 3;
+ ucs4 = c & 0x0F;
+ } else {
+ /* NOTE: can't convert UTF8 sequences longer than 4 */
+ utf8total = 4;
+ ucs4 = c & 0x03;
+ }
+ continue;
+ }
+ /* loop to split ucs4 into two utf16 chars if necessary */
+ utf8total = 0;
+ do {
+ if (ucs4 >= UTF16BASE) {
+ ucs4 -= UTF16BASE;
+ bitbuf = (bitbuf << 16) | ((ucs4 >> UTF16SHIFT)
+ + UTF16HIGHSTART);
+ ucs4 = (ucs4 & UTF16MASK) + UTF16LOSTART;
+ utf16flag = 1;
+ } else {
+ bitbuf = (bitbuf << 16) | ucs4;
+ utf16flag = 0;
+ }
+ bitstogo += 16;
+ /* spew out base64 */
+ while (bitstogo >= 6) {
+ bitstogo -= 6;
+ *dst++ = base64chars[(bitstogo ? (bitbuf >> bitstogo)
+ : bitbuf)
+ & 0x3F];
+ }
+ } while (utf16flag);
+ }
+ /* if in UTF-7 mode, finish in ASCII */
+ if (utf7mode) {
+ if (bitstogo) {
+ *dst++ = base64chars[(bitbuf << (6 - bitstogo)) & 0x3F];
+ }
+ *dst++ = '-';
+ }
+ /* tie off string */
+ *dst = '\0';
+ return res;
+}
+
+#if 0
+int main(int argc, char *argv[])
+{
+ int i;
+ for(i=1; i<argc; i++) {
+ char *mbx = imap_utf8_to_mailbox(argv[i]);
+ char *utf8 = imap_mailbox_to_utf8(mbx);
+ printf("orig='%s' mbx='%s' back='%s'\n", argv[i], mbx, utf8);
+ free(mbx); free(utf8);
+ }
+ return 0;
+}
+#endif
Index: libbalsa/imap/util.h
===================================================================
RCS file: /cvs/gnome/balsa/libbalsa/imap/util.h,v
retrieving revision 1.3
diff -u -r1.3 util.h
--- libbalsa/imap/util.h 29 Feb 2004 16:40:37 -0000 1.3
+++ libbalsa/imap/util.h 2 Mar 2004 23:13:23 -0000
@@ -28,4 +28,7 @@
size_t len, size_t olen);
int lit_conv_from_base64(char *out, const char *in);
+char* imap_mailbox_to_utf8(const unsigned char *src);
+char* imap_utf8_to_mailbox(const unsigned char *src);
+
#endif
--=-nwTs0j4VlFf5ger7Kyvg--
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]