2 * Copyright 2011, Haiku, Inc. All rights reserved.
3 * Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved.
11 #include <SupportDefs.h>
13 #include <mail_encoding.h>
16 #define DEC(c) (((c) - ' ') & 077)
19 static const char kHexAlphabet
[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
20 '8','9','A','B','C','D','E','F'};
24 encode(mail_encoding encoding
, char *out
, const char *in
, off_t length
,
29 return encode_base64(out
,in
,length
,headerMode
);
30 case quoted_printable
:
31 return encode_qp(out
,in
,length
,headerMode
);
35 memcpy(out
,in
,length
);
47 decode(mail_encoding encoding
, char *out
, const char *in
, off_t length
,
48 int underscoreIsSpace
)
52 return decode_base64(out
, in
, length
);
54 return uu_decode(out
, in
, length
);
58 memcpy(out
, in
, length
);
60 case quoted_printable
:
61 return decode_qp(out
, in
, length
, underscoreIsSpace
);
71 max_encoded_length(mail_encoding encoding
, off_t length
)
76 double result
= length
* 1.33333333333333;
77 result
+= (result
/ BASE64_LINELENGTH
) * 2 + 20;
78 return (ssize_t
)(result
);
80 case quoted_printable
:
96 encoding_for_cte(const char *cte
)
101 if (strcasecmp(cte
,"uuencode") == 0)
103 if (strcasecmp(cte
,"base64") == 0)
105 if (strcasecmp(cte
,"quoted-printable") == 0)
106 return quoted_printable
;
107 if (strcasecmp(cte
,"7bit") == 0)
109 if (strcasecmp(cte
,"8bit") == 0)
117 decode_qp(char *out
, const char *in
, off_t length
, int underscoreIsSpace
)
119 // decode Quoted Printable
121 const char *datain
= in
, *dataend
= in
+ length
;
123 while (datain
< dataend
) {
124 if (*datain
== '=' && dataend
- datain
> 2) {
125 int a
= toupper(datain
[1]);
126 a
-= a
>= '0' && a
<= '9' ? '0' : (a
>= 'A' && a
<= 'F'
129 int b
= toupper(datain
[2]);
130 b
-= b
>= '0' && b
<= '9' ? '0' : (b
>= 'A' && b
<= 'F'
133 if (a
>= 0 && b
>= 0) {
134 *dataout
++ = (a
<< 4) + b
;
137 } else if (datain
[1] == '\r' && datain
[2] == '\n') {
142 } else if (*datain
== '_' && underscoreIsSpace
) {
148 *dataout
++ = *datain
++;
152 return dataout
- out
;
157 encode_qp(char *out
, const char *in
, off_t length
, int headerMode
)
161 for (; i
< length
; i
++) {
162 if (((uint8
*)(in
))[i
] > 127 || in
[i
] == '?' || in
[i
] == '='
164 // Also encode the letter F in "From " at the start of the line,
165 // which Unix systems use to mark the start of messages in their
167 || (in
[i
] == 'F' && i
+ 5 <= length
&& (i
== 0 || in
[i
- 1] == '\n')
168 && in
[i
+ 1] == 'r' && in
[i
+ 2] == 'o' && in
[i
+ 3] == 'm'
169 && in
[i
+ 4] == ' ')) {
171 out
[g
++] = kHexAlphabet
[(in
[i
] >> 4) & 0x0f];
172 out
[g
++] = kHexAlphabet
[in
[i
] & 0x0f];
173 } else if (headerMode
&& (in
[i
] == ' ' || in
[i
] == '\t')) {
175 } else if (headerMode
&& in
[i
] >= 0 && in
[i
] < 32) {
176 // Control codes in headers need to be sanitized, otherwise certain
177 // Japanese ISPs mangle the headers badly. But they don't mangle
180 out
[g
++] = kHexAlphabet
[(in
[i
] >> 4) & 0x0f];
181 out
[g
++] = kHexAlphabet
[in
[i
] & 0x0f];
191 uu_decode(char *out
, const char *in
, off_t length
)
194 uint8
*p
, *inBuffer
= (uint8
*)in
;
195 uint8
*outBuffer
= (uint8
*)out
;
197 inBuffer
= (uint8
*)strstr((char *)inBuffer
, "begin");
200 while ((inBuffer
- (uint8
*)in
) <= length
201 && strncmp((char *)inBuffer
, "end", 3)) {
203 n
= DEC(inBuffer
[0]);
205 for (++inBuffer
; n
> 0; inBuffer
+= 4, n
-= 3) {
207 *outBuffer
++ = DEC(inBuffer
[0]) << 2 | DEC (inBuffer
[1]) >> 4;
208 *outBuffer
++ = DEC(inBuffer
[1]) << 4 | DEC (inBuffer
[2]) >> 2;
209 *outBuffer
++ = DEC(inBuffer
[2]) << 6 | DEC (inBuffer
[3]);
212 *outBuffer
++ = DEC(inBuffer
[0]) << 2
213 | DEC (inBuffer
[1]) >> 4;
216 *outBuffer
++ = DEC(inBuffer
[1]) << 4
217 | DEC (inBuffer
[2]) >> 2;
224 while (inBuffer
[0] != '\n' && inBuffer
[0] != '\r' && inBuffer
[0] != 0)
226 while (inBuffer
[0] == '\n' || inBuffer
[0] == '\r')
230 return (ssize_t
)(outBuffer
- (uint8
*)in
);