Skip to content

Commit bbb8d78

Browse files
authored
Merge pull request #1726 from nodeSolidServer/resourceName
checkItmName recursively & reject resource with $.ext
2 parents 31b4ed4 + 74a3d61 commit bbb8d78

File tree

3 files changed

+46
-13
lines changed

3 files changed

+46
-13
lines changed

lib/ldp.js

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,14 @@ class LDP {
243243
'PUT request requires a content-type via the Content-Type header')
244244
}
245245

246+
// reject resource with percent-encoded $ extension
247+
const dollarExtensionRegex = /%(?:24)\.[^%(?:24)]*$/ // /\$\.[^$]*$/
248+
if ((url.url || url).match(dollarExtensionRegex)) {
249+
throw error(400, 'Resource with a $.ext is not allowed by the server')
250+
}
251+
246252
// check if a folder or file with same name exists
253+
// const urlItem = url.url || url
247254
await this.checkItemName(url)
248255

249256
// First check if we are above quota
@@ -350,17 +357,27 @@ class LDP {
350357

351358
async checkItemName (url) {
352359
let testName
353-
const itemUrl = (url.url || url)
360+
const { hostname, pathname } = this.resourceMapper._parseUrl(url) // (url.url || url)
361+
let itemUrl = this.resourceMapper.resolveUrl(hostname, pathname)
354362
const container = itemUrl.endsWith('/')
355363
try {
356364
const testUrl = container ? itemUrl.slice(0, -1) : itemUrl + '/'
357365
const { path: testPath } = await this.resourceMapper.mapUrlToFile({ url: testUrl })
358-
// testName = fs.lstatSync(testPath).isDirectory()
359366
testName = container ? fs.lstatSync(testPath).isFile() : fs.lstatSync(testPath).isDirectory()
360-
} catch (err) { testName = false }
361-
367+
} catch (err) {
368+
testName = false
369+
370+
// item does not exist, check one level up the tree
371+
if (itemUrl.endsWith('/')) itemUrl = itemUrl.substring(0, itemUrl.length - 1)
372+
itemUrl = itemUrl.substring(0, itemUrl.lastIndexOf('/') + 1)
373+
const { pathname } = this.resourceMapper._parseUrl(itemUrl) // (url.url || url)
374+
// check not at root
375+
if (pathname !== '/') {
376+
await this.checkItemName(itemUrl)
377+
}
378+
}
362379
if (testName) {
363-
throw error(200, 'Container and resource cannot have the same name in URI')
380+
throw error(404, 'Container and resource cannot have the same name in URI')
364381
}
365382
}
366383

test/integration/http-test.js

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -535,13 +535,29 @@ describe('HTTP APIs', function () {
535535
.expect(hasHeader('acl', 'baz.ttl' + suffixAcl))
536536
.expect(201, done)
537537
})
538-
it('should not create new resource if folder with same name exists', function (done) {
539-
server.put('/foo/bar')
538+
it('should not create a resource with percent-encoded $.ext', function (done) {
539+
server.put('/foo/bar/baz%24.ttl')
540540
.send(putRequestBody)
541541
.set('content-type', 'text/turtle')
542-
.expect(hasHeader('describedBy', 'bar' + suffixMeta))
543-
.expect(hasHeader('acl', 'bar' + suffixAcl))
544-
.expect(200, done)
542+
// .expect(hasHeader('describedBy', 'baz.ttl' + suffixMeta))
543+
// .expect(hasHeader('acl', 'baz.ttl' + suffixAcl))
544+
.expect(400, done) // 404
545+
})
546+
it('should create a resource without extension', function (done) {
547+
server.put('/foo/bar/baz')
548+
.send(putRequestBody)
549+
.set('content-type', 'text/turtle')
550+
.expect(hasHeader('describedBy', 'baz' + suffixMeta))
551+
.expect(hasHeader('acl', 'baz' + suffixAcl))
552+
.expect(201, done)
553+
})
554+
it('should not create new resource if a folder/resource with same name will exist in tree', function (done) {
555+
server.put('/foo/bar/baz/test.ttl')
556+
.send(putRequestBody)
557+
.set('content-type', 'text/turtle')
558+
.expect(hasHeader('describedBy', 'test.ttl' + suffixMeta))
559+
.expect(hasHeader('acl', 'test.ttl' + suffixAcl))
560+
.expect(404, done)
545561
})
546562
it('should return 201 when trying to put to a container without content-type',
547563
function (done) {
@@ -587,7 +603,7 @@ describe('HTTP APIs', function () {
587603
return Promise.all([
588604
rm('/false-file-48484848'),
589605
createTestResource('/.acl'),
590-
createTestResource('/profile/card$.ttl'),
606+
createTestResource('/profile/card'),
591607
createTestResource('/delete-test-empty-container/.meta.acl'),
592608
createTestResource('/put-resource-1.ttl'),
593609
createTestResource('/put-resource-with-acl.ttl'),

test/integration/ldp-test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,13 +162,13 @@ describe('LDP', function () {
162162

163163
it.skip('with a larger file to exceed allowed quota', function () {
164164
const randstream = stringToStream(randomBytes(2100))
165-
return ldp.put('localhost', '/resources/testQuota.txt', randstream).catch((err) => {
165+
return ldp.put('/localhost', '/resources/testQuota.txt', randstream).catch((err) => {
166166
assert.notOk(err)
167167
})
168168
})
169169
it('should fail if a over quota', function () {
170170
const hellostream = stringToStream('hello world')
171-
return ldp.put('localhost', '/resources/testOverQuota.txt', hellostream).catch((err) => {
171+
return ldp.put('/localhost', '/resources/testOverQuota.txt', hellostream).catch((err) => {
172172
assert.equal(err.status, 413)
173173
})
174174
})

0 commit comments

Comments
 (0)