HTTP-Cookies-Chrome

 view release on metacpan or  search on metacpan

lib/HTTP/Cookies/Chrome.pm  view on Meta::CPAN


{
my $creation_offset = 0;

sub _insert {
	my( $self, @parts ) = @_;

	my $rest = $parts[REST];

	$rest->{httponly}           //= 0;
	$rest->{last_update_utc}    //= time() * 1000;
	$rest->{samesite}           //= -1;  # magic value for unspecified
	$rest->{source_scheme}      //= '';
	$rest->{source_type}        //= '';
	$rest->{top_frame_site_key} //= '';
	$rest->{has_cross_site_ancestor} //= 0;

	# possibly thinking about a feature to remove the encryption,
	# so we'd need to re-encrypt things. Here we assume that already
	# exists so we always re-encrypt.
	my $encrypted_value = '';

	# If we have a value and there was a previous encrypted value,
	# encrypted the current value and blank out the value. Other
	if( $parts[VALUE] and $rest->{encrypted_value} and $self->_cipher ) {
		$encrypted_value = $self->_encrypt( $parts[VALUE] );
		$parts[VALUE] = '';
		}

	# Some cookies don't have values. WTF?
	$parts[VALUE] //= '';

	my @values = (
		$rest->{creation_utc},
		$parts[DOMAIN],
		$rest->{top_frame_site_key},
		@parts[KEY, VALUE],
		$encrypted_value,
		$parts[PATH],
		$rest->{expires_utc},
		$parts[SECURE],
		@{ $rest }{ qw(is_httponly last_access_utc has_expires is_persistent priority samesite source_scheme) },
		$parts[PORT],
		@{$rest}{qw(last_update_utc source_type has_cross_site_ancestor)},
		);

	$self->{insert_sth}->execute( @values );
	}
}

sub _get_utc_microseconds {
	no warnings 'uninitialized';
	use bignum;
	POSIX::strftime( '%s', gmtime() ) * 1_000_000 + ($_[1]//0);
	}

sub _make_cipher {
	my( $self, $password ) = @_;

	my $key = do {
		state $rc2 = require PBKDF2::Tiny;
		my $s = $self->_platform_settings;
		my $salt = 'saltysalt';
		my $length = 16;
		PBKDF2::Tiny::derive( 'SHA-1', $password, $salt, $s->{iterations}, $length );
		};

	state $rc1 = require Crypt::Rijndael;
	my $cipher = Crypt::Rijndael->new( $key, Crypt::Rijndael::MODE_CBC() );
	$cipher->set_iv( ' ' x 16 );

	$self->_add_value( chrome_safe_storage_password => $password );
	$self->_add_value( cipher => $cipher );
	}

sub _platform_settings {
# https://n8henrie.com/2014/05/decrypt-chrome-cookies-with-python/
# https://github.com/n8henrie/pycookiecheat/issues/12
	state $settings = {
		darwin => {
			iterations => 1003,
			},
		linux => {
			iterations => 1,
			},
		MSWin32 => {
			},
		};

	$settings->{$^O};
	}

sub _prepare_insert {
	my( $self ) = @_;
	state $columns = [qw(
		creation_utc
		host_key
		top_frame_site_key
		name
		value
		encrypted_value
		path
		expires_utc
		is_secure
		is_httponly
		last_access_utc
		has_expires
		is_persistent
		priority
		samesite
		source_scheme
		source_port
		last_update_utc
		source_type
		has_cross_site_ancestor
		)];
	state $columns_str = join ', ', @$columns;
	state $placeholders = join ', ', ('?') x @$columns;
	my $sth = $self->{insert_sth} = $self->_dbh->prepare_cached( <<"SQL" );
INSERT INTO cookies ($columns_str) VALUES ( $placeholders )
SQL

	}

sub _stash {
	state $mod_key = 'X-CHROME';
	$_[0]->{$mod_key} //= {};
	}



( run in 1.866 second using v1.01-cache-2.11-cpan-39bf76dae61 )