dbox-file-fix.c revision d1ba8ecbb936ace90179d2292952546708d68f71
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi/* Copyright (c) 2009-2017 Dovecot authors, see the included COPYING file */
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi#define DBOX_MAIL_FILE_BROKEN_COPY_SUFFIX ".broken"
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi const unsigned char *data;
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi if (memcmp(hdr->magic_pre, DBOX_MAGIC_PRE, strlen(DBOX_MAGIC_PRE)) != 0)
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi if (hex2dec(hdr->message_size_hex, sizeof(hdr->message_size_hex)) == 0 &&
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi memcmp(hdr->message_size_hex, "0000000000000000", sizeof(hdr->message_size_hex)) != 0)
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomistatic bool memchr_nocontrol(const unsigned char *data, char chr,
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi unsigned int i;
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi for (i = 0; i < len; i++) {
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomidbox_file_match_post_magic(struct istream *input, bool input_full,
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi const unsigned char *data, *p;
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi if (memcmp(data, DBOX_MAGIC_POST, strlen(DBOX_MAGIC_POST)) != 0)
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi /* see if the metadata block looks valid */
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi switch (data[i]) {
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi /* these could contain anything */
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi /* no control chars */
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi /* unknown */
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi /* LF not found - try to find the end-of-metadata LF */
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi /* can't look any further - assume it's ok */
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomidbox_file_find_next_magic(struct dbox_file *file, uoff_t *offset_r, bool *pre_r)
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi /* We're scanning message bodies here, trying to find the beginning of
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi the next message. Although our magic strings are very unlikely to
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi be found in regular emails, they are much more likely when emails
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi are stored compressed.. So try to be sure we find the correct
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi magic markers. */
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi uoff_t orig_offset, pre_offset, post_offset, prev_offset;
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi need_bytes = strlen(DBOX_MAGIC_POST); prev_need_bytes = 0;
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi while ((ret = i_stream_read_bytes(input, &data, &size, need_bytes)) > 0 ||
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi /* search for the beginning of a potential pre/post magic */
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi if (magic == data && input->v_offset == orig_offset) {
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi /* beginning of the file */
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi /* PRE/POST block? leave \n */
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi match = dbox_file_match_pre_magic(input, &pre_offset, &need_bytes);
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi /* more data needed */
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi match = dbox_file_match_post_magic(input, ret == -2, &need_bytes);
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi /* more data needed */
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi if (ret <= 0) {
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomistream_copy(struct dbox_file *file, struct ostream *output,
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi input = i_stream_create_limit(file->input, count);
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi mail_storage_set_critical(&file->storage->storage,
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi mail_storage_set_critical(&file->storage->storage,
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi mail_storage_set_critical(&file->storage->storage,
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi "o_stream_send_istream(%s) copied only %"
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomistatic void dbox_file_skip_broken_header(struct dbox_file *file)
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi const unsigned char *data;
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi /* if there's LF close to our position, assume that the header ends
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi for (i = 0; i < size; i++) {
bool *have_guid_r)
const char *line;
bool has_nuls;
int ret;
if (start_offset > 0) {
if (ret <= 0) {
if (ret < 0)
if (ret <= 0)
if (ret <= 0)
if (write_header) {
if (ret < 0) {
if (ret < 0)
if (ret == 0)
if (!have_guid) {
return ret;
if (ret < 0)
if (ret < 0) {
if (!have_messages) {