⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cookies.pm

📁 1. 记录每个帖子的访问人情况
💻 PM
📖 第 1 页 / 共 2 页
字号:
package HTTP::Cookies;use strict;use HTTP::Date qw(str2time time2str);use HTTP::Headers::Util qw(split_header_words join_header_words);use LWP::Debug ();use vars qw($VERSION);$VERSION = sprintf("%d.%02d", q$Revision: 1.24 $ =~ /(\d+)\.(\d+)/);my $EPOCH_OFFSET = 0;  # difference from Unix epochif ($^O eq "MacOS") {    require Time::Local;    $EPOCH_OFFSET = Time::Local::timelocal(0,0,0,1,0,70);}=head1 NAMEHTTP::Cookies - Cookie storage and management=head1 SYNOPSIS use HTTP::Cookies; $cookie_jar = HTTP::Cookies->new; $cookie_jar->add_cookie_header($request); $cookie_jar->extract_cookies($response);=head1 DESCRIPTIONCookies are a general mechanism which server side connections can useto both store and retrieve information on the client side of theconnection.  For more information about cookies refer to<URL:http://www.netscape.com/newsref/std/cookie_spec.html> and<URL:http://www.cookiecentral.com/>.  This module also implements thenew style cookies described in I<RFC 2965>.The two variants of cookies are supposed to be able to coexist happily.Instances of the class I<HTTP::Cookies> are able to store a collectionof Set-Cookie2: and Set-Cookie: headers and are able to use thisinformation to initialize Cookie-headers in I<HTTP::Request> objects.The state of a I<HTTP::Cookies> object can be saved in and restored fromfiles.=head1 METHODSThe following methods are provided:=over 4=cut# A HTTP::Cookies object is a hash.  The main attribute is the# COOKIES 3 level hash:  $self->{COOKIES}{$domain}{$path}{$key}.=item $cookie_jar = HTTP::Cookies->new;The constructor takes hash style parameters.  The followingparameters are recognized:  file:            name of the file to restore cookies from and save cookies to  autosave:        save during destruction (bool)  ignore_discard:  save even cookies that are requested to be discarded (bool)  hide_cookie2:    don't add Cookie2 header to requestsFuture parameters might include (not yet implemented):  max_cookies               300  max_cookies_per_domain    20  max_cookie_size           4096  no_cookies   list of domain names that we never return cookies to=cutsub new{    my $class = shift;    my $self = bless {	COOKIES => {},    }, $class;    my %cnf = @_;    for (keys %cnf) {	$self->{lc($_)} = $cnf{$_};    }    $self->load;    $self;}=item $cookie_jar->add_cookie_header($request);The add_cookie_header() method will set the appropriate Cookie:-headerfor the I<HTTP::Request> object given as argument.  The $request musthave a valid url attribute before this method is called.=cutsub add_cookie_header{    my $self = shift;    my $request = shift || return;    my $url = $request->url;    my $domain = _host($request, $url);    $domain = "$domain.local" unless $domain =~ /\./;    my $secure_request = ($url->scheme eq "https");    my $req_path = _url_path($url);    my $req_port = $url->port;    my $now = time();    _normalize_path($req_path) if $req_path =~ /%/;    my @cval;    # cookie values for the "Cookie" header    my $set_ver;    my $netscape_only = 0; # An exact domain match applies to any cookie    while ($domain =~ /\./) {        LWP::Debug::debug("Checking $domain for cookies");	my $cookies = $self->{COOKIES}{$domain};	next unless $cookies;	# Want to add cookies corresponding to the most specific paths	# first (i.e. longest path first)	my $path;	for $path (sort {length($b) <=> length($a) } keys %$cookies) {            LWP::Debug::debug("- checking cookie path=$path");	    if (index($req_path, $path) != 0) {	        LWP::Debug::debug("  path $path:$req_path does not fit");		next;	    }	    my($key,$array);	    while (($key,$array) = each %{$cookies->{$path}}) {		my($version,$val,$port,$path_spec,$secure,$expires) = @$array;	        LWP::Debug::debug(" - checking cookie $key=$val");		if ($secure && !$secure_request) {		    LWP::Debug::debug("   not a secure requests");		    next;		}		if ($expires && $expires < $now) {		    LWP::Debug::debug("   expired");		    next;		}		if ($port) {		    my $found;		    if ($port =~ s/^_//) {			# The correponding Set-Cookie attribute was empty			$found++ if $port eq $req_port;			$port = "";		    } else {			my $p;			for $p (split(/,/, $port)) {			    $found++, last if $p eq $req_port;			}		    }		    unless ($found) {		        LWP::Debug::debug("   port $port:$req_port does not fit");			next;		    }		}		if ($version > 0 && $netscape_only) {		    LWP::Debug::debug("   domain $domain applies to " .				      "Netscape-style cookies only");		    next;		}	        LWP::Debug::debug("   it's a match");		# set version number of cookie header.	        # XXX: What should it be if multiple matching                #      Set-Cookie headers have different versions themselves		if (!$set_ver++) {		    if ($version >= 1) {			push(@cval, "\$Version=$version");		    } elsif (!$self->{hide_cookie2}) {			$request->header(Cookie2 => '$Version="1"');		    }		}		# do we need to quote the value		if ($val =~ /\W/ && $version) {		    $val =~ s/([\\\"])/\\$1/g;		    $val = qq("$val");		}		# and finally remember this cookie		push(@cval, "$key=$val");		if ($version >= 1) {		    push(@cval, qq(\$Path="$path"))     if $path_spec;		    push(@cval, qq(\$Domain="$domain")) if $domain =~ /^\./;		    if (defined $port) {			my $p = '$Port';			$p .= qq(="$port") if length $port;			push(@cval, $p);		    }		}	    }        }    } continue {	# Try with a more general domain, alternately stripping	# leading name components and leading dots.  When this	# results in a domain with no leading dot, it is for	# Netscape cookie compatibility only:	#	# a.b.c.net	Any cookie	# .b.c.net	Any cookie	# b.c.net	Netscape cookie only	# .c.net	Any cookie	if ($domain =~ s/^\.+//) {	    $netscape_only = 1;	} else {	    $domain =~ s/[^.]*//;	    $netscape_only = 0;	}    }    $request->header(Cookie => join("; ", @cval)) if @cval;    $request;}=item $cookie_jar->extract_cookies($response);The extract_cookies() method will look for Set-Cookie: andSet-Cookie2: headers in the I<HTTP::Response> object passed asargument.  Any of these headers that are found are used to updatethe state of the $cookie_jar.=cutsub extract_cookies{    my $self = shift;    my $response = shift || return;    my @set = split_header_words($response->_header("Set-Cookie2"));    my @ns_set = $response->_header("Set-Cookie");    return $response unless @set || @ns_set;  # quick exit    my $request = $response->request;    my $url = $request->url;    my $req_host = _host($request, $url);    $req_host = "$req_host.local" unless $req_host =~ /\./;    my $req_port = $url->port;    my $req_path = _url_path($url);    _normalize_path($req_path) if $req_path =~ /%/;    if (@ns_set) {	# The old Netscape cookie format for Set-Cookie        # http://www.netscape.com/newsref/std/cookie_spec.html	# can for instance contain an unquoted "," in the expires	# field, so we have to use this ad-hoc parser.	my $now = time();	# Build a hash of cookies that was present in Set-Cookie2	# headers.  We need to skip them if we also find them in a	# Set-Cookie header.	my %in_set2;	for (@set) {	    $in_set2{$_->[0]}++;	}	my $set;	for $set (@ns_set) {	    my @cur;	    my $param;	    my $expires;	    for $param (split(/;\s*/, $set)) {		my($k,$v) = split(/\s*=\s*/, $param, 2);		$v =~ s/\s+$//;		#print "$k => $v\n";		my $lc = lc($k);		if ($lc eq "expires") {		    my $etime = str2time($v);		    if ($etime) {			push(@cur, "Max-Age" => str2time($v) - $now);			$expires++;		    }		} else {		    push(@cur, $k => $v);		}	    }	    next if $in_set2{$cur[0]};#	    push(@cur, "Port" => $req_port);	    push(@cur, "Discard" => undef) unless $expires;	    push(@cur, "Version" => 0);	    push(@cur, "ns-cookie" => 1);	    push(@set, \@cur);	}    }  SET_COOKIE:    for my $set (@set) {	next unless @$set >= 2;	my $key = shift @$set;	my $val = shift @$set;        LWP::Debug::debug("Set cookie $key => $val");	my %hash;	while (@$set) {	    my $k = shift @$set;	    my $v = shift @$set;	    my $lc = lc($k);	    # don't loose case distinction for unknown fields	    $k = $lc if $lc =~ /^(?:discard|domain|max-age|                                    path|port|secure|version)$/x;	    if ($k eq "discard" || $k eq "secure") {		$v = 1 unless defined $v;	    }	    next if exists $hash{$k};  # only first value is signigicant	    $hash{$k} = $v;	};	my %orig_hash = %hash;	my $version   = delete $hash{version};	$version = 1 unless defined($version);	my $discard   = delete $hash{discard};	my $secure    = delete $hash{secure};	my $maxage    = delete $hash{'max-age'};	my $ns_cookie = delete $hash{'ns-cookie'};	# Check domain	my $domain  = delete $hash{domain};	if (defined($domain)	    && $domain ne $req_host && $domain ne ".$req_host") {	    if ($domain !~ /\./ && $domain ne "local") {	        LWP::Debug::debug("Domain $domain contains no dot");		next SET_COOKIE;	    }	    $domain = ".$domain" unless $domain =~ /^\./;	    if ($domain =~ /\.\d+$/) {	        LWP::Debug::debug("IP-address $domain illeagal as domain");		next SET_COOKIE;	    }	    my $len = length($domain);	    unless (substr($req_host, -$len) eq $domain) {	        LWP::Debug::debug("Domain $domain does not match host $req_host");		next SET_COOKIE;	    }	    my $hostpre = substr($req_host, 0, length($req_host) - $len);	    if ($hostpre =~ /\./ && !$ns_cookie) {	        LWP::Debug::debug("Host prefix contain a dot: $hostpre => $domain");		next SET_COOKIE;	    }	} else {	    $domain = $req_host;	}	my $path = delete $hash{path};	my $path_spec;	if (defined $path && $path ne '') {	    $path_spec++;	    _normalize_path($path) if $path =~ /%/;	    if (!$ns_cookie &&                substr($req_path, 0, length($path)) ne $path) {	        LWP::Debug::debug("Path $path is not a prefix of $req_path");		next SET_COOKIE;	    }	} else {	    $path = $req_path;	    $path =~ s,/[^/]*$,,;	    $path = "/" unless length($path);	}	my $port;	if (exists $hash{port}) {	    $port = delete $hash{port};	    if (defined $port) {		$port =~ s/\s+//g;		my $found;		for my $p (split(/,/, $port)) {		    unless ($p =~ /^\d+$/) {		      LWP::Debug::debug("Bad port $port (not numeric)");			next SET_COOKIE;		    }		    $found++ if $p eq $req_port;		}		unless ($found) {		    LWP::Debug::debug("Request port ($req_port) not found in $port");		    next SET_COOKIE;		}	    } else {		$port = "_$req_port";	    }	}	$self->set_cookie($version,$key,$val,$path,$domain,$port,$path_spec,$secure,$maxage,$discard, \%hash)	    if $self->set_cookie_ok(\%orig_hash);    }    $response;}sub set_cookie_ok { 1 };

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -