X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=functions%2Fmime.php;h=8c4404f59efd99ba0c48ad462c69679928009be0;hb=3d6c7e964247034a8e7c1853d63badc02dcaebdd;hp=cab32d51ce4b147c194e4b686ee3934e3f98ad51;hpb=2d32cb9fa03e48b447881b5950ee8e194feb32e5;p=squirrelmail.git diff --git a/functions/mime.php b/functions/mime.php index cab32d51..8c4404f5 100644 --- a/functions/mime.php +++ b/functions/mime.php @@ -4,6 +4,7 @@ ** This contains the functions necessary to detect and decode MIME ** messages. ** + ** $Id$ **/ $debug_mime = false; @@ -23,10 +24,11 @@ /** msg_header contains generic variables for values that **/ /** could be in a header. **/ - var $type0, $type1, $boundary, $charset, $encoding, $size; - var $to, $from, $date, $cc, $bcc, $reply_to, $subject; - var $id, $mailbox, $description; - var $entity_id, $message_id, $charset; + var $type0 = '', $type1 = '', $boundary = '', $charset = ''; + var $encoding = '', $size = 0, $to = array(), $from = '', $date = ''; + var $cc = array(), $bcc = array(), $reply_to = '', $subject = ''; + var $id = 0, $mailbox = '', $description = '', $filename = ''; + var $entity_id = 0, $message_id = 0, $name = ''; } class message { @@ -35,11 +37,11 @@ more objects of type message. See documentation in mime.txt for a better description of how this works. **/ - var $header; - var $entities; + var $header = ''; + var $entities = array(); function addEntity ($msg) { - $this->entities[count($this->entities)] = $msg; + $this->entities[] = $msg; } } @@ -58,14 +60,17 @@ $id = $header->id; fputs ($imap_stream, "a001 FETCH $id BODYSTRUCTURE\r\n"); + // + // This should use sqimap_read_data instead of reading it itself + // $read = fgets ($imap_stream, 10000); $response = substr($read, 0, 4); + $bodystructure = ""; while ($response != "a001") { $bodystructure .= $read; $read = fgets ($imap_stream, 10000); $response = substr($read, 0, 4); } - // $read = strtolower($bodystructure); $read = $bodystructure; if ($debug_mime) echo "$read

\n"; @@ -114,7 +119,7 @@ } else { // parse the elements if ($debug_mime) echo "
$structure
"; - $msg = mime_get_element (&$structure, $msg, $ent_id); + $msg = mime_get_element ($structure, $msg, $ent_id); if ($debug_mime) echo "
"; } return $msg; @@ -156,6 +161,7 @@ $elem_num = 1; $msg->header = new msg_header(); $msg->header->entity_id = $ent_id; + $properties = array(); while (strlen($structure) > 0) { $structure = trim($structure); @@ -168,6 +174,7 @@ // loop through until we find the matching quote, and return that as a string $pos = 1; $char = substr($structure, $pos, 1); + $text = ""; while ($char != "\"" && $pos < strlen($structure)) { $text .= $char; $pos++; @@ -184,6 +191,7 @@ // loop through until we find a space or an end parenthesis $pos = 0; $char = substr($structure, $pos, 1); + $text = ""; while ($char != " " && $char != ")" && $pos < strlen($structure)) { $text .= $char; $pos++; @@ -288,6 +296,7 @@ if ($char == "\"") { $pos = 1; $char = substr($structure, $pos, 1); + $tmp = ""; while ($char != "\"" && $pos < strlen($structure)) { $tmp .= $char; $pos++; @@ -299,6 +308,7 @@ if ($char == "\"") { $pos = 1; $char = substr($structure, $pos, 1); + $value = ""; while ($char != "\"" && $pos < strlen($structure)) { $value .= $char; $pos++; @@ -312,6 +322,8 @@ } else if ($char == "(") { $end = mime_match_parenthesis (0, $structure); $sub = substr($structure, 1, $end-1); + if (! isset($props)) + $props = array(); $props = mime_get_props($props, $sub); $structure = substr($structure, strlen($sub) + 2); } @@ -339,6 +351,8 @@ // ignore all extra characters // If inside of a string, skip string -- Boundary IDs and other // things can have ) in them. + if ($char != '(') + return strlen($structure); while ($pos < strlen($structure)) { $pos++; $char = substr($structure, $pos, 1); @@ -348,12 +362,18 @@ $pos ++; while (substr($structure, $pos, 1) != '"' && $pos < strlen($structure)) { + if (substr($structure, $pos, 2) == '\\"') + $pos ++; + elseif (substr($structure, $pos, 2) == '\\\\') + $pos ++; $pos ++; } } else if ($char == "(") { $pos = mime_match_parenthesis ($pos, $structure); } } + echo "Error decoding mime structure. Report this as a bug!
\n"; + return $pos; } function mime_fetch_body ($imap_stream, $id, $ent_id) { @@ -361,15 +381,14 @@ // that it is the first one. That is usually the case anyway. if (!$ent_id) $ent_id = 1; - fputs ($imap_stream, "a001 FETCH $id BODY[$ent_id]\r\n"); - $data = sqimap_read_data ($imap_stream, 'a001', true, $response, $message); + fputs ($imap_stream, "a010 FETCH $id BODY[$ent_id]\r\n"); + $data = sqimap_read_data ($imap_stream, 'a010', true, $response, $message); $topline = array_shift($data); - while (! ereg('\* [0-9]+ FETCH ', $topline) && data) + while (! ereg('\\* [0-9]+ FETCH ', $topline) && data) $topline = array_shift($data); - while ($data) - $wholemessage .= array_shift($data); + $wholemessage = implode('', $data); - if (ereg('\{([^\}]*)\}', $topline, $regs)) { + if (ereg('\\{([^\\}]*)\\}', $topline, $regs)) { return substr($wholemessage, 0, $regs[1]); } else if (ereg('"([^"]*)"', $topline, $regs)) { @@ -390,6 +409,33 @@ return "Body retrival error, please report this bug!\n\nTop line is \"$topline\"\n"; } + function mime_print_body_lines ($imap_stream, $id, $ent_id, $encoding) { + // do a bit of error correction. If we couldn't find the entity id, just guess + // that it is the first one. That is usually the case anyway. + if (!$ent_id) $ent_id = 1; + + fputs ($imap_stream, "a001 FETCH $id BODY[$ent_id]\r\n"); + $cnt = 0; + $continue = true; + $read = fgets ($imap_stream,4096); + while (!ereg("^a001 (OK|BAD|NO)(.*)$", $read, $regs)) { + if (trim($read) == ")==") { + $read1 = $read; + $read = fgets ($imap_stream,4096); + if (ereg("^a001 (OK|BAD|NO)(.*)$", $read, $regs)) { + return; + } else { + echo decodeBody($read1, $encoding); + echo decodeBody($read, $encoding); + } + } else if ($cnt) { + echo decodeBody($read, $encoding); + } + $read = fgets ($imap_stream,4096); + $cnt++; + } + } + /* -[ END MIME DECODING ]----------------------------------------------------------- */ @@ -397,7 +443,7 @@ /** This is the first function called. It decides if this is a multipart message or if it should be handled as a single entity **/ - function decodeMime ($imap_stream, $body, $header) { + function decodeMime ($imap_stream, &$header) { global $username, $key, $imapServerAddress, $imapPort; return mime_structure ($imap_stream, $header); } @@ -422,7 +468,7 @@ if ($message->header->entity_id == $ent_id && strlen($ent_id) == strlen($message->header->entity_id)) { return $message; } else { - for ($i = 0; $message->entities[$i]; $i++) { + for ($i = 0; isset($message->entities[$i]); $i++) { $msg = getEntity ($message->entities[$i], $ent_id); if ($msg) return $msg; @@ -433,19 +479,48 @@ // figures out what entity to display and returns the $message object // for that entity. - function findDisplayEntity ($message) { - if ($message) { - if ($message->header->type0 == "text") { - if ($message->header->type1 == "plain" || - $message->header->type1 == "html") { - return $message->header->entity_id; - } - } else { - for ($i=0; $message->entities[$i]; $i++) { - return findDisplayEntity($message->entities[$i]); - } - } - } + function findDisplayEntity ($message, $textOnly = 1, $next = 'none') + { + global $show_html_default; + + if (! $message) + return; + + // Show text/plain or text/html -- the first one we find. + if ($message->header->type0 == 'text' && + ($message->header->type1 == 'plain' || + $message->header->type1 == 'html')) + { + // If the next part is an HTML version, this will + // all be true. Show it, if the user so desires. + // HTML mails this way all have entity_id of 2. 1 = text/plain + if ($next != 'none' && + $textOnly == 0 && + $next->header->type0 == "text" && + $next->header->type1 == "html" && + $next->header->entity_id == 2 && + $message->header->type1 == "plain" && + isset($show_html_default) && + $show_html_default) + $message = $next; + + if (isset($message->header->entity_id)) + return $message->header->entity_id; + } + else + { + for ($i=0; isset($message->entities[$i]); $i++) + { + $next = 'none'; + if (isset($message->entities[$i + 1])) + $next = $message->entities[$i + 1]; + $entity = findDisplayEntity($message->entities[$i], + $textOnly, $next); + if ($entity != 0) + return $entity; + } + } + return 0; } /** This returns a parsed string called $body. That string can then @@ -463,12 +538,13 @@ $urlmailbox = urlencode($message->header->mailbox); // Get the right entity and redefine message to be this entity - $ent_num = findDisplayEntity ($message); + // 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); // If there are other types that shouldn't be formatted, add @@ -481,7 +557,7 @@ /** Display the ATTACHMENTS: message if there's more than one part **/ $body .= ""; - if ($message->entities) { + if (isset($message->entities[0])) { $body .= formatAttachments ($message, $ent_num, $message->header->mailbox, $id); } } else { @@ -495,15 +571,16 @@ function formatAttachments ($message, $ent_id, $mailbox, $id) { global $where, $what; global $startMessage, $color; - static $ShownHTML; + static $ShownHTML = 0; + $body = ""; if ($ShownHTML == 0) { $ShownHTML = 1; $body .= "\n"; $body .= "
\n"; - $body .= _('Attachments') . ':'; + $body .= _("Attachments") . ':'; $body .= "
\n"; $body .= "\n"; @@ -519,11 +596,17 @@ if (!$message->entities) { $type0 = strtolower($message->header->type0); $type1 = strtolower($message->header->type1); + $name = decodeHeader($message->header->name); if ($message->header->entity_id != $ent_id) { $filename = decodeHeader($message->header->filename); if (trim($filename) == "") { - $display_filename = "untitled-".$message->header->entity_id; + if (trim($name) == "") { + $display_filename = "untitled-".$message->header->entity_id; + } else { + $display_filename = $name; + $filename = $name; + } } else { $display_filename = $filename; } @@ -535,7 +618,7 @@ "../src/download.php?startMessage=$startMessage&passed_id=$id&mailbox=$urlMailbox&passed_ent_id=$ent"; if ($where && $what) $DefaultLink .= '&where=' . urlencode($where) . '&what=' . urlencode($what); - $Links['download link']['text'] = _('download'); + $Links['download link']['text'] = _("download"); $Links['download link']['href'] = "../src/download.php?absolute_dl=true&passed_id=$id&mailbox=$urlMailbox&passed_ent_id=$ent"; $ImageURL = ''; @@ -609,7 +692,7 @@ // This functions decode strings that is encoded according to // RFC1522 (MIME Part Two: Message Header Extensions for Non-ASCII Text). function decodeHeader ($string) { - if (eregi('=\?([^?]+)\?(q|b)\?([^?]+)\?=', + if (eregi('=\\?([^?]+)\\?(q|b)\\?([^?]+)\\?=', $string, $res)) { if (ucfirst($res[2]) == "B") { $replace = base64_decode($res[3]); @@ -617,7 +700,7 @@ $replace = ereg_replace("_", " ", $res[3]); // Convert lowercase Quoted Printable to uppercase for // quoted_printable_decode to understand it. - while (ereg("(=([0-9][a-f])|([a-f][0-9])|([a-f][0-9]))", $replace, $res)) { + while (ereg("(=(([0-9][abcdef])|([abcdef][0-9])|([abcdef][abcdef])))", $replace, $res)) { $replace = str_replace($res[1], strtoupper($res[1]), $replace); } $replace = quoted_printable_decode($replace); @@ -625,9 +708,10 @@ $replace = charset_decode ($res[1], $replace); - $string = eregi_replace - ('=\?([^?]+)\?(q|b)\?([^?]+)\?=', + // Remove the name of the character set. + $string = eregi_replace ('=\\?([^?]+)\\?(q|b)\\?([^?]+)\\?=', $replace, $string); + // In case there should be more encoding in the string: recurse return (decodeHeader($string)); } else @@ -642,7 +726,6 @@ // Encode only if the string contains 8-bit characters or =? if (ereg("([\200-\377]|=\\?)", $string)) { - $newstring = "=?$default_charset?Q?"; // First the special characters $string = str_replace("=", "=3D", $string); @@ -650,10 +733,9 @@ $string = str_replace("_", "=5F", $string); $string = str_replace(" ", "_", $string); - - while (ereg("([\200-\377])", $string, $regs)) { - $replace = $regs[1]; - $insert = "=" . strtoupper(bin2hex($replace)); + for ( $ch = 127 ; $ch <= 255 ; $ch++ ) { + $replace = chr($ch); + $insert = sprintf("=%02X", $ch); $string = str_replace($replace, $insert, $string); }