Add mutt_mkdir() library function supporting recursive mkdir.
Co-authored-by: Richard Russon <rich@flatcap.org>
# libautocrypt
@if USE_AUTOCRYPT
LIBAUTOCRYPT= libautocrypt.a
-LIBAUTOCRYPTOBJS= autocrypt/autocrypt.o
+LIBAUTOCRYPTOBJS= autocrypt/autocrypt.o \
+ autocrypt/autocrypt_db.o \
+ autocrypt/autocrypt_schema.o
CLEANFILES+= $(LIBAUTOCRYPT) $(LIBAUTOCRYPTOBJS)
MUTTLIBS+= $(LIBAUTOCRYPT)
ALLOBJS+= $(LIBAUTOCRYPTOBJS)
*/
#include "config.h"
-
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "autocrypt_private.h"
#include "mutt.h"
#include "autocrypt.h"
+#include "curs_lib.h"
+#include "globals.h"
-void mutt_autocrypt_init(void)
+static int autocrypt_dir_init(int can_create)
{
+ int rv = 0;
+ struct stat sb;
+ struct Buffer *prompt = NULL;
+
+ if (!stat(C_AutocryptDir, &sb))
+ return 0;
+
+ if (!can_create)
+ return -1;
+
+ prompt = mutt_buffer_pool_get();
+ mutt_buffer_printf(prompt, _("%s does not exist. Create it?"), C_AutocryptDir);
+ if (mutt_yesorno(mutt_b2s(prompt), MUTT_YES) == MUTT_YES)
+ {
+ if (mutt_file_mkdir(C_AutocryptDir, S_IRWXU) < 0)
+ {
+ mutt_error(_("Can't create %s: %s."), C_AutocryptDir, strerror(errno));
+ rv = -1;
+ }
+ }
+
+ mutt_buffer_pool_release(&prompt);
+ return rv;
+}
+
+int mutt_autocrypt_init(int can_create)
+{
+ if (AutocryptDB)
+ return 0;
+
+ if (!C_Autocrypt || !C_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?
+ */
mutt_debug(LL_DEBUG1, "In mutt_autocrypt_init()\n");
+ return 0;
+
+bail:
+ C_Autocrypt = false;
+ mutt_autocrypt_db_close();
+ return -1;
}
void mutt_autocrypt_cleanup(void)
{
+ mutt_autocrypt_db_close();
mutt_debug(LL_DEBUG1, "In mutt_autocrypt_cleanup()\n");
}
#ifndef MUTT_AUTOCRYPT_AUTOCRYPT_H
#define MUTT_AUTOCRYPT_AUTOCRYPT_H
-void mutt_autocrypt_init (void);
+#include <sqlite3.h>
+#include "where.h"
+
+WHERE sqlite3 *AutocryptDB;
+
+int mutt_autocrypt_init (int);
void mutt_autocrypt_cleanup (void);
#endif /* MUTT_AUTOCRYPT_AUTOCRYPT_H */
--- /dev/null
+/**
+ * @file
+ * XXX
+ *
+ * @authors
+ * Copyright (C) 2019 Kevin J. McCarthy <kevin@8t8.us>
+ *
+ * @copyright
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "autocrypt_private.h"
+#include "mutt.h"
+#include "autocrypt.h"
+#include "globals.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);
+ return -1;
+ }
+ return mutt_autocrypt_schema_init();
+}
+
+int mutt_autocrypt_db_init(int can_create)
+{
+ int rv = -1;
+ struct Buffer *db_path = NULL;
+ struct stat sb;
+
+ if (AutocryptDB)
+ return 0;
+
+ if (!C_Autocrypt || !C_AutocryptDir)
+ return -1;
+
+ db_path = mutt_buffer_pool_get();
+ mutt_buffer_concat_path(db_path, C_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));
+ 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
+/**
+ * @file
+ * XXX
+ *
+ * @authors
+ * Copyright (C) 2019 Kevin J. McCarthy <kevin@8t8.us>
+ *
+ * @copyright
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUTT_AUTOCRYPT_AUTOCRYPT_PRIVATE_H
+#define MUTT_AUTOCRYPT_AUTOCRYPT_PRIVATE_H
+
+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 /* MUTT_AUTOCRYPT_AUTOCRYPT_PRIVATE_H */
--- /dev/null
+/**
+ * @file
+ * XXX
+ *
+ * @authors
+ * Copyright (C) 2019 Kevin J. McCarthy <kevin@8t8.us>
+ *
+ * @copyright
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include "autocrypt_private.h"
+#include "mutt.h"
+#include "autocrypt.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)
+ {
+ mutt_debug(LL_DEBUG1, "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"));
+ 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;
+}
/* Initialize crypto backends. */
crypt_init();
#ifdef USE_AUTOCRYPT
- mutt_autocrypt_init();
+ if (C_Autocrypt)
+ mutt_autocrypt_init(!(sendflags & SEND_BATCH));
#endif
if (new_magic)