Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <bio.h>
4
#include <auth.h>
5
#include "imap4d.h"
6
 
7
/*
8
 * modified utf-7, as per imap4 spec
9
 * like utf-7, but substitues , for / in base 64,
10
 * does not allow escaped ascii characters.
11
 *
12
 * /lib/rfc/rfc2152 is utf-7
13
 * /lib/rfc/rfc1642 is obsolete utf-7
14
 *
15
 * test sequences from rfc1642
16
 *	'A≢Α.'		'A&ImIDkQ-.'
17
 *	'Hi Mom ☺!"	'Hi Mom &Jjo-!'
18
 *	'日本語'		'&ZeVnLIqe-'
19
 */
20
 
21
static uchar mt64d[256];
22
static char mt64e[64];
23
 
24
static void
25
initm64(void)
26
{
27
	int c, i;
28
 
29
	memset(mt64d, 255, 256);
30
	memset(mt64e, '=', 64);
31
	i = 0;
32
	for(c = 'A'; c <= 'Z'; c++){
33
		mt64e[i] = c;
34
		mt64d[c] = i++;
35
	}
36
	for(c = 'a'; c <= 'z'; c++){
37
		mt64e[i] = c;
38
		mt64d[c] = i++;
39
	}
40
	for(c = '0'; c <= '9'; c++){
41
		mt64e[i] = c;
42
		mt64d[c] = i++;
43
	}
44
	mt64e[i] = '+';
45
	mt64d['+'] = i++;
46
	mt64e[i] = ',';
47
	mt64d[','] = i;
48
}
49
 
50
int
51
encmutf7(char *out, int lim, char *in)
52
{
53
	Rune rr;
54
	ulong r, b;
55
	char *start = out;
56
	char *e = out + lim;
57
	int nb;
58
 
59
	if(mt64e[0] == 0)
60
		initm64();
61
	for(;;){
62
		r = *(uchar*)in;
63
 
64
		if(r < ' ' || r >= Runeself){
65
			if(r == '\0')
66
				break;
67
			if(out + 1 >= e)
68
				return -1;
69
			*out++ = '&';
70
			b = 0;
71
			nb = 0;
72
			for(;;){
73
				in += chartorune(&rr, in);
74
				r = rr;
75
				if(r == '\0' || r >= ' ' && r < Runeself)
76
					break;
77
				b = (b << 16) | r;
78
				for(nb += 16; nb >= 6; nb -= 6){
79
					if(out + 1 >= e)
80
						return -1;
81
					*out++ = mt64e[(b>>(nb-6))&0x3f];
82
				}
83
			}
84
			for(; nb >= 6; nb -= 6){
85
				if(out + 1 >= e)
86
					return -1;
87
				*out++ = mt64e[(b>>(nb-6))&0x3f];
88
			}
89
			if(nb){
90
				if(out + 1 >= e)
91
					return -1;
92
				*out++ = mt64e[(b<<(6-nb))&0x3f];
93
			}
94
 
95
			if(out + 1 >= e)
96
				return -1;
97
			*out++ = '-';
98
			if(r == '\0')
99
				break;
100
		}else
101
			in++;
102
		if(out + 1 >= e)
103
			return -1;
104
		*out = r;
105
		out++;
106
		if(r == '&')
107
			*out++ = '-';
108
	}
109
 
110
	if(out >= e)
111
		return -1;
112
	*out = '\0';
113
	return out - start;
114
}
115
 
116
int
117
decmutf7(char *out, int lim, char *in)
118
{
119
	Rune rr;
120
	char *start = out;
121
	char *e = out + lim;
122
	int c, b, nb;
123
 
124
	if(mt64e[0] == 0)
125
		initm64();
126
	for(;;){
127
		c = *in;
128
 
129
		if(c < ' ' || c >= Runeself){
130
			if(c == '\0')
131
				break;
132
			return -1;
133
		}
134
		if(c != '&'){
135
			if(out + 1 >= e)
136
				return -1;
137
			*out++ = c;
138
			in++;
139
			continue;
140
		}
141
		in++;
142
		if(*in == '-'){
143
			if(out + 1 >= e)
144
				return -1;
145
			*out++ = '&';
146
			in++;
147
			continue;
148
		}
149
 
150
		b = 0;
151
		nb = 0;
152
		while((c = *in++) != '-'){
153
			c = mt64d[c];
154
			if(c >= 64)
155
				return -1;
156
			b = (b << 6) | c;
157
			nb += 6;
158
			if(nb >= 16){
159
				rr = b >> (nb - 16);
160
				nb -= 16;
161
				if(out + UTFmax + 1 >= e && out + runelen(rr) + 1 >= e)
162
					return -1;
163
				out += runetochar(out, &rr);
164
			}
165
		}
166
		if(b & ((1 << nb) - 1))
167
			return -1;
168
	}
169
 
170
	if(out >= e)
171
		return -1;
172
	*out = '\0';
173
	return out - start;
174
}