From: Richard Russon Date: Sun, 27 Oct 2019 03:14:14 +0000 (+0000) Subject: PATCHES X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=37449fedf2fe08ffc87c3953802e2a39b793047a;p=neomutt PATCHES --- diff --git a/0001-Rename-browser-fields-to-display_name-and-full_path.patch b/0001-Rename-browser-fields-to-display_name-and-full_path.patch new file mode 100644 index 000000000..edd0cf564 --- /dev/null +++ b/0001-Rename-browser-fields-to-display_name-and-full_path.patch @@ -0,0 +1,459 @@ +From 1600dd189b064341b6579d8b07d0bf5f6ad80f8d Mon Sep 17 00:00:00 2001 +From: Kevin McCarthy +Date: Sun, 8 Sep 2019 12:09:51 -0700 +Subject: Rename browser fields to display_name and full_path + +Mailbox and Folder view don't make use of the desc field. They store +an abbreviated version in the name field and expand it when selecting +or testing it. + +IMAP stores the full URL in name, and stores an abbreviated +version(possibly with a trailing slash) in the desc field. + +The asymetricity makes it awkward, and interferes with a smart-cursor +option in the next commit. So instead rename the fields to +"display_name" and "full_path". + +In Mailfox and Folder view, store the fully expanded path, which we +have while iterating, in "full_path", and the shortened version in +"display_name". + +Likewise in IMAP, store the full URL in "full_path" and the shortened +version in "display_name". + +Simplify the code in browser.c to use the full_path instead of +concatenating and expanding. + +Upstream-commit: https://gitlab.com/muttmua/mutt/commit/1600dd189b064341b6579d8b07d0bf5f6ad80f8d +Co-authored-by: +--- + browser.c | 135 ++++++++++++++++---------------------------------- + browser.h | 4 +- + imap/browse.c | 6 +-- + 3 files changed, 49 insertions(+), 96 deletions(-) + +diff --git a/browser.c b/browser.c +index 973e17ae..56ce75d2 100644 +--- a/browser.c ++++ b/browser.c +@@ -72,8 +72,8 @@ static void destroy_state(struct browser_state *state) + + for (c = 0; c < state->entrylen; c++) + { +- FREE(& ((state->entry)[c].name)); +- FREE(& ((state->entry)[c].desc)); ++ FREE(& ((state->entry)[c].display_name)); ++ FREE(& ((state->entry)[c].full_path)); + } + #ifdef USE_IMAP + FREE(&state->folder); +@@ -86,7 +86,7 @@ static int browser_compare_subject(const void *a, const void *b) + struct folder_file *pa =(struct folder_file *) a; + struct folder_file *pb =(struct folder_file *) b; + +- int r = mutt_str_strcoll(pa->name, pb->name); ++ int r = mutt_str_strcoll(pa->display_name, pb->display_name); + + return ((SortBrowser & SORT_REVERSE) ? -r : r); + } +@@ -159,21 +159,14 @@ static void browser_sort(struct browser_state *state) + qsort(state->entry, state->entrylen, sizeof(struct folder_file), f); + } + +-static int link_is_dir(const char *folder, const char *path) ++static int link_is_dir(const char *full_path) + { + struct stat st; +- struct Buffer *fullpath = NULL; + int retval = 0; + +- fullpath = mutt_buffer_pool_get(); +- +- mutt_buffer_concat_path(fullpath, folder, path); +- +- if (stat(mutt_b2s(fullpath), &st) == 0) ++ if (stat(full_path, &st) == 0) + retval = S_ISDIR(st.st_mode); + +- mutt_buffer_pool_release(&fullpath); +- + return retval; + } + +@@ -232,13 +225,7 @@ folder_format_str(char *dest, size_t destlen, size_t col, int cols, char op, co + + case 'f': + { +- char *s; +-#ifdef USE_IMAP +- if (folder->ff->imap) +- s = NONULL(folder->ff->desc); +- else +-#endif +- s = NONULL(folder->ff->name); ++ char *s = NONULL(folder->ff->display_name); + + snprintf(fn, sizeof(fn), "%s%s", s, + folder->ff->local ? +@@ -389,7 +376,8 @@ folder_format_str(char *dest, size_t destlen, size_t col, int cols, char op, co + } + + static void add_folder(struct Menu *m, struct browser_state *state, +- const char *name, const struct stat *s, struct Mailbox *b) ++ const char *display_name, const char *full_path, ++ const struct stat *s, struct Mailbox *b) + { + if (state->entrylen == state->entrymax) + { +@@ -422,8 +410,8 @@ static void add_folder(struct Menu *m, struct browser_state *state, + (state->entry)[state->entrylen].msg_unread = b->msg_unread; + } + +-(state->entry)[state->entrylen].name = mutt_str_strdup(name); +-(state->entry)[state->entrylen].desc = mutt_str_strdup(name); ++(state->entry)[state->entrylen].display_name = mutt_str_strdup(display_name); ++(state->entry)[state->entrylen].full_path = mutt_str_strdup(full_path); + #ifdef USE_IMAP + (state->entry)[state->entrylen].imap = 0; + #endif +@@ -448,7 +436,7 @@ static int examine_directory(struct Menu *menu, struct browser_state *state, + struct stat s; + DIR *dp; + struct dirent *de; +- struct Buffer *buffer = NULL; ++ struct Buffer *full_path = NULL; + struct Mailbox *tmp; + + while (stat(d, &s) == -1) +@@ -482,7 +470,7 @@ static int examine_directory(struct Menu *menu, struct browser_state *state, + return (-1); + } + +- buffer = mutt_buffer_pool_get(); ++ full_path = mutt_buffer_pool_get(); + init_state(state, menu); + + while ((de = readdir(dp)) != NULL) +@@ -495,8 +483,8 @@ static int examine_directory(struct Menu *menu, struct browser_state *state, + if (!((mutt/regex.c(C_Mask.regex, de->d_name, 0, NULL, 0) == 0) ^ C_Mask.not)) + continue; + +- mutt_buffer_concat_path(buffer, d, de->d_name); +- if (lstat(mutt_b2s(buffer), &s) == -1) ++ mutt_buffer_concat_path(full_path, d, de->d_name); ++ if (lstat(mutt_b2s(full_path), &s) == -1) + continue; + + /* No size for directories or symlinks */ +@@ -506,7 +494,7 @@ static int examine_directory(struct Menu *menu, struct browser_state *state, + continue; + + tmp = AllMailboxes; +- while (tmp && mutt_str_strcmp(mutt_b2s(buffer), mutt_b2s(tmp->pathbuf))) ++ while (tmp && mutt_str_strcmp(mutt_b2s(full_path), mutt_b2s(tmp->pathbuf))) + tmp = tmp->next; + if (tmp && Context && + !mutt_str_strcmp(tmp->realpath, Context->realpath)) +@@ -514,12 +502,12 @@ static int examine_directory(struct Menu *menu, struct browser_state *state, + tmp->msg_count = Context->msgcount; + tmp->msg_unread = Context->unread; + } +- add_folder(menu, state, de->d_name, &s, tmp); ++ add_folder(menu, state, de->d_name, mutt_b2s(full_path), &s, tmp); + } + closedir(dp); + browser_sort(state); + +- mutt_buffer_pool_release(&buffer); ++ mutt_buffer_pool_release(&full_path); + return 0; + } + +@@ -554,14 +542,14 @@ static int examine_mailboxes(struct Menu *menu, struct browser_state *state) + #ifdef USE_IMAP + if (mx_is_imap(mutt_b2s(tmp->pathbuf))) + { +- add_folder(menu, state, mutt_b2s(mailbox), NULL, tmp); ++ add_folder(menu, state, mutt_b2s(mailbox), mutt_b2s(tmp->pathbuf), NULL, tmp); + continue; + } + #endif + #ifdef USE_POP + if (mx_is_pop(mutt_b2s(tmp->pathbuf))) + { +- add_folder(menu, state, mutt_b2s(mailbox), NULL, tmp); ++ add_folder(menu, state, mutt_b2s(mailbox), mutt_b2s(tmp->pathbuf), NULL, tmp); + continue; + } + #endif +@@ -586,7 +574,7 @@ static int examine_mailboxes(struct Menu *menu, struct browser_state *state) + s.st_mtime = st2.st_mtime; + } + +- add_folder(menu, state, mutt_b2s(mailbox), &s, tmp); ++ add_folder(menu, state, mutt_b2s(mailbox), mutt_b2s(tmp->pathbuf), &s, tmp); + } + while ((tmp = tmp->next)); + browser_sort(state); +@@ -598,7 +586,7 @@ static int examine_mailboxes(struct Menu *menu, struct browser_state *state) + + static int select_file_search(struct Menu *menu, regex_t *re, int n) + { +- return (mutt/regex.c(re, ((struct folder_file *) menu->data)[n].name, 0, NULL, 0)); ++ return (mutt/regex.c(re, ((struct folder_file *) menu->data)[n].display_name, 0, NULL, 0)); + } + + static void folder_entry(char *s, size_t slen, struct Menu *menu, int num) +@@ -655,7 +643,7 @@ static int file_tag(struct Menu *menu, int n, int m) + struct folder_file *ff = & (((struct folder_file *)menu->data)[n]); + int ot; + if (S_ISDIR(ff->mode) || +- (S_ISLNK(ff->mode) && link_is_dir(mutt_b2s(LastDir), ff->name))) ++ (S_ISLNK(ff->mode) && link_is_dir(ff->full_path))) + { + mutt_error _("Can't attach a directory!"); + return 0; +@@ -832,28 +820,14 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + + if (S_ISDIR(state.entry[menu->current].mode) || + (S_ISLNK(state.entry[menu->current].mode) && +- link_is_dir(mutt_b2s(LastDir), state.entry[menu->current].name)) ++ link_is_dir(state.entry[menu->current].full_path)) + #ifdef USE_IMAP + || state.entry[menu->current].inferiors + #endif + ) + { +- /* make sure this isn't a MH or maildir mailbox */ +- if (mailbox) +- { +- mutt_buffer_strcpy(buf, state.entry[menu->current].name); +- mutt_buffer_expand_path(buf); +- } +-#ifdef USE_IMAP +- else if (state.imap_browse) +- { +- mutt_buffer_strcpy(buf, state.entry[menu->current].name); +- } +-#endif +- else +- mutt_buffer_concat_path(buf, mutt_b2s(LastDir), state.entry[menu->current].name); +- +- if (op == OP_DESCEND_DIRECTORY || (mx_get_magic(mutt_b2s(buf)) <= 0) ++ if (op == OP_DESCEND_DIRECTORY ++ || (mx_get_magic(state.entry[menu->current].full_path) <= 0) + #ifdef USE_IMAP + || state.entry[menu->current].inferiors + #endif +@@ -862,7 +836,7 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + /* save the old directory */ + mutt_buffer_strcpy(OldLastDir, mutt_b2s(LastDir)); + +- if (mutt_str_strcmp(state.entry[menu->current].name, "..") == 0) ++ if (mutt_str_strcmp(state.entry[menu->current].display_name, "..") == 0) + { + size_t lastdirlen = mutt_buffer_len(LastDir); + +@@ -893,19 +867,18 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + } + else if (mailbox) + { +- mutt_buffer_strcpy(LastDir, state.entry[menu->current].name); +- mutt_buffer_expand_path(LastDir); ++ mutt_buffer_strcpy(LastDir, state.entry[menu->current].full_path); + } + #ifdef USE_IMAP + else if (state.imap_browse) + { + struct Url url; + +- mutt_buffer_strcpy(LastDir, state.entry[menu->current].name); ++ mutt_buffer_strcpy(LastDir, state.entry[menu->current].full_path); + /* tack on delimiter here */ + + /* special case "" needs no delimiter */ +- url_parse(&url, state.entry[menu->current].name); ++ url_parse(&url, state.entry[menu->current].full_path); + if (url.path && + (state.entry[menu->current].delim != '\0')) + { +@@ -915,8 +888,7 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + #endif + else + { +- mutt_buffer_concat_path(tmp, mutt_b2s(LastDir), state.entry[menu->current].name); +- mutt_buffer_strcpy(LastDir, mutt_b2s(tmp)); ++ mutt_buffer_strcpy(LastDir, state.entry[menu->current].full_path); + } + + destroy_state(&state); +@@ -955,21 +927,11 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + } + else if (op == OP_DESCEND_DIRECTORY) + { +- mutt_error(_("%s is not a directory."), state.entry[menu->current].name); ++ mutt_error(_("%s is not a directory."), state.entry[menu->current].display_name); + break; + } + +- if (mailbox) +- { +- mutt_buffer_strcpy(f, state.entry[menu->current].name); +- mutt_buffer_expand_path(f); +- } +-#ifdef USE_IMAP +- else if (state.imap_browse) +- mutt_buffer_strcpy(f, state.entry[menu->current].name); +-#endif +- else +- mutt_buffer_concat_path(f, mutt_b2s(LastDir), state.entry[menu->current].name); ++ mutt_buffer_strcpy(f, state.entry[menu->current].full_path); + + /* Fall through to OP_EXIT */ + +@@ -984,22 +946,14 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + *numfiles = menu->tagged; + tfiles = mutt_mem_calloc(*numfiles, sizeof(char *)); + for (i = 0, j = 0; i < state.entrylen; i++) +- { +- struct folder_file ff = state.entry[i]; +- if (ff.tagged) +- { +- mutt_buffer_concat_path(tmp, mutt_b2s(LastDir), ff.name); +- mutt_buffer_expand_path(tmp); +- tfiles[j++] = mutt_str_strdup(mutt_b2s(tmp)); +- } +- } ++ if (state.entry[i].tagged) ++ tfiles[j++] = mutt_str_strdup(state.entry[i].full_path); + *files = tfiles; + } + else if ((mutt_b2s(f))[0]) /* no tagged entries. return selected entry */ + { + *numfiles = 1; + tfiles = mutt_mem_calloc(*numfiles, sizeof(char *)); +- mutt_buffer_expand_path(f); + tfiles[0] = mutt_str_strdup(mutt_b2s(f)); + *files = tfiles; + } +@@ -1010,16 +964,16 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + + case OP_BROWSER_TELL: + if (state.entrylen) +- mutt_message("%s", state.entry[menu->current].name); ++ mutt_message("%s", state.entry[menu->current].display_name); + break; + + #ifdef USE_IMAP + case OP_BROWSER_SUBSCRIBE: +- imap_subscribe(state.entry[menu->current].name, 1); ++ imap_subscribe(state.entry[menu->current].full_path, 1); + break; + + case OP_BROWSER_UNSUBSCRIBE: +- imap_subscribe(state.entry[menu->current].name, 0); ++ imap_subscribe(state.entry[menu->current].full_path, 0); + break; + + case OP_BROWSER_TOGGLE_LSUB: +@@ -1062,7 +1016,7 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + { + int nentry = menu->current; + +- if (imap_mailbox_rename(state.entry[nentry].name) >= 0) ++ if (imap_mailbox_rename(state.entry[nentry].full_path) >= 0) + { + destroy_state(&state); + init_state(&state, NULL); +@@ -1086,7 +1040,7 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + IMAP_MBOX mx; + int nentry = menu->current; + +- imap_parse_path(state.entry[nentry].name, &mx); ++ imap_parse_path(state.entry[nentry].full_path, &mx); + if (!mx.mbox) + { + mutt_error _("Cannot delete root folder"); +@@ -1099,8 +1053,8 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + if (!imap_delete_mailbox(Context, mx)) + { + /* free the mailbox from the browser */ +- FREE(& ((state.entry)[nentry].name)); +- FREE(& ((state.entry)[nentry].desc)); ++ FREE(& ((state.entry)[nentry].display_name)); ++ FREE(& ((state.entry)[nentry].full_path)); + /* and move all other entries up */ + if (nentry+1 < state.entrylen) + memmove(state.entry + nentry, state.entry + nentry + 1, +@@ -1367,7 +1321,7 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + #ifdef USE_IMAP + if (state.entry[menu->current].selectable) + { +- mutt_buffer_strcpy(f, state.entry[menu->current].name); ++ mutt_buffer_strcpy(f, state.entry[menu->current].full_path); + destroy_state(&state); + goto bail; + } +@@ -1375,7 +1329,7 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + #endif + if (S_ISDIR(state.entry[menu->current].mode) || + (S_ISLNK(state.entry[menu->current].mode) && +- link_is_dir(mutt_b2s(LastDir), state.entry[menu->current].name))) ++ link_is_dir(state.entry[menu->current].full_path))) + { + mutt_error _("Can't view a directory"); + break; +@@ -1384,8 +1338,7 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + { + struct Body *b; + +- mutt_buffer_concat_path(buf, mutt_b2s(LastDir), state.entry[menu->current].name); +- b = mutt_make_file_attach(mutt_b2s(buf)); ++ b = mutt_make_file_attach(state.entry[menu->current].full_path); + if (b != NULL) + { + mutt_view_attachment(NULL, b, MUTT_REGULAR, NULL, NULL); +diff --git a/browser.h b/browser.h +index a7103743..39c257b6 100644 +--- a/browser.h ++++ b/browser.h +@@ -28,8 +28,8 @@ struct folder_file + gid_t gid; + nlink_t nlink; + +- char *name; +- char *desc; ++ char *display_name; ++ char *full_path; + + short new; /* true if mailbox has "new mail" */ + int msg_count; /* total number of messages */ +diff --git a/imap/browse.c b/imap/browse.c +index ab965803..277444aa 100644 +--- a/imap/browse.c ++++ b/imap/browse.c +@@ -426,7 +426,7 @@ static void imap_add_folder(char delim, char *folder, int noselect, + } + + imap_qualify_path(tmp, sizeof(tmp), &mx, folder); +-(state->entry)[state->entrylen].name = mutt_str_strdup(tmp); ++(state->entry)[state->entrylen].full_path = mutt_str_strdup(tmp); + + /* mark desc with delim in browser if it can have subfolders */ + if (!isparent && !noinferiors && strlen(relpath) < sizeof(relpath) - 1) +@@ -435,7 +435,7 @@ static void imap_add_folder(char delim, char *folder, int noselect, + relpath[strlen(relpath)] = delim; + } + +-(state->entry)[state->entrylen].desc = mutt_str_strdup(relpath); ++(state->entry)[state->entrylen].display_name = mutt_str_strdup(relpath); + + (state->entry)[state->entrylen].imap = 1; + /* delimiter at the root is useless. */ +@@ -469,5 +469,5 @@ static void imap_add_folder(char delim, char *folder, int noselect, + + static int compare_names(struct folder_file *a, struct folder_file *b) + { +- return mutt_str_strcmp(a->name, b->name); ++ return mutt_str_strcmp(a->full_path, b->full_path); + } diff --git a/0002-Add-browser_sticky_cursor-default-set.patch b/0002-Add-browser_sticky_cursor-default-set.patch new file mode 100644 index 000000000..2ae3a3616 --- /dev/null +++ b/0002-Add-browser_sticky_cursor-default-set.patch @@ -0,0 +1,361 @@ +From 0fa710308f8ad337376bee1af6bd73595a71cadb Mon Sep 17 00:00:00 2001 +From: Kevin McCarthy +Date: Sun, 8 Sep 2019 10:49:37 -0700 +Subject: Add $browser_sticky_cursor default set + +This option attempts to keep the browser cursor on the same mailbox. + +It does this by keeping track of the current selected mailbox and +comparing that when regenerating the menu. + +Modify imap_mailbox_create() and imap_mailbox_rename() to return the +new mailbox name so it can be automatically selected. + +Upstream-commit: https://gitlab.com/muttmua/mutt/commit/0fa710308f8ad337376bee1af6bd73595a71cadb +Co-authored-by: +--- + browser.c | 63 +++++++++++++++++++++++++++++++++++---------- + imap/browse.c | 8 ++++-- + imap/imap.h | 4 +-- + imap/imap_private.h | 1 + + imap/util.c | 10 +++++++ + init.h | 9 +++++++ + mutt.h | 1 + + 7 files changed, 78 insertions(+), 18 deletions(-) + +diff --git a/browser.c b/browser.c +index 56ce75d2..c75406ca 100644 +--- a/browser.c ++++ b/browser.c +@@ -601,9 +601,10 @@ static void folder_entry(char *s, size_t slen, struct Menu *menu, int num) + } + + static void init_menu(struct browser_state *state, struct Menu *menu, char *title, +- size_t titlelen, int mailbox) ++ size_t titlelen, int mailbox, const char *defaultsel) + { + struct Buffer *path = NULL; ++ int i; + + path = mutt_buffer_pool_get(); + +@@ -635,6 +636,18 @@ static void init_menu(struct browser_state *state, struct Menu *menu, char *title, + } + menu->redraw = REDRAW_FULL; + ++ if (option(OPTBROWSERSTICKYCURSOR) && defaultsel && *defaultsel) ++ { ++ for (i = 0; i < menu->max; i++) ++ { ++ if (!mutt_str_strcmp(defaultsel, state->entry[i].full_path)) ++ { ++ menu->current = i; ++ break; ++ } ++ } ++ } ++ + mutt_buffer_pool_release(&path); + } + +@@ -674,6 +687,7 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + struct Buffer *prefix = NULL; + struct Buffer *tmp = NULL; + struct Buffer *OldLastDir = NULL; ++ struct Buffer *defaultsel = NULL; + char helpstr[1024]; + char title[256]; + struct browser_state state; +@@ -691,6 +705,7 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + prefix = mutt_buffer_pool_get(); + tmp = mutt_buffer_pool_get(); + OldLastDir = mutt_buffer_pool_get(); ++ defaultsel = mutt_buffer_pool_get(); + + memset(&state, 0, sizeof(struct browser_state)); + +@@ -757,6 +772,9 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + else if (!*(mutt_b2s(LastDir))) + mutt_buffer_strcpy(LastDir, NONULL(Folder)); + ++ if (Context) ++ mutt_buffer_strcpy(defaultsel, NONULL(Context->path)); ++ + #ifdef USE_IMAP + if (!mailbox && mx_is_imap(mutt_b2s(LastDir))) + { +@@ -803,11 +821,16 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + FolderHelp); + mutt_menu_push_current(menu); + +- init_menu(&state, menu, title, sizeof(title), mailbox); ++ init_menu(&state, menu, title, sizeof(title), mailbox, mutt_b2s(defaultsel)); + + FOREVER + { +- switch(op = mutt_menu_loop(menu)) ++ op = mutt_menu_loop(menu); ++ ++ if (state.entrylen) ++ mutt_buffer_strcpy(defaultsel, state.entry[menu->current].full_path); ++ ++ switch(op) + { + case OP_DESCEND_DIRECTORY: + case OP_GENERIC_SELECT_ENTRY: +@@ -836,6 +859,13 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + /* save the old directory */ + mutt_buffer_strcpy(OldLastDir, mutt_b2s(LastDir)); + ++ mutt_buffer_strcpy(defaultsel, mutt_b2s(OldLastDir)); ++ if (mutt_buffer_len(defaultsel) && (*(defaultsel->dptr - 1) == '/')) ++ { ++ defaultsel->dptr--; ++ *(defaultsel->dptr) = '\0'; ++ } ++ + if (mutt_str_strcmp(state.entry[menu->current].display_name, "..") == 0) + { + size_t lastdirlen = mutt_buffer_len(LastDir); +@@ -921,7 +951,7 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + } + menu->current = 0; + menu->top = 0; +- init_menu(&state, menu, title, sizeof(title), mailbox); ++ init_menu(&state, menu, title, sizeof(title), mailbox, mutt_b2s(defaultsel)); + break; + } + } +@@ -992,7 +1022,7 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + break; + } + +- if (!imap_mailbox_create(mutt_b2s(LastDir))) ++ if (!imap_mailbox_create(mutt_b2s(LastDir), defaultsel)) + { + /* TODO: find a way to detect if the new folder would appear in + * this window, and insert it without starting over. */ +@@ -1004,7 +1034,7 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + menu->data = state.entry; + menu->current = 0; + menu->top = 0; +- init_menu(&state, menu, title, sizeof(title), mailbox); ++ init_menu(&state, menu, title, sizeof(title), mailbox, mutt_b2s(defaultsel)); + } + /* else leave error on screen */ + break; +@@ -1016,7 +1046,7 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + { + int nentry = menu->current; + +- if (imap_mailbox_rename(state.entry[nentry].full_path) >= 0) ++ if (imap_mailbox_rename(state.entry[nentry].full_path, defaultsel) >= 0) + { + destroy_state(&state); + init_state(&state, NULL); +@@ -1026,7 +1056,7 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + menu->data = state.entry; + menu->current = 0; + menu->top = 0; +- init_menu(&state, menu, title, sizeof(title), mailbox); ++ init_menu(&state, menu, title, sizeof(title), mailbox, mutt_b2s(defaultsel)); + } + } + break; +@@ -1063,7 +1093,8 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + sizeof(struct folder_file)); + state.entrylen--; + mutt_message _("Mailbox deleted."); +- init_menu(&state, menu, title, sizeof(title), mailbox); ++ mutt_buffer_clear(defaultsel); ++ init_menu(&state, menu, title, sizeof(title), mailbox, mutt_b2s(defaultsel)); + } + else + mutt_error _("Mailbox deletion failed."); +@@ -1078,6 +1109,7 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + case OP_CHANGE_DIRECTORY: + + mutt_buffer_strcpy(buf, mutt_b2s(LastDir)); ++ mutt_buffer_clear(defaultsel); + #ifdef USE_IMAP + if (!state.imap_browse) + #endif +@@ -1107,7 +1139,7 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + menu->data = state.entry; + menu->current = 0; + menu->top = 0; +- init_menu(&state, menu, title, sizeof(title), mailbox); ++ init_menu(&state, menu, title, sizeof(title), mailbox, mutt_b2s(defaultsel)); + } + else + #endif +@@ -1136,7 +1168,7 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + } + menu->current = 0; + menu->top = 0; +- init_menu(&state, menu, title, sizeof(title), mailbox); ++ init_menu(&state, menu, title, sizeof(title), mailbox, mutt_b2s(defaultsel)); + } + else + mutt_error(_("%s is not a directory."), mutt_b2s(buf)); +@@ -1195,12 +1227,12 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + imap_browse(mutt_b2s(LastDir), &state); + browser_sort(&state); + menu->data = state.entry; +- init_menu(&state, menu, title, sizeof(title), mailbox); ++ init_menu(&state, menu, title, sizeof(title), mailbox, mutt_b2s(defaultsel)); + } + else + #endif + if (examine_directory(menu, &state, mutt_b2s(LastDir), NULL) == 0) +- init_menu(&state, menu, title, sizeof(title), mailbox); ++ init_menu(&state, menu, title, sizeof(title), mailbox, mutt_b2s(defaultsel)); + else + { + mutt_error _("Error scanning directory."); +@@ -1268,6 +1300,8 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + + case OP_TOGGLE_MAILBOXES: + mailbox = 1 - mailbox; ++ menu->current = 0; ++ /* fall through */ + + case OP_CHECK_NEW: + destroy_state(&state); +@@ -1291,7 +1325,7 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + #endif + else if (examine_directory(menu, &state, mutt_b2s(LastDir), mutt_b2s(prefix)) == -1) + goto bail; +- init_menu(&state, menu, title, sizeof(title), mailbox); ++ init_menu(&state, menu, title, sizeof(title), mailbox, mutt_b2s(defaultsel)); + break; + + case OP_MAILBOX_LIST: +@@ -1356,6 +1390,7 @@ bail: + mutt_buffer_pool_release(&prefix); + mutt_buffer_pool_release(&tmp); + mutt_buffer_pool_release(&OldLastDir); ++ mutt_buffer_pool_release(&defaultsel); + + if (menu) + { +diff --git a/imap/browse.c b/imap/browse.c +index 277444aa..fee412d6 100644 +--- a/imap/browse.c ++++ b/imap/browse.c +@@ -229,7 +229,7 @@ fail: + } + + /* imap_mailbox_create: Prompt for a new mailbox name, and try to create it */ +-int imap_mailbox_create(const char* folder) ++int imap_mailbox_create(const char* folder, struct Buffer *result) + { + IMAP_DATA* idata; + IMAP_MBOX mx; +@@ -272,6 +272,8 @@ int imap_mailbox_create(const char* folder) + if (imap_create_mailbox(idata, buf) < 0) + goto fail; + ++ imap_buffer_qualify_path(result, &mx, buf); ++ + mutt_message _("Mailbox created."); + mutt_sleep(0); + +@@ -283,7 +285,7 @@ fail: + return -1; + } + +-int imap_mailbox_rename(const char* mailbox) ++int imap_mailbox_rename(const char* mailbox, struct Buffer *result) + { + IMAP_DATA* idata; + IMAP_MBOX mx; +@@ -331,6 +333,8 @@ int imap_mailbox_rename(const char* mailbox) + goto fail; + } + ++ imap_buffer_qualify_path(result, &mx, buf); ++ + mutt_message(_("Mailbox renamed.")); + mutt_sleep(0); + +diff --git a/imap/imap.h b/imap/imap.h +index fe99472b..24001c5e 100644 +--- a/imap/imap.h ++++ b/imap/imap.h +@@ -51,8 +51,8 @@ extern struct mx_ops mx_imap_ops; + + /* imap/browse.c */ + int imap_browse(const char* path, struct browser_state* state); +-int imap_mailbox_create(const char* folder); +-int imap_mailbox_rename(const char* mailbox); ++int imap_mailbox_create(const char* folder, struct Buffer *result); ++int imap_mailbox_rename(const char* mailbox, struct Buffer *result); + + /* imap/message.c */ + int imap_append_message(struct Context* ctx, struct Message* msg); +diff --git a/imap/imap_private.h b/imap/imap_private.h +index 7d12ec25..67376d2b 100644 +--- a/imap/imap_private.h ++++ b/imap/imap_private.h +@@ -323,6 +323,7 @@ char* imap_next_word(char* s); + time_t mutt_date_parse_imap(char* s); + void mutt_date_make_imap(char* buf, time_t timestamp); + void imap_qualify_path(char *dest, size_t len, IMAP_MBOX *mx, char* path); ++void imap_buffer_qualify_path(struct Buffer *dest, IMAP_MBOX *mx, char* path); + void imap_quote_string(char* dest, size_t dlen, const char* src); + void imap_quote_string_and_backquotes(char *dest, size_t dlen, const char *src); + void imap_unquote_string(char* s); +diff --git a/imap/util.c b/imap/util.c +index 01b57d08..315e77d8 100644 +--- a/imap/util.c ++++ b/imap/util.c +@@ -707,6 +707,16 @@ void imap_qualify_path(char *dest, size_t len, IMAP_MBOX *mx, char* path) + url_tostring(&url, dest, len, 0); + } + ++void imap_buffer_qualify_path(struct Buffer *dest, IMAP_MBOX *mx, char* path) ++{ ++ struct Url url; ++ ++ mutt_account_tourl(&mx->account, &url); ++ url.path = path; ++ ++ url_ciss_tobuffer(&url, dest, 0); ++} ++ + + static void _imap_quote_string(char *dest, size_t dlen, const char *src, + const char *to_quote) +diff --git a/init.h b/init.h +index 2f450a43..39e5d8cd 100644 +--- a/init.h ++++ b/init.h +@@ -422,6 +422,15 @@ struct option_t MuttVars[] = { + ** doesn't make intuitive sense. In those cases, it may be + ** desirable to \fIunset\fP this variable. + */ ++ { "browser_sticky_cursor", DT_BOOL, R_NONE, {.l=OPTBROWSERSTICKYCURSOR}, {.l=1} }, ++ /* ++ ** .pp ++ ** When this variable is \fIset\fP, the browser will attempt to keep ++ ** the cursor on the same mailbox when performing various functions. ++ ** These include moving up a directory, toggling between mailboxes ++ ** and directory listing, creating/renaming a mailbox, toggling ++ ** subscribed mailboxes, and entering a new mask. ++ */ + #if defined(USE_SSL) + { "certificate_file", DT_STRING|DT_PATH, R_NONE, {.p=&CertificateFile}, {.p="~/.mutt_certificates"} }, + /* +diff --git a/mutt.h b/mutt.h +index ce9056d7..549a4dde 100644 +--- a/mutt.h ++++ b/mutt.h +@@ -392,6 +392,7 @@ enum + C_ChangeFolderNext, + C_BrailleFriendly, + C_BrowserAbbreviateMailboxes, ++ OPTBROWSERSTICKYCURSOR, + C_CheckMboxSize, + C_CheckNew, + C_CollapseUnread, diff --git a/0003-Convert-remaining-mutt_encode_path-call-to-use-buffer.patch b/0003-Convert-remaining-mutt_encode_path-call-to-use-buffer.patch new file mode 100644 index 000000000..5a7dfe111 --- /dev/null +++ b/0003-Convert-remaining-mutt_encode_path-call-to-use-buffer.patch @@ -0,0 +1,105 @@ +From 2e6d4903a1e81f673ba2b66ab372dd09f95d6d5a Mon Sep 17 00:00:00 2001 +From: Kevin McCarthy +Date: Mon, 9 Sep 2019 14:06:31 -0700 +Subject: Convert remaining mutt_encode_path() call to use struct Buffer + +Then rename the other uses of mutt_buffer_encode_path() to +mutt_encode_path(). + +Upstream-commit: https://gitlab.com/muttmua/mutt/commit/2e6d4903a1e81f673ba2b66ab372dd09f95d6d5a +Co-authored-by: +--- + bcache.c | 2 +- + hcache/hcache.c | 16 +++++++++------- + muttlib.c | 11 +---------- + protos.h | 3 +-- + 4 files changed, 12 insertions(+), 20 deletions(-) + +diff --git a/bcache.c b/bcache.c +index 0fef6c32..b6925d4a 100644 +--- a/bcache.c ++++ b/bcache.c +@@ -62,7 +62,7 @@ static int bcache_path(struct Account *account, const char *mailbox, struct BodyCache *bcac + + path = mutt_buffer_pool_get(); + dst = mutt_buffer_pool_get(); +- mutt_buffer_encode_path(path, NONULL(mailbox)); ++ mutt_encode_path(path, NONULL(mailbox)); + + mutt_buffer_printf(dst, "%s/%s%s", C_MessageCachedir, host, mutt_b2s(path)); + if (*(dst->dptr - 1) != '/') +diff --git a/hcache/hcache.c b/hcache/hcache.c +index 07f3fbd3..b8d7a9da 100644 +--- a/hcache/hcache.c ++++ b/hcache/hcache.c +@@ -995,25 +995,27 @@ mutt_hcache_store_raw(header_cache_t* h, const char* filename, void* data, + #endif + } + +-static char* get_foldername(const char *folder) ++static char* get_foldername(const char *folder) + { + char *p = NULL; +- char path[PATH_MAX]; ++ struct Buffer *path; + struct stat st; + +- mutt_encode_path(path, sizeof(path), folder); ++ path = mutt_buffer_pool_get(); ++ mutt_encode_path(path, folder); + + /* if the folder is local, canonify the path to avoid + * to ensure equivalent paths share the hcache */ +- if (stat(path, &st) == 0) ++ if (stat(mutt_b2s(path), &st) == 0) + { + p = mutt_mem_malloc(PATH_MAX+1); +- if (!realpath(path, p)) +- mutt_str_replace(&p, path); ++ if (!realpath(mutt_b2s(path), p)) ++ mutt_str_replace(&p, mutt_b2s(path)); + } + else +- p = mutt_str_strdup(path); ++ p = mutt_str_strdup(mutt_b2s(path)); + ++ mutt_buffer_pool_release(&path); + return p; + } + +diff --git a/muttlib.c b/muttlib.c +index 82f90faf..69641230 100644 +--- a/muttlib.c ++++ b/muttlib.c +@@ -2247,16 +2247,7 @@ int mutt_replacelist_match(const char *s, struct ReplaceList *l, char *text, int textsi + return 0; + } + +-void mutt_encode_path(char *dest, size_t dlen, const char *src) +-{ +- char *p = mutt_str_strdup(src); +- int rc = mutt_cs_convert_string(&p, C_Charset, "utf-8", 0); +- /* `src' may be NULL, such as when called from the pop3 driver. */ +- mutt_str_strfcpy(dest, (rc == 0) ? NONULL(p) : NONULL(src), dlen); +- FREE(&p); +-} +- +-void mutt_buffer_encode_path(struct Buffer *dest, const char *src) ++void mutt_encode_path(struct Buffer *dest, const char *src) + { + char *p; + int rc; +diff --git a/protos.h b/protos.h +index 66348bc3..f747bcb9 100644 +--- a/protos.h ++++ b/protos.h +@@ -204,8 +204,7 @@ int mutt_label_complete(char *, size_t, int); + void mutt_curses_error(const char *, ...); + void mutt_curses_message(const char *, ...); + void mutt_encode_descriptions(struct Body *, short); +-void mutt_encode_path(char *, size_t, const char *); +-void mutt_buffer_encode_path(struct Buffer *, const char *); ++void mutt_encode_path(struct Buffer *, const char *); + void mutt_enter_command(void); + void mutt_error_history_display(void); + void mutt_error_history_init(void); diff --git a/0004-Change-browser-display-filename-to-show-full_path.patch b/0004-Change-browser-display-filename-to-show-full_path.patch new file mode 100644 index 000000000..0aa982e35 --- /dev/null +++ b/0004-Change-browser-display-filename-to-show-full_path.patch @@ -0,0 +1,30 @@ +From 773166e9ef0a2bc3eca93a8e16560fa4571673ad Mon Sep 17 00:00:00 2001 +From: Kevin McCarthy +Date: Mon, 9 Sep 2019 18:19:03 -0700 +Subject: Change browser to show full_path + +Prior to the introduction of display_name/full_path, it showed "name", +which was the full IMAP URL but the shortname for folder/mailbox view. + +Now that the full_path is available, it makes sense to show that for +all cases. + +Upstream-commit: https://gitlab.com/muttmua/mutt/commit/773166e9ef0a2bc3eca93a8e16560fa4571673ad +Co-authored-by: +--- + browser.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/browser.c b/browser.c +index c75406ca..4e45013d 100644 +--- a/browser.c ++++ b/browser.c +@@ -994,7 +994,7 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + + case OP_BROWSER_TELL: + if (state.entrylen) +- mutt_message("%s", state.entry[menu->current].display_name); ++ mutt_message("%s", state.entry[menu->current].full_path); + break; + + #ifdef USE_IMAP diff --git a/0005-Improve-sidebar-indentation-and-shortpath-behavior.patch b/0005-Improve-sidebar-indentation-and-shortpath-behavior.patch new file mode 100644 index 000000000..9abd76886 --- /dev/null +++ b/0005-Improve-sidebar-indentation-and-shortpath-behavior.patch @@ -0,0 +1,264 @@ +From a4b53e19ef471efc1938348d1623b811354f1c93 Mon Sep 17 00:00:00 2001 +From: Kevin McCarthy +Date: Sun, 15 Sep 2019 15:41:42 -0700 +Subject: Improve sidebar indentation and shortpath behavior + +The previous implementation only enabled $sidebar_folder_indent for +mailboxes underneath $folder. Change indentation to be based upon the +previous common-path mailbox in the list. Indent one more than the +common-path mailbox, rather than the number of delimiters after +$folder. + +Change $sidebar_short_path to shorten based on the previous mailbox in +the list too. + +Invoke mutt_buffer_pretty_mailbox() to prefix the mailbox with '~' or +'=' characters. This changes the output for the case where mailbox +equals $folder, but provides uniform display behavior across mutt. + +Thanks to Christopher Zimmermann(@madroach) for the original patch, +which this commit is based upon. + +Upstream-commit: https://gitlab.com/muttmua/mutt/commit/a4b53e19ef471efc1938348d1623b811354f1c93 +Co-authored-by: +--- + sidebar.c | 194 +++++++++++++++++++++++++++++++++++++++--------------- + 1 file changed, 140 insertions(+), 54 deletions(-) + +diff --git a/sidebar.c b/sidebar.c +index 9df19872..364b2285 100644 +--- a/sidebar.c ++++ b/sidebar.c +@@ -520,6 +520,79 @@ static void fill_empty_space(int first_row, int num_rows, int width) + } + } + ++/** ++ * calculate_depth - Calculate depth of path based on C_SidebarDelimChars. ++ * ++ * If lastpath is not NULL, common_depth is also calculated. These ++ * are used for indentation and short_path calculation. ++ */ ++static void calculate_depth(const char *path, const char *lastpath, ++ int *depth, int *common_depth) ++{ ++ int i, has_trailing_delim = 0; ++ ++ *depth = *common_depth = 0; ++ if (!C_SidebarDelimChars || !path) ++ return; ++ ++ for (i = 0; path[i]; i++) ++ { ++ if (strchr(C_SidebarDelimChars, path[i])) ++ { ++ (*depth)++; ++ ++ /* /a/b/c and /a/b/c/ both are a depth of 3. ++ * Only count the final '\0' if the last character wasn't a separator. ++ */ ++ if (!path[i+1]) ++ has_trailing_delim = 1; ++ } ++ ++ if (lastpath) ++ { ++ /* path /a/b/c/d ++ * lastpath /a/b ++ * lastpath /a/ ++ * lastpath /a ++ * ^ ++ */ ++ if (strchr(C_SidebarDelimChars, path[i]) && ++ (strchr(C_SidebarDelimChars, lastpath[i]) || !lastpath[i])) ++ { ++ (*common_depth)++; ++ if (!lastpath[i]) ++ lastpath = NULL; ++ } ++ ++ /* path /abc ++ * lastpath /ad ++ * lastpath /a/ ++ * lastpath /a ++ * ^ ++ */ ++ else if (!lastpath[i] || path[i] != lastpath[i]) ++ lastpath = NULL; ++ } ++ } ++ ++ if (!has_trailing_delim) ++ { ++ (*depth)++; ++ ++ /* path /a ++ * lastpath /a/b/c ++ * lastpath /a/ ++ * lastpath /a ++ * ^ ++ */ ++ if (lastpath && ++ (strchr(C_SidebarDelimChars, lastpath[i]) || !lastpath[i])) ++ (*common_depth)++; ++ } ++} ++ ++#define SIDEBAR_MAX_INDENT 32 ++ + /** + * draw_sidebar - Write out a list of mailboxes, on the left + * @num_rows: Height of the Sidebar +@@ -546,9 +619,18 @@ static void draw_sidebar(int num_rows, int num_cols, int div_width) + int entryidx; + struct SbEntry *entry; + struct Mailbox *b; ++ int indent_width = -1; ++ int indent_depths[SIDEBAR_MAX_INDENT]; ++ const char *sidebar_folder_name; ++ struct Buffer *pretty_folder_name, *last_folder_name, *indent_folder_name; ++ + if (TopIndex < 0) + return; + ++ pretty_folder_name = mutt_buffer_pool_get(); ++ last_folder_name = mutt_buffer_pool_get(); ++ indent_folder_name = mutt_buffer_pool_get(); ++ + int w = MIN(num_cols, (C_SidebarWidth - div_width)); + int row = 0; + for (entryidx = TopIndex;(entryidx < EntryCount) && (row < num_rows); entryidx++) +@@ -586,75 +668,79 @@ static void draw_sidebar(int num_rows, int num_cols, int div_width) + b->msg_flagged = Context->flagged; + } + +- /* compute length of Folder without trailing separator */ +- size_t maildirlen = mutt_str_strlen(Folder); +- if (maildirlen && +- C_SidebarDelimChars && +- strchr(C_SidebarDelimChars, Folder[maildirlen - 1])) +- maildirlen--; +- +- /* check whether Folder is a prefix of the current folder's path */ +- short maildir_is_prefix = 0; +- if ((mutt_buffer_len(b->pathbuf) > maildirlen) && +- (mutt_str_strncmp(Folder, mutt_b2s(b->pathbuf), maildirlen) == 0) && +- C_SidebarDelimChars && +- strchr(C_SidebarDelimChars, mutt_b2s(b->pathbuf)[maildirlen])) +- maildir_is_prefix = 1; +- +- /* calculate depth of current folder and generate its display name with indented spaces */ +- int sidebar_folder_depth = 0; +- const char *sidebar_folder_name; +- struct Buffer *short_folder_name = NULL; +- int i; +- if (option(C_SidebarShortPath)) ++ mutt_buffer_strcpy(pretty_folder_name, mutt_b2s(b->pathbuf)); ++ mutt_buffer_pretty_mailbox(pretty_folder_name); ++ sidebar_folder_name = mutt_b2s(pretty_folder_name); ++ ++ if (C_SidebarDelimChars) + { +- /* disregard a trailing separator, so strlen() - 2 */ +- sidebar_folder_name = mutt_b2s(b->pathbuf); +- for (i = mutt_str_strlen(sidebar_folder_name) - 2; i >= 0; i--) ++ int parent_depth = 0; ++ int i; ++ ++ if (option(C_SidebarShortPath) || option(C_SidebarFolderIndent)) + { +- if (C_SidebarDelimChars && +- strchr(C_SidebarDelimChars, sidebar_folder_name[i])) +- { +- sidebar_folder_name +=(i + 1); +- break; +- } ++ int depth = 0, common_depth = 0; ++ ++ calculate_depth(sidebar_folder_name, mutt_b2s(last_folder_name), ++ &depth, &common_depth); ++ mutt_buffer_strcpy(last_folder_name, sidebar_folder_name); ++ ++ if (indent_width < SIDEBAR_MAX_INDENT) ++ indent_width++; ++ ++ /* indent_depths[] hold the path depths at each level of indentation. ++ * Indent based off the longest path that we share in common. ++ * ++ * The 'indent_depths[] >= depth' test below is for a corner case: ++ * ++ * path depth common_depth indent_width ++ * /a 2 0 0 ++ * /a/b 3 2 1 ++ * /a/b/ 3 3 1 ++ * ++ * Because the common_depth of /a/b/ matches the depth of ++ * /a/b, we need the additional test to continue popping the ++ * indent_depths[] stack. ++ */ ++ while (indent_width && ++ ((indent_depths[indent_width - 1] > common_depth) || ++ (indent_depths[indent_width - 1] >= depth))) ++ indent_width--; ++ ++ if (indent_width < SIDEBAR_MAX_INDENT) ++ indent_depths[indent_width] = depth; ++ if (indent_width) ++ parent_depth = indent_depths[indent_width - 1]; + } +- } +- else +- sidebar_folder_name = mutt_b2s(b->pathbuf) + maildir_is_prefix *(maildirlen + 1); + +- if (maildir_is_prefix && option(C_SidebarFolderIndent)) +- { +- const char *tmp_folder_name; +- int lastsep = 0; +- tmp_folder_name = mutt_b2s(b->pathbuf) + maildirlen + 1; +- int tmplen =(int) mutt_str_strlen(tmp_folder_name) - 1; +- for (i = 0; i < tmplen; i++) ++ if (option(C_SidebarShortPath) && parent_depth) + { +- if (C_SidebarDelimChars && strchr(C_SidebarDelimChars, tmp_folder_name[i])) +- { +- sidebar_folder_depth++; +- lastsep = i + 1; +- } ++ for (i = 0; parent_depth && sidebar_folder_name[i]; i++) ++ if (strchr(C_SidebarDelimChars, sidebar_folder_name[i])) ++ parent_depth--; ++ sidebar_folder_name += i; + } +- if (sidebar_folder_depth > 0) ++ ++ if (option(C_SidebarFolderIndent) && indent_width) + { +- if (option(C_SidebarShortPath)) +- tmp_folder_name += lastsep; /* basename */ +- short_folder_name = mutt_buffer_pool_get(); +- for (i=0; i < sidebar_folder_depth; i++) +- mutt_buffer_addstr(short_folder_name, NONULL(C_SidebarIndentString)); +- mutt_buffer_addstr(short_folder_name, tmp_folder_name); +- sidebar_folder_name = mutt_b2s(short_folder_name); ++ mutt_buffer_clear(indent_folder_name); ++ for (i = 0; i < indent_width; i++) ++ mutt_buffer_addstr(indent_folder_name, NONULL(C_SidebarIndentString)); ++ mutt_buffer_addstr(indent_folder_name, sidebar_folder_name); ++ sidebar_folder_name = mutt_b2s(indent_folder_name); + } + } ++ + char str[256]; + make_sidebar_entry(str, sizeof(str), w, sidebar_folder_name, entry); + printw("%s", str); +- mutt_buffer_pool_release(&short_folder_name); + row++; + } + ++ mutt_buffer_pool_release(&pretty_folder_name); ++ mutt_buffer_pool_release(&last_folder_name); ++ mutt_buffer_pool_release(&indent_folder_name); ++ + fill_empty_space(row, num_rows - row, w); + } + diff --git a/0006-Memcpy-header-cache-fetch-values-to-ensure-alignment.patch b/0006-Memcpy-header-cache-fetch-values-to-ensure-alignment.patch new file mode 100644 index 000000000..657d0c059 --- /dev/null +++ b/0006-Memcpy-header-cache-fetch-values-to-ensure-alignment.patch @@ -0,0 +1,218 @@ +From a6bccbe1d1b731e69b2b609278ef0811d547a6e7 Mon Sep 17 00:00:00 2001 +From: Kevin McCarthy +Date: Mon, 30 Sep 2019 18:50:27 -0700 +Subject: Memcpy header cache fetch values to ensure alignment + +While testing the hcache buffer pool changes, I noticed a misaligned +pointer warning when using LMDB. + +The other header cache backends must ensure alignment of the pointer +they return, but LMDB apparently does not. + +Instead of directly assigning and dereferencing the pointer fetched, +use memcpy to the appropriate type, just as the header cache restore +operation does. + +Upstream-commit: https://gitlab.com/muttmua/mutt/commit/a6bccbe1d1b731e69b2b609278ef0811d547a6e7 +Co-authored-by: +--- + imap/imap.c | 40 ++++++++++++++++++++++++---------------- + imap/message.c | 19 +++++++++++-------- + imap/util.c | 18 ++++++++++-------- + maildir/mh.c | 7 ++++--- + 4 files changed, 49 insertions(+), 35 deletions(-) + +diff --git a/imap/imap.c b/imap/imap.c +index ccba3a38..33469f5f 100644 +--- a/imap/imap.c ++++ b/imap/imap.c +@@ -1800,9 +1800,9 @@ IMAP_STATUS* imap_mboxcache_get(IMAP_DATA* idata, const char* mbox, int create) + IMAP_STATUS scache; + #ifdef USE_HCACHE + header_cache_t *hc = NULL; +- unsigned int *uidvalidity = NULL; +- unsigned int *uidnext = NULL; +- unsigned long long *modseq = NULL; ++ void *puidvalidity = NULL; ++ void *puidnext = NULL; ++ void *pmodseq = NULL; + #endif + + for (cur = idata->mboxcache; cur; cur = cur->next) +@@ -1829,28 +1829,36 @@ IMAP_STATUS* imap_mboxcache_get(IMAP_DATA* idata, const char* mbox, int create) + hc = imap_hcache_open(idata, mbox); + if (hc) + { +- uidvalidity = mutt_hcache_fetch_raw(hc, "/UIDVALIDITY", imap_hcache_keylen); +- uidnext = mutt_hcache_fetch_raw(hc, "/UIDNEXT", imap_hcache_keylen); +- modseq = mutt_hcache_fetch_raw(hc, "/MODSEQ", imap_hcache_keylen); +- if (uidvalidity) ++ puidvalidity = mutt_hcache_fetch_raw(hc, "/UIDVALIDITY", imap_hcache_keylen); ++ puidnext = mutt_hcache_fetch_raw(hc, "/UIDNEXT", imap_hcache_keylen); ++ pmodseq = mutt_hcache_fetch_raw(hc, "/MODSEQ", imap_hcache_keylen); ++ if (puidvalidity) + { + if (!status) + { +- mutt_hcache_free((void **)&uidvalidity); +- mutt_hcache_free((void **)&uidnext); +- mutt_hcache_free((void **)&modseq); ++ mutt_hcache_free((void **)&puidvalidity); ++ mutt_hcache_free((void **)&puidnext); ++ mutt_hcache_free((void **)&pmodseq); + mutt_hcache_close(hc); + return imap_mboxcache_get(idata, mbox, 1); + } +- status->uidvalidity = *uidvalidity; +- status->uidnext = uidnext ? *uidnext: 0; +- status->modseq = modseq ? *modseq: 0; ++ memcpy(&status->uidvalidity, puidvalidity, sizeof(unsigned int)); ++ ++ if (puidnext) ++ memcpy(&status->uidnext, puidnext, sizeof(unsigned int)); ++ else ++ status->uidnext = 0; ++ ++ if (pmodseq) ++ memcpy(&status->modseq, pmodseq, sizeof(unsigned long long)); ++ else ++ status->modseq = 0; + mutt_debug(LL_DEBUG3, "mboxcache: hcache uidvalidity %u, uidnext %u, modseq %llu\n", + status->uidvalidity, status->uidnext, status->modseq); + } +- mutt_hcache_free((void **)&uidvalidity); +- mutt_hcache_free((void **)&uidnext); +- mutt_hcache_free((void **)&modseq); ++ mutt_hcache_free((void **)&puidvalidity); ++ mutt_hcache_free((void **)&puidnext); ++ mutt_hcache_free((void **)&pmodseq); + mutt_hcache_close(hc); + } + #endif +diff --git a/imap/message.c b/imap/message.c +index f32f5db6..48dc0437 100644 +--- a/imap/message.c ++++ b/imap/message.c +@@ -228,14 +228,15 @@ int imap_read_headers(IMAP_DATA* idata, unsigned int msn_begin, unsigned int ms + int evalhc = 0; + + #if USE_HCACHE +- unsigned int *uid_validity = NULL; +- unsigned int *puidnext = NULL; ++ void *puid_validity = NULL; ++ unsigned int uid_validity = 0; ++ void *puidnext = NULL; + unsigned int uidnext = 0; + int has_condstore = 0; + int has_qresync = 0; + int eval_condstore = 0; + int eval_qresync = 0; +- unsigned long long *pmodseq = NULL; ++ void *pmodseq = NULL; + unsigned long long hc_modseq = 0; + char *uid_seqset = NULL; + #endif /* USE_HCACHE */ +@@ -257,11 +258,13 @@ int imap_read_headers(IMAP_DATA* idata, unsigned int msn_begin, unsigned int ms + + if (idata->hcache && initial_download) + { +- uid_validity = mutt_hcache_fetch_raw(idata->hcache, "/UIDVALIDITY", imap_hcache_keylen); ++ puid_validity = mutt_hcache_fetch_raw(idata->hcache, "/UIDVALIDITY", imap_hcache_keylen); ++ if (puid_validity) ++ memcpy(&uid_validity, puid_validity, sizeof(unsigned int)); + puidnext = mutt_hcache_fetch_raw(idata->hcache, "/UIDNEXT", imap_hcache_keylen); + if (puidnext) + { +- uidnext = *puidnext; ++ memcpy(&uidnext, puidnext, sizeof(unsigned int));; + mutt_hcache_free((void **)&puidnext); + } + +@@ -278,13 +281,13 @@ int imap_read_headers(IMAP_DATA* idata, unsigned int msn_begin, unsigned int ms + has_qresync = 1; + } + +- if (uid_validity && uidnext && *uid_validity == idata->uid_validity) ++ if (puid_validity && uidnext && (uid_validity == idata->uid_validity)) + { + evalhc = 1; + pmodseq = mutt_hcache_fetch_raw(idata->hcache, "/MODSEQ", imap_hcache_keylen); + if (pmodseq) + { +- hc_modseq = *pmodseq; ++ memcpy(&hc_modseq, pmodseq, sizeof(unsigned long long));; + mutt_hcache_free((void **)&pmodseq); + } + if (hc_modseq) +@@ -300,7 +303,7 @@ int imap_read_headers(IMAP_DATA* idata, unsigned int msn_begin, unsigned int ms + eval_condstore = 1; + } + } +- mutt_hcache_free((void **)&uid_validity); ++ mutt_hcache_free((void **)&puid_validity); + } + if (evalhc) + { +diff --git a/imap/util.c b/imap/util.c +index 0812bac3..42f07cc2 100644 +--- a/imap/util.c ++++ b/imap/util.c +@@ -179,22 +179,24 @@ void imap_hcache_close(IMAP_DATA* idata) + struct Email* imap_hcache_get(IMAP_DATA* idata, unsigned int uid) + { + char key[16]; +- unsigned int* uv; ++ void *data; ++ unsigned int uv; + struct Email* h = NULL; + + if (!idata->hcache) + return NULL; + + sprintf(key, "/%u", uid); +- uv =(unsigned int*)mutt_hcache_fetch(idata->hcache, key, +- imap_hcache_keylen); +- if (uv) ++ data = mutt_hcache_fetch(idata->hcache, key, ++ imap_hcache_keylen); ++ if (data) + { +- if (*uv == idata->uid_validity) +- h = mutt_hcache_restore((unsigned char*)uv, NULL); ++ memcpy(&uv, data, sizeof(unsigned int)); ++ if (uv == idata->uid_validity) ++ h = mutt_hcache_restore((unsigned char *)data, NULL); + else +- mutt_debug(LL_DEBUG3, "hcache uidvalidity mismatch: %u", *uv); +- mutt_hcache_free((void **)&uv); ++ mutt_debug(LL_DEBUG3, "hcache uidvalidity mismatch: %u", uv); ++ mutt_hcache_free((void **)&data); + } + + return h; +diff --git a/maildir/mh.c b/maildir/mh.c +index 37cef860..ad3c8253 100644 +--- a/maildir/mh.c ++++ b/maildir/mh.c +@@ -1145,7 +1145,7 @@ static void maildir_delayed_parsing(struct Context * ctx, struct maildir **md, + #if USE_HCACHE + header_cache_t *hc = NULL; + void *data; +- struct timeval *when = NULL; ++ struct timeval when; + struct stat lastchanged; + int ret; + #endif +@@ -1207,9 +1207,10 @@ static void maildir_delayed_parsing(struct Context * ctx, struct maildir **md, + data = mutt_hcache_fetch(hc, p->h->path, strlen); + else + data = mutt_hcache_fetch(hc, p->h->path + 3, &maildir_hcache_keylen); +- when =(struct timeval *) data; ++ if (data) ++ memcpy(&when, data, sizeof(struct timeval)); + +- if (data != NULL && !ret && lastchanged.st_mtime <= when->tv_sec) ++ if (data != NULL && !ret && lastchanged.st_mtime <= when.tv_sec) + { + p->h = mutt_hcache_restore((unsigned char *)data, &p->h); + if (ctx->magic == MUTT_MAILDIR) diff --git a/0007-Add-sticky-browser-behavior-for-sorting.patch b/0007-Add-sticky-browser-behavior-for-sorting.patch new file mode 100644 index 000000000..6c163ff6e --- /dev/null +++ b/0007-Add-sticky-browser-behavior-for-sorting.patch @@ -0,0 +1,77 @@ +From fe69e4d1a30aabb70dc4a5890bb7188841b61421 Mon Sep 17 00:00:00 2001 +From: Kevin McCarthy +Date: Wed, 9 Oct 2019 08:36:59 +0800 +Subject: Add sticky browser behavior for sorting + +The menu isn't rebuilt after sorting, so the selected mailbox was not +sticky for that operation. + +Refactor the sticky cursor setting out so it can be explicitly called +after sorting too. + +Upstream-commit: https://gitlab.com/muttmua/mutt/commit/fe69e4d1a30aabb70dc4a5890bb7188841b61421 +Co-authored-by: +--- + browser.c | 31 +++++++++++++++++++------------ + 1 file changed, 19 insertions(+), 12 deletions(-) + +diff --git a/browser.c b/browser.c +index eb212d3e..b560c54d 100644 +--- a/browser.c ++++ b/browser.c +@@ -600,11 +600,27 @@ static void folder_entry(char *s, size_t slen, struct Menu *menu, int num) + (unsigned long) &folder, MUTT_FORMAT_ARROWCURSOR); + } + ++static void set_sticky_cursor(struct browser_state *state, struct Menu *menu, const char *defaultsel) ++{ ++ int i; ++ ++ if (option(OPTBROWSERSTICKYCURSOR) && defaultsel && *defaultsel) ++ { ++ for (i = 0; i < menu->max; i++) ++ { ++ if (!mutt_str_strcmp(defaultsel, state->entry[i].full_path)) ++ { ++ menu->current = i; ++ break; ++ } ++ } ++ } ++} ++ + static void init_menu(struct browser_state *state, struct Menu *menu, char *title, + size_t titlelen, int mailbox, const char *defaultsel) + { + struct Buffer *path = NULL; +- int i; + + path = mutt_buffer_pool_get(); + +@@ -636,17 +652,7 @@ static void init_menu(struct browser_state *state, struct Menu *menu, char *title, + } + menu->redraw = REDRAW_FULL; + +- if (option(OPTBROWSERSTICKYCURSOR) && defaultsel && *defaultsel) +- { +- for (i = 0; i < menu->max; i++) +- { +- if (!mutt_str_strcmp(defaultsel, state->entry[i].full_path)) +- { +- menu->current = i; +- break; +- } +- } +- } ++ set_sticky_cursor(state, menu, defaultsel); + + mutt_buffer_pool_release(&path); + } +@@ -1290,6 +1296,7 @@ void _mutt_buffer_select_file(struct Buffer *f, int flags, char ***files, int *numfile + { + SortBrowser |= reverse ? SORT_REVERSE : 0; + browser_sort(&state); ++ set_sticky_cursor(&state, menu, mutt_b2s(defaultsel)); + menu->redraw = REDRAW_FULL; + } + break; diff --git a/0008-Add-new-browse-mailboxes-function-in-index-and-pager.patch b/0008-Add-new-browse-mailboxes-function-in-index-and-pager.patch new file mode 100644 index 000000000..a3c6273b7 --- /dev/null +++ b/0008-Add-new-browse-mailboxes-function-in-index-and-pager.patch @@ -0,0 +1,139 @@ +From 0e32b977454de79899c497debcd460470e720e7a Mon Sep 17 00:00:00 2001 +From: Kevin McCarthy +Date: Thu, 10 Oct 2019 15:03:05 +0800 +Subject: Add new browse-mailboxes function in index and pager + +This allows direct access to the mailboxes list in the folder menu. +This is useful, for instance, if $browser_sticky_cursor is set and the +current directory does not contain the open mailbox. The macro +version will lose the current mailbox while toggling to the mailboxes +list. + +Upstream-commit: https://gitlab.com/muttmua/mutt/commit/0e32b977454de79899c497debcd460470e720e7a +Co-authored-by: +--- + opcodes.h | 2 ++ + index.c | 31 +++++++++++++++++++------------ + doc/neomuttrc.head | 5 +++-- + functions.h | 4 ++++ + 4 files changed, 28 insertions(+), 14 deletions(-) + +diff --git a/opcodes.h b/opcodes.h +index a91a14ab..4e3bd1d0 100644 +--- a/opcodes.h ++++ b/opcodes.h +@@ -109,6 +109,8 @@ OP_LIST_REPLY "reply to specified mailing list" + OP_MACRO "execute a macro" + OP_MAIL "compose a new mail message" + OP_MAIN_BREAK_THREAD "break the thread in two" ++OP_MAIN_BROWSE_MAILBOXES "select a new mailbox from the browser" ++OP_MAIN_BROWSE_MAILBOXES_READONLY "select a new mailbox from the browser in read only mode" + OP_MAIN_CHANGE_FOLDER "open a different folder" + OP_MAIN_CHANGE_FOLDER_READONLY "open a different folder in read only mode" + OP_MAIN_CLEAR_FLAG "clear a status flag from a message" +diff --git a/index.c b/index.c +index 919cf154..4e0f6e86 100644 +--- a/index.c ++++ b/index.c +@@ -1266,8 +1266,13 @@ int mutt_index_menu(void) + if (attach_msg) + op = OP_MAIN_CHANGE_FOLDER_READONLY; + ++ case OP_MAIN_BROWSE_MAILBOXES: ++ if (attach_msg && (op != OP_MAIN_CHANGE_FOLDER_READONLY)) ++ op = OP_MAIN_BROWSE_MAILBOXES_READONLY; ++ + /* fallback to the readonly case */ + ++ case OP_MAIN_BROWSE_MAILBOXES_READONLY: + case OP_MAIN_CHANGE_FOLDER_READONLY: + { + struct Buffer *folderbuf; +@@ -1293,13 +1298,13 @@ int mutt_index_menu(void) + } + #ifdef USE_SIDEBAR + else if (op == OP_SIDEBAR_OPEN) +- { +- const char *path = mutt_sb_get_highlight(); +- if (!path || !*path) +- goto changefoldercleanup; +- mutt_buffer_strcpy(folderbuf, path); +- } ++ mutt_buffer_strcpy(folderbuf, NONULL(mutt_sb_get_highlight())); + #endif ++ ++ else if ((op == OP_MAIN_BROWSE_MAILBOXES) || ++ (op == OP_MAIN_BROWSE_MAILBOXES_READONLY)) ++ mutt_buffer_select_file(folderbuf, MUTT_SEL_FOLDER | MUTT_SEL_MAILBOX); ++ + else + { + if (option(C_ChangeFolderNext) && Context && Context->path) +@@ -1318,13 +1323,13 @@ int mutt_index_menu(void) + } + goto changefoldercleanup; + } +- if (!mutt_buffer_len(folderbuf)) +- { +- mutt_window_clearline(MuttMessageWindow, 0); +- goto changefoldercleanup; +- } + } + ++ if (!mutt_buffer_len(folderbuf)) ++ { ++ mutt_window_clearline(MuttMessageWindow, 0); ++ goto changefoldercleanup; ++ } + mutt_buffer_expand_path(folderbuf); + if (mx_get_magic(mutt_b2s(folderbuf)) <= 0) + { +@@ -1386,7 +1391,9 @@ int mutt_index_menu(void) + mutt_folder_hook(mutt_b2s(folderbuf)); + + if ((Context = mx_open_mailbox(mutt_b2s(folderbuf), +- (option(C_ReadOnly) || op == OP_MAIN_CHANGE_FOLDER_READONLY) ? ++ (option(C_ReadOnly) || ++ op == OP_MAIN_CHANGE_FOLDER_READONLY || ++ op == OP_MAIN_BROWSE_MAILBOXES_READONLY) ? + MUTT_READONLY : 0, NULL)) != NULL) + { + menu->current = ci_first_message(); +diff --git a/doc/neomuttrc.head b/doc/neomuttrc.head +index 2b0020f7..0d2b2f52 100644 +--- a/doc/neomuttrc.head ++++ b/doc/neomuttrc.head +@@ -26,8 +26,9 @@ macro index,pager,attach,compose \cb "\ + macro generic,pager " less @docdir@/manual.txt" "show Mutt documentation" + + # show the incoming mailboxes list(just like "mutt -y") and back when pressing "y" +-macro index y "?" "show incoming mailboxes list" +-macro pager y "?" "show incoming mailboxes list" ++# note: these macros have been subsumed by the function. ++# macro index y "?" "show incoming mailboxes list" ++# macro pager y "?" "show incoming mailboxes list" + bind browser y exit + + # Handler for gzip compressed mailboxes +diff --git a/functions.h b/functions.h +index 419dfc50..ba8340b8 100644 +--- a/functions.h ++++ b/functions.h +@@ -91,6 +91,8 @@ const struct binding_t OpMain[] = { /* map: index */ + #endif + { "bounce-message", OP_BOUNCE_MESSAGE, "b" }, + { "break-thread", OP_MAIN_BREAK_THREAD, "#" }, ++ { "browse-mailboxes", OP_MAIN_BROWSE_MAILBOXES, "y" }, ++ { "browse-mailboxes-readonly", OP_MAIN_BROWSE_MAILBOXES_READONLY, NULL }, + { "change-folder", OP_MAIN_CHANGE_FOLDER, "c" }, + { "change-folder-readonly", OP_MAIN_CHANGE_FOLDER_READONLY, "\033c" }, + { "next-unread-mailbox", OP_MAIN_NEXT_UNREAD_MAILBOX, NULL }, +@@ -195,6 +197,8 @@ const struct binding_t OpMain[] = { /* map: index */ + + const struct binding_t OpPager[] = { /* map: pager */ + { "break-thread", OP_MAIN_BREAK_THREAD, "#" }, ++ { "browse-mailboxes", OP_MAIN_BROWSE_MAILBOXES, "y" }, ++ { "browse-mailboxes-readonly", OP_MAIN_BROWSE_MAILBOXES_READONLY, NULL }, + { "create-alias", OP_CREATE_ALIAS, "a" }, + { "bounce-message", OP_BOUNCE_MESSAGE, "b" }, + { "change-folder", OP_MAIN_CHANGE_FOLDER, "c" }, diff --git a/0009-Update-mime-fields-when-piping-a-message-with-pipe_d.patch b/0009-Update-mime-fields-when-piping-a-message-with-pipe_d.patch new file mode 100644 index 000000000..01fccba29 --- /dev/null +++ b/0009-Update-mime-fields-when-piping-a-message-with-pipe_d.patch @@ -0,0 +1,47 @@ +From 71d6dbea64b3f6d9676867030214236878693bcb Mon Sep 17 00:00:00 2001 +From: Kevin McCarthy +Date: Sun, 13 Oct 2019 16:25:54 +0800 +Subject: Update mime fields when piping a message with $pipe_decode set + +Programs that process the message may get confused if the original +mime fields are in the output. Add the CH_MIME flag to strip mime +headers and CH_TXTPLAIN to add decoded text mime headers in their +place, just as does. + +However, make sure not to add the flags when printing, as printers +highly likely won't care and users probably don't want to see those +headers in their printout. + +Upstream-commit: https://gitlab.com/muttmua/mutt/commit/71d6dbea64b3f6d9676867030214236878693bcb +Co-authored-by: +--- + commands.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/commands.c b/commands.c +index b88335d1..9a27614f 100644 +--- a/commands.c ++++ b/commands.c +@@ -440,14 +440,21 @@ static void pipe_set_flags(int decode, int print, int *cmflags, int *chflags) + { + if (decode) + { +- *cmflags |= MUTT_CM_DECODE | MUTT_CM_CHARCONV; + *chflags |= CH_DECODE | CH_REORDER; ++ *cmflags |= MUTT_CM_DECODE | MUTT_CM_CHARCONV; + + if (option(C_Weed)) + { + *chflags |= CH_WEED; + *cmflags |= MUTT_CM_WEED; + } ++ ++ /* Just as with copy-decode, we need to update the ++ * mime fields to avoid confusing programs that may ++ * process the email. However, we don't want to force ++ * those fields to appear in printouts. */ ++ if (!print) ++ *chflags |= CH_MIME | CH_TXTPLAIN; + } + + if (print) diff --git a/0010-Reduce-line-buffer-size-in-mx_get_magic.patch b/0010-Reduce-line-buffer-size-in-mx_get_magic.patch new file mode 100644 index 000000000..ab6e48078 --- /dev/null +++ b/0010-Reduce-line-buffer-size-in-mx_get_magic.patch @@ -0,0 +1,34 @@ +From 9506db1e4a01fadf503b63381ab2b60dee32b836 Mon Sep 17 00:00:00 2001 +From: Kevin McCarthy +Date: Tue, 15 Oct 2019 15:26:20 +0800 +Subject: Reduce line buffer size in mx_get_magic() + +tmp is only used for mbox and mmdf iniital line examination. That +only needs to look at 6 characters from the first line. + +Upstream-commit: https://gitlab.com/muttmua/mutt/commit/9506db1e4a01fadf503b63381ab2b60dee32b836 +Co-authored-by: +--- + mx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/mx.c b/mx.c +index 472e8ee3..f693f0e0 100644 +--- a/mx.c ++++ b/mx.c +@@ -391,7 +391,6 @@ int mx_get_magic(const char *path) + { + struct stat st; + int magic = 0; +- char tmp[PATH_MAX]; + FILE *f; + + #ifdef USE_IMAP +@@ -437,6 +436,7 @@ int mx_get_magic(const char *path) + struct utimbuf times; + #endif /* HAVE_UTIMENSAT */ + int ch; ++ char tmp[10]; + + /* Some mailbox creation tools erroneously append a blank line to + * a file before appending a mail message. This allows mutt to diff --git a/0011-Stable-branch-quick-fix-for-pager-change-mailbox-pus.patch b/0011-Stable-branch-quick-fix-for-pager-change-mailbox-pus.patch new file mode 100644 index 000000000..cd18cff55 --- /dev/null +++ b/0011-Stable-branch-quick-fix-for-pager-change-mailbox-pus.patch @@ -0,0 +1,45 @@ +From a327386c5bf676a8321335fca849159ddd664ab9 Mon Sep 17 00:00:00 2001 +From: Kevin McCarthy +Date: Thu, 17 Oct 2019 15:48:31 +0800 +Subject: Stable branch quick fix for pager change-mailbox push/exec bug + +The menu functions mutt_push/pop_current_menu() keep track of the menu +stack, automatically setting CurrentMenu when exiting menus. + +The only gotcha was the function sharing between the index and pager +menus. The index uses a hack, setting menu->menu to MENU_PAGER for +operations redirecting through the index and back to the pager +afterwards. + +I thought this was covered by the restoration of the menu before +returning to the pager, or when exiting the index switch. However it +is not: invoking other menus, such as the browser, will result in +CurrentMenu being set to the C_Pager when exiting those(by +mutt_menu_pop_current()). This can result in folder hooks failing for +unshared functions. + +A better fix is to remove the hack of using menu->menu, because this +can easily cause a problem in the future in other situations.(I will +make this fix in master next.) For the stable branch, I am explicitly +setting/restoring CurrentMenu before invoking the folder hooks. + +Upstream-commit: https://gitlab.com/muttmua/mutt/commit/a327386c5bf676a8321335fca849159ddd664ab9 +Co-authored-by: +--- + index.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/index.c b/index.c +index 32925f29..d57ce985 100644 +--- a/index.c ++++ b/index.c +@@ -1371,6 +1371,9 @@ int mutt_index_menu(void) + + mutt_sleep(0); + ++ /* XXX: quick fix in stable branch. Better fix will be in master */ ++ CurrentMenu = MENU_MAIN; ++ + /* Note that menu->menu may be MENU_PAGER if the change folder + * operation originated from the pager. + * diff --git a/0012-Remove-menu-menu-hack-when-redirecting-pager-ops-thr.patch b/0012-Remove-menu-menu-hack-when-redirecting-pager-ops-thr.patch new file mode 100644 index 000000000..bc37213e0 --- /dev/null +++ b/0012-Remove-menu-menu-hack-when-redirecting-pager-ops-thr.patch @@ -0,0 +1,313 @@ +From b15e8659514362e85114a6db4a89f799a9593787 Mon Sep 17 00:00:00 2001 +From: Kevin McCarthy +Date: Thu, 17 Oct 2019 17:30:03 +0800 +Subject: Remove menu->menu hack when redirecting pager ops through index + +As noted in commit a327386c, this causes problems when redirecting ops +that open new menus. There is no need to change the menu->menu type, +as a flag works perfectly well with no such side effects. + +This also removes the need for comments explaning the hack before +mutt_folder_hooks() when changing folders, or before displaying a +message in the pager. + +Upstream-commit: https://gitlab.com/muttmua/mutt/commit/b15e8659514362e85114a6db4a89f799a9593787 +Co-authored-by: +--- + index.c | 81 ++++++++++++++++++++++------------------------------- + 1 file changed, 33 insertions(+), 48 deletions(-) + +diff --git a/index.c b/index.c +index 9a0df384..35f106b0 100644 +--- a/index.c ++++ b/index.c +@@ -622,6 +622,7 @@ int mutt_index_menu(void) + int do_buffy_notify = 1; + int close = 0; /* did we OP_QUIT or OP_EXIT out of this menu? */ + int attach_msg = option(OptAttachMsg); ++ int in_pager = 0; /* set when pager redirects a function through the index */ + + menu = mutt_menu_new(MENU_MAIN); + menu->make_entry = index_make_entry; +@@ -746,7 +747,7 @@ int mutt_index_menu(void) + if (op >= 0) + mutt_curs_set(0); + +- if (menu->menu == MENU_MAIN) ++ if (!in_pager) + { + index_menu_redraw(menu); + +@@ -908,7 +909,7 @@ int mutt_index_menu(void) + if (mutt_get_field(_("Jump to message: "), buf, sizeof(buf), 0) != 0 + || !buf[0]) + { +- if (menu->menu == MENU_PAGER) ++ if (in_pager) + { + op = OP_DISPLAY_MESSAGE; + continue; +@@ -941,7 +942,7 @@ int mutt_index_menu(void) + if (j >= 0) + { + menu->current = Context->hdrs[j]->virtual; +- if (menu->menu == MENU_PAGER) ++ if (in_pager) + { + op = OP_DISPLAY_MESSAGE; + continue; +@@ -1094,7 +1095,7 @@ int mutt_index_menu(void) + resort_index(menu); + set_option(OptSearchInvalid); + } +- if (menu->menu == MENU_PAGER) ++ if (in_pager) + { + op = OP_DISPLAY_MESSAGE; + continue; +@@ -1248,7 +1249,7 @@ int mutt_index_menu(void) + FREE(&Context); + + /* if we were in the pager, redisplay the message */ +- if (menu->menu == MENU_PAGER) ++ if (in_pager) + { + op = OP_DISPLAY_MESSAGE; + continue; +@@ -1316,7 +1317,7 @@ int mutt_index_menu(void) + + if (mutt_buffer_enter_fname(cp, folderbuf, 1) == -1) + { +- if (menu->menu == MENU_PAGER) ++ if (in_pager) + { + op = OP_DISPLAY_MESSAGE; + cont = 1; +@@ -1380,17 +1381,6 @@ int mutt_index_menu(void) + + mutt_sleep(0); + +- /* XXX: quick fix in stable branch. Better fix will be in master */ +- CurrentMenu = MENU_MAIN; +- +- /* Note that menu->menu may be MENU_PAGER if the change folder +- * operation originated from the pager. +- * +- * However, exec commands currently use CurrentMenu to determine what +- * functions are available, which is automatically set by the +- * mutt_push/pop_current_menu() functions. If that changes, the menu +- * would need to be reset here, and the pager cleanup code after the +- * switch statement would need to be run. */ + mutt_folder_hook(mutt_b2s(folderbuf)); + + if ((Context = mx_open_mailbox(mutt_b2s(folderbuf), +@@ -1451,11 +1441,6 @@ int mutt_index_menu(void) + if (option(C_PgpAutoDecode) && (tag || !(CURHDR->security & PGP_TRADITIONAL_CHECKED))) + mutt_check_traditional_pgp(tag ? NULL : CURHDR, &menu->redraw); + +- /* If we are returning to the pager via an index menu redirection, we +- * need to reset the menu->menu. Otherwise mutt_menu_pop_current() will +- * set CurrentMenu incorrectly when we return back to the index menu. */ +- menu->menu = MENU_MAIN; +- + if ((op = mutt_display_message(CURHDR)) < 0) + { + unset_option(OptNeedResort); +@@ -1463,22 +1448,22 @@ int mutt_index_menu(void) + } + + /* This is used to redirect a single operation back here afterwards. If +- * mutt_display_message() returns 0, then the menu and pager state will ++ * mutt_display_message() returns 0, then this flag and pager state will + * be cleaned up after this switch statement. */ +- menu->menu = MENU_PAGER; ++ in_pager = 1; + menu->oldcurrent = menu->current; + continue; + + case OP_EXIT: + + close = op; +- if (menu->menu == MENU_MAIN && attach_msg) ++ if (!in_pager && attach_msg) + { + done = 1; + break; + } + +- if ((menu->menu == MENU_MAIN) ++ if ((!in_pager) + && (query_quadoption(C_Quit, + _("Exit Mutt without saving?")) == MUTT_YES)) + { +@@ -1512,7 +1497,7 @@ int mutt_index_menu(void) + Context->changed = 1; + mutt_message _("Thread broken"); + +- if (menu->menu == MENU_PAGER) ++ if (in_pager) + { + op = OP_DISPLAY_MESSAGE; + continue; +@@ -1556,7 +1541,7 @@ int mutt_index_menu(void) + mutt_error _("No thread linked"); + } + +- if (menu->menu == MENU_PAGER) ++ if (in_pager) + { + op = OP_DISPLAY_MESSAGE; + continue; +@@ -1573,7 +1558,7 @@ int mutt_index_menu(void) + CHECK_ATTACH; + mutt_edit_content_type(CURHDR, CURHDR->content, NULL); + /* if we were in the pager, redisplay the message */ +- if (menu->menu == MENU_PAGER) ++ if (in_pager) + { + op = OP_DISPLAY_MESSAGE; + continue; +@@ -1588,17 +1573,17 @@ int mutt_index_menu(void) + CHECK_VISIBLE; + if (menu->current >= Context->vcount - 1) + { +- if (menu->menu == MENU_MAIN) ++ if (!in_pager) + mutt_error _("You are on the last message."); + break; + } + if ((menu->current = ci_next_undeleted(menu->current)) == -1) + { + menu->current = menu->oldcurrent; +- if (menu->menu == MENU_MAIN) ++ if (!in_pager) + mutt_error _("No undeleted messages."); + } +- else if (menu->menu == MENU_PAGER) ++ else if (in_pager) + { + op = OP_DISPLAY_MESSAGE; + continue; +@@ -1613,12 +1598,12 @@ int mutt_index_menu(void) + CHECK_VISIBLE; + if (menu->current >= Context->vcount - 1) + { +- if (menu->menu == MENU_MAIN) ++ if (!in_pager) + mutt_error _("You are on the last message."); + break; + } + menu->current++; +- if (menu->menu == MENU_PAGER) ++ if (in_pager) + { + op = OP_DISPLAY_MESSAGE; + continue; +@@ -1639,10 +1624,10 @@ int mutt_index_menu(void) + if ((menu->current = ci_previous_undeleted(menu->current)) == -1) + { + menu->current = menu->oldcurrent; +- if (menu->menu == MENU_MAIN) ++ if (!in_pager) + mutt_error _("No undeleted messages."); + } +- else if (menu->menu == MENU_PAGER) ++ else if (in_pager) + { + op = OP_DISPLAY_MESSAGE; + continue; +@@ -1657,11 +1642,11 @@ int mutt_index_menu(void) + CHECK_VISIBLE; + if (menu->current < 1) + { +- if (menu->menu == MENU_MAIN) mutt_error _("You are on the first message."); ++ if (!in_pager) mutt_error _("You are on the first message."); + break; + } + menu->current--; +- if (menu->menu == MENU_PAGER) ++ if (in_pager) + { + op = OP_DISPLAY_MESSAGE; + continue; +@@ -1797,7 +1782,7 @@ int mutt_index_menu(void) + mutt_error(_("No unread messages.")); + } + } +- else if (menu->menu == MENU_PAGER) ++ else if (in_pager) + { + op = OP_DISPLAY_MESSAGE; + continue; +@@ -1895,7 +1880,7 @@ int mutt_index_menu(void) + CHECK_IN_MAILBOX; + if (mx_toggle_write(Context) == 0) + { +- if (menu->menu == MENU_PAGER) ++ if (in_pager) + { + op = OP_DISPLAY_MESSAGE; + continue; +@@ -1939,7 +1924,7 @@ int mutt_index_menu(void) + else + mutt_error _("You are on the first thread."); + } +- else if (menu->menu == MENU_PAGER) ++ else if (in_pager) + { + op = OP_DISPLAY_MESSAGE; + continue; +@@ -1959,7 +1944,7 @@ int mutt_index_menu(void) + { + menu->current = menu->oldcurrent; + } +- else if (menu->menu == MENU_PAGER) ++ else if (in_pager) + { + op = OP_DISPLAY_MESSAGE; + continue; +@@ -2146,7 +2131,7 @@ int mutt_index_menu(void) + menu->current = menu->oldcurrent; + menu->redraw |= REDRAW_CURRENT; + } +- else if (menu->menu == MENU_PAGER) ++ else if (in_pager) + { + op = OP_DISPLAY_MESSAGE; + continue; +@@ -2285,7 +2270,7 @@ int mutt_index_menu(void) + if (tag || !(CURHDR->security & PGP_TRADITIONAL_CHECKED)) + mutt_check_traditional_pgp(tag ? NULL : CURHDR, &menu->redraw); + +- if (menu->menu == MENU_PAGER) ++ if (in_pager) + { + op = OP_DISPLAY_MESSAGE; + continue; +@@ -2347,7 +2332,7 @@ int mutt_index_menu(void) + if ((menu->current =(op == OP_MAIN_READ_THREAD ? + mutt_next_thread(CURHDR) : mutt_next_subthread(CURHDR))) == -1) + menu->current = menu->oldcurrent; +- else if (menu->menu == MENU_PAGER) ++ else if (in_pager) + { + op = OP_DISPLAY_MESSAGE; + continue; +@@ -2584,14 +2569,14 @@ int mutt_index_menu(void) + #endif + + default: +- if (menu->menu == MENU_MAIN) ++ if (!in_pager) + km_error_key(MENU_MAIN); + } + +- if (menu->menu == MENU_PAGER) ++ if (in_pager) + { + mutt_clear_pager_position(); +- menu->menu = MENU_MAIN; ++ in_pager = 0; + menu->redraw = REDRAW_FULL; + } + diff --git a/0013-Clean-up-pager-change-folder-aborts-to-return-to-pag.patch b/0013-Clean-up-pager-change-folder-aborts-to-return-to-pag.patch new file mode 100644 index 000000000..4c4a1805f --- /dev/null +++ b/0013-Clean-up-pager-change-folder-aborts-to-return-to-pag.patch @@ -0,0 +1,74 @@ +From e750e39c4a80bb98e98c5fc38500e0897a3e0279 Mon Sep 17 00:00:00 2001 +From: Kevin McCarthy +Date: Thu, 17 Oct 2019 18:34:55 +0800 +Subject: Clean up pager change folder aborts to return to pager + +Changing folder from within the pager behaved inconsistently when +aborting, or upon a normal error. It would sometimes return the pager +and other times return to the index. + +Ensure it returns to the pager, except in the case where +mx_close_mailbox() fails due to a new mail or reopen event. In that +case we likely want to be in the index - the message we were viewing +could have disappeared or relocated. + +Upstream-commit: https://gitlab.com/muttmua/mutt/commit/e750e39c4a80bb98e98c5fc38500e0897a3e0279 +Co-authored-by: +--- + index.c | 20 +++++++++----------- + 1 file changed, 9 insertions(+), 11 deletions(-) + +diff --git a/index.c b/index.c +index 35f106b0..0f93df3f 100644 +--- a/index.c ++++ b/index.c +@@ -1277,7 +1277,7 @@ int mutt_index_menu(void) + case OP_MAIN_CHANGE_FOLDER_READONLY: + { + struct Buffer *folderbuf; +- int cont = 0; /* Set if we want to continue instead of break */ ++ int pager_return = 1; /* return to display message in pager */ + + folderbuf = mutt_buffer_pool_get(); + +@@ -1316,14 +1316,7 @@ int mutt_index_menu(void) + mutt_buffer_buffy(folderbuf); + + if (mutt_buffer_enter_fname(cp, folderbuf, 1) == -1) +- { +- if (in_pager) +- { +- op = OP_DISPLAY_MESSAGE; +- cont = 1; +- } + goto changefoldercleanup; +- } + } + + if (!mutt_buffer_len(folderbuf)) +@@ -1338,6 +1331,9 @@ int mutt_index_menu(void) + goto changefoldercleanup; + } + ++ /* past this point, we don't return to the pager on error */ ++ pager_return = 0; ++ + /* keepalive failure in mutt_enter_fname may kill connection. #3028 */ + if (Context && !Context->path) + FREE(&Context); +@@ -1410,10 +1406,12 @@ int mutt_index_menu(void) + + changefoldercleanup: + mutt_buffer_pool_release(&folderbuf); +- if (cont) ++ if (in_pager && pager_return) ++ { ++ op = OP_DISPLAY_MESSAGE; + continue; +- else +- break; ++ } ++ break; + } + + case OP_DISPLAY_MESSAGE: diff --git a/0014-Add-typelen-parameter-to-rfc1524_mailcap_lookup.patch b/0014-Add-typelen-parameter-to-rfc1524_mailcap_lookup.patch new file mode 100644 index 000000000..79fabe713 --- /dev/null +++ b/0014-Add-typelen-parameter-to-rfc1524_mailcap_lookup.patch @@ -0,0 +1,195 @@ +From 12cd2d529c8462268c3958e4ae2bab25cee92ae7 Mon Sep 17 00:00:00 2001 +From: Kevin McCarthy +Date: Wed, 23 Oct 2019 19:17:09 +0800 +Subject: Add typelen parameter to rfc1524_mailcap_lookup() + +Because of mime_lookup commands, the call to mutt_check_lookup_list() +inside the function can modify the passed in type. Add an explicit +length parameter to the function, rather than assume the parameter +size. This also makes it more evident the type parameter can be +modified to callers. + +Change the len parameter to mutt_check_lookup_list() to type size_t, +just to be correct about it. + +Upstream-commit: https://gitlab.com/muttmua/mutt/commit/12cd2d529c8462268c3958e4ae2bab25cee92ae7 +Co-authored-by: +--- + email/attach.c | 14 +++++++------- + handler.c | 6 +++--- + protos.h | 2 +- + recvattach.c | 5 +++-- + mailcap.c | 5 ++--- + mailcap.h | 2 +- + 6 files changed, 17 insertions(+), 17 deletions(-) + +diff --git a/email/attach.c b/email/attach.c +index de32d1fb..5e9906f5 100644 +--- a/email/attach.c ++++ b/email/attach.c +@@ -58,7 +58,7 @@ int mutt_get_tmp_attachment(struct Body *a) + entry = rfc1524_new_entry(); + + snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype); +- rfc1524_mailcap_lookup(a, type, entry, 0); ++ rfc1524_mailcap_lookup(a, type, sizeof(type), entry, 0); + mutt_rfc1524_expand_filename(entry->nametemplate, a->filename, tempfile); + + rfc1524_free_entry(&entry); +@@ -103,7 +103,7 @@ int mutt_compose_attachment(struct Body *a) + int rc = 0; + + snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype); +- if (rfc1524_mailcap_lookup(a, type, entry, MUTT_COMPOSE)) ++ if (rfc1524_mailcap_lookup(a, type, sizeof(type), entry, MUTT_COMPOSE)) + { + if (entry->composecommand || entry->composetypecommand) + { +@@ -239,7 +239,7 @@ int mutt_edit_attachment(struct Body *a) + int rc = 0; + + snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype); +- if (rfc1524_mailcap_lookup(a, type, entry, MUTT_EDIT)) ++ if (rfc1524_mailcap_lookup(a, type, sizeof(type), entry, MUTT_EDIT)) + { + if (entry->editcommand) + { +@@ -303,7 +303,7 @@ bailout: + } + + +-void mutt_check_lookup_list(struct Body *b, char *type, int len) ++void mutt_check_lookup_list(struct Body *b, char *type, size_t len) + { + struct ListHead *t = MimeLookupList; + int i; +@@ -374,7 +374,7 @@ int mutt_view_attachment(FILE *fp, struct Body *a, int flag, struct Email *hdr, + if (use_mailcap) + { + entry = rfc1524_new_entry(); +- if (!rfc1524_mailcap_lookup(a, type, entry, 0)) ++ if (!rfc1524_mailcap_lookup(a, type, sizeof(type), entry, 0)) + { + if (flag == MUTT_REGULAR) + { +@@ -929,7 +929,7 @@ int mutt_print_attachment(FILE *fp, struct Body *a) + + snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype); + +- if (rfc1524_mailcap_lookup(a, type, NULL, MUTT_PRINT)) ++ if (rfc1524_mailcap_lookup(a, type, sizeof(type), NULL, MUTT_PRINT)) + { + struct MailcapEntry *entry = NULL; + int piped = FALSE; +@@ -937,7 +937,7 @@ int mutt_print_attachment(FILE *fp, struct Body *a) + mutt_debug(LL_DEBUG2, "Using mailcap...\n")); + + entry = rfc1524_new_entry(); +- rfc1524_mailcap_lookup(a, type, entry, MUTT_PRINT); ++ rfc1524_mailcap_lookup(a, type, sizeof(type), entry, MUTT_PRINT); + mutt_rfc1524_expand_filename(entry->nametemplate, a->filename, + newfile); + +diff --git a/handler.c b/handler.c +index 5a0766a8..5e613d41 100644 +--- a/handler.c ++++ b/handler.c +@@ -955,7 +955,7 @@ static int is_mmnoask(const char *buf) + */ + static int is_autoview(struct Body *b) + { +- char type[128]; ++ char type[256]; + int is_autoview = 0; + + snprintf(type, sizeof(type), "%s/%s", TYPE(b), b->subtype); +@@ -988,7 +988,7 @@ static int is_autoview(struct Body *b) + * + * WARNING: type is altered by this call as a result of `mime_lookup' support */ + if (is_autoview) +- return rfc1524_mailcap_lookup(b, type, NULL, MUTT_AUTOVIEW); ++ return rfc1524_mailcap_lookup(b, type, sizeof(type), NULL, MUTT_AUTOVIEW); + + return 0; + } +@@ -1320,7 +1320,7 @@ static int autoview_handler(struct Body *a, struct State *s) + tempfile = mutt_buffer_pool_get(); + + snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype); +- rfc1524_mailcap_lookup(a, type, entry, MUTT_AUTOVIEW); ++ rfc1524_mailcap_lookup(a, type, sizeof(type), entry, MUTT_AUTOVIEW); + + fname = mutt_str_strdup(a->filename); + mutt_file_sanitize_filename(fname, 1); +diff --git a/protos.h b/protos.h +index 8ee932c8..759acc4f 100644 +--- a/protos.h ++++ b/protos.h +@@ -236,7 +236,7 @@ const char *mutt_getcwd(struct Buffer *); + void mutt_help(int); + const char *mutt_idxfmt_hook(const char *, struct Context *, struct Email *); + void mutt_draw_tree(struct Context *); +-void mutt_check_lookup_list(struct Body *, char *, int); ++void mutt_check_lookup_list(struct Body *, char *, size_t); + void mutt_make_attribution(struct Context *ctx, struct Email *cur, FILE *out); + void mutt_make_forward_subject(struct Envelope *env, struct Context *ctx, struct Email *cur); + void mutt_make_help(char *, size_t, const char *, int, int); +diff --git a/recvattach.c b/recvattach.c +index 087858c9..c2da1785 100644 +--- a/recvattach.c ++++ b/recvattach.c +@@ -741,7 +741,7 @@ static int can_print(ATTACH_CONTEXT *actx, struct Body *top, int tag) + snprintf(type, sizeof(type), "%s/%s", TYPE(top), top->subtype); + if (!tag || top->tagged) + { +- if (!rfc1524_mailcap_lookup(top, type, NULL, MUTT_PRINT)) ++ if (!rfc1524_mailcap_lookup(top, type, sizeof(type), NULL, MUTT_PRINT)) + { + if (mutt_str_strcasecmp("text/plain", top->subtype) && + mutt_str_strcasecmp("application/postscript", top->subtype)) +@@ -775,7 +775,8 @@ static void print_attachment_list(ATTACH_CONTEXT *actx, FILE *fp, int tag, struct Body + if (!tag || top->tagged) + { + snprintf(type, sizeof(type), "%s/%s", TYPE(top), top->subtype); +- if (!option(C_AttachSplit) && !rfc1524_mailcap_lookup(top, type, NULL, MUTT_PRINT)) ++ if (!option(C_AttachSplit) && ++ !rfc1524_mailcap_lookup(top, type, sizeof(type), NULL, MUTT_PRINT)) + { + if (!mutt_str_strcasecmp("text/plain", top->subtype) || + !mutt_str_strcasecmp("application/postscript", top->subtype)) +diff --git a/mailcap.c b/mailcap.c +index 6597df2b..2fc9f175 100644 +--- a/mailcap.c ++++ b/mailcap.c +@@ -420,7 +420,7 @@ void rfc1524_free_entry(struct MailcapEntry **entry) + * in *entry, and returns 1. On failure(not found), returns 0. + * If entry == NULL just return 1 if the given type is found. + */ +-int rfc1524_mailcap_lookup(struct Body *a, char *type, struct MailcapEntry *entry, int opt) ++int rfc1524_mailcap_lookup(struct Body *a, char *type, size_t typelen, struct MailcapEntry *entry, int opt) + { + struct Buffer *path = NULL; + int found = FALSE; +@@ -438,8 +438,7 @@ int rfc1524_mailcap_lookup(struct Body *a, char *type, struct MailcapEntry *entry, int opt) + return 0; + } + +- /* FIXME: sizeof type should be passed to rfc1524_mailcap_lookup() */ +- mutt_check_lookup_list(a, type, 128); ++ mutt_check_lookup_list(a, type, typelen); + + path = mutt_buffer_pool_get(); + +diff --git a/mailcap.h b/mailcap.h +index 87b06d6d..bdf0468e 100644 +--- a/mailcap.h ++++ b/mailcap.h +@@ -38,7 +38,7 @@ struct MailcapEntry *rfc1524_new_entry(void); + void rfc1524_free_entry(struct MailcapEntry **); + int mutt_rfc1524_expand_command(struct Body *, const char *, const char *, struct Buffer *); + void mutt_rfc1524_expand_filename(const char *, const char *, struct Buffer *); +-int rfc1524_mailcap_lookup(struct Body *, char *, struct MailcapEntry *, int); ++int rfc1524_mailcap_lookup(struct Body *, char *, size_t, struct MailcapEntry *, int); + int mutt_file_rename(const char *, const char *); + + #endif /* _RFC1524_H */ diff --git a/0015-Convert-mutt_message_to_7bit-to-use-buffer.patch b/0015-Convert-mutt_message_to_7bit-to-use-buffer.patch new file mode 100644 index 000000000..f37e322b1 --- /dev/null +++ b/0015-Convert-mutt_message_to_7bit-to-use-buffer.patch @@ -0,0 +1,96 @@ +From 671e653c6b5d70adeb644a36961bdc2c8d2f2e9f Mon Sep 17 00:00:00 2001 +From: Kevin McCarthy +Date: Fri, 25 Oct 2019 15:28:25 +0800 +Subject: Convert mutt_message_to_7bit() to use buffer + +Clean up the error handling a bit. + +Because of the recursive invocation, avoid the buffer pool in this +case. + +Upstream-commit: https://gitlab.com/muttmua/mutt/commit/671e653c6b5d70adeb644a36961bdc2c8d2f2e9f +Co-authored-by: +--- + sendlib.c | 36 ++++++++++++++++++++++-------------- + 1 file changed, 22 insertions(+), 14 deletions(-) + +diff --git a/sendlib.c b/sendlib.c +index 72ac3a93..de2cf78f 100644 +--- a/sendlib.c ++++ b/sendlib.c +@@ -1072,8 +1072,7 @@ bye: + + void mutt_message_to_7bit(struct Body *a, FILE *fp) + { +- char temp[PATH_MAX]; +- char *line = NULL; ++ struct Buffer *temp = NULL; + FILE *fpin = NULL; + FILE *fpout = NULL; + struct stat sb; +@@ -1092,12 +1091,15 @@ void mutt_message_to_7bit(struct Body *a, FILE *fp) + { + mutt_perror("stat"); + mutt_file_fclose(&fpin); ++ goto cleanup; + } + a->length = sb.st_size; + } + +- mutt_mktemp(temp, sizeof(temp)); +- if (!(fpout = mutt_file_fopen(temp, "w+"))) ++ /* Avoid buffer pool due to recursion */ ++ temp = mutt_buffer_new(); ++ mutt_buffer_mktemp(temp); ++ if (!(fpout = mutt_file_fopen(mutt_b2s(temp), "w+"))) + { + mutt_perror("fopen"); + goto cleanup; +@@ -1116,31 +1118,37 @@ void mutt_message_to_7bit(struct Body *a, FILE *fp) + fputc('\n', fpout); + mutt_write_mime_body(a->parts, fpout); + +-cleanup: +- FREE(&line); +- +- if (fpin && fpin != fp) ++ if (fpin != fp) + mutt_file_fclose(&fpin); +- if (fpout) +- mutt_file_fclose(&fpout); +- else +- return; ++ mutt_file_fclose(&fpout); + + a->encoding = ENC_7BIT; + FREE(&a->d_filename); + a->d_filename = a->filename; + if (a->filename && a->unlink) + unlink(a->filename); +- a->filename = mutt_str_strdup(temp); ++ a->filename = mutt_str_strdup(mutt_b2s(temp)); + a->unlink = 1; + if (stat(a->filename, &sb) == -1) + { + mutt_perror("stat"); +- return; ++ goto cleanup; + } + a->length = sb.st_size; + mutt_body_free(&a->parts); + a->hdr->content = NULL; ++ ++cleanup: ++ if (fpin && fpin != fp) ++ mutt_file_fclose(&fpin); ++ ++ if (fpout) ++ { ++ mutt_file_fclose(&fpout); ++ mutt_file_unlink(mutt_b2s(temp)); ++ } ++ ++ mutt_buffer_free(&temp); + } + + static void transform_to_7bit(struct Body *a, FILE *fpin) diff --git a/0016-Convert-transform_to_7bit-to-use-buffer-pool.patch b/0016-Convert-transform_to_7bit-to-use-buffer-pool.patch new file mode 100644 index 000000000..bbb04da44 --- /dev/null +++ b/0016-Convert-transform_to_7bit-to-use-buffer-pool.patch @@ -0,0 +1,51 @@ +From 3565f686bf929fe91ca07d683d99125b5a8b2c21 Mon Sep 17 00:00:00 2001 +From: Kevin McCarthy +Date: Fri, 25 Oct 2019 15:55:49 +0800 +Subject: Convert transform_to_7bit() to use buffer pool + +Upstream-commit: https://gitlab.com/muttmua/mutt/commit/3565f686bf929fe91ca07d683d99125b5a8b2c21 +Co-authored-by: +--- + sendlib.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/sendlib.c b/sendlib.c +index de2cf78f..5850da3e 100644 +--- a/sendlib.c ++++ b/sendlib.c +@@ -1153,7 +1153,7 @@ cleanup: + + static void transform_to_7bit(struct Body *a, FILE *fpin) + { +- char buff[PATH_MAX]; ++ struct Buffer *buff; + struct State s; + struct stat sb; + +@@ -1176,10 +1176,14 @@ static void transform_to_7bit(struct Body *a, FILE *fpin) + a->noconv = 1; + a->force_charset = 1; + +- mutt_mktemp(buff, sizeof(buff)); +- if ((s.fpout = mutt_file_fopen(buff, "w")) == NULL) ++ /* Because of the potential recursion in message types, we ++ * restrict the lifetime of the buffer tightly */ ++ buff = mutt_buffer_pool_get(); ++ mutt_buffer_mktemp(buff); ++ if ((s.fpout = mutt_file_fopen(mutt_b2s(buff), "w")) == NULL) + { + mutt_perror("fopen"); ++ mutt_buffer_pool_release(&buff); + return; + } + s.fpin = fpin; +@@ -1187,7 +1191,8 @@ static void transform_to_7bit(struct Body *a, FILE *fpin) + mutt_file_fclose(&s.fpout); + FREE(&a->d_filename); + a->d_filename = a->filename; +- a->filename = mutt_str_strdup(buff); ++ a->filename = mutt_str_strdup(mutt_b2s(buff)); ++ mutt_buffer_pool_release(&buff); + a->unlink = 1; + if (stat(a->filename, &sb) == -1) + { diff --git a/0017-Convert-send_msg-sendmail_wait-to-use-buffer-pool.patch b/0017-Convert-send_msg-sendmail_wait-to-use-buffer-pool.patch new file mode 100644 index 000000000..455d53a3b --- /dev/null +++ b/0017-Convert-send_msg-sendmail_wait-to-use-buffer-pool.patch @@ -0,0 +1,31 @@ +From 8de05d5ffc86c1a9dad61e83189a74331c2869b9 Mon Sep 17 00:00:00 2001 +From: Kevin McCarthy +Date: Fri, 25 Oct 2019 19:13:50 +0800 +Subject: Convert send_msg() $sendmail_wait to use buffer pool + +Upstream-commit: https://gitlab.com/muttmua/mutt/commit/8de05d5ffc86c1a9dad61e83189a74331c2869b9 +Co-authored-by: +--- + sendlib.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/sendlib.c b/sendlib.c +index 5850da3e..0b1766ce 100644 +--- a/sendlib.c ++++ b/sendlib.c +@@ -2268,10 +2268,12 @@ send_msg(const char *path, char **args, const char *msg, char **tempfile) + + if (C_SendmailWait >= 0 && tempfile) + { +- char tmp[PATH_MAX]; ++ struct Buffer *tmp; + +- mutt_mktemp(tmp, sizeof(tmp)); +- *tempfile = mutt_str_strdup(tmp); ++ tmp = mutt_buffer_pool_get(); ++ mutt_buffer_mktemp(tmp); ++ *tempfile = mutt_str_strdup(mutt_b2s(tmp)); ++ mutt_buffer_pool_release(&tmp); + } + + if ((pid = fork()) == 0) diff --git a/0018-Convert-_mutt_bounce_message-to-use-buffer-pool.patch b/0018-Convert-_mutt_bounce_message-to-use-buffer-pool.patch new file mode 100644 index 000000000..00a7b94ad --- /dev/null +++ b/0018-Convert-_mutt_bounce_message-to-use-buffer-pool.patch @@ -0,0 +1,56 @@ +From 58a8189770149329507f4d64224a8c6cc26b09f2 Mon Sep 17 00:00:00 2001 +From: Kevin McCarthy +Date: Fri, 25 Oct 2019 19:29:56 +0800 +Subject: Convert _mutt_bounce_message to use buffer pool + +Upstream-commit: https://gitlab.com/muttmua/mutt/commit/58a8189770149329507f4d64224a8c6cc26b09f2 +Co-authored-by: +--- + sendlib.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/sendlib.c b/sendlib.c +index 0b1766ce..2d5d221a 100644 +--- a/sendlib.c ++++ b/sendlib.c +@@ -2633,7 +2633,8 @@ static int _mutt_bounce_message(FILE *fp, struct Email *h, struct Address *to, const char *r + { + int i, ret = 0; + FILE *f; +- char date[128], tempfile[PATH_MAX]; ++ char date[128]; ++ struct Buffer *tempfile; + struct Message *msg = NULL; + + if (!h) +@@ -2651,8 +2652,9 @@ static int _mutt_bounce_message(FILE *fp, struct Email *h, struct Address *to, const char *r + + if (!fp) fp = msg->fp; + +- mutt_mktemp(tempfile, sizeof(tempfile)); +- if ((f = mutt_file_fopen(tempfile, "w")) != NULL) ++ tempfile = mutt_buffer_pool_get(); ++ mutt_buffer_mktemp(tempfile); ++ if ((f = mutt_file_fopen(mutt_b2s(tempfile), "w")) != NULL) + { + int ch_flags = CH_XMIT | CH_NONEWLINE | CH_NOQFROM; + char* msgid_str; +@@ -2675,14 +2677,16 @@ static int _mutt_bounce_message(FILE *fp, struct Email *h, struct Address *to, const char *r + + #if USE_SMTP + if (C_SmtpUrl) +- ret = mutt_smtp_send(env_from, to, NULL, NULL, tempfile, ++ ret = mutt_smtp_send(env_from, to, NULL, NULL, mutt_b2s(tempfile), + h->content->encoding == ENC_8BIT); + else + #endif /* USE_SMTP */ +- ret = mutt_invoke_sendmail(env_from, to, NULL, NULL, tempfile, ++ ret = mutt_invoke_sendmail(env_from, to, NULL, NULL, mutt_b2s(tempfile), + h->content->encoding == ENC_8BIT); + } + ++ mutt_buffer_pool_release(&tempfile); ++ + if (msg) + mx_close_message(Context, &msg); + diff --git a/0019-Convert-mutt_write_fcc-to-use-buffer-pool.patch b/0019-Convert-mutt_write_fcc-to-use-buffer-pool.patch new file mode 100644 index 000000000..bc8b6cc00 --- /dev/null +++ b/0019-Convert-mutt_write_fcc-to-use-buffer-pool.patch @@ -0,0 +1,108 @@ +From 7e29eb237f17bd573a93c6e5f71bfe87f92909c7 Mon Sep 17 00:00:00 2001 +From: Kevin McCarthy +Date: Sat, 26 Oct 2019 19:36:33 +0800 +Subject: Convert mutt_write_fcc() to use buffer pool + +Upstream-commit: https://gitlab.com/muttmua/mutt/commit/7e29eb237f17bd573a93c6e5f71bfe87f92909c7 +Co-authored-by: +--- + sendlib.c | 35 ++++++++++++++++++++++------------- + 1 file changed, 22 insertions(+), 13 deletions(-) + +diff --git a/sendlib.c b/sendlib.c +index 2d5d221a..cc7a8145 100644 +--- a/sendlib.c ++++ b/sendlib.c +@@ -2807,9 +2807,9 @@ int mutt_write_fcc(const char *path, struct Email *hdr, const char *msgid, int post, + { + struct Context f; + struct Message *msg; +- char tempfile[PATH_MAX]; ++ struct Buffer *tempfile = NULL; + FILE *tempfp = NULL; +- int r, need_buffy_cleanup = 0; ++ int r = -1, need_buffy_cleanup = 0; + struct stat st; + char buf[128]; + int onm_flags; +@@ -2821,7 +2821,7 @@ int mutt_write_fcc(const char *path, struct Email *hdr, const char *msgid, int post, + { + mutt_debug(LL_DEBUG1, "mutt_write_fcc(): unable to open mailbox %s in append-mode, aborting.\n", + path)); +- return (-1); ++ goto cleanup; + } + + /* We need to add a Content-Length field to avoid problems where a line in +@@ -2829,12 +2829,13 @@ int mutt_write_fcc(const char *path, struct Email *hdr, const char *msgid, int post, + */ + if (f.magic == MUTT_MMDF || f.magic == MUTT_MBOX) + { +- mutt_mktemp(tempfile, sizeof(tempfile)); +- if ((tempfp = mutt_file_fopen(tempfile, "w+")) == NULL) ++ tempfile = mutt_buffer_pool_get(); ++ mutt_buffer_mktemp(tempfile); ++ if ((tempfp = mutt_file_fopen(mutt_b2s(tempfile), "w+")) == NULL) + { +- mutt_perror(tempfile); ++ mutt_perror(mutt_b2s(tempfile)); + mx_close_mailbox(&f, NULL); +- return (-1); ++ goto cleanup; + } + /* remember new mail status before appending message */ + need_buffy_cleanup = 1; +@@ -2848,7 +2849,7 @@ int mutt_write_fcc(const char *path, struct Email *hdr, const char *msgid, int post, + if ((msg = mx_open_new_message(&f, hdr, onm_flags)) == NULL) + { + mx_close_mailbox(&f, NULL); +- return (-1); ++ goto cleanup; + } + + /* post == 1 => postpone message. +@@ -2971,13 +2972,13 @@ int mutt_write_fcc(const char *path, struct Email *hdr, const char *msgid, int post, + fflush(tempfp); + if (ferror(tempfp)) + { +- mutt_debug(LL_DEBUG1, "mutt_write_fcc(): %s: write failed.\n", tempfile)); ++ mutt_debug(LL_DEBUG1, "mutt_write_fcc(): %s: write failed.\n", mutt_b2s(tempfile))); + mutt_file_fclose(&tempfp); +- unlink(tempfile); ++ unlink(mutt_b2s(tempfile)); + mx_commit_message(msg, &f); /* XXX - really? */ + mx_close_message(&f, &msg); + mx_close_mailbox(&f, NULL); +- return -1; ++ goto cleanup; + } + + /* count the number of lines */ +@@ -2990,11 +2991,11 @@ int mutt_write_fcc(const char *path, struct Email *hdr, const char *msgid, int post, + /* copy the body and clean up */ + rewind(tempfp); + r = mutt_file_copy_stream(tempfp, msg->fp); +- if (fclose(tempfp) != 0) ++ if (mutt_file_fclose(&tempfp) != 0) + r = -1; + /* if there was an error, leave the temp version */ + if (!r) +- unlink(tempfile); ++ unlink(mutt_b2s(tempfile)); + } + else + { +@@ -3013,5 +3014,13 @@ int mutt_write_fcc(const char *path, struct Email *hdr, const char *msgid, int post, + if (post) + set_noconv_flags(hdr->content, 0); + ++cleanup: ++ if (tempfp) ++ { ++ mutt_file_fclose(&tempfp); ++ unlink(mutt_b2s(tempfile)); ++ } ++ mutt_buffer_pool_release(&tempfile); ++ + return r; + }