Skip to content

Commit

Permalink
lib-mail: istream-header-filter: Fixed stat() with HEADER_FILTER_END_…
Browse files Browse the repository at this point in the history
…BODY_WITH_LF
  • Loading branch information
sirainen committed May 11, 2016
1 parent a3cdcdd commit 6d16133
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 0 deletions.
23 changes: 23 additions & 0 deletions src/lib-mail/istream-header-filter.c
Expand Up @@ -547,6 +547,28 @@ i_stream_header_filter_stat(struct istream_private *stream, bool exact)
if (skip_header(mstream) < 0)
return -1;

if (!mstream->end_body_with_lf) {
/* no last-LF */
} else if (mstream->last_lf_added) {
/* yes, we have added LF */
stream->statbuf.st_size += mstream->crlf ? 2 : 1;
} else if (mstream->last_lf_offset != (uoff_t)-1) {
/* no, we didn't need to add LF */
} else {
/* check if we need to add LF */
i_stream_seek(stream->parent, st->st_size - 1);
(void)i_stream_read(stream->parent);
if (stream->parent->stream_errno != 0) {
stream->istream.stream_errno =
stream->parent->stream_errno;
return -1;
}
i_assert(stream->parent->eof);
ssize_t ret = handle_end_body_with_lf(mstream, -1);
if (ret > 0)
stream->statbuf.st_size += ret;
}

stream->statbuf.st_size -=
(off_t)mstream->header_size.physical_size -
(off_t)mstream->header_size.virtual_size;
Expand Down Expand Up @@ -601,6 +623,7 @@ i_stream_create_header_filter(struct istream *input,
mstream->add_missing_eoh = (flags & HEADER_FILTER_ADD_MISSING_EOH) != 0;
mstream->end_body_with_lf =
(flags & HEADER_FILTER_END_BODY_WITH_LF) != 0;
mstream->last_lf_offset = (uoff_t)-1;

mstream->istream.iostream.destroy = i_stream_header_filter_destroy;
mstream->istream.read = i_stream_header_filter_read;
Expand Down
19 changes: 19 additions & 0 deletions src/lib-mail/test-istream-header-filter.c
Expand Up @@ -12,6 +12,7 @@ test_istream_run(struct istream *test_istream, struct istream *filter,
unsigned int input_len, const char *output)
{
unsigned int i, output_len = strlen(output);
const struct stat *st;
const unsigned char *data;
size_t size;

Expand All @@ -32,6 +33,8 @@ test_istream_run(struct istream *test_istream, struct istream *filter,
while (i_stream_read(filter) > 0) ;
data = i_stream_get_data(filter, &size);
test_assert(size == output_len && memcmp(data, output, size) == 0);
test_assert(i_stream_stat(filter, TRUE, &st) == 0 &&
(uoff_t)st->st_size == size);
}

static void ATTR_NULL(3)
Expand All @@ -55,6 +58,7 @@ static void test_istream_filter(void)
unsigned int i, input_len = strlen(input);
unsigned int output_len = strlen(output);
const unsigned char *data;
const struct stat *st;
size_t size;

test_begin("i_stream_create_header_filter(exclude)");
Expand Down Expand Up @@ -86,11 +90,16 @@ static void test_istream_filter(void)
data = i_stream_get_data(filter, &size);
test_assert(size == output_len && memcmp(data, output, size) == 0);

test_assert(i_stream_stat(filter, TRUE, &st) == 0 &&
(uoff_t)st->st_size == size);

i_stream_skip(filter, size);
i_stream_seek(filter, 0);
while (i_stream_read(filter) > 0) ;
data = i_stream_get_data(filter, &size);
test_assert(size == output_len && memcmp(data, output, size) == 0);
test_assert(i_stream_stat(filter, TRUE, &st) == 0 &&
(uoff_t)st->st_size == size);

i_stream_unref(&filter);
i_stream_unref(&istream);
Expand Down Expand Up @@ -119,6 +128,7 @@ static void test_istream_filter_large_buffer(void)
{
string_t *input, *output;
struct istream *istream, *filter;
const struct stat *st;
const unsigned char *data;
size_t size, prefix_len;
const char *p;
Expand Down Expand Up @@ -172,6 +182,9 @@ static void test_istream_filter_large_buffer(void)
i_assert(p != NULL);
test_assert(strcmp(p+1, str_c(output) + prefix_len) == 0);

test_assert(i_stream_stat(filter, TRUE, &st) == 0 &&
(uoff_t)st->st_size == filter->v_offset + size);

/* seek back and retry once with caching and different
buffer size */
i_stream_seek(filter, 0);
Expand Down Expand Up @@ -199,6 +212,7 @@ filter3_callback(struct header_filter_istream *input ATTR_UNUSED,
static void test_istream_callbacks(void)
{
string_t *input, *output;
const struct stat *st;
struct istream *istream, *filter;
unsigned int i;

Expand Down Expand Up @@ -230,6 +244,8 @@ static void test_istream_callbacks(void)
i_stream_skip(filter, i_stream_get_data_size(filter));
}

test_assert(i_stream_stat(filter, TRUE, &st) == 0 &&
(uoff_t)st->st_size == str_len(output));
test_assert(strcmp(str_c(output), str_c(input)) == 0);
str_free(&input);
str_free(&output);
Expand Down Expand Up @@ -276,6 +292,7 @@ static void test_istream_end_body_with_lf(void)
{
const char *input = "From: foo\n\nhello world";
const char *output = "From: foo\n\nhello world\n";
const struct stat *st;
struct istream *istream, *filter;
unsigned int i, input_len = strlen(input);
unsigned int output_len = strlen(output);
Expand Down Expand Up @@ -304,6 +321,8 @@ static void test_istream_end_body_with_lf(void)

data = i_stream_get_data(filter, &size);
test_assert(size == output_len && memcmp(data, output, size) == 0);
test_assert(i_stream_stat(filter, TRUE, &st) == 0 &&
(uoff_t)st->st_size == filter->v_offset + size);

i_stream_skip(filter, size);
i_stream_seek(filter, 0);
Expand Down

0 comments on commit 6d16133

Please sign in to comment.