This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
3afeae22dd432ea21ffc096c44bed6d70b71d0d1
[perl5.git] / lib / CGI / Cookie.pm
1 package 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
10 # Copyright 1995-1999, Lincoln D. Stein.  All rights reserved.
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
16 $CGI::Cookie::VERSION='1.24';
17
18 use CGI::Util qw(rearrange unescape escape);
19 use overload '""' => \&as_string,
20     'cmp' => \&compare,
21     'fallback'=>1;
22
23 # Turn on special checking for Doug MacEachern's modperl
24 my $MOD_PERL = 0;
25 if (exists $ENV{MOD_PERL}) {
26   eval "require mod_perl";
27   if (defined $mod_perl::VERSION) {
28     my $float = $mod_perl::VERSION;
29     $float = ~ s/^.+?([\d.]+).+$/$1/;
30     if ($float >= 1.99) {
31       $MOD_PERL = 2;
32       require Apache::RequestUtil;
33       eval "require APR::Table";  # Changing APIs? I hope not.
34     } else {
35       $MOD_PERL = 1;
36       require Apache;
37     }
38   }
39 }
40
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.
44 sub fetch {
45     my $class = shift;
46     my $raw_cookie = get_raw_cookie(@_) or return;
47     return $class->parse($raw_cookie);
48 }
49
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
75 sub 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()";
83     }
84     $raw_cookie = $ENV{HTTP_COOKIE} || $ENV{COOKIE};
85   }
86 }
87
88
89 sub parse {
90   my ($self,$raw_cookie) = @_;
91   my %results;
92
93   my(@pairs) = split("; ?",$raw_cookie);
94   foreach (@pairs) {
95     s/\s*(.*?)\s*/$1/;
96     my($key,$value) = split("=",$_,2);
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 '') {
103       @values = map unescape($_),split(/[&;]/,$value.'&dmy');
104       pop @values;
105     }
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;
113 }
114
115 sub new {
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;
128     }
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;
148 #  $self->max_age($expires) if defined $expires;
149   return $self;
150 }
151
152 sub as_string {
153     my $self = shift;
154     return "" unless $self->name;
155
156     my(@constant_values,$domain,$path,$expires,$max_age,$secure);
157
158     push(@constant_values,"domain=$domain")   if $domain = $self->domain;
159     push(@constant_values,"path=$path")       if $path = $self->path;
160     push(@constant_values,"expires=$expires") if $expires = $self->expires;
161     push(@constant_values,"max-age=$max_age") if $max_age = $self->max_age;
162     push(@constant_values,"secure") if $secure = $self->secure;
163
164     my($key) = escape($self->name);
165     my($cookie) = join("=",$key,join("&",map escape($_),$self->value));
166     return join("; ",$cookie,@constant_values);
167 }
168
169 sub compare {
170     my $self = shift;
171     my $value = shift;
172     return "$self" cmp $value;
173 }
174
175 # accessors
176 sub name {
177     my $self = shift;
178     my $name = shift;
179     $self->{'name'} = $name if defined $name;
180     return $self->{'name'};
181 }
182
183 sub value {
184     my $self = shift;
185     my $value = shift;
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       }
199     return wantarray ? @{$self->{'value'}} : $self->{'value'}->[0]
200 }
201
202 sub domain {
203     my $self = shift;
204     my $domain = shift;
205     $self->{'domain'} = lc $domain if defined $domain;
206     return $self->{'domain'};
207 }
208
209 sub secure {
210     my $self = shift;
211     my $secure = shift;
212     $self->{'secure'} = $secure if defined $secure;
213     return $self->{'secure'};
214 }
215
216 sub expires {
217     my $self = shift;
218     my $expires = shift;
219     $self->{'expires'} = CGI::Util::expires($expires,'cookie') if defined $expires;
220     return $self->{'expires'};
221 }
222
223 sub max_age {
224   my $self = shift;
225   my $expires = shift;
226   $self->{'max-age'} = CGI::Util::expire_calc($expires)-time() if defined $expires;
227   return $self->{'max-age'};
228 }
229
230 sub path {
231     my $self = shift;
232     my $path = shift;
233     $self->{'path'} = $path if defined $path;
234     return $self->{'path'};
235 }
236
237 1;
238
239 =head1 NAME
240
241 CGI::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
265 CGI::Cookie is an interface to Netscape (HTTP/1.1) cookies, an
266 innovation that allows Web servers to store persistent information on
267 the browser's side of the connection.  Although CGI::Cookie is
268 intended to be used in conjunction with CGI.pm (and is in fact used by
269 it internally), you can use this module independently.
270
271 For full information on cookies see 
272
273         http://www.ics.uci.edu/pub/ietf/http/rfc2109.txt
274
275 =head1 USING CGI::Cookie
276
277 CGI::Cookie is object oriented.  Each cookie object has a name and a
278 value.  The name is any scalar value.  The value is any scalar or
279 array value (associative arrays are also allowed).  Cookies also have
280 several optional attributes, including:
281
282 =over 4
283
284 =item B<1. expiration date>
285
286 The expiration date tells the browser how long to hang on to the
287 cookie.  If the cookie specifies an expiration date in the future, the
288 browser will store the cookie information in a disk file and return it
289 to the server every time the user reconnects (until the expiration
290 date is reached).  If the cookie species an expiration date in the
291 past, the browser will remove the cookie from the disk file.  If the
292 expiration date is not specified, the cookie will persist only until
293 the user quits the browser.
294
295 =item B<2. domain>
296
297 This is a partial or complete domain name for which the cookie is 
298 valid.  The browser will return the cookie to any host that matches
299 the partial domain name.  For example, if you specify a domain name
300 of ".capricorn.com", then Netscape will return the cookie to
301 Web servers running on any of the machines "www.capricorn.com", 
302 "ftp.capricorn.com", "feckless.capricorn.com", etc.  Domain names
303 must contain at least two periods to prevent attempts to match
304 on top level domains like ".edu".  If no domain is specified, then
305 the browser will only return the cookie to servers on the host the
306 cookie originated from.
307
308 =item B<3. path>
309
310 If you provide a cookie path attribute, the browser will check it
311 against your script's URL before returning the cookie.  For example,
312 if you specify the path "/cgi-bin", then the cookie will be returned
313 to 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
315 "/cgi-private/site_admin.pl".  By default, the path is set to "/", so
316 that all scripts at your site will receive the cookie.
317
318 =item B<4. secure flag>
319
320 If the "secure" attribute is set, the cookie will only be sent to your
321 script 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',
331                              -path    =>  '/cgi-bin/database',
332                              -secure  =>  1
333                             );
334
335 Create cookies from scratch with the B<new> method.  The B<-name> and
336 B<-value> parameters are required.  The name must be a scalar value.
337 The 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
339 object serialization protocols for full generality).
340
341 B<-expires> accepts any of the relative or absolute date formats
342 recognized by CGI.pm, for example "+3M" for three months in the
343 future.  See CGI.pm's documentation for details.
344
345 B<-domain> points to a domain name or to a fully qualified host name.
346 If not specified, the cookie will be returned only to the Web server
347 that created it.
348
349 B<-path> points to a partial URL on the current server.  The cookie
350 will be returned to all URLs beginning with the specified path.  If
351 not specified, it defaults to '/', which returns the cookie to all
352 pages at your site.
353
354 B<-secure> if set to a true value instructs the browser to return the
355 cookie only when a cryptographic protocol is in use.
356
357 =head2 Sending the Cookie to the Browser
358
359 Within a CGI script you can send a cookie to the browser by creating
360 one or more Set-Cookie: fields in the HTTP header.  Here is a typical
361 sequence:
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
370 To send more than one cookie, create several Set-Cookie: fields.
371
372 If you are using CGI.pm, you send cookies by providing a -cookie
373 argument to the header() method:
374
375   print header(-cookie=>$c);
376
377 Mod_perl users can set cookies using the request object's header_out()
378 method:
379
380   $r->headers_out->set('Set-Cookie' => $c);
381
382 Internally, Cookie overloads the "" operator to call its as_string()
383 method when incorporated into the HTTP header.  as_string() turns the
384 Cookie's internal representation into an RFC-compliant text
385 representation.  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
393 B<fetch> returns an associative array consisting of all cookies
394 returned by the browser.  The keys of the array are the cookie names.  You
395 can iterate through the cookies this way:
396
397         %cookies = fetch CGI::Cookie;
398         foreach (keys %cookies) {
399            do_something($cookies{$_});
400         }
401
402 In a scalar context, fetch() returns a hash reference, which may be more
403 efficient if you are manipulating multiple cookies.
404
405 CGI.pm uses the URL escaping methods to save and restore reserved characters
406 in its cookies.  If you are trying to retrieve a cookie set by a foreign server,
407 this escaping method may trip you up.  Use raw_fetch() instead, which has the
408 same semantics as fetch(), but performs no unescaping.
409
410 You may also retrieve cookies that were stored in some external
411 form using the parse() class method:
412
413        $COOKIES = `cat /usr/tmp/Cookie_stash`;
414        %cookies = parse CGI::Cookie($COOKIES);
415
416 If you are in a mod_perl environment, you can save some overhead by
417 passing the request object to fetch() like this:
418
419    CGI::Cookie->fetch($r);
420
421 =head2 Manipulating Cookies
422
423 Cookie objects have a series of accessor methods to get and set cookie
424 attributes.  Each accessor has a similar syntax.  Called without
425 arguments, the accessor returns the current value of the attribute.
426 Called with an argument, the accessor changes the attribute and
427 returns its new value.
428
429 =over 4
430
431 =item B<name()>
432
433 Get or set the cookie's name.  Example:
434
435         $name = $c->name;
436         $new_name = $c->name('fred');
437
438 =item B<value()>
439
440 Get or set the cookie's value.  Example:
441
442         $value = $c->value;
443         @new_value = $c->value(['a','b','c','d']);
444
445 B<value()> is context sensitive.  In a list context it will return
446 the current value of the cookie as an array.  In a scalar context it
447 will return the B<first> value of a multivalued cookie.
448
449 =item B<domain()>
450
451 Get or set the cookie's domain.
452
453 =item B<path()>
454
455 Get or set the cookie's path.
456
457 =item B<expires()>
458
459 Get or set the cookie's expiration time.
460
461 =back
462
463
464 =head1 AUTHOR INFORMATION
465
466 Copyright 1997-1998, Lincoln D. Stein.  All rights reserved.  
467
468 This library is free software; you can redistribute it and/or modify
469 it under the same terms as Perl itself.
470
471 Address bug reports and comments to: lstein@cshl.org
472
473 =head1 BUGS
474
475 This section intentionally left blank.
476
477 =head1 SEE ALSO
478
479 L<CGI::Carp>, L<CGI>
480
481 =cut