ezyang / htmlpurifier

Standards compliant HTML filter written in PHP
http://htmlpurifier.org
GNU Lesser General Public License v2.1
3.03k stars 323 forks source link

How to allow google fonts ? #325

Closed netsevdam closed 2 years ago

netsevdam commented 2 years ago

Hi guys, I am having problem with allowing google fonts by url, I allowed fonts CSS.AllowedProperties and set $config->set('CSS.MaxImgLength', NULL);. I have tried many other solutions over 3 hours but couldnt make is work.

These are the urls I want to allow :

<link href="https://fonts.googleapis.com/css?family=Roboto+Condensed:300,400,700&display=swap&subset=cyrillic,cyrillic-ext,greek,greek-ext,latin-ext,vietnamese" rel="stylesheet">

<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700&display=swap" rel="stylesheet">

I know you guys have tons of works to do, I wouldn't not ask this question if I could solve it.

Here is my full setup

  function strTrim($dirty_html, $config = FALSE){
     require_once('ThirdParty/HTMLPurifier/library/HTMLPurifier.auto.php');
     if (is_array($dirty_html)) {
        foreach ($dirty_html as $key => $val) {
            $clean_html[$key] = strTrim($val, $config);
        }
     } else {
        $config = HTMLPurifier_Config::createDefault();
        $config->set('Core.Encoding', 'utf-8');
        $config->set("AutoFormat.AutoParagraph", false);
        $config->set("Core.NormalizeNewlines", true);
        $config->set('HTML.Allowed', 'iframe[src|title|frameborder|allowfullscreen|class|width|height],p,b,strong,a[href|title],abbr[title],blockquote[cite],code,pre[class],em,i,strike,u,s,sub,sup,ol,ul,li,hr,img[title|alt|src|class|style],h1,h2,h3,h4,h5,h6,object[width|height|data],param[name|value],embed[src|type|allowscriptaccess|width|height],br,*[style]');
        $config->set('CSS.AllowedProperties', 'font,font-size,font-weight,font-style,font-family,text-decoration,margin-left,margin-right,float,color,background-color,text-align,width,max-width,padding-left,border');
        $config->set('HTML.MaxImgLength', NULL);
        $config->set('CSS.MaxImgLength', NULL);
        $config->set('HTML.SafeObject', true);
        $config->set('HTML.SafeEmbed', true);
        $config->set('Output.FlashCompat', true);
        $config->set('AutoFormat.RemoveEmpty', true);
        $config->set('AutoFormat.RemoveEmpty.RemoveNbsp', true);
        $config->set('HTML.SafeIframe', true);
        $config->set('URI.SafeIframeRegexp', '%^//(www.youtube(?:-nocookie)?.com/embed/|player.vimeo.com/video/)%');
        $def = $config->getHTMLDefinition(true);
        $def->addAttribute('iframe','allowfullscreen', 'Bool');
        $purifier = new HTMLPurifier($config);
        $clean_html = $purifier->purify($dirty_html);
     }
     return $clean_html;
  }

Thanks for any help.

peterdd commented 2 years ago

Quick shot in the blue: link tag is missing in HTML.Allowed configuration.

netsevdam commented 2 years ago

stylesheet

Thank you for the answer, I tried that and now I am facing to Cannot retrieve undefined attribute type link

Here is setup : $config->set('HTML.Allowed', 'link[href|rel]'); $config->set('CSS.AllowedProperties', 'stylesheet'); $def->addAttribute('iframe','allowfullscreen', 'Bool');

@peterdd

peterdd commented 2 years ago

link is a tag, not an attribute of the iframe tag. Check also for correct ' in your examples.

netsevdam commented 2 years ago

link is a tag, not an attribute of the iframe tag. Check also for correct ' in your examples. Sorry I shortened code that is why ' was missed.

I corrected it now, still getting Element 'link' is not supported (for information on implementing this, see the support forums) error.

bytestream commented 2 years ago

As noted in the error, link isn't supported. https://packagist.org/packages/xemlock/htmlpurifier-html5 implements a link element definition.

peterdd commented 2 years ago

Played a bit and adapted from http://htmlpurifier.org/docs/enduser-customize.html

<?php

require_once 'htmlpurifier-4.14.0/library/HTMLPurifier.auto.php';

$config = HTMLPurifier_Config::createDefault();
#$config->set('HTML.DefinitionID', 'enduser-customize.html tutorial');
#$config->set('HTML.DefinitionRev', 1);
#$config->set('Cache.DefinitionImpl', null); // remove this later!
$def = $config->getHTMLDefinition(true);
$link = $def->addElement(
  'link',   // name
  'Block',  // content set
  'Empty', // no children
  'Common', // attribute collection
  array( // attributes
    'href*' => 'URI',
    'rel*' => 'Enum#stylesheet'
  )
);
$link->excludes = array('link' => true);

$purifier = new HTMLPurifier($config);

$dirty_html='
<link rel="invalid">
<link href="https://fonts.googleapis.com/css?family=Roboto+Condensed:300,400,700&display=swap&subset=cyrillic,cyrillic-ext,greek,greek-ext,latin-ext,vietnamese" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700&display=swap" rel="stylesheet">
<p>Blabla</p>';

echo "dirty:\n".$dirty_html;
$clean_html = $purifier->purify($dirty_html);

echo "\n\nclean:\n".$clean_html."\n";

Run:

php htmlpurifier_addelement.php 
dirty:

<link rel="invalid">
<link href="https://fonts.googleapis.com/css?family=Roboto+Condensed:300,400,700&display=swap&subset=cyrillic,cyrillic-ext,greek,greek-ext,latin-ext,vietnamese" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700&display=swap" rel="stylesheet">
<p>Blabla</p>

clean:

<link href="https://fonts.googleapis.com/css?family=Roboto+Condensed:300,400,700&amp;display=swap&amp;subset=cyrillic,cyrillic-ext,greek,greek-ext,latin-ext,vietnamese" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700&amp;display=swap" rel="stylesheet" />
<p>Blabla</p>

Probably you want to further restrict the URI part, so only the font files from google are allowed. http://htmlpurifier.org/docs/enduser-uri-filter.html

netsevdam commented 2 years ago

@peterdd you are an awesome person, thank you so much.

Last and a simple question :

I want to filter inputs both side, when inserting and selecting but Htmlpurifier converts & to amp;. I want to know if there is a way to prevent converting & to amp; ?

Here is my latest complete setup, if someone need it.

  function html_pruify($dirty_html, $config = FALSE){
     require_once('ThirdParty/HTMLPurifier/library/HTMLPurifier.auto.php');
     if (is_array($dirty_html)) {
        foreach ($dirty_html as $key => $val) {
            $clean_html[$key] = html_pruify($val, $config);
        }
     } else {
        $config = HTMLPurifier_Config::createDefault();
        $config->set('Core.Encoding', 'UTF-8');
        $config->set('URI.AllowedSchemes', array(
                                                  'http' => true,
                                                  'https' => true,
                                                  'mailto' => true,
                                                  'ftp' => true,
                                                  'nntp' => true,
                                                  'news' => true,
                                                  'tel' => true,
                                                  'data' => true
                                                ));
        $config->set("AutoFormat.AutoParagraph", false);
        $config->set("Core.NormalizeNewlines", true);
        $config->set('HTML.Allowed', 'link[href|rel],iframe[src|title|frameborder|allowfullscreen|class|width|height],p,b,strong,a[href|title],abbr[title],blockquote[cite],code,pre[class],em,i,strike,u,s,sub,sup,ol,ul,li,hr,img[title|alt|src|class|style],h1,h2,h3,h4,h5,h6,object[width|height|data],param[name|value],embed[src|type|allowscriptaccess|width|height],br,*[style]');
        $config->set('CSS.AllowedProperties', 'font,font-size,font-weight,font-style,font-family,text-decoration,float,color,background-color,text-align,width,max-width,padding,padding-left,padding-right,margin,margin-left,margin-right,border');
        $config->set('HTML.MaxImgLength', NULL);
        $config->set('CSS.MaxImgLength', NULL);
        $config->set('HTML.SafeObject', true);
        $config->set('HTML.SafeEmbed', true);
        $config->set('Output.FlashCompat', true);
        $config->set('AutoFormat.RemoveEmpty', true);
        $config->set('AutoFormat.RemoveEmpty.RemoveNbsp', true);
        $config->set('AutoFormat.Linkify', TRUE);
        $config->set('HTML.SafeIframe', true);
        $config->set('URI.SafeIframeRegexp', '%^//(www.youtube(?:-nocookie)?.com/embed/|player.vimeo.com/video/)%');
        $def = $config->getHTMLDefinition(true);
        if ($def) {
          $link = $def->addElement(
            'link',
            'Block',
            'Empty',
            'Common',
            array( 
              'href*' => 'URI',
              'rel*' => 'Enum#stylesheet'
            )
          );
          $link->excludes = array('link' => true);
          $def->addElement(
              'iframe',
              'Inline',
              'Flow',
              'Common',
              [
                  'src'                   => 'URI#embedded',
                  'width'                 => 'Length',
                  'height'                => 'Length',
                  'name'                  => 'ID',
                  'scrolling'             => 'Enum#yes,no,auto',
                  'frameborder'           => 'Enum#0,1',
                  'allow'                 => 'Text',
                  'allowfullscreen'       => 'Bool',
                  'webkitallowfullscreen' => 'Bool',
                  'mozallowfullscreen'    => 'Bool',
                  'longdesc'              => 'URI',
                  'marginheight'          => 'Pixels',
                  'marginwidth'           => 'Pixels',
              ]
          );
        }
        $purifier = new HTMLPurifier($config);
        $clean_html = $purifier->purify($dirty_html);
     }
     return $clean_html;
  }