diff options
Diffstat (limited to '')
-rw-r--r-- | library/vendor/Zend/Mime.php | 670 | ||||
-rw-r--r-- | library/vendor/Zend/Mime/Decode.php | 275 | ||||
-rw-r--r-- | library/vendor/Zend/Mime/Exception.php | 35 | ||||
-rw-r--r-- | library/vendor/Zend/Mime/Message.php | 302 | ||||
-rw-r--r-- | library/vendor/Zend/Mime/Part.php | 329 |
5 files changed, 1611 insertions, 0 deletions
diff --git a/library/vendor/Zend/Mime.php b/library/vendor/Zend/Mime.php new file mode 100644 index 0000000..5530b6c --- /dev/null +++ b/library/vendor/Zend/Mime.php @@ -0,0 +1,670 @@ +<?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 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$ + */ + +/** + * Support class for MultiPart Mime Messages + * + * @category Zend + * @package 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 Zend_Mime +{ + const TYPE_OCTETSTREAM = 'application/octet-stream'; + const TYPE_TEXT = 'text/plain'; + const TYPE_HTML = 'text/html'; + const ENCODING_7BIT = '7bit'; + const ENCODING_8BIT = '8bit'; + const ENCODING_QUOTEDPRINTABLE = 'quoted-printable'; + const ENCODING_BASE64 = 'base64'; + const DISPOSITION_ATTACHMENT = 'attachment'; + const DISPOSITION_INLINE = 'inline'; + const LINELENGTH = 72; + const LINEEND = "\n"; + const MULTIPART_ALTERNATIVE = 'multipart/alternative'; + const MULTIPART_MIXED = 'multipart/mixed'; + const MULTIPART_RELATED = 'multipart/related'; + + /** + * Boundary + * + * @var null|string + */ + protected $_boundary; + + /** + * @var int + */ + protected static $makeUnique = 0; + + /** + * Lookup-Tables for QuotedPrintable + * + * @var array + */ + public static $qpKeys = array( + "\x00", + "\x01", + "\x02", + "\x03", + "\x04", + "\x05", + "\x06", + "\x07", + "\x08", + "\x09", + "\x0A", + "\x0B", + "\x0C", + "\x0D", + "\x0E", + "\x0F", + "\x10", + "\x11", + "\x12", + "\x13", + "\x14", + "\x15", + "\x16", + "\x17", + "\x18", + "\x19", + "\x1A", + "\x1B", + "\x1C", + "\x1D", + "\x1E", + "\x1F", + "\x7F", + "\x80", + "\x81", + "\x82", + "\x83", + "\x84", + "\x85", + "\x86", + "\x87", + "\x88", + "\x89", + "\x8A", + "\x8B", + "\x8C", + "\x8D", + "\x8E", + "\x8F", + "\x90", + "\x91", + "\x92", + "\x93", + "\x94", + "\x95", + "\x96", + "\x97", + "\x98", + "\x99", + "\x9A", + "\x9B", + "\x9C", + "\x9D", + "\x9E", + "\x9F", + "\xA0", + "\xA1", + "\xA2", + "\xA3", + "\xA4", + "\xA5", + "\xA6", + "\xA7", + "\xA8", + "\xA9", + "\xAA", + "\xAB", + "\xAC", + "\xAD", + "\xAE", + "\xAF", + "\xB0", + "\xB1", + "\xB2", + "\xB3", + "\xB4", + "\xB5", + "\xB6", + "\xB7", + "\xB8", + "\xB9", + "\xBA", + "\xBB", + "\xBC", + "\xBD", + "\xBE", + "\xBF", + "\xC0", + "\xC1", + "\xC2", + "\xC3", + "\xC4", + "\xC5", + "\xC6", + "\xC7", + "\xC8", + "\xC9", + "\xCA", + "\xCB", + "\xCC", + "\xCD", + "\xCE", + "\xCF", + "\xD0", + "\xD1", + "\xD2", + "\xD3", + "\xD4", + "\xD5", + "\xD6", + "\xD7", + "\xD8", + "\xD9", + "\xDA", + "\xDB", + "\xDC", + "\xDD", + "\xDE", + "\xDF", + "\xE0", + "\xE1", + "\xE2", + "\xE3", + "\xE4", + "\xE5", + "\xE6", + "\xE7", + "\xE8", + "\xE9", + "\xEA", + "\xEB", + "\xEC", + "\xED", + "\xEE", + "\xEF", + "\xF0", + "\xF1", + "\xF2", + "\xF3", + "\xF4", + "\xF5", + "\xF6", + "\xF7", + "\xF8", + "\xF9", + "\xFA", + "\xFB", + "\xFC", + "\xFD", + "\xFE", + "\xFF" + ); + + /** + * @var array + */ + public static $qpReplaceValues = array( + "=00", + "=01", + "=02", + "=03", + "=04", + "=05", + "=06", + "=07", + "=08", + "=09", + "=0A", + "=0B", + "=0C", + "=0D", + "=0E", + "=0F", + "=10", + "=11", + "=12", + "=13", + "=14", + "=15", + "=16", + "=17", + "=18", + "=19", + "=1A", + "=1B", + "=1C", + "=1D", + "=1E", + "=1F", + "=7F", + "=80", + "=81", + "=82", + "=83", + "=84", + "=85", + "=86", + "=87", + "=88", + "=89", + "=8A", + "=8B", + "=8C", + "=8D", + "=8E", + "=8F", + "=90", + "=91", + "=92", + "=93", + "=94", + "=95", + "=96", + "=97", + "=98", + "=99", + "=9A", + "=9B", + "=9C", + "=9D", + "=9E", + "=9F", + "=A0", + "=A1", + "=A2", + "=A3", + "=A4", + "=A5", + "=A6", + "=A7", + "=A8", + "=A9", + "=AA", + "=AB", + "=AC", + "=AD", + "=AE", + "=AF", + "=B0", + "=B1", + "=B2", + "=B3", + "=B4", + "=B5", + "=B6", + "=B7", + "=B8", + "=B9", + "=BA", + "=BB", + "=BC", + "=BD", + "=BE", + "=BF", + "=C0", + "=C1", + "=C2", + "=C3", + "=C4", + "=C5", + "=C6", + "=C7", + "=C8", + "=C9", + "=CA", + "=CB", + "=CC", + "=CD", + "=CE", + "=CF", + "=D0", + "=D1", + "=D2", + "=D3", + "=D4", + "=D5", + "=D6", + "=D7", + "=D8", + "=D9", + "=DA", + "=DB", + "=DC", + "=DD", + "=DE", + "=DF", + "=E0", + "=E1", + "=E2", + "=E3", + "=E4", + "=E5", + "=E6", + "=E7", + "=E8", + "=E9", + "=EA", + "=EB", + "=EC", + "=ED", + "=EE", + "=EF", + "=F0", + "=F1", + "=F2", + "=F3", + "=F4", + "=F5", + "=F6", + "=F7", + "=F8", + "=F9", + "=FA", + "=FB", + "=FC", + "=FD", + "=FE", + "=FF" + ); + + /** + * @var string + */ + public static $qpKeysString = + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"; + + /** + * Check if the given string is "printable" + * + * Checks that a string contains no unprintable characters. If this returns + * false, encode the string for secure delivery. + * + * @param string $str + * @return boolean + */ + public static function isPrintable($str) + { + return (strcspn($str, self::$qpKeysString) == strlen($str)); + } + + /** + * Encode a given string with the QUOTED_PRINTABLE mechanism and wrap the lines. + * + * @param string $str + * @param int $lineLength Line length; defaults to {@link LINELENGTH} + * @param string $lineEnd Line end; defaults to {@link LINEEND} + * @return string + */ + public static function encodeQuotedPrintable( + $str, + $lineLength = self::LINELENGTH, + $lineEnd = self::LINEEND + ) + { + $out = ''; + $str = self::_encodeQuotedPrintable($str); + + // Split encoded text into separate lines + while (strlen($str) > 0) { + $ptr = strlen($str); + if ($ptr > $lineLength) { + $ptr = $lineLength; + } + + // Ensure we are not splitting across an encoded character + $pos = strrpos(substr($str, 0, $ptr), '='); + if ($pos !== false && $pos >= $ptr - 2) { + $ptr = $pos; + } + + // Check if there is a space at the end of the line and rewind + if ($ptr > 0 && $str[$ptr - 1] == ' ') { + --$ptr; + } + + // Add string and continue + $out .= substr($str, 0, $ptr) . '=' . $lineEnd; + $str = substr($str, $ptr); + } + + $out = rtrim($out, $lineEnd); + $out = rtrim($out, '='); + + return $out; + } + + /** + * Converts a string into quoted printable format. + * + * @param string $str + * @return string + */ + private static function _encodeQuotedPrintable($str) + { + $str = str_replace('=', '=3D', $str); + $str = str_replace(self::$qpKeys, self::$qpReplaceValues, $str); + $str = rtrim($str); + + return $str; + } + + /** + * Encode a given string with the QUOTED_PRINTABLE mechanism for Mail Headers. + * + * Mail headers depend on an extended quoted printable algorithm otherwise + * a range of bugs can occur. + * + * @param string $str + * @param string $charset + * @param int $lineLength Line length; defaults to {@link LINELENGTH} + * @param string $lineEnd Line end; defaults to {@link LINEEND} + * @return string + */ + public static function encodeQuotedPrintableHeader( + $str, $charset, $lineLength = self::LINELENGTH, $lineEnd = self::LINEEND + ) + { + // Reduce line-length by the length of the required delimiter, charsets and encoding + $prefix = sprintf('=?%s?Q?', $charset); + $lineLength = $lineLength - strlen($prefix) - 3; + + $str = self::_encodeQuotedPrintable($str); + + // Mail-Header required chars have to be encoded also: + $str = str_replace( + array('?', ' ', '_', ','), array('=3F', '=20', '=5F', '=2C'), $str + ); + + // initialize first line, we need it anyways + $lines = array(0 => ""); + + // Split encoded text into separate lines + $tmp = ""; + while (strlen($str) > 0) { + $currentLine = max(count($lines) - 1, 0); + $token = self::getNextQuotedPrintableToken($str); + $str = substr($str, strlen($token)); + + $tmp .= $token; + if ($token == '=20') { + // only if we have a single char token or space, we can append the + // tempstring it to the current line or start a new line if necessary. + if (strlen($lines[$currentLine] . $tmp) > $lineLength) { + $lines[$currentLine + 1] = $tmp; + } else { + $lines[$currentLine] .= $tmp; + } + $tmp = ""; + } + // don't forget to append the rest to the last line + if (strlen($str) == 0) { + $lines[$currentLine] .= $tmp; + } + } + + // assemble the lines together by pre- and appending delimiters, charset, encoding. + for ($i = 0; $i < count($lines); $i++) { + $lines[$i] = " " . $prefix . $lines[$i] . "?="; + } + $str = trim(implode($lineEnd, $lines)); + + return $str; + } + + /** + * Retrieves the first token from a quoted printable string. + * + * @param string $str + * @return string + */ + private static function getNextQuotedPrintableToken($str) + { + if (substr($str, 0, 1) == "=") { + $token = substr($str, 0, 3); + } else { + $token = substr($str, 0, 1); + } + + return $token; + } + + /** + * Encode a given string in mail header compatible base64 encoding. + * + * @param string $str + * @param string $charset + * @param int $lineLength Line length; defaults to {@link LINELENGTH} + * @param string $lineEnd Line end; defaults to {@link LINEEND} + * @return string + */ + public static function encodeBase64Header( + $str, $charset, $lineLength = self::LINELENGTH, $lineEnd = self::LINEEND + ) + { + $prefix = '=?' . $charset . '?B?'; + $suffix = '?='; + $remainingLength = $lineLength - strlen($prefix) - strlen($suffix); + + $encodedValue = self::encodeBase64($str, $remainingLength, $lineEnd); + $encodedValue = str_replace( + $lineEnd, $suffix . $lineEnd . ' ' . $prefix, $encodedValue + ); + $encodedValue = $prefix . $encodedValue . $suffix; + + return $encodedValue; + } + + /** + * Encode a given string in base64 encoding and break lines + * according to the maximum linelength. + * + * @param string $str + * @param int $lineLength Line length; defaults to {@link LINELENGTH} + * @param string $lineEnd Line end; defaults to {@link LINEEND} + * @return string + */ + public static function encodeBase64( + $str, $lineLength = self::LINELENGTH, $lineEnd = self::LINEEND + ) + { + return rtrim(chunk_split(base64_encode($str), $lineLength, $lineEnd)); + } + + /** + * Constructor + * + * @param null|string $boundary + */ + public function __construct($boundary = null) + { + // This string needs to be somewhat unique + if ($boundary === null) { + $this->_boundary = '=_' . md5(microtime(1) . self::$makeUnique++); + } else { + $this->_boundary = $boundary; + } + } + + /** + * Encode the given string with the given encoding. + * + * @param string $str + * @param string $encoding + * @param string $EOL Line end; defaults to {@link Zend_Mime::LINEEND} + * @return string + */ + public static function encode($str, $encoding, $EOL = self::LINEEND) + { + switch ($encoding) { + case self::ENCODING_BASE64: + return self::encodeBase64($str, self::LINELENGTH, $EOL); + + case self::ENCODING_QUOTEDPRINTABLE: + return self::encodeQuotedPrintable($str, self::LINELENGTH, $EOL); + + default: + /** + * @todo 7Bit and 8Bit is currently handled the same way. + */ + return $str; + } + } + + /** + * Return a MIME boundary + * + * @access public + * @return string + */ + public function boundary() + { + return $this->_boundary; + } + + /** + * Return a MIME boundary line + * + * @param string $EOL Line end; defaults to {@link LINEEND} + * @return string + */ + public function boundaryLine($EOL = self::LINEEND) + { + return $EOL . '--' . $this->_boundary . $EOL; + } + + /** + * Return MIME ending + * + * @param string $EOL Line end; defaults to {@link LINEEND} + * @return string + */ + public function mimeEnd($EOL = self::LINEEND) + { + return $EOL . '--' . $this->_boundary . '--' . $EOL; + } +} diff --git a/library/vendor/Zend/Mime/Decode.php b/library/vendor/Zend/Mime/Decode.php new file mode 100644 index 0000000..a63f861 --- /dev/null +++ b/library/vendor/Zend/Mime/Decode.php @@ -0,0 +1,275 @@ +<?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 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 Zend_Mime + */ + +/** + * @category Zend + * @package 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 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 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 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 Zend_Mime::LINEEND} + * @return array|null parts as array('header' => array(name => value), 'body' => content), null if no parts found + * @throws Zend_Exception + */ + public static function splitMessageStruct( + $message, $boundary, $EOL = 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 Zend_Mime::LINEEND} + * @return null + */ + public static function splitMessage( + $message, &$headers, &$body, $EOL = 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 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 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/library/vendor/Zend/Mime/Exception.php b/library/vendor/Zend/Mime/Exception.php new file mode 100644 index 0000000..a803058 --- /dev/null +++ b/library/vendor/Zend/Mime/Exception.php @@ -0,0 +1,35 @@ +<?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 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$ + */ + +/** + * Zend_Exception + */ + +/** + * @category Zend + * @package 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 Zend_Mime_Exception extends Zend_Exception +{ +} + diff --git a/library/vendor/Zend/Mime/Message.php b/library/vendor/Zend/Mime/Message.php new file mode 100644 index 0000000..6082890 --- /dev/null +++ b/library/vendor/Zend/Mime/Message.php @@ -0,0 +1,302 @@ +<?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 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$ + */ + +/** + * Zend_Mime + */ + +/** + * Zend_Mime_Part + */ + +/** + * @category Zend + * @package 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 Zend_Mime_Message +{ + /** + * The Zend_Mime_Parts of the message + * + * @var array + */ + protected $_parts = array(); + + /** + * The Zend_Mime object for the message + * + * @var Zend_Mime|null + */ + protected $_mime = null; + + /** + * Returns the list of all Zend_Mime_Parts in the message + * + * @return array of Zend_Mime_Part + */ + public function getParts() + { + return $this->_parts; + } + + /** + * Sets the given array of Zend_Mime_Parts as the array for the message + * + * @param array $parts + */ + public function setParts($parts) + { + $this->_parts = $parts; + } + + /** + * Append a new Zend_Mime_Part to the current message + * + * @param Zend_Mime_Part $part + */ + public function addPart(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 Zend_Mime object for the message + * + * This can be used to set the boundary specifically or to use a subclass of + * Zend_Mime for generating the boundary. + * + * @param Zend_Mime $mime + */ + public function setMime(Zend_Mime $mime) + { + $this->_mime = $mime; + } + + /** + * Returns the 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 Zend_Mime + */ + public function getMime() + { + if ($this->_mime === null) { + $this->_mime = new 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 Zend_Mime. If + * {@link setMime()} has been called before this method, the Zend_Mime + * object set by this call will be used. Otherwise, a new Zend_Mime object + * is generated and used. + * + * @param string $EOL EOL string; defaults to {@link Zend_Mime::LINEEND} + * @return string + */ + public function generateMessage($EOL = 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 = 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 = 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 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 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 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 Zend_Mime::LINEEND} + * @throws Zend_Exception + * @return Zend_Mime_Message + */ + public static function createFromMessage( + $message, $boundary, $EOL = Zend_Mime::LINEEND + ) + { + $parts = 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 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 Zend_Exception( + 'Unknown header ignored for MimePart:' . $key + ); + } + } + $res->addPart($newPart); + } + + return $res; + } +} diff --git a/library/vendor/Zend/Mime/Part.php b/library/vendor/Zend/Mime/Part.php new file mode 100644 index 0000000..852fb56 --- /dev/null +++ b/library/vendor/Zend/Mime/Part.php @@ -0,0 +1,329 @@ +<?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 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$ + */ + +/** + * Zend_Mime + */ + +/** + * Class representing a MIME part. + * + * @category Zend + * @package 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 Zend_Mime_Part +{ + + /** + * Type + * + * @var string + */ + public $type = Zend_Mime::TYPE_OCTETSTREAM; + + /** + * Encoding + * + * @var string + */ + public $encoding = 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 Zend_Mime_Exception if not a stream or unable to append filter + */ + public function getEncodedStream() + { + if (!$this->_isStream) { + throw new Zend_Mime_Exception( + 'Attempt to get a stream from a string part' + ); + } + + //stream_filter_remove(); // ??? is that right? + switch ($this->encoding) { + case Zend_Mime::ENCODING_QUOTEDPRINTABLE: + $filter = stream_filter_append( + $this->_content, + 'convert.quoted-printable-encode', + STREAM_FILTER_READ, + array( + 'line-length' => 76, + 'line-break-chars' => Zend_Mime::LINEEND + ) + ); + if (!is_resource($filter)) { + throw new Zend_Mime_Exception( + 'Failed to append quoted-printable filter' + ); + } + break; + + case Zend_Mime::ENCODING_BASE64: + $filter = stream_filter_append( + $this->_content, + 'convert.base64-encode', + STREAM_FILTER_READ, + array( + 'line-length' => 76, + 'line-break-chars' => Zend_Mime::LINEEND + ) + ); + if (!is_resource($filter)) { + throw new 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 Zend_Mime::LINEEND} + * @throws Zend_Mime_Exception + * @return string + */ + public function getContent($EOL = Zend_Mime::LINEEND) + { + if ($this->_isStream) { + return stream_get_contents($this->getEncodedStream()); + } else { + return 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 Zend_Mime::LINEEND} + * @return array + */ + public function getHeadersArray($EOL = 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 Zend_Mime::LINEEND} + * @return string + */ + public function getHeaders($EOL = Zend_Mime::LINEEND) + { + $res = ''; + foreach ($this->getHeadersArray($EOL) as $header) { + $res .= $header[0] . ': ' . $header[1] . $EOL; + } + + return $res; + } +} |