diff options
-rw-r--r-- | browser.c | 214 | ||||
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | contrib/mutt_oauth2.py | 1 | ||||
-rw-r--r-- | curs_lib.c | 14 | ||||
-rw-r--r-- | curs_main.c | 2 | ||||
-rw-r--r-- | enter.c | 2 | ||||
-rw-r--r-- | globals.h | 2 | ||||
-rw-r--r-- | headers.c | 4 | ||||
-rw-r--r-- | hook.c | 2 | ||||
-rw-r--r-- | init.h | 16 | ||||
-rw-r--r-- | main.c | 2 | ||||
-rw-r--r-- | mutt.h | 9 | ||||
-rw-r--r-- | mutt_socket.c | 16 | ||||
-rw-r--r-- | mutt_ssl.c | 234 | ||||
-rw-r--r-- | po/fr.po | 914 | ||||
-rwxr-xr-x | smime_keys.pl | 2 |
16 files changed, 725 insertions, 713 deletions
@@ -56,13 +56,13 @@ typedef struct folder_t int num; } FOLDER; -static BUFFER *LastDir = NULL; -static BUFFER *LastDirBackup = NULL; +static BUFFER *LastMailboxDir = NULL; +static BUFFER *LastFileDir = NULL; void mutt_browser_cleanup (void) { - mutt_buffer_free (&LastDir); - mutt_buffer_free (&LastDirBackup); + mutt_buffer_free (&LastMailboxDir); + mutt_buffer_free (&LastFileDir); } /* Frees up the memory allocated for the local-global variables. */ @@ -728,7 +728,8 @@ static void set_sticky_cursor (struct browser_state *state, MUTTMENU *menu, cons } static void init_menu (struct browser_state *state, MUTTMENU *menu, char *title, - size_t titlelen, const char *defaultsel) + size_t titlelen, const char *defaultsel, + const char *working_dir) { BUFFER *path = NULL; @@ -749,7 +750,7 @@ static void init_menu (struct browser_state *state, MUTTMENU *menu, char *title, snprintf (title, titlelen, _("Mailboxes [%d]"), mutt_buffy_check (0)); else { - mutt_buffer_strcpy (path, mutt_b2s (LastDir)); + mutt_buffer_strcpy (path, working_dir); mutt_buffer_pretty_mailbox (path); #ifdef USE_IMAP if (state->imap_browse && option (OPTIMAPLSUB)) @@ -807,8 +808,8 @@ void _mutt_buffer_select_file (BUFFER *f, int flags, char ***files, int *numfile BUFFER *buf = NULL; BUFFER *prefix = NULL; BUFFER *tmp = NULL; - BUFFER *OldLastDir = NULL; BUFFER *defaultsel = NULL; + BUFFER *working_dir = NULL, *old_working_dir = NULL; char helpstr[LONG_STRING]; char title[STRING]; struct browser_state state; @@ -817,31 +818,35 @@ void _mutt_buffer_select_file (BUFFER *f, int flags, char ***files, int *numfile int op, killPrefix = 0; int i, j; int multiple = (flags & MUTT_SEL_MULTI) ? 1 : 0; - int folder = (flags & MUTT_SEL_FOLDER) ? 1 : 0; - int buffy = (flags & MUTT_SEL_BUFFY) ? 1 : 0; - - buffy = buffy && folder; buf = mutt_buffer_pool_get (); prefix = mutt_buffer_pool_get (); tmp = mutt_buffer_pool_get (); - OldLastDir = mutt_buffer_pool_get (); - defaultsel = mutt_buffer_pool_get (); + defaultsel = mutt_buffer_pool_get (); + working_dir = mutt_buffer_pool_get (); + old_working_dir = mutt_buffer_pool_get (); memset (&state, 0, sizeof (struct browser_state)); - state.buffy = buffy; + state.buffy = (flags & MUTT_SEL_BUFFY) ? 1 : 0; - if (!LastDir) + if (!LastMailboxDir) + { + LastMailboxDir = mutt_buffer_new (); + mutt_buffer_increase_size (LastMailboxDir, _POSIX_PATH_MAX); + } + if (!LastFileDir) { - LastDir = mutt_buffer_new (); - mutt_buffer_increase_size (LastDir, _POSIX_PATH_MAX); - LastDirBackup = mutt_buffer_new (); - mutt_buffer_increase_size (LastDirBackup, _POSIX_PATH_MAX); + LastFileDir = mutt_buffer_new (); + mutt_buffer_increase_size (LastFileDir, _POSIX_PATH_MAX); } - if (!folder) - mutt_buffer_strcpy (LastDirBackup, mutt_b2s (LastDir)); + if (flags & MUTT_SEL_MAILBOX) + mutt_buffer_strcpy (working_dir, mutt_b2s (LastMailboxDir)); + else if (flags & MUTT_SEL_FILE) + mutt_buffer_strcpy (working_dir, mutt_b2s (LastFileDir)); + else + mutt_getcwd (working_dir); if (*(mutt_b2s (f))) { @@ -859,7 +864,7 @@ void _mutt_buffer_select_file (BUFFER *f, int flags, char ***files, int *numfile init_state (&state, NULL); state.imap_browse = 1; if (!imap_browse (mutt_b2s (f), &state)) - mutt_buffer_strcpy (LastDir, state.folder); + mutt_buffer_strcpy (working_dir, state.folder); } else { @@ -870,20 +875,20 @@ void _mutt_buffer_select_file (BUFFER *f, int flags, char ***files, int *numfile if (i > 0) { if ((mutt_b2s (f))[0] == '/') - mutt_buffer_strcpy_n (LastDir, mutt_b2s (f), i); + mutt_buffer_strcpy_n (working_dir, mutt_b2s (f), i); else { - mutt_getcwd (LastDir); - mutt_buffer_addch (LastDir, '/'); - mutt_buffer_addstr_n (LastDir, mutt_b2s (f), i); + mutt_getcwd (working_dir); + mutt_buffer_addch (working_dir, '/'); + mutt_buffer_addstr_n (working_dir, mutt_b2s (f), i); } } else { if ((mutt_b2s (f))[0] == '/') - mutt_buffer_strcpy (LastDir, "/"); + mutt_buffer_strcpy (working_dir, "/"); else - mutt_getcwd (LastDir); + mutt_getcwd (working_dir); } if (i <= 0 && (mutt_b2s (f))[0] != '/') @@ -897,31 +902,34 @@ void _mutt_buffer_select_file (BUFFER *f, int flags, char ***files, int *numfile } else { - if (!folder) - mutt_getcwd (LastDir); - else if (!*(mutt_b2s (LastDir))) - mutt_buffer_strcpy (LastDir, NONULL(Maildir)); + if (!*(mutt_b2s (working_dir))) + { + if (flags & MUTT_SEL_MAILBOX) + mutt_buffer_strcpy (working_dir, NONULL(Maildir)); + else + mutt_getcwd (working_dir); + } if (Context) mutt_buffer_strcpy (defaultsel, NONULL (Context->path)); #ifdef USE_IMAP - if (!state.buffy && mx_is_imap (mutt_b2s (LastDir))) + if (!state.buffy && mx_is_imap (mutt_b2s (working_dir))) { init_state (&state, NULL); state.imap_browse = 1; - imap_browse (mutt_b2s (LastDir), &state); + imap_browse (mutt_b2s (working_dir), &state); browser_sort (&state); } else #endif { - i = mutt_buffer_len (LastDir); - while (i && mutt_b2s (LastDir)[--i] == '/') - LastDir->data[i] = '\0'; - mutt_buffer_fix_dptr (LastDir); - if (!*(mutt_b2s (LastDir))) - mutt_getcwd (LastDir); + i = mutt_buffer_len (working_dir); + while (i && mutt_b2s (working_dir)[--i] == '/') + working_dir->data[i] = '\0'; + mutt_buffer_fix_dptr (working_dir); + if (!*(mutt_b2s (working_dir))) + mutt_getcwd (working_dir); } } @@ -936,7 +944,7 @@ void _mutt_buffer_select_file (BUFFER *f, int flags, char ***files, int *numfile #ifdef USE_IMAP if (!state.imap_browse) #endif - if (examine_directory (NULL, &state, mutt_b2s (LastDir), mutt_b2s (prefix)) == -1) + if (examine_directory (NULL, &state, mutt_b2s (working_dir), mutt_b2s (prefix)) == -1) goto bail; menu = mutt_new_menu (MENU_FOLDER); @@ -951,7 +959,8 @@ void _mutt_buffer_select_file (BUFFER *f, int flags, char ***files, int *numfile FolderHelp); mutt_push_current_menu (menu); - init_menu (&state, menu, title, sizeof (title), mutt_b2s (defaultsel)); + init_menu (&state, menu, title, sizeof (title), mutt_b2s (defaultsel), + mutt_b2s (working_dir)); FOREVER { @@ -987,9 +996,9 @@ void _mutt_buffer_select_file (BUFFER *f, int flags, char ***files, int *numfile ) { /* save the old directory */ - mutt_buffer_strcpy (OldLastDir, mutt_b2s (LastDir)); + mutt_buffer_strcpy (old_working_dir, mutt_b2s (working_dir)); - mutt_buffer_strcpy (defaultsel, mutt_b2s (OldLastDir)); + mutt_buffer_strcpy (defaultsel, mutt_b2s (old_working_dir)); if (mutt_buffer_len (defaultsel) && (*(defaultsel->dptr - 1) == '/')) { defaultsel->dptr--; @@ -998,46 +1007,46 @@ void _mutt_buffer_select_file (BUFFER *f, int flags, char ***files, int *numfile if (mutt_strcmp (state.entry[menu->current].display_name, "..") == 0) { - size_t lastdirlen = mutt_buffer_len (LastDir); + size_t workingdirlen = mutt_buffer_len (working_dir); - if ((lastdirlen > 1) && - mutt_strcmp ("..", mutt_b2s (LastDir) + lastdirlen - 2) == 0) + if ((workingdirlen > 1) && + mutt_strcmp ("..", mutt_b2s (working_dir) + workingdirlen - 2) == 0) { - mutt_buffer_addstr (LastDir, "/.."); + mutt_buffer_addstr (working_dir, "/.."); } else { char *p = NULL; - if (lastdirlen > 1) + if (workingdirlen > 1) { - /* "mutt_b2s (LastDir) + 1" triggers a compiler warning */ - p = strrchr (LastDir->data + 1, '/'); + /* "mutt_b2s (working_dir) + 1" triggers a compiler warning */ + p = strrchr (working_dir->data + 1, '/'); } if (p) { *p = 0; - mutt_buffer_fix_dptr (LastDir); + mutt_buffer_fix_dptr (working_dir); } else { - if (mutt_b2s (LastDir)[0] == '/') - mutt_buffer_strcpy (LastDir, "/"); + if (mutt_b2s (working_dir)[0] == '/') + mutt_buffer_strcpy (working_dir, "/"); else - mutt_buffer_addstr (LastDir, "/.."); + mutt_buffer_addstr (working_dir, "/.."); } } } else if (state.buffy) { - mutt_buffer_strcpy (LastDir, state.entry[menu->current].full_path); + mutt_buffer_strcpy (working_dir, state.entry[menu->current].full_path); } #ifdef USE_IMAP else if (state.imap_browse) { ciss_url_t url; - mutt_buffer_strcpy (LastDir, state.entry[menu->current].full_path); + mutt_buffer_strcpy (working_dir, state.entry[menu->current].full_path); /* tack on delimiter here */ /* special case "" needs no delimiter */ @@ -1045,13 +1054,13 @@ void _mutt_buffer_select_file (BUFFER *f, int flags, char ***files, int *numfile if (url.path && (state.entry[menu->current].delim != '\0')) { - mutt_buffer_addch (LastDir, state.entry[menu->current].delim); + mutt_buffer_addch (working_dir, state.entry[menu->current].delim); } } #endif else { - mutt_buffer_strcpy (LastDir, state.entry[menu->current].full_path); + mutt_buffer_strcpy (working_dir, state.entry[menu->current].full_path); } destroy_state (&state); @@ -1066,25 +1075,26 @@ void _mutt_buffer_select_file (BUFFER *f, int flags, char ***files, int *numfile { init_state (&state, NULL); state.imap_browse = 1; - imap_browse (mutt_b2s (LastDir), &state); + imap_browse (mutt_b2s (working_dir), &state); browser_sort (&state); menu->data = state.entry; } else #endif - if (examine_directory (menu, &state, mutt_b2s (LastDir), mutt_b2s (prefix)) == -1) + if (examine_directory (menu, &state, mutt_b2s (working_dir), mutt_b2s (prefix)) == -1) { /* try to restore the old values */ - mutt_buffer_strcpy (LastDir, mutt_b2s (OldLastDir)); - if (examine_directory (menu, &state, mutt_b2s (LastDir), mutt_b2s (prefix)) == -1) + mutt_buffer_strcpy (working_dir, mutt_b2s (old_working_dir)); + if (examine_directory (menu, &state, mutt_b2s (working_dir), mutt_b2s (prefix)) == -1) { - mutt_buffer_strcpy (LastDir, NONULL(Homedir)); + mutt_buffer_strcpy (working_dir, NONULL(Homedir)); goto bail; } } menu->current = 0; menu->top = 0; - init_menu (&state, menu, title, sizeof (title), mutt_b2s (defaultsel)); + init_menu (&state, menu, title, sizeof (title), mutt_b2s (defaultsel), + mutt_b2s (working_dir)); break; } } @@ -1161,19 +1171,20 @@ void _mutt_buffer_select_file (BUFFER *f, int flags, char ***files, int *numfile break; } - if (!imap_mailbox_create (mutt_b2s (LastDir), defaultsel)) + if (!imap_mailbox_create (mutt_b2s (working_dir), defaultsel)) { /* TODO: find a way to detect if the new folder would appear in * this window, and insert it without starting over. */ destroy_state (&state); init_state (&state, NULL); state.imap_browse = 1; - imap_browse (mutt_b2s (LastDir), &state); + imap_browse (mutt_b2s (working_dir), &state); browser_sort (&state); menu->data = state.entry; menu->current = 0; menu->top = 0; - init_menu (&state, menu, title, sizeof (title), mutt_b2s (defaultsel)); + init_menu (&state, menu, title, sizeof (title), mutt_b2s (defaultsel), + mutt_b2s (working_dir)); } /* else leave error on screen */ break; @@ -1190,12 +1201,13 @@ void _mutt_buffer_select_file (BUFFER *f, int flags, char ***files, int *numfile destroy_state (&state); init_state (&state, NULL); state.imap_browse = 1; - imap_browse (mutt_b2s (LastDir), &state); + imap_browse (mutt_b2s (working_dir), &state); browser_sort (&state); menu->data = state.entry; menu->current = 0; menu->top = 0; - init_menu (&state, menu, title, sizeof (title), mutt_b2s (defaultsel)); + init_menu (&state, menu, title, sizeof (title), mutt_b2s (defaultsel), + mutt_b2s (working_dir)); } } break; @@ -1233,7 +1245,8 @@ void _mutt_buffer_select_file (BUFFER *f, int flags, char ***files, int *numfile state.entrylen--; mutt_message _("Mailbox deleted."); mutt_buffer_clear (defaultsel); - init_menu (&state, menu, title, sizeof (title), mutt_b2s (defaultsel)); + init_menu (&state, menu, title, sizeof (title), mutt_b2s (defaultsel), + mutt_b2s (working_dir)); } else mutt_error _("Mailbox deletion failed."); @@ -1247,15 +1260,15 @@ void _mutt_buffer_select_file (BUFFER *f, int flags, char ***files, int *numfile case OP_CHANGE_DIRECTORY: - mutt_buffer_strcpy (buf, mutt_b2s (LastDir)); + mutt_buffer_strcpy (buf, mutt_b2s (working_dir)); mutt_buffer_clear (defaultsel); #ifdef USE_IMAP if (!state.imap_browse) #endif { /* add '/' at the end of the directory name if not already there */ - size_t len = mutt_buffer_len (LastDir); - if (len && (mutt_b2s (LastDir)[len-1] != '/')) + size_t len = mutt_buffer_len (working_dir); + if (len && (mutt_b2s (working_dir)[len-1] != '/')) mutt_buffer_addch (buf, '/'); } @@ -1265,30 +1278,31 @@ void _mutt_buffer_select_file (BUFFER *f, int flags, char ***files, int *numfile { state.buffy = 0; /* no relative path expansion, because that should be compared - * to LastDir, not cwd */ + * to working_dir, not cwd */ mutt_buffer_expand_path_norel (buf); #ifdef USE_IMAP if (mx_is_imap (mutt_b2s (buf))) { - mutt_buffer_strcpy (LastDir, mutt_b2s (buf)); + mutt_buffer_strcpy (working_dir, mutt_b2s (buf)); destroy_state (&state); init_state (&state, NULL); state.imap_browse = 1; - imap_browse (mutt_b2s (LastDir), &state); + imap_browse (mutt_b2s (working_dir), &state); browser_sort (&state); menu->data = state.entry; menu->current = 0; menu->top = 0; - init_menu (&state, menu, title, sizeof (title), mutt_b2s (defaultsel)); + init_menu (&state, menu, title, sizeof (title), mutt_b2s (defaultsel), + mutt_b2s (working_dir)); } else #endif { if (*(mutt_b2s (buf)) != '/') { - /* in case dir is relative, make it relative to LastDir, + /* in case dir is relative, make it relative to working_dir, * not current working dir */ - mutt_buffer_concat_path (tmp, mutt_b2s (LastDir), mutt_b2s (buf)); + mutt_buffer_concat_path (tmp, mutt_b2s (working_dir), mutt_b2s (buf)); mutt_buffer_strcpy (buf, mutt_b2s (tmp)); } if (stat (mutt_b2s (buf), &st) == 0) @@ -1297,18 +1311,19 @@ void _mutt_buffer_select_file (BUFFER *f, int flags, char ***files, int *numfile { destroy_state (&state); if (examine_directory (menu, &state, mutt_b2s (buf), mutt_b2s (prefix)) == 0) - mutt_buffer_strcpy (LastDir, mutt_b2s (buf)); + mutt_buffer_strcpy (working_dir, mutt_b2s (buf)); else { mutt_error _("Error scanning directory."); - if (examine_directory (menu, &state, mutt_b2s (LastDir), mutt_b2s (prefix)) == -1) + if (examine_directory (menu, &state, mutt_b2s (working_dir), mutt_b2s (prefix)) == -1) { goto bail; } } menu->current = 0; menu->top = 0; - init_menu (&state, menu, title, sizeof (title), mutt_b2s (defaultsel)); + init_menu (&state, menu, title, sizeof (title), mutt_b2s (defaultsel), + mutt_b2s (working_dir)); } else mutt_error (_("%s is not a directory."), mutt_b2s (buf)); @@ -1362,15 +1377,17 @@ void _mutt_buffer_select_file (BUFFER *f, int flags, char ***files, int *numfile { init_state (&state, NULL); state.imap_browse = 1; - imap_browse (mutt_b2s (LastDir), &state); + imap_browse (mutt_b2s (working_dir), &state); browser_sort (&state); menu->data = state.entry; - init_menu (&state, menu, title, sizeof (title), mutt_b2s (defaultsel)); + init_menu (&state, menu, title, sizeof (title), mutt_b2s (defaultsel), + mutt_b2s (working_dir)); } else #endif - if (examine_directory (menu, &state, mutt_b2s (LastDir), NULL) == 0) - init_menu (&state, menu, title, sizeof (title), mutt_b2s (defaultsel)); + if (examine_directory (menu, &state, mutt_b2s (working_dir), NULL) == 0) + init_menu (&state, menu, title, sizeof (title), mutt_b2s (defaultsel), + mutt_b2s (working_dir)); else { mutt_error _("Error scanning directory."); @@ -1415,18 +1432,19 @@ void _mutt_buffer_select_file (BUFFER *f, int flags, char ***files, int *numfile goto bail; } #ifdef USE_IMAP - else if (mx_is_imap (mutt_b2s (LastDir))) + else if (mx_is_imap (mutt_b2s (working_dir))) { init_state (&state, NULL); state.imap_browse = 1; - imap_browse (mutt_b2s (LastDir), &state); + imap_browse (mutt_b2s (working_dir), &state); browser_sort (&state); menu->data = state.entry; } #endif - else if (examine_directory (menu, &state, mutt_b2s (LastDir), mutt_b2s (prefix)) == -1) + else if (examine_directory (menu, &state, mutt_b2s (working_dir), mutt_b2s (prefix)) == -1) goto bail; - init_menu (&state, menu, title, sizeof (title), mutt_b2s (defaultsel)); + init_menu (&state, menu, title, sizeof (title), mutt_b2s (defaultsel), + mutt_b2s (working_dir)); break; case OP_BUFFY_LIST: @@ -1435,7 +1453,7 @@ void _mutt_buffer_select_file (BUFFER *f, int flags, char ***files, int *numfile case OP_BROWSER_NEW_FILE: - mutt_buffer_printf (buf, "%s/", mutt_b2s (LastDir)); + mutt_buffer_printf (buf, "%s/", mutt_b2s (working_dir)); /* buf comes from the buffer pool, so defaults to size LONG_STRING */ if (mutt_buffer_get_field (_("New file name: "), buf, MUTT_FILE) == 0) { @@ -1495,19 +1513,21 @@ void _mutt_buffer_select_file (BUFFER *f, int flags, char ***files, int *numfile } bail: + if (flags & MUTT_SEL_MAILBOX) + mutt_buffer_strcpy (LastMailboxDir, mutt_b2s (working_dir)); + else if (flags & MUTT_SEL_FILE) + mutt_buffer_strcpy (LastFileDir, mutt_b2s (working_dir)); + mutt_buffer_pool_release (&buf); mutt_buffer_pool_release (&prefix); mutt_buffer_pool_release (&tmp); - mutt_buffer_pool_release (&OldLastDir); mutt_buffer_pool_release (&defaultsel); + mutt_buffer_pool_release (&working_dir); + mutt_buffer_pool_release (&old_working_dir); if (menu) { mutt_pop_current_menu (menu); mutt_menuDestroy (&menu); } - - if (!folder) - mutt_buffer_strcpy (LastDir, mutt_b2s (LastDirBackup)); - } diff --git a/configure.ac b/configure.ac index 2e38c49f..9348b4c3 100644 --- a/configure.ac +++ b/configure.ac @@ -1325,10 +1325,10 @@ AC_CACHE_CHECK([whether iconv is non-transcribing], mutt_cv_iconv_nontrans, int main() { iconv_t cd; - const char *ib; + char *ib; char *ob; size_t ibl, obl; - const char *s = "\304\211"; + char *s = (char *) "\304\211"; changequote(, )dnl char t[3]; changequote([, ])dnl diff --git a/contrib/mutt_oauth2.py b/contrib/mutt_oauth2.py index 52358e94..c973b98e 100644 --- a/contrib/mutt_oauth2.py +++ b/contrib/mutt_oauth2.py @@ -38,6 +38,7 @@ from pathlib import Path import socket import http.server import subprocess +import readline # The token file must be encrypted because it contains multi-use bearer tokens # whose usage does not require additional verification. Specify whichever @@ -1093,11 +1093,19 @@ static int _enter_fname (const char *prompt, BUFFER *fname, int flags, } else if (ch.ch == '?') { + int sel_flags = 0; + + if (flags & MUTT_MAILBOX) + sel_flags |= MUTT_SEL_MAILBOX; + else if (flags & MUTT_FILE) + sel_flags |= MUTT_SEL_FILE; + + if (multiple) + sel_flags |= MUTT_SEL_MULTI; + mutt_refresh (); mutt_buffer_clear (fname); - _mutt_buffer_select_file (fname, - MUTT_SEL_FOLDER | (multiple ? MUTT_SEL_MULTI : 0), - files, numfiles); + _mutt_buffer_select_file (fname, sel_flags, files, numfiles); } else { diff --git a/curs_main.c b/curs_main.c index 71a4e06e..3d79723c 100644 --- a/curs_main.c +++ b/curs_main.c @@ -1360,7 +1360,7 @@ int mutt_index_menu (void) else if ((op == OP_MAIN_BROWSE_MAILBOXES) || (op == OP_MAIN_BROWSE_MAILBOXES_READONLY)) - mutt_buffer_select_file (folderbuf, MUTT_SEL_FOLDER | MUTT_SEL_BUFFY); + mutt_buffer_select_file (folderbuf, MUTT_SEL_MAILBOX | MUTT_SEL_BUFFY); else { @@ -725,7 +725,7 @@ int _mutt_enter_string (char *buf, size_t buflen, int col, !memcmp (tempbuf, state->wbuf, state->lastchar * sizeof (wchar_t)))) { _mutt_select_file (buf, buflen, - ((flags & MUTT_MAILBOX) ? MUTT_SEL_FOLDER : 0) | (multiple ? MUTT_SEL_MULTI : 0), + ((flags & MUTT_MAILBOX) ? MUTT_SEL_MAILBOX : 0) | (multiple ? MUTT_SEL_MULTI : 0), files, numfiles); if (!multiple && *buf) { @@ -103,6 +103,8 @@ WHERE char *MsgFmt; WHERE char *Preconnect; WHERE char *Tunnel; WHERE short NetInc; +WHERE short SocketReceiveTimeout; +WHERE short SocketSendTimeout; #endif /* USE_SOCKET */ #ifdef MIXMASTER @@ -347,9 +347,7 @@ int mutt_label_message(HEADER *hdr) if (label_message(Context, HDR_OF(i), new)) { ++changed; - mutt_set_flag(Context, HDR_OF(i), - MUTT_TAG, 0); - /* mutt_set_flag re-evals the header color */ + mutt_set_header_color (Context, HDR_OF(i)); } } } @@ -165,7 +165,7 @@ int mutt_parse_hook (BUFFER *buf, BUFFER *s, union pointer_long_t udata, BUFFER } else if (data & MUTT_FCCHOOK) { - /* Do not perform relative path expansion "\^" can be expanded later: + /* Do not perform relative path expansion. "\^" can be expanded later: * mutt_select_fcc() => mutt_addr_hook() => mutt_make_string() * which will perform backslash expansion, converting "\^" to "^". * save_fcc_mailbox_part() then calls mutt_buffer_expand_path() on each part. @@ -4161,6 +4161,22 @@ struct option_t MuttVars[] = { ** Also see $$write_bcc. */ #endif /* USE_SMTP */ +#ifdef USE_SOCKET + { "socket_receive_timeout", DT_NUM, R_NONE, {.p=&SocketReceiveTimeout}, {.l=0} }, + /* + ** .pp + ** Causes Mutt to timeout any socket read operation (e.g. SSL_read) after + ** this many seconds. A zero (default) or negative value causes Mutt to wait + ** indefinitely for the read to complete. + */ + { "socket_send_timeout", DT_NUM, R_NONE, {.p=&SocketSendTimeout}, {.l=0} }, + /* + ** .pp + ** Causes Mutt to timeout any socket write operation (e.g. SSL_write) after + ** this many seconds. A zero (default) or negative value causes Mutt to wait + ** indefinitely for the write to complete. + */ +#endif /* USE_SOCKET */ { "sort", DT_SORT, R_INDEX|R_RESORT, {.p=&Sort}, {.l=SORT_DATE} }, /* ** .pp @@ -1356,7 +1356,7 @@ int main (int argc, char **argv, char **environ) goto cleanup_and_exit; } mutt_buffer_clear (folder); - mutt_buffer_select_file (folder, MUTT_SEL_FOLDER | MUTT_SEL_BUFFY); + mutt_buffer_select_file (folder, MUTT_SEL_MAILBOX | MUTT_SEL_BUFFY); if (!mutt_buffer_len (folder)) { exit_code = 0; @@ -371,10 +371,11 @@ enum #define MUTT_EDIT_HEADERS_RESUME 2 /* flags to _mutt_select_file() */ -#define MUTT_SEL_BUFFY (1<<0) -#define MUTT_SEL_MULTI (1<<1) -#define MUTT_SEL_FOLDER (1<<2) -#define MUTT_SEL_DIRECTORY (1<<3) /* Allow directories to be selected +#define MUTT_SEL_BUFFY (1<<0) +#define MUTT_SEL_MULTI (1<<1) +#define MUTT_SEL_MAILBOX (1<<2) /* Use LastMailboxDir state */ +#define MUTT_SEL_FILE (1<<3) /* Use LastFileDir state */ +#define MUTT_SEL_DIRECTORY (1<<4) /* Allow directories to be selected * via <view-file> */ /* flags for parse_spam_list */ diff --git a/mutt_socket.c b/mutt_socket.c index 3e192072..898faa07 100644 --- a/mutt_socket.c +++ b/mutt_socket.c @@ -433,6 +433,22 @@ static int socket_connect (int fd, struct sockaddr* sa) save_errno = 0; + if (SocketReceiveTimeout > 0) + { + struct timeval tv = { SocketReceiveTimeout, 0 }; + if (setsockopt (fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)) < 0) + dprint (1, (debugfile, "socket_connect: error setting receive timeout (%s)\n", + strerror(errno))); + } + + if (SocketSendTimeout > 0) + { + struct timeval tv = { SocketSendTimeout, 0 }; + if (setsockopt (fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv)) < 0) + dprint (1, (debugfile, "socket_connect: error setting send timeout (%s)\n", + strerror(errno))); + } + if (connect (fd, sa, sa_size) < 0) { save_errno = errno; @@ -92,7 +92,7 @@ static int ssl_socket_write (CONNECTION* conn, const char* buf, size_t len); static int ssl_socket_poll (CONNECTION* conn, time_t wait_secs); static int ssl_socket_open (CONNECTION * conn); static int ssl_socket_close (CONNECTION * conn); -static int tls_close (CONNECTION* conn); +static int starttls_close (CONNECTION* conn); static void ssl_err (sslsockdata *data, int err); static void ssl_dprint_err_stack (void); static int ssl_cache_trusted_cert (X509 *cert); @@ -204,44 +204,33 @@ static void reset_allowed_proto_version_range (sslsockdata *ssldata) #endif } -/* mutt_ssl_starttls: Negotiate TLS over an already opened connection. - * TODO: Merge this code better with ssl_socket_open. */ -int mutt_ssl_starttls (CONNECTION* conn) +/* mutt_ssl_setup_common: common code paths for Implicit TLS and in-band STARTTLS (STLS) modes */ +static int mutt_ssl_setup_common (CONNECTION *conn, long ssl_options) { - sslsockdata* ssldata; + sslsockdata *data; int maxbits; - long ssl_options = 0; - - if (mutt_socket_has_buffered_input (conn)) - { - /* L10N: - The server is not supposed to send data immediately after - confirming STARTTLS. This warns the user that something - weird is going on. - */ - mutt_error _("Warning: clearing unexpected server data before TLS negotiation"); - mutt_sleep (0); - mutt_socket_clear_buffered_input (conn); - } - if (ssl_init()) + if (ssl_init ()) goto bail; - ssldata = (sslsockdata*) safe_calloc (1, sizeof (sslsockdata)); - /* the ssl_use_xxx protocol options don't apply. We must use TLS in TLS. + data = (sslsockdata*) safe_calloc (1, sizeof (sslsockdata)); + /* the ssl_use_sslxxx protocol options don't apply to starttls, + * we must use TLS in TLS, so we do not refactor these. * * However, we need to be able to negotiate amongst various TLS versions, * which at present can only be done with the SSLv23_client_method; * TLSv1_client_method gives us explicitly TLSv1.0, not 1.1 or 1.2 (True as - * of OpenSSL 1.0.1c) + * of OpenSSL 1.0.1c ... 3.0.x) */ - if (! (ssldata->ctx = SSL_CTX_new (SSLv23_client_method()))) + if (! (data->ctx = SSL_CTX_new (SSLv23_client_method()))) { dprint (1, (debugfile, "mutt_ssl_starttls: Error allocating SSL_CTX\n")); + mutt_error (_("Unable to create SSL context")); + ssl_dprint_err_stack (); goto bail_ssldata; } - reset_allowed_proto_version_range (ssldata); + reset_allowed_proto_version_range (data); #ifdef SSL_OP_NO_TLSv1_3 if (!option(OPTTLSV1_3)) @@ -259,89 +248,112 @@ int mutt_ssl_starttls (CONNECTION* conn) if (!option(OPTTLSV1)) ssl_options |= SSL_OP_NO_TLSv1; #endif - /* these are always set */ -#ifdef SSL_OP_NO_SSLv3 - ssl_options |= SSL_OP_NO_SSLv3; -#endif -#ifdef SSL_OP_NO_SSLv2 - ssl_options |= SSL_OP_NO_SSLv2; -#endif - if (! SSL_CTX_set_options(ssldata->ctx, ssl_options)) - { - dprint(1, (debugfile, "mutt_ssl_starttls: Error setting options to %ld\n", ssl_options)); - goto bail_ctx; - } + (void)SSL_CTX_set_options (data->ctx, ssl_options); /* would only return new values -> discard */ if (option (OPTSSLSYSTEMCERTS)) { - if (! SSL_CTX_set_default_verify_paths (ssldata->ctx)) + if (! SSL_CTX_set_default_verify_paths (data->ctx)) { dprint (1, (debugfile, "mutt_ssl_starttls: Error setting default verify paths\n")); goto bail_ctx; } } - if (SslCertFile && !ssl_load_certificates (ssldata->ctx)) - dprint (1, (debugfile, "mutt_ssl_starttls: Error loading trusted certificates\n")); + if (SslCertFile && !ssl_load_certificates (data->ctx)) + dprint (1, (debugfile, "mutt_ssl_setup_common: Error loading trusted certificates\n")); - ssl_get_client_cert(ssldata, conn); + ssl_get_client_cert (data, conn); if (SslCiphers) { - if (!SSL_CTX_set_cipher_list (ssldata->ctx, SslCiphers)) + if (!SSL_CTX_set_cipher_list (data->ctx, SslCiphers)) { - dprint (1, (debugfile, "mutt_ssl_starttls: Could not select preferred ciphers\n")); + dprint (1, (debugfile, "mutt_ssl_setup_common: Could not select preferred ciphers\n")); goto bail_ctx; } } - if (ssl_set_verify_partial (ssldata->ctx)) + if (ssl_set_verify_partial (data->ctx)) { mutt_error (_("Warning: error enabling ssl_verify_partial_chains")); mutt_sleep (2); } - if (! (ssldata->ssl = SSL_new (ssldata->ctx))) + if (! (data->ssl = SSL_new (data->ctx))) { - dprint (1, (debugfile, "mutt_ssl_starttls: Error allocating SSL\n")); + dprint (1, (debugfile, "mutt_ssl_setup_common: Error allocating SSL\n")); goto bail_ctx; } - if (SSL_set_fd (ssldata->ssl, conn->fd) != 1) + if (SSL_set_fd (data->ssl, conn->fd) != 1) { - dprint (1, (debugfile, "mutt_ssl_starttls: Error setting fd\n")); + dprint (1, (debugfile, "mutt_ssl_setup_common: Error setting fd\n")); goto bail_ssl; } - if (ssl_negotiate (conn, ssldata)) |