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.53';
3 2     2   130718 use strict;
  2         3  
  2         48  
4 2     2   6 use warnings;
  2         3  
  2         49  
5              
6 2     2   414 use parent 'Perl::Critic::Policy';
  2         280  
  2         8  
7              
8 2     2   149022 use Perl::Critic::Utils qw( :classification :severities );
  2         4  
  2         87  
9 2     2   459 use Readonly ();
  2         2  
  2         27  
10 2     2   6 use Scalar::Util 'blessed';
  2         3  
  2         782  
11              
12             Readonly::Scalar my $DESC => 'Use of HTTP::Cookies';
13             Readonly::Scalar my $EXPL => 'HTTP::Cookies does not respect Public Suffix';
14              
15       27 0   sub supported_parameters {}
16 15     15 1 79 sub default_severity { $SEVERITY_MEDIUM }
17 0     0 1 0 sub default_themes { qw( http lwp ) }
18             # TODO: Review "applies_to"
19 27     27 1 73790 sub applies_to { 'PPI::Token::Word' }
20              
21             sub violates {
22 80     80 1 2344 my ($self, $elem) = @_;
23              
24             # HTTP::Cookies->new
25 80         82 my ($is_new_cookies) = _is_constructor($elem, 'HTTP::Cookies');
26 80 100       107 if ($is_new_cookies) {
27 4         14 return $self->violation( $DESC, $EXPL, $elem );
28             }
29              
30             # LWP::UserAgent->new with default cookie jar
31             else {
32 76         72 my ( $is_new_ua, $args_elem ) = _is_constructor($elem, 'LWP::UserAgent');
33 76 100       117 if ($is_new_ua) {
34 21 100 100     77 if ( blessed $args_elem && $args_elem->isa('PPI::Structure::List') ) {
35 17         105 foreach my $expression ($args_elem->schildren) {
36             # $expression isa PPI::Statement::Expression
37 17 100       151 if ( $self->_cookie_jar_violation($expression) ) {
38 11         26 return $self->violation( $DESC, $EXPL, $elem );
39             }
40             }
41             }
42             }
43             }
44              
45 65         87 return;
46             }
47              
48             sub _cookie_jar_violation {
49 17     17   12 my ( $self, $expression ) = @_;
50              
51 17         27 foreach my $token ($expression->schildren) {
52             # TODO: Check the token's type, not just its content
53 45 100       194 if ($token =~ /cookie_jar/) {
54 17         75 my $possible_operator = $token->snext_sibling;
55 17 50 66     238 if (
      66        
56             blessed $possible_operator
57             && $possible_operator->isa('PPI::Token::Operator')
58             && $possible_operator =~ /^(?:=>|,)$/
59             ) {
60 16         88 my $possible_hashref = $possible_operator->snext_sibling;
61 16 100 66     245 if (
      66        
62             blessed $possible_hashref
63             && $possible_hashref->isa('PPI::Structure')
64             && $possible_hashref->braces eq '{}'
65             ) {
66 11         113 return 1;
67             }
68             }
69             }
70             }
71 6         24 return 0;
72             }
73              
74             sub _is_constructor {
75 156     156   111 my ($elem, $class_name) = @_;
76              
77 156         105 my $is_constructor = 0;
78 156         80 my $args_elem;
79              
80             # Detect "$class->new"
81 156 100 100     208 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 22         1838 $args_elem = $elem->snext_sibling->snext_sibling->snext_sibling;
88 22         487 $is_constructor = 1;
89             }
90             # Detect "new $class"
91             elsif (
92             $elem eq 'new'
93             && $elem->snext_sibling eq $class_name
94             ) {
95 3         98 $args_elem = $elem->snext_sibling->snext_sibling;
96 3         49 $is_constructor = 1;
97             }
98              
99 156         4006 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.53
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:
120             L<< https://github.com/libwww-perl/http-cookies/pull/7 >>
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