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