remove C<my $x if foo> construct from core modules
[p5sagit/p5-mst-13.2.git] / lib / Net / NNTP.pm
CommitLineData
406c51ee 1# Net::NNTP.pm
2#
3# Copyright (c) 1995-1997 Graham Barr <gbarr@pobox.com>. All rights reserved.
4# This program is free software; you can redistribute it and/or
5# modify it under the same terms as Perl itself.
6
7package Net::NNTP;
8
9use strict;
10use vars qw(@ISA $VERSION $debug);
11use IO::Socket;
12use Net::Cmd;
13use Carp;
14use Time::Local;
15use Net::Config;
16
dea4d7df 17$VERSION = "2.22"; # $Id: //depot/libnet/Net/NNTP.pm#18 $
406c51ee 18@ISA = qw(Net::Cmd IO::Socket::INET);
19
20sub new
21{
22 my $self = shift;
23 my $type = ref($self) || $self;
76df5e8f 24 my $host;
25 $host = shift if @_ % 2;
406c51ee 26 my %arg = @_;
27 my $obj;
28
29 $host ||= $ENV{NNTPSERVER} || $ENV{NEWSHOST};
30
31 my $hosts = defined $host ? [ $host ] : $NetConfig{nntp_hosts};
32
33 @{$hosts} = qw(news)
34 unless @{$hosts};
35
36 my $h;
37 foreach $h (@{$hosts})
38 {
39 $obj = $type->SUPER::new(PeerAddr => ($host = $h),
40 PeerPort => $arg{Port} || 'nntp(119)',
41 Proto => 'tcp',
42 Timeout => defined $arg{Timeout}
43 ? $arg{Timeout}
44 : 120
45 ) and last;
46 }
47
48 return undef
49 unless defined $obj;
50
51 ${*$obj}{'net_nntp_host'} = $host;
52
53 $obj->autoflush(1);
54 $obj->debug(exists $arg{Debug} ? $arg{Debug} : undef);
55
56 unless ($obj->response() == CMD_OK)
57 {
58 $obj->close;
59 return undef;
60 }
61
62 my $c = $obj->code;
63 my @m = $obj->message;
686337f3 64
406c51ee 65 unless(exists $arg{Reader} && $arg{Reader} == 0) {
66 # if server is INN and we have transfer rights the we are currently
67 # talking to innd not nnrpd
68 if($obj->reader)
69 {
70 # If reader suceeds the we need to consider this code to determine postok
71 $c = $obj->code;
72 }
73 else
74 {
75 # I want to ignore this failure, so restore the previous status.
76 $obj->set_status($c,\@m);
77 }
78 }
79
80 ${*$obj}{'net_nntp_post'} = $c == 200 ? 1 : 0;
81
82 $obj;
83}
84
85sub debug_text
86{
87 my $nntp = shift;
88 my $inout = shift;
89 my $text = shift;
90
dea4d7df 91 if((ref($nntp) and $nntp->code == 350 and $text =~ /^(\S+)/)
406c51ee 92 || ($text =~ /^(authinfo\s+pass)/io))
93 {
94 $text = "$1 ....\n"
95 }
96
97 $text;
98}
99
100sub postok
101{
102 @_ == 1 or croak 'usage: $nntp->postok()';
103 my $nntp = shift;
104 ${*$nntp}{'net_nntp_post'} || 0;
105}
106
107sub article
108{
109 @_ >= 1 && @_ <= 3 or croak 'usage: $nntp->article( [ MSGID ], [ FH ] )';
110 my $nntp = shift;
111 my @fh;
112
113 @fh = (pop) if @_ == 2 || (@_ && ref($_[0]) || ref(\$_[0]) eq 'GLOB');
114
115 $nntp->_ARTICLE(@_)
116 ? $nntp->read_until_dot(@fh)
117 : undef;
118}
119
12df23ee 120sub articlefh {
121 @_ >= 1 && @_ <= 2 or croak 'usage: $nntp->articlefh( [ MSGID ] )';
122 my $nntp = shift;
123
124 return unless $nntp->_ARTICLE(@_);
125 return $nntp->tied_fh;
126}
127
406c51ee 128sub authinfo
129{
130 @_ == 3 or croak 'usage: $nntp->authinfo( USER, PASS )';
131 my($nntp,$user,$pass) = @_;
132
133 $nntp->_AUTHINFO("USER",$user) == CMD_MORE
134 && $nntp->_AUTHINFO("PASS",$pass) == CMD_OK;
135}
136
137sub authinfo_simple
138{
139 @_ == 3 or croak 'usage: $nntp->authinfo( USER, PASS )';
140 my($nntp,$user,$pass) = @_;
141
142 $nntp->_AUTHINFO('SIMPLE') == CMD_MORE
143 && $nntp->command($user,$pass)->response == CMD_OK;
144}
145
146sub body
147{
148 @_ >= 1 && @_ <= 3 or croak 'usage: $nntp->body( [ MSGID ], [ FH ] )';
149 my $nntp = shift;
150 my @fh;
151
152 @fh = (pop) if @_ == 2 || (@_ && ref($_[0]) || ref(\$_[0]) eq 'GLOB');
153
154 $nntp->_BODY(@_)
155 ? $nntp->read_until_dot(@fh)
156 : undef;
157}
158
12df23ee 159sub bodyfh
160{
161 @_ >= 1 && @_ <= 2 or croak 'usage: $nntp->bodyfh( [ MSGID ] )';
162 my $nntp = shift;
163 return unless $nntp->_BODY(@_);
164 return $nntp->tied_fh;
165}
166
406c51ee 167sub head
168{
169 @_ >= 1 && @_ <= 3 or croak 'usage: $nntp->head( [ MSGID ], [ FH ] )';
170 my $nntp = shift;
171 my @fh;
172
173 @fh = (pop) if @_ == 2 || (@_ && ref($_[0]) || ref(\$_[0]) eq 'GLOB');
174
175 $nntp->_HEAD(@_)
176 ? $nntp->read_until_dot(@fh)
177 : undef;
178}
179
12df23ee 180sub headfh
181{
182 @_ >= 1 && @_ <= 2 or croak 'usage: $nntp->headfh( [ MSGID ] )';
183 my $nntp = shift;
184 return unless $nntp->_HEAD(@_);
185 return $nntp->tied_fh;
186}
187
406c51ee 188sub nntpstat
189{
190 @_ == 1 || @_ == 2 or croak 'usage: $nntp->nntpstat( [ MSGID ] )';
191 my $nntp = shift;
192
193 $nntp->_STAT(@_) && $nntp->message =~ /(<[^>]+>)/o
194 ? $1
195 : undef;
196}
197
198
199sub group
200{
201 @_ == 1 || @_ == 2 or croak 'usage: $nntp->group( [ GROUP ] )';
202 my $nntp = shift;
203 my $grp = ${*$nntp}{'net_nntp_group'} || undef;
204
205 return $grp
206 unless(@_ || wantarray);
207
208 my $newgrp = shift;
209
210 return wantarray ? () : undef
211 unless $nntp->_GROUP($newgrp || $grp || "")
212 && $nntp->message =~ /(\d+)\s+(\d+)\s+(\d+)\s+(\S+)/;
213
214 my($count,$first,$last,$group) = ($1,$2,$3,$4);
215
216 # group may be replied as '(current group)'
217 $group = ${*$nntp}{'net_nntp_group'}
218 if $group =~ /\(/;
219
220 ${*$nntp}{'net_nntp_group'} = $group;
221
222 wantarray
223 ? ($count,$first,$last,$group)
224 : $group;
225}
226
227sub help
228{
229 @_ == 1 or croak 'usage: $nntp->help()';
230 my $nntp = shift;
231
232 $nntp->_HELP
233 ? $nntp->read_until_dot
234 : undef;
235}
236
237sub ihave
238{
239 @_ >= 2 or croak 'usage: $nntp->ihave( MESSAGE-ID [, MESSAGE ])';
240 my $nntp = shift;
241 my $mid = shift;
242
243 $nntp->_IHAVE($mid) && $nntp->datasend(@_)
244 ? @_ == 0 || $nntp->dataend
245 : undef;
246}
247
248sub last
249{
250 @_ == 1 or croak 'usage: $nntp->last()';
251 my $nntp = shift;
252
253 $nntp->_LAST && $nntp->message =~ /(<[^>]+>)/o
254 ? $1
255 : undef;
256}
257
258sub list
259{
260 @_ == 1 or croak 'usage: $nntp->list()';
261 my $nntp = shift;
262
263 $nntp->_LIST
264 ? $nntp->_grouplist
265 : undef;
266}
267
268sub newgroups
269{
270 @_ >= 2 or croak 'usage: $nntp->newgroups( SINCE [, DISTRIBUTIONS ])';
271 my $nntp = shift;
272 my $time = _timestr(shift);
273 my $dist = shift || "";
274
275 $dist = join(",", @{$dist})
276 if ref($dist);
277
278 $nntp->_NEWGROUPS($time,$dist)
279 ? $nntp->_grouplist
280 : undef;
281}
282
283sub newnews
284{
285 @_ >= 2 && @_ <= 4 or
286 croak 'usage: $nntp->newnews( SINCE [, GROUPS [, DISTRIBUTIONS ]])';
287 my $nntp = shift;
288 my $time = _timestr(shift);
289 my $grp = @_ ? shift : $nntp->group;
290 my $dist = shift || "";
291
292 $grp ||= "*";
293 $grp = join(",", @{$grp})
294 if ref($grp);
295
296 $dist = join(",", @{$dist})
297 if ref($dist);
298
299 $nntp->_NEWNEWS($grp,$time,$dist)
300 ? $nntp->_articlelist
301 : undef;
302}
303
304sub next
305{
306 @_ == 1 or croak 'usage: $nntp->next()';
307 my $nntp = shift;
308
309 $nntp->_NEXT && $nntp->message =~ /(<[^>]+>)/o
310 ? $1
311 : undef;
312}
313
314sub post
315{
316 @_ >= 1 or croak 'usage: $nntp->post( [ MESSAGE ] )';
317 my $nntp = shift;
318
319 $nntp->_POST() && $nntp->datasend(@_)
320 ? @_ == 0 || $nntp->dataend
321 : undef;
322}
323
12df23ee 324sub postfh {
325 my $nntp = shift;
326 return unless $nntp->_POST();
327 return $nntp->tied_fh;
328}
329
406c51ee 330sub quit
331{
332 @_ == 1 or croak 'usage: $nntp->quit()';
333 my $nntp = shift;
334
335 $nntp->_QUIT;
336 $nntp->close;
337}
338
339sub slave
340{
341 @_ == 1 or croak 'usage: $nntp->slave()';
342 my $nntp = shift;
343
344 $nntp->_SLAVE;
345}
346
347##
348## The following methods are not implemented by all servers
349##
350
351sub active
352{
353 @_ == 1 || @_ == 2 or croak 'usage: $nntp->active( [ PATTERN ] )';
354 my $nntp = shift;
355
356 $nntp->_LIST('ACTIVE',@_)
357 ? $nntp->_grouplist
358 : undef;
359}
360
361sub active_times
362{
363 @_ == 1 or croak 'usage: $nntp->active_times()';
364 my $nntp = shift;
365
366 $nntp->_LIST('ACTIVE.TIMES')
367 ? $nntp->_grouplist
368 : undef;
369}
370
371sub distributions
372{
373 @_ == 1 or croak 'usage: $nntp->distributions()';
374 my $nntp = shift;
375
376 $nntp->_LIST('DISTRIBUTIONS')
377 ? $nntp->_description
378 : undef;
379}
380
381sub distribution_patterns
382{
383 @_ == 1 or croak 'usage: $nntp->distributions()';
384 my $nntp = shift;
385
386 my $arr;
387 local $_;
388
389 $nntp->_LIST('DISTRIB.PATS') && ($arr = $nntp->read_until_dot)
390 ? [grep { /^\d/ && (chomp, $_ = [ split /:/ ]) } @$arr]
391 : undef;
392}
393
394sub newsgroups
395{
396 @_ == 1 || @_ == 2 or croak 'usage: $nntp->newsgroups( [ PATTERN ] )';
397 my $nntp = shift;
398
399 $nntp->_LIST('NEWSGROUPS',@_)
400 ? $nntp->_description
401 : undef;
402}
403
404sub overview_fmt
405{
406 @_ == 1 or croak 'usage: $nntp->overview_fmt()';
407 my $nntp = shift;
408
409 $nntp->_LIST('OVERVIEW.FMT')
410 ? $nntp->_articlelist
411 : undef;
412}
413
414sub subscriptions
415{
416 @_ == 1 or croak 'usage: $nntp->subscriptions()';
417 my $nntp = shift;
418
419 $nntp->_LIST('SUBSCRIPTIONS')
420 ? $nntp->_articlelist
421 : undef;
422}
423
424sub listgroup
425{
426 @_ == 1 || @_ == 2 or croak 'usage: $nntp->listgroup( [ GROUP ] )';
427 my $nntp = shift;
428
429 $nntp->_LISTGROUP(@_)
430 ? $nntp->_articlelist
431 : undef;
432}
433
434sub reader
435{
436 @_ == 1 or croak 'usage: $nntp->reader()';
437 my $nntp = shift;
438
439 $nntp->_MODE('READER');
440}
441
442sub xgtitle
443{
444 @_ == 1 || @_ == 2 or croak 'usage: $nntp->xgtitle( [ PATTERN ] )';
445 my $nntp = shift;
446
447 $nntp->_XGTITLE(@_)
448 ? $nntp->_description
449 : undef;
450}
451
452sub xhdr
453{
454 @_ >= 2 && @_ <= 4 or croak 'usage: $nntp->xhdr( HEADER, [ MESSAGE-SPEC ] )';
455 my $nntp = shift;
456 my $hdr = shift;
457 my $arg = _msg_arg(@_);
458
459 $nntp->_XHDR($hdr, $arg)
460 ? $nntp->_description
461 : undef;
462}
463
464sub xover
465{
466 @_ == 2 || @_ == 3 or croak 'usage: $nntp->xover( MESSAGE-SPEC )';
467 my $nntp = shift;
468 my $arg = _msg_arg(@_);
469
470 $nntp->_XOVER($arg)
471 ? $nntp->_fieldlist
472 : undef;
473}
474
475sub xpat
476{
477 @_ == 4 || @_ == 5 or croak '$nntp->xpat( HEADER, PATTERN, MESSAGE-SPEC )';
478 my $nntp = shift;
479 my $hdr = shift;
480 my $pat = shift;
481 my $arg = _msg_arg(@_);
482
483 $pat = join(" ", @$pat)
484 if ref($pat);
485
486 $nntp->_XPAT($hdr,$arg,$pat)
487 ? $nntp->_description
488 : undef;
489}
490
491sub xpath
492{
493 @_ == 2 or croak 'usage: $nntp->xpath( MESSAGE-ID )';
494 my($nntp,$mid) = @_;
495
496 return undef
497 unless $nntp->_XPATH($mid);
498
499 my $m; ($m = $nntp->message) =~ s/^\d+\s+//o;
500 my @p = split /\s+/, $m;
501
502 wantarray ? @p : $p[0];
503}
504
505sub xrover
506{
507 @_ == 2 || @_ == 3 or croak 'usage: $nntp->xrover( MESSAGE-SPEC )';
508 my $nntp = shift;
509 my $arg = _msg_arg(@_);
510
511 $nntp->_XROVER($arg)
512 ? $nntp->_description
513 : undef;
514}
515
516sub date
517{
518 @_ == 1 or croak 'usage: $nntp->date()';
519 my $nntp = shift;
520
521 $nntp->_DATE && $nntp->message =~ /(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/
522 ? timegm($6,$5,$4,$3,$2-1,$1 - 1900)
523 : undef;
524}
525
526
527##
528## Private subroutines
529##
530
531sub _msg_arg
532{
533 my $spec = shift;
534 my $arg = "";
535
536 if(@_)
537 {
538 carp "Depriciated passing of two message numbers, "
539 . "pass a reference"
540 if $^W;
541 $spec = [ $spec, $_[0] ];
542 }
543
544 if(defined $spec)
545 {
546 if(ref($spec))
547 {
686337f3 548 $arg = $spec->[0];
549 if(defined $spec->[1])
550 {
551 $arg .= "-"
552 if $spec->[1] != $spec->[0];
553 $arg .= $spec->[1]
554 if $spec->[1] > $spec->[0];
555 }
406c51ee 556 }
557 else
558 {
559 $arg = $spec;
560 }
561 }
562
563 $arg;
564}
565
566sub _timestr
567{
568 my $time = shift;
569 my @g = reverse((gmtime($time))[0..5]);
570 $g[1] += 1;
571 $g[0] %= 100;
572 sprintf "%02d%02d%02d %02d%02d%02d GMT", @g;
573}
574
575sub _grouplist
576{
577 my $nntp = shift;
578 my $arr = $nntp->read_until_dot or
579 return undef;
580
581 my $hash = {};
582 my $ln;
583
584 foreach $ln (@$arr)
585 {
586 my @a = split(/[\s\n]+/,$ln);
587 $hash->{$a[0]} = [ @a[1,2,3] ];
588 }
589
590 $hash;
591}
592
593sub _fieldlist
594{
595 my $nntp = shift;
596 my $arr = $nntp->read_until_dot or
597 return undef;
598
599 my $hash = {};
600 my $ln;
601
602 foreach $ln (@$arr)
603 {
604 my @a = split(/[\t\n]/,$ln);
605 my $m = shift @a;
606 $hash->{$m} = [ @a ];
607 }
608
609 $hash;
610}
611
612sub _articlelist
613{
614 my $nntp = shift;
615 my $arr = $nntp->read_until_dot;
616
617 chomp(@$arr)
618 if $arr;
619
620 $arr;
621}
622
623sub _description
624{
625 my $nntp = shift;
626 my $arr = $nntp->read_until_dot or
627 return undef;
628
629 my $hash = {};
630 my $ln;
631
632 foreach $ln (@$arr)
633 {
634 chomp($ln);
635
636 $hash->{$1} = $ln
637 if $ln =~ s/^\s*(\S+)\s*//o;
638 }
639
640 $hash;
641
642}
643
644##
645## The commands
646##
647
648sub _ARTICLE { shift->command('ARTICLE',@_)->response == CMD_OK }
649sub _AUTHINFO { shift->command('AUTHINFO',@_)->response }
650sub _BODY { shift->command('BODY',@_)->response == CMD_OK }
651sub _DATE { shift->command('DATE')->response == CMD_INFO }
652sub _GROUP { shift->command('GROUP',@_)->response == CMD_OK }
653sub _HEAD { shift->command('HEAD',@_)->response == CMD_OK }
654sub _HELP { shift->command('HELP',@_)->response == CMD_INFO }
655sub _IHAVE { shift->command('IHAVE',@_)->response == CMD_MORE }
656sub _LAST { shift->command('LAST')->response == CMD_OK }
657sub _LIST { shift->command('LIST',@_)->response == CMD_OK }
658sub _LISTGROUP { shift->command('LISTGROUP',@_)->response == CMD_OK }
659sub _NEWGROUPS { shift->command('NEWGROUPS',@_)->response == CMD_OK }
660sub _NEWNEWS { shift->command('NEWNEWS',@_)->response == CMD_OK }
661sub _NEXT { shift->command('NEXT')->response == CMD_OK }
662sub _POST { shift->command('POST',@_)->response == CMD_MORE }
663sub _QUIT { shift->command('QUIT',@_)->response == CMD_OK }
664sub _SLAVE { shift->command('SLAVE',@_)->response == CMD_OK }
665sub _STAT { shift->command('STAT',@_)->response == CMD_OK }
666sub _MODE { shift->command('MODE',@_)->response == CMD_OK }
667sub _XGTITLE { shift->command('XGTITLE',@_)->response == CMD_OK }
668sub _XHDR { shift->command('XHDR',@_)->response == CMD_OK }
669sub _XPAT { shift->command('XPAT',@_)->response == CMD_OK }
670sub _XPATH { shift->command('XPATH',@_)->response == CMD_OK }
671sub _XOVER { shift->command('XOVER',@_)->response == CMD_OK }
672sub _XROVER { shift->command('XROVER',@_)->response == CMD_OK }
673sub _XTHREAD { shift->unsupported }
674sub _XSEARCH { shift->unsupported }
675sub _XINDEX { shift->unsupported }
676
677##
678## IO/perl methods
679##
680
681sub DESTROY
682{
683 my $nntp = shift;
684 defined(fileno($nntp)) && $nntp->quit
685}
686
687
6881;
689
690__END__
691
692=head1 NAME
693
694Net::NNTP - NNTP Client class
695
696=head1 SYNOPSIS
697
698 use Net::NNTP;
686337f3 699
406c51ee 700 $nntp = Net::NNTP->new("some.host.name");
701 $nntp->quit;
702
703=head1 DESCRIPTION
704
705C<Net::NNTP> is a class implementing a simple NNTP client in Perl as described
706in RFC977. C<Net::NNTP> inherits its communication methods from C<Net::Cmd>
707
708=head1 CONSTRUCTOR
709
710=over 4
711
712=item new ( [ HOST ] [, OPTIONS ])
713
714This is the constructor for a new Net::NNTP object. C<HOST> is the
715name of the remote host to which a NNTP connection is required. If not
716given two environment variables are checked, first C<NNTPSERVER> then
717C<NEWSHOST>, then C<Net::Config> is checked, and if a host is not found
718then C<news> is used.
719
720C<OPTIONS> are passed in a hash like fashion, using key and value pairs.
721Possible options are:
722
723B<Timeout> - Maximum time, in seconds, to wait for a response from the
724NNTP server, a value of zero will cause all IO operations to block.
725(default: 120)
726
727B<Debug> - Enable the printing of debugging information to STDERR
728
729B<Reader> - If the remote server is INN then initially the connection
730will be to nnrpd, by default C<Net::NNTP> will issue a C<MODE READER> command
731so that the remote server becomes innd. If the C<Reader> option is given
732with a value of zero, then this command will not be sent and the
733connection will be left talking to nnrpd.
734
735=back
736
737=head1 METHODS
738
739Unless otherwise stated all methods return either a I<true> or I<false>
740value, with I<true> meaning that the operation was a success. When a method
741states that it returns a value, failure will be returned as I<undef> or an
742empty list.
743
744=over 4
745
746=item article ( [ MSGID|MSGNUM ], [FH] )
747
748Retrieve the header, a blank line, then the body (text) of the
749specified article.
750
751If C<FH> is specified then it is expected to be a valid filehandle
a6d05634 752and the result will be printed to it, on success a true value will be
753returned. If C<FH> is not specified then the return value, on success,
406c51ee 754will be a reference to an array containg the article requested, each
755entry in the array will contain one line of the article.
756
757If no arguments are passed then the current article in the currently
758selected newsgroup is fetched.
759
760C<MSGNUM> is a numeric id of an article in the current newsgroup, and
761will change the current article pointer. C<MSGID> is the message id of
762an article as shown in that article's header. It is anticipated that the
763client will obtain the C<MSGID> from a list provided by the C<newnews>
764command, from references contained within another article, or from the
765message-id provided in the response to some other commands.
766
767If there is an error then C<undef> will be returned.
768
769=item body ( [ MSGID|MSGNUM ], [FH] )
770
771Like C<article> but only fetches the body of the article.
772
773=item head ( [ MSGID|MSGNUM ], [FH] )
774
775Like C<article> but only fetches the headers for the article.
776
12df23ee 777=item articlefh ( [ MSGID|MSGNUM ] )
778
779=item bodyfh ( [ MSGID|MSGNUM ] )
780
781=item headfh ( [ MSGID|MSGNUM ] )
782
783These are similar to article(), body() and head(), but rather than
784returning the requested data directly, they return a tied filehandle
785from which to read the article.
786
406c51ee 787=item nntpstat ( [ MSGID|MSGNUM ] )
788
789The C<nntpstat> command is similar to the C<article> command except that no
790text is returned. When selecting by message number within a group,
791the C<nntpstat> command serves to set the "current article pointer" without
792sending text.
793
794Using the C<nntpstat> command to
795select by message-id is valid but of questionable value, since a
796selection by message-id does B<not> alter the "current article pointer".
797
798Returns the message-id of the "current article".
799
800=item group ( [ GROUP ] )
801
802Set and/or get the current group. If C<GROUP> is not given then information
803is returned on the current group.
804
805In a scalar context it returns the group name.
806
807In an array context the return value is a list containing, the number
808of articles in the group, the number of the first article, the number
809of the last article and the group name.
810
811=item ihave ( MSGID [, MESSAGE ])
812
813The C<ihave> command informs the server that the client has an article
814whose id is C<MSGID>. If the server desires a copy of that
815article, and C<MESSAGE> has been given the it will be sent.
816
817Returns I<true> if the server desires the article and C<MESSAGE> was
818successfully sent,if specified.
819
820If C<MESSAGE> is not specified then the message must be sent using the
821C<datasend> and C<dataend> methods from L<Net::Cmd>
822
823C<MESSAGE> can be either an array of lines or a reference to an array.
824
825=item last ()
826
827Set the "current article pointer" to the previous article in the current
828newsgroup.
829
830Returns the message-id of the article.
831
832=item date ()
833
834Returns the date on the remote server. This date will be in a UNIX time
835format (seconds since 1970)
836
837=item postok ()
838
839C<postok> will return I<true> if the servers initial response indicated
840that it will allow posting.
841
842=item authinfo ( USER, PASS )
843
844=item list ()
845
846Obtain information about all the active newsgroups. The results is a reference
847to a hash where the key is a group name and each value is a reference to an
686337f3 848array. The elements in this array are:- the last article number in the group,
849the first article number in the group and any information flags about the group.
406c51ee 850
851=item newgroups ( SINCE [, DISTRIBUTIONS ])
852
853C<SINCE> is a time value and C<DISTRIBUTIONS> is either a distribution
854pattern or a reference to a list of distribution patterns.
855The result is the same as C<list>, but the
856groups return will be limited to those created after C<SINCE> and, if
857specified, in one of the distribution areas in C<DISTRIBUTIONS>.
858
859=item newnews ( SINCE [, GROUPS [, DISTRIBUTIONS ]])
860
861C<SINCE> is a time value. C<GROUPS> is either a group pattern or a reference
862to a list of group patterns. C<DISTRIBUTIONS> is either a distribution
863pattern or a reference to a list of distribution patterns.
864
865Returns a reference to a list which contains the message-ids of all news posted
866after C<SINCE>, that are in a groups which matched C<GROUPS> and a
867distribution which matches C<DISTRIBUTIONS>.
868
869=item next ()
870
871Set the "current article pointer" to the next article in the current
872newsgroup.
873
874Returns the message-id of the article.
875
876=item post ( [ MESSAGE ] )
877
878Post a new article to the news server. If C<MESSAGE> is specified and posting
879is allowed then the message will be sent.
880
881If C<MESSAGE> is not specified then the message must be sent using the
882C<datasend> and C<dataend> methods from L<Net::Cmd>
883
884C<MESSAGE> can be either an array of lines or a reference to an array.
885
dea4d7df 886The message, either sent via C<datasend> or as the C<MESSAGE>
887parameter, must be in the format as described by RFC822 and must
888contain From:, Newsgroups: and Subject: headers.
889
12df23ee 890=item postfh ()
891
892Post a new article to the news server using a tied filehandle. If
893posting is allowed, this method will return a tied filehandle that you
894can print() the contents of the article to be posted. You must
895explicitly close() the filehandle when you are finished posting the
896article, and the return value from the close() call will indicate
897whether the message was successfully posted.
898
406c51ee 899=item slave ()
900
901Tell the remote server that I am not a user client, but probably another
902news server.
903
904=item quit ()
905
906Quit the remote server and close the socket connection.
907
908=back
909
910=head2 Extension methods
911
912These methods use commands that are not part of the RFC977 documentation. Some
913servers may not support all of them.
914
915=over 4
916
917=item newsgroups ( [ PATTERN ] )
918
919Returns a reference to a hash where the keys are all the group names which
920match C<PATTERN>, or all of the groups if no pattern is specified, and
921each value contains the description text for the group.
922
923=item distributions ()
924
925Returns a reference to a hash where the keys are all the possible
926distribution names and the values are the distribution descriptions.
927
928=item subscriptions ()
929
930Returns a reference to a list which contains a list of groups which
931are recommended for a new user to subscribe to.
932
933=item overview_fmt ()
934
935Returns a reference to an array which contain the names of the fields returned
936by C<xover>.
937
938=item active_times ()
939
940Returns a reference to a hash where the keys are the group names and each
941value is a reference to an array containing the time the groups was created
942and an identifier, possibly an Email address, of the creator.
943
944=item active ( [ PATTERN ] )
945
946Similar to C<list> but only active groups that match the pattern are returned.
947C<PATTERN> can be a group pattern.
948
949=item xgtitle ( PATTERN )
950
951Returns a reference to a hash where the keys are all the group names which
952match C<PATTERN> and each value is the description text for the group.
953
954=item xhdr ( HEADER, MESSAGE-SPEC )
955
956Obtain the header field C<HEADER> for all the messages specified.
957
958The return value will be a reference
959to a hash where the keys are the message numbers and each value contains
960the text of the requested header for that message.
961
962=item xover ( MESSAGE-SPEC )
963
964The return value will be a reference
965to a hash where the keys are the message numbers and each value contains
966a reference to an array which contains the overview fields for that
967message.
968
969The names of the fields can be obtained by calling C<overview_fmt>.
970
971=item xpath ( MESSAGE-ID )
972
973Returns the path name to the file on the server which contains the specified
974message.
975
976=item xpat ( HEADER, PATTERN, MESSAGE-SPEC)
977
978The result is the same as C<xhdr> except the is will be restricted to
979headers where the text of the header matches C<PATTERN>
980
981=item xrover
982
983The XROVER command returns reference information for the article(s)
984specified.
985
986Returns a reference to a HASH where the keys are the message numbers and the
987values are the References: lines from the articles
988
989=item listgroup ( [ GROUP ] )
990
991Returns a reference to a list of all the active messages in C<GROUP>, or
992the current group if C<GROUP> is not specified.
993
994=item reader
995
996Tell the server that you are a reader and not another server.
997
998This is required by some servers. For example if you are connecting to
999an INN server and you have transfer permission your connection will
1000be connected to the transfer daemon, not the NNTP daemon. Issuing
1001this command will cause the transfer daemon to hand over control
1002to the NNTP daemon.
1003
1004Some servers do not understand this command, but issuing it and ignoring
1005the response is harmless.
1006
1007=back
1008
1009=head1 UNSUPPORTED
1010
1011The following NNTP command are unsupported by the package, and there are
1012no plans to do so.
1013
1014 AUTHINFO GENERIC
1015 XTHREAD
1016 XSEARCH
1017 XINDEX
1018
1019=head1 DEFINITIONS
1020
1021=over 4
1022
1023=item MESSAGE-SPEC
1024
1025C<MESSAGE-SPEC> is either a single message-id, a single message number, or
1026a reference to a list of two message numbers.
1027
1028If C<MESSAGE-SPEC> is a reference to a list of two message numbers and the
1029second number in a range is less than or equal to the first then the range
1030represents all messages in the group after the first message number.
1031
1032B<NOTE> For compatibility reasons only with earlier versions of Net::NNTP
1033a message spec can be passed as a list of two numbers, this is deprecated
1034and a reference to the list should now be passed
1035
1036=item PATTERN
1037
1038The C<NNTP> protocol uses the C<WILDMAT> format for patterns.
1039The WILDMAT format was first developed by Rich Salz based on
1040the format used in the UNIX "find" command to articulate
1041file names. It was developed to provide a uniform mechanism
1042for matching patterns in the same manner that the UNIX shell
1043matches filenames.
1044
1045Patterns are implicitly anchored at the
1046beginning and end of each string when testing for a match.
1047
1048There are five pattern matching operations other than a strict
1049one-to-one match between the pattern and the source to be
1050checked for a match.
1051
1052The first is an asterisk C<*> to match any sequence of zero or more
1053characters.
1054
1055The second is a question mark C<?> to match any single character. The
1056third specifies a specific set of characters.
1057
1058The set is specified as a list of characters, or as a range of characters
1059where the beginning and end of the range are separated by a minus (or dash)
1060character, or as any combination of lists and ranges. The dash can
1061also be included in the set as a character it if is the beginning
1062or end of the set. This set is enclosed in square brackets. The
1063close square bracket C<]> may be used in a set if it is the first
1064character in the set.
1065
1066The fourth operation is the same as the
1067logical not of the third operation and is specified the same
1068way as the third with the addition of a caret character C<^> at
1069the beginning of the test string just inside the open square
1070bracket.
1071
1072The final operation uses the backslash character to
d1be9408 1073invalidate the special meaning of an open square bracket C<[>,
406c51ee 1074the asterisk, backslash or the question mark. Two backslashes in
1075sequence will result in the evaluation of the backslash as a
1076character with no special meaning.
1077
1078=over 4
1079
1080=item Examples
1081
1082=item C<[^]-]>
1083
1084matches any single character other than a close square
1085bracket or a minus sign/dash.
1086
1087=item C<*bdc>
1088
1089matches any string that ends with the string "bdc"
1090including the string "bdc" (without quotes).
1091
1092=item C<[0-9a-zA-Z]>
1093
1094matches any single printable alphanumeric ASCII character.
1095
1096=item C<a??d>
1097
1098matches any four character string which begins
1099with a and ends with d.
1100
1101=back
1102
1103=back
1104
1105=head1 SEE ALSO
1106
1107L<Net::Cmd>
1108
1109=head1 AUTHOR
1110
1111Graham Barr <gbarr@pobox.com>
1112
1113=head1 COPYRIGHT
1114
1115Copyright (c) 1995-1997 Graham Barr. All rights reserved.
1116This program is free software; you can redistribute it and/or modify
1117it under the same terms as Perl itself.
1118
686337f3 1119=for html <hr>
1120
dea4d7df 1121I<$Id: //depot/libnet/Net/NNTP.pm#18 $>
686337f3 1122
406c51ee 1123=cut