Add mutt_mkdir() library function supporting recursive mkdir.
noinst_LIBRARIES = libautocrypt.a
-libautocrypt_a_SOURCES = autocrypt.c autocrypt.h
+libautocrypt_a_SOURCES = autocrypt.c autocrypt.h autocrypt_db.c autocrypt_private.h \
+ autocrypt_schema.c
#include "mutt.h"
#include "autocrypt.h"
+#include "autocrypt_private.h"
-void mutt_autocrypt_init (void)
+#include <errno.h>
+
+static int autocrypt_dir_init (int can_create)
{
+ int rv = 0;
+ struct stat sb;
+ BUFFER *prompt = NULL;
+
+ if (!stat (AutocryptDir, &sb))
+ return 0;
+
+ if (!can_create)
+ return -1;
+
+ prompt = mutt_buffer_pool_get ();
+ mutt_buffer_printf (prompt, _("%s does not exist. Create it?"), AutocryptDir);
+ if (mutt_yesorno (mutt_b2s (prompt), MUTT_YES) == MUTT_YES)
+ {
+ if (mutt_mkdir (AutocryptDir, 0700) < 0)
+ {
+ mutt_error ( _("Can't create %s: %s."), AutocryptDir, strerror (errno));
+ mutt_sleep (0);
+ rv = -1;
+ }
+ }
+
+ mutt_buffer_pool_release (&prompt);
+ return rv;
+}
+
+int mutt_autocrypt_init (int can_create)
+{
+ if (AutocryptDB)
+ return 0;
+
+ if (!option (OPTAUTOCRYPT) || !AutocryptDir)
+ return -1;
+
+ if (autocrypt_dir_init (can_create))
+ goto bail;
+
+ if (mutt_autocrypt_db_init (can_create))
+ goto bail;
+
+ /* mutt_autocrypt_gpgme_init()
+ * - init gpgme
+ * - create key if doesn't exist
+ * - perhaps should query account table and if empty do that?
+ */
dprint (1, (debugfile, "In mutt_autocrypt_init()\n"));
+ return 0;
+
+bail:
+ unset_option (OPTAUTOCRYPT);
+ mutt_autocrypt_db_close ();
+ return -1;
}
void mutt_autocrypt_cleanup (void)
{
+ mutt_autocrypt_db_close ();
dprint (1, (debugfile, "In mutt_autocrypt_cleanup()\n"));
}
#ifndef _AUTOCRYPT_H
#define _AUTOCRYPT_H 1
-void mutt_autocrypt_init (void);
+#include <sqlite3.h>
+
+WHERE sqlite3 *AutocryptDB;
+
+int mutt_autocrypt_init (int);
void mutt_autocrypt_cleanup (void);
#endif
--- /dev/null
+/*
+ * Copyright (C) 2019 Kevin J. McCarthy <kevin@8t8.us>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "mutt.h"
+#include "autocrypt.h"
+#include "autocrypt_private.h"
+
+static int autocrypt_db_create (const char *db_path)
+{
+ if (sqlite3_open_v2 (db_path,
+ &AutocryptDB,
+ SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE,
+ NULL) != SQLITE_OK)
+ {
+ mutt_error (_("Unable to open autocrypt database %s"), db_path);
+ mutt_sleep (0);
+ return -1;
+ }
+ return mutt_autocrypt_schema_init ();
+}
+
+int mutt_autocrypt_db_init (int can_create)
+{
+ int rv = -1;
+ BUFFER *db_path = NULL;
+ struct stat sb;
+
+ if (AutocryptDB)
+ return 0;
+
+ if (!option (OPTAUTOCRYPT) || !AutocryptDir)
+ return -1;
+
+ db_path = mutt_buffer_pool_get ();
+ mutt_buffer_concat_path (db_path, AutocryptDir, "autocrypt.db");
+ if (stat (mutt_b2s (db_path), &sb))
+ {
+ if (!can_create || autocrypt_db_create (mutt_b2s (db_path)))
+ goto cleanup;
+ }
+ else
+ {
+ if (sqlite3_open_v2 (mutt_b2s (db_path),
+ &AutocryptDB,
+ SQLITE_OPEN_READWRITE,
+ NULL) != SQLITE_OK)
+ {
+ mutt_error (_("Unable to open autocrypt database %s"), mutt_b2s (db_path));
+ mutt_sleep (0);
+ goto cleanup;
+ }
+ }
+
+ if (mutt_autocrypt_schema_update ())
+ goto cleanup;
+
+ rv = 0;
+
+cleanup:
+ mutt_buffer_pool_release (&db_path);
+ return rv;
+}
+
+void mutt_autocrypt_db_close (void)
+{
+ if (!AutocryptDB)
+ return;
+
+ /* TODO:
+ * call sqlite3_finalize () for each prepared statement
+ */
+
+ sqlite3_close_v2 (AutocryptDB);
+ AutocryptDB = NULL;
+}
--- /dev/null
+/*
+ * Copyright (C) 2019 Kevin J. McCarthy <kevin@8t8.us>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _AUTOCRYPT_PRIVATE_H
+#define _AUTOCRYPT_PRIVATE_H 1
+
+int mutt_autocrypt_db_init (int can_create);
+void mutt_autocrypt_db_close (void);
+
+int mutt_autocrypt_schema_init (void);
+int mutt_autocrypt_schema_update (void);
+
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2019 Kevin J. McCarthy <kevin@8t8.us>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "mutt.h"
+#include "autocrypt.h"
+#include "autocrypt_private.h"
+
+int mutt_autocrypt_schema_init (void)
+{
+ const char *schema;
+ char *errmsg = NULL;
+
+ schema =
+ "BEGIN TRANSACTION; "
+
+ "CREATE TABLE account ("
+ "email_addr text primary key not null, "
+ "keyid text, "
+ "keydata text, "
+ "prefer_encrypt int, "
+ "enabled int);"
+
+ "CREATE TABLE peer ("
+ "email_addr text primary key not null, "
+ "last_seen int, "
+ "autocrypt_timestamp int, "
+ "keyid text, "
+ "keydata text, "
+ "prefer_encrypt int, "
+ "gossip_timestamp int, "
+ "gossip_keyid text, "
+ "gossip_keydata text);"
+
+ "CREATE TABLE peer_history ("
+ "peer_email_addr text not null, "
+ "email_msgid text, "
+ "timestamp int, "
+ "keydata text);"
+
+ "CREATE INDEX peer_history_email "
+ "ON peer_history ("
+ "peer_email_addr);"
+
+ "CREATE TABLE gossip_history ("
+ "peer_email_addr text not null, "
+ "sender_email_addr text, "
+ "email_msgid text, "
+ "timestamp int, "
+ "gossip_keydata text);"
+
+ "CREATE INDEX gossip_history_email "
+ "ON gossip_history ("
+ "peer_email_addr);"
+
+ "CREATE TABLE schema ("
+ "version int);"
+
+ "INSERT into schema (version) values (1);"
+
+ "COMMIT TRANSACTION";
+
+ if (sqlite3_exec (AutocryptDB, schema, NULL, NULL, &errmsg) != SQLITE_OK)
+ {
+ dprint (1, (debugfile, "mutt_autocrypt_schema_init() returned %s\n", errmsg));
+ sqlite3_free (errmsg);
+ return -1;
+ }
+ return 0;
+}
+
+int mutt_autocrypt_schema_update (void)
+{
+ sqlite3_stmt *stmt = NULL;
+ int rv = -1, version;
+
+ if (sqlite3_prepare_v2 (
+ AutocryptDB,
+ "SELECT version FROM schema;",
+ -1,
+ &stmt,
+ NULL) != SQLITE_OK)
+ goto cleanup;
+
+ if (sqlite3_step (stmt) != SQLITE_ROW)
+ goto cleanup;
+
+ version = sqlite3_column_int (stmt, 0);
+
+ if (version > 1)
+ {
+ /* L10N:
+ The autocrypt database keeps track of schema version numbers.
+ This error occurs if the version number is too high.
+ Presumably because this is an old version of mutt and the
+ database was upgraded by a future version.
+ */
+ mutt_error _("Autocrypt database version is too new");
+ mutt_sleep (0);
+ goto cleanup;
+ }
+
+ /* TODO: schema version upgrades go here.
+ * Bump one by one, each update inside a transaction. */
+
+ rv = 0;
+
+cleanup:
+ sqlite3_finalize (stmt);
+ return rv;
+}
return (s);
}
+int mutt_mkdir (char *path, mode_t mode)
+{
+ struct stat sb;
+ char *s;
+ int rv = -1;
+
+ if (stat (path, &sb) >= 0)
+ return 0;
+
+ s = path;
+ do
+ {
+ s = strchr (s + 1, '/');
+ if (s)
+ *s = '\0';
+ if (stat (path, &sb) < 0)
+ {
+ if (errno != ENOENT)
+ goto cleanup;
+ if (mkdir (path, mode) < 0)
+ goto cleanup;
+ }
+ if (s)
+ *s = '/';
+ } while (s);
+
+ rv = 0;
+
+cleanup:
+ if (s)
+ *s = '/';
+
+ return rv;
+}
+
void mutt_unlink (const char *s)
{
int fd;
void mutt_remove_trailing_ws (char *);
void mutt_sanitize_filename (char *, short);
void mutt_str_replace (char **p, const char *s);
+int mutt_mkdir (char *path, mode_t mode);
void mutt_str_adjust (char **p);
void mutt_unlink (const char *);
void safe_free (void *);
/* Initialize crypto backends. */
crypt_init ();
#ifdef USE_AUTOCRYPT
- mutt_autocrypt_init ();
+ if (option (OPTAUTOCRYPT))
+ mutt_autocrypt_init (!(sendflags & SENDBATCH));
#endif
if (newMagic)