ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/staticperl/perl/lib/Net/NNTP.pm
Revision: 1.1
Committed: Thu Jun 30 14:27:14 2005 UTC (21 years, 3 months ago) by root
Branch: MAIN
CVS Tags: HEAD
Branch point for: PERL
Log Message:
*** empty log message ***

File Contents

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