mirror of
https://github.com/DirectoryLister/DirectoryLister.git
synced 2025-08-29 08:40:42 +02:00
Additional work to fix zip downloading directories with URL special characters
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
namespace App\ViewFunctions;
|
||||
|
||||
use App\Support\Str;
|
||||
use RuntimeException;
|
||||
|
||||
class Url extends ViewFunction
|
||||
{
|
||||
@@ -23,21 +24,33 @@ class Url extends ViewFunction
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the URL for a given path.
|
||||
* Return the URL for a given path and action.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $path
|
||||
* @param string|null $action
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __invoke(string $path = '/'): string
|
||||
public function __invoke(string $path = '/', string $action = null): string
|
||||
{
|
||||
$path = preg_replace('/^.?(\/|\\\)+/', '', $path);
|
||||
|
||||
if (is_file($path)) {
|
||||
return $this->escape($path);
|
||||
}
|
||||
switch ($action) {
|
||||
case null:
|
||||
return $this->escape($path);
|
||||
|
||||
return empty($path) ? '' : sprintf('?dir=%s', $this->escape($path));
|
||||
case 'dir':
|
||||
return empty($path) ? '' : sprintf('?dir=%s', $this->escape($path));
|
||||
|
||||
case 'info':
|
||||
return empty($path) ? '?info=.' : sprintf('?info=%s', $this->escape($path));
|
||||
|
||||
case 'zip':
|
||||
return empty($path) ? '?zip=.' : sprintf('?zip=%s', $this->escape($path));
|
||||
|
||||
default:
|
||||
throw new RuntimeException(sprintf('Invalid action "%s"', $action));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<a
|
||||
href="{{ parentDir ? parent_dir(path) : url(file.getPathname) }}"
|
||||
href="{{ parentDir ? parent_dir(path) : url(file.getPathname, 'dir') }}"
|
||||
class="flex flex-col items-center rounded-lg font-mono group hover:bg-gray-200 hover:shadow"
|
||||
>
|
||||
<div class="flex justify-between items-center p-4 w-full">
|
||||
|
@@ -14,7 +14,7 @@
|
||||
|
||||
<div class="flex justify-end items-center">
|
||||
{% if path and config('zip_downloads', true) %}
|
||||
<a href="?zip={{ path }}" title="{{ translate('download') }}" class="inline-block text-white mx-2 p-1 hover:text-gray-400">
|
||||
<a href="{{ url(path, 'zip') }}" title="{{ translate('download') }}" class="inline-block text-white mx-2 p-1 hover:text-gray-400">
|
||||
<i class="fas fa-download fa-lg"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
@@ -3,53 +3,91 @@
|
||||
namespace Tests\ViewFunctions;
|
||||
|
||||
use App\ViewFunctions\Url;
|
||||
use RuntimeException;
|
||||
use Tests\TestCase;
|
||||
|
||||
class UrlTest extends TestCase
|
||||
{
|
||||
public function test_it_can_return_a_url_for_a_directory(): void
|
||||
public function test_it_can_return_a_url(): void
|
||||
{
|
||||
$url = new Url;
|
||||
|
||||
$this->assertEquals('', $url('/'));
|
||||
$this->assertEquals('', $url('./'));
|
||||
$this->assertEquals('?dir=some/path', $url('some/path'));
|
||||
$this->assertEquals('?dir=some/path', $url('./some/path'));
|
||||
$this->assertEquals('?dir=some/path', $url('./some/path'));
|
||||
$this->assertEquals('?dir=some/file.test', $url('some/file.test'));
|
||||
$this->assertEquals('?dir=some/file.test', $url('./some/file.test'));
|
||||
$this->assertEquals('some/path', $url('some/path'));
|
||||
$this->assertEquals('some/path', $url('./some/path'));
|
||||
$this->assertEquals('some/path', $url('./some/path'));
|
||||
$this->assertEquals('some/file.test', $url('some/file.test'));
|
||||
$this->assertEquals('some/file.test', $url('./some/file.test'));
|
||||
}
|
||||
|
||||
public function test_it_can_return_a_url_for_a_directory_using_back_slashes(): void
|
||||
public function test_it_can_return_a_directory_url(): void
|
||||
{
|
||||
$url = new Url;
|
||||
|
||||
$this->assertEquals('', $url('/', 'dir'));
|
||||
$this->assertEquals('', $url('./', 'dir'));
|
||||
$this->assertEquals('?dir=some/path', $url('some/path', 'dir'));
|
||||
$this->assertEquals('?dir=some/path', $url('./some/path', 'dir'));
|
||||
$this->assertEquals('?dir=some/path', $url('./some/path', 'dir'));
|
||||
$this->assertEquals('?dir=some/file.test', $url('some/file.test', 'dir'));
|
||||
$this->assertEquals('?dir=some/file.test', $url('./some/file.test', 'dir'));
|
||||
}
|
||||
|
||||
public function test_it_can_return_a_file_info_url(): void
|
||||
{
|
||||
$url = new Url;
|
||||
|
||||
$this->assertEquals('?info=.', $url('/', 'info'));
|
||||
$this->assertEquals('?info=.', $url('./', 'info'));
|
||||
$this->assertEquals('?info=some/path', $url('some/path', 'info'));
|
||||
$this->assertEquals('?info=some/path', $url('./some/path', 'info'));
|
||||
$this->assertEquals('?info=some/path', $url('./some/path', 'info'));
|
||||
$this->assertEquals('?info=some/file.test', $url('some/file.test', 'info'));
|
||||
$this->assertEquals('?info=some/file.test', $url('./some/file.test', 'info'));
|
||||
}
|
||||
|
||||
public function test_it_can_return_a_zip_url(): void
|
||||
{
|
||||
$url = new Url;
|
||||
|
||||
$this->assertEquals('?zip=.', $url('/', 'zip'));
|
||||
$this->assertEquals('?zip=.', $url('./', 'zip'));
|
||||
$this->assertEquals('?zip=some/path', $url('some/path', 'zip'));
|
||||
$this->assertEquals('?zip=some/path', $url('./some/path', 'zip'));
|
||||
$this->assertEquals('?zip=some/path', $url('./some/path', 'zip'));
|
||||
}
|
||||
|
||||
public function test_it_can_return_a_url_with_back_slashes(): void
|
||||
{
|
||||
$url = new Url('\\');
|
||||
|
||||
$this->assertEquals('', $url('\\'));
|
||||
$this->assertEquals('', $url('.\\'));
|
||||
$this->assertEquals('?dir=some\path', $url('some\path'));
|
||||
$this->assertEquals('?dir=some\path', $url('.\some\path'));
|
||||
$this->assertEquals('?dir=some\file.test', $url('some\file.test'));
|
||||
$this->assertEquals('?dir=some\file.test', $url('.\some\file.test'));
|
||||
$this->assertEquals('some\path', $url('some\path'));
|
||||
$this->assertEquals('some\path', $url('.\some\path'));
|
||||
$this->assertEquals('some\file.test', $url('some\file.test'));
|
||||
$this->assertEquals('some\file.test', $url('.\some\file.test'));
|
||||
$this->assertEquals('?dir=some\path', $url('some\path', 'dir'));
|
||||
$this->assertEquals('?info=some\path', $url('some\path', 'info'));
|
||||
$this->assertEquals('?zip=some\path', $url('some\path', 'zip'));
|
||||
}
|
||||
|
||||
public function test_it_can_return_a_url_for_a_file(): void
|
||||
{
|
||||
chdir($this->filePath('.'));
|
||||
|
||||
$url = new Url;
|
||||
|
||||
$this->assertEquals('README.md', $url('README.md'));
|
||||
$this->assertEquals('README.md', $url('./README.md'));
|
||||
$this->assertEquals('subdir/alpha.scss', $url('subdir/alpha.scss'));
|
||||
$this->assertEquals('subdir/alpha.scss', $url('./subdir/alpha.scss'));
|
||||
}
|
||||
|
||||
public function test_it_url_encodes_directory_names(): void
|
||||
public function test_it_throws_an_exception_for_an_invalid_action(): void
|
||||
{
|
||||
$url = new Url;
|
||||
|
||||
$this->assertEquals('?dir=foo/bar%2Bbaz', $url('foo/bar+baz'));
|
||||
$this->assertEquals('?dir=foo/bar%23baz', $url('foo/bar#baz'));
|
||||
$this->assertEquals('?dir=foo/bar%26baz', $url('foo/bar&baz'));
|
||||
$this->expectException(RuntimeException::class);
|
||||
|
||||
$url('some/path', 'INVALID_ACTION');
|
||||
}
|
||||
|
||||
public function test_segments_are_url_encoded(): void
|
||||
{
|
||||
$url = new Url;
|
||||
|
||||
$this->assertEquals('foo/bar%2Bbaz', $url('foo/bar+baz'));
|
||||
$this->assertEquals('foo/bar%23baz', $url('foo/bar#baz'));
|
||||
$this->assertEquals('foo/bar%26baz', $url('foo/bar&baz'));
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user