From: Kevin McCarthy Date: Mon, 29 Jul 2019 02:24:11 +0000 (-0700) Subject: Basic autocrypt account menu X-Git-Tag: 2019-10-25~97^2~26 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9d0c65310586daaf10d931e716c91303358cf535;p=neomutt Basic autocrypt account menu Provide ability to create, delete, and toggle the prefer-encrypt and enabled flag for an account. Hook into the index via 'A' . Co-authored-by: Richard Russon --- diff --git a/Makefile.autosetup b/Makefile.autosetup index b33cda8c8..107638f7a 100644 --- a/Makefile.autosetup +++ b/Makefile.autosetup @@ -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) diff --git a/autocrypt/autocrypt.c b/autocrypt/autocrypt.c index 7fb1dbadf..c7b6db8d5 100644 --- a/autocrypt/autocrypt.c +++ b/autocrypt/autocrypt.c @@ -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(); diff --git a/autocrypt/autocrypt.h b/autocrypt/autocrypt.h index 6ca8a347a..0b39830e3 100644 --- a/autocrypt/autocrypt.h +++ b/autocrypt/autocrypt.h @@ -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 index 000000000..07aa3937e --- /dev/null +++ b/autocrypt/autocrypt_acct_menu.c @@ -0,0 +1,285 @@ +/** + * @file + * XXX + * + * @authors + * Copyright (C) 2019 Kevin J. McCarthy + * + * @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 . + */ + +#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); +} diff --git a/autocrypt/autocrypt_db.c b/autocrypt/autocrypt_db.c index fc82cb119..f6cb0f460 100644 --- a/autocrypt/autocrypt_db.c +++ b/autocrypt/autocrypt_db.c @@ -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)); diff --git a/autocrypt/autocrypt_private.h b/autocrypt/autocrypt_private.h index c0838a0a8..d1a5bf27c 100644 --- a/autocrypt/autocrypt_private.h +++ b/autocrypt/autocrypt_private.h @@ -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); diff --git a/doc/manual.xml.tail b/doc/manual.xml.tail index e3dec08f5..048f09087 100644 --- a/doc/manual.xml.tail +++ b/doc/manual.xml.tail @@ -24,6 +24,7 @@ __print_map(smime) __print_map(summary) __print_map(mixmaster) __print_map(editor) +__print_map(autocrypt account) diff --git a/functions.h b/functions.h index b889ebfc8..9ac7d16e5 100644 --- a/functions.h +++ b/functions.h @@ -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 */ diff --git a/globals.h b/globals.h index 13d3aa5e7..b7fa1944b 100644 --- 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 f49119276..7c25461da 100644 --- 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 '' @@ -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 39773a8d0..03f05ec72 100644 --- 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 diff --git a/keymap.c b/keymap.c index 4596e5c92..9c9c513b5 100644 --- 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: diff --git a/keymap.h b/keymap.h index 63ce9cd9c..8d3fc2031 100644 --- 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); diff --git a/opcodes.h b/opcodes.h index d9bab1d88..6ba9fa72c 100644 --- a/opcodes.h +++ b/opcodes.h @@ -29,6 +29,11 @@ _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")) \ diff --git a/po/POTFILES.in b/po/POTFILES.in index fa73ce111..755196e8c 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -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