1 /* Quick and dirty RFC 2047 */
8 if('0' <= c && c <= '9')
10 if('a' <= c && c <= 'f')
12 if('A' <= c && c <= 'F')
20 return unhex1(s[0])*16+unhex1(s[1]);
24 _decqp(uchar *out, int lim, char *in, int n, int underscores)
31 for(p=in, ep=in+n; p<ep && out<eout; ){
32 if(underscores && *p == '_'){
54 decqp(uchar *out, int lim, char *in, int n)
56 return _decqp(out, lim, in, n, 0);
60 decode(int kind, char *s, int *len)
69 case QuotedPrintableU:
72 l = _decqp((uchar*)t, l, s, l-1, kind==QuotedPrintableU);
80 l = dec64((uchar*)t, l, s, l-1);
95 "iso-8859-2", "8859-2",
96 "iso-8859-3", "8859-3",
97 "iso-8859-4", "8859-4",
98 "iso-8859-5", "8859-5",
99 "iso-8859-6", "8859-6",
100 "iso-8859-7", "8859-7",
101 "iso-8859-8", "8859-8",
102 "iso-8859-9", "8859-9",
103 "iso-8859-10", "8859-10",
104 "iso-8859-15", "8859-15",
106 "iso-2022-jp", "jis-kanji",
107 "windows-1250", "windows-1250",
108 "windows-1251", "windows-1251",
109 "windows-1252", "windows-1252",
110 "windows-1253", "windows-1253",
111 "windows-1254", "windows-1254",
112 "windows-1255", "windows-1255",
113 "windows-1256", "windows-1256",
114 "windows-1257", "windows-1257",
115 "windows-1258", "windows-1258",
119 typedef struct Writeargs Writeargs;
132 write(w->fd, w->s, strlen(w->s));
139 tcs(char *charset, char *s)
143 int fd[3], p[2], pp[2];
149 if(s == nil || charset == nil || *s == 0)
152 if(cistrcmp(charset, "utf-8") == 0)
154 if(cistrcmp(charset, "iso-8859-1") == 0 || cistrcmp(charset, "us-ascii") == 0){
157 for(us=(uchar*)s; *us; us++)
161 for(us=(uchar*)s, u=t; *us; us++){
163 u += runetochar(u, &r);
169 for(i=0; i<nelem(tcstab); i++)
170 if(cistrcmp(charset, tcstab[i].mime) == 0)
175 if(pipe(p) < 0 || pipe(pp) < 0)
176 sysfatal("pipe: %r");
180 if(threadspawnl(fd, "tcs", "tcs", "-f", tcstab[i].tcs, nil) < 0){
191 nbuf = UTFmax*strlen(s)+100; /* just a guess at worst case */
194 w = emalloc(sizeof *w);
197 proccreate(twriter, w, STACK);
199 n = readn(pp[1], buf, nbuf-1);
215 char *p, *q, *t, *u, *v;
223 if(strstr(s, "=?") == nil)
228 /* =?charset?e?text?= */
229 if(*p=='=' && *(p+1)=='?'){
235 if(*q == '?' || *(q+1) != '?')
239 if(u == nil || *(u+1) != '=')
245 v = decode(QuotedPrintableU, t, &len);
250 v = decode(Base64, t, &len);
262 p += chartorune(&r, p);
265 p = fmtstrflush(&fmt);
267 sysfatal("out of memory");
276 "hello =?iso-8859-1?q?this is some text?=",
277 "=?US-ASCII?Q?Keith_Moore?=",
278 "=?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?=",
279 "=?ISO-8859-1?Q?Andr=E9?= Pirard",
280 "=?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?=",
281 "=?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=",
282 "=?ISO-8859-1?Q?Olle_J=E4rnefors?=",
283 "=?iso-2022-jp?B?GyRCTTVKISRKP006SiRyS34kPyQ3JEZKcz03JCIkahsoQg==?=",
284 "=?UTF-8?B?Ik5pbHMgTy4gU2Vsw6VzZGFsIg==?="
288 threadmain(int argc, char **argv)
292 for(i=0; i<nelem(test); i++)
293 print("%s\n\t%s\n", test[i], unrfc2047(estrdup(test[i])));