fix: faulty upload of files with # in the name #722
Massimo Melina committed
Sep 4, 2024 at 16:39 UTC
ccca4cd5529c9feacd4e580db0f7c861fc1c624b
4 files changed
+8
-7
admin/src/addFiles.ts
+4
-4
@@ -7,7 +7,7 @@ import { reloadVfs } from './VfsPage'
7
import { state } from './state'
8
import { apiCall } from './api'
9
import FilePicker from './FilePicker'
10
-import { focusSelector } from '@hfs/shared'
10
+import { focusSelector, pathEncode } from '@hfs/shared'
11
12
let lastFolder: undefined | string
13
export default function addFiles() {
@@ -36,7 +36,7 @@ export default function addFiles() {
36
h('li', { key: file }, file, ': ', err))
37
)
38
), 'error')
39
- const ids = res.filter(x => x.name).map(x => parent.id + encodeURI(x.name) + (x.link.endsWith('/') ? '/' : ''))
39
+ const ids = res.filter(x => x.name).map(x => parent.id + pathEncode(x.name) + (x.link.endsWith('/') ? '/' : ''))
40
reloadVfs(ids)
41
close()
42
}
@@ -53,7 +53,7 @@ export async function addVirtual() {
53
const { id: parent } = getFolderFromSelected()
54
const res = await apiCall('add_vfs', { parent, name })
55
await alertDialog(`Folder "${res.name}" created`, 'success')
56
- reloadVfs([ parent + encodeURI(res.name) + '/' ])
56
+ reloadVfs([ parent + pathEncode(res.name) + '/' ])
57
}
58
catch(e) {
59
await alertDialog(e as Error)
@@ -64,7 +64,7 @@ export async function addLink() {
64
try {
65
const { id: parent } = getFolderFromSelected()
66
const res = await apiCall('add_vfs', { parent, name: 'new link', url: 'https://example.com' })
67
- reloadVfs([ parent + encodeURI(res.name) ])
67
+ reloadVfs([ parent + pathEncode(res.name) ])
68
toast("Link created", 'success', {
69
onClose: () => focusSelector('input[name=url]')
70
})
frontend/src/fileMenu.ts
+1
-1
@@ -79,7 +79,7 @@ export function openFileMenu(entry: DirEntry, ev: MouseEvent, addToMenu: (Falsy
79
id: 'folder',
80
label: t`Folder`,
81
value: h(Link, {
82
- to: (folder.startsWith('/') ? '' : location.pathname) + folder.split('/').map(encodeURIComponent).join('/') + '/',
82
+ to: (folder.startsWith('/') ? '' : location.pathname) + pathEncode(folder) + '/',
83
onClick: () => closeDialog(null, true)
84
}, folder.replaceAll('/', ' / '))
85
},
frontend/src/upload.ts
+2
-2
@@ -5,7 +5,7 @@ import { Btn, Flex, FlexV, iconBtn, Select } from './components'
5
import {
6
basename, closeDialog, formatBytes, formatPerc, hIcon, useIsMobile, newDialog, prefix, selectFiles, working,
7
HTTP_CONFLICT, HTTP_PAYLOAD_TOO_LARGE, formatSpeed, dirname, getHFS, onlyTruthy, with_, cpuSpeedIndex,
8
- buildUrlQueryString, randomId, HTTP_MESSAGES,
8
+ buildUrlQueryString, randomId, HTTP_MESSAGES, pathEncode,
9
} from './misc'
10
import _ from 'lodash'
11
import { INTERNAL_Snapshot, proxy, ref, snapshot, subscribe, useSnapshot } from 'valtio'
@@ -335,7 +335,7 @@ async function startUpload(toUpload: ToUpload, to: string, resume=0) {
335
let uploadPath = path(toUpload.file)
336
if (toUpload.name)
337
uploadPath = prefix('', dirname(uploadPath), '/') + toUpload.name
338
- req.open('PUT', to + encodeURI(uploadPath) + buildUrlQueryString({
338
+ req.open('PUT', to + pathEncode(uploadPath) + buildUrlQueryString({
339
notificationChannel,
340
...resume && { resume: String(resume) },
341
...toUpload.comment && { comment: toUpload.comment },
src/cross.ts
+1
@@ -398,6 +398,7 @@ export async function promiseBestEffort<T>(promises: Promise<T>[]) {
398
return res.filter(x => x.status === 'fulfilled').map((x: any) => x.value as T)
399
}
400
401
+// encode paths leaving / separator unencoded (not like encodeURIComponent), but still encode #
402
export function pathEncode(s: string) {
403
return encodeURI(s).replace(/#/g, encodeURIComponent)
404
}