?????????? ????????? - ??????????????? - /home/agenciai/public_html/cd38d8/HTTP-CookieJar-0.014-0.tar
???????
xt/author/pod-coverage.t 0000644 00000000334 15125143463 0011245 0 ustar 00 #!perl # This file was automatically generated by Dist::Zilla::Plugin::PodCoverageTests. use Test::Pod::Coverage 1.08; use Pod::Coverage::TrustPod; all_pod_coverage_ok({ coverage_class => 'Pod::Coverage::TrustPod' }); xt/author/pod-syntax.t 0000644 00000000252 15125143463 0010777 0 ustar 00 #!perl # This file was automatically generated by Dist::Zilla::Plugin::PodSyntaxTests. use strict; use warnings; use Test::More; use Test::Pod 1.41; all_pod_files_ok(); xt/author/distmeta.t 0000644 00000000172 15125143463 0010504 0 ustar 00 #!perl # This file was automatically generated by Dist::Zilla::Plugin::MetaTests. use Test::CPAN::Meta; meta_yaml_ok(); xt/author/test-version.t 0000644 00000000637 15125143463 0011342 0 ustar 00 use strict; use warnings; use Test::More; # generated by Dist::Zilla::Plugin::Test::Version 1.09 use Test::Version; my @imports = qw( version_all_ok ); my $params = { is_strict => 0, has_version => 1, multiple => 0, }; push @imports, $params if version->parse( $Test::Version::VERSION ) >= version->parse('1.002'); Test::Version->import(@imports); version_all_ok; done_testing; xt/author/critic.t 0000644 00000000201 15125143463 0010140 0 ustar 00 #!perl use strict; use warnings; use Test::Perl::Critic (-profile => "perlcritic.rc") x!! -e "perlcritic.rc"; all_critic_ok(); xt/author/00-compile.t 0000644 00000002720 15125143463 0010540 0 ustar 00 use 5.006; use strict; use warnings; # this test was generated with Dist::Zilla::Plugin::Test::Compile 2.058 use Test::More; plan tests => 3; my @module_files = ( 'HTTP/CookieJar.pm', 'HTTP/CookieJar/LWP.pm' ); # fake home for cpan-testers use File::Temp; local $ENV{HOME} = File::Temp::tempdir( CLEANUP => 1 ); my @switches = ( -d 'blib' ? '-Mblib' : '-Ilib', ); use File::Spec; use IPC::Open3; use IO::Handle; open my $stdin, '<', File::Spec->devnull or die "can't open devnull: $!"; my @warnings; for my $lib (@module_files) { # see L<perlfaq8/How can I capture STDERR from an external command?> my $stderr = IO::Handle->new; diag('Running: ', join(', ', map { my $str = $_; $str =~ s/'/\\'/g; q{'} . $str . q{'} } $^X, @switches, '-e', "require q[$lib]")) if $ENV{PERL_COMPILE_TEST_DEBUG}; my $pid = open3($stdin, '>&STDERR', $stderr, $^X, @switches, '-e', "require q[$lib]"); binmode $stderr, ':crlf' if $^O eq 'MSWin32'; my @_warnings = <$stderr>; waitpid($pid, 0); is($?, 0, "$lib loaded ok"); shift @_warnings if @_warnings and $_warnings[0] =~ /^Using .*\bblib/ and not eval { +require blib; blib->VERSION('1.01') }; if (@_warnings) { warn @_warnings; push @warnings, @_warnings; } } is(scalar(@warnings), 0, 'no warnings found') or diag 'got warnings: ', ( Test::More->can('explain') ? Test::More::explain(\@warnings) : join("\n", '', @warnings) ); xt/author/portability.t 0000644 00000000322 15125143463 0011231 0 ustar 00 use strict; use warnings; use Test::More; eval 'use Test::Portability::Files'; plan skip_all => 'Test::Portability::Files required for testing portability' if $@; options(test_one_dot => 0); run_tests(); xt/author/pod-spell.t 0000644 00000000527 15125143463 0010575 0 ustar 00 use strict; use warnings; use Test::More; # generated by Dist::Zilla::Plugin::Test::PodSpelling 2.007005 use Test::Spelling 0.12; use Pod::Wordlist; add_stopwords(<DATA>); all_pod_files_spelling_ok( qw( bin lib ) ); __DATA__ Book CookieJar Dan David Golden HTTP Javascript LWP RFC's dagolden grinnz hostonly httponly jdv jvolkening lib xdg xt/author/minimum-version.t 0000644 00000000152 15125143463 0012026 0 ustar 00 use strict; use warnings; use Test::More; use Test::MinimumVersion; all_minimum_version_ok( qq{5.010} ); CONTRIBUTING.mkdn 0000644 00000006604 15125143463 0007340 0 ustar 00 ## HOW TO CONTRIBUTE Thank you for considering contributing to this distribution. This file contains instructions that will help you work with the source code. The distribution is managed with Dist::Zilla. This means that many of the usual files you might expect are not in the repository, but are generated at release time, as is much of the documentation. Some generated files are kept in the repository as a convenience (e.g. Makefile.PL or cpanfile). Generally, **you do not need Dist::Zilla to contribute patches**. You do need Dist::Zilla to create a tarball. See below for guidance. ### Getting dependencies If you have App::cpanminus 1.6 or later installed, you can use `cpanm` to satisfy dependencies like this: $ cpanm --installdeps . Otherwise, look for either a `Makefile.PL` or `cpanfile` file for a list of dependencies to satisfy. ### Running tests You can run tests directly using the `prove` tool: $ prove -l $ prove -lv t/some_test_file.t For most of my distributions, `prove` is entirely sufficient for you to test any patches you have. I use `prove` for 99% of my testing during development. ### Code style and tidying Please try to match any existing coding style. If there is a `.perltidyrc` file, please install Perl::Tidy and use perltidy before submitting patches. If there is a `tidyall.ini` file, you can also install Code::TidyAll and run `tidyall` on a file or `tidyall -a` to tidy all files. ### Patching documentation Much of the documentation Pod is generated at release time. Some is generated boilerplate; other documentation is built from pseudo-POD directives in the source like C<=method> or C<=func>. If you would like to submit a documentation edit, please limit yourself to the documentation you see. If you see typos or documentation issues in the generated docs, please email or open a bug ticket instead of patching. ### Where to send patches and pull requests If you found this distribution on Github, sending a pull-request is the best way to contribute. If a pull-request isn't possible, a bug ticket with a patch file is the next best option. As a last resort, an email to the author(s) is acceptable. ## Installing and using Dist::Zilla Dist::Zilla is not required for contributing, but if you'd like to learn more, this section will get you up to speed. Dist::Zilla is a very powerful authoring tool, optimized for maintaining a large number of distributions with a high degree of automation, but it has a large dependency chain, a bit of a learning curve and requires a number of author-specific plugins. To install it from CPAN, I recommend one of the following approaches for the quickest installation: # using CPAN.pm, but bypassing non-functional pod tests $ cpan TAP::Harness::Restricted $ PERL_MM_USE_DEFAULT=1 HARNESS_CLASS=TAP::Harness::Restricted cpan Dist::Zilla # using cpanm, bypassing *all* tests $ cpanm -n Dist::Zilla In either case, it's probably going to take about 10 minutes. Go for a walk, go get a cup of your favorite beverage, take a bathroom break, or whatever. When you get back, Dist::Zilla should be ready for you. Then you need to install any plugins specific to this distribution: $ cpan `dzil authordeps` $ dzil authordeps | cpanm Once installed, here are some dzil commands you might try: $ dzil build $ dzil test $ dzil xtest You can learn more about Dist::Zilla at http://dzil.org/ pm_to_blib 0000644 00000000000 15125143463 0006567 0 ustar 00 Changes 0000644 00000004117 15125143463 0006046 0 ustar 00 Revision history for HTTP-CookieJar 0.014 2022-07-25 09:45:56-04:00 America/New_York - No changes from 0.013 0.013 2022-07-17 10:13:20-04:00 America/New_York (TRIAL RELEASE) [FIXED] - Cookie last access time is updated when a cookie is retrieved; this has no functional effect but is consistent with RFC 6265. 0.012 2021-06-16 05:34:31-04:00 America/New_York - No changes from 0.011 0.011 2021-06-15 19:29:51-04:00 America/New_York (TRIAL RELEASE) [FIXED] - Pushed test cookie expiration dates from 2021 to 2041. If I'm still maintaining this module in 2041, I'll bump them again then. 0.010 2020-09-20 11:28:49-04:00 America/New_York - No changes from 0.009 0.009 2020-09-17 22:39:16-04:00 America/New_York (TRIAL RELEASE) [FIXED] - Fixed handling of edge case where Max-Age == 0 0.008 2015-11-06 22:48:19-05:00 America/New_York [PREREQS] - Dropped minimum Perl requirement to 5.8.1 0.007 2015-08-21 13:57:31-04:00 America/New_York [PREREQS] - Dropped Time::Mock dependency to allow building on Windows [META] - Modernized repo layout for newest DAGOLDEN Dist::Zilla bundle 0.006 2014-02-19 19:52:00-05:00 America/New_York [FIXED] - Fixed file encoding of test files [CHANGED] - Updated distribution repo URL and other meta files - Tidied test files 0.005 2013-08-03 21:41:10 America/New_York [FIXED] - Fixed test failure under hash randomization 0.004 2013-04-23 22:24:25 America/New_York [REMOVED] - Removed test dependency on HTTP::Request/Response; The LWP adapter test will only be run if they are already available 0.003 2013-03-07 17:49:40 America/New_York [FIXED] - Another attempt to avoid test failures on older, 32-bit Perls 0.002 2013-03-07 06:12:04 America/New_York [FIXED] - Won't warn about undefined value for length on empty cookie on old Perls - Requires Time::Local 1.1901 to fix Y2038 bug on old Perls 0.001 2013-02-13 16:41:24 America/New_York - First release cpanfile 0000644 00000003366 15125143463 0006264 0 ustar 00 # This file is generated by Dist::Zilla::Plugin::CPANFile v6.025 # Do not edit this file directly. To change prereqs, edit the `dist.ini` file. requires "Carp" => "0"; requires "HTTP::Date" => "0"; requires "Time::Local" => "1.1901"; requires "parent" => "0"; requires "perl" => "5.008001"; requires "strict" => "0"; requires "warnings" => "0"; recommends "Mozilla::PublicSuffix" => "0"; on 'test' => sub { requires "ExtUtils::MakeMaker" => "0"; requires "File::Spec" => "0"; requires "Test::Deep" => "0"; requires "Test::More" => "0.96"; requires "Test::Requires" => "0"; requires "Time::Local" => "1.1901"; requires "URI" => "0"; requires "lib" => "0"; requires "perl" => "5.008001"; }; on 'test' => sub { recommends "CPAN::Meta" => "2.120900"; }; on 'configure' => sub { requires "ExtUtils::MakeMaker" => "6.17"; requires "perl" => "5.008001"; }; on 'develop' => sub { requires "Dist::Zilla" => "5"; requires "Dist::Zilla::Plugin::Prereqs" => "0"; requires "Dist::Zilla::Plugin::ReleaseStatus::FromVersion" => "0"; requires "Dist::Zilla::Plugin::RemovePrereqs" => "0"; requires "Dist::Zilla::PluginBundle::DAGOLDEN" => "0.072"; requires "File::Spec" => "0"; requires "File::Temp" => "0"; requires "IO::Handle" => "0"; requires "IPC::Open3" => "0"; requires "Pod::Coverage::TrustPod" => "0"; requires "Pod::Wordlist" => "0"; requires "Software::License::Apache_2_0" => "0"; requires "Test::CPAN::Meta" => "0"; requires "Test::MinimumVersion" => "0"; requires "Test::More" => "0"; requires "Test::Perl::Critic" => "0"; requires "Test::Pod" => "1.41"; requires "Test::Pod::Coverage" => "1.08"; requires "Test::Portability::Files" => "0"; requires "Test::Spelling" => "0.12"; requires "Test::Version" => "1"; }; tidyall.ini 0000644 00000000240 15125143463 0006707 0 ustar 00 ; Install Code::TidyAll ; run "tidyall -a" to tidy all files ; run "tidyall -g" to tidy only files modified from git [PerlTidy] select = {lib,t}/**/*.{pl,pm,t} Makefile 0000644 00000076100 15125143463 0006214 0 ustar 00 # This Makefile is for the HTTP::CookieJar extension to perl. # # It was generated automatically by MakeMaker version # 7.60 (Revision: 76000) from the contents of # Makefile.PL. Don't edit this file, edit Makefile.PL instead. # # ANY CHANGES MADE HERE WILL BE LOST! # # MakeMaker ARGV: () # # MakeMaker Parameters: # ABSTRACT => q[A minimalist HTTP user agent cookie jar] # AUTHOR => [q[David Golden <dagolden@cpan.org>]] # BUILD_REQUIRES => { } # CONFIGURE_REQUIRES => { ExtUtils::MakeMaker=>q[6.17] } # DISTNAME => q[HTTP-CookieJar] # LICENSE => q[apache] # MIN_PERL_VERSION => q[5.008001] # NAME => q[HTTP::CookieJar] # PREREQ_PM => { Carp=>q[0], ExtUtils::MakeMaker=>q[0], File::Spec=>q[0], HTTP::Date=>q[0], Test::Deep=>q[0], Test::More=>q[0.96], Test::Requires=>q[0], Time::Local=>q[1.1901], URI=>q[0], lib=>q[0], parent=>q[0], strict=>q[0], warnings=>q[0] } # TEST_REQUIRES => { ExtUtils::MakeMaker=>q[0], File::Spec=>q[0], Test::Deep=>q[0], Test::More=>q[0.96], Test::Requires=>q[0], Time::Local=>q[1.1901], URI=>q[0], lib=>q[0] } # VERSION => q[0.014] # test => { TESTS=>q[t/*.t] } # --- MakeMaker post_initialize section: # --- MakeMaker const_config section: # These definitions are from config.sh (via /usr/lib64/perl5/Config.pm). # They may have been overridden via Makefile.PL or on the command line. AR = ar CC = gcc CCCDLFLAGS = -fPIC CCDLFLAGS = -Wl,--enable-new-dtags -Wl,-z,relro -Wl,--as-needed -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 DLEXT = so DLSRC = dl_dlopen.xs EXE_EXT = FULL_AR = /usr/bin/ar LD = gcc LDDLFLAGS = -lpthread -shared -Wl,-z,relro -Wl,--as-needed -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -L/usr/local/lib -fstack-protector-strong LDFLAGS = -Wl,-z,relro -Wl,--as-needed -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -fstack-protector-strong -L/usr/local/lib LIBC = /lib/../lib64/libc.so.6 LIB_EXT = .a OBJ_EXT = .o OSNAME = linux OSVERS = 4.18.0-513.18.1.el8_9.x86_64 RANLIB = : SITELIBEXP = /usr/local/share/perl5/5.32 SITEARCHEXP = /usr/local/lib64/perl5/5.32 SO = so VENDORARCHEXP = /usr/lib64/perl5/vendor_perl VENDORLIBEXP = /usr/share/perl5/vendor_perl # --- MakeMaker constants section: AR_STATIC_ARGS = cr DIRFILESEP = / DFSEP = $(DIRFILESEP) NAME = HTTP::CookieJar NAME_SYM = HTTP_CookieJar VERSION = 0.014 VERSION_MACRO = VERSION VERSION_SYM = 0_014 DEFINE_VERSION = -D$(VERSION_MACRO)=\"$(VERSION)\" XS_VERSION = 0.014 XS_VERSION_MACRO = XS_VERSION XS_DEFINE_VERSION = -D$(XS_VERSION_MACRO)=\"$(XS_VERSION)\" INST_ARCHLIB = blib/arch INST_SCRIPT = blib/script INST_BIN = blib/bin INST_LIB = blib/lib INST_MAN1DIR = blib/man1 INST_MAN3DIR = blib/man3 MAN1EXT = 1 MAN3EXT = 3pm MAN1SECTION = 1 MAN3SECTION = 3 INSTALLDIRS = site DESTDIR = PREFIX = $(SITEPREFIX) PERLPREFIX = /usr SITEPREFIX = /usr/local VENDORPREFIX = /usr INSTALLPRIVLIB = /usr/share/perl5 DESTINSTALLPRIVLIB = $(DESTDIR)$(INSTALLPRIVLIB) INSTALLSITELIB = /usr/local/share/perl5/5.32 DESTINSTALLSITELIB = $(DESTDIR)$(INSTALLSITELIB) INSTALLVENDORLIB = /usr/share/perl5/vendor_perl DESTINSTALLVENDORLIB = $(DESTDIR)$(INSTALLVENDORLIB) INSTALLARCHLIB = /usr/lib64/perl5 DESTINSTALLARCHLIB = $(DESTDIR)$(INSTALLARCHLIB) INSTALLSITEARCH = /usr/local/lib64/perl5/5.32 DESTINSTALLSITEARCH = $(DESTDIR)$(INSTALLSITEARCH) INSTALLVENDORARCH = /usr/lib64/perl5/vendor_perl DESTINSTALLVENDORARCH = $(DESTDIR)$(INSTALLVENDORARCH) INSTALLBIN = /usr/bin DESTINSTALLBIN = $(DESTDIR)$(INSTALLBIN) INSTALLSITEBIN = /usr/local/bin DESTINSTALLSITEBIN = $(DESTDIR)$(INSTALLSITEBIN) INSTALLVENDORBIN = /usr/bin DESTINSTALLVENDORBIN = $(DESTDIR)$(INSTALLVENDORBIN) INSTALLSCRIPT = /usr/bin DESTINSTALLSCRIPT = $(DESTDIR)$(INSTALLSCRIPT) INSTALLSITESCRIPT = /usr/local/bin DESTINSTALLSITESCRIPT = $(DESTDIR)$(INSTALLSITESCRIPT) INSTALLVENDORSCRIPT = /usr/bin DESTINSTALLVENDORSCRIPT = $(DESTDIR)$(INSTALLVENDORSCRIPT) INSTALLMAN1DIR = /usr/share/man/man1 DESTINSTALLMAN1DIR = $(DESTDIR)$(INSTALLMAN1DIR) INSTALLSITEMAN1DIR = /usr/local/share/man/man1 DESTINSTALLSITEMAN1DIR = $(DESTDIR)$(INSTALLSITEMAN1DIR) INSTALLVENDORMAN1DIR = /usr/share/man/man1 DESTINSTALLVENDORMAN1DIR = $(DESTDIR)$(INSTALLVENDORMAN1DIR) INSTALLMAN3DIR = /usr/share/man/man3 DESTINSTALLMAN3DIR = $(DESTDIR)$(INSTALLMAN3DIR) INSTALLSITEMAN3DIR = /usr/local/share/man/man3 DESTINSTALLSITEMAN3DIR = $(DESTDIR)$(INSTALLSITEMAN3DIR) INSTALLVENDORMAN3DIR = /usr/share/man/man3 DESTINSTALLVENDORMAN3DIR = $(DESTDIR)$(INSTALLVENDORMAN3DIR) PERL_LIB = /usr/share/perl5 PERL_ARCHLIB = /usr/lib64/perl5 PERL_ARCHLIBDEP = /usr/lib64/perl5 LIBPERL_A = libperl.a FIRST_MAKEFILE = Makefile MAKEFILE_OLD = Makefile.old MAKE_APERL_FILE = Makefile.aperl PERLMAINCC = $(CC) PERL_INC = /usr/lib64/perl5/CORE PERL_INCDEP = /usr/lib64/perl5/CORE PERL = "/usr/bin/perl" FULLPERL = "/usr/bin/perl" ABSPERL = $(PERL) PERLRUN = $(PERL) FULLPERLRUN = $(FULLPERL) ABSPERLRUN = $(ABSPERL) PERLRUNINST = $(PERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" FULLPERLRUNINST = $(FULLPERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" ABSPERLRUNINST = $(ABSPERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" PERL_CORE = 0 PERM_DIR = 755 PERM_RW = 644 PERM_RWX = 755 MAKEMAKER = /usr/share/perl5/vendor_perl/ExtUtils/MakeMaker.pm MM_VERSION = 7.60 MM_REVISION = 76000 # FULLEXT = Pathname for extension directory (eg Foo/Bar/Oracle). # BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT. (eg Oracle) # PARENT_NAME = NAME without BASEEXT and no trailing :: (eg Foo::Bar) # DLBASE = Basename part of dynamic library. May be just equal BASEEXT. MAKE = make FULLEXT = HTTP/CookieJar BASEEXT = CookieJar PARENT_NAME = HTTP DLBASE = $(BASEEXT) VERSION_FROM = OBJECT = LDFROM = $(OBJECT) LINKTYPE = dynamic BOOTDEP = # Handy lists of source code files: XS_FILES = C_FILES = O_FILES = H_FILES = MAN1PODS = MAN3PODS = lib/HTTP/CookieJar.pm \ lib/HTTP/CookieJar/LWP.pm # Where is the Config information that we are using/depend on CONFIGDEP = $(PERL_ARCHLIBDEP)$(DFSEP)Config.pm $(PERL_INCDEP)$(DFSEP)config.h # Where to build things INST_LIBDIR = $(INST_LIB)/HTTP INST_ARCHLIBDIR = $(INST_ARCHLIB)/HTTP INST_AUTODIR = $(INST_LIB)/auto/$(FULLEXT) INST_ARCHAUTODIR = $(INST_ARCHLIB)/auto/$(FULLEXT) INST_STATIC = INST_DYNAMIC = INST_BOOT = # Extra linker info EXPORT_LIST = PERL_ARCHIVE = PERL_ARCHIVEDEP = PERL_ARCHIVE_AFTER = TO_INST_PM = lib/HTTP/CookieJar.pm \ lib/HTTP/CookieJar/LWP.pm # --- MakeMaker platform_constants section: MM_Unix_VERSION = 7.60 PERL_MALLOC_DEF = -DPERL_EXTMALLOC_DEF -Dmalloc=Perl_malloc -Dfree=Perl_mfree -Drealloc=Perl_realloc -Dcalloc=Perl_calloc # --- MakeMaker tool_autosplit section: # Usage: $(AUTOSPLITFILE) FileToSplit AutoDirToSplitInto AUTOSPLITFILE = $(ABSPERLRUN) -e 'use AutoSplit; autosplit($$$$ARGV[0], $$$$ARGV[1], 0, 1, 1)' -- # --- MakeMaker tool_xsubpp section: # --- MakeMaker tools_other section: SHELL = /bin/sh CHMOD = chmod CP = cp MV = mv NOOP = $(TRUE) NOECHO = @ RM_F = rm -f RM_RF = rm -rf TEST_F = test -f TOUCH = touch UMASK_NULL = umask 0 DEV_NULL = > /dev/null 2>&1 MKPATH = $(ABSPERLRUN) -MExtUtils::Command -e 'mkpath' -- EQUALIZE_TIMESTAMP = $(ABSPERLRUN) -MExtUtils::Command -e 'eqtime' -- FALSE = false TRUE = true ECHO = echo ECHO_N = echo -n UNINST = 0 VERBINST = 0 MOD_INSTALL = $(ABSPERLRUN) -MExtUtils::Install -e 'install([ from_to => {@ARGV}, verbose => '\''$(VERBINST)'\'', uninstall_shadows => '\''$(UNINST)'\'', dir_mode => '\''$(PERM_DIR)'\'' ]);' -- DOC_INSTALL = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'perllocal_install' -- UNINSTALL = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'uninstall' -- WARN_IF_OLD_PACKLIST = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'warn_if_old_packlist' -- MACROSTART = MACROEND = USEMAKEFILE = -f FIXIN = $(ABSPERLRUN) -MExtUtils::MY -e 'MY->fixin(shift)' -- CP_NONEMPTY = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'cp_nonempty' -- # --- MakeMaker makemakerdflt section: makemakerdflt : all $(NOECHO) $(NOOP) # --- MakeMaker dist section: TAR = tar TARFLAGS = cvf ZIP = zip ZIPFLAGS = -r COMPRESS = gzip --best SUFFIX = .gz SHAR = shar PREOP = $(NOECHO) $(NOOP) POSTOP = $(NOECHO) $(NOOP) TO_UNIX = $(NOECHO) $(NOOP) CI = ci -u RCS_LABEL = rcs -Nv$(VERSION_SYM): -q DIST_CP = best DIST_DEFAULT = tardist DISTNAME = HTTP-CookieJar DISTVNAME = HTTP-CookieJar-0.014 # --- MakeMaker macro section: # --- MakeMaker depend section: # --- MakeMaker cflags section: # --- MakeMaker const_loadlibs section: # --- MakeMaker const_cccmd section: # --- MakeMaker post_constants section: # --- MakeMaker pasthru section: PASTHRU = LIBPERL_A="$(LIBPERL_A)"\ LINKTYPE="$(LINKTYPE)"\ PREFIX="$(PREFIX)"\ PASTHRU_DEFINE='$(DEFINE) $(PASTHRU_DEFINE)'\ PASTHRU_INC='$(INC) $(PASTHRU_INC)' # --- MakeMaker special_targets section: .SUFFIXES : .xs .c .C .cpp .i .s .cxx .cc $(OBJ_EXT) .PHONY: all config static dynamic test linkext manifest blibdirs clean realclean disttest distdir pure_all subdirs clean_subdirs makemakerdflt manifypods realclean_subdirs subdirs_dynamic subdirs_pure_nolink subdirs_static subdirs-test_dynamic subdirs-test_static test_dynamic test_static # --- MakeMaker c_o section: # --- MakeMaker xs_c section: # --- MakeMaker xs_o section: # --- MakeMaker top_targets section: all :: pure_all manifypods $(NOECHO) $(NOOP) pure_all :: config pm_to_blib subdirs linkext $(NOECHO) $(NOOP) subdirs :: $(MYEXTLIB) $(NOECHO) $(NOOP) config :: $(FIRST_MAKEFILE) blibdirs $(NOECHO) $(NOOP) help : perldoc ExtUtils::MakeMaker # --- MakeMaker blibdirs section: blibdirs : $(INST_LIBDIR)$(DFSEP).exists $(INST_ARCHLIB)$(DFSEP).exists $(INST_AUTODIR)$(DFSEP).exists $(INST_ARCHAUTODIR)$(DFSEP).exists $(INST_BIN)$(DFSEP).exists $(INST_SCRIPT)$(DFSEP).exists $(INST_MAN1DIR)$(DFSEP).exists $(INST_MAN3DIR)$(DFSEP).exists $(NOECHO) $(NOOP) # Backwards compat with 6.18 through 6.25 blibdirs.ts : blibdirs $(NOECHO) $(NOOP) $(INST_LIBDIR)$(DFSEP).exists :: Makefile.PL $(NOECHO) $(MKPATH) $(INST_LIBDIR) $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_LIBDIR) $(NOECHO) $(TOUCH) $(INST_LIBDIR)$(DFSEP).exists $(INST_ARCHLIB)$(DFSEP).exists :: Makefile.PL $(NOECHO) $(MKPATH) $(INST_ARCHLIB) $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_ARCHLIB) $(NOECHO) $(TOUCH) $(INST_ARCHLIB)$(DFSEP).exists $(INST_AUTODIR)$(DFSEP).exists :: Makefile.PL $(NOECHO) $(MKPATH) $(INST_AUTODIR) $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_AUTODIR) $(NOECHO) $(TOUCH) $(INST_AUTODIR)$(DFSEP).exists $(INST_ARCHAUTODIR)$(DFSEP).exists :: Makefile.PL $(NOECHO) $(MKPATH) $(INST_ARCHAUTODIR) $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_ARCHAUTODIR) $(NOECHO) $(TOUCH) $(INST_ARCHAUTODIR)$(DFSEP).exists $(INST_BIN)$(DFSEP).exists :: Makefile.PL $(NOECHO) $(MKPATH) $(INST_BIN) $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_BIN) $(NOECHO) $(TOUCH) $(INST_BIN)$(DFSEP).exists $(INST_SCRIPT)$(DFSEP).exists :: Makefile.PL $(NOECHO) $(MKPATH) $(INST_SCRIPT) $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_SCRIPT) $(NOECHO) $(TOUCH) $(INST_SCRIPT)$(DFSEP).exists $(INST_MAN1DIR)$(DFSEP).exists :: Makefile.PL $(NOECHO) $(MKPATH) $(INST_MAN1DIR) $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_MAN1DIR) $(NOECHO) $(TOUCH) $(INST_MAN1DIR)$(DFSEP).exists $(INST_MAN3DIR)$(DFSEP).exists :: Makefile.PL $(NOECHO) $(MKPATH) $(INST_MAN3DIR) $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_MAN3DIR) $(NOECHO) $(TOUCH) $(INST_MAN3DIR)$(DFSEP).exists # --- MakeMaker linkext section: linkext :: dynamic $(NOECHO) $(NOOP) # --- MakeMaker dlsyms section: # --- MakeMaker dynamic_bs section: BOOTSTRAP = # --- MakeMaker dynamic section: dynamic :: $(FIRST_MAKEFILE) config $(INST_BOOT) $(INST_DYNAMIC) $(NOECHO) $(NOOP) # --- MakeMaker dynamic_lib section: # --- MakeMaker static section: ## $(INST_PM) has been moved to the all: target. ## It remains here for awhile to allow for old usage: "make static" static :: $(FIRST_MAKEFILE) $(INST_STATIC) $(NOECHO) $(NOOP) # --- MakeMaker static_lib section: # --- MakeMaker manifypods section: POD2MAN_EXE = $(PERLRUN) "-MExtUtils::Command::MM" -e pod2man "--" POD2MAN = $(POD2MAN_EXE) manifypods : pure_all config \ lib/HTTP/CookieJar.pm \ lib/HTTP/CookieJar/LWP.pm $(NOECHO) $(POD2MAN) --section=$(MAN3SECTION) --perm_rw=$(PERM_RW) -u \ lib/HTTP/CookieJar.pm $(INST_MAN3DIR)/HTTP::CookieJar.$(MAN3EXT) \ lib/HTTP/CookieJar/LWP.pm $(INST_MAN3DIR)/HTTP::CookieJar::LWP.$(MAN3EXT) # --- MakeMaker processPL section: # --- MakeMaker installbin section: # --- MakeMaker subdirs section: # none # --- MakeMaker clean_subdirs section: clean_subdirs : $(NOECHO) $(NOOP) # --- MakeMaker clean section: # Delete temporary files but do not touch installed files. We don't delete # the Makefile here so a later make realclean still has a makefile to use. clean :: clean_subdirs - $(RM_F) \ $(BASEEXT).bso $(BASEEXT).def \ $(BASEEXT).exp $(BASEEXT).x \ $(BOOTSTRAP) $(INST_ARCHAUTODIR)/extralibs.all \ $(INST_ARCHAUTODIR)/extralibs.ld $(MAKE_APERL_FILE) \ *$(LIB_EXT) *$(OBJ_EXT) \ *perl.core MYMETA.json \ MYMETA.yml blibdirs.ts \ core core.*perl.*.? \ core.[0-9] core.[0-9][0-9] \ core.[0-9][0-9][0-9] core.[0-9][0-9][0-9][0-9] \ core.[0-9][0-9][0-9][0-9][0-9] lib$(BASEEXT).def \ mon.out perl \ perl$(EXE_EXT) perl.exe \ perlmain.c pm_to_blib \ pm_to_blib.ts so_locations \ tmon.out - $(RM_RF) \ blib $(NOECHO) $(RM_F) $(MAKEFILE_OLD) - $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD) $(DEV_NULL) # --- MakeMaker realclean_subdirs section: # so clean is forced to complete before realclean_subdirs runs realclean_subdirs : clean $(NOECHO) $(NOOP) # --- MakeMaker realclean section: # Delete temporary files (via clean) and also delete dist files realclean purge :: realclean_subdirs - $(RM_F) \ $(FIRST_MAKEFILE) $(MAKEFILE_OLD) - $(RM_RF) \ $(DISTVNAME) # --- MakeMaker metafile section: metafile : create_distdir $(NOECHO) $(ECHO) Generating META.yml $(NOECHO) $(ECHO) '---' > META_new.yml $(NOECHO) $(ECHO) 'abstract: '\''A minimalist HTTP user agent cookie jar'\''' >> META_new.yml $(NOECHO) $(ECHO) 'author:' >> META_new.yml $(NOECHO) $(ECHO) ' - '\''David Golden <dagolden@cpan.org>'\''' >> META_new.yml $(NOECHO) $(ECHO) 'build_requires:' >> META_new.yml $(NOECHO) $(ECHO) ' ExtUtils::MakeMaker: '\''0'\''' >> META_new.yml $(NOECHO) $(ECHO) ' File::Spec: '\''0'\''' >> META_new.yml $(NOECHO) $(ECHO) ' Test::Deep: '\''0'\''' >> META_new.yml $(NOECHO) $(ECHO) ' Test::More: '\''0.96'\''' >> META_new.yml $(NOECHO) $(ECHO) ' Test::Requires: '\''0'\''' >> META_new.yml $(NOECHO) $(ECHO) ' Time::Local: '\''1.1901'\''' >> META_new.yml $(NOECHO) $(ECHO) ' URI: '\''0'\''' >> META_new.yml $(NOECHO) $(ECHO) ' lib: '\''0'\''' >> META_new.yml $(NOECHO) $(ECHO) 'configure_requires:' >> META_new.yml $(NOECHO) $(ECHO) ' ExtUtils::MakeMaker: '\''6.17'\''' >> META_new.yml $(NOECHO) $(ECHO) 'dynamic_config: 1' >> META_new.yml $(NOECHO) $(ECHO) 'generated_by: '\''ExtUtils::MakeMaker version 7.60, CPAN::Meta::Converter version 2.150010'\''' >> META_new.yml $(NOECHO) $(ECHO) 'license: apache' >> META_new.yml $(NOECHO) $(ECHO) 'meta-spec:' >> META_new.yml $(NOECHO) $(ECHO) ' url: http://module-build.sourceforge.net/META-spec-v1.4.html' >> META_new.yml $(NOECHO) $(ECHO) ' version: '\''1.4'\''' >> META_new.yml $(NOECHO) $(ECHO) 'name: HTTP-CookieJar' >> META_new.yml $(NOECHO) $(ECHO) 'no_index:' >> META_new.yml $(NOECHO) $(ECHO) ' directory:' >> META_new.yml $(NOECHO) $(ECHO) ' - t' >> META_new.yml $(NOECHO) $(ECHO) ' - inc' >> META_new.yml $(NOECHO) $(ECHO) 'requires:' >> META_new.yml $(NOECHO) $(ECHO) ' Carp: '\''0'\''' >> META_new.yml $(NOECHO) $(ECHO) ' HTTP::Date: '\''0'\''' >> META_new.yml $(NOECHO) $(ECHO) ' Time::Local: '\''1.1901'\''' >> META_new.yml $(NOECHO) $(ECHO) ' parent: '\''0'\''' >> META_new.yml $(NOECHO) $(ECHO) ' perl: '\''5.008001'\''' >> META_new.yml $(NOECHO) $(ECHO) ' strict: '\''0'\''' >> META_new.yml $(NOECHO) $(ECHO) ' warnings: '\''0'\''' >> META_new.yml $(NOECHO) $(ECHO) 'version: '\''0.014'\''' >> META_new.yml $(NOECHO) $(ECHO) 'x_serialization_backend: '\''CPAN::Meta::YAML version 0.018'\''' >> META_new.yml -$(NOECHO) $(MV) META_new.yml $(DISTVNAME)/META.yml $(NOECHO) $(ECHO) Generating META.json $(NOECHO) $(ECHO) '{' > META_new.json $(NOECHO) $(ECHO) ' "abstract" : "A minimalist HTTP user agent cookie jar",' >> META_new.json $(NOECHO) $(ECHO) ' "author" : [' >> META_new.json $(NOECHO) $(ECHO) ' "David Golden <dagolden@cpan.org>"' >> META_new.json $(NOECHO) $(ECHO) ' ],' >> META_new.json $(NOECHO) $(ECHO) ' "dynamic_config" : 1,' >> META_new.json $(NOECHO) $(ECHO) ' "generated_by" : "ExtUtils::MakeMaker version 7.60, CPAN::Meta::Converter version 2.150010",' >> META_new.json $(NOECHO) $(ECHO) ' "license" : [' >> META_new.json $(NOECHO) $(ECHO) ' "apache_2_0"' >> META_new.json $(NOECHO) $(ECHO) ' ],' >> META_new.json $(NOECHO) $(ECHO) ' "meta-spec" : {' >> META_new.json $(NOECHO) $(ECHO) ' "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",' >> META_new.json $(NOECHO) $(ECHO) ' "version" : 2' >> META_new.json $(NOECHO) $(ECHO) ' },' >> META_new.json $(NOECHO) $(ECHO) ' "name" : "HTTP-CookieJar",' >> META_new.json $(NOECHO) $(ECHO) ' "no_index" : {' >> META_new.json $(NOECHO) $(ECHO) ' "directory" : [' >> META_new.json $(NOECHO) $(ECHO) ' "t",' >> META_new.json $(NOECHO) $(ECHO) ' "inc"' >> META_new.json $(NOECHO) $(ECHO) ' ]' >> META_new.json $(NOECHO) $(ECHO) ' },' >> META_new.json $(NOECHO) $(ECHO) ' "prereqs" : {' >> META_new.json $(NOECHO) $(ECHO) ' "build" : {' >> META_new.json $(NOECHO) $(ECHO) ' "requires" : {' >> META_new.json $(NOECHO) $(ECHO) ' "ExtUtils::MakeMaker" : "0"' >> META_new.json $(NOECHO) $(ECHO) ' }' >> META_new.json $(NOECHO) $(ECHO) ' },' >> META_new.json $(NOECHO) $(ECHO) ' "configure" : {' >> META_new.json $(NOECHO) $(ECHO) ' "requires" : {' >> META_new.json $(NOECHO) $(ECHO) ' "ExtUtils::MakeMaker" : "6.17"' >> META_new.json $(NOECHO) $(ECHO) ' }' >> META_new.json $(NOECHO) $(ECHO) ' },' >> META_new.json $(NOECHO) $(ECHO) ' "runtime" : {' >> META_new.json $(NOECHO) $(ECHO) ' "requires" : {' >> META_new.json $(NOECHO) $(ECHO) ' "Carp" : "0",' >> META_new.json $(NOECHO) $(ECHO) ' "HTTP::Date" : "0",' >> META_new.json $(NOECHO) $(ECHO) ' "Time::Local" : "1.1901",' >> META_new.json $(NOECHO) $(ECHO) ' "parent" : "0",' >> META_new.json $(NOECHO) $(ECHO) ' "perl" : "5.008001",' >> META_new.json $(NOECHO) $(ECHO) ' "strict" : "0",' >> META_new.json $(NOECHO) $(ECHO) ' "warnings" : "0"' >> META_new.json $(NOECHO) $(ECHO) ' }' >> META_new.json $(NOECHO) $(ECHO) ' },' >> META_new.json $(NOECHO) $(ECHO) ' "test" : {' >> META_new.json $(NOECHO) $(ECHO) ' "requires" : {' >> META_new.json $(NOECHO) $(ECHO) ' "ExtUtils::MakeMaker" : "0",' >> META_new.json $(NOECHO) $(ECHO) ' "File::Spec" : "0",' >> META_new.json $(NOECHO) $(ECHO) ' "Test::Deep" : "0",' >> META_new.json $(NOECHO) $(ECHO) ' "Test::More" : "0.96",' >> META_new.json $(NOECHO) $(ECHO) ' "Test::Requires" : "0",' >> META_new.json $(NOECHO) $(ECHO) ' "Time::Local" : "1.1901",' >> META_new.json $(NOECHO) $(ECHO) ' "URI" : "0",' >> META_new.json $(NOECHO) $(ECHO) ' "lib" : "0"' >> META_new.json $(NOECHO) $(ECHO) ' }' >> META_new.json $(NOECHO) $(ECHO) ' }' >> META_new.json $(NOECHO) $(ECHO) ' },' >> META_new.json $(NOECHO) $(ECHO) ' "release_status" : "stable",' >> META_new.json $(NOECHO) $(ECHO) ' "version" : "0.014",' >> META_new.json $(NOECHO) $(ECHO) ' "x_serialization_backend" : "JSON::PP version 4.06"' >> META_new.json $(NOECHO) $(ECHO) '}' >> META_new.json -$(NOECHO) $(MV) META_new.json $(DISTVNAME)/META.json # --- MakeMaker signature section: signature : cpansign -s # --- MakeMaker dist_basics section: distclean :: realclean distcheck $(NOECHO) $(NOOP) distcheck : $(PERLRUN) "-MExtUtils::Manifest=fullcheck" -e fullcheck skipcheck : $(PERLRUN) "-MExtUtils::Manifest=skipcheck" -e skipcheck manifest : $(PERLRUN) "-MExtUtils::Manifest=mkmanifest" -e mkmanifest veryclean : realclean $(RM_F) *~ */*~ *.orig */*.orig *.bak */*.bak *.old */*.old # --- MakeMaker dist_core section: dist : $(DIST_DEFAULT) $(FIRST_MAKEFILE) $(NOECHO) $(ABSPERLRUN) -l -e 'print '\''Warning: Makefile possibly out of date with $(VERSION_FROM)'\''' \ -e ' if -e '\''$(VERSION_FROM)'\'' and -M '\''$(VERSION_FROM)'\'' < -M '\''$(FIRST_MAKEFILE)'\'';' -- tardist : $(DISTVNAME).tar$(SUFFIX) $(NOECHO) $(NOOP) uutardist : $(DISTVNAME).tar$(SUFFIX) uuencode $(DISTVNAME).tar$(SUFFIX) $(DISTVNAME).tar$(SUFFIX) > $(DISTVNAME).tar$(SUFFIX)_uu $(NOECHO) $(ECHO) 'Created $(DISTVNAME).tar$(SUFFIX)_uu' $(DISTVNAME).tar$(SUFFIX) : distdir $(PREOP) $(TO_UNIX) $(TAR) $(TARFLAGS) $(DISTVNAME).tar $(DISTVNAME) $(RM_RF) $(DISTVNAME) $(COMPRESS) $(DISTVNAME).tar $(NOECHO) $(ECHO) 'Created $(DISTVNAME).tar$(SUFFIX)' $(POSTOP) zipdist : $(DISTVNAME).zip $(NOECHO) $(NOOP) $(DISTVNAME).zip : distdir $(PREOP) $(ZIP) $(ZIPFLAGS) $(DISTVNAME).zip $(DISTVNAME) $(RM_RF) $(DISTVNAME) $(NOECHO) $(ECHO) 'Created $(DISTVNAME).zip' $(POSTOP) shdist : distdir $(PREOP) $(SHAR) $(DISTVNAME) > $(DISTVNAME).shar $(RM_RF) $(DISTVNAME) $(NOECHO) $(ECHO) 'Created $(DISTVNAME).shar' $(POSTOP) # --- MakeMaker distdir section: create_distdir : $(RM_RF) $(DISTVNAME) $(PERLRUN) "-MExtUtils::Manifest=manicopy,maniread" \ -e "manicopy(maniread(),'$(DISTVNAME)', '$(DIST_CP)');" distdir : create_distdir distmeta $(NOECHO) $(NOOP) # --- MakeMaker dist_test section: disttest : distdir cd $(DISTVNAME) && $(ABSPERLRUN) Makefile.PL cd $(DISTVNAME) && $(MAKE) $(PASTHRU) cd $(DISTVNAME) && $(MAKE) test $(PASTHRU) # --- MakeMaker dist_ci section: ci : $(ABSPERLRUN) -MExtUtils::Manifest=maniread -e '@all = sort keys %{ maniread() };' \ -e 'print(qq{Executing $(CI) @all\n});' \ -e 'system(qq{$(CI) @all}) == 0 or die $$!;' \ -e 'print(qq{Executing $(RCS_LABEL) ...\n});' \ -e 'system(qq{$(RCS_LABEL) @all}) == 0 or die $$!;' -- # --- MakeMaker distmeta section: distmeta : create_distdir metafile $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'exit unless -e q{META.yml};' \ -e 'eval { maniadd({q{META.yml} => q{Module YAML meta-data (added by MakeMaker)}}) }' \ -e ' or die "Could not add META.yml to MANIFEST: $${'\''@'\''}"' -- $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'exit unless -f q{META.json};' \ -e 'eval { maniadd({q{META.json} => q{Module JSON meta-data (added by MakeMaker)}}) }' \ -e ' or die "Could not add META.json to MANIFEST: $${'\''@'\''}"' -- # --- MakeMaker distsignature section: distsignature : distmeta $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'eval { maniadd({q{SIGNATURE} => q{Public-key signature (added by MakeMaker)}}) }' \ -e ' or die "Could not add SIGNATURE to MANIFEST: $${'\''@'\''}"' -- $(NOECHO) cd $(DISTVNAME) && $(TOUCH) SIGNATURE cd $(DISTVNAME) && cpansign -s # --- MakeMaker install section: install :: pure_install doc_install $(NOECHO) $(NOOP) install_perl :: pure_perl_install doc_perl_install $(NOECHO) $(NOOP) install_site :: pure_site_install doc_site_install $(NOECHO) $(NOOP) install_vendor :: pure_vendor_install doc_vendor_install $(NOECHO) $(NOOP) pure_install :: pure_$(INSTALLDIRS)_install $(NOECHO) $(NOOP) doc_install :: doc_$(INSTALLDIRS)_install $(NOECHO) $(NOOP) pure__install : pure_site_install $(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site doc__install : doc_site_install $(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site pure_perl_install :: all $(NOECHO) $(MOD_INSTALL) \ read "$(PERL_ARCHLIB)/auto/$(FULLEXT)/.packlist" \ write "$(DESTINSTALLARCHLIB)/auto/$(FULLEXT)/.packlist" \ "$(INST_LIB)" "$(DESTINSTALLPRIVLIB)" \ "$(INST_ARCHLIB)" "$(DESTINSTALLARCHLIB)" \ "$(INST_BIN)" "$(DESTINSTALLBIN)" \ "$(INST_SCRIPT)" "$(DESTINSTALLSCRIPT)" \ "$(INST_MAN1DIR)" "$(DESTINSTALLMAN1DIR)" \ "$(INST_MAN3DIR)" "$(DESTINSTALLMAN3DIR)" $(NOECHO) $(WARN_IF_OLD_PACKLIST) \ "$(SITEARCHEXP)/auto/$(FULLEXT)" pure_site_install :: all $(NOECHO) $(MOD_INSTALL) \ read "$(SITEARCHEXP)/auto/$(FULLEXT)/.packlist" \ write "$(DESTINSTALLSITEARCH)/auto/$(FULLEXT)/.packlist" \ "$(INST_LIB)" "$(DESTINSTALLSITELIB)" \ "$(INST_ARCHLIB)" "$(DESTINSTALLSITEARCH)" \ "$(INST_BIN)" "$(DESTINSTALLSITEBIN)" \ "$(INST_SCRIPT)" "$(DESTINSTALLSITESCRIPT)" \ "$(INST_MAN1DIR)" "$(DESTINSTALLSITEMAN1DIR)" \ "$(INST_MAN3DIR)" "$(DESTINSTALLSITEMAN3DIR)" $(NOECHO) $(WARN_IF_OLD_PACKLIST) \ "$(PERL_ARCHLIB)/auto/$(FULLEXT)" pure_vendor_install :: all $(NOECHO) $(MOD_INSTALL) \ read "$(VENDORARCHEXP)/auto/$(FULLEXT)/.packlist" \ write "$(DESTINSTALLVENDORARCH)/auto/$(FULLEXT)/.packlist" \ "$(INST_LIB)" "$(DESTINSTALLVENDORLIB)" \ "$(INST_ARCHLIB)" "$(DESTINSTALLVENDORARCH)" \ "$(INST_BIN)" "$(DESTINSTALLVENDORBIN)" \ "$(INST_SCRIPT)" "$(DESTINSTALLVENDORSCRIPT)" \ "$(INST_MAN1DIR)" "$(DESTINSTALLVENDORMAN1DIR)" \ "$(INST_MAN3DIR)" "$(DESTINSTALLVENDORMAN3DIR)" doc_perl_install :: all $(NOECHO) $(ECHO) Appending installation info to "$(DESTINSTALLARCHLIB)/perllocal.pod" -$(NOECHO) $(MKPATH) "$(DESTINSTALLARCHLIB)" -$(NOECHO) $(DOC_INSTALL) \ "Module" "$(NAME)" \ "installed into" "$(INSTALLPRIVLIB)" \ LINKTYPE "$(LINKTYPE)" \ VERSION "$(VERSION)" \ EXE_FILES "$(EXE_FILES)" \ >> "$(DESTINSTALLARCHLIB)/perllocal.pod" doc_site_install :: all $(NOECHO) $(ECHO) Appending installation info to "$(DESTINSTALLARCHLIB)/perllocal.pod" -$(NOECHO) $(MKPATH) "$(DESTINSTALLARCHLIB)" -$(NOECHO) $(DOC_INSTALL) \ "Module" "$(NAME)" \ "installed into" "$(INSTALLSITELIB)" \ LINKTYPE "$(LINKTYPE)" \ VERSION "$(VERSION)" \ EXE_FILES "$(EXE_FILES)" \ >> "$(DESTINSTALLARCHLIB)/perllocal.pod" doc_vendor_install :: all $(NOECHO) $(ECHO) Appending installation info to "$(DESTINSTALLARCHLIB)/perllocal.pod" -$(NOECHO) $(MKPATH) "$(DESTINSTALLARCHLIB)" -$(NOECHO) $(DOC_INSTALL) \ "Module" "$(NAME)" \ "installed into" "$(INSTALLVENDORLIB)" \ LINKTYPE "$(LINKTYPE)" \ VERSION "$(VERSION)" \ EXE_FILES "$(EXE_FILES)" \ >> "$(DESTINSTALLARCHLIB)/perllocal.pod" uninstall :: uninstall_from_$(INSTALLDIRS)dirs $(NOECHO) $(NOOP) uninstall_from_perldirs :: $(NOECHO) $(UNINSTALL) "$(PERL_ARCHLIB)/auto/$(FULLEXT)/.packlist" uninstall_from_sitedirs :: $(NOECHO) $(UNINSTALL) "$(SITEARCHEXP)/auto/$(FULLEXT)/.packlist" uninstall_from_vendordirs :: $(NOECHO) $(UNINSTALL) "$(VENDORARCHEXP)/auto/$(FULLEXT)/.packlist" # --- MakeMaker force section: # Phony target to force checking subdirectories. FORCE : $(NOECHO) $(NOOP) # --- MakeMaker perldepend section: # --- MakeMaker makefile section: # We take a very conservative approach here, but it's worth it. # We move Makefile to Makefile.old here to avoid gnu make looping. $(FIRST_MAKEFILE) : Makefile.PL $(CONFIGDEP) $(NOECHO) $(ECHO) "Makefile out-of-date with respect to $?" $(NOECHO) $(ECHO) "Cleaning current config before rebuilding Makefile..." -$(NOECHO) $(RM_F) $(MAKEFILE_OLD) -$(NOECHO) $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD) - $(MAKE) $(USEMAKEFILE) $(MAKEFILE_OLD) clean $(DEV_NULL) $(PERLRUN) Makefile.PL $(NOECHO) $(ECHO) "==> Your Makefile has been rebuilt. <==" $(NOECHO) $(ECHO) "==> Please rerun the $(MAKE) command. <==" $(FALSE) # --- MakeMaker staticmake section: # --- MakeMaker makeaperl section --- MAP_TARGET = perl FULLPERL = "/usr/bin/perl" MAP_PERLINC = "-Iblib/arch" "-Iblib/lib" "-I/usr/lib64/perl5" "-I/usr/share/perl5" $(MAP_TARGET) :: $(MAKE_APERL_FILE) $(MAKE) $(USEMAKEFILE) $(MAKE_APERL_FILE) $@ $(MAKE_APERL_FILE) : static $(FIRST_MAKEFILE) pm_to_blib $(NOECHO) $(ECHO) Writing \"$(MAKE_APERL_FILE)\" for this $(MAP_TARGET) $(NOECHO) $(PERLRUNINST) \ Makefile.PL DIR="" \ MAKEFILE=$(MAKE_APERL_FILE) LINKTYPE=static \ MAKEAPERL=1 NORECURS=1 CCCDLFLAGS= # --- MakeMaker test section: TEST_VERBOSE=0 TEST_TYPE=test_$(LINKTYPE) TEST_FILE = test.pl TEST_FILES = t/*.t TESTDB_SW = -d testdb :: testdb_$(LINKTYPE) $(NOECHO) $(NOOP) test :: $(TEST_TYPE) $(NOECHO) $(NOOP) # Occasionally we may face this degenerate target: test_ : test_dynamic $(NOECHO) $(NOOP) subdirs-test_dynamic :: dynamic pure_all test_dynamic :: subdirs-test_dynamic PERL_DL_NONLAZY=1 $(FULLPERLRUN) "-MExtUtils::Command::MM" "-MTest::Harness" "-e" "undef *Test::Harness::Switches; test_harness($(TEST_VERBOSE), '$(INST_LIB)', '$(INST_ARCHLIB)')" $(TEST_FILES) testdb_dynamic :: dynamic pure_all PERL_DL_NONLAZY=1 $(FULLPERLRUN) $(TESTDB_SW) "-I$(INST_LIB)" "-I$(INST_ARCHLIB)" $(TEST_FILE) subdirs-test_static :: static pure_all test_static :: subdirs-test_static PERL_DL_NONLAZY=1 $(FULLPERLRUN) "-MExtUtils::Command::MM" "-MTest::Harness" "-e" "undef *Test::Harness::Switches; test_harness($(TEST_VERBOSE), '$(INST_LIB)', '$(INST_ARCHLIB)')" $(TEST_FILES) testdb_static :: static pure_all PERL_DL_NONLAZY=1 $(FULLPERLRUN) $(TESTDB_SW) "-I$(INST_LIB)" "-I$(INST_ARCHLIB)" $(TEST_FILE) # --- MakeMaker ppd section: # Creates a PPD (Perl Package Description) for a binary distribution. ppd : $(NOECHO) $(ECHO) '<SOFTPKG NAME="HTTP-CookieJar" VERSION="0.014">' > HTTP-CookieJar.ppd $(NOECHO) $(ECHO) ' <ABSTRACT>A minimalist HTTP user agent cookie jar</ABSTRACT>' >> HTTP-CookieJar.ppd $(NOECHO) $(ECHO) ' <AUTHOR>David Golden <dagolden@cpan.org></AUTHOR>' >> HTTP-CookieJar.ppd $(NOECHO) $(ECHO) ' <IMPLEMENTATION>' >> HTTP-CookieJar.ppd $(NOECHO) $(ECHO) ' <PERLCORE VERSION="5,008001,0,0" />' >> HTTP-CookieJar.ppd $(NOECHO) $(ECHO) ' <REQUIRE NAME="Carp::" />' >> HTTP-CookieJar.ppd $(NOECHO) $(ECHO) ' <REQUIRE NAME="HTTP::Date" />' >> HTTP-CookieJar.ppd $(NOECHO) $(ECHO) ' <REQUIRE NAME="Time::Local" VERSION="1.1901" />' >> HTTP-CookieJar.ppd $(NOECHO) $(ECHO) ' <REQUIRE NAME="parent::" />' >> HTTP-CookieJar.ppd $(NOECHO) $(ECHO) ' <REQUIRE NAME="strict::" />' >> HTTP-CookieJar.ppd $(NOECHO) $(ECHO) ' <REQUIRE NAME="warnings::" />' >> HTTP-CookieJar.ppd $(NOECHO) $(ECHO) ' <ARCHITECTURE NAME="x86_64-linux-thread-multi-5.32" />' >> HTTP-CookieJar.ppd $(NOECHO) $(ECHO) ' <CODEBASE HREF="" />' >> HTTP-CookieJar.ppd $(NOECHO) $(ECHO) ' </IMPLEMENTATION>' >> HTTP-CookieJar.ppd $(NOECHO) $(ECHO) '</SOFTPKG>' >> HTTP-CookieJar.ppd # --- MakeMaker pm_to_blib section: pm_to_blib : $(FIRST_MAKEFILE) $(TO_INST_PM) $(NOECHO) $(ABSPERLRUN) -MExtUtils::Install -e 'pm_to_blib({@ARGV}, '\''$(INST_LIB)/auto'\'', q[$(PM_FILTER)], '\''$(PERM_DIR)'\'')' -- \ 'lib/HTTP/CookieJar.pm' 'blib/lib/HTTP/CookieJar.pm' \ 'lib/HTTP/CookieJar/LWP.pm' 'blib/lib/HTTP/CookieJar/LWP.pm' $(NOECHO) $(TOUCH) pm_to_blib # --- MakeMaker selfdocument section: # here so even if top_targets is overridden, these will still be defined # gmake will silently still work if any are .PHONY-ed but nmake won't static :: $(NOECHO) $(NOOP) dynamic :: $(NOECHO) $(NOOP) config :: $(NOECHO) $(NOOP) # --- MakeMaker postamble section: # End. META.json 0000644 00000006633 15125143463 0006201 0 ustar 00 { "abstract" : "A minimalist HTTP user agent cookie jar", "author" : [ "David Golden <dagolden@cpan.org>" ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 6.025, CPAN::Meta::Converter version 2.150010", "license" : [ "apache_2_0" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "HTTP-CookieJar", "no_index" : { "directory" : [ "corpus", "examples", "t", "xt" ], "package" : [ "DB" ] }, "prereqs" : { "configure" : { "requires" : { "ExtUtils::MakeMaker" : "6.17", "perl" : "5.008001" } }, "develop" : { "requires" : { "Dist::Zilla" : "5", "Dist::Zilla::Plugin::Prereqs" : "0", "Dist::Zilla::Plugin::ReleaseStatus::FromVersion" : "0", "Dist::Zilla::Plugin::RemovePrereqs" : "0", "Dist::Zilla::PluginBundle::DAGOLDEN" : "0.072", "File::Spec" : "0", "File::Temp" : "0", "IO::Handle" : "0", "IPC::Open3" : "0", "Pod::Coverage::TrustPod" : "0", "Pod::Wordlist" : "0", "Software::License::Apache_2_0" : "0", "Test::CPAN::Meta" : "0", "Test::MinimumVersion" : "0", "Test::More" : "0", "Test::Perl::Critic" : "0", "Test::Pod" : "1.41", "Test::Pod::Coverage" : "1.08", "Test::Portability::Files" : "0", "Test::Spelling" : "0.12", "Test::Version" : "1" } }, "runtime" : { "recommends" : { "Mozilla::PublicSuffix" : "0" }, "requires" : { "Carp" : "0", "HTTP::Date" : "0", "Time::Local" : "1.1901", "parent" : "0", "perl" : "5.008001", "strict" : "0", "warnings" : "0" } }, "test" : { "recommends" : { "CPAN::Meta" : "2.120900" }, "requires" : { "ExtUtils::MakeMaker" : "0", "File::Spec" : "0", "Test::Deep" : "0", "Test::More" : "0.96", "Test::Requires" : "0", "Time::Local" : "1.1901", "URI" : "0", "lib" : "0", "perl" : "5.008001" } } }, "provides" : { "HTTP::CookieJar" : { "file" : "lib/HTTP/CookieJar.pm", "version" : "0.014" }, "HTTP::CookieJar::LWP" : { "file" : "lib/HTTP/CookieJar/LWP.pm", "version" : "0.014" } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/dagolden/HTTP-CookieJar/issues" }, "homepage" : "https://github.com/dagolden/HTTP-CookieJar", "repository" : { "type" : "git", "url" : "https://github.com/dagolden/HTTP-CookieJar.git", "web" : "https://github.com/dagolden/HTTP-CookieJar" } }, "version" : "0.014", "x_authority" : "cpan:DAGOLDEN", "x_contributors" : [ "Dan Book <grinnz@grinnz.com>", "David Golden <xdg@xdg.me>", "jvolkening <jdv@base2bio.com>" ], "x_generated_by_perl" : "v5.36.0", "x_serialization_backend" : "Cpanel::JSON::XS version 4.29", "x_spdx_expression" : "Apache-2.0" } LICENSE 0000644 00000026335 15125143463 0005566 0 ustar 00 This software is Copyright (c) 2013 by David Golden. This is free software, licensed under: The Apache License, Version 2.0, January 2004 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright 2013 David Golden Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. t/examples.t 0000644 00000002737 15125143463 0007027 0 ustar 00 use 5.008001; use strict; use warnings; use Test::More 0.96; use HTTP::CookieJar; my $req = "http://www.example.com/foo/bar"; my $sreq = "https://www.example.com/foo/bar"; my $jar = new_ok("HTTP::CookieJar"); subtest "just key & value" => sub { $jar->clear; $jar->add( $req, "SID=31d4d96e407aad42" ); is( $jar->cookie_header($req), "SID=31d4d96e407aad42" ); }; subtest "secure" => sub { $jar->clear; $jar->add( $req, "SID=31d4d96e407aad42; Secure" ); $jar->add( $req, "lang=en-US; Path=/; Domain=example.com" ); is( $jar->cookie_header($sreq), "SID=31d4d96e407aad42; lang=en-US" ); is( $jar->cookie_header($req), "lang=en-US" ); }; subtest "not a subdomain" => sub { $jar->clear; $jar->add( $req, "SID=31d4d96e407aad42" ); is( $jar->cookie_header("http://wwww.example.com/foo/baz"), "" ); }; subtest "wrong path" => sub { $jar->clear; $jar->add( $req, "SID=31d4d96e407aad42" ); is( $jar->cookie_header("http://www.example.com/"), "" ); }; subtest "expiration" => sub { $jar->clear; $jar->add( $req, "lang=en-US; Expires=Sun, 09 Jun 2041 10:18:14 GMT" ); is( $jar->cookie_header($req), "lang=en-US" ); $jar->add( $req, "lang=; Expires=Sun, 06 Nov 1994 08:49:37 GMT" ); is( $jar->cookie_header($req), "" ); }; done_testing; # # This file is part of HTTP-CookieJar # # This software is Copyright (c) 2013 by David Golden. # # This is free software, licensed under: # # The Apache License, Version 2.0, January 2004 # t/zzz-lwp.t 0000644 00000053450 15125143463 0006644 0 ustar 00 use 5.008001; use warnings; use Test::More 0.96; use Time::Local; use HTTP::CookieJar::LWP; use Test::Requires qw( HTTP::Request HTTP::Response ); #------------------------------------------------------------------- # First we check that it works for the original example at # http://curl.haxx.se/rfc/cookie_spec.html # Client requests a document, and receives in the response: # # Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/; expires=Wednesday, 09-Nov-99 23:12:40 GMT # # When client requests a URL in path "/" on this server, it sends: # # Cookie: CUSTOMER=WILE_E_COYOTE # # Client requests a document, and receives in the response: # # Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/ # # When client requests a URL in path "/" on this server, it sends: # # Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001 # # Client receives: # # Set-Cookie: SHIPPING=FEDEX; path=/fo # # When client requests a URL in path "/" on this server, it sends: # # Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001 # # When client requests a URL in path "/foo" on this server, it sends: # # Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001; SHIPPING=FEDEX # # The last Cookie is buggy, because both specifications says that the # most specific cookie must be sent first. SHIPPING=FEDEX is the # most specific and should thus be first. my $year_plus_one = (localtime)[5] + 1900 + 1; $c = HTTP::CookieJar::LWP->new; $req = HTTP::Request->new( GET => "http://1.1.1.1/" ); $req->header( "Host", "www.acme.com:80" ); $res = HTTP::Response->new( 200, "OK" ); $res->request($req); $res->header( "Set-Cookie" => "CUSTOMER=WILE_E_COYOTE; path=/ ; expires=Wednesday, 09-Nov-$year_plus_one 23:12:40 GMT" ); #; $c->extract_cookies($res); $req = HTTP::Request->new( GET => "http://www.acme.com/" ); $c->add_cookie_header($req); is( $req->header("Cookie"), "CUSTOMER=WILE_E_COYOTE" ) or diag explain $c; $res->request($req); $res->header( "Set-Cookie" => "PART_NUMBER=ROCKET_LAUNCHER_0001; path=/" ); $c->extract_cookies($res); $req = HTTP::Request->new( GET => "http://www.acme.com/foo/bar" ); $c->add_cookie_header($req); $h = $req->header("Cookie"); ok( $h =~ /PART_NUMBER=ROCKET_LAUNCHER_0001/ ); ok( $h =~ /CUSTOMER=WILE_E_COYOTE/ ); $res->request($req); $res->header( "Set-Cookie", "SHIPPING=FEDEX; path=/foo" ); $c->extract_cookies($res); $req = HTTP::Request->new( GET => "http://www.acme.com/" ); $c->add_cookie_header($req); $h = $req->header("Cookie"); ok( $h =~ /PART_NUMBER=ROCKET_LAUNCHER_0001/ ); ok( $h =~ /CUSTOMER=WILE_E_COYOTE/ ); ok( $h !~ /SHIPPING=FEDEX/ ); $req = HTTP::Request->new( GET => "http://www.acme.com/foo/" ); $c->add_cookie_header($req); $h = $req->header("Cookie"); ok( $h =~ /PART_NUMBER=ROCKET_LAUNCHER_0001/ ); ok( $h =~ /CUSTOMER=WILE_E_COYOTE/ ); ok( $h =~ /^SHIPPING=FEDEX;/ ); # Second Example transaction sequence: # # Assume all mappings from above have been cleared. # # Client receives: # # Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/ # # When client requests a URL in path "/" on this server, it sends: # # Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001 # # Client receives: # # Set-Cookie: PART_NUMBER=RIDING_ROCKET_0023; path=/ammo # # When client requests a URL in path "/ammo" on this server, it sends: # # Cookie: PART_NUMBER=RIDING_ROCKET_0023; PART_NUMBER=ROCKET_LAUNCHER_0001 # # NOTE: There are two name/value pairs named "PART_NUMBER" due to # the inheritance of the "/" mapping in addition to the "/ammo" mapping. $c = HTTP::CookieJar::LWP->new; # clear it $req = HTTP::Request->new( GET => "http://www.acme.com/" ); $res = HTTP::Response->new( 200, "OK" ); $res->request($req); $res->header( "Set-Cookie", "PART_NUMBER=ROCKET_LAUNCHER_0001; path=/" ); $c->extract_cookies($res); $req = HTTP::Request->new( GET => "http://www.acme.com/" ); $c->add_cookie_header($req); is( $req->header("Cookie"), "PART_NUMBER=ROCKET_LAUNCHER_0001" ); $res->request($req); $res->header( "Set-Cookie", "PART_NUMBER=RIDING_ROCKET_0023; path=/ammo" ); $c->extract_cookies($res); $req = HTTP::Request->new( GET => "http://www.acme.com/ammo" ); $c->add_cookie_header($req); ok( $req->header("Cookie") =~ /^PART_NUMBER=RIDING_ROCKET_0023;\s*PART_NUMBER=ROCKET_LAUNCHER_0001/ ); undef($c); #------------------------------------------------------------------- # When there are no "Set-Cookie" header, then even responses # without any request URLs connected should be allowed. $c = HTTP::CookieJar::LWP->new; $c->extract_cookies( HTTP::Response->new( "200", "OK" ) ); is( count_cookies($c), 0 ); #------------------------------------------------------------------- # Then we test with the examples from RFC 2965. # # 5. EXAMPLES # XXX BUT CONVERT THEM FROM COOKIE2 TO REGULAR COOKIE --xdg $c = HTTP::CookieJar::LWP->new; # # 5.1 Example 1 # # Most detail of request and response headers has been omitted. Assume # the user agent has no stored cookies. # # 1. User Agent -> Server # # POST /acme/login HTTP/1.1 # [form data] # # User identifies self via a form. # # 2. Server -> User Agent # # HTTP/1.1 200 OK # Set-Cookie2: Customer="WILE_E_COYOTE"; Version="1"; Path="/acme" # # Cookie reflects user's identity. $cookie = interact( $c, 'http://www.acme.com/acme/login', 'Customer=WILE_E_COYOTE; Path=/acme' ); ok( !$cookie ); # # 3. User Agent -> Server # # POST /acme/pickitem HTTP/1.1 # Cookie: $Version="1"; Customer="WILE_E_COYOTE"; $Path="/acme" # [form data] # # User selects an item for ``shopping basket.'' # # 4. Server -> User Agent # # HTTP/1.1 200 OK # Set-Cookie2: Part_Number="Rocket_Launcher_0001"; Version="1"; # Path="/acme" # # Shopping basket contains an item. $cookie = interact( $c, 'http://www.acme.com/acme/pickitem', 'Part_Number=Rocket_Launcher_0001; Path=/acme' ); is( $cookie, "Customer=WILE_E_COYOTE" ); # # 5. User Agent -> Server # # POST /acme/shipping HTTP/1.1 # Cookie: $Version="1"; # Customer="WILE_E_COYOTE"; $Path="/acme"; # Part_Number="Rocket_Launcher_0001"; $Path="/acme" # [form data] # # User selects shipping method from form. # # 6. Server -> User Agent # # HTTP/1.1 200 OK # Set-Cookie2: Shipping="FedEx"; Version="1"; Path="/acme" # # New cookie reflects shipping method. $cookie = interact( $c, "http://www.acme.com/acme/shipping", 'Shipping=FedEx; Path=/acme' ); like( $cookie, qr/Part_Number=Rocket_Launcher_0001/ ); like( $cookie, qr/Customer=WILE_E_COYOTE/ ); # # 7. User Agent -> Server # # POST /acme/process HTTP/1.1 # Cookie: $Version="1"; # Customer="WILE_E_COYOTE"; $Path="/acme"; # Part_Number="Rocket_Launcher_0001"; $Path="/acme"; # Shipping="FedEx"; $Path="/acme" # [form data] # # User chooses to process order. # # 8. Server -> User Agent # # HTTP/1.1 200 OK # # Transaction is complete. $cookie = interact( $c, "http://www.acme.com/acme/process" ); like( $cookie, qr/Shipping=FedEx/ ); like( $cookie, qr/WILE_E_COYOTE/ ); # # The user agent makes a series of requests on the origin server, after # each of which it receives a new cookie. All the cookies have the same # Path attribute and (default) domain. Because the request URLs all have # /acme as a prefix, and that matches the Path attribute, each request # contains all the cookies received so far. ##; # 5.2 Example 2 # # This example illustrates the effect of the Path attribute. All detail # of request and response headers has been omitted. Assume the user agent # has no stored cookies. $c = HTTP::CookieJar::LWP->new; # Imagine the user agent has received, in response to earlier requests, # the response headers # # Set-Cookie2: Part_Number="Rocket_Launcher_0001"; Version="1"; # Path="/acme" # # and # # Set-Cookie2: Part_Number="Riding_Rocket_0023"; Version="1"; # Path="/acme/ammo" interact( $c, "http://www.acme.com/acme/ammo/specific", 'Part_Number=Rocket_Launcher_0001; Path=/acme', 'Part_Number=Riding_Rocket_0023; Path=/acme/ammo' ); # A subsequent request by the user agent to the (same) server for URLs of # the form /acme/ammo/... would include the following request header: # # Cookie: $Version="1"; # Part_Number="Riding_Rocket_0023"; $Path="/acme/ammo"; # Part_Number="Rocket_Launcher_0001"; $Path="/acme" # # Note that the NAME=VALUE pair for the cookie with the more specific Path # attribute, /acme/ammo, comes before the one with the less specific Path # attribute, /acme. Further note that the same cookie name appears more # than once. $cookie = interact( $c, "http://www.acme.com/acme/ammo/..." ); like( $cookie, qr/Riding_Rocket_0023.*Rocket_Launcher_0001/ ); # A subsequent request by the user agent to the (same) server for a URL of # the form /acme/parts/ would include the following request header: # # Cookie: $Version="1"; Part_Number="Rocket_Launcher_0001"; $Path="/acme" # # Here, the second cookie's Path attribute /acme/ammo is not a prefix of # the request URL, /acme/parts/, so the cookie does not get forwarded to # the server. $cookie = interact( $c, "http://www.acme.com/acme/parts/" ); ok( $cookie =~ /Rocket_Launcher_0001/ ); ok( $cookie !~ /Riding_Rocket_0023/ ); ##; #----------------------------------------------------------------------- # Test rejection of Set-Cookie2 responses based on domain, path or port $c = HTTP::CookieJar::LWP->new; # XXX RFC 6265 says strip leading dots and embedded dots in prefix are OK ### illegal domain (no embedded dots) ##$cookie = interact($c, "http://www.acme.com", 'foo=bar; domain=.com'); ##is(count_cookies($c), 0); # legal domain $cookie = interact( $c, "http://www.acme.com", 'foo=bar; domain=acme.com' ); is( count_cookies($c), 1 ); # illegal domain (host prefix "www.a" contains a dot) $cookie = interact( $c, "http://www.a.acme.com", 'foo=bar; domain=acme.com' ); is( count_cookies($c), 1 ); # legal domain $cookie = interact( $c, "http://www.a.acme.com", 'foo=bar; domain=.a.acme.com' ); is( count_cookies($c), 2 ); # can't use a IP-address as domain $cookie = interact( $c, "http://125.125.125.125", 'foo=bar; domain=125.125.125' ); is( count_cookies($c), 2 ); # XXX RFC 6265 doesn't prohibit this; path matching happens on cookie header generation ### illegal path (must be prefix of request path) ##$cookie = interact($c, "http://www.sol.no", 'foo=bar; domain=.sol.no; path=/foo'); ##is(count_cookies($c), 2); # legal path $cookie = interact( $c, "http://www.sol.no/foo/bar", 'foo=bar; domain=.sol.no; path=/foo' ); is( count_cookies($c), 3 ); # XXX ports not part of RFC 6265 standard ### illegal port (request-port not in list) ##$cookie = interact($c, "http://www.sol.no", 'foo=bar; domain=.sol.no; port=90,100'); ##is(count_cookies($c), 3); # legal port $cookie = interact( $c, "http://www.sol.no", 'foo=bar; domain=.sol.no; port=90,100, 80,8080; max-age=100; Comment = "Just kidding! (\"|\\\\) "' ); is( count_cookies($c), 4 ); # port attribute without any value (current port) $cookie = interact( $c, "http://www.sol.no", 'foo9=bar; domain=.sol.no; port; max-age=100;' ); is( count_cookies($c), 5 ) or diag explain $c; # encoded path $cookie = interact( $c, "http://www.sol.no/foo/", 'foo8=bar; path=/%66oo' ); is( count_cookies($c), 6 ); # XXX not doing save/load ##my $file = "lwp-cookies-$$.txt"; ##$c->save($file); ##$old = $c->as_string; ##undef($c); ##$c = HTTP::CookieJar::LWP->new; ##$c->load($file); ##unlink($file) || warn "Can't unlink $file: $!"; ## ##is($old, $c->as_string); ## ##undef($c); # # Try some URL encodings of the PATHs # $c = HTTP::CookieJar::LWP->new; interact( $c, "http://www.acme.com/foo%2f%25/%40%40%0Anew%E5/%E5", 'foo = bar' ); ##; $cookie = interact( $c, "http://www.acme.com/foo%2f%25/@@%0anewå/æøå", "bar=baz; path=/foo/" ); ok( $cookie =~ /foo=bar/ ); $cookie = interact( $c, "http://www.acme.com/foo/%25/@@%0anewå/æøå" ); ok($cookie); undef($c); # ### Try to use the Netscape cookie file format for saving ### ##$file = "cookies-$$.txt"; ##$c = HTTP::CookieJar::LWP->new(file => $file); ##interact($c, "http://www.acme.com/", "foo1=bar; max-age=100"); ##interact($c, "http://www.acme.com/", "foo2=bar; port=\"80\"; max-age=100; Discard; Version=1"); ##interact($c, "http://www.acme.com/", "foo3=bar; secure; Version=1"); ##$c->save; ##undef($c); ## ##$c = HTTP::CookieJar::LWP->new(file => $file); ##is(count_cookies($c), 1); # 2 of them discarded on save ## ##ok($c->as_string =~ /foo1=bar/); ##undef($c); ##unlink($file); # # Some additional Netscape cookies test # $c = HTTP::CookieJar::LWP->new; $req = HTTP::Request->new( POST => "http://foo.bar.acme.com/foo" ); # Netscape allows a host part that contains dots $res = HTTP::Response->new( 200, "OK" ); $res->header( set_cookie => 'Customer=WILE_E_COYOTE; domain=.acme.com' ); $res->request($req); $c->extract_cookies($res); # and that the domain is the same as the host without adding a leading # dot to the domain. Should not quote even if strange chars are used # in the cookie value. $res = HTTP::Response->new( 200, "OK" ); $res->header( set_cookie => 'PART_NUMBER=3,4; domain=foo.bar.acme.com' ); $res->request($req); $c->extract_cookies($res); ##; require URI; $req = HTTP::Request->new( POST => URI->new("http://foo.bar.acme.com/foo") ); $c->add_cookie_header($req); #; ok( $req->header("Cookie") =~ /PART_NUMBER=3,4/ ); ok( $req->header("Cookie") =~ /Customer=WILE_E_COYOTE/ ); # XXX the .local mechanism is not in RFC 6265 # Test handling of local intranet hostnames without a dot ##$c->clear; ##print "---\n"; ## ##interact($c, "http://example/", "foo1=bar; PORT; Discard;"); ##$cookie=interact($c, "http://example/", 'foo2=bar; domain=".local"'); ##like($cookie, qr/foo1=bar/); ## ##$cookie=interact($c, "http://example/", 'foo3=bar'); ##$cookie=interact($c, "http://example/"); ##like($cookie, qr/foo2=bar/); ##is(count_cookies($c), 3); # Test for empty path # Broken web-server ORION/1.3.38 returns to the client response like # # Set-Cookie: JSESSIONID=ABCDERANDOM123; Path= # # e.g. with Path set to nothing. # In this case routine extract_cookies() must set cookie to / (root) $c = HTTP::CookieJar::LWP->new; # clear it $req = HTTP::Request->new( GET => "http://www.ants.com/" ); $res = HTTP::Response->new( 200, "OK" ); $res->request($req); $res->header( "Set-Cookie" => "JSESSIONID=ABCDERANDOM123; Path=" ); $c->extract_cookies($res); $req = HTTP::Request->new( GET => "http://www.ants.com/" ); $c->add_cookie_header($req); is( $req->header("Cookie"), "JSESSIONID=ABCDERANDOM123" ); # missing path in the request URI $req = HTTP::Request->new( GET => URI->new("http://www.ants.com:8080") ); $c->add_cookie_header($req); is( $req->header("Cookie"), "JSESSIONID=ABCDERANDOM123" ); # XXX we don't support Cookie2 ### test mixing of Set-Cookie and Set-Cookie2 headers. ### Example from http://www.trip.com/trs/trip/flighttracker/flight_tracker_home.xsl ### which gives up these headers: ### ### HTTP/1.1 200 OK ### Connection: close ### Date: Fri, 20 Jul 2001 19:54:58 GMT ### Server: Apache/1.3.19 (Unix) ApacheJServ/1.1.2 ### Content-Type: text/html ### Content-Type: text/html; charset=iso-8859-1 ### Link: </trip/stylesheet.css>; rel="stylesheet"; type="text/css" ### Servlet-Engine: Tomcat Web Server/3.2.1 (JSP 1.1; Servlet 2.2; Java 1.3.0; SunOS 5.8 sparc; java.vendor=Sun Microsystems Inc.) ### Set-Cookie: trip.appServer=1111-0000-x-024;Domain=.trip.com;Path=/ ### Set-Cookie: JSESSIONID=fkumjm7nt1.JS24;Path=/trs ### Set-Cookie2: JSESSIONID=fkumjm7nt1.JS24;Version=1;Discard;Path="/trs" ### Title: TRIP.com Travel - FlightTRACKER ### X-Meta-Description: Trip.com privacy policy ### X-Meta-Keywords: privacy policy ## ##$req = HTTP::Request->new('GET', 'http://www.trip.com/trs/trip/flighttracker/flight_tracker_home.xsl'); ##$res = HTTP::Response->new(200, "OK"); ##$res->request($req); ##$res->push_header("Set-Cookie" => qq(trip.appServer=1111-0000-x-024;Domain=.trip.com;Path=/)); ##$res->push_header("Set-Cookie" => qq(JSESSIONID=fkumjm7nt1.JS24;Path=/trs)); ##$res->push_header("Set-Cookie2" => qq(JSESSIONID=fkumjm7nt1.JS24;Version=1;Discard;Path="/trs")); ###; ## ##$c = HTTP::CookieJar::LWP->new; # clear it ##$c->extract_cookies($res); ##; ##is($c->as_string, <<'EOT'); ##Set-Cookie3: trip.appServer=1111-0000-x-024; path="/"; domain=.trip.com; path_spec; discard; version=0 ##Set-Cookie3: JSESSIONID=fkumjm7nt1.JS24; path="/trs"; domain=www.trip.com; path_spec; discard; version=1 ##EOT # XXX not implemented yet -- xdg, 2013-02-11 ###------------------------------------------------------------------- ### Test if temporary cookies are deleted properly with ### $jar->clear_temporary_cookies() ## ##$req = HTTP::Request->new('GET', 'http://www.perlmeister.com/scripts'); ##$res = HTTP::Response->new(200, "OK"); ##$res->request($req); ## # Set session/perm cookies and mark their values as "session" vs. "perm" ## # to recognize them later ##$res->push_header("Set-Cookie" => qq(s1=session;Path=/scripts)); ##$res->push_header("Set-Cookie" => qq(p1=perm; Domain=.perlmeister.com;Path=/;expires=Fri, 02-Feb-$year_plus_one 23:24:20 GMT)); ##$res->push_header("Set-Cookie" => qq(p2=perm;Path=/;expires=Fri, 02-Feb-$year_plus_one 23:24:20 GMT)); ##$res->push_header("Set-Cookie" => qq(s2=session;Path=/scripts;Domain=.perlmeister.com)); ##$res->push_header("Set-Cookie2" => qq(s3=session;Version=1;Discard;Path="/")); ## ##$c = HTTP::CookieJar::LWP->new; # clear jar ##$c->extract_cookies($res); ### How many session/permanent cookies do we have? ##my %counter = ("session_after" => 0); ##$c->scan( sub { $counter{"${_[2]}_before"}++ } ); ##$c->clear_temporary_cookies(); ### How many now? ##$c->scan( sub { $counter{"${_[2]}_after"}++ } ); ##is($counter{"perm_after"}, $counter{"perm_before"}); # a permanent cookie got lost accidently ##is($counter{"session_after"}, 0); # a session cookie hasn't been cleared ##is($counter{"session_before"}, 3); # we didn't have session cookies in the first place ###; # Test handling of 'secure ' attribute for classic cookies $c = HTTP::CookieJar::LWP->new; $req = HTTP::Request->new( GET => "https://1.1.1.1/" ); $req->header( "Host", "www.acme.com:80" ); $res = HTTP::Response->new( 200, "OK" ); $res->request($req); $res->header( "Set-Cookie" => "CUSTOMER=WILE_E_COYOTE ; secure ; path=/" ); #; $c->extract_cookies($res); $req = HTTP::Request->new( GET => "http://www.acme.com/" ); $c->add_cookie_header($req); ok( !$req->header("Cookie") ); $req->uri->scheme("https"); $c->add_cookie_header($req); is( $req->header("Cookie"), "CUSTOMER=WILE_E_COYOTE" ); $req = HTTP::Request->new( GET => "ftp://ftp.activestate.com/" ); $c->add_cookie_header($req); ok( !$req->header("Cookie") ); $req = HTTP::Request->new( GET => "file:/etc/motd" ); $c->add_cookie_header($req); ok( !$req->header("Cookie") ); $req = HTTP::Request->new( GET => "mailto:gisle\@aas.no" ); $c->add_cookie_header($req); ok( !$req->header("Cookie") ); # Test cookie called 'expires' <https://rt.cpan.org/Ticket/Display.html?id=8108> $c = HTTP::CookieJar::LWP->new; $cookie = interact( $c, "http://example.com/", 'Expires=10101' ); $cookie = interact( $c, "http://example.com/" ); is( $cookie, 'Expires=10101' ) or diag explain $c; # Test empty cookie header [RT#29401] $c = HTTP::CookieJar::LWP->new; $cookie = interact( $c, "http://example.com/", "CUSTOMER=WILE_E_COYOTE; path=/;", "" ); is( count_cookies($c), 1, "empty cookie not set" ); # Test empty cookie part [RT#38480] $c = HTTP::CookieJar::LWP->new; $cookie = interact( $c, "http://example.com/", "CUSTOMER=WILE_E_COYOTE;;path=/;" ); $cookie = interact( $c, "http://example.com/" ); like( $cookie, qr/CUSTOMER=WILE_E_COYOTE/, "empty attribute ignored" ); # Test Set-Cookie with version set $c = HTTP::CookieJar::LWP->new; $cookie = interact( $c, "http://example.com/", "foo=\"bar\";version=1" ); $cookie = interact( $c, "http://example.com/" ); is( $cookie, "foo=\"bar\"", "version ignored" ); # Test cookies that expire far into the future [RT#50147] ( or past ? ) # if we can't do far future, use 2037 my $future = eval { timegm( 1, 2, 3, 4, 5, 2039 ) } ? 2211 : 2037; $c = HTTP::CookieJar::LWP->new; interact( $c, "http://example.com/foo", "PREF=ID=cee18f7c4e977184:TM=1254583090:LM=1254583090:S=Pdb0-hy9PxrNj4LL; expires=Mon, 03-Oct-$future 15:18:10 GMT; path=/; domain=.example.com", "expired1=1; expires=Mon, 03-Oct-2001 15:18:10 GMT; path=/; domain=.example.com", "expired2=1; expires=Fri Jan 1 00:00:00 GMT 1970; path=/; domain=.example.com", "expired3=1; expires=Fri Jan 1 00:00:01 GMT 1970; path=/; domain=.example.com", "expired4=1; expires=Thu Dec 31 23:59:59 GMT 1969; path=/; domain=.example.com", "expired5=1; expires=Fri Feb 2 00:00:00 GMT 1950; path=/; domain=.example.com", ); $cookie = interact( $c, "http://example.com/foo" ); is( $cookie, "PREF=ID=cee18f7c4e977184:TM=1254583090:LM=1254583090:S=Pdb0-hy9PxrNj4LL", "far future and past" ) or diag explain $c; # Test merging of cookies $c = HTTP::CookieJar::LWP->new; interact( $c, "http://example.com/foo/bar", "foo=1" ); interact( $c, "http://example.com/foo", "foo=2; path=/" ); $cookie = interact( $c, "http://example.com/foo/bar" ); is( $cookie, "foo=1; foo=2", "merging cookies" ); #------------------------------------------------------------------- sub interact { my $c = shift; my $url = shift; my $req = HTTP::Request->new( POST => $url ); $c->add_cookie_header($req); my $cookie = $req->header("Cookie"); my $res = HTTP::Response->new( 200, "OK" ); $res->request($req); for (@_) { $res->push_header( "Set-Cookie" => $_ ) } $c->extract_cookies($res); return $cookie; } sub count_cookies { my $c = shift; return scalar $c->_all_cookies; } done_testing; # # This file is part of HTTP-CookieJar # # This software is Copyright (c) 2013 by David Golden. # # This is free software, licensed under: # # The Apache License, Version 2.0, January 2004 # t/cookies_for.t 0000644 00000002417 15125143463 0007506 0 ustar 00 use 5.008001; use strict; use warnings; use Test::More 0.96; use Test::Deep '!blessed'; use lib 't/lib'; use MockTime; use HTTP::CookieJar; my $url = "http://example.com/foo/bar/"; my @input = ( [ $url, "SID=2; Path=/" ], [ $url, "SID=1; Path=/foo" ], [ $url, "SID=0; Path=/foo/bar" ], ); # MockTime keeps this constant my $creation_time = time; my $jar = HTTP::CookieJar->new; $jar->add(@$_) for @input; # Move up the clock for access time MockTime->offset(10); my $last_access_time = time; # Check that cookies_for has expected times for my $c ( $jar->cookies_for($url) ) { is( $c->{creation_time}, $creation_time, "$c->{name}=$c->{value} creation_time" ); is( $c->{last_access_time}, $last_access_time, "$c->{name}=$c->{value} last_access_time" ); } # Modify cookies from cookies_for and verify they aren't changed # from private originals. for my $c ( $jar->cookies_for($url) ) { $c->{creation_time} = 0; } for my $c ( $jar->_cookies_for($url) ) { is( $c->{creation_time}, $creation_time, "$c->{name}=$c->{value} creation_time" ); } done_testing; # # This file is part of HTTP-CookieJar # # This software is Copyright (c) 2013 by David Golden. # # This is free software, licensed under: # # The Apache License, Version 2.0, January 2004 # t/publicsuffix.t 0000644 00000006036 15125143463 0007710 0 ustar 00 use 5.008001; use strict; use warnings; use Test::More 0.96; use Test::Deep '!blessed'; use Test::Requires 'Mozilla::PublicSuffix'; use HTTP::CookieJar; my @cases = ( { label => "host is public suffix", request => "http://com.au/", cookies => ["SID=31d4d96e407aad42; Domain=com.au"], store => { 'com.au' => { '/' => { SID => { name => "SID", value => "31d4d96e407aad42", creation_time => ignore(), last_access_time => ignore(), domain => "com.au", hostonly => 1, path => "/", } } }, }, }, { label => "host is suffix of public suffix", request => "http://au/", cookies => ["SID=31d4d96e407aad42; Domain=au"], store => { 'au' => { '/' => { SID => { name => "SID", value => "31d4d96e407aad42", creation_time => ignore(), last_access_time => ignore(), domain => "au", hostonly => 1, path => "/", } } }, }, }, { label => "host is unrecognized single level", request => "http://localhost/", cookies => ["SID=31d4d96e407aad42; Domain=localhost"], store => { 'localhost' => { '/' => { SID => { name => "SID", value => "31d4d96e407aad42", creation_time => ignore(), last_access_time => ignore(), domain => "localhost", hostonly => 1, path => "/", } } }, }, }, { label => "cookie is public suffix", request => "http://example.com.au/", cookies => ["SID=31d4d96e407aad42; Domain=com.au"], store => {}, }, { label => "cookie is suffix of public suffix", request => "http://example.com.au/", cookies => ["SID=31d4d96e407aad42; Domain=au"], store => {}, }, ); for my $c (@cases) { my $jar = HTTP::CookieJar->new; for my $cookie ( @{ $c->{cookies} } ) { $jar->add( $c->{request}, $cookie ); } cmp_deeply $jar->{store}, $c->{store}, $c->{label} or diag explain $jar->{store}; } done_testing; # # This file is part of HTTP-CookieJar # # This software is Copyright (c) 2013 by David Golden. # # This is free software, licensed under: # # The Apache License, Version 2.0, January 2004 # t/parse.t 0000644 00000005216 15125143463 0006316 0 ustar 00 use 5.008001; use strict; use warnings; use Test::More 0.96; use Test::Deep '!blessed'; use HTTP::CookieJar; my @cases = ( { cookie => "", parse => undef, }, { cookie => "SID=", parse => { name => "SID", value => "", } }, { cookie => "=31d4d96e407aad42", parse => undef, }, { cookie => "; Max-Age: 1360343635", parse => undef, }, { cookie => "SID=31d4d96e407aad42", parse => { name => "SID", value => "31d4d96e407aad42", } }, { cookie => "SID=ID=31d4d96e407aad42", parse => { name => "SID", value => "ID=31d4d96e407aad42", } }, { cookie => "SID=31d4d96e407aad42 ; ; ; ", parse => { name => "SID", value => "31d4d96e407aad42", } }, { cookie => "SID=31d4d96e407aad42; Path=/; Secure; HttpOnly", parse => { name => "SID", value => "31d4d96e407aad42", path => "/", secure => 1, httponly => 1, } }, { cookie => "SID=31d4d96e407aad42; Domain=.example.com", parse => { name => "SID", value => "31d4d96e407aad42", domain => "example.com", } }, { cookie => "SID=31d4d96e407aad42; Path=/; Domain=example.com", parse => { name => "SID", value => "31d4d96e407aad42", path => "/", domain => "example.com", } }, { cookie => "SID=31d4d96e407aad42; Path=/; Domain=", parse => { name => "SID", value => "31d4d96e407aad42", path => "/", } }, { cookie => "lang=en-US; Expires = Sun, 09 Jun 2041 10:18:14 GMT", parse => { name => "lang", value => "en-US", expires => 2254385894, } }, { cookie => "lang=en-US; Expires = Sun, 09 Jun 2041 10:18:14 GMT; Max-Age=3600", parse => { name => "lang", value => "en-US", expires => 2254385894, 'max-age' => 3600, } }, ); for my $c (@cases) { my $got = HTTP::CookieJar::_parse_cookie( $c->{cookie} ); cmp_deeply $got, $c->{parse}, $c->{cookie} || q{''}; } done_testing; # # This file is part of HTTP-CookieJar # # This software is Copyright (c) 2013 by David Golden. # # This is free software, licensed under: # # The Apache License, Version 2.0, January 2004 # t/sort.t 0000644 00000002744 15125143463 0006176 0 ustar 00 use 5.008001; use strict; use warnings; use Test::More 0.96; use Test::Deep '!blessed'; use lib 't/lib'; use MockTime; use HTTP::CookieJar; my @cases = ( { label => "path length", request => "http://example.com/foo/bar/", cookies => [ [ "http://example.com/foo/bar/", "SID=2; Path=/" ], [ "http://example.com/foo/bar/", "SID=1; Path=/foo" ], [ "http://example.com/foo/bar/", "SID=0; Path=/foo/bar" ], ], }, { label => "creation time", request => "http://foo.bar.baz.example.com/", cookies => [ [ "http://foo.bar.baz.example.com/", "SID=0; Path=/; Domain=bar.baz.example.com" ], [ "http://foo.bar.baz.example.com/", "SID=1; Path=/; Domain=baz.example.com" ], [ "http://foo.bar.baz.example.com/", "SID=2; Path=/; Domain=example.com" ], ], }, ); for my $c (@cases) { my $jar = HTTP::CookieJar->new; my $offset = 0; for my $cookie ( @{ $c->{cookies} } ) { MockTime->offset($offset); $jar->add(@$cookie); $offset += 10; } my @cookies = $jar->cookies_for( $c->{request} ); my @vals = map { $_->{value} } @cookies; cmp_deeply \@vals, [ 0 .. $#vals ], $c->{label} or diag explain \@cookies; } done_testing; # # This file is part of HTTP-CookieJar # # This software is Copyright (c) 2013 by David Golden. # # This is free software, licensed under: # # The Apache License, Version 2.0, January 2004 # t/save.t 0000644 00000004171 15125143463 0006141 0 ustar 00 use 5.008001; use strict; use warnings; use Test::More 0.96; use Test::Deep '!blessed'; use HTTP::CookieJar; my $jar = HTTP::CookieJar->new; my $jar2; my @cookies = ( 'SID=31d4d96e407aad42; Path=/; Secure; HttpOnly', ); my @persistent = ( 'lang=en_US; Path=/; Domain=example.com; Secure; HttpOnly; Max-Age = 3600', ); subtest "empty cookie jar" => sub { my $jar = HTTP::CookieJar->new; my @list = $jar->dump_cookies; is( scalar @list, 0, "dumped zero cookies" ); ok( my $jar2 = HTTP::CookieJar->new->load_cookies(@list), "load new cookie jar" ); is( scalar $jar2->dump_cookies, 0, "second jar is empty" ); }; subtest "roundtrip" => sub { my $jar = HTTP::CookieJar->new; $jar->add( "http://www.example.com/", $_ ) for @cookies, @persistent; my @list = $jar->dump_cookies; is( scalar @list, @cookies + @persistent, "dumped correct number of cookies" ); ok( my $jar2 = HTTP::CookieJar->new->load_cookies(@list), "load new cookie jar" ); is( scalar $jar2->dump_cookies, @cookies + @persistent, "second jar has correct count" ); cmp_deeply( $jar, $jar2, "old and new jars are the same" ) or diag explain [ $jar, $jar2 ]; }; subtest "persistent" => sub { my $jar = HTTP::CookieJar->new; $jar->add( "http://www.example.com/", $_ ) for @cookies, @persistent; my @list = $jar->dump_cookies( { persistent => 1 } ); is( scalar @list, @cookies, "dumped correct number of cookies" ); ok( my $jar2 = HTTP::CookieJar->new->load_cookies(@list), "load new cookie jar" ); is( scalar $jar2->dump_cookies, @cookies, "second jar has correct count" ); }; # can load raw cookies with both path and domain subtest "liberal load" => sub { my $jar = HTTP::CookieJar->new; ok( $jar->load_cookies( @persistent, @cookies ), "load_cookies with raw cookies" ); is( scalar $jar->dump_cookies, @persistent, "jar has correct count" ); }; done_testing; # # This file is part of HTTP-CookieJar # # This software is Copyright (c) 2013 by David Golden. # # This is free software, licensed under: # # The Apache License, Version 2.0, January 2004 # # vim: ts=4 sts=4 sw=4 et: t/00-report-prereqs.dd 0000644 00000006336 15125143463 0010543 0 ustar 00 do { my $x = { 'configure' => { 'requires' => { 'ExtUtils::MakeMaker' => '6.17', 'perl' => '5.008001' } }, 'develop' => { 'requires' => { 'Dist::Zilla' => '5', 'Dist::Zilla::Plugin::Prereqs' => '0', 'Dist::Zilla::Plugin::ReleaseStatus::FromVersion' => '0', 'Dist::Zilla::Plugin::RemovePrereqs' => '0', 'Dist::Zilla::PluginBundle::DAGOLDEN' => '0.072', 'File::Spec' => '0', 'File::Temp' => '0', 'IO::Handle' => '0', 'IPC::Open3' => '0', 'Pod::Coverage::TrustPod' => '0', 'Pod::Wordlist' => '0', 'Software::License::Apache_2_0' => '0', 'Test::CPAN::Meta' => '0', 'Test::MinimumVersion' => '0', 'Test::More' => '0', 'Test::Perl::Critic' => '0', 'Test::Pod' => '1.41', 'Test::Pod::Coverage' => '1.08', 'Test::Portability::Files' => '0', 'Test::Spelling' => '0.12', 'Test::Version' => '1' } }, 'runtime' => { 'recommends' => { 'Mozilla::PublicSuffix' => '0' }, 'requires' => { 'Carp' => '0', 'HTTP::Date' => '0', 'Time::Local' => '1.1901', 'parent' => '0', 'perl' => '5.008001', 'strict' => '0', 'warnings' => '0' } }, 'test' => { 'recommends' => { 'CPAN::Meta' => '2.120900' }, 'requires' => { 'ExtUtils::MakeMaker' => '0', 'File::Spec' => '0', 'Test::Deep' => '0', 'Test::More' => '0.96', 'Test::Requires' => '0', 'Time::Local' => '1.1901', 'URI' => '0', 'lib' => '0', 'perl' => '5.008001' } } }; $x; } t/00-report-prereqs.t 0000644 00000013452 15125143463 0010414 0 ustar 00 #!perl use strict; use warnings; # This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.028 use Test::More tests => 1; use ExtUtils::MakeMaker; use File::Spec; # from $version::LAX my $lax_version_re = qr/(?: undef | (?: (?:[0-9]+) (?: \. | (?:\.[0-9]+) (?:_[0-9]+)? )? | (?:\.[0-9]+) (?:_[0-9]+)? ) | (?: v (?:[0-9]+) (?: (?:\.[0-9]+)+ (?:_[0-9]+)? )? | (?:[0-9]+)? (?:\.[0-9]+){2,} (?:_[0-9]+)? ) )/x; # hide optional CPAN::Meta modules from prereq scanner # and check if they are available my $cpan_meta = "CPAN::Meta"; my $cpan_meta_pre = "CPAN::Meta::Prereqs"; my $HAS_CPAN_META = eval "require $cpan_meta; $cpan_meta->VERSION('2.120900')" && eval "require $cpan_meta_pre"; ## no critic # Verify requirements? my $DO_VERIFY_PREREQS = 1; sub _max { my $max = shift; $max = ( $_ > $max ) ? $_ : $max for @_; return $max; } sub _merge_prereqs { my ($collector, $prereqs) = @_; # CPAN::Meta::Prereqs object if (ref $collector eq $cpan_meta_pre) { return $collector->with_merged_prereqs( CPAN::Meta::Prereqs->new( $prereqs ) ); } # Raw hashrefs for my $phase ( keys %$prereqs ) { for my $type ( keys %{ $prereqs->{$phase} } ) { for my $module ( keys %{ $prereqs->{$phase}{$type} } ) { $collector->{$phase}{$type}{$module} = $prereqs->{$phase}{$type}{$module}; } } } return $collector; } my @include = qw( ); my @exclude = qw( ); # Add static prereqs to the included modules list my $static_prereqs = do './t/00-report-prereqs.dd'; # Merge all prereqs (either with ::Prereqs or a hashref) my $full_prereqs = _merge_prereqs( ( $HAS_CPAN_META ? $cpan_meta_pre->new : {} ), $static_prereqs ); # Add dynamic prereqs to the included modules list (if we can) my ($source) = grep { -f } 'MYMETA.json', 'MYMETA.yml'; my $cpan_meta_error; if ( $source && $HAS_CPAN_META && (my $meta = eval { CPAN::Meta->load_file($source) } ) ) { $full_prereqs = _merge_prereqs($full_prereqs, $meta->prereqs); } else { $cpan_meta_error = $@; # capture error from CPAN::Meta->load_file($source) $source = 'static metadata'; } my @full_reports; my @dep_errors; my $req_hash = $HAS_CPAN_META ? $full_prereqs->as_string_hash : $full_prereqs; # Add static includes into a fake section for my $mod (@include) { $req_hash->{other}{modules}{$mod} = 0; } for my $phase ( qw(configure build test runtime develop other) ) { next unless $req_hash->{$phase}; next if ($phase eq 'develop' and not $ENV{AUTHOR_TESTING}); for my $type ( qw(requires recommends suggests conflicts modules) ) { next unless $req_hash->{$phase}{$type}; my $title = ucfirst($phase).' '.ucfirst($type); my @reports = [qw/Module Want Have/]; for my $mod ( sort keys %{ $req_hash->{$phase}{$type} } ) { next if $mod eq 'perl'; next if grep { $_ eq $mod } @exclude; my $file = $mod; $file =~ s{::}{/}g; $file .= ".pm"; my ($prefix) = grep { -e File::Spec->catfile($_, $file) } @INC; my $want = $req_hash->{$phase}{$type}{$mod}; $want = "undef" unless defined $want; $want = "any" if !$want && $want == 0; my $req_string = $want eq 'any' ? 'any version required' : "version '$want' required"; if ($prefix) { my $have = MM->parse_version( File::Spec->catfile($prefix, $file) ); $have = "undef" unless defined $have; push @reports, [$mod, $want, $have]; if ( $DO_VERIFY_PREREQS && $HAS_CPAN_META && $type eq 'requires' ) { if ( $have !~ /\A$lax_version_re\z/ ) { push @dep_errors, "$mod version '$have' cannot be parsed ($req_string)"; } elsif ( ! $full_prereqs->requirements_for( $phase, $type )->accepts_module( $mod => $have ) ) { push @dep_errors, "$mod version '$have' is not in required range '$want'"; } } } else { push @reports, [$mod, $want, "missing"]; if ( $DO_VERIFY_PREREQS && $type eq 'requires' ) { push @dep_errors, "$mod is not installed ($req_string)"; } } } if ( @reports ) { push @full_reports, "=== $title ===\n\n"; my $ml = _max( map { length $_->[0] } @reports ); my $wl = _max( map { length $_->[1] } @reports ); my $hl = _max( map { length $_->[2] } @reports ); if ($type eq 'modules') { splice @reports, 1, 0, ["-" x $ml, "", "-" x $hl]; push @full_reports, map { sprintf(" %*s %*s\n", -$ml, $_->[0], $hl, $_->[2]) } @reports; } else { splice @reports, 1, 0, ["-" x $ml, "-" x $wl, "-" x $hl]; push @full_reports, map { sprintf(" %*s %*s %*s\n", -$ml, $_->[0], $wl, $_->[1], $hl, $_->[2]) } @reports; } push @full_reports, "\n"; } } } if ( @full_reports ) { diag "\nVersions for all modules listed in $source (including optional ones):\n\n", @full_reports; } if ( $cpan_meta_error || @dep_errors ) { diag "\n*** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ***\n"; } if ( $cpan_meta_error ) { my ($orig_source) = grep { -f } 'MYMETA.json', 'MYMETA.yml'; diag "\nCPAN::Meta->load_file('$orig_source') failed with: $cpan_meta_error\n"; } if ( @dep_errors ) { diag join("\n", "\nThe following REQUIRED prerequisites were not satisfied:\n", @dep_errors, "\n" ); } pass('Reported prereqs'); # vim: ts=4 sts=4 sw=4 et: t/add.t 0000644 00000021162 15125143463 0005732 0 ustar 00 use 5.008001; use strict; use warnings; use Test::More 0.96; use Test::Deep '!blessed'; use HTTP::CookieJar; my @cases = ( { label => "no cookies", request => "http://example.com/", cookies => [], store => {}, }, { label => "simple key=value", request => "http://example.com/", cookies => ["SID=31d4d96e407aad42"], store => { 'example.com' => { '/' => { SID => { name => "SID", value => "31d4d96e407aad42", creation_time => ignore(), last_access_time => ignore(), domain => "example.com", hostonly => 1, path => "/", } } }, }, }, { label => "invalid cookie not stored", request => "http://example.com/", cookies => [";"], store => {}, }, { label => "localhost treated as host only", request => "http://localhost/", cookies => ["SID=31d4d96e407aad42; Domain=localhost"], store => { 'localhost' => { '/' => { SID => { name => "SID", value => "31d4d96e407aad42", creation_time => ignore(), last_access_time => ignore(), domain => "localhost", hostonly => 1, path => "/", } } }, }, }, { label => "single domain level treated as host only", request => "http://foobar/", cookies => ["SID=31d4d96e407aad42; Domain=foobar"], store => { 'foobar' => { '/' => { SID => { name => "SID", value => "31d4d96e407aad42", creation_time => ignore(), last_access_time => ignore(), domain => "foobar", hostonly => 1, path => "/", } } }, }, }, { label => "different domain not stored", request => "http://example.com/", cookies => ["SID=31d4d96e407aad42; Domain=example.org"], store => {}, }, { label => "subdomain not stored", request => "http://example.com/", cookies => ["SID=31d4d96e407aad42; Domain=www.example.com"], store => {}, }, { label => "superdomain stored", request => "http://www.example.com/", cookies => ["SID=31d4d96e407aad42; Domain=example.com"], store => { 'example.com' => { '/' => { SID => { name => "SID", value => "31d4d96e407aad42", creation_time => ignore(), last_access_time => ignore(), domain => "example.com", path => "/", } } }, }, }, { label => "path prefix /foo/ stored", request => "http://www.example.com/foo/bar", cookies => ["SID=31d4d96e407aad42; Path=/foo/"], store => { 'www.example.com' => { '/foo/' => { SID => { name => "SID", value => "31d4d96e407aad42", creation_time => ignore(), last_access_time => ignore(), domain => "www.example.com", hostonly => 1, path => "/foo/", } } }, }, }, { label => "path prefix /foo stored", request => "http://www.example.com/foo/bar", cookies => ["SID=31d4d96e407aad42; Path=/foo"], store => { 'www.example.com' => { '/foo' => { SID => { name => "SID", value => "31d4d96e407aad42", creation_time => ignore(), last_access_time => ignore(), domain => "www.example.com", hostonly => 1, path => "/foo", } } }, }, }, { label => "last cookie wins", request => "http://example.com/", cookies => [ "SID=31d4d96e407aad42", "SID=0000000000000000", ], store => { 'example.com' => { '/' => { SID => { name => "SID", value => "0000000000000000", creation_time => ignore(), last_access_time => ignore(), domain => "example.com", hostonly => 1, path => "/", } } }, }, }, { label => "expired supercedes prior", request => "http://example.com/", cookies => [ "SID=31d4d96e407aad42", "SID=0000000000000000; Max-Age=-60", ], store => { 'example.com' => { '/' => {}, }, }, }, { label => "separated by path", request => "http://example.com/foo/bar", cookies => [ "SID=31d4d96e407aad42; Path=/", "SID=0000000000000000", ], store => { 'example.com' => { '/' => { SID => { name => "SID", value => "31d4d96e407aad42", creation_time => ignore(), last_access_time => ignore(), domain => "example.com", hostonly => 1, path => "/", } }, '/foo' => { SID => { name => "SID", value => "0000000000000000", creation_time => ignore(), last_access_time => ignore(), domain => "example.com", hostonly => 1, path => "/foo", } } }, }, }, # check that Max-Age supercedes Expires and that Max-Age <= 0 forces # expiration { label => "max-age supercedes expires", request => "http://example.com/", cookies => [ "lang=en-us; Max-Age=100; Expires=Thu, 1 Jan 1970 00:00:00 GMT", "SID=0000000000000000; Expires=Thu, 3 Jan 4841 00:00:00 GMT", "SID=31d4d96e407aad42; Max-Age=0; Expires=Thu, 3 Jan 4841 00:00:00 GMT", "FOO=0000000000000000; Max-Age=-100; Expires=Thu, 3 Jan 4841 00:00:00 GMT", ], store => { 'example.com' => { '/' => { lang => { name => "lang", value => "en-us", expires => ignore(), creation_time => ignore(), last_access_time => ignore(), domain => "example.com", hostonly => 1, path => "/", }, }, }, }, }, ); for my $c (@cases) { my $jar = HTTP::CookieJar->new; for my $cookie ( @{ $c->{cookies} } ) { $jar->add( $c->{request}, $cookie ); } cmp_deeply $jar->{store}, $c->{store}, $c->{label} or diag explain $jar->{store}; } done_testing; # # This file is part of HTTP-CookieJar # # This software is Copyright (c) 2013 by David Golden. # # This is free software, licensed under: # # The Apache License, Version 2.0, January 2004 # t/lib/MockTime.pm 0000644 00000000473 15125143463 0007633 0 ustar 00 use strict; use warnings; package MockTime; my ( $_original_time, $_offset ); sub time () { return $_original_time + $_offset; } sub offset { my ( $class, $offset ) = @_; $_offset = $offset; } BEGIN { ( $_original_time, $_offset ) = ( CORE::time(), 0 ); *CORE::GLOBAL::time = \&time; } 1; perlcritic.rc 0000644 00000001166 15125143463 0007242 0 ustar 00 severity = 5 verbose = 8 [Variables::ProhibitPunctuationVars] allow = $@ $! [TestingAndDebugging::ProhibitNoStrict] allow = refs [Variables::ProhibitEvilVariables] variables = $DB::single # Turn these off [-BuiltinFunctions::ProhibitStringyEval] [-ControlStructures::ProhibitPostfixControls] [-ControlStructures::ProhibitUnlessBlocks] [-Documentation::RequirePodSections] [-InputOutput::ProhibitInteractiveTest] [-References::ProhibitDoubleSigils] [-RegularExpressions::RequireExtendedFormatting] [-InputOutput::ProhibitTwoArgOpen] [-Modules::ProhibitEvilModules] # Turn this on [Lax::ProhibitStringyEval::ExceptForRequire] META.yml 0000644 00000002676 15125143463 0006034 0 ustar 00 --- abstract: 'A minimalist HTTP user agent cookie jar' author: - 'David Golden <dagolden@cpan.org>' build_requires: ExtUtils::MakeMaker: '0' File::Spec: '0' Test::Deep: '0' Test::More: '0.96' Test::Requires: '0' Time::Local: '1.1901' URI: '0' lib: '0' perl: '5.008001' configure_requires: ExtUtils::MakeMaker: '6.17' perl: '5.008001' dynamic_config: 0 generated_by: 'Dist::Zilla version 6.025, CPAN::Meta::Converter version 2.150010' license: apache meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: HTTP-CookieJar no_index: directory: - corpus - examples - t - xt package: - DB provides: HTTP::CookieJar: file: lib/HTTP/CookieJar.pm version: '0.014' HTTP::CookieJar::LWP: file: lib/HTTP/CookieJar/LWP.pm version: '0.014' recommends: Mozilla::PublicSuffix: '0' requires: Carp: '0' HTTP::Date: '0' Time::Local: '1.1901' parent: '0' perl: '5.008001' strict: '0' warnings: '0' resources: bugtracker: https://github.com/dagolden/HTTP-CookieJar/issues homepage: https://github.com/dagolden/HTTP-CookieJar repository: https://github.com/dagolden/HTTP-CookieJar.git version: '0.014' x_authority: cpan:DAGOLDEN x_contributors: - 'Dan Book <grinnz@grinnz.com>' - 'David Golden <xdg@xdg.me>' - 'jvolkening <jdv@base2bio.com>' x_generated_by_perl: v5.36.0 x_serialization_backend: 'YAML::Tiny version 1.73' x_spdx_expression: Apache-2.0 dist.ini 0000644 00000000737 15125143463 0006223 0 ustar 00 name = HTTP-CookieJar author = David Golden <dagolden@cpan.org> license = Apache_2_0 copyright_holder = David Golden copyright_year = 2013 [@DAGOLDEN] :version = 0.072 stopwords = Javascript stopwords = RFC's stopwords = hostonly stopwords = httponly [ReleaseStatus::FromVersion] testing = third_decimal_odd [Prereqs] ; fixes Y2038 bug on older Perls Time::Local = 1.1901 [RemovePrereqs] remove = Mozilla::PublicSuffix [Prereqs / Recommends] Mozilla::PublicSuffix = 0 Makefile.PL 0000644 00000003042 15125143463 0006521 0 ustar 00 # This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.025. use strict; use warnings; use 5.008001; use ExtUtils::MakeMaker 6.17; my %WriteMakefileArgs = ( "ABSTRACT" => "A minimalist HTTP user agent cookie jar", "AUTHOR" => "David Golden <dagolden\@cpan.org>", "CONFIGURE_REQUIRES" => { "ExtUtils::MakeMaker" => "6.17" }, "DISTNAME" => "HTTP-CookieJar", "LICENSE" => "apache", "MIN_PERL_VERSION" => "5.008001", "NAME" => "HTTP::CookieJar", "PREREQ_PM" => { "Carp" => 0, "HTTP::Date" => 0, "Time::Local" => "1.1901", "parent" => 0, "strict" => 0, "warnings" => 0 }, "TEST_REQUIRES" => { "ExtUtils::MakeMaker" => 0, "File::Spec" => 0, "Test::Deep" => 0, "Test::More" => "0.96", "Test::Requires" => 0, "Time::Local" => "1.1901", "URI" => 0, "lib" => 0 }, "VERSION" => "0.014", "test" => { "TESTS" => "t/*.t" } ); my %FallbackPrereqs = ( "Carp" => 0, "ExtUtils::MakeMaker" => 0, "File::Spec" => 0, "HTTP::Date" => 0, "Test::Deep" => 0, "Test::More" => "0.96", "Test::Requires" => 0, "Time::Local" => "1.1901", "URI" => 0, "lib" => 0, "parent" => 0, "strict" => 0, "warnings" => 0 ); unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) { delete $WriteMakefileArgs{TEST_REQUIRES}; delete $WriteMakefileArgs{BUILD_REQUIRES}; $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs; } delete $WriteMakefileArgs{CONFIGURE_REQUIRES} unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; WriteMakefile(%WriteMakefileArgs); blib/man3/HTTP::CookieJar.3pm 0000644 00000023521 15125143463 0011474 0 ustar 00 .\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.42) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "HTTP::CookieJar 3" .TH HTTP::CookieJar 3 "2022-07-25" "perl v5.32.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" HTTP::CookieJar \- A minimalist HTTP user agent cookie jar .SH "VERSION" .IX Header "VERSION" version 0.014 .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use HTTP::CookieJar; \& \& my $jar = HTTP::CookieJar\->new; \& \& # add cookie received from a request \& $jar\->add( "http://www.example.com/", "CUSTOMER=WILE_E_COYOTE; Path=/; Domain=example.com" ); \& \& # extract cookie header for a given request \& my $cookie = $jar\->cookie_header( "http://www.example.com/" ); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This module implements a minimalist \s-1HTTP\s0 user agent cookie jar in conformance with \s-1RFC 6265\s0 <http://tools.ietf.org/html/rfc6265>. .PP Unlike the commonly used HTTP::Cookies module, this module does not require use of HTTP::Request and HTTP::Response objects. An LWP-compatible adapter is available as HTTP::CookieJar::LWP. .SH "CONSTRUCTORS" .IX Header "CONSTRUCTORS" .SS "new" .IX Subsection "new" .Vb 1 \& my $jar = HTTP::CookieJar\->new; .Ve .PP Return a new, empty cookie jar .SH "METHODS" .IX Header "METHODS" .SS "add" .IX Subsection "add" .Vb 3 \& $jar\->add( \& "http://www.example.com/", "lang=en\-US; Path=/; Domain=example.com" \& ); .Ve .PP Given a request \s-1URL\s0 and a \f(CW\*(C`Set\-Cookie\*(C'\fR header string, attempts to adds the cookie to the jar. If the cookie is expired, instead it deletes any matching cookie from the jar. A \f(CW\*(C`Max\-Age\*(C'\fR attribute will be converted to an absolute \&\f(CW\*(C`Expires\*(C'\fR attribute. .PP It will throw an exception if the request \s-1URL\s0 is missing or invalid. Returns true if successful cookie processing or undef/empty\-list on failure. .SS "clear" .IX Subsection "clear" .Vb 1 \& $jar\->clear .Ve .PP Empties the cookie jar. .SS "cookies_for" .IX Subsection "cookies_for" .Vb 1 \& my @cookies = $jar\->cookies_for("http://www.example.com/foo/bar"); .Ve .PP Given a request \s-1URL,\s0 returns a list of hash references representing cookies that should be sent. The hash references are copies \*(-- changing values will not change the cookies in the jar. .PP Cookies set \f(CW\*(C`secure\*(C'\fR will only be returned if the request scheme is \f(CW\*(C`https\*(C'\fR. Expired cookies will not be returned. .PP Keys of a cookie hash reference might include: .IP "\(bu" 4 name \*(-- the name of the cookie .IP "\(bu" 4 value \*(-- the value of the cookie .IP "\(bu" 4 domain \*(-- the domain name to which the cookie applies .IP "\(bu" 4 path \*(-- the path to which the cookie applies .IP "\(bu" 4 expires \*(-- if present, when the cookie expires in epoch seconds .IP "\(bu" 4 secure \*(-- if present, the cookie was set \f(CW\*(C`Secure\*(C'\fR .IP "\(bu" 4 httponly \*(-- if present, the cookie was set \f(CW\*(C`HttpOnly\*(C'\fR .IP "\(bu" 4 hostonly \*(-- if present, the cookie may only be used with the domain as a host .IP "\(bu" 4 creation_time \*(-- epoch time when the cookie was first stored .IP "\(bu" 4 last_access_time \*(-- epoch time when the cookie was last accessed (i.e. \*(L"now\*(R") .PP Keep in mind that \f(CW\*(C`httponly\*(C'\fR means it should only be used in requests and not made available via Javascript, etc. This is pretty meaningless for Perl user agents. .PP Generally, user agents should use the \f(CW\*(C`cookie_header\*(C'\fR method instead. .PP It will throw an exception if the request \s-1URL\s0 is missing or invalid. .SS "cookie_header" .IX Subsection "cookie_header" .Vb 1 \& my $header = $jar\->cookie_header("http://www.example.com/foo/bar"); .Ve .PP Given a request \s-1URL,\s0 returns a correctly-formatted string with all relevant cookies for the request. This string is ready to be used in a \f(CW\*(C`Cookie\*(C'\fR header in an \s-1HTTP\s0 request. E.g.: .PP .Vb 1 \& SID=31d4d96e407aad42; lang=en\-US .Ve .PP It follows the same exclusion rules as \f(CW\*(C`cookies_for\*(C'\fR. .PP If the request is invalid or no cookies apply, it will return an empty string. .SS "dump_cookies" .IX Subsection "dump_cookies" .Vb 2 \& my @list = $jar\->dump_cookies; \& my @list = $jar\->dump_cookies( { persistent => 1 } ); .Ve .PP Returns a list of raw cookies in string form. The strings resemble what would be received from \f(CW\*(C`Set\-Cookie\*(C'\fR headers, but with additional internal fields. The list is only intended for use with \f(CW\*(C`load_cookies\*(C'\fR to allow cookie jar persistence. .PP If a hash reference with a true \f(CW\*(C`persistent\*(C'\fR key is given as an argument, cookies without an \f(CW\*(C`Expires\*(C'\fR time (i.e. \*(L"session cookies\*(R") will be omitted. .PP Here is a trivial example of saving a cookie jar file with Path::Tiny: .PP .Vb 1 \& path("jar.txt")\->spew( join "\en", $jar\->dump_cookies ); .Ve .SS "load_cookies" .IX Subsection "load_cookies" .Vb 1 \& $jar\->load_cookies( @cookies ); .Ve .PP Given a list of cookie strings from \f(CW\*(C`dump_cookies\*(C'\fR, it adds them to the cookie jar. Cookies added in this way will supersede any existing cookies with similar domain, path and name. .PP It returns the jar object for convenience when loading a new object: .PP .Vb 1 \& my $jar = HTTP::CookieJar\->new\->load_cookies( @cookies ); .Ve .PP Here is a trivial example of loading a cookie jar file with Path::Tiny: .PP .Vb 3 \& my $jar = HTTP::CookieJar\->new\->load_cookies( \& path("jar.txt")\->lines \& ); .Ve .SH "LIMITATIONS AND CAVEATS" .IX Header "LIMITATIONS AND CAVEATS" .SS "\s-1RFC 6265\s0 vs prior standards" .IX Subsection "RFC 6265 vs prior standards" This modules adheres as closely as possible to the user-agent rules of \s-1RFC 6265.\s0 Therefore, it does not handle nor generate \f(CW\*(C`Set\-Cookie2\*(C'\fR and \f(CW\*(C`Cookie2\*(C'\fR headers, implement \f(CW\*(C`.local\*(C'\fR suffixes, or do path/domain matching in accord with prior \s-1RFC\s0's. .SS "Internationalized domain names" .IX Subsection "Internationalized domain names" Internationalized domain names given in requests must be properly encoded in \s-1ASCII\s0 form. .SS "Public suffixes" .IX Subsection "Public suffixes" If Mozilla::PublicSuffix is installed, cookie domains will be checked against the public suffix list. Public suffix cookies are only allowed as host-only cookies. .SS "Third-party cookies" .IX Subsection "Third-party cookies" According to \s-1RFC 6265,\s0 a cookie may be accepted only if has no \f(CW\*(C`Domain\*(C'\fR attribute (in which case it is \*(L"host-only\*(R") or if the \f(CW\*(C`Domain\*(C'\fR attribute is a suffix of the request \s-1URL.\s0 This effectively prohibits Site A from setting a cookie for unrelated Site B, which is one potential third-party cookie vector. .SH "SEE ALSO" .IX Header "SEE ALSO" .IP "\(bu" 4 HTTP::Cookies .IP "\(bu" 4 Mojo::UserAgent::CookieJar .SH "SUPPORT" .IX Header "SUPPORT" .SS "Bugs / Feature Requests" .IX Subsection "Bugs / Feature Requests" Please report any bugs or feature requests through the issue tracker at <https://github.com/dagolden/HTTP\-CookieJar/issues>. You will be notified automatically of any progress on your issue. .SS "Source Code" .IX Subsection "Source Code" This is open source software. The code repository is available for public review and contribution under the terms of the license. .PP <https://github.com/dagolden/HTTP\-CookieJar> .PP .Vb 1 \& git clone https://github.com/dagolden/HTTP\-CookieJar.git .Ve .SH "AUTHOR" .IX Header "AUTHOR" David Golden <dagolden@cpan.org> .SH "CONTRIBUTORS" .IX Header "CONTRIBUTORS" .IP "\(bu" 4 Dan Book <grinnz@grinnz.com> .IP "\(bu" 4 David Golden <xdg@xdg.me> .IP "\(bu" 4 jvolkening <jdv@base2bio.com> .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" This software is Copyright (c) 2013 by David Golden. .PP This is free software, licensed under: .PP .Vb 1 \& The Apache License, Version 2.0, January 2004 .Ve blib/man3/.exists 0000644 00000000000 15125143463 0007624 0 ustar 00 blib/man3/HTTP::CookieJar::LWP.3pm 0000644 00000006101 15125143463 0012236 0 ustar 00 .\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.42) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "HTTP::CookieJar::LWP 3" .TH HTTP::CookieJar::LWP 3 "2022-07-25" "perl v5.32.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" HTTP::CookieJar::LWP \- LWP adapter for HTTP::CookieJar .SH "VERSION" .IX Header "VERSION" version 0.014 .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& use LWP::UserAgent; \& use HTTP::CookieJar::LWP; \& \& my $ua = LWP::UserAgent\->new( \& cookie_jar => HTTP::CookieJar::LWP\->new \& ); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This module is an experimental adapter to make HTTP::CookieJar work with \&\s-1LWP\s0. It implements the two methods that \f(CW\*(C`LWP\*(C'\fR calls from HTTP::Cookies. .PP It is not a general-purpose drop-in replacement for \f(CW\*(C`HTTP::Cookies\*(C'\fR in any other way. .SH "AUTHOR" .IX Header "AUTHOR" David Golden <dagolden@cpan.org> .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" This software is Copyright (c) 2013 by David Golden. .PP This is free software, licensed under: .PP .Vb 1 \& The Apache License, Version 2.0, January 2004 .Ve blib/man1/.exists 0000644 00000000000 15125143463 0007622 0 ustar 00 blib/arch/.exists 0000644 00000000000 15125143463 0007703 0 ustar 00 blib/arch/auto/HTTP/CookieJar/.exists 0000644 00000000000 15125143463 0013300 0 ustar 00 blib/bin/.exists 0000644 00000000000 15125143463 0007536 0 ustar 00 blib/script/.exists 0000644 00000000000 15125143463 0010272 0 ustar 00 blib/lib/HTTP/CookieJar.pm 0000444 00000045563 15125143463 0011224 0 ustar 00 use 5.008001; use strict; use warnings; package HTTP::CookieJar; # ABSTRACT: A minimalist HTTP user agent cookie jar our $VERSION = '0.014'; use Carp (); use HTTP::Date (); my $HAS_MPS = eval { require Mozilla::PublicSuffix; 1 }; #pod =construct new #pod #pod my $jar = HTTP::CookieJar->new; #pod #pod Return a new, empty cookie jar #pod #pod =cut sub new { my ($class) = @_; bless { store => {} }, $class; } #pod =method add #pod #pod $jar->add( #pod "http://www.example.com/", "lang=en-US; Path=/; Domain=example.com" #pod ); #pod #pod Given a request URL and a C<Set-Cookie> header string, attempts to adds the #pod cookie to the jar. If the cookie is expired, instead it deletes any matching #pod cookie from the jar. A C<Max-Age> attribute will be converted to an absolute #pod C<Expires> attribute. #pod #pod It will throw an exception if the request URL is missing or invalid. Returns true if #pod successful cookie processing or undef/empty-list on failure. #pod #pod =cut sub add { my ( $self, $request, $cookie ) = @_; return unless defined $cookie and length $cookie; my ( $scheme, $host, $port, $request_path ) = eval { _split_url($request) }; Carp::croak($@) if $@; return unless my $parse = _parse_cookie($cookie); my $name = $parse->{name}; # check and normalize domain if ( exists $parse->{domain} ) { _normalize_domain( $host, $parse ) or return; } else { $parse->{domain} = $host; $parse->{hostonly} = 1; } my $domain = $parse->{domain}; # normalize path if ( !exists $parse->{path} || substr( $parse->{path}, 0, 1 ) ne "/" ) { $parse->{path} = _default_path($request_path); } my $path = $parse->{path}; # set timestamps and normalize expires my $now = $parse->{creation_time} = $parse->{last_access_time} = time; if ( exists $parse->{'max-age'} ) { # "If delta-seconds is less than or equal to zero (0), let expiry-time # be the earliest representable date and time." $parse->{expires} = $parse->{'max-age'} <= 0 ? 0 : $now + $parse->{'max-age'}; delete $parse->{'max-age'}; } # update creation time from old cookie, if exists if ( my $old = $self->{store}{$domain}{$path}{$name} ) { $parse->{creation_time} = $old->{creation_time}; } # if cookie has expired, purge any old matching cookie, too if ( defined $parse->{expires} && $parse->{expires} < $now ) { delete $self->{store}{$domain}{$path}{$name}; } else { $self->{store}{$domain}{$path}{$name} = $parse; } return 1; } #pod =method clear #pod #pod $jar->clear #pod #pod Empties the cookie jar. #pod #pod =cut sub clear { my ($self) = @_; $self->{store} = {}; return 1; } #pod =method cookies_for #pod #pod my @cookies = $jar->cookies_for("http://www.example.com/foo/bar"); #pod #pod Given a request URL, returns a list of hash references representing cookies #pod that should be sent. The hash references are copies -- changing values #pod will not change the cookies in the jar. #pod #pod Cookies set C<secure> will only be returned if the request scheme is C<https>. #pod Expired cookies will not be returned. #pod #pod Keys of a cookie hash reference might include: #pod #pod =for :list #pod * name -- the name of the cookie #pod * value -- the value of the cookie #pod * domain -- the domain name to which the cookie applies #pod * path -- the path to which the cookie applies #pod * expires -- if present, when the cookie expires in epoch seconds #pod * secure -- if present, the cookie was set C<Secure> #pod * httponly -- if present, the cookie was set C<HttpOnly> #pod * hostonly -- if present, the cookie may only be used with the domain as a host #pod * creation_time -- epoch time when the cookie was first stored #pod * last_access_time -- epoch time when the cookie was last accessed (i.e. "now") #pod #pod Keep in mind that C<httponly> means it should only be used in requests and not #pod made available via Javascript, etc. This is pretty meaningless for Perl user #pod agents. #pod #pod Generally, user agents should use the C<cookie_header> method instead. #pod #pod It will throw an exception if the request URL is missing or invalid. #pod #pod =cut sub cookies_for { my ( $self, $request ) = @_; my @found = $self->_cookies_for($request); return map { {%$_} } @found; } # _cookies_for returns originals, not copies, which helps in testing sub _cookies_for { my ( $self, $request ) = @_; my ( $scheme, $host, $port, $request_path ) = eval { _split_url($request) }; Carp::croak($@) if $@; my @found; my $now = time; for my $cookie ( $self->_all_cookies ) { next if $cookie->{hostonly} && $host ne $cookie->{domain}; next if $cookie->{secure} && $scheme ne 'https'; next if defined( $cookie->{expires} ) && $cookie->{expires} < $now; next unless _domain_match( $host, $cookie->{domain} ); next unless _path_match( $request_path, $cookie->{path} ); $cookie->{last_access_time} = time; push @found, $cookie; } @found = sort { length( $b->{path} ) <=> length( $a->{path} ) || $a->{creation_time} <=> $b->{creation_time} } @found; return @found; } #pod =method cookie_header #pod #pod my $header = $jar->cookie_header("http://www.example.com/foo/bar"); #pod #pod Given a request URL, returns a correctly-formatted string with all relevant #pod cookies for the request. This string is ready to be used in a C<Cookie> header #pod in an HTTP request. E.g.: #pod #pod SID=31d4d96e407aad42; lang=en-US #pod #pod It follows the same exclusion rules as C<cookies_for>. #pod #pod If the request is invalid or no cookies apply, it will return an empty string. #pod #pod =cut sub cookie_header { my ( $self, $req ) = @_; return join( "; ", map { "$_->{name}=$_->{value}" } $self->cookies_for($req) ); } #pod =method dump_cookies #pod #pod my @list = $jar->dump_cookies; #pod my @list = $jar->dump_cookies( { persistent => 1 } ); #pod #pod Returns a list of raw cookies in string form. The strings resemble what #pod would be received from C<Set-Cookie> headers, but with additional internal #pod fields. The list is only intended for use with C<load_cookies> to allow #pod cookie jar persistence. #pod #pod If a hash reference with a true C<persistent> key is given as an argument, #pod cookies without an C<Expires> time (i.e. "session cookies") will be omitted. #pod #pod Here is a trivial example of saving a cookie jar file with L<Path::Tiny>: #pod #pod path("jar.txt")->spew( join "\n", $jar->dump_cookies ); #pod #pod =cut sub dump_cookies { my ( $self, $args ) = @_; my @list; for my $c ( $self->_all_cookies ) { my @parts = "$c->{name}=$c->{value}"; if ( defined $c->{expires} ) { push @parts, 'Expires=' . HTTP::Date::time2str( $c->{expires} ); } else { next if $args->{persistent}; } for my $attr (qw/Domain Path Creation_Time Last_Access_Time/) { push @parts, "$attr=$c->{lc $attr}" if defined $c->{ lc $attr }; } for my $attr (qw/Secure HttpOnly HostOnly/) { push @parts, $attr if $c->{ lc $attr }; } push @list, join( "; ", @parts ); } return @list; } #pod =method load_cookies #pod #pod $jar->load_cookies( @cookies ); #pod #pod Given a list of cookie strings from C<dump_cookies>, it adds them to #pod the cookie jar. Cookies added in this way will supersede any existing #pod cookies with similar domain, path and name. #pod #pod It returns the jar object for convenience when loading a new object: #pod #pod my $jar = HTTP::CookieJar->new->load_cookies( @cookies ); #pod #pod Here is a trivial example of loading a cookie jar file with L<Path::Tiny>: #pod #pod my $jar = HTTP::CookieJar->new->load_cookies( #pod path("jar.txt")->lines #pod ); #pod #pod =cut sub load_cookies { my ( $self, @cookies ) = @_; for my $cookie (@cookies) { my $p = _parse_cookie( $cookie, 1 ); next unless exists $p->{domain} && exists $p->{path}; $p->{$_} = time for grep { !defined $p->{$_} } qw/creation_time last_access_time/; $self->{store}{ $p->{domain} }{ $p->{path} }{ $p->{name} } = $p; } return $self; } #--------------------------------------------------------------------------# # private methods #--------------------------------------------------------------------------# # return flattened list of all cookies sub _all_cookies { return map { values %$_ } map { values %$_ } values %{ $_[0]->{store} }; } #--------------------------------------------------------------------------# # Helper subroutines #--------------------------------------------------------------------------# my $pub_re = qr/(?:domain|path|expires|max-age|httponly|secure)/; my $pvt_re = qr/(?:$pub_re|creation_time|last_access_time|hostonly)/; sub _parse_cookie { my ( $cookie, $private ) = @_; $cookie = '' unless defined $cookie; my ( $kvp, @attrs ) = split /;/, $cookie; $kvp = '' unless defined $kvp; my ( $name, $value ) = map { s/^\s*//; s/\s*$//; $_ } split( /=/, $kvp, 2 ); ## no critic return unless defined $name and length $name; $value = '' unless defined $value; my $parse = { name => $name, value => $value }; for my $s (@attrs) { next unless defined $s && $s =~ /\S/; my ( $k, $v ) = map { s/^\s*//; s/\s*$//; $_ } split( /=/, $s, 2 ); ## no critic $k = lc $k; next unless $private ? ( $k =~ m/^$pvt_re$/ ) : ( $k =~ m/^$pub_re$/ ); $v = 1 if $k =~ m/^(?:httponly|secure|hostonly)$/; # boolean flag if present $v = HTTP::Date::str2time($v) || 0 if $k eq 'expires'; # convert to epoch next unless length $v; $v =~ s{^\.}{} if $k eq 'domain'; # strip leading dot $v =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg if $k eq 'path'; # unescape $parse->{$k} = $v; } return $parse; } sub _domain_match { my ( $string, $dom_string ) = @_; return 1 if $dom_string eq $string; return unless $string =~ /[a-z]/i; # non-numeric if ( $string =~ s{\Q$dom_string\E$}{} ) { return substr( $string, -1, 1 ) eq '.'; # "foo." } return; } sub _normalize_domain { my ( $host, $parse ) = @_; if ($HAS_MPS) { my $host_pub_suff = eval { Mozilla::PublicSuffix::public_suffix($host) }; $host_pub_suff = '' unless defined $host_pub_suff; if ( _domain_match( $host_pub_suff, $parse->{domain} ) ) { if ( $parse->{domain} eq $host ) { return $parse->{hostonly} = 1; } else { return; } } } if ( $parse->{domain} !~ m{\.} && $parse->{domain} eq $host ) { return $parse->{hostonly} = 1; } return _domain_match( $host, $parse->{domain} ); } sub _default_path { my ($path) = @_; return "/" if !length $path || substr( $path, 0, 1 ) ne "/"; my ($default) = $path =~ m{^(.*)/}; # greedy to last / return length($default) ? $default : "/"; } sub _path_match { my ( $req_path, $cookie_path ) = @_; return 1 if $req_path eq $cookie_path; if ( $req_path =~ m{^\Q$cookie_path\E(.*)} ) { my $rest = $1; return 1 if substr( $cookie_path, -1, 1 ) eq '/'; return 1 if substr( $rest, 0, 1 ) eq '/'; } return; } sub _split_url { my $url = shift; die(qq/No URL provided\n/) unless defined $url and length $url; # URI regex adapted from the URI module # XXX path_query here really chops at ? or # to get just the path and not the query my ( $scheme, $authority, $path_query ) = $url =~ m<\A([^:/?#]+)://([^/?#]*)([^#?]*)> or die(qq/Cannot parse URL: '$url'\n/); $scheme = lc $scheme; $path_query = "/$path_query" unless $path_query =~ m<\A/>; $path_query =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg; my $host = ( length($authority) ) ? lc $authority : 'localhost'; $host =~ s/\A[^@]*@//; # userinfo my $port = do { $host =~ s/:([0-9]*)\z// && length $1 ? $1 : ( $scheme eq 'http' ? 80 : $scheme eq 'https' ? 443 : undef ); }; return ( $scheme, $host, $port, $path_query ); } 1; # vim: ts=4 sts=4 sw=4 et: __END__ =pod =encoding UTF-8 =head1 NAME HTTP::CookieJar - A minimalist HTTP user agent cookie jar =head1 VERSION version 0.014 =head1 SYNOPSIS use HTTP::CookieJar; my $jar = HTTP::CookieJar->new; # add cookie received from a request $jar->add( "http://www.example.com/", "CUSTOMER=WILE_E_COYOTE; Path=/; Domain=example.com" ); # extract cookie header for a given request my $cookie = $jar->cookie_header( "http://www.example.com/" ); =head1 DESCRIPTION This module implements a minimalist HTTP user agent cookie jar in conformance with L<RFC 6265|http://tools.ietf.org/html/rfc6265>. Unlike the commonly used L<HTTP::Cookies> module, this module does not require use of L<HTTP::Request> and L<HTTP::Response> objects. An LWP-compatible adapter is available as L<HTTP::CookieJar::LWP>. =head1 CONSTRUCTORS =head2 new my $jar = HTTP::CookieJar->new; Return a new, empty cookie jar =head1 METHODS =head2 add $jar->add( "http://www.example.com/", "lang=en-US; Path=/; Domain=example.com" ); Given a request URL and a C<Set-Cookie> header string, attempts to adds the cookie to the jar. If the cookie is expired, instead it deletes any matching cookie from the jar. A C<Max-Age> attribute will be converted to an absolute C<Expires> attribute. It will throw an exception if the request URL is missing or invalid. Returns true if successful cookie processing or undef/empty-list on failure. =head2 clear $jar->clear Empties the cookie jar. =head2 cookies_for my @cookies = $jar->cookies_for("http://www.example.com/foo/bar"); Given a request URL, returns a list of hash references representing cookies that should be sent. The hash references are copies -- changing values will not change the cookies in the jar. Cookies set C<secure> will only be returned if the request scheme is C<https>. Expired cookies will not be returned. Keys of a cookie hash reference might include: =over 4 =item * name -- the name of the cookie =item * value -- the value of the cookie =item * domain -- the domain name to which the cookie applies =item * path -- the path to which the cookie applies =item * expires -- if present, when the cookie expires in epoch seconds =item * secure -- if present, the cookie was set C<Secure> =item * httponly -- if present, the cookie was set C<HttpOnly> =item * hostonly -- if present, the cookie may only be used with the domain as a host =item * creation_time -- epoch time when the cookie was first stored =item * last_access_time -- epoch time when the cookie was last accessed (i.e. "now") =back Keep in mind that C<httponly> means it should only be used in requests and not made available via Javascript, etc. This is pretty meaningless for Perl user agents. Generally, user agents should use the C<cookie_header> method instead. It will throw an exception if the request URL is missing or invalid. =head2 cookie_header my $header = $jar->cookie_header("http://www.example.com/foo/bar"); Given a request URL, returns a correctly-formatted string with all relevant cookies for the request. This string is ready to be used in a C<Cookie> header in an HTTP request. E.g.: SID=31d4d96e407aad42; lang=en-US It follows the same exclusion rules as C<cookies_for>. If the request is invalid or no cookies apply, it will return an empty string. =head2 dump_cookies my @list = $jar->dump_cookies; my @list = $jar->dump_cookies( { persistent => 1 } ); Returns a list of raw cookies in string form. The strings resemble what would be received from C<Set-Cookie> headers, but with additional internal fields. The list is only intended for use with C<load_cookies> to allow cookie jar persistence. If a hash reference with a true C<persistent> key is given as an argument, cookies without an C<Expires> time (i.e. "session cookies") will be omitted. Here is a trivial example of saving a cookie jar file with L<Path::Tiny>: path("jar.txt")->spew( join "\n", $jar->dump_cookies ); =head2 load_cookies $jar->load_cookies( @cookies ); Given a list of cookie strings from C<dump_cookies>, it adds them to the cookie jar. Cookies added in this way will supersede any existing cookies with similar domain, path and name. It returns the jar object for convenience when loading a new object: my $jar = HTTP::CookieJar->new->load_cookies( @cookies ); Here is a trivial example of loading a cookie jar file with L<Path::Tiny>: my $jar = HTTP::CookieJar->new->load_cookies( path("jar.txt")->lines ); =for Pod::Coverage method_names_here =head1 LIMITATIONS AND CAVEATS =head2 RFC 6265 vs prior standards This modules adheres as closely as possible to the user-agent rules of RFC 6265. Therefore, it does not handle nor generate C<Set-Cookie2> and C<Cookie2> headers, implement C<.local> suffixes, or do path/domain matching in accord with prior RFC's. =head2 Internationalized domain names Internationalized domain names given in requests must be properly encoded in ASCII form. =head2 Public suffixes If L<Mozilla::PublicSuffix> is installed, cookie domains will be checked against the public suffix list. Public suffix cookies are only allowed as host-only cookies. =head2 Third-party cookies According to RFC 6265, a cookie may be accepted only if has no C<Domain> attribute (in which case it is "host-only") or if the C<Domain> attribute is a suffix of the request URL. This effectively prohibits Site A from setting a cookie for unrelated Site B, which is one potential third-party cookie vector. =head1 SEE ALSO =over 4 =item * L<HTTP::Cookies> =item * L<Mojo::UserAgent::CookieJar> =back =for :stopwords cpan testmatrix url bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan =head1 SUPPORT =head2 Bugs / Feature Requests Please report any bugs or feature requests through the issue tracker at L<https://github.com/dagolden/HTTP-CookieJar/issues>. You will be notified automatically of any progress on your issue. =head2 Source Code This is open source software. The code repository is available for public review and contribution under the terms of the license. L<https://github.com/dagolden/HTTP-CookieJar> git clone https://github.com/dagolden/HTTP-CookieJar.git =head1 AUTHOR David Golden <dagolden@cpan.org> =head1 CONTRIBUTORS =for stopwords Dan Book David Golden jvolkening =over 4 =item * Dan Book <grinnz@grinnz.com> =item * David Golden <xdg@xdg.me> =item * jvolkening <jdv@base2bio.com> =back =head1 COPYRIGHT AND LICENSE This software is Copyright (c) 2013 by David Golden. This is free software, licensed under: The Apache License, Version 2.0, January 2004 =cut blib/lib/HTTP/CookieJar/LWP.pm 0000444 00000005053 15125143463 0011654 0 ustar 00 use 5.008001; use strict; use warnings; package HTTP::CookieJar::LWP; # ABSTRACT: LWP adapter for HTTP::CookieJar our $VERSION = '0.014'; use parent 'HTTP::CookieJar'; sub add_cookie_header { my ( $self, $request ) = @_; my $url = _get_url( $request, $request->uri ); return unless ( $url->scheme =~ /^https?\z/ ); my $header = $self->cookie_header($url); $request->header( Cookie => $header ); return $request; } sub extract_cookies { my ( $self, $response ) = @_; my $request = $response->request or return; my $url = _get_url( $request, $request->uri ); $self->add( $url, $_ ) for $response->_header("Set-Cookie"); return $response; } #--------------------------------------------------------------------------# # helper subroutines #--------------------------------------------------------------------------# sub _get_url { my ( $request, $url ) = @_; my $new_url = $url->clone; if ( my $h = $request->header("Host") ) { $h =~ s/:\d+$//; # might have a port as well $new_url->host($h); } return $new_url; } sub _url_path { my $url = shift; my $path; if ( $url->can('epath') ) { $path = $url->epath; # URI::URL method } else { $path = $url->path; # URI::_generic method } $path = "/" unless length $path; $path; } sub _normalize_path # so that plain string compare can be used { my $x; $_[0] =~ s/%([0-9a-fA-F][0-9a-fA-F])/ $x = uc($1); $x eq "2F" || $x eq "25" ? "%$x" : pack("C", hex($x)); /eg; $_[0] =~ s/([\0-\x20\x7f-\xff])/sprintf("%%%02X",ord($1))/eg; } 1; # vim: ts=4 sts=4 sw=4 et: __END__ =pod =encoding UTF-8 =head1 NAME HTTP::CookieJar::LWP - LWP adapter for HTTP::CookieJar =head1 VERSION version 0.014 =head1 SYNOPSIS use LWP::UserAgent; use HTTP::CookieJar::LWP; my $ua = LWP::UserAgent->new( cookie_jar => HTTP::CookieJar::LWP->new ); =head1 DESCRIPTION This module is an experimental adapter to make L<HTTP::CookieJar> work with L<LWP>. It implements the two methods that C<LWP> calls from L<HTTP::Cookies>. It is not a general-purpose drop-in replacement for C<HTTP::Cookies> in any other way. =for Pod::Coverage method_names_here add_cookie_header extract_cookies =head1 AUTHOR David Golden <dagolden@cpan.org> =head1 COPYRIGHT AND LICENSE This software is Copyright (c) 2013 by David Golden. This is free software, licensed under: The Apache License, Version 2.0, January 2004 =cut blib/lib/HTTP/.exists 0000644 00000000000 15125143463 0010313 0 ustar 00 blib/lib/auto/HTTP/CookieJar/.exists 0000644 00000000000 15125143463 0013131 0 ustar 00 MYMETA.yml 0000644 00000002637 15125143463 0006277 0 ustar 00 --- abstract: 'A minimalist HTTP user agent cookie jar' author: - 'David Golden <dagolden@cpan.org>' build_requires: ExtUtils::MakeMaker: '0' File::Spec: '0' Test::Deep: '0' Test::More: '0.96' Test::Requires: '0' Time::Local: '1.1901' URI: '0' lib: '0' configure_requires: ExtUtils::MakeMaker: '6.17' dynamic_config: 0 generated_by: 'Dist::Zilla version 6.025, CPAN::Meta::Converter version 2.150010' license: apache meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: HTTP-CookieJar no_index: directory: - corpus - examples - t - xt package: - DB provides: HTTP::CookieJar: file: lib/HTTP/CookieJar.pm version: '0.014' HTTP::CookieJar::LWP: file: lib/HTTP/CookieJar/LWP.pm version: '0.014' recommends: Mozilla::PublicSuffix: '0' requires: Carp: '0' HTTP::Date: '0' Time::Local: '1.1901' parent: '0' perl: '5.008001' strict: '0' warnings: '0' resources: bugtracker: https://github.com/dagolden/HTTP-CookieJar/issues homepage: https://github.com/dagolden/HTTP-CookieJar repository: https://github.com/dagolden/HTTP-CookieJar.git version: '0.014' x_authority: cpan:DAGOLDEN x_contributors: - 'Dan Book <grinnz@grinnz.com>' - 'David Golden <xdg@xdg.me>' - 'jvolkening <jdv@base2bio.com>' x_generated_by_perl: v5.36.0 x_serialization_backend: 'CPAN::Meta::YAML version 0.018' x_spdx_expression: Apache-2.0 MANIFEST 0000644 00000001155 15125143463 0005703 0 ustar 00 # This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.025. CONTRIBUTING.mkdn Changes LICENSE MANIFEST META.json META.yml Makefile.PL README cpanfile dist.ini lib/HTTP/CookieJar.pm lib/HTTP/CookieJar/LWP.pm perlcritic.rc t/00-report-prereqs.dd t/00-report-prereqs.t t/add.t t/cookies_for.t t/examples.t t/lib/MockTime.pm t/parse.t t/publicsuffix.t t/save.t t/sort.t t/zzz-lwp.t tidyall.ini xt/author/00-compile.t xt/author/critic.t xt/author/distmeta.t xt/author/minimum-version.t xt/author/pod-coverage.t xt/author/pod-spell.t xt/author/pod-syntax.t xt/author/portability.t xt/author/test-version.t lib/HTTP/CookieJar.pm 0000644 00000045563 15125143463 0010316 0 ustar 00 use 5.008001; use strict; use warnings; package HTTP::CookieJar; # ABSTRACT: A minimalist HTTP user agent cookie jar our $VERSION = '0.014'; use Carp (); use HTTP::Date (); my $HAS_MPS = eval { require Mozilla::PublicSuffix; 1 }; #pod =construct new #pod #pod my $jar = HTTP::CookieJar->new; #pod #pod Return a new, empty cookie jar #pod #pod =cut sub new { my ($class) = @_; bless { store => {} }, $class; } #pod =method add #pod #pod $jar->add( #pod "http://www.example.com/", "lang=en-US; Path=/; Domain=example.com" #pod ); #pod #pod Given a request URL and a C<Set-Cookie> header string, attempts to adds the #pod cookie to the jar. If the cookie is expired, instead it deletes any matching #pod cookie from the jar. A C<Max-Age> attribute will be converted to an absolute #pod C<Expires> attribute. #pod #pod It will throw an exception if the request URL is missing or invalid. Returns true if #pod successful cookie processing or undef/empty-list on failure. #pod #pod =cut sub add { my ( $self, $request, $cookie ) = @_; return unless defined $cookie and length $cookie; my ( $scheme, $host, $port, $request_path ) = eval { _split_url($request) }; Carp::croak($@) if $@; return unless my $parse = _parse_cookie($cookie); my $name = $parse->{name}; # check and normalize domain if ( exists $parse->{domain} ) { _normalize_domain( $host, $parse ) or return; } else { $parse->{domain} = $host; $parse->{hostonly} = 1; } my $domain = $parse->{domain}; # normalize path if ( !exists $parse->{path} || substr( $parse->{path}, 0, 1 ) ne "/" ) { $parse->{path} = _default_path($request_path); } my $path = $parse->{path}; # set timestamps and normalize expires my $now = $parse->{creation_time} = $parse->{last_access_time} = time; if ( exists $parse->{'max-age'} ) { # "If delta-seconds is less than or equal to zero (0), let expiry-time # be the earliest representable date and time." $parse->{expires} = $parse->{'max-age'} <= 0 ? 0 : $now + $parse->{'max-age'}; delete $parse->{'max-age'}; } # update creation time from old cookie, if exists if ( my $old = $self->{store}{$domain}{$path}{$name} ) { $parse->{creation_time} = $old->{creation_time}; } # if cookie has expired, purge any old matching cookie, too if ( defined $parse->{expires} && $parse->{expires} < $now ) { delete $self->{store}{$domain}{$path}{$name}; } else { $self->{store}{$domain}{$path}{$name} = $parse; } return 1; } #pod =method clear #pod #pod $jar->clear #pod #pod Empties the cookie jar. #pod #pod =cut sub clear { my ($self) = @_; $self->{store} = {}; return 1; } #pod =method cookies_for #pod #pod my @cookies = $jar->cookies_for("http://www.example.com/foo/bar"); #pod #pod Given a request URL, returns a list of hash references representing cookies #pod that should be sent. The hash references are copies -- changing values #pod will not change the cookies in the jar. #pod #pod Cookies set C<secure> will only be returned if the request scheme is C<https>. #pod Expired cookies will not be returned. #pod #pod Keys of a cookie hash reference might include: #pod #pod =for :list #pod * name -- the name of the cookie #pod * value -- the value of the cookie #pod * domain -- the domain name to which the cookie applies #pod * path -- the path to which the cookie applies #pod * expires -- if present, when the cookie expires in epoch seconds #pod * secure -- if present, the cookie was set C<Secure> #pod * httponly -- if present, the cookie was set C<HttpOnly> #pod * hostonly -- if present, the cookie may only be used with the domain as a host #pod * creation_time -- epoch time when the cookie was first stored #pod * last_access_time -- epoch time when the cookie was last accessed (i.e. "now") #pod #pod Keep in mind that C<httponly> means it should only be used in requests and not #pod made available via Javascript, etc. This is pretty meaningless for Perl user #pod agents. #pod #pod Generally, user agents should use the C<cookie_header> method instead. #pod #pod It will throw an exception if the request URL is missing or invalid. #pod #pod =cut sub cookies_for { my ( $self, $request ) = @_; my @found = $self->_cookies_for($request); return map { {%$_} } @found; } # _cookies_for returns originals, not copies, which helps in testing sub _cookies_for { my ( $self, $request ) = @_; my ( $scheme, $host, $port, $request_path ) = eval { _split_url($request) }; Carp::croak($@) if $@; my @found; my $now = time; for my $cookie ( $self->_all_cookies ) { next if $cookie->{hostonly} && $host ne $cookie->{domain}; next if $cookie->{secure} && $scheme ne 'https'; next if defined( $cookie->{expires} ) && $cookie->{expires} < $now; next unless _domain_match( $host, $cookie->{domain} ); next unless _path_match( $request_path, $cookie->{path} ); $cookie->{last_access_time} = time; push @found, $cookie; } @found = sort { length( $b->{path} ) <=> length( $a->{path} ) || $a->{creation_time} <=> $b->{creation_time} } @found; return @found; } #pod =method cookie_header #pod #pod my $header = $jar->cookie_header("http://www.example.com/foo/bar"); #pod #pod Given a request URL, returns a correctly-formatted string with all relevant #pod cookies for the request. This string is ready to be used in a C<Cookie> header #pod in an HTTP request. E.g.: #pod #pod SID=31d4d96e407aad42; lang=en-US #pod #pod It follows the same exclusion rules as C<cookies_for>. #pod #pod If the request is invalid or no cookies apply, it will return an empty string. #pod #pod =cut sub cookie_header { my ( $self, $req ) = @_; return join( "; ", map { "$_->{name}=$_->{value}" } $self->cookies_for($req) ); } #pod =method dump_cookies #pod #pod my @list = $jar->dump_cookies; #pod my @list = $jar->dump_cookies( { persistent => 1 } ); #pod #pod Returns a list of raw cookies in string form. The strings resemble what #pod would be received from C<Set-Cookie> headers, but with additional internal #pod fields. The list is only intended for use with C<load_cookies> to allow #pod cookie jar persistence. #pod #pod If a hash reference with a true C<persistent> key is given as an argument, #pod cookies without an C<Expires> time (i.e. "session cookies") will be omitted. #pod #pod Here is a trivial example of saving a cookie jar file with L<Path::Tiny>: #pod #pod path("jar.txt")->spew( join "\n", $jar->dump_cookies ); #pod #pod =cut sub dump_cookies { my ( $self, $args ) = @_; my @list; for my $c ( $self->_all_cookies ) { my @parts = "$c->{name}=$c->{value}"; if ( defined $c->{expires} ) { push @parts, 'Expires=' . HTTP::Date::time2str( $c->{expires} ); } else { next if $args->{persistent}; } for my $attr (qw/Domain Path Creation_Time Last_Access_Time/) { push @parts, "$attr=$c->{lc $attr}" if defined $c->{ lc $attr }; } for my $attr (qw/Secure HttpOnly HostOnly/) { push @parts, $attr if $c->{ lc $attr }; } push @list, join( "; ", @parts ); } return @list; } #pod =method load_cookies #pod #pod $jar->load_cookies( @cookies ); #pod #pod Given a list of cookie strings from C<dump_cookies>, it adds them to #pod the cookie jar. Cookies added in this way will supersede any existing #pod cookies with similar domain, path and name. #pod #pod It returns the jar object for convenience when loading a new object: #pod #pod my $jar = HTTP::CookieJar->new->load_cookies( @cookies ); #pod #pod Here is a trivial example of loading a cookie jar file with L<Path::Tiny>: #pod #pod my $jar = HTTP::CookieJar->new->load_cookies( #pod path("jar.txt")->lines #pod ); #pod #pod =cut sub load_cookies { my ( $self, @cookies ) = @_; for my $cookie (@cookies) { my $p = _parse_cookie( $cookie, 1 ); next unless exists $p->{domain} && exists $p->{path}; $p->{$_} = time for grep { !defined $p->{$_} } qw/creation_time last_access_time/; $self->{store}{ $p->{domain} }{ $p->{path} }{ $p->{name} } = $p; } return $self; } #--------------------------------------------------------------------------# # private methods #--------------------------------------------------------------------------# # return flattened list of all cookies sub _all_cookies { return map { values %$_ } map { values %$_ } values %{ $_[0]->{store} }; } #--------------------------------------------------------------------------# # Helper subroutines #--------------------------------------------------------------------------# my $pub_re = qr/(?:domain|path|expires|max-age|httponly|secure)/; my $pvt_re = qr/(?:$pub_re|creation_time|last_access_time|hostonly)/; sub _parse_cookie { my ( $cookie, $private ) = @_; $cookie = '' unless defined $cookie; my ( $kvp, @attrs ) = split /;/, $cookie; $kvp = '' unless defined $kvp; my ( $name, $value ) = map { s/^\s*//; s/\s*$//; $_ } split( /=/, $kvp, 2 ); ## no critic return unless defined $name and length $name; $value = '' unless defined $value; my $parse = { name => $name, value => $value }; for my $s (@attrs) { next unless defined $s && $s =~ /\S/; my ( $k, $v ) = map { s/^\s*//; s/\s*$//; $_ } split( /=/, $s, 2 ); ## no critic $k = lc $k; next unless $private ? ( $k =~ m/^$pvt_re$/ ) : ( $k =~ m/^$pub_re$/ ); $v = 1 if $k =~ m/^(?:httponly|secure|hostonly)$/; # boolean flag if present $v = HTTP::Date::str2time($v) || 0 if $k eq 'expires'; # convert to epoch next unless length $v; $v =~ s{^\.}{} if $k eq 'domain'; # strip leading dot $v =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg if $k eq 'path'; # unescape $parse->{$k} = $v; } return $parse; } sub _domain_match { my ( $string, $dom_string ) = @_; return 1 if $dom_string eq $string; return unless $string =~ /[a-z]/i; # non-numeric if ( $string =~ s{\Q$dom_string\E$}{} ) { return substr( $string, -1, 1 ) eq '.'; # "foo." } return; } sub _normalize_domain { my ( $host, $parse ) = @_; if ($HAS_MPS) { my $host_pub_suff = eval { Mozilla::PublicSuffix::public_suffix($host) }; $host_pub_suff = '' unless defined $host_pub_suff; if ( _domain_match( $host_pub_suff, $parse->{domain} ) ) { if ( $parse->{domain} eq $host ) { return $parse->{hostonly} = 1; } else { return; } } } if ( $parse->{domain} !~ m{\.} && $parse->{domain} eq $host ) { return $parse->{hostonly} = 1; } return _domain_match( $host, $parse->{domain} ); } sub _default_path { my ($path) = @_; return "/" if !length $path || substr( $path, 0, 1 ) ne "/"; my ($default) = $path =~ m{^(.*)/}; # greedy to last / return length($default) ? $default : "/"; } sub _path_match { my ( $req_path, $cookie_path ) = @_; return 1 if $req_path eq $cookie_path; if ( $req_path =~ m{^\Q$cookie_path\E(.*)} ) { my $rest = $1; return 1 if substr( $cookie_path, -1, 1 ) eq '/'; return 1 if substr( $rest, 0, 1 ) eq '/'; } return; } sub _split_url { my $url = shift; die(qq/No URL provided\n/) unless defined $url and length $url; # URI regex adapted from the URI module # XXX path_query here really chops at ? or # to get just the path and not the query my ( $scheme, $authority, $path_query ) = $url =~ m<\A([^:/?#]+)://([^/?#]*)([^#?]*)> or die(qq/Cannot parse URL: '$url'\n/); $scheme = lc $scheme; $path_query = "/$path_query" unless $path_query =~ m<\A/>; $path_query =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg; my $host = ( length($authority) ) ? lc $authority : 'localhost'; $host =~ s/\A[^@]*@//; # userinfo my $port = do { $host =~ s/:([0-9]*)\z// && length $1 ? $1 : ( $scheme eq 'http' ? 80 : $scheme eq 'https' ? 443 : undef ); }; return ( $scheme, $host, $port, $path_query ); } 1; # vim: ts=4 sts=4 sw=4 et: __END__ =pod =encoding UTF-8 =head1 NAME HTTP::CookieJar - A minimalist HTTP user agent cookie jar =head1 VERSION version 0.014 =head1 SYNOPSIS use HTTP::CookieJar; my $jar = HTTP::CookieJar->new; # add cookie received from a request $jar->add( "http://www.example.com/", "CUSTOMER=WILE_E_COYOTE; Path=/; Domain=example.com" ); # extract cookie header for a given request my $cookie = $jar->cookie_header( "http://www.example.com/" ); =head1 DESCRIPTION This module implements a minimalist HTTP user agent cookie jar in conformance with L<RFC 6265|http://tools.ietf.org/html/rfc6265>. Unlike the commonly used L<HTTP::Cookies> module, this module does not require use of L<HTTP::Request> and L<HTTP::Response> objects. An LWP-compatible adapter is available as L<HTTP::CookieJar::LWP>. =head1 CONSTRUCTORS =head2 new my $jar = HTTP::CookieJar->new; Return a new, empty cookie jar =head1 METHODS =head2 add $jar->add( "http://www.example.com/", "lang=en-US; Path=/; Domain=example.com" ); Given a request URL and a C<Set-Cookie> header string, attempts to adds the cookie to the jar. If the cookie is expired, instead it deletes any matching cookie from the jar. A C<Max-Age> attribute will be converted to an absolute C<Expires> attribute. It will throw an exception if the request URL is missing or invalid. Returns true if successful cookie processing or undef/empty-list on failure. =head2 clear $jar->clear Empties the cookie jar. =head2 cookies_for my @cookies = $jar->cookies_for("http://www.example.com/foo/bar"); Given a request URL, returns a list of hash references representing cookies that should be sent. The hash references are copies -- changing values will not change the cookies in the jar. Cookies set C<secure> will only be returned if the request scheme is C<https>. Expired cookies will not be returned. Keys of a cookie hash reference might include: =over 4 =item * name -- the name of the cookie =item * value -- the value of the cookie =item * domain -- the domain name to which the cookie applies =item * path -- the path to which the cookie applies =item * expires -- if present, when the cookie expires in epoch seconds =item * secure -- if present, the cookie was set C<Secure> =item * httponly -- if present, the cookie was set C<HttpOnly> =item * hostonly -- if present, the cookie may only be used with the domain as a host =item * creation_time -- epoch time when the cookie was first stored =item * last_access_time -- epoch time when the cookie was last accessed (i.e. "now") =back Keep in mind that C<httponly> means it should only be used in requests and not made available via Javascript, etc. This is pretty meaningless for Perl user agents. Generally, user agents should use the C<cookie_header> method instead. It will throw an exception if the request URL is missing or invalid. =head2 cookie_header my $header = $jar->cookie_header("http://www.example.com/foo/bar"); Given a request URL, returns a correctly-formatted string with all relevant cookies for the request. This string is ready to be used in a C<Cookie> header in an HTTP request. E.g.: SID=31d4d96e407aad42; lang=en-US It follows the same exclusion rules as C<cookies_for>. If the request is invalid or no cookies apply, it will return an empty string. =head2 dump_cookies my @list = $jar->dump_cookies; my @list = $jar->dump_cookies( { persistent => 1 } ); Returns a list of raw cookies in string form. The strings resemble what would be received from C<Set-Cookie> headers, but with additional internal fields. The list is only intended for use with C<load_cookies> to allow cookie jar persistence. If a hash reference with a true C<persistent> key is given as an argument, cookies without an C<Expires> time (i.e. "session cookies") will be omitted. Here is a trivial example of saving a cookie jar file with L<Path::Tiny>: path("jar.txt")->spew( join "\n", $jar->dump_cookies ); =head2 load_cookies $jar->load_cookies( @cookies ); Given a list of cookie strings from C<dump_cookies>, it adds them to the cookie jar. Cookies added in this way will supersede any existing cookies with similar domain, path and name. It returns the jar object for convenience when loading a new object: my $jar = HTTP::CookieJar->new->load_cookies( @cookies ); Here is a trivial example of loading a cookie jar file with L<Path::Tiny>: my $jar = HTTP::CookieJar->new->load_cookies( path("jar.txt")->lines ); =for Pod::Coverage method_names_here =head1 LIMITATIONS AND CAVEATS =head2 RFC 6265 vs prior standards This modules adheres as closely as possible to the user-agent rules of RFC 6265. Therefore, it does not handle nor generate C<Set-Cookie2> and C<Cookie2> headers, implement C<.local> suffixes, or do path/domain matching in accord with prior RFC's. =head2 Internationalized domain names Internationalized domain names given in requests must be properly encoded in ASCII form. =head2 Public suffixes If L<Mozilla::PublicSuffix> is installed, cookie domains will be checked against the public suffix list. Public suffix cookies are only allowed as host-only cookies. =head2 Third-party cookies According to RFC 6265, a cookie may be accepted only if has no C<Domain> attribute (in which case it is "host-only") or if the C<Domain> attribute is a suffix of the request URL. This effectively prohibits Site A from setting a cookie for unrelated Site B, which is one potential third-party cookie vector. =head1 SEE ALSO =over 4 =item * L<HTTP::Cookies> =item * L<Mojo::UserAgent::CookieJar> =back =for :stopwords cpan testmatrix url bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan =head1 SUPPORT =head2 Bugs / Feature Requests Please report any bugs or feature requests through the issue tracker at L<https://github.com/dagolden/HTTP-CookieJar/issues>. You will be notified automatically of any progress on your issue. =head2 Source Code This is open source software. The code repository is available for public review and contribution under the terms of the license. L<https://github.com/dagolden/HTTP-CookieJar> git clone https://github.com/dagolden/HTTP-CookieJar.git =head1 AUTHOR David Golden <dagolden@cpan.org> =head1 CONTRIBUTORS =for stopwords Dan Book David Golden jvolkening =over 4 =item * Dan Book <grinnz@grinnz.com> =item * David Golden <xdg@xdg.me> =item * jvolkening <jdv@base2bio.com> =back =head1 COPYRIGHT AND LICENSE This software is Copyright (c) 2013 by David Golden. This is free software, licensed under: The Apache License, Version 2.0, January 2004 =cut lib/HTTP/CookieJar/LWP.pm 0000644 00000005053 15125143463 0010746 0 ustar 00 use 5.008001; use strict; use warnings; package HTTP::CookieJar::LWP; # ABSTRACT: LWP adapter for HTTP::CookieJar our $VERSION = '0.014'; use parent 'HTTP::CookieJar'; sub add_cookie_header { my ( $self, $request ) = @_; my $url = _get_url( $request, $request->uri ); return unless ( $url->scheme =~ /^https?\z/ ); my $header = $self->cookie_header($url); $request->header( Cookie => $header ); return $request; } sub extract_cookies { my ( $self, $response ) = @_; my $request = $response->request or return; my $url = _get_url( $request, $request->uri ); $self->add( $url, $_ ) for $response->_header("Set-Cookie"); return $response; } #--------------------------------------------------------------------------# # helper subroutines #--------------------------------------------------------------------------# sub _get_url { my ( $request, $url ) = @_; my $new_url = $url->clone; if ( my $h = $request->header("Host") ) { $h =~ s/:\d+$//; # might have a port as well $new_url->host($h); } return $new_url; } sub _url_path { my $url = shift; my $path; if ( $url->can('epath') ) { $path = $url->epath; # URI::URL method } else { $path = $url->path; # URI::_generic method } $path = "/" unless length $path; $path; } sub _normalize_path # so that plain string compare can be used { my $x; $_[0] =~ s/%([0-9a-fA-F][0-9a-fA-F])/ $x = uc($1); $x eq "2F" || $x eq "25" ? "%$x" : pack("C", hex($x)); /eg; $_[0] =~ s/([\0-\x20\x7f-\xff])/sprintf("%%%02X",ord($1))/eg; } 1; # vim: ts=4 sts=4 sw=4 et: __END__ =pod =encoding UTF-8 =head1 NAME HTTP::CookieJar::LWP - LWP adapter for HTTP::CookieJar =head1 VERSION version 0.014 =head1 SYNOPSIS use LWP::UserAgent; use HTTP::CookieJar::LWP; my $ua = LWP::UserAgent->new( cookie_jar => HTTP::CookieJar::LWP->new ); =head1 DESCRIPTION This module is an experimental adapter to make L<HTTP::CookieJar> work with L<LWP>. It implements the two methods that C<LWP> calls from L<HTTP::Cookies>. It is not a general-purpose drop-in replacement for C<HTTP::Cookies> in any other way. =for Pod::Coverage method_names_here add_cookie_header extract_cookies =head1 AUTHOR David Golden <dagolden@cpan.org> =head1 COPYRIGHT AND LICENSE This software is Copyright (c) 2013 by David Golden. This is free software, licensed under: The Apache License, Version 2.0, January 2004 =cut MYMETA.json 0000644 00000006666 15125143463 0006455 0 ustar 00 { "abstract" : "A minimalist HTTP user agent cookie jar", "author" : [ "David Golden <dagolden@cpan.org>" ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 6.025, CPAN::Meta::Converter version 2.150010", "license" : [ "apache_2_0" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "HTTP-CookieJar", "no_index" : { "directory" : [ "corpus", "examples", "t", "xt" ], "package" : [ "DB" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "6.17" } }, "develop" : { "requires" : { "Dist::Zilla" : "5", "Dist::Zilla::Plugin::Prereqs" : "0", "Dist::Zilla::Plugin::ReleaseStatus::FromVersion" : "0", "Dist::Zilla::Plugin::RemovePrereqs" : "0", "Dist::Zilla::PluginBundle::DAGOLDEN" : "0.072", "File::Spec" : "0", "File::Temp" : "0", "IO::Handle" : "0", "IPC::Open3" : "0", "Pod::Coverage::TrustPod" : "0", "Pod::Wordlist" : "0", "Software::License::Apache_2_0" : "0", "Test::CPAN::Meta" : "0", "Test::MinimumVersion" : "0", "Test::More" : "0", "Test::Perl::Critic" : "0", "Test::Pod" : "1.41", "Test::Pod::Coverage" : "1.08", "Test::Portability::Files" : "0", "Test::Spelling" : "0.12", "Test::Version" : "1" } }, "runtime" : { "recommends" : { "Mozilla::PublicSuffix" : "0" }, "requires" : { "Carp" : "0", "HTTP::Date" : "0", "Time::Local" : "1.1901", "parent" : "0", "perl" : "5.008001", "strict" : "0", "warnings" : "0" } }, "test" : { "recommends" : { "CPAN::Meta" : "2.120900" }, "requires" : { "ExtUtils::MakeMaker" : "0", "File::Spec" : "0", "Test::Deep" : "0", "Test::More" : "0.96", "Test::Requires" : "0", "Time::Local" : "1.1901", "URI" : "0", "lib" : "0" } } }, "provides" : { "HTTP::CookieJar" : { "file" : "lib/HTTP/CookieJar.pm", "version" : "0.014" }, "HTTP::CookieJar::LWP" : { "file" : "lib/HTTP/CookieJar/LWP.pm", "version" : "0.014" } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/dagolden/HTTP-CookieJar/issues" }, "homepage" : "https://github.com/dagolden/HTTP-CookieJar", "repository" : { "type" : "git", "url" : "https://github.com/dagolden/HTTP-CookieJar.git", "web" : "https://github.com/dagolden/HTTP-CookieJar" } }, "version" : "0.014", "x_authority" : "cpan:DAGOLDEN", "x_contributors" : [ "Dan Book <grinnz@grinnz.com>", "David Golden <xdg@xdg.me>", "jvolkening <jdv@base2bio.com>" ], "x_generated_by_perl" : "v5.36.0", "x_serialization_backend" : "JSON::PP version 4.06", "x_spdx_expression" : "Apache-2.0" } README 0000644 00000014652 15125143463 0005440 0 ustar 00 NAME HTTP::CookieJar - A minimalist HTTP user agent cookie jar VERSION version 0.014 SYNOPSIS use HTTP::CookieJar; my $jar = HTTP::CookieJar->new; # add cookie received from a request $jar->add( "http://www.example.com/", "CUSTOMER=WILE_E_COYOTE; Path=/; Domain=example.com" ); # extract cookie header for a given request my $cookie = $jar->cookie_header( "http://www.example.com/" ); DESCRIPTION This module implements a minimalist HTTP user agent cookie jar in conformance with RFC 6265 <http://tools.ietf.org/html/rfc6265>. Unlike the commonly used HTTP::Cookies module, this module does not require use of HTTP::Request and HTTP::Response objects. An LWP-compatible adapter is available as HTTP::CookieJar::LWP. CONSTRUCTORS new my $jar = HTTP::CookieJar->new; Return a new, empty cookie jar METHODS add $jar->add( "http://www.example.com/", "lang=en-US; Path=/; Domain=example.com" ); Given a request URL and a "Set-Cookie" header string, attempts to adds the cookie to the jar. If the cookie is expired, instead it deletes any matching cookie from the jar. A "Max-Age" attribute will be converted to an absolute "Expires" attribute. It will throw an exception if the request URL is missing or invalid. Returns true if successful cookie processing or undef/empty-list on failure. clear $jar->clear Empties the cookie jar. cookies_for my @cookies = $jar->cookies_for("http://www.example.com/foo/bar"); Given a request URL, returns a list of hash references representing cookies that should be sent. The hash references are copies -- changing values will not change the cookies in the jar. Cookies set "secure" will only be returned if the request scheme is "https". Expired cookies will not be returned. Keys of a cookie hash reference might include: * name -- the name of the cookie * value -- the value of the cookie * domain -- the domain name to which the cookie applies * path -- the path to which the cookie applies * expires -- if present, when the cookie expires in epoch seconds * secure -- if present, the cookie was set "Secure" * httponly -- if present, the cookie was set "HttpOnly" * hostonly -- if present, the cookie may only be used with the domain as a host * creation_time -- epoch time when the cookie was first stored * last_access_time -- epoch time when the cookie was last accessed (i.e. "now") Keep in mind that "httponly" means it should only be used in requests and not made available via Javascript, etc. This is pretty meaningless for Perl user agents. Generally, user agents should use the "cookie_header" method instead. It will throw an exception if the request URL is missing or invalid. cookie_header my $header = $jar->cookie_header("http://www.example.com/foo/bar"); Given a request URL, returns a correctly-formatted string with all relevant cookies for the request. This string is ready to be used in a "Cookie" header in an HTTP request. E.g.: SID=31d4d96e407aad42; lang=en-US It follows the same exclusion rules as "cookies_for". If the request is invalid or no cookies apply, it will return an empty string. dump_cookies my @list = $jar->dump_cookies; my @list = $jar->dump_cookies( { persistent => 1 } ); Returns a list of raw cookies in string form. The strings resemble what would be received from "Set-Cookie" headers, but with additional internal fields. The list is only intended for use with "load_cookies" to allow cookie jar persistence. If a hash reference with a true "persistent" key is given as an argument, cookies without an "Expires" time (i.e. "session cookies") will be omitted. Here is a trivial example of saving a cookie jar file with Path::Tiny: path("jar.txt")->spew( join "\n", $jar->dump_cookies ); load_cookies $jar->load_cookies( @cookies ); Given a list of cookie strings from "dump_cookies", it adds them to the cookie jar. Cookies added in this way will supersede any existing cookies with similar domain, path and name. It returns the jar object for convenience when loading a new object: my $jar = HTTP::CookieJar->new->load_cookies( @cookies ); Here is a trivial example of loading a cookie jar file with Path::Tiny: my $jar = HTTP::CookieJar->new->load_cookies( path("jar.txt")->lines ); LIMITATIONS AND CAVEATS RFC 6265 vs prior standards This modules adheres as closely as possible to the user-agent rules of RFC 6265. Therefore, it does not handle nor generate "Set-Cookie2" and "Cookie2" headers, implement ".local" suffixes, or do path/domain matching in accord with prior RFC's. Internationalized domain names Internationalized domain names given in requests must be properly encoded in ASCII form. Public suffixes If Mozilla::PublicSuffix is installed, cookie domains will be checked against the public suffix list. Public suffix cookies are only allowed as host-only cookies. Third-party cookies According to RFC 6265, a cookie may be accepted only if has no "Domain" attribute (in which case it is "host-only") or if the "Domain" attribute is a suffix of the request URL. This effectively prohibits Site A from setting a cookie for unrelated Site B, which is one potential third-party cookie vector. SEE ALSO * HTTP::Cookies * Mojo::UserAgent::CookieJar SUPPORT Bugs / Feature Requests Please report any bugs or feature requests through the issue tracker at <https://github.com/dagolden/HTTP-CookieJar/issues>. You will be notified automatically of any progress on your issue. Source Code This is open source software. The code repository is available for public review and contribution under the terms of the license. <https://github.com/dagolden/HTTP-CookieJar> git clone https://github.com/dagolden/HTTP-CookieJar.git AUTHOR David Golden <dagolden@cpan.org> CONTRIBUTORS * Dan Book <grinnz@grinnz.com> * David Golden <xdg@xdg.me> * jvolkening <jdv@base2bio.com> COPYRIGHT AND LICENSE This software is Copyright (c) 2013 by David Golden. This is free software, licensed under: The Apache License, Version 2.0, January 2004
| ver. 1.6 |
Github
|
.
| PHP 8.2.30 | ??????????? ?????????: 0 |
proxy
|
phpinfo
|
???????????