diff --git a/notmuch-config.c b/notmuch-config.c index d26277f6..b7f0784f 100644 --- a/notmuch-config.c +++ b/notmuch-config.c @@ -24,6 +24,8 @@ #include #include +#include "unicode-util.h" + static const char toplevel_config_comment[] = " .notmuch-config - Configuration file for the notmuch mail system\n" "\n" @@ -790,6 +792,43 @@ _item_split (char *item, char **group, char **key) return 0; } +/* These are more properly called Xapian fields, but the user facing + docs call them prefixes, so make the error message match */ +static bool +validate_field_name (const char *str) +{ + const char *key; + + if (! g_utf8_validate (str, -1, NULL)) { + fprintf (stderr, "Invalid utf8: %s\n", str); + return false; + } + + key = g_utf8_strrchr (str, -1, '.'); + if (! key ) { + INTERNAL_ERROR ("Impossible code path on input: %s\n", str); + } + + key++; + + if (! *key) { + fprintf (stderr, "Empty prefix name: %s\n", str); + return false; + } + + if (! unicode_word_utf8 (key)) { + fprintf (stderr, "Non-word character in prefix name: %s\n", key); + return false; + } + + if (key[0] >= 'a' && key[0] <= 'z') { + fprintf (stderr, "Prefix names starting with lower case letters are reserved: %s\n", key); + return false; + } + + return true; +} + #define BUILT_WITH_PREFIX "built_with." typedef struct config_key { @@ -802,7 +841,7 @@ typedef struct config_key { static struct config_key config_key_table[] = { {"index.decrypt", true, false, NULL}, - {"index.header.", true, true, NULL}, + {"index.header.", true, true, validate_field_name}, {"query.", true, true, NULL}, }; diff --git a/test/T750-user-header.sh b/test/T750-user-header.sh index 75fb1635..b97b00b6 100755 --- a/test/T750-user-header.sh +++ b/test/T750-user-header.sh @@ -15,6 +15,36 @@ notmuch search '*' | notmuch_search_sanitize > initial-threads notmuch search --output=messages '*' > initial-message-ids notmuch dump > initial-dump +test_begin_subtest "adding illegal prefix name, bad utf8" +notmuch config set index.header.$'\xFF' "List-Id" 2>&1 | sed 's/:.*$//' >OUTPUT +cat < EXPECTED +Invalid utf8 +EOF +test_expect_equal_file EXPECTED OUTPUT + +test_begin_subtest "adding illegal prefix name, reserved for notmuch" +notmuch config set index.header.list "List-Id" 2>OUTPUT +cat < EXPECTED +Prefix names starting with lower case letters are reserved: list +EOF +test_expect_equal_file EXPECTED OUTPUT + +test_begin_subtest "adding illegal prefix name, non-word character." +notmuch config set index.header.l:st "List-Id" 2>OUTPUT +cat < EXPECTED +Non-word character in prefix name: l:st +EOF +test_expect_equal_file EXPECTED OUTPUT + +test_begin_subtest "adding empty prefix name." +notmuch config set index.header. "List-Id" 2>OUTPUT +Non-word character in prefix name: l:st +cat < EXPECTED +Empty prefix name: index.header. +EOF +test_expect_equal_file EXPECTED OUTPUT + + test_begin_subtest "adding user header" test_expect_code 0 "notmuch config set index.header.List \"List-Id\""