HTTP-Cookies-6.10/000755 000765 000024 00000000000 13774710302 015074 5ustar00olafaldersstaff000000 000000 HTTP-Cookies-6.10/perltidyrc000644 000765 000024 00000000330 13774710302 017174 0ustar00olafaldersstaff000000 000000 --blank-lines-before-packages=0 --iterations=2 --no-outdent-long-comments -b -bar -boc -ci=4 -i=4 -l=78 -nolq -se -wbb="% + - * / x != == >= <= =~ !~ < > | & >= < = **= += *= &= <<= &&= -= /= |= >>= ||= .= %= ^= x=" HTTP-Cookies-6.10/perlcriticrc000644 000765 000024 00000004405 13774710302 017507 0ustar00olafaldersstaff000000 000000 severity = 3 verbose = 11 theme = core + pbp + bugs + maintenance + cosmetic + complexity + security + tests + moose exclude = Subroutines::ProhibitCallsToUndeclaredSubs [BuiltinFunctions::ProhibitStringySplit] severity = 3 [CodeLayout::RequireTrailingCommas] severity = 3 [ControlStructures::ProhibitCStyleForLoops] severity = 3 [InputOutput::RequireCheckedSyscalls] functions = :builtins exclude_functions = sleep severity = 3 [Moose::RequireCleanNamespace] modules = Moose Moose::Role MooseX::Role::Parameterized Moose::Util::TypeConstraints cleaners = namespace::autoclean [NamingConventions::Capitalization] package_exemptions = [A-Z]\w+|minFraud file_lexical_variables = [A-Z]\w+|[^A-Z]+ global_variables = :starts_with_upper scoped_lexical_variables = [A-Z]\w+|[^A-Z]+ severity = 3 # Given our code base, leaving this at 5 would be a huge pain [Subroutines::ProhibitManyArgs] max_arguments = 10 [RegularExpressions::ProhibitComplexRegexes] max_characters = 200 [RegularExpressions::ProhibitUnusualDelimiters] severity = 3 [Subroutines::ProhibitUnusedPrivateSubroutines] private_name_regex = _(?!build)\w+ skip_when_using = Moo::Role Moose::Role MooseX::Role::Parameterized Role::Tiny Test::Class::Moose::Role [TestingAndDebugging::ProhibitNoWarnings] allow = redefine [ValuesAndExpressions::ProhibitEmptyQuotes] severity = 3 [ValuesAndExpressions::ProhibitInterpolationOfLiterals] severity = 3 [ValuesAndExpressions::RequireUpperCaseHeredocTerminator] severity = 3 [Variables::ProhibitPackageVars] add_packages = Test::Builder [TestingAndDebugging::RequireUseStrict] [TestingAndDebugging::RequireUseWarnings] [-ControlStructures::ProhibitCascadingIfElse] [-ErrorHandling::RequireCarping] [-InputOutput::RequireBriefOpen] [-ValuesAndExpressions::ProhibitConstantPragma] # No need for /xsm everywhere [-RegularExpressions::RequireDotMatchAnything] [-RegularExpressions::RequireExtendedFormatting] [-RegularExpressions::RequireLineBoundaryMatching] [-Subroutines::ProhibitExplicitReturnUndef] # http://stackoverflow.com/questions/2275317/why-does-perlcritic-dislike-using-shift-to-populate-subroutine-variables [-Subroutines::RequireArgUnpacking] [-Subroutines::RequireFinalReturn] # "use v5.14" is more readable than "use 5.014" [-ValuesAndExpressions::ProhibitVersionStrings] HTTP-Cookies-6.10/cpanfile000644 000765 000024 00000002162 13774710302 016601 0ustar00olafaldersstaff000000 000000 # This file is generated by Dist::Zilla::Plugin::CPANFile v6.017 # Do not edit this file directly. To change prereqs, edit the `dist.ini` file. requires "Carp" => "0"; requires "HTTP::Date" => "6"; requires "HTTP::Headers::Util" => "6"; requires "HTTP::Request" => "0"; requires "locale" => "0"; requires "perl" => "5.008001"; requires "strict" => "0"; on 'test' => sub { requires "ExtUtils::MakeMaker" => "0"; requires "File::Spec" => "0"; requires "HTTP::Response" => "0"; requires "Test" => "0"; requires "Test::More" => "0"; requires "URI" => "0"; requires "warnings" => "0"; }; on 'test' => sub { recommends "CPAN::Meta" => "2.120900"; }; on 'configure' => sub { requires "ExtUtils::MakeMaker" => "0"; }; on 'develop' => sub { requires "Pod::Coverage::TrustPod" => "0"; requires "Test::CPAN::Changes" => "0.19"; requires "Test::EOL" => "0"; requires "Test::Mojibake" => "0"; requires "Test::More" => "0.96"; requires "Test::Pod" => "1.41"; requires "Test::Pod::Coverage" => "1.08"; requires "Test::Portability::Files" => "0"; requires "Test::Version" => "1"; requires "warnings" => "0"; }; HTTP-Cookies-6.10/Changes000644 000765 000024 00000004333 13774710302 016372 0ustar00olafaldersstaff000000 000000 Revision history for HTTP-Cookies. The HTTP::Cookies module used to be bundled with the libwww-perl distribution. 6.10 2021-01-04 22:03:43Z - Do not set discard if max-age is set (GH#61) (robnagler, simbabque) - Add tests for #61 - do not set discard if max-age is set (GH#65) (Julien Fiegehenn) 6.09 2020-11-19 22:20:47Z - Allow HttpOnly cookies to be loaded by HTTP::Cookies::Netscape (GH#63) (Charlie Hothersall-Thomas) 6.08 2019-12-02 15:58:32Z - allow different "ignore_discard" value at save() time (GH#2) (Alex Peters) 6.07 2019-11-15 18:11:42Z - Fix t/issue32.t on old perl versions (GH#59) (Bernhard M. Wiedemann) 6.06 2019-11-12 14:28:31Z - Make test pass in 2025 (GH#56) (Bernhard M. Wiedemann) 6.05 2019-10-24 02:21:51Z - Fix GH#32 by checking for " as well as ; when splitting. (GH#49) (colinnewell) - Fix GH#48 update documentation about $version (GH#55) (Dave Menninger) - Fix broken README badge (GH#54) (Alex Peters) - Whenever possible, use an absolute four digit year for Time::Local (GH#52) (Olaf Alders) - Add test case for Issue #26 (GH#45) (George-NG) - Long numbers (GH#47) (pludlamCVL) - Cookies.pm: die if close on $fh in ->save fails (GH#46) (MCRayRay) - Replace "use vars" with "our" (GH#43) (James Raspass) - Fixed minor typo in the pod for HTTP::Cookies. (GH#39) (Mohammad S Anwar) 6.04 2017-08-03 15:05:22Z - Fix package version numbers 6.03 2017-04-03 11:35:35-04:00 America/Toronto - No changes since TRIAL release 6.02 6.02 2017-01-12 18:02:49-05:00 America/Toronto (TRIAL RELEASE) - Document the lack of Public Suffix https://publicsuffix.org/ support - Add TODO tests for lack of Public Suffix support - Improve "maxage" documentation - Update the GitHub repository location - Use GitHub Issues instead of RT - Stop using bareword filehandles - Various internal distribution management and testing changes - Add get_cookies() method 6.01 2012-02-15 - Restore 5.8.1 compatiblity. 6.00 2011-02-27 - Initial release of HTTP-Cookies as a separate distribution. There are no code changes besides incrementing the version number since libwww-perl-5.837. HTTP-Cookies-6.10/INSTALL000644 000765 000024 00000004332 13774710302 016127 0ustar00olafaldersstaff000000 000000 This is the Perl distribution HTTP-Cookies. Installing HTTP-Cookies is straightforward. ## Installation with cpanm If you have cpanm, you only need one line: % cpanm HTTP::Cookies If it does not have permission to install modules to the current perl, cpanm will automatically set up and install to a local::lib in your home directory. See the local::lib documentation (https://metacpan.org/pod/local::lib) for details on enabling it in your environment. ## Installing with the CPAN shell Alternatively, if your CPAN shell is set up, you should just be able to do: % cpan HTTP::Cookies ## Manual installation As a last resort, you can manually install it. Download the tarball, untar it, install configure prerequisites (see below), then build it: % perl Makefile.PL % make && make test Then install it: % make install On Windows platforms, you should use `dmake` or `nmake`, instead of `make`. If your perl is system-managed, you can create a local::lib in your home directory to install modules to. For details, see the local::lib documentation: https://metacpan.org/pod/local::lib The prerequisites of this distribution will also have to be installed manually. The prerequisites are listed in one of the files: `MYMETA.yml` or `MYMETA.json` generated by running the manual build process described above. ## Configure Prerequisites This distribution requires other modules to be installed before this distribution's installer can be run. They can be found under the "configure_requires" key of META.yml or the "{prereqs}{configure}{requires}" key of META.json. ## Other Prerequisites This distribution may require additional modules to be installed after running Makefile.PL. Look for prerequisites in the following phases: * to run make, PHASE = build * to use the module code itself, PHASE = runtime * to run tests, PHASE = test They can all be found in the "PHASE_requires" key of MYMETA.yml or the "{prereqs}{PHASE}{requires}" key of MYMETA.json. ## Documentation HTTP-Cookies documentation is available as POD. You can run `perldoc` from a shell to read the documentation: % perldoc HTTP::Cookies For more information on installing Perl modules via CPAN, please see: https://www.cpan.org/modules/INSTALL.html HTTP-Cookies-6.10/MANIFEST000644 000765 000024 00000001145 13774710302 016226 0ustar00olafaldersstaff000000 000000 # This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.017. CONTRIBUTORS Changes INSTALL LICENSE MANIFEST META.json META.yml Makefile.PL README.md cpanfile dist.ini lib/HTTP/Cookies.pm lib/HTTP/Cookies/Microsoft.pm lib/HTTP/Cookies/Netscape.pm perlcriticrc perltidyrc t/00-report-prereqs.dd t/00-report-prereqs.t t/10-original_spec.t t/11-rfc_2965.t t/cookies.t t/data/netscape-httponly.txt t/issue26.t t/issue32.t t/publicsuffix.t xt/author/eol.t xt/author/mojibake.t xt/author/pod-coverage.t xt/author/pod-syntax.t xt/author/portability.t xt/author/test-version.t xt/release/cpan-changes.t HTTP-Cookies-6.10/LICENSE000644 000765 000024 00000043644 13774710302 016114 0ustar00olafaldersstaff000000 000000 This software is copyright (c) 2002 by Gisle Aas. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. Terms of the Perl programming language system itself a) the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or b) the "Artistic License" --- The GNU General Public License, Version 1, February 1989 --- This software is Copyright (c) 2002 by Gisle Aas. This is free software, licensed under: The GNU General Public License, Version 1, February 1989 GNU GENERAL PUBLIC LICENSE Version 1, February 1989 Copyright (C) 1989 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The license agreements of most software companies try to keep users at the mercy of those companies. By contrast, our General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. The General Public License applies to the Free Software Foundation's software and to any other program whose authors commit to using it. You can use it for your programs, too. When we speak of free software, we are referring to freedom, not price. Specifically, the General Public License is designed to make sure that you have the freedom to give away or sell copies of free software, that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of a such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must tell them their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any work containing the Program or a portion of it, either verbatim or with modifications. Each licensee is addressed as "you". 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this General Public License and to the absence of any warranty; and give any other recipients of the Program a copy of this General Public License along with the Program. You may charge a fee for the physical act of transferring a copy. 2. You may modify your copy or copies of the Program or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: a) cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and b) cause the whole of any work that you distribute or publish, that in whole or in part contains the Program or any part thereof, either with or without modifications, to be licensed at no charge to all third parties under the terms of this General Public License (except that you may choose to grant warranty protection to some or all third parties, at your option). c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the simplest and most usual way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this General Public License. d) You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. Mere aggregation of another independent work with the Program (or its derivative) on a volume of a storage or distribution medium does not bring the other work under the scope of these terms. 3. You may copy and distribute the Program (or a portion or derivative of it, under Paragraph 2) in object code or executable form under the terms of Paragraphs 1 and 2 above provided that you also do one of the following: a) accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Paragraphs 1 and 2 above; or, b) accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal charge for the cost of distribution) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, c) accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) Source code for a work means the preferred form of the work for making modifications to it. For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs, or for standard header files or definitions files that accompany that operating system. 4. You may not copy, modify, sublicense, distribute or transfer the Program except as expressly provided under this General Public License. Any attempt otherwise to copy, modify, sublicense, distribute or transfer the Program is void, and will automatically terminate your rights to use the Program under this License. However, parties who have received copies, or rights to use copies, from you under this General Public License will not have their licenses terminated so long as such parties remain in full compliance. 5. By copying, distributing or modifying the Program (or any work based on the Program) you indicate your acceptance of this license to do so, and all its terms and conditions. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. 7. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of the license which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the license, you may choose any version ever published by the Free Software Foundation. 8. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to humanity, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19xx name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (a program to direct compilers to make passes at assemblers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice That's all there is to it! --- The Artistic License 1.0 --- This software is Copyright (c) 2002 by Gisle Aas. This is free software, licensed under: The Artistic License 1.0 The Artistic License Preamble The intent of this document is to state the conditions under which a Package may be copied, such that the Copyright Holder maintains some semblance of artistic control over the development of the package, while giving the users of the package the right to use and distribute the Package in a more-or-less customary fashion, plus the right to make reasonable modifications. Definitions: - "Package" refers to the collection of files distributed by the Copyright Holder, and derivatives of that collection of files created through textual modification. - "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder. - "Copyright Holder" is whoever is named in the copyright or copyrights for the package. - "You" is you, if you're thinking about copying or distributing this Package. - "Reasonable copying fee" is whatever you can justify on the basis of media cost, duplication charges, time of people involved, and so on. (You will not be required to justify it to the Copyright Holder, but only to the computing community at large as a market that must bear the fee.) - "Freely Available" means that no fee is charged for the item itself, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes and other modifications derived from the Public Domain or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed file stating how and when you changed that file, and provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major archive site such as ftp.uu.net, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. b) use the modified Package only within your corporation or organization. c) rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page for each non-standard executable that clearly documents how it differs from the Standard Version. d) make other distribution arrangements with the Copyright Holder. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) accompany the distribution with the machine-readable source of the Package with your modifications. c) accompany any non-standard executables with their corresponding Standard Version executables, giving the non-standard executables non-standard names, and clearly documenting the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) make other distribution arrangements with the Copyright Holder. 5. You may charge a reasonable copying fee for any distribution of this Package. You may charge any fee you choose for support of this Package. You may not charge a fee for this Package itself. However, you may distribute this Package in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution provided that you do not advertise this Package as a product of your own. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this Package. 7. C or perl subroutines supplied by you and linked into this Package shall not be considered part of this Package. 8. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. The End HTTP-Cookies-6.10/t/000755 000765 000024 00000000000 13774710302 015337 5ustar00olafaldersstaff000000 000000 HTTP-Cookies-6.10/xt/000755 000765 000024 00000000000 13774710302 015527 5ustar00olafaldersstaff000000 000000 HTTP-Cookies-6.10/META.yml000644 000765 000024 00000045007 13774710302 016353 0ustar00olafaldersstaff000000 000000 --- abstract: 'HTTP cookie jars' author: - 'Gisle Aas ' build_requires: ExtUtils::MakeMaker: '0' File::Spec: '0' HTTP::Response: '0' Test: '0' Test::More: '0' URI: '0' warnings: '0' configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 1 generated_by: 'Dist::Zilla version 6.017, CPAN::Meta::Converter version 2.150010' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: HTTP-Cookies no_index: directory: - examples - t - xt requires: Carp: '0' HTTP::Date: '6' HTTP::Headers::Util: '6' HTTP::Request: '0' locale: '0' perl: '5.008001' strict: '0' resources: bugtracker: https://github.com/libwww-perl/HTTP-Cookies/issues homepage: https://github.com/libwww-perl/HTTP-Cookies repository: https://github.com/libwww-perl/HTTP-Cookies.git version: '6.10' x_Dist_Zilla: perl: version: '5.030003' plugins: - class: Dist::Zilla::Plugin::Encoding name: Encoding version: '6.017' - class: Dist::Zilla::Plugin::OSPrereqs config: Dist::Zilla::Plugin::OSPrereqs: os: MSWin32 name: MSWin32 version: '0.011' - class: Dist::Zilla::Plugin::AutoPrereqs name: AutoPrereqs version: '6.017' - class: Dist::Zilla::Plugin::Prereqs config: Dist::Zilla::Plugin::Prereqs: phase: runtime type: requires name: Prereqs version: '6.017' - class: Dist::Zilla::Plugin::PromptIfStale config: Dist::Zilla::Plugin::PromptIfStale: check_all_plugins: 0 check_all_prereqs: 0 modules: - Dist::Zilla::PluginBundle::Author::OALDERS phase: build run_under_travis: 0 skip: [] name: '@Author::OALDERS/stale modules, build' version: '0.057' - class: Dist::Zilla::Plugin::PromptIfStale config: Dist::Zilla::Plugin::PromptIfStale: check_all_plugins: 1 check_all_prereqs: 1 modules: [] phase: release run_under_travis: 0 skip: [] name: '@Author::OALDERS/stale modules, release' version: '0.057' - class: Dist::Zilla::Plugin::CheckChangesHasContent name: '@Author::OALDERS/CheckChangesHasContent' version: '0.011' - class: Dist::Zilla::Plugin::MakeMaker config: Dist::Zilla::Role::TestRunner: default_jobs: '4' name: '@Author::OALDERS/MakeMaker' version: '6.017' - class: Dist::Zilla::Plugin::CPANFile name: '@Author::OALDERS/CPANFile' version: '6.017' - class: Dist::Zilla::Plugin::ContributorsFile name: '@Author::OALDERS/ContributorsFile' version: 0.3.0 - class: Dist::Zilla::Plugin::MetaJSON name: '@Author::OALDERS/MetaJSON' version: '6.017' - class: Dist::Zilla::Plugin::MetaYAML name: '@Author::OALDERS/MetaYAML' version: '6.017' - class: Dist::Zilla::Plugin::Manifest name: '@Author::OALDERS/Manifest' version: '6.017' - class: Dist::Zilla::Plugin::MetaNoIndex name: '@Author::OALDERS/MetaNoIndex' version: '6.017' - class: Dist::Zilla::Plugin::MetaConfig name: '@Author::OALDERS/MetaConfig' version: '6.017' - class: Dist::Zilla::Plugin::MetaResources name: '@Author::OALDERS/MetaResources' version: '6.017' - class: Dist::Zilla::Plugin::License name: '@Author::OALDERS/License' version: '6.017' - class: Dist::Zilla::Plugin::InstallGuide config: Dist::Zilla::Role::ModuleMetadata: Module::Metadata: '1.000037' version: '0.006' name: '@Author::OALDERS/InstallGuide' version: '1.200013' - class: Dist::Zilla::Plugin::ExecDir name: '@Author::OALDERS/ExecDir' version: '6.017' - class: Dist::Zilla::Plugin::MojibakeTests name: '@Author::OALDERS/MojibakeTests' version: '0.8' - class: Dist::Zilla::Plugin::PodSyntaxTests name: '@Author::OALDERS/PodSyntaxTests' version: '6.017' - class: Dist::Zilla::Plugin::Test::CPAN::Changes config: Dist::Zilla::Plugin::Test::CPAN::Changes: changelog: Changes name: '@Author::OALDERS/Test::CPAN::Changes' version: '0.012' - class: Dist::Zilla::Plugin::Test::EOL config: Dist::Zilla::Plugin::Test::EOL: filename: xt/author/eol.t finder: - ':ExecFiles' - ':InstallModules' - ':TestFiles' trailing_whitespace: 1 name: '@Author::OALDERS/Test::EOL' version: '0.19' - class: Dist::Zilla::Plugin::Test::Pod::Coverage::Configurable name: '@Author::OALDERS/Test::Pod::Coverage::Configurable' version: '0.07' - class: Dist::Zilla::Plugin::Test::Portability config: Dist::Zilla::Plugin::Test::Portability: options: '' name: '@Author::OALDERS/Test::Portability' version: '2.001000' - class: Dist::Zilla::Plugin::TestRelease name: '@Author::OALDERS/TestRelease' version: '6.017' - class: Dist::Zilla::Plugin::Test::ReportPrereqs name: '@Author::OALDERS/Test::ReportPrereqs' version: '0.028' - class: Dist::Zilla::Plugin::Test::Version name: '@Author::OALDERS/Test::Version' version: '1.09' - class: Dist::Zilla::Plugin::RunExtraTests config: Dist::Zilla::Role::TestRunner: default_jobs: '4' name: '@Author::OALDERS/RunExtraTests' version: '0.029' - class: Dist::Zilla::Plugin::PodWeaver config: Dist::Zilla::Plugin::PodWeaver: finder: - ':InstallModules' - ':ExecFiles' plugins: - class: Pod::Weaver::Plugin::EnsurePod5 name: '@CorePrep/EnsurePod5' version: '4.015' - class: Pod::Weaver::Plugin::H1Nester name: '@CorePrep/H1Nester' version: '4.015' - class: Pod::Weaver::Plugin::SingleEncoding name: '@Default/SingleEncoding' version: '4.015' - class: Pod::Weaver::Section::Name name: '@Default/Name' version: '4.015' - class: Pod::Weaver::Section::Version name: '@Default/Version' version: '4.015' - class: Pod::Weaver::Section::Region name: '@Default/prelude' version: '4.015' - class: Pod::Weaver::Section::Generic name: SYNOPSIS version: '4.015' - class: Pod::Weaver::Section::Generic name: DESCRIPTION version: '4.015' - class: Pod::Weaver::Section::Generic name: OVERVIEW version: '4.015' - class: Pod::Weaver::Section::Collect name: ATTRIBUTES version: '4.015' - class: Pod::Weaver::Section::Collect name: METHODS version: '4.015' - class: Pod::Weaver::Section::Collect name: FUNCTIONS version: '4.015' - class: Pod::Weaver::Section::Leftovers name: '@Default/Leftovers' version: '4.015' - class: Pod::Weaver::Section::Region name: '@Default/postlude' version: '4.015' - class: Pod::Weaver::Section::Authors name: '@Default/Authors' version: '4.015' - class: Pod::Weaver::Section::Legal name: '@Default/Legal' version: '4.015' name: '@Author::OALDERS/PodWeaver' version: '4.008' - class: Dist::Zilla::Plugin::PruneCruft name: '@Author::OALDERS/PruneCruft' version: '6.017' - class: Dist::Zilla::Plugin::CopyFilesFromBuild name: '@Author::OALDERS/CopyFilesFromBuild' version: '0.170880' - class: Dist::Zilla::Plugin::GithubMeta name: '@Author::OALDERS/GithubMeta' version: '0.58' - class: Dist::Zilla::Plugin::Git::GatherDir config: Dist::Zilla::Plugin::GatherDir: exclude_filename: - Install - LICENSE - META.json - Makefile.PL - README.md - cpanfile exclude_match: [] follow_symlinks: 0 include_dotfiles: 0 prefix: '' prune_directory: [] root: . Dist::Zilla::Plugin::Git::GatherDir: include_untracked: 0 name: '@Author::OALDERS/Git::GatherDir' version: '2.047' - class: Dist::Zilla::Plugin::CopyFilesFromRelease config: Dist::Zilla::Plugin::CopyFilesFromRelease: filename: - Install match: [] name: '@Author::OALDERS/CopyFilesFromRelease' version: '0.007' - class: Dist::Zilla::Plugin::Git::Check config: Dist::Zilla::Plugin::Git::Check: untracked_files: die Dist::Zilla::Role::Git::DirtyFiles: allow_dirty: - Changes - Install - LICENSE - META.json - Makefile.PL - README.md - cpanfile - dist.ini allow_dirty_match: [] changelog: Changes Dist::Zilla::Role::Git::Repo: git_version: 2.29.2 repo_root: . name: '@Author::OALDERS/Git::Check' version: '2.047' - class: Dist::Zilla::Plugin::Git::Contributors config: Dist::Zilla::Plugin::Git::Contributors: git_version: 2.29.2 include_authors: 0 include_releaser: 1 order_by: name paths: [] name: '@Author::OALDERS/Git::Contributors' version: '0.036' - class: Dist::Zilla::Plugin::ReadmeAnyFromPod config: Dist::Zilla::Role::FileWatcher: version: '0.006' name: '@Author::OALDERS/ReadmeMdInBuild' version: '0.163250' - class: Dist::Zilla::Plugin::StaticInstall config: Dist::Zilla::Plugin::StaticInstall: dry_run: 0 mode: off name: '@Author::OALDERS/StaticInstall' version: '0.012' - class: Dist::Zilla::Plugin::ShareDir name: '@Author::OALDERS/ShareDir' version: '6.017' - class: Dist::Zilla::Plugin::CheckIssues name: '@Author::OALDERS/CheckIssues' version: '0.011' - class: Dist::Zilla::Plugin::ConfirmRelease name: '@Author::OALDERS/ConfirmRelease' version: '6.017' - class: Dist::Zilla::Plugin::UploadToCPAN name: '@Author::OALDERS/UploadToCPAN' version: '6.017' - class: Dist::Zilla::Plugin::RewriteVersion::Transitional config: Dist::Zilla::Plugin::RewriteVersion: add_tarball_name: 0 finders: - ':ExecFiles' - ':InstallModules' global: 0 skip_version_provider: 0 Dist::Zilla::Plugin::RewriteVersion::Transitional: {} name: '@Author::OALDERS/@Git::VersionManager/RewriteVersion::Transitional' version: '0.009' - class: Dist::Zilla::Plugin::MetaProvides::Update name: '@Author::OALDERS/@Git::VersionManager/MetaProvides::Update' version: '0.007' - class: Dist::Zilla::Plugin::CopyFilesFromRelease config: Dist::Zilla::Plugin::CopyFilesFromRelease: filename: - Changes match: [] name: '@Author::OALDERS/@Git::VersionManager/CopyFilesFromRelease' version: '0.007' - class: Dist::Zilla::Plugin::Git::Commit config: Dist::Zilla::Plugin::Git::Commit: add_files_in: [] commit_msg: v%V%n%n%c signoff: 0 Dist::Zilla::Role::Git::DirtyFiles: allow_dirty: - Changes - Install - LICENSE - META.json - Makefile.PL - README.md - cpanfile - dist.ini allow_dirty_match: [] changelog: Changes Dist::Zilla::Role::Git::Repo: git_version: 2.29.2 repo_root: . Dist::Zilla::Role::Git::StringFormatter: time_zone: local name: '@Author::OALDERS/@Git::VersionManager/release snapshot' version: '2.047' - class: Dist::Zilla::Plugin::Git::Tag config: Dist::Zilla::Plugin::Git::Tag: branch: ~ changelog: Changes signed: 0 tag: v6.10 tag_format: v%V tag_message: v%V Dist::Zilla::Role::Git::Repo: git_version: 2.29.2 repo_root: . Dist::Zilla::Role::Git::StringFormatter: time_zone: local name: '@Author::OALDERS/@Git::VersionManager/Git::Tag' version: '2.047' - class: Dist::Zilla::Plugin::BumpVersionAfterRelease::Transitional config: Dist::Zilla::Plugin::BumpVersionAfterRelease: finders: - ':ExecFiles' - ':InstallModules' global: 0 munge_makefile_pl: 1 Dist::Zilla::Plugin::BumpVersionAfterRelease::Transitional: {} name: '@Author::OALDERS/@Git::VersionManager/BumpVersionAfterRelease::Transitional' version: '0.009' - class: Dist::Zilla::Plugin::NextRelease name: '@Author::OALDERS/@Git::VersionManager/NextRelease' version: '6.017' - class: Dist::Zilla::Plugin::Git::Commit config: Dist::Zilla::Plugin::Git::Commit: add_files_in: [] commit_msg: 'increment $VERSION after %v release' signoff: 0 Dist::Zilla::Role::Git::DirtyFiles: allow_dirty: - Build.PL - Changes - Makefile.PL allow_dirty_match: - (?^:^lib/.*\.pm$) changelog: Changes Dist::Zilla::Role::Git::Repo: git_version: 2.29.2 repo_root: . Dist::Zilla::Role::Git::StringFormatter: time_zone: local name: '@Author::OALDERS/@Git::VersionManager/post-release commit' version: '2.047' - class: Dist::Zilla::Plugin::Git::Push config: Dist::Zilla::Plugin::Git::Push: push_to: - origin remotes_must_exist: 1 Dist::Zilla::Role::Git::Repo: git_version: 2.29.2 repo_root: . name: '@Author::OALDERS/Git::Push' version: '2.047' - class: Dist::Zilla::Plugin::BumpVersionAfterRelease config: Dist::Zilla::Plugin::BumpVersionAfterRelease: finders: - ':ExecFiles' - ':InstallModules' global: 0 munge_makefile_pl: 1 name: BumpVersionAfterRelease version: '0.018' - class: Dist::Zilla::Plugin::FinderCode name: ':InstallModules' version: '6.017' - class: Dist::Zilla::Plugin::FinderCode name: ':IncModules' version: '6.017' - class: Dist::Zilla::Plugin::FinderCode name: ':TestFiles' version: '6.017' - class: Dist::Zilla::Plugin::FinderCode name: ':ExtraTestFiles' version: '6.017' - class: Dist::Zilla::Plugin::FinderCode name: ':ExecFiles' version: '6.017' - class: Dist::Zilla::Plugin::FinderCode name: ':PerlExecFiles' version: '6.017' - class: Dist::Zilla::Plugin::FinderCode name: ':ShareFiles' version: '6.017' - class: Dist::Zilla::Plugin::FinderCode name: ':MainModule' version: '6.017' - class: Dist::Zilla::Plugin::FinderCode name: ':AllFiles' version: '6.017' - class: Dist::Zilla::Plugin::FinderCode name: ':NoFiles' version: '6.017' zilla: class: Dist::Zilla::Dist::Builder config: is_trial: '0' version: '6.017' x_contributors: - 'Adam Kennedy ' - 'Adam Sjogren ' - 'Alexey Tourbin ' - 'Alex Kapranoff ' - 'Alex Peters ' - 'Alex Peters ' - 'amire80 ' - 'Andreas J. Koenig ' - 'Bernhard M. Wiedemann ' - 'Bill Mann ' - 'Bron Gondwana ' - 'Charlie Hothersall-Thomas ' - 'Chase Whitener ' - 'Colin Newell ' - 'Colin Newell ' - 'Daniel Hedlund ' - 'Dave Menninger ' - 'David E. Wheeler ' - 'DAVIDRW ' - 'Father Chrysostomos ' - 'FWILES ' - 'Gavin Peters ' - 'George Grozdev ' - 'Graeme Thompson ' - 'Hans-H. Froehlich ' - 'Ian Kilgore ' - 'Jacob J ' - 'James McCoy ' - 'James Raspass ' - 'jefflee ' - 'john9art ' - 'Mark Raymond ' - 'Mark Stosberg ' - 'Mike Schilli ' - 'Mohammad S Anwar ' - 'murphy ' - 'Olaf Alders ' - 'Ondrej Hanak ' - 'Perlover ' - 'Peter Rabbitson ' - 'Philip J. Ludlam ' - 'phrstbrn ' - 'Robert Stone ' - 'robnagler ' - 'Rolf Grossmann ' - 'ruff ' - 'sasao ' - 'Sean M. Burke ' - 'simbabque ' - 'Slaven Rezic ' - 'Spiros Denaxas ' - 'Steve Hay ' - 'Todd Lipcon ' - 'Tom Hukins ' - 'Tony Finch ' - 'Toru Yamaguchi ' - 'Ville Skyttä ' - 'Yuri Karaban ' - 'Zefram ' x_generated_by_perl: v5.30.3 x_serialization_backend: 'YAML::Tiny version 1.73' x_spdx_expression: 'Artistic-1.0-Perl OR GPL-1.0-or-later' x_static_install: 0 HTTP-Cookies-6.10/CONTRIBUTORS000644 000765 000024 00000002530 13774710302 016754 0ustar00olafaldersstaff000000 000000 # HTTP-COOKIES CONTRIBUTORS # This is the (likely incomplete) list of people who have helped make this distribution what it is, either via code contributions, patches, bug reports, help with troubleshooting, etc. A huge 'thank you' to all of them. * Adam Kennedy * Adam Sjogren * Alexey Tourbin * Alex Kapranoff * Alex Peters * Alex Peters * amire80 * Andreas J. Koenig * Bernhard M. Wiedemann * Bill Mann * Bron Gondwana * Charlie Hothersall-Thomas * Chase Whitener * Colin Newell * Colin Newell * Daniel Hedlund * Dave Menninger * David E. Wheeler * DAVIDRW * Father Chrysostomos * FWILES * Gavin Peters * George Grozdev * Graeme Thompson * Hans-H. Froehlich * Ian Kilgore * Jacob J * James McCoy * James Raspass * jefflee * john9art * Mark Raymond * Mark Stosberg * Mike Schilli * Mohammad S Anwar * murphy * Olaf Alders * Ondrej Hanak * Perlover * Peter Rabbitson * Philip J. Ludlam * phrstbrn * Robert Stone * robnagler * Rolf Grossmann * ruff * sasao * Sean M. Burke * simbabque * Slaven Rezic * Spiros Denaxas * Steve Hay * Todd Lipcon * Tom Hukins * Tony Finch * Toru Yamaguchi * Ville Skyttä * Yuri Karaban * Zefram HTTP-Cookies-6.10/META.json000644 000765 000024 00000067417 13774710302 016534 0ustar00olafaldersstaff000000 000000 { "abstract" : "HTTP cookie jars", "author" : [ "Gisle Aas " ], "dynamic_config" : 1, "generated_by" : "Dist::Zilla version 6.017, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "HTTP-Cookies", "no_index" : { "directory" : [ "examples", "t", "xt" ] }, "prereqs" : { "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "develop" : { "requires" : { "Pod::Coverage::TrustPod" : "0", "Test::CPAN::Changes" : "0.19", "Test::EOL" : "0", "Test::Mojibake" : "0", "Test::More" : "0.96", "Test::Pod" : "1.41", "Test::Pod::Coverage" : "1.08", "Test::Portability::Files" : "0", "Test::Version" : "1", "warnings" : "0" } }, "runtime" : { "requires" : { "Carp" : "0", "HTTP::Date" : "6", "HTTP::Headers::Util" : "6", "HTTP::Request" : "0", "locale" : "0", "perl" : "5.008001", "strict" : "0" } }, "test" : { "recommends" : { "CPAN::Meta" : "2.120900" }, "requires" : { "ExtUtils::MakeMaker" : "0", "File::Spec" : "0", "HTTP::Response" : "0", "Test" : "0", "Test::More" : "0", "URI" : "0", "warnings" : "0" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/libwww-perl/HTTP-Cookies/issues" }, "homepage" : "https://github.com/libwww-perl/HTTP-Cookies", "repository" : { "type" : "git", "url" : "https://github.com/libwww-perl/HTTP-Cookies.git", "web" : "https://github.com/libwww-perl/HTTP-Cookies" } }, "version" : "6.10", "x_Dist_Zilla" : { "perl" : { "version" : "5.030003" }, "plugins" : [ { "class" : "Dist::Zilla::Plugin::Encoding", "name" : "Encoding", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::OSPrereqs", "config" : { "Dist::Zilla::Plugin::OSPrereqs" : { "os" : "MSWin32" } }, "name" : "MSWin32", "version" : "0.011" }, { "class" : "Dist::Zilla::Plugin::AutoPrereqs", "name" : "AutoPrereqs", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::Prereqs", "config" : { "Dist::Zilla::Plugin::Prereqs" : { "phase" : "runtime", "type" : "requires" } }, "name" : "Prereqs", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::PromptIfStale", "config" : { "Dist::Zilla::Plugin::PromptIfStale" : { "check_all_plugins" : 0, "check_all_prereqs" : 0, "modules" : [ "Dist::Zilla::PluginBundle::Author::OALDERS" ], "phase" : "build", "run_under_travis" : 0, "skip" : [] } }, "name" : "@Author::OALDERS/stale modules, build", "version" : "0.057" }, { "class" : "Dist::Zilla::Plugin::PromptIfStale", "config" : { "Dist::Zilla::Plugin::PromptIfStale" : { "check_all_plugins" : 1, "check_all_prereqs" : 1, "modules" : [], "phase" : "release", "run_under_travis" : 0, "skip" : [] } }, "name" : "@Author::OALDERS/stale modules, release", "version" : "0.057" }, { "class" : "Dist::Zilla::Plugin::CheckChangesHasContent", "name" : "@Author::OALDERS/CheckChangesHasContent", "version" : "0.011" }, { "class" : "Dist::Zilla::Plugin::MakeMaker", "config" : { "Dist::Zilla::Role::TestRunner" : { "default_jobs" : "4" } }, "name" : "@Author::OALDERS/MakeMaker", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::CPANFile", "name" : "@Author::OALDERS/CPANFile", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::ContributorsFile", "name" : "@Author::OALDERS/ContributorsFile", "version" : "0.3.0" }, { "class" : "Dist::Zilla::Plugin::MetaJSON", "name" : "@Author::OALDERS/MetaJSON", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::MetaYAML", "name" : "@Author::OALDERS/MetaYAML", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::Manifest", "name" : "@Author::OALDERS/Manifest", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::MetaNoIndex", "name" : "@Author::OALDERS/MetaNoIndex", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::MetaConfig", "name" : "@Author::OALDERS/MetaConfig", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::MetaResources", "name" : "@Author::OALDERS/MetaResources", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::License", "name" : "@Author::OALDERS/License", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::InstallGuide", "config" : { "Dist::Zilla::Role::ModuleMetadata" : { "Module::Metadata" : "1.000037", "version" : "0.006" } }, "name" : "@Author::OALDERS/InstallGuide", "version" : "1.200013" }, { "class" : "Dist::Zilla::Plugin::ExecDir", "name" : "@Author::OALDERS/ExecDir", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::MojibakeTests", "name" : "@Author::OALDERS/MojibakeTests", "version" : "0.8" }, { "class" : "Dist::Zilla::Plugin::PodSyntaxTests", "name" : "@Author::OALDERS/PodSyntaxTests", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::Test::CPAN::Changes", "config" : { "Dist::Zilla::Plugin::Test::CPAN::Changes" : { "changelog" : "Changes" } }, "name" : "@Author::OALDERS/Test::CPAN::Changes", "version" : "0.012" }, { "class" : "Dist::Zilla::Plugin::Test::EOL", "config" : { "Dist::Zilla::Plugin::Test::EOL" : { "filename" : "xt/author/eol.t", "finder" : [ ":ExecFiles", ":InstallModules", ":TestFiles" ], "trailing_whitespace" : 1 } }, "name" : "@Author::OALDERS/Test::EOL", "version" : "0.19" }, { "class" : "Dist::Zilla::Plugin::Test::Pod::Coverage::Configurable", "name" : "@Author::OALDERS/Test::Pod::Coverage::Configurable", "version" : "0.07" }, { "class" : "Dist::Zilla::Plugin::Test::Portability", "config" : { "Dist::Zilla::Plugin::Test::Portability" : { "options" : "" } }, "name" : "@Author::OALDERS/Test::Portability", "version" : "2.001000" }, { "class" : "Dist::Zilla::Plugin::TestRelease", "name" : "@Author::OALDERS/TestRelease", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::Test::ReportPrereqs", "name" : "@Author::OALDERS/Test::ReportPrereqs", "version" : "0.028" }, { "class" : "Dist::Zilla::Plugin::Test::Version", "name" : "@Author::OALDERS/Test::Version", "version" : "1.09" }, { "class" : "Dist::Zilla::Plugin::RunExtraTests", "config" : { "Dist::Zilla::Role::TestRunner" : { "default_jobs" : "4" } }, "name" : "@Author::OALDERS/RunExtraTests", "version" : "0.029" }, { "class" : "Dist::Zilla::Plugin::PodWeaver", "config" : { "Dist::Zilla::Plugin::PodWeaver" : { "finder" : [ ":InstallModules", ":ExecFiles" ], "plugins" : [ { "class" : "Pod::Weaver::Plugin::EnsurePod5", "name" : "@CorePrep/EnsurePod5", "version" : "4.015" }, { "class" : "Pod::Weaver::Plugin::H1Nester", "name" : "@CorePrep/H1Nester", "version" : "4.015" }, { "class" : "Pod::Weaver::Plugin::SingleEncoding", "name" : "@Default/SingleEncoding", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Name", "name" : "@Default/Name", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Version", "name" : "@Default/Version", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Region", "name" : "@Default/prelude", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Generic", "name" : "SYNOPSIS", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Generic", "name" : "DESCRIPTION", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Generic", "name" : "OVERVIEW", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Collect", "name" : "ATTRIBUTES", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Collect", "name" : "METHODS", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Collect", "name" : "FUNCTIONS", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Leftovers", "name" : "@Default/Leftovers", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Region", "name" : "@Default/postlude", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Authors", "name" : "@Default/Authors", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Legal", "name" : "@Default/Legal", "version" : "4.015" } ] } }, "name" : "@Author::OALDERS/PodWeaver", "version" : "4.008" }, { "class" : "Dist::Zilla::Plugin::PruneCruft", "name" : "@Author::OALDERS/PruneCruft", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::CopyFilesFromBuild", "name" : "@Author::OALDERS/CopyFilesFromBuild", "version" : "0.170880" }, { "class" : "Dist::Zilla::Plugin::GithubMeta", "name" : "@Author::OALDERS/GithubMeta", "version" : "0.58" }, { "class" : "Dist::Zilla::Plugin::Git::GatherDir", "config" : { "Dist::Zilla::Plugin::GatherDir" : { "exclude_filename" : [ "Install", "LICENSE", "META.json", "Makefile.PL", "README.md", "cpanfile" ], "exclude_match" : [], "follow_symlinks" : 0, "include_dotfiles" : 0, "prefix" : "", "prune_directory" : [], "root" : "." }, "Dist::Zilla::Plugin::Git::GatherDir" : { "include_untracked" : 0 } }, "name" : "@Author::OALDERS/Git::GatherDir", "version" : "2.047" }, { "class" : "Dist::Zilla::Plugin::CopyFilesFromRelease", "config" : { "Dist::Zilla::Plugin::CopyFilesFromRelease" : { "filename" : [ "Install" ], "match" : [] } }, "name" : "@Author::OALDERS/CopyFilesFromRelease", "version" : "0.007" }, { "class" : "Dist::Zilla::Plugin::Git::Check", "config" : { "Dist::Zilla::Plugin::Git::Check" : { "untracked_files" : "die" }, "Dist::Zilla::Role::Git::DirtyFiles" : { "allow_dirty" : [ "Changes", "Install", "LICENSE", "META.json", "Makefile.PL", "README.md", "cpanfile", "dist.ini" ], "allow_dirty_match" : [], "changelog" : "Changes" }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.29.2", "repo_root" : "." } }, "name" : "@Author::OALDERS/Git::Check", "version" : "2.047" }, { "class" : "Dist::Zilla::Plugin::Git::Contributors", "config" : { "Dist::Zilla::Plugin::Git::Contributors" : { "git_version" : "2.29.2", "include_authors" : 0, "include_releaser" : 1, "order_by" : "name", "paths" : [] } }, "name" : "@Author::OALDERS/Git::Contributors", "version" : "0.036" }, { "class" : "Dist::Zilla::Plugin::ReadmeAnyFromPod", "config" : { "Dist::Zilla::Role::FileWatcher" : { "version" : "0.006" } }, "name" : "@Author::OALDERS/ReadmeMdInBuild", "version" : "0.163250" }, { "class" : "Dist::Zilla::Plugin::StaticInstall", "config" : { "Dist::Zilla::Plugin::StaticInstall" : { "dry_run" : 0, "mode" : "off" } }, "name" : "@Author::OALDERS/StaticInstall", "version" : "0.012" }, { "class" : "Dist::Zilla::Plugin::ShareDir", "name" : "@Author::OALDERS/ShareDir", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::CheckIssues", "name" : "@Author::OALDERS/CheckIssues", "version" : "0.011" }, { "class" : "Dist::Zilla::Plugin::ConfirmRelease", "name" : "@Author::OALDERS/ConfirmRelease", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::UploadToCPAN", "name" : "@Author::OALDERS/UploadToCPAN", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::RewriteVersion::Transitional", "config" : { "Dist::Zilla::Plugin::RewriteVersion" : { "add_tarball_name" : 0, "finders" : [ ":ExecFiles", ":InstallModules" ], "global" : 0, "skip_version_provider" : 0 }, "Dist::Zilla::Plugin::RewriteVersion::Transitional" : {} }, "name" : "@Author::OALDERS/@Git::VersionManager/RewriteVersion::Transitional", "version" : "0.009" }, { "class" : "Dist::Zilla::Plugin::MetaProvides::Update", "name" : "@Author::OALDERS/@Git::VersionManager/MetaProvides::Update", "version" : "0.007" }, { "class" : "Dist::Zilla::Plugin::CopyFilesFromRelease", "config" : { "Dist::Zilla::Plugin::CopyFilesFromRelease" : { "filename" : [ "Changes" ], "match" : [] } }, "name" : "@Author::OALDERS/@Git::VersionManager/CopyFilesFromRelease", "version" : "0.007" }, { "class" : "Dist::Zilla::Plugin::Git::Commit", "config" : { "Dist::Zilla::Plugin::Git::Commit" : { "add_files_in" : [], "commit_msg" : "v%V%n%n%c", "signoff" : 0 }, "Dist::Zilla::Role::Git::DirtyFiles" : { "allow_dirty" : [ "Changes", "Install", "LICENSE", "META.json", "Makefile.PL", "README.md", "cpanfile", "dist.ini" ], "allow_dirty_match" : [], "changelog" : "Changes" }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.29.2", "repo_root" : "." }, "Dist::Zilla::Role::Git::StringFormatter" : { "time_zone" : "local" } }, "name" : "@Author::OALDERS/@Git::VersionManager/release snapshot", "version" : "2.047" }, { "class" : "Dist::Zilla::Plugin::Git::Tag", "config" : { "Dist::Zilla::Plugin::Git::Tag" : { "branch" : null, "changelog" : "Changes", "signed" : 0, "tag" : "v6.10", "tag_format" : "v%V", "tag_message" : "v%V" }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.29.2", "repo_root" : "." }, "Dist::Zilla::Role::Git::StringFormatter" : { "time_zone" : "local" } }, "name" : "@Author::OALDERS/@Git::VersionManager/Git::Tag", "version" : "2.047" }, { "class" : "Dist::Zilla::Plugin::BumpVersionAfterRelease::Transitional", "config" : { "Dist::Zilla::Plugin::BumpVersionAfterRelease" : { "finders" : [ ":ExecFiles", ":InstallModules" ], "global" : 0, "munge_makefile_pl" : 1 }, "Dist::Zilla::Plugin::BumpVersionAfterRelease::Transitional" : {} }, "name" : "@Author::OALDERS/@Git::VersionManager/BumpVersionAfterRelease::Transitional", "version" : "0.009" }, { "class" : "Dist::Zilla::Plugin::NextRelease", "name" : "@Author::OALDERS/@Git::VersionManager/NextRelease", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::Git::Commit", "config" : { "Dist::Zilla::Plugin::Git::Commit" : { "add_files_in" : [], "commit_msg" : "increment $VERSION after %v release", "signoff" : 0 }, "Dist::Zilla::Role::Git::DirtyFiles" : { "allow_dirty" : [ "Build.PL", "Changes", "Makefile.PL" ], "allow_dirty_match" : [ "(?^:^lib/.*\\.pm$)" ], "changelog" : "Changes" }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.29.2", "repo_root" : "." }, "Dist::Zilla::Role::Git::StringFormatter" : { "time_zone" : "local" } }, "name" : "@Author::OALDERS/@Git::VersionManager/post-release commit", "version" : "2.047" }, { "class" : "Dist::Zilla::Plugin::Git::Push", "config" : { "Dist::Zilla::Plugin::Git::Push" : { "push_to" : [ "origin" ], "remotes_must_exist" : 1 }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.29.2", "repo_root" : "." } }, "name" : "@Author::OALDERS/Git::Push", "version" : "2.047" }, { "class" : "Dist::Zilla::Plugin::BumpVersionAfterRelease", "config" : { "Dist::Zilla::Plugin::BumpVersionAfterRelease" : { "finders" : [ ":ExecFiles", ":InstallModules" ], "global" : 0, "munge_makefile_pl" : 1 } }, "name" : "BumpVersionAfterRelease", "version" : "0.018" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":InstallModules", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":IncModules", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":TestFiles", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":ExtraTestFiles", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":ExecFiles", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":PerlExecFiles", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":ShareFiles", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":MainModule", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":AllFiles", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":NoFiles", "version" : "6.017" } ], "zilla" : { "class" : "Dist::Zilla::Dist::Builder", "config" : { "is_trial" : 0 }, "version" : "6.017" } }, "x_contributors" : [ "Adam Kennedy ", "Adam Sjogren ", "Alexey Tourbin ", "Alex Kapranoff ", "Alex Peters ", "Alex Peters ", "amire80 ", "Andreas J. Koenig ", "Bernhard M. Wiedemann ", "Bill Mann ", "Bron Gondwana ", "Charlie Hothersall-Thomas ", "Chase Whitener ", "Colin Newell ", "Colin Newell ", "Daniel Hedlund ", "Dave Menninger ", "David E. Wheeler ", "DAVIDRW ", "Father Chrysostomos ", "FWILES ", "Gavin Peters ", "George Grozdev ", "Graeme Thompson ", "Hans-H. Froehlich ", "Ian Kilgore ", "Jacob J ", "James McCoy ", "James Raspass ", "jefflee ", "john9art ", "Mark Raymond ", "Mark Stosberg ", "Mike Schilli ", "Mohammad S Anwar ", "murphy ", "Olaf Alders ", "Ondrej Hanak ", "Perlover ", "Peter Rabbitson ", "Philip J. Ludlam ", "phrstbrn ", "Robert Stone ", "robnagler ", "Rolf Grossmann ", "ruff ", "sasao ", "Sean M. Burke ", "simbabque ", "Slaven Rezic ", "Spiros Denaxas ", "Steve Hay ", "Todd Lipcon ", "Tom Hukins ", "Tony Finch ", "Toru Yamaguchi ", "Ville Skytt\u00e4 ", "Yuri Karaban ", "Zefram " ], "x_generated_by_perl" : "v5.30.3", "x_serialization_backend" : "Cpanel::JSON::XS version 4.19", "x_spdx_expression" : "Artistic-1.0-Perl OR GPL-1.0-or-later", "x_static_install" : 0 } HTTP-Cookies-6.10/README.md000644 000765 000024 00000016644 13774710302 016366 0ustar00olafaldersstaff000000 000000 # NAME HTTP::Cookies - HTTP cookie jars # VERSION version 6.10 # SYNOPSIS use HTTP::Cookies; $cookie_jar = HTTP::Cookies->new( file => "$ENV{'HOME'}/lwp_cookies.dat", autosave => 1, ); use LWP; my $browser = LWP::UserAgent->new; $browser->cookie_jar($cookie_jar); Or for an empty and temporary cookie jar: use LWP; my $browser = LWP::UserAgent->new; $browser->cookie_jar( {} ); # DESCRIPTION This class is for objects that represent a "cookie jar" -- that is, a database of all the HTTP cookies that a given LWP::UserAgent object knows about. Cookies are a general mechanism which server side connections can use to both store and retrieve information on the client side of the connection. For more information about cookies refer to [Cookie Spec](http://curl.haxx.se/rfc/cookie_spec.html) and [Cookie Central](http://www.cookiecentral.com). This module also implements the new style cookies described in [RFC 2965](https://tools.ietf.org/html/rfc2965). The two variants of cookies are supposed to be able to coexist happily. Instances of the class _HTTP::Cookies_ are able to store a collection of Set-Cookie2: and Set-Cookie: headers and are able to use this information to initialize Cookie-headers in _HTTP::Request_ objects. The state of a _HTTP::Cookies_ object can be saved in and restored from files. # LIMITATIONS This module does not support [Public Suffix](https://publicsuffix.org/) encouraged by a more recent standard, [RFC 6265](https://tools.ietf.org/html/rfc6265). This module's shortcomings mean that a malicious Web site can set cookies to track your user agent across all sites under a top level domain. See `t/publicsuffix.t` in this module's distribution for details. [HTTP::CookieJar::LWP](https://metacpan.org/pod/HTTP%3A%3ACookieJar%3A%3ALWP) supports Public Suffix, but only provides a limited subset of this module's functionality and [does not support](https://metacpan.org/pod/HTTP%3A%3ACookieJar#LIMITATIONS-AND-CAVEATS) standards older than _RFC 6265_. # METHODS The following methods are provided: - $cookie\_jar = HTTP::Cookies->new The constructor takes hash style parameters. The following parameters are recognized: file: name of the file to restore cookies from and save cookies to autosave: save during destruction (bool) ignore_discard: save even cookies that are requested to be discarded (bool) hide_cookie2: do not add Cookie2 header to requests Future parameters might include (not yet implemented): max_cookies 300 max_cookies_per_domain 20 max_cookie_size 4096 no_cookies list of domain names that we never return cookies to - $cookie\_jar->get\_cookies( $url\_or\_domain ) - $cookie\_jar->get\_cookies( $url\_or\_domain, $cookie\_key,... ) Returns a hash of the cookies that applies to the given URL. If a domainname is given as argument, then a prefix of "https://" is assumed. If one or more $cookie\_key parameters are provided return the given values, or `undef` if the cookie isn't available. - $cookie\_jar->add\_cookie\_header( $request ) The add\_cookie\_header() method will set the appropriate Cookie:-header for the _HTTP::Request_ object given as argument. The $request must have a valid url attribute before this method is called. - $cookie\_jar->extract\_cookies( $response ) The extract\_cookies() method will look for Set-Cookie: and Set-Cookie2: headers in the _HTTP::Response_ object passed as argument. Any of these headers that are found are used to update the state of the $cookie\_jar. - $cookie\_jar->set\_cookie( $version, $key, $val, $path, $domain, $port, $path\_spec, $secure, $maxage, $discard, \\%rest ) The set\_cookie() method updates the state of the $cookie\_jar. The $key, $val, $domain, $port and $path arguments are strings. The $path\_spec, $secure, $discard arguments are boolean values. The $maxage value is a number indicating number of seconds that this cookie will live. A value of $maxage <= 0 will delete this cookie. The $version argument sets the version of the cookie; the default value is 0 ( original Netscape spec ). Setting $version to another value indicates the RFC to which the cookie conforms (e.g. version 1 for RFC 2109). %rest defines various other attributes like "Comment" and "CommentURL". - $cookie\_jar->save - $cookie\_jar->save( $file ) - $cookie\_jar->save( file => $file, ignore\_discard => $ignore\_discard ) This method file saves the state of the $cookie\_jar to a file. The state can then be restored later using the load() method. If a filename is not specified we will use the name specified during construction. If the $ignore\_discard value is true (or not specified, but attribute _ignore\_discard_ was set at cookie jar construction), then we will even save cookies that are marked to be discarded. The default is to save a sequence of "Set-Cookie3" lines. "Set-Cookie3" is a proprietary LWP format, not known to be compatible with any browser. The _HTTP::Cookies::Netscape_ sub-class can be used to save in a format compatible with Netscape. - $cookie\_jar->load - $cookie\_jar->load( $file ) This method reads the cookies from the file and adds them to the $cookie\_jar. The file must be in the format written by the save() method. - $cookie\_jar->revert This method empties the $cookie\_jar and re-loads the $cookie\_jar from the last save file. - $cookie\_jar->clear - $cookie\_jar->clear( $domain ) - $cookie\_jar->clear( $domain, $path ) - $cookie\_jar->clear( $domain, $path, $key ) Invoking this method without arguments will empty the whole $cookie\_jar. If given a single argument only cookies belonging to that domain will be removed. If given two arguments, cookies belonging to the specified path within that domain are removed. If given three arguments, then the cookie with the specified key, path and domain is removed. - $cookie\_jar->clear\_temporary\_cookies Discard all temporary cookies. Scans for all cookies in the jar with either no expire field or a true `discard` flag. To be called when the user agent shuts down according to RFC 2965. - $cookie\_jar->scan( \\&callback ) The argument is a subroutine that will be invoked for each cookie stored in the $cookie\_jar. The subroutine will be invoked with the following arguments: 0 version 1 key 2 val 3 path 4 domain 5 port 6 path_spec 7 secure 8 expires 9 discard 10 hash - $cookie\_jar->as\_string - $cookie\_jar->as\_string( $skip\_discardables ) The as\_string() method will return the state of the $cookie\_jar represented as a sequence of "Set-Cookie3" header lines separated by "\\n". If $skip\_discardables is TRUE, it will not return lines for cookies with the _Discard_ attribute. # SEE ALSO [HTTP::Cookies::Netscape](https://metacpan.org/pod/HTTP%3A%3ACookies%3A%3ANetscape), [HTTP::Cookies::Microsoft](https://metacpan.org/pod/HTTP%3A%3ACookies%3A%3AMicrosoft) # AUTHOR Gisle Aas # COPYRIGHT AND LICENSE This software is copyright (c) 2002 by Gisle Aas. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. HTTP-Cookies-6.10/lib/000755 000765 000024 00000000000 13774710302 015642 5ustar00olafaldersstaff000000 000000 HTTP-Cookies-6.10/Makefile.PL000644 000765 000024 00000003104 13774710302 017044 0ustar00olafaldersstaff000000 000000 # This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.017. use strict; use warnings; use 5.008001; use ExtUtils::MakeMaker; my %WriteMakefileArgs = ( "ABSTRACT" => "HTTP cookie jars", "AUTHOR" => "Gisle Aas ", "CONFIGURE_REQUIRES" => { "ExtUtils::MakeMaker" => 0 }, "DISTNAME" => "HTTP-Cookies", "LICENSE" => "perl", "MIN_PERL_VERSION" => "5.008001", "NAME" => "HTTP::Cookies", "PREREQ_PM" => { "Carp" => 0, "HTTP::Date" => 6, "HTTP::Headers::Util" => 6, "HTTP::Request" => 0, "locale" => 0, "strict" => 0 }, "TEST_REQUIRES" => { "ExtUtils::MakeMaker" => 0, "File::Spec" => 0, "HTTP::Response" => 0, "Test" => 0, "Test::More" => 0, "URI" => 0, "warnings" => 0 }, "VERSION" => "6.10", "test" => { "TESTS" => "t/*.t" } ); my %FallbackPrereqs = ( "Carp" => 0, "ExtUtils::MakeMaker" => 0, "File::Spec" => 0, "HTTP::Date" => 6, "HTTP::Headers::Util" => 6, "HTTP::Request" => 0, "HTTP::Response" => 0, "Test" => 0, "Test::More" => 0, "URI" => 0, "locale" => 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) }; if ( $^O eq 'MSWin32' ) { $WriteMakefileArgs{PREREQ_PM}{'Win32'} = $FallbackPrereqs{'Win32'} = '0'; } WriteMakefile(%WriteMakefileArgs); HTTP-Cookies-6.10/dist.ini000644 000765 000024 00000001512 13774710302 016537 0ustar00olafaldersstaff000000 000000 name = HTTP-Cookies author = Gisle Aas license = Perl_5 main_module = lib/HTTP/Cookies.pm copyright_holder = Gisle Aas copyright_year = 2002 [Encoding] encoding = ISO-8859-1 filename = t/cookies.t [OSPrereqs / MSWin32] Win32 = 0 [AutoPrereqs] skip = ^Win32 [Prereqs] HTTP::Date = 6 HTTP::Headers::Util = 6 perl = 5.008001 [@Author::OALDERS] -remove = AutoPrereqs -remove = MinimumPerl -remove = OALDERS::TidyAll -remove = PkgVersion -remove = PodCoverageTests -remove = Prereqs -remove = Test::Perl::Critic -remove = Test::PodSpelling -remove = Test::TidyAll -remove = Test::Synopsis StaticInstall.mode = off StaticInstall.dry_run = 0 Test::Pod::Coverage::Configurable.skip = HTTP::Cookies::Microsoft Test::Pod::Coverage::Configurable.trustme = HTTP::Cookies => qr/set_cookie_ok/ [BumpVersionAfterRelease] HTTP-Cookies-6.10/lib/HTTP/000755 000765 000024 00000000000 13774710302 016421 5ustar00olafaldersstaff000000 000000 HTTP-Cookies-6.10/lib/HTTP/Cookies.pm000644 000765 000024 00000057321 13774710302 020363 0ustar00olafaldersstaff000000 000000 package HTTP::Cookies; use strict; use HTTP::Date qw(str2time parse_date time2str); use HTTP::Headers::Util qw(_split_header_words join_header_words); our $EPOCH_OFFSET; our $VERSION = '6.10'; # Legacy: because "use "HTTP::Cookies" used be the ONLY way # to load the class HTTP::Cookies::Netscape. require HTTP::Cookies::Netscape; $EPOCH_OFFSET = 0; # difference from Unix epoch # A HTTP::Cookies object is a hash. The main attribute is the # COOKIES 3 level hash: $self->{COOKIES}{$domain}{$path}{$key}. sub new { my $class = shift; my $self = bless { COOKIES => {}, }, $class; my %cnf = @_; for (keys %cnf) { $self->{lc($_)} = $cnf{$_}; } $self->load; $self; } sub add_cookie_header { my $self = shift; my $request = shift || return; my $url = $request->uri; my $scheme = $url->scheme; unless ($scheme =~ /^https?\z/) { return; } my $domain = _host($request, $url); $domain = "$domain.local" unless $domain =~ /\./; my $secure_request = ($scheme eq "https"); my $req_path = _url_path($url); my $req_port = $url->port; my $now = time(); _normalize_path($req_path) if $req_path =~ /%/; my @cval; # cookie values for the "Cookie" header my $set_ver; my $netscape_only = 0; # An exact domain match applies to any cookie while ($domain =~ /\./) { # Checking $domain for cookies" my $cookies = $self->{COOKIES}{$domain}; next unless $cookies; if ($self->{delayload} && defined($cookies->{'//+delayload'})) { my $cookie_data = $cookies->{'//+delayload'}{'cookie'}; delete $self->{COOKIES}{$domain}; $self->load_cookie($cookie_data->[1]); $cookies = $self->{COOKIES}{$domain}; next unless $cookies; # should not really happen } # Want to add cookies corresponding to the most specific paths # first (i.e. longest path first) my $path; for $path (sort {length($b) <=> length($a) } keys %$cookies) { if (index($req_path, $path) != 0) { next; } my($key,$array); while (($key,$array) = each %{$cookies->{$path}}) { my($version,$val,$port,$path_spec,$secure,$expires) = @$array; if ($secure && !$secure_request) { next; } if ($expires && $expires < $now) { next; } if ($port) { my $found; if ($port =~ s/^_//) { # The corresponding Set-Cookie attribute was empty $found++ if $port eq $req_port; $port = ""; } else { my $p; for $p (split(/,/, $port)) { $found++, last if $p eq $req_port; } } unless ($found) { next; } } if ($version > 0 && $netscape_only) { next; } # set version number of cookie header. # XXX: What should it be if multiple matching # Set-Cookie headers have different versions themselves if (!$set_ver++) { if ($version >= 1) { push(@cval, "\$Version=$version"); } elsif (!$self->{hide_cookie2}) { $request->header(Cookie2 => '$Version="1"'); } } # do we need to quote the value if ($val =~ /\W/ && $version) { $val =~ s/([\\\"])/\\$1/g; $val = qq("$val"); } # and finally remember this cookie push(@cval, "$key=$val"); if ($version >= 1) { push(@cval, qq(\$Path="$path")) if $path_spec; push(@cval, qq(\$Domain="$domain")) if $domain =~ /^\./; if (defined $port) { my $p = '$Port'; $p .= qq(="$port") if length $port; push(@cval, $p); } } } } } continue { # Try with a more general domain, alternately stripping # leading name components and leading dots. When this # results in a domain with no leading dot, it is for # Netscape cookie compatibility only: # # a.b.c.net Any cookie # .b.c.net Any cookie # b.c.net Netscape cookie only # .c.net Any cookie if ($domain =~ s/^\.+//) { $netscape_only = 1; } else { $domain =~ s/[^.]*//; $netscape_only = 0; } } if (@cval) { if (my $old = $request->header("Cookie")) { unshift(@cval, $old); } $request->header(Cookie => join("; ", @cval)); if (my $hash = $request->{_http_cookies}) { %$hash = (map split(/=/, $_, 2), @cval); } } $request; } sub get_cookies { my $self = shift; my $url = shift; $url = "https://$url" unless $url =~ m,^[a-zA-Z][a-zA-Z0-9.+\-]*:,; require HTTP::Request; my $req = HTTP::Request->new(GET => $url); my $cookies = $req->{_http_cookies} = {}; $self->add_cookie_header($req); if (@_) { return map $cookies->{$_}, @_ if wantarray; return $cookies->{$_[0]}; } return $cookies; } sub extract_cookies { my $self = shift; my $response = shift || return; my @set = _split_header_words($response->_header("Set-Cookie2")); my @ns_set = $response->_header("Set-Cookie"); return $response unless @set || @ns_set; # quick exit my $request = $response->request; my $url = $request->uri; my $req_host = _host($request, $url); $req_host = "$req_host.local" unless $req_host =~ /\./; my $req_port = $url->port; my $req_path = _url_path($url); _normalize_path($req_path) if $req_path =~ /%/; if (@ns_set) { # The old Netscape cookie format for Set-Cookie # http://curl.haxx.se/rfc/cookie_spec.html # can for instance contain an unquoted "," in the expires # field, so we have to use this ad-hoc parser. my $now = time(); # Build a hash of cookies that was present in Set-Cookie2 # headers. We need to skip them if we also find them in a # Set-Cookie header. my %in_set2; for (@set) { $in_set2{$_->[0]}++; } my $set; for $set (@ns_set) { $set =~ s/^\s+//; my @cur; my $param; my $expires; my $first_param = 1; for $param (@{_split_text($set)}) { next unless length($param); my($k,$v) = split(/\s*=\s*/, $param, 2); if (defined $v) { $v =~ s/\s+$//; #print "$k => $v\n"; } else { $k =~ s/\s+$//; #print "$k => undef"; } if (!$first_param && lc($k) eq "expires") { my $etime = str2time($v); if (defined $etime) { push(@cur, "Max-Age" => $etime - $now); $expires++; } else { # parse_date can deal with years outside the range of time_t, my($year, $mon, $day, $hour, $min, $sec, $tz) = parse_date($v); if ($year) { my $thisyear = (gmtime)[5] + 1900; if ($year < $thisyear) { push(@cur, "Max-Age" => -1); # any negative value will do $expires++; } elsif ($year >= $thisyear + 10) { # the date is at least 10 years into the future, just replace # it with something approximate push(@cur, "Max-Age" => 10 * 365 * 24 * 60 * 60); $expires++; } } } } elsif (!$first_param && lc($k) eq 'max-age') { $expires++; } elsif (!$first_param && lc($k) =~ /^(?:version|discard|ns-cookie)/) { # ignore } else { push(@cur, $k => $v); } $first_param = 0; } next unless @cur; next if $in_set2{$cur[0]}; # push(@cur, "Port" => $req_port); push(@cur, "Discard" => undef) unless $expires; push(@cur, "Version" => 0); push(@cur, "ns-cookie" => 1); push(@set, \@cur); } } SET_COOKIE: for my $set (@set) { next unless @$set >= 2; my $key = shift @$set; my $val = shift @$set; my %hash; while (@$set) { my $k = shift @$set; my $v = shift @$set; my $lc = lc($k); # don't loose case distinction for unknown fields $k = $lc if $lc =~ /^(?:discard|domain|max-age| path|port|secure|version)$/x; if ($k eq "discard" || $k eq "secure") { $v = 1 unless defined $v; } next if exists $hash{$k}; # only first value is significant $hash{$k} = $v; }; my %orig_hash = %hash; my $version = delete $hash{version}; $version = 1 unless defined($version); my $discard = delete $hash{discard}; my $secure = delete $hash{secure}; my $maxage = delete $hash{'max-age'}; my $ns_cookie = delete $hash{'ns-cookie'}; # Check domain my $domain = delete $hash{domain}; $domain = lc($domain) if defined $domain; if (defined($domain) && $domain ne $req_host && $domain ne ".$req_host") { if ($domain !~ /\./ && $domain ne "local") { next SET_COOKIE; } $domain = ".$domain" unless $domain =~ /^\./; if ($domain =~ /\.\d+$/) { next SET_COOKIE; } my $len = length($domain); unless (substr($req_host, -$len) eq $domain) { next SET_COOKIE; } my $hostpre = substr($req_host, 0, length($req_host) - $len); if ($hostpre =~ /\./ && !$ns_cookie) { next SET_COOKIE; } } else { $domain = $req_host; } my $path = delete $hash{path}; my $path_spec; if (defined $path && $path ne '') { $path_spec++; _normalize_path($path) if $path =~ /%/; if (!$ns_cookie && substr($req_path, 0, length($path)) ne $path) { next SET_COOKIE; } } else { $path = $req_path; $path =~ s,/[^/]*$,,; $path = "/" unless length($path); } my $port; if (exists $hash{port}) { $port = delete $hash{port}; if (defined $port) { $port =~ s/\s+//g; my $found; for my $p (split(/,/, $port)) { unless ($p =~ /^\d+$/) { next SET_COOKIE; } $found++ if $p eq $req_port; } unless ($found) { next SET_COOKIE; } } else { $port = "_$req_port"; } } $self->set_cookie($version,$key,$val,$path,$domain,$port,$path_spec,$secure,$maxage,$discard, \%hash) if $self->set_cookie_ok(\%orig_hash); } $response; } sub set_cookie_ok { 1; } sub set_cookie { my $self = shift; my($version, $key, $val, $path, $domain, $port, $path_spec, $secure, $maxage, $discard, $rest) = @_; # path and key can not be empty (key can't start with '$') return $self if !defined($path) || $path !~ m,^/, || !defined($key) || $key =~ m,^\$,; # ensure legal port if (defined $port) { return $self unless $port =~ /^_?\d+(?:,\d+)*$/; } my $expires; if (defined $maxage) { if ($maxage <= 0) { delete $self->{COOKIES}{$domain}{$path}{$key}; return $self; } $expires = time() + $maxage; } $version = 0 unless defined $version; my @array = ($version, $val,$port, $path_spec, $secure, $expires, $discard); push(@array, {%$rest}) if defined($rest) && %$rest; # trim off undefined values at end pop(@array) while !defined $array[-1]; $self->{COOKIES}{$domain}{$path}{$key} = \@array; $self; } sub save { my $self = shift; my %args = ( file => $self->{'file'}, ignore_discard => $self->{'ignore_discard'}, @_ == 1 ? ( file => $_[0] ) : @_ ); Carp::croak('Unexpected argument to save method') if keys %args > 2; my $file = $args{'file'} || return; open(my $fh, '>', $file) or die "Can't open $file: $!"; print {$fh} "#LWP-Cookies-1.0\n"; print {$fh} $self->as_string(!$args{'ignore_discard'}); close $fh or die "Can't close $file: $!"; 1; } sub load { my $self = shift; my $file = shift || $self->{'file'} || return; local $/ = "\n"; # make sure we got standard record separator open(my $fh, '<', $file) or return; # check that we have the proper header my $magic = <$fh>; chomp $magic; unless ($magic =~ /^#LWP-Cookies-\d+\.\d+/) { warn "$file does not seem to contain cookies"; return; } # go through the file while (my $line = <$fh>) { chomp $line; next unless $line =~ s/^Set-Cookie3:\s*//; my $cookie; for $cookie (_split_header_words($line)) { my($key,$val) = splice(@$cookie, 0, 2); my %hash; while (@$cookie) { my $k = shift @$cookie; my $v = shift @$cookie; $hash{$k} = $v; } my $version = delete $hash{version}; my $path = delete $hash{path}; my $domain = delete $hash{domain}; my $port = delete $hash{port}; my $expires = str2time(delete $hash{expires}); my $path_spec = exists $hash{path_spec}; delete $hash{path_spec}; my $secure = exists $hash{secure}; delete $hash{secure}; my $discard = exists $hash{discard}; delete $hash{discard}; my @array = ($version, $val, $port, $path_spec, $secure, $expires, $discard); push(@array, \%hash) if %hash; $self->{COOKIES}{$domain}{$path}{$key} = \@array; } } 1; } sub revert { my $self = shift; $self->clear->load; $self; } sub clear { my $self = shift; if (@_ == 0) { $self->{COOKIES} = {}; } elsif (@_ == 1) { delete $self->{COOKIES}{$_[0]}; } elsif (@_ == 2) { delete $self->{COOKIES}{$_[0]}{$_[1]}; } elsif (@_ == 3) { delete $self->{COOKIES}{$_[0]}{$_[1]}{$_[2]}; } else { require Carp; Carp::carp('Usage: $c->clear([domain [,path [,key]]])'); } $self; } sub clear_temporary_cookies { my($self) = @_; $self->scan(sub { if($_[9] or # "Discard" flag set not $_[8]) { # No expire field? $_[8] = -1; # Set the expire/max_age field $self->set_cookie(@_); # Clear the cookie } }); } sub DESTROY { my $self = shift; local($., $@, $!, $^E, $?); $self->save if $self->{'autosave'}; } sub scan { my($self, $cb) = @_; my($domain,$path,$key); for $domain (sort keys %{$self->{COOKIES}}) { for $path (sort keys %{$self->{COOKIES}{$domain}}) { for $key (sort keys %{$self->{COOKIES}{$domain}{$path}}) { my($version,$val,$port,$path_spec, $secure,$expires,$discard,$rest) = @{$self->{COOKIES}{$domain}{$path}{$key}}; $rest = {} unless defined($rest); &$cb($version,$key,$val,$path,$domain,$port, $path_spec,$secure,$expires,$discard,$rest); } } } } sub as_string { my($self, $skip_discard) = @_; my @res; $self->scan(sub { my($version,$key,$val,$path,$domain,$port, $path_spec,$secure,$expires,$discard,$rest) = @_; return if $discard && $skip_discard; my @h = ($key, $val); push(@h, "path", $path); push(@h, "domain" => $domain); push(@h, "port" => $port) if defined $port; push(@h, "path_spec" => undef) if $path_spec; push(@h, "secure" => undef) if $secure; push(@h, "expires" => HTTP::Date::time2isoz($expires)) if $expires; push(@h, "discard" => undef) if $discard; my $k; for $k (sort keys %$rest) { push(@h, $k, $rest->{$k}); } push(@h, "version" => $version); push(@res, "Set-Cookie3: " . join_header_words(\@h)); }); join("\n", @res, ""); } sub _host { my($request, $url) = @_; if (my $h = $request->header("Host")) { $h =~ s/:\d+$//; # might have a port as well return lc($h); } return lc($url->host); } 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; } # deals with splitting values by ; and the fact that they could # be in quotes which can also have escaping. sub _split_text { my $val = shift; my @vals = grep { $_ ne q{} } split(/([;\\"])/, $val); my @chunks; # divide it up into chunks to be processed. my $in_string = 0; my @current_string; for(my $i = 0; $i < @vals; $i++) { my $chunk = $vals[$i]; if($in_string) { if($chunk eq q{\\}) { # don't care about next char probably. # having said that, probably need to be appending to the chunks # just dropping this. $i++; if($i < @vals) { push @current_string, $vals[$i]; } } elsif($chunk eq q{"}) { $in_string = 0; } else { push @current_string, $chunk; } } else { if($chunk eq q{"}) { $in_string = 1; } elsif($chunk eq q{;}) { push @chunks, join(q{}, @current_string); @current_string = (); } else { push @current_string, $chunk; } } } push @chunks, join(q{}, @current_string) if @current_string; s/^\s+// for @chunks; return \@chunks; } 1; =pod =encoding UTF-8 =head1 NAME HTTP::Cookies - HTTP cookie jars =head1 VERSION version 6.10 =head1 SYNOPSIS use HTTP::Cookies; $cookie_jar = HTTP::Cookies->new( file => "$ENV{'HOME'}/lwp_cookies.dat", autosave => 1, ); use LWP; my $browser = LWP::UserAgent->new; $browser->cookie_jar($cookie_jar); Or for an empty and temporary cookie jar: use LWP; my $browser = LWP::UserAgent->new; $browser->cookie_jar( {} ); =head1 DESCRIPTION This class is for objects that represent a "cookie jar" -- that is, a database of all the HTTP cookies that a given LWP::UserAgent object knows about. Cookies are a general mechanism which server side connections can use to both store and retrieve information on the client side of the connection. For more information about cookies refer to L and L. This module also implements the new style cookies described in L. The two variants of cookies are supposed to be able to coexist happily. Instances of the class I are able to store a collection of Set-Cookie2: and Set-Cookie: headers and are able to use this information to initialize Cookie-headers in I objects. The state of a I object can be saved in and restored from files. =head1 LIMITATIONS This module does not support L<< Public Suffix|https://publicsuffix.org/ >> encouraged by a more recent standard, L<< RFC 6265|https://tools.ietf.org/html/rfc6265 >>. This module's shortcomings mean that a malicious Web site can set cookies to track your user agent across all sites under a top level domain. See F<< t/publicsuffix.t >> in this module's distribution for details. L<< HTTP::CookieJar::LWP >> supports Public Suffix, but only provides a limited subset of this module's functionality and L<< does not support|HTTP::CookieJar/LIMITATIONS-AND-CAVEATS >> standards older than I. =head1 METHODS The following methods are provided: =over 4 =item $cookie_jar = HTTP::Cookies->new The constructor takes hash style parameters. The following parameters are recognized: file: name of the file to restore cookies from and save cookies to autosave: save during destruction (bool) ignore_discard: save even cookies that are requested to be discarded (bool) hide_cookie2: do not add Cookie2 header to requests Future parameters might include (not yet implemented): max_cookies 300 max_cookies_per_domain 20 max_cookie_size 4096 no_cookies list of domain names that we never return cookies to =item $cookie_jar->get_cookies( $url_or_domain ) =item $cookie_jar->get_cookies( $url_or_domain, $cookie_key,... ) Returns a hash of the cookies that applies to the given URL. If a domainname is given as argument, then a prefix of "https://" is assumed. If one or more $cookie_key parameters are provided return the given values, or C if the cookie isn't available. =item $cookie_jar->add_cookie_header( $request ) The add_cookie_header() method will set the appropriate Cookie:-header for the I object given as argument. The $request must have a valid url attribute before this method is called. =item $cookie_jar->extract_cookies( $response ) The extract_cookies() method will look for Set-Cookie: and Set-Cookie2: headers in the I object passed as argument. Any of these headers that are found are used to update the state of the $cookie_jar. =item $cookie_jar->set_cookie( $version, $key, $val, $path, $domain, $port, $path_spec, $secure, $maxage, $discard, \%rest ) The set_cookie() method updates the state of the $cookie_jar. The $key, $val, $domain, $port and $path arguments are strings. The $path_spec, $secure, $discard arguments are boolean values. The $maxage value is a number indicating number of seconds that this cookie will live. A value of $maxage <= 0 will delete this cookie. The $version argument sets the version of the cookie; the default value is 0 ( original Netscape spec ). Setting $version to another value indicates the RFC to which the cookie conforms (e.g. version 1 for RFC 2109). %rest defines various other attributes like "Comment" and "CommentURL". =item $cookie_jar->save =item $cookie_jar->save( $file ) =item $cookie_jar->save( file => $file, ignore_discard => $ignore_discard ) This method file saves the state of the $cookie_jar to a file. The state can then be restored later using the load() method. If a filename is not specified we will use the name specified during construction. If the $ignore_discard value is true (or not specified, but attribute I was set at cookie jar construction), then we will even save cookies that are marked to be discarded. The default is to save a sequence of "Set-Cookie3" lines. "Set-Cookie3" is a proprietary LWP format, not known to be compatible with any browser. The I sub-class can be used to save in a format compatible with Netscape. =item $cookie_jar->load =item $cookie_jar->load( $file ) This method reads the cookies from the file and adds them to the $cookie_jar. The file must be in the format written by the save() method. =item $cookie_jar->revert This method empties the $cookie_jar and re-loads the $cookie_jar from the last save file. =item $cookie_jar->clear =item $cookie_jar->clear( $domain ) =item $cookie_jar->clear( $domain, $path ) =item $cookie_jar->clear( $domain, $path, $key ) Invoking this method without arguments will empty the whole $cookie_jar. If given a single argument only cookies belonging to that domain will be removed. If given two arguments, cookies belonging to the specified path within that domain are removed. If given three arguments, then the cookie with the specified key, path and domain is removed. =item $cookie_jar->clear_temporary_cookies Discard all temporary cookies. Scans for all cookies in the jar with either no expire field or a true C flag. To be called when the user agent shuts down according to RFC 2965. =item $cookie_jar->scan( \&callback ) The argument is a subroutine that will be invoked for each cookie stored in the $cookie_jar. The subroutine will be invoked with the following arguments: 0 version 1 key 2 val 3 path 4 domain 5 port 6 path_spec 7 secure 8 expires 9 discard 10 hash =item $cookie_jar->as_string =item $cookie_jar->as_string( $skip_discardables ) The as_string() method will return the state of the $cookie_jar represented as a sequence of "Set-Cookie3" header lines separated by "\n". If $skip_discardables is TRUE, it will not return lines for cookies with the I attribute. =back =head1 SEE ALSO L, L =head1 AUTHOR Gisle Aas =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2002 by Gisle Aas. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut __END__ #ABSTRACT: HTTP cookie jars HTTP-Cookies-6.10/lib/HTTP/Cookies/000755 000765 000024 00000000000 13774710302 020015 5ustar00olafaldersstaff000000 000000 HTTP-Cookies-6.10/lib/HTTP/Cookies/Netscape.pm000644 000765 000024 00000006513 13774710302 022122 0ustar00olafaldersstaff000000 000000 package HTTP::Cookies::Netscape; use strict; our $VERSION = '6.10'; require HTTP::Cookies; our @ISA=qw(HTTP::Cookies); sub load { my ($self, $file) = @_; $file ||= $self->{'file'} || return; local $/ = "\n"; # make sure we got standard record separator open (my $fh, '<', $file) || return; my $magic = <$fh>; chomp $magic; unless ($magic =~ /^#(?: Netscape)? HTTP Cookie File/) { warn "$file does not look like a netscape cookies file"; return; } my $now = time() - $HTTP::Cookies::EPOCH_OFFSET; while (my $line = <$fh>) { chomp($line); $line =~ s/\s*\#HttpOnly_//; next if $line =~ /^\s*\#/; next if $line =~ /^\s*$/; $line =~ tr/\n\r//d; my($domain,$bool1,$path,$secure, $expires,$key,$val) = split(/\t/, $line); $secure = ($secure eq "TRUE"); $self->set_cookie(undef, $key, $val, $path, $domain, undef, 0, $secure, $expires-$now, 0); } 1; } sub save { my $self = shift; my %args = ( file => $self->{'file'}, ignore_discard => $self->{'ignore_discard'}, @_ == 1 ? ( file => $_[0] ) : @_ ); Carp::croak('Unexpected argument to save method') if keys %args > 2; my $file = $args{'file'} || return; open(my $fh, '>', $file) || return; # Use old, now broken link to the old cookie spec just in case something # else (not us!) requires the comment block exactly this way. print {$fh} <scan(sub { my ($version, $key, $val, $path, $domain, $port, $path_spec, $secure, $expires, $discard, $rest) = @_; return if $discard && !$args{'ignore_discard'}; $expires = $expires ? $expires - $HTTP::Cookies::EPOCH_OFFSET : 0; return if $now > $expires; $secure = $secure ? "TRUE" : "FALSE"; my $bool = $domain =~ /^\./ ? "TRUE" : "FALSE"; print {$fh} join("\t", $domain, $bool, $path, $secure, $expires, $key, $val), "\n"; }); 1; } 1; =pod =encoding UTF-8 =head1 NAME HTTP::Cookies::Netscape - Access to Netscape cookies files =head1 VERSION version 6.10 =head1 SYNOPSIS use LWP; use HTTP::Cookies::Netscape; $cookie_jar = HTTP::Cookies::Netscape->new( file => "c:/program files/netscape/users/ZombieCharity/cookies.txt", ); my $browser = LWP::UserAgent->new; $browser->cookie_jar( $cookie_jar ); =head1 DESCRIPTION This is a subclass of C that reads (and optionally writes) Netscape/Mozilla cookie files. See the documentation for L. =head1 CAVEATS Please note that the Netscape/Mozilla cookie file format can't store all the information available in the Set-Cookie2 headers, so you will probably lose some information if you save in this format. At time of writing, this module seems to work fine with Mozilla Phoenix/Firebird. =head1 SEE ALSO L =head1 AUTHOR Gisle Aas =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2002 by Gisle Aas. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut __END__ #ABSTRACT: Access to Netscape cookies files HTTP-Cookies-6.10/lib/HTTP/Cookies/Microsoft.pm000644 000765 000024 00000021600 13774710302 022317 0ustar00olafaldersstaff000000 000000 package HTTP::Cookies::Microsoft; use strict; our $VERSION = '6.10'; require HTTP::Cookies; our @ISA=qw(HTTP::Cookies); sub load_cookies_from_file { my ($file) = @_; my @cookies; open (my $fh, '<', $file) || return; while (my $key = <$fh>) { chomp $key; my ($value, $domain_path, $flags, $lo_expire, $hi_expire); my ($lo_create, $hi_create, $sep); chomp($value = <$fh>); chomp($domain_path= <$fh>); chomp($flags = <$fh>); # 0x0001 bit is for secure chomp($lo_expire = <$fh>); chomp($hi_expire = <$fh>); chomp($lo_create = <$fh>); chomp($hi_create = <$fh>); chomp($sep = <$fh>); if (!defined($key) || !defined($value) || !defined($domain_path) || !defined($flags) || !defined($hi_expire) || !defined($lo_expire) || !defined($hi_create) || !defined($lo_create) || !defined($sep) || ($sep ne '*')) { last; } if ($domain_path =~ /^([^\/]+)(\/.*)$/) { my $domain = $1; my $path = $2; push @cookies, { KEY => $key, VALUE => $value, DOMAIN => $domain, PATH => $path, FLAGS =>$flags, HIXP =>$hi_expire, LOXP => $lo_expire, HICREATE => $hi_create, LOCREATE => $lo_create }; } } return \@cookies; } sub get_user_name { use Win32; use locale; my $user = lc(Win32::LoginName()); return $user; } # MSIE stores create and expire times as Win32 FILETIME, # which is 64 bits of 100 nanosecond intervals since Jan 01 1601 # # But Cookies code expects time in 32-bit value expressed # in seconds since Jan 01 1970 # sub epoch_time_offset_from_win32_filetime { my ($high, $low) = @_; #-------------------------------------------------------- # USEFUL CONSTANT #-------------------------------------------------------- # 0x019db1de 0xd53e8000 is 1970 Jan 01 00:00:00 in Win32 FILETIME # # 100 nanosecond intervals == 0.1 microsecond intervals my $filetime_low32_1970 = 0xd53e8000; my $filetime_high32_1970 = 0x019db1de; #------------------------------------ # ALGORITHM #------------------------------------ # To go from 100 nanosecond intervals to seconds since 00:00 Jan 01 1970: # # 1. Adjust 100 nanosecond intervals to Jan 01 1970 base # 2. Divide by 10 to get to microseconds (1/millionth second) # 3. Divide by 1000000 (10 ^ 6) to get to seconds # # We can combine Step 2 & 3 into one divide. # # After much trial and error, I came up with the following code which # avoids using Math::BigInt or floating pt, but still gives correct answers # If the filetime is before the epoch, return 0 if (($high < $filetime_high32_1970) || (($high == $filetime_high32_1970) && ($low < $filetime_low32_1970))) { return 0; } # Can't multiply by 0x100000000, (1 << 32), # without Perl issuing an integer overflow warning # # So use two multiplies by 0x10000 instead of one multiply by 0x100000000 # # The result is the same. # my $date1970 = (($filetime_high32_1970 * 0x10000) * 0x10000) + $filetime_low32_1970; my $time = (($high * 0x10000) * 0x10000) + $low; $time -= $date1970; $time /= 10000000; return $time; } sub load_cookie { my($self, $file) = @_; my $now = time() - $HTTP::Cookies::EPOCH_OFFSET; my $cookie_data; if (-f $file) { # open the cookie file and get the data $cookie_data = load_cookies_from_file($file); foreach my $cookie (@{$cookie_data}) { my $secure = ($cookie->{FLAGS} & 1) != 0; my $expires = epoch_time_offset_from_win32_filetime($cookie->{HIXP}, $cookie->{LOXP}); $self->set_cookie(undef, $cookie->{KEY}, $cookie->{VALUE}, $cookie->{PATH}, $cookie->{DOMAIN}, undef, 0, $secure, $expires-$now, 0); } } } sub load { my($self, $cookie_index) = @_; my $now = time() - $HTTP::Cookies::EPOCH_OFFSET; my $cookie_dir = ''; my $delay_load = (defined($self->{'delayload'}) && $self->{'delayload'}); my $user_name = get_user_name(); my $data; $cookie_index ||= $self->{'file'} || return; if ($cookie_index =~ /[\\\/][^\\\/]+$/) { $cookie_dir = $` . "\\"; } open (my $fh, '<:raw', $cookie_index) || return; if (256 != read($fh, $data, 256)) { warn "$cookie_index file is not large enough"; return; } # Cookies' index.dat file starts with 32 bytes of signature # followed by an offset to the first record, stored as a little-endian DWORD my ($sig, $size) = unpack('a32 V', $data); # check that sig is valid (only tested in IE6.0) if (($sig !~ /^Client UrlCache MMF Ver 5\.2/) || (0x4000 != $size)) { warn "$cookie_index ['$sig' $size] does not seem to contain cookies"; return; } # move the file ptr to start of the first record if (0 == seek($fh, $size, 0)) { return; } # Cookies are usually stored in 'URL ' records in two contiguous 0x80 byte sectors (256 bytes) # so read in two 0x80 byte sectors and adjust if not a Cookie. while (256 == read($fh, $data, 256)) { # each record starts with a 4-byte signature # and a count (little-endian DWORD) of 0x80 byte sectors for the record ($sig, $size) = unpack('a4 V', $data); # Cookies are found in 'URL ' records if ('URL ' ne $sig) { # skip over uninteresting record: I've seen 'HASH' and 'LEAK' records if (($sig eq 'HASH') || ($sig eq 'LEAK')) { # '-2' takes into account the two 0x80 byte sectors we've just read in if (($size > 0) && ($size != 2)) { if (0 == seek($fh, ($size-2)*0x80, 1)) { # Seek failed. Something's wrong. Gonna stop. last; } } } next; } #$REMOVE Need to check if URL records in Cookies' index.dat will # ever use more than two 0x80 byte sectors if ($size > 2) { my $more_data = ($size-2)*0x80; if ($more_data != read($fh, $data, $more_data, 256)) { last; } } (my $user_name2 = $user_name) =~ s/ /_/g; if ($data =~ /Cookie:\Q$user_name\E@([\x21-\xFF]+).*?((?:\Q$user_name\E|\Q$user_name2\E)@[\x21-\xFF]+\.txt)/) { my $cookie_file = $cookie_dir . $2; # form full pathname if (!$delay_load) { $self->load_cookie($cookie_file); } else { my $domain = $1; # grab only the domain name, drop everything from the first dir sep on if ($domain =~ m{[\\/]}) { $domain = $`; } # set the delayload cookie for this domain with # the cookie_file as cookie for later-loading info $self->set_cookie(undef, 'cookie', $cookie_file, '//+delayload', $domain, undef, 0, 0, $now+86_400, 0); } } } 1; } 1; =pod =encoding UTF-8 =head1 NAME HTTP::Cookies::Microsoft - Access to Microsoft cookies files =head1 VERSION version 6.10 =head1 SYNOPSIS use LWP; use HTTP::Cookies::Microsoft; use Win32::TieRegistry(Delimiter => "/"); my $cookies_dir = $Registry-> {"CUser/Software/Microsoft/Windows/CurrentVersion/Explorer/Shell Folders/Cookies"}; $cookie_jar = HTTP::Cookies::Microsoft->new( file => "$cookies_dir\\index.dat", 'delayload' => 1, ); my $browser = LWP::UserAgent->new; $browser->cookie_jar( $cookie_jar ); =head1 DESCRIPTION This is a subclass of C which loads Microsoft Internet Explorer 5.x and 6.x for Windows (MSIE) cookie files. See the documentation for L. =head1 METHODS The following methods are provided: =over 4 =item $cookie_jar = HTTP::Cookies::Microsoft->new; The constructor takes hash style parameters. In addition to the regular HTTP::Cookies parameters, HTTP::Cookies::Microsoft recognizes the following: delayload: delay loading of cookie data until a request is actually made. This results in faster runtime unless you use most of the cookies since only the domain's cookie data is loaded on demand. =back =head1 CAVEATS Please note that the code DOESN'T support saving to the MSIE cookie file format. =head1 AUTHOR Johnny Lee =head1 COPYRIGHT Copyright 2002 Johnny Lee This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 AUTHOR Gisle Aas =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2002 by Gisle Aas. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut __END__ #ABSTRACT: Access to Microsoft cookies files HTTP-Cookies-6.10/xt/author/000755 000765 000024 00000000000 13774710302 017031 5ustar00olafaldersstaff000000 000000 HTTP-Cookies-6.10/xt/release/000755 000765 000024 00000000000 13774710302 017147 5ustar00olafaldersstaff000000 000000 HTTP-Cookies-6.10/xt/release/cpan-changes.t000644 000765 000024 00000000344 13774710302 021664 0ustar00olafaldersstaff000000 000000 use strict; use warnings; # this test was generated with Dist::Zilla::Plugin::Test::CPAN::Changes 0.012 use Test::More 0.96 tests => 1; use Test::CPAN::Changes; subtest 'changes_ok' => sub { changes_file_ok('Changes'); }; HTTP-Cookies-6.10/xt/author/mojibake.t000644 000765 000024 00000000151 13774710302 020774 0ustar00olafaldersstaff000000 000000 #!perl use strict; use warnings qw(all); use Test::More; use Test::Mojibake; all_files_encoding_ok(); HTTP-Cookies-6.10/xt/author/test-version.t000644 000765 000024 00000000637 13774710302 021666 0ustar00olafaldersstaff000000 000000 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; HTTP-Cookies-6.10/xt/author/eol.t000644 000765 000024 00000001050 13774710302 017771 0ustar00olafaldersstaff000000 000000 use strict; use warnings; # this test was generated with Dist::Zilla::Plugin::Test::EOL 0.19 use Test::More 0.88; use Test::EOL; my @files = ( 'lib/HTTP/Cookies.pm', 'lib/HTTP/Cookies/Microsoft.pm', 'lib/HTTP/Cookies/Netscape.pm', 't/00-report-prereqs.dd', 't/00-report-prereqs.t', 't/10-original_spec.t', 't/11-rfc_2965.t', 't/cookies.t', 't/data/netscape-httponly.txt', 't/issue26.t', 't/issue32.t', 't/publicsuffix.t' ); eol_unix_ok($_, { trailing_whitespace => 1 }) foreach @files; done_testing; HTTP-Cookies-6.10/xt/author/pod-syntax.t000644 000765 000024 00000000252 13774710302 021323 0ustar00olafaldersstaff000000 000000 #!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(); HTTP-Cookies-6.10/xt/author/portability.t000644 000765 000024 00000000267 13774710302 021565 0ustar00olafaldersstaff000000 000000 use strict; use warnings; use Test::More; eval 'use Test::Portability::Files'; plan skip_all => 'Test::Portability::Files required for testing portability' if $@; run_tests(); HTTP-Cookies-6.10/xt/author/pod-coverage.t000644 000765 000024 00000002154 13774710302 021573 0ustar00olafaldersstaff000000 000000 #!perl # This file was automatically generated by Dist::Zilla::Plugin::Test::Pod::Coverage::Configurable 0.07. use Test::Pod::Coverage 1.08; use Test::More 0.88; BEGIN { if ( $] <= 5.008008 ) { plan skip_all => 'These tests require Pod::Coverage::TrustPod, which only works with Perl 5.8.9+'; } } use Pod::Coverage::TrustPod; my %skip = map { $_ => 1 } qw( HTTP::Cookies::Microsoft ); my @modules; for my $module ( all_modules() ) { next if $skip{$module}; push @modules, $module; } plan skip_all => 'All the modules we found were excluded from POD coverage test.' unless @modules; plan tests => scalar @modules; my %trustme = ( 'HTTP::Cookies' => [ qr/set_cookie_ok/ ] ); my @also_private; for my $module ( sort @modules ) { pod_coverage_ok( $module, { coverage_class => 'Pod::Coverage::TrustPod', also_private => \@also_private, trustme => $trustme{$module} || [], }, "pod coverage for $module" ); } done_testing(); HTTP-Cookies-6.10/t/issue26.t000644 000765 000024 00000001026 13774710302 017023 0ustar00olafaldersstaff000000 000000 use strict; use Test::More; use HTTP::Cookies; use HTTP::Response; use HTTP::Request; my $CRLF="\015\012"; my $cookie_jar = HTTP::Cookies->new(); my $request = HTTP::Request->new(GET => 'http://www.en.com/'); my $response = HTTP::Response->parse ("HTTP/1.1 302 Moved" . $CRLF . "Set-Cookie: expires=10101$CRLF$CRLF"); $response->request($request); $cookie_jar->extract_cookies($response); is $cookie_jar->as_string(), 'Set-Cookie3: expires=10101; path="/"; domain=www.en.com; discard; version=0' . "\n"; done_testing; HTTP-Cookies-6.10/t/issue32.t000644 000765 000024 00000001665 13774710302 017031 0ustar00olafaldersstaff000000 000000 use strict; use warnings; use Test::More; use HTTP::Cookies; use HTTP::Request; use HTTP::Response; my $nextyear = 1901+(gmtime())[5]; my $req = HTTP::Request->new(GET => "http://example.com"); my $resp = HTTP::Response->new(200, 'OK', ['Set-Cookie', q!a="b;c;\\"d"; expires=Fri, 06-Nov-! . $nextyear . " 08:58:34 GMT; domain=example.com; path=/"]); $resp->request($req); my $c = HTTP::Cookies->new; $c->extract_cookies($resp); is $c->as_string, 'Set-Cookie3: a="b;c;\"d"; path="/"; domain=example.com; path_spec; expires="' . $nextyear . '-11-06 08:58:34Z"; version=0' . "\n"; # test the implementation of the split function in isolation. # should probably name the function better too. my $simple = 'b;c;d'; is_deeply HTTP::Cookies::_split_text($simple), [qw/b c d/], "Parse $simple"; my $complex = '"b;c;\\"d";blah=32;foo="/"'; is_deeply HTTP::Cookies::_split_text($complex), ['b;c;"d','blah=32','foo=/'], "Parse $complex"; done_testing; HTTP-Cookies-6.10/t/00-report-prereqs.t000644 000765 000024 00000013452 13774710302 020740 0ustar00olafaldersstaff000000 000000 #!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: HTTP-Cookies-6.10/t/cookies.t000644 000765 000024 00000061163 13774710302 017167 0ustar00olafaldersstaff000000 000000 #!perl -w use Test; plan tests => 81; use HTTP::Cookies; use HTTP::Request; use 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::Cookies->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"); #print $res->as_string; $c->extract_cookies($res); $req = HTTP::Request->new(GET => "http://www.acme.com/"); $c->add_cookie_header($req); ok($req->header("Cookie"), "CUSTOMER=WILE_E_COYOTE"); ok($req->header("Cookie2"), "\$Version=\"1\""); $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;/); print $c->as_string; # 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::Cookies->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); ok($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/); print $c->as_string; undef($c); #------------------------------------------------------------------- # When there are no "Set-Cookie" header, then even responses # without any request URLs connected should be allowed. $c = HTTP::Cookies->new; $c->extract_cookies(HTTP::Response->new("200", "OK")); ok(count_cookies($c), 0); #------------------------------------------------------------------- # Then we test with the examples from RFC 2965. # # 5. EXAMPLES $c = HTTP::Cookies->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"; Version="1"; 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"; Version="1"; Path="/acme"'); ok($cookie =~ m(^\$Version="?1"?; Customer="?WILE_E_COYOTE"?; \$Path="/acme"$)); # # 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"; Version="1"; Path="/acme"'); ok($cookie =~ /^\$Version="?1"?;/); ok($cookie =~ /Part_Number="?Rocket_Launcher_0001"?;\s*\$Path="\/acme"/); ok($cookie =~ /Customer="?WILE_E_COYOTE"?;\s*\$Path="\/acme"/); # # 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"); print "FINAL COOKIE: $cookie\n"; ok($cookie =~ /Shipping="?FedEx"?;\s*\$Path="\/acme"/); ok($cookie =~ /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. print $c->as_string; # 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::Cookies->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"; Version="1"; Path="/acme"', 'Part_Number="Riding_Rocket_0023"; Version="1"; 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/..."); ok($cookie =~ /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/); print $c->as_string; #----------------------------------------------------------------------- # Test rejection of Set-Cookie2 responses based on domain, path or port $c = HTTP::Cookies->new; # illegal domain (no embedded dots) $cookie = interact($c, "http://www.acme.com", 'foo=bar; domain=".com"'); ok(count_cookies($c), 0); # legal domain $cookie = interact($c, "http://www.acme.com", 'foo=bar; domain="acme.com"'); ok(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"'); ok(count_cookies($c), 1); # legal domain $cookie = interact($c, "http://www.a.acme.com", 'foo=bar; domain=".a.acme.com"'); ok(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"'); ok(count_cookies($c), 2); # illegal path (must be prefix of request path) $cookie = interact($c, "http://www.sol.no", 'foo=bar; domain=".sol.no"; path="/foo"'); ok(count_cookies($c), 2); # legal path $cookie = interact($c, "http://www.sol.no/foo/bar", 'foo=bar; domain=".sol.no"; path="/foo"'); ok(count_cookies($c), 3); # illegal port (request-port not in list) $cookie = interact($c, "http://www.sol.no", 'foo=bar; domain=".sol.no"; port="90,100"'); ok(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! (\"|\\\\) "'); ok(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;'); ok(count_cookies($c), 5); # encoded path $cookie = interact($c, "http://www.sol.no/foo/", 'foo8=bar; path="/%66oo"'); ok(count_cookies($c), 6); my $file = "lwp-cookies-$$.txt"; $c->save($file); $old = $c->as_string; undef($c); $c = HTTP::Cookies->new; $c->load($file); unlink($file) || warn "Can't unlink $file: $!"; ok($old, $c->as_string); undef($c); # # Try some URL encodings of the PATHs # $c = HTTP::Cookies->new; interact($c, "http://www.acme.com/foo%2f%25/%40%40%0Anew%E5/%E5", 'foo = bar; version = 1'); print $c->as_string; $cookie = interact($c, "http://www.acme.com/foo%2f%25/@@%0anewå/æøå", "bar=baz; path=\"/foo/\"; version=1"); ok($cookie =~ /foo=bar/); ok($cookie =~ /^\$version=\"?1\"?/i); $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::Cookies::Netscape->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::Cookies::Netscape->new(file => $file); ok(count_cookies($c), 1); # 2 of them discarded on save ok($c->as_string =~ /foo1=bar/); undef($c); unlink($file); # Expect a HttpOnly cookie to be loaded, rather than treated as a comment $c = HTTP::Cookies::Netscape->new(file => 't/data/netscape-httponly.txt'); ok(count_cookies($c), 4); undef($c); # # Some additional Netscape cookies test # $c = HTTP::Cookies->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); print $c->as_string; require URI; $req = HTTP::Request->new(POST => URI->new("http://foo.bar.acme.com/foo")); $c->add_cookie_header($req); #print $req->as_string; ok($req->header("Cookie") =~ /PART_NUMBER=3,4/); ok($req->header("Cookie") =~ /Customer=WILE_E_COYOTE/); # Test handling of local intranet hostnames without a dot $c->clear; print "---\n"; interact($c, "http://example/", "foo1=bar; PORT; Discard;"); $_=interact($c, "http://example/", 'foo2=bar; domain=".local"'); ok(/foo1=bar/); $_=interact($c, "http://example/", 'foo3=bar'); $_=interact($c, "http://example/"); print "Cookie: $_\n"; ok(/foo2=bar/); ok(count_cookies($c), 3); print $c->as_string; # 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) print "---\n"; print "Test for empty path...\n"; $c = HTTP::Cookies->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="); print $res->as_string; $c->extract_cookies($res); #print $c->as_string; $req = HTTP::Request->new(GET => "http://www.ants.com/"); $c->add_cookie_header($req); #print $req->as_string; ok($req->header("Cookie"), "JSESSIONID=ABCDERANDOM123"); ok($req->header("Cookie2"), "\$Version=\"1\""); # missing path in the request URI $req = HTTP::Request->new(GET => URI->new("http://www.ants.com:8080")); $c->add_cookie_header($req); #print $req->as_string; ok($req->header("Cookie"), "JSESSIONID=ABCDERANDOM123"); ok($req->header("Cookie2"), "\$Version=\"1\""); # 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: ; 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")); #print $res->as_string; $c = HTTP::Cookies->new; # clear it $c->extract_cookies($res); print $c->as_string; ok($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 #------------------------------------------------------------------- # 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::Cookies->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"}++ } ); ok($counter{"perm_after"}, $counter{"perm_before"}); # a permanent cookie got lost accidently ok($counter{"session_after"}, 0); # a session cookie hasn't been cleared ok($counter{"session_before"}, 3); # we didn't have session cookies in the first place #print $c->as_string; # Test handling of 'secure ' attribute for classic cookies $c = HTTP::Cookies->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=/"); #print $res->as_string; $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); ok($req->header("Cookie"), "CUSTOMER=WILE_E_COYOTE"); #print $req->as_string; #print $c->as_string; $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' $c = HTTP::Cookies->new; $req = HTTP::Request->new("GET" => "http://example.com"); $res = HTTP::Response->new(200, "OK"); $res->request($req); $res->header("Set-Cookie" => "Expires=10101"); $c->extract_cookies($res); #print $c->as_string; ok($c->as_string, <<'EOT'); Set-Cookie3: Expires=10101; path="/"; domain=example.com; discard; version=0 EOT # Test empty cookie header [RT#29401] $c = HTTP::Cookies->new; $res->header("Set-Cookie" => ["CUSTOMER=WILE_E_COYOTE; path=/;", ""]); #print $res->as_string; $c->extract_cookies($res); #print $c->as_string; ok($c->as_string, <<'EOT'); Set-Cookie3: CUSTOMER=WILE_E_COYOTE; path="/"; domain=example.com; path_spec; discard; version=0 EOT # Test empty cookie part [RT#38480] $c = HTTP::Cookies->new; $res->header("Set-Cookie" => "CUSTOMER=WILE_E_COYOTE;;path=/;"); #print $res->as_string; $c->extract_cookies($res); #print $c->as_string; ok($c->as_string, <<'EOT'); Set-Cookie3: CUSTOMER=WILE_E_COYOTE; path="/"; domain=example.com; path_spec; discard; version=0 EOT # Test Set-Cookie with version set $c = HTTP::Cookies->new; $res->header("Set-Cookie" => "foo=\"bar\";version=1"); #print $res->as_string; $c->extract_cookies($res); #print $c->as_string; $req = HTTP::Request->new(GET => "http://www.example.com/foo"); $c->add_cookie_header($req); #print $req->as_string; ok($req->header("Cookie"), "foo=bar"); # Test cookies that expire far into the future [RT#50147] $c = HTTP::Cookies->new; $res->header("Set-Cookie", "PREF=ID=cee18f7c4e977184:TM=1254583090:LM=1254583090:S=Pdb0-hy9PxrNj4LL; expires=Mon, 03-Oct-2211 15:18:10 GMT; path=/; domain=.example.com"); $res->push_header("Set-Cookie", "expired1=1; expires=Mon, 03-Oct-2001 15:18:10 GMT; path=/; domain=.example.com"); $res->push_header("Set-Cookie", "expired2=1; expires=Fri Jan 1 00:00:00 GMT 1970; path=/; domain=.example.com"); $res->push_header("Set-Cookie", "expired3=1; expires=Fri Jan 1 00:00:01 GMT 1970; path=/; domain=.example.com"); $res->push_header("Set-Cookie", "expired4=1; expires=Thu Dec 31 23:59:59 GMT 1969; path=/; domain=.example.com"); $res->push_header("Set-Cookie", "expired5=1; expires=Fri Feb 2 00:00:00 GMT 1950; path=/; domain=.example.com"); $c->extract_cookies($res); #print $res->as_string; #print "---\n"; #print $c->as_string; $req = HTTP::Request->new(GET => "http://www.example.com/foo"); $c->add_cookie_header($req); #print $req->as_string; ok($req->header("Cookie"), "PREF=ID=cee18f7c4e977184:TM=1254583090:LM=1254583090:S=Pdb0-hy9PxrNj4LL"); $c->clear_temporary_cookies; $req = HTTP::Request->new(GET => "http://www.example.com/foo"); $c->add_cookie_header($req); #print $req->as_string; ok($req->header("Cookie"), "PREF=ID=cee18f7c4e977184:TM=1254583090:LM=1254583090:S=Pdb0-hy9PxrNj4LL"); # Test merging of cookies $c = HTTP::Cookies->new; $res->header("Set-Cookie", "foo=1; path=/"); $c->extract_cookies($res); $req = HTTP::Request->new(GET => "http://www.example.com/foo"); $req->header("Cookie", "x=bcd"); $c->add_cookie_header($req); ok($req->header("Cookie"), "x=bcd; foo=1"); $c->add_cookie_header($req); ok($req->header("Cookie"), "x=bcd; foo=1; foo=1"); #print $req->as_string; # Test get_cookies $c = HTTP::Cookies->new; $res->header("Set-Cookie", "foo=42"); $c->extract_cookies($res); ok($c->get_cookies("example.com")->{foo}, 42); ok($c->get_cookies("example.com", "foo"), 42); ok($c->get_cookies("example.com", "bar"), undef); ok($c->get_cookies("http://example.com", "foo"), 42); ok($c->get_cookies("https://example.com", "foo"), 42); ok($c->get_cookies(URI->new("https://example.com"), "foo"), 42); ok($c->get_cookies("foo.example.com", "foo"), 42); ok($c->get_cookies("example.org", "foo"), undef); my @a = $c->get_cookies("example.com", "bar", "foo"); ok(@a, 2); ok($a[0], undef); ok($a[1], 42); # Test ignore_discard argument of save() $c = HTTP::Cookies->new( ignore_discard => 0 ); interact($c, 'http://example.com/', 'foo=bar; Discard;'); $old = $c->as_string; $c->save( file => $file, ignore_discard => 1 ); undef $c; $c = HTTP::Cookies->new( ignore_discard => 0 ); $c->load($file); unlink($file) || warn "Can't unlink $file: $!"; ok($c->as_string, $old); $c = HTTP::Cookies::Netscape->new( ignore_discard => 0 ); $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" => "foo=bar; path=/; discard; expires=Wednesday, 09-Nov-$year_plus_one 23:12:40 GMT"); $c->extract_cookies($res); $old = $c->as_string; $c->save( file => $file, ignore_discard => 1 ); undef $c; $c = HTTP::Cookies::Netscape->new( ignore_discard => 0 ); $c->load($file); $req = HTTP::Request->new(GET => "http://www.acme.com/foo/bar"); $c->add_cookie_header($req); $h = $req->header("Cookie"); ok($h =~ /foo=bar/); unlink($file) || warn "Can't unlink $file: $!"; # Test discard isn't set when max-age is set $c = HTTP::Cookies->new; $req = HTTP::Request->new("GET" => "http://example.com"); $res = HTTP::Response->new(200, "OK"); $res->request($req); $res->header("Set-Cookie" => "foo=bar; max-age=1337"); $c->extract_cookies($res); #print $c->as_string; ok($c->as_string, <<'EOT'); Set-Cookie3: foo=bar; path="/"; domain=example.com; version=0 EOT #------------------------------------------------------------------- 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-Cookie2" => $_) } $c->extract_cookies($res); return $cookie; } sub count_cookies { my $c = shift; my $no = 0; $c->scan(sub { $no++ }); $no; } HTTP-Cookies-6.10/t/10-original_spec.t000644 000765 000024 00000014074 13774710302 020566 0ustar00olafaldersstaff000000 000000 #!perl use strict; use warnings; use Test::More; use HTTP::Cookies (); use HTTP::Date (); use HTTP::Request (); use HTTP::Response (); use URI (); my $expiry_string = HTTP::Date::time2str( time + 86_400 ); my $jar = HTTP::Cookies->new(); plan tests => 20; # https://curl.haxx.se/rfc/cookie_spec.html # First Example transaction sequence: { my $res = HTTP::Response->new( 200, 'OK' ); my $req = request_for('www.acme.com'); $res->request($req); # 1.1 # 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 $res->header("Set-Cookie" => "CUSTOMER=WILE_E_COYOTE; path=/ ; expires=${expiry_string}"); $jar->extract_cookies($res); is(count_cookies_for('www.acme.com'), 1, '1.1: res: found the cookie'); # 1.2 # 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=/ $req = request_for('www.acme.com'); $jar->add_cookie_header($req); is($req->header("Cookie"), "CUSTOMER=WILE_E_COYOTE", '1.2: req: customer'); is($req->header("Cookie2"), q{$Version="1"}, '1.2: req: version'); $res->request($req); $res->header("Set-Cookie" => "PART_NUMBER=ROCKET_LAUNCHER_0001; path=/"); $jar->extract_cookies($res); is(count_cookies_for('www.acme.com'), 2, '1.2: res: two cookies found'); # 1.3 # 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=/foo $req = request_for('www.acme.com'); $jar->add_cookie_header($req); my $h = $req->header("Cookie"); # checking header contents is easier like($h, qr/PART_NUMBER=ROCKET_LAUNCHER_0001/, '1.3: req: first cookie found'); like($h, qr/CUSTOMER=WILE_E_COYOTE/, '1.3: req: second cookie found'); $res->request($req); $res->header("Set-Cookie" => "SHIPPING=FEDEX; path=/foo"); $jar->extract_cookies($res); is(count_cookies_for('www.acme.com'), 3, '1.3: res: three cookies found'); # 1.4 # When client requests a URL in path "/" on this server, it sends: # Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001 $req = request_for('www.acme.com'); $jar->add_cookie_header($req); $h = $req->header("Cookie"); # checking header contents is easier like($h, qr/PART_NUMBER=ROCKET_LAUNCHER_0001/, '1.4: req: first cookie found'); like($h, qr/CUSTOMER=WILE_E_COYOTE/, '1.4: req: second cookie found'); unlike($h, qr/SHIPPING=FEDEX/, '1.4: req: no shipping cookie'); $res->request($req); $res->header("Set-Cookie" => "CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001"); $jar->extract_cookies($res); is(count_cookies_for('www.acme.com'), 3, '1.4: res: three cookies found'); # 1.5 # 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. $req = request_for('www.acme.com/foo'); $jar->add_cookie_header($req); $h = $req->header("Cookie"); # checking header contents is easier like($h, qr/PART_NUMBER=ROCKET_LAUNCHER_0001/, '1.5: req: first cookie found'); like($h, qr/CUSTOMER=WILE_E_COYOTE/, '1.5: req: second cookie found'); like($h, qr/SHIPPING=FEDEX/, '1.5: req: third cookie found'); $res->request($req); $res->header("Set-Cookie" => "CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001"); $jar->extract_cookies($res); is(count_cookies_for('www.acme.com'), 3, '1.5: res: three cookies found'); } # Second Example transaction sequence: # Assume all mappings from above have been cleared. { $jar->clear(); my $res = HTTP::Response->new( 200, 'OK' ); my $req = request_for('www.acme.com'); $res->request($req); # 2.1 # 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 $res->header("Set-Cookie" => "PART_NUMBER=ROCKET_LAUNCHER_0001; path=/"); $jar->extract_cookies($res); $req = request_for('www.acme.com'); $jar->add_cookie_header($req); is($req->header("Cookie"), "PART_NUMBER=ROCKET_LAUNCHER_0001", '2.1: req: cookie found'); $res->request($req); $res->header("Set-Cookie" => "PART_NUMBER=ROCKET_LAUNCHER_0001; path=/"); $jar->extract_cookies($res); is(count_cookies_for('www.acme.com'), 1, '2.1: res: one cookie found'); # 2.2 # 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. $res->header("Set-Cookie", "PART_NUMBER=RIDING_ROCKET_0023; path=/ammo"); $jar->extract_cookies($res); $req = request_for('www.acme.com/ammo'); $jar->add_cookie_header($req); my $h = $req->header("Cookie"); # checking header contents is easier like($h, qr/PART_NUMBER=ROCKET_LAUNCHER_0001/, '2.2: req: first cookie found'); like($h, qr/PART_NUMBER=RIDING_ROCKET_0023/, '2.2: req: second cookie found'); $res->request($req); $jar->extract_cookies($res); is(count_cookies_for('www.acme.com'), 2, '2.2: res: three cookies found'); } sub count_cookies_for { my $host = shift; my $count = 0; $jar->scan( sub { $_[4] eq $host && $count++ }); return $count; } sub request_for { my $uri = URI->new('http://'.shift)->canonical; my $req = HTTP::Request->new( GET => $uri); $req->header( Host => $uri->host_port ); return $req; } HTTP-Cookies-6.10/t/00-report-prereqs.dd000644 000765 000024 00000004167 13774710302 021067 0ustar00olafaldersstaff000000 000000 do { my $x = { 'configure' => { 'requires' => { 'ExtUtils::MakeMaker' => '0' } }, 'develop' => { 'requires' => { 'Pod::Coverage::TrustPod' => '0', 'Test::CPAN::Changes' => '0.19', 'Test::EOL' => '0', 'Test::Mojibake' => '0', 'Test::More' => '0.96', 'Test::Pod' => '1.41', 'Test::Pod::Coverage' => '1.08', 'Test::Portability::Files' => '0', 'Test::Version' => '1', 'warnings' => '0' } }, 'runtime' => { 'requires' => { 'Carp' => '0', 'HTTP::Date' => '6', 'HTTP::Headers::Util' => '6', 'HTTP::Request' => '0', 'locale' => '0', 'perl' => '5.008001', 'strict' => '0' } }, 'test' => { 'recommends' => { 'CPAN::Meta' => '2.120900' }, 'requires' => { 'ExtUtils::MakeMaker' => '0', 'File::Spec' => '0', 'HTTP::Response' => '0', 'Test' => '0', 'Test::More' => '0', 'URI' => '0', 'warnings' => '0' } } }; $x; }HTTP-Cookies-6.10/t/data/000755 000765 000024 00000000000 13774710302 016250 5ustar00olafaldersstaff000000 000000 HTTP-Cookies-6.10/t/publicsuffix.t000644 000765 000024 00000003536 13774710302 020236 0ustar00olafaldersstaff000000 000000 #!perl use strict; use warnings; use Test::More; use HTTP::Cookies (); use HTTP::Date (); use HTTP::Request (); use HTTP::Response (); my $expiry_string = HTTP::Date::time2str( time + 86_400 ); my $jar = HTTP::Cookies->new; { local $TODO = 'Unexpected cookies stored'; my $res = HTTP::Response->new( 200, 'OK' ); my $req = request_for('www.exceptone.co.uk'); $res->header( 'Set-Cookie' => "security=fail; Domain=.co.uk; Expires=${expiry_string}" ); $res->request($req); $jar->extract_cookies($res); is count_cookies_for('.co.uk'), 0, 'No .co.uk cookies stored in the jar'; } { local $TODO = 'Unexpected cookies stored'; my $req = request_for('www.google.co.uk'); $jar->add_cookie_header($req); is $req->header('Cookie'), undef, 'No cookies sent to www.google.co.uk'; } { my $req = request_for('www.google.com'); $jar->add_cookie_header($req); is $req->header('Cookie'), undef, 'No cookies sent to www.google.com'; } { local $TODO = 'Unexpected cookies stored'; my $res = HTTP::Response->new( 200, 'OK' ); my $req = request_for('www.example.com'); $res->header( 'Set-Cookie' => "dotcom=pwned; Domain=.com; Expires=${expiry_string}" ); $res->request($req); $jar->extract_cookies($res); is count_cookies_for('.com'), 0, 'No .com cookies stored in the jar'; } { local $TODO = 'Unexpected cookies stored'; my $req = request_for('www.google.com'); $jar->add_cookie_header($req); is $req->header('Cookie'), undef, 'No cookies sent to www.google.com'; } sub count_cookies_for { my $host = shift; my $count = 0; $jar->scan( sub { $_[4] eq $host && $count++ }); return $count; } sub request_for { my $host = shift; my $req = HTTP::Request->new( GET => "http://${host}/"); $req->header( Host => $host ); return $req; } done_testing(); HTTP-Cookies-6.10/t/11-rfc_2965.t000644 000765 000024 00000012644 13774710302 017211 0ustar00olafaldersstaff000000 000000 #!perl use strict; use warnings; use Test::More; use HTTP::Cookies (); use HTTP::Request (); use HTTP::Response (); use URI (); my $jar = HTTP::Cookies->new(); plan tests => 13; # https://www.rfc-editor.org/rfc/rfc2965.txt # Section 4 # Example 1 { # 1-2 # 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. my $res = HTTP::Response->new( 200, 'OK' ); $res->header('Set-Cookie2' => q{Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"}); my $req = request_for('www.acme.com/acme/login', 'POST'); # we can skip the form data as it's not necessary here $res->request($req); $jar->extract_cookies($res); is(count_cookies_for('www.acme.com'), 1, '1.1-2: res: found the cookie'); # 3-4 # 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. $req = request_for('www.acme.com/acme/pickitem', 'POST'); $jar->add_cookie_header($req); my $h = $req->header("Cookie"); # checking header contents is easier like($h, qr/Customer="?WILE_E_COYOTE"?/, '1.3-4: req: contains header'); $res->header('Set-Cookie2' => q{Part_Number="Rocket_Launcher_0001"; Version="1"; Path="/acme"}); $res->request($req); $jar->extract_cookies($res); is(count_cookies_for('www.acme.com'), 2, '1.3-4: res: found the cookies'); # 5-6 # 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. $req = request_for('www.acme.com/acme/shipping', 'POST'); $jar->add_cookie_header($req); $h = $req->header("Cookie"); # checking header contents is easier like($h, qr/Customer="?WILE_E_COYOTE"?/, '1.5-6: req: contains cust'); like($h, qr/Part_Number="?Rocket_Launcher_0001"?/, '1.5-6: req: contains part'); $res->header('Set-Cookie2' => q{Shipping="FedEx"; Version="1"; Path="/acme"}); $res->request($req); $jar->extract_cookies($res); is(count_cookies_for('www.acme.com'), 3, '1.5-6: res: found the cookies'); # 7-8 # 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. $req = request_for('www.acme.com/acme/process', 'POST'); $jar->add_cookie_header($req); $h = $req->header("Cookie"); # checking header contents is easier like($h, qr/Customer="?WILE_E_COYOTE"?/, '1.7-8: req: contains cust'); like($h, qr/Part_Number="?Rocket_Launcher_0001"?/, '1.7-8: req: contains part'); like($h, qr/Shipping="?FedEx"?/, '1.7-8: req: contains shipping'); $res = HTTP::Response->new( 200, 'OK' ); $res->request($req); $jar->extract_cookies($res); is(count_cookies_for('www.acme.com'), 3, '1.7-8: res: found the cookies'); } # 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. { $jar->clear(); my $res = HTTP::Response->new( 200, 'OK' ); # requests to /acme get rocket launcher $res->push_header('Set-Cookie2' => q{Part_Number="Rocket_Launcher_0001"; Version="1"; Path="/acme"}); # requests to /acme/ammo will get rocket launcher and rocket $res->push_header('Set-Cookie2' => q{Part_Number="Riding_Rocket_0023"; Version="1"; Path="/acme/ammo"}); # requests to /acme/anything_else will just get rocket launcher my $req = request_for('www.acme.com/acme/', 'POST'); $res->request($req); $jar->extract_cookies($res); is(count_cookies_for('www.acme.com'), 1, '2: acme: res: one cookie'); $jar->clear(); $req = request_for('www.acme.com/acme/ammo', 'POST'); $res->request($req); $jar->extract_cookies($res); is(count_cookies_for('www.acme.com'), 2, '2: acme/ammo: res: two cookies'); $jar->clear(); $req = request_for('www.acme.com/acme/parts', 'POST'); $res->request($req); $jar->extract_cookies($res); is(count_cookies_for('www.acme.com'), 1, '2: acme/parts: res: one cookie'); } sub count_cookies_for { my $host = shift; my $count = 0; $jar->scan(sub { $_[4] eq $host && $count++ }); return $count; } sub request_for { my $uri = URI->new('http://'.shift); my $method = shift || 'GET'; my $req = HTTP::Request->new($method => $uri); $req->header(Host => $uri->host_port); return $req; } HTTP-Cookies-6.10/t/data/netscape-httponly.txt000644 000765 000024 00000001166 13774710302 022476 0ustar00olafaldersstaff000000 000000 # Netscape HTTP Cookie File # http://www.netscape.com/newsref/std/cookie_spec.html # This is a generated file! Do not edit. # Should be loaded as normal www.acme.com FALSE / FALSE 2147483647 foo1 bar # Should be loaded with hostname www.acme.com #HttpOnly_www.acme.com FALSE / FALSE 2147483647 foo2 bar #HttpOnly_www.acme.com FALSE / FALSE 2147483647 foo3 bar #HttpOnly_www.acme.com FALSE / FALSE 2147483647 foo4 bar # Should not be loaded (double prefix) #HttpOnly_#HttpOnly_www.acme.com FALSE / FALSE 2147483647 foo5 bar # Should not be loaded (case-sensitivity) #Httponly_www.acme.com FALSE / FALSE 2147483647 foo6 bar