File Coverage

blib/lib/Mojo/UserAgent/CookieJar/ChromeMacOS.pm
Criterion Covered Total %
statement 23 67 34.3
branch 0 16 0.0
condition 0 11 0.0
subroutine 8 15 53.3
pod 4 4 100.0
total 35 113 30.9


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__