* This contains the functions necessary to detect and decode MIME
* messages.
*
- * @copyright © 1999-2006 The SquirrelMail Project Team
+ * @copyright © 1999-2007 The SquirrelMail Project Team
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
* @version $Id$
* @package squirrelmail
if (!is_object($msg)) {
global $color, $mailbox;
- /* removed urldecode because $_GET is auto urldecoded ??? */
displayPageHeader( $color, $mailbox );
$errormessage = _("SquirrelMail could not decode the bodystructure of the message");
$errormessage .= '<br />'._("The bodystructure provided by your IMAP server:").'<br /><br />';
$errormessage .= '<pre>' . htmlspecialchars($read) . '</pre>';
- plain_error_message( $errormessage, $color );
+ plain_error_message( $errormessage );
echo '</body></html>';
exit;
}
if (count($flags)) {
foreach ($flags as $flag) {
+//FIXME: please document why it is we have to check the first char of the flag but we then go ahead and do a full string comparison anyway. Is this a speed enhancement? If not, let's keep it simple and just compare the full string and forget the switch block.
$char = strtoupper($flag{1});
switch ($char) {
case 'S':
// }
} else if (ereg('"([^"]*)"', $topline, $regs)) {
$ret = $regs[1];
+ } else if ((stristr($topline, 'nil') !== false) && (empty($wholemessage))) {
+ $ret = $wholemessage;
} else {
global $where, $what, $mailbox, $passed_id, $startMessage;
$par = 'mailbox=' . urlencode($mailbox) . '&passed_id=' . $passed_id;
global $startMessage, $languages, $squirrelmail_language,
$show_html_default, $sort, $has_unsafe_images, $passed_ent_id,
$use_iframe, $iframe_height, $download_and_unsafe_link,
- $download_href, $unsafe_image_toggle_href, $unsafe_image_toggle_text;
+ $download_href, $unsafe_image_toggle_href, $unsafe_image_toggle_text,
+ $oTemplate, $nbsp;
// workaround for not updated config.php
if (! isset($use_iframe)) $use_iframe = false;
- if( !sqgetGlobalVar('view_unsafe_images', $view_unsafe_images, SQ_GET) ) {
- $view_unsafe_images = false;
- }
+ // If there's no "view_unsafe_images" variable in the URL, turn unsafe
+ // images off by default.
+ sqgetGlobalVar('view_unsafe_images', $view_unsafe_images, SQ_GET, FALSE);
$body = '';
$urlmailbox = urlencode($mailbox);
$body = call_user_func($languages[$squirrelmail_language]['XTRA_CODE'] . '_decode',$body);
}
}
- $hookResults = do_hook("message_body", $body);
- $body = $hookResults[1];
+
+ /* As of 1.5.2, $body is passed (and modified) by reference */
+ do_hook('message_body', $body);
/* If there are other types that shouldn't be formatted, add
* them here.
global $oTemplate;
$oTemplate->assign('iframe_url', $iframeurl);
+ $oTemplate->assign('iframe_height', $iframe_height);
$oTemplate->assign('html_body', $html_body);
$body = $oTemplate->fetch('read_html_iframe.tpl');
} else {
// old way of html rendering
- $body = magicHTML($body, $id, $message, $mailbox);
/**
* convert character set. charset_decode does not remove html special chars
* applied by magicHTML functions and does not sanitize them second time if
* fourth argument is true.
*/
- $body = charset_decode($body_message->header->getParameter('charset'),$body,false,true);
+ $charset = $body_message->header->getParameter('charset');
+ if (!empty($charset)) {
+ $body = charset_decode($charset,$body,false,true);
+ }
+ $body = magicHTML($body, $id, $message, $mailbox);
}
} else {
translateText($body, $wrap_at,
return $body;
}
+ /*
+ * Previously the links for downloading and unsafe images were printed
+ * under the mail. By putting the links in a global variable we can
+ * print it in the toolbar where it belongs. Since the original code was
+ * in this place it's left here. It might be possible to move it to some
+ * other place if that makes sense. The possibility to do so has not
+ * been evaluated yet.
+ */
+
+ // Initialize the global variable to an empty string.
+ // FIXME: To have $download_and_unsafe_link as a global variable might not be needed since the use of separate variables ($download_href, $unsafe_image_toggle_href, and $unsafe_image_toggle_text) for the templates was introduced.
$download_and_unsafe_link = '';
+ // Prepare and build a link for downloading the mail.
$link = 'passed_id=' . $id . '&ent_id='.$ent_num.
'&mailbox=' . $urlmailbox .'&sort=' . $sort .
'&startMessage=' . $startMessage . '&show_more=0';
$link .= '&passed_ent_id='.$passed_ent_id;
}
$download_href = SM_PATH . 'src/download.php?absolute_dl=true&' . $link;
- $download_and_unsafe_link .= ' | <a href="'. $download_href .'">' . _("Download this as a file") . '</a>';
+
+ // Always add the link for downloading the mail as a file to the global
+ // variable.
+ $download_and_unsafe_link .= "$nbsp|$nbsp"
+ . create_hyperlink($download_href, _("Download this as a file"));
+
+ // Find out the right text to use in the link depending on the
+ // circumstances. If the unsafe images are displayed the link should
+ // hide them, if they aren't displayed the link should only appear if
+ // the mail really contains unsafe images.
if ($view_unsafe_images) {
$text = _("Hide Unsafe Images");
} else {
$text = '';
}
}
+
+ // Only create a link for unsafe images if there's need for one. If so:
+ // add it to the global variable.
if($text != '') {
$unsafe_image_toggle_href = SM_PATH . 'src/read_body.php?'.$link;
$unsafe_image_toggle_text = $text;
- $download_and_unsafe_link .= ' | <a href="'. $unsafe_image_toggle_href .'">' . $text . '</a>';
+ $download_and_unsafe_link .= "$nbsp|$nbsp"
+ . create_hyperlink($unsafe_image_toggle_href, $text);
}
}
return $body;
* for a more generic type. Finally, a hook for ALL attachment
* types is run as well.
*/
- $hookresults = do_hook("attachment $type0/$type1", $links,
- $startMessage, $id, $urlMailbox, $ent, $defaultlink,
- $display_filename, $where, $what);
- if(count($hookresults[1]) <= 1) {
- $hookresults = do_hook("attachment $type0/*", $links,
- $startMessage, $id, $urlMailbox, $ent, $defaultlink,
- $display_filename, $where, $what);
+ // First remember the default link.
+ $defaultlink_orig = $defaultlink;
+
+ /* The API for this hook has changed as of 1.5.2 so that all plugin
+ arguments are passed in an array instead of each their own plugin
+ argument, and arguments are passed by reference, so instead of
+ returning any changes, changes should simply be made to the original
+ arguments themselves. */
+ $temp = array(&$links, &$startMessage, &$id, &$urlMailbox, &$ent,
+ &$defaultlink, &$display_filename, &$where, &$what);
+ do_hook("attachment $type0/$type1", $temp);
+ if(count($links) <= 1 && $defaultlink == $defaultlink_orig) {
+ /* The API for this hook has changed as of 1.5.2 so that all plugin
+ arguments are passed in an array instead of each their own plugin
+ argument, and arguments are passed by reference, so instead of
+ returning any changes, changes should simply be made to the original
+ arguments themselves. */
+ $temp = array(&$links, &$startMessage, &$id, &$urlMailbox, &$ent,
+ &$defaultlink, &$display_filename, &$where, &$what);
+ do_hook("attachment $type0/*", $temp);
}
- $hookresults = do_hook("attachment */*", $hookresults[1],
- $startMessage, $id, $urlMailbox, $ent, $hookresults[6],
- $display_filename, $where, $what);
-
- $links = $hookresults[1];
- $defaultlink = $hookresults[6];
+ /* The API for this hook has changed as of 1.5.2 so that all plugin
+ arguments are passed in an array instead of each their own plugin
+ argument, and arguments are passed by reference, so instead of
+ returning any changes, changes should simply be made to the original
+ arguments themselves. */
+ $temp = array(&$links, &$startMessage, &$id, &$urlMailbox, &$ent,
+ &$defaultlink, &$display_filename, &$where, &$what);
+ // Do not let a generic plugin change the default link if a more
+ // specialized one already did it...
+ if ($defaultlink != $defaultlink_orig) {
+ $dummy = '';
+ $temp[5] = &$dummy;
+ }
+ do_hook("attachment */*", $temp);
$this_attachment = array();
$this_attachment['Name'] = decodeHeader($display_filename);
$body = str_replace("\r\n", "\n", $body);
$encoding = strtolower($encoding);
- $encoding_handler = do_hook_function('decode_body', $encoding);
+ $encoding_handler = do_hook('decode_body', $encoding);
// plugins get first shot at decoding the body
/**
* Decodes headers
*
- * This functions decode strings that is encoded according to
+ * This function decodes strings that are encoded according to
* RFC1522 (MIME Part Two: Message Header Extensions for Non-ASCII Text).
* Patched by Christian Schmidt <christian@ostenfeld.dk> 23/03/2002
*
* @param string $string header string that has to be made readable
* @param boolean $utfencode change message in order to be readable on user's charset. defaults to true
- * @param boolean $htmlsave preserve spaces and sanitize html special characters. defaults to true
+ * @param boolean $htmlsafe preserve spaces and sanitize html special characters. defaults to true
* @param boolean $decide decide if string can be utfencoded. defaults to false
* @return string decoded header string
*/
-function decodeHeader ($string, $utfencode=true,$htmlsave=true,$decide=false) {
+function decodeHeader ($string, $utfencode=true,$htmlsafe=true,$decide=false) {
global $languages, $squirrelmail_language,$default_charset;
if (is_array($string)) {
$string = implode("\n", $string);
while ($match = preg_match('/^(.*)=\?([^?]*)\?(Q|B)\?([^?]*)\?=(.*)$/Ui',$chunk,$res)) {
/* if the last chunk isn't an encoded string then put back the space, otherwise don't */
if ($iLastMatch !== $j) {
- if ($htmlsave) {
+ if ($htmlsafe) {
$ret .= ' ';
} else {
$ret .= ' ';
}
$iLastMatch = $i;
$j = $i;
- if ($htmlsave) {
+ if ($htmlsafe) {
$ret .= htmlspecialchars($res[1]);
} else {
$ret .= $res[1];
/* convert string to different charset,
* if functions asks for it (usually in compose)
*/
- $ret .= charset_convert($res[2],$replace,$default_charset,$htmlsave);
+ $ret .= charset_convert($res[2],$replace,$default_charset,$htmlsafe);
} else {
// convert string to html codes in order to display it
$ret .= charset_decode($res[2],$replace);
}
} else {
- if ($htmlsave) {
+ if ($htmlsafe) {
$replace = htmlspecialchars($replace);
}
$ret.= $replace;
/* convert string to different charset,
* if functions asks for it (usually in compose)
*/
- $replace = charset_convert($res[2], $replace,$default_charset,$htmlsave);
+ $replace = charset_convert($res[2], $replace,$default_charset,$htmlsafe);
} else {
// convert string to html codes in order to display it
$replace = charset_decode($res[2], $replace);
}
} else {
- if ($htmlsave) {
+ if ($htmlsafe) {
$replace = htmlspecialchars($replace);
}
}
$encoded = true;
}
if (!$encoded) {
- if ($htmlsave) {
+ if ($htmlsafe) {
$ret .= ' ';
} else {
$ret .= ' ';
}
}
- if (!$encoded && $htmlsave) {
+ if (!$encoded && $htmlsafe) {
$ret .= htmlspecialchars($chunk);
} else {
$ret .= $chunk;
}
/* remove the first added space */
if ($ret) {
- if ($htmlsave) {
+ if ($htmlsafe) {
$ret = substr($ret,5);
} else {
$ret = substr($ret,1);
}
/**
- * Translate all dangerous Unicode or Shift_JIS characters which are acepted by
+ * Translate all dangerous Unicode or Shift_JIS characters which are accepted by
* IE as regular characters.
*
* @param attvalue The attribute value before dangerous characters are translated.
// remove comments
$attvalue = preg_replace("/(\/\*.*?\*\/)/","",$attvalue);
- // IE has the evil habit of excepting every possible value for the attribute expression
- // The table below contain characters which are valid in IE if they are used in the "expression"
+ // IE has the evil habit of accepting every possible value for the attribute expression.
+ // The table below contains characters which are parsed by IE if they are used in the "expression"
// attribute value.
$aDangerousCharsReplacementTable = array(
array('ʟ', 'ʟ' ,/* L UNICODE IPA Extension */
'ʀ', 'ʀ' ,/* R UNICODE IPA Extension */
'ɴ', 'ɴ' ,/* N UNICODE IPA Extension */
- 'E', 'E' ,/* Unicode FULLWIDTH LATIN CAPITAL LETTER E */
- 'e', 'e' ,/* Unicode FULLWIDTH LATIN SMALL LETTER E */
+ 'E', 'E' ,/* Unicode FULLWIDTH LATIN CAPITAL LETTER E */
+ 'e', 'e' ,/* Unicode FULLWIDTH LATIN SMALL LETTER E */
'X', 'X',/* Unicode FULLWIDTH LATIN CAPITAL LETTER X */
'x', 'x',/* Unicode FULLWIDTH LATIN SMALL LETTER X */
'P', 'P',/* Unicode FULLWIDTH LATIN CAPITAL LETTER P */
'U', 'U',/* Unicode FULLWIDTH LATIN CAPITAL LETTER U */
'u', 'u',/* Unicode FULLWIDTH LATIN SMALL LETTER U */
'ⁿ', 'ⁿ' ,/* Unicode SUPERSCRIPT LATIN SMALL LETTER N */
- '艤', /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER E */ // in unicode this is some chinese char range
- '芅', /* Shift JIS FULLWIDTH LATIN SMALL LETTER E */
- '艷', /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER X */
- '芘', /* Shift JIS FULLWIDTH LATIN SMALL LETTER X */
- '良', /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER P */
- '芐', /* Shift JIS FULLWIDTH LATIN SMALL LETTER P */
- '艱', /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER R */
- '芒', /* Shift JIS FULLWIDTH LATIN SMALL LETTER R */
- '色', /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER S */
- '芓', /* Shift JIS FULLWIDTH LATIN SMALL LETTER S */
- '艨', /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER I */
- '芉', /* Shift JIS FULLWIDTH LATIN SMALL LETTER I */
- '艮', /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER O */
- '芏', /* Shift JIS FULLWIDTH LATIN SMALL LETTER O */
- '艭', /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER N */
- '芎'), /* Shift JIS FULLWIDTH LATIN SMALL LETTER N */
+ "\xEF\xBC\xA5", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER E */ // in unicode this is some Chinese char range
+ "\xEF\xBD\x85", /* Shift JIS FULLWIDTH LATIN SMALL LETTER E */
+ "\xEF\xBC\xB8", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER X */
+ "\xEF\xBD\x98", /* Shift JIS FULLWIDTH LATIN SMALL LETTER X */
+ "\xEF\xBC\xB0", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER P */
+ "\xEF\xBD\x90", /* Shift JIS FULLWIDTH LATIN SMALL LETTER P */
+ "\xEF\xBC\xB2", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER R */
+ "\xEF\xBD\x92", /* Shift JIS FULLWIDTH LATIN SMALL LETTER R */
+ "\xEF\xBC\xB3", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER S */
+ "\xEF\xBD\x93", /* Shift JIS FULLWIDTH LATIN SMALL LETTER S */
+ "\xEF\xBC\xA9", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER I */
+ "\xEF\xBD\x89", /* Shift JIS FULLWIDTH LATIN SMALL LETTER I */
+ "\xEF\xBC\xAF", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER O */
+ "\xEF\xBD\x8F", /* Shift JIS FULLWIDTH LATIN SMALL LETTER O */
+ "\xEF\xBC\xAE", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER N */
+ "\xEF\xBD\x8E", /* Shift JIS FULLWIDTH LATIN SMALL LETTER N */
+ "\xEF\xBC\xAC", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER L */
+ "\xEF\xBD\x8C", /* Shift JIS FULLWIDTH LATIN SMALL LETTER L */
+ "\xEF\xBC\xB5", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER U */
+ "\xEF\xBD\x95", /* Shift JIS FULLWIDTH LATIN SMALL LETTER U */
+ "\xE2\x81\xBF", /* Shift JIS FULLWIDTH SUPERSCRIPT N */
+ "\xCA\x9F", /* L UNICODE IPA Extension */
+ "\xCA\x80", /* R UNICODE IPA Extension */
+ "\xC9\xB4"), /* N UNICODE IPA Extension */
array('l', 'l', 'r','r','n','n',
- 'E','E','e','e','X','X','x','x','P','P','p','p','S','S','s','s','I','I',
- 'i','i','O','O','o','o','N','N','n','n','L','L','l','l','U','U','u','u','n',
- 'E','e','X','x','P','p','S','s','I','i','O','o','N','n'));
+ 'E','E','e','e','X','X','x','x','P','P','p','p','R','R','r','r','S','S','s','s','I','I',
+ 'i','i','O','O','o','o','N','N','n','n','L','L','l','l','U','U','u','u','n','n',
+ 'E','e','X','x','P','p','R','r','S','s','I','i','O','o','N','n','L','l','U','u','n','l','r','n'));
$attvalue = str_replace($aDangerousCharsReplacementTable[0],$aDangerousCharsReplacementTable[1],$attvalue);
- // Escapes are usefull for special characters like "{}[]()'&. In other cases they are
- // used for XSS
+ // Escapes are useful for special characters like "{}[]()'&. In other cases they are
+ // used for XSS.
$attvalue = preg_replace("/(\\\\)([a-zA-Z]{1})/",'$2',$attvalue);
}
preg_replace($valmatch, $valrepl, $attvalue);
if ($newvalue != $attvalue){
$attary{$attname} = $newvalue;
+ $attvalue = $newvalue;
}
}
}
}
}
-
- /**
- * Replace empty src tags with the blank image. src is only used
- * for frames, images, and image inputs. Doing a replace should
- * not affect them working as should be, however it will stop
- * IE from being kicked off when src for img tags are not set
- */
- if (($attname == 'src') && ($attvalue == '""')) {
- $attary{$attname} = '"' . SM_PATH . 'images/blank.png"';
- }
-
- /**
- * Turn cid: urls into http-friendly ones.
- */
- if (preg_match("/^[\'\"]\s*cid:/si", $attvalue)){
- $attary{$attname} = sq_cid2http($message, $id, $attvalue, $mailbox);
+ if ($attname == 'style') {
+ if (preg_match('/[\0-\37\200-\377]+/',$attvalue)) {
+ // 8bit and control characters in style attribute values can be used for XSS, remove them
+ $attary{$attname} = '"disallowed character"';
+ }
+ preg_match_all("/url\s*\((.+)\)/si",$attvalue,$aMatch);
+ if (count($aMatch)) {
+ foreach($aMatch[1] as $sMatch) {
+ // url value
+ $urlvalue = $sMatch;
+ sq_fix_url($attname, $urlvalue, $message, $id, $mailbox,"'");
+ $attary{$attname} = str_replace($sMatch,$urlvalue,$attvalue);
+ }
+ }
}
-
/**
- * "Hack" fix for Outlook using propriatary outbind:// protocol in img tags.
- * One day MS might actually make it match something useful, for now, falling
- * back to using cid2http, so we can grab the blank.png.
+ * Use white list based filtering on attributes which can contain url's
*/
- if (preg_match("/^[\'\"]\s*outbind:\/\//si", $attvalue)) {
- $attary{$attname} = sq_cid2http($message, $id, $attvalue, $mailbox);
+ else if ($attname == 'href' || $attname == 'src' || $attname == 'background') {
+ sq_fix_url($attname, $attvalue, $message, $id, $mailbox);
+ $attary{$attname} = $attvalue;
}
-
}
/**
* See if we need to append any attributes to this tag.
return $attary;
}
+/**
+ * This function filters url's
+ *
+ * @param $attvalue String with attribute value to filter
+ * @param $message message object
+ * @param $id message id
+ * @param $mailbox mailbox
+ * @param $sQuote quoting characters around url's
+ */
+function sq_fix_url($attname, &$attvalue, $message, $id, $mailbox,$sQuote = '"') {
+ $attvalue = trim($attvalue);
+ if ($attvalue && ($attvalue[0] =='"'|| $attvalue[0] == "'")) {
+ // remove the double quotes
+ $sQuote = $attvalue[0];
+ $attvalue = trim(substr($attvalue,1,-1));
+ }
+
+ // If there's no "view_unsafe_images" variable in the URL, turn unsafe
+ // images off by default.
+ sqgetGlobalVar('view_unsafe_images', $view_unsafe_images, SQ_GET, FALSE);
+
+ $secremoveimg = '../images/' . _("sec_remove_eng.png");
+
+ /**
+ * Replace empty src tags with the blank image. src is only used
+ * for frames, images, and image inputs. Doing a replace should
+ * not affect them working as should be, however it will stop
+ * IE from being kicked off when src for img tags are not set
+ */
+ if ($attvalue == '') {
+ $attvalue = '"' . SM_PATH . 'images/blank.png"';
+ } else {
+ // first, disallow 8 bit characters and control characters
+ if (preg_match('/[\0-\37\200-\377]+/',$attvalue)) {
+ switch ($attname) {
+ case 'href':
+ $attvalue = $sQuote . 'http://invalid-stuff-detected.example.com' . $sQuote;
+ break;
+ default:
+ $attvalue = $sQuote . SM_PATH . 'images/blank.png'. $sQuote;
+ break;
+ }
+ } else {
+ $aUrl = parse_url($attvalue);
+ if (isset($aUrl['scheme'])) {
+ switch(strtolower($aUrl['scheme'])) {
+ case 'mailto':
+ case 'http':
+ case 'https':
+ case 'ftp':
+ if ($attname != 'href') {
+ if ($view_unsafe_images == false) {
+ $attvalue = $sQuote . $secremoveimg . $sQuote;
+ } else {
+ if (isset($aUrl['path'])) {
+ // validate image extension.
+ $ext = strtolower(substr($aUrl['path'],strrpos($aUrl['path'],'.')));
+ if (!in_array($ext,array('.jpeg','.jpg','xjpeg','.gif','.bmp','.jpe','.png','.xbm'))) {
+ $attvalue = $sQuote . SM_PATH . 'images/blank.png'. $sQuote;
+ }
+ } else {
+ $attvalue = $sQuote . SM_PATH . 'images/blank.png'. $sQuote;
+ }
+ }
+ }
+ break;
+ case 'outbind':
+ /**
+ * "Hack" fix for Outlook using propriatary outbind:// protocol in img tags.
+ * One day MS might actually make it match something useful, for now, falling
+ * back to using cid2http, so we can grab the blank.png.
+ */
+ $attvalue = sq_cid2http($message, $id, $attvalue, $mailbox);
+ break;
+ case 'cid':
+ /**
+ * Turn cid: urls into http-friendly ones.
+ */
+ $attvalue = sq_cid2http($message, $id, $attvalue, $mailbox);
+ break;
+ default:
+ $attvalue = $sQuote . SM_PATH . 'images/blank.png' . $sQuote;
+ break;
+ }
+ } else {
+ if (!(isset($aUrl['path']) && $aUrl['path'] == $secremoveimg)) {
+ // parse_url did not lead to satisfying result
+ $attvalue = $sQuote . SM_PATH . 'images/blank.png' . $sQuote;
+ }
+ }
+ }
+ }
+}
+
/**
* This function edits the style definition to make them friendly and
* usable in SquirrelMail.
* @return a string with edited content.
*/
function sq_fixstyle($body, $pos, $message, $id, $mailbox){
- global $view_unsafe_images;
$me = 'sq_fixstyle';
// workaround for </style> in between comments
$iCurrentPos = $pos;
$char = $body{$i};
switch ($char) {
case '<':
- $sToken .= $char;
+ $sToken = $char;
break;
case '/':
if ($sToken == '<') {
/**
- * First look for general BODY style declaration, which would be
- * like so:
- * body {background: blah-blah}
- * and change it to .bodyclass so we can just assign it to a <div>
- */
+ * First look for general BODY style declaration, which would be
+ * like so:
+ * body {background: blah-blah}
+ * and change it to .bodyclass so we can just assign it to a <div>
+ */
$content = preg_replace("|body(\s*\{.*?\})|si", ".bodyclass\\1", $content);
$secremoveimg = '../images/' . _("sec_remove_eng.png");
/**
// $content = preg_replace("|url\s*\(\s*([\'\"])\s*\S+script\s*:.*?([\'\"])\s*\)|si",
// "url(\\1$secremoveimg\\2)", $content);
+ // first check for 8bit sequences and disallowed control characters
+ if (preg_match('/[\16-\37\200-\377]+/',$content)) {
+ $content = '<!-- style block removed by html filter due to presence of 8bit characters -->';
+ return array($content, $newpos);
+ }
+
// IE Sucks hard. We have a special function for it.
sq_fixIE_idiocy($content);
// translate ur\l and variations (IE parses that)
// TODO check if the sq_fixIE_idiocy function already handles this.
$content = preg_replace("/(\\\\)?u(\\\\)?r(\\\\)?l(\\\\)?/i", 'url', $content);
- // NB I insert NUL characters to keep to avoid an infinite loop. They are removed after the loop.
- while (preg_match("/url\s*\(\s*[\'\"]?([^:]+):(.*)?[\'\"]?\s*\)/si", $content, $matches)) {
- $sProto = strtolower($matches[1]);
- switch ($sProto) {
- /**
- * Fix url('https*://.*) declarations but only if $view_unsafe_images
- * is false.
- */
- case 'https':
- case 'http':
- if (!$view_unsafe_images){
-
- $sExpr = "/url\s*\(\s*[\'\"]?\s*$sProto*:.*[\'\"]?\s*\)/si";
- $content = preg_replace($sExpr, "u\0r\0l(\\1$secremoveimg\\2)", $content);
-
- } else {
- $content = preg_replace('/url/i',"u\0r\0l",$content);
- }
- break;
- /**
- * Fix urls that refer to cid:
- */
- case 'cid':
- $cidurl = 'cid:'. $matches[2];
- $httpurl = sq_cid2http($message, $id, $cidurl, $mailbox);
- // escape parentheses that can modify the regular expression
- $cidurl = str_replace(array('(',')'),array('\\(','\\)'),$cidurl);
- $content = preg_replace("|url\s*\(\s*$cidurl\s*\)|si",
- "u\0r\0l($httpurl)", $content);
- break;
- default:
- /**
- * replace url with protocol other then the white list
- * http,https and cid by an empty string.
- */
- $content = preg_replace("/url\s*\(\s*[\'\"]?([^:]+):(.*)?[\'\"]?\s*\)/si",
- "", $content);
- break;
+ preg_match_all("/url\s*\((.+)\)/si",$content,$aMatch);
+ if (count($aMatch)) {
+ $aValue = $aReplace = array();
+ foreach($aMatch[1] as $sMatch) {
+ // url value
+ $urlvalue = $sMatch;
+ sq_fix_url('style',$urlvalue, $message, $id, $mailbox,"'");
+ $aValue[] = $sMatch;
+ $aReplace[] = $urlvalue;
}
+ $content = str_replace($aValue,$aReplace,$content);
}
- // remove NUL
- $content = str_replace("\0", "", $content);
- /**
- * Remove any backslashes, entities, and extraneous whitespace.
- */
+
+ /**
+ * Remove any backslashes, entities, and extraneous whitespace.
+ */
$contentTemp = $content;
sq_defang($contentTemp);
sq_unspace($contentTemp);
$cidurl = preg_replace($match_str, $str_rep, $cidurl);
$linkurl = find_ent_id($cidurl, $message);
- /* in case of non-save cid links $httpurl should be replaced by a sort of
- unsave link image */
+ /* in case of non-safe cid links $httpurl should be replaced by a sort of
+ unsafe link image */
$httpurl = '';
/**
"idiocy",
"idiocy",
"idiocy",
- "",
+ "idiocy",
"url",
"url(\\1#\\1)",
"url(\\1#\\1)",
)
)
);
- if( !sqgetGlobalVar('view_unsafe_images', $view_unsafe_images, SQ_GET) ) {
- $view_unsafe_images = false;
- }
+
+ // If there's no "view_unsafe_images" variable in the URL, turn unsafe
+ // images off by default.
+ sqgetGlobalVar('view_unsafe_images', $view_unsafe_images, SQ_GET, FALSE);
+
if (!$view_unsafe_images){
/**
* Remove any references to http/https if view_unsafe_images set
$id,
$mailbox
);
- if (preg_match("|$secremoveimg|i", $trusted)){
+ if (strpos($trusted,$secremoveimg)){
$has_unsafe_images = true;
}