File Coverage

blib/lib/LWP/UserAgent.pm
Criterion Covered Total %
statement 464 603 76.9
branch 198 364 54.4
condition 73 160 45.6
subroutine 62 74 83.7
pod 41 45 91.1
total 838 1246 67.2


line stmt bran cond sub pod time code
1             package LWP::UserAgent;
2              
3 15     15   582214 use strict;
  15         107  
  15         428  
4              
5 15     15   72 use base qw(LWP::MemberMixin);
  15         23  
  15         4329  
6              
7 15     15   88 use Carp ();
  15         24  
  15         189  
8 15     15   2035 use HTTP::Request ();
  15         144062  
  15         234  
9 15     15   3470 use HTTP::Response ();
  15         56207  
  15         272  
10 15     15   3933 use HTTP::Date ();
  15         39058  
  15         341  
11              
12 15     15   5474 use LWP ();
  15         40  
  15         336  
13 15     15   3782 use LWP::Protocol ();
  15         36  
  15         324  
14              
15 15     15   91 use Scalar::Util qw(blessed);
  15         28  
  15         782  
16 15     15   82 use Try::Tiny qw(try catch);
  15         40  
  15         26059  
17              
18             our $VERSION = '6.29';
19              
20             sub new
21             {
22             # Check for common user mistake
23 32 50   32 1 286879 Carp::croak("Options to LWP::UserAgent should be key/value pairs, not hash reference")
24             if ref($_[1]) eq 'HASH';
25              
26 32         98 my($class, %cnf) = @_;
27              
28 32         74 my $agent = delete $cnf{agent};
29 32         60 my $from = delete $cnf{from};
30 32         56 my $def_headers = delete $cnf{default_headers};
31 32         54 my $timeout = delete $cnf{timeout};
32 32 50       105 $timeout = 3*60 unless defined $timeout;
33 32         59 my $local_address = delete $cnf{local_address};
34 32   100     162 my $ssl_opts = delete $cnf{ssl_opts} || {};
35 32 100       93 unless (exists $ssl_opts->{verify_hostname}) {
36             # The processing of HTTPS_CA_* below is for compatibility with Crypt::SSLeay
37 29 100 33     181 if (exists $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}) {
    50          
38 8         18 $ssl_opts->{verify_hostname} = $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME};
39             }
40             elsif ($ENV{HTTPS_CA_FILE} || $ENV{HTTPS_CA_DIR}) {
41             # Crypt-SSLeay compatibility (verify peer certificate; but not the hostname)
42 0         0 $ssl_opts->{verify_hostname} = 0;
43 0         0 $ssl_opts->{SSL_verify_mode} = 1;
44             }
45             else {
46 21         60 $ssl_opts->{verify_hostname} = 1;
47             }
48             }
49 32 100       87 unless (exists $ssl_opts->{SSL_ca_file}) {
50 31 50 33     191 if (my $ca_file = $ENV{PERL_LWP_SSL_CA_FILE} || $ENV{HTTPS_CA_FILE}) {
51 0         0 $ssl_opts->{SSL_ca_file} = $ca_file;
52             }
53             }
54 32 50       89 unless (exists $ssl_opts->{SSL_ca_path}) {
55 32 50 33     160 if (my $ca_path = $ENV{PERL_LWP_SSL_CA_PATH} || $ENV{HTTPS_CA_DIR}) {
56 0         0 $ssl_opts->{SSL_ca_path} = $ca_path;
57             }
58             }
59 32         55 my $use_eval = delete $cnf{use_eval};
60 32 50       87 $use_eval = 1 unless defined $use_eval;
61 32         50 my $parse_head = delete $cnf{parse_head};
62 32 50       74 $parse_head = 1 unless defined $parse_head;
63 32         51 my $show_progress = delete $cnf{show_progress};
64 32         51 my $max_size = delete $cnf{max_size};
65 32         45 my $max_redirect = delete $cnf{max_redirect};
66 32 50       69 $max_redirect = 7 unless defined $max_redirect;
67 32 100       81 my $env_proxy = exists $cnf{env_proxy} ? delete $cnf{env_proxy} : $ENV{PERL_LWP_ENV_PROXY};
68 32 100       80 my $no_proxy = exists $cnf{no_proxy} ? delete $cnf{no_proxy} : [];
69 32 50       106 Carp::croak(qq{no_proxy must be an arrayref, not $no_proxy!}) if ref $no_proxy ne 'ARRAY';
70              
71 32         56 my $cookie_jar = delete $cnf{cookie_jar};
72 32         62 my $conn_cache = delete $cnf{conn_cache};
73 32         55 my $keep_alive = delete $cnf{keep_alive};
74              
75 32 50 33     104 Carp::croak("Can't mix conn_cache and keep_alive")
76             if $conn_cache && $keep_alive;
77              
78 32         53 my $protocols_allowed = delete $cnf{protocols_allowed};
79 32         49 my $protocols_forbidden = delete $cnf{protocols_forbidden};
80              
81 32         45 my $requests_redirectable = delete $cnf{requests_redirectable};
82 32 50       110 $requests_redirectable = ['GET', 'HEAD']
83             unless defined $requests_redirectable;
84              
85             # Actually ""s are just as good as 0's, but for concision we'll just say:
86 32 50 33     95 Carp::croak("protocols_allowed has to be an arrayref or 0, not \"$protocols_allowed\"!")
87             if $protocols_allowed and ref($protocols_allowed) ne 'ARRAY';
88 32 50 33     84 Carp::croak("protocols_forbidden has to be an arrayref or 0, not \"$protocols_forbidden\"!")
89             if $protocols_forbidden and ref($protocols_forbidden) ne 'ARRAY';
90 32 50 33     154 Carp::croak("requests_redirectable has to be an arrayref or 0, not \"$requests_redirectable\"!")
91             if $requests_redirectable and ref($requests_redirectable) ne 'ARRAY';
92              
93 32 50 66     89 if (%cnf && $^W) {
94 0         0 Carp::carp("Unrecognized LWP::UserAgent options: @{[sort keys %cnf]}");
  0         0  
95             }
96              
97             my $self = bless {
98             def_headers => $def_headers,
99             timeout => $timeout,
100             local_address => $local_address,
101             ssl_opts => $ssl_opts,
102             use_eval => $use_eval,
103             show_progress => $show_progress,
104             max_size => $max_size,
105             max_redirect => $max_redirect,
106             # We set proxy later as we do validation on the values
107             proxy => {},
108 32         74 no_proxy => [ @{ $no_proxy } ],
  32         248  
109             protocols_allowed => $protocols_allowed,
110             protocols_forbidden => $protocols_forbidden,
111             requests_redirectable => $requests_redirectable,
112             }, $class;
113              
114 32 100 66     259 $self->agent(defined($agent) ? $agent : $class->_agent)
    50 33        
115             if defined($agent) || !$def_headers || !$def_headers->header("User-Agent");
116 32 100       1613 $self->from($from) if $from;
117 32 50       178 $self->cookie_jar($cookie_jar) if $cookie_jar;
118 32         124 $self->parse_head($parse_head);
119 32 100       82 $self->env_proxy if $env_proxy;
120              
121 32 100       100 if (exists $cnf{proxy}) {
122             Carp::croak(qq{proxy must be an arrayref, not $cnf{proxy}!})
123 1 50       4 if ref $cnf{proxy} ne 'ARRAY';
124 1         5 $self->proxy($cnf{proxy});
125             }
126              
127 32 50       87 $self->protocols_allowed( $protocols_allowed ) if $protocols_allowed;
128 32 50       65 $self->protocols_forbidden($protocols_forbidden) if $protocols_forbidden;
129              
130 32 100       78 if ($keep_alive) {
131 1   50     6 $conn_cache ||= { total_capacity => $keep_alive };
132             }
133 32 100       72 $self->conn_cache($conn_cache) if $conn_cache;
134              
135 32         228 return $self;
136             }
137              
138              
139             sub send_request
140             {
141 70     70 0 162 my($self, $request, $arg, $size) = @_;
142 70         198 my($method, $url) = ($request->method, $request->uri);
143 70         1166 my $scheme = $url->scheme;
144              
145 70         1266 local($SIG{__DIE__}); # protect against user defined die handlers
146              
147 70         257 $self->progress("begin", $request);
148              
149 70         151 my $response = $self->run_handlers("request_send", $request);
150              
151 70 50       171 unless ($response) {
152 70         100 my $protocol;
153              
154             {
155             # Honor object-specific restrictions by forcing protocol objects
156             # into class LWP::Protocol::nogo.
157 70         95 my $x;
  70         98  
158 70 50       183 if($x = $self->protocols_allowed) {
    100          
159 0 0       0 if (grep lc($_) eq $scheme, @$x) {
160             }
161             else {
162 0         0 require LWP::Protocol::nogo;
163 0         0 $protocol = LWP::Protocol::nogo->new;
164             }
165             }
166             elsif ($x = $self->protocols_forbidden) {
167 1 50       5 if(grep lc($_) eq $scheme, @$x) {
168 1         276 require LWP::Protocol::nogo;
169 1         7 $protocol = LWP::Protocol::nogo->new;
170             }
171             }
172             # else fall thru and create the protocol object normally
173             }
174              
175             # Locate protocol to use
176 70         135 my $proxy = $request->{proxy};
177 70 100       245 if ($proxy) {
178 16         117 $scheme = $proxy->scheme;
179             }
180              
181 70 100       314 unless ($protocol) {
182             try {
183 69     69   2783 $protocol = LWP::Protocol::create($scheme, $self);
184             }
185             catch {
186 1     1   37 my $error = $_;
187 1         7 $error =~ s/ at .* line \d+.*//s; # remove file/line number
188 1         3 $response = _new_response($request, HTTP::Status::RC_NOT_IMPLEMENTED, $error);
189 1 50       6 if ($scheme eq "https") {
190 0         0 $response->message($response->message . " (LWP::Protocol::https not installed)");
191 0         0 $response->content_type("text/plain");
192 0         0 $response->content(<
193             LWP will support https URLs if the LWP::Protocol::https module
194             is installed.
195             EOT
196             }
197 69         500 };
198             }
199              
200 70 100 66     1337 if (!$response && $self->{use_eval}) {
    50          
201             # we eval, and turn dies into responses below
202             try {
203 69   50 69   2670 $response = $protocol->request($request, $proxy, $arg, $size, $self->{timeout}) || die "No response returned by $protocol";
204             }
205             catch {
206 1     1   31 my $error = $_;
207 1 50 33     12 if (blessed($error) && $error->isa("HTTP::Response")) {
208 0         0 $response = $error;
209 0         0 $response->request($request);
210             }
211             else {
212 1         2 my $full = $error;
213 1         19 (my $status = $error) =~ s/\n.*//s;
214 1         4 $status =~ s/ at .* line \d+.*//s; # remove file/line number
215 1 50       6 my $code = ($status =~ s/^(\d\d\d)\s+//) ? $1 : HTTP::Status::RC_INTERNAL_SERVER_ERROR;
216 1         8 $response = _new_response($request, $code, $status, $full);
217             }
218 69         492 };
219             }
220             elsif (!$response) {
221             $response = $protocol->request($request, $proxy,
222 0         0 $arg, $size, $self->{timeout});
223             # XXX: Should we die unless $response->is_success ???
224             }
225             }
226              
227 70         1763 $response->request($request); # record request for reference
228 70         948 $response->header("Client-Date" => HTTP::Date::time2str(time));
229              
230 70         6329 $self->run_handlers("response_done", $response);
231              
232 70         209 $self->progress("end", $response);
233 70         376 return $response;
234             }
235              
236              
237             sub prepare_request
238             {
239 72     72 1 160 my($self, $request) = @_;
240 72 100       192 die "Method missing" unless $request->method;
241 71         922 my $url = $request->uri;
242 71 50       1035 die "URL missing" unless $url;
243 71 100       655 die "URL must be absolute" unless $url->scheme;
244              
245 70         1692 $self->run_handlers("request_preprepare", $request);
246              
247 70 50       3531 if (my $def_headers = $self->{def_headers}) {
248 70         264 for my $h ($def_headers->header_field_names) {
249 130         6364 $request->init_header($h => [$def_headers->header($h)]);
250             }
251             }
252              
253 70         4736 $self->run_handlers("request_prepare", $request);
254              
255 70         750 return $request;
256             }
257              
258              
259             sub simple_request
260             {
261 72     72 1 5872 my($self, $request, $arg, $size) = @_;
262              
263             # sanity check the request passed in
264 72 50       188 if (defined $request) {
265 72 50       175 if (ref $request) {
266 72 50 33     954 Carp::croak("You need a request object, not a " . ref($request) . " object")
      33        
      33        
267             if ref($request) eq 'ARRAY' or ref($request) eq 'HASH' or
268             !$request->can('method') or !$request->can('uri');
269             }
270             else {
271 0         0 Carp::croak("You need a request object, not '$request'");
272             }
273             }
274             else {
275 0         0 Carp::croak("No request object passed in");
276             }
277              
278 72         170 my $error;
279             try {
280 72     72   3429 $request = $self->prepare_request($request);
281             }
282             catch {
283 2     2   52 $error = $_;
284 2         16 $error =~ s/ at .* line \d+.*//s; # remove file/line number
285 72         593 };
286              
287 72 100       1217 if ($error) {
288 2         7 return _new_response($request, HTTP::Status::RC_BAD_REQUEST, $error);
289             }
290 70         223 return $self->send_request($request, $arg, $size);
291             }
292              
293              
294             sub request {
295 73     73 1 58816 my ($self, $request, $arg, $size, $previous) = @_;
296              
297 73         218 my $response = $self->simple_request($request, $arg, $size);
298 73 100       220 $response->previous($previous) if $previous;
299              
300 73 100       346 if ($response->redirects >= $self->{max_redirect}) {
301 2         127 $response->header("Client-Warning" =>
302             "Redirect loop detected (max_redirect = $self->{max_redirect})"
303             );
304 2         206 return $response;
305             }
306              
307 71 50       1609 if (my $req = $self->run_handlers("response_redirect", $response)) {
308 0         0 return $self->request($req, $arg, $size, $response);
309             }
310              
311 71         199 my $code = $response->code;
312              
313 71 100 66     1365 if ( $code == HTTP::Status::RC_MOVED_PERMANENTLY
    100 66        
      33        
      66        
314             or $code == HTTP::Status::RC_FOUND
315             or $code == HTTP::Status::RC_SEE_OTHER
316             or $code == HTTP::Status::RC_TEMPORARY_REDIRECT)
317             {
318 6         23 my $referral = $request->clone;
319              
320             # These headers should never be forwarded
321 6         1033 $referral->remove_header('Host', 'Cookie');
322              
323 6 0 33     203 if ( $referral->header('Referer')
      33        
324             && $request->uri->scheme eq 'https'
325             && $referral->uri->scheme eq 'http')
326             {
327             # RFC 2616, section 15.1.3.
328             # https -> http redirect, suppressing Referer
329 0         0 $referral->remove_header('Referer');
330             }
331              
332 6 50 33     361 if ( $code == HTTP::Status::RC_SEE_OTHER
333             || $code == HTTP::Status::RC_FOUND)
334             {
335 0         0 my $method = uc($referral->method);
336 0 0 0     0 unless ($method eq "GET" || $method eq "HEAD") {
337 0         0 $referral->method("GET");
338 0         0 $referral->content("");
339 0         0 $referral->remove_content_headers;
340             }
341             }
342              
343             # And then we update the URL based on the Location:-header.
344 6         18 my $referral_uri = $response->header('Location');
345             {
346             # Some servers erroneously return a relative URL for redirects,
347             # so make it absolute if it not already is.
348 6         238 local $URI::ABS_ALLOW_RELATIVE_SCHEME = 1;
  6         13  
349 6         21 my $base = $response->base;
350 6 50       2778 $referral_uri = "" unless defined $referral_uri;
351 6         24 $referral_uri
352             = $HTTP::URI_CLASS->new($referral_uri, $base)->abs($base);
353             }
354 6         1339 $referral->uri($referral_uri);
355              
356 6 50       155 return $response unless $self->redirect_ok($referral, $response);
357 6         54 return $self->request($referral, $arg, $size, $response);
358              
359             }
360             elsif ($code == HTTP::Status::RC_UNAUTHORIZED
361             || $code == HTTP::Status::RC_PROXY_AUTHENTICATION_REQUIRED)
362             {
363 8         22 my $proxy = ($code == HTTP::Status::RC_PROXY_AUTHENTICATION_REQUIRED);
364 8 50 33     49 my $ch_header
365             = $proxy || $request->method eq 'CONNECT'
366             ? "Proxy-Authenticate"
367             : "WWW-Authenticate";
368 8         101 my @challenges = $response->header($ch_header);
369 8 50       384 unless (@challenges) {
370 0         0 $response->header(
371             "Client-Warning" => "Missing Authenticate header");
372 0         0 return $response;
373             }
374              
375 8         477 require HTTP::Headers::Util;
376 8         1057 CHALLENGE: for my $challenge (@challenges) {
377 8         18 $challenge =~ tr/,/;/; # "," is used to separate auth-params!!
378 8         32 ($challenge) = HTTP::Headers::Util::split_header_words($challenge);
379 8         603 my $scheme = shift(@$challenge);
380 8         23 shift(@$challenge); # no value
381 8         44 $challenge = {@$challenge}; # make rest into a hash
382              
383 8 50       62 unless ($scheme =~ /^([a-z]+(?:-[a-z]+)*)$/) {
384 0         0 $response->header(
385             "Client-Warning" => "Bad authentication scheme '$scheme'");
386 0         0 return $response;
387             }
388 8         23 $scheme = $1; # untainted now
389 8         30 my $class = "LWP::Authen::\u$scheme";
390 8         21 $class =~ s/-/_/g;
391              
392 15     15   120 no strict 'refs';
  15         33  
  15         56942  
393 8 100       13 unless (%{"$class\::"}) {
  8         66  
394             # try to load it
395 2         5 my $error;
396             try {
397 2     2   100 (my $req = $class) =~ s{::}{/}g;
398 2 50       13 $req .= '.pm' unless $req =~ /\.pm$/;
399 2         910 require $req;
400             }
401             catch {
402 0     0   0 $error = $_;
403 2         25 };
404 2 50       39 if ($error) {
405 0 0       0 if ($error =~ /^Can\'t locate/) {
406 0         0 $response->header("Client-Warning" =>
407             "Unsupported authentication scheme '$scheme'");
408             }
409             else {
410 0         0 $response->header("Client-Warning" => $error);
411             }
412 0         0 next CHALLENGE;
413             }
414             }
415 8 50       396 unless ($class->can("authenticate")) {
416 0         0 $response->header("Client-Warning" =>
417             "Unsupported authentication scheme '$scheme'");
418 0         0 next CHALLENGE;
419             }
420 8         36 return $class->authenticate($self, $proxy, $challenge, $response,
421             $request, $arg, $size);
422             }
423 0         0 return $response;
424             }
425 57         283 return $response;
426             }
427              
428             #
429             # Now the shortcuts...
430             #
431             sub get {
432 13     13 1 12672 require HTTP::Request::Common;
433 13         11730 my($self, @parameters) = @_;
434 13         60 my @suff = $self->_process_colonic_headers(\@parameters,1);
435 13         68 return $self->request( HTTP::Request::Common::GET( @parameters ), @suff );
436             }
437              
438             sub _has_raw_content {
439 10     10   13 my $self = shift;
440 10         12 shift; # drop url
441              
442             # taken from HTTP::Request::Common::request_type_with_data
443 10         11 my $content;
444 10 100 66     35 $content = shift if @_ and ref $_[0];
445 10         15 my($k, $v);
446 10         22 while (($k,$v) = splice(@_, 0, 2)) {
447 6 50       20 if (lc($k) eq 'content') {
448 6         13 $content = $v;
449             }
450             }
451              
452             # We were given Content => 'string' ...
453 10 100 66     30 if (defined $content && ! ref ($content)) {
454 2         6 return 1;
455             }
456              
457 8         22 return;
458             }
459              
460             sub _maybe_copy_default_content_type {
461 13     13   34 my ($self, $req, @parameters) = @_;
462              
463             # If we have a default Content-Type and someone passes in a POST/PUT
464             # with Content => 'some-string-value', use that Content-Type instead
465             # of x-www-form-urlencoded
466 13         30 my $ct = $self->default_header('Content-Type');
467 13 100 100     379 return unless defined $ct && $self->_has_raw_content(@parameters);
468              
469 2         7 $req->header('Content-Type' => $ct);
470             }
471              
472             sub post {
473 6     6 1 6701 require HTTP::Request::Common;
474 6         21 my($self, @parameters) = @_;
475 6 100       29 my @suff = $self->_process_colonic_headers(\@parameters, (ref($parameters[1]) ? 2 : 1));
476 6         20 my $req = HTTP::Request::Common::POST(@parameters);
477 6         2146 $self->_maybe_copy_default_content_type($req, @parameters);
478 6         51 return $self->request($req, @suff);
479             }
480              
481              
482             sub head {
483 0     0 1 0 require HTTP::Request::Common;
484 0         0 my($self, @parameters) = @_;
485 0         0 my @suff = $self->_process_colonic_headers(\@parameters,1);
486 0         0 return $self->request( HTTP::Request::Common::HEAD( @parameters ), @suff );
487             }
488              
489              
490             sub put {
491 7     7 1 6605 require HTTP::Request::Common;
492 7         1653 my($self, @parameters) = @_;
493 7 100       39 my @suff = $self->_process_colonic_headers(\@parameters, (ref($parameters[1]) ? 2 : 1));
494 7         24 my $req = HTTP::Request::Common::PUT(@parameters);
495 7         7515 $self->_maybe_copy_default_content_type($req, @parameters);
496 7         56 return $self->request($req, @suff);
497             }
498              
499              
500             sub delete {
501 1     1 1 1457 require HTTP::Request::Common;
502 1         9 my($self, @parameters) = @_;
503 1         6 my @suff = $self->_process_colonic_headers(\@parameters,1);
504 1         5 return $self->request( HTTP::Request::Common::DELETE( @parameters ), @suff );
505             }
506              
507              
508             sub _process_colonic_headers {
509             # Process :content_cb / :content_file / :read_size_hint headers.
510 27     27   60 my($self, $args, $start_index) = @_;
511              
512 27         44 my($arg, $size);
513 27         109 for(my $i = $start_index; $i < @$args; $i += 2) {
514 19 50       81 next unless defined $args->[$i];
515              
516             #printf "Considering %s => %s\n", $args->[$i], $args->[$i + 1];
517              
518 19 50       54 if($args->[$i] eq ':content_cb') {
    50          
    50          
519             # Some sanity-checking...
520 0         0 $arg = $args->[$i + 1];
521 0 0       0 Carp::croak("A :content_cb value can't be undef") unless defined $arg;
522 0 0 0     0 Carp::croak("A :content_cb value must be a coderef")
523             unless ref $arg and UNIVERSAL::isa($arg, 'CODE');
524              
525             }
526             elsif ($args->[$i] eq ':content_file') {
527 0         0 $arg = $args->[$i + 1];
528              
529             # Some sanity-checking...
530 0 0       0 Carp::croak("A :content_file value can't be undef")
531             unless defined $arg;
532 0 0       0 Carp::croak("A :content_file value can't be a reference")
533             if ref $arg;
534 0 0       0 Carp::croak("A :content_file value can't be \"\"")
535             unless length $arg;
536              
537             }
538             elsif ($args->[$i] eq ':read_size_hint') {
539 0         0 $size = $args->[$i + 1];
540             # Bother checking it?
541              
542             }
543             else {
544 19         41 next;
545             }
546 0         0 splice @$args, $i, 2;
547 0         0 $i -= 2;
548             }
549              
550             # And return a suitable suffix-list for request(REQ,...)
551              
552 27 50       96 return unless defined $arg;
553 0 0       0 return $arg, $size if defined $size;
554 0         0 return $arg;
555             }
556              
557              
558             sub is_online {
559 0     0 1 0 my $self = shift;
560 0 0       0 return 1 if $self->get("http://www.msftncsi.com/ncsi.txt")->content eq "Microsoft NCSI";
561 0 0       0 return 1 if $self->get("http://www.apple.com")->content =~ m,Apple,;
562 0         0 return 0;
563             }
564              
565              
566             my @ANI = qw(- \ | /);
567              
568             sub progress {
569 186     186 1 345 my($self, $status, $m) = @_;
570 186 50       519 return unless $self->{show_progress};
571              
572 0         0 local($,, $\);
573 0 0       0 if ($status eq "begin") {
    0          
    0          
574 0         0 print STDERR "** ", $m->method, " ", $m->uri, " ==> ";
575 0         0 $self->{progress_start} = time;
576 0         0 $self->{progress_lastp} = "";
577 0         0 $self->{progress_ani} = 0;
578             }
579             elsif ($status eq "end") {
580 0         0 delete $self->{progress_lastp};
581 0         0 delete $self->{progress_ani};
582 0         0 print STDERR $m->status_line;
583 0         0 my $t = time - delete $self->{progress_start};
584 0 0       0 print STDERR " (${t}s)" if $t;
585 0         0 print STDERR "\n";
586             }
587             elsif ($status eq "tick") {
588 0         0 print STDERR "$ANI[$self->{progress_ani}++]\b";
589 0         0 $self->{progress_ani} %= @ANI;
590             }
591             else {
592 0         0 my $p = sprintf "%3.0f%%", $status * 100;
593 0 0       0 return if $p eq $self->{progress_lastp};
594 0         0 print STDERR "$p\b\b\b\b";
595 0         0 $self->{progress_lastp} = $p;
596             }
597 0         0 STDERR->flush;
598             }
599              
600              
601             #
602             # This whole allow/forbid thing is based on man 1 at's way of doing things.
603             #
604             sub is_protocol_supported
605             {
606 1     1 1 598 my($self, $scheme) = @_;
607 1 50       4 if (ref $scheme) {
608             # assume we got a reference to an URI object
609 0         0 $scheme = $scheme->scheme;
610             }
611             else {
612 1 50       5 Carp::croak("Illegal scheme '$scheme' passed to is_protocol_supported")
613             if $scheme =~ /\W/;
614 1         2 $scheme = lc $scheme;
615             }
616              
617 1         2 my $x;
618 1 50 33     5 if(ref($self) and $x = $self->protocols_allowed) {
    50 33        
619 0 0       0 return 0 unless grep lc($_) eq $scheme, @$x;
620             }
621             elsif (ref($self) and $x = $self->protocols_forbidden) {
622 1 50       7 return 0 if grep lc($_) eq $scheme, @$x;
623             }
624              
625 0         0 local($SIG{__DIE__}); # protect against user defined die handlers
626 0         0 $x = LWP::Protocol::implementor($scheme);
627 0 0 0     0 return 1 if $x and $x ne 'LWP::Protocol::nogo';
628 0         0 return 0;
629             }
630              
631              
632 72     72 1 269 sub protocols_allowed { shift->_elem('protocols_allowed' , @_) }
633 76     76 1 189 sub protocols_forbidden { shift->_elem('protocols_forbidden' , @_) }
634 6     6 1 20 sub requests_redirectable { shift->_elem('requests_redirectable', @_) }
635              
636              
637             sub redirect_ok
638             {
639             # RFC 2616, section 10.3.2 and 10.3.3 say:
640             # If the 30[12] status code is received in response to a request other
641             # than GET or HEAD, the user agent MUST NOT automatically redirect the
642             # request unless it can be confirmed by the user, since this might
643             # change the conditions under which the request was issued.
644              
645             # Note that this routine used to be just:
646             # return 0 if $_[1]->method eq "POST"; return 1;
647              
648 6     6 1 15 my($self, $new_request, $response) = @_;
649 6         21 my $method = $response->request->method;
650             return 0 unless grep $_ eq $method,
651 6 50       128 @{ $self->requests_redirectable || [] };
  6 50       15  
652              
653 6 50       20 if ($new_request->uri->scheme eq 'file') {
654 0         0 $response->header("Client-Warning" =>
655             "Can't redirect to a file:// URL!");
656 0         0 return 0;
657             }
658              
659             # Otherwise it's apparently okay...
660 6         167 return 1;
661             }
662              
663             sub credentials {
664 56     56 1 4773 my $self = shift;
665 56   100     156 my $netloc = lc(shift || '');
666 56   100     112 my $realm = shift || "";
667 56         115 my $old = $self->{basic_authentication}{$netloc}{$realm};
668 56 100       113 if (@_) {
669 13         41 $self->{basic_authentication}{$netloc}{$realm} = [@_];
670             }
671 56 100       137 return unless $old;
672 29 100       80 return @$old if wantarray;
673 14         62 return join(":", @$old);
674             }
675              
676             sub get_basic_credentials
677             {
678 4     4 1 10 my($self, $realm, $uri, $proxy) = @_;
679 4 50       10 return if $proxy;
680 4         15 return $self->credentials($uri->host_port, $realm);
681             }
682              
683              
684 4     4 1 31 sub timeout { shift->_elem('timeout', @_); }
685 0     0 1 0 sub local_address{ shift->_elem('local_address',@_); }
686 2     2 1 1220 sub max_size { shift->_elem('max_size', @_); }
687 6     6 1 6498 sub max_redirect { shift->_elem('max_redirect', @_); }
688 0     0 1 0 sub show_progress{ shift->_elem('show_progress', @_); }
689              
690             sub ssl_opts {
691 17     17 1 876 my $self = shift;
692 17 100       39 if (@_ == 1) {
693 13         17 my $k = shift;
694 13         57 return $self->{ssl_opts}{$k};
695             }
696 4 100       8 if (@_) {
697 2         3 my $old;
698 2         4 while (@_) {
699 2         5 my($k, $v) = splice(@_, 0, 2);
700 2 50       6 $old = $self->{ssl_opts}{$k} unless @_;
701 2 100       6 if (defined $v) {
702 1         3 $self->{ssl_opts}{$k} = $v;
703             }
704             else {
705 1         4 delete $self->{ssl_opts}{$k};
706             }
707             }
708 2         2 %{$self->{ssl_opts}} = (%{$self->{ssl_opts}}, @_);
  2         4  
  2         6  
709 2         8 return $old;
710             }
711              
712 2         3 return keys %{$self->{ssl_opts}};
  2         12  
713             }
714              
715             sub parse_head {
716 38     38 1 66 my $self = shift;
717 38 100       110 if (@_) {
718 37         64 my $flag = shift;
719 37         52 my $parser;
720             my $old = $self->set_my_handler("response_header", $flag ? sub {
721 8     8   18 my($response, $ua) = @_;
722 8         1554 require HTML::HeadParser;
723 8         14177 $parser = HTML::HeadParser->new;
724 8 50       905 $parser->xml_mode(1) if $response->content_is_xhtml;
725 8 50 33     407 $parser->utf8_mode(1) if $] >= 5.008 && $HTML::Parser::VERSION >= 3.40;
726              
727 8         99 push(@{$response->{handlers}{response_data}}, {
728             callback => sub {
729 8 50       25 return unless $parser;
730 8 50       114 unless ($parser->parse($_[3])) {
731 8         1524 my $h = $parser->header;
732 8         56 my $r = $_[0];
733 8         32 for my $f ($h->header_field_names) {
734 11         498 $r->init_header($f, [$h->header($f)]);
735             }
736 8         850 undef($parser);
737             }
738             },
739 8         15 });
740              
741             } : undef,
742 37 100       336 m_media_type => "html",
743             );
744 37         464 return !!$old;
745             }
746             else {
747 1         4 return !!$self->get_my_handler("response_header");
748             }
749             }
750              
751             sub cookie_jar {
752 1     1 1 2 my $self = shift;
753 1         2 my $old = $self->{cookie_jar};
754 1 50       3 if (@_) {
755 1         2 my $jar = shift;
756 1 50       3 if (ref($jar) eq "HASH") {
757 0         0 require HTTP::Cookies;
758 0         0 $jar = HTTP::Cookies->new(%$jar);
759             }
760 1         2 $self->{cookie_jar} = $jar;
761             $self->set_my_handler("request_prepare",
762 0     0   0 $jar ? sub { $jar->add_cookie_header($_[0]); } : undef,
763 1 50       3 );
764             $self->set_my_handler("response_done",
765 0     0   0 $jar ? sub { $jar->extract_cookies($_[0]); } : undef,
766 1 50       3 );
767             }
768 1         1 $old;
769             }
770              
771             sub default_headers {
772 60     60 1 84 my $self = shift;
773 60   66     406 my $old = $self->{def_headers} ||= HTTP::Headers->new;
774 60 50       428 if (@_) {
775 0 0 0     0 Carp::croak("default_headers not set to HTTP::Headers compatible object")
776             unless @_ == 1 && $_[0]->can("header_field_names");
777 0         0 $self->{def_headers} = shift;
778             }
779 60         174 return $old;
780             }
781              
782             sub default_header {
783 58     58 1 616 my $self = shift;
784 58         133 return $self->default_headers->header(@_);
785             }
786              
787 32     32   141 sub _agent { "libwww-perl/$VERSION" }
788              
789             sub agent {
790 39     39 1 123 my $self = shift;
791 39 100       99 if (@_) {
792 37         61 my $agent = shift;
793 37 50       81 if ($agent) {
794 37 100       146 $agent .= $self->_agent if $agent =~ /\s+$/;
795             }
796             else {
797 0         0 undef($agent)
798             }
799 37         129 return $self->default_header("User-Agent", $agent);
800             }
801 2         5 return $self->default_header("User-Agent");
802             }
803              
804             sub from { # legacy
805 3     3 1 44 my $self = shift;
806 3         9 return $self->default_header("From", @_);
807             }
808              
809              
810             sub conn_cache {
811 1     1 1 2 my $self = shift;
812 1         2 my $old = $self->{conn_cache};
813 1 50       3 if (@_) {
814 1         1 my $cache = shift;
815 1 50       4 if (ref($cache) eq "HASH") {
816 1         317 require LWP::ConnCache;
817 1         8 $cache = LWP::ConnCache->new(%$cache);
818             }
819 1         3 $self->{conn_cache} = $cache;
820             }
821 1         2 $old;
822             }
823              
824              
825             sub add_handler {
826 48     48 1 149 my($self, $phase, $cb, %spec) = @_;
827 48   33     110 $spec{line} ||= join(":", (caller)[1,2]);
828 48   33     158 my $conf = $self->{handlers}{$phase} ||= do {
829 48         4439 require HTTP::Config;
830 48         24494 HTTP::Config->new;
831             };
832 48         475 $conf->add(%spec, callback => $cb);
833             }
834              
835             sub set_my_handler {
836 56     56 1 183 my($self, $phase, $cb, %spec) = @_;
837 56 50       354 $spec{owner} = (caller(1))[3] unless exists $spec{owner};
838 56         273 $self->remove_handler($phase, %spec);
839 56   33     436 $spec{line} ||= join(":", (caller)[1,2]);
840 56 100       256 $self->add_handler($phase, $cb, %spec) if $cb;
841             }
842              
843             sub get_my_handler {
844 9     9 1 18 my $self = shift;
845 9         15 my $phase = shift;
846 9 100       25 my $init = pop if @_ % 2;
847 9         34 my %spec = @_;
848 9         25 my $conf = $self->{handlers}{$phase};
849 9 100       26 unless ($conf) {
850 4 50       14 return unless $init;
851 4         44 require HTTP::Config;
852 4         25 $conf = $self->{handlers}{$phase} = HTTP::Config->new;
853             }
854 9 50       96 $spec{owner} = (caller(1))[3] unless exists $spec{owner};
855 9         55 my @h = $conf->find(%spec);
856 9 100 66     282 if (!@h && $init) {
857 6 50       21 if (ref($init) eq "CODE") {
    0          
858 6         19 $init->(\%spec);
859             }
860             elsif (ref($init) eq "HASH") {
861 0         0 while (my($k, $v) = each %$init) {
862 0         0 $spec{$k} = $v;
863             }
864             }
865 6   50 0   21 $spec{callback} ||= sub {};
866 6   33     50 $spec{line} ||= join(":", (caller)[1,2]);
867 6         28 $conf->add(\%spec);
868 6         58 return \%spec;
869             }
870 3 50       16 return wantarray ? @h : $h[0];
871             }
872              
873             sub remove_handler {
874 56     56 1 200 my($self, $phase, %spec) = @_;
875 56 50       153 if ($phase) {
876 56   100     236 my $conf = $self->{handlers}{$phase} || return;
877 11         39 my @h = $conf->remove(%spec);
878 11 100       336 delete $self->{handlers}{$phase} if $conf->empty;
879 11         109 return @h;
880             }
881              
882 0 0       0 return unless $self->{handlers};
883 0         0 return map $self->remove_handler($_), sort keys %{$self->{handlers}};
  0         0  
884             }
885              
886             sub handlers {
887 460     460 1 786 my($self, $phase, $o) = @_;
888 460         605 my @h;
889 460 100 100     1044 if ($o->{handlers} && $o->{handlers}{$phase}) {
890 47         78 push(@h, @{$o->{handlers}{$phase}});
  47         98  
891             }
892 460 100       1133 if (my $conf = $self->{handlers}{$phase}) {
893 92         303 push(@h, $conf->matching($o));
894             }
895 460         19828 return @h;
896             }
897              
898             sub run_handlers {
899 414     414 0 903 my($self, $phase, $o) = @_;
900 414 100       869 if (defined(wantarray)) {
901 141         269 for my $h ($self->handlers($phase, $o)) {
902 0         0 my $ret = $h->{callback}->($o, $self, $h);
903 0 0       0 return $ret if $ret;
904             }
905 141         341 return undef;
906             }
907              
908 273         605 for my $h ($self->handlers($phase, $o)) {
909 52         161 $h->{callback}->($o, $self, $h);
910             }
911             }
912              
913              
914             # deprecated
915 0     0 0 0 sub use_eval { shift->_elem('use_eval', @_); }
916             sub use_alarm
917             {
918 0 0 0 0 0 0 Carp::carp("LWP::UserAgent->use_alarm(BOOL) is a no-op")
919             if @_ > 1 && $^W;
920 0         0 "";
921             }
922              
923              
924             sub clone
925             {
926 1     1 1 4 my $self = shift;
927 1         7 my $copy = bless { %$self }, ref $self; # copy most fields
928              
929 1         2 delete $copy->{handlers};
930 1         2 delete $copy->{conn_cache};
931              
932             # copy any plain arrays and hashes; known not to need recursive copy
933 1         3 for my $k (qw(proxy no_proxy requests_redirectable ssl_opts)) {
934 4 50       9 next unless $copy->{$k};
935 4 100       10 if (ref($copy->{$k}) eq "ARRAY") {
    50          
936 2         2 $copy->{$k} = [ @{$copy->{$k}} ];
  2         4  
937             }
938             elsif (ref($copy->{$k}) eq "HASH") {
939 2         3 $copy->{$k} = { %{$copy->{$k}} };
  2         5  
940             }
941             }
942              
943 1 50       2 if ($self->{def_headers}) {
944 1         69 $copy->{def_headers} = $self->{def_headers}->clone;
945             }
946              
947             # re-enable standard handlers
948 1         4 $copy->parse_head($self->parse_head);
949              
950             # no easy way to clone the cookie jar; so let's just remove it for now
951 1         3 $copy->cookie_jar(undef);
952              
953 1         2 $copy;
954             }
955              
956              
957             sub mirror
958             {
959 0     0 1 0 my($self, $url, $file) = @_;
960              
961 0         0 my $request = HTTP::Request->new('GET', $url);
962              
963             # If the file exists, add a cache-related header
964 0 0       0 if ( -e $file ) {
965 0         0 my ($mtime) = ( stat($file) )[9];
966 0 0       0 if ($mtime) {
967 0         0 $request->header( 'If-Modified-Since' => HTTP::Date::time2str($mtime) );
968             }
969             }
970 0         0 my $tmpfile = "$file-$$";
971              
972 0         0 my $response = $self->request($request, $tmpfile);
973 0 0       0 if ( $response->header('X-Died') ) {
974 0         0 die $response->header('X-Died');
975             }
976              
977             # Only fetching a fresh copy of the would be considered success.
978             # If the file was not modified, "304" would returned, which
979             # is considered by HTTP::Status to be a "redirect", /not/ "success"
980 0 0       0 if ( $response->is_success ) {
981 0 0       0 my @stat = stat($tmpfile) or die "Could not stat tmpfile '$tmpfile': $!";
982 0         0 my $file_length = $stat[7];
983 0         0 my ($content_length) = $response->header('Content-length');
984              
985 0 0 0     0 if ( defined $content_length and $file_length < $content_length ) {
    0 0        
986 0         0 unlink($tmpfile);
987 0         0 die "Transfer truncated: " . "only $file_length out of $content_length bytes received\n";
988             }
989             elsif ( defined $content_length and $file_length > $content_length ) {
990 0         0 unlink($tmpfile);
991 0         0 die "Content-length mismatch: " . "expected $content_length bytes, got $file_length\n";
992             }
993             # The file was the expected length.
994             else {
995             # Replace the stale file with a fresh copy
996 0 0       0 if ( -e $file ) {
997             # Some DOSish systems fail to rename if the target exists
998 0         0 chmod 0777, $file;
999 0         0 unlink $file;
1000             }
1001 0 0       0 rename( $tmpfile, $file )
1002             or die "Cannot rename '$tmpfile' to '$file': $!\n";
1003              
1004             # make sure the file has the same last modification time
1005 0 0       0 if ( my $lm = $response->last_modified ) {
1006 0         0 utime $lm, $lm, $file;
1007             }
1008             }
1009             }
1010             # The local copy is fresh enough, so just delete the temp file
1011             else {
1012 0         0 unlink($tmpfile);
1013             }
1014 0         0 return $response;
1015             }
1016              
1017              
1018             sub _need_proxy {
1019 23     23   47 my($req, $ua) = @_;
1020 23 50       60 return if exists $req->{proxy};
1021 23   100     67 my $proxy = $ua->{proxy}{$req->uri->scheme} || return;
1022 16 50       336 if ($ua->{no_proxy}) {
1023 16 50       25 if (my $host = eval { $req->uri->host }) {
  16         38  
1024 16         445 for my $domain (@{$ua->{no_proxy}}) {
  16         41  
1025 0 0       0 if ($host =~ /\Q$domain\E$/) {
1026 0         0 return;
1027             }
1028             }
1029             }
1030             }
1031 16         47 $req->{proxy} = $HTTP::URI_CLASS->new($proxy);
1032             }
1033              
1034              
1035             sub proxy {
1036 28     28 1 4826 my $self = shift;
1037 28         44 my $key = shift;
1038 28 100 100     85 if (!@_ && ref $key eq 'ARRAY') {
1039 1 50       1 die 'odd number of items in proxy arrayref!' unless @{$key} % 2 == 0;
  1         5  
1040              
1041             # This map reads the elements of $key 2 at a time
1042             return
1043 2         9 map { $self->proxy($key->[2 * $_], $key->[2 * $_ + 1]) }
1044 1         2 (0 .. @{$key} / 2 - 1);
  1         6  
1045             }
1046 27 100       55 return map { $self->proxy($_, @_) } @$key if ref $key;
  5         9  
1047              
1048 25 50       271 Carp::croak("'$key' is not a valid URI scheme") unless $key =~ /^$URI::scheme_re\z/;
1049 25         61 my $old = $self->{'proxy'}{$key};
1050 25 100       47 if (@_) {
1051 15         22 my $url = shift;
1052 15 100 66     68 if (defined($url) && length($url)) {
1053 14 50       153 Carp::croak("Proxy must be specified as absolute URI; '$url' is not") unless $url =~ /^$URI::scheme_re:/;
1054 14 50 66     101 Carp::croak("Bad http proxy specification '$url'") if $url =~ /^https?:/ && $url !~ m,^https?://\w,;
1055             }
1056 15         49 $self->{proxy}{$key} = $url;
1057 15         59 $self->set_my_handler("request_preprepare", \&_need_proxy)
1058             }
1059 25         222 return $old;
1060             }
1061              
1062              
1063             sub env_proxy {
1064 6     6 1 165 my ($self) = @_;
1065 6         1368 require Encode;
1066 6         30337 require Encode::Locale;
1067 6         9496 my($k,$v);
1068 6         30 while(($k, $v) = each %ENV) {
1069 205 50       302 if ($ENV{REQUEST_METHOD}) {
1070             # Need to be careful when called in the CGI environment, as
1071             # the HTTP_PROXY variable is under control of that other guy.
1072 0 0       0 next if $k =~ /^HTTP_/;
1073 0 0       0 $k = "HTTP_PROXY" if $k eq "CGI_HTTP_PROXY";
1074             }
1075 205         259 $k = lc($k);
1076 205 100       516 next unless $k =~ /^(.*)_proxy$/;
1077 5         13 $k = $1;
1078 5 50       14 if ($k eq 'no') {
1079 0         0 $self->no_proxy(split(/\s*,\s*/, $v));
1080             }
1081             else {
1082             # Ignore random _proxy variables, allow only valid schemes
1083 5 100       68 next unless $k =~ /^$URI::scheme_re\z/;
1084             # Ignore xxx_proxy variables if xxx isn't a supported protocol
1085 3 100       17 next unless LWP::Protocol::implementor($k);
1086 2         8 $self->proxy($k, Encode::decode(locale => $v));
1087             }
1088             }
1089             }
1090              
1091              
1092             sub no_proxy {
1093 0     0 1 0 my($self, @no) = @_;
1094 0 0       0 if (@no) {
1095 0         0 push(@{ $self->{'no_proxy'} }, @no);
  0         0  
1096             }
1097             else {
1098 0         0 $self->{'no_proxy'} = [];
1099             }
1100             }
1101              
1102              
1103             sub _new_response {
1104 4     4   15 my($request, $code, $message, $content) = @_;
1105 4   33     11 $message ||= HTTP::Status::status_message($code);
1106 4         36 my $response = HTTP::Response->new($code, $message);
1107 4         224 $response->request($request);
1108 4         44 $response->header("Client-Date" => HTTP::Date::time2str(time));
1109 4         480 $response->header("Client-Warning" => "Internal response");
1110 4         246 $response->header("Content-Type" => "text/plain");
1111 4   66     200 $response->content($content || "$code $message\n");
1112 4         98 return $response;
1113             }
1114              
1115              
1116             1;
1117              
1118             __END__