Blob


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>
9 enum { None, Base64, Quoted };
10 static int decquoted(char *out, char *in, char *e);
12 void
13 main(void)
14 {
15 Biobuf b, b1;
16 char *p, *encoding;
17 int e, len;
19 Binit(&b, 0, OREAD);
20 Binit(&b1, 1, OWRITE);
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 }
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;
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 }
60 /*
61 * decode quoted
62 */
63 enum
64 {
65 Self= 1,
66 Hex= 2
67 };
68 uchar tableqp[256];
70 static void
71 initquoted(void)
72 {
73 int c;
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 }
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 }
96 static char*
97 decquotedline(char *out, char *in, char *e)
98 {
99 int c, soft;
101 /* dump trailing white space */
102 while(e >= in && (*e == ' ' || *e == '\t' || *e == '\r' || *e == '\n'))
103 e--;
105 /* trailing '=' means no newline */
106 if(*e == '='){
107 soft = 1;
108 e--;
109 } else
110 soft = 0;
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;
125 if(!soft)
126 *out++ = '\n';
127 *out = 0;
129 return out;
132 static int
133 decquoted(char *out, char *in, char *e)
135 char *p, *nl;
137 if(tableqp[' '] == 0)
138 initquoted();
140 p = out;
141 while((nl = strchr(in, '\n')) != nil && nl < e){
142 p = decquotedline(p, in, nl);
143 in = nl + 1;
145 if(in < e)
146 p = decquotedline(p, in, e-1);
148 /* make sure we end with a new line */
149 if(*(p-1) != '\n'){
150 *p++ = '\n';
151 *p = 0;
154 return p - out;