| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Cookie::Baker; |
|
2
|
|
|
|
|
|
|
|
|
3
|
3
|
|
|
3
|
|
132743
|
use 5.008001; |
|
|
3
|
|
|
|
|
33
|
|
|
4
|
3
|
|
|
3
|
|
17
|
use strict; |
|
|
3
|
|
|
|
|
5
|
|
|
|
3
|
|
|
|
|
58
|
|
|
5
|
3
|
|
|
3
|
|
15
|
use warnings; |
|
|
3
|
|
|
|
|
5
|
|
|
|
3
|
|
|
|
|
82
|
|
|
6
|
3
|
|
|
3
|
|
17
|
use base qw/Exporter/; |
|
|
3
|
|
|
|
|
5
|
|
|
|
3
|
|
|
|
|
261
|
|
|
7
|
3
|
|
|
3
|
|
1297
|
use URI::Escape; |
|
|
3
|
|
|
|
|
4513
|
|
|
|
3
|
|
|
|
|
554
|
|
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
BEGIN { |
|
10
|
3
|
|
|
3
|
|
14
|
our $VERSION = "0.10"; |
|
11
|
3
|
|
|
|
|
7
|
our @EXPORT = qw/bake_cookie crush_cookie/; |
|
12
|
3
|
|
|
|
|
9
|
my $use_pp = $ENV{COOKIE_BAKER_PP}; |
|
13
|
3
|
50
|
|
|
|
11
|
if (!$use_pp) { |
|
14
|
3
|
|
|
|
|
4
|
eval { |
|
15
|
3
|
|
|
|
|
449
|
require Cookie::Baker::XS; |
|
16
|
0
|
0
|
|
|
|
0
|
if ( $Cookie::Baker::XS::VERSION < $VERSION ) { |
|
17
|
0
|
|
|
|
|
0
|
warn "Cookie::Baker::XS $VERSION is require. fallback to PP version"; |
|
18
|
0
|
|
|
|
|
0
|
die; |
|
19
|
|
|
|
|
|
|
} |
|
20
|
|
|
|
|
|
|
}; |
|
21
|
3
|
|
|
|
|
15
|
$use_pp = !!$@; |
|
22
|
|
|
|
|
|
|
} |
|
23
|
3
|
50
|
|
|
|
10
|
if ($use_pp) { |
|
24
|
3
|
|
|
|
|
1402
|
*crush_cookie = \&pp_crush_cookie; |
|
25
|
|
|
|
|
|
|
} |
|
26
|
|
|
|
|
|
|
else { |
|
27
|
0
|
|
|
|
|
0
|
*crush_cookie = \&Cookie::Baker::XS::crush_cookie; |
|
28
|
|
|
|
|
|
|
} |
|
29
|
|
|
|
|
|
|
} |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
sub bake_cookie { |
|
32
|
25
|
|
|
25
|
1
|
12393
|
my ($name,$val) = @_; |
|
33
|
|
|
|
|
|
|
|
|
34
|
25
|
50
|
|
|
|
63
|
return '' unless defined $val; |
|
35
|
25
|
100
|
|
|
|
66
|
my %args = ref $val ? %{$val} : (value => $val); |
|
|
24
|
|
|
|
|
99
|
|
|
36
|
25
|
50
|
|
|
|
97
|
$name = URI::Escape::uri_escape($name) if $name =~ m![^a-zA-Z\-\._~]!; |
|
37
|
25
|
|
|
|
|
81
|
my $cookie = "$name=" . URI::Escape::uri_escape($args{value}) . '; '; |
|
38
|
25
|
50
|
|
|
|
373
|
$cookie .= 'domain=' . $args{domain} . '; ' if $args{domain}; |
|
39
|
25
|
100
|
|
|
|
62
|
$cookie .= 'path='. $args{path} . '; ' if $args{path}; |
|
40
|
25
|
100
|
100
|
|
|
105
|
$cookie .= 'expires=' . _date($args{expires}) . '; ' if exists $args{expires} && defined $args{expires}; |
|
41
|
25
|
100
|
|
|
|
55
|
$cookie .= 'max-age=' . $args{"max-age"} . '; ' if exists $args{"max-age"}; |
|
42
|
25
|
100
|
100
|
|
|
70
|
if (exists $args{samesite} && $args{samesite} =~ m/^(?:lax|strict)/i) { |
|
43
|
2
|
|
|
|
|
7
|
$cookie .= 'SameSite=' . ucfirst(lc($args{samesite})) . '; ' |
|
44
|
|
|
|
|
|
|
} |
|
45
|
25
|
100
|
|
|
|
44
|
$cookie .= 'secure; ' if $args{secure}; |
|
46
|
25
|
100
|
|
|
|
39
|
$cookie .= 'HttpOnly; ' if $args{httponly}; |
|
47
|
25
|
|
|
|
|
49
|
substr($cookie,-2,2,''); |
|
48
|
25
|
|
|
|
|
86
|
$cookie; |
|
49
|
|
|
|
|
|
|
} |
|
50
|
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
my @MON = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ); |
|
52
|
|
|
|
|
|
|
my @WDAY = qw( Sun Mon Tue Wed Thu Fri Sat ); |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
my %term = ( |
|
55
|
|
|
|
|
|
|
's' => 1, |
|
56
|
|
|
|
|
|
|
'm' => 60, |
|
57
|
|
|
|
|
|
|
'h' => 3600, |
|
58
|
|
|
|
|
|
|
'd' => 86400, |
|
59
|
|
|
|
|
|
|
'M' => 86400 * 30, |
|
60
|
|
|
|
|
|
|
'y' => 86400 * 365, |
|
61
|
|
|
|
|
|
|
); |
|
62
|
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
sub _date { |
|
64
|
13
|
|
|
13
|
|
22
|
my $expires = shift; |
|
65
|
|
|
|
|
|
|
|
|
66
|
13
|
|
|
|
|
17
|
my $expires_at; |
|
67
|
13
|
100
|
|
|
|
86
|
if ($expires =~ /^\d+$/) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
# all numbers -> epoch date |
|
69
|
2
|
|
|
|
|
4
|
$expires_at = $expires; |
|
70
|
|
|
|
|
|
|
} |
|
71
|
|
|
|
|
|
|
elsif ( $expires =~ /^([-+]?(?:\d+|\d*\.\d*))([smhdMy]?)/ ) { |
|
72
|
3
|
|
|
3
|
|
25
|
no warnings; |
|
|
3
|
|
|
|
|
6
|
|
|
|
3
|
|
|
|
|
1181
|
|
|
73
|
9
|
|
100
|
|
|
47
|
my $offset = ($term{$2} || 1) * $1; |
|
74
|
9
|
|
|
|
|
25
|
$expires_at = time + $offset; |
|
75
|
|
|
|
|
|
|
} |
|
76
|
|
|
|
|
|
|
elsif ( $expires eq 'now' ) { |
|
77
|
1
|
|
|
|
|
4
|
$expires_at = time; |
|
78
|
|
|
|
|
|
|
} |
|
79
|
|
|
|
|
|
|
else { |
|
80
|
1
|
|
|
|
|
3
|
return $expires; |
|
81
|
|
|
|
|
|
|
} |
|
82
|
12
|
|
|
|
|
108
|
my($sec, $min, $hour, $mday, $mon, $year, $wday) = gmtime($expires_at); |
|
83
|
12
|
|
|
|
|
27
|
$year += 1900; |
|
84
|
|
|
|
|
|
|
# (cookies use '-' as date separator, HTTP uses ' ') |
|
85
|
12
|
|
|
|
|
82
|
return sprintf("%s, %02d-%s-%04d %02d:%02d:%02d GMT", |
|
86
|
|
|
|
|
|
|
$WDAY[$wday], $mday, $MON[$mon], $year, $hour, $min, $sec); |
|
87
|
|
|
|
|
|
|
} |
|
88
|
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
sub pp_crush_cookie { |
|
90
|
44
|
|
|
44
|
0
|
11138
|
my $cookie_string = shift; |
|
91
|
44
|
100
|
|
|
|
107
|
return {} unless $cookie_string; |
|
92
|
40
|
|
|
|
|
54
|
my %results; |
|
93
|
40
|
|
|
|
|
384
|
my @pairs = grep m/=/, split /; ?/, $cookie_string; |
|
94
|
40
|
|
|
|
|
95
|
for my $pair ( @pairs ) { |
|
95
|
|
|
|
|
|
|
# trim leading trailing whitespace |
|
96
|
114
|
|
|
|
|
249
|
$pair =~ s/^\s+//; $pair =~ s/\s+$//; |
|
|
114
|
|
|
|
|
253
|
|
|
97
|
|
|
|
|
|
|
|
|
98
|
114
|
|
|
|
|
298
|
my ($key, $value) = split( "=", $pair, 2 ); |
|
99
|
|
|
|
|
|
|
|
|
100
|
114
|
|
|
|
|
265
|
$key = URI::Escape::uri_unescape($key); |
|
101
|
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
# Values can be quoted |
|
103
|
114
|
50
|
|
|
|
885
|
$value = "" unless defined $value; |
|
104
|
114
|
|
|
|
|
188
|
$value =~ s/\A"(.*)"\z/$1/; |
|
105
|
114
|
|
|
|
|
191
|
$value = URI::Escape::uri_unescape($value); |
|
106
|
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
# Take the first one like CGI.pm or rack do |
|
108
|
114
|
100
|
|
|
|
1125
|
$results{$key} = $value unless exists $results{$key}; |
|
109
|
|
|
|
|
|
|
} |
|
110
|
40
|
|
|
|
|
149
|
return \%results; |
|
111
|
|
|
|
|
|
|
} |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
1; |
|
114
|
|
|
|
|
|
|
__END__ |