From 8685b47fc79c227d439177c8dc63de5a7bb95f76 Mon Sep 17 00:00:00 2001 From: Michael M Slusarz Date: Mon, 24 Nov 2008 14:00:45 -0700 Subject: [PATCH] Merge Horde_Mime_Message into Horde_Mime_Part. --- framework/Mime/lib/Horde/Mime/Mail.php | 2 +- framework/Mime/lib/Horde/Mime/Mdn.php | 4 +- framework/Mime/lib/Horde/Mime/Message.php | 399 ------------------------------ framework/Mime/lib/Horde/Mime/Part.php | 381 +++++++++++++++++++++++++++- framework/Mime/package.xml | 2 - 5 files changed, 380 insertions(+), 408 deletions(-) delete mode 100644 framework/Mime/lib/Horde/Mime/Message.php diff --git a/framework/Mime/lib/Horde/Mime/Mail.php b/framework/Mime/lib/Horde/Mime/Mail.php index 473e2e6be..7d8ae007c 100644 --- a/framework/Mime/lib/Horde/Mime/Mail.php +++ b/framework/Mime/lib/Horde/Mime/Mail.php @@ -409,7 +409,7 @@ class Horde_Mime_Mail } /* Build mime message. */ - $mime = new Horde_Mime_Message(); + $mime = new Horde_Mime_Part(); if (!empty($this->_body) && !empty($this->_htmlBody)) { $basepart = new Horde_Mime_Part('multipart/alternative'); $this->_body->setDescription(_("Plaintext Version of Message")); diff --git a/framework/Mime/lib/Horde/Mime/Mdn.php b/framework/Mime/lib/Horde/Mime/Mdn.php index b2acc8512..93a2e1003 100644 --- a/framework/Mime/lib/Horde/Mime/Mdn.php +++ b/framework/Mime/lib/Horde/Mime/Mdn.php @@ -133,7 +133,7 @@ class Horde_Mime_Mdn $err = array()) { require_once dirname(__FILE__) . '/Headers.php'; - require_once dirname(__FILE__) . '/Message.php'; + require_once dirname(__FILE__) . '/Part.php'; require_once 'Horde/Identity.php'; require_once 'Horde/Text.php'; @@ -172,7 +172,7 @@ class Horde_Mime_Mdn $msg_headers->addHeader('Subject', _("Disposition Notification")); /* MDNs are a subtype of 'multipart/report'. */ - $msg = new Horde_Mime_Message(); + $msg = new Horde_Mime_Part(); $msg->setType('multipart/report'); $msg->setContentTypeParameter('report-type', 'disposition-notification'); diff --git a/framework/Mime/lib/Horde/Mime/Message.php b/framework/Mime/lib/Horde/Mime/Message.php deleted file mode 100644 index fc2affeb3..000000000 --- a/framework/Mime/lib/Horde/Mime/Message.php +++ /dev/null @@ -1,399 +0,0 @@ - - * @author Michael Slusarz - * @package Horde_Mime - */ -class Horde_Mime_Message extends Horde_Mime_Part -{ - /** - * Sends this message. - * - * @param string $email The address list to send to. - * @param Horde_Mime_Headers $headers The Horde_Mime_Headers object - * holding this message's headers. - * @param string $driver The Mail:: driver to use. - * @param array $params Any parameters necessary for the - * Mail driver. - * - * @return mixed True on success, PEAR_Error on error. - */ - public function send($email, $headers, $driver, $params = array()) - { - require_once 'Mail.php'; - $mailer = Mail::factory($driver, $params); - - /* Add MIME Headers if they don't already exist. */ - if (!$headers->getValue('MIME-Version')) { - $headers = $this->addMimeHeaders($headers); - } - $headerArray = $headers->toArray(array('charset' => $this->getCharset())); - - /* Does the SMTP backend support 8BITMIME (RFC 1652) or - * BINARYMIME (RFC 3030) extensions? Requires PEAR's Mail package - * version 1.2+ and Net_SMTP version 1.3+. */ - if (($driver == 'smtp') && method_exists($mailer, 'getSMTPObject')) { - $net_smtp = $mailer->getSMTPObject(); - if (!is_a($net_smtp, 'PEAR_Error') && - method_exists($net_smtp, 'getServiceExtensions')) { - $smtp_ext = $net_smtp->getServiceExtensions(); - $message->strict7bit(false); - $encoding = $message->getTransferEncoding(); - if (($encoding == '8bit') && - isset($smtp_ext['8BITMIME'])) { - $mailer->addServiceExtensionParameter('BODY', '8BITMIME'); - } elseif (($encoding == 'binary') && - isset($smtp_ext['BINARYMIME'])) { - $mailer->addServiceExtensionParameter('BODY', 'BINARYMIME'); - } else { - $message->strict7bit(true); - $encoding = $message->getTransferEncoding(); - } - $headers->addHeader('Content-Transfer-Encoding', $encoding); - } - } - - /* Make sure the message has a trailing newline. */ - $msg = $this->toString(); - if (substr($msg, -1) != "\n") { - $msg .= "\n"; - } - - $result = $mailer->send(Horde_Mime::encodeAddress($email), $headerArray, $msg); - - if (is_a($result, 'PEAR_Error') && ($driver == 'sendmail')) { - $error = Horde_Mime_Mail::sendmailError($result->getCode()); - if (is_null($error)) { - $error = $result; - $userinfo = null; - } else { - $userinfo = $result->toString(); - } - return PEAR::raiseError($error, null, null, null, $userinfo); - } - - return $result; - } - - /** - * Get the list of MIME headers for this part in an array. - * - * @return array The full set of MIME headers. - */ - public function getHeaderArray() - { - /* Per RFC 2045 [4], this MUST appear in the message headers. */ - return parent::header(array('MIME-Version' => '1.0')); - } - - /** - * Finds the main "body" text part (if any) in a message. - * "Body" data is the first text part in the base MIME part. - * - * @param string $subtype Specifically search for this subtype. - * - * @return mixed The MIME ID of the main body part, or null if a body - part is not found. - */ - public function findBody($subtype = null) - { - foreach ($this->contentTypeMap() as $mime_id => $mime_type) { - if ((strpos($mime_type, 'text/') === 0) && - (intval($mime_id) == 1) && - (is_null($subtype) || (substr($mime_type, 5) == $subtype))) { - return $mime_id; - } - } - - return null; - } - - /** - * Parse an array of MIME structure information into a Horde_Mime_Message - * object. - * This function can be called statically via: - * $mime_message = Horde_Mime_Message::parseStructure(); - * - * @param array $structure An array of structure information in the - * following format: - *
-     * MANDATORY:
-     *   'type' - (string) The MIME type
-     *   'subtype' - (string) The MIME subtype
-     *
-     * The array MAY contain the following information:
-     *   'contents' - (string) The contents of the part.
-     *   'disposition' - (string) The disposition type of the part (e.g.
-     *                   'attachment', 'inline').
-     *   'dparameters' - (array) Attribute/value pairs from the part's
-     *                   Content-Disposition header.
-     *   'language' - (array) A list of body language values.
-     *   'location' - (string) The body content URI.
-     *
-     * Depending on the MIME type of the part, the array will also contain
-     * further information. If labeled as [OPTIONAL], the array MAY
-     * contain this information, but only if 'noext' is false and the
-     * server returned the requested information. Else, the value is not
-     * set.
-     *
-     * multipart/* parts:
-     * ==================
-     * 'parts' - (array) An array of subparts (follows the same format as
-     *           the base structure array).
-     * 'parameters' - [OPTIONAL] (array) Attribute/value pairs from the
-     *                part's Content-Type header.
-     *
-     * All other parts:
-     * ================
-     * 'parameters' - (array) Attribute/value pairs from the part's
-     *                Content-Type header.
-     * 'id' - (string) The part's Content-ID value.
-     * 'description' - (string) The part's Content-Description value.
-     * 'encoding' - (string) The part's Content-Transfer-Encoding value.
-     * 'size' - (integer) - The part's size in bytes.
-     * 'envelope' - [ONLY message/rfc822] (array) See 'envelope' response.
-     * 'structure' - [ONLY message/rfc822] (array) See 'structure'
-     *               response.
-     * 'lines' - [ONLY message/rfc822 and text/*] (integer) The size of
-     *           the body in text lines.
-     * 'md5' - [OPTIONAL] (string) The part's MD5 value.
-     * 
- * @param array $options Additional options: - *
-     * 'mimepart' - (boolean) Return a Horde_Mime_Part object instead of a
-     *              Horde_Mime_Message object?
-     * 
- * - * @return object A Horde_Mime_Message object. - */ - static public function parseStructure($structure, $options = array()) - { - $ob = self::_parseStructure($structure, empty($options['mimepart'])); - $ob->buildMimeIds(); - return $ob; - } - - /** - * Parse a subpart of a MIME message into a - * Horde_Mime_Message/Horde_Mime_Part object. - * - * @param array $data Structure information in the format described - * in parseStructure(). - * @param boolean $rfc822 Force the part to be treated as a - * message/rfc822 part. - * - * @return mixed Returns either a Horde_Mime_Message or a Horde_Mime_Part - * object, depending on the part's MIME type. - */ - static protected function _parseStructure($data, $rfc822 = false) - { - $type = $data['type'] . '/' . $data['subtype']; - - if ($rfc822 || ($type == 'message/rfc822')) { - $ob = new Horde_Mime_Message(); - } else { - $ob = new Horde_Mime_Part(); - } - - $ob->setType($type); - - if (isset($data['encoding'])) { - $ob->setTransferEncoding($data['encoding']); - } - - if (isset($data['contents'])) { - $ob->setContents($data['contents'], $ob->getTransferEncoding()); - $ob->transferDecodeContents(); - } - - if (isset($data['disposition'])) { - $ob->setDisposition($data['disposition']); - if (!empty($data['dparameters'])) { - foreach ($data['dparameters'] as $key => $val) { - /* Disposition parameters are supposed to be encoded via - * RFC 2231, but many mailers do RFC 2045 encoding - * instead. */ - // @todo: RFC 2231 decoding - $ob->setDispositionParameter($key, Horde_Mime::decode($val)); - } - } - } - - if (isset($data['size'])) { - $ob->setBytes($data['size']); - } - - if (isset($data['id'])) { - $ob->setContentId($data['id']); - } - - if (!empty($data['parameters'])) { - foreach ($data['parameters'] as $key => $val) { - /* Content-type parameters are supposed to be encoded via RFC - * 2231, but many mailers do RFC 2045 encoding instead. */ - // @todo: RFC 2231 decoding - $ob->setContentTypeParameter($key, Horde_Mime::decode($val)); - } - } - - /* Set the default character set. */ - if (($data['subtype'] == 'text') && - (String::lower($ob->getCharset()) == 'us-ascii') && - isset($GLOBALS['mime_structure']['default_charset'])) { - /* @todo - switch to using static variable for this. */ - //$ob->setCharset($GLOBALS['mime_structure']['default_charset']); - } - - if (isset($data['description'])) { - $ob->setDescription(Horde_Mime::decode($data['description'])); - } - - /* Set the name. */ - if (!$ob->getName()) { - $ob->setName($ob->getDispositionParameter('filename')); - } - - // @todo Handle language, location, md5, lines, envelope - - /* Add multipart parts. */ - if (!empty($data['parts'])) { - reset($data['parts']); - while (list(,$val) = each($data['parts'])) { - $ob->addPart(self::_parseStructure($val)); - } - } elseif (!empty($data['structure'])) { - $ob->addPart(self::_parseStructure($data['structure'])); - } - - return $ob; - } - - /** - * Attempts to build a Horde_Mime_Message object from message text. - * This function can be called statically via: - * $mime_message = Horde_Mime_Message::parseMessage(); - * - * @param string $text The text of the MIME message. - * @param array $options Additional options: - *
-     * 'mimepart' - (boolean) Return a Horde_Mime_Part object instead of a
-     *              Horde_Mime_Message object?
-     * 
- * - * @return Horde_Mime_Message A Horde_Mime_Message object, or false on - * error. - */ - static public function parseMessage($text, $options = array()) - { - /* Set up the options for the mimeDecode class. */ - $decode_args = array( - 'include_bodies' => true, - 'decode_bodies' => false, - 'decode_headers' => false - ); - - require_once 'Mail/mimeDecode.php'; - $mimeDecode = new Mail_mimeDecode($text, Horde_Mime_Part::EOL); - if (!($ob = $mimeDecode->decode($decode_args))) { - return false; - } - - return self::parseStructure(self::_convertMimeDecodeData($ob), $options); - } - - /** - * Convert the output from Mail_mimeDecode::decode() into a structure that - * parse() can handle. - * - * @param stdClass $ob The output from Mail_mimeDecode::decode(). - * - * @return array An array of structure information. - */ - static protected function _convertMimeDecodeData($ob) - { - /* Primary content-type. */ - if (isset($ob->ctype_primary)) { - $part = array( - 'type' => strtolower($ob->ctype_primary), - 'subtype' => isset($ob->ctype_secondary) ? strtolower($ob->ctype_secondary) : 'x-unknown' - ); - } else { - $part = array( - 'type' => 'application', - 'subtype' => 'octet-stream' - ); - } - - /* Content transfer encoding. */ - if (isset($ob->headers['content-transfer-encoding'])) { - $part['encoding'] = strtolower($ob->headers['content-transfer-encoding']); - } - - /* Content-type and Disposition parameters. */ - $param_types = array( - 'ctype_parameters' => 'parameters', - 'd_parameters' => 'dparameters' - ); - - foreach ($param_types as $param_key => $param_value) { - if (isset($ob->$param_key)) { - $part[$param_value] = array(); - foreach ($ob->$param_key as $key => $val) { - $part[$param_value][strtolower($key)] = $val; - } - } - } - - /* Content-Description. */ - if (isset($ob->headers['content-description'])) { - $part['description'] = $ob->headers['content-description']; - } - - /* Content-Disposition. */ - if (isset($ob->headers['content-disposition'])) { - $hdr = $ob->headers['content-disposition']; - $pos = strpos($hdr, ';'); - if ($pos !== false) { - $hdr = substr($hdr, 0, $pos); - } - $part['disposition'] = strtolower($hdr); - } - - /* Content-ID. */ - if (isset($ob->headers['content-id'])) { - $part['id'] = $ob->headers['content-id']; - } - - /* Get file size (if 'body' text is set). */ - if (isset($ob->body)) { - $part['contents'] = $ob->body; - if (($part['type'] != 'message') && - ($part['subtype'] != 'rfc822')) { - /* Mail_mimeDecode puts an extra linebreak at the end of body - * text. */ - $size = strlen(str_replace(array("\r\n", "\n"), array("\n", "\r\n"), $ob->body)) - 2; - $part['size'] = ($size < 0) ? 0 : $size; - } - } - - /* Process parts also. */ - if (isset($ob->parts)) { - $part['parts'] = array(); - reset($ob->parts); - while (list($key,) = each($ob->parts)) { - $part['parts'][] = self::_convertMimeDecodeData($ob->parts[$key]); - } - } - - return $part; - } - -} diff --git a/framework/Mime/lib/Horde/Mime/Part.php b/framework/Mime/lib/Horde/Mime/Part.php index e7d2ac4fc..4606163d9 100644 --- a/framework/Mime/lib/Horde/Mime/Part.php +++ b/framework/Mime/lib/Horde/Mime/Part.php @@ -169,9 +169,11 @@ class Horde_Mime_Part protected $_reindex = false; /** - * TODO + * Is this the base MIME part? + * + * @var boolean */ - protected $_headers; + protected $_basepart = false; /** * Set the content-disposition of this part. @@ -698,7 +700,7 @@ class Horde_Mime_Part */ public function getAllContentTypeParameters() { - return $this->_contentTypeParameters; + return $this->_contentTypeParams; } /** @@ -752,6 +754,13 @@ class Horde_Mime_Part */ public function getHeaderArray() { + $headers = array(); + + if ($this->_basepart) { + /* Per RFC 2046 [4], this MUST appear in the message headers. */ + $headers['MIME-Version'] = '1.0'; + } + $ptype = $this->getPrimaryType(); $stype = $this->getSubType(); @@ -961,7 +970,7 @@ class Horde_Mime_Part * MUST be in binary format. RFC 2046 [2.7, 2.8, 2.9]. Q-P and base64 * can handle binary data fine so no need to switch those encodings. */ if (in_array($encoding, array('8bit', '7bit')) && - preg_match('/\x00/', $this->_encoding)) { + preg_match('/\x00/', $this->_contents)) { $encoding = ($this->_encode7bit) ? 'base64' : 'binary'; } @@ -1330,4 +1339,368 @@ class Horde_Mime_Part return $map; } + /** + * Is this the base MIME part? + * + * @param boolean $base True if this is the base MIME part. + */ + public function isBasePart($base) + { + $this->_basepart = $base; + } + + /** + * Sends this message. + * + * @param string $email The address list to send to. + * @param Horde_Mime_Headers $headers The Horde_Mime_Headers object + * holding this message's headers. + * @param string $driver The Mail:: driver to use. + * @param array $params Any parameters necessary for the + * Mail driver. + * + * @return mixed True on success, PEAR_Error on error. + */ + public function send($email, $headers, $driver, $params = array()) + { + require_once 'Mail.php'; + $mailer = Mail::factory($driver, $params); + + $old_basepart = $this->_basepart; + $this->_basepart = true; + + /* Add MIME Headers if they don't already exist. */ + if (!$headers->getValue('MIME-Version')) { + $headers = $this->addMimeHeaders($headers); + } + $headerArray = $headers->toArray(array('charset' => $this->getCharset())); + + /* Does the SMTP backend support 8BITMIME (RFC 1652) or + * BINARYMIME (RFC 3030) extensions? Requires PEAR's Mail package + * version 1.2+ and Net_SMTP version 1.3+. */ + if (($driver == 'smtp') && method_exists($mailer, 'getSMTPObject')) { + $net_smtp = $mailer->getSMTPObject(); + if (!is_a($net_smtp, 'PEAR_Error') && + method_exists($net_smtp, 'getServiceExtensions')) { + $smtp_ext = $net_smtp->getServiceExtensions(); + $this->strict7bit(false); + $encoding = $this->getTransferEncoding(); + if (($encoding == '8bit') && + isset($smtp_ext['8BITMIME'])) { + $mailer->addServiceExtensionParameter('BODY', '8BITMIME'); + } elseif (($encoding == 'binary') && + isset($smtp_ext['BINARYMIME'])) { + $mailer->addServiceExtensionParameter('BODY', 'BINARYMIME'); + } else { + $this->strict7bit(true); + $encoding = $this->getTransferEncoding(); + } + $headers->addHeader('Content-Transfer-Encoding', $encoding); + } + } + + /* Make sure the message has a trailing newline. */ + $msg = $this->toString(); + if (substr($msg, -1) != "\n") { + $msg .= "\n"; + } + + $result = $mailer->send(Horde_Mime::encodeAddress($email), $headerArray, $msg); + + $this->_basepart = $old_basepart; + + if (is_a($result, 'PEAR_Error') && ($driver == 'sendmail')) { + $error = Horde_Mime_Mail::sendmailError($result->getCode()); + if (is_null($error)) { + $error = $result; + $userinfo = null; + } else { + $userinfo = $result->toString(); + } + return PEAR::raiseError($error, null, null, null, $userinfo); + } + + return $result; + } + + /** + * Finds the main "body" text part (if any) in a message. + * "Body" data is the first text part under this part. + * + * @param string $subtype Specifically search for this subtype. + * + * @return mixed The MIME ID of the main body part, or null if a body + part is not found. + */ + public function findBody($subtype = null) + { + foreach ($this->contentTypeMap() as $mime_id => $mime_type) { + if ((strpos($mime_type, 'text/') === 0) && + (intval($mime_id) == 1) && + (is_null($subtype) || (substr($mime_type, 5) == $subtype))) { + return $mime_id; + } + } + + return null; + } + + /** + * Parse an array of MIME structure information into a Horde_Mime_Part + * object. + * This function can be called statically via: + * $mime_part = Horde_Mime_Part::parseStructure(); + * + * @param array $structure An array of structure information in the + * following format: + *
+     * MANDATORY:
+     *   'type' - (string) The MIME type
+     *   'subtype' - (string) The MIME subtype
+     *
+     * The array MAY contain the following information:
+     *   'contents' - (string) The contents of the part.
+     *   'disposition' - (string) The disposition type of the part (e.g.
+     *                   'attachment', 'inline').
+     *   'dparameters' - (array) Attribute/value pairs from the part's
+     *                   Content-Disposition header.
+     *   'language' - (array) A list of body language values.
+     *   'location' - (string) The body content URI.
+     *
+     * Depending on the MIME type of the part, the array will also contain
+     * further information. If labeled as [OPTIONAL], the array MAY
+     * contain this information, but only if 'noext' is false and the
+     * server returned the requested information. Else, the value is not
+     * set.
+     *
+     * multipart/* parts:
+     * ==================
+     * 'parts' - (array) An array of subparts (follows the same format as
+     *           the base structure array).
+     * 'parameters' - [OPTIONAL] (array) Attribute/value pairs from the
+     *                part's Content-Type header.
+     *
+     * All other parts:
+     * ================
+     * 'parameters' - (array) Attribute/value pairs from the part's
+     *                Content-Type header.
+     * 'id' - (string) The part's Content-ID value.
+     * 'description' - (string) The part's Content-Description value.
+     * 'encoding' - (string) The part's Content-Transfer-Encoding value.
+     * 'size' - (integer) - The part's size in bytes.
+     * 'envelope' - [ONLY message/rfc822] (array) See 'envelope' response.
+     * 'structure' - [ONLY message/rfc822] (array) See 'structure'
+     *               response.
+     * 'lines' - [ONLY message/rfc822 and text/*] (integer) The size of
+     *           the body in text lines.
+     * 'md5' - [OPTIONAL] (string) The part's MD5 value.
+     * 
+ * + * @return object A Horde_Mime_Part object. + */ + static public function parseStructure($structure) + { + $ob = self::_parseStructure($structure); + $ob->buildMimeIds(); + return $ob; + } + + /** + * Parse a subpart of a MIME message into a Horde_Mime_Part object. + * + * @param array $data Structure information in the format described + * in parseStructure(). + * + * @return Horde_Mime_Part The generated object. + */ + static protected function _parseStructure($data) + { + $ob = new Horde_Mime_Part(); + $ob->setType($data['type'] . '/' . $data['subtype']); + + if (isset($data['encoding'])) { + $ob->setTransferEncoding($data['encoding']); + } + + if (isset($data['contents'])) { + $ob->setContents($data['contents'], $ob->getTransferEncoding()); + $ob->transferDecodeContents(); + } + + if (isset($data['disposition'])) { + $ob->setDisposition($data['disposition']); + if (!empty($data['dparameters'])) { + foreach ($data['dparameters'] as $key => $val) { + /* Disposition parameters are supposed to be encoded via + * RFC 2231, but many mailers do RFC 2045 encoding + * instead. */ + // @todo: RFC 2231 decoding + $ob->setDispositionParameter($key, Horde_Mime::decode($val)); + } + } + } + + if (isset($data['size'])) { + $ob->setBytes($data['size']); + } + + if (isset($data['id'])) { + $ob->setContentId($data['id']); + } + + if (!empty($data['parameters'])) { + foreach ($data['parameters'] as $key => $val) { + /* Content-type parameters are supposed to be encoded via RFC + * 2231, but many mailers do RFC 2045 encoding instead. */ + // @todo: RFC 2231 decoding + $ob->setContentTypeParameter($key, Horde_Mime::decode($val)); + } + } + + /* Set the default character set. */ + if (($data['subtype'] == 'text') && + (String::lower($ob->getCharset()) == 'us-ascii') && + isset($GLOBALS['mime_structure']['default_charset'])) { + /* @todo - switch to using static variable for this. */ + //$ob->setCharset($GLOBALS['mime_structure']['default_charset']); + } + + if (isset($data['description'])) { + $ob->setDescription(Horde_Mime::decode($data['description'])); + } + + /* Set the name. */ + if (!$ob->getName()) { + $ob->setName($ob->getDispositionParameter('filename')); + } + + // @todo Handle language, location, md5, lines, envelope + + /* Add multipart parts. */ + if (!empty($data['parts'])) { + reset($data['parts']); + while (list(,$val) = each($data['parts'])) { + $ob->addPart(self::_parseStructure($val)); + } + } elseif (!empty($data['structure'])) { + $ob->addPart(self::_parseStructure($data['structure'])); + } + + return $ob; + } + + /** + * Attempts to build a Horde_Mime_Part object from message text. + * This function can be called statically via: + * $mime_part = Horde_Mime_Part::parseMessage(); + * + * @param string $text The text of the MIME message. + * + * @return Horde_Mime_Part A Horde_Mime_Part object, or false on error. + */ + static public function parseMessage($text, $options = array()) + { + /* Set up the options for the mimeDecode class. */ + $decode_args = array( + 'include_bodies' => true, + 'decode_bodies' => false, + 'decode_headers' => false + ); + + require_once 'Mail/mimeDecode.php'; + $mimeDecode = new Mail_mimeDecode($text, Horde_Mime_Part::EOL); + if (!($ob = $mimeDecode->decode($decode_args))) { + return false; + } + + return self::parseStructure(self::_convertMimeDecodeData($ob), $options); + } + + /** + * Convert the output from Mail_mimeDecode::decode() into a structure that + * parse() can handle. + * + * @param stdClass $ob The output from Mail_mimeDecode::decode(). + * + * @return array An array of structure information. + */ + static protected function _convertMimeDecodeData($ob) + { + /* Primary content-type. */ + if (isset($ob->ctype_primary)) { + $part = array( + 'type' => strtolower($ob->ctype_primary), + 'subtype' => isset($ob->ctype_secondary) ? strtolower($ob->ctype_secondary) : 'x-unknown' + ); + } else { + $part = array( + 'type' => 'application', + 'subtype' => 'octet-stream' + ); + } + + /* Content transfer encoding. */ + if (isset($ob->headers['content-transfer-encoding'])) { + $part['encoding'] = strtolower($ob->headers['content-transfer-encoding']); + } + + /* Content-type and Disposition parameters. */ + $param_types = array( + 'ctype_parameters' => 'parameters', + 'd_parameters' => 'dparameters' + ); + + foreach ($param_types as $param_key => $param_value) { + if (isset($ob->$param_key)) { + $part[$param_value] = array(); + foreach ($ob->$param_key as $key => $val) { + $part[$param_value][strtolower($key)] = $val; + } + } + } + + /* Content-Description. */ + if (isset($ob->headers['content-description'])) { + $part['description'] = $ob->headers['content-description']; + } + + /* Content-Disposition. */ + if (isset($ob->headers['content-disposition'])) { + $hdr = $ob->headers['content-disposition']; + $pos = strpos($hdr, ';'); + if ($pos !== false) { + $hdr = substr($hdr, 0, $pos); + } + $part['disposition'] = strtolower($hdr); + } + + /* Content-ID. */ + if (isset($ob->headers['content-id'])) { + $part['id'] = $ob->headers['content-id']; + } + + /* Get file size (if 'body' text is set). */ + if (isset($ob->body)) { + $part['contents'] = $ob->body; + if (($part['type'] != 'message') && + ($part['subtype'] != 'rfc822')) { + /* Mail_mimeDecode puts an extra linebreak at the end of body + * text. */ + $size = strlen(str_replace(array("\r\n", "\n"), array("\n", "\r\n"), $ob->body)) - 2; + $part['size'] = ($size < 0) ? 0 : $size; + } + } + + /* Process parts also. */ + if (isset($ob->parts)) { + $part['parts'] = array(); + reset($ob->parts); + while (list($key,) = each($ob->parts)) { + $part['parts'][] = self::_convertMimeDecodeData($ob->parts[$key]); + } + } + + return $part; + } + } diff --git a/framework/Mime/package.xml b/framework/Mime/package.xml index ee6680bd1..17b52558d 100644 --- a/framework/Mime/package.xml +++ b/framework/Mime/package.xml @@ -90,7 +90,6 @@ http://pear.php.net/dtd/package-2.0.xsd"> - @@ -216,7 +215,6 @@ http://pear.php.net/dtd/package-2.0.xsd"> - -- 2.11.0