old header were to complicated for nothin. drop class Header, and treat it from Post
[banana.git] / include / NetNNTP.inc.php
CommitLineData
bb3b9f8e 1<?php
2/********************************************************************************
3* include/NetNNTP.inc.php : NNTP subroutines
4* -------------------------
5*
6* This file is part of the banana distribution
7* Copyright: See COPYING files that comes with this distribution
8********************************************************************************/
9
10/** Class NNTP
11 * implements some basic functions for NNTP protocol
12 */
13class nntp {
e785d91c 14 /** socket filehandle */
15 var $ns;
16 /** debug mode */
17 var $debug;
18 /** posting allowed */
19 var $posting;
20 /** last NNTP error code */
21 var $lasterrorcode;
22 /** last NNTP error text */
23 var $lasterrortext;
bb3b9f8e 24
25# Socket functions
26
e785d91c 27 /** get a line from server
28 * @return STRING
29 */
bb3b9f8e 30
e785d91c 31 function gline() {
e785d91c 32 if ($this->debug) {
11873d85 33 $line = trim(fgets($this->ns, 1200));
e785d91c 34 print "NNTP >>>> $line \n";
11873d85 35 return $line;
e785d91c 36 }
11873d85 37 return trim(fgets($this->ns, 1200));
bb3b9f8e 38 }
e785d91c 39
40 /** puts a line on server
41 * @param STRING $_line line to put
42 */
43
44 function pline($_line) {
45 if ($this->debug) {
46 $dline = preg_replace("/\r\n$/", "", $_line);
47 $dline = preg_replace("/(\r|\n|\r\n)/", "\nNNTP <<<< ", $dline);
48 print "NNTP <<<< $dline \n";
49 }
50 return fputs($this->ns, $_line, strlen($_line));
bb3b9f8e 51 }
e785d91c 52
53 /** constructor
54 * @param $_host STRING NNTP host
55 * @param $_timeout INTEGER socket timeout
56 * @param $_debug BOOLEAN debug flag (generates verbose output if on)
57 * @param $_reader BOOLEAN sends a "MODE READER" at connection if true
58 */
59
60 function nntp($_host, $_timeout=120, $_debug=0, $_reader=true) {
61 if (preg_match("/([^:]+):([^:]+)/", $_host, $regs)) {
62 $host = $regs[1];
63 $port = $regs[2];
64 } else {
65 $host = $_host;
66 $port = 119;
67 }
68 $this->ns = fsockopen($host, $port, $errno, $errstr, $_timeout);
69 $this->debug = $_debug;
70 if (!$this->ns) {
71 if ($this->debug) {
72 echo "ERREUR: $errno - $errstr <br />\n";
73 }
74 $this = false;
75 return false;
76 }
77 $result = $this->gline();
78 $this->posting = (substr($result, 0, 3)=="200");
79 if ($_reader && ($result{0}=="2")) {
80 $this->pline("MODE READER\r\n");
81 $result = $this->gline();
82 $this->posting = ($result{0}=="200");
83 }
84 return ($result{0}=="2");
bb3b9f8e 85 }
bb3b9f8e 86
87# strict NNTP Functions [RFC 977]
88# see http://www.faqs.org/rfcs/rfc977.html
89
e785d91c 90 /** authentification
91 * @param $_user STRING login
92 * @param $_pass INTEGER password
93 * @return BOOLEAN true if authentication was successful
94 */
95
96 function authinfo($_user, $_pass) {
97 $user = preg_replace("/(\r|\n)/", "", $_user);
98 $pass = preg_replace("/(\r|\n)/", "", $_pass);
99 $this->pline("AUTHINFO USER $user\r\n");
100 $this->gline();
101 $this->pline("AUTHINFO PASS $pass\r\n");
102 $result=$this->gline();
103 if ($result{0}!="2") {
104 $this->lasterrorcode = substr($result, 0, 3);
105 $this->lasterrortext = substr($result, 4);
106 return false;
107 }
bb3b9f8e 108 return true;
bb3b9f8e 109 }
e785d91c 110
111 /** retrieves an article
112 * MSGID is a numeric ID a shown in article's headers. MSGNUM is a
113 * server-dependent ID (see X-Ref on many servers) and retriving
114 * an article by this way will change the current article pointer.
115 * If an error occur, false is returned.
116 * @param $_msgid STRING MSGID or MSGNUM of article
117 * @return ARRAY lines of the article
118 * @see body
119 * @see head
120 */
121
122 function article($_msgid="") {
123 $msgid = preg_replace("/(\r|\n)/", "", $_msgid);
124 $this->pline("ARTICLE $msgid\r\n");
125 $result = $this->gline();
126 if ($result{0} != '2') {
127 $this->lasterrorcode = substr($result, 0, 3);
128 $this->lasterrortext = substr($result, 4);
129 return false;
130 }
131 $result = $this->gline();
132 while ($result != ".") {
133 $array[] = $result;
134 $result = $this->gline();
135 }
136 return $array;
bb3b9f8e 137 }
e785d91c 138
139 /** post a message
140 * if an error occur, false is returned
141 * @param $_message STRING message to post
142 * @return STRING MSGID of article
143 */
144
145 function post($_message) {
146 if (is_array($_message)) {
147 $message=join("\n", $_message);
148 } else {
149 $message=$_message;
150 }
151 $this->pline("POST \r\n");
152 $result=$this->gline();
153 if ($result{0} != '3') {
154 $this->lasterrorcode = substr($result, 0, 3);
155 $this->lasterrortext = substr($result, 4);
156 return false;
157 }
158 $this->pline($message."\r\n.\r\n");
159 $result = $this->gline();
160 if ($result{0} != '2') {
161 $this->lasterrorcode = substr($result, 0, 3);
162 $this->lasterrortext = substr($result, 4);
163 return false;
164 }
165 if ($result{0} == '2') {
166 if (preg_match("/(<[^@>]+@[^@>]+>)/", $result, $regs)) {
167 return $regs[0];
168 } else {
169 return true;
170 }
171 }
172 return false;
bb3b9f8e 173 }
e785d91c 174
175 /** fetches the body of an article
176 * params are the same as article
177 * @param $_msgid STRING MSGID or MSGNUM of article
178 * @return ARRAY lines of the article
179 * @see article
180 * @see head
181 */
182
183 function body($_msgid="") {
184 $msgid = preg_replace("/(\r|\n)/", "", $_msgid);
185 $this->pline("BODY $msgid\r\n");
186 $result = $this->gline();
187 if ($result{0} != '2') {
188 $this->lasterrorcode = substr($result, 0, 3);
189 $this->lasterrortext = substr($result, 4);
190 return false;
191 }
192 $result = $this->gline();
193 while ($result != ".") {
194 $array[] = $result;
195 $result = $this->gline();
196 }
197 return $array;
bb3b9f8e 198 }
e785d91c 199
200 /** fetches the headers of an article
201 * params are the same as article
202 * @param $_msgid STRING MSGID or MSGNUM of article
203 * @return ARRAY lines of the article
204 * @see article
205 * @see body
206 */
207
208 function head($_msgid="") {
209 $msgid = preg_replace("/(\r|\n)/", "", $_msgid);
210 $this->pline("HEAD $msgid\r\n");
211 $result = $this->gline();
212 if ($result{0}!="2") {
213 $this->lasterrorcode = substr($result, 0, 3);
214 $this->lasterrortext = substr($result, 4);
215 return false;
216 }
217 $result = $this->gline();
218 while ($result != ".") {
219 $array[] = $result;
220 $result = $this->gline();
221 }
222 return $array;
bb3b9f8e 223 }
e785d91c 224
225 /** set current group
226 * @param $_group STRING
227 * @return ARRAY array : nb of articles in group, MSGNUM of first article, MSGNUM of last article, and group name
228 */
229
230 function group($_group) {
231 $group = preg_replace("/(\r|\n)/", "", $_group);
232 $this->pline("GROUP $group\r\n");
233 $line = $this->gline();
234 if ($line{0}!="2") {
235 $this->lasterrorcode = substr($line, 0, 3);
236 $this->lasterrortext = substr($line, 4);
237 return false;
238 }
239 if (preg_match("/^2\d{2} (\d+) (\d+) (\d+) ([^ ]+)/", $line, $regs)) {
240 return array($regs[1], $regs[2], $regs[3], $regs[4]);
241 }
11873d85 242 return false;
bb3b9f8e 243 }
e785d91c 244
245 /** set the article pointer to the previous article in current group
246 * @return STRING MSGID of article
247 * @see next
248 */
249
250 function last() {
251 $this->pline("LAST \r\n");
252 $line = $this->gline();
253 if ($line{0}!="2") {
254 $this->lasterrorcode = substr($result, 0, 3);
255 $this->lasterrortext = substr($result, 4);
256 return false;
257 }
258 if (preg_match("/^2\d{2} \d+ <([^>]+)>/", $line, $regs)) {
259 return "<{$regs[1]}>";
260 }
11873d85 261 return false;
bb3b9f8e 262 }
e785d91c 263
264 /** set the article pointer to the next article in current group
265 * @return STRING MSGID of article
266 * @see last
267 */
268
269 function next() {
270 $this->pline("NEXT \r\n");
271 $line = $this->gline();
272 if ($line{0}!="2") {
273 $this->lasterrorcode = substr($result, 0, 3);
274 $this->lasterrortext = substr($result, 4);
275 return false;
276 }
277 if (preg_match("/^2\d{2} \d+ <([^>]+)>/", $line, $regs)) {
278 return "<{$regs[1]}>";
279 }
11873d85 280 return false;
bb3b9f8e 281 }
e785d91c 282
283 /** set the current article pointer
284 * @param $_msgid STRING MSGID or MSGNUM of article
285 * @return BOOLEAN true if authentication was successful, error code otherwise
286 * @see article
287 * @see body
288 */
289
290 function nntpstat($_msgid) {
291 $msgid = preg_replace("/(\r|\n)/", "", $_msgid);
292 $this->pline("STAT $msgid\r\n");
293 $line = $this->gline();
294 if ($line{0}!="2") {
295 $this->lasterrorcode = substr($result, 0, 3);
296 $this->lasterrortext = substr($result, 4);
297 return false;
298 }
299 if (preg_match("/^2\d{2} \d+ <([^>]+)>/", $line, $regs)) {
300 return "<{$regs[1]}>";
301 }
302 return false;
bb3b9f8e 303 }
e785d91c 304
305 /** returns true if posting is allowed
306 * @return BOOLEAN true if posting is allowed lines
307 */
308
309 function postok() {
310 return ($this->posting);
bb3b9f8e 311 }
e785d91c 312
313 /** gets information about all active newsgroups
314 * @return ARRAY group name => (MSGNUM of first article, MSGNUM of last article, NNTP flags)
315 * @see newgroups
316 */
317
318 function liste() {
319 $this->pline("LIST\r\n");
320 if (substr($this->gline(), 0, 1)!="2") return false;
321 $result = $this->gline();
322 while ($result != ".") {
323 preg_match("/([^ ]+) (\d+) (\d+) (.)/", $result, $regs);
324 $array[$regs[1]] = array(intval($regs[2]), intval($regs[3]), intval($regs[4]));
325 $result = $this->gline();
326 }
327 return $array;
bb3b9f8e 328 }
e785d91c 329
330 /** get information about recent newsgroups
331 * same as list, but information are limited to newgroups created after $_since
332 * @param $_since INTEGER unix timestamp
333 * @param $_distributions STRING distributions
334 * @return ARRAY same format as liste
335 * @see liste
336 */
337
338 function newgroups($_since, $_distributions="") {
339#assume $_since is a unix timestamp
340 $distributions = preg_replace("/(\r|\n)/", "", $_distributions);
341 $this->pline("NEWGROUPS ".gmdate("ymd His", $_since)
342 ." GMT $distributions\r\n");
343 if (substr($this->gline(), 0, 1)!="2") {
344 return false;
345 }
346 $result = $this->gline();
347 $array = array();
348 while ($result != ".") {
349 preg_match("/([^ ]+) (\d+) (\d+) (.)/", $result, $regs);
350 $array[$regs[1]] = array(intval($regs[2]), intval($regs[3]), intval($regs[4]));
351 $result = $this->gline();
352 }
353 return $array;
bb3b9f8e 354 }
e785d91c 355
356 /** gets a list of new articles
357 * @param $_since INTEGER unix timestamp
358 * @parma $_groups STRING pattern of intersting groups
359 * @return ARRAY MSGID of new articles
360 */
361
362 function newnews($_since, $_groups="*", $_distributions="") {
363 $distributions = preg_replace("/(\r|\n)/", "", $_distributions);
364 $groups = preg_replace("/(\r|\n)/", "", $_groups);
365 $array = array();
366#assume $since is a unix timestamp
367 $this->pline("NEWNEWS $_groups ".gmdate("ymd His", $_since)." GMT $distributions\r\n");
368 if (substr($this->gline(), 0, 1)!="2") {
369 return false;
370 }
371 $result = $this->gline();
372 while ($result != ".") {
373 $array[] = $result;
374 $result = $this->gline();
375 }
376 return $array;
bb3b9f8e 377 }
e785d91c 378
379 /** Tell the remote server that I am not a user client, but probably another news server
380 * @return BOOLEAN true if sucessful
381 */
382
383 function slave() {
384 $this->pline("SLAVE \r\n");
385 return (substr($this->gline(), 0, 1)=="2");
bb3b9f8e 386 }
e785d91c 387
388 /** implements IHAVE method
389 * @param $_msgid STRING MSGID of article
390 * @param $_message STRING article
391 * @return BOOLEAN
392 */
393
394 function ihave($_msgid, $_message=false) {
395 $msgid = preg_replace("/(\r|\n)/", "", $_msgid);
396 if (is_array($message)) {
397 $message = join("\n", $_message);
398 } else {
399 $message = $_message;
400 }
401 $this->pline("IHAVE $msgid \r\n");
402 $result = $this->gline();
403 if ($message && ($result{0}=="3")) {
404 $this->pline("$message\r\n.\r\n");
405 $result = $this->gline();
406 }
407 return ($result{0}=="2");
bb3b9f8e 408 }
e785d91c 409
410 /** closes connection to server
411 */
412
413 function quit() {
414 $this->pline("QUIT\r\n");
415 $this->gline();
416 fclose($this->ns);
bb3b9f8e 417 }
bb3b9f8e 418
419# NNTP Extensions [RFC 2980]
420
e785d91c 421 /** Returns the date on the remote server
422 * @return INTEGER timestamp
423 */
424
425 function date() {
426 $this->pline("DATE \r\n");
427 $result = $this->gline();
428 if (preg_match("/^111 (\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/", $result, $r)) {
429 return gmmktime($r[4], $r[5], $r[6], $r[2], $r[3], $r[1]);
430 }
431 return false;
bb3b9f8e 432 }
e785d91c 433
434 /** returns group descriptions
435 * @param $_pattern STRING pattern of intersting groups
436 * @return ARRAY group name => description
437 */
438
439 function xgtitle($_pattern="*") {
440 $pattern = preg_replace("/(\r|\n)/", "", $_pattern);
441 $this->pline("XGTITLE $pattern \r\n");
442 if (substr($this->gline(), 0, 1)!="2") return false;
443 $result = $this->gline();
444 while ($result != ".") {
445 preg_match("/([^ \t]+)( |\t)+(.+)$/", $result, $regs);
446 $array[$regs[1]] = $regs[3];
447 $result = $this->gline();
448 }
449 return $array;
bb3b9f8e 450 }
e785d91c 451
452 /** obtain the header field $hdr for all the messages specified
453 * @param $_hdr STRING name of the header (eg: 'From')
454 * @param $_range STRING range of articles
455 * @return ARRAY MSGNUM => header value
456 */
457
458 function xhdr($_hdr, $_range="") {
459 $hdr = preg_replace("/(\r|\n)/", "", $_hdr);
460 $range = preg_replace("/(\r|\n)/", "", $_range);
461 $this->pline("XHDR $hdr $range \r\n");
462 if (substr($this->gline(), 0, 1)!="2") {
463 return false;
464 }
11873d85 465
e785d91c 466 $array = array();
11873d85 467 while (($result = $this->gline()) != '.') {
e785d91c 468 preg_match("/([^ \t]+) (.*)$/", $result, $regs);
469 $array[$regs[1]] = $regs[2];
e785d91c 470 }
471 return $array;
bb3b9f8e 472 }
e785d91c 473
474 /** obtain the header field $_hdr matching $_pat for all the messages specified
475 * @param $_hdr STRING name of the header (eg: 'From')
476 * @param $_range STRING range of articles
477 * @param $_pat STRING pattern
478 * @return ARRAY MSGNUM => header value
479 */
480
481 function xpat($_hdr, $_range, $_pat) {
482 $hdr = preg_replace("/(\r|\n)/", "", $_hdr);
483 $range = preg_replace("/(\r|\n)/", "", $_range);
484 $pat = preg_replace("/(\r|\n)/", "", $_pat);
485 $this->pline("XPAT $hdr $range $pat\r\n");
486 if (substr($this->gline(), 0, 1)!="2") {
487 return false;
488 }
489 $result = $this->gline();
490 while ($result != ".") {
491 preg_match("/([^ \t]+) (.*)$/", $result, $regs);
492 $array[$regs[1]] = $regs[2];
493 $result = $this->gline();
494 }
495 return $array;
5d502f47 496 }
bb3b9f8e 497}
498
499?>