Add missing exit when no mbox is found
[banana.git] / banana / mbox.inc.php
CommitLineData
7027794f 1<?php
2/********************************************************************************
3* banana/protocoleinterface.inc.php : interface for box access
4* ------------------------
5*
6* This file is part of the banana distribution
7* Copyright: See COPYING files that comes with this distribution
8********************************************************************************/
9
10require_once dirname(__FILE__) . '/banana.inc.php';
11require_once dirname(__FILE__) . '/protocoleinterface.inc.php';
12require_once dirname(__FILE__) . '/message.inc.php';
13
14class BananaMBox implements BananaProtocoleInterface
15{
19fc7e1d 16 private $debug = false;
6a684b9b 17 private $bt = array();
18
7027794f 19 private $_lasterrno = 0;
20 private $_lasterror = null;
19fc7e1d 21
0e25d15d 22 public function __construct()
7027794f 23 {
19fc7e1d 24 $this->debug = Banana::$debug_mbox;
7027794f 25 }
19fc7e1d 26
7027794f 27 public function isValid()
28 {
c28d3016 29 return true;
30 //!Banana::$group || $this->file;
7027794f 31 }
32
598a1c53 33 /** Indicate last error n°
7027794f 34 */
35 public function lastErrNo()
36 {
37 return $this->_lasterrno;;
38 }
39
40 /** Indicate last error text
41 */
42 public function lastError()
43 {
44 return $this->_lasterror;
45 }
46
47 /** Return the description of the current box
48 */
49 public function getDescription()
50 {
51 return null;
52 }
53
54 /** Return the list of the boxes
55 * @param mode Kind of boxes to list
56 * @param since date of last check (for new boxes and new messages)
57 * @param withstats Indicated whether msgnum and unread must be set in the result
58 * @return Array(boxname => array(desc => boxdescripton, msgnum => number of message, unread =>number of unread messages)
59 */
60 public function getBoxList($mode = Banana::BOXES_ALL, $since = 0, $withstats = false)
61 {
0e25d15d 62 return array(Banana::$group => array('desc' => '', 'msgnum' => 0, 'unread' => 0));
7027794f 63 }
64
19fc7e1d 65 private function &getRawMessage($id)
7027794f 66 {
7d3f4749 67 $message = null;
7a5823f9 68 if (!is_numeric($id)) {
19fc7e1d 69 if (!Banana::$spool) {
7d3f4749 70 return $message;
7027794f 71 }
72 $id = Banana::$spool->ids[$id];
73 }
19fc7e1d 74 $options = array ('-m ' . $id);
75 if (Banana::$spool->overview) {
76 if (Banana::$spool->overview[$id]) {
77 $options[] = '-p ' . $id . ':' . Banana::$spool->overview[$id]->storage['offset'];
78 } else {
79 $key = max(array_keys(Banana::$spool->overview));
80 if ($key < $id) {
81 $options[] = '-p ' . $key . ':' . Banana::$spool->overview[$key]->storage['offset'];
82 }
83 }
7027794f 84 }
19fc7e1d 85 return $this->callHelper('-b', $options);
86 }
87
88 /** Return a message
89 * @param id Id of the emssage (can be either an Message-id or a message index)
90 * @return A BananaMessage or null if the given id can't be retreived
91 */
92 public function &getMessage($id)
93 {
94 $messages =& $this->getRawMessage($id);
95 if ($messages) {
96 $messages = new BananaMessage($messages);
97 }
98 return $messages;
7027794f 99 }
100
7a5823f9 101 /** Return the sources of the given message
102 */
103 public function getMessageSource($id)
19fc7e1d 104 {
105 $message =& $this->getRawMessage($id);
106 if ($message) {
107 $message = implode("\n", $message);
c28d3016 108 }
19fc7e1d 109 return $message;
7a5823f9 110 }
111
112 /** Compute the number of messages of the box
113 */
7027794f 114 private function getCount()
115 {
19fc7e1d 116 $options = array();
117 if (Banana::$spool->overview) {
118 $key = max(array_keys(Banana::$spool->overview));
119 $options[] = '-p ' . $key . ':' . Banana::$spool->overview[$key]->storage['offset'];
120 }
121 $val =& $this->callHelper('-c', $options);
122 if (!$val) {
123 return 0;
124 }
125 return intval(trim($val[0]));
7027794f 126 }
127
128 /** Return the indexes of the messages presents in the Box
129 * @return Array(number of messages, MSGNUM of the first message, MSGNUM of the last message)
130 */
131 public function getIndexes()
132 {
19fc7e1d 133 $count = $this->getCount();
134 return array($count, 0, $count - 1);
7027794f 135 }
136
137 /** Return the message headers (in BananaMessage) for messages from firstid to lastid
138 * @return Array(id => array(headername => headervalue))
139 */
140 public function &getMessageHeaders($firstid, $lastid, array $msg_headers = array())
141 {
19fc7e1d 142 $headers = null;
143 $options = array();
144 $options[] = "-m $firstid:$lastid";
145 if (Banana::$spool->overview) {
146 if (isset(Banana::$spool->overview[$firstid])) {
147 $options[] = '-p ' . $firstid . ':' . Banana::$spool->overview[$firstid]->storage['offset'];
148 } else {
149 $key = max(array_keys(Banana::$spool->overview));
150 if ($key < $firstid) {
151 $options[] = '-p ' . $key . ':' . Banana::$spool->overview[$key]->storage['offset'];
152 }
153 }
154 }
155 $lines =& $this->callHelper('-d', $options, $msg_headers);
156 if (!$lines) {
c28d3016 157 return $headers;
158 }
19fc7e1d 159 $headers = array();
160 while ($lines) {
161 $id = array_shift($lines);
162 if ($id === '') {
163 continue;
164 }
165 $offset = array_shift($lines);
166 if ($offset === '') {
167 continue;
168 }
169 $id = intval($id);
170 $headers[$id] = array('beginning' => intval($offset));
171 while (true) {
172 $hname = array_shift($lines);
173 if ($hname === '') {
174 break;
175 }
176 $hval = array_shift($lines);
177 if ($hval === '') {
178 break;
7027794f 179 }
19fc7e1d 180 if ($hname == 'date') {
181 $headers[$id][$hname] = @strtotime($hval);
7027794f 182 } else {
19fc7e1d 183 $headers[$id][$hname] = $hval;
7027794f 184 }
185 }
19fc7e1d 186 if (!isset($headers[$id]['date'])) {
187 print_r($id);
188 print_r($offset);
189 print_r($headers[$id]);
190 }
7027794f 191 }
19fc7e1d 192 array_walk_recursive($headers, array('BananaMimePart', 'decodeHeader'));
7027794f 193 return $headers;
194 }
195
196 /** Add storage data in spool overview
197 */
198 public function updateSpool(array &$messages)
199 {
200 foreach ($messages as $id=>&$data) {
201 if (isset(Banana::$spool->overview[$id])) {
202 Banana::$spool->overview[$id]->storage['offset'] = $data['beginning'];
7027794f 203 }
204 }
205 }
206
207 /** Return the indexes of the new messages since the give date
208 * @return Array(MSGNUM of new messages)
209 */
210 public function getNewIndexes($since)
211 {
703b83c3 212 $this->open();
c28d3016 213 if (is_null($this->file)) {
214 return array();
215 }
7027794f 216 if (is_null($this->new_messages)) {
217 $this->getCount();
218 }
219 return range($this->count - $this->new_messages, $this->count - 1);
220 }
221
222 /** Return wether or not the protocole can be used to add new messages
223 */
224 public function canSend()
225 {
226 return true;
227 }
228
229 /** Return false because we can't cancel a mail
230 */
231 public function canCancel()
232 {
233 return false;
234 }
235
236 /** Return the list of requested headers
237 * @return Array('header1', 'header2', ...) with the key 'dest' for the destination header
238 * and 'reply' for the reply header, eg:
239 * * for a mail: Array('From', 'Subject', 'dest' => 'To', 'Cc', 'Bcc', 'reply' => 'Reply-To')
240 * * for a post: Array('From', 'Subject', 'dest' => 'Newsgroups', 'reply' => 'Followup-To')
241 */
242 public function requestedHeaders()
243 {
244 return Array('From', 'Subject', 'dest' => 'To', 'Cc', 'Bcc', 'reply' => 'Reply-To');
245 }
246
247 /** Send a message
248 * @return true if it was successfull
249 */
250 public function send(BananaMessage &$message)
251 {
e1debf92 252 $headers = $message->getHeaders();
253 $to = $headers['To'];
254 $subject = $headers['Subject'];
255 unset($headers['To']);
256 unset($headers['Subject']);
257 $hdrs = '';
258 foreach ($headers as $key=>$value) {
259 if (!empty($value)) {
260 $hdrs .= "$key: $value\r\n";
261 }
262 }
263 $body = $message->get(false);
264 return mail($to, $subject, $body, $hdrs);
7027794f 265 }
266
267 /** Cancel a message
268 * @return true if it was successfull
269 */
270 public function cancel(BananaMessage &$message)
271 {
272 return false;
273 }
274
275 /** Return the protocole name
276 */
277 public function name()
278 {
279 return 'MBOX';
280 }
281
e9360b11 282 /** Return the spool filename
283 */
284 public function filename()
285 {
286 @list($mail, $domain) = explode('@', Banana::$group);
287 $file = "";
288 if (isset($domain)) {
289 $file = $domain . '_';
290 }
291 return $file . $mail;
292 }
293
6a684b9b 294 /** Return the execution backtrace
295 */
296 public function backtrace()
297 {
298 if ($this->debug) {
299 return $this->bt;
300 } else {
301 return null;
302 }
303 }
304
7027794f 305#######
306# Filesystem functions
307#######
308
c28d3016 309 protected function getFileName()
7027794f 310 {
c28d3016 311 if (is_null(Banana::$group)) {
7027794f 312 return null;
313 }
c28d3016 314 @list($mail, $domain) = explode('@', Banana::$group);
e9360b11 315 return Banana::$mbox_path . '/' . $mail;
7027794f 316 }
317
318#######
319# MBox parser
320#######
321
19fc7e1d 322 private function &callHelper($action, array $options = array(), array $headers = array())
7027794f 323 {
19fc7e1d 324 $action .= ' -f ' . $this->getFileName();
325 $cmd = Banana::$mbox_helper . " $action " . implode(' ', $options) . ' ' . implode(' ', $headers);
326 if ($this->debug) {
19fc7e1d 327 $start = microtime(true);
7027794f 328 }
19fc7e1d 329 exec($cmd, $out, $return);
330 if ($this->debug) {
6a684b9b 331 $this->bt[] = array('action' => $cmd, 'time' => (microtime(true) - $start),
332 'code' => $return, 'response' => count($out));
7027794f 333 }
19fc7e1d 334 if ($return != 0) {
335 $this->_lasterrorno = 1;
336 $this->_lasterrorcode = "Helper failed";
337 $out = null;
7027794f 338 }
19fc7e1d 339 return $out;
7027794f 340 }
341}
342
598a1c53 343// vim:set et sw=4 sts=4 ts=4 enc=utf-8:
7027794f 344?>