int maildir_save_begin(struct mail_save_context *_ctx, struct istream *input) { struct maildir_save_context *ctx = (struct maildir_save_context *)_ctx; struct maildir_filename *mf; /* new mail, new failure state */ ctx->failed = FALSE; T_BEGIN { /* create a new file in tmp/ directory */ const char *fname; ctx->fd = maildir_create_tmp(ctx->mbox, ctx->tmpdir, &fname); if (ctx->fd == -1) ctx->failed = TRUE; else { if (ctx->mbox->storage->storage.set->mail_save_crlf) ctx->input = i_stream_create_crlf(input); else ctx->input = i_stream_create_lf(input); mf = maildir_save_add(_ctx, fname, NULL); if (_ctx->data.guid != NULL) { maildir_save_set_dest_basename(_ctx, mf, _ctx->data.guid); } } } T_END; if (!ctx->failed) { _ctx->data.output = o_stream_create_fd_file(ctx->fd, 0, FALSE); o_stream_cork(_ctx->data.output); ctx->last_save_finished = FALSE; } return ctx->failed ? -1 : 0; }
int dsync_mail_get_hdr_hash(struct mail *mail, const char **hdr_hash_r) { struct istream *hdr_input, *input; struct mailbox_header_lookup_ctx *hdr_ctx; struct md5_context md5_ctx; unsigned char md5_result[MD5_RESULTLEN]; const unsigned char *data; size_t size; int ret = 0; hdr_ctx = mailbox_header_lookup_init(mail->box, hashed_headers); ret = mail_get_header_stream(mail, hdr_ctx, &hdr_input); mailbox_header_lookup_unref(&hdr_ctx); if (ret < 0) return -1; input = i_stream_create_lf(hdr_input); md5_init(&md5_ctx); while (!i_stream_is_eof(input)) { if (i_stream_read_data(input, &data, &size, 0) == -1) break; if (size == 0) break; md5_update(&md5_ctx, data, size); i_stream_skip(input, size); } if (input->stream_errno != 0) ret = -1; i_stream_unref(&input); md5_final(&md5_ctx, md5_result); *hdr_hash_r = binary_to_hex(md5_result, sizeof(md5_result)); return ret; }
static struct istream * mbox_save_get_input_stream(struct mbox_save_context *ctx, struct istream *input) { struct istream *filter, *ret, *cache_input, *streams[3]; /* filter out unwanted headers and keep track of headers' MD5 sum */ filter = i_stream_create_header_filter(input, HEADER_FILTER_EXCLUDE | HEADER_FILTER_NO_CR | HEADER_FILTER_ADD_MISSING_EOH | HEADER_FILTER_END_BODY_WITH_LF, mbox_save_drop_headers, mbox_save_drop_headers_count, save_header_callback, ctx); if ((ctx->mbox->storage->storage.flags & MAIL_STORAGE_FLAG_KEEP_HEADER_MD5) != 0) { /* we're using MD5 sums to generate POP3 UIDLs. clients don't like it much if there are duplicates, so make sure that there can't be any by appending our own X-Delivery-ID header. */ const char *hdr; T_BEGIN { mbox_save_x_delivery_id(ctx); } T_END; hdr = ctx->x_delivery_id_header; streams[0] = i_stream_create_from_data(hdr, strlen(hdr)); streams[1] = filter; streams[2] = NULL; ret = i_stream_create_concat(streams); i_stream_unref(&filter); filter = ret; } /* convert linefeeds to wanted format */ ret = ctx->mbox->storage->storage.set->mail_save_crlf ? i_stream_create_crlf(filter) : i_stream_create_lf(filter); i_stream_unref(&filter); if (ctx->ctx.dest_mail != NULL) { /* caching creates a tee stream */ cache_input = index_mail_cache_parse_init(ctx->ctx.dest_mail, ret); i_stream_unref(&ret); ret = cache_input; } return ret; }
void dbox_save_begin(struct dbox_save_context *ctx, struct istream *input) { struct mail_save_context *_ctx = &ctx->ctx; struct mail_storage *_storage = _ctx->transaction->box->storage; struct dbox_storage *storage = (struct dbox_storage *)_storage; struct dbox_message_header dbox_msg_hdr; struct istream *crlf_input; dbox_save_add_to_index(ctx); if (_ctx->dest_mail == NULL) { if (ctx->mail == NULL) ctx->mail = mail_alloc(_ctx->transaction, 0, NULL); _ctx->dest_mail = ctx->mail; } mail_set_seq_saving(_ctx->dest_mail, ctx->seq); crlf_input = i_stream_create_lf(input); ctx->input = index_mail_cache_parse_init(_ctx->dest_mail, crlf_input); i_stream_unref(&crlf_input); /* write a dummy header. it'll get rewritten when we're finished */ memset(&dbox_msg_hdr, 0, sizeof(dbox_msg_hdr)); o_stream_cork(ctx->dbox_output); if (o_stream_send(ctx->dbox_output, &dbox_msg_hdr, sizeof(dbox_msg_hdr)) < 0) { mail_storage_set_critical(_storage, "write(%s) failed: %m", o_stream_get_name(ctx->dbox_output)); ctx->failed = TRUE; } _ctx->data.output = ctx->dbox_output; if (_ctx->data.received_date == (time_t)-1) _ctx->data.received_date = ioloop_time; index_attachment_save_begin(_ctx, storage->attachment_fs, ctx->input); }
static void test_istream_crlf_input(const char *input) { string_t *output; const unsigned char *data; size_t size = 0; ssize_t ret1, ret2; unsigned int i, j, pos, input_len = strlen(input); struct istream *istream, *crlf_istream; output = t_str_new(256); for (j = 0; j < 4; j++) { istream = i_stream_create_from_data(input, input_len); str_truncate(output, 0); if (j%2 == 0) { /* drop CRs */ crlf_istream = i_stream_create_lf(istream); for (i = 0; i < input_len; i++) { if (input[i] == '\r' && (i == input_len || input[i+1] == '\n')) ; else str_append_c(output, input[i]); } } else { /* add missing CRs */ crlf_istream = i_stream_create_crlf(istream); for (i = 0; i < input_len; i++) { if (input[i] == '\n' && (i == 0 || input[i-1] != '\r')) str_append_c(output, '\r'); str_append_c(output, input[i]); } } pos = 0; for (i = 1; i <= input_len; i++) { if (j >= 2) { i_stream_unref(&istream); i_stream_unref(&crlf_istream); istream = i_stream_create_from_data(input, input_len); crlf_istream = j%2 == 0 ? i_stream_create_lf(istream) : i_stream_create_crlf(istream); pos = 0; } istream->real_stream->pos = i; ret1 = i_stream_read(crlf_istream); if (crlf_istream->real_stream->buffer_size != 0) { /* this is pretty evil */ crlf_istream->real_stream->buffer_size = I_MAX(crlf_istream->real_stream->pos, i); } ret2 = i_stream_read(crlf_istream); data = i_stream_get_data(crlf_istream, &size); if (ret1 > 0 || ret2 > 0) { ret1 = I_MAX(ret1, 0) + I_MAX(ret2, 0); test_assert(pos + (unsigned int)ret1 == size); pos += ret1; } test_assert(memcmp(data, str_data(output), size) == 0); } test_assert(size == str_len(output)); i_stream_unref(&crlf_istream); i_stream_unref(&istream); } }