]> granicus.if.org Git - neomutt/commitdiff
Basic autocrypt account menu
authorKevin McCarthy <kevin@8t8.us>
Mon, 29 Jul 2019 02:24:11 +0000 (19:24 -0700)
committerRichard Russon <rich@flatcap.org>
Mon, 19 Aug 2019 23:14:27 +0000 (00:14 +0100)
Provide ability to create, delete, and toggle the prefer-encrypt and
enabled flag for an account.

Hook into the index via 'A' <autocrypt-acct-menu>.

Co-authored-by: Richard Russon <rich@flatcap.org>
15 files changed:
Makefile.autosetup
autocrypt/autocrypt.c
autocrypt/autocrypt.h
autocrypt/autocrypt_acct_menu.c [new file with mode: 0644]
autocrypt/autocrypt_db.c
autocrypt/autocrypt_private.h
doc/manual.xml.tail
functions.h
globals.h
index.c
init.h
keymap.c
keymap.h
opcodes.h
po/POTFILES.in

index b33cda8c8408cb87d084fa96ae398823d13a6e74..107638f7ad24edc611ee4dabbd7c3fce67590529 100644 (file)
@@ -97,9 +97,11 @@ ALLOBJS+=    $(NEOMUTTOBJS)
 @if USE_AUTOCRYPT
 LIBAUTOCRYPT=  libautocrypt.a
 LIBAUTOCRYPTOBJS=      autocrypt/autocrypt.o \
+                       autocrypt/autocrypt_acct_menu.o \
                        autocrypt/autocrypt_db.o \
                        autocrypt/autocrypt_gpgme.o \
                        autocrypt/autocrypt_schema.o
+
 CLEANFILES+=   $(LIBAUTOCRYPT) $(LIBAUTOCRYPTOBJS)
 MUTTLIBS+=     $(LIBAUTOCRYPT)
 ALLOBJS+=      $(LIBAUTOCRYPTOBJS)
index 7fb1dbadfc40c0c16fb4db0848f877bf9a127bc4..c7b6db8d52cccfc8465bae33095cd7dd841917fc 100644 (file)
@@ -104,8 +104,10 @@ void mutt_autocrypt_cleanup(void)
   mutt_autocrypt_db_close();
 }
 
-/* Creates a brand new account the first time autocrypt is initialized */
-int mutt_autocrypt_account_init(void)
+/* Creates a brand new account.
+ * This is used the first time autocrypt is initialized, and
+ * in the account menu. */
+int mutt_autocrypt_account_init(int prompt)
 {
   struct Address *addr = NULL;
   struct AutocryptAccount *account = NULL;
@@ -113,9 +115,11 @@ int mutt_autocrypt_account_init(void)
   int rc = -1;
   int prefer_encrypt = 0;
 
-  mutt_debug(LL_DEBUG1, "In mutt_autocrypt_account_init\n");
-  if (mutt_yesorno(_("Create an initial autocrypt account?"), MUTT_YES) != MUTT_YES)
-    return 0;
+  if (prompt)
+  {
+    if (mutt_yesorno(_("Create an initial autocrypt account?"), MUTT_YES) != MUTT_YES)
+      return 0;
+  }
 
   struct Buffer *keyid = mutt_buffer_pool_get();
   struct Buffer *keydata = mutt_buffer_pool_get();
index 6ca8a347af88efdd1f37a8b8970c99d83e616a2c..0b39830e3b8280659726dd2efc1d8fb1f6a53a05 100644 (file)
@@ -85,5 +85,6 @@ int mutt_autocrypt_set_sign_as_default_key (struct Email *hdr);
 int mutt_autocrypt_write_autocrypt_header (struct Envelope *env, FILE *fp);
 int mutt_autocrypt_write_gossip_headers (struct Envelope *env, FILE *fp);
 int mutt_autocrypt_generate_gossip_list (struct Email *hdr);
+void mutt_autocrypt_account_menu (void);
 
 #endif /* MUTT_AUTOCRYPT_AUTOCRYPT_H */
diff --git a/autocrypt/autocrypt_acct_menu.c b/autocrypt/autocrypt_acct_menu.c
new file mode 100644 (file)
index 0000000..07aa393
--- /dev/null
@@ -0,0 +1,285 @@
+/**
+ * @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 "address/lib.h"
+#include "mutt.h"
+#include "autocrypt.h"
+#include "curs_lib.h"
+#include "format_flags.h"
+#include "globals.h"
+#include "mutt_menu.h"
+#include "mutt_window.h"
+#include "muttlib.h"
+#include "opcodes.h"
+
+struct Entry
+{
+  int tagged; /* TODO */
+  int num;
+  struct AutocryptAccount *account;
+  struct Address *addr;
+};
+
+static const struct Mapping AutocryptAcctHelp[] = {
+  { N_("Exit"), OP_EXIT },
+  /* L10N: Autocrypt Account Menu Help line:
+     create new account
+  */
+  { N_("Create"), OP_AUTOCRYPT_CREATE_ACCT },
+  /* L10N: Autocrypt Account Menu Help line:
+     delete account
+  */
+  { N_("Delete"), OP_AUTOCRYPT_DELETE_ACCT },
+  /* L10N: Autocrypt Account Menu Help line:
+     toggle an account active/inactive
+  */
+  { N_("Tgl Active"), OP_AUTOCRYPT_TOGGLE_ACTIVE },
+  /* L10N: Autocrypt Account Menu Help line:
+     toggle "prefer-encrypt" on an account
+  */
+  { N_("Prf Enc"), OP_AUTOCRYPT_TOGGLE_PREFER },
+  { N_("Help"), OP_HELP },
+  { NULL, 0 }
+};
+
+static const char *account_format_str(char *dest, size_t destlen, size_t col, int cols,
+                                      char op, const char *src, const char *fmt,
+                                      const char *ifstring, const char *elsestring,
+                                      unsigned long data, MuttFormatFlags flags)
+{
+  struct Entry *entry = (struct Entry *) data;
+  char tmp[128];
+
+  switch (op)
+  {
+    case 'a':
+      mutt_format_s(dest, destlen, fmt, entry->addr->mailbox);
+      break;
+    case 'k':
+      mutt_format_s(dest, destlen, fmt, entry->account->keyid);
+      break;
+    case 'n':
+      snprintf(tmp, sizeof(tmp), "%%%sd", fmt);
+      snprintf(dest, destlen, tmp, entry->num);
+      break;
+    case 'p':
+      if (entry->account->prefer_encrypt)
+        /* L10N:
+           Autocrypt Account menu.
+           flag that an account has prefer-encrypt set
+        */
+        mutt_format_s(dest, destlen, fmt, _("prefer encrypt"));
+      else
+        /* L10N:
+           Autocrypt Account menu.
+           flag that an account has prefer-encrypt unset;
+           thus encryption will need to be manually enabled.
+        */
+        mutt_format_s(dest, destlen, fmt, _("manual encrypt"));
+      break;
+    case 's':
+      if (entry->account->enabled)
+        /* L10N:
+           Autocrypt Account menu.
+           flag that an account is enabled/active
+        */
+        mutt_format_s(dest, destlen, fmt, _("active"));
+      else
+        /* L10N:
+           Autocrypt Account menu.
+           flag that an account is disabled/inactive
+        */
+        mutt_format_s(dest, destlen, fmt, _("inactive"));
+      break;
+  }
+
+  return (src);
+}
+
+static void account_entry(char *s, size_t slen, struct Menu *m, int num)
+{
+  struct Entry *entry = &((struct Entry *) m->data)[num];
+
+  mutt_expando_format(s, slen, 0, MuttIndexWindow->cols,
+                      NONULL(C_AutocryptAcctFormat), account_format_str,
+                      (unsigned long) entry, MUTT_FORMAT_ARROWCURSOR);
+}
+
+static struct Menu *create_menu(void)
+{
+  struct Menu *menu = NULL;
+  struct AutocryptAccount **accounts = NULL;
+  struct Entry *entries = NULL;
+  int num_accounts = 0, i;
+  char *helpstr;
+
+  if (mutt_autocrypt_db_account_get_all(&accounts, &num_accounts) < 0)
+    return NULL;
+
+  menu = mutt_menu_new(MENU_AUTOCRYPT_ACCT);
+  menu->menu_make_entry = account_entry;
+  /* menu->tag = account_tag; */
+  /* L10N:
+     Autocrypt Account Management Menu title
+  */
+  menu->title = _("Autocrypt Accounts");
+  helpstr = mutt_mem_malloc(256);
+  menu->help = mutt_compile_help(helpstr, 256, MENU_AUTOCRYPT_ACCT, AutocryptAcctHelp);
+
+  menu->data = entries = mutt_mem_calloc(num_accounts, sizeof(struct Entry));
+  menu->max = num_accounts;
+
+  for (i = 0; i < num_accounts; i++)
+  {
+    entries[i].num = i + 1;
+    /* note: we are transfering the account pointer to the entries
+     * array, and freeing the accounts array below.  the account
+     * will be freed in free_menu().
+     */
+    entries[i].account = accounts[i];
+
+    entries[i].addr = mutt_addr_new();
+    entries[i].addr->mailbox = mutt_str_strdup(accounts[i]->email_addr);
+    mutt_addr_to_local(entries[i].addr);
+  }
+  FREE(&accounts);
+
+  mutt_menu_push_current(menu);
+
+  return menu;
+}
+
+static void free_menu(struct Menu **menu)
+{
+  int i;
+  struct Entry *entries;
+
+  entries = (struct Entry *) (*menu)->data;
+  for (i = 0; i < (*menu)->max; i++)
+  {
+    mutt_autocrypt_db_account_free(&entries[i].account);
+    mutt_addr_free(&entries[i].addr);
+  }
+  FREE(&(*menu)->data);
+
+  mutt_menu_pop_current(*menu);
+  FREE(&(*menu)->help);
+  mutt_menu_destroy(menu);
+}
+
+static void toggle_active(struct Entry *entry)
+{
+  entry->account->enabled = !entry->account->enabled;
+  if (mutt_autocrypt_db_account_update(entry->account) != 0)
+  {
+    entry->account->enabled = !entry->account->enabled;
+    mutt_error(_("Error updating account record"));
+  }
+}
+
+static void toggle_prefer_encrypt(struct Entry *entry)
+{
+  entry->account->prefer_encrypt = !entry->account->prefer_encrypt;
+  if (mutt_autocrypt_db_account_update(entry->account))
+  {
+    entry->account->prefer_encrypt = !entry->account->prefer_encrypt;
+    mutt_error(_("Error updating account record"));
+  }
+}
+
+void mutt_autocrypt_account_menu(void)
+{
+  struct Menu *menu;
+  int done = 0, op;
+  struct Entry *entry;
+  char msg[128];
+
+  if (!C_Autocrypt)
+    return;
+
+  if (mutt_autocrypt_init(0))
+    return;
+
+  menu = create_menu();
+  if (!menu)
+    return;
+
+  while (!done)
+  {
+    switch ((op = mutt_menu_loop(menu)))
+    {
+      case OP_EXIT:
+        done = 1;
+        break;
+
+      case OP_AUTOCRYPT_CREATE_ACCT:
+        if (!mutt_autocrypt_account_init(0))
+        {
+          free_menu(&menu);
+          menu = create_menu();
+        }
+        break;
+
+      case OP_AUTOCRYPT_DELETE_ACCT:
+        if (menu->data)
+        {
+          entry = (struct Entry *) (menu->data) + menu->current;
+          snprintf(msg, sizeof(msg),
+                   /* L10N:
+                       Confirms deleting an autocrypt account
+                    */
+                   _("Really delete account \"%s\"?"), entry->addr->mailbox);
+          if (mutt_yesorno(msg, MUTT_NO) != MUTT_YES)
+            break;
+
+          if (!mutt_autocrypt_db_account_delete(entry->account))
+          {
+            free_menu(&menu);
+            menu = create_menu();
+          }
+        }
+        break;
+
+      case OP_AUTOCRYPT_TOGGLE_ACTIVE:
+        if (menu->data)
+        {
+          entry = (struct Entry *) (menu->data) + menu->current;
+          toggle_active(entry);
+          menu->redraw |= REDRAW_FULL;
+        }
+        break;
+
+      case OP_AUTOCRYPT_TOGGLE_PREFER:
+        if (menu->data)
+        {
+          entry = (struct Entry *) (menu->data) + menu->current;
+          toggle_prefer_encrypt(entry);
+          menu->redraw |= REDRAW_FULL;
+        }
+        break;
+    }
+  }
+
+  free_menu(&menu);
+}
index fc82cb1190eeb83ac2b8fc0a522139c4d34b8f3e..f6cb0f460a02cbed718aebd6ca28555686ab3a1a 100644 (file)
@@ -33,6 +33,8 @@
 /* Prepared statements */
 static sqlite3_stmt *AccountGetStmt;
 static sqlite3_stmt *AccountInsertStmt;
+static sqlite3_stmt *AccountUpdateStmt;
+static sqlite3_stmt *AccountDeleteStmt;
 static sqlite3_stmt *PeerGetStmt;
 static sqlite3_stmt *PeerInsertStmt;
 static sqlite3_stmt *PeerUpdateStmt;
@@ -76,7 +78,7 @@ int mutt_autocrypt_db_init(int can_create)
     if (autocrypt_db_create(mutt_b2s(db_path)))
       goto cleanup;
     /* Don't abort the whole init process because account creation failed */
-    mutt_autocrypt_account_init();
+    mutt_autocrypt_account_init(1);
   }
   else
   {
@@ -106,6 +108,10 @@ void mutt_autocrypt_db_close(void)
   AccountGetStmt = NULL;
   sqlite3_finalize(AccountInsertStmt);
   AccountInsertStmt = NULL;
+  sqlite3_finalize(AccountUpdateStmt);
+  AccountUpdateStmt = NULL;
+  sqlite3_finalize(AccountDeleteStmt);
+  AccountDeleteStmt = NULL;
 
   sqlite3_finalize(PeerGetStmt);
   PeerGetStmt = NULL;
@@ -287,6 +293,128 @@ cleanup:
   return rv;
 }
 
+int mutt_autocrypt_db_account_update(struct AutocryptAccount *acct)
+{
+  int rv = -1;
+
+  if (!AccountUpdateStmt)
+  {
+    if (sqlite3_prepare_v3(AutocryptDB,
+                           "UPDATE account SET "
+                           "keyid = ?, "
+                           "keydata = ?, "
+                           "prefer_encrypt = ?, "
+                           "enabled = ? "
+                           "WHERE email_addr = ?;",
+                           -1, SQLITE_PREPARE_PERSISTENT, &AccountUpdateStmt, NULL) != SQLITE_OK)
+      goto cleanup;
+  }
+
+  if (sqlite3_bind_text(AccountUpdateStmt, 1, acct->keyid, -1, SQLITE_STATIC) != SQLITE_OK)
+    goto cleanup;
+  if (sqlite3_bind_text(AccountUpdateStmt, 2, acct->keydata, -1, SQLITE_STATIC) != SQLITE_OK)
+    goto cleanup;
+  if (sqlite3_bind_int(AccountUpdateStmt, 3, acct->prefer_encrypt) != SQLITE_OK)
+    goto cleanup;
+  if (sqlite3_bind_int(AccountUpdateStmt, 4, acct->enabled) != SQLITE_OK)
+    goto cleanup;
+  if (sqlite3_bind_text(AccountUpdateStmt, 5, acct->email_addr, -1, SQLITE_STATIC) != SQLITE_OK)
+    goto cleanup;
+
+  if (sqlite3_step(AccountUpdateStmt) != SQLITE_DONE)
+    goto cleanup;
+
+  rv = 0;
+
+cleanup:
+  sqlite3_reset(AccountUpdateStmt);
+  return rv;
+}
+
+int mutt_autocrypt_db_account_delete(struct AutocryptAccount *acct)
+{
+  int rv = -1;
+
+  if (!AccountDeleteStmt)
+  {
+    if (sqlite3_prepare_v3(AutocryptDB,
+                           "DELETE from account "
+                           "WHERE email_addr = ?;",
+                           -1, SQLITE_PREPARE_PERSISTENT, &AccountDeleteStmt, NULL) != SQLITE_OK)
+      goto cleanup;
+  }
+
+  if (sqlite3_bind_text(AccountDeleteStmt, 1, acct->email_addr, -1, SQLITE_STATIC) != SQLITE_OK)
+    goto cleanup;
+
+  if (sqlite3_step(AccountDeleteStmt) != SQLITE_DONE)
+    goto cleanup;
+
+  rv = 0;
+
+cleanup:
+  sqlite3_reset(AccountDeleteStmt);
+  return rv;
+}
+
+int mutt_autocrypt_db_account_get_all(struct AutocryptAccount ***accounts, int *num_accounts)
+{
+  int rv = -1, result;
+  sqlite3_stmt *stmt = NULL;
+  struct AutocryptAccount **results = NULL, *account;
+  int results_len = 0, results_count = 0;
+
+  *accounts = NULL;
+  *num_accounts = 0;
+
+  /* Note, speed is not of the essence for the account management screen,
+   * so we don't bother with a persistent prepared statement */
+  if (sqlite3_prepare_v2(AutocryptDB,
+                         "SELECT "
+                         "email_addr, "
+                         "keyid, "
+                         "keydata, "
+                         "prefer_encrypt, "
+                         "enabled "
+                         "FROM account "
+                         "ORDER BY email_addr",
+                         -1, &stmt, NULL) != SQLITE_OK)
+    goto cleanup;
+
+  while ((result = sqlite3_step(stmt)) == SQLITE_ROW)
+  {
+    if (results_count == results_len)
+    {
+      results_len += 5;
+      mutt_mem_realloc(&results, results_len * sizeof(struct AutocryptAccount *));
+    }
+
+    results[results_count++] = account = mutt_autocrypt_db_account_new();
+
+    account->email_addr = strdup_column_text(stmt, 0);
+    account->keyid = strdup_column_text(stmt, 1);
+    account->keydata = strdup_column_text(stmt, 2);
+    account->prefer_encrypt = sqlite3_column_int(stmt, 3);
+    account->enabled = sqlite3_column_int(stmt, 4);
+  }
+
+  if (result == SQLITE_DONE)
+  {
+    *accounts = results;
+    rv = *num_accounts = results_count;
+  }
+  else
+  {
+    while (results_count > 0)
+      mutt_autocrypt_db_account_free(&results[--results_count]);
+    FREE(&results);
+  }
+
+cleanup:
+  sqlite3_finalize(stmt);
+  return rv;
+}
+
 struct AutocryptPeer *mutt_autocrypt_db_peer_new(void)
 {
   return mutt_mem_calloc(1, sizeof(struct AutocryptPeer));
index c0838a0a8ce121f16a8f942fb7d18c59cfb78029..d1a5bf27cdf39818b2d73699a06d9b2483c7e36f 100644 (file)
@@ -29,7 +29,7 @@ struct Address;
 struct AddressList;
 struct Buffer;
 
-int mutt_autocrypt_account_init (void);
+int mutt_autocrypt_account_init (int prompt);
 
 int mutt_autocrypt_db_init (int can_create);
 void mutt_autocrypt_db_close (void);
@@ -42,6 +42,9 @@ void mutt_autocrypt_db_account_free (struct AutocryptAccount **account);
 int mutt_autocrypt_db_account_get (struct Address *addr, struct AutocryptAccount **account);
 int mutt_autocrypt_db_account_insert (struct Address *addr, const char *keyid,
                                       const char *keydata, int prefer_encrypt);
+int mutt_autocrypt_db_account_update (struct AutocryptAccount *acct);
+int mutt_autocrypt_db_account_delete (struct AutocryptAccount *acct);
+int mutt_autocrypt_db_account_get_all (struct AutocryptAccount ***accounts, int *num_accounts);
 
 struct AutocryptPeer *mutt_autocrypt_db_peer_new (void);
 void mutt_autocrypt_db_peer_free (struct AutocryptPeer **peer);
index e3dec08f5d09ca8bc5e9cd7be756dfb3dc81188f..048f090872c989fe2288891c2369aca5151e34d9 100644 (file)
@@ -24,6 +24,7 @@ __print_map(smime)
 __print_map(summary)
 __print_map(mixmaster)
 __print_map(editor)
+__print_map(autocrypt account)
 
     </sect1>
   </chapter>
index b889ebfc8c0341f91aec82f565f8c85b7590f20f..9ac7d16e51a640239f0e16c70614cf6164513ca2 100644 (file)
@@ -101,6 +101,9 @@ const struct Binding OpGeneric[] = { /* map: generic */
  * OpMain - Key bindings for the index menu
  */
 const struct Binding OpMain[] = { /* map: index */
+#ifdef USE_AUTOCRYPT
+  { "autocrypt-acct-menu",        OP_AUTOCRYPT_ACCT_MENU,                "A" },
+#endif
   { "bounce-message",            OP_BOUNCE_MESSAGE,                 "b" },
   { "break-thread",              OP_MAIN_BREAK_THREAD,              "#" },
 #ifdef USE_NNTP
@@ -662,6 +665,16 @@ const struct Binding OpMix[] = { /* map: mixmaster */
 };
 #endif /* MIXMASTER */
 
+#ifdef USE_AUTOCRYPT
+const struct Binding OpAutocryptAcct[] = { /* map: autocrypt account */
+  { "create-account",        OP_AUTOCRYPT_CREATE_ACCT,       "c" },
+  { "delete-account",        OP_AUTOCRYPT_DELETE_ACCT,       "D" },
+  { "toggle-active",         OP_AUTOCRYPT_TOGGLE_ACTIVE,     "a" },
+  { "toggle-prefer-encrypt", OP_AUTOCRYPT_TOGGLE_PREFER,     "p" },
+  { NULL,                    0,                              NULL }
+};
+#endif
+
 // clang-format on
 
 #endif /* MUTT_FUNCTIONS_H */
index 13d3aa5e7f34bc1b9626d202100d60ceb2e700a4..b7fa1944b69eebd4ef0ac9cfa965d85ad55e93ee 100644 (file)
--- a/globals.h
+++ b/globals.h
@@ -97,6 +97,7 @@ WHERE char *C_Attribution;                   ///< Config: Message to start a rep
 WHERE char *C_AttributionLocale;             ///< Config: Locale for dates in the attribution message
 WHERE char *C_AttachFormat;                  ///< Config: printf-like format string for the attachment menu
 #ifdef USE_AUTOCRYPT
+WHERE char *C_AutocryptAcctFormat;
 WHERE char *C_AutocryptDir;
 WHERE char *AutocryptSignAs;  /* This is used in ncrypt/crypt_gpgme.c */
 WHERE char *AutocryptDefaultKey;  /* Used for postponing messages */
diff --git a/index.c b/index.c
index f4911927641c0044b9dd7cb8b792865bcbc1d209..7c25461dac7502d78653f3d672dbc1dfd6263307 100644 (file)
--- a/index.c
+++ b/index.c
@@ -96,6 +96,9 @@
 #ifdef USE_INOTIFY
 #include "monitor.h"
 #endif
+#ifdef USE_AUTOCRYPT
+#include "autocrypt/autocrypt.h"
+#endif
 
 /* These Config Variables are only used in index.c */
 bool C_ChangeFolderNext; ///< Config: Suggest the next folder, rather than the first when using '<change-folder>'
@@ -3609,6 +3612,13 @@ int mutt_index_menu(void)
         mutt_window_reflow();
         break;
 #endif
+
+#ifdef USE_AUTOCRYPT
+      case OP_AUTOCRYPT_ACCT_MENU:
+        mutt_autocrypt_account_menu();
+        break;
+#endif
+
       default:
         if (menu->menu == MENU_MAIN)
           km_error_key(MENU_MAIN);
diff --git a/init.h b/init.h
index 39773a8d00c0e0a6ca8c399c48aa0ea9302d4a54..03f05ec72321a6dc15d54b74c94e7d5e3f125d91 100644 (file)
--- a/init.h
+++ b/init.h
@@ -398,6 +398,20 @@ struct ConfigDef MuttVars[] = {
   ** passive encryption protection with keys exchanged via headers.
   ** TODO: add a section in the manual describing this is more detail.
   */
+  { "autocrypt_acct_format", DT_STRING|R_MENU, &C_AutocryptAcctFormat, IP "%4n %-30a %20p %10s" },
+  /*
+  ** .pp
+  ** This variable describes the format of the ``autocrypt account'' menu.
+  ** The following \fCprintf(3)\fP-style sequences are understood
+  ** .dl
+  ** .dt %a  .dd email address
+  ** .dt %k  .dd gpg keyid
+  ** .dt %n  .dd current entry number
+  ** .dt %p  .dd prefer-encrypt flag
+  ** .dt %s  .dd status flag (active/inactive)
+  ** .de
+  ** .pp
+  */
   { "autocrypt_dir", DT_STRING|DT_PATH, &C_AutocryptDir, IP "~/.mutt/autocrypt" },
   /*
   ** .pp
index 4596e5c9201984ae38e66da2524f1fa406177fcd..9c9c513b5212f64950635d330f97c01944e45c0d 100644 (file)
--- a/keymap.c
+++ b/keymap.c
@@ -952,6 +952,10 @@ void km_init(void)
   km_bindkey("l", MENU_MIX, OP_MIX_CHAIN_NEXT);
 #endif
 
+#ifdef USE_AUTOCRYPT
+  create_bindings(OpAutocryptAcct, MENU_AUTOCRYPT_ACCT);
+#endif
+
   /* bindings for the line editor */
   create_bindings(OpEditor, MENU_EDITOR);
 
@@ -1219,6 +1223,10 @@ const struct Binding *km_get_table(int menu)
       return OpAlias;
     case MENU_ATTACH:
       return OpAttach;
+#ifdef USE_AUTOCRYPT
+    case MENU_AUTOCRYPT_ACCT:
+      return OpAutocryptAcct;
+#endif
     case MENU_COMPOSE:
       return OpCompose;
     case MENU_EDITOR:
index 63ce9cd9cfa7971b88c4d21f603637328a40c240..8d3fc2031c274496ab145eb708827fff24568ea9 100644 (file)
--- a/keymap.h
+++ b/keymap.h
@@ -86,6 +86,9 @@ enum MenuType
 #endif
 #ifdef MIXMASTER
   MENU_MIX,              ///< Create/edit a Mixmaster chain
+#endif
+#ifdef USE_AUTOCRYPT
+  MENU_AUTOCRYPT_ACCT,
 #endif
   MENU_MAX,
 };
@@ -128,6 +131,10 @@ extern const struct Binding OpSmime[];
 extern const struct Binding OpMix[];
 #endif
 
+#ifdef USE_AUTOCRYPT
+extern const struct Binding OpAutocryptAcct[];
+#endif
+
 void mutt_free_keys(void);
 
 enum CommandResult mutt_parse_bind(struct Buffer *buf, struct Buffer *s, unsigned long data, struct Buffer *err);
index d9bab1d8833a715280f0583242f6dcb708a4d68a..6ba9fa72ca9f8e4b7bdb96ce9c280a6194dd88b9 100644 (file)
--- a/opcodes.h
+++ b/opcodes.h
   _fmt(OP_ATTACH_COLLAPSE,                N_("toggle display of subparts")) \
   _fmt(OP_ATTACH_VIEW_MAILCAP,            N_("force viewing of attachment using mailcap")) \
   _fmt(OP_ATTACH_VIEW_TEXT,               N_("view attachment as text")) \
+  _fmt(OP_AUTOCRYPT_ACCT_MENU,            N_("manage autocrypt accounts")) \
+  _fmt(OP_AUTOCRYPT_CREATE_ACCT,          N_("create a new autocrypt account")) \
+  _fmt(OP_AUTOCRYPT_DELETE_ACCT,          N_("delete the current account")) \
+  _fmt(OP_AUTOCRYPT_TOGGLE_ACTIVE,        N_("toggle the current account active/inactive")) \
+  _fmt(OP_AUTOCRYPT_TOGGLE_PREFER,        N_("toggle the current account prefer-encrypt flag")) \
   _fmt(OP_BOTTOM_PAGE,                    N_("move to the bottom of the page")) \
   _fmt(OP_BOUNCE_MESSAGE,                 N_("remail a message to another user")) \
   _fmt(OP_BROWSER_GOTO_FOLDER,            N_("swap the current folder position with $folder if it exists")) \
index fa73ce11120709d30379c1da1d21f847d109eb05..755196e8c7536a5ced1110996d4ae73d9d1ef3d0 100644 (file)
@@ -5,6 +5,7 @@ address/idna.c
 alias.c
 autocrypt/autocrypt.c
 autocrypt/autocrypt_db.c
+autocrypt/autocrypt_acct_menu.c
 autocrypt/autocrypt_gpgme.c
 autocrypt/autocrypt_schema.c
 backtrace.c