index-attachment.c revision 0482d891a6669537e10a1abc9866b45f2fc55fcc
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2010-2013 Dovecot authors, see the included COPYING file */
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic const char *index_attachment_dir_get(struct mail_storage *storage)
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainenstatic bool index_attachment_want(const struct istream_attachment_header *hdr,
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen apart.content_disposition = hdr->content_disposition;
cf64e39cef453f5a4704ea52b81b188ca411cb15Timo Sirainen /* don't treat text/ parts as attachments */
cf64e39cef453f5a4704ea52b81b188ca411cb15Timo Sirainen strncasecmp(hdr->content_type, "text/", 5) != 0;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainenstatic int index_attachment_open_temp_fd(void *context)
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen struct mail_storage *storage = ctx->transaction->box->storage;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen mail_user_set_get_temp_prefix(temp_path, storage->user->set);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen fd = safe_mkstemp_hostpid(temp_path, 0600, (uid_t)-1, (gid_t)-1);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen "safe_mkstemp(%s) failed: %m", str_c(temp_path));
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainenindex_attachment_open_ostream(struct istream_attachment_info *info,
0482d891a6669537e10a1abc9866b45f2fc55fccTimo Sirainen const char **error_r ATTR_UNUSED, void *context)
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen struct mail_save_attachment *attach = ctx->data.attach;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen struct mail_storage *storage = ctx->transaction->box->storage;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen const char *attachment_dir, *path, *digest = info->hash;
d11111fc5356108b6408a58b4ff1811d5b5678edTimo Sirainen if (storage->set->parsed_fsync_mode != FSYNC_MODE_NEVER)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen /* make sure we can access first 4 bytes without accessing
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen out of bounds memory */
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen digest = t_strconcat(digest, "\0\0\0\0", NULL);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen attachment_dir = index_attachment_dir_get(storage);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen path = t_strdup_printf("%s/%c%c/%c%c/%s-%s", attachment_dir,
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen attach->cur_file = fs_file_init(attach->fs, path,
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen extref = array_append_space(&attach->extrefs);
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen extref->base64_blocks_per_line = info->base64_blocks_per_line;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen extref->base64_have_crlf = info->base64_have_crlf;
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen *output_r = fs_write_stream(attach->cur_file);
0482d891a6669537e10a1abc9866b45f2fc55fccTimo Sirainenindex_attachment_close_ostream(struct ostream *output, bool success,
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen struct mail_save_attachment *attach = ctx->data.attach;
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen fs_write_stream_abort(attach->cur_file, &output);
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen else if (fs_write_stream_finish(attach->cur_file, &output) < 0) {
0482d891a6669537e10a1abc9866b45f2fc55fccTimo Sirainen *error_r = t_strdup(fs_file_last_error(attach->cur_file));
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainenvoid index_attachment_save_begin(struct mail_save_context *ctx,
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen struct mail_storage *storage = ctx->transaction->box->storage;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen if (*storage->set->mail_attachment_dir == '\0')
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen set.min_size = storage->set->mail_attachment_min_size;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen if (hash_format_init(storage->set->mail_attachment_hash,
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen /* we already checked this when verifying settings */
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen i_panic("mail_attachment_hash=%s unexpectedly failed: %s",
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen set.open_temp_fd = index_attachment_open_temp_fd;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen set.open_attachment_ostream = index_attachment_open_ostream;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen set.close_attachment_ostream = index_attachment_close_ostream;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen pool = pool_alloconly_create("save attachment", 1024);
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen attach = p_new(pool, struct mail_save_attachment, 1);
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen attach->input = i_stream_create_attachment_extractor(input, &set, ctx);
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen p_array_init(&attach->extrefs, attach->pool, 8);
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainenstatic int save_check_write_error(struct mail_storage *storage,
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen if (!mail_storage_set_error_from_errno(storage)) {
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen mail_storage_set_critical(storage, "write(%s) failed: %m",
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenint index_attachment_save_continue(struct mail_save_context *ctx)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen struct mail_storage *storage = ctx->transaction->box->storage;
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen struct mail_save_attachment *attach = ctx->data.attach;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen const unsigned char *data;
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen data = i_stream_get_data(attach->input, &size);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen index_mail_cache_parse_continue(ctx->dest_mail);
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen if (ret == 0 && !i_stream_attachment_extractor_can_retry(attach->input)) {
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen /* need more input */
0482d891a6669537e10a1abc9866b45f2fc55fccTimo Sirainen mail_storage_set_critical(storage, "read(%s) failed: %s",
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen if (save_check_write_error(storage, ctx->data.output) < 0)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenint index_attachment_save_finish(struct mail_save_context *ctx)
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen struct mail_save_attachment *attach = ctx->data.attach;
0482d891a6669537e10a1abc9866b45f2fc55fccTimo Sirainen return attach->input->stream_errno == 0 ? 0 : -1;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenvoid index_attachment_save_free(struct mail_save_context *ctx)
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen struct mail_save_attachment *attach = ctx->data.attach;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenindex_attachment_save_get_extrefs(struct mail_save_context *ctx)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenindex_attachment_delete_real(struct mail_storage *storage,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen path = t_strdup_printf("%s/%s", index_attachment_dir_get(storage), name);
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen file = fs_file_init(fs, path, FS_OPEN_MODE_READONLY);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen mail_storage_set_critical(storage, "%s", fs_last_error(fs));
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenint index_attachment_delete(struct mail_storage *storage,