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.
10 use vars qw(@ISA $VERSION $debug);
18 @ISA = qw(Net::Cmd IO::Socket::INET);
23 my $type = ref($self) || $self;
31 $host = delete $arg{Host};
35 $host ||= $ENV{NNTPSERVER} || $ENV{NEWSHOST};
37 my $hosts = defined $host ? [$host] : $NetConfig{nntp_hosts};
43 foreach $h (@{$hosts}) {
44 $obj = $type->SUPER::new(
45 PeerAddr => ($host = $h),
46 PeerPort => $arg{Port} || 'nntp(119)',
48 Timeout => defined $arg{Timeout}
58 ${*$obj}{'net_nntp_host'} = $host;
61 $obj->debug(exists $arg{Debug} ? $arg{Debug} : undef);
63 unless ($obj->response() == CMD_OK) {
69 my @m = $obj->message;
71 unless (exists $arg{Reader} && $arg{Reader} == 0) {
73 # if server is INN and we have transfer rights the we are currently
74 # talking to innd not nnrpd
77 # If reader suceeds the we need to consider this code to determine postok
82 # I want to ignore this failure, so restore the previous status.
83 $obj->set_status($c, \@m);
87 ${*$obj}{'net_nntp_post'} = $c == 200 ? 1 : 0;
95 ${*$me}{'net_nntp_host'};
104 if ( (ref($nntp) and $nntp->code == 350 and $text =~ /^(\S+)/)
105 || ($text =~ /^(authinfo\s+pass)/io))
115 @_ == 1 or croak 'usage: $nntp->postok()';
117 ${*$nntp}{'net_nntp_post'} || 0;
122 @_ >= 1 && @_ <= 3 or croak 'usage: $nntp->article( [ MSGID ], [ FH ] )';
126 @fh = (pop) if @_ == 2 || (@_ && (ref($_[0]) || ref(\$_[0]) eq 'GLOB'));
129 ? $nntp->read_until_dot(@fh)
135 @_ >= 1 && @_ <= 2 or croak 'usage: $nntp->articlefh( [ MSGID ] )';
138 return unless $nntp->_ARTICLE(@_);
139 return $nntp->tied_fh;
144 @_ == 3 or croak 'usage: $nntp->authinfo( USER, PASS )';
145 my ($nntp, $user, $pass) = @_;
147 $nntp->_AUTHINFO("USER", $user) == CMD_MORE
148 && $nntp->_AUTHINFO("PASS", $pass) == CMD_OK;
152 sub authinfo_simple {
153 @_ == 3 or croak 'usage: $nntp->authinfo( USER, PASS )';
154 my ($nntp, $user, $pass) = @_;
156 $nntp->_AUTHINFO('SIMPLE') == CMD_MORE
157 && $nntp->command($user, $pass)->response == CMD_OK;
162 @_ >= 1 && @_ <= 3 or croak 'usage: $nntp->body( [ MSGID ], [ FH ] )';
166 @fh = (pop) if @_ == 2 || (@_ && ref($_[0]) || ref(\$_[0]) eq 'GLOB');
169 ? $nntp->read_until_dot(@fh)
175 @_ >= 1 && @_ <= 2 or croak 'usage: $nntp->bodyfh( [ MSGID ] )';
177 return unless $nntp->_BODY(@_);
178 return $nntp->tied_fh;
183 @_ >= 1 && @_ <= 3 or croak 'usage: $nntp->head( [ MSGID ], [ FH ] )';
187 @fh = (pop) if @_ == 2 || (@_ && ref($_[0]) || ref(\$_[0]) eq 'GLOB');
190 ? $nntp->read_until_dot(@fh)
196 @_ >= 1 && @_ <= 2 or croak 'usage: $nntp->headfh( [ MSGID ] )';
198 return unless $nntp->_HEAD(@_);
199 return $nntp->tied_fh;
204 @_ == 1 || @_ == 2 or croak 'usage: $nntp->nntpstat( [ MSGID ] )';
207 $nntp->_STAT(@_) && $nntp->message =~ /(<[^>]+>)/o
214 @_ == 1 || @_ == 2 or croak 'usage: $nntp->group( [ GROUP ] )';
216 my $grp = ${*$nntp}{'net_nntp_group'} || undef;
219 unless (@_ || wantarray);
223 return wantarray ? () : undef
224 unless $nntp->_GROUP($newgrp || $grp || "")
225 && $nntp->message =~ /(\d+)\s+(\d+)\s+(\d+)\s+(\S+)/;
227 my ($count, $first, $last, $group) = ($1, $2, $3, $4);
229 # group may be replied as '(current group)'
230 $group = ${*$nntp}{'net_nntp_group'}
233 ${*$nntp}{'net_nntp_group'} = $group;
236 ? ($count, $first, $last, $group)
242 @_ == 1 or croak 'usage: $nntp->help()';
246 ? $nntp->read_until_dot
252 @_ >= 2 or croak 'usage: $nntp->ihave( MESSAGE-ID [, MESSAGE ])';
256 $nntp->_IHAVE($mid) && $nntp->datasend(@_)
257 ? @_ == 0 || $nntp->dataend
263 @_ == 1 or croak 'usage: $nntp->last()';
266 $nntp->_LAST && $nntp->message =~ /(<[^>]+>)/o
273 @_ == 1 or croak 'usage: $nntp->list()';
283 @_ >= 2 or croak 'usage: $nntp->newgroups( SINCE [, DISTRIBUTIONS ])';
285 my $time = _timestr(shift);
286 my $dist = shift || "";
288 $dist = join(",", @{$dist})
291 $nntp->_NEWGROUPS($time, $dist)
299 or croak 'usage: $nntp->newnews( SINCE [, GROUPS [, DISTRIBUTIONS ]])';
301 my $time = _timestr(shift);
302 my $grp = @_ ? shift: $nntp->group;
303 my $dist = shift || "";
306 $grp = join(",", @{$grp})
309 $dist = join(",", @{$dist})
312 $nntp->_NEWNEWS($grp, $time, $dist)
313 ? $nntp->_articlelist
319 @_ == 1 or croak 'usage: $nntp->next()';
322 $nntp->_NEXT && $nntp->message =~ /(<[^>]+>)/o
329 @_ >= 1 or croak 'usage: $nntp->post( [ MESSAGE ] )';
332 $nntp->_POST() && $nntp->datasend(@_)
333 ? @_ == 0 || $nntp->dataend
340 return unless $nntp->_POST();
341 return $nntp->tied_fh;
346 @_ == 1 or croak 'usage: $nntp->quit()';
355 @_ == 1 or croak 'usage: $nntp->slave()';
362 ## The following methods are not implemented by all servers
367 @_ == 1 || @_ == 2 or croak 'usage: $nntp->active( [ PATTERN ] )';
370 $nntp->_LIST('ACTIVE', @_)
377 @_ == 1 or croak 'usage: $nntp->active_times()';
380 $nntp->_LIST('ACTIVE.TIMES')
387 @_ == 1 or croak 'usage: $nntp->distributions()';
390 $nntp->_LIST('DISTRIBUTIONS')
391 ? $nntp->_description
396 sub distribution_patterns {
397 @_ == 1 or croak 'usage: $nntp->distributions()';
403 $nntp->_LIST('DISTRIB.PATS')
404 && ($arr = $nntp->read_until_dot)
405 ? [grep { /^\d/ && (chomp, $_ = [split /:/]) } @$arr]
411 @_ == 1 || @_ == 2 or croak 'usage: $nntp->newsgroups( [ PATTERN ] )';
414 $nntp->_LIST('NEWSGROUPS', @_)
415 ? $nntp->_description
421 @_ == 1 or croak 'usage: $nntp->overview_fmt()';
424 $nntp->_LIST('OVERVIEW.FMT')
425 ? $nntp->_articlelist
431 @_ == 1 or croak 'usage: $nntp->subscriptions()';
434 $nntp->_LIST('SUBSCRIPTIONS')
435 ? $nntp->_articlelist
441 @_ == 1 || @_ == 2 or croak 'usage: $nntp->listgroup( [ GROUP ] )';
444 $nntp->_LISTGROUP(@_)
445 ? $nntp->_articlelist
451 @_ == 1 or croak 'usage: $nntp->reader()';
454 $nntp->_MODE('READER');
459 @_ == 1 || @_ == 2 or croak 'usage: $nntp->xgtitle( [ PATTERN ] )';
463 ? $nntp->_description
469 @_ >= 2 && @_ <= 4 or croak 'usage: $nntp->xhdr( HEADER, [ MESSAGE-SPEC ] )';
472 my $arg = _msg_arg(@_);
474 $nntp->_XHDR($hdr, $arg)
475 ? $nntp->_description
481 @_ == 2 || @_ == 3 or croak 'usage: $nntp->xover( MESSAGE-SPEC )';
483 my $arg = _msg_arg(@_);
492 @_ == 4 || @_ == 5 or croak '$nntp->xpat( HEADER, PATTERN, MESSAGE-SPEC )';
496 my $arg = _msg_arg(@_);
498 $pat = join(" ", @$pat)
501 $nntp->_XPAT($hdr, $arg, $pat)
502 ? $nntp->_description
508 @_ == 2 or croak 'usage: $nntp->xpath( MESSAGE-ID )';
509 my ($nntp, $mid) = @_;
512 unless $nntp->_XPATH($mid);
515 ($m = $nntp->message) =~ s/^\d+\s+//o;
516 my @p = split /\s+/, $m;
518 wantarray ? @p : $p[0];
523 @_ == 2 || @_ == 3 or croak 'usage: $nntp->xrover( MESSAGE-SPEC )';
525 my $arg = _msg_arg(@_);
528 ? $nntp->_description
534 @_ == 1 or croak 'usage: $nntp->date()';
538 && $nntp->message =~ /(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/
539 ? timegm($6, $5, $4, $3, $2 - 1, $1 - 1900)
545 ## Private subroutines
554 carp "Depriciated passing of two message numbers, " . "pass a reference"
556 $spec = [$spec, $_[0]];
562 if (defined $spec->[1]) {
564 if $spec->[1] != $spec->[0];
566 if $spec->[1] > $spec->[0];
580 my @g = reverse((gmtime($time))[0 .. 5]);
583 sprintf "%02d%02d%02d %02d%02d%02d GMT", @g;
589 my $arr = $nntp->read_until_dot
595 foreach $ln (@$arr) {
596 my @a = split(/[\s\n]+/, $ln);
597 $hash->{$a[0]} = [@a[1, 2, 3]];
606 my $arr = $nntp->read_until_dot
612 foreach $ln (@$arr) {
613 my @a = split(/[\t\n]/, $ln);
624 my $arr = $nntp->read_until_dot;
635 my $arr = $nntp->read_until_dot
641 foreach $ln (@$arr) {
645 if $ln =~ s/^\s*(\S+)\s*//o;
657 sub _ARTICLE { shift->command('ARTICLE', @_)->response == CMD_OK }
658 sub _AUTHINFO { shift->command('AUTHINFO', @_)->response }
659 sub _BODY { shift->command('BODY', @_)->response == CMD_OK }
660 sub _DATE { shift->command('DATE')->response == CMD_INFO }
661 sub _GROUP { shift->command('GROUP', @_)->response == CMD_OK }
662 sub _HEAD { shift->command('HEAD', @_)->response == CMD_OK }
663 sub _HELP { shift->command('HELP', @_)->response == CMD_INFO }
664 sub _IHAVE { shift->command('IHAVE', @_)->response == CMD_MORE }
665 sub _LAST { shift->command('LAST')->response == CMD_OK }
666 sub _LIST { shift->command('LIST', @_)->response == CMD_OK }
667 sub _LISTGROUP { shift->command('LISTGROUP', @_)->response == CMD_OK }
668 sub _NEWGROUPS { shift->command('NEWGROUPS', @_)->response == CMD_OK }
669 sub _NEWNEWS { shift->command('NEWNEWS', @_)->response == CMD_OK }
670 sub _NEXT { shift->command('NEXT')->response == CMD_OK }
671 sub _POST { shift->command('POST', @_)->response == CMD_MORE }
672 sub _QUIT { shift->command('QUIT', @_)->response == CMD_OK }
673 sub _SLAVE { shift->command('SLAVE', @_)->response == CMD_OK }
674 sub _STAT { shift->command('STAT', @_)->response == CMD_OK }
675 sub _MODE { shift->command('MODE', @_)->response == CMD_OK }
676 sub _XGTITLE { shift->command('XGTITLE', @_)->response == CMD_OK }
677 sub _XHDR { shift->command('XHDR', @_)->response == CMD_OK }
678 sub _XPAT { shift->command('XPAT', @_)->response == CMD_OK }
679 sub _XPATH { shift->command('XPATH', @_)->response == CMD_OK }
680 sub _XOVER { shift->command('XOVER', @_)->response == CMD_OK }
681 sub _XROVER { shift->command('XROVER', @_)->response == CMD_OK }
682 sub _XTHREAD { shift->unsupported }
683 sub _XSEARCH { shift->unsupported }
684 sub _XINDEX { shift->unsupported }
693 defined(fileno($nntp)) && $nntp->quit;
703 Net::NNTP - NNTP Client class
709 $nntp = Net::NNTP->new("some.host.name");
714 C<Net::NNTP> is a class implementing a simple NNTP client in Perl as described
715 in RFC977. C<Net::NNTP> inherits its communication methods from C<Net::Cmd>
721 =item new ( [ HOST ] [, OPTIONS ])
723 This is the constructor for a new Net::NNTP object. C<HOST> is the
724 name of the remote host to which a NNTP connection is required. If not
725 given then it may be passed as the C<Host> option described below. If no host is passed
726 then two environment variables are checked, first C<NNTPSERVER> then
727 C<NEWSHOST>, then C<Net::Config> is checked, and if a host is not found
728 then C<news> is used.
730 C<OPTIONS> are passed in a hash like fashion, using key and value pairs.
731 Possible options are:
733 B<Host> - NNTP host to connect to. It may be a single scalar, as defined for
734 the C<PeerAddr> option in L<IO::Socket::INET>, or a reference to
735 an array with hosts to try in turn. The L</host> method will return the value
736 which was used to connect to the host.
738 B<Timeout> - Maximum time, in seconds, to wait for a response from the
739 NNTP server, a value of zero will cause all IO operations to block.
742 B<Debug> - Enable the printing of debugging information to STDERR
744 B<Reader> - If the remote server is INN then initially the connection
745 will be to nnrpd, by default C<Net::NNTP> will issue a C<MODE READER> command
746 so that the remote server becomes innd. If the C<Reader> option is given
747 with a value of zero, then this command will not be sent and the
748 connection will be left talking to nnrpd.
754 Unless otherwise stated all methods return either a I<true> or I<false>
755 value, with I<true> meaning that the operation was a success. When a method
756 states that it returns a value, failure will be returned as I<undef> or an
761 =item article ( [ MSGID|MSGNUM ], [FH] )
763 Retrieve the header, a blank line, then the body (text) of the
766 If C<FH> is specified then it is expected to be a valid filehandle
767 and the result will be printed to it, on success a true value will be
768 returned. If C<FH> is not specified then the return value, on success,
769 will be a reference to an array containing the article requested, each
770 entry in the array will contain one line of the article.
772 If no arguments are passed then the current article in the currently
773 selected newsgroup is fetched.
775 C<MSGNUM> is a numeric id of an article in the current newsgroup, and
776 will change the current article pointer. C<MSGID> is the message id of
777 an article as shown in that article's header. It is anticipated that the
778 client will obtain the C<MSGID> from a list provided by the C<newnews>
779 command, from references contained within another article, or from the
780 message-id provided in the response to some other commands.
782 If there is an error then C<undef> will be returned.
784 =item body ( [ MSGID|MSGNUM ], [FH] )
786 Like C<article> but only fetches the body of the article.
788 =item head ( [ MSGID|MSGNUM ], [FH] )
790 Like C<article> but only fetches the headers for the article.
792 =item articlefh ( [ MSGID|MSGNUM ] )
794 =item bodyfh ( [ MSGID|MSGNUM ] )
796 =item headfh ( [ MSGID|MSGNUM ] )
798 These are similar to article(), body() and head(), but rather than
799 returning the requested data directly, they return a tied filehandle
800 from which to read the article.
802 =item nntpstat ( [ MSGID|MSGNUM ] )
804 The C<nntpstat> command is similar to the C<article> command except that no
805 text is returned. When selecting by message number within a group,
806 the C<nntpstat> command serves to set the "current article pointer" without
809 Using the C<nntpstat> command to
810 select by message-id is valid but of questionable value, since a
811 selection by message-id does B<not> alter the "current article pointer".
813 Returns the message-id of the "current article".
815 =item group ( [ GROUP ] )
817 Set and/or get the current group. If C<GROUP> is not given then information
818 is returned on the current group.
820 In a scalar context it returns the group name.
822 In an array context the return value is a list containing, the number
823 of articles in the group, the number of the first article, the number
824 of the last article and the group name.
826 =item ihave ( MSGID [, MESSAGE ])
828 The C<ihave> command informs the server that the client has an article
829 whose id is C<MSGID>. If the server desires a copy of that
830 article, and C<MESSAGE> has been given the it will be sent.
832 Returns I<true> if the server desires the article and C<MESSAGE> was
833 successfully sent,if specified.
835 If C<MESSAGE> is not specified then the message must be sent using the
836 C<datasend> and C<dataend> methods from L<Net::Cmd>
838 C<MESSAGE> can be either an array of lines or a reference to an array.
842 Set the "current article pointer" to the previous article in the current
845 Returns the message-id of the article.
849 Returns the date on the remote server. This date will be in a UNIX time
850 format (seconds since 1970)
854 C<postok> will return I<true> if the servers initial response indicated
855 that it will allow posting.
857 =item authinfo ( USER, PASS )
859 Authenticates to the server (using AUTHINFO USER / AUTHINFO PASS)
860 using the supplied username and password. Please note that the
861 password is sent in clear text to the server. This command should not
862 be used with valuable passwords unless the connection to the server is
867 Obtain information about all the active newsgroups. The results is a reference
868 to a hash where the key is a group name and each value is a reference to an
869 array. The elements in this array are:- the last article number in the group,
870 the first article number in the group and any information flags about the group.
872 =item newgroups ( SINCE [, DISTRIBUTIONS ])
874 C<SINCE> is a time value and C<DISTRIBUTIONS> is either a distribution
875 pattern or a reference to a list of distribution patterns.
876 The result is the same as C<list>, but the
877 groups return will be limited to those created after C<SINCE> and, if
878 specified, in one of the distribution areas in C<DISTRIBUTIONS>.
880 =item newnews ( SINCE [, GROUPS [, DISTRIBUTIONS ]])
882 C<SINCE> is a time value. C<GROUPS> is either a group pattern or a reference
883 to a list of group patterns. C<DISTRIBUTIONS> is either a distribution
884 pattern or a reference to a list of distribution patterns.
886 Returns a reference to a list which contains the message-ids of all news posted
887 after C<SINCE>, that are in a groups which matched C<GROUPS> and a
888 distribution which matches C<DISTRIBUTIONS>.
892 Set the "current article pointer" to the next article in the current
895 Returns the message-id of the article.
897 =item post ( [ MESSAGE ] )
899 Post a new article to the news server. If C<MESSAGE> is specified and posting
900 is allowed then the message will be sent.
902 If C<MESSAGE> is not specified then the message must be sent using the
903 C<datasend> and C<dataend> methods from L<Net::Cmd>
905 C<MESSAGE> can be either an array of lines or a reference to an array.
907 The message, either sent via C<datasend> or as the C<MESSAGE>
908 parameter, must be in the format as described by RFC822 and must
909 contain From:, Newsgroups: and Subject: headers.
913 Post a new article to the news server using a tied filehandle. If
914 posting is allowed, this method will return a tied filehandle that you
915 can print() the contents of the article to be posted. You must
916 explicitly close() the filehandle when you are finished posting the
917 article, and the return value from the close() call will indicate
918 whether the message was successfully posted.
922 Tell the remote server that I am not a user client, but probably another
927 Quit the remote server and close the socket connection.
931 =head2 Extension methods
933 These methods use commands that are not part of the RFC977 documentation. Some
934 servers may not support all of them.
938 =item newsgroups ( [ PATTERN ] )
940 Returns a reference to a hash where the keys are all the group names which
941 match C<PATTERN>, or all of the groups if no pattern is specified, and
942 each value contains the description text for the group.
944 =item distributions ()
946 Returns a reference to a hash where the keys are all the possible
947 distribution names and the values are the distribution descriptions.
949 =item subscriptions ()
951 Returns a reference to a list which contains a list of groups which
952 are recommended for a new user to subscribe to.
954 =item overview_fmt ()
956 Returns a reference to an array which contain the names of the fields returned
959 =item active_times ()
961 Returns a reference to a hash where the keys are the group names and each
962 value is a reference to an array containing the time the groups was created
963 and an identifier, possibly an Email address, of the creator.
965 =item active ( [ PATTERN ] )
967 Similar to C<list> but only active groups that match the pattern are returned.
968 C<PATTERN> can be a group pattern.
970 =item xgtitle ( PATTERN )
972 Returns a reference to a hash where the keys are all the group names which
973 match C<PATTERN> and each value is the description text for the group.
975 =item xhdr ( HEADER, MESSAGE-SPEC )
977 Obtain the header field C<HEADER> for all the messages specified.
979 The return value will be a reference
980 to a hash where the keys are the message numbers and each value contains
981 the text of the requested header for that message.
983 =item xover ( MESSAGE-SPEC )
985 The return value will be a reference
986 to a hash where the keys are the message numbers and each value contains
987 a reference to an array which contains the overview fields for that
990 The names of the fields can be obtained by calling C<overview_fmt>.
992 =item xpath ( MESSAGE-ID )
994 Returns the path name to the file on the server which contains the specified
997 =item xpat ( HEADER, PATTERN, MESSAGE-SPEC)
999 The result is the same as C<xhdr> except the is will be restricted to
1000 headers where the text of the header matches C<PATTERN>
1004 The XROVER command returns reference information for the article(s)
1007 Returns a reference to a HASH where the keys are the message numbers and the
1008 values are the References: lines from the articles
1010 =item listgroup ( [ GROUP ] )
1012 Returns a reference to a list of all the active messages in C<GROUP>, or
1013 the current group if C<GROUP> is not specified.
1017 Tell the server that you are a reader and not another server.
1019 This is required by some servers. For example if you are connecting to
1020 an INN server and you have transfer permission your connection will
1021 be connected to the transfer daemon, not the NNTP daemon. Issuing
1022 this command will cause the transfer daemon to hand over control
1025 Some servers do not understand this command, but issuing it and ignoring
1026 the response is harmless.
1032 The following NNTP command are unsupported by the package, and there are
1046 C<MESSAGE-SPEC> is either a single message-id, a single message number, or
1047 a reference to a list of two message numbers.
1049 If C<MESSAGE-SPEC> is a reference to a list of two message numbers and the
1050 second number in a range is less than or equal to the first then the range
1051 represents all messages in the group after the first message number.
1053 B<NOTE> For compatibility reasons only with earlier versions of Net::NNTP
1054 a message spec can be passed as a list of two numbers, this is deprecated
1055 and a reference to the list should now be passed
1059 The C<NNTP> protocol uses the C<WILDMAT> format for patterns.
1060 The WILDMAT format was first developed by Rich Salz based on
1061 the format used in the UNIX "find" command to articulate
1062 file names. It was developed to provide a uniform mechanism
1063 for matching patterns in the same manner that the UNIX shell
1066 Patterns are implicitly anchored at the
1067 beginning and end of each string when testing for a match.
1069 There are five pattern matching operations other than a strict
1070 one-to-one match between the pattern and the source to be
1071 checked for a match.
1073 The first is an asterisk C<*> to match any sequence of zero or more
1076 The second is a question mark C<?> to match any single character. The
1077 third specifies a specific set of characters.
1079 The set is specified as a list of characters, or as a range of characters
1080 where the beginning and end of the range are separated by a minus (or dash)
1081 character, or as any combination of lists and ranges. The dash can
1082 also be included in the set as a character it if is the beginning
1083 or end of the set. This set is enclosed in square brackets. The
1084 close square bracket C<]> may be used in a set if it is the first
1085 character in the set.
1087 The fourth operation is the same as the
1088 logical not of the third operation and is specified the same
1089 way as the third with the addition of a caret character C<^> at
1090 the beginning of the test string just inside the open square
1093 The final operation uses the backslash character to
1094 invalidate the special meaning of an open square bracket C<[>,
1095 the asterisk, backslash or the question mark. Two backslashes in
1096 sequence will result in the evaluation of the backslash as a
1097 character with no special meaning.
1105 matches any single character other than a close square
1106 bracket or a minus sign/dash.
1110 matches any string that ends with the string "bdc"
1111 including the string "bdc" (without quotes).
1113 =item C<[0-9a-zA-Z]>
1115 matches any single printable alphanumeric ASCII character.
1119 matches any four character string which begins
1120 with a and ends with d.
1132 Graham Barr <gbarr@pobox.com>
1136 Copyright (c) 1995-1997 Graham Barr. All rights reserved.
1137 This program is free software; you can redistribute it and/or modify
1138 it under the same terms as Perl itself.