1 package LWP::Protocol::nntp;
3 # Implementation of the Network News Transfer Protocol (RFC 977)
6 @ISA = qw(LWP::Protocol);
9 require HTTP::Response;
18 my($self, $request, $proxy, $arg, $size, $timeout) = @_;
20 LWP::Debug::trace('()');
22 $size = 4096 unless $size;
26 return HTTP::Response->new(&HTTP::Status::RC_BAD_REQUEST,
27 'You can not proxy through NNTP');
30 # Check that the scheme is as expected
31 my $url = $request->url;
32 my $scheme = $url->scheme;
33 unless ($scheme eq 'news' || $scheme eq 'nntp') {
34 return HTTP::Response->new(&HTTP::Status::RC_INTERNAL_SERVER_ERROR,
35 "LWP::Protocol::nntp::request called for '$scheme'");
38 # check for a valid method
39 my $method = $request->method;
40 unless ($method eq 'GET' || $method eq 'HEAD' || $method eq 'POST') {
41 return HTTP::Response->new(&HTTP::Status::RC_BAD_REQUEST,
42 'Library does not allow method ' .
43 "$method for '$scheme:' URLs");
46 # extract the identifier and check against posting to an article
47 my $groupart = $url->_group;
48 my $is_art = $groupart =~ /@/;
50 if ($is_art && $method eq 'POST') {
51 return HTTP::Response->new(&HTTP::Status::RC_BAD_REQUEST,
52 "Can't post to an article <$groupart>");
55 my $nntp = Net::NNTP->new($url->host,
60 die "Can't connect to nntp server" unless $nntp;
62 # Check the initial welcome message from the NNTP server
63 if ($nntp->status != 2) {
64 return HTTP::Response->new(&HTTP::Status::RC_SERVICE_UNAVAILABLE,
67 my $response = HTTP::Response->new(&HTTP::Status::RC_OK, "OK");
69 my $mess = $nntp->message;
70 LWP::Debug::debug($mess);
72 # Try to extract server name from greeting message.
73 # Don't know if this works well for a large class of servers, but
74 # this works for our server.
75 $mess =~ s/\s+ready\b.*//;
77 $response->header(Server => $mess);
79 # First we handle posting of articles
80 if ($method eq 'POST') {
81 $nntp->quit; $nntp = undef;
82 $response->code(&HTTP::Status::RC_NOT_IMPLEMENTED);
83 $response->message("POST not implemented yet");
87 # The method must be "GET" or "HEAD" by now
89 if (!$nntp->group($groupart)) {
90 $response->code(&HTTP::Status::RC_NOT_FOUND);
91 $response->message($nntp->message);
93 $nntp->quit; $nntp = undef;
94 # HEAD: just check if the group exists
95 if ($method eq 'GET' && $response->is_success) {
96 $response->code(&HTTP::Status::RC_NOT_IMPLEMENTED);
97 $response->message("GET newsgroup not implemented yet");
102 # Send command to server to retrieve an article (or just the headers)
103 my $get = $method eq 'HEAD' ? "head" : "article";
104 my $art = $nntp->$get("<$groupart>");
106 $nntp->quit; $nntp = undef;
107 $response->code(&HTTP::Status::RC_NOT_FOUND);
108 $response->message($nntp->message);
111 LWP::Debug::debug($nntp->message);
116 while ($_ = shift @$art) {
118 last; # end of headers
120 elsif (/^(\S+):\s*(.*)/) {
121 $response->push_header($key, $val) if $key;
122 ($key, $val) = ($1, $2);
133 $response->push_header($key, $val) if $key;
135 # Ensure that there is a Content-Type header
136 $response->header("Content-Type", "text/plain")
137 unless $response->header("Content-Type");
140 $response = $self->collect_once($arg, $response, join("", @$art))
143 # Say goodbye to the server