6 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
7 static int b64_val
[256];
9 static void b64_init(void)
12 for (i
= 0; i
< 64; i
++)
13 b64_val
[b64_ch
[i
]] = i
;
16 static int b64_dec(char *d
, char *s
)
32 return 3 - (s
[1] == '=') - (s
[2] == '=') - (s
[3] == '=');
35 static char *dec_b64(char *dst
, char *src
, int len
)
37 char *end
= src
+ len
;
40 while (src
+ 4 <= end
) {
41 while (src
< end
&& isspace(*src
))
44 dst
+= b64_dec(dst
, src
);
51 static int hexval(int c
)
53 if (c
>= '0' && c
<= '9')
55 if (c
>= 'A' && c
<= 'F')
57 if (c
>= 'a' && c
<= 'f')
62 static char *dec_qp(char *d
, char *s
, int len
)
76 char *enc_qu
= memchr(s
+ 2, '?', end
- s
- 4);
78 int b64
= tolower(enc_qu
[1]) == 'b';
80 char *e
= memchr(b
, '?', end
- b
);
82 d
= (b64
? dec_b64
: dec_qp
)(d
, b
, e
- b
);
88 *d
++ = hexval(s
[1]) << 4 | hexval(s
[2]);
94 #define MAXPARTS (1 << 3)
95 #define BOUNDLEN (1 << 7)
98 #define TYPE_MPART 0x01
107 char bound
[MAXPARTS
][BOUNDLEN
];
113 static void copy_till(struct mime
*m
, char *s
)
115 int len
= s
- m
->src
;
116 memcpy(m
->dst
, m
->src
, len
);
121 static int starts(char *r
, char *s
)
124 if (tolower(*s
++) != tolower(*r
++))
129 static void read_boundary(struct mime
*m
, char *s
)
131 char *bound
= m
->bound
[m
->depth
];
133 s
= memchr(s
, '=', m
->end
- s
);
139 e
= memchr(s
, '"', m
->end
- s
);
142 while (e
< m
->end
&& !isspace(*e
))
149 memcpy(bound
+ 2, s
, e
- s
);
150 bound
[e
- s
+ 2] = '\0';
154 static int read_hdrs(struct mime
*m
)
159 while (s
&& s
< e
&& *s
!= '\n') {
160 char *n
= memchr(s
, '\n', e
- s
);
161 while (n
&& n
+ 1 < e
&& n
[1] != '\n' && isspace(n
[1]))
162 n
= memchr(n
+ 1, '\n', e
- n
- 1);
167 if (starts(s
, "Subject:") || starts(s
, "From:")) {
168 m
->dst
= dec_qp(m
->dst
, m
->src
, n
- s
);
171 if (starts(s
, "Content-Type:")) {
172 char *t
= strchr(s
, ':') + 1;
173 while (isspace(*t
) && t
< e
)
175 if (starts(t
, "text"))
177 if (starts(t
, "multipart")) {
182 if (starts(s
, "Content-Transfer-Encoding:")) {
183 char *t
= strchr(s
, ':') + 1;
184 while (isspace(*t
) && t
< e
)
186 if (starts(t
, "quoted-printable"))
188 if (starts(t
, "base64"))
194 copy_till(m
, s
? s
+ 1 : e
);
198 static int is_bound(struct mime
*m
, char *s
)
200 return starts(s
, m
->bound
[m
->depth
- 1]);
203 static void read_bound(struct mime
*m
)
206 int len
= strlen(m
->bound
[m
->depth
- 1]);
207 if (s
[len
] == '-' && s
[len
+ 1] == '-')
209 s
= memchr(s
, '\n', m
->end
- s
);
210 s
= s
? s
+ 1 : m
->end
;
214 static char *find_bound(struct mime
*m
)
221 if (!(s
= memchr(s
, '\n', e
- s
)))
228 static void read_body(struct mime
*m
, int type
)
230 char *end
= m
->depth
? find_bound(m
) : m
->end
;
231 if (~type
& TYPE_TXT
) {
236 m
->dst
= dec_qp(m
->dst
, m
->src
, end
- m
->src
);
240 if (type
& ENC_B64
) {
241 m
->dst
= dec_b64(m
->dst
, m
->src
, end
- m
->src
);
248 int mime_decode(char *dst
, char *src
, int len
)
251 memset(&m
, 0, sizeof(m
));
255 while ((m
.depth
&& m
.src
< m
.end
) || m
.src
== src
) {
256 int type
= read_hdrs(&m
);