Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 53 additions & 3 deletions __tests__/files/node.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -740,16 +740,66 @@ describe('Undefined properties are allowed', () => {
})

describe('Encoded source is handled properly', () => {
test('File', () => {
test('File with special characters', () => {
const file = new File({
source: 'https://cloud.domain.com/remote.php/dav/files/em ma!/Photos~⛰️ shot of a $[big} mountain/realy #1\'s.md',
source: 'https://cloud.domain.com/remote.php/dav/files/em ma!/Photos~⛰️ shot of a $[big} mountain/really #1\'s.md',
owner: 'em ma!',
id: 123456,
mime: 'image/jpeg',
root: '/files/em ma!',
})

expect(file.encodedSource).toBe('https://cloud.domain.com/remote.php/dav/files/em%20ma!/Photos~%E2%9B%B0%EF%B8%8F%20shot%20of%20a%20%24%5Bbig%7D%20mountain/realy%20%231\'s.md')
expect(file.encodedSource).toBe('https://cloud.domain.com/remote.php/dav/files/em%20ma!/Photos~%E2%9B%B0%EF%B8%8F%20shot%20of%20a%20%24%5Bbig%7D%20mountain/really%20%231\'s.md')
expect(file.path).toBe('/Photos~⛰️ shot of a $[big} mountain/really #1\'s.md')
expect(file.basename).toBe('really #1\'s.md')
})

test('Folder with question mark', () => {
const folder = new Folder({
source: 'https://cloud.domain.com/remote.php/dav/files/emma?/Photos?',
owner: 'emma?',
root: '/files/emma?',
})

expect(folder.encodedSource).toBe('https://cloud.domain.com/remote.php/dav/files/emma%3F/Photos%3F')
expect(folder.path).toBe('/Photos?')
expect(folder.basename).toBe('Photos?')
})

test('Folder with percent characters', () => {
const folder = new Folder({
source: 'https://cloud.domain.com/remote.php/dav/files/emma%/Ph%otos/rea%lly%',
owner: 'emma%',
root: '/files/emma%',
})

expect(folder.encodedSource).toBe('https://cloud.domain.com/remote.php/dav/files/emma%25/Ph%25otos/rea%25lly%25')
expect(folder.path).toBe('/Ph%otos/rea%lly%')
expect(folder.basename).toBe('rea%lly%')
})

test('Unicode combining marks', () => {
const file = new File({
source: 'https://cloud.domain.com/remote.php/dav/files/emma/cre\u0301me',
owner: 'emma',
root: '/files/emma',
})

expect(file.encodedSource).toBe('https://cloud.domain.com/remote.php/dav/files/emma/cre%CC%81me')
expect(file.path).toBe('/créme')
expect(file.basename).toBe('créme')
})

test('Plus signs in filename', () => {
const folder = new Folder({
source: 'https://cloud.domain.com/remote.php/dav/files/emma/My+Folder/fi+le+.txt',
owner: 'emma',
root: '/files/emma',
})

expect(folder.encodedSource).toBe('https://cloud.domain.com/remote.php/dav/files/emma/My%2BFolder/fi%2Ble%2B.txt')
expect(folder.path).toBe('/My+Folder/fi+le+.txt')
expect(folder.basename).toBe('fi+le+.txt')
})
})

Expand Down
17 changes: 15 additions & 2 deletions lib/node/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,8 +270,21 @@ export abstract class Node {
* Get the absolute path of this object relative to the root
*/
get path(): string {
const url = new URL(this.source)
let source = decodeURI(url.pathname)
// Extract the path part from the source URL
// e.g. https://cloud.domain.com/remote.php/dav/files/username/Path/To/File.txt
const idx = this.source.indexOf('://')
const protocol = this.source.slice(0, idx) // e.g. https
const remainder = this.source.slice(idx + 3) // e.g. cloud.domain.com/remote.php/dav/files/username/Path/To/File.txt

const slashIndex = remainder.indexOf('/')
const host = remainder.slice(0, slashIndex) // e.g. cloud.domain.com
const rawPath = remainder.slice(slashIndex) // e.g. /remote.php/dav/files/username/Path/To/File.txt

// Rebuild a safe URL with encoded path
const safeUrl = `${protocol}://${host}${encodePath(rawPath)}`
const url = new URL(safeUrl)

let source = decodeURIComponent(url.pathname)

if (this.isDavResource) {
// ensure we only work on the real path in case root is not distinct
Expand Down