From 4184555b82b7cb663096a1be7a8c5b102178f2d6 Mon Sep 17 00:00:00 2001 From: Slava Zanko Date: Thu, 5 Apr 2012 12:51:06 +0300 Subject: [PATCH] Ticket #2760: The password for session ftp remains in input history Signed-off-by: Slava Zanko --- lib/widget/input.c | 71 ++++++++++++++++++++++--------------- lib/widget/input.h | 1 + lib/widget/quick.c | 2 ++ lib/widget/quick.h | 1 + lib/widget/wtools.c | 20 ++++++----- lib/widget/wtools.h | 2 +- src/filemanager/cmd.c | 14 ++++---- tests/lib/vfs/path_recode.c | 5 +++ 8 files changed, 70 insertions(+), 46 deletions(-) diff --git a/lib/widget/input.c b/lib/widget/input.c index a913db45e..c14842d33 100644 --- a/lib/widget/input.c +++ b/lib/widget/input.c @@ -203,53 +203,65 @@ do_show_hist (WInput * in) in->history_changed = TRUE; } +/* --------------------------------------------------------------------------------------------- */ +/** Strip password from incomplete url (just user:pass@host without VFS prefix). + * + * @param url partial URL + * @return newly allocated string without password + */ + +static char * +input_history_strip_password (const char *url) +{ + char *at, *delim, *colon; + + at = strrchr (url, '@'); + if (at == NULL) + return g_strdup (url); + + /* TODO: handle ':' and '@' in password */ + + delim = strstr (url, VFS_PATH_URL_DELIMITER); + if (delim != NULL) + colon = strchr (delim + strlen (VFS_PATH_URL_DELIMITER), ':'); + else + colon = strchr (url, ':'); + + if (colon == NULL) + return g_strdup (url); + *colon = '\0'; + + return g_strconcat (url, at, NULL); +} + /* --------------------------------------------------------------------------------------------- */ static void push_history (WInput * in, const char *text) { - /* input widget where urls with passwords are entered without any - vfs prefix */ - const char *password_input_fields[] = { - " Link to a remote machine ", - " FTP to machine ", - " SMB link to machine " - }; - const size_t ELEMENTS = (sizeof (password_input_fields) / sizeof (password_input_fields[0])); - char *t; - size_t i; gboolean empty; if (text == NULL) return; -#ifdef ENABLE_NLS - for (i = 0; i < ELEMENTS; i++) - password_input_fields[i] = _(password_input_fields[i]); -#endif - t = g_strstrip (g_strdup (text)); empty = *t == '\0'; g_free (t); t = g_strdup (empty ? "" : text); - if (in->history_name != NULL) + if (!empty && in->history_name != NULL && in->strip_password) { - /* FIXME: It is the strange code. Rewrite is needed. */ - const char *p = in->history_name + 3; + /* + We got string user:pass@host without any VFS prefixes + and vfs_path_to_str_flags (t, VPF_STRIP_PASSWORD) doesn't work. + Therefore we want to strip password in separate algorithm + */ + char *url_with_stripped_password; - for (i = 0; i < ELEMENTS; i++) - if (strcmp (p, password_input_fields[i]) == 0) - { - vfs_path_t *vpath; - - vpath = vfs_path_from_str (t); - g_free (t); - t = vfs_path_to_str_flags (vpath, 0, VPF_STRIP_PASSWORD); - vfs_path_free (vpath); - break; - } + url_with_stripped_password = input_history_strip_password (t); + g_free (t); + t = url_with_stripped_password; } if (in->history == NULL || in->history->data == NULL || strcmp (in->history->data, t) != 0 || @@ -979,6 +991,7 @@ input_new (int y, int x, const int *input_colors, int width, const char *def_tex in->need_push = TRUE; in->is_password = FALSE; in->charpoint = 0; + in->strip_password = FALSE; /* in->buffer will be corrected in "history_load" event handler */ in->current_max_size = width + 1; diff --git a/lib/widget/input.h b/lib/widget/input.h index ebecd5fba..8eeaeabd9 100644 --- a/lib/widget/input.h +++ b/lib/widget/input.h @@ -62,6 +62,7 @@ typedef struct GList *history; /* the history */ gboolean history_changed; /* the history has changed */ gboolean need_push; /* need to push the current Input on hist? */ + gboolean strip_password; /* need to strip password before placing string to history */ char **completions; /* possible completions array */ input_complete_t completion_flags; char charbuf[MB_LEN_MAX]; /* buffer for multibytes characters */ diff --git a/lib/widget/quick.c b/lib/widget/quick.c index aa0bdb6cd..c6b415a23 100644 --- a/lib/widget/quick.c +++ b/lib/widget/quick.c @@ -109,6 +109,8 @@ quick_dialog_skip (QuickDialog * qd, int nskip) in->is_password = (qw->u.input.flags == 1); if ((qw->u.input.flags & 2) != 0) in->completion_flags |= INPUT_COMPLETE_CD; + if ((qw->u.input.flags & 4) != 0) + in->strip_password = TRUE; qw->widget = (Widget *) in; *qw->u.input.result = NULL; break; diff --git a/lib/widget/quick.h b/lib/widget/quick.h index f7ac2c23f..000b27eed 100644 --- a/lib/widget/quick.h +++ b/lib/widget/quick.h @@ -186,6 +186,7 @@ typedef struct int flags; /* 1 -- is_password, 2 -- INPUT_COMPLETE_CD */ const char *histname; char **result; + gboolean strip_password; } input; struct diff --git a/lib/widget/wtools.c b/lib/widget/wtools.c index 360d58a45..1f54d5d81 100644 --- a/lib/widget/wtools.c +++ b/lib/widget/wtools.c @@ -180,14 +180,14 @@ bg_message (int dummy, int *flags, char *title, const char *text) */ static char * fg_input_dialog_help (const char *header, const char *text, const char *help, - const char *history_name, const char *def_text) + const char *history_name, const char *def_text, gboolean strip_password) { char *my_str; - + int flags = (strip_password) ? 4 : 0; QuickWidget quick_widgets[] = { /* 0 */ QUICK_BUTTON (6, 64, 1, 0, N_("&Cancel"), B_CANCEL, NULL), /* 1 */ QUICK_BUTTON (3, 64, 1, 0, N_("&OK"), B_ENTER, NULL), - /* 2 */ QUICK_INPUT (3, 64, 0, 0, def_text, 58, 0, NULL, &my_str), + /* 2 */ QUICK_INPUT (3, 64, 0, 0, def_text, 58, flags, NULL, &my_str), /* 3 */ QUICK_LABEL (3, 64, 2, 0, ""), QUICK_END }; @@ -474,7 +474,7 @@ message (int flags, const char *title, const char *text, ...) char * input_dialog_help (const char *header, const char *text, const char *help, - const char *history_name, const char *def_text) + const char *history_name, const char *def_text, gboolean strip_password) { #ifdef ENABLE_BACKGROUND if (mc_global.we_are_background) @@ -482,18 +482,20 @@ input_dialog_help (const char *header, const char *text, const char *help, union { void *p; - char *(*f) (const char *, const char *, const char *, const char *, const char *); + char *(*f) (const char *, const char *, const char *, const char *, const char *, + gboolean); } func; func.f = fg_input_dialog_help; - return wtools_parent_call_string (func.p, 5, + return wtools_parent_call_string (func.p, 6, strlen (header), header, strlen (text), text, strlen (help), help, strlen (history_name), history_name, - strlen (def_text), def_text); + strlen (def_text), def_text, + sizeof (gboolean), strip_password); } else #endif /* ENABLE_BACKGROUND */ - return fg_input_dialog_help (header, text, help, history_name, def_text); + return fg_input_dialog_help (header, text, help, history_name, def_text, strip_password); } /* --------------------------------------------------------------------------------------------- */ @@ -502,7 +504,7 @@ input_dialog_help (const char *header, const char *text, const char *help, char * input_dialog (const char *header, const char *text, const char *history_name, const char *def_text) { - return input_dialog_help (header, text, "[Input Line Keys]", history_name, def_text); + return input_dialog_help (header, text, "[Input Line Keys]", history_name, def_text, FALSE); } /* --------------------------------------------------------------------------------------------- */ diff --git a/lib/widget/wtools.h b/lib/widget/wtools.h index d6162625f..61f203667 100644 --- a/lib/widget/wtools.h +++ b/lib/widget/wtools.h @@ -33,7 +33,7 @@ enum char *input_dialog (const char *header, const char *text, const char *history_name, const char *def_text); char *input_dialog_help (const char *header, const char *text, const char *help, - const char *history_name, const char *def_text); + const char *history_name, const char *def_text, gboolean strip_password); char *input_expand_dialog (const char *header, const char *text, const char *history_name, const char *def_text); diff --git a/src/filemanager/cmd.c b/src/filemanager/cmd.c index c9a89b7ac..f03a95301 100644 --- a/src/filemanager/cmd.c +++ b/src/filemanager/cmd.c @@ -234,7 +234,7 @@ set_panel_filter (WPanel * p) reg_exp = input_dialog_help (_("Filter"), _("Set expression for filtering filenames"), - "[Filter...]", MC_HISTORY_FM_PANEL_FILTER, x); + "[Filter...]", MC_HISTORY_FM_PANEL_FILTER, x, FALSE); if (!reg_exp) return; set_panel_filter_to (p, reg_exp); @@ -539,7 +539,7 @@ transform_prefix (const char *prefix) static void nice_cd (const char *text, const char *xtext, const char *help, - const char *history_name, const char *prefix, int to_home) + const char *history_name, const char *prefix, int to_home, gboolean strip_password) { char *machine; char *cd_path; @@ -547,7 +547,7 @@ nice_cd (const char *text, const char *xtext, const char *help, if (!SELECTED_IS_PANEL) return; - machine = input_dialog_help (text, xtext, help, history_name, ""); + machine = input_dialog_help (text, xtext, help, history_name, "", strip_password); if (!machine) return; @@ -1537,7 +1537,7 @@ void ftplink_cmd (void) { nice_cd (_("FTP to machine"), _(machine_str), - "[FTP File System]", ":ftplink_cmd: FTP to machine ", "/#ftp:", 1); + "[FTP File System]", ":ftplink_cmd: FTP to machine ", "/#ftp:", 1, TRUE); } #endif /* ENABLE_VFS_FTP */ @@ -1549,7 +1549,7 @@ fishlink_cmd (void) { nice_cd (_("Shell link to machine"), _(machine_str), "[FIle transfer over SHell filesystem]", ":fishlink_cmd: Shell link to machine ", - "/#sh:", 1); + "/#sh:", 1, TRUE); } #endif /* ENABLE_VFS_FISH */ @@ -1560,7 +1560,7 @@ void smblink_cmd (void) { nice_cd (_("SMB link to machine"), _(machine_str), - "[SMB File System]", ":smblink_cmd: SMB link to machine ", "/#smb:", 0); + "[SMB File System]", ":smblink_cmd: SMB link to machine ", "/#smb:", 0, TRUE); } #endif /* ENABLE_VFS_SMB */ #endif /* ENABLE_VFS_NET */ @@ -1573,7 +1573,7 @@ undelete_cmd (void) { nice_cd (_("Undelete files on an ext2 file system"), _("Enter device (without /dev/) to undelete\nfiles on: (F1 for details)"), - "[Undelete File System]", ":undelete_cmd: Undel on ext2 fs ", "/#undel:", 0); + "[Undelete File System]", ":undelete_cmd: Undel on ext2 fs ", "/#undel:", 0, FALSE); } #endif /* ENABLE_VFS_UNDELFS */ diff --git a/tests/lib/vfs/path_recode.c b/tests/lib/vfs/path_recode.c index 5d2377cea..8c67aedae 100644 --- a/tests/lib/vfs/path_recode.c +++ b/tests/lib/vfs/path_recode.c @@ -159,6 +159,11 @@ START_TEST(test_path_to_str_flags) vfs_test_ops1.prefix = "test1"; vfs_register_class (&vfs_test_ops1); + vpath = vfs_path_from_str_flags ("test1://user:passwd@127.0.0.1", VPF_NO_CANON); + str_path = vfs_path_to_str_flags (vpath, 0, VPF_STRIP_PASSWORD); + fail_unless (strcmp ("test1://user@127.0.0.1/", str_path) == 0, "\nstr=%s\n", str_path); + g_free (str_path); + vfs_path_free (vpath); vpath = vfs_path_from_str ("/test1://user:passwd@host.name/#enc:KOI8-R/тестовый/путь"); str_path = vfs_path_to_str_flags (vpath, 0, VPF_STRIP_PASSWORD);