$attributes = str_replace("\n", ' ', stripslashes($attributes));
$attributes = str_replace('= "', '="', $attributes);
foreach ($conv as $att=>$stl) {
- $pattern = '/\b' . preg_quote($att, '/') . '="(.+?)"/i';
+ $pattern = '/\b' . preg_quote($att, '/') . '=([\'"])?(.+?)(?(1)\1|(?:$| ))/i';
if (preg_match($pattern, $attributes, $matches)) {
$attributes = preg_replace($pattern, '', $attributes);
- $val = $matches[1];
+ $val = $matches[2];
if ($att == 'cellspacing' && strpos($style, 'border-collapse') === false) {
$style .= "border-collapse: separate; border-spacing: $val $val; ";
} elseif ($att == 'cellpadding' && $tag == 'table') {
}
return ' ' . $style . trim($attributes);
}
+
+function banana__filterCss($text)
+{
+ $text = preg_replace("/(,[\s\n\r]*)/s", '\1 .banana .message .body .html ', $text);
+ return '.banana .message .body .html ' . $text;
+}
+
+function banana_filterCss($css)
+{
+ preg_match_all("/(^|\n|,\s*)\s*([\#\.@\w][^;\{\}\<]*?[\{])/s", $css, $matches);
+ $css = preg_replace("/(^|\n)\s*([\#\.@\w][^;\{\}\<]*?)([\{])/se", '"\1" . banana__filterCss("\2") . "\3"', $css);
+ $css = preg_replace('/ body\b/i', '', $css);
+ if (!Banana::$msgshow_externalimages) {
+ if (preg_match('!url\([^:\)]+:(//|\\\).*?\)!i', $css)) {
+ $css = preg_replace('!url\([^:\)]+:(//|\\\).*?\)!i', 'url(invalid-image.png)', $css);
+ Banana::$msgshow_hasextimages = true;
+ }
+ }
+ return $css;
+}
/**
* @return string
* @param string
* @desc Strip forbidden tags and delegate tag-source check to removeEvilAttributes()
*/
-function banana_cleanHtml($source)
+function banana_cleanHtml($source, $to_xhtml = false)
{
if (function_exists('tidy_repair_string')) {
- $tidy_on = Array(
- 'drop-empty-paras', 'drop-proprietary-attributes',
- 'hide-comments', 'logical-emphasis', 'output-xhtml',
- 'replace-color',
- );
- $tidy_off = Array('join-classes', 'clean', 'show-body-only'); // 'clean' may be a good idea, but it is too aggressive
-
- foreach($tidy_on as $opt) {
- tidy_setopt($opt, true);
- }
- foreach($tidy_off as $opt) {
- tidy_setopt($opt, false);
+ $tidy_config = array('drop-empty-paras' => true,
+ 'drop-proprietary-attributes' => true,
+ 'hide-comments' => true,
+ 'logical-emphasis' => true,
+ 'output-xhtml' => true,
+ 'replace-color' => true,
+ 'join-classes' => false,
+ 'clean' => false,
+ 'show-body-only' => false,
+ 'alt-text' => '[ inserted by TIDY ]',
+ 'wrap' => 120);
+ if (function_exists('tidy_setopt')) { // Tidy 1.0
+ foreach ($tidy_config as $field=>$value) {
+ tidy_setopt($field, $value);
+ }
+ tidy_set_encoding('utf8');
+ $source = tidy_repair_string($source);
+ } else { // Tidy 2.0
+ $source = tidy_repair_string($source, $tidy_config, 'utf8');
}
- tidy_setopt('alt-text', '[ inserted by TIDY ]');
- tidy_setopt('wrap', '120');
- tidy_set_encoding('utf8');
- $source = tidy_repair_string($source);
}
// To XHTML
- // catch inline CSS
- $css = null;
- if (preg_match('/<head.*?>(.*?)<\/head>/is', $source, $matches)) {
- $source = preg_replace('/<head.*?>.*?<\/head>/is', '', $source);
- preg_match_all('/<style.*?type="text\/css".*?>(.*?)<\/style>/is', $matches[1], $matches);
- foreach ($matches[1] as &$match) {
- $css .= $match;
+ if ($to_xhtml) {
+ // catch inline CSS
+ $css = null;
+ if (preg_match('/<head.*?>(.*?)<\/head>/is', $source, $matches)) {
+ $source = preg_replace('/<head.*?>.*?<\/head>/is', '', $source);
+ preg_match_all('/<style(?:.*?type="text\/css".*?)?>(.*?)<\/style>/is', $matches[1], $matches);
+ foreach ($matches[1] as &$match) {
+ $css .= $match;
+ }
+ $css = banana_filterCss($css);
+ Banana::$page->addCssInline($css);
}
- $css = preg_replace("/(^|\n|,)\s*(\w+[^\{\}\<]+\{)/s", '\1.banana .message .body .html \2', $css);
- $css = preg_replace('/ body\b/i', '', $css);
- Banana::$page->addCssInline($css);
- }
-
- // clean DTD
- $source = str_replace('<font', '<span', $source);
- $source = preg_replace('/<u\b/', '<span style="text-decoration: underline"', $source);
- $source = preg_replace('/<\/(font|u)>/', '</span>', $source);
- $source = str_replace('<body', $css ? '<div class="html"' : '<div class="html default"', $source);
- $source = str_replace('</body>', '</div>', $source);
+ // clean DTD
+ $source = str_replace('<font', '<span', $source);
+ $source = preg_replace('/<u\b/', '<span style="text-decoration: underline"', $source);
+ $source = preg_replace('/<\/(font|u)>/', '</span>', $source);
+ $source = str_replace('<body', $css ? '<div class="html"' : '<div class="html default"', $source);
+ $source = str_replace('</body>', '</div>', $source);
+ }
$allowedTags = '<h1><h2><h3><b><i><a><ul><li><pre><hr><blockquote><img><br><div><span>'
. '<p><small><big><sup><sub><code><em><strong><table><tr><td><th>';
$source = strip_tags($source, $allowedTags);
// Use inlined style instead of old html attributes
- $source = preg_replace('/<(\/?\w+)(.*?)(\/?>)/ise', "'<\\1' . banana_cleanStyles('\\1', '\\2') . '\\3'", $source);
+ if ($to_xhtml) {
+ $source = preg_replace('/<(\/?\w+)(.*?)(\/?>)/uise', "'<\\1' . banana_cleanStyles('\\1', '\\2') . '\\3'", $source);
+ }
return preg_replace('/<(.*?)>/ie', "'<'.banana_removeEvilAttributes('\\1').'>'", $source);
}
function banana_hideExternalImages($text)
{
- return preg_replace("/<img([^>]*?)src=['\"](?!cid).*?['\"](.*?)>/i",
- '<img\1src="invalid"\2>',
- $text);
+ if (preg_match("/<img([^>]*?)src=['\"](?!cid).*?['\"](.*?)>/i", $text)) {
+ Banana::$msgshow_hasextimages = true;
+ return preg_replace("/<img([^>]*?)src=['\"](?!cid).*?['\"](.*?)>/i",
+ '<img\1src="invalid"\2>',
+ $text);
+ }
+ return $text;
}
function banana_catchPartLinks($text)
$text = banana_hideExternalImages($text);
}
$text = banana_catchPartLinks($text);
- return banana_cleanHtml($text);
+ return banana_cleanHtml($text, true);
}
function banana_quoteHtml(BananaMimePart &$part)