Allow clean background:url(...) styles in safe mode. This will make Roundcube pass the Email Standards Acid Test

pull/1/head
thomascube 13 years ago
parent 231fae7ad4
commit 2b017e7f79

@ -883,19 +883,19 @@ function rcmail_get_edit_field($col, $value, $attrib, $type='text')
* @param string Container ID to use as prefix
* @return string Modified CSS source
*/
function rcmail_mod_css_styles($source, $container_id)
function rcmail_mod_css_styles($source, $container_id, $allow_remote=false)
{
$last_pos = 0;
$replacements = new rcube_string_replacer;
// ignore the whole block if evil styles are detected
$stripped = preg_replace('/[^a-z\(:;]/', '', rcmail_xss_entity_decode($source));
if (preg_match('/expression|behavior|url\(|import[^a]/', $stripped))
$source = rcmail_xss_entity_decode($source);
$stripped = preg_replace('/[^a-z\(:;]/i', '', $source);
$evilexpr = 'expression|behavior' . (!$allow_remote ? '|url\(|import[^a]' : '');
if (preg_match("/$evilexpr/i", $stripped) // don't accept No-Gos
|| (strpos($stripped, 'url(') && !preg_match('!url\s*\([ "\'](https?:)//[a-z0-9/._+-]+["\' ]\)!Ui', $source))) // only allow clean urls
return '/* evil! */';
// remove css comments (sometimes used for some ugly hacks)
$source = preg_replace('!/\*(.+)\*/!Ums', '', $source);
// cut out all contents between { and }
while (($pos = strpos($source, '{', $last_pos)) && ($pos2 = strpos($source, '}', $pos)))
{
@ -937,7 +937,7 @@ function rcmail_xss_entity_decode($content)
{
$out = html_entity_decode(html_entity_decode($content));
$out = preg_replace_callback('/\\\([0-9a-f]{4})/i', 'rcmail_xss_entity_decode_callback', $out);
$out = preg_replace('#/\*.*\*/#Um', '', $out);
$out = preg_replace('#/\*.*\*/#Ums', '', $out);
return $out;
}

@ -243,7 +243,7 @@ class washtml
case XML_ELEMENT_NODE: //Check element
$tagName = strtolower($node->tagName);
if ($callback = $this->handlers[$tagName]) {
$dump .= call_user_func($callback, $tagName, $this->wash_attribs($node), $this->dumpHtml($node));
$dump .= call_user_func($callback, $tagName, $this->wash_attribs($node), $this->dumpHtml($node), $this);
}
else if (isset($this->_html_elements[$tagName])) {
$content = $this->dumpHtml($node);
@ -301,6 +301,14 @@ class washtml
return $this->dumpHtml($node);
}
/**
* Getter for config parameters
*/
public function get_config($prop)
{
return $this->config[$prop];
}
}
?>

@ -822,7 +822,7 @@ function rcmail_plain_body($body, $flowed=false)
/**
* Callback function for washtml cleaning class
*/
function rcmail_washtml_callback($tagname, $attrib, $content)
function rcmail_washtml_callback($tagname, $attrib, $content, $washtml)
{
switch ($tagname) {
case 'form':
@ -834,8 +834,11 @@ function rcmail_washtml_callback($tagname, $attrib, $content)
$stripped = preg_replace('/[^a-zA-Z\(:;]/', '', rcmail_xss_entity_decode($content));
// now check for evil strings like expression, behavior or url()
if (!preg_match('/expression|behavior|url\(|import[^a]/', $stripped)) {
$out = html::tag('style', array('type' => 'text/css'), $content);
if (!preg_match('/expression|behavior/i', $stripped)) {
if (!$washtml->get_config('allow_remote') && preg_match('/url\(|import[^a]/i', $stripped))
$washtml->extlinks = true;
else
$out = html::tag('style', array('type' => 'text/css'), $content);
break;
}
@ -1021,7 +1024,7 @@ function rcmail_message_body($attrib)
$body = rcmail_print_body($part, array('safe' => $safe_mode, 'plain' => !$CONFIG['prefer_html']));
if ($part->ctype_secondary == 'html') {
$body = rcmail_html4inline($body, $attrib['id'], 'rcmBody', $attrs);
$body = rcmail_html4inline($body, $attrib['id'], 'rcmBody', $attrs, $safe_mode);
$div_attr = array('class' => 'message-htmlpart');
$style = array();
@ -1104,7 +1107,7 @@ function rcmail_resolve_base($body)
/**
* modify a HTML message that it can be displayed inside a HTML page
*/
function rcmail_html4inline($body, $container_id, $body_id='', &$attributes=null)
function rcmail_html4inline($body, $container_id, $body_id='', &$attributes=null, $allow_remote=false)
{
$last_style_pos = 0;
$cont_id = $container_id.($body_id ? ' div.'.$body_id : '');
@ -1116,7 +1119,7 @@ function rcmail_html4inline($body, $container_id, $body_id='', &$attributes=null
// replace all css definitions with #container [def]
$styles = rcmail_mod_css_styles(
substr($body, $pos, $pos2-$pos), $cont_id);
substr($body, $pos, $pos2-$pos), $cont_id, $allow_remote);
$body = substr_replace($body, $styles, $pos, $pos2-$pos);
$last_style_pos = $pos2;

Loading…
Cancel
Save