/** * @param array $attr * @param HTMLPurifier_Config $config * @param HTMLPurifier_Context $context * @return array */ public function transform($attr, $config, $context) { $src = true; if (!isset($attr['src'])) { if ($config->get('Core.RemoveInvalidImg')) { return $attr; } $attr['src'] = $config->get('Attr.DefaultInvalidImage'); $src = false; } if (!isset($attr['alt'])) { if ($src) { $alt = $config->get('Attr.DefaultImageAlt'); if ($alt === null) { // truncate if the alt is too long $attr['alt'] = substr(basename($attr['src']), 0, 40); } else { $attr['alt'] = $alt; } } else { $attr['alt'] = $config->get('Attr.DefaultInvalidImageAlt'); } } return $attr; }
/** * Factory method that creates a cache object based on configuration * @param string $type Name of definitions handled by cache * @param HTMLPurifier_Config $config Config instance * @return mixed */ public function create($type, $config) { $method = $config->get('Cache.DefinitionImpl'); if ($method === null) { return new HTMLPurifier_DefinitionCache_Null($type); } if (!empty($this->caches[$method][$type])) { return $this->caches[$method][$type]; } if (isset($this->implementations[$method]) && class_exists($class = $this->implementations[$method], false)) { $cache = new $class($type); } else { if ($method != 'Serializer') { trigger_error("Unrecognized DefinitionCache {$method}, using Serializer instead", E_USER_WARNING); } $cache = new HTMLPurifier_DefinitionCache_Serializer($type); } foreach ($this->decorators as $decorator) { $new_cache = $decorator->decorate($cache); // prevent infinite recursion in PHP 4 unset($cache); $cache = $new_cache; } $this->caches[$method][$type] = $cache; return $this->caches[$method][$type]; }
/** * @param string $string * @param HTMLPurifier_Config $config * @param HTMLPurifier_Context $context * @return bool|string */ public function validate($string, $config, $context) { if ($this->valid_values === false) { $this->valid_values = $config->get('Attr.AllowedFrameTargets'); } return parent::validate($string, $config, $context); }
/** * @param HTMLPurifier_Config $config * @return void */ public function prepare($config) { $our_host = $config->getDefinition('URI')->host; if ($our_host !== null) { $this->ourHostParts = array_reverse(explode('.', $our_host)); } }
/** * @param HTMLPurifier_URI $uri * @param HTMLPurifier_Config $config * @param HTMLPurifier_Context $context * @return bool */ public function filter(&$uri, $config, $context) { // check if filter not applicable if (!$config->get('HTML.SafeIframe')) { return true; } // check if the filter should actually trigger if (!$context->get('EmbeddedURI', true)) { return true; } $token = $context->get('CurrentToken', true); if (!($token && $token->name == 'iframe')) { return true; } // check if we actually have some whitelists enabled if ($this->regexp === null) { return false; } // actually check the whitelists if (!preg_match($this->regexp, $uri->toString())) { return false; } // Make sure that if we're an HTTPS site, the iframe is also HTTPS if (is_https() && $uri->scheme == 'http') { // Convert it to a protocol-relative URL $uri->scheme = null; } return $uri; }
/** * @param HTMLPurifier_Config $config */ public function __construct($config) { $def = $config->getCSSDefinition(); $this->info['border-width'] = $def->info['border-width']; $this->info['border-style'] = $def->info['border-style']; $this->info['border-top-color'] = $def->info['border-top-color']; }
/** * @param HTMLPurifier_Config $config */ public function setup($config) { if ($config->get('HTML.SafeIframe')) { $this->safe = true; } $this->addElement('iframe', 'Inline', 'Flow', 'Common', array('src' => 'URI#embedded', 'width' => 'Length', 'height' => 'Length', 'name' => 'ID', 'scrolling' => 'Enum#yes,no,auto', 'frameborder' => 'Enum#0,1', 'longdesc' => 'URI', 'marginheight' => 'Pixels', 'marginwidth' => 'Pixels')); }
/** * @param HTMLPurifier_Config $config */ public function __construct($config) { $def = $config->getCSSDefinition(); $this->info['list-style-type'] = $def->info['list-style-type']; $this->info['list-style-position'] = $def->info['list-style-position']; $this->info['list-style-image'] = $def->info['list-style-image']; }
/** * @param string $string * @param HTMLPurifier_Config $config * @param HTMLPurifier_Context $context * @return bool|string */ public function validate($string, $config, $context) { static $colors = null; if ($colors === null) { $colors = $config->get('Core.ColorKeywords'); } $string = trim($string); if (empty($string)) { return false; } $lower = strtolower($string); if (isset($colors[$lower])) { return $colors[$lower]; } if ($string[0] === '#') { $hex = substr($string, 1); } else { $hex = $string; } $length = strlen($hex); if ($length !== 3 && $length !== 6) { return false; } if (!ctype_xdigit($hex)) { return false; } if ($length === 3) { $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2]; } return "#{$hex}"; }
/** * Public interface for validating components of a URI. Performs a * bunch of default actions. Don't overload this method. * @param HTMLPurifier_URI $uri Reference to a HTMLPurifier_URI object * @param HTMLPurifier_Config $config * @param HTMLPurifier_Context $context * @return bool success or failure */ public function validate(&$uri, $config, $context) { if ($this->default_port == $uri->port) { $uri->port = null; } // kludge: browsers do funny things when the scheme but not the // authority is set if (!$this->may_omit_host && (!is_null($uri->scheme) && ($uri->host === '' || is_null($uri->host))) || is_null($uri->scheme) && $uri->host === '') { do { if (is_null($uri->scheme)) { if (substr($uri->path, 0, 2) != '//') { $uri->host = null; break; } // URI is '////path', so we cannot nullify the // host to preserve semantics. Try expanding the // hostname instead (fall through) } // first see if we can manually insert a hostname $host = $config->get('URI.Host'); if (!is_null($host)) { $uri->host = $host; } else { // we can't do anything sensible, reject the URL. return false; } } while (false); } return $this->doValidate($uri, $config, $context); }
/** * @param array $attr * @param HTMLPurifier_Config $config * @param HTMLPurifier_Context $context * @return array */ public function transform($attr, $config, $context) { if (isset($attr['dir'])) { return $attr; } $attr['dir'] = $config->get('Attr.DefaultTextDir'); return $attr; }
/** * @param HTMLPurifier_Config $config */ public function setup($config) { // These definitions are not intrinsically safe: the attribute transforms // are a vital part of ensuring safety. $allowed = $config->get('HTML.SafeScripting'); $script = $this->addElement('script', 'Inline', 'Empty', null, array('type' => 'Enum#application/javascript', 'src*' => new HTMLPurifier_AttrDef_Enum(array_keys($allowed)))); $script->attr_transform_pre[] = $script->attr_transform_post[] = new HTMLPurifier_AttrTransform_ScriptRequired(); }
/** * @param HTMLPurifier_Config $config */ public function __construct($config) { $def = $config->getCSSDefinition(); $this->info['background-color'] = $def->info['background-color']; $this->info['background-image'] = $def->info['background-image']; $this->info['background-repeat'] = $def->info['background-repeat']; $this->info['background-attachment'] = $def->info['background-attachment']; $this->info['background-position'] = $def->info['background-position']; }
/** * @param HTMLPurifier_Config $config */ public function __construct($config) { $def = $config->getCSSDefinition(); $this->info['font-style'] = $def->info['font-style']; $this->info['font-variant'] = $def->info['font-variant']; $this->info['font-weight'] = $def->info['font-weight']; $this->info['font-size'] = $def->info['font-size']; $this->info['line-height'] = $def->info['line-height']; $this->info['font-family'] = $def->info['font-family']; }
/** * @param HTMLPurifier_Config $config */ public function setup($config) { $max = $config->get('HTML.MaxImgLength'); $img = $this->addElement('img', 'Inline', 'Empty', 'Common', array('alt*' => 'Text', 'height' => 'Pixels#' . $max, 'width' => 'Pixels#' . $max, 'longdesc' => 'URI', 'src*' => new HTMLPurifier_AttrDef_URI(true))); if ($max === null || $config->get('HTML.Trusted')) { $img->attr['height'] = $img->attr['width'] = 'Length'; } // kind of strange, but splitting things up would be inefficient $img->attr_transform_pre[] = $img->attr_transform_post[] = new HTMLPurifier_AttrTransform_ImgRequired(); }
/** * @param HTMLPurifier_Config $config */ public function setup($config) { // These definitions are not intrinsically safe: the attribute transforms // are a vital part of ensuring safety. $max = $config->get('HTML.MaxImgLength'); $object = $this->addElement('object', 'Inline', 'Optional: param | Flow | #PCDATA', 'Common', array('type' => 'Enum#application/x-shockwave-flash', 'width' => 'Pixels#' . $max, 'height' => 'Pixels#' . $max, 'data' => 'URI#embedded', 'codebase' => new HTMLPurifier_AttrDef_Enum(array('http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0')))); $object->attr_transform_post[] = new HTMLPurifier_AttrTransform_SafeObject(); $param = $this->addElement('param', false, 'Empty', false, array('id' => 'ID', 'name*' => 'Text', 'value' => 'Text')); $param->attr_transform_post[] = new HTMLPurifier_AttrTransform_SafeParam(); $this->info_injector[] = 'SafeObject'; }
/** * @param HTMLPurifier_Config $config */ public function setup($config) { $elements = array('a', 'applet', 'form', 'frame', 'iframe', 'img', 'map'); foreach ($elements as $name) { $element = $this->addBlankElement($name); $element->attr['name'] = 'CDATA'; if (!$config->get('HTML.Attr.Name.UseCDATA')) { $element->attr_transform_post[] = new HTMLPurifier_AttrTransform_NameSync(); } } }
/** * @return \HTMLPurifier_Config */ protected function get_config() { if (is_null($this->config)) { $this->config = \HTMLPurifier_Config::createDefault(); $this->config->set('HTML.Doctype', 'HTML 4.01 Transitional'); $this->config->set('HTML.AllowedAttributes', array('a.href', 'a.target', 'img.src', '*.class')); $this->config->set('Attr.AllowedFrameTargets', array('_blank')); $this->config->set('HTML.Allowed', 'a,abbr,acronym,b,blockquote,cite,code,dd,div,dl,dt,em,i,li,ol,p,pre,s,span,strike,strong,sub,sup,table,tbody,td,tfoot,th,thead,tr,tt,u,ul'); } return $this->config; }
/** * @param HTMLPurifier_Config $config * @return bool */ public function prepare($config) { $this->target = $config->get('URI.' . $this->name); $this->parser = new HTMLPurifier_URIParser(); $this->doEmbed = $config->get('URI.MungeResources'); $this->secretKey = $config->get('URI.MungeSecretKey'); if ($this->secretKey && !function_exists('hash_hmac')) { throw new Exception("Cannot use %URI.MungeSecretKey without hash_hmac support."); } return true; }
/** * @param array $children * @param HTMLPurifier_Config $config * @param HTMLPurifier_Context $context * @return array */ public function validateChildren($children, $config, $context) { // Flag for subclasses $this->whitespace = false; // if there are no tokens, delete parent node if (empty($children)) { return false; } // if li is not allowed, delete parent node if (!isset($config->getHTMLDefinition()->info['li'])) { trigger_error("Cannot allow ul/ol without allowing li", E_USER_WARNING); return false; } // the new set of children $result = array(); // a little sanity check to make sure it's not ALL whitespace $all_whitespace = true; $current_li = false; foreach ($children as $node) { if (!empty($node->is_whitespace)) { $result[] = $node; continue; } $all_whitespace = false; // phew, we're not talking about whitespace if ($node->name === 'li') { // good $current_li = $node; $result[] = $node; } else { // we want to tuck this into the previous li // Invariant: we expect the node to be ol/ul // ToDo: Make this more robust in the case of not ol/ul // by distinguishing between existing li and li created // to handle non-list elements; non-list elements should // not be appended to an existing li; only li created // for non-list. This distinction is not currently made. if ($current_li === false) { $current_li = new HTMLPurifier_Node_Element('li'); $result[] = $current_li; } $current_li->children[] = $node; $current_li->empty = false; // XXX fascinating! Check for this error elsewhere ToDo } } if (empty($result)) { return false; } if ($all_whitespace) { return false; } return $result; }
/** * @param array $tokens * @param HTMLPurifier_Config $config * @param HTMLPurifier_Context $context * @return array */ protected function filter($tokens, $config, $context) { $allowed = $config->get('Attr.AllowedClasses'); $forbidden = $config->get('Attr.ForbiddenClasses'); $ret = array(); foreach ($tokens as $token) { if (($allowed === null || isset($allowed[$token])) && !isset($forbidden[$token]) && !in_array($token, $ret, true)) { $ret[] = $token; } } return $ret; }
/** * @param string $uri * @param HTMLPurifier_Config $config * @param HTMLPurifier_Context $context * @return bool|string */ public function validate($uri, $config, $context) { if ($config->get('URI.Disable')) { return false; } $uri = $this->parseCDATA($uri); // parse the URI $uri = $this->parser->parse($uri); if ($uri === false) { return false; } // add embedded flag to context for validators $context->register('EmbeddedURI', $this->embedsResource); $ok = false; do { // generic validation $result = $uri->validate($config, $context); if (!$result) { break; } // chained filtering $uri_def = $config->getDefinition('URI'); $result = $uri_def->filter($uri, $config, $context); if (!$result) { break; } // scheme-specific validation $scheme_obj = $uri->getSchemeObj($config, $context); if (!$scheme_obj) { break; } if ($this->embedsResource && !$scheme_obj->browsable) { break; } $result = $scheme_obj->validate($uri, $config, $context); if (!$result) { break; } // Post chained filtering $result = $uri_def->postFilter($uri, $config, $context); if (!$result) { break; } // survived gauntlet $ok = true; } while (false); $context->destroy('EmbeddedURI'); if (!$ok) { return false; } // back to string return $uri->toString(); }
/** * @param array $attr * @param HTMLPurifier_Config $config * @param HTMLPurifier_Context $context * @return array */ public function transform($attr, $config, $context) { $attr['allowscriptaccess'] = 'never'; $attr['allownetworking'] = 'internal'; $attr['type'] = 'application/x-shockwave-flash'; // Added by Ivan Tcholakov, 24-DEC-2013. if (!$config->get('HTML.FlashAllowFullScreen') || !$attr['allowfullscreen'] == 'true') { unset($attr['allowfullscreen']); // if omitted, assume to be 'false' } // return $attr; }
/** * @param HTMLPurifier_Config $config * @return string */ public function render($config) { $ret = ''; $this->config =& $config; $this->def = $config->getHTMLDefinition(); $ret .= $this->start('div', array('class' => 'HTMLPurifier_Printer')); $ret .= $this->renderDoctype(); $ret .= $this->renderEnvironment(); $ret .= $this->renderContentSets(); $ret .= $this->renderInfo(); $ret .= $this->end('div'); return $ret; }
/** * @param array $attr * @param HTMLPurifier_Config $config * @param HTMLPurifier_Context $context * @return array */ public function transform($attr, $config, $context) { // If we add support for other objects, we'll need to alter the // transforms. switch ($attr['name']) { // application/x-shockwave-flash // Keep this synchronized with Injector/SafeObject.php case 'allowScriptAccess': // Added by Ivan Tcholakov, 24-DEC-2013. // Added by Ivan Tcholakov, 24-DEC-2013. case 'allowscriptaccess': // $attr['value'] = 'never'; break; case 'allowNetworking': // Added by Ivan Tcholakov, 24-DEC-2013. // Added by Ivan Tcholakov, 24-DEC-2013. case 'allownetworking': // $attr['value'] = 'internal'; break; case 'allowFullScreen': // Added by Ivan Tcholakov, 24-DEC-2013. // Added by Ivan Tcholakov, 24-DEC-2013. case 'allowfullscreen': // if ($config->get('HTML.FlashAllowFullScreen')) { $attr['value'] = $attr['value'] == 'true' ? 'true' : 'false'; } else { $attr['value'] = 'false'; } break; case 'wmode': $attr['value'] = $this->wmode->validate($attr['value'], $config, $context); break; case 'movie': case 'src': $attr['name'] = "movie"; $attr['value'] = $this->uri->validate($attr['value'], $config, $context); break; case 'flashvars': // we're going to allow arbitrary inputs to the SWF, on // the reasoning that it could only hack the SWF, not us. break; // add other cases to support other param name/value pairs // add other cases to support other param name/value pairs default: $attr['name'] = $attr['value'] = null; } return $attr; }
public function setUp() { $config = \HTMLPurifier_Config::createDefault(); $this->config = $this->getMockBuilder('\\HTMLPurifier_Config')->disableOriginalConstructor()->getMock(); $this->config->expects($this->atLeastOnce())->method('set')->with('Cache.SerializerPath', '/tmp'); $this->config->expects($this->any())->method('getHTMLDefinition')->will($this->returnValue($config->getHTMLDefinition())); $this->config->expects($this->any())->method('get')->will($this->returnCallback(function ($argument) { $config = \HTMLPurifier_Config::createDefault(); return $config->get($argument); })); $this->config->expects($this->any())->method('getBatch')->will($this->returnCallback(function ($argument) { $config = \HTMLPurifier_Config::createDefault(); return $config->getBatch($argument); })); }
/** * Build new instance * @param type $config * @return */ public static function setInstance($config = null) { if (is_null($config)) { $config = HTMLPurifier_Config::createDefault(); } self::$_instance = new HTMLPurifier($config); }
/** * clean the comment text field from html, in order to use it as submitted text * uses the htmlpurifier library, or a simple strip_tags call, based on the app.yml config file * * @return String * @param String - the text to be cleaned * * @author Guglielmo Celata * @see http://htmlpurifier.org/ **/ public static function clean($text) { $allowed_html_tags = sfConfig::get('app_deppPropelActAsCommentableBehaviorPlugin_allowed_tags', array()); $use_htmlpurifier = sfConfig::get('app_deppPropelActAsCommentableBehaviorPlugin_use_htmlpurifier', false); if ($use_htmlpurifier) { $htmlpurifier_path = sfConfig::get('app_deppPropelActAsCommentableBehaviorPlugin_htmlpurifier_path', SF_ROOT_DIR . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'htmlpurifier' . DIRECTORY_SEPARATOR . 'library' . DIRECTORY_SEPARATOR); require_once $htmlpurifier_path . 'HTMLPurifier.auto.php'; $config = HTMLPurifier_Config::createDefault(); $config->set('HTML', 'Doctype', 'XHTML 1.0 Strict'); $config->set('HTML', 'Allowed', implode(',', array_keys($allowed_html_tags))); if (isset($allowed_html_tags['a'])) { $config->set('HTML', 'AllowedAttributes', 'a.href'); $config->set('AutoFormat', 'Linkify', true); } if (isset($allowed_html_tags['p'])) { $config->set('AutoFormat', 'AutoParagraph', true); } $purifier = new HTMLPurifier($config); $clean_text = $purifier->purify($text); } else { $allowed_html_tags_as_string = ""; foreach ($allowed_html_tags as $tag) { $allowed_html_tags_as_string .= "{$tag}"; } $clean_text = strip_tags($text, $allowed_html_tags_as_string); } return $clean_text; }
function execute() { // HTMLPurifier runs with PHP5 only if (version_compare(PHP_VERSION, '5.0.0') < 0) { die('Turn postcommon_post_htmlpurify4everyone.php off because this filter cannot run with PHP4'); } /* if ( file_exists( XOOPS_ROOT_PATH.'/class/icms.htmlpurifier.php' ) ) { // use HTMLPurifier inside ImpressCMS if ( ! class_exists( 'icms_HTMLPurifier' ) ) { require_once ICMS_ROOT_PATH.'/class/icms.htmlpurifier.php' ; } // $pure =& icms_HTMLPurifier::getPurifierInstance() ; // $_POST = $pure->icms_html_purifier( $_POST , 'protector' ) ; $this->purifier =& icms_HTMLPurifier::getPurifierInstance() ; $this->method = 'icms_html_purifier' ; } else { */ // use HTMLPurifier inside Protector require_once dirname(dirname(__FILE__)) . '/library/HTMLPurifier.auto.php'; $config = HTMLPurifier_Config::createDefault(); $config->set('Cache', 'SerializerPath', XOOPS_TRUST_PATH . '/modules/protector/configs'); $config->set('Core', 'Encoding', _CHARSET); //$config->set('HTML', 'Doctype', 'HTML 4.01 Transitional'); $this->purifier = new HTMLPurifier($config); $this->method = 'purify'; // } $_POST = $this->purify_recursive($_POST); }
function test() { generate_mock_once('HTMLPurifier_URIScheme'); $config = HTMLPurifier_Config::create(array('URI.AllowedSchemes' => 'http, telnet', 'URI.OverrideAllowedSchemes' => true)); $context = new HTMLPurifier_Context(); $registry = new HTMLPurifier_URISchemeRegistry(); $this->assertIsA($registry->getScheme('http', $config, $context), 'HTMLPurifier_URIScheme_http'); $scheme_http = new HTMLPurifier_URISchemeMock(); $scheme_telnet = new HTMLPurifier_URISchemeMock(); $scheme_foobar = new HTMLPurifier_URISchemeMock(); // register a new scheme $registry->register('telnet', $scheme_telnet); $this->assertIdentical($registry->getScheme('telnet', $config, $context), $scheme_telnet); // overload a scheme, this is FINAL (forget about defaults) $registry->register('http', $scheme_http); $this->assertIdentical($registry->getScheme('http', $config, $context), $scheme_http); // when we register a scheme, it's automatically allowed $registry->register('foobar', $scheme_foobar); $this->assertIdentical($registry->getScheme('foobar', $config, $context), $scheme_foobar); // now, test when overriding is not allowed $config = HTMLPurifier_Config::create(array('URI.AllowedSchemes' => 'http, telnet', 'URI.OverrideAllowedSchemes' => false)); $this->assertNull($registry->getScheme('foobar', $config, $context)); // scheme not allowed and never registered $this->assertNull($registry->getScheme('ftp', $config, $context)); }