/* * 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(cistrncmp(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; }