$structure_end = substr($structure, $endprop+2);
$structure = trim(substr($structure,0,$startprop));
}
-
/* get type1 */
$pos = strrpos($structure,' ');
+ if ($structure{$pos+1} =='(') $pos++;
+
$type1 = strtolower(substr($structure, $pos+2, (count($structure)-2)));
-
/* cut off type1 */
if ($pos && $startprop) {
$structure = trim(substr($structure, 0, $pos));
$pos++;
}
$structure = substr($structure, strlen($text) + 2);
+ } else if ($char == '{') {
+ /**
+ * loop through until we find the matching quote,
+ * and return that as a string
+ */
+ $pos = 1;
+ $len = '';
+ while (($char = $structure{$pos}) != '}'
+ && $pos < strlen($structure)) {
+ $len .= $char;
+ $pos++;
+ }
+ $structure = substr($structure, strlen($len) + 4);
+ $text = substr($structure, 0, $len);
+ $structure = substr($structure, $len + 1);
} else if ($char == '(') {
// comment me
$end = mime_match_parenthesis (0, $structure);
$j = strlen( $structure );
- // ignore all extra characters
- // If inside of a string, skip string -- Boundary IDs and other
- // things can have ) in them.
+ /*
+ * ignore all extra characters
+ * If inside of a quoted string or literal, skip it -- Boundary IDs and other
+ * things can have ) in them.
+ */
+
if ( $structure{$pos} != '(' ) {
return( $j );
}
$pos++;
if ($structure{$pos} == ')') {
return $pos;
- } elseif ($structure{$pos} == '"') {
+ } elseif ($structure{$pos} == '"') { /* check for quoted string */
$pos++;
while ( $structure{$pos} != '"' &&
$pos < $j ) {
}
$pos++;
}
+ } elseif ($structure{$pos} == '{') { /* check for literal */
+ $str = substr($structure, $pos);
+ $pos++;
+ if (preg_match("/^\{(\d+)\}.*/",$str,$reg)) {
+ $pos = $pos + strlen($reg[1]) + $reg[1] + 2;
+ }
} elseif ( $structure{$pos} == '(' ) {
$pos = mime_match_parenthesis ($pos, $structure);
}
return( $pos );
}
-function mime_fetch_body($imap_stream, $id, $ent_id ) {
+function mime_fetch_body($imap_stream, $id, $ent_id) {
/*
* do a bit of error correction. If we couldn't find the entity id, just guess
if (!$ent_id) {
$ent_id = 1;
}
-
$cmd = "FETCH $id BODY[$ent_id]";
- $data = sqimap_run_command ($imap_stream, $cmd, true, $response, $message);
+ $data = sqimap_run_command ($imap_stream, $cmd, true, $response, $message);
do {
$topline = trim(array_shift( $data ));
} while( $topline && $topline[0] == '*' && !preg_match( '/\* [0-9]+ FETCH.*/i', $topline )) ;
* figures out what entity to display and returns the $message object
* for that entity.
*/
-function findDisplayEntity ($msg, $textOnly = 1) {
+function findDisplayEntity ($msg, $textOnly = true, $entity = array() ) {
global $show_html_default;
- $entity = 0;
-
+ $found = false;
if ($msg) {
- if ( $msg->header->type0 == 'multipart' &&
- ( $msg->header->type1 == 'alternative' ||
- $msg->header->type1 == 'mixed' ||
- $msg->header->type1 == 'related' ) &&
- $show_html_default && ! $textOnly ) {
- $entity = findDisplayEntityHTML($msg);
- }
-
- // Show text/plain or text/html -- the first one we find.
- if ( $entity == 0 &&
+ $type = $msg->header->type0.'/'.$msg->header->type1;
+ if ( $type == 'multipart/alternative') {
+ $msg = findAlternativeEntity($msg, $textOnly);
+ if (count($msg->entities) == 0) {
+ $entity[] = $msg->header->entity_id;
+ } else {
+ $found = true;
+ $entity =findDisplayEntity($msg,$textOnly, $entity);
+ }
+ } else if ( $type == 'multipart/related') {
+ $msgs = findRelatedEntity($msg);
+ for ($i = 0; $i < count($msgs); $i++) {
+ $msg = $msgs[$i];
+ if (count($msg->entities) == 0) {
+ $entity[] = $msg->header->entity_id;
+ } else {
+ $found = true;
+ $entity =findDisplayEntity($msg,$textOnly, $entity);
+ }
+ }
+ } else if ( count($entity) == 0 &&
$msg->header->type0 == 'text' &&
( $msg->header->type1 == 'plain' ||
$msg->header->type1 == 'html' ) &&
isset($msg->header->entity_id) ) {
- $entity = $msg->header->entity_id;
- }
-
- $i = 0;
- while ($entity == 0 && isset($msg->entities[$i]) ) {
- $entity = findDisplayEntity($msg->entities[$i], $textOnly);
- $i++;
- }
+ if (count($msg->entities) == 0) {
+ $entity[] = $msg->header->entity_id;
+ }
+ }
+ $i = 0;
+ while ( isset($msg->entities[$i]) && count($entity) == 0 && !$found ) {
+ $entity = findDisplayEntity($msg->entities[$i], $textOnly, $entity);
+ $i++;
+ }
+ }
+ if ( !isset($entity[0]) ) {
+ $entity[]="";
}
-
return( $entity );
}
isset($message->header->entity_id)) {
return 0;
}
+
$entity = findDisplayEntityHTML($message->entities[$i]);
if ($entity != 0) {
return $entity;
return 0;
}
+function findAlternativeEntity ($message, $textOnly) {
+ global $show_html_default;
+ /* if we are dealing with alternative parts then we choose the best
+ * viewable message supported by SM.
+ */
+ if ($show_html_default && !$textOnly) {
+ $alt_order = array ('text/plain','text/html');
+ } else {
+ $alt_order = array ('text/plain');
+ }
+ $best_view = 0;
+ $ent_id = 0;
+ $k = 0;
+ for ($i = 0; $i < count($message->entities); $i ++) {
+ $type = $message->entities[$i]->header->type0.'/'.$message->entities[$i]->header->type1;
+ if ($type == 'multipart/related') {
+ $type = $message->entities[$i]->header->type;
+ }
+ for ($j = $k; $j < count($alt_order); $j++) {
+ if ($alt_order[$j] == $type && $j > $best_view) {
+ $best_view = $j;
+ $ent_id = $i;
+ $k = $j;
+ }
+ }
+ }
+ return $message->entities[$ent_id];
+}
+
+function findRelatedEntity ($message) {
+ $msgs = array();
+ for ($i = 0; $i < count($message->entities); $i ++) {
+ $type = $message->entities[$i]->header->type0.'/'.$message->entities[$i]->header->type1;
+ if ($message->header->type == $type) {
+ $msgs[] = $message->entities[$i];
+ }
+ }
+ return $msgs;
+}
+
/*
* translateText
* Extracted from strings.php 23/03/2002
everything needed, including HTML Tags, Attachments at the
bottom, etc.
*/
-function formatBody($imap_stream, $message, $color, $wrap_at) {
+function formatBody($imap_stream, $message, $color, $wrap_at, $ent_num) {
// this if statement checks for the entity to show as the
// primary message. To add more of them, just put them in the
// order that is their priority.
- global $startMessage, $username, $key, $imapServerAddress, $imapPort, $body,
+ global $startMessage, $username, $key, $imapServerAddress, $imapPort,
$show_html_default, $has_unsafe_images, $view_unsafe_images, $sort;
$has_unsafe_images = 0;
$id = $message->header->id;
$urlmailbox = urlencode($message->header->mailbox);
- // Get the right entity and redefine message to be this entity
- // Pass the 0 to mean that we want the 'best' viewable one
- $ent_num = findDisplayEntity ($message, 0);
+
$body_message = getEntity($message, $ent_num);
if (($body_message->header->type0 == 'text') ||
($body_message->header->type0 == 'rfc822')) {
- $body = mime_fetch_body ($imap_stream, $id, $ent_num);
+ $body = mime_fetch_body ($imap_stream, $id, $ent_num);
+
$body = decodeBody($body, $body_message->header->encoding);
$hookResults = do_hook("message_body", $body);
$body = $hookResults[1];
$body = strip_tags( $body );
translateText($body, $wrap_at, $body_message->header->charset);
} else {
- $body = MagicHTML( $body, $id );
+ $body = magicHTML( $body, $id, $message );
}
} else {
translateText($body, $wrap_at, $body_message->header->charset);
}
-
$body .= "<CENTER><SMALL><A HREF=\"../src/download.php?absolute_dl=true&passed_id=$id&passed_ent_id=$ent_num&mailbox=$urlmailbox&showHeaders=1\">". _("Download this as a file") ."</A></SMALL></CENTER><BR>";
if ($has_unsafe_images) {
if ($view_unsafe_images) {
/** Display the ATTACHMENTS: message if there's more than one part **/
if (isset($message->entities[1])) {
- $body .= formatAttachments ($message, $ent_num, $message->header->mailbox, $id);
+ /* Header-type alternative means we choose the best one to display
+ so don't show the alternatives as attachment. Header-type related
+ means that the attachments are already part of the related message.
+ */
+ if ($message->header->type1 !='related' && $message->header->type1 !='alternative') {
+ $body .= formatAttachments ($message, $ent_num, $message->header->mailbox, $id);
+ }
}
} else {
$body = formatAttachments ($message, -1, $message->header->mailbox, $id);
global $show_html_default;
- if ($encoding == 'quoted-printable') {
+ if ($encoding == 'quoted-printable' ||
+ $encoding == 'quoted_printable') {
$body = quoted_printable_decode($body);
if (sizeof($matches{1})){
$count = strlen($matches{1});
$offset += $count;
- //if ($pos >= strlen($body)){
- //}
}
return $offset;
}
* A comment or an SGML declaration.
*/
if (substr($body, $pos+1, 2) == "--"){
- $gt = strpos($body, "-->", $pos)+2;
+ $gt = strpos($body, "-->", $pos);
if ($gt === false){
$gt = strlen($body);
- }
+ } else {
+ $gt += 2;
+ }
return Array(false, false, false, $lt, $gt);
} else {
$gt = sq_findnxstr($body, $pos, ">");
*/
$matches = Array();
if (preg_match("%^(\s*)(>|/>)%s", substr($body, $pos), $matches)) {
- if ($matches{0}){
- /**
- * Yep. So we did.
- */
- $pos += strlen($matches{1});
- if ($matches{2} == "/>"){
- $tagtype = 3;
- $pos++;
- }
- return Array($tagname, $attary, $tagtype, $lt, $pos);
- }
- }
+ /**
+ * Yep. So we did.
+ */
+ $pos += strlen($matches{1});
+ if ($matches{2} == "/>"){
+ $tagtype = 3;
+ $pos++;
+ }
+ return Array($tagname, $attary, $tagtype, $lt, $pos);
+ }
/**
* There are several types of attributes, with optional
$pos++;
$tagtype = 3;
} else {
- $gt = getnxstr($body, $pos, ">");
+ $gt = sq_findnxstr($body, $pos, ">");
$retary = Array(false, false, false, $lt, $gt);
return $retary;
}
}
/**
- * Fix stupid expression: declarations which lead to vulnerabilities
+ * Fix stupid css declarations which lead to vulnerabilities
* in IE.
*/
- $content = preg_replace("/expression\s*:/si", "idiocy:", $content);
+ $match = Array('/expression/si',
+ '/behaviou*r/si',
+ '/binding/si');
+ $replace = Array('idiocy', 'idiocy', 'idiocy');
+ $content = preg_replace($match, $replace, $content);
return $content;
}
$open_tags = Array();
$trusted = "<!-- begin sanitized html -->\n";
$skip_content = false;
+ /**
+ * Take care of netscape's stupid javascript entities like
+ * &{alert('boo')};
+ */
+ $body = preg_replace("/&(\{.*?\};)/si", "&\\1", $body);
while (($curtag=sq_getnxtag($body, $curpos)) != FALSE){
list($tagname, $attary, $tagtype, $lt, $gt) = $curtag;
* content before we apply it.
*/
$free_content = sq_fixstyle($message, $id, $free_content);
- } else if ($tagname == "body"){
- $tagname = "div";
- if ($tagtype == 1){
- $attary = sq_body2div($attary);
- }
}
if ($skip_content == false){
$trusted .= $free_content;
$skip_content = false;
} else {
if ($skip_content == false){
- if (isset($open_tags{$tagname}) &&
- $open_tags{$tagname} > 0){
- $open_tags{$tagname}--;
+ if ($tagname == "body"){
+ $tagname = "div";
} else {
- $tagname = false;
+ if (isset($open_tags{$tagname}) &&
+ $open_tags{$tagname} > 0){
+ $open_tags{$tagname}--;
+ } else {
+ $tagname = false;
+ }
}
} else {
}
$id
);
}
+ /**
+ * Convert body into div.
+ */
+ if ($tagname == "body"){
+ $tagname = "div";
+ $attary = sq_body2div($attary, $message, $id);
+ }
}
}
} else {
* @param $id the id of the message
* @return a string with html safe to display in the browser.
*/
-function magicHTML($body, $id){
+function magicHTML($body, $id, $message){
global $attachment_common_show_images, $view_unsafe_images,
- $has_unsafe_images, $message;
+ $has_unsafe_images;
/**
* Don't display attached images in HTML mode.
*/
"/.*/" =>
Array(
"/target/si",
- "/^on.*/si"
+ "/^on.*/si",
+ "/^dynsrc/si",
+ "/^data.*/si"
)
);
Array(
Array(
"|^([\'\"])\s*\.\./.*([\'\"])|si",
- "/^([\'\"])\s*\S+script\s*:.*([\'\"])/si"
+ "/^([\'\"])\s*\S+script\s*:.*([\'\"])/si",
+ "/^([\'\"])\s*mocha\s*:*.*([\'\"])/si",
+ "/^([\'\"])\s*about\s*:.*([\'\"])/si"
),
Array(
"\\1$secremoveimg\\2",
- "\\1$secremoveimg\\2"
+ "\\1$secremoveimg\\2",
+ "\\1$secremoveimg\\2",
+ "\\1$secremoveimg\\2"
)
),
"/^style/si" =>
Array(
Array(
- "/expression\s*:/si",
+ "/expression/si",
+ "/binding/si",
+ "/behaviou*r/si",
"|url\(([\'\"])\s*\.\./.*([\'\"])\)|si",
"/url\(([\'\"])\s*\S+script:.*([\'\"])\)/si"
),
Array(
- "idiocy:",
+ "idiocy",
+ "idiocy",
+ "idiocy",
"url(\\1$secremoveimg\\2)",
"url(\\1$secremoveimg\\2)"
)
* Remove any references to http/https if view_unsafe_images set
* to false.
*/
- $addendum = Array(
- "/.*/" =>
- Array(
- "/^src|background/i" =>
- Array(
- Array(
- "/^([\'\"])\s*https*:.*([\'\"])/si"
- ),
- Array(
- "\\1$secremoveimg\\2"
- )
- ),
- "/^style/si" =>
- Array(
- Array(
- "/url\(([\'\"])\s*https*:.*([\'\"])\)/si"
- ),
- Array(
- "url(\\1$secremoveimg\\2)"
- )
- )
- )
- );
- $bad_attvals = array_merge($bad_attvals, $addendum);
+ array_push($bad_attvals{'/.*/'}{'/^src|background|href|action/i'}[0],
+ '/^([\'\"])\s*https*:.*([\'\"])/si');
+ array_push($bad_attvals{'/.*/'}{'/^src|background|href|action/i'}[1],
+ "\\1$secremoveimg\\2");
+ array_push($bad_attvals{'/.*/'}{'/^style/si'}[0],
+ '/url\(([\'\"])\s*https*:.*([\'\"])\)/si');
+ array_push($bad_attvals{'/.*/'}{'/^style/si'}[1],
+ "url(\\1$secremoveimg\\2)");
}
$add_attr_to_tag = Array(