2 /********************************************************************************
3 * banana/protocoleinterface.inc.php : interface for box access
4 * ------------------------
6 * This file is part of the banana distribution
7 * Copyright: See COPYING files that comes with this distribution
8 ********************************************************************************/
10 require_once dirname(__FILE__
) . '/banana.inc.php';
11 require_once dirname(__FILE__
) . '/protocoleinterface.inc.php';
12 require_once dirname(__FILE__
) . '/message.inc.php';
14 class BananaMBox
implements BananaProtocoleInterface
16 private $debug = false
;
17 private $bt = array();
19 private $_lasterrno = 0;
20 private $_lasterror = null
;
22 public function __construct()
24 $this->debug
= Banana
::$debug_mbox;
27 public function isValid()
30 //!Banana::$group || $this->file;
33 /** Indicate last error n°
35 public function lastErrNo()
37 return $this->_lasterrno
;;
40 /** Indicate last error text
42 public function lastError()
44 return $this->_lasterror
;
47 /** Return the description of the current box
49 public function getDescription()
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)
60 public function getBoxList($mode = Banana
::BOXES_ALL
, $since = 0, $withstats = false
)
62 return array(Banana
::$group => array('desc' => '', 'msgnum' => 0, 'unread' => 0));
65 private function &getRawMessage($id)
68 if (!is_numeric($id)) {
69 if (!Banana
::$spool) {
72 $id = Banana
::$spool->ids
[$id];
74 $options = array ('-m ' . $id);
75 $this->getMBoxPosition($options, $id);
76 return $this->callHelper('-b', $options);
80 * @param id Id of the emssage (can be either an Message-id or a message index)
81 * @return A BananaMessage or null if the given id can't be retreived
83 public function &getMessage($id)
85 $messages =& $this->getRawMessage($id);
87 $messages = new BananaMessage($messages);
92 /** Return the sources of the given message
94 public function getMessageSource($id)
96 $message =& $this->getRawMessage($id);
98 $message = implode("\n", $message);
103 /** Compute the number of messages of the box
105 private function getCount()
108 if (@filesize
($this->getFileName()) == Banana
::$spool->storage
['size']) {
109 return max(Banana
::$spool->ids
) +
1;
111 $this->getMBoxPosition($options);
112 $val =& $this->callHelper('-c', $options);
116 return intval(trim($val[0]));
119 /** Return the indexes of the messages presents in the Box
120 * @return Array(number of messages, MSGNUM of the first message, MSGNUM of the last message)
122 public function getIndexes()
124 $count = $this->getCount();
125 return array($count, 0, $count - 1);
128 /** Return the message headers (in BananaMessage) for messages from firstid to lastid
129 * @return Array(id => array(headername => headervalue))
131 public function &getMessageHeaders($firstid, $lastid, array $msg_headers = array())
135 $options[] = "-m $firstid:$lastid";
136 $this->getMboxPosition($options, $firstid);
137 $lines =& $this->callHelper('-d', $options, $msg_headers);
145 foreach ($lines as $key=>&$line) {
152 } elseif ($get_pos) {
153 $headers[$id] = array('beginning' => intval($line));
155 } elseif (empty($line) && empty($hname)) {
157 } elseif (empty($hname)) {
159 } elseif ($hname == 'date') {
160 $headers[$id][$hname] = @strtotime
($line);
163 BananaMimePart
::decodeHeader($line, $hname);
164 $headers[$id][$hname] = $line;
172 /** Add storage data in spool overview
174 public function updateSpool(array &$messages)
176 foreach ($messages as $id=>&$data) {
177 if (isset(Banana
::$spool->overview
[$id])) {
178 Banana
::$spool->overview
[$id]->storage
['offset'] = $data['beginning'];
181 Banana
::$spool->storage
['size'] = @filesize
($this->getFileName());
184 /** Return the indexes of the new messages since the give date
185 * @return Array(MSGNUM of new messages)
187 public function getNewIndexes($since)
190 if (is_null($this->file
)) {
193 if (is_null($this->new_messages
)) {
196 return range($this->count
- $this->new_messages
, $this->count
- 1);
199 /** Return wether or not the protocole can be used to add new messages
201 public function canSend()
206 /** Return false because we can't cancel a mail
208 public function canCancel()
213 /** Return the list of requested headers
214 * @return Array('header1', 'header2', ...) with the key 'dest' for the destination header
215 * and 'reply' for the reply header, eg:
216 * * for a mail: Array('From', 'Subject', 'dest' => 'To', 'Cc', 'Bcc', 'reply' => 'Reply-To')
217 * * for a post: Array('From', 'Subject', 'dest' => 'Newsgroups', 'reply' => 'Followup-To')
219 public function requestedHeaders()
221 return Array('From', 'Subject', 'dest' => 'To', 'Cc', 'Bcc', 'reply' => 'Reply-To');
225 * @return true if it was successfull
227 public function send(BananaMessage
&$message)
229 $headers = $message->getHeaders();
230 $to = $headers['To'];
231 $subject = $headers['Subject'];
232 unset($headers['To']);
233 unset($headers['Subject']);
235 foreach ($headers as $key=>$value) {
236 if (!empty($value)) {
237 $hdrs .= "$key: $value\r\n";
240 $body = $message->get(false
);
241 return mail($to, $subject, $body, $hdrs);
245 * @return true if it was successfull
247 public function cancel(BananaMessage
&$message)
252 /** Return the protocole name
254 public function name()
259 /** Return the spool filename
261 public function filename()
263 @list
($mail, $domain) = explode('@', Banana
::$group);
265 if (isset($domain)) {
266 $file = $domain . '_';
268 return $file . $mail;
271 /** Return the execution backtrace
273 public function backtrace()
283 # Filesystem functions
286 protected function getFileName()
288 if (is_null(Banana
::$group)) {
291 @list
($mail, $domain) = explode('@', Banana
::$group);
292 return Banana
::$mbox_path . '/' . $mail;
299 /** Add the '-p' optioin for callHelper
301 private function getMBoxPosition(array &$options, $id = null
)
303 if (Banana
::$spool->overview
) {
304 if (!is_null($id) && isset(Banana
::$spool->overview
[$id])) {
307 $key = max(Banana
::$spool->ids
);
308 if (!is_null($id) && $key >= $id) {
312 if (isset(Banana
::$spool->overview
[$key]->storage
['offset'])) {
313 $options[] = '-p ' . $key . ':' . Banana
::$spool->overview
[$key]->storage
['offset'];
318 private function &callHelper($action, array $options = array(), array $headers = array())
320 $action .= ' -f ' . $this->getFileName();
321 $cmd = Banana
::$mbox_helper . " $action " . implode(' ', $options) . ' ' . implode(' ', $headers);
323 $start = microtime(true
);
325 exec($cmd, $out, $return);
327 $this->bt
[] = array('action' => $cmd, 'time' => (microtime(true
) - $start),
328 'code' => $return, 'response' => count($out), 'error' => $return ?
"Helper failed" : null
);
331 $this->_lasterrorno
= 1;
332 $this->_lasterrorcode
= "Helper failed";
339 // vim:set et sw=4 sts=4 ts=4 enc=utf-8: