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__ |