X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/934a833818b77e51f83d21a22478aea36ae9a294..refs/pull/3918/head:/tests/Entity/ExportTest.php
diff --git a/tests/Entity/ExportTest.php b/tests/Entity/ExportTest.php
index 4c6fb1a74..0f80bdd49 100644
--- a/tests/Entity/ExportTest.php
+++ b/tests/Entity/ExportTest.php
@@ -2,9 +2,11 @@
namespace Tests\Entity;
+use BookStack\Auth\Role;
use BookStack\Entities\Models\Book;
use BookStack\Entities\Models\Chapter;
use BookStack\Entities\Models\Page;
+use BookStack\Entities\Tools\PdfGenerator;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Tests\TestCase;
@@ -13,7 +15,7 @@ class ExportTest extends TestCase
{
public function test_page_text_export()
{
- $page = Page::query()->first();
+ $page = $this->entities->page();
$this->asEditor();
$resp = $this->get($page->getUrl('/export/plaintext'));
@@ -24,7 +26,7 @@ class ExportTest extends TestCase
public function test_page_pdf_export()
{
- $page = Page::query()->first();
+ $page = $this->entities->page();
$this->asEditor();
$resp = $this->get($page->getUrl('/export/pdf'));
@@ -34,7 +36,7 @@ class ExportTest extends TestCase
public function test_page_html_export()
{
- $page = Page::query()->first();
+ $page = $this->entities->page();
$this->asEditor();
$resp = $this->get($page->getUrl('/export/html'));
@@ -45,7 +47,7 @@ class ExportTest extends TestCase
public function test_book_text_export()
{
- $page = Page::query()->first();
+ $page = $this->entities->page();
$book = $page->book;
$this->asEditor();
@@ -58,7 +60,7 @@ class ExportTest extends TestCase
public function test_book_pdf_export()
{
- $page = Page::query()->first();
+ $page = $this->entities->page();
$book = $page->book;
$this->asEditor();
@@ -69,7 +71,7 @@ class ExportTest extends TestCase
public function test_book_html_export()
{
- $page = Page::query()->first();
+ $page = $this->entities->page();
$book = $page->book;
$this->asEditor();
@@ -83,7 +85,7 @@ class ExportTest extends TestCase
public function test_book_html_export_shows_chapter_descriptions()
{
$chapterDesc = 'My custom test chapter description ' . Str::random(12);
- $chapter = Chapter::query()->first();
+ $chapter = $this->entities->chapter();
$chapter->description = $chapterDesc;
$chapter->save();
@@ -96,7 +98,7 @@ class ExportTest extends TestCase
public function test_chapter_text_export()
{
- $chapter = Chapter::query()->first();
+ $chapter = $this->entities->chapter();
$page = $chapter->pages[0];
$this->asEditor();
@@ -109,7 +111,7 @@ class ExportTest extends TestCase
public function test_chapter_pdf_export()
{
- $chapter = Chapter::query()->first();
+ $chapter = $this->entities->chapter();
$this->asEditor();
$resp = $this->get($chapter->getUrl('/export/pdf'));
@@ -119,7 +121,7 @@ class ExportTest extends TestCase
public function test_chapter_html_export()
{
- $chapter = Chapter::query()->first();
+ $chapter = $this->entities->chapter();
$page = $chapter->pages[0];
$this->asEditor();
@@ -132,30 +134,30 @@ class ExportTest extends TestCase
public function test_page_html_export_contains_custom_head_if_set()
{
- $page = Page::query()->first();
+ $page = $this->entities->page();
$customHeadContent = '';
$this->setSettings(['app-custom-head' => $customHeadContent]);
$resp = $this->asEditor()->get($page->getUrl('/export/html'));
- $resp->assertSee($customHeadContent);
+ $resp->assertSee($customHeadContent, false);
}
public function test_page_html_export_does_not_break_with_only_comments_in_custom_head()
{
- $page = Page::query()->first();
+ $page = $this->entities->page();
$customHeadContent = '';
$this->setSettings(['app-custom-head' => $customHeadContent]);
$resp = $this->asEditor()->get($page->getUrl('/export/html'));
$resp->assertStatus(200);
- $resp->assertSee($customHeadContent);
+ $resp->assertSee($customHeadContent, false);
}
public function test_page_html_export_use_absolute_dates()
{
- $page = Page::query()->first();
+ $page = $this->entities->page();
$resp = $this->asEditor()->get($page->getUrl('/export/html'));
$resp->assertSee($page->created_at->formatLocalized('%e %B %Y %H:%M:%S'));
@@ -166,7 +168,7 @@ class ExportTest extends TestCase
public function test_page_export_does_not_include_user_or_revision_links()
{
- $page = Page::query()->first();
+ $page = $this->entities->page();
$resp = $this->asEditor()->get($page->getUrl('/export/html'));
$resp->assertDontSee($page->getUrl('/revisions'));
@@ -176,7 +178,7 @@ class ExportTest extends TestCase
public function test_page_export_sets_right_data_type_for_svg_embeds()
{
- $page = Page::query()->first();
+ $page = $this->entities->page();
Storage::disk('local')->makeDirectory('uploads/images/gallery');
Storage::disk('local')->put('uploads/images/gallery/svg_test.svg', '');
$page->html = '
';
@@ -187,12 +189,12 @@ class ExportTest extends TestCase
Storage::disk('local')->delete('uploads/images/gallery/svg_test.svg');
$resp->assertStatus(200);
- $resp->assertSee('
first();
+ $page = $this->entities->page();
Storage::disk('local')->makeDirectory('uploads/images/gallery');
Storage::disk('local')->put('uploads/images/gallery/svg_test.svg', '');
Storage::disk('local')->put('uploads/images/gallery/svg_test2.svg', '');
@@ -208,7 +210,7 @@ class ExportTest extends TestCase
public function test_page_export_contained_html_image_fetches_only_run_when_url_points_to_image_upload_folder()
{
- $page = Page::query()->first();
+ $page = $this->entities->page();
$page->html = '
'
. '
'
. '
';
@@ -223,9 +225,37 @@ class ExportTest extends TestCase
$storageDisk->delete('uploads/images/gallery/svg_test.svg');
$storageDisk->delete('uploads/svg_test.svg');
- $resp->assertDontSee('http://localhost/uploads/images/gallery/svg_test.svg');
+ $resp->assertDontSee('http://localhost/uploads/images/gallery/svg_test.svg', false);
$resp->assertSee('http://localhost/uploads/svg_test.svg');
- $resp->assertSee('src="/uploads/svg_test.svg"');
+ $resp->assertSee('src="/uploads/svg_test.svg"', false);
+ }
+
+ public function test_page_export_contained_html_does_not_allow_upward_traversal_with_local()
+ {
+ $contents = file_get_contents(public_path('.htaccess'));
+ config()->set('filesystems.images', 'local');
+
+ $page = $this->entities->page();
+ $page->html = '
';
+ $page->save();
+
+ $resp = $this->asEditor()->get($page->getUrl('/export/html'));
+ $resp->assertDontSee(base64_encode($contents));
+ }
+
+ public function test_page_export_contained_html_does_not_allow_upward_traversal_with_local_secure()
+ {
+ $testFilePath = storage_path('logs/test.txt');
+ config()->set('filesystems.images', 'local_secure');
+ file_put_contents($testFilePath, 'I am a cat');
+
+ $page = $this->entities->page();
+ $page->html = '
';
+ $page->save();
+
+ $resp = $this->asEditor()->get($page->getUrl('/export/html'));
+ $resp->assertDontSee(base64_encode('I am a cat'));
+ unlink($testFilePath);
}
public function test_exports_removes_scripts_from_custom_head()
@@ -238,7 +268,7 @@ class ExportTest extends TestCase
foreach ($entities as $entity) {
$resp = $this->asEditor()->get($entity->getUrl('/export/html'));
$resp->assertDontSee('window.donkey');
- $resp->assertDontSee('script');
+ $resp->assertDontSee('