10Sstevel@tonic-gatepackage CGI::Cookie; 20Sstevel@tonic-gate 30Sstevel@tonic-gate# See the bottom of this file for the POD documentation. Search for the 40Sstevel@tonic-gate# string '=head'. 50Sstevel@tonic-gate 60Sstevel@tonic-gate# You can run this file through either pod2man or pod2html to produce pretty 70Sstevel@tonic-gate# documentation in manual or html file format (these utilities are part of the 80Sstevel@tonic-gate# Perl 5 distribution). 90Sstevel@tonic-gate 100Sstevel@tonic-gate# Copyright 1995-1999, Lincoln D. Stein. All rights reserved. 110Sstevel@tonic-gate# It may be used and modified freely, but I do request that this copyright 120Sstevel@tonic-gate# notice remain attached to the file. You may modify this module as you 130Sstevel@tonic-gate# wish, but if you redistribute a modified version, please attach a note 140Sstevel@tonic-gate# listing the modifications you have made. 150Sstevel@tonic-gate 16*6287Sps156622$CGI::Cookie::VERSION='1.28'; 170Sstevel@tonic-gate 180Sstevel@tonic-gateuse CGI::Util qw(rearrange unescape escape); 19*6287Sps156622use CGI; 200Sstevel@tonic-gateuse overload '""' => \&as_string, 210Sstevel@tonic-gate 'cmp' => \&compare, 220Sstevel@tonic-gate 'fallback'=>1; 230Sstevel@tonic-gate 240Sstevel@tonic-gate# Turn on special checking for Doug MacEachern's modperl 250Sstevel@tonic-gatemy $MOD_PERL = 0; 260Sstevel@tonic-gateif (exists $ENV{MOD_PERL}) { 27667Sps156622 if (exists $ENV{MOD_PERL_API_VERSION} && $ENV{MOD_PERL_API_VERSION} == 2) { 280Sstevel@tonic-gate $MOD_PERL = 2; 29667Sps156622 require Apache2::RequestUtil; 30667Sps156622 require APR::Table; 31667Sps156622 } else { 32667Sps156622 $MOD_PERL = 1; 33667Sps156622 require Apache; 340Sstevel@tonic-gate } 350Sstevel@tonic-gate} 360Sstevel@tonic-gate 370Sstevel@tonic-gate# fetch a list of cookies from the environment and 380Sstevel@tonic-gate# return as a hash. the cookies are parsed as normal 390Sstevel@tonic-gate# escaped URL data. 400Sstevel@tonic-gatesub fetch { 410Sstevel@tonic-gate my $class = shift; 420Sstevel@tonic-gate my $raw_cookie = get_raw_cookie(@_) or return; 430Sstevel@tonic-gate return $class->parse($raw_cookie); 440Sstevel@tonic-gate} 450Sstevel@tonic-gate 460Sstevel@tonic-gate# Fetch a list of cookies from the environment or the incoming headers and 470Sstevel@tonic-gate# return as a hash. The cookie values are not unescaped or altered in any way. 480Sstevel@tonic-gate sub raw_fetch { 490Sstevel@tonic-gate my $class = shift; 500Sstevel@tonic-gate my $raw_cookie = get_raw_cookie(@_) or return; 510Sstevel@tonic-gate my %results; 520Sstevel@tonic-gate my($key,$value); 530Sstevel@tonic-gate 54*6287Sps156622 my(@pairs) = split("[;,] ?",$raw_cookie); 550Sstevel@tonic-gate foreach (@pairs) { 560Sstevel@tonic-gate s/\s*(.*?)\s*/$1/; 570Sstevel@tonic-gate if (/^([^=]+)=(.*)/) { 580Sstevel@tonic-gate $key = $1; 590Sstevel@tonic-gate $value = $2; 600Sstevel@tonic-gate } 610Sstevel@tonic-gate else { 620Sstevel@tonic-gate $key = $_; 630Sstevel@tonic-gate $value = ''; 640Sstevel@tonic-gate } 650Sstevel@tonic-gate $results{$key} = $value; 660Sstevel@tonic-gate } 670Sstevel@tonic-gate return \%results unless wantarray; 680Sstevel@tonic-gate return %results; 690Sstevel@tonic-gate} 700Sstevel@tonic-gate 710Sstevel@tonic-gatesub get_raw_cookie { 720Sstevel@tonic-gate my $r = shift; 73667Sps156622 $r ||= eval { $MOD_PERL == 2 ? 74667Sps156622 Apache2::RequestUtil->request() : 75667Sps156622 Apache->request } if $MOD_PERL; 760Sstevel@tonic-gate if ($r) { 770Sstevel@tonic-gate $raw_cookie = $r->headers_in->{'Cookie'}; 780Sstevel@tonic-gate } else { 790Sstevel@tonic-gate if ($MOD_PERL && !exists $ENV{REQUEST_METHOD}) { 800Sstevel@tonic-gate die "Run $r->subprocess_env; before calling fetch()"; 810Sstevel@tonic-gate } 820Sstevel@tonic-gate $raw_cookie = $ENV{HTTP_COOKIE} || $ENV{COOKIE}; 830Sstevel@tonic-gate } 840Sstevel@tonic-gate} 850Sstevel@tonic-gate 860Sstevel@tonic-gate 870Sstevel@tonic-gatesub parse { 880Sstevel@tonic-gate my ($self,$raw_cookie) = @_; 890Sstevel@tonic-gate my %results; 900Sstevel@tonic-gate 910Sstevel@tonic-gate my(@pairs) = split("; ?",$raw_cookie); 920Sstevel@tonic-gate foreach (@pairs) { 930Sstevel@tonic-gate s/\s*(.*?)\s*/$1/; 940Sstevel@tonic-gate my($key,$value) = split("=",$_,2); 950Sstevel@tonic-gate 960Sstevel@tonic-gate # Some foreign cookies are not in name=value format, so ignore 970Sstevel@tonic-gate # them. 980Sstevel@tonic-gate next if !defined($value); 990Sstevel@tonic-gate my @values = (); 1000Sstevel@tonic-gate if ($value ne '') { 1010Sstevel@tonic-gate @values = map unescape($_),split(/[&;]/,$value.'&dmy'); 1020Sstevel@tonic-gate pop @values; 1030Sstevel@tonic-gate } 1040Sstevel@tonic-gate $key = unescape($key); 1050Sstevel@tonic-gate # A bug in Netscape can cause several cookies with same name to 1060Sstevel@tonic-gate # appear. The FIRST one in HTTP_COOKIE is the most recent version. 1070Sstevel@tonic-gate $results{$key} ||= $self->new(-name=>$key,-value=>\@values); 1080Sstevel@tonic-gate } 1090Sstevel@tonic-gate return \%results unless wantarray; 1100Sstevel@tonic-gate return %results; 1110Sstevel@tonic-gate} 1120Sstevel@tonic-gate 1130Sstevel@tonic-gatesub new { 1140Sstevel@tonic-gate my $class = shift; 1150Sstevel@tonic-gate $class = ref($class) if ref($class); 116*6287Sps156622 # Ignore mod_perl request object--compatability with Apache::Cookie. 117*6287Sps156622 shift if ref $_[0] 118*6287Sps156622 && eval { $_[0]->isa('Apache::Request::Req') || $_[0]->isa('Apache') }; 119*6287Sps156622 my($name,$value,$path,$domain,$secure,$expires,$httponly) = 120*6287Sps156622 rearrange([NAME,[VALUE,VALUES],PATH,DOMAIN,SECURE,EXPIRES,HTTPONLY],@_); 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate # Pull out our parameters. 1230Sstevel@tonic-gate my @values; 1240Sstevel@tonic-gate if (ref($value)) { 1250Sstevel@tonic-gate if (ref($value) eq 'ARRAY') { 1260Sstevel@tonic-gate @values = @$value; 1270Sstevel@tonic-gate } elsif (ref($value) eq 'HASH') { 1280Sstevel@tonic-gate @values = %$value; 1290Sstevel@tonic-gate } 1300Sstevel@tonic-gate } else { 1310Sstevel@tonic-gate @values = ($value); 1320Sstevel@tonic-gate } 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate bless my $self = { 1350Sstevel@tonic-gate 'name'=>$name, 1360Sstevel@tonic-gate 'value'=>[@values], 1370Sstevel@tonic-gate },$class; 1380Sstevel@tonic-gate 1390Sstevel@tonic-gate # IE requires the path and domain to be present for some reason. 1400Sstevel@tonic-gate $path ||= "/"; 1410Sstevel@tonic-gate # however, this breaks networks which use host tables without fully qualified 1420Sstevel@tonic-gate # names, so we comment it out. 1430Sstevel@tonic-gate # $domain = CGI::virtual_host() unless defined $domain; 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate $self->path($path) if defined $path; 1460Sstevel@tonic-gate $self->domain($domain) if defined $domain; 1470Sstevel@tonic-gate $self->secure($secure) if defined $secure; 1480Sstevel@tonic-gate $self->expires($expires) if defined $expires; 149*6287Sps156622 $self->httponly($httponly) if defined $httponly; 1500Sstevel@tonic-gate# $self->max_age($expires) if defined $expires; 1510Sstevel@tonic-gate return $self; 1520Sstevel@tonic-gate} 1530Sstevel@tonic-gate 1540Sstevel@tonic-gatesub as_string { 1550Sstevel@tonic-gate my $self = shift; 1560Sstevel@tonic-gate return "" unless $self->name; 1570Sstevel@tonic-gate 158*6287Sps156622 my(@constant_values,$domain,$path,$expires,$max_age,$secure,$httponly); 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate push(@constant_values,"domain=$domain") if $domain = $self->domain; 1610Sstevel@tonic-gate push(@constant_values,"path=$path") if $path = $self->path; 1620Sstevel@tonic-gate push(@constant_values,"expires=$expires") if $expires = $self->expires; 1630Sstevel@tonic-gate push(@constant_values,"max-age=$max_age") if $max_age = $self->max_age; 1640Sstevel@tonic-gate push(@constant_values,"secure") if $secure = $self->secure; 165*6287Sps156622 push(@constant_values,"HttpOnly") if $httponly = $self->httponly; 1660Sstevel@tonic-gate 1670Sstevel@tonic-gate my($key) = escape($self->name); 168*6287Sps156622 my($cookie) = join("=",(defined $key ? $key : ''),join("&",map escape(defined $_ ? $_ : ''),$self->value)); 1690Sstevel@tonic-gate return join("; ",$cookie,@constant_values); 1700Sstevel@tonic-gate} 1710Sstevel@tonic-gate 1720Sstevel@tonic-gatesub compare { 1730Sstevel@tonic-gate my $self = shift; 1740Sstevel@tonic-gate my $value = shift; 1750Sstevel@tonic-gate return "$self" cmp $value; 1760Sstevel@tonic-gate} 1770Sstevel@tonic-gate 178*6287Sps156622sub bake { 179*6287Sps156622 my ($self, $r) = @_; 180*6287Sps156622 181*6287Sps156622 $r ||= eval { 182*6287Sps156622 $MOD_PERL == 2 183*6287Sps156622 ? Apache2::RequestUtil->request() 184*6287Sps156622 : Apache->request 185*6287Sps156622 } if $MOD_PERL; 186*6287Sps156622 if ($r) { 187*6287Sps156622 $r->headers_out->add('Set-Cookie' => $self->as_string); 188*6287Sps156622 } else { 189*6287Sps156622 print CGI::header(-cookie => $self); 190*6287Sps156622 } 191*6287Sps156622 192*6287Sps156622} 193*6287Sps156622 1940Sstevel@tonic-gate# accessors 1950Sstevel@tonic-gatesub name { 1960Sstevel@tonic-gate my $self = shift; 1970Sstevel@tonic-gate my $name = shift; 1980Sstevel@tonic-gate $self->{'name'} = $name if defined $name; 1990Sstevel@tonic-gate return $self->{'name'}; 2000Sstevel@tonic-gate} 2010Sstevel@tonic-gate 2020Sstevel@tonic-gatesub value { 2030Sstevel@tonic-gate my $self = shift; 2040Sstevel@tonic-gate my $value = shift; 2050Sstevel@tonic-gate if (defined $value) { 2060Sstevel@tonic-gate my @values; 2070Sstevel@tonic-gate if (ref($value)) { 2080Sstevel@tonic-gate if (ref($value) eq 'ARRAY') { 2090Sstevel@tonic-gate @values = @$value; 2100Sstevel@tonic-gate } elsif (ref($value) eq 'HASH') { 2110Sstevel@tonic-gate @values = %$value; 2120Sstevel@tonic-gate } 2130Sstevel@tonic-gate } else { 2140Sstevel@tonic-gate @values = ($value); 2150Sstevel@tonic-gate } 2160Sstevel@tonic-gate $self->{'value'} = [@values]; 2170Sstevel@tonic-gate } 2180Sstevel@tonic-gate return wantarray ? @{$self->{'value'}} : $self->{'value'}->[0] 2190Sstevel@tonic-gate} 2200Sstevel@tonic-gate 2210Sstevel@tonic-gatesub domain { 2220Sstevel@tonic-gate my $self = shift; 2230Sstevel@tonic-gate my $domain = shift; 224667Sps156622 $self->{'domain'} = lc $domain if defined $domain; 2250Sstevel@tonic-gate return $self->{'domain'}; 2260Sstevel@tonic-gate} 2270Sstevel@tonic-gate 2280Sstevel@tonic-gatesub secure { 2290Sstevel@tonic-gate my $self = shift; 2300Sstevel@tonic-gate my $secure = shift; 2310Sstevel@tonic-gate $self->{'secure'} = $secure if defined $secure; 2320Sstevel@tonic-gate return $self->{'secure'}; 2330Sstevel@tonic-gate} 2340Sstevel@tonic-gate 2350Sstevel@tonic-gatesub expires { 2360Sstevel@tonic-gate my $self = shift; 2370Sstevel@tonic-gate my $expires = shift; 2380Sstevel@tonic-gate $self->{'expires'} = CGI::Util::expires($expires,'cookie') if defined $expires; 2390Sstevel@tonic-gate return $self->{'expires'}; 2400Sstevel@tonic-gate} 2410Sstevel@tonic-gate 2420Sstevel@tonic-gatesub max_age { 2430Sstevel@tonic-gate my $self = shift; 2440Sstevel@tonic-gate my $expires = shift; 2450Sstevel@tonic-gate $self->{'max-age'} = CGI::Util::expire_calc($expires)-time() if defined $expires; 2460Sstevel@tonic-gate return $self->{'max-age'}; 2470Sstevel@tonic-gate} 2480Sstevel@tonic-gate 2490Sstevel@tonic-gatesub path { 2500Sstevel@tonic-gate my $self = shift; 2510Sstevel@tonic-gate my $path = shift; 2520Sstevel@tonic-gate $self->{'path'} = $path if defined $path; 2530Sstevel@tonic-gate return $self->{'path'}; 2540Sstevel@tonic-gate} 2550Sstevel@tonic-gate 256*6287Sps156622 257*6287Sps156622sub httponly { # HttpOnly 258*6287Sps156622 my $self = shift; 259*6287Sps156622 my $httponly = shift; 260*6287Sps156622 $self->{'httponly'} = $httponly if defined $httponly; 261*6287Sps156622 return $self->{'httponly'}; 262*6287Sps156622} 263*6287Sps156622 2640Sstevel@tonic-gate1; 2650Sstevel@tonic-gate 2660Sstevel@tonic-gate=head1 NAME 2670Sstevel@tonic-gate 2680Sstevel@tonic-gateCGI::Cookie - Interface to Netscape Cookies 2690Sstevel@tonic-gate 2700Sstevel@tonic-gate=head1 SYNOPSIS 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate use CGI qw/:standard/; 2730Sstevel@tonic-gate use CGI::Cookie; 2740Sstevel@tonic-gate 2750Sstevel@tonic-gate # Create new cookies and send them 2760Sstevel@tonic-gate $cookie1 = new CGI::Cookie(-name=>'ID',-value=>123456); 2770Sstevel@tonic-gate $cookie2 = new CGI::Cookie(-name=>'preferences', 2780Sstevel@tonic-gate -value=>{ font => Helvetica, 2790Sstevel@tonic-gate size => 12 } 2800Sstevel@tonic-gate ); 2810Sstevel@tonic-gate print header(-cookie=>[$cookie1,$cookie2]); 2820Sstevel@tonic-gate 2830Sstevel@tonic-gate # fetch existing cookies 2840Sstevel@tonic-gate %cookies = fetch CGI::Cookie; 2850Sstevel@tonic-gate $id = $cookies{'ID'}->value; 2860Sstevel@tonic-gate 2870Sstevel@tonic-gate # create cookies returned from an external source 2880Sstevel@tonic-gate %cookies = parse CGI::Cookie($ENV{COOKIE}); 2890Sstevel@tonic-gate 2900Sstevel@tonic-gate=head1 DESCRIPTION 2910Sstevel@tonic-gate 2920Sstevel@tonic-gateCGI::Cookie is an interface to Netscape (HTTP/1.1) cookies, an 2930Sstevel@tonic-gateinnovation that allows Web servers to store persistent information on 2940Sstevel@tonic-gatethe browser's side of the connection. Although CGI::Cookie is 2950Sstevel@tonic-gateintended to be used in conjunction with CGI.pm (and is in fact used by 2960Sstevel@tonic-gateit internally), you can use this module independently. 2970Sstevel@tonic-gate 2980Sstevel@tonic-gateFor full information on cookies see 2990Sstevel@tonic-gate 3000Sstevel@tonic-gate http://www.ics.uci.edu/pub/ietf/http/rfc2109.txt 3010Sstevel@tonic-gate 3020Sstevel@tonic-gate=head1 USING CGI::Cookie 3030Sstevel@tonic-gate 3040Sstevel@tonic-gateCGI::Cookie is object oriented. Each cookie object has a name and a 3050Sstevel@tonic-gatevalue. The name is any scalar value. The value is any scalar or 3060Sstevel@tonic-gatearray value (associative arrays are also allowed). Cookies also have 3070Sstevel@tonic-gateseveral optional attributes, including: 3080Sstevel@tonic-gate 3090Sstevel@tonic-gate=over 4 3100Sstevel@tonic-gate 3110Sstevel@tonic-gate=item B<1. expiration date> 3120Sstevel@tonic-gate 3130Sstevel@tonic-gateThe expiration date tells the browser how long to hang on to the 3140Sstevel@tonic-gatecookie. If the cookie specifies an expiration date in the future, the 3150Sstevel@tonic-gatebrowser will store the cookie information in a disk file and return it 3160Sstevel@tonic-gateto the server every time the user reconnects (until the expiration 3170Sstevel@tonic-gatedate is reached). If the cookie species an expiration date in the 3180Sstevel@tonic-gatepast, the browser will remove the cookie from the disk file. If the 3190Sstevel@tonic-gateexpiration date is not specified, the cookie will persist only until 3200Sstevel@tonic-gatethe user quits the browser. 3210Sstevel@tonic-gate 3220Sstevel@tonic-gate=item B<2. domain> 3230Sstevel@tonic-gate 3240Sstevel@tonic-gateThis is a partial or complete domain name for which the cookie is 3250Sstevel@tonic-gatevalid. The browser will return the cookie to any host that matches 3260Sstevel@tonic-gatethe partial domain name. For example, if you specify a domain name 3270Sstevel@tonic-gateof ".capricorn.com", then Netscape will return the cookie to 3280Sstevel@tonic-gateWeb servers running on any of the machines "www.capricorn.com", 3290Sstevel@tonic-gate"ftp.capricorn.com", "feckless.capricorn.com", etc. Domain names 3300Sstevel@tonic-gatemust contain at least two periods to prevent attempts to match 3310Sstevel@tonic-gateon top level domains like ".edu". If no domain is specified, then 3320Sstevel@tonic-gatethe browser will only return the cookie to servers on the host the 3330Sstevel@tonic-gatecookie originated from. 3340Sstevel@tonic-gate 3350Sstevel@tonic-gate=item B<3. path> 3360Sstevel@tonic-gate 3370Sstevel@tonic-gateIf you provide a cookie path attribute, the browser will check it 3380Sstevel@tonic-gateagainst your script's URL before returning the cookie. For example, 3390Sstevel@tonic-gateif you specify the path "/cgi-bin", then the cookie will be returned 3400Sstevel@tonic-gateto each of the scripts "/cgi-bin/tally.pl", "/cgi-bin/order.pl", and 3410Sstevel@tonic-gate"/cgi-bin/customer_service/complain.pl", but not to the script 3420Sstevel@tonic-gate"/cgi-private/site_admin.pl". By default, the path is set to "/", so 3430Sstevel@tonic-gatethat all scripts at your site will receive the cookie. 3440Sstevel@tonic-gate 3450Sstevel@tonic-gate=item B<4. secure flag> 3460Sstevel@tonic-gate 3470Sstevel@tonic-gateIf the "secure" attribute is set, the cookie will only be sent to your 3480Sstevel@tonic-gatescript if the CGI request is occurring on a secure channel, such as SSL. 3490Sstevel@tonic-gate 350*6287Sps156622=item B<4. httponly flag> 351*6287Sps156622 352*6287Sps156622If the "httponly" attribute is set, the cookie will only be accessible 353*6287Sps156622through HTTP Requests. This cookie will be inaccessible via JavaScript 354*6287Sps156622(to prevent XSS attacks). 355*6287Sps156622 356*6287Sps156622But, currently this feature only used and recognised by 357*6287Sps156622MS Internet Explorer 6 Service Pack 1 and later. 358*6287Sps156622 359*6287Sps156622See this URL for more information: 360*6287Sps156622 361*6287Sps156622L<http://msdn.microsoft.com/workshop/author/dhtml/httponly_cookies.asp> 362*6287Sps156622 3630Sstevel@tonic-gate=back 3640Sstevel@tonic-gate 3650Sstevel@tonic-gate=head2 Creating New Cookies 3660Sstevel@tonic-gate 367*6287Sps156622 my $c = new CGI::Cookie(-name => 'foo', 3680Sstevel@tonic-gate -value => 'bar', 3690Sstevel@tonic-gate -expires => '+3M', 3700Sstevel@tonic-gate -domain => '.capricorn.com', 3710Sstevel@tonic-gate -path => '/cgi-bin/database', 3720Sstevel@tonic-gate -secure => 1 3730Sstevel@tonic-gate ); 3740Sstevel@tonic-gate 3750Sstevel@tonic-gateCreate cookies from scratch with the B<new> method. The B<-name> and 3760Sstevel@tonic-gateB<-value> parameters are required. The name must be a scalar value. 3770Sstevel@tonic-gateThe value can be a scalar, an array reference, or a hash reference. 3780Sstevel@tonic-gate(At some point in the future cookies will support one of the Perl 3790Sstevel@tonic-gateobject serialization protocols for full generality). 3800Sstevel@tonic-gate 3810Sstevel@tonic-gateB<-expires> accepts any of the relative or absolute date formats 3820Sstevel@tonic-gaterecognized by CGI.pm, for example "+3M" for three months in the 3830Sstevel@tonic-gatefuture. See CGI.pm's documentation for details. 3840Sstevel@tonic-gate 3850Sstevel@tonic-gateB<-domain> points to a domain name or to a fully qualified host name. 3860Sstevel@tonic-gateIf not specified, the cookie will be returned only to the Web server 3870Sstevel@tonic-gatethat created it. 3880Sstevel@tonic-gate 3890Sstevel@tonic-gateB<-path> points to a partial URL on the current server. The cookie 3900Sstevel@tonic-gatewill be returned to all URLs beginning with the specified path. If 3910Sstevel@tonic-gatenot specified, it defaults to '/', which returns the cookie to all 3920Sstevel@tonic-gatepages at your site. 3930Sstevel@tonic-gate 3940Sstevel@tonic-gateB<-secure> if set to a true value instructs the browser to return the 3950Sstevel@tonic-gatecookie only when a cryptographic protocol is in use. 3960Sstevel@tonic-gate 397*6287Sps156622B<-httponly> if set to a true value, the cookie will not be accessible 398*6287Sps156622via JavaScript. 399*6287Sps156622 400*6287Sps156622For compatibility with Apache::Cookie, you may optionally pass in 401*6287Sps156622a mod_perl request object as the first argument to C<new()>. It will 402*6287Sps156622simply be ignored: 403*6287Sps156622 404*6287Sps156622 my $c = new CGI::Cookie($r, 405*6287Sps156622 -name => 'foo', 406*6287Sps156622 -value => ['bar','baz']); 407*6287Sps156622 4080Sstevel@tonic-gate=head2 Sending the Cookie to the Browser 4090Sstevel@tonic-gate 410*6287Sps156622The simplest way to send a cookie to the browser is by calling the bake() 411*6287Sps156622method: 412*6287Sps156622 413*6287Sps156622 $c->bake; 414*6287Sps156622 415*6287Sps156622Under mod_perl, pass in an Apache request object: 416*6287Sps156622 417*6287Sps156622 $c->bake($r); 418*6287Sps156622 419*6287Sps156622If you want to set the cookie yourself, Within a CGI script you can send 420*6287Sps156622a cookie to the browser by creating one or more Set-Cookie: fields in the 421*6287Sps156622HTTP header. Here is a typical sequence: 4220Sstevel@tonic-gate 4230Sstevel@tonic-gate my $c = new CGI::Cookie(-name => 'foo', 4240Sstevel@tonic-gate -value => ['bar','baz'], 4250Sstevel@tonic-gate -expires => '+3M'); 4260Sstevel@tonic-gate 4270Sstevel@tonic-gate print "Set-Cookie: $c\n"; 4280Sstevel@tonic-gate print "Content-Type: text/html\n\n"; 4290Sstevel@tonic-gate 4300Sstevel@tonic-gateTo send more than one cookie, create several Set-Cookie: fields. 4310Sstevel@tonic-gate 4320Sstevel@tonic-gateIf you are using CGI.pm, you send cookies by providing a -cookie 4330Sstevel@tonic-gateargument to the header() method: 4340Sstevel@tonic-gate 4350Sstevel@tonic-gate print header(-cookie=>$c); 4360Sstevel@tonic-gate 4370Sstevel@tonic-gateMod_perl users can set cookies using the request object's header_out() 4380Sstevel@tonic-gatemethod: 4390Sstevel@tonic-gate 4400Sstevel@tonic-gate $r->headers_out->set('Set-Cookie' => $c); 4410Sstevel@tonic-gate 4420Sstevel@tonic-gateInternally, Cookie overloads the "" operator to call its as_string() 4430Sstevel@tonic-gatemethod when incorporated into the HTTP header. as_string() turns the 4440Sstevel@tonic-gateCookie's internal representation into an RFC-compliant text 4450Sstevel@tonic-gaterepresentation. You may call as_string() yourself if you prefer: 4460Sstevel@tonic-gate 4470Sstevel@tonic-gate print "Set-Cookie: ",$c->as_string,"\n"; 4480Sstevel@tonic-gate 4490Sstevel@tonic-gate=head2 Recovering Previous Cookies 4500Sstevel@tonic-gate 4510Sstevel@tonic-gate %cookies = fetch CGI::Cookie; 4520Sstevel@tonic-gate 4530Sstevel@tonic-gateB<fetch> returns an associative array consisting of all cookies 4540Sstevel@tonic-gatereturned by the browser. The keys of the array are the cookie names. You 4550Sstevel@tonic-gatecan iterate through the cookies this way: 4560Sstevel@tonic-gate 4570Sstevel@tonic-gate %cookies = fetch CGI::Cookie; 4580Sstevel@tonic-gate foreach (keys %cookies) { 4590Sstevel@tonic-gate do_something($cookies{$_}); 4600Sstevel@tonic-gate } 4610Sstevel@tonic-gate 4620Sstevel@tonic-gateIn a scalar context, fetch() returns a hash reference, which may be more 4630Sstevel@tonic-gateefficient if you are manipulating multiple cookies. 4640Sstevel@tonic-gate 4650Sstevel@tonic-gateCGI.pm uses the URL escaping methods to save and restore reserved characters 4660Sstevel@tonic-gatein its cookies. If you are trying to retrieve a cookie set by a foreign server, 4670Sstevel@tonic-gatethis escaping method may trip you up. Use raw_fetch() instead, which has the 4680Sstevel@tonic-gatesame semantics as fetch(), but performs no unescaping. 4690Sstevel@tonic-gate 4700Sstevel@tonic-gateYou may also retrieve cookies that were stored in some external 4710Sstevel@tonic-gateform using the parse() class method: 4720Sstevel@tonic-gate 4730Sstevel@tonic-gate $COOKIES = `cat /usr/tmp/Cookie_stash`; 4740Sstevel@tonic-gate %cookies = parse CGI::Cookie($COOKIES); 4750Sstevel@tonic-gate 4760Sstevel@tonic-gateIf you are in a mod_perl environment, you can save some overhead by 4770Sstevel@tonic-gatepassing the request object to fetch() like this: 4780Sstevel@tonic-gate 4790Sstevel@tonic-gate CGI::Cookie->fetch($r); 4800Sstevel@tonic-gate 4810Sstevel@tonic-gate=head2 Manipulating Cookies 4820Sstevel@tonic-gate 4830Sstevel@tonic-gateCookie objects have a series of accessor methods to get and set cookie 4840Sstevel@tonic-gateattributes. Each accessor has a similar syntax. Called without 4850Sstevel@tonic-gatearguments, the accessor returns the current value of the attribute. 4860Sstevel@tonic-gateCalled with an argument, the accessor changes the attribute and 4870Sstevel@tonic-gatereturns its new value. 4880Sstevel@tonic-gate 4890Sstevel@tonic-gate=over 4 4900Sstevel@tonic-gate 4910Sstevel@tonic-gate=item B<name()> 4920Sstevel@tonic-gate 4930Sstevel@tonic-gateGet or set the cookie's name. Example: 4940Sstevel@tonic-gate 4950Sstevel@tonic-gate $name = $c->name; 4960Sstevel@tonic-gate $new_name = $c->name('fred'); 4970Sstevel@tonic-gate 4980Sstevel@tonic-gate=item B<value()> 4990Sstevel@tonic-gate 5000Sstevel@tonic-gateGet or set the cookie's value. Example: 5010Sstevel@tonic-gate 5020Sstevel@tonic-gate $value = $c->value; 5030Sstevel@tonic-gate @new_value = $c->value(['a','b','c','d']); 5040Sstevel@tonic-gate 5050Sstevel@tonic-gateB<value()> is context sensitive. In a list context it will return 5060Sstevel@tonic-gatethe current value of the cookie as an array. In a scalar context it 5070Sstevel@tonic-gatewill return the B<first> value of a multivalued cookie. 5080Sstevel@tonic-gate 5090Sstevel@tonic-gate=item B<domain()> 5100Sstevel@tonic-gate 5110Sstevel@tonic-gateGet or set the cookie's domain. 5120Sstevel@tonic-gate 5130Sstevel@tonic-gate=item B<path()> 5140Sstevel@tonic-gate 5150Sstevel@tonic-gateGet or set the cookie's path. 5160Sstevel@tonic-gate 5170Sstevel@tonic-gate=item B<expires()> 5180Sstevel@tonic-gate 5190Sstevel@tonic-gateGet or set the cookie's expiration time. 5200Sstevel@tonic-gate 5210Sstevel@tonic-gate=back 5220Sstevel@tonic-gate 5230Sstevel@tonic-gate 5240Sstevel@tonic-gate=head1 AUTHOR INFORMATION 5250Sstevel@tonic-gate 5260Sstevel@tonic-gateCopyright 1997-1998, Lincoln D. Stein. All rights reserved. 5270Sstevel@tonic-gate 5280Sstevel@tonic-gateThis library is free software; you can redistribute it and/or modify 5290Sstevel@tonic-gateit under the same terms as Perl itself. 5300Sstevel@tonic-gate 5310Sstevel@tonic-gateAddress bug reports and comments to: lstein@cshl.org 5320Sstevel@tonic-gate 5330Sstevel@tonic-gate=head1 BUGS 5340Sstevel@tonic-gate 5350Sstevel@tonic-gateThis section intentionally left blank. 5360Sstevel@tonic-gate 5370Sstevel@tonic-gate=head1 SEE ALSO 5380Sstevel@tonic-gate 5390Sstevel@tonic-gateL<CGI::Carp>, L<CGI> 5400Sstevel@tonic-gate 5410Sstevel@tonic-gate=cut 542