ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-HTTP/HTTP.pm
(Generate patch)

Comparing AnyEvent-HTTP/HTTP.pm (file contents):
Revision 1.79 by root, Sat Jan 1 20:01:07 2011 UTC vs.
Revision 1.80 by root, Sat Jan 1 21:51:22 2011 UTC

196=item cookie_jar => $hash_ref 196=item cookie_jar => $hash_ref
197 197
198Passing this parameter enables (simplified) cookie-processing, loosely 198Passing this parameter enables (simplified) cookie-processing, loosely
199based on the original netscape specification. 199based on the original netscape specification.
200 200
201The C<$hash_ref> must be an (initially empty) hash reference which will 201The C<$hash_ref> must be an (initially empty) hash reference which
202get updated automatically. It is possible to save the cookie jar to 202will get updated automatically. It is possible to save the cookie jar
203persistent storage with something like JSON or Storable, but this is not 203to persistent storage with something like JSON or Storable - see the
204recommended, as session-only cookies might survive longer than expected. 204C<AnyEvent::HTTP::cookie_jar_expire> function if you wish to remove
205expired or session-only cookies, and also for documentation on the format
206of the cookie jar.
205 207
206Note that this cookie implementation is not meant to be complete. If 208Note that this cookie implementation is not meant to be complete. If
207you want complete cookie management you have to do that on your 209you want complete cookie management you have to do that on your
208own. C<cookie_jar> is meant as a quick fix to get some cookie-using sites 210own. C<cookie_jar> is meant as a quick fix to get most cookie-using sites
209working. Cookies are a privacy disaster, do not use them unless required 211working. Cookies are a privacy disaster, do not use them unless required
210to. 212to.
211 213
212When cookie processing is enabled, the C<Cookie:> and C<Set-Cookie:> 214When cookie processing is enabled, the C<Cookie:> and C<Set-Cookie:>
213headers will be set and handled by this module, otherwise they will be 215headers will be set and handled by this module, otherwise they will be
378 push @{ $CO_SLOT{$_[0]}[1] }, $_[1]; 380 push @{ $CO_SLOT{$_[0]}[1] }, $_[1];
379 381
380 _slot_schedule $_[0]; 382 _slot_schedule $_[0];
381} 383}
382 384
385#############################################################################
386
387# expire cookies
388sub cookie_jar_expire($;$) {
389 my ($jar, $session_end) = @_;
390
391 %$jar = () if $jar->{version} != 1;
392
393 my $anow = AE::now;
394
395 while (my ($chost, $paths) = each %$jar) {
396 next unless ref $paths;
397
398 while (my ($cpath, $cookies) = each %$paths) {
399 while (my ($cookie, $kv) = each %$cookies) {
400 if (exists $kv->{_expires}) {
401 delete $cookies->{$cookie}
402 if $anow > $kv->{_expires};
403 } elsif ($session_end) {
404 delete $cookies->{$cookie};
405 }
406 }
407
408 delete $paths->{$cpath}
409 unless %$cookies;
410 }
411
412 delete $jar->{$chost}
413 unless %$paths;
414 }
415}
416
383# extract cookies from jar 417# extract cookies from jar
384sub cookie_jar_extract($$$$) { 418sub cookie_jar_extract($$$$) {
385 my ($jar, $uscheme, $uhost, $upath) = @_; 419 my ($jar, $uscheme, $uhost, $upath) = @_;
386 420
387 %$jar = () if $jar->{version} != 1; 421 %$jar = () if $jar->{version} != 1;
403 next unless $cpath eq substr $upath, 0, length $cpath; 437 next unless $cpath eq substr $upath, 0, length $cpath;
404 438
405 while (my ($cookie, $kv) = each %$cookies) { 439 while (my ($cookie, $kv) = each %$cookies) {
406 next if $uscheme ne "https" && exists $kv->{secure}; 440 next if $uscheme ne "https" && exists $kv->{secure};
407 441
408 if (exists $kv->{expires}) { 442 if (exists $kv->{_expires} and AE::now > $kv->{_expires}) {
409 if (AE::now > parse_date ($kv->{expires})) {
410 delete $cookies->{$cookie}; 443 delete $cookies->{$cookie};
411 next; 444 next;
412 }
413 } 445 }
414 446
415 my $value = $kv->{value}; 447 my $value = $kv->{value};
416 448
417 if ($value =~ /[=;,[:space:]]/) { 449 if ($value =~ /[=;,[:space:]]/) {
426 458
427 \@cookies 459 \@cookies
428} 460}
429 461
430# parse set_cookie header into jar 462# parse set_cookie header into jar
431sub cookie_jar_set_cookie($$$) { 463sub cookie_jar_set_cookie($$$$) {
432 my ($jar, $set_cookie, $uhost) = @_; 464 my ($jar, $set_cookie, $uhost, $date) = @_;
465
466 my $anow = int AE::now;
467 my $snow; # server-now
433 468
434 for ($set_cookie) { 469 for ($set_cookie) {
435 # parse NAME=VALUE 470 # parse NAME=VALUE
436 my @kv; 471 my @kv;
437 472
467 last unless @kv; 502 last unless @kv;
468 503
469 my $name = shift @kv; 504 my $name = shift @kv;
470 my %kv = (value => shift @kv, @kv); 505 my %kv = (value => shift @kv, @kv);
471 506
472 $kv{expires} ||= format_date (AE::now + $kv{"max-age"})
473 if exists $kv{"max-age"}; 507 if (exists $kv{"max-age"}) {
508 $kv{_expires} = $anow + delete $kv{"max-age"};
509 } elsif (exists $kv{expires}) {
510 $snow ||= parse_date ($date) || $anow;
511 $kv{_expires} = $anow + (parse_date (delete $kv{expires}) - $snow);
512 } else {
513 delete $kv{_expires};
514 }
474 515
475 my $cdom; 516 my $cdom;
476 my $cpath = (delete $kv{path}) || "/"; 517 my $cpath = (delete $kv{path}) || "/";
477 518
478 if (exists $kv{domain}) { 519 if (exists $kv{domain}) {
752 $hdr{OrigReason} = $hdr{Reason}; $hdr{Reason} = $_[2]; 793 $hdr{OrigReason} = $hdr{Reason}; $hdr{Reason} = $_[2];
753 } 794 }
754 795
755 # set-cookie processing 796 # set-cookie processing
756 if ($arg{cookie_jar}) { 797 if ($arg{cookie_jar}) {
757 cookie_jar_set_cookie $arg{cookie_jar}, $hdr{"set-cookie"}, $uhost; 798 cookie_jar_set_cookie $arg{cookie_jar}, $hdr{"set-cookie"}, $uhost, $hdr{date};
758 } 799 }
759 800
760 if ($redirect && exists $hdr{location}) { 801 if ($redirect && exists $hdr{location}) {
761 # we ignore any errors, as it is very common to receive 802 # we ignore any errors, as it is very common to receive
762 # Content-Length != 0 but no actual body 803 # Content-Length != 0 but no actual body
958string of the form C<http://host:port> (optionally C<https:...>), croaks 999string of the form C<http://host:port> (optionally C<https:...>), croaks
959otherwise. 1000otherwise.
960 1001
961To clear an already-set proxy, use C<undef>. 1002To clear an already-set proxy, use C<undef>.
962 1003
1004=item AnyEvent::HTTP::cookie_jar_expire $jar[, $session_end]
1005
1006Remove all cookies from the cookie jar that have been expired. If
1007C<$session_end> is given and true, then additionally remove all session
1008cookies.
1009
1010You should call this function (with a true C<$session_end>) before you
1011save cookies to disk, and you should call this function after loading them
1012again. If you have a long-running program you can additonally call this
1013function from time to time.
1014
1015A cookie jar is initially an empty hash-reference that is managed by this
1016module. It's format is subject to change, but currently it is like this:
1017
1018The key C<version> has to contain C<1>, otherwise the hash gets
1019emptied. All other keys are hostnames or IP addresses pointing to
1020hash-references. The key for these inner hash references is the
1021server path for which this cookie is meant, and the values are again
1022hash-references. The keys of those hash-references is the cookie name, and
1023the value, you guessed it, is another hash-reference, this time with the
1024key-value pairs from the cookie, except for C<expires> and C<max-age>,
1025which have been replaced by a C<_expires> key that contains the cookie
1026expiry timestamp.
1027
1028Here is an example of a cookie jar with a single cookie, so you have a
1029chance of understanding the above paragraph:
1030
1031 {
1032 version => 1,
1033 "10.0.0.1" => {
1034 "/" => {
1035 "mythweb_id" => {
1036 _expires => 1293917923,
1037 value => "ooRung9dThee3ooyXooM1Ohm",
1038 },
1039 },
1040 },
1041 }
1042
963=item $date = AnyEvent::HTTP::format_date $timestamp 1043=item $date = AnyEvent::HTTP::format_date $timestamp
964 1044
965Takes a POSIX timestamp (seconds since the epoch) and formats it as a HTTP 1045Takes a POSIX timestamp (seconds since the epoch) and formats it as a HTTP
966Date (RFC 2616). 1046Date (RFC 2616).
967 1047

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines