]> granicus.if.org Git - neomutt/commitdiff
Add database and schema initialization
authorKevin McCarthy <kevin@8t8.us>
Sat, 6 Jul 2019 21:01:13 +0000 (14:01 -0700)
committerRichard Russon <rich@flatcap.org>
Mon, 19 Aug 2019 23:14:27 +0000 (00:14 +0100)
Add mutt_mkdir() library function supporting recursive mkdir.

Co-authored-by: Richard Russon <rich@flatcap.org>
Makefile.autosetup
autocrypt/autocrypt.c
autocrypt/autocrypt.h
autocrypt/autocrypt_db.c [new file with mode: 0644]
autocrypt/autocrypt_private.h [new file with mode: 0644]
autocrypt/autocrypt_schema.c [new file with mode: 0644]
main.c

index 0dab42461409a02fcca8ded906c29612f93b75f8..f3ade963097bee9d974466e49ccbb694b41a923d 100644 (file)
@@ -96,7 +96,9 @@ ALLOBJS+=     $(NEOMUTTOBJS)
 # 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)
index 4e859efa876a803aebf64460c4a51b404a0b3fe9..fa8ff9187103b39669d65a7c40679cbb7ed6880e 100644 (file)
  */
 
 #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");
 }
index 6172203e13f555ef6c61c908afa9e933b141deaf..8cb6d543bd2f390157a3d5716724edd17e7c0d77 100644 (file)
 #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 */
diff --git a/autocrypt/autocrypt_db.c b/autocrypt/autocrypt_db.c
new file mode 100644 (file)
index 0000000..e0cc46e
--- /dev/null
@@ -0,0 +1,92 @@
+/**
+ * @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;
+}
diff --git a/autocrypt/autocrypt_private.h b/autocrypt/autocrypt_private.h
new file mode 100644 (file)
index 0000000..56a45aa
--- /dev/null
@@ -0,0 +1,32 @@
+/**
+ * @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 */
diff --git a/autocrypt/autocrypt_schema.c b/autocrypt/autocrypt_schema.c
new file mode 100644 (file)
index 0000000..756a886
--- /dev/null
@@ -0,0 +1,123 @@
+/**
+ * @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;
+}
diff --git a/main.c b/main.c
index 37c436ad70f694eea676bd67b732b486826f0040..9bf30e242ec06e5c4405373e3eef46e70b06c7ef 100644 (file)
--- a/main.c
+++ b/main.c
@@ -737,7 +737,8 @@ int main(int argc, char *argv[], char *envp[])
   /* Initialize crypto backends.  */
   crypt_init();
 #ifdef USE_AUTOCRYPT
-  mutt_autocrypt_init();
+  if (C_Autocrypt)
+    mutt_autocrypt_init(!(sendflags & SEND_BATCH));
 #endif
 
   if (new_magic)