#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
static const char hex[] = "0123456789ABCDEF";
static const char urlunsafe[] = " \"#%&+:;<=>?@[\\]^`{|}";
static const char base64chars[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
#define UNDEFINED 64
#define UTF16MASK 0x03FFUL
#define UTF16SHIFT 10
#define UTF16BASE 0x10000UL
#define UTF16HIGHSTART 0xD800UL
#define UTF16HIGHEND 0xDBFFUL
#define UTF16LOSTART 0xDC00UL
#define UTF16LOEND 0xDFFFUL
static void MailboxToURL(char *dst, const char *src)
{
unsigned char c, i, bitcount;
unsigned long ucs4, utf16, bitbuf;
unsigned char base64[256], utf8[6];
memset(base64, UNDEFINED, sizeof (base64));
for (i = 0; i < sizeof (base64chars); ++i) {
base64[(int) base64chars[i]] = i;
}
while (*src != '\0') {
c = *src++;
if (c != '&' || *src == '-') {
if (c < ' ' || c > '~' || strchr(urlunsafe, c) != NULL) {
dst[0] = '%';
dst[1] = hex[c >> 4];
dst[2] = hex[c & 0x0f];
dst += 3;
} else {
*dst++ = c;
}
if (c == '&') ++src;
} else {
bitbuf = 0;
bitcount = 0;
ucs4 = 0;
while ((c = base64[(unsigned char) *src]) != UNDEFINED) {
++src;
bitbuf = (bitbuf << 6) | c;
bitcount += 6;
if (bitcount >= 16) {
bitcount -= 16;
utf16 = (bitcount ? bitbuf >> bitcount
: bitbuf) & 0xffff;
if
(utf16 >= UTF16HIGHSTART && utf16 <= UTF16HIGHEND) {
ucs4 = (utf16 - UTF16HIGHSTART) << UTF16SHIFT;
continue;
} else if
(utf16 >= UTF16LOSTART && utf16 <= UTF16LOEND) {
ucs4 += utf16 - UTF16LOSTART + UTF16BASE;
} else {
ucs4 = utf16;
}
if (ucs4 <= 0x7fUL) {
utf8[0] = ucs4;
i = 1;
} else if (ucs4 <= 0x7ffUL) {
utf8[0] = 0xc0 | (ucs4 >> 6);
utf8[1] = 0x80 | (ucs4 & 0x3f);
i = 2;
} else if (ucs4 <= 0xffffUL) {
utf8[0] = 0xe0 | (ucs4 >> 12);
utf8[1] = 0x80 | ((ucs4 >> 6) & 0x3f);
utf8[2] = 0x80 | (ucs4 & 0x3f);
i = 3;
} else {
utf8[0] = 0xf0 | (ucs4 >> 18);
utf8[1] = 0x80 | ((ucs4 >> 12) & 0x3f);
utf8[2] = 0x80 | ((ucs4 >> 6) & 0x3f);
utf8[3] = 0x80 | (ucs4 & 0x3f);
i = 4;
}
for (c = 0; c < i; ++c) {
dst[0] = '%';
dst[1] = hex[utf8[c] >> 4];
dst[2] = hex[utf8[c] & 0x0f];
dst += 3;
}
}
}
if (*src == '-') ++src;
}
}
*dst = '\0';
}
static void URLtoMailbox(char *dst, char *src)
{
unsigned int utf8pos = 0, utf8total, i, c, utf7mode, bitstogo, utf16flag;
unsigned long ucs4 = 0, bitbuf = 0;
unsigned char hextab[256];
memset(hextab, 0, sizeof (hextab));
for (i = 0; i < sizeof (hex); ++i) {
hextab[(int) hex[i]] = i;
if (isupper((unsigned char) hex[i])) hextab[tolower(hex[i])] = i;
}
utf7mode = 0;
utf8total = 0;
bitstogo = 0;
while ((c = (unsigned char)*src) != '\0') {
++src;
if (c == '%' && src[0] != '\0' && src[1] != '\0') {
c = (hextab[(int) src[0]] << 4) | hextab[(int) src[1]];
src += 2;
}
if (c >= ' ' && c <= '~') {
if (utf7mode) {
if (bitstogo) {
*dst++ = base64chars[(bitbuf << (6 - bitstogo)) & 0x3F];
}
*dst++ = '-';
utf7mode = 0;
bitstogo = bitbuf = 0;
}
*dst++ = c;
if (c == '&') {
*dst++ = '-';
}
continue;
}
if (!utf7mode) {
*dst++ = '&';
utf7mode = 1;
}
if (c < 0x80) {
ucs4 = c;
utf8total = 1;
} else if (utf8total) {
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 {
utf8total = 4;
ucs4 = c & 0x03;
}
continue;
}
if ((ucs4 < 0x80 && utf8total > 1) ||
(ucs4 < 0x0800 && utf8total > 2) ||
(ucs4 < 0x00010000 && utf8total > 3) ||
(ucs4 < 0x00200000 && utf8total > 4) ||
(ucs4 < 0x04000000 && utf8total > 5) ||
(ucs4 < 0x80000000 && utf8total > 6)) {
utf8total = 0;
continue;
}
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;
while (bitstogo >= 6) {
bitstogo -= 6;
*dst++ = base64chars[(bitstogo ? (bitbuf >> bitstogo)
: bitbuf)
& 0x3F];
}
} while (utf16flag);
}
if (utf7mode) {
if (bitstogo) {
*dst++ = base64chars[(bitbuf << (6 - bitstogo)) & 0x3F];
}
*dst++ = '-';
}
*dst = '\0';
}
void imapurl_fromURL(char *server, char *mailbox, const char *src)
{
if (server) server[0] = '\0';
if (mailbox) mailbox[0] = '\0';
if (src[0] == '{') {
char *se;
src++;
se = strchr(src, '}');
if (se == NULL) return;
if (server) {
strncpy(server, src, se - src);
server[se - src] = '\0';
}
se += 1;
if (mailbox) strcpy(mailbox, se);
} else if (!strncmp(src, "imap://", 7)) {
char *se;
char *at;
src += 7;
se = strchr(src, '/');
if (se == NULL) return;
at = strchr(src, '@');
if (at) {
src = at + 1;
}
*se = '\0';
if (server) {
strncpy(server, src, se - src);
server[se - src] = '\0';
}
se += 1;
if (mailbox) URLtoMailbox(mailbox, se);
}
}
void imapurl_toURL(char *dst, const char *server, const char *mailbox,
const char *mechname)
{
if(mechname) sprintf(dst, "imap://;AUTH=%s@%s/",mechname,server);
else sprintf(dst, "imap://%s/", server);
MailboxToURL(dst + strlen(dst), mailbox);
}