}
else
#endif
- if (examine_directory(menu, &state, LastDir, prefix) == -1)
{
- /* try to restore the old values */
- mutt_str_strfcpy(LastDir, OldLastDir, sizeof(LastDir));
if (examine_directory(menu, &state, LastDir, prefix) == -1)
{
- mutt_str_strfcpy(LastDir, NONULL(HomeDir), sizeof(LastDir));
- goto bail;
+ /* try to restore the old values */
+ mutt_str_strfcpy(LastDir, OldLastDir, sizeof(LastDir));
+ if (examine_directory(menu, &state, LastDir, prefix) == -1)
+ {
+ mutt_str_strfcpy(LastDir, NONULL(HomeDir), sizeof(LastDir));
+ goto bail;
+ }
}
+ /* resolve paths navigated from GUI */
+ if (mutt_realpath(LastDir) == 0)
+ break;
}
+
browser_highlight_default(&state, menu);
init_menu(&state, menu, title, sizeof(title), buffy);
if (GotoSwapper[0])
break;
#endif
+ case OP_GOTO_PARENT:
case OP_CHANGE_DIRECTORY:
#ifdef USE_NNTP
}
}
- if (mutt_get_field(_("Chdir to: "), buf, sizeof(buf), MUTT_FILE) == 0 && buf[0])
+ if (i == OP_CHANGE_DIRECTORY)
+ {
+ int ret = mutt_get_field(_("Chdir to: "), buf, sizeof(buf), MUTT_FILE);
+ if (ret != 0)
+ break;
+ }
+ else if (i == OP_GOTO_PARENT)
+ mutt_get_parent_path(buf, buf, sizeof(buf));
+
+ if (buf[0])
{
buffy = 0;
mutt_expand_path(buf, sizeof(buf));
mutt_file_concat_path(tmp, LastDir, buf, sizeof(tmp));
mutt_str_strfcpy(buf, tmp, sizeof(buf));
}
+ /* Resolve path from <chdir>
+ * Avoids buildup such as /a/b/../../c
+ * Symlinks are always unraveled to keep code simple */
+ if (mutt_realpath(buf) == 0)
+ break;
+
if (stat(buf, &st) == 0)
{
if (S_ISDIR(st.st_mode))
/* The file browser */
const struct Binding OpBrowser[] = { /* map: browser */
{ "change-dir", OP_CHANGE_DIRECTORY, "c" },
+ { "goto-parent", OP_GOTO_PARENT, "p" },
{ "display-filename", OP_BROWSER_TELL, "@" },
{ "enter-mask", OP_ENTER_MASK, "m" },
{ "sort", OP_SORT, "o" },
mutt_str_strfcpy(output, path, olen);
int n = mutt_str_strlen(output);
+ /* remove any final trailing '/' */
+ if (output[n - 1] == '/')
+ output[n - 1] = '\0';
+
/* Remove everything until the next slash */
for (n--; ((n >= 0) && (output[n] != '/')); n--)
;
}
}
+/**
+ * mutt_realpath - resolve path, unraveling symlinks
+ * @param buf Buffer containing path
+ * @retval len String length of resolved path
+ * @retval 0 Error, buf is not overwritten
+ *
+ * Resolve and overwrite the path in buf.
+ *
+ * @note Size of buf should be at least PATH_MAX bytes.
+ */
+size_t mutt_realpath(char *buf)
+{
+ char s[PATH_MAX];
+
+ if (realpath(buf, s) == NULL)
+ return 0;
+
+ return mutt_str_strfcpy(buf, s, PATH_MAX);
+}
+
char debugfilename[_POSIX_PATH_MAX];
FILE *debugfile = NULL;
int debuglevel;
_fmt(OP_BUFFY_LIST, N_("list mailboxes with new mail")) \
_fmt(OP_CATCHUP, N_("mark all articles in newsgroup as read")) \
_fmt(OP_CHANGE_DIRECTORY, N_("change directories")) \
+ _fmt(OP_GOTO_PARENT, N_("go to parent directory")) \
_fmt(OP_CHECK_NEW, N_("check mailboxes for new mail")) \
_fmt(OP_COMPOSE_ATTACH_FILE, N_("attach file(s) to this message")) \
_fmt(OP_COMPOSE_ATTACH_MESSAGE, N_("attach message(s) to this message")) \
void mutt_browser_select_dir(char *f);
void mutt_get_parent_path(char *output, char *path, size_t olen);
+size_t mutt_realpath(char *buf);
#define MUTT_RANDTAG_LEN (16)
void mutt_rand_base32(void *out, size_t len);