17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
4*9a747e4fSDavid du Colombier #include <auth.h>
57dd7cddfSDavid du Colombier #include "imap4d.h"
67dd7cddfSDavid du Colombier
77dd7cddfSDavid du Colombier /*
87dd7cddfSDavid du Colombier * modified utf-7, as per imap4 spec
97dd7cddfSDavid du Colombier * like utf-7, but substitues , for / in base 64,
107dd7cddfSDavid du Colombier * does not allow escaped ascii characters.
117dd7cddfSDavid du Colombier *
127dd7cddfSDavid du Colombier * /lib/rfc/rfc2152 is utf-7
137dd7cddfSDavid du Colombier * /lib/rfc/rfc1642 is obsolete utf-7
147dd7cddfSDavid du Colombier *
157dd7cddfSDavid du Colombier * test sequences from rfc1642
167dd7cddfSDavid du Colombier * 'A≢Α.' 'A&ImIDkQ-.'
177dd7cddfSDavid du Colombier * 'Hi Mom ☺!" 'Hi Mom &Jjo-!'
187dd7cddfSDavid du Colombier * '日本語' '&ZeVnLIqe-'
197dd7cddfSDavid du Colombier */
207dd7cddfSDavid du Colombier
217dd7cddfSDavid du Colombier static uchar mt64d[256];
227dd7cddfSDavid du Colombier static char mt64e[64];
237dd7cddfSDavid du Colombier
247dd7cddfSDavid du Colombier static void
initm64(void)257dd7cddfSDavid du Colombier initm64(void)
267dd7cddfSDavid du Colombier {
277dd7cddfSDavid du Colombier int c, i;
287dd7cddfSDavid du Colombier
297dd7cddfSDavid du Colombier memset(mt64d, 255, 256);
307dd7cddfSDavid du Colombier memset(mt64e, '=', 64);
317dd7cddfSDavid du Colombier i = 0;
327dd7cddfSDavid du Colombier for(c = 'A'; c <= 'Z'; c++){
337dd7cddfSDavid du Colombier mt64e[i] = c;
347dd7cddfSDavid du Colombier mt64d[c] = i++;
357dd7cddfSDavid du Colombier }
367dd7cddfSDavid du Colombier for(c = 'a'; c <= 'z'; c++){
377dd7cddfSDavid du Colombier mt64e[i] = c;
387dd7cddfSDavid du Colombier mt64d[c] = i++;
397dd7cddfSDavid du Colombier }
407dd7cddfSDavid du Colombier for(c = '0'; c <= '9'; c++){
417dd7cddfSDavid du Colombier mt64e[i] = c;
427dd7cddfSDavid du Colombier mt64d[c] = i++;
437dd7cddfSDavid du Colombier }
447dd7cddfSDavid du Colombier mt64e[i] = '+';
457dd7cddfSDavid du Colombier mt64d['+'] = i++;
467dd7cddfSDavid du Colombier mt64e[i] = ',';
477dd7cddfSDavid du Colombier mt64d[','] = i;
487dd7cddfSDavid du Colombier }
497dd7cddfSDavid du Colombier
507dd7cddfSDavid du Colombier int
encmutf7(char * out,int lim,char * in)517dd7cddfSDavid du Colombier encmutf7(char *out, int lim, char *in)
527dd7cddfSDavid du Colombier {
537dd7cddfSDavid du Colombier Rune rr;
547dd7cddfSDavid du Colombier ulong r, b;
557dd7cddfSDavid du Colombier char *start = out;
567dd7cddfSDavid du Colombier char *e = out + lim;
577dd7cddfSDavid du Colombier int nb;
587dd7cddfSDavid du Colombier
597dd7cddfSDavid du Colombier if(mt64e[0] == 0)
607dd7cddfSDavid du Colombier initm64();
617dd7cddfSDavid du Colombier for(;;){
627dd7cddfSDavid du Colombier r = *(uchar*)in;
637dd7cddfSDavid du Colombier
647dd7cddfSDavid du Colombier if(r < ' ' || r >= Runeself){
657dd7cddfSDavid du Colombier if(r == '\0')
667dd7cddfSDavid du Colombier break;
677dd7cddfSDavid du Colombier if(out + 1 >= e)
687dd7cddfSDavid du Colombier return -1;
697dd7cddfSDavid du Colombier *out++ = '&';
707dd7cddfSDavid du Colombier b = 0;
717dd7cddfSDavid du Colombier nb = 0;
727dd7cddfSDavid du Colombier for(;;){
737dd7cddfSDavid du Colombier in += chartorune(&rr, in);
747dd7cddfSDavid du Colombier r = rr;
757dd7cddfSDavid du Colombier if(r == '\0' || r >= ' ' && r < Runeself)
767dd7cddfSDavid du Colombier break;
777dd7cddfSDavid du Colombier b = (b << 16) | r;
787dd7cddfSDavid du Colombier for(nb += 16; nb >= 6; nb -= 6){
797dd7cddfSDavid du Colombier if(out + 1 >= e)
807dd7cddfSDavid du Colombier return -1;
817dd7cddfSDavid du Colombier *out++ = mt64e[(b>>(nb-6))&0x3f];
827dd7cddfSDavid du Colombier }
837dd7cddfSDavid du Colombier }
847dd7cddfSDavid du Colombier for(; nb >= 6; nb -= 6){
857dd7cddfSDavid du Colombier if(out + 1 >= e)
867dd7cddfSDavid du Colombier return -1;
877dd7cddfSDavid du Colombier *out++ = mt64e[(b>>(nb-6))&0x3f];
887dd7cddfSDavid du Colombier }
897dd7cddfSDavid du Colombier if(nb){
907dd7cddfSDavid du Colombier if(out + 1 >= e)
917dd7cddfSDavid du Colombier return -1;
927dd7cddfSDavid du Colombier *out++ = mt64e[(b<<(6-nb))&0x3f];
937dd7cddfSDavid du Colombier }
947dd7cddfSDavid du Colombier
957dd7cddfSDavid du Colombier if(out + 1 >= e)
967dd7cddfSDavid du Colombier return -1;
977dd7cddfSDavid du Colombier *out++ = '-';
987dd7cddfSDavid du Colombier if(r == '\0')
997dd7cddfSDavid du Colombier break;
1007dd7cddfSDavid du Colombier }else
1017dd7cddfSDavid du Colombier in++;
1027dd7cddfSDavid du Colombier if(out + 1 >= e)
1037dd7cddfSDavid du Colombier return -1;
1047dd7cddfSDavid du Colombier *out = r;
1057dd7cddfSDavid du Colombier out++;
1067dd7cddfSDavid du Colombier if(r == '&')
1077dd7cddfSDavid du Colombier *out++ = '-';
1087dd7cddfSDavid du Colombier }
1097dd7cddfSDavid du Colombier
1107dd7cddfSDavid du Colombier if(out >= e)
1117dd7cddfSDavid du Colombier return -1;
1127dd7cddfSDavid du Colombier *out = '\0';
1137dd7cddfSDavid du Colombier return out - start;
1147dd7cddfSDavid du Colombier }
1157dd7cddfSDavid du Colombier
1167dd7cddfSDavid du Colombier int
decmutf7(char * out,int lim,char * in)1177dd7cddfSDavid du Colombier decmutf7(char *out, int lim, char *in)
1187dd7cddfSDavid du Colombier {
1197dd7cddfSDavid du Colombier Rune rr;
1207dd7cddfSDavid du Colombier char *start = out;
1217dd7cddfSDavid du Colombier char *e = out + lim;
1227dd7cddfSDavid du Colombier int c, b, nb;
1237dd7cddfSDavid du Colombier
1247dd7cddfSDavid du Colombier if(mt64e[0] == 0)
1257dd7cddfSDavid du Colombier initm64();
1267dd7cddfSDavid du Colombier for(;;){
1277dd7cddfSDavid du Colombier c = *in;
1287dd7cddfSDavid du Colombier
1297dd7cddfSDavid du Colombier if(c < ' ' || c >= Runeself){
1307dd7cddfSDavid du Colombier if(c == '\0')
1317dd7cddfSDavid du Colombier break;
1327dd7cddfSDavid du Colombier return -1;
1337dd7cddfSDavid du Colombier }
1347dd7cddfSDavid du Colombier if(c != '&'){
1357dd7cddfSDavid du Colombier if(out + 1 >= e)
1367dd7cddfSDavid du Colombier return -1;
1377dd7cddfSDavid du Colombier *out++ = c;
1387dd7cddfSDavid du Colombier in++;
1397dd7cddfSDavid du Colombier continue;
1407dd7cddfSDavid du Colombier }
1417dd7cddfSDavid du Colombier in++;
1427dd7cddfSDavid du Colombier if(*in == '-'){
1437dd7cddfSDavid du Colombier if(out + 1 >= e)
1447dd7cddfSDavid du Colombier return -1;
1457dd7cddfSDavid du Colombier *out++ = '&';
1467dd7cddfSDavid du Colombier in++;
1477dd7cddfSDavid du Colombier continue;
1487dd7cddfSDavid du Colombier }
1497dd7cddfSDavid du Colombier
1507dd7cddfSDavid du Colombier b = 0;
1517dd7cddfSDavid du Colombier nb = 0;
1527dd7cddfSDavid du Colombier while((c = *in++) != '-'){
1537dd7cddfSDavid du Colombier c = mt64d[c];
1547dd7cddfSDavid du Colombier if(c >= 64)
1557dd7cddfSDavid du Colombier return -1;
1567dd7cddfSDavid du Colombier b = (b << 6) | c;
1577dd7cddfSDavid du Colombier nb += 6;
1587dd7cddfSDavid du Colombier if(nb >= 16){
1597dd7cddfSDavid du Colombier rr = b >> (nb - 16);
1607dd7cddfSDavid du Colombier nb -= 16;
1617dd7cddfSDavid du Colombier if(out + UTFmax + 1 >= e && out + runelen(rr) + 1 >= e)
1627dd7cddfSDavid du Colombier return -1;
1637dd7cddfSDavid du Colombier out += runetochar(out, &rr);
1647dd7cddfSDavid du Colombier }
1657dd7cddfSDavid du Colombier }
1667dd7cddfSDavid du Colombier if(b & ((1 << nb) - 1))
1677dd7cddfSDavid du Colombier return -1;
1687dd7cddfSDavid du Colombier }
1697dd7cddfSDavid du Colombier
1707dd7cddfSDavid du Colombier if(out >= e)
1717dd7cddfSDavid du Colombier return -1;
1727dd7cddfSDavid du Colombier *out = '\0';
1737dd7cddfSDavid du Colombier return out - start;
1747dd7cddfSDavid du Colombier }
175