Merge pull request #4969 from BookStackApp/pdf_command_option
PDF Exports: New command option and library/option cleanup
This commit is contained in:
		
						commit
						e1149a27e9
					
				| 
						 | 
				
			
			@ -325,6 +325,14 @@ FILE_UPLOAD_SIZE_LIMIT=50
 | 
			
		|||
# Can be 'a4' or 'letter'.
 | 
			
		||||
EXPORT_PAGE_SIZE=a4
 | 
			
		||||
 | 
			
		||||
# Export PDF Command
 | 
			
		||||
# Set a command which can be used to convert a HTML file into a PDF file.
 | 
			
		||||
# When false this will not be used.
 | 
			
		||||
# String values represent the command to be called for conversion.
 | 
			
		||||
# Supports '{input_html_path}' and '{output_pdf_path}' placeholder values.
 | 
			
		||||
# Example: EXPORT_PDF_COMMAND="/scripts/convert.sh {input_html_path} {output_pdf_path}"
 | 
			
		||||
EXPORT_PDF_COMMAND=false
 | 
			
		||||
 | 
			
		||||
# Set path to wkhtmltopdf binary for PDF generation.
 | 
			
		||||
# Can be 'false' or a path path like: '/home/bins/wkhtmltopdf'
 | 
			
		||||
# When false, BookStack will attempt to find a wkhtmltopdf in the application
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -116,8 +116,6 @@ return [
 | 
			
		|||
    // Application Service Providers
 | 
			
		||||
    'providers' => ServiceProvider::defaultProviders()->merge([
 | 
			
		||||
        // Third party service providers
 | 
			
		||||
        Barryvdh\DomPDF\ServiceProvider::class,
 | 
			
		||||
        Barryvdh\Snappy\ServiceProvider::class,
 | 
			
		||||
        SocialiteProviders\Manager\ServiceProvider::class,
 | 
			
		||||
 | 
			
		||||
        // BookStack custom service providers
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,23 +1,45 @@
 | 
			
		|||
<?php
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * DOMPDF configuration options.
 | 
			
		||||
 * Export configuration options.
 | 
			
		||||
 *
 | 
			
		||||
 * Changes to these config files are not supported by BookStack and may break upon updates.
 | 
			
		||||
 * Configuration should be altered via the `.env` file or environment variables.
 | 
			
		||||
 * Do not edit this file unless you're happy to maintain any changes yourself.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
$snappyPaperSizeMap = [
 | 
			
		||||
    'a4'     => 'A4',
 | 
			
		||||
    'letter' => 'Letter',
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
$dompdfPaperSizeMap = [
 | 
			
		||||
    'a4'     => 'a4',
 | 
			
		||||
    'letter' => 'letter',
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
$exportPageSize = env('EXPORT_PAGE_SIZE', 'a4');
 | 
			
		||||
 | 
			
		||||
return [
 | 
			
		||||
 | 
			
		||||
    'show_warnings' => false,   // Throw an Exception on warnings from dompdf
 | 
			
		||||
    // Set a command which can be used to convert a HTML file into a PDF file.
 | 
			
		||||
    // When false this will not be used.
 | 
			
		||||
    // String values represent the command to be called for conversion.
 | 
			
		||||
    // Supports '{input_html_path}' and '{output_pdf_path}' placeholder values.
 | 
			
		||||
    // Example: EXPORT_PDF_COMMAND="/scripts/convert.sh {input_html_path} {output_pdf_path}"
 | 
			
		||||
    'pdf_command' => env('EXPORT_PDF_COMMAND', false),
 | 
			
		||||
 | 
			
		||||
    'options'       => [
 | 
			
		||||
    // 2024-04: Snappy/WKHTMLtoPDF now considered deprecated in regard to BookStack support.
 | 
			
		||||
    'snappy' => [
 | 
			
		||||
        'pdf_binary' => env('WKHTMLTOPDF', false),
 | 
			
		||||
        'options' => [
 | 
			
		||||
            'print-media-type' => true,
 | 
			
		||||
            'outline'   => true,
 | 
			
		||||
            'page-size' => $snappyPaperSizeMap[$exportPageSize] ?? 'A4',
 | 
			
		||||
        ],
 | 
			
		||||
    ],
 | 
			
		||||
 | 
			
		||||
    'dompdf' => [
 | 
			
		||||
        /**
 | 
			
		||||
         * The location of the DOMPDF font directory.
 | 
			
		||||
         *
 | 
			
		||||
| 
						 | 
				
			
			@ -101,7 +123,7 @@ return [
 | 
			
		|||
        /**
 | 
			
		||||
         * Whether to enable font subsetting or not.
 | 
			
		||||
         */
 | 
			
		||||
        'enable_fontsubsetting' => false,
 | 
			
		||||
        'enable_font_subsetting' => false,
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * The PDF rendering backend to use.
 | 
			
		||||
| 
						 | 
				
			
			@ -165,7 +187,7 @@ return [
 | 
			
		|||
         *
 | 
			
		||||
         * @see CPDF_Adapter::PAPER_SIZES for valid sizes ('letter', 'legal', 'A4', etc.)
 | 
			
		||||
         */
 | 
			
		||||
        'default_paper_size' => $dompdfPaperSizeMap[env('EXPORT_PAGE_SIZE', 'a4')] ?? 'a4',
 | 
			
		||||
        'default_paper_size' => $dompdfPaperSizeMap[$exportPageSize] ?? 'a4',
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * The default paper orientation.
 | 
			
		||||
| 
						 | 
				
			
			@ -268,15 +290,6 @@ return [
 | 
			
		|||
         */
 | 
			
		||||
        'font_height_ratio' => 1.1,
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Enable CSS float.
 | 
			
		||||
         *
 | 
			
		||||
         * Allows people to disabled CSS float support
 | 
			
		||||
         *
 | 
			
		||||
         * @var bool
 | 
			
		||||
         */
 | 
			
		||||
        'enable_css_float' => true,
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Use the HTML5 Lib parser.
 | 
			
		||||
         *
 | 
			
		||||
| 
						 | 
				
			
			@ -286,5 +299,4 @@ return [
 | 
			
		|||
         */
 | 
			
		||||
        'enable_html5_parser' => true,
 | 
			
		||||
    ],
 | 
			
		||||
 | 
			
		||||
];
 | 
			
		||||
| 
						 | 
				
			
			@ -1,34 +0,0 @@
 | 
			
		|||
<?php
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SnappyPDF configuration options.
 | 
			
		||||
 *
 | 
			
		||||
 * Changes to these config files are not supported by BookStack and may break upon updates.
 | 
			
		||||
 * Configuration should be altered via the `.env` file or environment variables.
 | 
			
		||||
 * Do not edit this file unless you're happy to maintain any changes yourself.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
$snappyPaperSizeMap = [
 | 
			
		||||
    'a4'     => 'A4',
 | 
			
		||||
    'letter' => 'Letter',
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
return [
 | 
			
		||||
    'pdf' => [
 | 
			
		||||
        'enabled' => true,
 | 
			
		||||
        'binary'  => file_exists(base_path('wkhtmltopdf')) ? base_path('wkhtmltopdf') : env('WKHTMLTOPDF', false),
 | 
			
		||||
        'timeout' => false,
 | 
			
		||||
        'options' => [
 | 
			
		||||
            'outline'   => true,
 | 
			
		||||
            'page-size' => $snappyPaperSizeMap[env('EXPORT_PAGE_SIZE', 'a4')] ?? 'A4',
 | 
			
		||||
        ],
 | 
			
		||||
        'env'     => [],
 | 
			
		||||
    ],
 | 
			
		||||
    'image' => [
 | 
			
		||||
        'enabled' => false,
 | 
			
		||||
        'binary'  => '/usr/local/bin/wkhtmltoimage',
 | 
			
		||||
        'timeout' => false,
 | 
			
		||||
        'options' => [],
 | 
			
		||||
        'env'     => [],
 | 
			
		||||
    ],
 | 
			
		||||
];
 | 
			
		||||
| 
						 | 
				
			
			@ -2,27 +2,28 @@
 | 
			
		|||
 | 
			
		||||
namespace BookStack\Entities\Tools;
 | 
			
		||||
 | 
			
		||||
use Barryvdh\DomPDF\Facade\Pdf as DomPDF;
 | 
			
		||||
use Barryvdh\Snappy\Facades\SnappyPdf;
 | 
			
		||||
use BookStack\Exceptions\PdfExportException;
 | 
			
		||||
use Knp\Snappy\Pdf as SnappyPdf;
 | 
			
		||||
use Dompdf\Dompdf;
 | 
			
		||||
use Symfony\Component\Process\Process;
 | 
			
		||||
 | 
			
		||||
class PdfGenerator
 | 
			
		||||
{
 | 
			
		||||
    const ENGINE_DOMPDF = 'dompdf';
 | 
			
		||||
    const ENGINE_WKHTML = 'wkhtml';
 | 
			
		||||
    const ENGINE_COMMAND = 'command';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Generate PDF content from the given HTML content.
 | 
			
		||||
     * @throws PdfExportException
 | 
			
		||||
     */
 | 
			
		||||
    public function fromHtml(string $html): string
 | 
			
		||||
    {
 | 
			
		||||
        if ($this->getActiveEngine() === self::ENGINE_WKHTML) {
 | 
			
		||||
            $pdf = SnappyPDF::loadHTML($html);
 | 
			
		||||
            $pdf->setOption('print-media-type', true);
 | 
			
		||||
        } else {
 | 
			
		||||
            $pdf = DomPDF::loadHTML($html);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $pdf->output();
 | 
			
		||||
        return match ($this->getActiveEngine()) {
 | 
			
		||||
            self::ENGINE_COMMAND => $this->renderUsingCommand($html),
 | 
			
		||||
            self::ENGINE_WKHTML => $this->renderUsingWkhtml($html),
 | 
			
		||||
            default => $this->renderUsingDomPdf($html)
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -31,8 +32,101 @@ class PdfGenerator
 | 
			
		|||
     */
 | 
			
		||||
    public function getActiveEngine(): string
 | 
			
		||||
    {
 | 
			
		||||
        $useWKHTML = config('snappy.pdf.binary') !== false && config('app.allow_untrusted_server_fetching') === true;
 | 
			
		||||
        if (config('exports.pdf_command')) {
 | 
			
		||||
            return self::ENGINE_COMMAND;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $useWKHTML ? self::ENGINE_WKHTML : self::ENGINE_DOMPDF;
 | 
			
		||||
        if ($this->getWkhtmlBinaryPath() && config('app.allow_untrusted_server_fetching') === true) {
 | 
			
		||||
            return self::ENGINE_WKHTML;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return self::ENGINE_DOMPDF;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function getWkhtmlBinaryPath(): string
 | 
			
		||||
    {
 | 
			
		||||
        $wkhtmlBinaryPath = config('exports.snappy.pdf_binary');
 | 
			
		||||
        if (file_exists(base_path('wkhtmltopdf'))) {
 | 
			
		||||
            $wkhtmlBinaryPath = base_path('wkhtmltopdf');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $wkhtmlBinaryPath ?: '';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function renderUsingDomPdf(string $html): string
 | 
			
		||||
    {
 | 
			
		||||
        $options = config('exports.dompdf');
 | 
			
		||||
        $domPdf = new Dompdf($options);
 | 
			
		||||
        $domPdf->setBasePath(base_path('public'));
 | 
			
		||||
 | 
			
		||||
        $domPdf->loadHTML($this->convertEntities($html));
 | 
			
		||||
        $domPdf->render();
 | 
			
		||||
 | 
			
		||||
        return (string) $domPdf->output();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @throws PdfExportException
 | 
			
		||||
     */
 | 
			
		||||
    protected function renderUsingCommand(string $html): string
 | 
			
		||||
    {
 | 
			
		||||
        $command = config('exports.pdf_command');
 | 
			
		||||
        $inputHtml = tempnam(sys_get_temp_dir(), 'bs-pdfgen-html-');
 | 
			
		||||
        $outputPdf = tempnam(sys_get_temp_dir(), 'bs-pdfgen-output-');
 | 
			
		||||
 | 
			
		||||
        $replacementsByPlaceholder = [
 | 
			
		||||
            '{input_html_path}' => $inputHtml,
 | 
			
		||||
            '{output_pdf_path}' => $outputPdf,
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        foreach ($replacementsByPlaceholder as $placeholder => $replacement) {
 | 
			
		||||
            $command = str_replace($placeholder, escapeshellarg($replacement), $command);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        file_put_contents($inputHtml, $html);
 | 
			
		||||
 | 
			
		||||
        $process = Process::fromShellCommandline($command);
 | 
			
		||||
        $process->setTimeout(15);
 | 
			
		||||
        $process->run();
 | 
			
		||||
 | 
			
		||||
        if (!$process->isSuccessful()) {
 | 
			
		||||
            throw new PdfExportException("PDF Export via command failed with exit code {$process->getExitCode()}, stdout: {$process->getOutput()}, stderr: {$process->getErrorOutput()}");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $pdfContents = file_get_contents($outputPdf);
 | 
			
		||||
        unlink($outputPdf);
 | 
			
		||||
 | 
			
		||||
        if ($pdfContents === false) {
 | 
			
		||||
            throw new PdfExportException("PDF Export via command failed, unable to read PDF output file");
 | 
			
		||||
        } else if (empty($pdfContents)) {
 | 
			
		||||
            throw new PdfExportException("PDF Export via command failed, PDF output file is empty");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $pdfContents;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function renderUsingWkhtml(string $html): string
 | 
			
		||||
    {
 | 
			
		||||
        $snappy = new SnappyPdf($this->getWkhtmlBinaryPath());
 | 
			
		||||
        $options = config('exports.snappy.options');
 | 
			
		||||
        return $snappy->getOutputFromHtml($html, $options);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Taken from https://github.com/barryvdh/laravel-dompdf/blob/v2.1.1/src/PDF.php
 | 
			
		||||
     * Copyright (c) 2021 barryvdh, MIT License
 | 
			
		||||
     * https://github.com/barryvdh/laravel-dompdf/blob/v2.1.1/LICENSE
 | 
			
		||||
     */
 | 
			
		||||
    protected function convertEntities(string $subject): string
 | 
			
		||||
    {
 | 
			
		||||
        $entities = [
 | 
			
		||||
            '€' => '€',
 | 
			
		||||
            '£' => '£',
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        foreach ($entities as $search => $replace) {
 | 
			
		||||
            $subject = str_replace($search, $replace, $subject);
 | 
			
		||||
        }
 | 
			
		||||
        return $subject;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
<?php
 | 
			
		||||
 | 
			
		||||
namespace BookStack\Exceptions;
 | 
			
		||||
 | 
			
		||||
class PdfExportException extends \Exception
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -17,11 +17,11 @@
 | 
			
		|||
        "ext-mbstring": "*",
 | 
			
		||||
        "ext-xml": "*",
 | 
			
		||||
        "bacon/bacon-qr-code": "^2.0",
 | 
			
		||||
        "barryvdh/laravel-dompdf": "^2.0",
 | 
			
		||||
        "barryvdh/laravel-snappy": "^1.0",
 | 
			
		||||
        "doctrine/dbal": "^3.5",
 | 
			
		||||
        "dompdf/dompdf": "^2.0",
 | 
			
		||||
        "guzzlehttp/guzzle": "^7.4",
 | 
			
		||||
        "intervention/image": "^3.5",
 | 
			
		||||
        "knplabs/knp-snappy": "^1.5",
 | 
			
		||||
        "laravel/framework": "^10.10",
 | 
			
		||||
        "laravel/socialite": "^5.10",
 | 
			
		||||
        "laravel/tinker": "^2.8",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,7 @@
 | 
			
		|||
        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
 | 
			
		||||
        "This file is @generated automatically"
 | 
			
		||||
    ],
 | 
			
		||||
    "content-hash": "ccfc07d0ecc580962915a0457f0466a7",
 | 
			
		||||
    "content-hash": "97259e40ffe5518cfcdf1e32eacbb175",
 | 
			
		||||
    "packages": [
 | 
			
		||||
        {
 | 
			
		||||
            "name": "aws/aws-crt-php",
 | 
			
		||||
| 
						 | 
				
			
			@ -209,161 +209,6 @@
 | 
			
		|||
            },
 | 
			
		||||
            "time": "2022-12-07T17:46:57+00:00"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "barryvdh/laravel-dompdf",
 | 
			
		||||
            "version": "v2.1.1",
 | 
			
		||||
            "source": {
 | 
			
		||||
                "type": "git",
 | 
			
		||||
                "url": "https://github.com/barryvdh/laravel-dompdf.git",
 | 
			
		||||
                "reference": "cb37868365f9b937039d316727a1fced1e87b31c"
 | 
			
		||||
            },
 | 
			
		||||
            "dist": {
 | 
			
		||||
                "type": "zip",
 | 
			
		||||
                "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/cb37868365f9b937039d316727a1fced1e87b31c",
 | 
			
		||||
                "reference": "cb37868365f9b937039d316727a1fced1e87b31c",
 | 
			
		||||
                "shasum": ""
 | 
			
		||||
            },
 | 
			
		||||
            "require": {
 | 
			
		||||
                "dompdf/dompdf": "^2.0.3",
 | 
			
		||||
                "illuminate/support": "^6|^7|^8|^9|^10|^11",
 | 
			
		||||
                "php": "^7.2 || ^8.0"
 | 
			
		||||
            },
 | 
			
		||||
            "require-dev": {
 | 
			
		||||
                "larastan/larastan": "^1.0|^2.7.0",
 | 
			
		||||
                "orchestra/testbench": "^4|^5|^6|^7|^8|^9",
 | 
			
		||||
                "phpro/grumphp": "^1 || ^2.5",
 | 
			
		||||
                "squizlabs/php_codesniffer": "^3.5"
 | 
			
		||||
            },
 | 
			
		||||
            "type": "library",
 | 
			
		||||
            "extra": {
 | 
			
		||||
                "branch-alias": {
 | 
			
		||||
                    "dev-master": "2.0-dev"
 | 
			
		||||
                },
 | 
			
		||||
                "laravel": {
 | 
			
		||||
                    "providers": [
 | 
			
		||||
                        "Barryvdh\\DomPDF\\ServiceProvider"
 | 
			
		||||
                    ],
 | 
			
		||||
                    "aliases": {
 | 
			
		||||
                        "Pdf": "Barryvdh\\DomPDF\\Facade\\Pdf",
 | 
			
		||||
                        "PDF": "Barryvdh\\DomPDF\\Facade\\Pdf"
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "autoload": {
 | 
			
		||||
                "psr-4": {
 | 
			
		||||
                    "Barryvdh\\DomPDF\\": "src"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "notification-url": "https://packagist.org/downloads/",
 | 
			
		||||
            "license": [
 | 
			
		||||
                "MIT"
 | 
			
		||||
            ],
 | 
			
		||||
            "authors": [
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Barry vd. Heuvel",
 | 
			
		||||
                    "email": "barryvdh@gmail.com"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "description": "A DOMPDF Wrapper for Laravel",
 | 
			
		||||
            "keywords": [
 | 
			
		||||
                "dompdf",
 | 
			
		||||
                "laravel",
 | 
			
		||||
                "pdf"
 | 
			
		||||
            ],
 | 
			
		||||
            "support": {
 | 
			
		||||
                "issues": "https://github.com/barryvdh/laravel-dompdf/issues",
 | 
			
		||||
                "source": "https://github.com/barryvdh/laravel-dompdf/tree/v2.1.1"
 | 
			
		||||
            },
 | 
			
		||||
            "funding": [
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://fruitcake.nl",
 | 
			
		||||
                    "type": "custom"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://github.com/barryvdh",
 | 
			
		||||
                    "type": "github"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "time": "2024-03-15T12:48:39+00:00"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "barryvdh/laravel-snappy",
 | 
			
		||||
            "version": "v1.0.3",
 | 
			
		||||
            "source": {
 | 
			
		||||
                "type": "git",
 | 
			
		||||
                "url": "https://github.com/barryvdh/laravel-snappy.git",
 | 
			
		||||
                "reference": "716dcb6db24de4ce8e6ae5941cfab152af337ea0"
 | 
			
		||||
            },
 | 
			
		||||
            "dist": {
 | 
			
		||||
                "type": "zip",
 | 
			
		||||
                "url": "https://api.github.com/repos/barryvdh/laravel-snappy/zipball/716dcb6db24de4ce8e6ae5941cfab152af337ea0",
 | 
			
		||||
                "reference": "716dcb6db24de4ce8e6ae5941cfab152af337ea0",
 | 
			
		||||
                "shasum": ""
 | 
			
		||||
            },
 | 
			
		||||
            "require": {
 | 
			
		||||
                "illuminate/filesystem": "^9|^10|^11.0",
 | 
			
		||||
                "illuminate/support": "^9|^10|^11.0",
 | 
			
		||||
                "knplabs/knp-snappy": "^1.4.4",
 | 
			
		||||
                "php": ">=7.2"
 | 
			
		||||
            },
 | 
			
		||||
            "require-dev": {
 | 
			
		||||
                "orchestra/testbench": "^7|^8|^9.0"
 | 
			
		||||
            },
 | 
			
		||||
            "type": "library",
 | 
			
		||||
            "extra": {
 | 
			
		||||
                "branch-alias": {
 | 
			
		||||
                    "dev-master": "1.0-dev"
 | 
			
		||||
                },
 | 
			
		||||
                "laravel": {
 | 
			
		||||
                    "providers": [
 | 
			
		||||
                        "Barryvdh\\Snappy\\ServiceProvider"
 | 
			
		||||
                    ],
 | 
			
		||||
                    "aliases": {
 | 
			
		||||
                        "PDF": "Barryvdh\\Snappy\\Facades\\SnappyPdf",
 | 
			
		||||
                        "SnappyImage": "Barryvdh\\Snappy\\Facades\\SnappyImage"
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "autoload": {
 | 
			
		||||
                "psr-4": {
 | 
			
		||||
                    "Barryvdh\\Snappy\\": "src/"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "notification-url": "https://packagist.org/downloads/",
 | 
			
		||||
            "license": [
 | 
			
		||||
                "MIT"
 | 
			
		||||
            ],
 | 
			
		||||
            "authors": [
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Barry vd. Heuvel",
 | 
			
		||||
                    "email": "barryvdh@gmail.com"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "description": "Snappy PDF/Image for Laravel",
 | 
			
		||||
            "keywords": [
 | 
			
		||||
                "image",
 | 
			
		||||
                "laravel",
 | 
			
		||||
                "pdf",
 | 
			
		||||
                "snappy",
 | 
			
		||||
                "wkhtmltoimage",
 | 
			
		||||
                "wkhtmltopdf"
 | 
			
		||||
            ],
 | 
			
		||||
            "support": {
 | 
			
		||||
                "issues": "https://github.com/barryvdh/laravel-snappy/issues",
 | 
			
		||||
                "source": "https://github.com/barryvdh/laravel-snappy/tree/v1.0.3"
 | 
			
		||||
            },
 | 
			
		||||
            "funding": [
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://fruitcake.nl",
 | 
			
		||||
                    "type": "custom"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://github.com/barryvdh",
 | 
			
		||||
                    "type": "github"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "time": "2024-03-09T19:20:39+00:00"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "brick/math",
 | 
			
		||||
            "version": "0.11.0",
 | 
			
		||||
| 
						 | 
				
			
			@ -1127,16 +972,16 @@
 | 
			
		|||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "dompdf/dompdf",
 | 
			
		||||
            "version": "v2.0.4",
 | 
			
		||||
            "version": "v2.0.7",
 | 
			
		||||
            "source": {
 | 
			
		||||
                "type": "git",
 | 
			
		||||
                "url": "https://github.com/dompdf/dompdf.git",
 | 
			
		||||
                "reference": "093f2d9739cec57428e39ddadedfd4f3ae862c0f"
 | 
			
		||||
                "reference": "ab0123052b42ad0867348f25df8c228f1ece8f14"
 | 
			
		||||
            },
 | 
			
		||||
            "dist": {
 | 
			
		||||
                "type": "zip",
 | 
			
		||||
                "url": "https://api.github.com/repos/dompdf/dompdf/zipball/093f2d9739cec57428e39ddadedfd4f3ae862c0f",
 | 
			
		||||
                "reference": "093f2d9739cec57428e39ddadedfd4f3ae862c0f",
 | 
			
		||||
                "url": "https://api.github.com/repos/dompdf/dompdf/zipball/ab0123052b42ad0867348f25df8c228f1ece8f14",
 | 
			
		||||
                "reference": "ab0123052b42ad0867348f25df8c228f1ece8f14",
 | 
			
		||||
                "shasum": ""
 | 
			
		||||
            },
 | 
			
		||||
            "require": {
 | 
			
		||||
| 
						 | 
				
			
			@ -1144,7 +989,7 @@
 | 
			
		|||
                "ext-mbstring": "*",
 | 
			
		||||
                "masterminds/html5": "^2.0",
 | 
			
		||||
                "phenx/php-font-lib": ">=0.5.4 <1.0.0",
 | 
			
		||||
                "phenx/php-svg-lib": ">=0.3.3 <1.0.0",
 | 
			
		||||
                "phenx/php-svg-lib": ">=0.5.2 <1.0.0",
 | 
			
		||||
                "php": "^7.1 || ^8.0"
 | 
			
		||||
            },
 | 
			
		||||
            "require-dev": {
 | 
			
		||||
| 
						 | 
				
			
			@ -1183,9 +1028,9 @@
 | 
			
		|||
            "homepage": "https://github.com/dompdf/dompdf",
 | 
			
		||||
            "support": {
 | 
			
		||||
                "issues": "https://github.com/dompdf/dompdf/issues",
 | 
			
		||||
                "source": "https://github.com/dompdf/dompdf/tree/v2.0.4"
 | 
			
		||||
                "source": "https://github.com/dompdf/dompdf/tree/v2.0.7"
 | 
			
		||||
            },
 | 
			
		||||
            "time": "2023-12-12T20:19:39+00:00"
 | 
			
		||||
            "time": "2024-04-15T12:40:33+00:00"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "dragonmantank/cron-expression",
 | 
			
		||||
| 
						 | 
				
			
			@ -4067,16 +3912,16 @@
 | 
			
		|||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "phenx/php-svg-lib",
 | 
			
		||||
            "version": "0.5.3",
 | 
			
		||||
            "version": "0.5.4",
 | 
			
		||||
            "source": {
 | 
			
		||||
                "type": "git",
 | 
			
		||||
                "url": "https://github.com/dompdf/php-svg-lib.git",
 | 
			
		||||
                "reference": "0e46722c154726a5f9ac218197ccc28adba16fcf"
 | 
			
		||||
                "reference": "46b25da81613a9cf43c83b2a8c2c1bdab27df691"
 | 
			
		||||
            },
 | 
			
		||||
            "dist": {
 | 
			
		||||
                "type": "zip",
 | 
			
		||||
                "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/0e46722c154726a5f9ac218197ccc28adba16fcf",
 | 
			
		||||
                "reference": "0e46722c154726a5f9ac218197ccc28adba16fcf",
 | 
			
		||||
                "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/46b25da81613a9cf43c83b2a8c2c1bdab27df691",
 | 
			
		||||
                "reference": "46b25da81613a9cf43c83b2a8c2c1bdab27df691",
 | 
			
		||||
                "shasum": ""
 | 
			
		||||
            },
 | 
			
		||||
            "require": {
 | 
			
		||||
| 
						 | 
				
			
			@ -4107,9 +3952,9 @@
 | 
			
		|||
            "homepage": "https://github.com/PhenX/php-svg-lib",
 | 
			
		||||
            "support": {
 | 
			
		||||
                "issues": "https://github.com/dompdf/php-svg-lib/issues",
 | 
			
		||||
                "source": "https://github.com/dompdf/php-svg-lib/tree/0.5.3"
 | 
			
		||||
                "source": "https://github.com/dompdf/php-svg-lib/tree/0.5.4"
 | 
			
		||||
            },
 | 
			
		||||
            "time": "2024-02-23T20:39:24+00:00"
 | 
			
		||||
            "time": "2024-04-08T12:52:34+00:00"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "phpoption/phpoption",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -51,6 +51,7 @@
 | 
			
		|||
    <server name="LOG_FAILED_LOGIN_MESSAGE" value=""/>
 | 
			
		||||
    <server name="LOG_FAILED_LOGIN_CHANNEL" value="testing"/>
 | 
			
		||||
    <server name="WKHTMLTOPDF" value="false"/>
 | 
			
		||||
    <server name="EXPORT_PDF_COMMAND" value="false"/>
 | 
			
		||||
    <server name="APP_DEFAULT_DARK_MODE" value="false"/>
 | 
			
		||||
    <server name="IP_ADDRESS_PRECISION" value="4"/>
 | 
			
		||||
  </php>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -142,8 +142,7 @@ Note: This is not an exhaustive list of all libraries and projects that would be
 | 
			
		|||
* [Google Material Icons](https://github.com/google/material-design-icons) - _[Apache-2.0](https://github.com/google/material-design-icons/blob/master/LICENSE)_
 | 
			
		||||
* [markdown-it](https://github.com/markdown-it/markdown-it) and [markdown-it-task-lists](https://github.com/revin/markdown-it-task-lists) - _[MIT](https://github.com/markdown-it/markdown-it/blob/master/LICENSE) and [ISC](https://github.com/revin/markdown-it-task-lists/blob/master/LICENSE)_
 | 
			
		||||
* [Dompdf](https://github.com/dompdf/dompdf) - _[LGPL v2.1](https://github.com/dompdf/dompdf/blob/master/LICENSE.LGPL)_
 | 
			
		||||
* [BarryVD/Dompdf](https://github.com/barryvdh/laravel-dompdf) - _[MIT](https://github.com/barryvdh/laravel-dompdf/blob/master/LICENSE)_
 | 
			
		||||
* [BarryVD/Snappy (WKHTML2PDF)](https://github.com/barryvdh/laravel-snappy) - _[MIT](https://github.com/barryvdh/laravel-snappy/blob/master/LICENSE)_
 | 
			
		||||
* [KnpLabs/snappy](https://github.com/KnpLabs/snappy) - _[MIT](https://github.com/KnpLabs/snappy/blob/master/LICENSE)_
 | 
			
		||||
* [WKHTMLtoPDF](http://wkhtmltopdf.org/index.html) - _[LGPL v3.0](https://github.com/wkhtmltopdf/wkhtmltopdf/blob/master/LICENSE)_
 | 
			
		||||
* [diagrams.net](https://github.com/jgraph/drawio) - _[Embedded Version Terms](https://www.diagrams.net/trust/) / [Source Project - Apache-2.0](https://github.com/jgraph/drawio/blob/dev/LICENSE)_
 | 
			
		||||
* [OneLogin's SAML PHP Toolkit](https://github.com/onelogin/php-saml) - _[MIT](https://github.com/onelogin/php-saml/blob/master/LICENSE)_
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,8 +6,8 @@ use BookStack\Entities\Models\Book;
 | 
			
		|||
use BookStack\Entities\Models\Chapter;
 | 
			
		||||
use BookStack\Entities\Models\Page;
 | 
			
		||||
use BookStack\Entities\Tools\PdfGenerator;
 | 
			
		||||
use BookStack\Exceptions\PdfExportException;
 | 
			
		||||
use Illuminate\Support\Facades\Storage;
 | 
			
		||||
use Illuminate\Support\Str;
 | 
			
		||||
use Tests\TestCase;
 | 
			
		||||
 | 
			
		||||
class ExportTest extends TestCase
 | 
			
		||||
| 
						 | 
				
			
			@ -483,7 +483,7 @@ class ExportTest extends TestCase
 | 
			
		|||
    {
 | 
			
		||||
        $page = $this->entities->page();
 | 
			
		||||
 | 
			
		||||
        config()->set('snappy.pdf.binary', '/abc123');
 | 
			
		||||
        config()->set('exports.snappy.pdf_binary', '/abc123');
 | 
			
		||||
        config()->set('app.allow_untrusted_server_fetching', false);
 | 
			
		||||
 | 
			
		||||
        $resp = $this->asEditor()->get($page->getUrl('/export/pdf'));
 | 
			
		||||
| 
						 | 
				
			
			@ -494,6 +494,41 @@ class ExportTest extends TestCase
 | 
			
		|||
        $resp->assertStatus(500); // Bad response indicates wkhtml usage
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function test_pdf_command_option_used_if_set()
 | 
			
		||||
    {
 | 
			
		||||
        $page = $this->entities->page();
 | 
			
		||||
        $command = 'cp {input_html_path} {output_pdf_path}';
 | 
			
		||||
        config()->set('exports.pdf_command', $command);
 | 
			
		||||
 | 
			
		||||
        $resp = $this->asEditor()->get($page->getUrl('/export/pdf'));
 | 
			
		||||
        $download = $resp->getContent();
 | 
			
		||||
 | 
			
		||||
        $this->assertStringContainsString(e($page->name), $download);
 | 
			
		||||
        $this->assertStringContainsString('<html lang=', $download);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function test_pdf_command_option_errors_if_output_path_not_written_to()
 | 
			
		||||
    {
 | 
			
		||||
        $page = $this->entities->page();
 | 
			
		||||
        $command = 'echo "hi"';
 | 
			
		||||
        config()->set('exports.pdf_command', $command);
 | 
			
		||||
 | 
			
		||||
        $this->assertThrows(function () use ($page) {
 | 
			
		||||
            $this->withoutExceptionHandling()->asEditor()->get($page->getUrl('/export/pdf'));
 | 
			
		||||
        }, PdfExportException::class);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function test_pdf_command_option_errors_if_command_returns_error_status()
 | 
			
		||||
    {
 | 
			
		||||
        $page = $this->entities->page();
 | 
			
		||||
        $command = 'exit 1';
 | 
			
		||||
        config()->set('exports.pdf_command', $command);
 | 
			
		||||
 | 
			
		||||
        $this->assertThrows(function () use ($page) {
 | 
			
		||||
            $this->withoutExceptionHandling()->asEditor()->get($page->getUrl('/export/pdf'));
 | 
			
		||||
        }, PdfExportException::class);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function test_html_exports_contain_csp_meta_tag()
 | 
			
		||||
    {
 | 
			
		||||
        $entities = [
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -80,22 +80,22 @@ class ConfigTest extends TestCase
 | 
			
		|||
 | 
			
		||||
    public function test_dompdf_remote_fetching_controlled_by_allow_untrusted_server_fetching_false()
 | 
			
		||||
    {
 | 
			
		||||
        $this->checkEnvConfigResult('ALLOW_UNTRUSTED_SERVER_FETCHING', 'false', 'dompdf.options.enable_remote', false);
 | 
			
		||||
        $this->checkEnvConfigResult('ALLOW_UNTRUSTED_SERVER_FETCHING', 'true', 'dompdf.options.enable_remote', true);
 | 
			
		||||
        $this->checkEnvConfigResult('ALLOW_UNTRUSTED_SERVER_FETCHING', 'false', 'exports.dompdf.enable_remote', false);
 | 
			
		||||
        $this->checkEnvConfigResult('ALLOW_UNTRUSTED_SERVER_FETCHING', 'true', 'exports.dompdf.enable_remote', true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function test_dompdf_paper_size_options_are_limited()
 | 
			
		||||
    {
 | 
			
		||||
        $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'cat', 'dompdf.options.default_paper_size', 'a4');
 | 
			
		||||
        $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'letter', 'dompdf.options.default_paper_size', 'letter');
 | 
			
		||||
        $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'a4', 'dompdf.options.default_paper_size', 'a4');
 | 
			
		||||
        $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'cat', 'exports.dompdf.default_paper_size', 'a4');
 | 
			
		||||
        $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'letter', 'exports.dompdf.default_paper_size', 'letter');
 | 
			
		||||
        $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'a4', 'exports.dompdf.default_paper_size', 'a4');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function test_snappy_paper_size_options_are_limited()
 | 
			
		||||
    {
 | 
			
		||||
        $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'cat', 'snappy.pdf.options.page-size', 'A4');
 | 
			
		||||
        $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'letter', 'snappy.pdf.options.page-size', 'Letter');
 | 
			
		||||
        $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'a4', 'snappy.pdf.options.page-size', 'A4');
 | 
			
		||||
        $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'cat', 'exports.snappy.options.page-size', 'A4');
 | 
			
		||||
        $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'letter', 'exports.snappy.options.page-size', 'Letter');
 | 
			
		||||
        $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'a4', 'exports.snappy.options.page-size', 'A4');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function test_sendmail_command_is_configurable()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue