From 235759b96134bd7c0fbe9ea806a09b9e529c6ad7 Mon Sep 17 00:00:00 2001 From: bourgeoa Date: Wed, 29 Mar 2023 17:01:11 +0200 Subject: [PATCH 1/5] checkItmName recursively & reject resource with $.ext --- lib/ldp.js | 27 ++++++++++++++++++++++----- test/integration/http-test.js | 28 ++++++++++++++++++++++------ test/integration/ldp-test.js | 4 ++-- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/lib/ldp.js b/lib/ldp.js index 448e3ac52..32b92b925 100644 --- a/lib/ldp.js +++ b/lib/ldp.js @@ -243,7 +243,14 @@ class LDP { 'PUT request requires a content-type via the Content-Type header') } + // reject resource with $ extension + const dollarExtensionRegex = /\$\.[^$]*$/ + if ((url.url || url).match(dollarExtensionRegex)) { + throw error(400, 'Resource with a $.ext is not allowed by the server') + } + // check if a folder or file with same name exists + // const urlItem = url.url || url await this.checkItemName(url) // First check if we are above quota @@ -350,17 +357,27 @@ class LDP { async checkItemName (url) { let testName - const itemUrl = (url.url || url) + const { hostname, pathname } = this.resourceMapper._parseUrl(url) // (url.url || url) + let itemUrl = this.resourceMapper.resolveUrl(hostname, pathname) const container = itemUrl.endsWith('/') try { const testUrl = container ? itemUrl.slice(0, -1) : itemUrl + '/' const { path: testPath } = await this.resourceMapper.mapUrlToFile({ url: testUrl }) - // testName = fs.lstatSync(testPath).isDirectory() testName = container ? fs.lstatSync(testPath).isFile() : fs.lstatSync(testPath).isDirectory() - } catch (err) { testName = false } - + } catch (err) { + testName = false + + // item do not exist, check one level up the tree + if (itemUrl.endsWith('/')) itemUrl = itemUrl.substring(0, itemUrl.length - 1) + itemUrl = itemUrl.substring(0, itemUrl.lastIndexOf('/') + 1) + const { pathname } = this.resourceMapper._parseUrl(itemUrl) // (url.url || url) + // check not at root + if (pathname !== '/') { + await this.checkItemName(itemUrl) + } + } if (testName) { - throw error(200, 'Container and resource cannot have the same name in URI') + throw error(404, 'Container and resource cannot have the same name in URI') } } diff --git a/test/integration/http-test.js b/test/integration/http-test.js index a4d913af9..5f070f259 100644 --- a/test/integration/http-test.js +++ b/test/integration/http-test.js @@ -535,13 +535,29 @@ describe('HTTP APIs', function () { .expect(hasHeader('acl', 'baz.ttl' + suffixAcl)) .expect(201, done) }) - it('should not create new resource if folder with same name exists', function (done) { - server.put('/foo/bar') + it('should not create a resource with $.ext', function (done) { // alain + server.put('/foo/bar/baz$.ttl') .send(putRequestBody) .set('content-type', 'text/turtle') - .expect(hasHeader('describedBy', 'bar' + suffixMeta)) - .expect(hasHeader('acl', 'bar' + suffixAcl)) - .expect(200, done) + // .expect(hasHeader('describedBy', 'baz.ttl' + suffixMeta)) + // .expect(hasHeader('acl', 'baz.ttl' + suffixAcl)) + .expect(400, done) // 404 + }) + it('should not create a resource with $.ext', function (done) { // alain + server.put('/foo/bar/baz') + .send(putRequestBody) + .set('content-type', 'text/turtle') + .expect(hasHeader('describedBy', 'baz' + suffixMeta)) + .expect(hasHeader('acl', 'baz' + suffixAcl)) + .expect(201, done) + }) + it('should not create new resource if a folder/resource with same name will exist in tree', function (done) { + server.put('/foo/bar/baz/test.ttl') + .send(putRequestBody) + .set('content-type', 'text/turtle') + .expect(hasHeader('describedBy', 'test.ttl' + suffixMeta)) + .expect(hasHeader('acl', 'test.ttl' + suffixAcl)) + .expect(404, done) }) it('should return 201 when trying to put to a container without content-type', function (done) { @@ -587,7 +603,7 @@ describe('HTTP APIs', function () { return Promise.all([ rm('/false-file-48484848'), createTestResource('/.acl'), - createTestResource('/profile/card$.ttl'), + createTestResource('/profile/card'), createTestResource('/delete-test-empty-container/.meta.acl'), createTestResource('/put-resource-1.ttl'), createTestResource('/put-resource-with-acl.ttl'), diff --git a/test/integration/ldp-test.js b/test/integration/ldp-test.js index 0027cfcbc..cca0cc2fc 100644 --- a/test/integration/ldp-test.js +++ b/test/integration/ldp-test.js @@ -162,13 +162,13 @@ describe('LDP', function () { it.skip('with a larger file to exceed allowed quota', function () { const randstream = stringToStream(randomBytes(2100)) - return ldp.put('localhost', '/resources/testQuota.txt', randstream).catch((err) => { + return ldp.put('/localhost', '/resources/testQuota.txt', randstream).catch((err) => { assert.notOk(err) }) }) it('should fail if a over quota', function () { const hellostream = stringToStream('hello world') - return ldp.put('localhost', '/resources/testOverQuota.txt', hellostream).catch((err) => { + return ldp.put('/localhost', '/resources/testOverQuota.txt', hellostream).catch((err) => { assert.equal(err.status, 413) }) }) From e7d34260e534b5e67d237ae17c5fe7fd15c5f26d Mon Sep 17 00:00:00 2001 From: Alain Bourgeois Date: Wed, 29 Mar 2023 19:43:06 +0200 Subject: [PATCH 2/5] Update lib/ldp.js Co-authored-by: Ted Thibodeau Jr --- lib/ldp.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ldp.js b/lib/ldp.js index 32b92b925..1abf880fd 100644 --- a/lib/ldp.js +++ b/lib/ldp.js @@ -367,7 +367,7 @@ class LDP { } catch (err) { testName = false - // item do not exist, check one level up the tree + // item does not exist, check one level up the tree if (itemUrl.endsWith('/')) itemUrl = itemUrl.substring(0, itemUrl.length - 1) itemUrl = itemUrl.substring(0, itemUrl.lastIndexOf('/') + 1) const { pathname } = this.resourceMapper._parseUrl(itemUrl) // (url.url || url) From ff5799ef75f714b4bf8cd42ec00a52e2dbcf141b Mon Sep 17 00:00:00 2001 From: bourgeoa Date: Mon, 3 Apr 2023 19:55:49 +0200 Subject: [PATCH 3/5] updates --- lib/ldp.js | 4 ++-- test/integration/http-test.js | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/ldp.js b/lib/ldp.js index 32b92b925..f6f4bfbb4 100644 --- a/lib/ldp.js +++ b/lib/ldp.js @@ -243,8 +243,8 @@ class LDP { 'PUT request requires a content-type via the Content-Type header') } - // reject resource with $ extension - const dollarExtensionRegex = /\$\.[^$]*$/ + // reject resource with % encoded $ extension + const dollarExtensionRegex = /%(?:24)\.[^%(?:24)]*$/ // /\$\.[^$]*$/ if ((url.url || url).match(dollarExtensionRegex)) { throw error(400, 'Resource with a $.ext is not allowed by the server') } diff --git a/test/integration/http-test.js b/test/integration/http-test.js index 5f070f259..b7230f480 100644 --- a/test/integration/http-test.js +++ b/test/integration/http-test.js @@ -535,15 +535,15 @@ describe('HTTP APIs', function () { .expect(hasHeader('acl', 'baz.ttl' + suffixAcl)) .expect(201, done) }) - it('should not create a resource with $.ext', function (done) { // alain - server.put('/foo/bar/baz$.ttl') + it('should not create a resource with % encoded $.ext', function (done) { + server.put('/foo/bar/baz%24.ttl') .send(putRequestBody) .set('content-type', 'text/turtle') // .expect(hasHeader('describedBy', 'baz.ttl' + suffixMeta)) // .expect(hasHeader('acl', 'baz.ttl' + suffixAcl)) .expect(400, done) // 404 }) - it('should not create a resource with $.ext', function (done) { // alain + it('should create a resource without extension', function (done) { server.put('/foo/bar/baz') .send(putRequestBody) .set('content-type', 'text/turtle') From f9063220c899e235f3ca02c596ef0045fda00df8 Mon Sep 17 00:00:00 2001 From: Alain Bourgeois Date: Mon, 3 Apr 2023 21:45:02 +0200 Subject: [PATCH 4/5] Update lib/ldp.js Co-authored-by: Ted Thibodeau Jr --- lib/ldp.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ldp.js b/lib/ldp.js index cabe47336..e6ed2de7c 100644 --- a/lib/ldp.js +++ b/lib/ldp.js @@ -243,7 +243,7 @@ class LDP { 'PUT request requires a content-type via the Content-Type header') } - // reject resource with % encoded $ extension + // reject resource with percent-encoded $ extension const dollarExtensionRegex = /%(?:24)\.[^%(?:24)]*$/ // /\$\.[^$]*$/ if ((url.url || url).match(dollarExtensionRegex)) { throw error(400, 'Resource with a $.ext is not allowed by the server') From 74a3d61f7fdc1055d87643d8f6c57fe4df9b474c Mon Sep 17 00:00:00 2001 From: Alain Bourgeois Date: Mon, 3 Apr 2023 21:45:11 +0200 Subject: [PATCH 5/5] Update test/integration/http-test.js Co-authored-by: Ted Thibodeau Jr --- test/integration/http-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/http-test.js b/test/integration/http-test.js index b7230f480..cbe7d5bc9 100644 --- a/test/integration/http-test.js +++ b/test/integration/http-test.js @@ -535,7 +535,7 @@ describe('HTTP APIs', function () { .expect(hasHeader('acl', 'baz.ttl' + suffixAcl)) .expect(201, done) }) - it('should not create a resource with % encoded $.ext', function (done) { + it('should not create a resource with percent-encoded $.ext', function (done) { server.put('/foo/bar/baz%24.ttl') .send(putRequestBody) .set('content-type', 'text/turtle')