diff options
Diffstat (limited to 'src/cmd/upas/vf/unvf.c')
-rw-r--r-- | src/cmd/upas/vf/unvf.c | 156 |
1 files changed, 156 insertions, 0 deletions
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 <u.h> +#include <libc.h> +#include <bio.h> + +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; +} + |