From 95dd5fe5d7e9cd8169a6e3174ea27376acd92870 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Thu, 11 Nov 2010 14:32:17 -0800 Subject: [PATCH] notmuch_message_tags_to_maildir_flags: Do nothing outside of "new" and "cur" Some people use notmuch with non-maildir files, (for example, email messages in MH format, or else cool things like using sluk[*] to suck down feeds into a format that notmuch can index). To better support uses like that, don't do any renaming for files that are not in a directory named either "new" or "cur". [*] https://github.com/krl/sluk/ --- lib/message.cc | 60 +++++++++++++++++++++++++++++++------------ lib/notmuch-private.h | 3 +++ lib/notmuch.h | 10 +++++--- test/maildir-sync | 2 +- 4 files changed, 55 insertions(+), 20 deletions(-) diff --git a/lib/message.cc b/lib/message.cc index b4bf0ce0..6d8b6c7a 100644 --- a/lib/message.cc +++ b/lib/message.cc @@ -945,20 +945,45 @@ maildir_get_new_flags(notmuch_message_t *message, char *flags) *p = '\0'; } -static char * -maildir_get_subdir (char *filename) +/* Is the given filename within a maildir directory? + * + * Specifically, is the final directory component of 'filename' either + * "cur" or "new". If so, return a pointer to that final directory + * component within 'filename'. If not, return NULL. + * + * A non-NULL return value is guaranteed to be a valid string pointer + * pointing to the characters "new/" or "cur/", (but not + * NUL-terminated). + */ +static const char * +_filename_is_in_maildir (const char *filename) { - char *p, *subdir = NULL; - - p = filename + strlen (filename) - 1; - while (p > filename + 3 && *p != '/') - p--; - if (*p == '/') { - subdir = p - 3; - if (subdir > filename && *(subdir - 1) != '/') - subdir = NULL; + const char *slash, *dir = NULL; + + /* Find the last '/' separating directory from filename. */ + slash = strrchr (filename, '/'); + if (slash == NULL) + return NULL; + + /* Jump back 4 characters to where the previous '/' will be if the + * directory is named "cur" or "new". */ + if (slash - filename < 4) + return NULL; + + slash -= 4; + + if (*slash != '/') + return NULL; + + dir = slash + 1; + + if (STRNCMP_LITERAL (dir, "cur/") == 0 || + STRNCMP_LITERAL (dir, "new/") == 0) + { + return dir; } - return subdir; + + return NULL; } /* XXX: Needs to ensure that existing, unsupported flags in the @@ -971,7 +996,7 @@ notmuch_message_tags_to_maildir_flags (notmuch_message_t *message) notmuch_filenames_t *filenames; char flags[ARRAY_SIZE(flag2tag)+1]; const char *filename, *p; - char *filename_new, *subdir = NULL; + char *filename_new, *dir; int ret; maildir_get_new_flags (message, flags); @@ -982,6 +1007,9 @@ notmuch_message_tags_to_maildir_flags (notmuch_message_t *message) { filename = notmuch_filenames_get (filenames); + if (! _filename_is_in_maildir (filename)) + continue; + p = strstr(filename, ":2,"); if ((p && strcmp (p+3, flags) == 0) || (!p && flags[0] == '\0')) @@ -1001,9 +1029,9 @@ notmuch_message_tags_to_maildir_flags (notmuch_message_t *message) filename_new[p-filename] = '\0'; /* If message is in new/ move it under cur/. */ - subdir = maildir_get_subdir (filename_new); - if (subdir && memcmp (subdir, "new/", 4) == 0) - memcpy (subdir, "cur/", 4); + dir = (char *) _filename_is_in_maildir (filename_new); + if (dir && STRNCMP_LITERAL (dir, "new/") == 0) + memcpy (dir, "cur/", 4); strcpy (filename_new+(p-filename), ":2,"); strcpy (filename_new+(p-filename)+3, flags); diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h index 37ccbb31..592cfb2b 100644 --- a/lib/notmuch-private.h +++ b/lib/notmuch-private.h @@ -57,6 +57,9 @@ NOTMUCH_BEGIN_DECLS #define COMPILE_TIME_ASSERT(pred) ((void)sizeof(char[1 - 2*!(pred)])) +#define STRNCMP_LITERAL(var, literal) \ + strncmp ((var), (literal), sizeof (literal) - 1) + /* There's no point in continuing when we've detected that we've done * something wrong internally (as opposed to the user passing in a * bogus value). diff --git a/lib/notmuch.h b/lib/notmuch.h index ea12fe76..d2deca1e 100644 --- a/lib/notmuch.h +++ b/lib/notmuch.h @@ -947,9 +947,13 @@ notmuch_message_maildir_flags_to_tags (notmuch_message_t *message); * * Specifically, for each filename corresponding to this message: * - * Rename the file so that its filename ends with the sequence ":2," - * followed by zero or more of the following single-character flags - * (in ASCII order): + * If the filename is not in a maildir directory, do nothing. + * (A maildir directory is determined as a directory named "new" or + * "cur".) + * + * If the filename is in a maildir directory, rename the file so that + * its filename ends with the sequence ":2," followed by zero or more + * of the following single-character flags (in ASCII order): * * 'D' iff the message has the "draft" tag * 'F' iff the message has the "flagged" tag diff --git a/test/maildir-sync b/test/maildir-sync index d3931a1f..df9351de 100755 --- a/test/maildir-sync +++ b/test/maildir-sync @@ -118,7 +118,7 @@ output+=$(notmuch search subject:"Message to lose maildir info" | notmuch_search test_expect_equal "$output" "No new mail. Detected 1 file rename. thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Message to lose maildir info (inbox)" -add_message [subject]='"Non-maildir message"' [dir]=notmaildir/new [filename]='non-maildir-message' +add_message [subject]='"Non-maildir message"' [dir]=notmaildir [filename]='non-maildir-message' expected=$(notmuch search --output=files subject:"Non-maildir message") test_expect_success "Can remove unread tag from message in non-maildir directory" 'notmuch tag -unread subject:"Non-maildir message"' -- 2.26.2