File Coverage

blib/lib/LWP/Protocol/nntp.pm
Criterion Covered Total %
statement 35 71 49.3
branch 10 42 23.8
condition 4 15 26.6
subroutine 3 3 100.0
pod 1 1 100.0
total 53 132 40.1


line stmt bran cond sub pod time code
1             package LWP::Protocol::nntp;
2              
3             # Implementation of the Network News Transfer Protocol (RFC 977)
4              
5 1     1   5 use base qw(LWP::Protocol);
  1         2  
  1         123  
6              
7             our $VERSION = '6.34';
8              
9             require HTTP::Response;
10             require HTTP::Status;
11             require Net::NNTP;
12              
13 1     1   6 use strict;
  1         1  
  1         613  
14              
15              
16             sub request {
17 1     1 1 4 my ($self, $request, $proxy, $arg, $size, $timeout) = @_;
18              
19 1 50       2 $size = 4096 unless $size;
20              
21             # Check for proxy
22 1 50       6 if (defined $proxy) {
23 0         0 return HTTP::Response->new(HTTP::Status::RC_BAD_REQUEST,
24             'You can not proxy through NNTP');
25             }
26              
27             # Check that the scheme is as expected
28 1         9 my $url = $request->uri;
29 1         16 my $scheme = $url->scheme;
30 1 50 33     32 unless ($scheme eq 'news' || $scheme eq 'nntp') {
31 0         0 return HTTP::Response->new(HTTP::Status::RC_INTERNAL_SERVER_ERROR,
32             "LWP::Protocol::nntp::request called for '$scheme'");
33             }
34              
35             # check for a valid method
36 1         5 my $method = $request->method;
37 1 0 33     18 unless ($method eq 'GET' || $method eq 'HEAD' || $method eq 'POST') {
      33        
38 0         0 return HTTP::Response->new(HTTP::Status::RC_BAD_REQUEST,
39             'Library does not allow method ' . "$method for '$scheme:' URLs");
40             }
41              
42             # extract the identifier and check against posting to an article
43 1         11 my $groupart = $url->_group;
44 1         53 my $is_art = $groupart =~ /@/;
45              
46 1 50 33     7 if ($is_art && $method eq 'POST') {
47 0         0 return HTTP::Response->new(HTTP::Status::RC_BAD_REQUEST,
48             "Can't post to an article <$groupart>");
49             }
50              
51 1         10 my $nntp = Net::NNTP->new(
52             $url->host,
53              
54             #Port => 18574,
55             Timeout => $timeout,
56              
57             #Debug => 1,
58             );
59 1 50       709499 die "Can't connect to nntp server" unless $nntp;
60              
61             # Check the initial welcome message from the NNTP server
62 1 50       15 if ($nntp->status != 2) {
63 0         0 return HTTP::Response->new(HTTP::Status::RC_SERVICE_UNAVAILABLE,
64             $nntp->message);
65             }
66 1         32 my $response = HTTP::Response->new(HTTP::Status::RC_OK, "OK");
67              
68 1         130 my $mess = $nntp->message;
69              
70             # Try to extract server name from greeting message.
71             # Don't know if this works well for a large class of servers, but
72             # this works for our server.
73 1         22 $mess =~ s/\s+ready\b.*//;
74 1         6 $mess =~ s/^\S+\s+//;
75 1         16 $response->header(Server => $mess);
76              
77             # First we handle posting of articles
78 1 50       132 if ($method eq 'POST') {
79 0         0 $nntp->quit;
80 0         0 $nntp = undef;
81 0         0 $response->code(HTTP::Status::RC_NOT_IMPLEMENTED);
82 0         0 $response->message("POST not implemented yet");
83 0         0 return $response;
84             }
85              
86             # The method must be "GET" or "HEAD" by now
87 1 50       4 if (!$is_art) {
88 0 0       0 if (!$nntp->group($groupart)) {
89 0         0 $response->code(HTTP::Status::RC_NOT_FOUND);
90 0         0 $response->message($nntp->message);
91             }
92 0         0 $nntp->quit;
93 0         0 $nntp = undef;
94              
95             # HEAD: just check if the group exists
96 0 0 0     0 if ($method eq 'GET' && $response->is_success) {
97 0         0 $response->code(HTTP::Status::RC_NOT_IMPLEMENTED);
98 0         0 $response->message("GET newsgroup not implemented yet");
99             }
100 0         0 return $response;
101             }
102              
103             # Send command to server to retrieve an article (or just the headers)
104 1 50       6 my $get = $method eq 'HEAD' ? "head" : "article";
105 1         8 my $art = $nntp->$get("<$groupart>");
106 1 50       153693 unless ($art) {
107 1         8 $nntp->quit;
108 1         152773 $response->code(HTTP::Status::RC_NOT_FOUND);
109 1         24 $response->message($nntp->message);
110 1         32 $nntp = undef;
111 1         42 return $response;
112             }
113              
114             # Parse headers
115 0           my ($key, $val);
116 0           local $_;
117 0           while ($_ = shift @$art) {
118 0 0         if (/^\s+$/) {
    0          
    0          
119 0           last; # end of headers
120             }
121             elsif (/^(\S+):\s*(.*)/) {
122 0 0         $response->push_header($key, $val) if $key;
123 0           ($key, $val) = ($1, $2);
124             }
125             elsif (/^\s+(.*)/) {
126 0 0         next unless $key;
127 0           $val .= $1;
128             }
129             else {
130 0           unshift(@$art, $_);
131 0           last;
132             }
133             }
134 0 0         $response->push_header($key, $val) if $key;
135              
136             # Ensure that there is a Content-Type header
137 0 0         $response->header("Content-Type", "text/plain")
138             unless $response->header("Content-Type");
139              
140             # Collect the body
141 0 0         $response = $self->collect_once($arg, $response, join("", @$art)) if @$art;
142              
143             # Say goodbye to the server
144 0           $nntp->quit;
145 0           $nntp = undef;
146              
147 0           $response;
148             }
149              
150             1;