/usr/share/perl5/HTTP/Cookies/Microsoft.pm is in libhttp-cookies-perl 6.00-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 | package HTTP::Cookies::Microsoft;
use strict;
use vars qw(@ISA $VERSION);
$VERSION = "6.00";
require HTTP::Cookies;
@ISA=qw(HTTP::Cookies);
sub load_cookies_from_file
{
my ($file) = @_;
my @cookies;
my ($key, $value, $domain_path, $flags, $lo_expire, $hi_expire);
my ($lo_create, $hi_create, $sep);
open(COOKIES, $file) || return;
while ($key = <COOKIES>)
{
chomp($key);
chomp($value = <COOKIES>);
chomp($domain_path= <COOKIES>);
chomp($flags = <COOKIES>); # 0x0001 bit is for secure
chomp($lo_expire = <COOKIES>);
chomp($hi_expire = <COOKIES>);
chomp($lo_create = <COOKIES>);
chomp($hi_create = <COOKIES>);
chomp($sep = <COOKIES>);
if (!defined($key) || !defined($value) || !defined($domain_path) ||
!defined($flags) || !defined($hi_expire) || !defined($lo_expire) ||
!defined($hi_create) || !defined($lo_create) || !defined($sep) ||
($sep ne '*'))
{
last;
}
if ($domain_path =~ /^([^\/]+)(\/.*)$/)
{
my $domain = $1;
my $path = $2;
push(@cookies, {KEY => $key, VALUE => $value, DOMAIN => $domain,
PATH => $path, FLAGS =>$flags, HIXP =>$hi_expire,
LOXP => $lo_expire, HICREATE => $hi_create,
LOCREATE => $lo_create});
}
}
return \@cookies;
}
sub get_user_name
{
use Win32;
use locale;
my $user = lc(Win32::LoginName());
return $user;
}
# MSIE stores create and expire times as Win32 FILETIME,
# which is 64 bits of 100 nanosecond intervals since Jan 01 1601
#
# But Cookies code expects time in 32-bit value expressed
# in seconds since Jan 01 1970
#
sub epoch_time_offset_from_win32_filetime
{
my ($high, $low) = @_;
#--------------------------------------------------------
# USEFUL CONSTANT
#--------------------------------------------------------
# 0x019db1de 0xd53e8000 is 1970 Jan 01 00:00:00 in Win32 FILETIME
#
# 100 nanosecond intervals == 0.1 microsecond intervals
my $filetime_low32_1970 = 0xd53e8000;
my $filetime_high32_1970 = 0x019db1de;
#------------------------------------
# ALGORITHM
#------------------------------------
# To go from 100 nanosecond intervals to seconds since 00:00 Jan 01 1970:
#
# 1. Adjust 100 nanosecond intervals to Jan 01 1970 base
# 2. Divide by 10 to get to microseconds (1/millionth second)
# 3. Divide by 1000000 (10 ^ 6) to get to seconds
#
# We can combine Step 2 & 3 into one divide.
#
# After much trial and error, I came up with the following code which
# avoids using Math::BigInt or floating pt, but still gives correct answers
# If the filetime is before the epoch, return 0
if (($high < $filetime_high32_1970) ||
(($high == $filetime_high32_1970) && ($low < $filetime_low32_1970)))
{
return 0;
}
# Can't multiply by 0x100000000, (1 << 32),
# without Perl issuing an integer overflow warning
#
# So use two multiplies by 0x10000 instead of one multiply by 0x100000000
#
# The result is the same.
#
my $date1970 = (($filetime_high32_1970 * 0x10000) * 0x10000) + $filetime_low32_1970;
my $time = (($high * 0x10000) * 0x10000) + $low;
$time -= $date1970;
$time /= 10000000;
return $time;
}
sub load_cookie
{
my($self, $file) = @_;
my $now = time() - $HTTP::Cookies::EPOCH_OFFSET;
my $cookie_data;
if (-f $file)
{
# open the cookie file and get the data
$cookie_data = load_cookies_from_file($file);
foreach my $cookie (@{$cookie_data})
{
my $secure = ($cookie->{FLAGS} & 1) != 0;
my $expires = epoch_time_offset_from_win32_filetime($cookie->{HIXP}, $cookie->{LOXP});
$self->set_cookie(undef, $cookie->{KEY}, $cookie->{VALUE},
$cookie->{PATH}, $cookie->{DOMAIN}, undef,
0, $secure, $expires-$now, 0);
}
}
}
sub load
{
my($self, $cookie_index) = @_;
my $now = time() - $HTTP::Cookies::EPOCH_OFFSET;
my $cookie_dir = '';
my $delay_load = (defined($self->{'delayload'}) && $self->{'delayload'});
my $user_name = get_user_name();
my $data;
$cookie_index ||= $self->{'file'} || return;
if ($cookie_index =~ /[\\\/][^\\\/]+$/)
{
$cookie_dir = $` . "\\";
}
local(*INDEX, $_);
open(INDEX, $cookie_index) || return;
binmode(INDEX);
if (256 != read(INDEX, $data, 256))
{
warn "$cookie_index file is not large enough";
close(INDEX);
return;
}
# Cookies' index.dat file starts with 32 bytes of signature
# followed by an offset to the first record, stored as a little-endian DWORD
my ($sig, $size) = unpack('a32 V', $data);
if (($sig !~ /^Client UrlCache MMF Ver 5\.2/) || # check that sig is valid (only tested in IE6.0)
(0x4000 != $size))
{
warn "$cookie_index ['$sig' $size] does not seem to contain cookies";
close(INDEX);
return;
}
if (0 == seek(INDEX, $size, 0)) # move the file ptr to start of the first record
{
close(INDEX);
return;
}
# Cookies are usually stored in 'URL ' records in two contiguous 0x80 byte sectors (256 bytes)
# so read in two 0x80 byte sectors and adjust if not a Cookie.
while (256 == read(INDEX, $data, 256))
{
# each record starts with a 4-byte signature
# and a count (little-endian DWORD) of 0x80 byte sectors for the record
($sig, $size) = unpack('a4 V', $data);
# Cookies are found in 'URL ' records
if ('URL ' ne $sig)
{
# skip over uninteresting record: I've seen 'HASH' and 'LEAK' records
if (($sig eq 'HASH') || ($sig eq 'LEAK'))
{
# '-2' takes into account the two 0x80 byte sectors we've just read in
if (($size > 0) && ($size != 2))
{
if (0 == seek(INDEX, ($size-2)*0x80, 1))
{
# Seek failed. Something's wrong. Gonna stop.
last;
}
}
}
next;
}
#$REMOVE Need to check if URL records in Cookies' index.dat will
# ever use more than two 0x80 byte sectors
if ($size > 2)
{
my $more_data = ($size-2)*0x80;
if ($more_data != read(INDEX, $data, $more_data, 256))
{
last;
}
}
(my $user_name2 = $user_name) =~ s/ /_/g;
if ($data =~ /Cookie\:\Q$user_name\E\@([\x21-\xFF]+).*?((?:\Q$user_name\E|\Q$user_name2\E)\@[\x21-\xFF]+\.txt)/)
{
my $cookie_file = $cookie_dir . $2; # form full pathname
if (!$delay_load)
{
$self->load_cookie($cookie_file);
}
else
{
my $domain = $1;
# grab only the domain name, drop everything from the first dir sep on
if ($domain =~ m{[\\/]})
{
$domain = $`;
}
# set the delayload cookie for this domain with
# the cookie_file as cookie for later-loading info
$self->set_cookie(undef, 'cookie', $cookie_file,
'//+delayload', $domain, undef,
0, 0, $now+86400, 0);
}
}
}
close(INDEX);
1;
}
1;
__END__
=head1 NAME
HTTP::Cookies::Microsoft - access to Microsoft cookies files
=head1 SYNOPSIS
use LWP;
use HTTP::Cookies::Microsoft;
use Win32::TieRegistry(Delimiter => "/");
my $cookies_dir = $Registry->
{"CUser/Software/Microsoft/Windows/CurrentVersion/Explorer/Shell Folders/Cookies"};
$cookie_jar = HTTP::Cookies::Microsoft->new(
file => "$cookies_dir\\index.dat",
'delayload' => 1,
);
my $browser = LWP::UserAgent->new;
$browser->cookie_jar( $cookie_jar );
=head1 DESCRIPTION
This is a subclass of C<HTTP::Cookies> which
loads Microsoft Internet Explorer 5.x and 6.x for Windows (MSIE)
cookie files.
See the documentation for L<HTTP::Cookies>.
=head1 METHODS
The following methods are provided:
=over 4
=item $cookie_jar = HTTP::Cookies::Microsoft->new;
The constructor takes hash style parameters. In addition
to the regular HTTP::Cookies parameters, HTTP::Cookies::Microsoft
recognizes the following:
delayload: delay loading of cookie data until a request
is actually made. This results in faster
runtime unless you use most of the cookies
since only the domain's cookie data
is loaded on demand.
=back
=head1 CAVEATS
Please note that the code DOESN'T support saving to the MSIE
cookie file format.
=head1 AUTHOR
Johnny Lee <typo_pl@hotmail.com>
=head1 COPYRIGHT
Copyright 2002 Johnny Lee
This library is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
=cut
|