From: Kevin McCarthy Date: Mon, 29 Jul 2019 02:24:11 +0000 (-0700) Subject: Basic autocrypt account menu. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=85bd11b08d66ceaaeb30bafb963a950a507185d1;p=mutt 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' . --- diff --git a/OPS b/OPS index 076b4079..a91a14ab 100644 --- a/OPS +++ b/OPS @@ -3,6 +3,11 @@ OP_END_COND "end of conditional execution (noop)" OP_ATTACH_VIEW_MAILCAP "force viewing of attachment using mailcap" OP_ATTACH_VIEW_TEXT "view attachment as text" OP_ATTACH_COLLAPSE "Toggle display of subparts" +OP_AUTOCRYPT_ACCT_MENU "manage autocrypt accounts" +OP_AUTOCRYPT_CREATE_ACCT "create a new autocrypt account" +OP_AUTOCRYPT_DELETE_ACCT "delete the current account" +OP_AUTOCRYPT_TOGGLE_ACTIVE "toggle the current account active/inactive" +OP_AUTOCRYPT_TOGGLE_PREFER "toggle the current account prefer-encrypt flag" OP_BOTTOM_PAGE "move to the bottom of the page" OP_BOUNCE_MESSAGE "remail a message to another user" OP_BROWSER_NEW_FILE "select a new file in this directory" diff --git a/autocrypt/Makefile.am b/autocrypt/Makefile.am index d7f3f0da..aefff20a 100644 --- a/autocrypt/Makefile.am +++ b/autocrypt/Makefile.am @@ -8,4 +8,4 @@ AM_CPPFLAGS = -I$(top_srcdir) -I../intl noinst_LIBRARIES = libautocrypt.a libautocrypt_a_SOURCES = autocrypt.c autocrypt.h autocrypt_db.c autocrypt_private.h \ - autocrypt_schema.c autocrypt_gpgme.c + autocrypt_schema.c autocrypt_gpgme.c autocrypt_acct_menu.c diff --git a/autocrypt/autocrypt.c b/autocrypt/autocrypt.c index 82620035..2c866fca 100644 --- a/autocrypt/autocrypt.c +++ b/autocrypt/autocrypt.c @@ -100,18 +100,22 @@ 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) { ADDRESS *addr = NULL; BUFFER *keyid = NULL, *keydata = NULL; AUTOCRYPT_ACCOUNT *account = NULL; int done = 0, rv = -1, prefer_encrypt = 0; - dprint (1, (debugfile, "In mutt_autocrypt_account_init\n")); - if (mutt_yesorno (_("Create an initial autocrypt account?"), + if (prompt) + { + if (mutt_yesorno (_("Create an initial autocrypt account?"), MUTT_YES) != MUTT_YES) - return 0; + return 0; + } keyid = mutt_buffer_pool_get (); keydata = mutt_buffer_pool_get (); @@ -152,6 +156,7 @@ int mutt_autocrypt_account_init (void) if (account) { mutt_error _("That email address already has an autocrypt account"); + mutt_sleep (1); goto cleanup; } diff --git a/autocrypt/autocrypt.h b/autocrypt/autocrypt.h index 78779777..a50ec311 100644 --- a/autocrypt/autocrypt.h +++ b/autocrypt/autocrypt.h @@ -80,5 +80,6 @@ int mutt_autocrypt_set_sign_as_default_key (HEADER *hdr); int mutt_autocrypt_write_autocrypt_header (ENVELOPE *env, FILE *fp); int mutt_autocrypt_write_gossip_headers (ENVELOPE *env, FILE *fp); int mutt_autocrypt_generate_gossip_list (HEADER *hdr); +void mutt_autocrypt_account_menu (void); #endif diff --git a/autocrypt/autocrypt_acct_menu.c b/autocrypt/autocrypt_acct_menu.c new file mode 100644 index 00000000..dd1f0c5c --- /dev/null +++ b/autocrypt/autocrypt_acct_menu.c @@ -0,0 +1,282 @@ +/* + * Copyright (C) 2019 Kevin J. McCarthy + * + * 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 "mutt_menu.h" +#include "mutt_idna.h" + +#include "autocrypt.h" +#include "autocrypt_private.h" + +typedef struct entry +{ + int tagged; /* TODO */ + int num; + AUTOCRYPT_ACCOUNT *account; + ADDRESS *addr; +} ENTRY; + +static const struct mapping_t 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, format_flag flags) +{ + ENTRY *entry = (ENTRY *)data; + char tmp[SHORT_STRING]; + + 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, MUTTMENU *m, int num) +{ + ENTRY *entry = &((ENTRY *) m->data)[num]; + + mutt_FormatString (s, slen, 0, MuttIndexWindow->cols, + NONULL (AutocryptAcctFormat), account_format_str, + (unsigned long) entry, MUTT_FORMAT_ARROWCURSOR); +} + +static MUTTMENU *create_menu () +{ + MUTTMENU *menu = NULL; + AUTOCRYPT_ACCOUNT **accounts = NULL; + 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_new_menu (MENU_AUTOCRYPT_ACCT); + menu->make_entry = account_entry; + /* menu->tag = account_tag; */ + /* L10N: + Autocrypt Account Management Menu title + */ + menu->title = _("Autocrypt Accounts"); + helpstr = safe_malloc (STRING); + menu->help = mutt_compile_help (helpstr, STRING, MENU_AUTOCRYPT_ACCT, + AutocryptAcctHelp); + + menu->data = entries = safe_calloc (num_accounts, sizeof(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 = rfc822_new_address (); + entries[i].addr->mailbox = safe_strdup (accounts[i]->email_addr); + mutt_addrlist_to_local (entries[i].addr); + } + FREE (&accounts); + + mutt_push_current_menu (menu); + + return menu; +} + +static void free_menu (MUTTMENU **menu) +{ + int i; + ENTRY *entries; + + entries = (ENTRY *)(*menu)->data; + for (i = 0; i < (*menu)->max; i++) + { + mutt_autocrypt_db_account_free (&entries[i].account); + rfc822_free_address (&entries[i].addr); + } + FREE (&(*menu)->data); + + mutt_pop_current_menu (*menu); + FREE (&(*menu)->help); + mutt_menuDestroy (menu); +} + +static void toggle_active (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 (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) +{ + MUTTMENU *menu; + int done = 0, op; + ENTRY *entry; + char msg[SHORT_STRING]; + + if (!option (OPTAUTOCRYPT)) + return; + + if (mutt_autocrypt_init (0)) + return; + + menu = create_menu (); + if (!menu) + return; + + while (!done) + { + switch ((op = mutt_menuLoop (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 = (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 = (ENTRY *)(menu->data) + menu->current; + toggle_active (entry); + menu->redraw |= REDRAW_FULL; + } + break; + + case OP_AUTOCRYPT_TOGGLE_PREFER: + if (menu->data) + { + entry = (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 7fad7068..cadd0dcd 100644 --- a/autocrypt/autocrypt_db.c +++ b/autocrypt/autocrypt_db.c @@ -28,6 +28,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; @@ -74,7 +76,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 { @@ -108,6 +110,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; @@ -307,6 +313,159 @@ cleanup: return rv; } +int mutt_autocrypt_db_account_update (AUTOCRYPT_ACCOUNT *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 (AUTOCRYPT_ACCOUNT *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 (AUTOCRYPT_ACCOUNT ***accounts, int *num_accounts) +{ + int rv = -1, result; + sqlite3_stmt *stmt = NULL; + AUTOCRYPT_ACCOUNT **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; + safe_realloc (&results, results_len * sizeof(AUTOCRYPT_ACCOUNT *)); + } + + 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; +} + AUTOCRYPT_PEER *mutt_autocrypt_db_peer_new (void) { return safe_calloc (1, sizeof(AUTOCRYPT_PEER)); diff --git a/autocrypt/autocrypt_private.h b/autocrypt/autocrypt_private.h index 1c8a038f..96c487f5 100644 --- a/autocrypt/autocrypt_private.h +++ b/autocrypt/autocrypt_private.h @@ -21,7 +21,7 @@ #include -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); @@ -33,6 +33,9 @@ void mutt_autocrypt_db_account_free (AUTOCRYPT_ACCOUNT **account); int mutt_autocrypt_db_account_get (ADDRESS *addr, AUTOCRYPT_ACCOUNT **account); int mutt_autocrypt_db_account_insert (ADDRESS *addr, const char *keyid, const char *keydata, int prefer_encrypt); +int mutt_autocrypt_db_account_update (AUTOCRYPT_ACCOUNT *acct); +int mutt_autocrypt_db_account_delete (AUTOCRYPT_ACCOUNT *acct); +int mutt_autocrypt_db_account_get_all (AUTOCRYPT_ACCOUNT ***accounts, int *num_accounts); AUTOCRYPT_PEER *mutt_autocrypt_db_peer_new (void); void mutt_autocrypt_db_peer_free (AUTOCRYPT_PEER **peer); diff --git a/curs_main.c b/curs_main.c index 2054f42d..919cf154 100644 --- a/curs_main.c +++ b/curs_main.c @@ -45,6 +45,10 @@ #include "monitor.h" #endif +#ifdef USE_AUTOCRYPT +#include "autocrypt.h" +#endif + #include "mutt_crypt.h" @@ -2562,6 +2566,13 @@ int mutt_index_menu (void) mutt_reflow_windows(); 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/doc/manual.xml.tail b/doc/manual.xml.tail index d6da22e5..1ba52231 100644 --- a/doc/manual.xml.tail +++ b/doc/manual.xml.tail @@ -24,6 +24,7 @@ __print_map(pgp) __print_map(smime) __print_map(mixmaster) __print_map(editor) +__print_map(autocrypt account) diff --git a/functions.h b/functions.h index 6e9ba390..419dfc50 100644 --- a/functions.h +++ b/functions.h @@ -86,6 +86,9 @@ const struct binding_t OpGeneric[] = { /* map: generic */ const struct binding_t OpMain[] = { /* map: index */ { "create-alias", OP_CREATE_ALIAS, "a" }, +#ifdef USE_AUTOCRYPT + { "autocrypt-acct-menu", OP_AUTOCRYPT_ACCT_MENU, "A" }, +#endif { "bounce-message", OP_BOUNCE_MESSAGE, "b" }, { "break-thread", OP_MAIN_BREAK_THREAD, "#" }, { "change-folder", OP_MAIN_CHANGE_FOLDER, "c" }, @@ -500,3 +503,13 @@ const struct binding_t OpMix[] = { /* map: mixmaster */ { NULL, 0, NULL } }; #endif /* MIXMASTER */ + +#ifdef USE_AUTOCRYPT +const struct binding_t 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 diff --git a/globals.h b/globals.h index 43de6671..b69d42ea 100644 --- a/globals.h +++ b/globals.h @@ -41,6 +41,7 @@ WHERE char *AttributionLocale; WHERE char *AttachCharset; WHERE char *AttachFormat; #ifdef USE_AUTOCRYPT +WHERE char *AutocryptAcctFormat; WHERE char *AutocryptDir; WHERE char *AutocryptSignAs; /* This is used in crypt-gpgme.c */ WHERE char *AutocryptDefaultKey; /* Used for postponing messages */ diff --git a/init.h b/init.h index c2b8fa6d..aeef569e 100644 --- a/init.h +++ b/init.h @@ -325,6 +325,20 @@ struct option_t 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_STR, R_MENU, {.p=&AutocryptAcctFormat}, {.p="%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_PATH, R_NONE, {.p=&AutocryptDir}, {.p="~/.mutt/autocrypt"} }, /* ** .pp diff --git a/keymap.c b/keymap.c index eabd48ad..2a9fcf0b 100644 --- a/keymap.c +++ b/keymap.c @@ -770,6 +770,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); @@ -1027,6 +1031,11 @@ const struct binding_t *km_get_table (int menu) return OpMix; #endif +#ifdef USE_AUTOCRYPT + case MENU_AUTOCRYPT_ACCT: + return OpAutocryptAcct; +#endif + } return NULL; } diff --git a/keymap.h b/keymap.h index 0f11a984..cffafa6c 100644 --- a/keymap.h +++ b/keymap.h @@ -77,6 +77,9 @@ enum MENU_MIX, #endif +#ifdef USE_AUTOCRYPT + MENU_AUTOCRYPT_ACCT, +#endif MENU_MAX @@ -118,6 +121,10 @@ extern const struct binding_t OpSmime[]; extern const struct binding_t OpMix[]; #endif +#ifdef USE_AUTOCRYPT +extern const struct binding_t OpAutocryptAcct[]; +#endif + #include "keymap_defs.h" #endif /* KEYMAP_H */ diff --git a/po/POTFILES.in b/po/POTFILES.in index 9f7a544f..8f1f4f80 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -4,6 +4,7 @@ alias.c attach.c autocrypt/autocrypt.c autocrypt/autocrypt_db.c +autocrypt/autocrypt_acct_menu.c autocrypt/autocrypt_gpgme.c autocrypt/autocrypt_schema.c browser.c