From f17f78c557c4a437cd06bc7a69ed345176c157fd Mon Sep 17 00:00:00 2001 From: =?utf8?q?Va=CC=81clav=20Kobera?= Date: Sun, 26 Oct 2025 18:21:04 +0000 Subject: [PATCH] patch 9.1.1875: username parsing bug in netrw plugin MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Problem: username parsing bug in netrw plugin when using remote adding feature Solution: Allow any characters except for "@" (Václav Kobera), add a test for the netrw plugin closes: #18611 Signed-off-by: Václav Kobera Signed-off-by: Christian Brabandt --- .../pack/dist/opt/netrw/autoload/netrw.vim | 4 +- src/testdir/Make_all.mak | 2 + src/testdir/test_plugin_netrw.vim | 116 ++++++++++++++++++ src/version.c | 2 + 4 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 src/testdir/test_plugin_netrw.vim diff --git a/runtime/pack/dist/opt/netrw/autoload/netrw.vim b/runtime/pack/dist/opt/netrw/autoload/netrw.vim index 6206be79ae..f1ce7f393e 100644 --- a/runtime/pack/dist/opt/netrw/autoload/netrw.vim +++ b/runtime/pack/dist/opt/netrw/autoload/netrw.vim @@ -10,6 +10,7 @@ " 2025 Sep 17 by Vim Project tighten the regex to handle remote compressed archives #18318 " 2025 Sep 18 by Vim Project 'equalalways' not always respected #18358 " 2025 Oct 01 by Vim Project fix navigate to parent folder #18464 +" 2025 Oct 26 by Vim Project fix parsing of remote user names #18611 " Copyright: Copyright (C) 2016 Charles E. Campbell {{{1 " Permission is hereby granted to use and distribute this code, " with or without modifications, provided that this copyright @@ -9312,7 +9313,7 @@ endfunction function s:RemotePathAnalysis(dirname) " method :// user @ machine :port /path - let dirpat = '^\(\w\{-}\)://\(\(\w\+\)@\)\=\([^/:#]\+\)\%([:#]\(\d\+\)\)\=/\(.*\)$' + let dirpat = '^\(\w\{-}\)://\(\([^@]\+\)@\)\=\([^/:#]\+\)\%([:#]\(\d\+\)\)\=/\(.*\)$' let s:method = substitute(a:dirname,dirpat,'\1','') let s:user = substitute(a:dirname,dirpat,'\3','') let s:machine = substitute(a:dirname,dirpat,'\4','') @@ -9656,5 +9657,4 @@ let &cpo= s:keepcpo unlet s:keepcpo " }}} - " vim:ts=8 sts=4 sw=4 et fdm=marker diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak index 0d4aeb0432..a587034c81 100644 --- a/src/testdir/Make_all.mak +++ b/src/testdir/Make_all.mak @@ -247,6 +247,7 @@ NEW_TESTS = \ test_plugin_helptoc \ test_plugin_man \ test_plugin_matchparen \ + test_plugin_netrw \ test_plugin_tar \ test_plugin_termdebug \ test_plugin_tohtml \ @@ -520,6 +521,7 @@ NEW_TESTS_RES = \ test_plugin_helptoc.res \ test_plugin_man.res \ test_plugin_matchparen.res \ + test_plugin_netrw.res \ test_plugin_tar.res \ test_plugin_termdebug.res \ test_plugin_tohtml.res \ diff --git a/src/testdir/test_plugin_netrw.vim b/src/testdir/test_plugin_netrw.vim new file mode 100644 index 0000000000..750a7d1d92 --- /dev/null +++ b/src/testdir/test_plugin_netrw.vim @@ -0,0 +1,116 @@ +let s:netrw_path = $VIMRUNTIME . '/pack/dist/opt/netrw/autoload/netrw.vim' +let s:netrw_test_dir = 'samples' +let s:netrw_test_path = s:netrw_test_dir . '/netrw.vim' + +"make copy of netrw script and add function to print local variables" +func s:appendDebugToNetrw(netrw_path, netrw_test_path) + let netrwScript = readfile(a:netrw_path) + + let netrwScript += [ + \ '\n', + \ '"-- test helpers ---"', + \ 'function! TestNetrwCaptureRemotePath(dirname)', + \ ' call s:RemotePathAnalysis(a:dirname)', + \ ' return {"method": s:method, "user": s:user, "machine": s:machine, "port": s:port, "path": s:path, "fname": s:fname}', + \ 'endfunction' + \ ] + + call writefile(netrwScript, a:netrw_test_path) + execute 'source' a:netrw_test_path +endfunction + +func s:setup() + call s:appendDebugToNetrw(s:netrw_path, s:netrw_test_path) +endfunction + +func s:cleanup() + call delete(s:netrw_test_path) +endfunction + +func s:combine + \( usernames + \, methods + \, hosts + \, ports + \, dirs + \, files) + for username in a:usernames + for method in a:methods + for host in a:hosts + for port in a:ports + for dir in a:dirs + for file in a:files + " --- Build a full remote path --- + + let port_str = empty(port) ? "" : ':' . port + let remote = printf('%s://%s@%s%s/%s%s', method, username, host, port_str, dir, file) + + let result = TestNetrwCaptureRemotePath(remote) + + call assert_equal(result.method, method) + call assert_equal(result.user, username) + call assert_equal(result.machine, host) + call assert_equal(result.port, port) + call assert_equal(result.path, dir . file) + endfor + endfor + endfor + endfor + endfor + endfor +endfunction + + +func Test_netrw_parse_remote_simple() + call s:setup() + let result = TestNetrwCaptureRemotePath('scp://user@localhost:2222/test.txt') + call assert_equal(result.method, 'scp') + call assert_equal(result.user, 'user') + call assert_equal(result.machine, 'localhost') + call assert_equal(result.port, '2222') + call assert_equal(result.path, 'test.txt') + call s:cleanup() +endfunction + +"testing different combinations" +func Test_netrw_parse_regular_usernames() + call s:setup() + + " --- sample data for combinations ---" + let usernames = ["root", "toor", "user01", "skillIssue"] + let methods = ["scp", "ssh", "ftp", "sftp"] + let hosts = ["localhost", "server.com", "fit-workspaces.ksi.fit.cvut.cz", "192.168.1.42"] + let ports = ["", "22","420", "443", "2222", "1234"] + let dirs = ["", "somefolder/", "path/to/the/bottom/of/the/world/please/send/help/"] + let files = ["test.txt", "tttt.vim", "Makefile"] + + call s:combine(usernames, methods, hosts, ports, dirs, files) + + call s:cleanup() +endfunc + +"Host myserver +" HostName 192.168.1.42 +" User alice +func Test_netrw_parse_ssh_config_entries() + call s:setup() + let result = TestNetrwCaptureRemotePath('scp://myserver//etc/nginx/nginx.conf') + call assert_equal(result.method, 'scp') + call assert_equal(result.user, '') + call assert_equal(result.machine, 'myserver') + call assert_equal(result.port, '') + call assert_equal(result.path, '/etc/nginx/nginx.conf') + call s:cleanup() +endfunction + +"username containing special-chars" +func Test_netrw_parse_special_char_user () + call s:setup() + let result = TestNetrwCaptureRemotePath('scp://user-01@localhost:2222/test.txt') + call assert_equal(result.method, 'scp') + call assert_equal(result.user, 'user-01') + call assert_equal(result.machine, 'localhost') + call assert_equal(result.port, '2222') + call assert_equal(result.path, 'test.txt') + call s:cleanup() +endfunction diff --git a/src/version.c b/src/version.c index fd8ccb7c0b..2fdb0871b5 100644 --- a/src/version.c +++ b/src/version.c @@ -729,6 +729,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1875, /**/ 1874, /**/ -- 2.47.3