PageRenderTime 55ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/src/application/libraries/Zend/Mime/Decode.php

https://bitbucket.org/masnug/grc276-blog-laravel
PHP | 244 lines | 121 code | 21 blank | 102 comment | 30 complexity | 8f5e29919c4cc8a424fbb34264a6428e MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Mime
  17. * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. * @version $Id: Decode.php 23984 2011-05-03 19:35:48Z ralph $
  20. */
  21. /**
  22. * @see Zend_Mime
  23. */
  24. require_once 'Zend/Mime.php';
  25. /**
  26. * @category Zend
  27. * @package Zend_Mime
  28. * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
  29. * @license http://framework.zend.com/license/new-bsd New BSD License
  30. */
  31. class Zend_Mime_Decode
  32. {
  33. /**
  34. * Explode MIME multipart string into seperate parts
  35. *
  36. * Parts consist of the header and the body of each MIME part.
  37. *
  38. * @param string $body raw body of message
  39. * @param string $boundary boundary as found in content-type
  40. * @return array parts with content of each part, empty if no parts found
  41. * @throws Zend_Exception
  42. */
  43. public static function splitMime($body, $boundary)
  44. {
  45. // TODO: we're ignoring \r for now - is this function fast enough and is it safe to asume noone needs \r?
  46. $body = str_replace("\r", '', $body);
  47. $start = 0;
  48. $res = array();
  49. // find every mime part limiter and cut out the
  50. // string before it.
  51. // the part before the first boundary string is discarded:
  52. $p = strpos($body, '--' . $boundary . "\n", $start);
  53. if ($p === false) {
  54. // no parts found!
  55. return array();
  56. }
  57. // position after first boundary line
  58. $start = $p + 3 + strlen($boundary);
  59. while (($p = strpos($body, '--' . $boundary . "\n", $start)) !== false) {
  60. $res[] = substr($body, $start, $p-$start);
  61. $start = $p + 3 + strlen($boundary);
  62. }
  63. // no more parts, find end boundary
  64. $p = strpos($body, '--' . $boundary . '--', $start);
  65. if ($p===false) {
  66. throw new Zend_Exception('Not a valid Mime Message: End Missing');
  67. }
  68. // the remaining part also needs to be parsed:
  69. $res[] = substr($body, $start, $p-$start);
  70. return $res;
  71. }
  72. /**
  73. * decodes a mime encoded String and returns a
  74. * struct of parts with header and body
  75. *
  76. * @param string $message raw message content
  77. * @param string $boundary boundary as found in content-type
  78. * @param string $EOL EOL string; defaults to {@link Zend_Mime::LINEEND}
  79. * @return array|null parts as array('header' => array(name => value), 'body' => content), null if no parts found
  80. * @throws Zend_Exception
  81. */
  82. public static function splitMessageStruct($message, $boundary, $EOL = Zend_Mime::LINEEND)
  83. {
  84. $parts = self::splitMime($message, $boundary);
  85. if (count($parts) <= 0) {
  86. return null;
  87. }
  88. $result = array();
  89. foreach ($parts as $part) {
  90. self::splitMessage($part, $headers, $body, $EOL);
  91. $result[] = array('header' => $headers,
  92. 'body' => $body );
  93. }
  94. return $result;
  95. }
  96. /**
  97. * split a message in header and body part, if no header or an
  98. * invalid header is found $headers is empty
  99. *
  100. * The charset of the returned headers depend on your iconv settings.
  101. *
  102. * @param string $message raw message with header and optional content
  103. * @param array $headers output param, array with headers as array(name => value)
  104. * @param string $body output param, content of message
  105. * @param string $EOL EOL string; defaults to {@link Zend_Mime::LINEEND}
  106. * @return null
  107. */
  108. public static function splitMessage($message, &$headers, &$body, $EOL = Zend_Mime::LINEEND)
  109. {
  110. // check for valid header at first line
  111. $firstline = strtok($message, "\n");
  112. if (!preg_match('%^[^\s]+[^:]*:%', $firstline)) {
  113. $headers = array();
  114. // TODO: we're ignoring \r for now - is this function fast enough and is it safe to asume noone needs \r?
  115. $body = str_replace(array("\r", "\n"), array('', $EOL), $message);
  116. return;
  117. }
  118. // find an empty line between headers and body
  119. // default is set new line
  120. if (strpos($message, $EOL . $EOL)) {
  121. list($headers, $body) = explode($EOL . $EOL, $message, 2);
  122. // next is the standard new line
  123. } else if ($EOL != "\r\n" && strpos($message, "\r\n\r\n")) {
  124. list($headers, $body) = explode("\r\n\r\n", $message, 2);
  125. // next is the other "standard" new line
  126. } else if ($EOL != "\n" && strpos($message, "\n\n")) {
  127. list($headers, $body) = explode("\n\n", $message, 2);
  128. // at last resort find anything that looks like a new line
  129. } else {
  130. @list($headers, $body) = @preg_split("%([\r\n]+)\\1%U", $message, 2);
  131. }
  132. $headers = iconv_mime_decode_headers($headers, ICONV_MIME_DECODE_CONTINUE_ON_ERROR);
  133. if ($headers === false ) {
  134. // an error occurs during the decoding
  135. return;
  136. }
  137. // normalize header names
  138. foreach ($headers as $name => $header) {
  139. $lower = strtolower($name);
  140. if ($lower == $name) {
  141. continue;
  142. }
  143. unset($headers[$name]);
  144. if (!isset($headers[$lower])) {
  145. $headers[$lower] = $header;
  146. continue;
  147. }
  148. if (is_array($headers[$lower])) {
  149. $headers[$lower][] = $header;
  150. continue;
  151. }
  152. $headers[$lower] = array($headers[$lower], $header);
  153. }
  154. }
  155. /**
  156. * split a content type in its different parts
  157. *
  158. * @param string $type content-type
  159. * @param string $wantedPart the wanted part, else an array with all parts is returned
  160. * @return string|array wanted part or all parts as array('type' => content-type, partname => value)
  161. */
  162. public static function splitContentType($type, $wantedPart = null)
  163. {
  164. return self::splitHeaderField($type, $wantedPart, 'type');
  165. }
  166. /**
  167. * split a header field like content type in its different parts
  168. *
  169. * @param string $type header field
  170. * @param string $wantedPart the wanted part, else an array with all parts is returned
  171. * @param string $firstName key name for the first part
  172. * @return string|array wanted part or all parts as array($firstName => firstPart, partname => value)
  173. * @throws Zend_Exception
  174. */
  175. public static function splitHeaderField($field, $wantedPart = null, $firstName = 0)
  176. {
  177. $wantedPart = strtolower($wantedPart);
  178. $firstName = strtolower($firstName);
  179. // special case - a bit optimized
  180. if ($firstName === $wantedPart) {
  181. $field = strtok($field, ';');
  182. return $field[0] == '"' ? substr($field, 1, -1) : $field;
  183. }
  184. $field = $firstName . '=' . $field;
  185. if (!preg_match_all('%([^=\s]+)\s*=\s*("[^"]+"|[^;]+)(;\s*|$)%', $field, $matches)) {
  186. throw new Zend_Exception('not a valid header field');
  187. }
  188. if ($wantedPart) {
  189. foreach ($matches[1] as $key => $name) {
  190. if (strcasecmp($name, $wantedPart)) {
  191. continue;
  192. }
  193. if ($matches[2][$key][0] != '"') {
  194. return $matches[2][$key];
  195. }
  196. return substr($matches[2][$key], 1, -1);
  197. }
  198. return null;
  199. }
  200. $split = array();
  201. foreach ($matches[1] as $key => $name) {
  202. $name = strtolower($name);
  203. if ($matches[2][$key][0] == '"') {
  204. $split[$name] = substr($matches[2][$key], 1, -1);
  205. } else {
  206. $split[$name] = $matches[2][$key];
  207. }
  208. }
  209. return $split;
  210. }
  211. /**
  212. * decode a quoted printable encoded string
  213. *
  214. * The charset of the returned string depends on your iconv settings.
  215. *
  216. * @param string encoded string
  217. * @return string decoded string
  218. */
  219. public static function decodeQuotedPrintable($string)
  220. {
  221. return quoted_printable_decode($string);
  222. }
  223. }