| Filename | /usr/share/perl5/CGI/Cookie.pm |
| Statements | Executed 276 statements in 1.82ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 4 | 4 | 3 | 125µs | 226µs | CGI::Cookie::as_string |
| 2 | 2 | 2 | 55µs | 204µs | CGI::Cookie::new |
| 10 | 3 | 1 | 34µs | 34µs | CGI::Cookie::name |
| 1 | 1 | 1 | 26µs | 118µs | CGI::Cookie::parse |
| 7 | 3 | 2 | 20µs | 20µs | CGI::Cookie::value |
| 1 | 1 | 1 | 16µs | 98µs | CGI::Cookie::BEGIN@6 |
| 10 | 2 | 1 | 14µs | 14µs | CGI::Cookie::path |
| 1 | 1 | 1 | 12µs | 29µs | CGI::Cookie::BEGIN@3 |
| 1 | 1 | 1 | 11µs | 61µs | CGI::Cookie::BEGIN@11 |
| 1 | 1 | 1 | 10µs | 130µs | CGI::Cookie::fetch |
| 1 | 1 | 1 | 10µs | 26µs | CGI::Cookie::BEGIN@138 |
| 1 | 1 | 1 | 9µs | 18µs | CGI::Cookie::BEGIN@4 |
| 1 | 1 | 1 | 8µs | 42µs | CGI::Cookie::BEGIN@10 |
| 5 | 2 | 1 | 8µs | 8µs | CGI::Cookie::httponly |
| 4 | 1 | 1 | 6µs | 6µs | CGI::Cookie::domain |
| 4 | 1 | 1 | 5µs | 5µs | CGI::Cookie::max_age |
| 4 | 1 | 1 | 5µs | 5µs | CGI::Cookie::secure |
| 4 | 1 | 1 | 5µs | 5µs | CGI::Cookie::expires |
| 1 | 1 | 1 | 2µs | 2µs | CGI::Cookie::get_raw_cookie |
| 2 | 2 | 1 | 1µs | 1µs | CGI::Cookie::CORE:subst (opcode) |
| 0 | 0 | 0 | 0s | 0s | CGI::Cookie::bake |
| 0 | 0 | 0 | 0s | 0s | CGI::Cookie::compare |
| 0 | 0 | 0 | 0s | 0s | CGI::Cookie::raw_fetch |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package CGI::Cookie; | ||||
| 2 | |||||
| 3 | 2 | 29µs | 2 | 46µs | # spent 29µs (12+17) within CGI::Cookie::BEGIN@3 which was called:
# once (12µs+17µs) by CGI::cookie at line 3 # spent 29µs making 1 call to CGI::Cookie::BEGIN@3
# spent 17µs making 1 call to strict::import |
| 4 | 2 | 41µs | 2 | 26µs | # spent 18µs (9+8) within CGI::Cookie::BEGIN@4 which was called:
# once (9µs+8µs) by CGI::cookie at line 4 # spent 18µs making 1 call to CGI::Cookie::BEGIN@4
# spent 8µs making 1 call to warnings::import |
| 5 | |||||
| 6 | 2 | 39µs | 2 | 101µs | # spent 98µs (16+81) within CGI::Cookie::BEGIN@6 which was called:
# once (16µs+81µs) by CGI::cookie at line 6 # spent 98µs making 1 call to CGI::Cookie::BEGIN@6
# spent 4µs making 1 call to if::import |
| 7 | |||||
| 8 | 1 | 400ns | our $VERSION='4.09'; | ||
| 9 | |||||
| 10 | 2 | 37µs | 2 | 77µs | # spent 42µs (8+35) within CGI::Cookie::BEGIN@10 which was called:
# once (8µs+35µs) by CGI::cookie at line 10 # spent 42µs making 1 call to CGI::Cookie::BEGIN@10
# spent 34µs making 1 call to Exporter::import |
| 11 | 2 | 708µs | 2 | 111µs | # spent 61µs (11+50) within CGI::Cookie::BEGIN@11 which was called:
# once (11µs+50µs) by CGI::cookie at line 11 # spent 61µs making 1 call to CGI::Cookie::BEGIN@11
# spent 50µs making 1 call to overload::import |
| 12 | |||||
| 13 | 1 | 200ns | my $PERLEX = 0; | ||
| 14 | # Turn on special checking for ActiveState's PerlEx | ||||
| 15 | 1 | 700ns | $PERLEX++ if defined($ENV{'GATEWAY_INTERFACE'}) && $ENV{'GATEWAY_INTERFACE'} =~ /^CGI-PerlEx/; | ||
| 16 | |||||
| 17 | # Turn on special checking for mod_perl | ||||
| 18 | # PerlEx::DBI tries to fool DBI by setting MOD_PERL | ||||
| 19 | 1 | 100ns | my $MOD_PERL = 0; | ||
| 20 | 1 | 300ns | if (exists $ENV{MOD_PERL} && ! $PERLEX) { | ||
| 21 | if (exists $ENV{MOD_PERL_API_VERSION} && $ENV{MOD_PERL_API_VERSION} == 2) { | ||||
| 22 | $MOD_PERL = 2; | ||||
| 23 | require Apache2::RequestUtil; | ||||
| 24 | require APR::Table; | ||||
| 25 | } else { | ||||
| 26 | $MOD_PERL = 1; | ||||
| 27 | require Apache; | ||||
| 28 | } | ||||
| 29 | } | ||||
| 30 | |||||
| 31 | # fetch a list of cookies from the environment and | ||||
| 32 | # return as a hash. the cookies are parsed as normal | ||||
| 33 | # escaped URL data. | ||||
| 34 | # spent 130µs (10+120) within CGI::Cookie::fetch which was called:
# once (10µs+120µs) by CGI::cookie at line 12 of (eval 75)[CGI.pm:932] | ||||
| 35 | 1 | 300ns | my $class = shift; | ||
| 36 | 1 | 1µs | 1 | 2µs | my $raw_cookie = get_raw_cookie(@_) or return; # spent 2µs making 1 call to CGI::Cookie::get_raw_cookie |
| 37 | 1 | 3µs | 1 | 118µs | return $class->parse($raw_cookie); # spent 118µs making 1 call to CGI::Cookie::parse |
| 38 | } | ||||
| 39 | |||||
| 40 | # Fetch a list of cookies from the environment or the incoming headers and | ||||
| 41 | # return as a hash. The cookie values are not unescaped or altered in any way. | ||||
| 42 | sub raw_fetch { | ||||
| 43 | my $class = shift; | ||||
| 44 | my $raw_cookie = get_raw_cookie(@_) or return; | ||||
| 45 | my %results; | ||||
| 46 | my($key,$value); | ||||
| 47 | |||||
| 48 | my @pairs = split("[;,] ?",$raw_cookie); | ||||
| 49 | for my $pair ( @pairs ) { | ||||
| 50 | $pair =~ s/^\s+|\s+$//g; # trim leading trailing whitespace | ||||
| 51 | my ( $key, $value ) = split "=", $pair; | ||||
| 52 | |||||
| 53 | $value = defined $value ? $value : ''; | ||||
| 54 | $results{$key} = $value; | ||||
| 55 | } | ||||
| 56 | return wantarray ? %results : \%results; | ||||
| 57 | } | ||||
| 58 | |||||
| 59 | # spent 2µs within CGI::Cookie::get_raw_cookie which was called:
# once (2µs+0s) by CGI::Cookie::fetch at line 36 | ||||
| 60 | 1 | 100ns | my $r = shift; | ||
| 61 | 1 | 200ns | $r ||= eval { $MOD_PERL == 2 ? | ||
| 62 | Apache2::RequestUtil->request() : | ||||
| 63 | Apache->request } if $MOD_PERL; | ||||
| 64 | |||||
| 65 | 1 | 0s | return $r->headers_in->{'Cookie'} if $r; | ||
| 66 | |||||
| 67 | 1 | 0s | die "Run $r->subprocess_env; before calling fetch()" | ||
| 68 | if $MOD_PERL and !exists $ENV{REQUEST_METHOD}; | ||||
| 69 | |||||
| 70 | 1 | 5µs | return $ENV{HTTP_COOKIE} || $ENV{COOKIE}; | ||
| 71 | } | ||||
| 72 | |||||
| 73 | |||||
| 74 | # spent 118µs (26+92) within CGI::Cookie::parse which was called:
# once (26µs+92µs) by CGI::Cookie::fetch at line 37 | ||||
| 75 | 1 | 400ns | my ($self,$raw_cookie) = @_; | ||
| 76 | 1 | 100ns | return wantarray ? () : {} unless $raw_cookie; | ||
| 77 | |||||
| 78 | 1 | 100ns | my %results; | ||
| 79 | |||||
| 80 | 1 | 3µs | my @pairs = split("[;,] ?",$raw_cookie); | ||
| 81 | 1 | 700ns | for (@pairs) { | ||
| 82 | 1 | 5µs | 1 | 800ns | s/^\s+//; # spent 800ns making 1 call to CGI::Cookie::CORE:subst |
| 83 | 1 | 2µs | 1 | 600ns | s/\s+$//; # spent 600ns making 1 call to CGI::Cookie::CORE:subst |
| 84 | |||||
| 85 | 1 | 1µs | my($key,$value) = split("=",$_,2); | ||
| 86 | |||||
| 87 | # Some foreign cookies are not in name=value format, so ignore | ||||
| 88 | # them. | ||||
| 89 | 1 | 100ns | next if !defined($value); | ||
| 90 | 1 | 300ns | my @values = (); | ||
| 91 | 1 | 400ns | if ($value ne '') { | ||
| 92 | 1 | 5µs | 2 | 10µs | @values = map unescape($_),split(/[&;]/,$value.'&dmy'); # spent 10µs making 2 calls to CGI::Util::unescape, avg 5µs/call |
| 93 | 1 | 300ns | pop @values; | ||
| 94 | } | ||||
| 95 | 1 | 800ns | 1 | 3µs | $key = unescape($key); # spent 3µs making 1 call to CGI::Util::unescape |
| 96 | # A bug in Netscape can cause several cookies with same name to | ||||
| 97 | # appear. The FIRST one in HTTP_COOKIE is the most recent version. | ||||
| 98 | 1 | 3µs | 1 | 77µs | $results{$key} ||= $self->new(-name=>$key,-value=>\@values); # spent 77µs making 1 call to CGI::Cookie::new |
| 99 | } | ||||
| 100 | 1 | 4µs | return wantarray ? %results : \%results; | ||
| 101 | } | ||||
| 102 | |||||
| 103 | # spent 204µs (55+149) within CGI::Cookie::new which was called 2 times, avg 102µs/call:
# once (39µs+88µs) by CGI::cookie at line 33 of (eval 75)[CGI.pm:932]
# once (16µs+61µs) by CGI::Cookie::parse at line 98 | ||||
| 104 | 2 | 2µs | my ( $class, @params ) = @_; | ||
| 105 | 2 | 700ns | $class = ref( $class ) || $class; | ||
| 106 | # Ignore mod_perl request object--compatibility with Apache::Cookie. | ||||
| 107 | shift if ref $params[0] | ||||
| 108 | 2 | 500ns | && eval { $params[0]->isa('Apache::Request::Req') || $params[0]->isa('Apache') }; | ||
| 109 | 2 | 10µs | 2 | 105µs | my ( $name, $value, $path, $domain, $secure, $expires, $max_age, $httponly ) # spent 105µs making 2 calls to CGI::Util::rearrange, avg 52µs/call |
| 110 | = rearrange( | ||||
| 111 | [ | ||||
| 112 | 'NAME', [ 'VALUE', 'VALUES' ], | ||||
| 113 | 'PATH', 'DOMAIN', | ||||
| 114 | 'SECURE', 'EXPIRES', | ||||
| 115 | 'MAX-AGE','HTTPONLY' | ||||
| 116 | ], | ||||
| 117 | @params | ||||
| 118 | ); | ||||
| 119 | 2 | 1µs | return undef unless defined $name and defined $value; | ||
| 120 | 2 | 1µs | my $self = {}; | ||
| 121 | 2 | 3µs | bless $self, $class; | ||
| 122 | 2 | 5µs | 2 | 24µs | $self->name( $name ); # spent 24µs making 2 calls to CGI::Cookie::name, avg 12µs/call |
| 123 | 2 | 4µs | 2 | 12µs | $self->value( $value ); # spent 12µs making 2 calls to CGI::Cookie::value, avg 6µs/call |
| 124 | 2 | 800ns | $path ||= "/"; | ||
| 125 | 2 | 4µs | 2 | 6µs | $self->path( $path ) if defined $path; # spent 6µs making 2 calls to CGI::Cookie::path, avg 3µs/call |
| 126 | 2 | 700ns | $self->domain( $domain ) if defined $domain; | ||
| 127 | 2 | 400ns | $self->secure( $secure ) if defined $secure; | ||
| 128 | 2 | 400ns | $self->expires( $expires ) if defined $expires; | ||
| 129 | 2 | 400ns | $self->max_age( $max_age ) if defined $max_age; | ||
| 130 | 2 | 2µs | 1 | 3µs | $self->httponly( $httponly ) if defined $httponly; # spent 3µs making 1 call to CGI::Cookie::httponly |
| 131 | 2 | 7µs | return $self; | ||
| 132 | } | ||||
| 133 | |||||
| 134 | # spent 226µs (125+101) within CGI::Cookie::as_string which was called 4 times, avg 56µs/call:
# once (47µs+34µs) by C4::Output::output_with_http_headers at line 305 of C4/Output.pm
# once (29µs+25µs) by CGI::cookie at line 17 of (eval 75)[CGI.pm:932]
# once (26µs+23µs) by CGI::header at line 17 of (eval 81)[CGI.pm:932]
# once (22µs+19µs) by CGI::header at line 75 of (eval 81)[CGI.pm:932] | ||||
| 135 | 4 | 800ns | my $self = shift; | ||
| 136 | 4 | 5µs | 4 | 7µs | return "" unless $self->name; # spent 7µs making 4 calls to CGI::Cookie::name, avg 2µs/call |
| 137 | |||||
| 138 | 2 | 645µs | 2 | 42µs | # spent 26µs (10+16) within CGI::Cookie::BEGIN@138 which was called:
# once (10µs+16µs) by CGI::cookie at line 138 # spent 26µs making 1 call to CGI::Cookie::BEGIN@138
# spent 16µs making 1 call to warnings::unimport |
| 139 | |||||
| 140 | 4 | 9µs | 8 | 39µs | my $name = escape( $self->name ); # spent 36µs making 4 calls to CGI::Util::escape, avg 9µs/call
# spent 3µs making 4 calls to CGI::Cookie::name, avg 850ns/call |
| 141 | 8 | 27µs | 8 | 22µs | my $value = join "&", map { escape($_) } $self->value; # spent 15µs making 4 calls to CGI::Util::escape, avg 4µs/call
# spent 7µs making 4 calls to CGI::Cookie::value, avg 2µs/call |
| 142 | 4 | 5µs | my @cookie = ( "$name=$value" ); | ||
| 143 | |||||
| 144 | 4 | 5µs | 4 | 6µs | push @cookie,"domain=".$self->domain if $self->domain; # spent 6µs making 4 calls to CGI::Cookie::domain, avg 1µs/call |
| 145 | 4 | 9µs | 8 | 8µs | push @cookie,"path=".$self->path if $self->path; # spent 8µs making 8 calls to CGI::Cookie::path, avg 1µs/call |
| 146 | 4 | 4µs | 4 | 5µs | push @cookie,"expires=".$self->expires if $self->expires; # spent 5µs making 4 calls to CGI::Cookie::expires, avg 1µs/call |
| 147 | 4 | 4µs | 4 | 5µs | push @cookie,"max-age=".$self->max_age if $self->max_age; # spent 5µs making 4 calls to CGI::Cookie::max_age, avg 1µs/call |
| 148 | 4 | 4µs | 4 | 5µs | push @cookie,"secure" if $self->secure; # spent 5µs making 4 calls to CGI::Cookie::secure, avg 1µs/call |
| 149 | 4 | 4µs | 4 | 4µs | push @cookie,"HttpOnly" if $self->httponly; # spent 4µs making 4 calls to CGI::Cookie::httponly, avg 1µs/call |
| 150 | |||||
| 151 | 4 | 13µs | return join "; ", @cookie; | ||
| 152 | } | ||||
| 153 | |||||
| 154 | sub compare { | ||||
| 155 | my ( $self, $value ) = @_; | ||||
| 156 | return "$self" cmp $value; | ||||
| 157 | } | ||||
| 158 | |||||
| 159 | sub bake { | ||||
| 160 | my ($self, $r) = @_; | ||||
| 161 | |||||
| 162 | $r ||= eval { | ||||
| 163 | $MOD_PERL == 2 | ||||
| 164 | ? Apache2::RequestUtil->request() | ||||
| 165 | : Apache->request | ||||
| 166 | } if $MOD_PERL; | ||||
| 167 | if ($r) { | ||||
| 168 | $r->headers_out->add('Set-Cookie' => $self->as_string); | ||||
| 169 | } else { | ||||
| 170 | require CGI; | ||||
| 171 | print CGI::header(-cookie => $self); | ||||
| 172 | } | ||||
| 173 | |||||
| 174 | } | ||||
| 175 | |||||
| 176 | # accessors | ||||
| 177 | sub name { | ||||
| 178 | 10 | 3µs | my ( $self, $name ) = @_; | ||
| 179 | 10 | 20µs | $self->{'name'} = $name if defined $name; | ||
| 180 | 10 | 20µs | return $self->{'name'}; | ||
| 181 | } | ||||
| 182 | |||||
| 183 | # spent 20µs within CGI::Cookie::value which was called 7 times, avg 3µs/call:
# 4 times (7µs+0s) by CGI::Cookie::as_string at line 141, avg 2µs/call
# 2 times (12µs+0s) by CGI::Cookie::new at line 123, avg 6µs/call
# once (1µs+0s) by CGI::cookie at line 18 of (eval 75)[CGI.pm:932] | ||||
| 184 | 7 | 2µs | my ( $self, $value ) = @_; | ||
| 185 | 7 | 2µs | if ( defined $value ) { | ||
| 186 | my @values | ||||
| 187 | 2 | 3µs | = ref $value eq 'ARRAY' ? @$value | ||
| 188 | : ref $value eq 'HASH' ? %$value | ||||
| 189 | : ( $value ); | ||||
| 190 | 2 | 3µs | $self->{'value'} = [@values]; | ||
| 191 | } | ||||
| 192 | 7 | 18µs | return wantarray ? @{ $self->{'value'} } : $self->{'value'}->[0]; | ||
| 193 | } | ||||
| 194 | |||||
| 195 | # spent 6µs within CGI::Cookie::domain which was called 4 times, avg 1µs/call:
# 4 times (6µs+0s) by CGI::Cookie::as_string at line 144, avg 1µs/call | ||||
| 196 | 4 | 1µs | my ( $self, $domain ) = @_; | ||
| 197 | 4 | 700ns | $self->{'domain'} = lc $domain if defined $domain; | ||
| 198 | 4 | 8µs | return $self->{'domain'}; | ||
| 199 | } | ||||
| 200 | |||||
| 201 | # spent 5µs within CGI::Cookie::secure which was called 4 times, avg 1µs/call:
# 4 times (5µs+0s) by CGI::Cookie::as_string at line 148, avg 1µs/call | ||||
| 202 | 4 | 700ns | my ( $self, $secure ) = @_; | ||
| 203 | 4 | 500ns | $self->{'secure'} = $secure if defined $secure; | ||
| 204 | 4 | 7µs | return $self->{'secure'}; | ||
| 205 | } | ||||
| 206 | |||||
| 207 | # spent 5µs within CGI::Cookie::expires which was called 4 times, avg 1µs/call:
# 4 times (5µs+0s) by CGI::Cookie::as_string at line 146, avg 1µs/call | ||||
| 208 | 4 | 800ns | my ( $self, $expires ) = @_; | ||
| 209 | 4 | 700ns | $self->{'expires'} = CGI::Util::expires($expires,'cookie') if defined $expires; | ||
| 210 | 4 | 7µs | return $self->{'expires'}; | ||
| 211 | } | ||||
| 212 | |||||
| 213 | # spent 5µs within CGI::Cookie::max_age which was called 4 times, avg 1µs/call:
# 4 times (5µs+0s) by CGI::Cookie::as_string at line 147, avg 1µs/call | ||||
| 214 | 4 | 1µs | my ( $self, $max_age ) = @_; | ||
| 215 | 4 | 1µs | $self->{'max-age'} = CGI::Util::expire_calc($max_age)-time() if defined $max_age; | ||
| 216 | 4 | 7µs | return $self->{'max-age'}; | ||
| 217 | } | ||||
| 218 | |||||
| 219 | sub path { | ||||
| 220 | 10 | 2µs | my ( $self, $path ) = @_; | ||
| 221 | 10 | 2µs | $self->{'path'} = $path if defined $path; | ||
| 222 | 10 | 18µs | return $self->{'path'}; | ||
| 223 | } | ||||
| 224 | |||||
| 225 | |||||
| 226 | sub httponly { # HttpOnly | ||||
| 227 | 5 | 1µs | my ( $self, $httponly ) = @_; | ||
| 228 | 5 | 2µs | $self->{'httponly'} = $httponly if defined $httponly; | ||
| 229 | 5 | 11µs | return $self->{'httponly'}; | ||
| 230 | } | ||||
| 231 | |||||
| 232 | 1 | 6µs | 1; | ||
| 233 | |||||
| 234 | =head1 NAME | ||||
| 235 | |||||
| 236 | CGI::Cookie - Interface to HTTP Cookies | ||||
| 237 | |||||
| 238 | =head1 SYNOPSIS | ||||
| 239 | |||||
| 240 | use CGI qw/:standard/; | ||||
| 241 | use CGI::Cookie; | ||||
| 242 | |||||
| 243 | # Create new cookies and send them | ||||
| 244 | $cookie1 = CGI::Cookie->new(-name=>'ID',-value=>123456); | ||||
| 245 | $cookie2 = CGI::Cookie->new(-name=>'preferences', | ||||
| 246 | -value=>{ font => Helvetica, | ||||
| 247 | size => 12 } | ||||
| 248 | ); | ||||
| 249 | print header(-cookie=>[$cookie1,$cookie2]); | ||||
| 250 | |||||
| 251 | # fetch existing cookies | ||||
| 252 | %cookies = CGI::Cookie->fetch; | ||||
| 253 | $id = $cookies{'ID'}->value; | ||||
| 254 | |||||
| 255 | # create cookies returned from an external source | ||||
| 256 | %cookies = CGI::Cookie->parse($ENV{COOKIE}); | ||||
| 257 | |||||
| 258 | =head1 DESCRIPTION | ||||
| 259 | |||||
| 260 | CGI::Cookie is an interface to HTTP/1.1 cookies, a mechanism | ||||
| 261 | that allows Web servers to store persistent information on | ||||
| 262 | the browser's side of the connection. Although CGI::Cookie is | ||||
| 263 | intended to be used in conjunction with CGI.pm (and is in fact used by | ||||
| 264 | it internally), you can use this module independently. | ||||
| 265 | |||||
| 266 | For full information on cookies see | ||||
| 267 | |||||
| 268 | https://tools.ietf.org/html/rfc6265 | ||||
| 269 | |||||
| 270 | =head1 USING CGI::Cookie | ||||
| 271 | |||||
| 272 | CGI::Cookie is object oriented. Each cookie object has a name and a | ||||
| 273 | value. The name is any scalar value. The value is any scalar or | ||||
| 274 | array value (associative arrays are also allowed). Cookies also have | ||||
| 275 | several optional attributes, including: | ||||
| 276 | |||||
| 277 | =over 4 | ||||
| 278 | |||||
| 279 | =item B<1. expiration date> | ||||
| 280 | |||||
| 281 | The expiration date tells the browser how long to hang on to the | ||||
| 282 | cookie. If the cookie specifies an expiration date in the future, the | ||||
| 283 | browser will store the cookie information in a disk file and return it | ||||
| 284 | to the server every time the user reconnects (until the expiration | ||||
| 285 | date is reached). If the cookie species an expiration date in the | ||||
| 286 | past, the browser will remove the cookie from the disk file. If the | ||||
| 287 | expiration date is not specified, the cookie will persist only until | ||||
| 288 | the user quits the browser. | ||||
| 289 | |||||
| 290 | =item B<2. domain> | ||||
| 291 | |||||
| 292 | This is a partial or complete domain name for which the cookie is | ||||
| 293 | valid. The browser will return the cookie to any host that matches | ||||
| 294 | the partial domain name. For example, if you specify a domain name | ||||
| 295 | of ".capricorn.com", then the browser will return the cookie to | ||||
| 296 | Web servers running on any of the machines "www.capricorn.com", | ||||
| 297 | "ftp.capricorn.com", "feckless.capricorn.com", etc. Domain names | ||||
| 298 | must contain at least two periods to prevent attempts to match | ||||
| 299 | on top level domains like ".edu". If no domain is specified, then | ||||
| 300 | the browser will only return the cookie to servers on the host the | ||||
| 301 | cookie originated from. | ||||
| 302 | |||||
| 303 | =item B<3. path> | ||||
| 304 | |||||
| 305 | If you provide a cookie path attribute, the browser will check it | ||||
| 306 | against your script's URL before returning the cookie. For example, | ||||
| 307 | if you specify the path "/cgi-bin", then the cookie will be returned | ||||
| 308 | to each of the scripts "/cgi-bin/tally.pl", "/cgi-bin/order.pl", and | ||||
| 309 | "/cgi-bin/customer_service/complain.pl", but not to the script | ||||
| 310 | "/cgi-private/site_admin.pl". By default, the path is set to "/", so | ||||
| 311 | that all scripts at your site will receive the cookie. | ||||
| 312 | |||||
| 313 | =item B<4. secure flag> | ||||
| 314 | |||||
| 315 | If the "secure" attribute is set, the cookie will only be sent to your | ||||
| 316 | script if the CGI request is occurring on a secure channel, such as SSL. | ||||
| 317 | |||||
| 318 | =item B<5. httponly flag> | ||||
| 319 | |||||
| 320 | If the "httponly" attribute is set, the cookie will only be accessible | ||||
| 321 | through HTTP Requests. This cookie will be inaccessible via JavaScript | ||||
| 322 | (to prevent XSS attacks). | ||||
| 323 | |||||
| 324 | This feature is supported by nearly all modern browsers. | ||||
| 325 | |||||
| 326 | See these URLs for more information: | ||||
| 327 | |||||
| 328 | http://msdn.microsoft.com/en-us/library/ms533046.aspx | ||||
| 329 | http://www.browserscope.org/?category=security&v=top | ||||
| 330 | |||||
| 331 | =back | ||||
| 332 | |||||
| 333 | =head2 Creating New Cookies | ||||
| 334 | |||||
| 335 | my $c = CGI::Cookie->new(-name => 'foo', | ||||
| 336 | -value => 'bar', | ||||
| 337 | -expires => '+3M', | ||||
| 338 | '-max-age' => '+3M', | ||||
| 339 | -domain => '.capricorn.com', | ||||
| 340 | -path => '/cgi-bin/database', | ||||
| 341 | -secure => 1 | ||||
| 342 | ); | ||||
| 343 | |||||
| 344 | Create cookies from scratch with the B<new> method. The B<-name> and | ||||
| 345 | B<-value> parameters are required. The name must be a scalar value. | ||||
| 346 | The value can be a scalar, an array reference, or a hash reference. | ||||
| 347 | (At some point in the future cookies will support one of the Perl | ||||
| 348 | object serialization protocols for full generality). | ||||
| 349 | |||||
| 350 | B<-expires> accepts any of the relative or absolute date formats | ||||
| 351 | recognized by CGI.pm, for example "+3M" for three months in the | ||||
| 352 | future. See CGI.pm's documentation for details. | ||||
| 353 | |||||
| 354 | B<-max-age> accepts the same data formats as B<< -expires >>, but sets a | ||||
| 355 | relative value instead of an absolute like B<< -expires >>. This is intended to be | ||||
| 356 | more secure since a clock could be changed to fake an absolute time. In | ||||
| 357 | practice, as of 2011, C<< -max-age >> still does not enjoy the widespread support | ||||
| 358 | that C<< -expires >> has. You can set both, and browsers that support | ||||
| 359 | C<< -max-age >> should ignore the C<< Expires >> header. The drawback | ||||
| 360 | to this approach is the bit of bandwidth for sending an extra header on each cookie. | ||||
| 361 | |||||
| 362 | B<-domain> points to a domain name or to a fully qualified host name. | ||||
| 363 | If not specified, the cookie will be returned only to the Web server | ||||
| 364 | that created it. | ||||
| 365 | |||||
| 366 | B<-path> points to a partial URL on the current server. The cookie | ||||
| 367 | will be returned to all URLs beginning with the specified path. If | ||||
| 368 | not specified, it defaults to '/', which returns the cookie to all | ||||
| 369 | pages at your site. | ||||
| 370 | |||||
| 371 | B<-secure> if set to a true value instructs the browser to return the | ||||
| 372 | cookie only when a cryptographic protocol is in use. | ||||
| 373 | |||||
| 374 | B<-httponly> if set to a true value, the cookie will not be accessible | ||||
| 375 | via JavaScript. | ||||
| 376 | |||||
| 377 | For compatibility with Apache::Cookie, you may optionally pass in | ||||
| 378 | a mod_perl request object as the first argument to C<new()>. It will | ||||
| 379 | simply be ignored: | ||||
| 380 | |||||
| 381 | my $c = CGI::Cookie->new($r, | ||||
| 382 | -name => 'foo', | ||||
| 383 | -value => ['bar','baz']); | ||||
| 384 | |||||
| 385 | =head2 Sending the Cookie to the Browser | ||||
| 386 | |||||
| 387 | The simplest way to send a cookie to the browser is by calling the bake() | ||||
| 388 | method: | ||||
| 389 | |||||
| 390 | $c->bake; | ||||
| 391 | |||||
| 392 | This will print the Set-Cookie HTTP header to STDOUT using CGI.pm. CGI.pm | ||||
| 393 | will be loaded for this purpose if it is not already. Otherwise CGI.pm is not | ||||
| 394 | required or used by this module. | ||||
| 395 | |||||
| 396 | Under mod_perl, pass in an Apache request object: | ||||
| 397 | |||||
| 398 | $c->bake($r); | ||||
| 399 | |||||
| 400 | If you want to set the cookie yourself, Within a CGI script you can send | ||||
| 401 | a cookie to the browser by creating one or more Set-Cookie: fields in the | ||||
| 402 | HTTP header. Here is a typical sequence: | ||||
| 403 | |||||
| 404 | my $c = CGI::Cookie->new(-name => 'foo', | ||||
| 405 | -value => ['bar','baz'], | ||||
| 406 | -expires => '+3M'); | ||||
| 407 | |||||
| 408 | print "Set-Cookie: $c\n"; | ||||
| 409 | print "Content-Type: text/html\n\n"; | ||||
| 410 | |||||
| 411 | To send more than one cookie, create several Set-Cookie: fields. | ||||
| 412 | |||||
| 413 | If you are using CGI.pm, you send cookies by providing a -cookie | ||||
| 414 | argument to the header() method: | ||||
| 415 | |||||
| 416 | print header(-cookie=>$c); | ||||
| 417 | |||||
| 418 | Mod_perl users can set cookies using the request object's header_out() | ||||
| 419 | method: | ||||
| 420 | |||||
| 421 | $r->headers_out->set('Set-Cookie' => $c); | ||||
| 422 | |||||
| 423 | Internally, Cookie overloads the "" operator to call its as_string() | ||||
| 424 | method when incorporated into the HTTP header. as_string() turns the | ||||
| 425 | Cookie's internal representation into an RFC-compliant text | ||||
| 426 | representation. You may call as_string() yourself if you prefer: | ||||
| 427 | |||||
| 428 | print "Set-Cookie: ",$c->as_string,"\n"; | ||||
| 429 | |||||
| 430 | =head2 Recovering Previous Cookies | ||||
| 431 | |||||
| 432 | %cookies = CGI::Cookie->fetch; | ||||
| 433 | |||||
| 434 | B<fetch> returns an associative array consisting of all cookies | ||||
| 435 | returned by the browser. The keys of the array are the cookie names. You | ||||
| 436 | can iterate through the cookies this way: | ||||
| 437 | |||||
| 438 | %cookies = CGI::Cookie->fetch; | ||||
| 439 | for (keys %cookies) { | ||||
| 440 | do_something($cookies{$_}); | ||||
| 441 | } | ||||
| 442 | |||||
| 443 | In a scalar context, fetch() returns a hash reference, which may be more | ||||
| 444 | efficient if you are manipulating multiple cookies. | ||||
| 445 | |||||
| 446 | CGI.pm uses the URL escaping methods to save and restore reserved characters | ||||
| 447 | in its cookies. If you are trying to retrieve a cookie set by a foreign server, | ||||
| 448 | this escaping method may trip you up. Use raw_fetch() instead, which has the | ||||
| 449 | same semantics as fetch(), but performs no unescaping. | ||||
| 450 | |||||
| 451 | You may also retrieve cookies that were stored in some external | ||||
| 452 | form using the parse() class method: | ||||
| 453 | |||||
| 454 | $COOKIES = `cat /usr/tmp/Cookie_stash`; | ||||
| 455 | %cookies = CGI::Cookie->parse($COOKIES); | ||||
| 456 | |||||
| 457 | If you are in a mod_perl environment, you can save some overhead by | ||||
| 458 | passing the request object to fetch() like this: | ||||
| 459 | |||||
| 460 | CGI::Cookie->fetch($r); | ||||
| 461 | |||||
| 462 | If the value passed to parse() is undefined, an empty array will returned in list | ||||
| 463 | context, and an empty hashref will be returned in scalar context. | ||||
| 464 | |||||
| 465 | =head2 Manipulating Cookies | ||||
| 466 | |||||
| 467 | Cookie objects have a series of accessor methods to get and set cookie | ||||
| 468 | attributes. Each accessor has a similar syntax. Called without | ||||
| 469 | arguments, the accessor returns the current value of the attribute. | ||||
| 470 | Called with an argument, the accessor changes the attribute and | ||||
| 471 | returns its new value. | ||||
| 472 | |||||
| 473 | =over 4 | ||||
| 474 | |||||
| 475 | =item B<name()> | ||||
| 476 | |||||
| 477 | Get or set the cookie's name. Example: | ||||
| 478 | |||||
| 479 | $name = $c->name; | ||||
| 480 | $new_name = $c->name('fred'); | ||||
| 481 | |||||
| 482 | =item B<value()> | ||||
| 483 | |||||
| 484 | Get or set the cookie's value. Example: | ||||
| 485 | |||||
| 486 | $value = $c->value; | ||||
| 487 | @new_value = $c->value(['a','b','c','d']); | ||||
| 488 | |||||
| 489 | B<value()> is context sensitive. In a list context it will return | ||||
| 490 | the current value of the cookie as an array. In a scalar context it | ||||
| 491 | will return the B<first> value of a multivalued cookie. | ||||
| 492 | |||||
| 493 | =item B<domain()> | ||||
| 494 | |||||
| 495 | Get or set the cookie's domain. | ||||
| 496 | |||||
| 497 | =item B<path()> | ||||
| 498 | |||||
| 499 | Get or set the cookie's path. | ||||
| 500 | |||||
| 501 | =item B<expires()> | ||||
| 502 | |||||
| 503 | Get or set the cookie's expiration time. | ||||
| 504 | |||||
| 505 | =item B<max_age()> | ||||
| 506 | |||||
| 507 | Get or set the cookie's max_age value. | ||||
| 508 | |||||
| 509 | =back | ||||
| 510 | |||||
| 511 | |||||
| 512 | =head1 AUTHOR INFORMATION | ||||
| 513 | |||||
| 514 | The CGI.pm distribution is copyright 1995-2007, Lincoln D. Stein. It is | ||||
| 515 | distributed under GPL and the Artistic License 2.0. It is currently | ||||
| 516 | maintained by Lee Johnson with help from many contributors. | ||||
| 517 | |||||
| 518 | Address bug reports and comments to: https://github.com/leejo/CGI.pm/issues | ||||
| 519 | |||||
| 520 | The original bug tracker can be found at: https://rt.cpan.org/Public/Dist/Display.html?Queue=CGI.pm | ||||
| 521 | |||||
| 522 | When sending bug reports, please provide the version of CGI.pm, the version of | ||||
| 523 | Perl, the name and version of your Web server, and the name and version of the | ||||
| 524 | operating system you are using. If the problem is even remotely browser | ||||
| 525 | dependent, please provide information about the affected browsers as well. | ||||
| 526 | |||||
| 527 | =head1 BUGS | ||||
| 528 | |||||
| 529 | This section intentionally left blank. | ||||
| 530 | |||||
| 531 | =head1 SEE ALSO | ||||
| 532 | |||||
| 533 | L<CGI::Carp>, L<CGI> | ||||
| 534 | |||||
| 535 | L<RFC 2109|http://www.ietf.org/rfc/rfc2109.txt>, L<RFC 2695|http://www.ietf.org/rfc/rfc2965.txt> | ||||
| 536 | |||||
| 537 | =cut | ||||
sub CGI::Cookie::CORE:subst; # opcode |