Commit f4cd8d19 authored by Francois Marier's avatar Francois Marier
Browse files

htmlpurifier: migrate custom iframe filters to URI.SafeIframeRegexp



The new HTML.SafeIframe setting in HTML Purifier 4.4.0 allows us
to remove our fragile custom filters.

The regular expressions are not quite as tight, but they are
restricted to the src attribute and HTML Purifier will hopefully
apply the right filters.

Bug #922360 (also fixes bug #885066)

Change-Id: Ifaa9f13ae77b28e18df640103e205a94bc3af2d7
Signed-off-by: default avatarFrancois Marier <francois@catalyst.net.nz>
parent afadb872
......@@ -2825,5 +2825,9 @@ function xmldb_core_upgrade($oldversion=0) {
}
}
if ($oldversion < 2012022100) {
reload_html_filters();
}
return $status;
}
<?php
class HTMLPurifier_Filter_GlogsterIframe extends HTMLPurifier_Filter
{
//Defaults to half the standard iframe size
private $default_width = '480';
private $default_height = '650';
private $default_scale = '50';
private $max_scale = 100;
private $max_width = 960;
private $max_height = 1300;
public $name = 'GlogsterIframe';
public function preFilter($html, $config, $context) {
if (preg_match_all('#(<iframe[^>]+?glogster\.com[^>]+></iframe>)#', $html, $matches)) {
foreach ($matches[1] as $match) {
$xml = simplexml_load_string($match);
$width = $xml['width'] ? $xml['width']: $this->default_width;
$height = $xml['height'] ? $xml['height'] : $this->default_height;
$query = parse_url($xml['src'], PHP_URL_QUERY);
parse_str($query, $parts);
$id = $parts['glog_id'];
$scale = $parts['scale'] ? $parts['scale'] : $this->default_scale;
//These values all need to be set proportionally to their maximum values and to scale.
if ($scale > $this->max_scale or $width > $this->max_width or $height > $this->max_height) {
$scale = $this->max_scale;
$height = $this->max_height;
$width = $this->max_width;
}
else {
//width and height need to be proportional to scale
$width_scale = (int)$width/$this->max_width*100;
$height_scale = (int)$height/$this->max_height*100;
//Allowing for margin of error for calculating width/height based on scale.
$scale_range = range($scale-1,$scale+1);
$width_scale_range = range($width_scale-2, $width_scale+2);
//Ensure that width and height are scaled correctly,
//or that the scale is correctly set in the event
//that the width and height are within range of each other
if ((!in_array($width_scale, $scale_range) or !in_array($height_scale, $scale_range))
and !in_array($height_scale, $width_scale_range)) {
$width = $this->max_width*$scale/$this->max_scale;
$height = $this->max_height*$scale/$this->max_scale;
}
elseif (in_array($height_scale, $width_scale_range)) {
$scale = $width_scale;
}
}
$replace = '<span class="glogster-iframe">'.$scale.' '.$width.' '.$height.' '.$id.'</span>';
$html = str_replace($match, $replace, $html);
}
}
return $html;
}
public function postFilter($html, $config, $context) {
$post_regex = '#<span class="glogster-iframe">([0-9]+) ([0-9]+(%?|px)) ([0-9]+(%?|px)) ([0-9]+)</span>#';
$post_replace = '<iframe width="\2" height="\4" src="http://www.glogster.com/glog.php?glog_id=\6&scale=\1"></iframe>';
return preg_replace($post_regex, $post_replace, $html);
}
}
<?php
class HTMLPurifier_Filter_SlideShareIframe extends HTMLPurifier_Filter
{
//defaults based on standard SlideShare iframe width and height
private $default_width = 425;
private $default_height = 355;
//Max values set at double the defaults - seems like a sane limit
//and it still looks fine at that size
private $max_width = 850;
private $max_height = 710;
public $name = 'SlideShareIframe';
public function preFilter($html, $config, $context) {
if (preg_match_all('#(<iframe[^>]+?slideshare\.net/slideshow/embed_code/[^>]+></iframe>)#', $html, $matches)) {
foreach ($matches[1] as $match) {
$xml = simplexml_load_string($match);
$width = $xml['width'] ? $xml['width']: $this->default_width;
$height = $xml['height'] ? $xml['height'] : $this->default_height;
$path = parse_url($xml['src'], PHP_URL_PATH);
$id = '';
if (preg_match('#/slideshow/embed_code/([0-9]+)#', $path, $code)) {
$id = $code[1];
}
if ((int)$width > $this->max_width) {
$width = $this->max_width;
}
if ((int)$height > $this->max_height) {
$height = $this->max_height;
}
$replace = '<span class="slideshare-iframe">'.$width.' '.$height.' '.$id.'</span>';
$html = str_replace($match, $replace, $html);
}
}
return $html;
}
public function postFilter($html, $config, $context) {
$post_regex = '#<span class="slideshare-iframe">([0-9]+(%?|px)) ([0-9]+(%?|px)) ([0-9]+)</span>#';
$post_replace = '<iframe width="$1" height="$3" src="http://www.slideshare.net/slideshow/embed_code/$5" frameborder="0" marginwidth="0" marginheight="0"></iframe>';
return preg_replace($post_regex, $post_replace, $html);
}
}
<?php
class HTMLPurifier_Filter_VimeoIframe extends HTMLPurifier_Filter {
public $name = 'VimeoIframe';
private $max_width = 2000;
public function preFilter($html, $config, $context) {
$width = 400;
$height = round(($width * 0.564), 0);
$regex = '#<iframe src="http://player\.vimeo\.com/video/([^"]+)" width="([0-9]+)(px)?" height="([0-9]+)(px)?" .*></iframe>#';
if (preg_match($regex, $html, $matches)) {
if ($matches[2] <= $this->max_width) {
$width = $matches[2];
$height = round(($width * 0.564), 0);
}
$replace = '<span class="vimeo-iframe">' . $matches[1] . 'width=' . $width . $matches[3] . 'height=' . $height . $matches[3] . '</span>';
return str_replace($matches[0], $replace, $html);
}
return $html;
}
public function postFilter($html, $config, $context) {
$regex = '#<span class="vimeo-iframe">([^"]+)width=([0-9]+)(px)?height=([0-9]+)(px)?</span>#';
if (preg_match($regex, $html, $matches)) {
$iframe = '<iframe title="Vimeo video player" class="vimeo-player" type="text/html"';
$iframe .= 'width="' . $matches[2] . $matches[3] . '" height="' . $matches[4] . $matches[3] . '" src="http://player.vimeo.com/video/' . $matches[1] . '"';
$iframe .= 'frameborder="0" allowFullScreen></iframe>';
return str_replace($matches[0], $iframe, $html);
}
return $html;
}
}
<?php
class HTMLPurifier_Filter_WikiEducatorIframe extends HTMLPurifier_Filter
{
private $default_width = '100%';
private $default_height = '300';
private $max_width = 2000;
private $max_height = 2000;
private $max_percent_s = '100%';
private $max_percent = 100;
public $name = 'WikiEducatorIframe';
public function preFilter($html, $config, $context) {
if (preg_match_all('#(<iframe[^>]+?wikieducator\.org[^>]+></iframe>)#', $html, $matches)) {
foreach ($matches[1] as $match) {
$xml = simplexml_load_string($match);
$width = $xml['width'] ? $xml['width']: $this->default_width;
//if no percent, assume pixel value
if (strpos($width,'%') === false) {
if ((int)$width > $this->max_width) {
$width = $this->max_width;
}
}
else {
if ((int)$width > $this->max_percent) {
$width = $this->max_percent_s;
}
}
$height = $xml['height'] ? $xml['height'] : $this->default_height;
//if no percent, assume pixel value
if (strpos($height,'%') === false) {
if ((int)$height > $this->max_height) {
$height = $this->max_height;
}
}
else {
if ((int)$height > $this->max_percent) {
$height = $this->max_percent_s;
}
}
$query = parse_url($xml['src'], PHP_URL_QUERY);
parse_str($query, $parts);
$id = '';
$revision ='';
if (array_key_exists('curid', $parts)) {
$revision = 'cur';
$id = $parts['curid'];
}
else if (array_key_exists('oldid', $parts)) {
$revision = 'old';
$id = $parts['oldid'];
}
else {
continue;
}
$replace = '<span class="wikieducator-iframe">'.$revision.' '.$width.' '.$height.' '.$id.'</span>';
$html = str_replace($match, $replace, $html);
}
}
return $html;
}
public function postFilter($html, $config, $context) {
$post_regex = '#<span class="wikieducator-iframe">([a-z]{3}) ([0-9]+(%?|px)) ([0-9]+(%?|px)) ([0-9]+)</span>#';
$post_replace = '<iframe width="\2" height="\4" src="http://wikieducator.org/index.php?\1id=\6"></iframe>';
return preg_replace($post_regex, $post_replace, $html);
}
}
<?php
class HTMLPurifier_Filter_YouTubeIframe extends HTMLPurifier_Filter
{
public $name = 'YouTubeIframe';
public function preFilter($html, $config, $context) {
$url_regex = '([A-Za-z0-9\-_]+(\?[A-Za-z]+=[A-Za-z0-9]+((&amp;|&)[A-Za-z]+=[A-Za-z0-9]+)*)?)';
$pre_regex = '#<iframe\b[a-zA-Z0-9/"=-\s]+?\bsrc="http://www.youtube.com/embed/' . $url_regex . '"[a-zA-Z0-9/"=-\s]*?></iframe>#';
$pre_replace = '<span class="youtube-iframe">\1</span>';
return preg_replace($pre_regex, $pre_replace, $html);
}
public function postFilter($html, $config, $context) {
$url_regex = '([A-Za-z0-9\-_]+(\?[A-Za-z]+=[A-Za-z0-9]+((&amp;|&)[A-Za-z]+=[A-Za-z0-9]+)*)?)';
$post_regex = '#<span class="youtube-iframe">' . $url_regex . '</span>#';
return preg_replace_callback($post_regex, array($this, 'postFilterCallback'), $html);
}
protected function postFilterCallback($matches) {
return '<iframe title="YouTube video player" class="youtube-player" type="text/html"'.
'width="480" height="390" src="http://www.youtube.com/embed/'.$matches[1].
'" frameborder="0" allowFullScreen></iframe>';
}
}
......@@ -8,24 +8,4 @@
<filename>Twitter</filename>
<site>http://twitter.com</site>
</filter>
<filter>
<filename>YouTubeIframe</filename>
<site>http://youtube.com (iframe code)</site>
</filter>
<filter>
<filename>WikiEducatorIframe</filename>
<site>http://wikieducator.org (iframe code)</site>
</filter>
<filter>
<filename>GlogsterIframe</filename>
<site>http://www.glogster.com (iframe code)</site>
</filter>
<filter>
<filename>SlideShareIframe</filename>
<site>http://www.slideshare.net (iframe code)</site>
</filter>
<filter>
<filename>VimeoIframe</filename>
<site>http://vimeo.com (iframe code)</site>
</filter>
</filters>
......@@ -28,7 +28,7 @@
defined('INTERNAL') || die();
$config = new StdClass;
$config->version = 2012021700;
$config->version = 2012022100;
$config->release = '1.5.0dev';
$config->minupgradefrom = 2008040200;
$config->minupgraderelease = '1.0.0 (release tag 1.0.0_RELEASE)';
......
......@@ -2729,9 +2729,18 @@ function clean_html($text, $xhtml=false) {
}
// Permit embedding contents from other sites
$safeiframesources = array('www.youtube.com/embed/',
'player.vimeo.com/video/',
'www.slideshare.net/slideshow/embed_code/',
'(www|edu).glogster.com/glog(/|.php)',
'wikieducator.org/index.php',
);
$config->set('HTML.SafeEmbed', true);
$config->set('HTML.SafeObject', true);
$config->set('Output.FlashCompat', true);
$config->set('HTML.SafeIframe', true);
$config->set('URI.SafeIframeRegexp',
'%^https?://('.implode('|', $safeiframesources).')%');
// Allow namespaced IDs
// see http://htmlpurifier.org/docs/enduser-id.html
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment