1<?php 2 3/** 4 * webtrees: online genealogy 5 * Copyright (C) 2019 webtrees development team 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18declare(strict_types=1); 19 20namespace Fisharebest\Webtrees\Services; 21 22use HTMLPurifier; 23use HTMLPurifier_AttrDef_Enum; 24use HTMLPurifier_Config; 25use HTMLPurifier_HTMLDefinition; 26 27use function assert; 28 29/** 30 * Filter/sanitize HTML 31 */ 32class HtmlService 33{ 34 /** 35 * Take some dirty HTML (as provided by the user), and clean it before 36 * we save/display it. 37 * 38 * @param string $html 39 * 40 * @return string 41 */ 42 public function sanitize(string $html): string 43 { 44 $config = HTMLPurifier_Config::createDefault(); 45 46 $config->set('Cache.DefinitionImpl', null); 47 48 $config->set('HTML.TidyLevel', 'none'); // Only XSS cleaning now 49 50 // Remove the default maximum width/height for images. This enables percentage values. 51 $config->set('CSS.MaxImgLength', null); 52 53 $def = $config->getHTMLDefinition(true); 54 assert($def instanceof HTMLPurifier_HTMLDefinition); 55 56 // Allow link targets. 57 $def->addAttribute('a', 'target', new HTMLPurifier_AttrDef_Enum(['_blank', '_self', '_target', '_top'])); 58 59 // Allow image maps. 60 $def->addAttribute('img', 'usemap', 'CDATA'); 61 62 $map = $def->addElement('map', 'Block', 'Flow', 'Common', [ 63 'name' => 'CDATA', 64 'id' => 'ID', 65 'title' => 'CDATA', 66 ]); 67 68 $map->excludes = ['map' => true]; 69 70 $area = $def->addElement('area', 'Block', 'Empty', 'Common', [ 71 'name' => 'CDATA', 72 'id' => 'ID', 73 'alt' => 'Text', 74 'coords' => 'CDATA', 75 'accesskey' => 'Character', 76 'nohref' => new HTMLPurifier_AttrDef_Enum(['nohref']), 77 'href' => 'URI', 78 'shape' => new HTMLPurifier_AttrDef_Enum(['rect', 'circle', 'poly', 'default']), 79 'tabindex' => 'Number', 80 ]); 81 82 $area->excludes = ['area' => true]; 83 84 $purifier = new HTMLPurifier($config); 85 86 return $purifier->purify($html); 87 } 88} 89