]> BookStack Code Mirror - bookstack/blob - app/Util/HtmlNonceApplicator.php
Comments: Added HTML filter test, fixed placeholder in dark mode
[bookstack] / app / Util / HtmlNonceApplicator.php
1 <?php
2
3 namespace BookStack\Util;
4
5 use DOMElement;
6 use DOMNodeList;
7
8 class HtmlNonceApplicator
9 {
10     protected static string $placeholder = '[CSP_NONCE_VALUE]';
11
12     /**
13      * Prepare the given HTML content with nonce attributes including a placeholder
14      * value which we can target later.
15      */
16     public static function prepare(string $html): string
17     {
18         if (empty($html)) {
19             return $html;
20         }
21
22         // LIBXML_SCHEMA_CREATE was found to be required here otherwise
23         // the PHP DOMDocument handling will attempt to format/close
24         // HTML tags within scripts and therefore change JS content.
25         $doc = new HtmlDocument($html, LIBXML_SCHEMA_CREATE);
26
27         // Apply to scripts
28         $scriptElems = $doc->queryXPath('//script');
29         static::addNonceAttributes($scriptElems, static::$placeholder);
30
31         // Apply to styles
32         $styleElems = $doc->queryXPath('//style');
33         static::addNonceAttributes($styleElems, static::$placeholder);
34
35         return $doc->getBodyInnerHtml();
36     }
37
38     /**
39      * Apply the give nonce value to the given prepared HTML.
40      */
41     public static function apply(string $html, string $nonce): string
42     {
43         return str_replace(static::$placeholder, $nonce, $html);
44     }
45
46     protected static function addNonceAttributes(DOMNodeList $nodes, string $attrValue): void
47     {
48         /** @var DOMElement $node */
49         foreach ($nodes as $node) {
50             $node->setAttribute('nonce', $attrValue);
51         }
52     }
53 }