Explain in more detail why -pipe and -fno-common are good.
[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
17$VERSION = "2.19"; # $Id: //depot/libnet/Net/NNTP.pm#8$
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;
63
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 {
517 $arg = $spec->[0] . "-";
518 $arg .= $spec->[1]
519 if defined $spec->[1] && $spec->[1] > $spec->[0];
520 }
521 else
522 {
523 $arg = $spec;
524 }
525 }
526
527 $arg;
528}
529
530sub _timestr
531{
532 my $time = shift;
533 my @g = reverse((gmtime($time))[0..5]);
534 $g[1] += 1;
535 $g[0] %= 100;
536 sprintf "%02d%02d%02d %02d%02d%02d GMT", @g;
537}
538
539sub _grouplist
540{
541 my $nntp = shift;
542 my $arr = $nntp->read_until_dot or
543 return undef;
544
545 my $hash = {};
546 my $ln;
547
548 foreach $ln (@$arr)
549 {
550 my @a = split(/[\s\n]+/,$ln);
551 $hash->{$a[0]} = [ @a[1,2,3] ];
552 }
553
554 $hash;
555}
556
557sub _fieldlist
558{
559 my $nntp = shift;
560 my $arr = $nntp->read_until_dot or
561 return undef;
562
563 my $hash = {};
564 my $ln;
565
566 foreach $ln (@$arr)
567 {
568 my @a = split(/[\t\n]/,$ln);
569 my $m = shift @a;
570 $hash->{$m} = [ @a ];
571 }
572
573 $hash;
574}
575
576sub _articlelist
577{
578 my $nntp = shift;
579 my $arr = $nntp->read_until_dot;
580
581 chomp(@$arr)
582 if $arr;
583
584 $arr;
585}
586
587sub _description
588{
589 my $nntp = shift;
590 my $arr = $nntp->read_until_dot or
591 return undef;
592
593 my $hash = {};
594 my $ln;
595
596 foreach $ln (@$arr)
597 {
598 chomp($ln);
599
600 $hash->{$1} = $ln
601 if $ln =~ s/^\s*(\S+)\s*//o;
602 }
603
604 $hash;
605
606}
607
608##
609## The commands
610##
611
612sub _ARTICLE { shift->command('ARTICLE',@_)->response == CMD_OK }
613sub _AUTHINFO { shift->command('AUTHINFO',@_)->response }
614sub _BODY { shift->command('BODY',@_)->response == CMD_OK }
615sub _DATE { shift->command('DATE')->response == CMD_INFO }
616sub _GROUP { shift->command('GROUP',@_)->response == CMD_OK }
617sub _HEAD { shift->command('HEAD',@_)->response == CMD_OK }
618sub _HELP { shift->command('HELP',@_)->response == CMD_INFO }
619sub _IHAVE { shift->command('IHAVE',@_)->response == CMD_MORE }
620sub _LAST { shift->command('LAST')->response == CMD_OK }
621sub _LIST { shift->command('LIST',@_)->response == CMD_OK }
622sub _LISTGROUP { shift->command('LISTGROUP',@_)->response == CMD_OK }
623sub _NEWGROUPS { shift->command('NEWGROUPS',@_)->response == CMD_OK }
624sub _NEWNEWS { shift->command('NEWNEWS',@_)->response == CMD_OK }
625sub _NEXT { shift->command('NEXT')->response == CMD_OK }
626sub _POST { shift->command('POST',@_)->response == CMD_MORE }
627sub _QUIT { shift->command('QUIT',@_)->response == CMD_OK }
628sub _SLAVE { shift->command('SLAVE',@_)->response == CMD_OK }
629sub _STAT { shift->command('STAT',@_)->response == CMD_OK }
630sub _MODE { shift->command('MODE',@_)->response == CMD_OK }
631sub _XGTITLE { shift->command('XGTITLE',@_)->response == CMD_OK }
632sub _XHDR { shift->command('XHDR',@_)->response == CMD_OK }
633sub _XPAT { shift->command('XPAT',@_)->response == CMD_OK }
634sub _XPATH { shift->command('XPATH',@_)->response == CMD_OK }
635sub _XOVER { shift->command('XOVER',@_)->response == CMD_OK }
636sub _XROVER { shift->command('XROVER',@_)->response == CMD_OK }
637sub _XTHREAD { shift->unsupported }
638sub _XSEARCH { shift->unsupported }
639sub _XINDEX { shift->unsupported }
640
641##
642## IO/perl methods
643##
644
645sub DESTROY
646{
647 my $nntp = shift;
648 defined(fileno($nntp)) && $nntp->quit
649}
650
651
6521;
653
654__END__
655
656=head1 NAME
657
658Net::NNTP - NNTP Client class
659
660=head1 SYNOPSIS
661
662 use Net::NNTP;
663
664 $nntp = Net::NNTP->new("some.host.name");
665 $nntp->quit;
666
667=head1 DESCRIPTION
668
669C<Net::NNTP> is a class implementing a simple NNTP client in Perl as described
670in RFC977. C<Net::NNTP> inherits its communication methods from C<Net::Cmd>
671
672=head1 CONSTRUCTOR
673
674=over 4
675
676=item new ( [ HOST ] [, OPTIONS ])
677
678This is the constructor for a new Net::NNTP object. C<HOST> is the
679name of the remote host to which a NNTP connection is required. If not
680given two environment variables are checked, first C<NNTPSERVER> then
681C<NEWSHOST>, then C<Net::Config> is checked, and if a host is not found
682then C<news> is used.
683
684C<OPTIONS> are passed in a hash like fashion, using key and value pairs.
685Possible options are:
686
687B<Timeout> - Maximum time, in seconds, to wait for a response from the
688NNTP server, a value of zero will cause all IO operations to block.
689(default: 120)
690
691B<Debug> - Enable the printing of debugging information to STDERR
692
693B<Reader> - If the remote server is INN then initially the connection
694will be to nnrpd, by default C<Net::NNTP> will issue a C<MODE READER> command
695so that the remote server becomes innd. If the C<Reader> option is given
696with a value of zero, then this command will not be sent and the
697connection will be left talking to nnrpd.
698
699=back
700
701=head1 METHODS
702
703Unless otherwise stated all methods return either a I<true> or I<false>
704value, with I<true> meaning that the operation was a success. When a method
705states that it returns a value, failure will be returned as I<undef> or an
706empty list.
707
708=over 4
709
710=item article ( [ MSGID|MSGNUM ], [FH] )
711
712Retrieve the header, a blank line, then the body (text) of the
713specified article.
714
715If C<FH> is specified then it is expected to be a valid filehandle
716and the result will be printed to it, on sucess a true value will be
717returned. If C<FH> is not specified then the return value, on sucess,
718will be a reference to an array containg the article requested, each
719entry in the array will contain one line of the article.
720
721If no arguments are passed then the current article in the currently
722selected newsgroup is fetched.
723
724C<MSGNUM> is a numeric id of an article in the current newsgroup, and
725will change the current article pointer. C<MSGID> is the message id of
726an article as shown in that article's header. It is anticipated that the
727client will obtain the C<MSGID> from a list provided by the C<newnews>
728command, from references contained within another article, or from the
729message-id provided in the response to some other commands.
730
731If there is an error then C<undef> will be returned.
732
733=item body ( [ MSGID|MSGNUM ], [FH] )
734
735Like C<article> but only fetches the body of the article.
736
737=item head ( [ MSGID|MSGNUM ], [FH] )
738
739Like C<article> but only fetches the headers for the article.
740
741=item nntpstat ( [ MSGID|MSGNUM ] )
742
743The C<nntpstat> command is similar to the C<article> command except that no
744text is returned. When selecting by message number within a group,
745the C<nntpstat> command serves to set the "current article pointer" without
746sending text.
747
748Using the C<nntpstat> command to
749select by message-id is valid but of questionable value, since a
750selection by message-id does B<not> alter the "current article pointer".
751
752Returns the message-id of the "current article".
753
754=item group ( [ GROUP ] )
755
756Set and/or get the current group. If C<GROUP> is not given then information
757is returned on the current group.
758
759In a scalar context it returns the group name.
760
761In an array context the return value is a list containing, the number
762of articles in the group, the number of the first article, the number
763of the last article and the group name.
764
765=item ihave ( MSGID [, MESSAGE ])
766
767The C<ihave> command informs the server that the client has an article
768whose id is C<MSGID>. If the server desires a copy of that
769article, and C<MESSAGE> has been given the it will be sent.
770
771Returns I<true> if the server desires the article and C<MESSAGE> was
772successfully sent,if specified.
773
774If C<MESSAGE> is not specified then the message must be sent using the
775C<datasend> and C<dataend> methods from L<Net::Cmd>
776
777C<MESSAGE> can be either an array of lines or a reference to an array.
778
779=item last ()
780
781Set the "current article pointer" to the previous article in the current
782newsgroup.
783
784Returns the message-id of the article.
785
786=item date ()
787
788Returns the date on the remote server. This date will be in a UNIX time
789format (seconds since 1970)
790
791=item postok ()
792
793C<postok> will return I<true> if the servers initial response indicated
794that it will allow posting.
795
796=item authinfo ( USER, PASS )
797
798=item list ()
799
800Obtain information about all the active newsgroups. The results is a reference
801to a hash where the key is a group name and each value is a reference to an
802array. The elements in this array are:- the first article number in the group,
803the last article number in the group and any information flags about the group.
804
805=item newgroups ( SINCE [, DISTRIBUTIONS ])
806
807C<SINCE> is a time value and C<DISTRIBUTIONS> is either a distribution
808pattern or a reference to a list of distribution patterns.
809The result is the same as C<list>, but the
810groups return will be limited to those created after C<SINCE> and, if
811specified, in one of the distribution areas in C<DISTRIBUTIONS>.
812
813=item newnews ( SINCE [, GROUPS [, DISTRIBUTIONS ]])
814
815C<SINCE> is a time value. C<GROUPS> is either a group pattern or a reference
816to a list of group patterns. C<DISTRIBUTIONS> is either a distribution
817pattern or a reference to a list of distribution patterns.
818
819Returns a reference to a list which contains the message-ids of all news posted
820after C<SINCE>, that are in a groups which matched C<GROUPS> and a
821distribution which matches C<DISTRIBUTIONS>.
822
823=item next ()
824
825Set the "current article pointer" to the next article in the current
826newsgroup.
827
828Returns the message-id of the article.
829
830=item post ( [ MESSAGE ] )
831
832Post a new article to the news server. If C<MESSAGE> is specified and posting
833is allowed then the message will be sent.
834
835If C<MESSAGE> is not specified then the message must be sent using the
836C<datasend> and C<dataend> methods from L<Net::Cmd>
837
838C<MESSAGE> can be either an array of lines or a reference to an array.
839
840=item slave ()
841
842Tell the remote server that I am not a user client, but probably another
843news server.
844
845=item quit ()
846
847Quit the remote server and close the socket connection.
848
849=back
850
851=head2 Extension methods
852
853These methods use commands that are not part of the RFC977 documentation. Some
854servers may not support all of them.
855
856=over 4
857
858=item newsgroups ( [ PATTERN ] )
859
860Returns a reference to a hash where the keys are all the group names which
861match C<PATTERN>, or all of the groups if no pattern is specified, and
862each value contains the description text for the group.
863
864=item distributions ()
865
866Returns a reference to a hash where the keys are all the possible
867distribution names and the values are the distribution descriptions.
868
869=item subscriptions ()
870
871Returns a reference to a list which contains a list of groups which
872are recommended for a new user to subscribe to.
873
874=item overview_fmt ()
875
876Returns a reference to an array which contain the names of the fields returned
877by C<xover>.
878
879=item active_times ()
880
881Returns a reference to a hash where the keys are the group names and each
882value is a reference to an array containing the time the groups was created
883and an identifier, possibly an Email address, of the creator.
884
885=item active ( [ PATTERN ] )
886
887Similar to C<list> but only active groups that match the pattern are returned.
888C<PATTERN> can be a group pattern.
889
890=item xgtitle ( PATTERN )
891
892Returns a reference to a hash where the keys are all the group names which
893match C<PATTERN> and each value is the description text for the group.
894
895=item xhdr ( HEADER, MESSAGE-SPEC )
896
897Obtain the header field C<HEADER> for all the messages specified.
898
899The return value will be a reference
900to a hash where the keys are the message numbers and each value contains
901the text of the requested header for that message.
902
903=item xover ( MESSAGE-SPEC )
904
905The return value will be a reference
906to a hash where the keys are the message numbers and each value contains
907a reference to an array which contains the overview fields for that
908message.
909
910The names of the fields can be obtained by calling C<overview_fmt>.
911
912=item xpath ( MESSAGE-ID )
913
914Returns the path name to the file on the server which contains the specified
915message.
916
917=item xpat ( HEADER, PATTERN, MESSAGE-SPEC)
918
919The result is the same as C<xhdr> except the is will be restricted to
920headers where the text of the header matches C<PATTERN>
921
922=item xrover
923
924The XROVER command returns reference information for the article(s)
925specified.
926
927Returns a reference to a HASH where the keys are the message numbers and the
928values are the References: lines from the articles
929
930=item listgroup ( [ GROUP ] )
931
932Returns a reference to a list of all the active messages in C<GROUP>, or
933the current group if C<GROUP> is not specified.
934
935=item reader
936
937Tell the server that you are a reader and not another server.
938
939This is required by some servers. For example if you are connecting to
940an INN server and you have transfer permission your connection will
941be connected to the transfer daemon, not the NNTP daemon. Issuing
942this command will cause the transfer daemon to hand over control
943to the NNTP daemon.
944
945Some servers do not understand this command, but issuing it and ignoring
946the response is harmless.
947
948=back
949
950=head1 UNSUPPORTED
951
952The following NNTP command are unsupported by the package, and there are
953no plans to do so.
954
955 AUTHINFO GENERIC
956 XTHREAD
957 XSEARCH
958 XINDEX
959
960=head1 DEFINITIONS
961
962=over 4
963
964=item MESSAGE-SPEC
965
966C<MESSAGE-SPEC> is either a single message-id, a single message number, or
967a reference to a list of two message numbers.
968
969If C<MESSAGE-SPEC> is a reference to a list of two message numbers and the
970second number in a range is less than or equal to the first then the range
971represents all messages in the group after the first message number.
972
973B<NOTE> For compatibility reasons only with earlier versions of Net::NNTP
974a message spec can be passed as a list of two numbers, this is deprecated
975and a reference to the list should now be passed
976
977=item PATTERN
978
979The C<NNTP> protocol uses the C<WILDMAT> format for patterns.
980The WILDMAT format was first developed by Rich Salz based on
981the format used in the UNIX "find" command to articulate
982file names. It was developed to provide a uniform mechanism
983for matching patterns in the same manner that the UNIX shell
984matches filenames.
985
986Patterns are implicitly anchored at the
987beginning and end of each string when testing for a match.
988
989There are five pattern matching operations other than a strict
990one-to-one match between the pattern and the source to be
991checked for a match.
992
993The first is an asterisk C<*> to match any sequence of zero or more
994characters.
995
996The second is a question mark C<?> to match any single character. The
997third specifies a specific set of characters.
998
999The set is specified as a list of characters, or as a range of characters
1000where the beginning and end of the range are separated by a minus (or dash)
1001character, or as any combination of lists and ranges. The dash can
1002also be included in the set as a character it if is the beginning
1003or end of the set. This set is enclosed in square brackets. The
1004close square bracket C<]> may be used in a set if it is the first
1005character in the set.
1006
1007The fourth operation is the same as the
1008logical not of the third operation and is specified the same
1009way as the third with the addition of a caret character C<^> at
1010the beginning of the test string just inside the open square
1011bracket.
1012
1013The final operation uses the backslash character to
1014invalidate the special meaning of the a open square bracket C<[>,
1015the asterisk, backslash or the question mark. Two backslashes in
1016sequence will result in the evaluation of the backslash as a
1017character with no special meaning.
1018
1019=over 4
1020
1021=item Examples
1022
1023=item C<[^]-]>
1024
1025matches any single character other than a close square
1026bracket or a minus sign/dash.
1027
1028=item C<*bdc>
1029
1030matches any string that ends with the string "bdc"
1031including the string "bdc" (without quotes).
1032
1033=item C<[0-9a-zA-Z]>
1034
1035matches any single printable alphanumeric ASCII character.
1036
1037=item C<a??d>
1038
1039matches any four character string which begins
1040with a and ends with d.
1041
1042=back
1043
1044=back
1045
1046=head1 SEE ALSO
1047
1048L<Net::Cmd>
1049
1050=head1 AUTHOR
1051
1052Graham Barr <gbarr@pobox.com>
1053
1054=head1 COPYRIGHT
1055
1056Copyright (c) 1995-1997 Graham Barr. All rights reserved.
1057This program is free software; you can redistribute it and/or modify
1058it under the same terms as Perl itself.
1059
1060=cut