commiting uncommited changes on live site
[weblabels.fsf.org.git] / crm.fsf.org / 20131203 / files / sites / all / modules-new / civicrm / packages / ezc / Mail / src / transports / mbox / mbox_transport.php
1 <?php
2 /**
3 * File containing the ezcMailMboxTransport class
4 *
5 * @package Mail
6 * @version 1.7beta1
7 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
8 * @license http://ez.no/licenses/new_bsd New BSD License
9 */
10
11 /**
12 * ezcMailMboxTransport implements mail retrieval from an mbox file.
13 *
14 * The mbox set is constructed from a file pointer and iterates over all the
15 * messages in an mbox file.
16 *
17 * @package Mail
18 * @version 1.7beta1
19 * @mainclass
20 */
21 class ezcMailMboxTransport
22 {
23 /**
24 * Holds the filepointer to the mbox
25 *
26 * @var resource(filepointer)
27 */
28 public $fh;
29
30 /**
31 * Constructs the ezcMailMboxTransport object
32 *
33 * Opens the mbox $fileName.
34 *
35 * @throws ezcBaseFileNotFoundException
36 * if the mbox file could not be found.
37 * @throws ezcBaseFilePermissionException
38 * if the mbox file could be opened for reading.
39 * @param string $fileName
40 */
41 public function __construct( $fileName )
42 {
43 if ( !file_exists( $fileName ) )
44 {
45 throw new ezcBaseFileNotFoundException( $fileName, 'mbox' );
46 }
47 if ( !is_readable( $fileName ) )
48 {
49 throw new ezcBaseFilePermissionException( $fileName, ezcBaseFileException::READ );
50 }
51 $this->fh = fopen( $fileName, 'rt' );
52 }
53
54 /**
55 * Finds the position of the first message while skipping a possible header.
56 *
57 * Mbox files can contain a header which does not describe an email
58 * message. This method skips over this optional header by checking for a
59 * specific From MAILER-DAEMON header.
60 *
61 * @return int
62 */
63 private function findFirstMessage()
64 {
65 $data = fgets( $this->fh );
66 fseek( $this->fh, 0 );
67 if ( substr( $data, 0, 18 ) === 'From MAILER-DAEMON' )
68 {
69 return $this->findNextMessage();
70 }
71 else
72 {
73 return 0;
74 }
75 }
76
77 /**
78 * Reads through the Mbox file and stops at the next message.
79 *
80 * Messages in Mbox files are separated with lines starting with "From "
81 * and this function reads to the next "From " marker. It then returns the
82 * current posistion in the file. If EOF is detected during reading the
83 * function returns false instead.
84 *
85 * @return int
86 */
87 private function findNextMessage()
88 {
89 do
90 {
91 $data = fgets( $this->fh );
92 } while ( !feof( $this->fh ) && substr( $data, 0, 5 ) !== "From " );
93
94 if ( feof( $this->fh ) )
95 {
96 return false;
97 }
98 return ftell( $this->fh );
99 }
100
101 /**
102 * This function reads through the whole mbox and returns starting positions of the messages.
103 *
104 * @return array(int=>int)
105 */
106 public function listMessages()
107 {
108 $messages = array();
109 fseek( $this->fh, 0 );
110 // Skip the first mail as this is the mbox header
111 $position = $this->findFirstMessage();
112 if ( $position === false )
113 {
114 return $messages;
115 }
116 // Continue reading through the rest of the mbox
117 do
118 {
119 $position = $this->findNextMessage();
120 if ( $position !== false )
121 {
122 $messages[] = $position;
123 }
124 } while ( $position !== false );
125
126 return $messages;
127 }
128
129 /**
130 * Returns an ezcMailMboxSet containing all the messages in the mbox.
131 *
132 * @return ezcMailMboxSet
133 */
134 public function fetchAll()
135 {
136 $messages = $this->listMessages();
137 return new ezcMailMboxSet( $this->fh, $messages );
138 }
139
140 /**
141 * Returns an ezcMailMboxSet containing only the $number -th message in the mbox.
142 *
143 * @throws ezcMailNoSuchMessageException
144 * if the message $number is out of range.
145 * @param int $number
146 * @return ezcMailMboxSet
147 */
148 public function fetchByMessageNr( $number )
149 {
150 $messages = $this->listMessages();
151 if ( !isset( $messages[$number] ) )
152 {
153 throw new ezcMailNoSuchMessageException( $number );
154 }
155 return new ezcMailMboxSet( $this->fh, array( 0 => $messages[$number] ) );
156 }
157
158 /**
159 * Returns an ezcMailMboxSet with $count messages starting from $offset.
160 *
161 * Fetches $count messages starting from the $offset and returns them as a
162 * ezcMailMboxSet. If $count is not specified or if it is 0, it fetches
163 * all messages starting from the $offset.
164 *
165 * @throws ezcMailInvalidLimitException
166 * if $count is negative.
167 * @throws ezcMailOffsetOutOfRangeException
168 * if $offset is outside of the existing range of messages.
169 * @param int $offset
170 * @param int $count
171 * @return ezcMailMboxSet
172 */
173 public function fetchFromOffset( $offset, $count = 0 )
174 {
175 if ( $count < 0 )
176 {
177 throw new ezcMailInvalidLimitException( $offset, $count );
178 }
179 $messages = $this->listMessages();
180 if ( !isset( $messages[$offset] ) )
181 {
182 throw new ezcMailOffsetOutOfRangeException( $offset, $count );
183 }
184 if ( $count == 0 )
185 {
186 $range = array_slice( $messages, $offset );
187 }
188 else
189 {
190 $range = array_slice( $messages, $offset, $count );
191 }
192 return new ezcMailMboxSet( $this->fh, $range );
193 }
194 }
195 ?>