| 
									
										
										
										
											2021-09-04 06:32:42 +08:00
										 |  |  | <?php | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace BookStack\Util; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | use DOMElement; | 
					
						
							|  |  |  | use DOMNodeList; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class HtmlNonceApplicator | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-11-14 23:46:32 +08:00
										 |  |  |     protected static string $placeholder = '[CSP_NONCE_VALUE]'; | 
					
						
							| 
									
										
										
										
											2021-09-04 20:57:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-04 06:32:42 +08:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2021-09-04 20:57:04 +08:00
										 |  |  |      * Prepare the given HTML content with nonce attributes including a placeholder | 
					
						
							|  |  |  |      * value which we can target later. | 
					
						
							| 
									
										
										
										
											2021-09-04 06:32:42 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-09-04 20:57:04 +08:00
										 |  |  |     public static function prepare(string $html): string | 
					
						
							| 
									
										
										
										
											2021-09-04 06:32:42 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         if (empty($html)) { | 
					
						
							|  |  |  |             return $html; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-14 23:46:32 +08:00
										 |  |  |         // LIBXML_SCHEMA_CREATE was found to be required here otherwise
 | 
					
						
							|  |  |  |         // the PHP DOMDocument handling will attempt to format/close
 | 
					
						
							|  |  |  |         // HTML tags within scripts and therefore change JS content.
 | 
					
						
							|  |  |  |         $doc = new HtmlDocument($html, LIBXML_SCHEMA_CREATE); | 
					
						
							| 
									
										
										
										
											2021-09-04 06:32:42 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // Apply to scripts
 | 
					
						
							| 
									
										
										
										
											2023-11-14 23:46:32 +08:00
										 |  |  |         $scriptElems = $doc->queryXPath('//script'); | 
					
						
							| 
									
										
										
										
											2021-09-04 20:57:04 +08:00
										 |  |  |         static::addNonceAttributes($scriptElems, static::$placeholder); | 
					
						
							| 
									
										
										
										
											2021-09-04 06:32:42 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // Apply to styles
 | 
					
						
							| 
									
										
										
										
											2023-11-14 23:46:32 +08:00
										 |  |  |         $styleElems = $doc->queryXPath('//style'); | 
					
						
							| 
									
										
										
										
											2021-09-04 20:57:04 +08:00
										 |  |  |         static::addNonceAttributes($styleElems, static::$placeholder); | 
					
						
							| 
									
										
										
										
											2021-09-04 06:32:42 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-14 23:46:32 +08:00
										 |  |  |         return $doc->getBodyInnerHtml(); | 
					
						
							| 
									
										
										
										
											2021-09-04 06:32:42 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-04 20:57:04 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Apply the give nonce value to the given prepared HTML. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public static function apply(string $html, string $nonce): string | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return str_replace(static::$placeholder, $nonce, $html); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     protected static function addNonceAttributes(DOMNodeList $nodes, string $attrValue): void | 
					
						
							| 
									
										
										
										
											2021-09-04 06:32:42 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         /** @var DOMElement $node */ | 
					
						
							|  |  |  |         foreach ($nodes as $node) { | 
					
						
							| 
									
										
										
										
											2021-09-04 20:57:04 +08:00
										 |  |  |             $node->setAttribute('nonce', $attrValue); | 
					
						
							| 
									
										
										
										
											2021-09-04 06:32:42 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |