xref: /plan9-contrib/sys/src/cmd/ip/imap4d/mutf7.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
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