X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FContent%2FText%2FHTML.php;h=51515137e56ddd00f3d576e93f4998b7652bf025;hb=2b5f1f8bca010bb6972e7080c02230b04c7b61d3;hp=c3c43822ab9e6e7e09dbdf363b863f694e3e6c40;hpb=5649861fdeead495ca04f49a8af912f28482505f;p=friendica.git diff --git a/src/Content/Text/HTML.php b/src/Content/Text/HTML.php index c3c43822ab..51515137e5 100644 --- a/src/Content/Text/HTML.php +++ b/src/Content/Text/HTML.php @@ -1,6 +1,6 @@ loadHTML($message, LIBXML_HTML_NODEFDTD); XML::deleteNode($doc, 'style'); @@ -588,6 +592,10 @@ class HTML $message = mb_convert_encoding($message, 'HTML-ENTITIES', "UTF-8"); + if (empty($message)) { + return ''; + } + @$doc->loadHTML($message, LIBXML_HTML_NODEFDTD); $message = $doc->saveHTML(); @@ -597,6 +605,10 @@ class HTML // Collecting all links $urls = self::collectURLs($message); + if (empty($message)) { + return ''; + } + @$doc->loadHTML($message, LIBXML_HTML_NODEFDTD); self::tagToBBCode($doc, 'html', [], '', ''); @@ -837,7 +849,7 @@ class HTML $redir = false; if ($redirect) { - $url = Contact::magicLink($contact['url']); + $url = Contact::magicLinkByContact($contact); if (strpos($url, 'redir/') === 0) { $sparkle = ' sparkle'; } @@ -953,4 +965,69 @@ class HTML { return str_replace('&', '&', $s); } + + /** + * Clean an HTML text for potentially harmful code + * + * @param string $text + * @param array $allowedIframeDomains List of allowed iframe source domains without the scheme + * @return string + */ + public static function purify(string $text, array $allowedIframeDomains = []): string + { + // Allows cid: URL scheme + \HTMLPurifier_URISchemeRegistry::instance()->register('cid', new HTMLPurifier_URIScheme_cid()); + + $config = \HTMLPurifier_HTML5Config::createDefault(); + $config->set('HTML.Doctype', 'HTML5'); + + // Used to remove iframe with src attribute filtered out + $config->set('AutoFormat.RemoveEmpty', true); + + $config->set('HTML.SafeIframe', true); + + array_walk($allowedIframeDomains, function (&$domain) { + // Allow the domain and all its eventual sub-domains + $domain = '(?:(?!-)[A-Za-z0-9-]{1,63}(?set('URI.SafeIframeRegexp', + '%^https://(?: + ' . implode('|', $allowedIframeDomains) . ' + ) + (?:/|$) # Prevents bogus domains like youtube.com.fake.tld + %xi' + ); + + $config->set('Attr.AllowedRel', [ + 'noreferrer' => true, + 'noopener' => true, + ]); + $config->set('Attr.AllowedFrameTargets', [ + '_blank' => true, + ]); + + $config->set('AutoFormat.RemoveEmpty.Predicate', [ + 'colgroup' => [], // | + 'th' => [], // | + 'td' => [], // | + 'iframe' => ['src'], // ↳ Default HTMLPurify values + 'i' => ['class'], // Allows forkawesome icons + ]); + + // Uncomment to debug HTMLPurifier behavior + //$config->set('Core.CollectErrors', true); + //$config->set('Core.MaintainLineNumbers', true); + + $HTMLPurifier = new \HTMLPurifier($config); + + $text = $HTMLPurifier->purify($text); + + /** @var \HTMLPurifier_ErrorCollector $errorCollector */ + // Uncomment to debug HTML Purifier behavior + //$errorCollector = $HTMLPurifier->context->get('ErrorCollector'); + //var_dump($errorCollector->getRaw()); + + return $text; + } }