diff options
Diffstat (limited to 'Postman/Postman-Mail/Zend-1.12.10/Mime')
-rw-r--r-- | Postman/Postman-Mail/Zend-1.12.10/Mime/Decode.php | 276 | ||||
-rw-r--r-- | Postman/Postman-Mail/Zend-1.12.10/Mime/Exception.php | 36 | ||||
-rw-r--r-- | Postman/Postman-Mail/Zend-1.12.10/Mime/Message.php | 305 | ||||
-rw-r--r-- | Postman/Postman-Mail/Zend-1.12.10/Mime/Part.php | 333 |
4 files changed, 950 insertions, 0 deletions
diff --git a/Postman/Postman-Mail/Zend-1.12.10/Mime/Decode.php b/Postman/Postman-Mail/Zend-1.12.10/Mime/Decode.php new file mode 100644 index 0000000..5fd17bd --- /dev/null +++ b/Postman/Postman-Mail/Zend-1.12.10/Mime/Decode.php @@ -0,0 +1,276 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Postman_Zend_Mime + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + +/** + * @see Postman_Zend_Mime + */ +require_once 'Zend/Mime.php'; + +/** + * @category Zend + * @package Postman_Zend_Mime + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Postman_Zend_Mime_Decode +{ + /** + * Explode MIME multipart string into seperate parts + * + * Parts consist of the header and the body of each MIME part. + * + * @param string $body raw body of message + * @param string $boundary boundary as found in content-type + * @return array parts with content of each part, empty if no parts found + * @throws Postman_Zend_Exception + */ + public static function splitMime($body, $boundary) + { + // TODO: we're ignoring \r for now - is this function fast enough and is it safe to asume noone needs \r? + $body = str_replace("\r", '', $body); + + $start = 0; + $res = array(); + // find every mime part limiter and cut out the + // string before it. + // the part before the first boundary string is discarded: + $p = strpos($body, '--' . $boundary . "\n", $start); + if ($p === false) { + // no parts found! + return array(); + } + + // position after first boundary line + $start = $p + 3 + strlen($boundary); + + while (($p = strpos($body, '--' . $boundary . "\n", $start)) !== false) { + $res[] = substr($body, $start, $p-$start); + $start = $p + 3 + strlen($boundary); + } + + // no more parts, find end boundary + $p = strpos($body, '--' . $boundary . '--', $start); + if ($p === false) { + throw new Postman_Zend_Exception('Not a valid Mime Message: End Missing'); + } + + // the remaining part also needs to be parsed: + $res[] = substr($body, $start, $p - $start); + + return $res; + } + + /** + * decodes a mime encoded String and returns a + * struct of parts with header and body + * + * @param string $message raw message content + * @param string $boundary boundary as found in content-type + * @param string $EOL EOL string; defaults to {@link Postman_Zend_Mime::LINEEND} + * @return array|null parts as array('header' => array(name => value), 'body' => content), null if no parts found + * @throws Postman_Zend_Exception + */ + public static function splitMessageStruct( + $message, $boundary, $EOL = Postman_Zend_Mime::LINEEND + ) + { + $parts = self::splitMime($message, $boundary); + if (count($parts) <= 0) { + return null; + } + $result = array(); + foreach ($parts as $part) { + self::splitMessage($part, $headers, $body, $EOL); + $result[] = array( + 'header' => $headers, + 'body' => $body + ); + } + + return $result; + } + + /** + * split a message in header and body part, if no header or an + * invalid header is found $headers is empty + * + * The charset of the returned headers depend on your iconv settings. + * + * @param string $message raw message with header and optional content + * @param array $headers output param, array with headers as array(name => value) + * @param string $body output param, content of message + * @param string $EOL EOL string; defaults to {@link Postman_Zend_Mime::LINEEND} + * @return null + */ + public static function splitMessage( + $message, &$headers, &$body, $EOL = Postman_Zend_Mime::LINEEND + ) + { + // check for valid header at first line + $firstline = strtok($message, "\n"); + if (!preg_match('%^[^\s]+[^:]*:%', $firstline)) { + $headers = array(); + // TODO: we're ignoring \r for now - is this function fast enough and is it safe to asume noone needs \r? + $body = str_replace( + array( + "\r", + "\n" + ), array( + '', + $EOL + ), $message + ); + + return; + } + + // find an empty line between headers and body + // default is set new line + if (strpos($message, $EOL . $EOL)) { + list($headers, $body) = explode($EOL . $EOL, $message, 2); + // next is the standard new line + } else { + if ($EOL != "\r\n" && strpos($message, "\r\n\r\n")) { + list($headers, $body) = explode("\r\n\r\n", $message, 2); + // next is the other "standard" new line + } else { + if ($EOL != "\n" && strpos($message, "\n\n")) { + list($headers, $body) = explode("\n\n", $message, 2); + // at last resort find anything that looks like a new line + } else { + @list($headers, $body) = + @preg_split("%([\r\n]+)\\1%U", $message, 2); + } + } + } + + $headers = iconv_mime_decode_headers( + $headers, ICONV_MIME_DECODE_CONTINUE_ON_ERROR + ); + + if ($headers === false) { + // an error occurs during the decoding + return; + } + + // normalize header names + foreach ($headers as $name => $header) { + $lower = strtolower($name); + if ($lower == $name) { + continue; + } + unset($headers[$name]); + if (!isset($headers[$lower])) { + $headers[$lower] = $header; + continue; + } + if (is_array($headers[$lower])) { + $headers[$lower][] = $header; + continue; + } + $headers[$lower] = array( + $headers[$lower], + $header + ); + } + } + + /** + * split a content type in its different parts + * + * @param string $type content-type + * @param string $wantedPart the wanted part, else an array with all parts is returned + * @return string|array wanted part or all parts as array('type' => content-type, partname => value) + */ + public static function splitContentType($type, $wantedPart = null) + { + return self::splitHeaderField($type, $wantedPart, 'type'); + } + + /** + * split a header field like content type in its different parts + * + * @param string $field + * @param string $wantedPart the wanted part, else an array with all parts is returned + * @param int|string $firstName key name for the first part + * @throws Postman_Zend_Exception + * @return string|array wanted part or all parts as array($firstName => firstPart, partname => value) + */ + public static function splitHeaderField( + $field, $wantedPart = null, $firstName = 0 + ) + { + $wantedPart = strtolower($wantedPart); + $firstName = strtolower($firstName); + + // special case - a bit optimized + if ($firstName === $wantedPart) { + $field = strtok($field, ';'); + + return $field[0] == '"' ? substr($field, 1, -1) : $field; + } + + $field = $firstName . '=' . $field; + if (!preg_match_all('%([^=\s]+)\s*=\s*("[^"]+"|[^;]+)(;\s*|$)%', $field, $matches)) { + throw new Postman_Zend_Exception('not a valid header field'); + } + + if ($wantedPart) { + foreach ($matches[1] as $key => $name) { + if (strcasecmp($name, $wantedPart)) { + continue; + } + if ($matches[2][$key][0] != '"') { + return $matches[2][$key]; + } + + return substr($matches[2][$key], 1, -1); + } + + return null; + } + + $split = array(); + foreach ($matches[1] as $key => $name) { + $name = strtolower($name); + if ($matches[2][$key][0] == '"') { + $split[$name] = substr($matches[2][$key], 1, -1); + } else { + $split[$name] = $matches[2][$key]; + } + } + + return $split; + } + + /** + * decode a quoted printable encoded string + * + * The charset of the returned string depends on your iconv settings. + * + * @param string $string Encoded string + * @return string Decoded string + */ + public static function decodeQuotedPrintable($string) + { + return quoted_printable_decode($string); + } +} diff --git a/Postman/Postman-Mail/Zend-1.12.10/Mime/Exception.php b/Postman/Postman-Mail/Zend-1.12.10/Mime/Exception.php new file mode 100644 index 0000000..e8f3b00 --- /dev/null +++ b/Postman/Postman-Mail/Zend-1.12.10/Mime/Exception.php @@ -0,0 +1,36 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Postman_Zend_Mime + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + +/** + * Postman_Zend_Exception + */ +require_once 'Zend/Exception.php'; + +/** + * @category Zend + * @package Postman_Zend_Mime + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Postman_Zend_Mime_Exception extends Postman_Zend_Exception +{ +} + diff --git a/Postman/Postman-Mail/Zend-1.12.10/Mime/Message.php b/Postman/Postman-Mail/Zend-1.12.10/Mime/Message.php new file mode 100644 index 0000000..e5783fb --- /dev/null +++ b/Postman/Postman-Mail/Zend-1.12.10/Mime/Message.php @@ -0,0 +1,305 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Postman_Zend_Mime + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + +/** + * Postman_Zend_Mime + */ +// require_once 'Zend/Mime.php'; + +/** + * Postman_Zend_Mime_Part + */ +// require_once 'Zend/Mime/Part.php'; + +/** + * @category Zend + * @package Postman_Zend_Mime + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Postman_Zend_Mime_Message +{ + /** + * The Postman_Zend_Mime_Parts of the message + * + * @var array + */ + protected $_parts = array(); + + /** + * The Postman_Zend_Mime object for the message + * + * @var Postman_Zend_Mime|null + */ + protected $_mime = null; + + /** + * Returns the list of all Postman_Zend_Mime_Parts in the message + * + * @return array of Postman_Zend_Mime_Part + */ + public function getParts() + { + return $this->_parts; + } + + /** + * Sets the given array of Postman_Zend_Mime_Parts as the array for the message + * + * @param array $parts + */ + public function setParts($parts) + { + $this->_parts = $parts; + } + + /** + * Append a new Postman_Zend_Mime_Part to the current message + * + * @param Postman_Zend_Mime_Part $part + */ + public function addPart(Postman_Zend_Mime_Part $part) + { + /** + * @todo check for duplicate object handle + */ + $this->_parts[] = $part; + } + + /** + * Check if message needs to be sent as multipart + * MIME message or if it has only one part. + * + * @return boolean + */ + public function isMultiPart() + { + return (count($this->_parts) > 1); + } + + /** + * Set Postman_Zend_Mime object for the message + * + * This can be used to set the boundary specifically or to use a subclass of + * Postman_Zend_Mime for generating the boundary. + * + * @param Postman_Zend_Mime $mime + */ + public function setMime(Postman_Zend_Mime $mime) + { + $this->_mime = $mime; + } + + /** + * Returns the Postman_Zend_Mime object in use by the message + * + * If the object was not present, it is created and returned. Can be used to + * determine the boundary used in this message. + * + * @return Postman_Zend_Mime + */ + public function getMime() + { + if ($this->_mime === null) { + $this->_mime = new Postman_Zend_Mime(); + } + + return $this->_mime; + } + + /** + * Generate MIME-compliant message from the current configuration + * + * This can be a multipart message if more than one MIME part was added. If + * only one part is present, the content of this part is returned. If no + * part had been added, an empty string is returned. + * + * Parts are seperated by the mime boundary as defined in Postman_Zend_Mime. If + * {@link setMime()} has been called before this method, the Postman_Zend_Mime + * object set by this call will be used. Otherwise, a new Postman_Zend_Mime object + * is generated and used. + * + * @param string $EOL EOL string; defaults to {@link Postman_Zend_Mime::LINEEND} + * @return string + */ + public function generateMessage($EOL = Postman_Zend_Mime::LINEEND) + { + if (!$this->isMultiPart()) { + $body = array_shift($this->_parts); + $body = $body->getContent($EOL); + } else { + $mime = $this->getMime(); + + $boundaryLine = $mime->boundaryLine($EOL); + $body = 'This is a message in Mime Format. If you see this, ' + . "your mail reader does not support this format." . $EOL; + + foreach (array_keys($this->_parts) as $p) { + $body .= $boundaryLine + . $this->getPartHeaders($p, $EOL) + . $EOL + . $this->getPartContent($p, $EOL); + } + + $body .= $mime->mimeEnd($EOL); + } + + return trim($body); + } + + /** + * Get the headers of a given part as an array + * + * @param int $partnum + * @return array + */ + public function getPartHeadersArray($partnum) + { + return $this->_parts[$partnum]->getHeadersArray(); + } + + /** + * Get the headers of a given part as a string + * + * @param int $partnum + * @param string $EOL + * @return string + */ + public function getPartHeaders($partnum, $EOL = Postman_Zend_Mime::LINEEND) + { + return $this->_parts[$partnum]->getHeaders($EOL); + } + + /** + * Get the (encoded) content of a given part as a string + * + * @param int $partnum + * @param string $EOL + * @return string + */ + public function getPartContent($partnum, $EOL = Postman_Zend_Mime::LINEEND) + { + return $this->_parts[$partnum]->getContent($EOL); + } + + /** + * Explode MIME multipart string into seperate parts + * + * Parts consist of the header and the body of each MIME part. + * + * @param string $body + * @param string $boundary + * @throws Postman_Zend_Exception + * @return array + */ + protected static function _disassembleMime($body, $boundary) + { + $start = 0; + $res = array(); + // find every mime part limiter and cut out the + // string before it. + // the part before the first boundary string is discarded: + $p = strpos($body, '--' . $boundary . "\n", $start); + if ($p === false) { + // no parts found! + return array(); + } + + // position after first boundary line + $start = $p + 3 + strlen($boundary); + + while (($p = strpos($body, '--' . $boundary . "\n", $start)) + !== false) { + $res[] = substr($body, $start, $p - $start); + $start = $p + 3 + strlen($boundary); + } + + // no more parts, find end boundary + $p = strpos($body, '--' . $boundary . '--', $start); + if ($p === false) { + throw new Postman_Zend_Exception('Not a valid Mime Message: End Missing'); + } + + // the remaining part also needs to be parsed: + $res[] = substr($body, $start, $p - $start); + + return $res; + } + + /** + * Decodes a MIME encoded string and returns a Postman_Zend_Mime_Message object with + * all the MIME parts set according to the given string + * + * @param string $message + * @param string $boundary + * @param string $EOL EOL string; defaults to {@link Postman_Zend_Mime::LINEEND} + * @throws Postman_Zend_Exception + * @return Postman_Zend_Mime_Message + */ + public static function createFromMessage( + $message, $boundary, $EOL = Postman_Zend_Mime::LINEEND + ) + { + require_once 'Zend/Mime/Decode.php'; + $parts = Postman_Zend_Mime_Decode::splitMessageStruct($message, $boundary, $EOL); + + $res = new self(); + foreach ($parts as $part) { + // now we build a new MimePart for the current Message Part: + $newPart = new Postman_Zend_Mime_Part($part['body']); + foreach ($part['header'] as $key => $value) { + /** + * @todo check for characterset and filename + */ + switch (strtolower($key)) { + case 'content-type': + $newPart->type = $value; + break; + case 'content-transfer-encoding': + $newPart->encoding = $value; + break; + case 'content-id': + $newPart->id = trim($value, '<>'); + break; + case 'content-disposition': + $newPart->disposition = $value; + break; + case 'content-description': + $newPart->description = $value; + break; + case 'content-location': + $newPart->location = $value; + break; + case 'content-language': + $newPart->language = $value; + break; + default: + throw new Postman_Zend_Exception( + 'Unknown header ignored for MimePart:' . $key + ); + } + } + $res->addPart($newPart); + } + + return $res; + } +} diff --git a/Postman/Postman-Mail/Zend-1.12.10/Mime/Part.php b/Postman/Postman-Mail/Zend-1.12.10/Mime/Part.php new file mode 100644 index 0000000..9051c28 --- /dev/null +++ b/Postman/Postman-Mail/Zend-1.12.10/Mime/Part.php @@ -0,0 +1,333 @@ +<?php +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Postman_Zend_Mime + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + +/** + * Postman_Zend_Mime + */ +// require_once 'Zend/Mime.php'; + +/** + * Class representing a MIME part. + * + * @category Zend + * @package Postman_Zend_Mime + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Postman_Zend_Mime_Part +{ + + /** + * Type + * + * @var string + */ + public $type = Postman_Zend_Mime::TYPE_OCTETSTREAM; + + /** + * Encoding + * + * @var string + */ + public $encoding = Postman_Zend_Mime::ENCODING_8BIT; + + /** + * ID + * + * @var string + */ + public $id; + + /** + * Disposition + * + * @var string + */ + public $disposition; + + /** + * Filename + * + * @var string + */ + public $filename; + + /** + * Description + * + * @var string + */ + public $description; + + /** + * Character set + * + * @var string + */ + public $charset; + + /** + * Boundary + * + * @var string + */ + public $boundary; + + /** + * Location + * + * @var string + */ + public $location; + + /** + * Language + * + * @var string + */ + public $language; + + /** + * Content + * + * @var mixed + */ + protected $_content; + + /** + * @var bool + */ + protected $_isStream = false; + + /** + * create a new Mime Part. + * The (unencoded) content of the Part as passed + * as a string or stream + * + * @param mixed $content String or Stream containing the content + */ + public function __construct($content) + { + $this->_content = $content; + if (is_resource($content)) { + $this->_isStream = true; + } + } + + /** + * @todo setters/getters + * @todo error checking for setting $type + * @todo error checking for setting $encoding + */ + + /** + * check if this part can be read as a stream. + * if true, getEncodedStream can be called, otherwise + * only getContent can be used to fetch the encoded + * content of the part + * + * @return bool + */ + public function isStream() + { + return $this->_isStream; + } + + /** + * if this was created with a stream, return a filtered stream for + * reading the content. very useful for large file attachments. + * + * @return mixed Stream + * @throws Postman_Zend_Mime_Exception if not a stream or unable to append filter + */ + public function getEncodedStream() + { + if (!$this->_isStream) { + require_once 'Zend/Mime/Exception.php'; + throw new Postman_Zend_Mime_Exception( + 'Attempt to get a stream from a string part' + ); + } + + //stream_filter_remove(); // ??? is that right? + switch ($this->encoding) { + case Postman_Zend_Mime::ENCODING_QUOTEDPRINTABLE: + $filter = stream_filter_append( + $this->_content, + 'convert.quoted-printable-encode', + STREAM_FILTER_READ, + array( + 'line-length' => 76, + 'line-break-chars' => Postman_Zend_Mime::LINEEND + ) + ); + if (!is_resource($filter)) { + require_once 'Zend/Mime/Exception.php'; + throw new Postman_Zend_Mime_Exception( + 'Failed to append quoted-printable filter' + ); + } + break; + + case Postman_Zend_Mime::ENCODING_BASE64: + $filter = stream_filter_append( + $this->_content, + 'convert.base64-encode', + STREAM_FILTER_READ, + array( + 'line-length' => 76, + 'line-break-chars' => Postman_Zend_Mime::LINEEND + ) + ); + if (!is_resource($filter)) { + require_once 'Zend/Mime/Exception.php'; + throw new Postman_Zend_Mime_Exception( + 'Failed to append base64 filter' + ); + } + break; + + default: + } + + return $this->_content; + } + + /** + * Get the Content of the current Mime Part in the given encoding. + * + * @param string $EOL Line end; defaults to {@link Postman_Zend_Mime::LINEEND} + * @throws Postman_Zend_Mime_Exception + * @return string + */ + public function getContent($EOL = Postman_Zend_Mime::LINEEND) + { + if ($this->_isStream) { + return stream_get_contents($this->getEncodedStream()); + } else { + return Postman_Zend_Mime::encode($this->_content, $this->encoding, $EOL); + } + } + + /** + * Get the RAW unencoded content from this part + * + * @return string + */ + public function getRawContent() + { + if ($this->_isStream) { + return stream_get_contents($this->_content); + } else { + return $this->_content; + } + } + + /** + * Create and return the array of headers for this MIME part + * + * @param string $EOL Line end; defaults to {@link Postman_Zend_Mime::LINEEND} + * @return array + */ + public function getHeadersArray($EOL = Postman_Zend_Mime::LINEEND) + { + $headers = array(); + + $contentType = $this->type; + if ($this->charset) { + $contentType .= '; charset=' . $this->charset; + } + + if ($this->boundary) { + $contentType .= ';' . $EOL + . " boundary=\"" . $this->boundary . '"'; + } + + $headers[] = array( + 'Content-Type', + $contentType + ); + + if ($this->encoding) { + $headers[] = array( + 'Content-Transfer-Encoding', + $this->encoding + ); + } + + if ($this->id) { + $headers[] = array( + 'Content-ID', + '<' . $this->id . '>' + ); + } + + if ($this->disposition) { + $disposition = $this->disposition; + if ($this->filename) { + $disposition .= '; filename="' . $this->filename . '"'; + } + $headers[] = array( + 'Content-Disposition', + $disposition + ); + } + + if ($this->description) { + $headers[] = array( + 'Content-Description', + $this->description + ); + } + + if ($this->location) { + $headers[] = array( + 'Content-Location', + $this->location + ); + } + + if ($this->language) { + $headers[] = array( + 'Content-Language', + $this->language + ); + } + + return $headers; + } + + /** + * Return the headers for this part as a string + * + * @param string $EOL Line end; defaults to {@link Postman_Zend_Mime::LINEEND} + * @return string + */ + public function getHeaders($EOL = Postman_Zend_Mime::LINEEND) + { + $res = ''; + foreach ($this->getHeadersArray($EOL) as $header) { + $res .= $header[0] . ': ' . $header[1] . $EOL; + } + + return $res; + } +} |