diff --git a/backend/Controllers/DownloadController.php b/backend/Controllers/DownloadController.php index 93951ea..163dce5 100644 --- a/backend/Controllers/DownloadController.php +++ b/backend/Controllers/DownloadController.php @@ -43,10 +43,10 @@ class DownloadController $this->storage->setPathPrefix($user->getHomeDir()); } - public function download($path_encoded, Request $request, Response $response, StreamedResponse $streamedResponse) + public function download(Request $request, Response $response, StreamedResponse $streamedResponse) { try { - $file = $this->storage->readStream((string) base64_decode($path_encoded)); + $file = $this->storage->readStream((string) base64_decode($request->input('path'))); } catch (\Exception $e) { return $response->redirect('/'); } @@ -67,7 +67,7 @@ class DownloadController $streamedResponse->headers->set( 'Content-Disposition', - HeaderUtils::makeDisposition(HeaderUtils::DISPOSITION_ATTACHMENT, $file['filename']) + HeaderUtils::makeDisposition(HeaderUtils::DISPOSITION_ATTACHMENT, $file['filename'], 'file') ); $streamedResponse->headers->set( 'Content-Type', @@ -131,7 +131,8 @@ class DownloadController 'Content-Disposition', HeaderUtils::makeDisposition( HeaderUtils::DISPOSITION_ATTACHMENT, - $this->config->get('frontend_config.default_archive_name') + $this->config->get('frontend_config.default_archive_name'), + 'archive.zip' ) ); $streamedResponse->headers->set( diff --git a/backend/Controllers/routes.php b/backend/Controllers/routes.php index 6bcf5dc..3129b06 100644 --- a/backend/Controllers/routes.php +++ b/backend/Controllers/routes.php @@ -184,7 +184,7 @@ return [ ], [ 'route' => [ - 'GET', '/download/{path_encoded}', '\Filegator\Controllers\DownloadController@download', + 'GET', '/download', '\Filegator\Controllers\DownloadController@download', ], 'roles' => [ 'guest', 'user', 'admin', diff --git a/frontend/views/Browser.vue b/frontend/views/Browser.vue index bb06fd1..a81d3e4 100644 --- a/frontend/views/Browser.vue +++ b/frontend/views/Browser.vue @@ -155,6 +155,7 @@ import Pagination from './partials/Pagination' import Upload from './partials/Upload' import api from '../api/api' import VueClipboard from 'vue-clipboard2' +import { Base64 } from 'js-base64' import _ from 'lodash' Vue.use(VueClipboard) @@ -335,7 +336,7 @@ export default { }) }, getDownloadLink(item) { - return Vue.config.baseURL+'/download/'+btoa(item.path) + return Vue.config.baseURL+'/download&path='+encodeURIComponent(Base64.encode(item.path)) }, download(item) { window.open(this.getDownloadLink(item), '_blank') diff --git a/package-lock.json b/package-lock.json index 6309a93..c0a39a9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11200,8 +11200,7 @@ "js-base64": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz", - "integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==", - "dev": true + "integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==" }, "js-beautify": { "version": "1.10.0", diff --git a/package.json b/package.json index f798ef9..9cb5b84 100644 --- a/package.json +++ b/package.json @@ -35,5 +35,7 @@ "vue-template-compiler": "^2.5.21", "vuex": "^3.1.1" }, - "dependencies": {} + "dependencies": { + "js-base64": "^2.5.1" + } } diff --git a/tests/backend/Feature/FilesTest.php b/tests/backend/Feature/FilesTest.php index b380286..85c49ee 100644 --- a/tests/backend/Feature/FilesTest.php +++ b/tests/backend/Feature/FilesTest.php @@ -156,7 +156,21 @@ class FilesTest extends TestCase touch(TEST_REPOSITORY.'/john/john.txt', $this->timestamp); $path_encoded = base64_encode('john.txt'); - $this->sendRequest('GET', '/download/'.$path_encoded); + $this->sendRequest('GET', '/download&path='.$path_encoded); + + $this->assertOk(); + } + + public function testDownloadUTF8File() + { + $username = 'john@example.com'; + $this->signIn($username, 'john123'); + + mkdir(TEST_REPOSITORY.'/john'); + touch(TEST_REPOSITORY.'/john/ąčęėįšųū.txt', $this->timestamp); + + $path_encoded = base64_encode('/ąčęėįšųū.txt'); + $this->sendRequest('GET', '/download&path='.$path_encoded); $this->assertOk(); } @@ -166,7 +180,7 @@ class FilesTest extends TestCase touch(TEST_REPOSITORY.'/test.txt', $this->timestamp); $path_encoded = base64_encode('test.txt'); - $this->sendRequest('GET', '/download/'.$path_encoded); + $this->sendRequest('GET', '/download&path='.$path_encoded); $this->assertStatus(404); } @@ -181,7 +195,7 @@ class FilesTest extends TestCase touch(TEST_REPOSITORY.'/jane/jane.txt', $this->timestamp); $path_encoded = base64_encode('jane.txt'); - $this->sendRequest('GET', '/download/'.$path_encoded); + $this->sendRequest('GET', '/download&path='.$path_encoded); $this->assertStatus(404); } @@ -192,7 +206,7 @@ class FilesTest extends TestCase $this->signIn($username, 'john123'); $path_encoded = base64_encode('missing.txt'); - $this->sendRequest('GET', '/download/'.$path_encoded); + $this->sendRequest('GET', '/download&path='.$path_encoded); $this->assertStatus(302); } diff --git a/tests/backend/Feature/UploadTest.php b/tests/backend/Feature/UploadTest.php index 36553ed..6e88dc3 100644 --- a/tests/backend/Feature/UploadTest.php +++ b/tests/backend/Feature/UploadTest.php @@ -317,4 +317,43 @@ class UploadTest extends TestCase ], ]); } + + public function testFileUploadWithUTF8() + { + $this->signIn('john@example.com', 'john123'); + + $files = ['file' => new UploadedFile(TEST_FILE, 'ąčęėįšųū.txt', 'text/plain', null, true)]; + + $data = [ + 'resumableChunkNumber' => 1, + 'resumableChunkSize' => 1048576, + 'resumableCurrentChunkSize' => 0.5 * 1024 * 1024, + 'resumableTotalChunks' => 1, + 'resumableTotalSize' => 0.5 * 1024 * 1024, + 'resumableType' => 'text/plain', + 'resumableIdentifier' => 'CHUNKS-SIMPLE-TEST', + 'resumableFilename' => "ąčęėįšųū.txt", + 'resumableRelativePath' => '/', + ]; + + $this->sendRequest('POST', '/upload', $data, $files); + + $this->assertOk(); + + $this->sendRequest('POST', '/getdir', [ + 'dir' => '/', + ]); + + $this->assertResponseJsonHas([ + 'data' => [ + 'files' => [ + 0 => [ + 'type' => 'file', + 'path' => '/ąčęėįšųū.txt', + 'name' => 'ąčęėįšųū.txt', + ], + ], + ], + ]); + } }