2 ** Copyright 2003-2004 Double Precision, Inc. See COPYING for
3 ** distribution information.
12 static int quoted_printable(struct libmail_encode_info
*,
13 const char *, size_t);
14 static int base64(struct libmail_encode_info
*,
15 const char *, size_t);
16 static int eflush(struct libmail_encode_info
*,
17 const char *, size_t);
19 void libmail_encode_start(struct libmail_encode_info
*info
,
20 const char *transfer_encoding
,
21 int (*callback_func
)(const char *, size_t, void *),
24 info
->output_buf_cnt
=0;
25 info
->input_buf_cnt
=0;
27 switch (*transfer_encoding
) {
30 info
->encoding_func
=quoted_printable
;
31 info
->input_buffer
[0]=0; /* Recycle for qp encoding */
35 info
->encoding_func
=base64
;
38 info
->encoding_func
=eflush
;
41 info
->callback_func
=callback_func
;
42 info
->callback_arg
=callback_arg
;
45 int libmail_encode(struct libmail_encode_info
*info
,
49 return ((*info
->encoding_func
)(info
, ptr
, cnt
));
52 int libmail_encode_end(struct libmail_encode_info
*info
)
54 int rc
=(*info
->encoding_func
)(info
, NULL
, 0);
56 if (rc
== 0 && info
->output_buf_cnt
> 0)
58 rc
= (*info
->callback_func
)(info
->output_buffer
,
61 info
->output_buf_cnt
=0;
67 static int eflush(struct libmail_encode_info
*info
, const char *ptr
, size_t n
)
73 if (info
->output_buf_cnt
== sizeof(info
->output_buffer
))
75 int rc
= (*info
->callback_func
)(info
->output_buffer
,
79 info
->output_buf_cnt
=0;
86 if (i
> sizeof(info
->output_buffer
) - info
->output_buf_cnt
)
87 i
=sizeof(info
->output_buffer
) - info
->output_buf_cnt
;
89 memcpy(info
->output_buffer
+ info
->output_buf_cnt
, ptr
, i
);
90 info
->output_buf_cnt
+= i
;
97 static int base64_flush(struct libmail_encode_info
*);
99 static int base64(struct libmail_encode_info
*info
,
100 const char *buf
, size_t n
)
106 if (info
->input_buf_cnt
> 0)
107 rc
=base64_flush(info
);
116 if (info
->input_buf_cnt
== sizeof(info
->input_buffer
))
118 int rc
=base64_flush(info
);
125 if (i
> sizeof(info
->input_buffer
) - info
->input_buf_cnt
)
126 i
=sizeof(info
->input_buffer
) - info
->input_buf_cnt
;
128 memcpy(info
->input_buffer
+ info
->input_buf_cnt
,
130 info
->input_buf_cnt
+= i
;
137 static const char base64tab
[]=
138 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
140 static int base64_flush(struct libmail_encode_info
*info
)
145 char output_buf
[ sizeof(info
->input_buffer
) / 3 * 4+1];
147 for (j
=i
=0; i
<info
->input_buf_cnt
; i
+= 3)
149 a
=(unsigned char)info
->input_buffer
[i
];
150 b
= i
+1 < info
->input_buf_cnt
?
151 (unsigned char)info
->input_buffer
[i
+1]:0;
152 c
= i
+2 < info
->input_buf_cnt
?
153 (unsigned char)info
->input_buffer
[i
+2]:0;
155 d
=base64tab
[ a
>> 2 ];
156 e
=base64tab
[ ((a
& 3 ) << 4) | (b
>> 4)];
157 f
=base64tab
[ ((b
& 15) << 2) | (c
>> 6)];
158 g
=base64tab
[ c
& 63 ];
159 if (i
+ 1 >= info
->input_buf_cnt
) f
='=';
160 if (i
+ 2 >= info
->input_buf_cnt
) g
='=';
167 info
->input_buf_cnt
=0;
169 output_buf
[j
++]='\n';
170 return eflush(info
, output_buf
, j
);
173 static const char xdigit
[]="0123456789ABCDEF";
175 static int quoted_printable(struct libmail_encode_info
*info
,
176 const char *p
, size_t n
)
181 #define QPUT(c) do { if (local_buf_cnt == sizeof(local_buf)) \
182 { int rc=eflush(info, local_buf, local_buf_cnt); \
183 local_buf_cnt=0; if (rc) return (rc); } \
184 local_buf[local_buf_cnt]=(c); ++local_buf_cnt; } while(0)
194 ** Repurpose input_buffer[0] as a flag whether the previous
195 ** character was a space.
197 ** A space before a newline gets escaped.
200 if (info
->input_buffer
[0])
212 ++info
->input_buf_cnt
;
215 info
->input_buffer
[0]=0;
219 info
->input_buffer
[0]=1;
225 if (info
->input_buf_cnt
> 72 && *p
!= '\n')
229 info
->input_buf_cnt
=0;
233 info
->input_buf_cnt
=0;
234 else if (*p
< ' ' || *p
== '=' || *p
>= 0x7F)
237 QPUT(xdigit
[ (*p
>> 4) & 15]);
238 QPUT(xdigit
[ *p
& 15 ]);
239 info
->input_buf_cnt
+= 3;
244 else info
->input_buf_cnt
++;
251 if (local_buf_cnt
> 0)
252 return eflush(info
, local_buf
, local_buf_cnt
);