static int mdbox_file_read_metadata_hdr(struct dbox_file *file, struct dbox_metadata_header *meta_hdr_r) { const unsigned char *data; size_t size; int ret; ret = i_stream_read_data(file->input, &data, &size, sizeof(*meta_hdr_r)); if (ret <= 0) { i_assert(ret == -1); if (file->input->stream_errno == 0) { dbox_file_set_corrupted(file, "missing metadata"); return 0; } mail_storage_set_critical(&file->storage->storage, "read(%s) failed: %m", file->cur_path); return -1; } memcpy(meta_hdr_r, data, sizeof(*meta_hdr_r)); if (memcmp(meta_hdr_r->magic_post, DBOX_MAGIC_POST, sizeof(meta_hdr_r->magic_post)) != 0) { dbox_file_set_corrupted(file, "invalid metadata magic"); return 0; } i_stream_skip(file->input, sizeof(*meta_hdr_r)); return 1; }
static int dbox_file_parse_header(struct dbox_file *file, const char *line) { const char *const *tmp, *value; unsigned int pos; enum dbox_header_key key; file->file_version = *line - '0'; if (!i_isdigit(line[0]) || line[1] != ' ' || (file->file_version != 1 && file->file_version != DBOX_VERSION)) { dbox_file_set_corrupted(file, "Invalid dbox version"); return -1; } line += 2; pos = 2; file->msg_header_size = 0; for (tmp = t_strsplit(line, " "); *tmp != NULL; tmp++) { uintmax_t time; key = **tmp; value = *tmp + 1; switch (key) { case DBOX_HEADER_OLDV1_APPEND_OFFSET: break; case DBOX_HEADER_MSG_HEADER_SIZE: if (str_to_uint_hex(value, &file->msg_header_size) < 0) { dbox_file_set_corrupted(file, "Invalid message header size"); return -1; } break; case DBOX_HEADER_CREATE_STAMP: if (str_to_uintmax_hex(value, &time) < 0) { dbox_file_set_corrupted(file, "Invalid create time stamp"); return -1; } file->create_time = (time_t)time; break; } pos += strlen(value) + 2; } if (file->msg_header_size == 0) { dbox_file_set_corrupted(file, "Missing message header size"); return -1; } return 0; }
static int mdbox_file_metadata_copy(struct dbox_file *file, struct ostream *output) { struct dbox_metadata_header meta_hdr; const char *line; size_t buf_size; int ret; if ((ret = mdbox_file_read_metadata_hdr(file, &meta_hdr)) <= 0) return ret; o_stream_nsend(output, &meta_hdr, sizeof(meta_hdr)); buf_size = i_stream_get_max_buffer_size(file->input); /* use unlimited line length for metadata */ i_stream_set_max_buffer_size(file->input, (size_t)-1); while ((line = i_stream_read_next_line(file->input)) != NULL) { if (*line == '\0') { /* end of metadata */ break; } o_stream_nsend_str(output, line); o_stream_nsend(output, "\n", 1); } i_stream_set_max_buffer_size(file->input, buf_size); if (line == NULL) { dbox_file_set_corrupted(file, "missing end-of-metadata line"); return 0; } o_stream_nsend(output, "\n", 1); return 1; }
int dbox_mail_get_stream(struct mail *_mail, bool get_body ATTR_UNUSED, struct message_size *hdr_size, struct message_size *body_size, struct istream **stream_r) { struct dbox_storage *storage = (struct dbox_storage *)_mail->box->storage; struct dbox_mail *mail = (struct dbox_mail *)_mail; struct index_mail_data *data = &mail->imail.data; struct istream *input; uoff_t offset; int ret; if (data->stream == NULL) { if (storage->v.mail_open(mail, &offset, &mail->open_file) < 0) return -1; ret = get_mail_stream(mail, offset, &input); if (ret <= 0) { if (ret < 0) return -1; dbox_file_set_corrupted(mail->open_file, "uid=%u points to broken data at offset=" "%"PRIuUOFF_T, _mail->uid, offset); if (input != NULL) i_stream_unref(&input); return -1; } data->stream = input; index_mail_set_read_buffer_size(_mail, input); } return index_mail_init_stream(&mail->imail, hdr_size, body_size, stream_r); }
int dbox_attachment_file_get_stream(struct dbox_file *file, struct istream **stream) { const char *ext_refs, *error; int ret; /* need to read metadata in case there are external references */ if ((ret = dbox_file_metadata_read(file)) <= 0) return ret; i_stream_seek(file->input, file->cur_offset + file->msg_header_size); ext_refs = dbox_file_metadata_get(file, DBOX_METADATA_EXT_REF); if (ext_refs == NULL) return 1; /* we have external references. */ T_BEGIN { ret = dbox_attachment_file_get_stream_from(file, ext_refs, stream, &error); if (ret == 0) { dbox_file_set_corrupted(file, "Corrupted ext-refs metadata %s: %s", ext_refs, error); } } T_END; return ret; }
static int dbox_file_read_header(struct dbox_file *file) { const char *line; unsigned int hdr_size; int ret; i_stream_seek(file->input, 0); line = i_stream_read_next_line(file->input); if (line == NULL) { if (file->input->stream_errno == 0) { dbox_file_set_corrupted(file, "EOF while reading file header"); return 0; } dbox_file_set_syscall_error(file, "read()"); return -1; } hdr_size = file->input->v_offset; T_BEGIN { ret = dbox_file_parse_header(file, line) < 0 ? 0 : 1; } T_END; if (ret > 0) file->file_header_size = hdr_size; return ret; }