istream-raw-mbox.c revision c74ea62a27878910e3ca1614ca055d7e2b3b00d5
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (C) 2003 Timo Sirainen */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "lib.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "buffer.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "istream-internal.h"
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen#include "istream-raw-mbox.h"
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen#include "mbox-from.h"
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainenstruct raw_mbox_istream {
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen struct _istream istream;
b1f37113a5760bee842c5a7678bb5fa6f5bd8b60Timo Sirainen
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen time_t received_time, next_received_time;
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen char *sender, *next_sender;
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen uoff_t from_offset, hdr_offset, body_offset, mail_size;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen struct istream *input;
13d98ffa534f2e7d04a832c9d0153fc9c568b878Timo Sirainen uoff_t input_peak_offset;
13d98ffa534f2e7d04a832c9d0153fc9c568b878Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int corrupted:1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int eof:1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen};
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainenstatic void _close(struct _iostream *stream __attr_unused__)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic void _destroy(struct _iostream *stream)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct raw_mbox_istream *rstream = (struct raw_mbox_istream *)stream;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_free(rstream->sender);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_free(rstream->next_sender);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_stream_seek(rstream->input, rstream->istream.istream.v_offset);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen i_stream_unref(rstream->input);
220e21750948941dc6e33b8f11b552fa21d7f81eTimo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic void _set_max_buffer_size(struct _iostream *stream, size_t max_size)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen{
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen struct raw_mbox_istream *rstream = (struct raw_mbox_istream *)stream;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen i_stream_set_max_buffer_size(rstream->input, max_size);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen}
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainenstatic int mbox_read_from_line(struct raw_mbox_istream *rstream)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen{
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen const unsigned char *buf, *p;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen char *sender;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen time_t received_time;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen size_t pos, line_pos;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen int skip;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen buf = i_stream_get_data(rstream->input, &pos);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_assert(pos > 0);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* from_offset points to "\nFrom ", so unless we're at the beginning
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen of the file, skip the initial \n */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen skip = rstream->from_offset != 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (skip && *buf == '\r')
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen skip++;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen while ((p = memchr(buf+skip, '\n', pos-skip)) == NULL) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (i_stream_read(rstream->input) < 0) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* EOF - shouldn't happen */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return -1;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen }
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen buf = i_stream_get_data(rstream->input, &pos);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen i_assert(pos > 0);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen }
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen line_pos = (size_t)(p - buf);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (rstream->from_offset != 0) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen buf += skip;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen pos -= skip;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* beginning of mbox */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (memcmp(buf, "From ", 5) != 0 ||
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mbox_from_parse(buf+5, pos-5, &received_time, &sender) < 0) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* broken From - should happen only at beginning of
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen file if this isn't a mbox.. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return -1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (rstream->istream.istream.v_offset == rstream->from_offset) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen rstream->received_time = received_time;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen i_free(rstream->sender);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen rstream->sender = sender;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen } else {
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen rstream->next_received_time = received_time;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen i_free(rstream->next_sender);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen rstream->next_sender = sender;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen }
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen /* we'll skip over From-line */
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen rstream->istream.istream.v_offset += line_pos+1;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen i_stream_skip(rstream->input, line_pos+1);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen rstream->hdr_offset = rstream->istream.istream.v_offset;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen return 0;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainenstatic void handle_end_of_mail(struct raw_mbox_istream *rstream, size_t pos)
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen rstream->mail_size = rstream->istream.istream.v_offset + pos -
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen rstream->hdr_offset;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (rstream->hdr_offset + rstream->mail_size < rstream->body_offset) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* a) Header didn't have ending \n
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen b) "headers\n\nFrom ..", the second \n belongs to next
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen message which we didn't know at the time yet. */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_assert(rstream->body_offset == (uoff_t)-1 ||
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen rstream->body_offset ==
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen rstream->hdr_offset + rstream->mail_size + 1);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen rstream->body_offset =
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen rstream->hdr_offset + rstream->mail_size;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic ssize_t _read(struct _istream *stream)
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen{
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen static const char *mbox_from = "\nFrom ";
63e207529879438e9f4412d97cdc34bdc82a3702Timo Sirainen struct raw_mbox_istream *rstream = (struct raw_mbox_istream *)stream;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen const unsigned char *buf;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen const char *fromp;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen char *sender;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen time_t received_time;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen size_t i, pos, new_pos, from_start_pos, from_after_pos;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen ssize_t ret = 0;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen int eoh_char;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen i_assert(stream->istream.v_offset >= rstream->from_offset);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen if (stream->istream.eof)
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen return -1;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen i_stream_seek(rstream->input, stream->istream.v_offset);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen stream->pos -= stream->skip;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen stream->skip = 0;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen stream->buffer = NULL;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ret = 0;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen do {
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen buf = i_stream_get_data(rstream->input, &pos);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (pos > 1 && stream->istream.v_offset + pos >
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen rstream->input_peak_offset) {
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen /* fake our read count. needed because if in the end
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen we have only one character in buffer and we skip it
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen (as potential CR), we want to get back to this
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen _read() to read more data. */
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen ret = pos;
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen break;
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen }
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen ret = i_stream_read(rstream->input);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen } while (ret > 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (ret < 0) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (ret == -2) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (stream->istream.v_offset + pos ==
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen rstream->input_peak_offset) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen stream->buffer = buf;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return -2;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
27586e4785d56aeb76e1fd96af8db799688dc64aTimo Sirainen } else if (stream->istream.v_offset != 0 || pos == 0) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* we've read the whole file, final byte should be
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen the \n trailer */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (pos > 0 && buf[pos-1] == '\n') {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen pos--;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (pos > 0 && buf[pos-1] == '\r')
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen pos--;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_assert(pos >= stream->pos);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ret = pos == stream->pos ? -1 :
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen (ssize_t)(pos - stream->pos);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen stream->buffer = buf;
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen stream->pos = pos;
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk if (stream->istream.v_offset == rstream->from_offset) {
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk /* haven't seen From-line yet, so this mbox
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk stream is now at EOF */
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk rstream->eof = TRUE;
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk }
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen stream->istream.eof = TRUE;
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen handle_end_of_mail(rstream, pos);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return ret < 0 ? _read(stream) : ret;
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen }
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen }
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen if (stream->istream.v_offset == rstream->from_offset) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* beginning of message, we haven't yet read our From-line */
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen if (mbox_read_from_line(rstream) < 0) {
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen stream->pos = 0;
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen rstream->eof = TRUE;
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen rstream->corrupted = TRUE;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen return -1;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen /* got it. we don't want to return it however,
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen so start again from headers */
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen buf = i_stream_get_data(rstream->input, &pos);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (pos == 0)
9abf5be0962538e1f6f5c73c838ff677341da0c9Timo Sirainen return _read(stream);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen }
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen /* See if we have From-line here - note that it works right only
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen because all characters are different in mbox_from. */
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen fromp = mbox_from; from_start_pos = from_after_pos = (size_t)-1;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen eoh_char = rstream->body_offset == (uoff_t)-1 ? '\n' : -1;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen for (i = stream->pos; i < pos; i++) {
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen if (buf[i] == eoh_char &&
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen ((i > 0 && buf[i-1] == '\n') ||
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen (i > 1 && buf[i-1] == '\r' && buf[i-2] == '\n') ||
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen stream->istream.v_offset + i == rstream->hdr_offset)) {
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen rstream->body_offset = stream->istream.v_offset + i + 1;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen eoh_char = -1;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen }
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen if (buf[i] == *fromp) {
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen if (*++fromp == '\0') {
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen /* potential From-line, see if we have the
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen rest of the line buffered.
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen FIXME: if From-line is longer than input
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen buffer, we break. probably irrelevant.. */
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen i++;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen from_after_pos = i;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen from_start_pos = i - 6;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen if (from_start_pos > 0 &&
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen buf[from_start_pos-1] == '\r') {
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen /* CR also belongs to it. */
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen from_start_pos--;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen }
5c597df6aa8d81de4053c6986fab7739f3b44b20Timo Sirainen fromp = mbox_from;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen } else if (from_start_pos != (size_t)-1) {
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen /* we have the whole From-line here now.
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen See if it's a valid one. */
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen if (mbox_from_parse(buf + from_after_pos,
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen pos - from_after_pos,
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen &received_time,
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen &sender) == 0) {
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen /* yep, we stop here. */
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen rstream->next_received_time =
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen received_time;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen i_free(rstream->next_sender);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen rstream->next_sender = sender;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen stream->istream.eof = TRUE;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen handle_end_of_mail(rstream,
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen from_start_pos);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen break;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen }
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen from_start_pos = (size_t)-1;
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen }
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen } else {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen fromp = mbox_from;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (buf[i] == *fromp)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen fromp++;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen }
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen /* we want to go at least one byte further next time */
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen rstream->input_peak_offset = stream->istream.v_offset + i;
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen if (from_start_pos != (size_t)-1) {
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen /* we're waiting for the \n at the end of From-line */
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen new_pos = from_start_pos;
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen } else {
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen /* leave out the beginnings of potential From-line + CR */
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen new_pos = i - (fromp - mbox_from) - 1;
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen stream->buffer = buf;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen if (new_pos == stream->pos) {
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen if (stream->istream.eof || ret > 0)
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen return _read(stream);
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen i_assert(new_pos > 0);
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen ret = -2;
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen } else {
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen i_assert(new_pos > stream->pos);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen ret = new_pos - stream->pos;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen stream->pos = new_pos;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen return ret;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen}
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenstatic void _seek(struct _istream *stream, uoff_t v_offset,
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen int mark __attr_unused__)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen{
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen struct raw_mbox_istream *rstream = (struct raw_mbox_istream *)stream;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen stream->istream.v_offset = v_offset;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen stream->skip = stream->pos = 0;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen stream->buffer = NULL;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen rstream->input_peak_offset = 0;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen rstream->eof = FALSE;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen}
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainenstatic void _sync(struct _istream *stream)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen{
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen struct raw_mbox_istream *rstream = (struct raw_mbox_istream *)stream;
5494a6bc149da8f02fd25c0434a9d612ac33f659Timo Sirainen
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen i_stream_sync(rstream->input);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen rstream->istream.skip = 0;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen rstream->istream.pos = 0;
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen}
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainenstatic const struct stat *_stat(struct _istream *stream, int exact)
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen{
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen struct raw_mbox_istream *rstream = (struct raw_mbox_istream *)stream;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen return i_stream_stat(rstream->input, exact);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen}
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenstruct istream *i_stream_create_raw_mbox(pool_t pool, struct istream *input)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen{
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen struct raw_mbox_istream *rstream;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen i_stream_ref(input);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen rstream = p_new(pool, struct raw_mbox_istream, 1);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen rstream->input = input;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen rstream->body_offset = (uoff_t)-1;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen rstream->mail_size = (uoff_t)-1;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen rstream->received_time = (time_t)-1;
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen rstream->next_received_time = (time_t)-1;
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen rstream->istream.iostream.close = _close;
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen rstream->istream.iostream.destroy = _destroy;
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen rstream->istream.iostream.set_max_buffer_size = _set_max_buffer_size;
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen rstream->istream.read = _read;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen rstream->istream.seek = _seek;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen rstream->istream.sync = _sync;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen rstream->istream.stat = _stat;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return _i_stream_create(&rstream->istream, pool, -1,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen input->real_stream->abs_start_offset);
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen}
4a514fb20e04df397842cde11cc9ea92abfe9728Timo Sirainen
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainenstatic int istream_raw_mbox_is_valid_from(struct raw_mbox_istream *rstream)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen{
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const unsigned char *data;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen size_t size;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen time_t received_time;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen char *sender;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* minimal: "From x Thu Nov 29 22:33:52 2001" = 31 chars */
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (i_stream_read_data(rstream->input, &data, &size, 30) == -1)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return -1;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if ((size == 1 && data[0] == '\n') ||
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen (size == 2 && data[0] == '\r' && data[1] == '\n')) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* EOF */
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return TRUE;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (size > 31 && memcmp(data, "\nFrom ", 6) == 0) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen data += 6;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen size -= 6;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen } else if (size > 32 && memcmp(data, "\r\nFrom ", 7) == 0) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen data += 7;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen size -= 7;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen } else {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return FALSE;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen while (memchr(data, '\n', size) == NULL) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (i_stream_read_data(rstream->input, &data, &size, size) < 0)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen break;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (mbox_from_parse(data, size, &received_time, &sender) < 0)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return FALSE;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen rstream->next_received_time = received_time;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen i_free(rstream->next_sender);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen rstream->next_sender = sender;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return TRUE;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen}
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainenuoff_t istream_raw_mbox_get_start_offset(struct istream *stream)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen{
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen struct raw_mbox_istream *rstream =
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen (struct raw_mbox_istream *)stream->real_stream;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return rstream->from_offset;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen}
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenuoff_t istream_raw_mbox_get_header_offset(struct istream *stream)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen{
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen struct raw_mbox_istream *rstream =
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen (struct raw_mbox_istream *)stream->real_stream;
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen if (rstream->hdr_offset == rstream->from_offset)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen (void)_read(&rstream->istream);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen if (rstream->corrupted) {
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen i_error("Unexpectedly lost From-line at "
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen "%"PRIuUOFF_T, rstream->from_offset);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return (uoff_t)-1;
494a5de15db3b2806ab31d5ecc3e1c306ae14d06Timo Sirainen }
08ed4ab71fd2a4e800d9025a736f0f46b771ea90Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return rstream->hdr_offset;
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen}
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainenuoff_t istream_raw_mbox_get_body_offset(struct istream *stream)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen{
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen struct raw_mbox_istream *rstream =
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen (struct raw_mbox_istream *)stream->real_stream;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen uoff_t offset;
08ed4ab71fd2a4e800d9025a736f0f46b771ea90Timo Sirainen size_t pos;
08ed4ab71fd2a4e800d9025a736f0f46b771ea90Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (rstream->body_offset != (uoff_t)-1)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return rstream->body_offset;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen offset = stream->v_offset;
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen i_stream_seek(stream, rstream->hdr_offset);
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen while (rstream->body_offset == (uoff_t)-1) {
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen i_stream_get_data(stream, &pos);
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen i_stream_skip(stream, pos);
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen if (_read(&rstream->istream) < 0) {
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen if (rstream->corrupted) {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen i_error("Unexpectedly lost From-line at "
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen "%"PRIuUOFF_T, rstream->from_offset);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen } else {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen i_assert(rstream->body_offset != (uoff_t)-1);
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen }
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen break;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen i_stream_seek(stream, offset);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return rstream->body_offset;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen}
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenuoff_t istream_raw_mbox_get_body_size(struct istream *stream, uoff_t body_size)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen{
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen struct raw_mbox_istream *rstream =
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen (struct raw_mbox_istream *)stream->real_stream;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen const unsigned char *data;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen size_t size;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen i_assert(rstream->hdr_offset != (uoff_t)-1);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen i_assert(rstream->body_offset != (uoff_t)-1);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (rstream->mail_size != (uoff_t)-1) {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return rstream->mail_size -
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen (rstream->body_offset - rstream->hdr_offset);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (body_size != (uoff_t)-1) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen i_stream_seek(rstream->input, rstream->body_offset + body_size);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (istream_raw_mbox_is_valid_from(rstream) > 0) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen rstream->mail_size = body_size +
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen (rstream->body_offset - rstream->hdr_offset);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return body_size;
8f70c97f7ab7b7e1683ed5cfcd96721a899c2520Timo Sirainen }
8f70c97f7ab7b7e1683ed5cfcd96721a899c2520Timo Sirainen }
8f70c97f7ab7b7e1683ed5cfcd96721a899c2520Timo Sirainen
8f70c97f7ab7b7e1683ed5cfcd96721a899c2520Timo Sirainen /* have to read through the message body */
8f70c97f7ab7b7e1683ed5cfcd96721a899c2520Timo Sirainen while (i_stream_read_data(stream, &data, &size, 0) > 0)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen i_stream_skip(stream, size);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen i_assert(rstream->mail_size != (uoff_t)-1);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return rstream->mail_size -
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen (rstream->body_offset - rstream->hdr_offset);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen}
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainentime_t istream_raw_mbox_get_received_time(struct istream *stream)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen{
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen struct raw_mbox_istream *rstream =
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen (struct raw_mbox_istream *)stream->real_stream;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (rstream->received_time == (time_t)-1)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen (void)_read(&rstream->istream);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return rstream->received_time;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen}
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainenconst char *istream_raw_mbox_get_sender(struct istream *stream)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen{
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen struct raw_mbox_istream *rstream =
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen (struct raw_mbox_istream *)stream->real_stream;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (rstream->sender == NULL)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen (void)_read(&rstream->istream);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return rstream->sender == NULL ? "" : rstream->sender;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen}
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainenvoid istream_raw_mbox_next(struct istream *stream, uoff_t body_size)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen{
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen struct raw_mbox_istream *rstream =
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen (struct raw_mbox_istream *)stream->real_stream;
9b00ecffbe74fd864d0d72e6112ec53b86f619baTimo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen body_size = istream_raw_mbox_get_body_size(stream, body_size);
9b00ecffbe74fd864d0d72e6112ec53b86f619baTimo Sirainen rstream->mail_size = (uoff_t)-1;
9b00ecffbe74fd864d0d72e6112ec53b86f619baTimo Sirainen
9b00ecffbe74fd864d0d72e6112ec53b86f619baTimo Sirainen rstream->received_time = rstream->next_received_time;
9b00ecffbe74fd864d0d72e6112ec53b86f619baTimo Sirainen rstream->next_received_time = (time_t)-1;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen i_free(rstream->sender);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen rstream->sender = rstream->next_sender;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen rstream->next_sender = NULL;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen rstream->from_offset = rstream->body_offset + body_size;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen rstream->hdr_offset = rstream->from_offset;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen rstream->body_offset = (uoff_t)-1;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen if (stream->v_offset != rstream->from_offset)
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen i_stream_seek_mark(stream, rstream->from_offset);
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen i_stream_seek_mark(rstream->input, rstream->from_offset);
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen rstream->eof = FALSE;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen rstream->istream.istream.eof = FALSE;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen}
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenint istream_raw_mbox_seek(struct istream *stream, uoff_t offset)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen{
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen struct raw_mbox_istream *rstream =
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen (struct raw_mbox_istream *)stream->real_stream;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen int check;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen rstream->corrupted = FALSE;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen rstream->eof = FALSE;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen rstream->istream.istream.eof = FALSE;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (rstream->mail_size != (uoff_t)-1 &&
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen rstream->hdr_offset + rstream->mail_size == offset) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen istream_raw_mbox_next(stream, (uoff_t)-1);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return 0;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (offset == rstream->from_offset) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen /* back to beginning of current message */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen offset = rstream->hdr_offset;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen check = offset == 0;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen } else {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen rstream->body_offset = (uoff_t)-1;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen rstream->mail_size = (uoff_t)-1;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen rstream->received_time = (time_t)-1;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen rstream->next_received_time = (time_t)-1;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen i_free(rstream->sender);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen rstream->sender = NULL;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_free(rstream->next_sender);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen rstream->next_sender = NULL;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen rstream->from_offset = offset;
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen rstream->hdr_offset = offset;
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen check = TRUE;
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen }
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen i_stream_seek_mark(stream, offset);
cb933f0a570a9cef5c975eadb818aa6b1002a269Timo Sirainen i_stream_seek_mark(rstream->input, offset);
cb933f0a570a9cef5c975eadb818aa6b1002a269Timo Sirainen
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen if (check)
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen (void)_read(&rstream->istream);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return rstream->corrupted ? -1 : 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenint istream_raw_mbox_is_eof(struct istream *stream)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct raw_mbox_istream *rstream =
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen (struct raw_mbox_istream *)stream->real_stream;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen return rstream->eof;
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen}
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen