summaryrefslogtreecommitdiffabout
path: root/kmicromail/libetpan/tools/mailstream_helper.c
Unidiff
Diffstat (limited to 'kmicromail/libetpan/tools/mailstream_helper.c') (more/less context) (ignore whitespace changes)
-rw-r--r--kmicromail/libetpan/tools/mailstream_helper.c383
1 files changed, 383 insertions, 0 deletions
diff --git a/kmicromail/libetpan/tools/mailstream_helper.c b/kmicromail/libetpan/tools/mailstream_helper.c
new file mode 100644
index 0000000..146f955
--- a/dev/null
+++ b/kmicromail/libetpan/tools/mailstream_helper.c
@@ -0,0 +1,383 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2002 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailstream_helper.h"
37#include <string.h>
38#include <stdio.h>
39#include "mail.h"
40
41static void remove_trailing_eol(MMAPString * mmapstr)
42{
43 if (mmapstr->str[mmapstr->len - 1] == '\n') {
44 mmapstr->len --;
45 mmapstr->str[mmapstr->len] = '\0';
46 }
47 if (mmapstr->str[mmapstr->len - 1] == '\r') {
48 mmapstr->len --;
49 mmapstr->str[mmapstr->len] = '\0';
50 }
51}
52
53char * mailstream_read_line(mailstream * stream, MMAPString * line)
54{
55 if (mmap_string_assign(line, "") == NULL)
56 return NULL;
57
58 return mailstream_read_line_append(stream, line);
59}
60
61static char * mailstream_read_len_append(mailstream * stream,
62 MMAPString * line,
63 size_t i)
64{
65 size_t cur_size;
66
67 cur_size = line->len;
68 if (mmap_string_set_size(line, line->len + i) == NULL)
69 return NULL;
70 if (mailstream_read(stream, line->str + cur_size, i) < 0)
71 return NULL;
72 return line->str;
73}
74
75char * mailstream_read_line_append(mailstream * stream, MMAPString * line)
76{
77 if (stream == NULL)
78 return NULL;
79
80 do {
81 if (stream->read_buffer_len > 0) {
82 size_t i;
83
84 i = 0;
85 while (i < stream->read_buffer_len) {
86 if (stream->read_buffer[i] == '\n')
87 return mailstream_read_len_append(stream, line, i + 1);
88 i++;
89 }
90 if (mailstream_read_len_append(stream, line,
91 stream->read_buffer_len) == NULL)
92 return NULL;
93 }
94 else {
95 ssize_t r;
96
97 r = mailstream_feed_read_buffer(stream);
98 if (r == -1)
99 return NULL;
100
101 if (r == 0)
102 break;
103 }
104 }
105 while (1);
106
107 return line->str;
108}
109
110char * mailstream_read_line_remove_eol(mailstream * stream, MMAPString * line)
111{
112 if (!mailstream_read_line(stream, line))
113 return NULL;
114
115 remove_trailing_eol(line);
116
117 return line->str;
118}
119
120int mailstream_is_end_multiline(const char * line)
121{
122 if (line[0] != '.')
123 return FALSE;
124 if (line[1] != 0)
125 return FALSE;
126 return TRUE;
127}
128
129#if 1
130char * mailstream_read_multiline(mailstream * s, size_t size,
131 MMAPString * stream_buffer,
132 MMAPString * multiline_buffer,
133 size_t progr_rate,
134 progress_function * progr_fun)
135{
136 size_t count;
137 char * line;
138 size_t last;
139
140 if (mmap_string_assign(multiline_buffer, "") == NULL)
141 return NULL;
142
143 count = 0;
144 last = 0;
145
146 while ((line = mailstream_read_line_remove_eol(s, stream_buffer)) != NULL) {
147 if (mailstream_is_end_multiline(line))
148 return multiline_buffer->str;
149
150 if (line[0] == '.') {
151 if (mmap_string_append(multiline_buffer, line + 1) == NULL)
152 return NULL;
153 }
154 else {
155 if (mmap_string_append(multiline_buffer, line) == NULL)
156 return NULL;
157 }
158 if (mmap_string_append(multiline_buffer, "\r\n") == NULL)
159 return NULL;
160
161 count += strlen(line);
162 if ((size != 0) && (progr_rate != 0) && (progr_fun != NULL))
163 if (count - last >= progr_rate) {
164 (* progr_fun)(count, size);
165 last = count;
166 }
167 }
168
169 return NULL;
170}
171
172#else
173
174/*
175 high speed but don't replace the line break with '\n' and neither
176 remove the '.'
177*/
178
179static gboolean end_of_multiline(const char * str, gint len)
180{
181 gint index;
182
183 index = len - 1;
184
185 if (str[index] != '\n')
186 return FALSE;
187 if (index == 0)
188 return FALSE;
189
190 index --;
191
192 if (str[index] == '\r') {
193 index --;
194 if (index == 0)
195 return FALSE;
196 }
197
198 if (str[index] != '.')
199 return FALSE;
200 if (index == 0)
201 return FALSE;
202
203 index--;
204
205 if (str[index] != '\n')
206 return FALSE;
207
208 return TRUE;
209}
210
211char * mailstream_read_multiline(mailstream * stream, size_t size,
212 MMAPString * stream_buffer,
213 MMAPString * line,
214 size_t progr_rate,
215 progress_function * progr_fun)
216{
217 if (stream == NULL)
218 return NULL;
219
220 mmap_string_assign(line, "");
221
222 do {
223 if (stream->read_buffer_len > 0) {
224 size_t i;
225
226 i = 0;
227 while (i < stream->read_buffer_len) {
228 if (end_of_multiline(stream->read_buffer, i + 1))
229 return mailstream_read_len_append(stream, line, i + 1);
230 i++;
231 }
232 if (mailstream_read_len_append(stream, line,
233 stream->read_buffer_len) == NULL)
234 return NULL;
235 if (end_of_multiline(line->str, line->len))
236 return line->str;
237 }
238 else
239 if (mailstream_feed_read_buffer(stream) == -1)
240 return NULL;
241 }
242 while (1);
243
244 return line->str;
245}
246#endif
247
248
249
250static ssize_t send_data_line(mailstream * s, const char * line, size_t length)
251{
252 int fix_eol;
253 const char * start;
254 size_t count;
255
256 start = line;
257
258 fix_eol = 0;
259 count = 0;
260
261 while (1) {
262 if (length == 0)
263 break;
264
265 if (* line == '\r') {
266 line ++;
267
268 count ++;
269 length --;
270
271 if (* line == '\n') {
272 line ++;
273
274 count ++;
275 length --;
276
277 break;
278 }
279 }
280
281 if (* line == '\n') {
282 line ++;
283
284 count ++;
285 length --;
286
287 fix_eol = 1;
288 break;
289 }
290
291 line ++;
292 length --;
293 count ++;
294 }
295
296 if (start[0] == '.')
297 if (mailstream_write(s, ".", 1) == -1)
298 goto err;
299
300 if (fix_eol) {
301 if (mailstream_write(s, start, count - 1) == -1)
302 goto err;
303 if (mailstream_write(s, "\r\n", 2) == -1)
304 goto err;
305 }
306 else {
307 if (mailstream_write(s, start, count) == -1)
308 goto err;
309 }
310
311
312#if 0
313 while (* line != '\n') {
314 if (* line == '\r')
315 pos = line;
316 if (* line == '\0')
317 return line;
318 if (mailstream_write(s, line, 1) == -1)
319 goto err;
320 line ++;
321 }
322 if (pos + 1 == line) {
323 if (mailstream_write(s, line, 1) == -1)
324 goto err;
325 }
326 else {
327 if (mailstream_write(s, "\r\n", 2) == -1)
328 goto err;
329 }
330 line ++;
331#endif
332
333 return count;
334
335 err:
336 return -1;
337}
338
339int mailstream_send_data(mailstream * s, const char * message,
340 size_t size,
341 size_t progr_rate,
342 progress_function * progr_fun)
343{
344 const char * current;
345 size_t count;
346 size_t last;
347 size_t remaining;
348
349 count = 0;
350 last = 0;
351
352 current = message;
353 remaining = size;
354
355 while (remaining > 0) {
356 ssize_t length;
357
358 length = send_data_line(s, current, remaining);
359 if (length < 0)
360 goto err;
361
362 current += length;
363
364 count += length;
365 if ((progr_rate != 0) && (progr_fun != NULL))
366 if (count - last >= progr_rate) {
367 (* progr_fun)(count, size);
368 last = count;
369 }
370
371 remaining -= length;
372 }
373 if (mailstream_write(s, "\r\n.\r\n", 5) == -1)
374 goto err;
375
376 if (mailstream_flush(s) == -1)
377 goto err;
378
379 return 0;
380
381 err:
382 return -1;
383}