Mercurial > dovecot > original-hg > dovecot-1.2
view src/lib-mail/message-send.c @ 1867:d9d05fc3c905 HEAD
message_send()'s skip parameter was buggy with messages having CRLF.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sat, 08 Nov 2003 22:47:07 +0200 |
parents | e42d97a85653 |
children | 118ed97bd25a |
line wrap: on
line source
/* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" #include "istream.h" #include "ostream.h" #include "message-parser.h" #include "message-send.h" #include "message-size.h" off_t message_send(struct ostream *output, struct istream *input, const struct message_size *msg_size, int cr_skipped, uoff_t max_virtual_size, int *last_cr, int fix_nuls) { const unsigned char *msg; size_t i, size; off_t ret; unsigned char add; if (last_cr != NULL) *last_cr = -1; if (msg_size->physical_size == 0) return 0; if (msg_size->physical_size == msg_size->virtual_size && !fix_nuls) { /* no need to kludge with CRs, we can use sendfile() */ input = i_stream_create_limit(default_pool, input, input->v_offset, max_virtual_size); ret = o_stream_send_istream(output, input); i_stream_unref(input); return ret; } /* go through the message data and insert CRs where needed. */ ret = 0; while (max_virtual_size > 0 && i_stream_read_data(input, &msg, &size, 0) > 0) { add = '\0'; for (i = 0; i < size && max_virtual_size > 0; i++) { max_virtual_size--; if (msg[i] == '\n') { if ((i > 0 && msg[i-1] != '\r') || (i == 0 && !cr_skipped)) { /* missing CR */ add = '\r'; break; } } else if (msg[i] == '\0') { add = 128; break; } } ret += i; if (o_stream_send(output, msg, i) < 0) return -1; if (add != '\0') { ret++; if (o_stream_send(output, &add, 1) < 0) return -1; cr_skipped = add == '\r'; if (add == 128) i++; } else { cr_skipped = i > 0 && msg[i-1] == '\r'; } i_stream_skip(input, i); } if (last_cr != NULL) *last_cr = cr_skipped; return ret; } void message_skip_virtual(struct istream *input, uoff_t virtual_skip, struct message_size *msg_size, int cr_skipped, int *last_cr) { const unsigned char *msg; size_t i, size, startpos; if (virtual_skip == 0) { *last_cr = cr_skipped; return; } *last_cr = FALSE; startpos = 0; while (i_stream_read_data(input, &msg, &size, startpos) > 0) { for (i = startpos; i < size && virtual_skip > 0; i++) { virtual_skip--; if (msg[i] == '\r') { /* CR */ if (virtual_skip == 0) *last_cr = TRUE; } else if (msg[i] == '\n') { /* LF */ if ((i == 0 && !cr_skipped) || (i > 0 && msg[i-1] != '\r')) { /* missing CR */ if (msg_size != NULL) msg_size->virtual_size++; if (virtual_skip == 0) { /* CR/LF boundary */ *last_cr = TRUE; break; } virtual_skip--; } /* increase after making sure we didn't break at virtual \r */ if (msg_size != NULL) msg_size->lines++; } } if (msg_size != NULL) { msg_size->physical_size += i; msg_size->virtual_size += i; } if (i < size) { i_stream_skip(input, i); break; } /* leave the last character, it may be \r */ i_stream_skip(input, i - 1); startpos = 1; cr_skipped = FALSE; } }