commit 20bd3ca2e2bc7c1b284a5a52e72a32530529d234 from: rsc date: Sun Apr 09 00:24:28 2006 UTC new commit - 0e6fee11c89b146aa5419bbdf26514bc34bdaf81 commit + 20bd3ca2e2bc7c1b284a5a52e72a32530529d234 blob - b17e4578835c211933263eb0740f5b7c05b586fb blob + 27a5ebbdb2245d7f1b1d3af0d75434ef905d833b --- src/cmd/upas/vf/mkfile +++ 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 blob - 4a8846b28abbb31b7892c6d5284628d6cd5d5f2f blob + 84cae90769a3ddf435532dea19963854a8e7854a --- src/cmd/upas/vf/vf.c +++ src/cmd/upas/vf/vf.c @@ -4,6 +4,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; - - if(access("/mail/lib/validateattachment", AEXEC) < 0) - return 0; + static char *val; + 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; } blob - /dev/null blob + 92af6bfb8582a14a3860db40aac061d4fd586490 (mode 644) --- /dev/null +++ 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; +} +