File Coverage

blib/lib/HTTP/Cookies/Safari.pm
Criterion Covered Total %
statement 72 73 98.6
branch 7 14 50.0
condition 7 18 38.8
subroutine 12 12 100.0
pod 2 2 100.0
total 100 119 84.0


line stmt bran cond sub pod time code
1             package HTTP::Cookies::Safari;
2 4     4   203345 use strict;
  4         12  
  4         124  
3              
4 4     4   23 use warnings;
  4         8  
  4         121  
5 4     4   20 no warnings;
  4         9  
  4         259  
6              
7             =encoding utf8
8              
9             =head1 NAME
10              
11             HTTP::Cookies::Safari - Cookie storage and management for Safari
12              
13             =head1 SYNOPSIS
14              
15             use HTTP::Cookies::Safari;
16              
17             my $cookie_jar = HTTP::Cookies::Safari->new;
18             $cookie_jar->load( '/Users/Buster/Library/Cookies/Cookies.plist' );
19              
20             # otherwise same as HTTP::Cookies
21              
22             =head1 DESCRIPTION
23              
24             This package overrides the C and C methods of
25             C so it can work with Safari cookie files.
26              
27             Note: If the source Safari cookie file specifies and expiry date past
28             the unix 32-bit epoch, this file changes the expiry date to 0xFFFFFFFF
29             in unix seconds. That should be enough for anyone, at least to the
30             next release.
31              
32             See L.
33              
34             =head1 SOURCE AVAILABILITY
35              
36             This module is in Github:
37              
38             http://github.com/briandfoy/HTTP-Cookies-Safari
39              
40             =head1 AUTHOR
41              
42             brian d foy, C<< >>
43              
44             =head1 CREDITS
45              
46             Jon Orwant pointed out the problem with dates too far in the future
47              
48             =head1 COPYRIGHT AND LICENSE
49              
50             Copyright © 2003-2017, brian d foy . All rights reserved.
51              
52             This program is free software; you can redistribute it and/or modify
53             it under the same terms as Perl itself.
54              
55             =cut
56              
57             #
58             #
59             # Domain
60             # usatoday.com
61             # Expires
62             # 2020-02-19T14:28:00Z
63             # Name
64             # v1st
65             # Path
66             # /
67             # Value
68             # 3E1B9B935912A908
69             #
70              
71 4     4   24 use base qw( HTTP::Cookies );
  4         20  
  4         1626  
72 4     4   50162 use vars qw( $VERSION );
  4         15  
  4         194  
73              
74 4     4   32 use constant TRUE => 'TRUE';
  4         10  
  4         350  
75 4     4   103 use constant FALSE => 'FALSE';
  4         15  
  4         275  
76              
77             $VERSION = '1.153';
78              
79 4     4   1396 use Date::Calc;
  4         36754  
  4         329  
80 4     4   2053 use Mac::PropertyList;
  4         121455  
  4         2529  
81              
82             sub load
83             {
84 3     3 1 393 my( $self, $file ) = @_;
85              
86 3   50     32 $file ||= $self->{'file'} || return;
      33        
87              
88 3         5 local $_;
89 3         15 local $/ = "\n"; # make sure we got standard record separator
90              
91 3 50       93 open my( $fh ), $file or return;
92              
93 3         12 my $data = do { local $/; <$fh> };
  3         11  
  3         62  
94              
95 3         21 my $plist = Mac::PropertyList::parse_plist( $data );
96              
97 3         47301 my $cookies = $plist->value;
98              
99 3         96 foreach my $hash ( @$cookies )
100             {
101 9         232 my $cookie = $hash->value;
102              
103 9         237 my @bits = map { $cookie->{$_}->value }
  45         654  
104             qw( Domain Path Name Value Expires );
105             # 0 1 2 3 4
106              
107 9         160 my $expires = $bits[4];
108              
109 9         71 my( $y, $m, $d, $h, $mn, $s ) = $expires =~
110             m/(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)Z/g;
111              
112 9   100     23 $expires = eval {
113             &Date::Calc::Mktime( $y, $m, $d, $h, $mn, $s ) } || 0xFFFFFFFF;
114              
115             # XXX: Convert Expires date to unix epoch
116              
117             #print STDERR "@bits\n";
118              
119 9         29 my $secure = FALSE;
120              
121 9         79 $self->set_cookie(undef, @bits[2,3,1,0], undef,
122             0, 0, $expires - time, 0);
123             }
124              
125 3         133 close $fh;
126              
127 3         116 1;
128             }
129              
130             sub save
131             {
132 1     1 1 866 my( $self, $file ) = @_;
133              
134 1   0     7 $file ||= $self->{'file'} || return;
      33        
135              
136 1         6 my $plist = Mac::PropertyList::array->new( [] );
137 1         83 print STDERR "plist is $plist\n";
138              
139              
140             $self->scan(
141 1         6 do {
142              
143 1         6 my $array = $plist->value;
144 1         31 my $n = 1;
145              
146             sub {
147 4     4   114 my( $version, $key, $val, $path, $domain, $port,
148             $path_spec, $secure, $expires, $discard, $rest ) = @_;
149              
150 4 50 33     12 return if $discard && not $self->{ignore_discard};
151              
152 4 50 33     32 return if defined $expires && time > $expires;
153              
154 4         10 $expires = do {
155 4 50       11 unless( $expires ) { 0 }
  0         0  
156             else
157             {
158 4         66 my @times = localtime( $expires );
159 4         12 $times[5] += 1900;
160 4         8 $times[4] += 1;
161              
162 4         32 sprintf "%4d-%02d-%02dT%02d:%02d:%02dZ",
163             @times[5,4,3,2,1,0];
164             }
165             };
166              
167 4 50       15 $secure = $secure ? TRUE : FALSE;
168              
169 4 50       20 my $bool = $domain =~ /^\./ ? TRUE : FALSE;
170              
171 4         24 my $hash = {
172             Value => Mac::PropertyList::string->new( $val ),
173             Path => Mac::PropertyList::string->new( $path ),
174             Domain => Mac::PropertyList::string->new( $domain ),
175             Name => Mac::PropertyList::string->new( $key ),
176             Expires => Mac::PropertyList::date ->new( $expires ),
177             };
178              
179 4         129 push @$array, Mac::PropertyList::dict->new( $hash );
180             }
181 1         23 } );
182              
183 1 50       145 open my $fh, "> $file" or die "Could not write file [$file]! $!\n";
184 1         10 print $fh ( Mac::PropertyList::plist_as_string( $plist ) );
185 1         1567 close $fh;
186             }
187              
188             1;