Blame


1 941e1713 2006-02-15 devnull /* Quick and dirty RFC 2047 */
2 941e1713 2006-02-15 devnull
3 941e1713 2006-02-15 devnull #include "a.h"
4 941e1713 2006-02-15 devnull
5 941e1713 2006-02-15 devnull static int
6 941e1713 2006-02-15 devnull unhex1(char c)
7 941e1713 2006-02-15 devnull {
8 941e1713 2006-02-15 devnull if('0' <= c && c <= '9')
9 941e1713 2006-02-15 devnull return c-'0';
10 941e1713 2006-02-15 devnull if('a' <= c && c <= 'f')
11 941e1713 2006-02-15 devnull return c-'a'+10;
12 941e1713 2006-02-15 devnull if('A' <= c && c <= 'F')
13 941e1713 2006-02-15 devnull return c-'A'+10;
14 941e1713 2006-02-15 devnull return 15;
15 941e1713 2006-02-15 devnull }
16 941e1713 2006-02-15 devnull
17 941e1713 2006-02-15 devnull static int
18 941e1713 2006-02-15 devnull unhex(char *s)
19 941e1713 2006-02-15 devnull {
20 941e1713 2006-02-15 devnull return unhex1(s[0])*16+unhex1(s[1]);
21 941e1713 2006-02-15 devnull }
22 941e1713 2006-02-15 devnull
23 941e1713 2006-02-15 devnull int
24 6a8add52 2006-02-23 devnull _decqp(uchar *out, int lim, char *in, int n, int underscores)
25 941e1713 2006-02-15 devnull {
26 941e1713 2006-02-15 devnull char *p, *ep;
27 941e1713 2006-02-15 devnull uchar *eout, *out0;
28 941e1713 2006-02-15 devnull
29 941e1713 2006-02-15 devnull out0 = out;
30 941e1713 2006-02-15 devnull eout = out+lim;
31 941e1713 2006-02-15 devnull for(p=in, ep=in+n; p<ep && out<eout; ){
32 6a8add52 2006-02-23 devnull if(underscores && *p == '_'){
33 941e1713 2006-02-15 devnull *out++ = ' ';
34 941e1713 2006-02-15 devnull p++;
35 941e1713 2006-02-15 devnull }
36 941e1713 2006-02-15 devnull else if(*p == '='){
37 941e1713 2006-02-15 devnull if(p+1 >= ep)
38 941e1713 2006-02-15 devnull break;
39 941e1713 2006-02-15 devnull if(*(p+1) == '\n'){
40 941e1713 2006-02-15 devnull p += 2;
41 941e1713 2006-02-15 devnull continue;
42 941e1713 2006-02-15 devnull }
43 941e1713 2006-02-15 devnull if(p+3 > ep)
44 941e1713 2006-02-15 devnull break;
45 941e1713 2006-02-15 devnull *out++ = unhex(p+1);
46 941e1713 2006-02-15 devnull p += 3;
47 941e1713 2006-02-15 devnull }else
48 941e1713 2006-02-15 devnull *out++ = *p++;
49 941e1713 2006-02-15 devnull }
50 941e1713 2006-02-15 devnull return out-out0;
51 941e1713 2006-02-15 devnull }
52 941e1713 2006-02-15 devnull
53 6a8add52 2006-02-23 devnull int
54 6a8add52 2006-02-23 devnull decqp(uchar *out, int lim, char *in, int n)
55 6a8add52 2006-02-23 devnull {
56 6a8add52 2006-02-23 devnull return _decqp(out, lim, in, n, 0);
57 6a8add52 2006-02-23 devnull }
58 6a8add52 2006-02-23 devnull
59 941e1713 2006-02-15 devnull char*
60 941e1713 2006-02-15 devnull decode(int kind, char *s, int *len)
61 941e1713 2006-02-15 devnull {
62 941e1713 2006-02-15 devnull char *t;
63 941e1713 2006-02-15 devnull int l;
64 941e1713 2006-02-15 devnull
65 941e1713 2006-02-15 devnull if(s == nil)
66 941e1713 2006-02-15 devnull return s;
67 941e1713 2006-02-15 devnull switch(kind){
68 384d563d 2006-02-23 devnull case QuotedPrintable:
69 6a8add52 2006-02-23 devnull case QuotedPrintableU:
70 941e1713 2006-02-15 devnull l = strlen(s)+1;
71 941e1713 2006-02-15 devnull t = emalloc(l);
72 1ff2c2b9 2006-02-23 devnull l = _decqp((uchar*)t, l, s, l-1, kind==QuotedPrintableU);
73 941e1713 2006-02-15 devnull *len = l;
74 941e1713 2006-02-15 devnull t[l] = 0;
75 941e1713 2006-02-15 devnull return t;
76 941e1713 2006-02-15 devnull
77 941e1713 2006-02-15 devnull case Base64:
78 941e1713 2006-02-15 devnull l = strlen(s)+1;
79 941e1713 2006-02-15 devnull t = emalloc(l);
80 941e1713 2006-02-15 devnull l = dec64((uchar*)t, l, s, l-1);
81 941e1713 2006-02-15 devnull *len = l;
82 941e1713 2006-02-15 devnull t[l] = 0;
83 941e1713 2006-02-15 devnull return t;
84 941e1713 2006-02-15 devnull
85 941e1713 2006-02-15 devnull default:
86 941e1713 2006-02-15 devnull *len = strlen(s);
87 941e1713 2006-02-15 devnull return estrdup(s);
88 941e1713 2006-02-15 devnull }
89 941e1713 2006-02-15 devnull }
90 941e1713 2006-02-15 devnull
91 941e1713 2006-02-15 devnull struct {
92 941e1713 2006-02-15 devnull char *mime;
93 941e1713 2006-02-15 devnull char *tcs;
94 941e1713 2006-02-15 devnull } tcstab[] = {
95 941e1713 2006-02-15 devnull "iso-8859-2", "8859-2",
96 941e1713 2006-02-15 devnull "iso-8859-3", "8859-3",
97 941e1713 2006-02-15 devnull "iso-8859-4", "8859-4",
98 941e1713 2006-02-15 devnull "iso-8859-5", "8859-5",
99 941e1713 2006-02-15 devnull "iso-8859-6", "8859-6",
100 941e1713 2006-02-15 devnull "iso-8859-7", "8859-7",
101 941e1713 2006-02-15 devnull "iso-8859-8", "8859-8",
102 941e1713 2006-02-15 devnull "iso-8859-9", "8859-9",
103 941e1713 2006-02-15 devnull "iso-8859-10", "8859-10",
104 941e1713 2006-02-15 devnull "iso-8859-15", "8859-15",
105 941e1713 2006-02-15 devnull "big5", "big5",
106 941e1713 2006-02-15 devnull "iso-2022-jp", "jis-kanji",
107 865e8b0f 2008-05-06 rsc "windows-1250", "windows-1250",
108 865e8b0f 2008-05-06 rsc "windows-1251", "windows-1251",
109 865e8b0f 2008-05-06 rsc "windows-1252", "windows-1252",
110 865e8b0f 2008-05-06 rsc "windows-1253", "windows-1253",
111 865e8b0f 2008-05-06 rsc "windows-1254", "windows-1254",
112 865e8b0f 2008-05-06 rsc "windows-1255", "windows-1255",
113 865e8b0f 2008-05-06 rsc "windows-1256", "windows-1256",
114 865e8b0f 2008-05-06 rsc "windows-1257", "windows-1257",
115 865e8b0f 2008-05-06 rsc "windows-1258", "windows-1258",
116 cbeb0b26 2006-04-01 devnull "koi8-r", "koi8"
117 941e1713 2006-02-15 devnull };
118 941e1713 2006-02-15 devnull
119 c5f88424 2008-07-14 rsc typedef struct Writeargs Writeargs;
120 c5f88424 2008-07-14 rsc struct Writeargs
121 c5f88424 2008-07-14 rsc {
122 c5f88424 2008-07-14 rsc int fd;
123 c5f88424 2008-07-14 rsc char *s;
124 c5f88424 2008-07-14 rsc };
125 c5f88424 2008-07-14 rsc
126 c5f88424 2008-07-14 rsc static void
127 c5f88424 2008-07-14 rsc twriter(void *v)
128 c5f88424 2008-07-14 rsc {
129 c5f88424 2008-07-14 rsc Writeargs *w;
130 c5f88424 2008-07-14 rsc
131 c5f88424 2008-07-14 rsc w = v;
132 c5f88424 2008-07-14 rsc write(w->fd, w->s, strlen(w->s));
133 c5f88424 2008-07-14 rsc close(w->fd);
134 c5f88424 2008-07-14 rsc free(w->s);
135 c5f88424 2008-07-14 rsc free(w);
136 c5f88424 2008-07-14 rsc }
137 c5f88424 2008-07-14 rsc
138 941e1713 2006-02-15 devnull char*
139 941e1713 2006-02-15 devnull tcs(char *charset, char *s)
140 941e1713 2006-02-15 devnull {
141 c5f88424 2008-07-14 rsc char *buf;
142 c5f88424 2008-07-14 rsc int i, n, nbuf;
143 941e1713 2006-02-15 devnull int fd[3], p[2], pp[2];
144 941e1713 2006-02-15 devnull uchar *us;
145 941e1713 2006-02-15 devnull char *t, *u;
146 941e1713 2006-02-15 devnull char *argv[4];
147 941e1713 2006-02-15 devnull Rune r;
148 c5f88424 2008-07-14 rsc Writeargs *w;
149 c5f88424 2008-07-14 rsc
150 941e1713 2006-02-15 devnull if(s == nil || charset == nil || *s == 0)
151 941e1713 2006-02-15 devnull return s;
152 941e1713 2006-02-15 devnull
153 941e1713 2006-02-15 devnull if(cistrcmp(charset, "utf-8") == 0)
154 941e1713 2006-02-15 devnull return s;
155 941e1713 2006-02-15 devnull if(cistrcmp(charset, "iso-8859-1") == 0 || cistrcmp(charset, "us-ascii") == 0){
156 941e1713 2006-02-15 devnull latin1:
157 941e1713 2006-02-15 devnull n = 0;
158 941e1713 2006-02-15 devnull for(us=(uchar*)s; *us; us++)
159 941e1713 2006-02-15 devnull n += runelen(*us);
160 941e1713 2006-02-15 devnull n++;
161 941e1713 2006-02-15 devnull t = emalloc(n);
162 941e1713 2006-02-15 devnull for(us=(uchar*)s, u=t; *us; us++){
163 941e1713 2006-02-15 devnull r = *us;
164 941e1713 2006-02-15 devnull u += runetochar(u, &r);
165 941e1713 2006-02-15 devnull }
166 941e1713 2006-02-15 devnull *u = 0;
167 941e1713 2006-02-15 devnull free(s);
168 941e1713 2006-02-15 devnull return t;
169 941e1713 2006-02-15 devnull }
170 941e1713 2006-02-15 devnull for(i=0; i<nelem(tcstab); i++)
171 941e1713 2006-02-15 devnull if(cistrcmp(charset, tcstab[i].mime) == 0)
172 941e1713 2006-02-15 devnull goto tcs;
173 941e1713 2006-02-15 devnull goto latin1;
174 941e1713 2006-02-15 devnull
175 941e1713 2006-02-15 devnull tcs:
176 941e1713 2006-02-15 devnull argv[0] = "tcs";
177 941e1713 2006-02-15 devnull argv[1] = "-f";
178 941e1713 2006-02-15 devnull argv[2] = charset;
179 941e1713 2006-02-15 devnull argv[3] = nil;
180 941e1713 2006-02-15 devnull
181 941e1713 2006-02-15 devnull if(pipe(p) < 0 || pipe(pp) < 0)
182 941e1713 2006-02-15 devnull sysfatal("pipe: %r");
183 941e1713 2006-02-15 devnull fd[0] = p[0];
184 941e1713 2006-02-15 devnull fd[1] = pp[0];
185 941e1713 2006-02-15 devnull fd[2] = dup(2, -1);
186 941e1713 2006-02-15 devnull if(threadspawnl(fd, "tcs", "tcs", "-f", tcstab[i].tcs, nil) < 0){
187 941e1713 2006-02-15 devnull close(p[0]);
188 941e1713 2006-02-15 devnull close(p[1]);
189 941e1713 2006-02-15 devnull close(pp[0]);
190 941e1713 2006-02-15 devnull close(pp[1]);
191 941e1713 2006-02-15 devnull close(fd[2]);
192 941e1713 2006-02-15 devnull goto latin1;
193 941e1713 2006-02-15 devnull }
194 941e1713 2006-02-15 devnull close(p[0]);
195 941e1713 2006-02-15 devnull close(pp[0]);
196 c5f88424 2008-07-14 rsc
197 c5f88424 2008-07-14 rsc nbuf = UTFmax*strlen(s)+100; /* just a guess at worst case */
198 c5f88424 2008-07-14 rsc buf = emalloc(nbuf);
199 c5f88424 2008-07-14 rsc
200 c5f88424 2008-07-14 rsc w = emalloc(sizeof *w);
201 c5f88424 2008-07-14 rsc w->fd = p[1];
202 c5f88424 2008-07-14 rsc w->s = estrdup(s);
203 c5f88424 2008-07-14 rsc proccreate(twriter, w, STACK);
204 c5f88424 2008-07-14 rsc
205 c5f88424 2008-07-14 rsc n = readn(pp[1], buf, nbuf-1);
206 941e1713 2006-02-15 devnull close(pp[1]);
207 c5f88424 2008-07-14 rsc if(n <= 0){
208 c5f88424 2008-07-14 rsc free(buf);
209 941e1713 2006-02-15 devnull goto latin1;
210 c5f88424 2008-07-14 rsc }
211 941e1713 2006-02-15 devnull buf[n] = 0;
212 c5f88424 2008-07-14 rsc free(s);
213 c5f88424 2008-07-14 rsc s = estrdup(buf);
214 c5f88424 2008-07-14 rsc free(buf);
215 c5f88424 2008-07-14 rsc return s;
216 941e1713 2006-02-15 devnull }
217 941e1713 2006-02-15 devnull
218 941e1713 2006-02-15 devnull char*
219 941e1713 2006-02-15 devnull unrfc2047(char *s)
220 941e1713 2006-02-15 devnull {
221 941e1713 2006-02-15 devnull char *p, *q, *t, *u, *v;
222 941e1713 2006-02-15 devnull int len;
223 941e1713 2006-02-15 devnull Rune r;
224 941e1713 2006-02-15 devnull Fmt fmt;
225 941e1713 2006-02-15 devnull
226 941e1713 2006-02-15 devnull if(s == nil)
227 941e1713 2006-02-15 devnull return nil;
228 941e1713 2006-02-15 devnull
229 941e1713 2006-02-15 devnull if(strstr(s, "=?") == nil)
230 941e1713 2006-02-15 devnull return s;
231 941e1713 2006-02-15 devnull
232 941e1713 2006-02-15 devnull fmtstrinit(&fmt);
233 941e1713 2006-02-15 devnull for(p=s; *p; ){
234 941e1713 2006-02-15 devnull /* =?charset?e?text?= */
235 941e1713 2006-02-15 devnull if(*p=='=' && *(p+1)=='?'){
236 941e1713 2006-02-15 devnull p += 2;
237 941e1713 2006-02-15 devnull q = strchr(p, '?');
238 941e1713 2006-02-15 devnull if(q == nil)
239 941e1713 2006-02-15 devnull goto emit;
240 941e1713 2006-02-15 devnull q++;
241 941e1713 2006-02-15 devnull if(*q == '?' || *(q+1) != '?')
242 941e1713 2006-02-15 devnull goto emit;
243 941e1713 2006-02-15 devnull t = q+2;
244 941e1713 2006-02-15 devnull u = strchr(t, '?');
245 941e1713 2006-02-15 devnull if(u == nil || *(u+1) != '=')
246 941e1713 2006-02-15 devnull goto emit;
247 941e1713 2006-02-15 devnull switch(*q){
248 941e1713 2006-02-15 devnull case 'q':
249 941e1713 2006-02-15 devnull case 'Q':
250 941e1713 2006-02-15 devnull *u = 0;
251 6a8add52 2006-02-23 devnull v = decode(QuotedPrintableU, t, &len);
252 941e1713 2006-02-15 devnull break;
253 941e1713 2006-02-15 devnull case 'b':
254 941e1713 2006-02-15 devnull case 'B':
255 941e1713 2006-02-15 devnull *u = 0;
256 941e1713 2006-02-15 devnull v = decode(Base64, t, &len);
257 941e1713 2006-02-15 devnull break;
258 941e1713 2006-02-15 devnull default:
259 941e1713 2006-02-15 devnull goto emit;
260 941e1713 2006-02-15 devnull }
261 941e1713 2006-02-15 devnull *(q-1) = 0;
262 941e1713 2006-02-15 devnull v = tcs(p, v);
263 941e1713 2006-02-15 devnull fmtstrcpy(&fmt, v);
264 941e1713 2006-02-15 devnull free(v);
265 941e1713 2006-02-15 devnull p = u+2;
266 941e1713 2006-02-15 devnull }
267 941e1713 2006-02-15 devnull emit:
268 941e1713 2006-02-15 devnull p += chartorune(&r, p);
269 941e1713 2006-02-15 devnull fmtrune(&fmt, r);
270 941e1713 2006-02-15 devnull }
271 941e1713 2006-02-15 devnull p = fmtstrflush(&fmt);
272 941e1713 2006-02-15 devnull if(p == nil)
273 941e1713 2006-02-15 devnull sysfatal("out of memory");
274 941e1713 2006-02-15 devnull free(s);
275 941e1713 2006-02-15 devnull return p;
276 941e1713 2006-02-15 devnull }
277 941e1713 2006-02-15 devnull
278 941e1713 2006-02-15 devnull #ifdef TEST
279 941e1713 2006-02-15 devnull char *test[] =
280 941e1713 2006-02-15 devnull {
281 941e1713 2006-02-15 devnull "hello world",
282 941e1713 2006-02-15 devnull "hello =?iso-8859-1?q?this is some text?=",
283 941e1713 2006-02-15 devnull "=?US-ASCII?Q?Keith_Moore?=",
284 941e1713 2006-02-15 devnull "=?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?=",
285 941e1713 2006-02-15 devnull "=?ISO-8859-1?Q?Andr=E9?= Pirard",
286 941e1713 2006-02-15 devnull "=?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?=",
287 941e1713 2006-02-15 devnull "=?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=",
288 941e1713 2006-02-15 devnull "=?ISO-8859-1?Q?Olle_J=E4rnefors?=",
289 941e1713 2006-02-15 devnull "=?iso-2022-jp?B?GyRCTTVKISRKP006SiRyS34kPyQ3JEZKcz03JCIkahsoQg==?=",
290 941e1713 2006-02-15 devnull "=?UTF-8?B?Ik5pbHMgTy4gU2Vsw6VzZGFsIg==?="
291 941e1713 2006-02-15 devnull };
292 941e1713 2006-02-15 devnull
293 941e1713 2006-02-15 devnull void
294 941e1713 2006-02-15 devnull threadmain(int argc, char **argv)
295 941e1713 2006-02-15 devnull {
296 941e1713 2006-02-15 devnull int i;
297 941e1713 2006-02-15 devnull
298 941e1713 2006-02-15 devnull for(i=0; i<nelem(test); i++)
299 941e1713 2006-02-15 devnull print("%s\n\t%s\n", test[i], unrfc2047(estrdup(test[i])));
300 941e1713 2006-02-15 devnull threadexitsall(0);
301 941e1713 2006-02-15 devnull }
302 941e1713 2006-02-15 devnull
303 941e1713 2006-02-15 devnull #endif