Skip to content

Commit

Permalink
be more conservative when generating cookies
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed May 8, 2012
1 parent 73d6ce2 commit 0a325c9
Show file tree
Hide file tree
Showing 8 changed files with 39 additions and 40 deletions.
4 changes: 2 additions & 2 deletions lib/Mojo/Cookie.pm
Expand Up @@ -27,8 +27,8 @@ sub _tokenize {
last unless $string =~ s/^\s*([^=;,]+)\s*=?\s*//;
my $name = $1;

# "Expires" is a special case, thank you Netscape...
$string =~ s/^([^;,]+,?[^;,]+)/"$1"/ if $name =~ /^Expires$/i;
# "expires" is a special case, thank you Netscape...
$string =~ s/^([^;,]+,?[^;,]+)/"$1"/ if $name =~ /^expires$/i;

# Value
my $value;
Expand Down
26 changes: 13 additions & 13 deletions lib/Mojo/Cookie/Response.pm
Expand Up @@ -6,7 +6,7 @@ use Mojo::Util 'quote';

has [qw/domain httponly max_age path secure/];

my $ATTR_RE = qr/(Domain|Expires|HttpOnly|Max-Age|Path|Secure)/msi;
my $ATTR_RE = qr/(domain|expires|HttpOnly|Max-Age|path|secure)/msi;

sub expires {
my $self = shift;
Expand Down Expand Up @@ -46,7 +46,7 @@ sub parse {
elsif (my @match = $name =~ $ATTR_RE) {
my $attr = lc $match[0];
$attr =~ tr/-/_/;
$cookies[-1]->$attr($attr =~ /(?:Secure|HttpOnly)/i ? 1 : $value);
$cookies[-1]->$attr($attr =~ /(?:secure|HttpOnly)/i ? 1 : $value);
}
}
}
Expand All @@ -63,22 +63,22 @@ sub to_string {
$value = $value =~ /[,;"]/ ? quote($value) : $value;
my $cookie = "$name=$value";

# Domain
if (my $domain = $self->domain) { $cookie .= "; Domain=$domain" }
# "domain"
if (my $domain = $self->domain) { $cookie .= "; domain=$domain" }

# Path
if (my $path = $self->path) { $cookie .= "; Path=$path" }
# "path"
if (my $path = $self->path) { $cookie .= "; path=$path" }

# Max-Age
# "Max-Age"
if (defined(my $m = $self->max_age)) { $cookie .= "; Max-Age=$m" }

# Expires
if (defined(my $e = $self->expires)) { $cookie .= "; Expires=$e" }
# "expires"
if (defined(my $e = $self->expires)) { $cookie .= "; expires=$e" }

# Secure
if (my $secure = $self->secure) { $cookie .= "; Secure" }
# "secure"
if (my $secure = $self->secure) { $cookie .= "; secure" }

# HttpOnly
# "HttpOnly"
if (my $httponly = $self->httponly) { $cookie .= "; HttpOnly" }

return $cookie;
Expand Down Expand Up @@ -160,7 +160,7 @@ Expiration for cookie in seconds.
=head2 C<parse>
my $cookies = $cookie->parse('f=b; Path=/');
my $cookies = $cookie->parse('f=b; path=/');
Parse cookies.
Expand Down
4 changes: 2 additions & 2 deletions lib/Mojo/Headers.pm
Expand Up @@ -297,7 +297,7 @@ Shortcut for the C<Content-Type> header.
=head2 C<cookie>
my $cookie = $headers->cookie;
$headers = $headers->cookie('$Version=1; f=b; $Path=/');
$headers = $headers->cookie('f=b');
Shortcut for the C<Cookie> header.
Expand Down Expand Up @@ -498,7 +498,7 @@ Shortcut for the C<Server> header.
=head2 C<set_cookie>
my $set_cookie = $headers->set_cookie;
$headers = $headers->set_cookie('f=b; Version=1; Path=/');
$headers = $headers->set_cookie('f=b; path=/');
Shortcut for the C<Set-Cookie> header.
Expand Down
28 changes: 14 additions & 14 deletions t/mojo/cookie.t
Expand Up @@ -146,18 +146,18 @@ $cookie = Mojo::Cookie::Response->new;
$cookie->name('foo');
$cookie->value('ba r');
$cookie->path('/test');
is $cookie->to_string, 'foo=ba r; Path=/test', 'right format';
is $cookie->to_string, 'foo=ba r; path=/test', 'right format';

# Response cookie without value as string
$cookie = Mojo::Cookie::Response->new;
$cookie->name('foo');
$cookie->path('/test');
is $cookie->to_string, 'foo=; Path=/test', 'right format';
is $cookie->to_string, 'foo=; path=/test', 'right format';
$cookie = Mojo::Cookie::Response->new;
$cookie->name('foo');
$cookie->value('');
$cookie->path('/test');
is $cookie->to_string, 'foo=; Path=/test', 'right format';
is $cookie->to_string, 'foo=; path=/test', 'right format';

# Full response cookie as string
$cookie = Mojo::Cookie::Response->new;
Expand All @@ -169,8 +169,8 @@ $cookie->max_age(60);
$cookie->expires(1218092879);
$cookie->secure(1);
$cookie->httponly(1);
is $cookie->to_string, 'foo=ba r; Domain=kraih.com; Path=/test; Max-Age=60;'
. ' Expires=Thu, 07 Aug 2008 07:07:59 GMT; Secure; HttpOnly', 'right format';
is $cookie->to_string, 'foo=ba r; domain=kraih.com; path=/test; Max-Age=60;'
. ' expires=Thu, 07 Aug 2008 07:07:59 GMT; secure; HttpOnly', 'right format';

# Parse response cookie (RFC 6265)
$cookies
Expand Down Expand Up @@ -205,8 +205,8 @@ is $cookies->[1], undef, 'no more cookies';
# Parse quoted response cookie (RFC 6265, alternative)
$cookies
= Mojo::Cookie::Response->parse(
'foo="b a\" ;r\"\\\\"; Domain=kraih.com; Path=/test; Max-Age=60;'
. ' Expires=Thu, 07 Aug 2008 07:07:59 GMT; Secure');
'foo="b a\" ;r\"\\\\"; domain=kraih.com; path=/test; Max-Age=60;'
. ' expires=Thu, 07 Aug 2008 07:07:59 GMT; secure');
is $cookies->[0]->name, 'foo', 'right name';
is $cookies->[0]->value, 'b a" ;r"\\', 'right value';
is $cookies->[0]->domain, 'kraih.com', 'right domain';
Expand Down Expand Up @@ -330,13 +330,13 @@ is $cookies->[0]->max_age, 60, 'right max age value';
is $cookies->[0]->expires, 'Thu, 07 Aug 2008 07:07:59 GMT',
'right expires value';
is $cookies->[0]->secure, '1', 'right secure flag';
is $cookies->[0]->to_string, 'foo=; Domain=kraih.com; Path=/test; Max-Age=60;'
. ' Expires=Thu, 07 Aug 2008 07:07:59 GMT; Secure', 'right result';
is $cookies->[0]->to_string, 'foo=; domain=kraih.com; path=/test; Max-Age=60;'
. ' expires=Thu, 07 Aug 2008 07:07:59 GMT; secure', 'right result';
is $cookies->[1], undef, 'no more cookies';
$cookies
= Mojo::Cookie::Response->parse(
'foo=; Version=1; Domain=kraih.com; Path=/test; Max-Age=60;'
. ' expires=Thu, 07 Aug 2008 07:07:59 GMT; Secure');
'foo=; Version=1; domain=kraih.com; path=/test; Max-Age=60;'
. ' expires=Thu, 07 Aug 2008 07:07:59 GMT; secure');
is $cookies->[0]->name, 'foo', 'right name';
is $cookies->[0]->value, '', 'no value';
is $cookies->[0]->domain, 'kraih.com', 'right domain';
Expand All @@ -345,8 +345,8 @@ is $cookies->[0]->max_age, 60, 'right max age value';
is $cookies->[0]->expires, 'Thu, 07 Aug 2008 07:07:59 GMT',
'right expires value';
is $cookies->[0]->secure, '1', 'right secure flag';
is $cookies->[0]->to_string, 'foo=; Domain=kraih.com; Path=/test; Max-Age=60;'
. ' Expires=Thu, 07 Aug 2008 07:07:59 GMT; Secure', 'right result';
is $cookies->[0]->to_string, 'foo=; domain=kraih.com; path=/test; Max-Age=60;'
. ' expires=Thu, 07 Aug 2008 07:07:59 GMT; secure', 'right result';
is $cookies->[1], undef, 'no more cookies';

# Response cookie with Max-Age 0 and Expires 0
Expand All @@ -357,7 +357,7 @@ $cookie->path('/');
$cookie->max_age(0);
$cookie->expires(0);
is $cookie->to_string,
'foo=bar; Path=/; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT',
'foo=bar; path=/; Max-Age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT',
'right format';

# Parse response cookie with Max-Age 0 and Expires 0 (RFC 6265)
Expand Down
4 changes: 2 additions & 2 deletions t/mojo/request.t
Expand Up @@ -1737,11 +1737,11 @@ $req->parse("plain\x0d\x0a");
is $counter, 4, 'right count';
ok !$req->content->is_parsing_body, 'is not parsing body';
ok !$req->is_finished, 'request is not finished';
$req->parse('Cookie: $Version=1; foo=bar; $Path=/foobar; bar=baz; $Path=/t');
$req->parse('Cookie: foo=bar; bar=baz');
is $counter, 5, 'right count';
ok !$req->content->is_parsing_body, 'is not parsing body';
ok !$req->is_finished, 'request is not finished';
$req->parse("est/23\x0d\x0a");
$req->parse("\x0d\x0a");
is $counter, 6, 'right count';
ok !$req->content->is_parsing_body, 'is not parsing body';
ok !$req->is_finished, 'request is not finished';
Expand Down
4 changes: 2 additions & 2 deletions t/mojo/response.t
Expand Up @@ -502,7 +502,7 @@ $res = Mojo::Message::Response->new;
$res->parse("HTTP/1.0 200 OK\x0d\x0a");
$res->parse("Content-Type: text/plain\x0d\x0a");
$res->parse("Content-Length: 27\x0d\x0a");
$res->parse("Set-Cookie: foo=bar; Version=1; Path=/test\x0d\x0a\x0d\x0a");
$res->parse("Set-Cookie: foo=bar; path=/test\x0d\x0a\x0d\x0a");
$res->parse("Hello World!\n1234\nlalalala\n");
ok $res->is_finished, 'response is finished';
is $res->code, 200, 'right status';
Expand All @@ -512,7 +512,7 @@ ok $res->at_least_version('1.0'), 'at least version 1.0';
ok !$res->at_least_version('1.2'), 'not version 1.2';
is $res->headers->content_type, 'text/plain', 'right "Content-Type" value';
is $res->headers->content_length, 27, 'right "Content-Length" value';
is $res->headers->set_cookie, 'foo=bar; Version=1; Path=/test',
is $res->headers->set_cookie, 'foo=bar; path=/test',
'right "Set-Cookie" value';
my $cookies = $res->cookies;
is $cookies->[0]->name, 'foo', 'right name';
Expand Down
4 changes: 2 additions & 2 deletions t/mojolicious/app.t
Expand Up @@ -392,8 +392,8 @@ $t->get_ok('/shortcut/act')->status_is(200)

# Session with domain
$t->get_ok('/foo/session')->status_is(200)
->header_like('Set-Cookie' => qr/; Domain=\.example\.com/)
->header_like('Set-Cookie' => qr|; Path=/bar|)
->header_like('Set-Cookie' => qr/; domain=\.example\.com/)
->header_like('Set-Cookie' => qr|; path=/bar|)
->content_is('Bender rockzzz!');

# Mixed formats
Expand Down
5 changes: 2 additions & 3 deletions t/mojolicious/group_lite_app.t
Expand Up @@ -254,9 +254,8 @@ ok $t->tx->res->cookie('mojolicious')->httponly,
$t->reset_session;
my $session = b("☃☃☃☃☃")->encode->b64_encode('');
my $hmac = $session->clone->hmac_md5_sum($t->app->secret);
my $broken = "\$Version=1; mojolicious=$session--$hmac; \$Path=/";
$t->get_ok('/bridge2stash' => {Cookie => $broken})->status_is(200)
->content_is("stash too!!!!!!!\n");
$t->get_ok('/bridge2stash' => {Cookie => "mojolicious=$session--$hmac"})
->status_is(200)->content_is("stash too!!!!!!!\n");

# GET /bridge2stash (without cookie jar)
$t->ua->cookie_jar(0);
Expand Down

0 comments on commit 0a325c9

Please sign in to comment.