PageRenderTime 50ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/Zend/Mail/Part.php

https://bitbucket.org/freddixx/e-business-vcrm-plugin
PHP | 486 lines | 203 code | 55 blank | 228 comment | 40 complexity | 0be81ceb83d1c0c72f820daf56cf5554 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_Mail
  17. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. * @version $Id: Part.php 9099 2008-03-30 19:35:47Z thomas $
  20. */
  21. /**
  22. * @see Zend_Mime_Decode
  23. */
  24. require_once 'Zend/Mime/Decode.php';
  25. /**
  26. * @see Zend_Mail_Part_Interface
  27. */
  28. require_once 'Zend/Mail/Part/Interface.php';
  29. /**
  30. * @category Zend
  31. * @package Zend_Mail
  32. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  33. * @license http://framework.zend.com/license/new-bsd New BSD License
  34. */
  35. class Zend_Mail_Part implements RecursiveIterator, Zend_Mail_Part_Interface
  36. {
  37. /**
  38. * headers of part as array
  39. * @var null|array
  40. */
  41. protected $_headers;
  42. /**
  43. * raw part body
  44. * @var null|string
  45. */
  46. protected $_content;
  47. /**
  48. * toplines as fetched with headers
  49. * @var string
  50. */
  51. protected $_topLines = '';
  52. /**
  53. * parts of multipart message
  54. * @var array
  55. */
  56. protected $_parts = array();
  57. /**
  58. * count of parts of a multipart message
  59. * @var null|int
  60. */
  61. protected $_countParts;
  62. /**
  63. * current position of iterator
  64. * @var int
  65. */
  66. protected $_iterationPos = 1;
  67. /**
  68. * mail handler, if late fetch is active
  69. * @var null|Zend_Mail_Storage_Abstract
  70. */
  71. protected $_mail;
  72. /**
  73. * message number for mail handler
  74. * @var int
  75. */
  76. protected $_messageNum = 0;
  77. /**
  78. * Public constructor
  79. *
  80. * Zend_Mail_Part supports different sources for content. The possible params are:
  81. * - handler a instance of Zend_Mail_Storage_Abstract for late fetch
  82. * - id number of message for handler
  83. * - raw raw content with header and body as string
  84. * - headers headers as array (name => value) or string, if a content part is found it's used as toplines
  85. * - noToplines ignore content found after headers in param 'headers'
  86. * - content content as string
  87. *
  88. * @param array $params full message with or without headers
  89. * @throws Zend_Mail_Exception
  90. */
  91. public function __construct(array $params)
  92. {
  93. if (isset($params['handler'])) {
  94. if (!$params['handler'] instanceof Zend_Mail_Storage_Abstract) {
  95. /**
  96. * @see Zend_Mail_Exception
  97. */
  98. require_once 'Zend/Mail/Exception.php';
  99. throw new Zend_Mail_Exception('handler is not a valid mail handler');
  100. }
  101. if (!isset($params['id'])) {
  102. /**
  103. * @see Zend_Mail_Exception
  104. */
  105. require_once 'Zend/Mail/Exception.php';
  106. throw new Zend_Mail_Exception('need a message id with a handler');
  107. }
  108. $this->_mail = $params['handler'];
  109. $this->_messageNum = $params['id'];
  110. }
  111. if (isset($params['raw'])) {
  112. Zend_Mime_Decode::splitMessage($params['raw'], $this->_headers, $this->_content);
  113. } else if (isset($params['headers'])) {
  114. if (is_array($params['headers'])) {
  115. $this->_headers = $params['headers'];
  116. } else {
  117. if (!empty($params['noToplines'])) {
  118. Zend_Mime_Decode::splitMessage($params['headers'], $this->_headers, $null);
  119. } else {
  120. Zend_Mime_Decode::splitMessage($params['headers'], $this->_headers, $this->_topLines);
  121. }
  122. }
  123. if (isset($params['content'])) {
  124. $this->_content = $params['content'];
  125. }
  126. }
  127. }
  128. /**
  129. * Check if part is a multipart message
  130. *
  131. * @return bool if part is multipart
  132. */
  133. public function isMultipart()
  134. {
  135. try {
  136. return stripos($this->contentType, 'multipart/') === 0;
  137. } catch(Zend_Mail_Exception $e) {
  138. return false;
  139. }
  140. }
  141. /**
  142. * Body of part
  143. *
  144. * If part is multipart the raw content of this part with all sub parts is returned
  145. *
  146. * @return string body
  147. * @throws Zend_Mail_Exception
  148. */
  149. public function getContent()
  150. {
  151. if ($this->_content !== null) {
  152. return $this->_content;
  153. }
  154. if ($this->_mail) {
  155. return $this->_mail->getRawContent($this->_messageNum);
  156. } else {
  157. /**
  158. * @see Zend_Mail_Exception
  159. */
  160. require_once 'Zend/Mail/Exception.php';
  161. throw new Zend_Mail_Exception('no content');
  162. }
  163. }
  164. /**
  165. * Return size of part
  166. *
  167. * Quite simple implemented currently (not decoding). Handle with care.
  168. *
  169. * @return int size
  170. */
  171. public function getSize() {
  172. return strlen($this->getContent());
  173. }
  174. /**
  175. * Cache content and split in parts if multipart
  176. *
  177. * @return null
  178. * @throws Zend_Mail_Exception
  179. */
  180. protected function _cacheContent()
  181. {
  182. // caching content if we can't fetch parts
  183. if ($this->_content === null && $this->_mail) {
  184. $this->_content = $this->_mail->getRawContent($this->_messageNum);
  185. }
  186. if (!$this->isMultipart()) {
  187. return;
  188. }
  189. // split content in parts
  190. $boundary = $this->getHeaderField('content-type', 'boundary');
  191. if (!$boundary) {
  192. /**
  193. * @see Zend_Mail_Exception
  194. */
  195. require_once 'Zend/Mail/Exception.php';
  196. throw new Zend_Mail_Exception('no boundary found in content type to split message');
  197. }
  198. $parts = Zend_Mime_Decode::splitMessageStruct($this->_content, $boundary);
  199. $counter = 1;
  200. foreach ($parts as $part) {
  201. $this->_parts[$counter++] = new self(array('headers' => $part['header'], 'content' => $part['body']));
  202. }
  203. }
  204. /**
  205. * Get part of multipart message
  206. *
  207. * @param int $num number of part starting with 1 for first part
  208. * @return Zend_Mail_Part wanted part
  209. * @throws Zend_Mail_Exception
  210. */
  211. public function getPart($num)
  212. {
  213. if (isset($this->_parts[$num])) {
  214. return $this->_parts[$num];
  215. }
  216. if (!$this->_mail && $this->_content === null) {
  217. /**
  218. * @see Zend_Mail_Exception
  219. */
  220. require_once 'Zend/Mail/Exception.php';
  221. throw new Zend_Mail_Exception('part not found');
  222. }
  223. if ($this->_mail && $this->_mail->hasFetchPart) {
  224. // TODO: fetch part
  225. // return
  226. }
  227. $this->_cacheContent();
  228. if (!isset($this->_parts[$num])) {
  229. /**
  230. * @see Zend_Mail_Exception
  231. */
  232. require_once 'Zend/Mail/Exception.php';
  233. throw new Zend_Mail_Exception('part not found');
  234. }
  235. return $this->_parts[$num];
  236. }
  237. /**
  238. * Count parts of a multipart part
  239. *
  240. * @return int number of sub-parts
  241. */
  242. public function countParts()
  243. {
  244. if ($this->_countParts) {
  245. return $this->_countParts;
  246. }
  247. $this->_countParts = count($this->_parts);
  248. if ($this->_countParts) {
  249. return $this->_countParts;
  250. }
  251. if ($this->_mail && $this->_mail->hasFetchPart) {
  252. // TODO: fetch part
  253. // return
  254. }
  255. $this->_cacheContent();
  256. $this->_countParts = count($this->_parts);
  257. return $this->_countParts;
  258. }
  259. /**
  260. * Get all headers
  261. *
  262. * The returned headers are as saved internally. All names are lowercased. The value is a string or an array
  263. * if a header with the same name occurs more than once.
  264. *
  265. * @return array headers as array(name => value)
  266. */
  267. public function getHeaders()
  268. {
  269. if ($this->_headers === null) {
  270. if (!$this->_mail) {
  271. $this->_headers = array();
  272. } else {
  273. $part = $this->_mail->getRawHeader($this->_messageNum);
  274. Zend_Mime_Decode::splitMessage($part, $this->_headers, $null);
  275. }
  276. }
  277. return $this->_headers;
  278. }
  279. /**
  280. * Get a header in specificed format
  281. *
  282. * Internally headers that occur more than once are saved as array, all other as string. If $format
  283. * is set to string implode is used to concat the values (with Zend_Mime::LINEEND as delim).
  284. *
  285. * @param string $name name of header, matches case-insensitive, but camel-case is replaced with dashes
  286. * @param string $format change type of return value to 'string' or 'array'
  287. * @return string|array value of header in wanted or internal format
  288. * @throws Zend_Mail_Exception
  289. */
  290. public function getHeader($name, $format = null)
  291. {
  292. if ($this->_headers === null) {
  293. $this->getHeaders();
  294. }
  295. $lowerName = strtolower($name);
  296. if (!isset($this->_headers[$lowerName])) {
  297. $lowerName = strtolower(preg_replace('%([a-z])([A-Z])%', '\1-\2', $name));
  298. if (!isset($this->_headers[$lowerName])) {
  299. /**
  300. * @see Zend_Mail_Exception
  301. */
  302. require_once 'Zend/Mail/Exception.php';
  303. throw new Zend_Mail_Exception("no Header with Name $name found");
  304. }
  305. }
  306. $name = $lowerName;
  307. $header = $this->_headers[$name];
  308. switch ($format) {
  309. case 'string':
  310. if (is_array($header)) {
  311. $header = implode(Zend_Mime::LINEEND, $header);
  312. }
  313. break;
  314. case 'array':
  315. $header = (array)$header;
  316. default:
  317. // do nothing
  318. }
  319. return $header;
  320. }
  321. /**
  322. * Get a specific field from a header like content type or all fields as array
  323. *
  324. * If the header occurs more than once, only the value from the first header
  325. * is returned.
  326. *
  327. * Throws a Zend_Mail_Exception if the requested header does not exist. If
  328. * the specific header field does not exist, returns null.
  329. *
  330. * @param string $name name of header, like in getHeader()
  331. * @param string $wantedPart the wanted part, default is first, if null an array with all parts is returned
  332. * @param string $firstName key name for the first part
  333. * @return string|array wanted part or all parts as array($firstName => firstPart, partname => value)
  334. * @throws Zend_Exception, Zend_Mail_Exception
  335. */
  336. public function getHeaderField($name, $wantedPart = 0, $firstName = 0) {
  337. return Zend_Mime_Decode::splitHeaderField(current($this->getHeader($name, 'array')), $wantedPart, $firstName);
  338. }
  339. /**
  340. * Getter for mail headers - name is matched in lowercase
  341. *
  342. * This getter is short for Zend_Mail_Part::getHeader($name, 'string')
  343. *
  344. * @see Zend_Mail_Part::getHeader()
  345. *
  346. * @param string $name header name
  347. * @return string value of header
  348. * @throws Zend_Mail_Exception
  349. */
  350. public function __get($name)
  351. {
  352. return $this->getHeader($name, 'string');
  353. }
  354. /**
  355. * magic method to get content of part
  356. *
  357. * @return string content
  358. */
  359. public function __toString()
  360. {
  361. return $this->getContent();
  362. }
  363. /**
  364. * implements RecursiveIterator::hasChildren()
  365. *
  366. * @return bool current element has children/is multipart
  367. */
  368. public function hasChildren()
  369. {
  370. $current = $this->current();
  371. return $current && $current instanceof Zend_Mail_Part && $current->isMultipart();
  372. }
  373. /**
  374. * implements RecursiveIterator::getChildren()
  375. *
  376. * @return Zend_Mail_Part same as self::current()
  377. */
  378. public function getChildren()
  379. {
  380. return $this->current();
  381. }
  382. /**
  383. * implements Iterator::valid()
  384. *
  385. * @return bool check if there's a current element
  386. */
  387. public function valid()
  388. {
  389. if ($this->_countParts === null) {
  390. $this->countParts();
  391. }
  392. return $this->_iterationPos && $this->_iterationPos <= $this->_countParts;
  393. }
  394. /**
  395. * implements Iterator::next()
  396. *
  397. * @return null
  398. */
  399. public function next()
  400. {
  401. ++$this->_iterationPos;
  402. }
  403. /**
  404. * implements Iterator::key()
  405. *
  406. * @return string key/number of current part
  407. */
  408. public function key()
  409. {
  410. return $this->_iterationPos;
  411. }
  412. /**
  413. * implements Iterator::current()
  414. *
  415. * @return Zend_Mail_Part current part
  416. */
  417. public function current()
  418. {
  419. return $this->getPart($this->_iterationPos);
  420. }
  421. /**
  422. * implements Iterator::rewind()
  423. *
  424. * @return null
  425. */
  426. public function rewind()
  427. {
  428. $this->countParts();
  429. $this->_iterationPos = 1;
  430. }
  431. }