HTTP::Cookies vs. Netscape cookies, part 1: domain matching
Andreas Gustafsson (gson@araneus.fi)
Wed, 30 Sep 1998 15:18:34 +0300 (EEST)
Here's one case where HTTP::Cookies still fails to handle
Netscape-style cookies correctly.
Suppose the web server foo.bar.fi issues a cookie:
Set-Cookie: NAME=VALUE; PATH=/; DOMAIN=foo.bar.fi
Later, we contact a second web server baz.foo.bar.fi.
The above cookie should be sent to the server baz.foo.bar.fi
according to the Netscape rules, but HTTP::Cookies won't.
My analysis of the problems is as follows. In
HTTP::Cookies::extract_cookies, the test
"if (defined($domain) && $domain ne $req_host)"
becomes false, because the DOMAIN= attribute matches
the host name of the issuing host. Therefore,
no leading dot is added to the domain foo.bar.fi.
Later, in add_cookie_header, the following attempts
are made to match the host name baz.foo.bar.fi
with the domain:
baz.foo.bar.fi != foo.bar.fi
.foo.bar.fi != foo.bar.fi
.bar.fi != foo.bar.fi
These attempts all fail, thus the Cookie header is never sent.
The patch below fixes the problem for me, but it is not as clean
as I would like.
*** Cookies.pm.orig Fri Apr 10 15:26:13 1998
--- Cookies.pm Tue Sep 29 09:45:42 1998
***************
*** 108,113 ****
--- 108,114 ----
my @cval; # cookie values for the "Cookie" header
my $set_ver;
+ my $netscape_only = 0; # An exact domain match applies to any cookie
while (($domain =~ tr/././) >= 2 || # must be at least 2 dots
$domain =~ /\.local$/)
***************
*** 156,161 ****
--- 157,167 ----
next;
}
}
+ if ($version > 0 && $netscape_only) {
+ LWP::Debug::debug(" domain $domain applies to " .
+ "Netscape-style cookies only");
+ }
+
LWP::Debug::debug(" it's a match");
# set version number of cookie header.
***************
*** 191,198 ****
}
} continue {
! # Try with a more general domain: www.sol.no ==> .sol.no
! $domain =~ s/^\.?[^.]*//;
}
$request->header(Cookie => join("; ", @cval)) if @cval;
--- 197,218 ----
}
} continue {
! # Try with a more general domain, alternately stripping
! # leading name components and leading dots. When this
! # results in a domain with no leading dot, it is for
! # Netscape cookie compatibility only:
! #
! # a.b.c.net Any cookie
! # .b.c.net Any cookie
! # b.c.net Netscape cookie only
! # .c.net Any cookie
!
! if ($domain =~ s/^\.+//) {
! $netscape_only = 1;
! } else {
! $domain =~ s/[^.]*//;
! $netscape_only = 0;
! }
}
$request->header(Cookie => join("; ", @cval)) if @cval;
--
Andreas Gustafsson, gson@araneus.fi