File Coverage

blib/lib/MojoX/UserAgent/CookieJar.pm
Criterion Covered Total %
statement 53 67 79.1
branch 14 30 46.6
condition 5 26 19.2
subroutine 6 6 100.0
pod 2 2 100.0
total 80 131 61.0


line stmt bran cond sub pod time code
1             # Copyright (C) 2009, Pascal Gaudette.
2              
3             package MojoX::UserAgent::CookieJar;
4              
5 2     2   125230 use warnings;
  2         6  
  2         72  
6 2     2   10 use strict;
  2         4  
  2         78  
7              
8 2     2   11 use base 'Mojo::Base';
  2         4  
  2         1144  
9              
10 2     2   11930 use Carp 'croak';
  2         4  
  2         3424  
11              
12             __PACKAGE__->attr('size' => 0);
13              
14             __PACKAGE__->attr('_jar' => sub { {} });
15              
16             sub store {
17 1     1 1 1164 my $self = shift;
18 1 50       7 my $cookies = (ref $_[0] eq 'ARRAY') ? shift : [@_];
19              
20 1         3 for my $cookie (@{$cookies}) {
  1         3  
21              
22 3 50       63 croak('Can\'t store cookie without domain') unless $cookie->domain;
23              
24 3         116 my $domain = $cookie->domain;
25 3         74 my $store = $self->_jar->{$domain};
26              
27             # max-age wins over expires
28 3 50       74 $cookie->expires($cookie->max_age + time) if $cookie->max_age;
29              
30 3 100       121 if ($store) {
31              
32             # Do we already have this cookie?
33 1         2 my $found = 0;
34 1         2 for my $i (0 .. $#{$store}) {
  1         5  
35              
36 1         2 my $candidate = $store->[$i];
37 1 50 33     29 if ( $candidate->domain eq $cookie->domain
      33        
38             && $candidate->path eq $cookie->path
39             && $candidate->name eq $cookie->name)
40             {
41              
42 0         0 $found = 1;
43              
44             # Check for unset
45 0 0 0     0 if ((defined $cookie->max_age && $cookie->max_age == 0)
      0        
      0        
46             || (defined $cookie->expires
47             && $cookie->expires->epoch < time)
48             )
49             {
50 0         0 splice @{$store}, $i, 1;
  0         0  
51 0         0 $self->{size}--;
52             }
53             else {
54              
55             # Got a match: replace.
56             # Should this be in-place (as below), or should we
57             # delete the old one and push new one?
58 0         0 $store->[$i] = $cookie;
59             }
60              
61 0         0 last;
62             }
63             }
64              
65 1 50       50 unless ($found) {
66             # push may not be enough here, might want to order by
67             # longest path?
68 1         2 push @{$store}, $cookie;
  1         3  
69 1         4 $self->{size}++;
70             }
71             }
72             else {
73 2         43 $self->_jar->{$domain} = [$cookie];
74 2         20 $self->{size}++;
75             }
76             }
77 1         23 return $self->size;
78             }
79              
80             sub cookies_for_url {
81 1     1 1 873 my $self = shift;
82 1         3 my $url = shift;
83              
84 1 50       4 croak 'Must provide url' unless $url;
85              
86 1         3 my @cookies = ();
87 1         9 my $urlobj = Mojo::URL->new;
88              
89 1 50 33     29 ref $url && $url->isa('Mojo::URL')
90             ? $urlobj = $url
91             : $urlobj->parse($url);
92              
93 1 50       427 croak 'Url must be absolute' unless $urlobj->is_abs;
94              
95 1         56 my $domain = $urlobj->host;
96              
97 1   33     7 do {
98 2         48 my $store = $self->_jar->{$domain};
99              
100 2 100       41 if ($store) {
101              
102 1         3 my $store_size = scalar @{$store};
  1         2  
103 1         2 my @not_expired;
104              
105 1         2 while (my $candidate = shift @{$store}) {
  1         8  
106              
107             # Check for expiry while we're here
108 1 50 33     9 (defined $candidate->expires
109             && $candidate->expires->epoch < time)
110             ? next
111             : push @not_expired, $candidate;
112              
113 1         207 my $path = $candidate->path;
114              
115 1 50       9 if ($urlobj->path =~ m{^$path}) {
116 1 0       690 unless ($candidate->port) {
117 0           push @cookies, $candidate;
118             }
119             else {
120 0   0       my $port = $urlobj->port || '80';
121 0 0         push @cookies, $candidate
122             if ($candidate->port =~ m{\b$port\b});
123             }
124             }
125             }
126              
127 0           push @{$store}, @not_expired;
  0            
128 0           $self->size($self->size + scalar(@not_expired) - $store_size);
129              
130             }
131             } while ( $domain =~ s{^[\w\-]+\.(.*)}{$1}x
132             && $domain =~ m{([\w\-]+\.[\w\-]+)$}x);
133             # Note to self: check DNS spec(s) for use of extended characters
134             # in domain names... (ie [\w\-] might not cut it...)
135              
136 0           return [@cookies];
137             }
138              
139              
140             1;
141             __END__