summaryrefslogtreecommitdiffabout
path: root/libetpan/src/data-types/mailstream_helper.c
Unidiff
Diffstat (limited to 'libetpan/src/data-types/mailstream_helper.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/data-types/mailstream_helper.c515
1 files changed, 515 insertions, 0 deletions
diff --git a/libetpan/src/data-types/mailstream_helper.c b/libetpan/src/data-types/mailstream_helper.c
new file mode 100644
index 0000000..2f0b9ae
--- a/dev/null
+++ b/libetpan/src/data-types/mailstream_helper.c
@@ -0,0 +1,515 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - 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 AUTHORS 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 AUTHORS 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 inline ssize_t send_data_line(mailstream * s,
251 const char * line, size_t length)
252{
253 int fix_eol;
254 const char * start;
255 size_t count;
256
257 start = line;
258
259 fix_eol = 0;
260 count = 0;
261
262 while (1) {
263 if (length == 0)
264 break;
265
266 if (* line == '\r') {
267 line ++;
268
269 count ++;
270 length --;
271
272 if (length == 0) {
273 fix_eol = 1;
274 break;
275 }
276
277 if (* line == '\n') {
278 line ++;
279
280 count ++;
281 length --;
282
283 break;
284 }
285 else {
286 fix_eol = 1;
287 break;
288 }
289 }
290 else if (* line == '\n') {
291 line ++;
292
293 count ++;
294 length --;
295
296 fix_eol = 1;
297 break;
298 }
299
300 line ++;
301 length --;
302 count ++;
303 }
304
305 if (fix_eol) {
306 if (mailstream_write(s, start, count - 1) == -1)
307 goto err;
308 if (mailstream_write(s, "\r\n", 2) == -1)
309 goto err;
310 }
311 else {
312 if (mailstream_write(s, start, count) == -1)
313 goto err;
314 }
315
316
317#if 0
318 while (* line != '\n') {
319 if (* line == '\r')
320 pos = line;
321 if (* line == '\0')
322 return line;
323 if (mailstream_write(s, line, 1) == -1)
324 goto err;
325 line ++;
326 }
327 if (pos + 1 == line) {
328 if (mailstream_write(s, line, 1) == -1)
329 goto err;
330 }
331 else {
332 if (mailstream_write(s, "\r\n", 2) == -1)
333 goto err;
334 }
335 line ++;
336#endif
337
338 return count;
339
340 err:
341 return -1;
342}
343
344static inline int send_data_crlf(mailstream * s, const char * message,
345 size_t size,
346 int quoted,
347 size_t progr_rate,
348 progress_function * progr_fun)
349{
350 const char * current;
351 size_t count;
352 size_t last;
353 size_t remaining;
354
355 count = 0;
356 last = 0;
357
358 current = message;
359 remaining = size;
360
361 while (remaining > 0) {
362 ssize_t length;
363
364 if (quoted) {
365 if (current[0] == '.')
366 if (mailstream_write(s, ".", 1) == -1)
367 goto err;
368 }
369
370 length = send_data_line(s, current, remaining);
371 if (length < 0)
372 goto err;
373
374 current += length;
375
376 count += length;
377 if ((progr_rate != 0) && (progr_fun != NULL))
378 if (count - last >= progr_rate) {
379 (* progr_fun)(count, size);
380 last = count;
381 }
382
383 remaining -= length;
384 }
385
386 return 0;
387
388 err:
389 return -1;
390}
391
392int mailstream_send_data_crlf(mailstream * s, const char * message,
393 size_t size,
394 size_t progr_rate,
395 progress_function * progr_fun)
396{
397 return send_data_crlf(s, message, size, 0, progr_rate, progr_fun);
398}
399
400int mailstream_send_data(mailstream * s, const char * message,
401 size_t size,
402 size_t progr_rate,
403 progress_function * progr_fun)
404{
405 if (send_data_crlf(s, message, size, 1, progr_rate, progr_fun) == -1)
406 goto err;
407
408 if (mailstream_write(s, "\r\n.\r\n", 5) == -1)
409 goto err;
410
411 if (mailstream_flush(s) == -1)
412 goto err;
413
414 return 0;
415
416 err:
417 return -1;
418}
419
420static inline ssize_t get_data_size(const char * line, size_t length,
421 size_t * result)
422{
423 int fix_eol;
424 const char * start;
425 size_t count;
426 size_t fixed_count;
427
428 start = line;
429
430 fix_eol = 0;
431 count = 0;
432 fixed_count = 0;
433
434 while (1) {
435 if (length == 0)
436 break;
437
438 if (* line == '\r') {
439 line ++;
440
441 count ++;
442 length --;
443
444 if (length == 0) {
445 fix_eol = 1;
446 fixed_count ++;
447 break;
448 }
449
450 if (* line == '\n') {
451 line ++;
452
453 count ++;
454 length --;
455
456 break;
457 }
458 else {
459 fix_eol = 1;
460 fixed_count ++;
461 break;
462 }
463 }
464 else if (* line == '\n') {
465 line ++;
466
467 count ++;
468 length --;
469
470 fix_eol = 1;
471 fixed_count ++;
472 break;
473 }
474
475 line ++;
476 length --;
477 count ++;
478 }
479
480 * result = count + fixed_count;
481
482 return count;
483}
484
485size_t mailstream_get_data_crlf_size(const char * message, size_t size)
486{
487 const char * current;
488 size_t count;
489 size_t last;
490 size_t remaining;
491 size_t fixed_count;
492
493 count = 0;
494 last = 0;
495 fixed_count = 0;
496
497 current = message;
498 remaining = size;
499
500 while (remaining > 0) {
501 ssize_t length;
502 size_t line_count;
503
504 length = get_data_size(current, remaining, &line_count);
505
506 fixed_count += line_count;
507 current += length;
508
509 count += length;
510
511 remaining -= length;
512 }
513
514 return fixed_count;
515}