Skip to content

Commit 7790ea0

Browse files
committed
patch 9.1.0686: zip-plugin has problems with special characters
Problem: zip-plugin has problems with special characters (user202729) Solution: escape '*?[\' on Unix and handle those chars a bit differently on MS-Windows, add a test, check before overwriting files runtime(zip): small fixes for zip plugin This does the following: - verify the unzip plugin is executable when loading the autoload plugin - handle extracting file names with '[*?\' in its name correctly by escaping those characters for the unzip command (and handle those characters a bit differently on MS-Windows, since the quoting is different) - verify, that the extract plugin is not overwriting a file (could cause a hang, because unzip asking for confirmation) - add a test zip file which contains those special file names fixes: #15505 closes: #15519 Signed-off-by: Christian Brabandt <cb@256bit.org>
1 parent 5f5f283 commit 7790ea0

5 files changed

Lines changed: 130 additions & 4 deletions

File tree

Filelist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ SRC_ALL = \
221221
src/testdir/samples/*.vim \
222222
src/testdir/samples/test000 \
223223
src/testdir/samples/test.zip \
224+
src/testdir/samples/testa.zip \
224225
src/testdir/color_ramp.vim \
225226
src/testdir/silent.wav \
226227
src/testdir/popupbounce.vim \

runtime/autoload/zip.vim

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
" zip.vim: Handles browsing zipfiles
22
" AUTOLOAD PORTION
3-
" Date: Aug 05, 2024
3+
" Date: Aug 18, 2024
44
" Version: 34
55
" Maintainer: This runtime file is looking for a new maintainer.
66
" Former Maintainer: Charles E Campbell
@@ -12,6 +12,7 @@
1212
" 2024 Aug 04 by Vim Project: escape '[' in name of file to be extracted
1313
" 2024 Aug 05 by Vim Project: workaround for the FreeBSD's unzip
1414
" 2024 Aug 05 by Vim Project: clean-up and make it work with shellslash on Windows
15+
" 2024 Aug 18 by Vim Project: correctly handle special globbing chars
1516
" License: Vim License (see vim's :help license)
1617
" Copyright: Copyright (C) 2005-2019 Charles E. Campbell {{{1
1718
" Permission is hereby granted to use and distribute this code,
@@ -73,6 +74,11 @@ if v:version < 901
7374
call s:Mess('WarningMsg', "***warning*** this version of zip needs vim 9.1 or later")
7475
finish
7576
endif
77+
" sanity checks
78+
if !executable(g:zip_unzipcmd)
79+
call s:Mess('Error', "***error*** (zip#Browse) unzip not available on your system")
80+
finish
81+
endif
7682
if !dist#vim#IsSafeExecutable('zip', g:zip_unzipcmd)
7783
call s:Mess('Error', "Warning: NOT executing " .. g:zip_unzipcmd .. " from current directory!")
7884
finish
@@ -199,7 +205,7 @@ fun! zip#Read(fname,mode)
199205
let zipfile = substitute(a:fname,'^.\{-}zipfile://\(.\{-}\)::[^\\].*$','\1','')
200206
let fname = substitute(a:fname,'^.\{-}zipfile://.\{-}::\([^\\].*\)$','\1','')
201207
endif
202-
let fname = substitute(fname, '[', '[[]', 'g')
208+
let fname = fname->substitute('[', '[[]', 'g')->escape('?*\\')
203209
" sanity check
204210
if !executable(substitute(g:zip_unzipcmd,'\s\+.*$','',''))
205211
call s:Mess('Error', "***error*** (zip#Read) sorry, your system doesn't appear to have the ".g:zip_unzipcmd." program")
@@ -331,9 +337,24 @@ fun! zip#Extract()
331337
call s:Mess('Error', "***error*** (zip#Extract) Please specify a file, not a directory")
332338
return
333339
endif
340+
if filereadable(fname)
341+
call s:Mess('Error', "***error*** (zip#Extract) <" .. fname .."> already exists in directory, not overwriting!")
342+
return
343+
endif
344+
let target = fname->substitute('\[', '[[]', 'g')
345+
if &shell =~ 'cmd' && (has("win32") || has("win64"))
346+
let target = target
347+
\ ->substitute('[?*]', '[&]', 'g')
348+
\ ->substitute('[\\]', '?', 'g')
349+
\ ->shellescape()
350+
" there cannot be a file name with '\' in its name, unzip replaces it by _
351+
let fname = fname->substitute('[\\?*]', '_', 'g')
352+
else
353+
let target = target->escape('*?\\')->shellescape()
354+
endif
334355

335356
" extract the file mentioned under the cursor
336-
call system($"{g:zip_extractcmd} {shellescape(b:zipfile)} {shellescape(fname)}")
357+
call system($"{g:zip_extractcmd} -o {shellescape(b:zipfile)} {target}")
337358
if v:shell_error != 0
338359
call s:Mess('Error', "***error*** ".g:zip_extractcmd." ".b:zipfile." ".fname.": failed!")
339360
elseif !filereadable(fname)

src/testdir/samples/testa.zip

1.21 KB
Binary file not shown.

src/testdir/test_zip_plugin.vim

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ def Test_zip_basic()
4040
execute("normal \<CR>"))
4141

4242
### Check ENTER on file
43-
:1|:/^$//file/
43+
:1
44+
search('file.txt')
4445
exe ":normal \<cr>"
4546
assert_match('zipfile://.*/X.zip::Xzip/file.txt', @%)
4647
assert_equal('one', getline(1))
@@ -65,6 +66,10 @@ def Test_zip_basic()
6566
:1|:/^$//file/
6667
normal x
6768
assert_true(filereadable("Xzip/file.txt"))
69+
70+
## Check not overwriting existing file
71+
assert_match('<Xzip/file.txt> .* not overwriting!', execute("normal x"))
72+
6873
delete("Xzip", "rf")
6974

7075
### Check extracting directory
@@ -131,5 +136,102 @@ def Test_zip_basic()
131136
assert_match('File not readable', execute("e Xnot_exists.zip"))
132137

133138
bw
139+
enddef
140+
141+
def Test_zip_glob_fname()
142+
CheckNotMSWindows
143+
# does not work on Windows, why?
144+
145+
### copy sample zip file
146+
if !filecopy("samples/testa.zip", "X.zip")
147+
assert_report("Can't copy samples/testa.zip")
148+
return
149+
endif
150+
defer delete("X.zip")
151+
defer delete('zipglob', 'rf')
152+
153+
e X.zip
154+
155+
### 1) Check extracting strange files
156+
:1
157+
var fname = 'a[a].txt'
158+
search('\V' .. fname)
159+
normal x
160+
assert_true(filereadable('zipglob/' .. fname))
161+
delete('zipglob', 'rf')
162+
163+
:1
164+
fname = 'a*.txt'
165+
search('\V' .. fname)
166+
normal x
167+
assert_true(filereadable('zipglob/' .. fname))
168+
delete('zipglob', 'rf')
169+
170+
:1
171+
fname = 'a?.txt'
172+
search('\V' .. fname)
173+
normal x
174+
assert_true(filereadable('zipglob/' .. fname))
175+
delete('zipglob', 'rf')
176+
177+
:1
178+
fname = 'a\.txt'
179+
search('\V' .. escape(fname, '\\'))
180+
normal x
181+
assert_true(filereadable('zipglob/' .. fname))
182+
delete('zipglob', 'rf')
183+
184+
:1
185+
fname = 'a\\.txt'
186+
search('\V' .. escape(fname, '\\'))
187+
normal x
188+
assert_true(filereadable('zipglob/' .. fname))
189+
delete('zipglob', 'rf')
190+
191+
### 2) Check entering strange file names
192+
:1
193+
fname = 'a[a].txt'
194+
search('\V' .. fname)
195+
exe ":normal \<cr>"
196+
assert_match('zipfile://.*/X.zip::zipglob/a\[a\].txt', @%)
197+
assert_equal('a test file with []', getline(1))
198+
bw
199+
200+
e X.zip
201+
:1
202+
fname = 'a*.txt'
203+
search('\V' .. fname)
204+
exe ":normal \<cr>"
205+
assert_match('zipfile://.*/X.zip::zipglob/a\*.txt', @%)
206+
assert_equal('a test file with a*', getline(1))
207+
bw
208+
209+
e X.zip
210+
:1
211+
fname = 'a?.txt'
212+
search('\V' .. fname)
213+
exe ":normal \<cr>"
214+
assert_match('zipfile://.*/X.zip::zipglob/a?.txt', @%)
215+
assert_equal('a test file with a?', getline(1))
216+
bw
217+
218+
e X.zip
219+
:1
220+
fname = 'a\.txt'
221+
search('\V' .. escape(fname, '\\'))
222+
exe ":normal \<cr>"
223+
assert_match('zipfile://.*/X.zip::zipglob/a\\.txt', @%)
224+
assert_equal('a test file with a\', getline(1))
225+
bw
134226

227+
e X.zip
228+
:1
229+
fname = 'a\\.txt'
230+
search('\V' .. escape(fname, '\\'))
231+
exe ":normal \<cr>"
232+
assert_match('zipfile://.*/X.zip::zipglob/a\\\\.txt', @%)
233+
assert_equal('a test file with a double \', getline(1))
234+
bw
235+
236+
bw
135237
enddef

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,8 @@ static char *(features[]) =
704704

705705
static int included_patches[] =
706706
{ /* Add new patch number below this line */
707+
/**/
708+
686,
707709
/**/
708710
685,
709711
/**/

0 commit comments

Comments
 (0)