unvf.c (2429B)
1 /* 2 * For decoding the files that get passed to validateattachment. 3 * NOT a general mime decoder. 4 */ 5 #include <u.h> 6 #include <libc.h> 7 #include <bio.h> 8 9 enum { None, Base64, Quoted }; 10 static int decquoted(char *out, char *in, char *e); 11 12 void 13 main(void) 14 { 15 Biobuf b, b1; 16 char *p, *encoding; 17 int e, len; 18 19 Binit(&b, 0, OREAD); 20 Binit(&b1, 1, OWRITE); 21 22 /* header */ 23 encoding = nil; 24 while((p = Brdstr(&b, '\n', 1)) != nil){ 25 if(p[0] == 0) 26 break; 27 if(cistrncmp(p, "Content-Transfer-Encoding: ", 27) == 0) 28 encoding = strdup(p+27); 29 free(p); 30 } 31 32 e = None; 33 if(encoding == nil) 34 e = None; 35 else if(strcmp(encoding, "base64") == 0) 36 e = Base64; 37 else if(strcmp(encoding, "quoted-printable") == 0) 38 e = Quoted; 39 40 while((p = Brdstr(&b, '\n', 0)) != nil){ 41 if(strncmp(p, "--", 2) == 0 && e != None) 42 break; 43 len = strlen(p); 44 switch(e){ 45 case None: 46 break; 47 case Base64: 48 len = dec64((uchar*)p, len, p, len); 49 break; 50 case Quoted: 51 len = decquoted(p, p, p+len); 52 break; 53 } 54 Bwrite(&b1, p, len); 55 free(p); 56 } 57 exits(0); 58 } 59 60 /* 61 * decode quoted 62 */ 63 enum 64 { 65 Self= 1, 66 Hex= 2 67 }; 68 uchar tableqp[256]; 69 70 static void 71 initquoted(void) 72 { 73 int c; 74 75 memset(tableqp, 0, 256); 76 for(c = ' '; c <= '<'; c++) 77 tableqp[c] = Self; 78 for(c = '>'; c <= '~'; c++) 79 tableqp[c] = Self; 80 tableqp['\t'] = Self; 81 tableqp['='] = Hex; 82 } 83 84 static int 85 hex2int(int x) 86 { 87 if(x >= '0' && x <= '9') 88 return x - '0'; 89 if(x >= 'A' && x <= 'F') 90 return (x - 'A') + 10; 91 if(x >= 'a' && x <= 'f') 92 return (x - 'a') + 10; 93 return 0; 94 } 95 96 static char* 97 decquotedline(char *out, char *in, char *e) 98 { 99 int c, soft; 100 101 /* dump trailing white space */ 102 while(e >= in && (*e == ' ' || *e == '\t' || *e == '\r' || *e == '\n')) 103 e--; 104 105 /* trailing '=' means no newline */ 106 if(*e == '='){ 107 soft = 1; 108 e--; 109 } else 110 soft = 0; 111 112 while(in <= e){ 113 c = (*in++) & 0xff; 114 switch(tableqp[c]){ 115 case Self: 116 *out++ = c; 117 break; 118 case Hex: 119 c = hex2int(*in++)<<4; 120 c |= hex2int(*in++); 121 *out++ = c; 122 break; 123 } 124 } 125 if(!soft) 126 *out++ = '\n'; 127 *out = 0; 128 129 return out; 130 } 131 132 static int 133 decquoted(char *out, char *in, char *e) 134 { 135 char *p, *nl; 136 137 if(tableqp[' '] == 0) 138 initquoted(); 139 140 p = out; 141 while((nl = strchr(in, '\n')) != nil && nl < e){ 142 p = decquotedline(p, in, nl); 143 in = nl + 1; 144 } 145 if(in < e) 146 p = decquotedline(p, in, e-1); 147 148 /* make sure we end with a new line */ 149 if(*(p-1) != '\n'){ 150 *p++ = '\n'; 151 *p = 0; 152 } 153 154 return p - out; 155 }