mirror of
https://github.com/BookStackApp/BookStack.git
synced 2026-05-04 18:08:46 +03:00
Merge branch 'development' into release
This commit is contained in:
@@ -323,7 +323,7 @@ class ExportFormatter
|
||||
$text .= $description . "\n\n";
|
||||
}
|
||||
|
||||
foreach ($chapter->pages as $page) {
|
||||
foreach ($chapter->getVisiblePages() as $page) {
|
||||
$text .= $this->pageToMarkdown($page) . "\n\n";
|
||||
}
|
||||
|
||||
|
||||
@@ -102,12 +102,15 @@ class DownloadResponseFactory
|
||||
protected function getHeaders(string $fileName, int $fileSize, string $mime = 'application/octet-stream'): array
|
||||
{
|
||||
$disposition = ($mime === 'application/octet-stream') ? 'attachment' : 'inline';
|
||||
$downloadName = str_replace('"', '', $fileName);
|
||||
|
||||
$downloadName = str_replace(['"', '/', '\\', '$'], '', $fileName);
|
||||
$downloadName = preg_replace('/[\x00-\x1F\x7F]/', '', $downloadName);
|
||||
$encodedDownloadName = rawurlencode($downloadName);
|
||||
|
||||
return [
|
||||
'Content-Type' => $mime,
|
||||
'Content-Length' => $fileSize,
|
||||
'Content-Disposition' => "{$disposition}; filename=\"{$downloadName}\"",
|
||||
'Content-Disposition' => "{$disposition}; filename*=UTF-8''{$encodedDownloadName}",
|
||||
'X-Content-Type-Options' => 'nosniff',
|
||||
];
|
||||
}
|
||||
|
||||
58
composer.lock
generated
58
composer.lock
generated
@@ -62,16 +62,16 @@
|
||||
},
|
||||
{
|
||||
"name": "aws/aws-sdk-php",
|
||||
"version": "3.373.2",
|
||||
"version": "3.373.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aws/aws-sdk-php.git",
|
||||
"reference": "483fba51c28b3a0c0647bf5100e0edca82090b18"
|
||||
"reference": "d23edc4cf9cd81cb98b5beb9c1fb3737f535b1e5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/483fba51c28b3a0c0647bf5100e0edca82090b18",
|
||||
"reference": "483fba51c28b3a0c0647bf5100e0edca82090b18",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/d23edc4cf9cd81cb98b5beb9c1fb3737f535b1e5",
|
||||
"reference": "d23edc4cf9cd81cb98b5beb9c1fb3737f535b1e5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -153,22 +153,22 @@
|
||||
"support": {
|
||||
"forum": "https://github.com/aws/aws-sdk-php/discussions",
|
||||
"issues": "https://github.com/aws/aws-sdk-php/issues",
|
||||
"source": "https://github.com/aws/aws-sdk-php/tree/3.373.2"
|
||||
"source": "https://github.com/aws/aws-sdk-php/tree/3.373.3"
|
||||
},
|
||||
"time": "2026-03-13T18:08:30+00:00"
|
||||
"time": "2026-03-16T18:15:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
"version": "v3.0.3",
|
||||
"version": "v3.0.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Bacon/BaconQrCode.git",
|
||||
"reference": "36a1cb2b81493fa5b82e50bf8068bf84d1542563"
|
||||
"reference": "3feed0e212b8412cc5d2612706744789b0615824"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/36a1cb2b81493fa5b82e50bf8068bf84d1542563",
|
||||
"reference": "36a1cb2b81493fa5b82e50bf8068bf84d1542563",
|
||||
"url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/3feed0e212b8412cc5d2612706744789b0615824",
|
||||
"reference": "3feed0e212b8412cc5d2612706744789b0615824",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -208,9 +208,9 @@
|
||||
"homepage": "https://github.com/Bacon/BaconQrCode",
|
||||
"support": {
|
||||
"issues": "https://github.com/Bacon/BaconQrCode/issues",
|
||||
"source": "https://github.com/Bacon/BaconQrCode/tree/v3.0.3"
|
||||
"source": "https://github.com/Bacon/BaconQrCode/tree/v3.0.4"
|
||||
},
|
||||
"time": "2025-11-19T17:15:36+00:00"
|
||||
"time": "2026-03-16T01:01:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "brick/math",
|
||||
@@ -2943,20 +2943,20 @@
|
||||
},
|
||||
{
|
||||
"name": "league/uri",
|
||||
"version": "7.8.0",
|
||||
"version": "7.8.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/uri.git",
|
||||
"reference": "4436c6ec8d458e4244448b069cc572d088230b76"
|
||||
"reference": "08cf38e3924d4f56238125547b5720496fac8fd4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/uri/zipball/4436c6ec8d458e4244448b069cc572d088230b76",
|
||||
"reference": "4436c6ec8d458e4244448b069cc572d088230b76",
|
||||
"url": "https://api.github.com/repos/thephpleague/uri/zipball/08cf38e3924d4f56238125547b5720496fac8fd4",
|
||||
"reference": "08cf38e3924d4f56238125547b5720496fac8fd4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"league/uri-interfaces": "^7.8",
|
||||
"league/uri-interfaces": "^7.8.1",
|
||||
"php": "^8.1",
|
||||
"psr/http-factory": "^1"
|
||||
},
|
||||
@@ -3029,7 +3029,7 @@
|
||||
"docs": "https://uri.thephpleague.com",
|
||||
"forum": "https://thephpleague.slack.com",
|
||||
"issues": "https://github.com/thephpleague/uri-src/issues",
|
||||
"source": "https://github.com/thephpleague/uri/tree/7.8.0"
|
||||
"source": "https://github.com/thephpleague/uri/tree/7.8.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3037,20 +3037,20 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-01-14T17:24:56+00:00"
|
||||
"time": "2026-03-15T20:22:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/uri-interfaces",
|
||||
"version": "7.8.0",
|
||||
"version": "7.8.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/uri-interfaces.git",
|
||||
"reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4"
|
||||
"reference": "85d5c77c5d6d3af6c54db4a78246364908f3c928"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/c5c5cd056110fc8afaba29fa6b72a43ced42acd4",
|
||||
"reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4",
|
||||
"url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/85d5c77c5d6d3af6c54db4a78246364908f3c928",
|
||||
"reference": "85d5c77c5d6d3af6c54db4a78246364908f3c928",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3113,7 +3113,7 @@
|
||||
"docs": "https://uri.thephpleague.com",
|
||||
"forum": "https://thephpleague.slack.com",
|
||||
"issues": "https://github.com/thephpleague/uri-src/issues",
|
||||
"source": "https://github.com/thephpleague/uri-interfaces/tree/7.8.0"
|
||||
"source": "https://github.com/thephpleague/uri-interfaces/tree/7.8.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3121,7 +3121,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-01-15T06:54:53+00:00"
|
||||
"time": "2026-03-08T20:05:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "masterminds/html5",
|
||||
@@ -9169,11 +9169,11 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "2.1.40",
|
||||
"version": "2.1.41",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/9b2c7aeb83a75d8680ea5e7c9b7fca88052b766b",
|
||||
"reference": "9b2c7aeb83a75d8680ea5e7c9b7fca88052b766b",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/a2eae8f20856b3afe74bf1f9726ce8c11438e300",
|
||||
"reference": "a2eae8f20856b3afe74bf1f9726ce8c11438e300",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -9218,7 +9218,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-02-23T15:04:35+00:00"
|
||||
"time": "2026-03-16T18:24:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
|
||||
@@ -19,7 +19,7 @@ class ExportsApiTest extends TestCase
|
||||
$resp = $this->get("/api/books/{$book->id}/export/html");
|
||||
$resp->assertStatus(200);
|
||||
$resp->assertSee($book->name);
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $book->slug . '.html"');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . $book->slug . '.html');
|
||||
}
|
||||
|
||||
public function test_book_plain_text_endpoint()
|
||||
@@ -30,7 +30,7 @@ class ExportsApiTest extends TestCase
|
||||
$resp = $this->get("/api/books/{$book->id}/export/plaintext");
|
||||
$resp->assertStatus(200);
|
||||
$resp->assertSee($book->name);
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $book->slug . '.txt"');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . $book->slug . '.txt');
|
||||
}
|
||||
|
||||
public function test_book_pdf_endpoint()
|
||||
@@ -40,7 +40,7 @@ class ExportsApiTest extends TestCase
|
||||
|
||||
$resp = $this->get("/api/books/{$book->id}/export/pdf");
|
||||
$resp->assertStatus(200);
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $book->slug . '.pdf"');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . $book->slug . '.pdf');
|
||||
}
|
||||
|
||||
public function test_book_markdown_endpoint()
|
||||
@@ -50,7 +50,7 @@ class ExportsApiTest extends TestCase
|
||||
|
||||
$resp = $this->get("/api/books/{$book->id}/export/markdown");
|
||||
$resp->assertStatus(200);
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $book->slug . '.md"');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . $book->slug . '.md');
|
||||
$resp->assertSee('# ' . $book->name);
|
||||
$resp->assertSee('# ' . $book->pages()->first()->name);
|
||||
$resp->assertSee('# ' . $book->chapters()->first()->name);
|
||||
@@ -63,7 +63,7 @@ class ExportsApiTest extends TestCase
|
||||
|
||||
$resp = $this->get("/api/books/{$book->id}/export/zip");
|
||||
$resp->assertStatus(200);
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $book->slug . '.zip"');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . $book->slug . '.zip');
|
||||
|
||||
$zip = ZipTestHelper::extractFromZipResponse($resp);
|
||||
$this->assertArrayHasKey('book', $zip->data);
|
||||
@@ -77,7 +77,7 @@ class ExportsApiTest extends TestCase
|
||||
$resp = $this->get("/api/chapters/{$chapter->id}/export/html");
|
||||
$resp->assertStatus(200);
|
||||
$resp->assertSee($chapter->name);
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $chapter->slug . '.html"');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . $chapter->slug . '.html');
|
||||
}
|
||||
|
||||
public function test_chapter_plain_text_endpoint()
|
||||
@@ -88,7 +88,7 @@ class ExportsApiTest extends TestCase
|
||||
$resp = $this->get("/api/chapters/{$chapter->id}/export/plaintext");
|
||||
$resp->assertStatus(200);
|
||||
$resp->assertSee($chapter->name);
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $chapter->slug . '.txt"');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . $chapter->slug . '.txt');
|
||||
}
|
||||
|
||||
public function test_chapter_pdf_endpoint()
|
||||
@@ -98,7 +98,7 @@ class ExportsApiTest extends TestCase
|
||||
|
||||
$resp = $this->get("/api/chapters/{$chapter->id}/export/pdf");
|
||||
$resp->assertStatus(200);
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $chapter->slug . '.pdf"');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . $chapter->slug . '.pdf');
|
||||
}
|
||||
|
||||
public function test_chapter_markdown_endpoint()
|
||||
@@ -108,7 +108,7 @@ class ExportsApiTest extends TestCase
|
||||
|
||||
$resp = $this->get("/api/chapters/{$chapter->id}/export/markdown");
|
||||
$resp->assertStatus(200);
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $chapter->slug . '.md"');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . $chapter->slug . '.md');
|
||||
$resp->assertSee('# ' . $chapter->name);
|
||||
$resp->assertSee('# ' . $chapter->pages()->first()->name);
|
||||
}
|
||||
@@ -120,7 +120,7 @@ class ExportsApiTest extends TestCase
|
||||
|
||||
$resp = $this->get("/api/chapters/{$chapter->id}/export/zip");
|
||||
$resp->assertStatus(200);
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $chapter->slug . '.zip"');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . $chapter->slug . '.zip');
|
||||
|
||||
$zip = ZipTestHelper::extractFromZipResponse($resp);
|
||||
$this->assertArrayHasKey('chapter', $zip->data);
|
||||
@@ -134,7 +134,7 @@ class ExportsApiTest extends TestCase
|
||||
$resp = $this->get("/api/pages/{$page->id}/export/html");
|
||||
$resp->assertStatus(200);
|
||||
$resp->assertSee($page->name);
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $page->slug . '.html"');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . $page->slug . '.html');
|
||||
}
|
||||
|
||||
public function test_page_plain_text_endpoint()
|
||||
@@ -145,7 +145,7 @@ class ExportsApiTest extends TestCase
|
||||
$resp = $this->get("/api/pages/{$page->id}/export/plaintext");
|
||||
$resp->assertStatus(200);
|
||||
$resp->assertSee($page->name);
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $page->slug . '.txt"');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . $page->slug . '.txt');
|
||||
}
|
||||
|
||||
public function test_page_pdf_endpoint()
|
||||
@@ -155,7 +155,7 @@ class ExportsApiTest extends TestCase
|
||||
|
||||
$resp = $this->get("/api/pages/{$page->id}/export/pdf");
|
||||
$resp->assertStatus(200);
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $page->slug . '.pdf"');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . $page->slug . '.pdf');
|
||||
}
|
||||
|
||||
public function test_page_markdown_endpoint()
|
||||
@@ -166,7 +166,7 @@ class ExportsApiTest extends TestCase
|
||||
$resp = $this->get("/api/pages/{$page->id}/export/markdown");
|
||||
$resp->assertStatus(200);
|
||||
$resp->assertSee('# ' . $page->name);
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $page->slug . '.md"');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . $page->slug . '.md');
|
||||
}
|
||||
|
||||
public function test_page_zip_endpoint()
|
||||
@@ -176,7 +176,7 @@ class ExportsApiTest extends TestCase
|
||||
|
||||
$resp = $this->get("/api/pages/{$page->id}/export/zip");
|
||||
$resp->assertStatus(200);
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $page->slug . '.zip"');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . $page->slug . '.zip');
|
||||
|
||||
$zip = ZipTestHelper::extractFromZipResponse($resp);
|
||||
$this->assertArrayHasKey('page', $zip->data);
|
||||
|
||||
@@ -18,7 +18,7 @@ class HtmlExportTest extends TestCase
|
||||
$resp = $this->get($page->getUrl('/export/html'));
|
||||
$resp->assertStatus(200);
|
||||
$resp->assertSee($page->name);
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $page->slug . '.html"');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . $page->slug . '.html');
|
||||
}
|
||||
|
||||
public function test_book_html_export()
|
||||
@@ -31,7 +31,7 @@ class HtmlExportTest extends TestCase
|
||||
$resp->assertStatus(200);
|
||||
$resp->assertSee($book->name);
|
||||
$resp->assertSee($page->name);
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $book->slug . '.html"');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . $book->slug . '.html');
|
||||
}
|
||||
|
||||
public function test_book_html_export_shows_html_descriptions()
|
||||
@@ -58,7 +58,7 @@ class HtmlExportTest extends TestCase
|
||||
$resp->assertStatus(200);
|
||||
$resp->assertSee($chapter->name);
|
||||
$resp->assertSee($page->name);
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $chapter->slug . '.html"');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . $chapter->slug . '.html');
|
||||
}
|
||||
|
||||
public function test_chapter_html_export_shows_html_descriptions()
|
||||
|
||||
@@ -14,7 +14,7 @@ class MarkdownExportTest extends TestCase
|
||||
$resp = $this->asEditor()->get($page->getUrl('/export/markdown'));
|
||||
$resp->assertStatus(200);
|
||||
$resp->assertSee($page->name);
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $page->slug . '.md"');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . $page->slug . '.md');
|
||||
}
|
||||
|
||||
public function test_page_markdown_export_uses_existing_markdown_if_apparent()
|
||||
@@ -56,6 +56,20 @@ class MarkdownExportTest extends TestCase
|
||||
$resp->assertSee('My **chapter** description');
|
||||
}
|
||||
|
||||
public function test_chapter_markdown_export_pages_are_permission_controlled()
|
||||
{
|
||||
$chapter = $this->entities->chapterHasPages();
|
||||
$page = $chapter->pages()->first();
|
||||
$page->name = 'MyPageWhichShouldNotBeFound';
|
||||
$page->save();
|
||||
$this->permissions->disableEntityInheritedPermissions($page);
|
||||
|
||||
$resp = $this->asEditor()->get($chapter->getUrl('/export/markdown'));
|
||||
|
||||
$resp->assertSee('# ' . $chapter->name);
|
||||
$resp->assertDontSee('MyPageWhichShouldNotBeFound');
|
||||
}
|
||||
|
||||
public function test_book_markdown_export()
|
||||
{
|
||||
$book = Book::query()->whereHas('pages')->whereHas('chapters')->first();
|
||||
@@ -76,6 +90,38 @@ class MarkdownExportTest extends TestCase
|
||||
$resp->assertSee('My **chapter** description');
|
||||
}
|
||||
|
||||
public function test_book_markdown_export_chapters_are_permission_controlled()
|
||||
{
|
||||
$book = $this->entities->bookHasChaptersAndPages();
|
||||
$chapter = $book->chapters()->first();
|
||||
$page = $chapter->pages()->first();
|
||||
$page->name = 'MyPageWhichShouldNotBeFound';
|
||||
$page->save();
|
||||
$chapter->name = 'MyChapterWhichShouldNotBeFound';
|
||||
$chapter->save();
|
||||
$this->permissions->disableEntityInheritedPermissions($chapter);
|
||||
|
||||
$resp = $this->asEditor()->get($book->getUrl('/export/markdown'));
|
||||
|
||||
$resp->assertSee('# ' . $book->name);
|
||||
$resp->assertDontSee('MyChapterWhichShouldNotBeFound');
|
||||
$resp->assertDontSee('MyPageWhichShouldNotBeFound');
|
||||
}
|
||||
|
||||
public function test_book_markdown_export_direct_pages_are_permission_controlled()
|
||||
{
|
||||
$book = $this->entities->bookHasChaptersAndPages();
|
||||
$page = $book->directPages()->first();
|
||||
$page->name = 'MyPageWhichShouldNotBeFound';
|
||||
$page->save();
|
||||
$this->permissions->disableEntityInheritedPermissions($page);
|
||||
|
||||
$resp = $this->asEditor()->get($book->getUrl('/export/markdown'));
|
||||
|
||||
$resp->assertSee('# ' . $book->name);
|
||||
$resp->assertDontSee('MyPageWhichShouldNotBeFound');
|
||||
}
|
||||
|
||||
public function test_book_markdown_export_concats_immediate_pages_with_newlines()
|
||||
{
|
||||
/** @var Book $book */
|
||||
|
||||
@@ -17,7 +17,7 @@ class PdfExportTest extends TestCase
|
||||
|
||||
$resp = $this->get($page->getUrl('/export/pdf'));
|
||||
$resp->assertStatus(200);
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $page->slug . '.pdf"');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . $page->slug . '.pdf');
|
||||
}
|
||||
|
||||
public function test_book_pdf_export()
|
||||
@@ -28,7 +28,7 @@ class PdfExportTest extends TestCase
|
||||
|
||||
$resp = $this->get($book->getUrl('/export/pdf'));
|
||||
$resp->assertStatus(200);
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $book->slug . '.pdf"');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . $book->slug . '.pdf');
|
||||
}
|
||||
|
||||
public function test_chapter_pdf_export()
|
||||
@@ -38,7 +38,7 @@ class PdfExportTest extends TestCase
|
||||
|
||||
$resp = $this->get($chapter->getUrl('/export/pdf'));
|
||||
$resp->assertStatus(200);
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $chapter->slug . '.pdf"');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . $chapter->slug . '.pdf');
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ class TextExportTest extends TestCase
|
||||
$resp = $this->get($page->getUrl('/export/plaintext'));
|
||||
$resp->assertStatus(200);
|
||||
$resp->assertSee($page->name);
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $page->slug . '.txt"');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . $page->slug . '.txt');
|
||||
}
|
||||
|
||||
public function test_book_text_export()
|
||||
@@ -35,7 +35,7 @@ class TextExportTest extends TestCase
|
||||
$resp->assertSee($directPage->name);
|
||||
$resp->assertSee('My awesome page');
|
||||
$resp->assertSee('My little nested page');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $book->slug . '.txt"');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . $book->slug . '.txt');
|
||||
}
|
||||
|
||||
public function test_book_text_export_format()
|
||||
@@ -68,7 +68,7 @@ class TextExportTest extends TestCase
|
||||
$resp->assertSee($chapter->name);
|
||||
$resp->assertSee($page->name);
|
||||
$resp->assertSee('This is content within the page!');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $chapter->slug . '.txt"');
|
||||
$resp->assertHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . $chapter->slug . '.txt');
|
||||
}
|
||||
|
||||
public function test_chapter_text_export_format()
|
||||
|
||||
@@ -324,7 +324,7 @@ class AttachmentTest extends TestCase
|
||||
$attachmentGet = $this->get($attachment->getUrl(true));
|
||||
// http-foundation/Response does some 'fixing' of responses to add charsets to text responses.
|
||||
$attachmentGet->assertHeader('Content-Type', 'text/plain; charset=utf-8');
|
||||
$attachmentGet->assertHeader('Content-Disposition', 'inline; filename="upload_test_file.txt"');
|
||||
$attachmentGet->assertHeader('Content-Disposition', 'inline; filename*=UTF-8\'\'upload_test_file.txt');
|
||||
$attachmentGet->assertHeader('X-Content-Type-Options', 'nosniff');
|
||||
|
||||
$this->files->deleteAllAttachmentFiles();
|
||||
@@ -340,7 +340,22 @@ class AttachmentTest extends TestCase
|
||||
$attachmentGet = $this->get($attachment->getUrl(true));
|
||||
// http-foundation/Response does some 'fixing' of responses to add charsets to text responses.
|
||||
$attachmentGet->assertHeader('Content-Type', 'text/plain; charset=utf-8');
|
||||
$attachmentGet->assertHeader('Content-Disposition', 'inline; filename="test_file.html"');
|
||||
$attachmentGet->assertHeader('Content-Disposition', 'inline; filename*=UTF-8\'\'test_file.html');
|
||||
|
||||
$this->files->deleteAllAttachmentFiles();
|
||||
}
|
||||
|
||||
public function test_file_access_name_in_content_disposition_header_is_sanitized()
|
||||
{
|
||||
$page = $this->entities->page();
|
||||
$this->asAdmin();
|
||||
|
||||
$attachment = $this->files->uploadAttachmentDataToPage($this, $page, 'test_file.html', '<html></html><p>testing</p>', 'text/html');
|
||||
$attachment->name = "my\\_/super\n_fu\$n_\tfile";
|
||||
$attachment->save();
|
||||
|
||||
$attachmentGet = $this->get($attachment->getUrl(true));
|
||||
$attachmentGet->assertHeader('Content-Disposition', 'inline; filename*=UTF-8\'\'my_super_fun_file.html');
|
||||
|
||||
$this->files->deleteAllAttachmentFiles();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user