aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/upas/nfs/decode.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/upas/nfs/decode.c')
-rw-r--r--src/cmd/upas/nfs/decode.c257
1 files changed, 257 insertions, 0 deletions
diff --git a/src/cmd/upas/nfs/decode.c b/src/cmd/upas/nfs/decode.c
new file mode 100644
index 00000000..0e46dbff
--- /dev/null
+++ b/src/cmd/upas/nfs/decode.c
@@ -0,0 +1,257 @@
+/* Quick and dirty RFC 2047 */
+
+#include "a.h"
+
+static int
+unhex1(char c)
+{
+ if('0' <= c && c <= '9')
+ return c-'0';
+ if('a' <= c && c <= 'f')
+ return c-'a'+10;
+ if('A' <= c && c <= 'F')
+ return c-'A'+10;
+ return 15;
+}
+
+static int
+unhex(char *s)
+{
+ return unhex1(s[0])*16+unhex1(s[1]);
+}
+
+int
+decqp(uchar *out, int lim, char *in, int n)
+{
+ char *p, *ep;
+ uchar *eout, *out0;
+
+ out0 = out;
+ eout = out+lim;
+ for(p=in, ep=in+n; p<ep && out<eout; ){
+ if(*p == '_'){
+ *out++ = ' ';
+ p++;
+ }
+ else if(*p == '='){
+ if(p+1 >= ep)
+ break;
+ if(*(p+1) == '\n'){
+ p += 2;
+ continue;
+ }
+ if(p+3 > ep)
+ break;
+ *out++ = unhex(p+1);
+ p += 3;
+ }else
+ *out++ = *p++;
+ }
+ return out-out0;
+}
+
+char*
+decode(int kind, char *s, int *len)
+{
+ char *t;
+ int l;
+
+ if(s == nil)
+ return s;
+ switch(kind){
+ case QuotedPrintable:
+ l = strlen(s)+1;
+ t = emalloc(l);
+ l = decqp((uchar*)t, l, s, l-1);
+ *len = l;
+ t[l] = 0;
+ return t;
+
+ case Base64:
+ l = strlen(s)+1;
+ t = emalloc(l);
+ l = dec64((uchar*)t, l, s, l-1);
+ *len = l;
+ t[l] = 0;
+ return t;
+
+ default:
+ *len = strlen(s);
+ return estrdup(s);
+ }
+}
+
+struct {
+ char *mime;
+ char *tcs;
+} tcstab[] = {
+ "iso-8859-2", "8859-2",
+ "iso-8859-3", "8859-3",
+ "iso-8859-4", "8859-4",
+ "iso-8859-5", "8859-5",
+ "iso-8859-6", "8859-6",
+ "iso-8859-7", "8859-7",
+ "iso-8859-8", "8859-8",
+ "iso-8859-9", "8859-9",
+ "iso-8859-10", "8859-10",
+ "iso-8859-15", "8859-15",
+ "big5", "big5",
+ "iso-2022-jp", "jis-kanji",
+ "windows-1251", "cp1251",
+ "koi8-r", "koi8",
+};
+
+char*
+tcs(char *charset, char *s)
+{
+ static char buf[4096];
+ int i, n;
+ int fd[3], p[2], pp[2];
+ uchar *us;
+ char *t, *u;
+ char *argv[4];
+ Rune r;
+
+ if(s == nil || charset == nil || *s == 0)
+ return s;
+
+ if(cistrcmp(charset, "utf-8") == 0)
+ return s;
+ if(cistrcmp(charset, "iso-8859-1") == 0 || cistrcmp(charset, "us-ascii") == 0){
+latin1:
+ n = 0;
+ for(us=(uchar*)s; *us; us++)
+ n += runelen(*us);
+ n++;
+ t = emalloc(n);
+ for(us=(uchar*)s, u=t; *us; us++){
+ r = *us;
+ u += runetochar(u, &r);
+ }
+ *u = 0;
+ free(s);
+ return t;
+ }
+ for(i=0; i<nelem(tcstab); i++)
+ if(cistrcmp(charset, tcstab[i].mime) == 0)
+ goto tcs;
+ goto latin1;
+
+tcs:
+ argv[0] = "tcs";
+ argv[1] = "-f";
+ argv[2] = charset;
+ argv[3] = nil;
+
+ if(pipe(p) < 0 || pipe(pp) < 0)
+ sysfatal("pipe: %r");
+ fd[0] = p[0];
+ fd[1] = pp[0];
+ fd[2] = dup(2, -1);
+ if(threadspawnl(fd, "tcs", "tcs", "-f", tcstab[i].tcs, nil) < 0){
+ close(p[0]);
+ close(p[1]);
+ close(pp[0]);
+ close(pp[1]);
+ close(fd[2]);
+ goto latin1;
+ }
+ close(p[0]);
+ close(pp[0]);
+ write(p[1], s, strlen(s));
+ close(p[1]);
+ n = readn(pp[1], buf, sizeof buf-1);
+ close(pp[1]);
+ if(n <= 0)
+ goto latin1;
+ free(s);
+ buf[n] = 0;
+ return estrdup(buf);
+}
+
+char*
+unrfc2047(char *s)
+{
+ char *p, *q, *t, *u, *v;
+ int len;
+ Rune r;
+ Fmt fmt;
+
+ if(s == nil)
+ return nil;
+
+ if(strstr(s, "=?") == nil)
+ return s;
+
+ fmtstrinit(&fmt);
+ for(p=s; *p; ){
+ /* =?charset?e?text?= */
+ if(*p=='=' && *(p+1)=='?'){
+ p += 2;
+ q = strchr(p, '?');
+ if(q == nil)
+ goto emit;
+ q++;
+ if(*q == '?' || *(q+1) != '?')
+ goto emit;
+ t = q+2;
+ u = strchr(t, '?');
+ if(u == nil || *(u+1) != '=')
+ goto emit;
+ switch(*q){
+ case 'q':
+ case 'Q':
+ *u = 0;
+ v = decode(QuotedPrintable, t, &len);
+ break;
+ case 'b':
+ case 'B':
+ *u = 0;
+ v = decode(Base64, t, &len);
+ break;
+ default:
+ goto emit;
+ }
+ *(q-1) = 0;
+ v = tcs(p, v);
+ fmtstrcpy(&fmt, v);
+ free(v);
+ p = u+2;
+ }
+ emit:
+ p += chartorune(&r, p);
+ fmtrune(&fmt, r);
+ }
+ p = fmtstrflush(&fmt);
+ if(p == nil)
+ sysfatal("out of memory");
+ free(s);
+ return p;
+}
+
+#ifdef TEST
+char *test[] =
+{
+ "hello world",
+ "hello =?iso-8859-1?q?this is some text?=",
+ "=?US-ASCII?Q?Keith_Moore?=",
+ "=?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?=",
+ "=?ISO-8859-1?Q?Andr=E9?= Pirard",
+ "=?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?=",
+ "=?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=",
+ "=?ISO-8859-1?Q?Olle_J=E4rnefors?=",
+ "=?iso-2022-jp?B?GyRCTTVKISRKP006SiRyS34kPyQ3JEZKcz03JCIkahsoQg==?=",
+ "=?UTF-8?B?Ik5pbHMgTy4gU2Vsw6VzZGFsIg==?="
+};
+
+void
+threadmain(int argc, char **argv)
+{
+ int i;
+
+ for(i=0; i<nelem(test); i++)
+ print("%s\n\t%s\n", test[i], unrfc2047(estrdup(test[i])));
+ threadexitsall(0);
+}
+
+#endif