X-Git-Url: https://vcs.fsf.org/?p=squirrelmail.git;a=blobdiff_plain;f=class%2Fdeliver%2FDeliver.class.php;h=45ed6ab8375faaa5033d7f57d713ed9e8f137991;hp=4d526a78e32d33ff2818bce74bbcba18673c0af8;hb=7c8a0b77c97d211c8900a47a88f9065f85605510;hpb=27ff4efb166979a1251e0a8b2faa801e55110ff9 diff --git a/class/deliver/Deliver.class.php b/class/deliver/Deliver.class.php index 4d526a78..45ed6ab8 100644 --- a/class/deliver/Deliver.class.php +++ b/class/deliver/Deliver.class.php @@ -1,15 +1,15 @@ rfc822_header; if (count($message->entities)) { $boundary = $this->mimeBoundary(); @@ -45,6 +54,37 @@ class Deliver { $boundary=''; } $raw_length = 0; + + + // calculate reply header if needed + // + if ($reply_id) { + global $imapConnection, $username, $imapServerAddress, + $imapPort, $mailbox; + if (!$imapConnection) + $imapConnection = sqimap_login($username, FALSE, + $imapServerAddress, $imapPort, 0); + + sqimap_mailbox_select($imapConnection, $mailbox); + $reply_message = sqimap_get_message($imapConnection, $reply_id, $mailbox); + + if ($reply_ent_id) { + /* redefine the messsage in case of message/rfc822 */ + $reply_message = $message->getEntity($reply_ent_id); + /* message is an entity which contains the envelope and type0=message + * and type1=rfc822. The actual entities are childs from + * $reply_message->entities[0]. That's where the encoding and is located + */ + + $orig_header = $reply_message->rfc822_header; /* here is the envelope located */ + + } else { + $orig_header = $reply_message->rfc822_header; + } + } + $message->reply_rfc822_header = $orig_header; + + $reply_rfc822_header = (isset($message->reply_rfc822_header) ? $message->reply_rfc822_header : ''); $header = $this->prepareRFC822_Header($rfc822_header, $reply_rfc822_header, $raw_length); @@ -151,8 +191,10 @@ class Deliver { } $last = $body_part; } elseif ($message->att_local_name) { + global $username, $attachment_dir; + $hashed_attachment_dir = getHashedDir($username, $attachment_dir); $filename = $message->att_local_name; - $file = fopen ($filename, 'rb'); + $file = fopen ($hashed_attachment_dir . '/' . $filename, 'rb'); while ($body_part = fgets($file, 4096)) { // remove NUL characters $body_part = str_replace("\0",'',$body_part); @@ -176,8 +218,10 @@ class Deliver { $this->writeToStream($stream, $body_part); } } elseif ($message->att_local_name) { + global $username, $attachment_dir; + $hashed_attachment_dir = getHashedDir($username, $attachment_dir); $filename = $message->att_local_name; - $file = fopen ($filename, 'rb'); + $file = fopen ($hashed_attachment_dir . '/' . $filename, 'rb'); while ($tmp = fread($file, 570)) { $body_part = chunk_split(base64_encode($tmp)); // Up to 4.3.10 chunk_split always appends a newline, @@ -378,7 +422,8 @@ class Deliver { * @return string $header */ function prepareRFC822_Header($rfc822_header, $reply_rfc822_header, &$raw_length) { - global $domain, $version, $username, $encode_header_key, $edit_identity, $hide_auth_header; + global $domain, $username, $encode_header_key, + $edit_identity, $hide_auth_header; /* if server var SERVER_NAME not available, use $domain */ if(!sqGetGlobalVar('SERVER_NAME', $SERVER_NAME, SQ_SERVER)) { @@ -394,7 +439,7 @@ class Deliver { $rn = "\r\n"; /* This creates an RFC 822 date */ - $date = date('D, j M Y H:i:s ', mktime()) . $this->timezone(); + $date = date('D, j M Y H:i:s ', time()) . $this->timezone(); /* Create a message-id */ $message_id = '<' . $REMOTE_PORT . '.'; if (isset($encode_header_key) && trim($encode_header_key)!='') { @@ -426,26 +471,38 @@ class Deliver { * unless you understand all possible forging issues or your * webmail installation does not prevent changes in user's email address. * See SquirrelMail bug tracker #847107 for more details about it. + * + * Add $hide_squirrelmail_header as a candidate for config_local.php + * to allow completely hiding SquirrelMail participation in message + * processing; This is dangerous, especially if users can modify their + * account information, as it makes mapping a sent message back to the + * original sender almost impossible. */ - if (isset($encode_header_key) && + $show_sm_header = ( defined('hide_squirrelmail_header') ? ! hide_squirrelmail_header : 1 ); + + if ( $show_sm_header ) { + if (isset($encode_header_key) && trim($encode_header_key)!='') { // use encoded headers, if encryption key is set and not empty $header[] = 'X-Squirrel-UserHash: '.OneTimePadEncrypt($username,base64_encode($encode_header_key)).$rn; $header[] = 'X-Squirrel-FromHash: '.OneTimePadEncrypt($this->ip2hex($REMOTE_ADDR),base64_encode($encode_header_key)).$rn; if (isset($HTTP_X_FORWARDED_FOR)) $header[] = 'X-Squirrel-ProxyHash:'.OneTimePadEncrypt($this->ip2hex($HTTP_X_FORWARDED_FOR),base64_encode($encode_header_key)).$rn; - } else { + } else { // use default received headers $header[] = "Received: from $received_from" . $rn; if ($edit_identity || ! isset($hide_auth_header) || ! $hide_auth_header) $header[] = " (SquirrelMail authenticated user $username)" . $rn; $header[] = " by $SERVER_NAME with HTTP;" . $rn; $header[] = " $date" . $rn; + } } /* Insert the rest of the header fields */ $header[] = 'Message-ID: '. $message_id . $rn; - if ($reply_rfc822_header->message_id) { + if (is_object($reply_rfc822_header) && + isset($reply_rfc822_header->message_id) && + $reply_rfc822_header->message_id) { $rep_message_id = $reply_rfc822_header->message_id; // $this->strip_crlf($message_id); $header[] = 'In-Reply-To: '.$rep_message_id . $rn; @@ -456,7 +513,8 @@ class Deliver { $header[] = 'Subject: '.encodeHeader($rfc822_header->subject) . $rn; $header[] = 'From: '. $rfc822_header->getAddr_s('from',",$rn ",true) . $rn; - // folding address list [From|To|Cc|Bcc] happens by using ",$rn" as delimiter + // folding address list [From|To|Cc|Bcc] happens by using ",$rn" + // as delimiter // Do not use foldLine for that. // RFC2822 if from contains more then 1 address @@ -483,7 +541,7 @@ class Deliver { } } /* Identify SquirrelMail */ - $header[] = 'User-Agent: SquirrelMail/' . $version . $rn; + $header[] = 'User-Agent: SquirrelMail/' . SM_VERSION . $rn; /* Do the MIME-stuff */ $header[] = 'MIME-Version: 1.0' . $rn; $contenttype = 'Content-Type: '. $rfc822_header->content_type->type0 .'/'. @@ -499,7 +557,7 @@ class Deliver { if ($encoding = $rfc822_header->encoding) { $header[] = 'Content-Transfer-Encoding: ' . $encoding . $rn; } - if ($rfc822_header->dnt) { + if (isset($rfc822_header->dnt) && $rfc822_header->dnt) { $dnt = $rfc822_header->getAddr_s('dnt'); /* Pegasus Mail */ $header[] = 'X-Confirm-Reading-To: '.$dnt. $rn; @@ -541,7 +599,9 @@ class Deliver { $aRefs = explode(' ',$sRefs); $sLine = 'References:'; foreach ($aRefs as $sReference) { - if (strlen($sLine)+strlen($sReference) >76) { + if ( trim($sReference) == '' ) { + /* Don't add spaces. */ + } elseif (strlen($sLine)+strlen($sReference) >76) { $hdr_s .= $sLine; $sLine = $rn . ' ' . $sReference; } else { @@ -705,27 +765,36 @@ class Deliver { } /** - * function calculate_references - calculate correct Referer string + * function calculate_references - calculate correct References string + * Adds the current message ID, and makes sure it doesn't grow forever, + * to that extent it drops message-ID's in a smart way until the string + * length is under the recommended value of 1000 ("References: <986>\r\n"). + * It always keeps the first and the last three ID's. * * @param Rfc822Header $hdr message header to calculate from * - * @return string $refer concatenated and trimmed Referer string + * @return string $refer concatenated and trimmed References string */ function calculate_references($hdr) { - $refer = $hdr->references; + $aReferences = preg_split('/\s+/', $hdr->references); $message_id = $hdr->message_id; $in_reply_to = $hdr->in_reply_to; - if (strlen($refer) > 2) { - $refer .= ' ' . $message_id; - } else { - if ($in_reply_to) { - $refer .= $in_reply_to . ' ' . $message_id; - } else { - $refer .= $message_id; - } + + // if References already exists, add the current message ID at the end. + // no References exists; if we know a IRT, add that aswell + if (count($aReferences) == 0 && $in_reply_to) { + $aReferences[] = $in_reply_to; + } + $aReferences[] = $message_id; + + // sanitize the array: trim whitespace, remove dupes + array_walk($aReferences, 'sq_trim_value'); + $aReferences = array_unique($aReferences); + + while ( count($aReferences) > 4 && strlen(implode(' ', $aReferences)) >= 986 ) { + $aReferences = array_merge(array_slice($aReferences,0,1),array_slice($aReferences,2)); } - trim($refer); - return $refer; + return implode(' ', $aReferences); } /** @@ -734,7 +803,7 @@ class Deliver { * Function is used to convert ipv4 and ipv6 addresses to hex strings. * It removes all delimiter symbols from ip addresses, converts decimal * ipv4 numbers to hex and pads strings in order to present full length - * address. ipv4 addresses are represented as 8 byte strings, ipv6 addresses + * address. ipv4 addresses are represented as 8 byte strings, ipv6 addresses * are represented as 32 byte string. * * If function fails to detect address format, it returns unprocessed string. @@ -789,4 +858,3 @@ class Deliver { return $ret; } } -?>