Some improvements, and fix spoolgen.php
[banana.git] / banana / nntp.inc.php
1 <?php
2 /********************************************************************************
3 * banana/nntp.inc.php : NNTP protocole handler
4 * ------------------------
5 *
6 * This file is part of the banana distribution
7 * Copyright: See COPYING files that comes with this distribution
8 ********************************************************************************/
9
10 require_once dirname(__FILE__) . '/banana.inc.php';
11 require_once dirname(__FILE__) . '/message.inc.php';
12 require_once dirname(__FILE__) . '/nntpcore.inc.php';
13 require_once dirname(__FILE__) . '/protocoleinterface.inc.php';
14
15 class BananaNNTP extends BananaNNTPCore implements BananaProtocoleInterface
16 {
17 private $description = null;
18 private $ingroup = null;
19
20 private $mode = null;
21 private $boxes = null;
22
23 /** Build a protocole handler plugged on the given box
24 */
25 public function __construct()
26 {
27 $url = parse_url(Banana::$host);
28 if ($url['scheme'] == 'nntps' || $url['scheme'] == 'snntp') {
29 $url['host'] = 'ssl://' . $url['host'];
30 }
31 if (!isset($url['port'])) {
32 $url['port'] = 119;
33 }
34 if (!isset($url['user'])) {
35 parent::__construct($url['host'], $url['port']);
36 } else {
37 parent::__construct($url['host'], $url['port'], 120, false);
38 $this->authinfo($url['user'], $url['pass']);
39 }
40 }
41
42 /** Return the descript;ion of the current box
43 */
44 public function getDescription()
45 {
46 if ($this->description) {
47 return $this->description;
48 }
49 $descs = $this->xgtitle(Banana::$group);
50 if (isset($descs[Banana::$group])) {
51 $this->description = $descs[Banana::$group];
52 }
53 return $this->description;
54 }
55
56 /** Return the list of the boxes
57 * @param mode Kind of boxes to list
58 * @param since date of last check (for new boxes and new messages)
59 * @return Array(boxname => array(desc => boxdescripton, msgnum => number of message, unread =>number of unread messages)
60 */
61 public function getBoxList($mode = Banana::BOXES_ALL, $since = 0, $withstats = false)
62 {
63 if (!is_array($this->boxes) || $this->mode != $mode) {
64 $descs = $this->xgtitle();
65 if ($mode == Banana::BOXES_NEW && $since) {
66 $list = $this->newgroups($since);
67 } else {
68 $list = $this->listGroups();
69 if ($mode == Banana::BOXES_SUB) {
70 $sub = array_flip(Banana::$profile['subscribe']);
71 $list = array_intersect_key($list, $sub);
72 }
73 }
74 $this->boxes = array();
75 foreach ($list as $group=>&$infos) {
76 if (isset($descs[$group])) {
77 $desc = $descs[$group];
78 if (!is_utf8($desc)) {
79 $desc = utf8_encode($desc);
80 }
81 $this->boxes[$group] = array('desc' => $desc);
82 } else {
83 $this->boxes[$group] = array('desc' => null);
84 }
85 }
86 ksort($this->boxes);
87 }
88 if ($withstats) {
89 foreach ($this->boxes as $group=>&$desc) {
90 list($msgnum, $first, $last, $groupname) = $this->group($group);
91 $this->ingroup = $group;
92 $new = count($this->newnews($group, $since));
93 $desc['msgnum'] = $msgnum;
94 $desc['unread'] = $new;
95 }
96 }
97 return $this->boxes;
98 }
99
100 /** Return a message
101 * @param id Id of the emssage (can be either an Message-id or a message index)
102 * @param msg_headers Headers to process
103 * @param is_msgid If is set, $id is en Message-Id
104 * @return A BananaMessage or null if the given id can't be retreived
105 */
106 public function getMessage($id, array $msg_headers = array(), $is_msgid = false)
107 {
108 if (!$is_msgid && Banana::$group != $this->ingroup) {
109 if (is_null(Banana::$spool)) {
110 $this->group(Banana::$group);
111 $this->ingroup = Banana::$group;
112 } else {
113 $id = array_search($id, Banana::$spool->ids);
114 }
115 }
116 $data = $this->article($id);
117 if ($data !== false) {
118 return new BananaMessage($data);
119 }
120 return null;
121 }
122
123 /** Return the indexes of the messages presents in the Box
124 * @return Array(number of messages, MSGNUM of the first message, MSGNUM of the last message)
125 */
126 public function getIndexes()
127 {
128 list($msgnum, $first, $last, $groupname) = $this->group(Banana::$group);
129 $this->ingroup = Banana::$group;
130 return array($msgnum, $first, $last);
131 }
132
133 /** Return the message headers (in BananaMessage) for messages from firstid to lastid
134 * @return Array(id => array(headername => headervalue))
135 */
136 public function &getMessageHeaders($firstid, $lastid, array $msg_headers = array())
137 {
138 $messages = array();
139 foreach ($msg_headers as $header) {
140 $headers = $this->xhdr($header, $firstid, $lastid);
141 array_walk($headers, array('BananaMimePart', 'decodeHeader'));
142 $header = strtolower($header);
143 if ($header == 'date') {
144 $headers = array_map('strtotime', $headers);
145 }
146 foreach ($headers as $id=>&$value) {
147 if (!isset($messages[$id])) {
148 $messages[$id] = array();
149 }
150 $messages[$id][$header] =& $value;
151 }
152 }
153 return $messages;
154 }
155
156 /** Add protocole specific data in the spool
157 */
158 public function updateSpool(array &$messages)
159 {
160 return true;
161 }
162
163 /** Return the indexes of the new messages since the give date
164 * @return Array(MSGNUM of new messages)
165 */
166 public function getNewIndexes($since)
167 {
168 return $this->newnews(Banana::$group, $since);
169 }
170
171 /** Return true if can post
172 */
173 public function canSend()
174 {
175 return $this->isValid();
176 }
177
178 /** Return true if can cancel
179 */
180 public function canCancel()
181 {
182 return $this->isValid();
183 }
184
185 /** Return the list of requested header for a new post
186 */
187 public function requestedHeaders()
188 {
189 return Array('From', 'Subject', 'dest' => 'Newsgroups', 'reply' => 'Followup-To', 'Organization');
190 }
191
192 /** Send the message
193 */
194 public function send(BananaMessage &$message)
195 {
196 $sources = $message->get(true);
197 return $this->post($sources);
198 }
199
200 /** Cancel the message
201 */
202 public function cancel(BananaMessage &$message)
203 {
204 $headers = Array('From' => Banana::$profile['From'],
205 'Newsgroups' => Banana::$group,
206 'Subject' => 'cmsg ' . $message->getHeaderValue('message-id'),
207 'Control' => 'cancel ' . $message->getHeaderValue('message-id'));
208 $headers = array_merge($headers, Banana::$custom_hdr);
209 $body = 'Message canceled with Banana';
210 $msg = BananaMessage::newMessage($headers, $body);
211 return $this->send($msg);
212 }
213
214 /** Return the protocole name
215 */
216 public function name()
217 {
218 return 'NNTP';
219 }
220 }
221
222 /*
223 require_once dirname(__FILE__) . '/spool.inc.php';
224 $time = microtime(true);
225 $nntp = new BananaNNTP('xorg.promo.x2002');
226 if (!$nntp->isValid()) {
227 echo "Beuh !\n";
228 exit;
229 }
230 Banana::$protocole =& $nntp;
231 Banana::$spool =& BananaSpool::getSpool('xorg.promo.x2002');
232 $msg = $nntp->getMessage(3424);
233 echo '<html><head>
234 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
235 <link rel="stylesheet" type="text/css" href="css/banana.css"/>
236 </head><body><table class="banana_msg"><tr><td>';
237 //echo $msg->getFormattedBody('plain');
238 echo $msg->getFormattedBody();
239 echo '</td></tr></table></body></html>', "\n";
240 $end = microtime(true);
241 echo ($end - $time) . "s\n";
242 */
243
244 // vim:set et sw=4 sts=4 ts=4:
245 ?>