* Actually parse a maildir message. This may also be used to fill
* out a fake header structure generated by lazy maildir parsing.
*/
-HEADER *maildir_parse_message (int magic, const char *fname,
+HEADER *maildir_parse_stream (int magic, FILE *f, const char *fname,
int is_old, HEADER * _h)
{
- FILE *f;
HEADER *h = _h;
struct stat st;
- if ((f = fopen (fname, "r")) != NULL)
- {
- if (!h)
- h = mutt_new_header ();
- h->env = mutt_read_rfc822_header (f, h, 0, 0);
+ if (!h)
+ h = mutt_new_header ();
+ h->env = mutt_read_rfc822_header (f, h, 0, 0);
- fstat (fileno (f), &st);
- safe_fclose (&f);
+ fstat (fileno (f), &st);
- if (!h->received)
- h->received = h->date_sent;
+ if (!h->received)
+ h->received = h->date_sent;
- /* always update the length since we have fresh information available. */
- h->content->length = st.st_size - h->content->offset;
+ /* always update the length since we have fresh information available. */
+ h->content->length = st.st_size - h->content->offset;
- h->index = -1;
+ h->index = -1;
- if (magic == M_MAILDIR)
- {
- /*
- * maildir stores its flags in the filename, so ignore the
- * flags in the header of the message
- */
+ if (magic == M_MAILDIR)
+ {
+ /*
+ * maildir stores its flags in the filename, so ignore the
+ * flags in the header of the message
+ */
- h->old = is_old;
- maildir_parse_flags (h, fname);
- }
+ h->old = is_old;
+ maildir_parse_flags (h, fname);
+ }
+ return h;
+}
+
+/*
+ * Actually parse a maildir message. This may also be used to fill
+ * out a fake header structure generated by lazy maildir parsing.
+ */
+HEADER *maildir_parse_message (int magic, const char *fname,
+ int is_old, HEADER * h)
+{
+ FILE *f;
+
+ if ((f = fopen (fname, "r")) != NULL) {
+ h = maildir_parse_stream (magic, f, fname, is_old, h);
+ safe_fclose (&f);
return h;
}
return NULL;
*/
static FILE *_maildir_open_find_message (const char *folder, const char *unique,
- const char *subfolder)
+ const char *subfolder, char **newname)
{
char dir[_POSIX_PATH_MAX];
char tunique[_POSIX_PATH_MAX];
closedir (dp);
+ if (newname && fp)
+ *newname = safe_strdup(fname);
+
errno = oe;
return fp;
}
-FILE *maildir_open_find_message (const char *folder, const char *msg)
+FILE *maildir_open_find_message (const char *folder, const char *msg,
+ char **newname)
{
char unique[_POSIX_PATH_MAX];
FILE *fp;
if (
(fp =
_maildir_open_find_message (folder, unique,
- new_hits > cur_hits ? "new" : "cur"))
+ new_hits > cur_hits ? "new" : "cur",
+ newname))
|| errno != ENOENT)
{
if (new_hits < UINT_MAX && cur_hits < UINT_MAX)
if (
(fp =
_maildir_open_find_message (folder, unique,
- new_hits > cur_hits ? "cur" : "new"))
+ new_hits > cur_hits ? "cur" : "new",
+ newname))
|| errno != ENOENT)
{
if (new_hits < UINT_MAX && cur_hits < UINT_MAX)
struct nm_hdrdata {
char *folder;
char *tags;
+ char *oldpath;
int magic;
};
struct uri_tag *query_items;
};
-
static void url_free_tags(struct uri_tag *tags)
{
while (tags) {
dprint(2, (debugfile, "nm: freeing header %p\n", data));
FREE(&data->folder);
FREE(&data->tags);
+ FREE(&data->oldpath);
FREE(&data);
}
return 1;
}
+static char *get_folder_from_path(const char *path)
+{
+ char *p = strrchr(path, '/');
+
+ if (p && p - path > 3 &&
+ (strncmp(p - 3, "cur", 3) == 0 ||
+ strncmp(p - 3, "new", 3) == 0 ||
+ strncmp(p - 3, "tmp", 3) == 0)) {
+
+ p -= 3;
+ return strndup(path, p - path - 1);
+ }
+
+ return NULL;
+}
+
static void deinit_header(HEADER *h)
{
if (h) {
static void append_message(CONTEXT *ctx, notmuch_message_t *msg)
{
const char *path = notmuch_message_get_filename(msg);
- HEADER *h;
+ char *newpath = NULL;
+ HEADER *h = NULL;
if (!path)
return;
if (ctx->msgcount >= ctx->hdrmax)
mx_alloc_memory(ctx);
- h = maildir_parse_message(M_MAILDIR, path, 0, NULL);
- if (!h)
- return;
+ if (access(path, F_OK) == 0)
+ h = maildir_parse_message(M_MAILDIR, path, 0, NULL);
+ else {
+ /* maybe moved try find it... */
+ char *folder = get_folder_from_path(path);
- if (init_header(h, path, msg) != 0) {
+ if (folder) {
+ FILE *f = maildir_open_find_message(folder, path, &newpath);
+ if (f) {
+ h = maildir_parse_stream(M_MAILDIR, f, path, 0, NULL);
+ fclose(f);
+
+ dprint(1, (debugfile, "nm: not up-to-date: %s -> %s\n",
+ path, newpath));
+ }
+ }
+ FREE(&folder);
+ }
+
+ if (!h) {
+ dprint(1, (debugfile, "nm: failed to parse message: %s\n", path));
+ goto done;
+ }
+ if (init_header(h, newpath ? newpath : path, msg) != 0) {
mutt_free_header(&h);
dprint(1, (debugfile, "nm: failed to append header!\n"));
- return;
+ goto done;
}
h->active = 1;
- h->content->hdr_offset;
ctx->hdrs[ctx->msgcount] = h;
ctx->msgcount++;
+
+ if (newpath) {
+ /* remember that file has been moved -- nm_sync() will update the DB */
+ struct nm_hdrdata *hd = (struct nm_hdrdata *) h->data;
+ if (hd)
+ hd->oldpath = safe_strdup(path);
+ }
+done:
+ FREE(&newpath);
}
int nm_read_query(CONTEXT *ctx)
*old = *new = '\0';
- nm_header_get_fullpath(h, old, sizeof(old));
+ if (hd->oldpath) {
+ strncpy(old, hd->oldpath, sizeof(old));
+ old[sizeof(old) - 1] = '\0';
+ } else
+ nm_header_get_fullpath(h, old, sizeof(old));
ctx->path = hd->folder;
ctx->magic = hd->magic;
changed = 1;
}
}
+
+ FREE(&hd->oldpath);
}
ctx->path = uri;
if ((msg->fp = fopen (path, "r")) == NULL && errno == ENOENT &&
(ctx->magic == M_MAILDIR || ctx->magic == M_NOTMUCH))
- msg->fp = maildir_open_find_message (folder, cur->path);
+ msg->fp = maildir_open_find_message (folder, cur->path, NULL);
if (msg->fp == NULL)
{
int maildir_check_empty (const char *);
HEADER *maildir_parse_message (int magic, const char *fname, int is_old, HEADER * _h);
+HEADER *maildir_parse_stream (int magic, FILE *f, const char *fname, int is_old, HEADER * _h);
void maildir_parse_flags (HEADER * h, const char *path);
void maildir_update_flags (CONTEXT *ctx, HEADER *o, HEADER *n);
int maildir_open_new_message (MESSAGE *, CONTEXT *, HEADER *);
int mh_open_new_message (MESSAGE *, CONTEXT *, HEADER *);
-FILE *maildir_open_find_message (const char *, const char *);
+FILE *maildir_open_find_message (const char *, const char *, char **);
int mbox_strict_cmp_headers (const HEADER *, const HEADER *);
int mutt_reopen_mailbox (CONTEXT *, int *);