| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Mojo::UserAgent::CookieJar::ChromeMacOS; |
|
2
|
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
12384
|
use strict; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
23
|
|
|
4
|
1
|
|
|
1
|
|
3
|
use warnings; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
17
|
|
|
5
|
1
|
|
|
1
|
|
9
|
use v5.10; |
|
|
1
|
|
|
|
|
2
|
|
|
6
|
|
|
|
|
|
|
our $VERSION = '0.01'; |
|
7
|
|
|
|
|
|
|
|
|
8
|
1
|
|
|
1
|
|
386
|
use Mojo::Base 'Mojo::UserAgent::CookieJar'; |
|
|
1
|
|
|
|
|
6429
|
|
|
|
1
|
|
|
|
|
4
|
|
|
9
|
|
|
|
|
|
|
|
|
10
|
1
|
|
|
1
|
|
37884
|
use Mojo::Cookie::Request; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
4
|
|
|
11
|
1
|
|
|
1
|
|
1314
|
use DBI; |
|
|
1
|
|
|
|
|
10878
|
|
|
|
1
|
|
|
|
|
51
|
|
|
12
|
1
|
|
|
1
|
|
417
|
use PBKDF2::Tiny qw/derive/; |
|
|
1
|
|
|
|
|
764
|
|
|
|
1
|
|
|
|
|
45
|
|
|
13
|
1
|
|
|
1
|
|
508
|
use Crypt::CBC; |
|
|
1
|
|
|
|
|
2776
|
|
|
|
1
|
|
|
|
|
519
|
|
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
# default Chrome cookie file for MacOSx |
|
16
|
|
|
|
|
|
|
has 'file' => sub { |
|
17
|
|
|
|
|
|
|
return $ENV{HOME} . "/Library/Application Support/Google/Chrome/Default/Cookies"; |
|
18
|
|
|
|
|
|
|
}; |
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
# readonly |
|
21
|
|
|
|
0
|
1
|
|
sub add {} |
|
22
|
|
|
|
0
|
1
|
|
sub collect {} |
|
23
|
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
sub find { |
|
25
|
0
|
|
|
0
|
1
|
|
my ($self, $url) = @_; |
|
26
|
|
|
|
|
|
|
|
|
27
|
0
|
0
|
|
|
|
|
return [] unless my $domain = my $host = $url->ihost; |
|
28
|
|
|
|
|
|
|
|
|
29
|
0
|
|
|
|
|
|
my $salt = 'saltysalt'; |
|
30
|
0
|
|
|
|
|
|
my $iv = ' ' x 16; |
|
31
|
0
|
|
|
|
|
|
my $salt_len = 16; |
|
32
|
0
|
|
|
|
|
|
my $pass = __get_pass(); |
|
33
|
0
|
|
|
|
|
|
my $iterations = 1003; |
|
34
|
0
|
|
|
|
|
|
my $key = derive( 'SHA-1', $pass, $salt, $iterations, $salt_len ); |
|
35
|
0
|
|
|
|
|
|
my $cipher = Crypt::CBC->new( |
|
36
|
|
|
|
|
|
|
-cipher => 'Crypt::OpenSSL::AES', |
|
37
|
|
|
|
|
|
|
-key => $key, |
|
38
|
|
|
|
|
|
|
-keysize => 16, |
|
39
|
|
|
|
|
|
|
-iv => $iv, |
|
40
|
|
|
|
|
|
|
-header => 'none', |
|
41
|
|
|
|
|
|
|
-literal_key => 1, |
|
42
|
|
|
|
|
|
|
); |
|
43
|
|
|
|
|
|
|
|
|
44
|
0
|
|
|
|
|
|
my @found; |
|
45
|
0
|
|
|
|
|
|
my $dbh = $self->__get_dbh; |
|
46
|
|
|
|
|
|
|
|
|
47
|
0
|
|
|
|
|
|
my $path = $url->path->to_abs_string; |
|
48
|
0
|
|
|
|
|
|
while ($domain) { |
|
49
|
0
|
0
|
|
|
|
|
next if $domain eq 'com'; # skip bad |
|
50
|
0
|
|
|
|
|
|
my $new = $self->{jar}{$domain} = []; |
|
51
|
|
|
|
|
|
|
|
|
52
|
0
|
|
|
|
|
|
my $sth = $dbh->prepare('SELECT * FROM cookies WHERE host_key = ? OR host_key = ?'); |
|
53
|
0
|
|
|
|
|
|
$sth->execute($domain, '.' . $domain); |
|
54
|
0
|
|
|
|
|
|
while (my $row = $sth->fetchrow_hashref) { |
|
55
|
0
|
|
0
|
|
|
|
my $value = $row->{value} || $row->{encrypted_value} || ''; |
|
56
|
0
|
0
|
|
|
|
|
if ( $value =~ /^v10/ ) { |
|
57
|
0
|
|
|
|
|
|
$value =~ s/^v10//; |
|
58
|
0
|
|
|
|
|
|
$value = $cipher->decrypt( $value ); |
|
59
|
|
|
|
|
|
|
} |
|
60
|
|
|
|
|
|
|
|
|
61
|
0
|
|
|
|
|
|
my $cookie = Mojo::Cookie::Request->new(name => $row->{name}, value => $value); |
|
62
|
0
|
|
|
|
|
|
push @$new, $cookie; |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
# Taste cookie (no care about expires since Chrome will handle it) |
|
65
|
0
|
0
|
0
|
|
|
|
next if $row->{secure} && $url->protocol ne 'https'; |
|
66
|
0
|
0
|
|
|
|
|
next unless _path($row->{path}, $path); |
|
67
|
|
|
|
|
|
|
|
|
68
|
0
|
|
|
|
|
|
push @found, $cookie; |
|
69
|
|
|
|
|
|
|
} |
|
70
|
|
|
|
|
|
|
} |
|
71
|
|
|
|
|
|
|
# Remove another part |
|
72
|
0
|
|
|
|
|
|
continue { $domain =~ s/^[^.]*\.*// } |
|
73
|
|
|
|
|
|
|
|
|
74
|
0
|
|
|
|
|
|
return \@found; |
|
75
|
|
|
|
|
|
|
} |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
sub prepare { |
|
78
|
0
|
|
|
0
|
1
|
|
my ($self, $tx) = @_; |
|
79
|
0
|
|
|
|
|
|
my $req = $tx->req; |
|
80
|
0
|
|
|
|
|
|
$req->cookies(@{$self->find($req->url)}); |
|
|
0
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
} |
|
82
|
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
sub __get_dbh { |
|
84
|
0
|
|
|
0
|
|
|
my ($self) = @_; |
|
85
|
|
|
|
|
|
|
|
|
86
|
0
|
|
|
|
|
|
state $dbh; |
|
87
|
0
|
0
|
0
|
|
|
|
return $dbh if $dbh && $dbh->ping; |
|
88
|
0
|
|
|
|
|
|
$dbh = DBI->connect( "dbi:SQLite:dbname=" . $self->file, '', '', { |
|
89
|
|
|
|
|
|
|
sqlite_see_if_its_a_number => 1, |
|
90
|
|
|
|
|
|
|
} ); |
|
91
|
|
|
|
|
|
|
|
|
92
|
0
|
|
|
|
|
|
return $dbh; |
|
93
|
|
|
|
|
|
|
} |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
sub __get_pass { |
|
96
|
0
|
|
|
0
|
|
|
state $pass; |
|
97
|
0
|
0
|
|
|
|
|
return $pass if $pass; |
|
98
|
0
|
|
|
|
|
|
$pass = `security find-generic-password -w -s "Chrome Safe Storage"`; |
|
99
|
0
|
|
|
|
|
|
chomp( $pass ); |
|
100
|
0
|
|
|
|
|
|
return $pass; |
|
101
|
|
|
|
|
|
|
} |
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
# copied from Mojo::UserAgent::CookieJar |
|
104
|
0
|
0
|
0
|
0
|
|
|
sub _path { $_[0] eq '/' || $_[0] eq $_[1] || index($_[1], "$_[0]/") == 0 } |
|
105
|
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
1; |
|
107
|
|
|
|
|
|
|
__END__ |