File Coverage

blib/lib/Perl/Critic/Policy/HTTPCookies.pm
Criterion Covered Total %
statement 49 50 98.0
branch 17 18 94.4
condition 22 27 81.4
subroutine 12 13 92.3
pod 4 5 80.0
total 104 113 92.0


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::HTTPCookies;
2             $Perl::Critic::Policy::HTTPCookies::VERSION = '0.54';
3 2     2   198613 use strict;
  2         10  
  2         60  
4 2     2   11 use warnings;
  2         4  
  2         55  
5              
6 2     2   531 use parent 'Perl::Critic::Policy';
  2         306  
  2         13  
7              
8 2     2   220185 use Perl::Critic::Utils qw( :classification :severities );
  2         6  
  2         106  
9 2     2   647 use Readonly ();
  2         4  
  2         41  
10 2     2   10 use Scalar::Util 'blessed';
  2         5  
  2         1197  
11              
12             Readonly::Scalar my $DESC => 'Use of HTTP::Cookies';
13             Readonly::Scalar my $EXPL => 'HTTP::Cookies does not respect Public Suffix';
14              
15       33 0   sub supported_parameters {}
16 18     18 1 183 sub default_severity { $SEVERITY_MEDIUM }
17 0     0 1 0 sub default_themes { qw( http lwp ) }
18             # TODO: Review "applies_to"
19 33     33 1 219452 sub applies_to { 'PPI::Token::Word' }
20              
21             sub violates {
22 104     104 1 5223 my ($self, $elem) = @_;
23              
24             # HTTP::Cookies->new
25 104         224 my ($is_new_cookies) = _is_constructor($elem, 'HTTP::Cookies');
26 104 100       273 if ($is_new_cookies) {
27 6         26 return $self->violation( $DESC, $EXPL, $elem );
28             }
29              
30             # LWP::UserAgent->new with default cookie jar
31             else {
32 98         170 my ( $is_new_ua, $args_elem ) = _is_constructor($elem, 'LWP::UserAgent');
33 98 100       267 if ($is_new_ua) {
34 26 100 100     163 if ( blessed $args_elem && $args_elem->isa('PPI::Structure::List') ) {
35 20         189 foreach my $expression ($args_elem->schildren) {
36             # $expression isa PPI::Statement::Expression
37 20 100       248 if ( $self->_cookie_jar_violation($expression) ) {
38 12         42 return $self->violation( $DESC, $EXPL, $elem );
39             }
40             }
41             }
42             }
43             }
44              
45 86         202 return;
46             }
47              
48             sub _cookie_jar_violation {
49 20     20   39 my ( $self, $expression ) = @_;
50              
51 20         42 foreach my $token ($expression->schildren) {
52             # TODO: Check the token's type, not just its content
53 52 100       448 if ($token =~ /\bcookie_jar\b/) {
54 18         160 my $possible_operator = $token->snext_sibling;
55 18 50 66     465 if (
      66        
56             blessed $possible_operator
57             && $possible_operator->isa('PPI::Token::Operator')
58             && $possible_operator =~ /^(?:=>|,)$/
59             ) {
60 17         136 my $possible_hashref = $possible_operator->snext_sibling;
61 17 100 66     467 if (
      66        
62             blessed $possible_hashref
63             && $possible_hashref->isa('PPI::Structure')
64             && $possible_hashref->braces eq '{}'
65             ) {
66 12         177 return 1;
67             }
68             }
69             }
70             }
71 8         70 return 0;
72             }
73              
74             sub _is_constructor {
75 202     202   369 my ($elem, $class_name) = @_;
76              
77 202         294 my $is_constructor = 0;
78 202         285 my $args_elem;
79              
80             # Detect "$class->new"
81 202 100 100     458 if (
    100 66        
      100        
      100        
82             $elem eq $class_name
83             && is_class_name($elem)
84             && $elem->snext_sibling eq '->'
85             && $elem->snext_sibling->snext_sibling eq 'new'
86             ) {
87 29         4378 $args_elem = $elem->snext_sibling->snext_sibling->snext_sibling;
88 29         1483 $is_constructor = 1;
89             }
90             # Detect "new $class"
91             elsif (
92             $elem eq 'new'
93             && $elem->snext_sibling eq $class_name
94             ) {
95 3         181 $args_elem = $elem->snext_sibling->snext_sibling;
96 3         103 $is_constructor = 1;
97             }
98              
99 202         8597 return ( $is_constructor, $args_elem );
100             }
101              
102             1;
103             __END__
104              
105             =head1 NAME
106              
107             Perl::Critic::Policy::HTTPCookies - Avoid using HTTP::Cookies
108              
109             =head1 VERSION
110              
111             version 0.54
112              
113             =head1 DESCRIPTION
114              
115             This module provides L<< Perl::Critic >> policies to detect the use of
116             L<< HTTP::Cookies >>.
117              
118             HTTP::Cookies takes a very lenient approach to setting cookies that does
119             not work well with today's Internet, described in
120             L<< HTTP::Cookies/LIMITATIONS >>.
121              
122             Consider using L<< HTTP::CookieJar >> or L<< HTTP::CookieJar::LWP >>
123             instead.
124              
125             =head1 BUG REPORTS
126              
127             Please submit bug reports to L<<
128             https://rt.cpan.org/Public/Dist/Display.html?Name=Perl-Critic-Policy-HTTPCookies
129             >>.
130              
131             If you would like to send patches, please send a git pull request to L<<
132             mailto:bug-Perl-Critic-Policy-HTTPCookies@rt.cpan.org >>.
133              
134             =head1 AUTHOR
135              
136             Tom Hukins