3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
10 namespace Zend\Mail\Storage\Part
;
12 use Zend\Mail\Headers
;
13 use Zend\Mail\Storage\Part
;
15 class File
extends Part
17 protected $contentPos = array();
18 protected $partPos = array();
24 * This handler supports the following params:
25 * - file filename or open file handler with message content (required)
26 * - startPos start position of message or part in file (default: current position)
27 * - endPos end position of message or part in file (default: end of file)
29 * @param array $params full message with or without headers
30 * @throws Exception\RuntimeException
31 * @throws Exception\InvalidArgumentException
33 public function __construct(array $params)
35 if (empty($params['file'])) {
36 throw new Exception\
InvalidArgumentException('no file given in params');
39 if (!is_resource($params['file'])) {
40 $this->fh
= fopen($params['file'], 'r');
42 $this->fh
= $params['file'];
45 throw new Exception\
RuntimeException('could not open file');
47 if (isset($params['startPos'])) {
48 fseek($this->fh
, $params['startPos']);
51 $endPos = isset($params['endPos']) ?
$params['endPos'] : null;
52 while (($endPos === null ||
ftell($this->fh
) < $endPos) && trim($line = fgets($this->fh
))) {
56 $this->headers
= Headers
::fromString($header);
58 $this->contentPos
[0] = ftell($this->fh
);
59 if ($endPos !== null) {
60 $this->contentPos
[1] = $endPos;
62 fseek($this->fh
, 0, SEEK_END
);
63 $this->contentPos
[1] = ftell($this->fh
);
65 if (!$this->isMultipart()) {
69 $boundary = $this->getHeaderField('content-type', 'boundary');
71 throw new Exception\
RuntimeException('no boundary found in content type to split message');
75 $pos = $this->contentPos
[0];
76 fseek($this->fh
, $pos);
77 while (!feof($this->fh
) && ($endPos === null ||
$pos < $endPos)) {
78 $line = fgets($this->fh
);
79 if ($line === false) {
80 if (feof($this->fh
)) {
83 throw new Exception\
RuntimeException('error reading file');
87 $pos = ftell($this->fh
);
90 if ($line == '--' . $boundary) {
94 $this->partPos
[] = $part;
97 } elseif ($line == '--' . $boundary . '--') {
99 $this->partPos
[] = $part;
103 $this->countParts
= count($this->partPos
);
111 * If part is multipart the raw content of this part with all sub parts is returned
113 * @param resource $stream Optional
114 * @return string body
116 public function getContent($stream = null)
118 fseek($this->fh
, $this->contentPos
[0]);
119 if ($stream !== null) {
120 return stream_copy_to_stream($this->fh
, $stream, $this->contentPos
[1] - $this->contentPos
[0]);
122 $length = $this->contentPos
[1] - $this->contentPos
[0];
123 return $length < 1 ?
'' : fread($this->fh
, $length);
127 * Return size of part
129 * Quite simple implemented currently (not decoding). Handle with care.
133 public function getSize()
135 return $this->contentPos
[1] - $this->contentPos
[0];
139 * Get part of multipart message
141 * @param int $num number of part starting with 1 for first part
142 * @throws Exception\RuntimeException
143 * @return Part wanted part
145 public function getPart($num)
148 if (!isset($this->partPos
[$num])) {
149 throw new Exception\
RuntimeException('part not found');
152 return new static(array('file' => $this->fh
, 'startPos' => $this->partPos
[$num][0],
153 'endPos' => $this->partPos
[$num][1]));