global $username, $attachment_dir;
$hashed_attachment_dir = getHashedDir($username, $attachment_dir);
$filename = $message->att_local_name;
+
+ // inspect attached file for lines longer than allowed by RFC,
+ // in which case we'll be using base64 encoding (so we can split
+ // the lines up without corrupting them) instead of 8bit unencoded...
+ // (see RFC 2822/2.1.1)
+ //
+ // using 990 because someone somewhere is folding lines at
+ // 990 instead of 998 and I'm too lazy to find who it is
+ //
+ $file_has_long_lines = file_has_long_lines($hashed_attachment_dir
+ . '/' . $filename, 990);
+
$file = fopen ($hashed_attachment_dir . '/' . $filename, 'rb');
- while ($body_part = fgets($file, 4096)) {
- // remove NUL characters
- $body_part = str_replace("\0",'',$body_part);
- $length += $this->clean_crlf($body_part);
- if ($stream) {
- $this->preWriteToStream($body_part);
- $this->writeToStream($stream, $body_part);
+
+ // long lines were found, need to use base64 encoding
+ //
+ if ($file_has_long_lines) {
+ while ($tmp = fread($file, 570)) {
+ $body_part = chunk_split(base64_encode($tmp));
+ // Up to 4.3.10 chunk_split always appends a newline,
+ // while in 4.3.11 it doesn't if the string to split
+ // is shorter than the chunk length.
+ if( substr($body_part, -1 , 1 ) != "\n" )
+ $body_part .= "\n";
+ $length += $this->clean_crlf($body_part);
+ if ($stream) {
+ $this->writeToStream($stream, $body_part);
+ }
}
- $last = $body_part;
}
+
+ // no excessively long lines - normal 8bit
+ //
+ else {
+ while ($body_part = fgets($file, 4096)) {
+ // remove NUL characters
+ $body_part = str_replace("\0",'',$body_part);
+ $length += $this->clean_crlf($body_part);
+ if ($stream) {
+ $this->preWriteToStream($body_part);
+ $this->writeToStream($stream, $body_part);
+ }
+ $last = $body_part;
+ }
+ }
+
fclose($file);
}
break;
if ($mime_header->encoding) {
$header[] = 'Content-Transfer-Encoding: ' . $mime_header->encoding . $rn;
} else {
- if ($mime_header->type0 == 'text' || $mime_header->type0 == 'message') {
- $header[] = 'Content-Transfer-Encoding: 8bit' . $rn;
- } else if ($mime_header->type0 == 'multipart' || $mime_header->type0 == 'alternative') {
+
+ // inspect attached file for lines longer than allowed by RFC,
+ // in which case we'll be using base64 encoding (so we can split
+ // the lines up without corrupting them) instead of 8bit unencoded...
+ // (see RFC 2822/2.1.1)
+ //
+ if (!empty($message->att_local_name)) { // is this redundant? I have no idea
+ global $username, $attachment_dir;
+ $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
+ $filename = $hashed_attachment_dir . '/' . $message->att_local_name;
+
+ // using 990 because someone somewhere is folding lines at
+ // 990 instead of 998 and I'm too lazy to find who it is
+ //
+ $file_has_long_lines = file_has_long_lines($filename, 990);
+ } else
+ $file_has_long_lines = FALSE;
+
+ if ($mime_header->type0 == 'multipart' || $mime_header->type0 == 'alternative') {
/* no-op; no encoding needed */
+ } else if (($mime_header->type0 == 'text' || $mime_header->type0 == 'message')
+ && !$file_has_long_lines) {
+ $header[] = 'Content-Transfer-Encoding: 8bit' . $rn;
} else {
$header[] = 'Content-Transfer-Encoding: base64' . $rn;
}
}
+/**
+ * Determine if there are lines in a file longer than a given length
+ *
+ * @param string $filename The full file path of the file to inspect
+ * @param int $max_length If any lines in the file are GREATER THAN
+ * this number, this function returns TRUE.
+ *
+ * @return boolean TRUE as explained above, otherwise, (no long lines
+ * found) FALSE is returned.
+ *
+ */
+function file_has_long_lines($filename, $max_length) {
+
+ $FILE = @fopen($filename, 'rb');
+
+ if ($FILE) {
+ while (!feof($FILE)) {
+ $buffer = fgets($FILE, 4096);
+ if (strlen($buffer) > $max_length) {
+ fclose($FILE);
+ return TRUE;
+ }
+ }
+ fclose($FILE);
+ }
+
+ return FALSE;
+}
+
+