[dw-free] Multiple domain cookies for same domain cause infinite loop.
[commit: http://hg.dwscoalition.org/dw-free/rev/cc792aafd776]
http://bugs.dwscoalition.org/show_bug.cgi?id=2574
Fix support for multiple cookies with the same name.
Patch by
exor674.
Files modified:
http://bugs.dwscoalition.org/show_bug.cgi?id=2574
Fix support for multiple cookies with the same name.
Patch by
Files modified:
- cgi-bin/DW/Request/Base.pm
- cgi-bin/LJ/Session.pm
--------------------------------------------------------------------------------
diff -r 7e8ff7c26de6 -r cc792aafd776 cgi-bin/DW/Request/Base.pm
--- a/cgi-bin/DW/Request/Base.pm Fri Apr 30 09:21:49 2010 +0000
+++ b/cgi-bin/DW/Request/Base.pm Fri Apr 30 19:08:00 2010 +0000
@@ -19,9 +19,11 @@ use strict;
use strict;
use Carp qw/ confess cluck /;
use CGI::Cookie;
+use CGI::Util qw( unescape );
use fields (
'cookies_in',
+ 'cookies_in_multi',
);
sub new {
@@ -30,14 +32,22 @@ sub new {
unless ref $self;
$self->{cookies_in} = undef;
+ $self->{cookies_in_multi} = undef;
}
sub cookie {
my DW::Request::Base $self = $_[0];
- $self->{cookies_in} ||= { CGI::Cookie->parse( $self->header_in( 'Cookie' ) ) };
- return unless exists $self->{cookies_in}->{$_[1]};
- return $self->{cookies_in}->{$_[1]}->value;
+ $self->parse( $self->header_in( 'Cookie' ) ) unless defined $self->{cookies_in};
+ my $val = $self->{cookies_in}->{$_[1]};
+ return wantarray ? @{ $val } : $val->[0];
+}
+
+sub cookie_multi {
+ my DW::Request::Base $self = $_[0];
+
+ $self->parse( $self->header_in( 'Cookie' ) ) unless defined $self->{cookies_in_multi};
+ return @{ $self->{cookies_in_multi}->{$_[1]} || [] };
}
sub add_cookie {
@@ -66,4 +76,40 @@ sub delete_cookie {
return $self->add_cookie( %args );
}
+#
+# Following sub was copied from CGI::Cookie and modified.
+#
+# Copyright 1995-1999, Lincoln D. Stein. All rights reserved.
+# It may be used and modified freely, but I do request that this copyright
+# notice remain attached to the file. You may modify this module as you
+# wish, but if you redistribute a modified version, please attach a note
+# listing the modifications you have made.
+#
+sub parse {
+ my DW::Request::Base $self = $_[0];
+ my %results;
+ my %results_multi;
+
+ my @pairs = split( "[;,] ?", $_[1] );
+ foreach ( @pairs ) {
+ $_ =~ s/\s*(.*?)\s*/$1/;
+ my ( $key, $value ) = split( "=", $_, 2 );
+
+ # Some foreign cookies are not in name=value format, so ignore
+ # them.
+ next unless defined( $value );
+ my @values = ();
+ if ( $value ne '' ) {
+ @values = map unescape( $_ ), split( /[&;]/, $value . '&dmy' );
+ pop @values;
+ }
+ $key = unescape( $key );
+ $results{$key} ||= \@values;
+ push @{ $results_multi{$key} }, \@values;
+ }
+
+ $self->{cookies_in} = \%results;
+ $self->{cookies_in_multi} = \%results_multi;
+}
+
1;
diff -r 7e8ff7c26de6 -r cc792aafd776 cgi-bin/LJ/Session.pm
--- a/cgi-bin/LJ/Session.pm Fri Apr 30 09:21:49 2010 +0000
+++ b/cgi-bin/LJ/Session.pm Fri Apr 30 19:08:00 2010 +0000
@@ -491,14 +491,14 @@ sub session_from_cookies {
my $domain_cookie = LJ::Session->domain_cookie;
if ($domain_cookie) {
# journal domain
- $sessobj = LJ::Session->session_from_domain_cookie( \%getopts, $r->cookie( $domain_cookie ) );
+ $sessobj = LJ::Session->session_from_domain_cookie( \%getopts, $r->cookie_multi( $domain_cookie ) );
} else {
# this is the master cookie at "www.livejournal.com" or "livejournal.com";
- my @cookies = $r->cookie( 'ljmastersession' );
+ my @cookies = $r->cookie_multi( 'ljmastersession' );
# but support old clients who are just sending an "ljsession" cookie which they got
# from ljprotocol's "generatesession" mode.
- unless (@cookies) {
- @cookies = $r->cookie( 'ljsession' );
+ unless ( @cookies ) {
+ @cookies = $r->cookie_multi( 'ljsession' );
$getopts{old_cookie} = 1;
}
$sessobj = LJ::Session->session_from_master_cookie(\%getopts, @cookies);
@@ -535,7 +535,7 @@ sub session_from_domain_cookie {
my $domcook = LJ::Session->domain_cookie;
foreach my $cookie (@cookies) {
- my $sess = valid_domain_cookie($domcook, $cookie, $li_cook);
+ my $sess = valid_domain_cookie($domcook, $cookie->[0], $li_cook);
return $sess if $sess;
}
@@ -561,7 +561,7 @@ sub session_from_master_cookie {
my $ignore_ip = delete $opts->{ignore_ip} ? 1 : 0;
my $old_cookie = delete $opts->{old_cookie} ? 1 : 0;
- delete $opts->{'redirect_ref'}; # we don't use this
+ delete $opts->{redirect_ref}; # we don't use this
croak("Unknown options") if %$opts;
my $now = time();
@@ -572,8 +572,8 @@ sub session_from_master_cookie {
my $li_cook = $r->cookie( 'ljloggedin' );
COOKIE:
- foreach my $sessdata (@cookies) {
- my ($cookie, $gen) = split(m!//!, $sessdata);
+ foreach my $sessdata ( @cookies ) {
+ my ( $cookie, $gen ) = split( m!//!, $sessdata->[0] );
my ($version, $userid, $sessid, $auth, $flags);
--------------------------------------------------------------------------------
