From 99f6b0435d78bba51043dbe14ad78069a710293c Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Fri, 15 Jul 2016 16:43:17 +0200 Subject: [PATCH 1/4] Switch the web UI to the new endpoint for logged in users --- core/js/files/client.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/js/files/client.js b/core/js/files/client.js index dc1fef5b65fd..946809da4687 100644 --- a/core/js/files/client.js +++ b/core/js/files/client.js @@ -837,7 +837,7 @@ var client = new OC.Files.Client({ host: OC.getHost(), - root: OC.linkToRemoteBase('webdav'), + root: OC.linkToRemoteBase('dav') + '/files/' + encodeURIComponent(OC.getCurrentUser().uid) + '/', useHTTPS: OC.getProtocol() === 'https' }); OC.Files._defaultClient = client; From c99f5b49b7d4140d451472b1f6f52ba9c095906a Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Mon, 21 Aug 2017 10:55:42 +0200 Subject: [PATCH 2/4] Fix encoding mismatch in JS Encode with encodeURIComponent again. Note that "@" gets encoded to "%40" but when Sabre DAV returns a PROPFIND response, the "@" in the URL is not encoded. To make sure that the href root is properly match, we now compare each section individually in their decoded form. --- core/js/files/client.js | 54 +++++++--- core/js/tests/specs/files/clientSpec.js | 127 ++++++++++++++++-------- 2 files changed, 125 insertions(+), 56 deletions(-) diff --git a/core/js/files/client.js b/core/js/files/client.js index 946809da4687..0ec58e58307f 100644 --- a/core/js/files/client.js +++ b/core/js/files/client.js @@ -43,6 +43,9 @@ }; this._baseUrl = url; + this._rootSections = _.filter(this._root.split('/'), function(section) { return section !== '';}); + this._rootSections = _.map(this._rootSections, window.decodeURIComponent); + var clientOptions = { baseUrl: this._baseUrl, xmlNamespaces: { @@ -240,6 +243,33 @@ return etag; }, + /** + * Parse sub-path from href + * + * @param {String} path href path + * @return {String} sub-path section + */ + _extractPath: function(path) { + var pathSections = path.split('/'); + pathSections = _.filter(pathSections, function(section) { return section !== '';}); + + var i = 0; + for (i = 0; i < this._rootSections.length; i++) { + if (this._rootSections[i] !== decodeURIComponent(pathSections[i])) { + // mismatch + return null; + } + } + + // build the sub-path from the remaining sections + var subPath = ''; + while (i < pathSections.length) { + subPath += '/' + decodeURIComponent(pathSections[i]); + i++; + } + return subPath; + }, + /** * Parse Webdav result * @@ -248,17 +278,12 @@ * @return {Array.} array of file info */ _parseFileInfo: function(response) { - var path = response.href; - if (path.substr(0, this._root.length) === this._root) { - path = path.substr(this._root.length); - } - - if (path.charAt(path.length - 1) === '/') { - path = path.substr(0, path.length - 1); + var path = this._extractPath(response.href); + // invalid subpath + if (path === null) { + return null; } - path = decodeURIComponent(path); - if (response.propStat.length === 0 || response.propStat[0].status !== 'HTTP/1.1 200 OK') { return null; } @@ -356,9 +381,14 @@ */ _parseResult: function(responses) { var self = this; - return _.map(responses, function(response) { - return self._parseFileInfo(response); - }); + var fileInfos = []; + for (var i = 0; i < responses.length; i++) { + var fileInfo = self._parseFileInfo(responses[i]); + if (fileInfo !== null) { + fileInfos.push(fileInfo); + } + } + return fileInfos; }, /** diff --git a/core/js/tests/specs/files/clientSpec.js b/core/js/tests/specs/files/clientSpec.js index 6145f2d72b94..5da884d603cc 100644 --- a/core/js/tests/specs/files/clientSpec.js +++ b/core/js/tests/specs/files/clientSpec.js @@ -171,7 +171,8 @@ describe('OC.Files.Client tests', function() { '' + '' + makeResponseBlock( - '/owncloud/remote.php/webdav/path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/', + // NOTE: Sabre DAV doesn't encode "@" sign in href response, but JS does, we still need to properly match + '/owncloud/remote.php/webdav/path/to%20sp@ce/%E6%96%87%E4%BB%B6%E5%A4%B9/', { 'd:getlastmodified': 'Fri, 10 Jul 2015 10:00:05 GMT', 'd:getetag': '"56cfcabd79abb"', @@ -187,7 +188,7 @@ describe('OC.Files.Client tests', function() { ] ) + makeResponseBlock( - '/owncloud/remote.php/webdav/path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt', + '/owncloud/remote.php/webdav/path/to%20sp@ce/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt', { 'd:getlastmodified': 'Fri, 10 Jul 2015 13:38:05 GMT', 'd:getetag': '"559fcabd79a38"', @@ -203,7 +204,7 @@ describe('OC.Files.Client tests', function() { ] ) + makeResponseBlock( - '/owncloud/remote.php/webdav/path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/sub', + '/owncloud/remote.php/webdav/path/to%20sp@ce/%E6%96%87%E4%BB%B6%E5%A4%B9/sub', { 'd:getlastmodified': 'Fri, 10 Jul 2015 14:00:00 GMT', 'd:getetag': '"66cfcabd79abb"', @@ -222,11 +223,11 @@ describe('OC.Files.Client tests', function() { ); it('sends PROPFIND with explicit properties to get file list', function() { - client.getFolderContents('path/to space/文件夹'); + client.getFolderContents('path/to sp@ce/文件夹'); expect(requestStub.calledOnce).toEqual(true); expect(requestStub.lastCall.args[0]).toEqual('PROPFIND'); - expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9'); + expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20sp%40ce/%E6%96%87%E4%BB%B6%E5%A4%B9'); expect(requestStub.lastCall.args[2].Depth).toEqual(1); var props = getRequestedProperties(requestStub.lastCall.args[3]); @@ -250,7 +251,7 @@ describe('OC.Files.Client tests', function() { expect(requestStub.lastCall.args[1]).toEqual(baseUrl); }); it('parses the result list into a FileInfo array', function() { - var promise = client.getFolderContents('path/to space/文件夹'); + var promise = client.getFolderContents('path/to sp@ce/文件夹'); expect(requestStub.calledOnce).toEqual(true); @@ -269,7 +270,7 @@ describe('OC.Files.Client tests', function() { var info = response[0]; expect(info instanceof OC.Files.FileInfo).toEqual(true); expect(info.id).toEqual(51); - expect(info.path).toEqual('/path/to space/文件夹'); + expect(info.path).toEqual('/path/to sp@ce/文件夹'); expect(info.name).toEqual('One.txt'); expect(info.permissions).toEqual(27); expect(info.size).toEqual(250); @@ -281,7 +282,7 @@ describe('OC.Files.Client tests', function() { info = response[1]; expect(info instanceof OC.Files.FileInfo).toEqual(true); expect(info.id).toEqual(15); - expect(info.path).toEqual('/path/to space/文件夹'); + expect(info.path).toEqual('/path/to sp@ce/文件夹'); expect(info.name).toEqual('sub'); expect(info.permissions).toEqual(31); expect(info.size).toEqual(100); @@ -291,7 +292,7 @@ describe('OC.Files.Client tests', function() { }); }); it('returns parent node in result if specified', function() { - var promise = client.getFolderContents('path/to space/文件夹', {includeParent: true}); + var promise = client.getFolderContents('path/to sp@ce/文件夹', {includeParent: true}); expect(requestStub.calledOnce).toEqual(true); @@ -310,7 +311,7 @@ describe('OC.Files.Client tests', function() { var info = response[0]; expect(info instanceof OC.Files.FileInfo).toEqual(true); expect(info.id).toEqual(11); - expect(info.path).toEqual('/path/to space'); + expect(info.path).toEqual('/path/to sp@ce'); expect(info.name).toEqual('文件夹'); expect(info.permissions).toEqual(31); expect(info.size).toEqual(120); @@ -324,7 +325,7 @@ describe('OC.Files.Client tests', function() { }); }); it('rejects promise when an error occurred', function() { - var promise = client.getFolderContents('path/to space/文件夹', {includeParent: true}); + var promise = client.getFolderContents('path/to sp@ce/文件夹', {includeParent: true}); respondAndCheckError(promise, 404); }); it('throws exception if arguments are missing', function() { @@ -339,7 +340,7 @@ describe('OC.Files.Client tests', function() { '' + '' + makeResponseBlock( - '/owncloud/remote.php/webdav/path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/', + '/owncloud/remote.php/webdav/path/to%20sp@ce/%E6%96%87%E4%BB%B6%E5%A4%B9/', { 'd:getlastmodified': 'Fri, 10 Jul 2015 10:00:05 GMT', 'd:getetag': '"56cfcabd79abb"', @@ -355,7 +356,7 @@ describe('OC.Files.Client tests', function() { ] ) + makeResponseBlock( - '/owncloud/remote.php/webdav/path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt', + '/owncloud/remote.php/webdav/path/to%20sp@ce/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt', { 'd:getlastmodified': 'Fri, 10 Jul 2015 13:38:05 GMT', 'd:getetag': '"559fcabd79a38"', @@ -371,7 +372,7 @@ describe('OC.Files.Client tests', function() { ] ) + makeResponseBlock( - '/owncloud/remote.php/webdav/path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/sub', + '/owncloud/remote.php/webdav/path/to%20sp@ce/%E6%96%87%E4%BB%B6%E5%A4%B9/sub', { 'd:getlastmodified': 'Fri, 10 Jul 2015 14:00:00 GMT', 'd:getetag': '"66cfcabd79abb"', @@ -489,7 +490,7 @@ describe('OC.Files.Client tests', function() { '' + '' + makeResponseBlock( - '/owncloud/remote.php/webdav/path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/', + '/owncloud/remote.php/webdav/path/to%20sp@ce/%E6%96%87%E4%BB%B6%E5%A4%B9/', { 'd:getlastmodified': 'Fri, 10 Jul 2015 10:00:05 GMT', 'd:getetag': '"56cfcabd79abb"', @@ -508,11 +509,11 @@ describe('OC.Files.Client tests', function() { ); it('sends PROPFIND with zero depth to get single file info', function() { - client.getFileInfo('path/to space/文件夹'); + client.getFileInfo('path/to sp@ce/文件夹'); expect(requestStub.calledOnce).toEqual(true); expect(requestStub.lastCall.args[0]).toEqual('PROPFIND'); - expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9'); + expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20sp%40ce/%E6%96%87%E4%BB%B6%E5%A4%B9'); expect(requestStub.lastCall.args[2].Depth).toEqual(0); var props = getRequestedProperties(requestStub.lastCall.args[3]); @@ -526,7 +527,7 @@ describe('OC.Files.Client tests', function() { expect(props).toContain('{http://owncloud.org/ns}permissions'); }); it('parses the result into a FileInfo', function() { - var promise = client.getFileInfo('path/to space/文件夹'); + var promise = client.getFileInfo('path/to sp@ce/文件夹'); expect(requestStub.calledOnce).toEqual(true); @@ -542,7 +543,7 @@ describe('OC.Files.Client tests', function() { var info = response; expect(info instanceof OC.Files.FileInfo).toEqual(true); expect(info.id).toEqual(11); - expect(info.path).toEqual('/path/to space'); + expect(info.path).toEqual('/path/to sp@ce'); expect(info.name).toEqual('文件夹'); expect(info.permissions).toEqual(31); expect(info.size).toEqual(120); @@ -600,7 +601,7 @@ describe('OC.Files.Client tests', function() { }); }); it('rejects promise when an error occurred', function() { - var promise = client.getFileInfo('path/to space/文件夹'); + var promise = client.getFileInfo('path/to sp@ce/文件夹'); respondAndCheckError(promise, 404); }); it('throws exception if arguments are missing', function() { @@ -712,11 +713,11 @@ describe('OC.Files.Client tests', function() { describe('get file contents', function() { it('returns file contents', function() { - var promise = client.getFileContents('path/to space/文件夹/One.txt'); + var promise = client.getFileContents('path/to sp@ce/文件夹/One.txt'); expect(requestStub.calledOnce).toEqual(true); expect(requestStub.lastCall.args[0]).toEqual('GET'); - expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt'); + expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20sp%40ce/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt'); requestDeferred.resolve({ status: 200, @@ -729,7 +730,7 @@ describe('OC.Files.Client tests', function() { }); }); it('rejects promise when an error occurred', function() { - var promise = client.getFileContents('path/to space/文件夹/One.txt'); + var promise = client.getFileContents('path/to sp@ce/文件夹/One.txt'); respondAndCheckError(promise, 409); }); it('throws exception if arguments are missing', function() { @@ -740,13 +741,13 @@ describe('OC.Files.Client tests', function() { describe('put file contents', function() { it('sends PUT with file contents', function() { var promise = client.putFileContents( - 'path/to space/文件夹/One.txt', + 'path/to sp@ce/文件夹/One.txt', 'some contents' ); expect(requestStub.calledOnce).toEqual(true); expect(requestStub.lastCall.args[0]).toEqual('PUT'); - expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt'); + expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20sp%40ce/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt'); expect(requestStub.lastCall.args[2]['If-None-Match']).toEqual('*'); expect(requestStub.lastCall.args[2]['Content-Type']).toEqual('text/plain;charset=utf-8'); expect(requestStub.lastCall.args[3]).toEqual('some contents'); @@ -755,7 +756,7 @@ describe('OC.Files.Client tests', function() { }); it('sends PUT with file contents with headers matching options', function() { var promise = client.putFileContents( - 'path/to space/文件夹/One.txt', + 'path/to sp@ce/文件夹/One.txt', 'some contents', { overwrite: false, @@ -765,7 +766,7 @@ describe('OC.Files.Client tests', function() { expect(requestStub.calledOnce).toEqual(true); expect(requestStub.lastCall.args[0]).toEqual('PUT'); - expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt'); + expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20sp%40ce/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt'); expect(requestStub.lastCall.args[2]['If-None-Match']).not.toBeDefined(); expect(requestStub.lastCall.args[2]['Content-Type']).toEqual('text/markdown'); expect(requestStub.lastCall.args[3]).toEqual('some contents'); @@ -774,7 +775,7 @@ describe('OC.Files.Client tests', function() { }); it('rejects promise when an error occurred', function() { var promise = client.putFileContents( - 'path/to space/文件夹/One.txt', + 'path/to sp@ce/文件夹/One.txt', 'some contents' ); respondAndCheckError(promise, 409); @@ -786,16 +787,16 @@ describe('OC.Files.Client tests', function() { describe('create directory', function() { it('sends MKCOL with specified path', function() { - var promise = client.createDirectory('path/to space/文件夹/new dir'); + var promise = client.createDirectory('path/to sp@ce/文件夹/new dir'); expect(requestStub.calledOnce).toEqual(true); expect(requestStub.lastCall.args[0]).toEqual('MKCOL'); - expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/new%20dir'); + expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20sp%40ce/%E6%96%87%E4%BB%B6%E5%A4%B9/new%20dir'); respondAndCheckStatus(promise, 201); }); it('rejects promise when an error occurred', function() { - var promise = client.createDirectory('path/to space/文件夹/new dir'); + var promise = client.createDirectory('path/to sp@ce/文件夹/new dir'); respondAndCheckError(promise, 404); }); it('throws exception if arguments are missing', function() { @@ -805,16 +806,16 @@ describe('OC.Files.Client tests', function() { describe('deletion', function() { it('sends DELETE with specified path', function() { - var promise = client.remove('path/to space/文件夹'); + var promise = client.remove('path/to sp@ce/文件夹'); expect(requestStub.calledOnce).toEqual(true); expect(requestStub.lastCall.args[0]).toEqual('DELETE'); - expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9'); + expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20sp%40ce/%E6%96%87%E4%BB%B6%E5%A4%B9'); respondAndCheckStatus(promise, 201); }); it('rejects promise when an error occurred', function() { - var promise = client.remove('path/to space/文件夹'); + var promise = client.remove('path/to sp@ce/文件夹'); respondAndCheckError(promise, 404); }); it('throws exception if arguments are missing', function() { @@ -825,15 +826,15 @@ describe('OC.Files.Client tests', function() { describe('move', function() { it('sends MOVE with specified paths with fail on overwrite by default', function() { var promise = client.move( - 'path/to space/文件夹', - 'path/to space/anotherdir/文件夹' + 'path/to sp@ce/文件夹', + 'path/to sp@ce/anotherdir/文件夹' ); expect(requestStub.calledOnce).toEqual(true); expect(requestStub.lastCall.args[0]).toEqual('MOVE'); - expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9'); + expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20sp%40ce/%E6%96%87%E4%BB%B6%E5%A4%B9'); expect(requestStub.lastCall.args[2].Destination) - .toEqual(baseUrl + 'path/to%20space/anotherdir/%E6%96%87%E4%BB%B6%E5%A4%B9'); + .toEqual(baseUrl + 'path/to%20sp%40ce/anotherdir/%E6%96%87%E4%BB%B6%E5%A4%B9'); expect(requestStub.lastCall.args[2].Overwrite) .toEqual('F'); @@ -841,16 +842,16 @@ describe('OC.Files.Client tests', function() { }); it('sends MOVE with silent overwrite mode when specified', function() { var promise = client.move( - 'path/to space/文件夹', - 'path/to space/anotherdir/文件夹', + 'path/to sp@ce/文件夹', + 'path/to sp@ce/anotherdir/文件夹', {allowOverwrite: true} ); expect(requestStub.calledOnce).toEqual(true); expect(requestStub.lastCall.args[0]).toEqual('MOVE'); - expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9'); + expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20sp%40ce/%E6%96%87%E4%BB%B6%E5%A4%B9'); expect(requestStub.lastCall.args[2].Destination) - .toEqual(baseUrl + 'path/to%20space/anotherdir/%E6%96%87%E4%BB%B6%E5%A4%B9'); + .toEqual(baseUrl + 'path/to%20sp%40ce/anotherdir/%E6%96%87%E4%BB%B6%E5%A4%B9'); expect(requestStub.lastCall.args[2].Overwrite) .not.toBeDefined(); @@ -858,8 +859,8 @@ describe('OC.Files.Client tests', function() { }); it('rejects promise when an error occurred', function() { var promise = client.move( - 'path/to space/文件夹', - 'path/to space/anotherdir/文件夹', + 'path/to sp@ce/文件夹', + 'path/to sp@ce/anotherdir/文件夹', {allowOverwrite: true} ); respondAndCheckError(promise, 404); @@ -868,4 +869,42 @@ describe('OC.Files.Client tests', function() { // TODO }); }); + + describe('default client', function() { + var getCurrentUserStub; + var propFindStub; + var getHostStub; + var getProtocolStub; + var getRootPathStub; + + beforeEach(function() { + getProtocolStub = sinon.stub(OC, 'getProtocol').returns('https'); + getHostStub = sinon.stub(OC, 'getHost').returns('somehost:8080'); + getRootPathStub = sinon.stub(OC, 'getRootPath').returns('/owncloud'); + getCurrentUserStub = sinon.stub(OC, 'getCurrentUser'); + getCurrentUserStub.returns({ + uid: 'test@#?%test' + }); + propFindStub = sinon.stub(dav.Client.prototype, 'propFind'); + propFindStub.returns($.Deferred().promise()); + delete OC.Files._defaultClient; + }); + afterEach(function() { + getProtocolStub.restore(); + getHostStub.restore(); + getRootPathStub.restore(); + propFindStub.restore(); + getCurrentUserStub.restore(); + }); + + it('returns default client based on current user', function() { + var client = OC.Files.getClient(); + + client.getFolderContents('path/to sp@ce/a@b#?%/x'); + + expect(propFindStub.calledOnce).toEqual(true); + expect(propFindStub.getCall(0).args[0]) + .toEqual('https://somehost:8080/owncloud/remote.php/dav/files/test%40%23%3F%25test/path/to%20sp%40ce/a%40b%23%3F%25/x'); + }); + }); }); From 15a049cd62e46e90b62514c7c8588b408ed59877 Mon Sep 17 00:00:00 2001 From: Artur Neumann Date: Mon, 21 Aug 2017 16:32:47 +0545 Subject: [PATCH 3/4] more UI tests to test special char in file/folder names --- tests/ui/features/bootstrap/FilesContext.php | 11 +++++++++++ tests/ui/features/files/files.feature | 17 +++++++++++++++-- tests/ui/features/files/renameFiles.feature | 11 +++++++---- tests/ui/features/files/renameFolders.feature | 15 +++++++++------ 4 files changed, 42 insertions(+), 12 deletions(-) diff --git a/tests/ui/features/bootstrap/FilesContext.php b/tests/ui/features/bootstrap/FilesContext.php index df8dadf9a422..f7bf03626b63 100644 --- a/tests/ui/features/bootstrap/FilesContext.php +++ b/tests/ui/features/bootstrap/FilesContext.php @@ -45,8 +45,19 @@ public function __construct(FilesPage $filesPage) public function iAmOnTheFilesPage() { $this->filesPage->open(); + $this->filesPage->waitTillPageIsLoaded($this->getSession()); } + + /** + * @When I create a folder with the name :name + * + * @param string $name + * @return void + */ + public function createAFolder($name) { + $this->filesPage->createFolder($name); + } /** * @Given the list of files\/folders does not fit in one browser page */ diff --git a/tests/ui/features/files/files.feature b/tests/ui/features/files/files.feature index f545cd57cafe..92189a29a7d5 100644 --- a/tests/ui/features/files/files.feature +++ b/tests/ui/features/files/files.feature @@ -1,9 +1,22 @@ Feature: files - @skipOnIE - Scenario: scroll fileactionsmenu into view + Background: Given a regular user exists And I am logged in as a regular user And I am on the files page + + @skipOnIE + Scenario: scroll fileactionsmenu into view And the list of files/folders does not fit in one browser page Then the filesactionmenu should be completely visible after clicking on it + + Scenario Outline: Create a folder using special characters + When I create a folder with the name + Then the folder should be listed + And the page is reloaded + Then the folder should be listed + Examples: + |folder_name | + |'सिमप्ले फोल्देर $%#?&@'| + |'"somequotes1"'| + |"'somequotes2'"| \ No newline at end of file diff --git a/tests/ui/features/files/renameFiles.feature b/tests/ui/features/files/renameFiles.feature index 4f160080fc48..c79d7d305342 100644 --- a/tests/ui/features/files/renameFiles.feature +++ b/tests/ui/features/files/renameFiles.feature @@ -9,10 +9,10 @@ Feature: renameFiles When I rename the file "lorem.txt" to Then the file should be listed Examples: - |to_file_name | - |'लोरेम।तयक्स्त $%&' | - |'"quotes1"' | - |"'quotes2'" | + |to_file_name | + |'लोरेम।तयक्स्त? $%#&@' | + |'"quotes1"' | + |"'quotes2'" | Scenario Outline: Rename a file that has special characters in its name @@ -33,6 +33,9 @@ Feature: renameFiles When I rename the file '"double"quotes.txt' to "no-double-quotes.txt" And the page is reloaded Then the file "no-double-quotes.txt" should be listed + When I rename the file 'no-double-quotes.txt' to "hash#And&QuestionMark?At@Filename.txt" + And the page is reloaded + Then the file "hash#And&QuestionMark?At@Filename.txt" should be listed Scenario: Rename a file using forbidden characters When I rename the file "data.zip" to one of these names diff --git a/tests/ui/features/files/renameFolders.feature b/tests/ui/features/files/renameFolders.feature index 1e5fda6e20d7..758430af0a0c 100644 --- a/tests/ui/features/files/renameFolders.feature +++ b/tests/ui/features/files/renameFolders.feature @@ -10,17 +10,17 @@ Feature: renameFolders Then the folder should be listed Examples: |to_folder_name| - |'सिमप्ले फोल्देर' | - |'"quotes1"' | - |"'quotes2'" | + |'सिमप्ले फोल्देर$%#?&@' | + |'"quotes1"' | + |"'quotes2'" | Scenario Outline: Rename a folder that has special characters in its name When I rename the folder to Then the folder should be listed Examples: - |from_name |to_name | - |"strängé नेपाली folder"|"strängé नेपाली folder-2"| - |"'single'quotes" |"single-quotes" | + |from_name |to_name | + |"strängé नेपाली folder"|"strängé नेपाली folder-#?2"| + |"'single'quotes" |"single-quotes" | Scenario: Rename a folder using special characters and check its existence after page reload When I rename the folder "simple-folder" to "लोरेम।तयक्स्त $%&" @@ -32,6 +32,9 @@ Feature: renameFolders When I rename the folder '"double"quotes' to "no-double-quotes" And the page is reloaded Then the folder "no-double-quotes" should be listed + When I rename the folder 'no-double-quotes' to "hash#And&QuestionMark?At@FolderName" + And the page is reloaded + Then the folder "hash#And&QuestionMark?At@FolderName" should be listed Scenario: Rename a folder using forbidden characters When I rename the folder "simple-folder" to one of these names From 9d42ce6095bdd994d345e5a8192b69e9efc96605 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Tue, 22 Aug 2017 12:08:02 +0200 Subject: [PATCH 4/4] Don't encode paths passed to OC.Files.Client The client takes care of encoding them when doing the Webdav requests --- apps/files/js/file-upload.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js index 4ab1a93de500..c11bbeef27c5 100644 --- a/apps/files/js/file-upload.js +++ b/apps/files/js/file-upload.js @@ -259,7 +259,7 @@ OC.FileUpload.prototype = { ) { data.isChunked = true; chunkFolderPromise = this.uploader.davClient.createDirectory( - 'uploads/' + encodeURIComponent(OC.getCurrentUser().uid) + '/' + encodeURIComponent(this.getId()) + 'uploads/' + OC.getCurrentUser().uid + '/' + this.getId() ); // TODO: if fails, it means same id already existed, need to retry } else { @@ -296,8 +296,8 @@ OC.FileUpload.prototype = { } return this.uploader.davClient.move( - 'uploads/' + encodeURIComponent(uid) + '/' + encodeURIComponent(this.getId()) + '/.file', - 'files/' + encodeURIComponent(uid) + '/' + OC.joinPaths(this.getFullPath(), this.getFileName()), + 'uploads/' + uid + '/' + this.getId() + '/.file', + 'files/' + uid + '/' + OC.joinPaths(this.getFullPath(), this.getFileName()), true, headers ); @@ -306,7 +306,7 @@ OC.FileUpload.prototype = { _deleteChunkFolder: function() { // delete transfer directory for this upload this.uploader.davClient.remove( - 'uploads/' + encodeURIComponent(OC.getCurrentUser().uid) + '/' + encodeURIComponent(this.getId()) + 'uploads/' + OC.getCurrentUser().uid + '/' + this.getId() ); },