istream-header-filter.c revision e8eb96edcfe8cff7839f1258ab6e871e41a4785e
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const char **headers;
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainenheader_filter_callback *null_header_filter_callback = NULL;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic void _close(struct _iostream *stream __attr_unused__)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen message_parse_header_deinit(&mstream->hdr_ctx);
461ffead9720d1e516b959d5e41f049c73d38c7cTimo Sirainenstatic void _set_max_buffer_size(struct _iostream *stream, size_t max_size)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_stream_set_max_buffer_size(mstream->input, max_size);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic ssize_t read_header(struct header_filter_istream *mstream)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen (mstream->istream.pos - mstream->istream.skip) ==
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* we don't support mixing headers and body.
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen it shouldn't be needed. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen message_parse_header_init(mstream->input, NULL, FALSE);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mstream->hdr_buf, mstream->istream.skip, (size_t)-1);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mstream->istream.pos -= mstream->istream.skip;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen buffer_set_used_size(mstream->hdr_buf, mstream->istream.pos);
637455ebee0453f860c9bce0626c485e35fb83deTimo Sirainen while ((hdr_ret = message_parse_header_next(mstream->hdr_ctx,
637455ebee0453f860c9bce0626c485e35fb83deTimo Sirainen matched = mstream->headers_count == 0 ? FALSE :
6ae329de09afb7214c906d762320847e05469d53Timo Sirainen if (mstream->cur_line > mstream->parsed_lines &&
637455ebee0453f860c9bce0626c485e35fb83deTimo Sirainen mstream->callback(hdr, &matched, mstream->context);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mstream->skip_count >= mstream->hdr_buf->used) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* we need more */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mstream->skip_count -= mstream->hdr_buf->used;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* don't copy eof here because we're only returning headers here.
73a87c2ff65c6116cde6fb158dfddb8ef7346901Timo Sirainen the body will be returned in separate read() call. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mstream->istream.buffer = buffer_get_data(mstream->hdr_buf, &pos);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ret = (ssize_t)(pos - mstream->istream.pos - mstream->istream.skip);
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen /* finished */
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen message_parse_header_deinit(&mstream->hdr_ctx);
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen if (!mstream->header_parsed && mstream->callback != NULL)
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen mstream->callback(NULL, &matched, mstream->context);
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen mstream->header_size.physical_size = mstream->input->v_offset;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen stream->istream.v_offset < mstream->header_size.virtual_size) {
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen i_stream_seek(mstream->input, mstream->start_offset +
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen stream->buffer = i_stream_get_data(mstream->input, &pos);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen if ((ret = i_stream_read(mstream->input)) == -2) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen stream->istream.stream_errno = mstream->input->stream_errno;
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen stream->buffer = i_stream_get_data(mstream->input, &pos);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ret = pos > stream->pos ? (ssize_t)(pos - stream->pos) :
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic void parse_header(struct header_filter_istream *mstream)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen (void)i_stream_get_data(&mstream->istream.istream, &pos);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_stream_skip(&mstream->istream.istream, pos);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic void _seek(struct _istream *stream, uoff_t v_offset,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen message_parse_header_deinit(&mstream->hdr_ctx);
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen if (v_offset < mstream->header_size.virtual_size) {
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen /* seek into headers. we'll have to re-parse them, use
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen skip_count to set the wanted position */
ddb018bc886680f462463b2c87f983fdedbf6cf0Timo Sirainen i_stream_seek(mstream->input, mstream->start_offset);
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen v_offset += mstream->header_size.physical_size -
37ee89f3cba22cd975912a882f0d3097fa5031e1Timo Sirainen i_stream_seek(mstream->input, mstream->start_offset + v_offset);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_panic("istream-header-filter sync() not implemented");
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic const struct stat *
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (st == NULL || st->st_size == -1 || !exact)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Siraineni_stream_create_header_filter(struct istream *input,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const char *const *headers,
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen header_filter_callback *callback, void *context)
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen unsigned int i;
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen i_assert((flags & (HEADER_FILTER_INCLUDE|HEADER_FILTER_EXCLUDE)) != 0);
4fded1eec06aba9ce37887ac30619768760cd0d0Timo Sirainen pool = pool_alloconly_create("header filter stream", 4096);
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen mstream = p_new(pool, struct header_filter_istream, 1);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mstream->headers = headers_count == 0 ? NULL :
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen for (i = 0; i < headers_count; i++)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mstream->headers[i] = p_strdup(pool, headers[i]);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mstream->hdr_buf = buffer_create_dynamic(pool, 1024);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mstream->exclude = (flags & HEADER_FILTER_EXCLUDE) != 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mstream->crlf = (flags & HEADER_FILTER_NO_CR) == 0;
f71c2d4e6b802bf8e622bcd5df29286262d05d5aTimo Sirainen mstream->hide_body = (flags & HEADER_FILTER_HIDE_BODY) != 0;
5b62dea2f88165f3f4d87bba9011343f3ff415ffTimo Sirainen mstream->istream.iostream.set_max_buffer_size = _set_max_buffer_size;