#include "dbox-storage.h"
#include "../maildir/maildir-storage.h"
#include "../maildir/maildir-filename.h"
+#include "dbox-index.h"
#include "dbox-file.h"
#include "dbox-file-maildir.h"
return str_c(str);
}
+static const char *
+dbox_file_maildir_get_old_metadata(struct dbox_file *file, char key)
+{
+ struct dbox_index_record *rec;
+ const char *p, *end;
+
+ rec = dbox_index_record_lookup(file->mbox->dbox_index, file->file_id);
+ if (rec == NULL)
+ return NULL;
+
+ for (p = strchr(rec->data, ' '); *p != '\0'; p++) {
+ if (*p == ' ') {
+ if (p[1] == key) {
+ end = strchr(p+2, ' ');
+ return t_strdup_until(p+2, end);
+ }
+ if (p[1] == ':')
+ break;
+ }
+ }
+ return NULL;
+}
+
const char *dbox_file_maildir_metadata_get(struct dbox_file *file,
enum dbox_metadata_key key)
{
MAILDIR_EXTRA_VIRTUAL_SIZE,
&size))
value = dec2str(size);
+ else
+ value = dbox_file_maildir_get_old_metadata(file, 'W');
break;
case DBOX_METADATA_POP3_UIDL:
+ value = dbox_file_maildir_get_old_metadata(file, 'P');
+ break;
case DBOX_METADATA_EXPUNGED:
case DBOX_METADATA_EXT_REF:
case DBOX_METADATA_SPACE:
rec = dbox_index_record_lookup(mbox->dbox_index, file_id);
if (rec != NULL && rec->status == DBOX_INDEX_FILE_STATUS_MAILDIR) {
- /* data contains <uid> <filename> */
+ /* data contains <uid> [<fields>] :<filename> */
*maildir_file_r = TRUE;
- p = strchr(rec->data, ' ');
- return i_strdup_printf("%s", p + 1);
+ p = strstr(rec->data, " :");
+ i_assert(p != NULL);
+ return i_strdup_printf("%s", p + 2);
}
return i_strdup_printf(DBOX_MAIL_FILE_MULTI_FORMAT, file_id);
static int dbox_index_parse_maildir(struct dbox_index *index, const char *line,
struct dbox_index_record *rec)
{
- char *p;
+ char *p, *p2;
unsigned long uid;
if (*line++ != ' ')
if (*p++ != ' ' || *p == '\0' || uid == 0 || uid >= (uint32_t)-1)
return -1;
- rec->data = p_strdup(index->record_data_pool, line);
+ p2 = strstr(p, " :");
+ if (p2 != NULL)
+ rec->data = p_strdup(index->record_data_pool, line);
+ else {
+ /* convert to new format */
+ rec->data = p_strconcat(index->record_data_pool,
+ t_strdup_until(line, p), ":", p, NULL);
+ }
return 0;
}
array_append(&ctx->files, &file, 1);
}
+static const char *dbox_file_maildir_get_index_data(struct dbox_file *file)
+{
+ const char *pop3_uidl = NULL, *const *changes;
+ unsigned int i, count;
+
+ changes = array_get(&file->metadata_changes, &count);
+ for (i = 0; i < count; i++) {
+ if (*changes[i] == DBOX_METADATA_POP3_UIDL) {
+ pop3_uidl = changes[i] + 1;
+ break;
+ }
+ }
+
+ if (pop3_uidl == NULL) {
+ return t_strdup_printf("%u :%s", file->last_append_uid,
+ file->fname);
+ } else {
+ return t_strdup_printf("%u P%s :%s", file->last_append_uid,
+ pop3_uidl, file->fname);
+ }
+}
+
static int dbox_index_append_commit_new(struct dbox_index_append_context *ctx,
struct dbox_file *file, string_t *str)
{
rec.file_offset = ctx->output_offset + str_len(str);
if (file->maildir_file) {
rec.status = DBOX_INDEX_FILE_STATUS_MAILDIR;
- rec.data = p_strdup_printf(ctx->index->record_data_pool,
- "%u %s", file->last_append_uid,
- file->fname);
+ rec.data = p_strdup(ctx->index->record_data_pool,
+ dbox_file_maildir_get_index_data(file));
} else {
rec.status = dbox_file_can_append(file, 0) ?
DBOX_INDEX_FILE_STATUS_UNLINKED = 'U',
/* File is a maildir file. Status-specific data contains
- <uid> <filename>. */
+ old: <uid> <filename>
+ new: <uid> [<maildir extra field>] :<filename>
+ */
DBOX_INDEX_FILE_STATUS_MAILDIR = 'M'
};
{
uint32_t seq, uid;
uoff_t physical_size;
- const char *path;
+ const char *path, *value;
bool expunged;
int ret;
i_warning("%s: Ignoring broken file (metadata)", path);
return 0;
}
+ if (file->maildir_file) {
+ /* preserve POP3 UIDL */
+ value = maildir_uidlist_lookup_ext(ctx->maildir_uidlist, uid,
+ MAILDIR_UIDLIST_REC_EXT_POP3_UIDL);
+ if (value != NULL) {
+ dbox_file_metadata_set(file, DBOX_METADATA_POP3_UIDL,
+ value);
+ }
+ }
if (!expunged) {
mail_index_append(ctx->trans, uid, &seq);
file->maildir_append_seq = seq;