fix: files with "*" in the name couldn't be selected as part of a zip
Massimo Melina committed
Jan 21, 2025 at 18:43 UTC
dea9d476a63d49d2e169cd85c31d023fba7d72fa
3 files changed
+4
-4
frontend/src/menu.ts
+2
-2
@@ -42,7 +42,7 @@ export function MenuPanel() {
42
43
// passing files as string in the url should allow 1-2000 items before hitting the url limit of 64KB. Shouldn't be a problem, right?
44
const ofs = location.pathname.length
45
- const list = useMemo(() => Object.keys(selected).map(s => s.slice(ofs, s.endsWith('/') ? -1 : Infinity)).join('*'), [selected])
45
+ const list = useMemo(() => Object.keys(selected).map(s => s.slice(ofs, s.endsWith('/') ? -1 : Infinity)).join('//'), [selected])
46
47
// avoid useless dom changes while we are still waiting for necessary data
48
const [changingButton, setChangingButton] = useState<'' | 'upload' | 'delete'>('')
@@ -68,7 +68,7 @@ export function MenuPanel() {
68
icon: 'delete',
69
label: t`Delete`,
70
className: 'show-sliding',
71
- disabled: !list.length,
71
+ disabled: !list,
72
tooltip: t('delete_select', "Select something to delete"),
73
onClick: () => deleteFiles(Object.keys(selected))
74
} : {
src/zip.ts
+1
-1
@@ -15,7 +15,7 @@ import { getCommentFor } from './comments'
15
16
// expects 'node' to have had permissions checked by caller
17
export async function zipStreamFromFolder(node: VfsNode, ctx: Koa.Context) {
18
- const list = wantArray(ctx.query.list)[0]?.split('*') // we are using * as separator because it cannot be used in a file name and doesn't need url encoding
18
+ const list = wantArray(ctx.query.list)[0]?.split('//') // slash is the only char not allowed in file names both for windows and unix, but still we need to encode whole paths, so the only safe choice to separate the entries is the double slash
19
if (!list && statusCodeForMissingPerm(node, 'can_archive', ctx)) return
20
ctx.status = HTTP_OK
21
ctx.mime = 'zip'
tests/test.ts
+1
-1
@@ -102,7 +102,7 @@ describe('basics', () => {
102
it('zip.partial', req('/f1/?get=zip', { re:/^C3$/, length: 2 }, { headers: { Range: `bytes=${zipOfs}-${zipOfs+1}` } }) )
103
it('zip.partial.resume', req('/f1/?get=zip', { re:/^C3/, length:zipSize-zipOfs }, { headers: { Range: `bytes=${zipOfs}-` } }) )
104
it('zip.partial.end', req('/f1/f2/?get=zip', { re:/^6/, length:10 }, { headers: { Range: 'bytes=-10' } }) )
105
- it('zip.alfa is forbidden', req('/protectFromAbove/child/?get=zip&list=alfa.txt*renamed', { empty: true, length:118 }, { method:'HEAD' }))
105
+ it('zip.alfa is forbidden', req('/protectFromAbove/child/?get=zip&list=alfa.txt//renamed', { empty: true, length:118 }, { method:'HEAD' }))
106
it('zip.cantReadPage', req('/cantReadPage/?get=zip', { length: 120 }, { method:'HEAD' }))
107
108
it('referer', req('/f1/page/gpl.png', 403, {