X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/7d9de23a25a5a055adf79e81f67768686f3a8c94..refs/pull/4322/head:/tests/Entity/ExportTest.php
diff --git a/tests/Entity/ExportTest.php b/tests/Entity/ExportTest.php
index 7031c3875..2b5244bf0 100644
--- a/tests/Entity/ExportTest.php
+++ b/tests/Entity/ExportTest.php
@@ -2,10 +2,10 @@
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;
@@ -14,7 +14,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'));
@@ -25,7 +25,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'));
@@ -35,7 +35,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'));
@@ -46,7 +46,7 @@ class ExportTest extends TestCase
public function test_book_text_export()
{
- $page = Page::query()->first();
+ $page = $this->entities->page();
$book = $page->book;
$this->asEditor();
@@ -59,7 +59,7 @@ class ExportTest extends TestCase
public function test_book_pdf_export()
{
- $page = Page::query()->first();
+ $page = $this->entities->page();
$book = $page->book;
$this->asEditor();
@@ -70,7 +70,7 @@ class ExportTest extends TestCase
public function test_book_html_export()
{
- $page = Page::query()->first();
+ $page = $this->entities->page();
$book = $page->book;
$this->asEditor();
@@ -84,7 +84,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();
@@ -97,7 +97,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();
@@ -110,7 +110,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'));
@@ -120,7 +120,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();
@@ -133,41 +133,41 @@ 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'));
+ $resp->assertSee($page->created_at->isoFormat('D MMMM Y HH:mm:ss'));
$resp->assertDontSee($page->created_at->diffForHumans());
- $resp->assertSee($page->updated_at->formatLocalized('%e %B %Y %H:%M:%S'));
+ $resp->assertSee($page->updated_at->isoFormat('D MMMM Y HH:mm:ss'));
$resp->assertDontSee($page->updated_at->diffForHumans());
}
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'));
@@ -177,7 +177,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 = '
';
@@ -188,12 +188,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', '');
@@ -209,7 +209,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 = '
'
. '
'
. '
';
@@ -224,9 +224,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()
@@ -239,15 +267,15 @@ 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('