author | zautrix <zautrix> | 2005-03-18 20:17:03 (UTC) |
---|---|---|
committer | zautrix <zautrix> | 2005-03-18 20:17:03 (UTC) |
commit | 9e549686b23b6dffdcbd09c9b10dc2cb795fbcdf (patch) (unidiff) | |
tree | 2528e6cc740225ca0f47d5ac8ff70f7d3bb10621 /libetpan/src/data-types/mailstream_helper.c | |
parent | 9319998f20f03dcc217fbb39656755dc65226276 (diff) | |
download | kdepimpi-9e549686b23b6dffdcbd09c9b10dc2cb795fbcdf.zip kdepimpi-9e549686b23b6dffdcbd09c9b10dc2cb795fbcdf.tar.gz kdepimpi-9e549686b23b6dffdcbd09c9b10dc2cb795fbcdf.tar.bz2 |
Initial revision
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.c | 515 |
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 | |||
41 | static 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 | |||
53 | char * 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 | |||
61 | static 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 | |||
75 | char * 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 | |||
110 | char * 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 | |||
120 | int 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 | ||
130 | char * 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 | |||
179 | static 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 | |||
211 | char * 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 | |||
250 | static 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 | |||
344 | static 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 | |||
392 | int 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 | |||
400 | int 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 | |||
420 | static 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 | |||
485 | size_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 | } | ||