PageRenderTime 50ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/zendframework/zend-mime/src/Message.php

https://github.com/tmccormi/openemr
PHP | 311 lines | 162 code | 30 blank | 119 comment | 14 complexity | b6998ef514af8a27cbef90b5e2349d17 MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework (http://framework.zend.com/)
  4. *
  5. * @link http://github.com/zendframework/zf2 for the canonical source repository
  6. * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  7. * @license http://framework.zend.com/license/new-bsd New BSD License
  8. */
  9. namespace Zend\Mime;
  10. class Message
  11. {
  12. protected $parts = [];
  13. protected $mime = null;
  14. /**
  15. * Returns the list of all Zend\Mime\Part in the message
  16. *
  17. * @return Part[]
  18. */
  19. public function getParts()
  20. {
  21. return $this->parts;
  22. }
  23. /**
  24. * Sets the given array of Zend\Mime\Part as the array for the message
  25. *
  26. * @param array $parts
  27. * @return self
  28. */
  29. public function setParts($parts)
  30. {
  31. $this->parts = $parts;
  32. return $this;
  33. }
  34. /**
  35. * Append a new Zend\Mime\Part to the current message
  36. *
  37. * @param \Zend\Mime\Part $part
  38. * @throws Exception\InvalidArgumentException
  39. * @return self
  40. */
  41. public function addPart(Part $part)
  42. {
  43. foreach ($this->getParts() as $key => $row) {
  44. if ($part == $row) {
  45. throw new Exception\InvalidArgumentException(sprintf(
  46. 'Provided part %s already defined.',
  47. $part->getId()
  48. ));
  49. }
  50. }
  51. $this->parts[] = $part;
  52. return $this;
  53. }
  54. /**
  55. * Check if message needs to be sent as multipart
  56. * MIME message or if it has only one part.
  57. *
  58. * @return bool
  59. */
  60. public function isMultiPart()
  61. {
  62. return (count($this->parts) > 1);
  63. }
  64. /**
  65. * Set Zend\Mime\Mime object for the message
  66. *
  67. * This can be used to set the boundary specifically or to use a subclass of
  68. * Zend\Mime for generating the boundary.
  69. *
  70. * @param \Zend\Mime\Mime $mime
  71. * @return self
  72. */
  73. public function setMime(Mime $mime)
  74. {
  75. $this->mime = $mime;
  76. return $this;
  77. }
  78. /**
  79. * Returns the Zend\Mime\Mime object in use by the message
  80. *
  81. * If the object was not present, it is created and returned. Can be used to
  82. * determine the boundary used in this message.
  83. *
  84. * @return \Zend\Mime\Mime
  85. */
  86. public function getMime()
  87. {
  88. if ($this->mime === null) {
  89. $this->mime = new Mime();
  90. }
  91. return $this->mime;
  92. }
  93. /**
  94. * Generate MIME-compliant message from the current configuration
  95. *
  96. * This can be a multipart message if more than one MIME part was added. If
  97. * only one part is present, the content of this part is returned. If no
  98. * part had been added, an empty string is returned.
  99. *
  100. * Parts are separated by the mime boundary as defined in Zend\Mime\Mime. If
  101. * {@link setMime()} has been called before this method, the Zend\Mime\Mime
  102. * object set by this call will be used. Otherwise, a new Zend\Mime\Mime object
  103. * is generated and used.
  104. *
  105. * @param string $EOL EOL string; defaults to {@link Zend\Mime\Mime::LINEEND}
  106. * @return string
  107. */
  108. public function generateMessage($EOL = Mime::LINEEND)
  109. {
  110. if (! $this->isMultiPart()) {
  111. if (empty($this->parts)) {
  112. return '';
  113. }
  114. $part = current($this->parts);
  115. $body = $part->getContent($EOL);
  116. } else {
  117. $mime = $this->getMime();
  118. $boundaryLine = $mime->boundaryLine($EOL);
  119. $body = 'This is a message in Mime Format. If you see this, '
  120. . "your mail reader does not support this format." . $EOL;
  121. foreach (array_keys($this->parts) as $p) {
  122. $body .= $boundaryLine
  123. . $this->getPartHeaders($p, $EOL)
  124. . $EOL
  125. . $this->getPartContent($p, $EOL);
  126. }
  127. $body .= $mime->mimeEnd($EOL);
  128. }
  129. return trim($body);
  130. }
  131. /**
  132. * Get the headers of a given part as an array
  133. *
  134. * @param int $partnum
  135. * @return array
  136. */
  137. public function getPartHeadersArray($partnum)
  138. {
  139. return $this->parts[$partnum]->getHeadersArray();
  140. }
  141. /**
  142. * Get the headers of a given part as a string
  143. *
  144. * @param int $partnum
  145. * @param string $EOL
  146. * @return string
  147. */
  148. public function getPartHeaders($partnum, $EOL = Mime::LINEEND)
  149. {
  150. return $this->parts[$partnum]->getHeaders($EOL);
  151. }
  152. /**
  153. * Get the (encoded) content of a given part as a string
  154. *
  155. * @param int $partnum
  156. * @param string $EOL
  157. * @return string
  158. */
  159. public function getPartContent($partnum, $EOL = Mime::LINEEND)
  160. {
  161. return $this->parts[$partnum]->getContent($EOL);
  162. }
  163. /**
  164. * Explode MIME multipart string into separate parts
  165. *
  166. * Parts consist of the header and the body of each MIME part.
  167. *
  168. * @param string $body
  169. * @param string $boundary
  170. * @throws Exception\RuntimeException
  171. * @return array
  172. */
  173. // @codingStandardsIgnoreStart
  174. protected static function _disassembleMime($body, $boundary)
  175. {
  176. // @codingStandardsIgnoreEnd
  177. $start = 0;
  178. $res = [];
  179. // find every mime part limiter and cut out the
  180. // string before it.
  181. // the part before the first boundary string is discarded:
  182. $p = strpos($body, '--' . $boundary."\n", $start);
  183. if ($p === false) {
  184. // no parts found!
  185. return [];
  186. }
  187. // position after first boundary line
  188. $start = $p + 3 + strlen($boundary);
  189. while (($p = strpos($body, '--' . $boundary . "\n", $start)) !== false) {
  190. $res[] = substr($body, $start, $p - $start);
  191. $start = $p + 3 + strlen($boundary);
  192. }
  193. // no more parts, find end boundary
  194. $p = strpos($body, '--' . $boundary . '--', $start);
  195. if ($p === false) {
  196. throw new Exception\RuntimeException('Not a valid Mime Message: End Missing');
  197. }
  198. // the remaining part also needs to be parsed:
  199. $res[] = substr($body, $start, $p - $start);
  200. return $res;
  201. }
  202. /**
  203. * Decodes a MIME encoded string and returns a Zend\Mime\Message object with
  204. * all the MIME parts set according to the given string
  205. *
  206. * @param string $message
  207. * @param string $boundary Multipart boundary; if omitted, $message will be
  208. * treated as a single part.
  209. * @param string $EOL EOL string; defaults to {@link Zend\Mime\Mime::LINEEND}
  210. * @throws Exception\RuntimeException
  211. * @return Message
  212. */
  213. public static function createFromMessage($message, $boundary = null, $EOL = Mime::LINEEND)
  214. {
  215. if ($boundary) {
  216. $parts = Decode::splitMessageStruct($message, $boundary, $EOL);
  217. } else {
  218. Decode::splitMessage($message, $headers, $body, $EOL);
  219. $parts = [[
  220. 'header' => $headers,
  221. 'body' => $body,
  222. ]];
  223. }
  224. $res = new static();
  225. foreach ($parts as $part) {
  226. // now we build a new MimePart for the current Message Part:
  227. $properties = [];
  228. foreach ($part['header'] as $header) {
  229. /** @var \Zend\Mail\Header\HeaderInterface $header */
  230. /**
  231. * @todo check for characterset and filename
  232. */
  233. $fieldName = $header->getFieldName();
  234. $fieldValue = $header->getFieldValue();
  235. switch (strtolower($fieldName)) {
  236. case 'content-type':
  237. $properties['type'] = $fieldValue;
  238. break;
  239. case 'content-transfer-encoding':
  240. $properties['encoding'] = $fieldValue;
  241. break;
  242. case 'content-id':
  243. $properties['id'] = trim($fieldValue, '<>');
  244. break;
  245. case 'content-disposition':
  246. $properties['disposition'] = $fieldValue;
  247. break;
  248. case 'content-description':
  249. $properties['description'] = $fieldValue;
  250. break;
  251. case 'content-location':
  252. $properties['location'] = $fieldValue;
  253. break;
  254. case 'content-language':
  255. $properties['language'] = $fieldValue;
  256. break;
  257. default:
  258. // Ignore unknown header
  259. break;
  260. }
  261. }
  262. $body = $part['body'];
  263. if (isset($properties['encoding'])) {
  264. switch ($properties['encoding']) {
  265. case 'quoted-printable':
  266. $body = quoted_printable_decode($body);
  267. break;
  268. case 'base64':
  269. $body = base64_decode($body);
  270. break;
  271. }
  272. }
  273. $newPart = new Part($body);
  274. foreach ($properties as $key => $value) {
  275. $newPart->$key = $value;
  276. }
  277. $res->addPart($newPart);
  278. }
  279. return $res;
  280. }
  281. }