From 20bd3ca2e2bc7c1b284a5a52e72a32530529d234 Mon Sep 17 00:00:00 2001 From: rsc Date: Sun, 9 Apr 2006 00:24:28 +0000 Subject: new --- src/cmd/upas/vf/mkfile | 6 +- src/cmd/upas/vf/unvf.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++++ src/cmd/upas/vf/vf.c | 24 +++++--- 3 files changed, 175 insertions(+), 11 deletions(-) create mode 100644 src/cmd/upas/vf/unvf.c (limited to 'src/cmd/upas') diff --git a/src/cmd/upas/vf/mkfile b/src/cmd/upas/vf/mkfile index b17e4578..27a5ebbd 100644 --- a/src/cmd/upas/vf/mkfile +++ b/src/cmd/upas/vf/mkfile @@ -1,8 +1,8 @@ <$PLAN9/src/mkhdr -TARG=vf +TARG=vf unvf -OFILES=vf.$O\ +OFILES= LIB=../common/libcommon.a\ @@ -16,5 +16,5 @@ UPDATE=\ $HFILES\ ${OFILES:%.$O=%.c}\ -<$PLAN9/src/mkone +<$PLAN9/src/mkmany CFLAGS=$CFLAGS -I../common diff --git a/src/cmd/upas/vf/unvf.c b/src/cmd/upas/vf/unvf.c new file mode 100644 index 00000000..92af6bfb --- /dev/null +++ b/src/cmd/upas/vf/unvf.c @@ -0,0 +1,156 @@ +/* + * For decoding the files that get passed to validateattachment. + * NOT a general mime decoder. + */ +#include +#include +#include + +enum { None, Base64, Quoted }; +static int decquoted(char *out, char *in, char *e); + +void +main(void) +{ + Biobuf b, b1; + char *p, *encoding; + int e, len; + + Binit(&b, 0, OREAD); + Binit(&b1, 1, OWRITE); + + /* header */ + encoding = nil; + while((p = Brdstr(&b, '\n', 1)) != nil){ + if(p[0] == 0) + break; + if(strncmp(p, "Content-Transfer-Encoding: ", 27) == 0) + encoding = strdup(p+27); + free(p); + } + + e = None; + if(encoding == nil) + e = None; + else if(strcmp(encoding, "base64") == 0) + e = Base64; + else if(strcmp(encoding, "quoted-printable") == 0) + e = Quoted; + + while((p = Brdstr(&b, '\n', 0)) != nil){ + if(strncmp(p, "--", 2) == 0 && e != None) + break; + len = strlen(p); + switch(e){ + case None: + break; + case Base64: + len = dec64((uchar*)p, len, p, len); + break; + case Quoted: + len = decquoted(p, p, p+len); + break; + } + Bwrite(&b1, p, len); + free(p); + } + exits(0); +} + +/* + * decode quoted + */ +enum +{ + Self= 1, + Hex= 2 +}; +uchar tableqp[256]; + +static void +initquoted(void) +{ + int c; + + memset(tableqp, 0, 256); + for(c = ' '; c <= '<'; c++) + tableqp[c] = Self; + for(c = '>'; c <= '~'; c++) + tableqp[c] = Self; + tableqp['\t'] = Self; + tableqp['='] = Hex; +} + +static int +hex2int(int x) +{ + if(x >= '0' && x <= '9') + return x - '0'; + if(x >= 'A' && x <= 'F') + return (x - 'A') + 10; + if(x >= 'a' && x <= 'f') + return (x - 'a') + 10; + return 0; +} + +static char* +decquotedline(char *out, char *in, char *e) +{ + int c, soft; + + /* dump trailing white space */ + while(e >= in && (*e == ' ' || *e == '\t' || *e == '\r' || *e == '\n')) + e--; + + /* trailing '=' means no newline */ + if(*e == '='){ + soft = 1; + e--; + } else + soft = 0; + + while(in <= e){ + c = (*in++) & 0xff; + switch(tableqp[c]){ + case Self: + *out++ = c; + break; + case Hex: + c = hex2int(*in++)<<4; + c |= hex2int(*in++); + *out++ = c; + break; + } + } + if(!soft) + *out++ = '\n'; + *out = 0; + + return out; +} + +static int +decquoted(char *out, char *in, char *e) +{ + char *p, *nl; + + if(tableqp[' '] == 0) + initquoted(); + + p = out; + while((nl = strchr(in, '\n')) != nil && nl < e){ + p = decquotedline(p, in, nl); + in = nl + 1; + } + if(in < e) + p = decquotedline(p, in, e-1); + + /* make sure we end with a new line */ + if(*(p-1) != '\n'){ + *p++ = '\n'; + *p = 0; + } + + return p - out; +} + diff --git a/src/cmd/upas/vf/vf.c b/src/cmd/upas/vf/vf.c index 4a8846b2..84cae907 100644 --- a/src/cmd/upas/vf/vf.c +++ b/src/cmd/upas/vf/vf.c @@ -5,6 +5,11 @@ #include "common.h" #include +enum { + Accept = 0xA, + Discard = 0xD, +}; + Biobuf in; Biobuf out; @@ -400,12 +405,12 @@ savetmp(Part *p) char buf[40], *name; int fd; - strcpy(buf, "/tmp/vf.XXXXXXXXXXX"); - name = mktemp(buf); - if((fd = create(name, OWRITE|OEXCL, 0666)) < 0){ + strcpy(buf, "/var/tmp/vf.XXXXXXXXXXX"); + if((fd = mkstemp(buf)) < 0){ fprint(2, "error creating temporary file: %r\n"); refuse(); } + name = buf; close(fd); if(save(p, name) < 0){ fprint(2, "error saving temporary file: %r\n"); @@ -433,10 +438,13 @@ runchecker(Part *p) int pid; char *name; Waitmsg *w; + static char *val; - if(access("/mail/lib/validateattachment", AEXEC) < 0) + if(val == nil) + val = unsharp("#9/mail/lib/validateattachment"); + if(val == nil || access(val, AEXEC) < 0) return 0; - + name = savetmp(p); fprint(2, "run checker %s\n", name); switch(pid = fork()){ @@ -444,7 +452,7 @@ runchecker(Part *p) sysfatal("fork: %r"); case 0: dup(2, 1); - execl("/mail/lib/validateattachment", "validateattachment", name, nil); + execl(val, "validateattachment", name, nil); _exits("exec failed"); } @@ -462,11 +470,11 @@ runchecker(Part *p) } if(p->filename) name = s_to_c(p->filename); - if(strstr(w->msg, "discard")){ + if(atoi(w->msg) == Discard){ syslog(0, "mail", "vf validateattachment rejected %s", name); refuse(); } - if(strstr(w->msg, "accept")){ + if(atoi(w->msg) == Accept){ syslog(0, "mail", "vf validateattachment accepted %s", name); return 1; } -- cgit v1.2.3