This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Upgrade to CGI 3.07.
[perl5.git] / lib / CGI / Cookie.pm
CommitLineData
424ec8fa
GS
1package CGI::Cookie;
2
3# See the bottom of this file for the POD documentation. Search for the
4# string '=head'.
5
6# You can run this file through either pod2man or pod2html to produce pretty
7# documentation in manual or html file format (these utilities are part of the
8# Perl 5 distribution).
9
3538e1d5 10# Copyright 1995-1999, Lincoln D. Stein. All rights reserved.
424ec8fa
GS
11# It may be used and modified freely, but I do request that this copyright
12# notice remain attached to the file. You may modify this module as you
13# wish, but if you redistribute a modified version, please attach a note
14# listing the modifications you have made.
15
976c4ade 16$CGI::Cookie::VERSION='1.25';
424ec8fa 17
3d1a2ec4 18use CGI::Util qw(rearrange unescape escape);
424ec8fa
GS
19use overload '""' => \&as_string,
20 'cmp' => \&compare,
21 'fallback'=>1;
22
8f3ccfa2
JH
23# Turn on special checking for Doug MacEachern's modperl
24my $MOD_PERL = 0;
25if (exists $ENV{MOD_PERL}) {
26 eval "require mod_perl";
27 if (defined $mod_perl::VERSION) {
29ddc2a4 28 my $float = $mod_perl::VERSION;
976c4ade 29 $float += 0;
29ddc2a4 30 if ($float >= 1.99) {
8f3ccfa2
JH
31 $MOD_PERL = 2;
32 require Apache::RequestUtil;
29ddc2a4 33 eval "require APR::Table"; # Changing APIs? I hope not.
8f3ccfa2
JH
34 } else {
35 $MOD_PERL = 1;
36 require Apache;
37 }
38 }
39}
40
424ec8fa
GS
41# fetch a list of cookies from the environment and
42# return as a hash. the cookies are parsed as normal
43# escaped URL data.
44sub fetch {
45 my $class = shift;
8f3ccfa2 46 my $raw_cookie = get_raw_cookie(@_) or return;
424ec8fa
GS
47 return $class->parse($raw_cookie);
48}
49
8f3ccfa2
JH
50# Fetch a list of cookies from the environment or the incoming headers and
51# return as a hash. The cookie values are not unescaped or altered in any way.
52 sub raw_fetch {
53 my $class = shift;
54 my $raw_cookie = get_raw_cookie(@_) or return;
55 my %results;
56 my($key,$value);
57
58 my(@pairs) = split("; ?",$raw_cookie);
59 foreach (@pairs) {
60 s/\s*(.*?)\s*/$1/;
61 if (/^([^=]+)=(.*)/) {
62 $key = $1;
63 $value = $2;
64 }
65 else {
66 $key = $_;
67 $value = '';
68 }
69 $results{$key} = $value;
70 }
71 return \%results unless wantarray;
72 return %results;
73}
74
75sub get_raw_cookie {
76 my $r = shift;
77 $r ||= eval { Apache->request() } if $MOD_PERL;
78 if ($r) {
79 $raw_cookie = $r->headers_in->{'Cookie'};
80 } else {
81 if ($MOD_PERL && !exists $ENV{REQUEST_METHOD}) {
82 die "Run $r->subprocess_env; before calling fetch()";
424ec8fa 83 }
8f3ccfa2
JH
84 $raw_cookie = $ENV{HTTP_COOKIE} || $ENV{COOKIE};
85 }
424ec8fa
GS
86}
87
424ec8fa 88
ba056755
JH
89sub parse {
90 my ($self,$raw_cookie) = @_;
91 my %results;
92
93 my(@pairs) = split("; ?",$raw_cookie);
94 foreach (@pairs) {
95 s/\s*(.*?)\s*/$1/;
199d4a26 96 my($key,$value) = split("=",$_,2);
ba056755
JH
97
98 # Some foreign cookies are not in name=value format, so ignore
99 # them.
100 next if !defined($value);
101 my @values = ();
102 if ($value ne '') {
199d4a26 103 @values = map unescape($_),split(/[&;]/,$value.'&dmy');
ba056755 104 pop @values;
424ec8fa 105 }
ba056755
JH
106 $key = unescape($key);
107 # A bug in Netscape can cause several cookies with same name to
108 # appear. The FIRST one in HTTP_COOKIE is the most recent version.
109 $results{$key} ||= $self->new(-name=>$key,-value=>\@values);
110 }
111 return \%results unless wantarray;
112 return %results;
424ec8fa
GS
113}
114
115sub new {
ba056755
JH
116 my $class = shift;
117 $class = ref($class) if ref($class);
118 my($name,$value,$path,$domain,$secure,$expires) =
119 rearrange([NAME,[VALUE,VALUES],PATH,DOMAIN,SECURE,EXPIRES],@_);
120
121 # Pull out our parameters.
122 my @values;
123 if (ref($value)) {
124 if (ref($value) eq 'ARRAY') {
125 @values = @$value;
126 } elsif (ref($value) eq 'HASH') {
127 @values = %$value;
424ec8fa 128 }
ba056755
JH
129 } else {
130 @values = ($value);
131 }
132
133 bless my $self = {
134 'name'=>$name,
135 'value'=>[@values],
136 },$class;
137
138 # IE requires the path and domain to be present for some reason.
139 $path ||= "/";
140 # however, this breaks networks which use host tables without fully qualified
141 # names, so we comment it out.
142 # $domain = CGI::virtual_host() unless defined $domain;
143
144 $self->path($path) if defined $path;
145 $self->domain($domain) if defined $domain;
146 $self->secure($secure) if defined $secure;
147 $self->expires($expires) if defined $expires;
188ba755 148# $self->max_age($expires) if defined $expires;
ba056755 149 return $self;
424ec8fa
GS
150}
151
152sub as_string {
153 my $self = shift;
154 return "" unless $self->name;
155
188ba755 156 my(@constant_values,$domain,$path,$expires,$max_age,$secure);
424ec8fa 157
188ba755
JH
158 push(@constant_values,"domain=$domain") if $domain = $self->domain;
159 push(@constant_values,"path=$path") if $path = $self->path;
424ec8fa 160 push(@constant_values,"expires=$expires") if $expires = $self->expires;
188ba755 161 push(@constant_values,"max-age=$max_age") if $max_age = $self->max_age;
ba056755 162 push(@constant_values,"secure") if $secure = $self->secure;
424ec8fa 163
3d1a2ec4
GS
164 my($key) = escape($self->name);
165 my($cookie) = join("=",$key,join("&",map escape($_),$self->value));
424ec8fa
GS
166 return join("; ",$cookie,@constant_values);
167}
168
169sub compare {
170 my $self = shift;
171 my $value = shift;
172 return "$self" cmp $value;
173}
174
175# accessors
176sub name {
177 my $self = shift;
178 my $name = shift;
179 $self->{'name'} = $name if defined $name;
180 return $self->{'name'};
181}
182
183sub value {
184 my $self = shift;
185 my $value = shift;
ac734d8b
JH
186 if (defined $value) {
187 my @values;
188 if (ref($value)) {
189 if (ref($value) eq 'ARRAY') {
190 @values = @$value;
191 } elsif (ref($value) eq 'HASH') {
192 @values = %$value;
193 }
194 } else {
195 @values = ($value);
196 }
197 $self->{'value'} = [@values];
198 }
424ec8fa
GS
199 return wantarray ? @{$self->{'value'}} : $self->{'value'}->[0]
200}
201
202sub domain {
203 my $self = shift;
204 my $domain = shift;
29ddc2a4 205 $self->{'domain'} = lc $domain if defined $domain;
424ec8fa
GS
206 return $self->{'domain'};
207}
208
209sub secure {
210 my $self = shift;
211 my $secure = shift;
212 $self->{'secure'} = $secure if defined $secure;
213 return $self->{'secure'};
214}
215
216sub expires {
217 my $self = shift;
218 my $expires = shift;
3d1a2ec4 219 $self->{'expires'} = CGI::Util::expires($expires,'cookie') if defined $expires;
424ec8fa
GS
220 return $self->{'expires'};
221}
222
188ba755
JH
223sub max_age {
224 my $self = shift;
225 my $expires = shift;
2ed511ec 226 $self->{'max-age'} = CGI::Util::expire_calc($expires)-time() if defined $expires;
188ba755
JH
227 return $self->{'max-age'};
228}
229
424ec8fa
GS
230sub path {
231 my $self = shift;
232 my $path = shift;
233 $self->{'path'} = $path if defined $path;
234 return $self->{'path'};
235}
236
2371;
238
239=head1 NAME
240
241CGI::Cookie - Interface to Netscape Cookies
242
243=head1 SYNOPSIS
244
245 use CGI qw/:standard/;
246 use CGI::Cookie;
247
248 # Create new cookies and send them
249 $cookie1 = new CGI::Cookie(-name=>'ID',-value=>123456);
250 $cookie2 = new CGI::Cookie(-name=>'preferences',
251 -value=>{ font => Helvetica,
252 size => 12 }
253 );
254 print header(-cookie=>[$cookie1,$cookie2]);
255
256 # fetch existing cookies
257 %cookies = fetch CGI::Cookie;
258 $id = $cookies{'ID'}->value;
259
260 # create cookies returned from an external source
261 %cookies = parse CGI::Cookie($ENV{COOKIE});
262
263=head1 DESCRIPTION
264
265CGI::Cookie is an interface to Netscape (HTTP/1.1) cookies, an
266innovation that allows Web servers to store persistent information on
267the browser's side of the connection. Although CGI::Cookie is
268intended to be used in conjunction with CGI.pm (and is in fact used by
269it internally), you can use this module independently.
270
271For full information on cookies see
272
273 http://www.ics.uci.edu/pub/ietf/http/rfc2109.txt
274
275=head1 USING CGI::Cookie
276
277CGI::Cookie is object oriented. Each cookie object has a name and a
278value. The name is any scalar value. The value is any scalar or
279array value (associative arrays are also allowed). Cookies also have
280several optional attributes, including:
281
282=over 4
283
284=item B<1. expiration date>
285
286The expiration date tells the browser how long to hang on to the
287cookie. If the cookie specifies an expiration date in the future, the
288browser will store the cookie information in a disk file and return it
289to the server every time the user reconnects (until the expiration
290date is reached). If the cookie species an expiration date in the
291past, the browser will remove the cookie from the disk file. If the
292expiration date is not specified, the cookie will persist only until
293the user quits the browser.
294
295=item B<2. domain>
296
297This is a partial or complete domain name for which the cookie is
298valid. The browser will return the cookie to any host that matches
299the partial domain name. For example, if you specify a domain name
300of ".capricorn.com", then Netscape will return the cookie to
301Web servers running on any of the machines "www.capricorn.com",
302"ftp.capricorn.com", "feckless.capricorn.com", etc. Domain names
303must contain at least two periods to prevent attempts to match
304on top level domains like ".edu". If no domain is specified, then
305the browser will only return the cookie to servers on the host the
306cookie originated from.
307
308=item B<3. path>
309
310If you provide a cookie path attribute, the browser will check it
311against your script's URL before returning the cookie. For example,
312if you specify the path "/cgi-bin", then the cookie will be returned
3538e1d5
GS
313to each of the scripts "/cgi-bin/tally.pl", "/cgi-bin/order.pl", and
314"/cgi-bin/customer_service/complain.pl", but not to the script
3d1a2ec4
GS
315"/cgi-private/site_admin.pl". By default, the path is set to "/", so
316that all scripts at your site will receive the cookie.
424ec8fa
GS
317
318=item B<4. secure flag>
319
320If the "secure" attribute is set, the cookie will only be sent to your
321script if the CGI request is occurring on a secure channel, such as SSL.
322
323=back
324
325=head2 Creating New Cookies
326
327 $c = new CGI::Cookie(-name => 'foo',
328 -value => 'bar',
329 -expires => '+3M',
330 -domain => '.capricorn.com',
199d4a26 331 -path => '/cgi-bin/database',
424ec8fa
GS
332 -secure => 1
333 );
334
335Create cookies from scratch with the B<new> method. The B<-name> and
336B<-value> parameters are required. The name must be a scalar value.
337The value can be a scalar, an array reference, or a hash reference.
338(At some point in the future cookies will support one of the Perl
339object serialization protocols for full generality).
340
341B<-expires> accepts any of the relative or absolute date formats
342recognized by CGI.pm, for example "+3M" for three months in the
343future. See CGI.pm's documentation for details.
344
345B<-domain> points to a domain name or to a fully qualified host name.
346If not specified, the cookie will be returned only to the Web server
347that created it.
348
349B<-path> points to a partial URL on the current server. The cookie
350will be returned to all URLs beginning with the specified path. If
351not specified, it defaults to '/', which returns the cookie to all
352pages at your site.
353
354B<-secure> if set to a true value instructs the browser to return the
355cookie only when a cryptographic protocol is in use.
356
357=head2 Sending the Cookie to the Browser
358
359Within a CGI script you can send a cookie to the browser by creating
360one or more Set-Cookie: fields in the HTTP header. Here is a typical
361sequence:
362
363 my $c = new CGI::Cookie(-name => 'foo',
364 -value => ['bar','baz'],
365 -expires => '+3M');
366
367 print "Set-Cookie: $c\n";
368 print "Content-Type: text/html\n\n";
369
370To send more than one cookie, create several Set-Cookie: fields.
424ec8fa
GS
371
372If you are using CGI.pm, you send cookies by providing a -cookie
373argument to the header() method:
374
375 print header(-cookie=>$c);
376
377Mod_perl users can set cookies using the request object's header_out()
378method:
379
8f3ccfa2 380 $r->headers_out->set('Set-Cookie' => $c);
424ec8fa
GS
381
382Internally, Cookie overloads the "" operator to call its as_string()
383method when incorporated into the HTTP header. as_string() turns the
384Cookie's internal representation into an RFC-compliant text
385representation. You may call as_string() yourself if you prefer:
386
387 print "Set-Cookie: ",$c->as_string,"\n";
388
389=head2 Recovering Previous Cookies
390
391 %cookies = fetch CGI::Cookie;
392
393B<fetch> returns an associative array consisting of all cookies
394returned by the browser. The keys of the array are the cookie names. You
395can iterate through the cookies this way:
396
397 %cookies = fetch CGI::Cookie;
398 foreach (keys %cookies) {
399 do_something($cookies{$_});
400 }
401
402In a scalar context, fetch() returns a hash reference, which may be more
403efficient if you are manipulating multiple cookies.
3cb6de81 404
424ec8fa
GS
405CGI.pm uses the URL escaping methods to save and restore reserved characters
406in its cookies. If you are trying to retrieve a cookie set by a foreign server,
407this escaping method may trip you up. Use raw_fetch() instead, which has the
408same semantics as fetch(), but performs no unescaping.
409
410You may also retrieve cookies that were stored in some external
411form using the parse() class method:
412
e70cb7eb 413 $COOKIES = `cat /usr/tmp/Cookie_stash`;
424ec8fa
GS
414 %cookies = parse CGI::Cookie($COOKIES);
415
8f3ccfa2
JH
416If you are in a mod_perl environment, you can save some overhead by
417passing the request object to fetch() like this:
418
419 CGI::Cookie->fetch($r);
420
424ec8fa
GS
421=head2 Manipulating Cookies
422
423Cookie objects have a series of accessor methods to get and set cookie
424attributes. Each accessor has a similar syntax. Called without
425arguments, the accessor returns the current value of the attribute.
426Called with an argument, the accessor changes the attribute and
427returns its new value.
428
429=over 4
430
431=item B<name()>
432
433Get or set the cookie's name. Example:
434
435 $name = $c->name;
436 $new_name = $c->name('fred');
437
438=item B<value()>
439
440Get or set the cookie's value. Example:
441
442 $value = $c->value;
443 @new_value = $c->value(['a','b','c','d']);
444
a3b3a725 445B<value()> is context sensitive. In a list context it will return
424ec8fa
GS
446the current value of the cookie as an array. In a scalar context it
447will return the B<first> value of a multivalued cookie.
448
449=item B<domain()>
450
451Get or set the cookie's domain.
452
453=item B<path()>
454
455Get or set the cookie's path.
456
457=item B<expires()>
458
459Get or set the cookie's expiration time.
460
461=back
462
463
464=head1 AUTHOR INFORMATION
465
71f3e297 466Copyright 1997-1998, Lincoln D. Stein. All rights reserved.
424ec8fa 467
71f3e297
JH
468This library is free software; you can redistribute it and/or modify
469it under the same terms as Perl itself.
470
471Address bug reports and comments to: lstein@cshl.org
424ec8fa
GS
472
473=head1 BUGS
474
475This section intentionally left blank.
476
477=head1 SEE ALSO
478
479L<CGI::Carp>, L<CGI>
3cb6de81 480
424ec8fa 481=cut