#include <netdb.h>
#include <assert.h>
+#include "unicode-util.h"
+
static const char toplevel_config_comment[] =
" .notmuch-config - Configuration file for the notmuch mail system\n"
"\n"
bool is_new;
char *database_path;
- char *crypto_gpg_path;
char *user_name;
char *user_primary_email;
const char **user_other_email;
char *name;
int e;
- pw_buf_size = sysconf(_SC_GETPW_R_SIZE_MAX);
+ pw_buf_size = sysconf (_SC_GETPW_R_SIZE_MAX);
if (pw_buf_size == -1) pw_buf_size = 64;
pw_buf = talloc_size (ctx, pw_buf_size);
while ((e = getpwuid_r (getuid (), &passwd, pw_buf,
- pw_buf_size, &ignored)) == ERANGE) {
- pw_buf_size = pw_buf_size * 2;
- pw_buf = talloc_zero_size(ctx, pw_buf_size);
+ pw_buf_size, &ignored)) == ERANGE) {
+ pw_buf_size = pw_buf_size * 2;
+ pw_buf = talloc_zero_size (ctx, pw_buf_size);
}
if (e == 0) {
char *name;
int e;
- pw_buf_size = sysconf(_SC_GETPW_R_SIZE_MAX);
+ pw_buf_size = sysconf (_SC_GETPW_R_SIZE_MAX);
if (pw_buf_size == -1) pw_buf_size = 64;
pw_buf = talloc_zero_size (ctx, pw_buf_size);
while ((e = getpwuid_r (getuid (), &passwd, pw_buf,
- pw_buf_size, &ignored)) == ERANGE) {
- pw_buf_size = pw_buf_size * 2;
- pw_buf = talloc_zero_size(ctx, pw_buf_size);
+ pw_buf_size, &ignored)) == ERANGE) {
+ pw_buf_size = pw_buf_size * 2;
+ pw_buf = talloc_zero_size (ctx, pw_buf_size);
}
if (e == 0)
GError *error = NULL;
bool ret = false;
- FILE *fp = fopen(config->filename, "r");
+ FILE *fp = fopen (config->filename, "r");
if (fp == NULL) {
if (errno == ENOENT) {
/* If create_new is true, then the caller is prepared for a
}
} else {
fprintf (stderr, "Error opening config file '%s': %s\n",
- config->filename, strerror(errno));
+ config->filename, strerror (errno));
}
goto out;
}
g_error_free (error);
-out:
+ out:
if (fp)
- fclose(fp);
+ fclose (fp);
if (config_str)
- talloc_free(config_str);
+ talloc_free (config_str);
return ret;
}
*
* If is_new_ret is NULL, then a "file not found" message will be
* printed to stderr and NULL will be returned.
-
+ *
* If is_new_ret is non-NULL then a default configuration will be
* returned and *is_new_ret will be set to 1 on return so that
* the caller can recognize this case.
*
- * These default configuration settings are determined as
- * follows:
+ * These default configuration settings are determined as
+ * follows:
*
* database_path: $MAILDIR, otherwise $HOME/mail
*
* user_name: $NAME variable if set, otherwise
* read from /etc/passwd
*
- * user_primary_mail: $EMAIL variable if set, otherwise
+ * user_primary_mail: $EMAIL variable if set, otherwise
* constructed from the username and
* hostname of the current machine.
*
int file_had_crypto_group;
notmuch_config_t *config = talloc_zero (ctx, notmuch_config_t);
+
if (config == NULL) {
fprintf (stderr, "Out of memory.\n");
return NULL;
}
-
+
talloc_set_destructor (config, notmuch_config_destructor);
/* non-zero defaults */
}
if (notmuch_config_get_new_tags (config, &tmp) == NULL) {
- const char *tags[] = { "unread", "inbox" };
+ const char *tags[] = { "unread", "inbox" };
notmuch_config_set_new_tags (config, tags, 2);
}
}
/* Close the given notmuch_config_t object, freeing all resources.
- *
+ *
* Note: Any changes made to the configuration are *not* saved by this
* function. To save changes, call notmuch_config_save before
* notmuch_config_close.
-*/
+ */
void
notmuch_config_close (notmuch_config_t *config)
{
const char *section, const char *key,
const char ***outlist, size_t *list_length, size_t *ret_length)
{
- assert(outlist);
+ assert (outlist);
/* read from config file and cache value, if not cached already */
if (*outlist == NULL) {
char **inlist = g_key_file_get_string_list (config->key_file,
- section, key, list_length, NULL);
+ section, key, list_length, NULL);
if (inlist) {
unsigned int i;
const char *
notmuch_config_get_database_path (notmuch_config_t *config)
{
- char *db_path = (char *)_config_get (config, &config->database_path, "database", "path");
+ char *db_path = (char *) _config_get (config, &config->database_path, "database", "path");
if (db_path && *db_path != '/') {
/* If the path in the configuration file begins with any
size_t length)
{
_config_set_list (config, "user", "other_email", list, length,
- &(config->user_other_email));
+ &(config->user_other_email));
}
void
notmuch_config_set_new_tags (notmuch_config_t *config,
- const char *list[],
- size_t length)
+ const char *list[],
+ size_t length)
{
_config_set_list (config, "new", "tags", list, length,
- &(config->new_tags));
+ &(config->new_tags));
}
void
size_t length)
{
_config_set_list (config, "new", "ignore", list, length,
- &(config->new_ignore));
+ &(config->new_ignore));
}
const char **
void
notmuch_config_set_search_exclude_tags (notmuch_config_t *config,
- const char *list[],
- size_t length)
+ const char *list[],
+ size_t length)
{
_config_set_list (config, "search", "exclude_tags", list, length,
&(config->search_exclude_tags));
*group = item;
period = strchr (item, '.');
- if (period == NULL || *(period+1) == '\0') {
+ if (period == NULL || *(period + 1) == '\0') {
fprintf (stderr,
"Invalid configuration name: %s\n"
"(Should be of the form <section>.<item>)\n", item);
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 {
+ const char *name;
+ bool in_db;
+ bool prefix;
+ bool (*validate)(const char *);
+} config_key_info_t;
+
+static struct config_key
+ config_key_table[] = {
+ { "index.decrypt", true, false, NULL },
+ { "index.header.", true, true, validate_field_name },
+ { "query.", true, true, NULL },
+};
+
+static config_key_info_t *
+_config_key_info (const char *item)
+{
+ for (size_t i = 0; i < ARRAY_SIZE (config_key_table); i++) {
+ if (config_key_table[i].prefix &&
+ strncmp (item, config_key_table[i].name,
+ strlen (config_key_table[i].name)) == 0)
+ return config_key_table + i;
+ if (strcmp (item, config_key_table[i].name) == 0)
+ return config_key_table + i;
+ }
+ return NULL;
+}
+
static bool
_stored_in_db (const char *item)
{
- const char * db_configs[] = {
- "index.decrypt",
- };
- if (STRNCMP_LITERAL (item, "query.") == 0)
- return true;
- for (size_t i = 0; i < ARRAY_SIZE (db_configs); i++)
- if (strcmp (item, db_configs[i]) == 0)
- return true;
- return false;
+ config_key_info_t *info;
+
+ info = _config_key_info (item);
+
+ return (info && info->in_db);
}
static int
-_print_db_config(notmuch_config_t *config, const char *name)
+_print_db_config (notmuch_config_t *config, const char *name)
{
notmuch_database_t *notmuch;
char *val;
notmuch_database_get_config (notmuch, name, &val)))
return EXIT_FAILURE;
- puts (val);
+ puts (val);
return EXIT_SUCCESS;
}
static int
notmuch_config_command_get (notmuch_config_t *config, char *item)
{
- if (strcmp(item, "database.path") == 0) {
+ if (strcmp (item, "database.path") == 0) {
printf ("%s\n", notmuch_config_get_database_path (config));
- } else if (strcmp(item, "user.name") == 0) {
+ } else if (strcmp (item, "user.name") == 0) {
printf ("%s\n", notmuch_config_get_user_name (config));
- } else if (strcmp(item, "user.primary_email") == 0) {
+ } else if (strcmp (item, "user.primary_email") == 0) {
printf ("%s\n", notmuch_config_get_user_primary_email (config));
- } else if (strcmp(item, "user.other_email") == 0) {
+ } else if (strcmp (item, "user.other_email") == 0) {
const char **other_email;
size_t i, length;
-
+
other_email = notmuch_config_get_user_other_email (config, &length);
for (i = 0; i < length; i++)
printf ("%s\n", other_email[i]);
- } else if (strcmp(item, "new.tags") == 0) {
+ } else if (strcmp (item, "new.tags") == 0) {
const char **tags;
size_t i, length;
}
static int
-_set_db_config(notmuch_config_t *config, const char *key, int argc, char **argv)
+_set_db_config (notmuch_config_t *config, const char *key, int argc, char **argv)
{
notmuch_database_t *notmuch;
const char *val = "";
notmuch_config_command_set (notmuch_config_t *config, char *item, int argc, char *argv[])
{
char *group, *key;
+ config_key_info_t *key_info;
if (STRNCMP_LITERAL (item, BUILT_WITH_PREFIX) == 0) {
fprintf (stderr, "Error: read only option: %s\n", item);
return 1;
}
- if (_stored_in_db (item)) {
+ key_info = _config_key_info (item);
+ if (key_info && key_info->validate && (! key_info->validate (item)))
+ return 1;
+
+ if (key_info && key_info->in_db) {
return _set_db_config (config, item, argc, argv);
}
void
_notmuch_config_list_built_with ()
{
- printf("%scompact=%s\n",
- BUILT_WITH_PREFIX,
- notmuch_built_with ("compact") ? "true" : "false");
- printf("%sfield_processor=%s\n",
- BUILT_WITH_PREFIX,
- notmuch_built_with ("field_processor") ? "true" : "false");
- printf("%sretry_lock=%s\n",
- BUILT_WITH_PREFIX,
- notmuch_built_with ("retry_lock") ? "true" : "false");
+ printf ("%scompact=%s\n",
+ BUILT_WITH_PREFIX,
+ notmuch_built_with ("compact") ? "true" : "false");
+ printf ("%sfield_processor=%s\n",
+ BUILT_WITH_PREFIX,
+ notmuch_built_with ("field_processor") ? "true" : "false");
+ printf ("%sretry_lock=%s\n",
+ BUILT_WITH_PREFIX,
+ notmuch_built_with ("retry_lock") ? "true" : "false");
}
static int
return EXIT_FAILURE;
for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) {
- printf("%s=%s\n", notmuch_config_list_key (list), notmuch_config_list_value(list));
+ printf ("%s=%s\n", notmuch_config_list_key (list), notmuch_config_list_value (list));
}
notmuch_config_list_destroy (list);
- return EXIT_SUCCESS;
+ return EXIT_SUCCESS;
}
static int
notmuch_requested_db_uuid);
/* skip at least subcommand argument */
- argc-= opt_index;
- argv+= opt_index;
+ argc -= opt_index;
+ argv += opt_index;
if (argc < 1) {
fprintf (stderr, "Error: notmuch config requires at least one argument.\n");