CGI-Application-Plugin-Session-1.05/0000775000175000017500000000000012255350127015653 5ustar frewfrewCGI-Application-Plugin-Session-1.05/dist.ini0000644000175000017500000000051412255350127017315 0ustar frewfrewname = CGI-Application-Plugin-Session author = Cees Hek license = Perl_5 copyright_holder = Cees Hek version = 1.05 [NextRelease] [@Git] [@Basic] [GithubMeta] [MetaJSON] [PodWeaver] [PkgVersion] [ReadmeFromPod] [PodSyntaxTests] [PodCoverageTests] [Prereqs::FromCPANfile] CGI-Application-Plugin-Session-1.05/Makefile.PL0000644000175000017500000000227712255350127017633 0ustar frewfrew use strict; use warnings; use ExtUtils::MakeMaker 6.30; my %WriteMakefileArgs = ( "ABSTRACT" => "Plugin that adds session support to CGI::Application", "AUTHOR" => "Cees Hek ", "BUILD_REQUIRES" => {}, "CONFIGURE_REQUIRES" => { "ExtUtils::MakeMaker" => "6.30" }, "DISTNAME" => "CGI-Application-Plugin-Session", "EXE_FILES" => [], "LICENSE" => "perl", "NAME" => "CGI::Application::Plugin::Session", "PREREQ_PM" => { "CGI::Application" => "3.21", "CGI::Session" => "4.48", "File::Spec" => 0, "Scalar::Util" => 0 }, "TEST_REQUIRES" => { "Test::More" => "1.001002" }, "VERSION" => "1.05", "test" => { "TESTS" => "t/*.t" } ); my %FallbackPrereqs = ( "CGI::Application" => "3.21", "CGI::Session" => "4.48", "File::Spec" => 0, "Scalar::Util" => 0, "Test::More" => "1.001002" ); unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) { delete $WriteMakefileArgs{TEST_REQUIRES}; delete $WriteMakefileArgs{BUILD_REQUIRES}; $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs; } delete $WriteMakefileArgs{CONFIGURE_REQUIRES} unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; WriteMakefile(%WriteMakefileArgs); CGI-Application-Plugin-Session-1.05/Changes0000644000175000017500000001050412255350127017144 0ustar frewfrewRevision history for Perl extension CGI::Application::Plugin::Session. 1.05 2013-12-21 11:31:00 America/Chicago - Stop depending on ->DESTROY to call ->flush (reported by Gareth Tunley) 1.04 2013-11-14 10:48:29 America/Chicago - Fix hash randomization bug tickled by perl 5.18 (Arthur Axel 'fREW' Schmidt) - Delete some dead code (RT#46587, Nate Smith) - Use instance name instead of global CGI::Session->name (Lee Carmichael) 1.03 - Add session_recreate method (suggested by Robert Bauck Hamar) - Add session_loaded method (Sven Neuhaus) 1.02 Tue May 23 12:03:19 EDT 2006 - When calling session_delete, make sure that the session is created first, in case the user hasn't called $self->session (Yuji Maeda) - When session_delete is called, make sure that we remove any session cookies that may be in the outgoing headers before adding in the session timeout cookie. 1.01 Fri Mar 3 21:03:45 EDT 2006 - Fix bug when using CGI::Fast (reported by Yuji Maeda) - Clarify the SEND_COOKIE docs to mention that a cookie is only set if the session object is created during the request (Mark Stosberg) 1.00 Sun Feb 5 16:44:33 EDT 2006 Bug fixes: - Test return value from CGI::Session to make sure the session object was created properly. (perlmonkey -at- gmail.com) 0.09 Sun Sep 11 21:22:06 EDT 2005 - Added session_delete() method to send expired cookie to client (Jason Purdy) 0.08 Wed Jul 6 12:06:04 EDT 2005 - Simplify the pod tests according to Test::Pod docs - Allow -expires attribute for the cookie header to be blank so that an expiry date is not put on the session automatically (Curtis Hawthorne) 0.07 Sat Jun 11 13:24:38 EDT 2005 - New config option DEFAULT_EXPIRY which will automatically call the CGI::Session 'expire' method for all newly created sessions - The cookie now sets the Expires header based on the expiry time of the CGI::Session object (patch by Mark Stosberg) - Changed the hash key where we store all the private info in the CGI::Application object to be a bit more unique to this plugin module - expanded the coverage of the test suite Bug fixes: - If you didn't import the session_cookie method into your namespace, calls to $self->session would fail. - If you called session_cookie manually, it was possible under specific conditions that the session wasn't created yet, and the cookie would not be created properly 0.06 Tue Oct 19 22:15:48 EST 2004 - CGI::Session will currently only work with CGI.pm so check to see if CGI::Application is configured to use another CGI.pm like module like CGI::Simple - Be more intelligent about choosing a default temporary directory for windows users (suggested by Dan Horne) - Add a doc note to warn users when they change the name of the cookie, to also notify CGI::Session->name 0.05 Sun Sep 19 18:13:03 EST 2004 - scrap CGI::Application::Plugin support for simple Exporter system. - Moved module to the CGI::Application::Plugin namespace 0.04 Mon Jul 26 23:44:39 EST 2004 - add support for the new CGI::Application::Plugin base class 0.03 Tue Feb 10 22:12:29 EST 2004 - fool Module::Build into ignoring the 'package CGI::Application' directive in CGI::Application::Session so that it doesn't list CGI::Application as being provided by the distribution in the META.yml file. (there must be a better way!) - updated the Build.PL script - Fixed a silly documentation error 0.02 Tue Feb 10 14:59:51 EST 2004 - WARNING: changed the way in which session_config accepts parameters. Please check the docs because this will affect anyone that was using the session_config method in version 0.01. It is more flexible now, and will allow for future additions. - altered doc example by moving authentication check to cgiapp_prerun to co-inside with the examples in the CGI::Application docs - "Clayton L. Scott" tex -at- engsoc.org - automatically add a cookie to the outgoing headers if there isn't one there already (requires CGI::Application 3.21) - changed the code to conform to some of the CGI::Application coding standards 0.01 Sun Jan 18 11:06:49 2004 - original version; created by h2xs 1.19 CGI-Application-Plugin-Session-1.05/LICENSE0000644000175000017500000004363712255350127016673 0ustar frewfrewThis software is copyright (c) 2013 by Cees Hek. 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) 2013 by Cees Hek. 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, Suite 500, Boston, MA 02110-1335 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) 2013 by Cees Hek. 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 CGI-Application-Plugin-Session-1.05/README0000644000175000017500000002464712255350127016546 0ustar frewfrewNAME CGI::Application::Plugin::Session - Plugin that adds session support to CGI::Application VERSION version 1.05 SYNOPSIS use CGI::Application::Plugin::Session; my $language = $self->session->param('language'); DESCRIPTION CGI::Application::Plugin::Session seamlessly adds session support to your CGI::Application modules by providing a CGI::Session object that is accessible from anywhere in the application. Lazy loading is used to prevent expensive file system or database calls from being made if the session is not needed during this request. In other words, the Session object is not created until it is actually needed. Also, the Session object will act as a singleton by always returning the same Session object for the duration of the request. This module aims to be as simple and non obtrusive as possible. By not requiring any changes to the inheritance tree of your modules, it can be easily added to existing applications. Think of it as a plugin module that adds a couple of new methods directly into the CGI::Application namespace simply by loading the module. NAME CGI::Application::Plugin::Session - Add CGI::Session support to CGI::Application METHODS session This method will return the current CGI::Session object. The CGI::Session object is created on the first call to this method, and any subsequent calls will return the same object. This effectively creates a singleton session object for the duration of the request. CGI::Session will look for a cookie or param containing the session ID, and create a new session if none is found. If "session_config" has not been called before the first call to "session", then it will choose some sane defaults to create the session object. # retrieve the session object my $session = $self->session; - or - # use the session object directly my $language = $self->session->param('language'); session_config This method can be used to customize the functionality of the CGI::Application::Plugin::Session module. Calling this method does not mean that a new session object will be immediately created. The session object will not be created until the first call to $self->session. This 'lazy loading' can prevent expensive file system or database calls from being made if the session is not needed during this request. The recommended place to call "session_config" is in the "cgiapp_init" stage of CGI::Application. If this method is called after the session object has already been accessed, then it will die with an error message. If this method is not called at all then a reasonable set of defaults will be used (the exact default values are defined below). The following parameters are accepted: CGI_SESSION_OPTIONS This allows you to customize how the CGI::Session object is created by providing a list of options that will be passed to the CGI::Session constructor. Please see the documentation for CGI::Session for the exact syntax of the parameters. DEFAULT_EXPIRY CGI::Session Allows you to set an expiry time for the session. You can set the DEFAULT_EXPIRY option to have a default expiry time set for all newly created sessions. It takes the same format as the $session->expiry method of CGI::Session takes. Note that it is only set for new session, not when a session is reloaded from the store. COOKIE_PARAMS This allows you to customize the options that are used when creating the session cookie. For example you could provide an expiry time for the cookie by passing -expiry => '+24h'. The -name and -value parameters for the cookie will be added automatically unless you specifically override them by providing -name and/or -value parameters. See the CGI::Cookie docs for the exact syntax of the parameters. NOTE: You can do the following to get both the cookie name and the internal name of the CGI::Session object to be changed: $self->session_config( CGI_SESSION_OPTIONS => [ $driver, $self->query, \%driver_options, { name => 'new_cookie_name' } # change cookie and session name ] ); Also, if '-name' parameter and 'name' of session don't match a warning will be emitted. SEND_COOKIE If set to a true value, the module will automatically add a cookie header to the outgoing headers if a new session is created (Since the session module is lazy loaded, this will only happen if you make a call to $self->session at some point to create the session object). This option defaults to true. If it is set to false, then no session cookies will be sent, which may be useful if you prefer URL based sessions (it is up to you to pass the session ID in this case). The following example shows what options are set by default (ie this is what you would get if you do not call session_config). $self->session_config( CGI_SESSION_OPTIONS => [ "driver:File", $self->query, {Directory=>'/tmp'} ], COOKIE_PARAMS => { -path => '/', }, SEND_COOKIE => 1, ); Here is a more customized example that uses the PostgreSQL driver and sets an expiry and domain on the cookie. $self->session_config( CGI_SESSION_OPTIONS => [ "driver:PostgreSQL;serializer:Storable", $self->query, {Handle=>$dbh} ], COOKIE_PARAMS => { -domain => 'mydomain.com', -expires => '+24h', -path => '/', -secure => 1, }, ); session_cookie This method will add a cookie to the outgoing headers containing the session ID that was assigned by the CGI::Session module. This method is called automatically the first time $self->session is accessed if SEND_COOKIE was set true, which is the default, so it will most likely never need to be called manually. NOTE that if you do choose to call it manually that a session object will automatically be created if it doesn't already exist. This removes the lazy loading benefits of the plugin where a session is only created/loaded when it is required. It could be useful if you want to force the cookie header to be sent out even if the session is not used on this request, or if you want to manage the headers yourself by turning SEND_COOKIE to false. # Force the cookie header to be sent including some # custom cookie parameters $self->session_cookie(-secure => 1, -expires => '+1w'); session_loaded This method will let you know if the session object has been loaded yet. In other words, it lets you know if $self->session has been called. sub cgiapp_postrun { my $self = shift; $self->session->flush if $self->session_loaded;; } session_recreate This method will delete the existing session, and create a brand new one for you with a new session ID. It copies over all existing parameters into the new session. This can be useful to protect against some login attacks when storing authentication tokens in the session. Very briefly, an attacker loads a page on your site and creates a session, then tries to trick a victim into loading this page with the same session ID (possibly by embedding it in a URL). Then if the victim follows the link and subsequently logs into their account, the attacker will have a valid session ID where the session is now logged in, and hence the attacker has access to the victims account. sub mylogin { my $self = shift; if ($newly_authenticated) { $self->session_recreate; } } session_delete This method will perform a more comprehensive clean-up of the session, calling both the CGI::Session delete() method, but also deleting the cookie from the client, if you are using cookies. sub logout { my $self = shift; $self->session_delete; # what now? redirect user back to the homepage? } EXAMPLE In a CGI::Application module: # configure the session once during the init stage sub cgiapp_init { my $self = shift; # Configure the session $self->session_config( CGI_SESSION_OPTIONS => [ "driver:PostgreSQL;serializer:Storable", $self->query, {Handle=>$self->dbh} ], DEFAULT_EXPIRY => '+1w', COOKIE_PARAMS => { -expires => '+24h', -path => '/', }, SEND_COOKIE => 1, ); } sub cgiapp_prerun { my $self = shift; # Redirect to login, if necessary unless ( $self->session->param('~logged-in') ) { $self->prerun_mode('login'); } } sub my_runmode { my $self = shift; # Load the template my $template = $self->load_tmpl('my_runmode.tmpl'); # Add all the session parameters to the template $template->param($self->session->param_hashref()); # return the template output return $template->output; } TODO * I am considering adding support for other session modules in the future, like Apache::Session and possibly others if there is a demand. * Possibly add some tests to make sure cookies are accepted by the client. * Allow a callback to be executed right after a session has been created SEE ALSO CGI::Application, CGI::Session, perl(1) AUTHOR Cees Hek LICENSE Copyright (C) 2004, 2005 Cees Hek This library is free software. You can modify and or distribute it under the same terms as Perl itself. AUTHOR Cees Hek COPYRIGHT AND LICENSE This software is copyright (c) 2013 by Cees Hek. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. CGI-Application-Plugin-Session-1.05/MANIFEST0000644000175000017500000000113112255350127016776 0ustar frewfrewChanges LICENSE MANIFEST META.json META.yml Makefile.PL README cpanfile dist.ini lib/CGI/Application/Plugin/Session.pm t/01_basic.t t/02_cookie.t t/03_nocookie.t t/04_cgisimple.t t/05_sid.t t/06_expiry.t t/07_defaults.t t/08_notcgipm.t t/09_options.t t/10_sessioncookie.t t/11_sessiondelete.t t/12_badconfig.t t/13_sessioncookiename.t t/TestAppBasic.pm t/TestAppCGISimple.pm t/TestAppCookie.pm t/TestAppDefaults.pm t/TestAppExpiry.pm t/TestAppNoCookie.pm t/TestAppSessionCookie.pm t/TestAppSessionCookieName.pm t/TestAppSessionDelete.pm t/TestAppSid.pm t/release-pod-coverage.t t/release-pod-syntax.t CGI-Application-Plugin-Session-1.05/lib/0000775000175000017500000000000012255350127016421 5ustar frewfrewCGI-Application-Plugin-Session-1.05/lib/CGI/0000775000175000017500000000000012255350127017023 5ustar frewfrewCGI-Application-Plugin-Session-1.05/lib/CGI/Application/0000775000175000017500000000000012255350127021266 5ustar frewfrewCGI-Application-Plugin-Session-1.05/lib/CGI/Application/Plugin/0000775000175000017500000000000012255350127022524 5ustar frewfrewCGI-Application-Plugin-Session-1.05/lib/CGI/Application/Plugin/Session.pm0000644000175000017500000004653412255350127024517 0ustar frewfrewpackage CGI::Application::Plugin::Session; { $CGI::Application::Plugin::Session::VERSION = '1.05'; } use CGI::Session (); use File::Spec (); use CGI::Application 3.21; use Carp qw(croak); use Scalar::Util (); # ABSTRACT: Plugin that adds session support to CGI::Application use strict; use vars qw($VERSION @EXPORT); require Exporter; @EXPORT = qw( session session_config session_cookie session_delete session_loaded session_recreate ); sub import { goto &Exporter::import } sub session { my $self = shift; if (!$self->{__CAP__SESSION_OBJ}) { # define the config hash if it doesn't exist to save some checks later $self->{__CAP__SESSION_CONFIG} = {} unless $self->{__CAP__SESSION_CONFIG}; # gather parameters for the CGI::Session module from the user, # or use some sane defaults my @params = ($self->{__CAP__SESSION_CONFIG}->{CGI_SESSION_OPTIONS}) ? @{ $self->{__CAP__SESSION_CONFIG}->{CGI_SESSION_OPTIONS} } : ('driver:File', $self->query, {Directory=>File::Spec->tmpdir}); # CGI::Session only works properly with CGI.pm so extract the sid manually if # another module is being used if (Scalar::Util::blessed($params[1]) && ! $params[1]->isa('CGI')) { my $name = __locate_session_name( $self ); ## plugin method call + my $sid = $params[1]->cookie($name) || $params[1]->param($name); $params[1] = $sid; } # create CGI::Session object or die with an error $self->{__CAP__SESSION_OBJ} = CGI::Session->new(@params); if (! $self->{__CAP__SESSION_OBJ} ) { my $errstr = CGI::Session->errstr || 'Unknown'; croak "Failed to Create CGI::Session object :: Reason: $errstr"; } # Set the default expiry if requested and if this is a new session if ($self->{__CAP__SESSION_CONFIG}->{DEFAULT_EXPIRY} && $self->{__CAP__SESSION_OBJ}->is_new) { $self->{__CAP__SESSION_OBJ}->expire($self->{__CAP__SESSION_CONFIG}->{DEFAULT_EXPIRY}); } # add the cookie to the outgoing headers under the following conditions # if the cookie doesn't exist, # or if the session ID doesn't match what is in the current cookie, # or if the session has an expiry set on it # but don't send it if SEND_COOKIE is set to 0 if (!defined $self->{__CAP__SESSION_CONFIG}->{SEND_COOKIE} || $self->{__CAP__SESSION_CONFIG}->{SEND_COOKIE}) { my $cid = $self->query->cookie( $self->{__CAP__SESSION_OBJ}->name ); if (!$cid || $cid ne $self->{__CAP__SESSION_OBJ}->id || $self->{__CAP__SESSION_OBJ}->expire()) { session_cookie($self); } } } return $self->{__CAP__SESSION_OBJ}; } sub session_config { my $self = shift; if (@_) { die "Calling session_config after the session has already been created" if (defined $self->{__CAP__SESSION_OBJ}); my $props; if (ref($_[0]) eq 'HASH') { $props = $self->_cap_hash($_[0]); } else { $props = $self->_cap_hash({ @_ }); } # Check for CGI_SESSION_OPTIONS if ($props->{CGI_SESSION_OPTIONS}) { die "session_config error: parameter CGI_SESSION_OPTIONS is not an array reference" if ref $props->{CGI_SESSION_OPTIONS} ne 'ARRAY'; $self->{__CAP__SESSION_CONFIG}->{CGI_SESSION_OPTIONS} = delete $props->{CGI_SESSION_OPTIONS}; } # Check for COOKIE_PARAMS if ($props->{COOKIE_PARAMS}) { die "session_config error: parameter COOKIE_PARAMS is not a hash reference" if ref $props->{COOKIE_PARAMS} ne 'HASH'; $self->{__CAP__SESSION_CONFIG}->{COOKIE_PARAMS} = delete $props->{COOKIE_PARAMS}; } # Check for SEND_COOKIE if (defined $props->{SEND_COOKIE}) { $self->{__CAP__SESSION_CONFIG}->{SEND_COOKIE} = (delete $props->{SEND_COOKIE}) ? 1 : 0; } # Check for DEFAULT_EXPIRY if (defined $props->{DEFAULT_EXPIRY}) { $self->{__CAP__SESSION_CONFIG}->{DEFAULT_EXPIRY} = delete $props->{DEFAULT_EXPIRY}; } # If there are still entries left in $props then they are invalid die "Invalid option(s) (".join(', ', keys %$props).") passed to session_config" if %$props; } $self->{__CAP__SESSION_CONFIG}; } sub session_cookie { my $self = shift; my %options = @_; # merge in any parameters set by config_session if ($self->{__CAP__SESSION_CONFIG}->{COOKIE_PARAMS}) { %options = (%{ $self->{__CAP__SESSION_CONFIG}->{COOKIE_PARAMS} }, %options); } if (!$self->{__CAP__SESSION_OBJ}) { # The session object has not been created yet, so make sure we at least call it once my $tmp = $self->session; } ## check cookie option -name with session name ## if different these may cause problems/confusion if ( exists $options{'-name'} and $options{'-name'} ne $self->session->name ) { warn sprintf( "Cookie '%s' and Session '%s' name don't match.\n", $options{'-name'}, $self->session->name ) } ## setup the values for cookie $options{'-name'} ||= $self->session->name; $options{'-value'} ||= $self->session->id; if(defined($self->session->expires()) && !defined($options{'-expires'})) { $options{'-expires'} = _build_exp_time( $self->session->expires() ); } my $cookie = $self->query->cookie(%options); # Look for a cookie header in the existing headers my %headers = $self->header_props; my $cookie_set = 0; if (my $cookies = $headers{'-cookie'}) { if (ref($cookies) eq 'ARRAY') { # multiple cookie headers so check them all for (my $i=0; $i < @$cookies; $i++) { # replace the cookie inline if we find a match if (substr($cookies->[$i], 0, length($options{'-name'})) eq $options{'-name'}) { $cookies->[$i] = $cookie; $cookie_set++; } } } elsif (substr($cookies, 0, length($options{'-name'})) eq $options{'-name'}) { # only one cookie and it is ours, so overwrite it $self->header_add(-cookie => $cookie); $cookie_set++; } } $self->header_add(-cookie => [$cookie]) unless $cookie_set; return 1; } sub _build_exp_time { my $secs_until_expiry = shift; return unless defined $secs_until_expiry; # Add a plus sign unless the number is negative my $prefix = ($secs_until_expiry >= 0) ? '+' : ''; # Add an 's' for "seconds". return $prefix.$secs_until_expiry.'s'; } sub session_delete { my $self = shift; if ( my $session = $self->session ) { $session->delete; $session->flush; if ( $self->{'__CAP__SESSION_CONFIG'}->{'SEND_COOKIE'} ) { my %options; if ( $self->{'__CAP__SESSION_CONFIG'}->{'COOKIE_PARAMS'} ) { %options = ( %{ $self->{'__CAP__SESSION_CONFIG'}->{'COOKIE_PARAMS'} }, %options ); } $options{'name'} ||= $session->name; $options{'value'} = ''; $options{'-expires'} = '-1d'; my $newcookie = $self->query->cookie(\%options); # See if a session cookie has already been set (this will happen if # this is a new session). We keep all existing cookies except the # session cookie, which we replace with the timed out session # cookie my @keep; my %headers = $self->header_props; my $cookies = $headers{'-cookie'} || []; $cookies = [$cookies] unless ref $cookies eq 'ARRAY'; foreach my $cookie (@$cookies) { if ( ref($cookie) ne 'CGI::Cookie' || $cookie->name ne $session->name ) { # keep this cookie push @keep, $cookie; } } push @keep, $newcookie; # We have to set the cookies this way, because CGI::Application has # an annoying interface to the headers (why can't we have # 'header_set as well as header_add?). The first call replaces all # cookie headers with the one new cookie header, and the next call # adds in the rest of the cookies if there are any. $self->header_add( -cookie => shift @keep ); $self->header_add( -cookie => \@keep ) if @keep; } } } sub session_loaded { my $self = shift; return defined $self->{__CAP__SESSION_OBJ}; } sub session_recreate { my $self = shift; my $data = {}; # Copy all values from existing session and delete it if (session_loaded($self)) { $data = $self->session->param_hashref; $self->session->delete; $self->session->flush; $self->{__CAP__SESSION_OBJ} = undef; } # create a new session and populate it # (This should also send out a new cookie if so configured) my $session = $self->session; while(my($k,$v) = each %$data) { next if index($k, '_SESSION_') == 0; $session->param($k => $v); } $session->flush; return 1; } ## all a hack to adjust for problems with cgi::session and ## it not playing with non-CGI.pm objects sub __locate_session_name { my $self = shift; my $sess_opts = $self->{__CAP__SESSION_CONFIG}->{CGI_SESSION_OPTIONS}; ## search for 'name' cgi session option if ( $sess_opts and $sess_opts->[4] and ref $sess_opts->[4] eq 'HASH' and exists $sess_opts->[4]->{name} ) { return $sess_opts->[4]->{name}; } return CGI::Session->name; } 1; __END__ =pod =encoding UTF-8 =head1 NAME CGI::Application::Plugin::Session - Plugin that adds session support to CGI::Application =head1 VERSION version 1.05 =head1 SYNOPSIS use CGI::Application::Plugin::Session; my $language = $self->session->param('language'); =head1 DESCRIPTION CGI::Application::Plugin::Session seamlessly adds session support to your L modules by providing a L object that is accessible from anywhere in the application. Lazy loading is used to prevent expensive file system or database calls from being made if the session is not needed during this request. In other words, the Session object is not created until it is actually needed. Also, the Session object will act as a singleton by always returning the same Session object for the duration of the request. This module aims to be as simple and non obtrusive as possible. By not requiring any changes to the inheritance tree of your modules, it can be easily added to existing applications. Think of it as a plugin module that adds a couple of new methods directly into the CGI::Application namespace simply by loading the module. =head1 NAME CGI::Application::Plugin::Session - Add CGI::Session support to CGI::Application =head1 METHODS =head2 session This method will return the current L object. The L object is created on the first call to this method, and any subsequent calls will return the same object. This effectively creates a singleton session object for the duration of the request. L will look for a cookie or param containing the session ID, and create a new session if none is found. If C has not been called before the first call to C, then it will choose some sane defaults to create the session object. # retrieve the session object my $session = $self->session; - or - # use the session object directly my $language = $self->session->param('language'); =head2 session_config This method can be used to customize the functionality of the CGI::Application::Plugin::Session module. Calling this method does not mean that a new session object will be immediately created. The session object will not be created until the first call to $self->session. This 'lazy loading' can prevent expensive file system or database calls from being made if the session is not needed during this request. The recommended place to call C is in the C stage of L. If this method is called after the session object has already been accessed, then it will die with an error message. If this method is not called at all then a reasonable set of defaults will be used (the exact default values are defined below). The following parameters are accepted: =over 4 =item CGI_SESSION_OPTIONS This allows you to customize how the L object is created by providing a list of options that will be passed to the L constructor. Please see the documentation for L for the exact syntax of the parameters. =item DEFAULT_EXPIRY L Allows you to set an expiry time for the session. You can set the DEFAULT_EXPIRY option to have a default expiry time set for all newly created sessions. It takes the same format as the $session->expiry method of L takes. Note that it is only set for new session, not when a session is reloaded from the store. =item COOKIE_PARAMS This allows you to customize the options that are used when creating the session cookie. For example you could provide an expiry time for the cookie by passing -expiry => '+24h'. The -name and -value parameters for the cookie will be added automatically unless you specifically override them by providing -name and/or -value parameters. See the L docs for the exact syntax of the parameters. NOTE: You can do the following to get both the cookie name and the internal name of the CGI::Session object to be changed: $self->session_config( CGI_SESSION_OPTIONS => [ $driver, $self->query, \%driver_options, { name => 'new_cookie_name' } # change cookie and session name ] ); Also, if '-name' parameter and 'name' of session don't match a warning will be emitted. =item SEND_COOKIE If set to a true value, the module will automatically add a cookie header to the outgoing headers if a new session is created (Since the session module is lazy loaded, this will only happen if you make a call to $self->session at some point to create the session object). This option defaults to true. If it is set to false, then no session cookies will be sent, which may be useful if you prefer URL based sessions (it is up to you to pass the session ID in this case). =back The following example shows what options are set by default (ie this is what you would get if you do not call session_config). $self->session_config( CGI_SESSION_OPTIONS => [ "driver:File", $self->query, {Directory=>'/tmp'} ], COOKIE_PARAMS => { -path => '/', }, SEND_COOKIE => 1, ); Here is a more customized example that uses the PostgreSQL driver and sets an expiry and domain on the cookie. $self->session_config( CGI_SESSION_OPTIONS => [ "driver:PostgreSQL;serializer:Storable", $self->query, {Handle=>$dbh} ], COOKIE_PARAMS => { -domain => 'mydomain.com', -expires => '+24h', -path => '/', -secure => 1, }, ); =head2 session_cookie This method will add a cookie to the outgoing headers containing the session ID that was assigned by the CGI::Session module. This method is called automatically the first time $self->session is accessed if SEND_COOKIE was set true, which is the default, so it will most likely never need to be called manually. NOTE that if you do choose to call it manually that a session object will automatically be created if it doesn't already exist. This removes the lazy loading benefits of the plugin where a session is only created/loaded when it is required. It could be useful if you want to force the cookie header to be sent out even if the session is not used on this request, or if you want to manage the headers yourself by turning SEND_COOKIE to false. # Force the cookie header to be sent including some # custom cookie parameters $self->session_cookie(-secure => 1, -expires => '+1w'); =head2 session_loaded This method will let you know if the session object has been loaded yet. In other words, it lets you know if $self->session has been called. sub cgiapp_postrun { my $self = shift; $self->session->flush if $self->session_loaded;; } =head2 session_recreate This method will delete the existing session, and create a brand new one for you with a new session ID. It copies over all existing parameters into the new session. This can be useful to protect against some login attacks when storing authentication tokens in the session. Very briefly, an attacker loads a page on your site and creates a session, then tries to trick a victim into loading this page with the same session ID (possibly by embedding it in a URL). Then if the victim follows the link and subsequently logs into their account, the attacker will have a valid session ID where the session is now logged in, and hence the attacker has access to the victims account. sub mylogin { my $self = shift; if ($newly_authenticated) { $self->session_recreate; } } =head2 session_delete This method will perform a more comprehensive clean-up of the session, calling both the CGI::Session delete() method, but also deleting the cookie from the client, if you are using cookies. sub logout { my $self = shift; $self->session_delete; # what now? redirect user back to the homepage? } =head1 EXAMPLE In a CGI::Application module: # configure the session once during the init stage sub cgiapp_init { my $self = shift; # Configure the session $self->session_config( CGI_SESSION_OPTIONS => [ "driver:PostgreSQL;serializer:Storable", $self->query, {Handle=>$self->dbh} ], DEFAULT_EXPIRY => '+1w', COOKIE_PARAMS => { -expires => '+24h', -path => '/', }, SEND_COOKIE => 1, ); } sub cgiapp_prerun { my $self = shift; # Redirect to login, if necessary unless ( $self->session->param('~logged-in') ) { $self->prerun_mode('login'); } } sub my_runmode { my $self = shift; # Load the template my $template = $self->load_tmpl('my_runmode.tmpl'); # Add all the session parameters to the template $template->param($self->session->param_hashref()); # return the template output return $template->output; } =head1 TODO =over 4 =item * I am considering adding support for other session modules in the future, like L and possibly others if there is a demand. =item * Possibly add some tests to make sure cookies are accepted by the client. =item * Allow a callback to be executed right after a session has been created =back =head1 SEE ALSO L, L, perl(1) =head1 AUTHOR Cees Hek =head1 LICENSE Copyright (C) 2004, 2005 Cees Hek This library is free software. You can modify and or distribute it under the same terms as Perl itself. =head1 AUTHOR Cees Hek =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2013 by Cees Hek. 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 CGI-Application-Plugin-Session-1.05/META.json0000644000175000017500000000264012255350127017274 0ustar frewfrew{ "abstract" : "Plugin that adds session support to CGI::Application", "author" : [ "Cees Hek " ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 5.006, CPAN::Meta::Converter version 2.120921", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "CGI-Application-Plugin-Session", "prereqs" : { "configure" : { "requires" : { "ExtUtils::MakeMaker" : "6.30" } }, "develop" : { "requires" : { "Pod::Coverage::TrustPod" : "0", "Test::Pod" : "1.41", "Test::Pod::Coverage" : "1.08" } }, "runtime" : { "requires" : { "CGI::Application" : "3.21", "CGI::Session" : "4.48", "File::Spec" : "0", "Scalar::Util" : "0" } }, "test" : { "requires" : { "Test::More" : "1.001002" } } }, "release_status" : "stable", "resources" : { "homepage" : "https://github.com/frioux/CGI-Application-Plugin-Session", "repository" : { "type" : "git", "url" : "https://github.com/frioux/CGI-Application-Plugin-Session.git", "web" : "https://github.com/frioux/CGI-Application-Plugin-Session" } }, "version" : "1.05" } CGI-Application-Plugin-Session-1.05/cpanfile0000644000175000017500000000026112255350127017354 0ustar frewfrewrequires 'CGI::Session' => 4.48; requires 'CGI::Application' => 3.21; requires 'File::Spec'; requires 'Scalar::Util'; on test => sub { requires 'Test::More' => 1.001002; }; CGI-Application-Plugin-Session-1.05/META.yml0000644000175000017500000000127212255350127017124 0ustar frewfrew--- abstract: 'Plugin that adds session support to CGI::Application' author: - 'Cees Hek ' build_requires: Test::More: 1.001002 configure_requires: ExtUtils::MakeMaker: 6.30 dynamic_config: 0 generated_by: 'Dist::Zilla version 5.006, CPAN::Meta::Converter version 2.120921' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: CGI-Application-Plugin-Session requires: CGI::Application: 3.21 CGI::Session: 4.48 File::Spec: 0 Scalar::Util: 0 resources: homepage: https://github.com/frioux/CGI-Application-Plugin-Session repository: https://github.com/frioux/CGI-Application-Plugin-Session.git version: 1.05 CGI-Application-Plugin-Session-1.05/t/0000775000175000017500000000000012255350127016116 5ustar frewfrewCGI-Application-Plugin-Session-1.05/t/11_sessiondelete.t0000644000175000017500000001131012255350127021444 0ustar frewfrewuse Test::More tests => 20; use File::Spec; BEGIN { use_ok('CGI::Application::Plugin::Session') }; use lib './t'; use strict; $ENV{CGI_APP_RETURN_ONLY} = 1; use CGI; use TestAppSessionDelete; my $t1_obj = TestAppSessionDelete->new(QUERY=>CGI->new()); my $t1_output = $t1_obj->run(); like($t1_output, qr/session created/, 'session created'); like($t1_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'session cookie set'); my ($id1) = $t1_output =~ /id=([a-zA-Z0-9]+)/s; ok($id1, 'found session id'); my ( $original_expiry ) = $t1_output =~ /expires=(.+)\s+Date/; # Test Plan ... create a session ... not going to test that, b/c there are # other tests for that. What we're going to do is now create a new CGI query # object and call the 'logout' runmode, which will call the new session_delete # method, which should remove the flat file as well as send a cookie header # with an expire timestamp in the past. # need to inject session into $query - this is done by an environment var $ENV{HTTP_COOKIE} = "CGISESSID=$id1"; my $query = new CGI({ rm => 'logout' }); $t1_obj = TestAppSessionDelete->new( QUERY => $query ); $t1_output = $t1_obj->run(); # vanilla output came through ok? ok( $t1_output =~ /logout finished/, 'vanilla output came through ok' ); # If that didn't pass, then I'm guessing the session wasn't injected properly # Was the session create cookie in the output? It shouldn't be unlike($t1_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'new session cookie not in output'); # Was the session delete cookie in the output? It should be like($t1_output, qr/Set-Cookie: CGISESSID=;/, 'delete session cookie in output'); my ( $new_expiry ) = $t1_output =~ /expires=(.+)\s+Date/; ok( $original_expiry ne $new_expiry, 'expirations are different' ); # Need to figure out if $new_expiry < $original_expiry and $new_expiry < NOW() SKIP: { eval { require Date::Parse; }; skip "Date::Parse not installed", 2 if $@; Date::Parse->import(); my $expired_time = str2time( $new_expiry ); my $original_time = str2time( $original_expiry ); ok( $expired_time < $original_time, 'The new expiry is older than the original expiry' ); my $current_time = time(); # Since the cookie is recreated with a time of minus one day, we shouldn't # have to worry about timezones ok( $expired_time < $current_time, 'The new expiry is older than now' ); } # Session object will not disappear and be written # to disk until it is DESTROYed undef $t1_obj; # Is the file gone? ok( !-e 't/cgisess_'.$id1, 'session_delete wiped the flat file ok' ); # We do the cookie tests again, this time we set some extra custom cookies # and make sure they don't get clobbered $ENV{HTTP_COOKIE} = "CGISESSID=$id1"; $query = new CGI({ rm => 'logout' }); $t1_obj = TestAppSessionDelete->new( QUERY => $query ); $t1_obj->header_add( -cookie => [ CGI::Cookie->new( -name => 'test', -value => 'testing' ) ]); $t1_obj->header_add( -cookie => [ 'test2=testing2; path=/' ]); $t1_output = $t1_obj->run(); # vanilla output came through ok? ok( $t1_output =~ /logout finished/, 'vanilla output came through ok' ); # If that didn't pass, then I'm guessing the session wasn't injected properly # Was the session create cookie in the output? It shouldn't be unlike($t1_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'new session cookie not in output'); # Was the session delete cookie in the output? It should be like($t1_output, qr/Set-Cookie: CGISESSID=;/, 'delete session cookie in output'); # Was the test cookie in the output? It should be like($t1_output, qr/Set-Cookie: test=testing/, 'test cookie in output'); # Was the test cookie in the output? It should be like($t1_output, qr/Set-Cookie: test2=testing2/, 'second test cookie in output'); # We do the cookie tests one last time, this time we clobber the session cookie # and set a single new cookie $ENV{HTTP_COOKIE} = "CGISESSID=$id1"; $query = new CGI({ rm => 'logout' }); $t1_obj = TestAppSessionDelete->new( QUERY => $query ); $t1_obj->session; # this sets the session cookie $t1_obj->header_add( -cookie => 'test2=testing2; path=/'); # this clobbers the session cookie $t1_output = $t1_obj->run(); # vanilla output came through ok? ok( $t1_output =~ /logout finished/, 'vanilla output came through ok' ); # If that didn't pass, then I'm guessing the session wasn't injected properly # Was the session create cookie in the output? It shouldn't be unlike($t1_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'new session cookie not in output'); # Was the session delete cookie in the output? It should be like($t1_output, qr/Set-Cookie: CGISESSID=;/, 'delete session cookie in output'); # Was the test cookie in the output? It should be like($t1_output, qr/Set-Cookie: test2=testing2/, 'test cookie in output'); CGI-Application-Plugin-Session-1.05/t/07_defaults.t0000644000175000017500000000110212255350127020410 0ustar frewfrewuse Test::More tests => 3; use File::Spec; BEGIN { use_ok('CGI::Application::Plugin::Session') }; use lib './t'; use strict; $ENV{CGI_APP_RETURN_ONLY} = 1; use CGI; use TestAppDefaults; my $t1_obj = TestAppDefaults->new(QUERY=>CGI->new()); my $t1_output = $t1_obj->run(); like($t1_output, qr/session created/, 'session created'); my ($id1) = $t1_output =~ /id=([a-zA-Z0-9]+)/s; ok($id1, 'found session id'); # Session object will not dissapear and be written # to disk until it is DESTROYed undef $t1_obj; unlink File::Spec->catdir(File::Spec->tmpdir, 'cgisess_'.$id1); CGI-Application-Plugin-Session-1.05/t/10_sessioncookie.t0000644000175000017500000000466312255350127021467 0ustar frewfrewuse Test::More tests => 17; use File::Spec; BEGIN { use_ok('CGI::Application::Plugin::Session') }; use lib './t'; use strict; $ENV{CGI_APP_RETURN_ONLY} = 1; use CGI; use TestAppSessionCookie; my $t1_obj = TestAppSessionCookie->new(QUERY=>CGI->new()); my $t1_output = $t1_obj->run(); like($t1_output, qr/session created/, 'session created'); like($t1_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'session cookie set'); my ($id1) = $t1_output =~ /id=([a-zA-Z0-9]+)/s; ok($id1, 'found session id'); # check domain like($t1_output, qr/domain=mydomain.com;/, 'domain found in cookie'); # check path like($t1_output, qr/path=\/testpath/, 'path found in cookie'); # check expires (should not exist) unlike($t1_output, qr/expires=/, 'expires not found in cookie'); # Session object will not disappear and be written # to disk until it is DESTROYed undef $t1_obj; unlink File::Spec->catdir('t', 'cgisess_'.$id1); my $query = new CGI({ rm => 'existing_session_cookie' }); $t1_obj = TestAppSessionCookie->new( QUERY => $query ); $t1_output = $t1_obj->run(); unlike($t1_output, qr/Set-Cookie: CGISESSID=test/, 'existing session cookie was deleted'); like($t1_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'new session cookie set'); ($id1) = $t1_output =~ /id=([a-zA-Z0-9]+)/s; ok($id1, 'found session id'); undef $t1_obj; unlink File::Spec->catdir('t', 'cgisess_'.$id1); $query = new CGI({ rm => 'existing_session_cookie_plus_extra_cookie' }); $t1_obj = TestAppSessionCookie->new( QUERY => $query ); $t1_output = $t1_obj->run(); unlike($t1_output, qr/Set-Cookie: CGISESSID=test/, 'existing session cookie was deleted'); like($t1_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'new session cookie set'); like($t1_output, qr/Set-Cookie: TESTCOOKIE=testvalue/, 'existing cookie was not deleted'); ($id1) = $t1_output =~ /id=([a-zA-Z0-9]+)/s; ok($id1, 'found session id'); undef $t1_obj; unlink File::Spec->catdir('t', 'cgisess_'.$id1); $query = new CGI({ rm => 'existing_extra_cookie' }); $t1_obj = TestAppSessionCookie->new( QUERY => $query ); $t1_output = $t1_obj->run(); like($t1_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'new session cookie set'); like($t1_output, qr/Set-Cookie: TESTCOOKIE=testvalue/, 'existing cookie was not deleted'); ($id1) = $t1_output =~ /id=([a-zA-Z0-9]+)/s; ok($id1, 'found session id'); undef $t1_obj; unlink File::Spec->catdir('t', 'cgisess_'.$id1); CGI-Application-Plugin-Session-1.05/t/TestAppNoCookie.pm0000644000175000017500000000131512255350127021461 0ustar frewfrewpackage TestAppNoCookie; use strict; use CGI::Application; use CGI::Application::Plugin::Session; @TestAppNoCookie::ISA = qw(CGI::Application); sub cgiapp_init { my $self = shift; $self->session_config( CGI_SESSION_OPTIONS => [ "driver:File", $self->query, {Directory=>'t/'} ], SEND_COOKIE => 0, ); } sub setup { my $self = shift; $self->start_mode('test_mode'); $self->run_modes(test_mode => 'test_mode' ); } sub test_mode { my $self = shift; my $output = ''; my $session = $self->session; $output .= $session->is_new ? "session created\n" : "session found\n"; $output .= "id=".$session->id."\n"; return $output; } 1; CGI-Application-Plugin-Session-1.05/t/04_cgisimple.t0000644000175000017500000000351712255350127020566 0ustar frewfrewuse Test::More; use File::Spec; use lib './t'; use strict; use CGI::Application::Plugin::Session; eval { require CGI::Simple; CGI::Simple->import; }; if ($@) { plan skip_all => "CGI::Simple required for this test"; exit; } plan tests => 12; $ENV{CGI_APP_RETURN_ONLY} = 1; use TestAppCGISimple; my $t1_obj = TestAppCGISimple->new(QUERY=>CGI::Simple->new()); my $t1_output = $t1_obj->run(); like($t1_output, qr/session created/, 'session created'); like($t1_output, qr/query=CGI::Simple/, 'using CGI::Simple'); like($t1_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'session cookie set'); my ($id1) = $t1_output =~ /id=([a-zA-Z0-9]+)/s; ok($id1, 'found session id'); # Session object will not dissapear and be written # to disk until it is DESTROYed undef $t1_obj; # Set a cookie in $ENV{HTTP_COOKIE} $ENV{HTTP_COOKIE} = CGI::Session->name.'='.$id1; my $t2_obj = TestAppCGISimple->new(QUERY=>CGI::Simple->new()); my $t2_output = $t2_obj->run(); like($t2_output, qr/session found/, 'session found'); like($t2_output, qr/value=test1/, 'session parameter retrieved'); like($t2_output, qr/query=CGI::Simple/, 'using CGI::Simple'); unlike($t2_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'session cookie not set'); undef $t2_obj; unlink File::Spec->catdir('t', 'cgisess_'.$id1); # test with an expired cookie $ENV{HTTP_COOKIE} = CGI::Session->name.'=badsessionid'; my $t3_obj = TestAppCGISimple->new(QUERY=>CGI::Simple->new()); my $t3_output = $t3_obj->run(); like($t3_output, qr/session created/, 'session created'); unlike($t3_output, qr/value=test1/, 'session parameter not found'); like($t3_output, qr/query=CGI::Simple/, 'using CGI::Simple'); like($t3_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'session cookie set'); my ($id3) = $t3_output =~ /id=([a-zA-Z0-9]+)/s; undef $t3_obj; unlink File::Spec->catdir('t', 'cgisess_'.$id3); CGI-Application-Plugin-Session-1.05/t/06_expiry.t0000644000175000017500000000436112255350127020132 0ustar frewfrewuse Test::More tests => 16; use File::Spec; BEGIN { use_ok('CGI::Application::Plugin::Session') }; use lib './t'; use strict; $ENV{CGI_APP_RETURN_ONLY} = 1; use CGI; use TestAppExpiry; $ENV{DEFAULT_EXPIRY} = '+1h'; my $t1_obj = TestAppExpiry->new(QUERY=>CGI->new()); my $t1_output = $t1_obj->run(); # Set-Cookie: CGISESSID=d7fc7bab0f9e1301fd21717c556337fe; path=/; expires=Sat, 11-Jun-2005 17:47:28 GMT like($t1_output, qr/\(3600\)/, 'expiry set correctly'); like($t1_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'session cookie set'); like($t1_output, qr/expires=\w{3}, /, 'session cookie expiry set'); my ($year) = $t1_output =~ /\d+\-\w{3}\-(\d+) /s; my ($id1) = $t1_output =~ /CGISESSID=([a-zA-Z0-9]+)/s; ok($id1, 'found session id'); undef $t1_obj; # Set a cookie in $ENV{HTTP_COOKIE} $ENV{HTTP_COOKIE} = CGI::Session->name.'='.$id1; # Change the default expiry $ENV{DEFAULT_EXPIRY} = '+1y'; $t1_obj = TestAppExpiry->new(QUERY=>CGI->new()); $t1_output = $t1_obj->run(); like($t1_output, qr/\(3600\)/, 'expiry set correctly'); like($t1_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'session cookie set'); like($t1_output, qr/expires=\w{3}, /, 'session cookie expiry set'); my ($year2) = $t1_output =~ /\d+\-\w{3}\-(\d+) /s; # This test will fail during the last hour of the year, but I can't be bother to # test for that :) is($year2, $year, 'Expiry should not change'); my ($id2) = $t1_output =~ /CGISESSID=([a-zA-Z0-9]+)/s; ok($id2, 'found session id'); is($id2, $id1, "Session was reused"); undef $t1_obj; unlink File::Spec->catdir('t', 'cgisess_'.$id1); delete $ENV{HTTP_COOKIE}; # Change the default expiry $ENV{DEFAULT_EXPIRY} = '-1y'; $t1_obj = TestAppExpiry->new(); $t1_output = $t1_obj->run(); like($t1_output, qr/\(\-31536000\)/, 'expiry set correctly'); like($t1_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'session cookie set'); like($t1_output, qr/expires=\w{3}, /, 'session cookie expiry set'); ($year2) = $t1_output =~ /\d+\-\w{3}\-(\d+) /s; # This test will fail during the last hour of the year, but I can't be bother to # test for that :) is($year2, $year-1, 'Expiry should not change'); ($id2) = $t1_output =~ /CGISESSID=([a-zA-Z0-9]+)/s; ok($id2, 'found session id'); undef $t1_obj; unlink File::Spec->catdir('t', 'cgisess_'.$id2); CGI-Application-Plugin-Session-1.05/t/TestAppBasic.pm0000644000175000017500000000135712255350127021002 0ustar frewfrewpackage TestAppBasic; use strict; use CGI::Application; use CGI::Application::Plugin::Session; @TestAppBasic::ISA = qw(CGI::Application); sub cgiapp_init { my $self = shift; $self->session_config(CGI_SESSION_OPTIONS => [ "driver:File", $self->query, {Directory=>'t/'} ]); } sub setup { my $self = shift; $self->start_mode('test_mode'); $self->run_modes(test_mode => 'test_mode' ); } sub test_mode { my $self = shift; my $output = ''; my $session = $self->session; $output .= $session->is_new ? "session created\n" : "session found\n"; my $value = $session->param('value') || ""; $output .= "value=$value\n"; $output .= "id=".$session->id."\n"; $session->param('value' => 'test1'); return $output; } 1; CGI-Application-Plugin-Session-1.05/t/TestAppCookie.pm0000644000175000017500000000227112255350127021166 0ustar frewfrewpackage TestAppCookie; use strict; use CGI::Application; use CGI::Application::Plugin::Session; @TestAppCookie::ISA = qw(CGI::Application); sub cgiapp_init { my $self = shift; $self->session_config({ CGI_SESSION_OPTIONS => [ "driver:File", $self->query, {Directory=>'t/'} ], SEND_COOKIE => 0, COOKIE_PARAMS => { -name => CGI::Session->name, -value => '1111', -path => '/testpath', -domain => 'mydomain.com', -expires => '+24h', }, }); } sub setup { my $self = shift; $self->start_mode('test_mode'); $self->run_modes(test_mode => 'test_mode' ); } sub test_mode { my $self = shift; my $output = ''; $self->session_cookie; my $session = $self->session; $output .= $session->is_new ? "session created\n" : "session found\n"; $output .= "id=".$session->id."\n"; return $output; } 1; CGI-Application-Plugin-Session-1.05/t/13_sessioncookiename.t0000644000175000017500000000072612255350127022327 0ustar frewfrew use warnings; use strict; use lib qw( t ); use Test::More; $ENV{CGI_APP_RETURN_ONLY} = 1; ## only run tests on newer CGI:Session versions plan tests => 2; ## need for the tests use CGI; use TestAppSessionCookieName; { my $t1_obj = TestAppSessionCookieName->new( QUERY => CGI->new ); my $t1_out = $t1_obj->run; like $t1_out, qr/session:/, 'session in output'; like $t1_out, qr/Set-Cookie: foobar=[a-zA-Z0-9]+/, 'session cookie with custom name'; } CGI-Application-Plugin-Session-1.05/t/01_basic.t0000644000175000017500000000422112255350127017661 0ustar frewfrewuse Test::More tests => 15; use File::Spec; BEGIN { use_ok('CGI::Application::Plugin::Session') }; use lib './t'; use strict; $ENV{CGI_APP_RETURN_ONLY} = 1; use CGI; use TestAppBasic; my $t1_obj = TestAppBasic->new(QUERY=>CGI->new()); my $t1_output = $t1_obj->run(); like($t1_output, qr/session created/, 'session created'); like($t1_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'session cookie set'); my ($id1) = $t1_output =~ /id=([a-zA-Z0-9]+)/s; ok($id1, 'found session id'); my $session_config = $t1_obj->session_config; is (ref($session_config), 'HASH', 'Retrieved Session Config'); eval { my $session_config = $t1_obj->session_config(SEND_COOKIE => 1) }; like($@, qr/Calling session_config after the session has already been created/, 'session_config called after session created'); # Session object will not dissapear and be written # to disk until it is DESTROYed undef $t1_obj; # Set the Session ID in a parameter my $t2_obj = TestAppBasic->new(QUERY=>CGI->new({ CGI::Session->name => $id1 })); my $t2_output = $t2_obj->run(); like($t2_output, qr/session found/, 'session found'); like($t2_output, qr/value=test1/, 'session parameter retrieved'); like($t2_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'session cookie set'); undef $t2_obj; # Set a cookie in $ENV{HTTP_COOKIE} $ENV{HTTP_COOKIE} = CGI::Session->name.'='.$id1; my $t3_obj = TestAppBasic->new(); my $t3_output = $t3_obj->run(); like($t3_output, qr/session found/, 'session found'); like($t3_output, qr/value=test1/, 'session parameter retrieved'); unlike($t3_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'session cookie not set'); undef $t3_obj; unlink File::Spec->catdir('t', 'cgisess_'.$id1); # test with an expired cookie $ENV{HTTP_COOKIE} = CGI::Session->name.'=badsessionid'; my $t4_obj = TestAppBasic->new(QUERY=>CGI->new()); my $t4_output = $t4_obj->run(); like($t4_output, qr/session created/, 'session created'); unlike($t4_output, qr/value=test1/, 'session parameter not found'); like($t4_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'session cookie set'); my ($id4) = $t4_output =~ /id=([a-zA-Z0-9]+)/s; undef $t4_obj; unlink File::Spec->catdir('t', 'cgisess_'.$id4); CGI-Application-Plugin-Session-1.05/t/09_options.t0000644000175000017500000000406112255350127020305 0ustar frewfrewuse Test::More tests => 9; use File::Spec; BEGIN { use_ok('CGI::Application::Plugin::Session') }; use lib './t'; use strict; use warnings; { package TestAppOptions; @TestAppOptions::ISA = qw(CGI::Application); use CGI::Application::Plugin::Session; }; my $t1_obj = TestAppOptions->new(); $t1_obj->session_config( CGI_SESSION_OPTIONS => [ "driver:File", $t1_obj->query, {Directory=>'t/'} ], SEND_COOKIE => 1, DEFAULT_EXPIRY => '+1y', COOKIE_PARAMS => { -domain => 'example.com' }, ); ok($t1_obj->{__CAP__SESSION_CONFIG}->{CGI_SESSION_OPTIONS}, 'CGI_SESSION_OPTIONS defined'); ok($t1_obj->{__CAP__SESSION_CONFIG}->{SEND_COOKIE}, 'SEND_COOKIE defined'); ok($t1_obj->{__CAP__SESSION_CONFIG}->{DEFAULT_EXPIRY}, 'DEFAULT_EXPIRY defined'); ok($t1_obj->{__CAP__SESSION_CONFIG}->{COOKIE_PARAMS}, 'COOKIE_PARAMS defined'); my $session = $t1_obj->session; my $session_id = $session->id; eval { $t1_obj->session_config( CGI_SESSION_OPTIONS => [ "driver:File", $t1_obj->query, {Directory=>'t/'} ], SEND_COOKIE => 1, DEFAULT_EXPIRY => '+1y', COOKIE_PARAMS => { -domain => 'example.com' }, ); }; like($@, qr/Calling session_config after the session has already been created/, 'Can not call config_session after session created'); eval { $t1_obj = TestAppOptions->new(); $t1_obj->session_config( CGI_SESSION_OPTIONS => 'invalid', ); }; like($@, qr/session_config error: parameter CGI_SESSION_OPTIONS is not an array reference/, 'CGI_SESSION_OPTIONS should be an arrayref'); eval { $t1_obj = TestAppOptions->new(); $t1_obj->session_config( COOKIE_PARAMS => 'invalid', ); }; like($@, qr/session_config error: parameter COOKIE_PARAMS is not a hash reference/, 'COOKIE_PARAMS should be a hashref'); eval { $t1_obj = TestAppOptions->new(); $t1_obj->session_config( INVALID_OPTION => 'invalid', ); }; like($@, qr/Invalid option\(s\)/, 'invalid option'); undef $t1_obj; undef $session; unlink File::Spec->catdir('t', 'cgisess_'.$session_id); CGI-Application-Plugin-Session-1.05/t/TestAppSid.pm0000644000175000017500000000142212255350127020471 0ustar frewfrewpackage TestAppSid; use strict; use CGI::Application; use CGI::Application::Plugin::Session; @TestAppSid::ISA = qw(CGI::Application); sub cgiapp_init { my $self = shift; my $sid = $self->query->cookie('CGISESSID'); $self->session_config(CGI_SESSION_OPTIONS => [ "driver:File", $sid, {Directory=>'t/'} ]); } sub setup { my $self = shift; $self->start_mode('test_mode'); $self->run_modes(test_mode => 'test_mode' ); } sub test_mode { my $self = shift; my $output = ''; my $session = $self->session; $output .= $session->is_new ? "session created\n" : "session found\n"; my $value = $session->param('value') || ""; $output .= "value=$value\n"; $output .= "id=".$session->id."\n"; $session->param('value' => 'test1'); return $output; } 1; CGI-Application-Plugin-Session-1.05/t/TestAppSessionDelete.pm0000644000175000017500000000245212255350127022524 0ustar frewfrewpackage TestAppSessionDelete; use strict; use CGI::Application; use CGI::Application::Plugin::Session; @TestAppSessionDelete::ISA = qw(CGI::Application); sub cgiapp_init { my $self = shift; $self->session_config({ CGI_SESSION_OPTIONS => [ "driver:File", $self->query, {Directory=>'t/'} ], SEND_COOKIE => 1, DEFAULT_EXPIRY => '+1h', COOKIE_PARAMS => { -path => '/testpath', -domain => 'mydomain.com', -expires => '+3M', }, }); } sub setup { my $self = shift; $self->start_mode('start'); $self->run_modes( [ qw( start logout ) ] ); } sub start { my $self = shift; my $output = ''; my $session = $self->session; $output .= $session->is_new ? "session created\n" : "session found\n"; $output .= "id=".$session->id."\n"; return $output; } sub logout { my $self = shift; my $query = $self->query; if ( ! $query->cookie( 'CGISESSID' ) ) { return "didn't get session passed in!"; } else { $self->session_delete; return "logout finished"; } } 1; CGI-Application-Plugin-Session-1.05/t/release-pod-coverage.t0000644000175000017500000000076512255350127022302 0ustar frewfrew#!perl BEGIN { unless ($ENV{RELEASE_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for release candidate testing'); } } use Test::More; eval "use Test::Pod::Coverage 1.08"; plan skip_all => "Test::Pod::Coverage 1.08 required for testing POD coverage" if $@; eval "use Pod::Coverage::TrustPod"; plan skip_all => "Pod::Coverage::TrustPod required for testing POD coverage" if $@; all_pod_coverage_ok({ coverage_class => 'Pod::Coverage::TrustPod' }); CGI-Application-Plugin-Session-1.05/t/08_notcgipm.t0000644000175000017500000000361712255350127020437 0ustar frewfrewuse Test::More tests => 13; use File::Spec; BEGIN { use_ok('CGI::Application::Plugin::Session') }; use lib './t'; use strict; $ENV{CGI_APP_RETURN_ONLY} = 1; use CGI; use TestAppBasic; my $t1_obj = TestAppBasic->new(QUERY=>CGI->new()); my $t1_output = $t1_obj->run(); like($t1_output, qr/session created/, 'session created'); like($t1_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'session cookie set'); my ($id1) = $t1_output =~ /id=([a-zA-Z0-9]+)/s; ok($id1, 'found session id'); # Session object will not dissapear and be written # to disk until it is DESTROYed undef $t1_obj; { package MyCGI; @MyCGI::ISA = qw(CGI); }; # Set the Session ID in a parameter my $t2_obj = TestAppBasic->new(QUERY=>MyCGI->new({ CGI::Session->name => $id1 })); my $t2_output = $t2_obj->run(); like($t2_output, qr/session found/, 'session found'); like($t2_output, qr/value=test1/, 'session parameter retrieved'); like($t2_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'session cookie set'); undef $t2_obj; # Set a cookie in $ENV{HTTP_COOKIE} $ENV{HTTP_COOKIE} = CGI::Session->name.'='.$id1; my $t3_obj = TestAppBasic->new(); my $t3_output = $t3_obj->run(); like($t3_output, qr/session found/, 'session found'); like($t3_output, qr/value=test1/, 'session parameter retrieved'); unlike($t3_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'session cookie not set'); undef $t3_obj; unlink File::Spec->catdir('t', 'cgisess_'.$id1); # test with an expired cookie $ENV{HTTP_COOKIE} = CGI::Session->name.'=badsessionid'; my $t4_obj = TestAppBasic->new(QUERY=>CGI->new()); my $t4_output = $t4_obj->run(); like($t4_output, qr/session created/, 'session created'); unlike($t4_output, qr/value=test1/, 'session parameter not found'); like($t4_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'session cookie set'); my ($id4) = $t4_output =~ /id=([a-zA-Z0-9]+)/s; undef $t4_obj; unlink File::Spec->catdir('t', 'cgisess_'.$id4); CGI-Application-Plugin-Session-1.05/t/12_badconfig.t0000644000175000017500000000207512255350127020523 0ustar frewfrewuse lib './t'; use Test::More; BEGIN { eval { require Test::Exception; Test::Exception->import; }; if ( $@ ) { plan skip_all => 'These tests require Test::Exception'; } else { plan tests => 3; } }; { package TestAppBadConfig; @TestAppBadConfig::ISA = qw(CGI::Application); use CGI::Application::Plugin::Session; }; my $app = TestAppBadConfig->new(); $app->session_config( CGI_SESSION_OPTIONS => [ "driver:invalid_driver", $app->query ] ); dies_ok(sub { $app->session }, 'creation of CGI::Session object fails with a bad config'); ## sub our own testing warn handler my $warning; $SIG{'__WARN__'} = sub { $warning = join ' ', @_ }; ## mismatch cookie name and session name my $app2 = TestAppBadConfig->new(); $app2->session_config( CGI_SESSION_OPTIONS => [ "driver:File", '1111', { Directory => 't/' }, { name => 'foobar' } ], COOKIE_PARAMS => { -name => 'monkeybeard' } ); ## should generate warning $app2->session; ok $warning, "cookie and session name don't match"; like $warning, qr/Cookie.*?Session/; 1; CGI-Application-Plugin-Session-1.05/t/TestAppSessionCookieName.pm0000644000175000017500000000134612255350127023335 0ustar frewfrewpackage TestAppSessionCookieName; use warnings; use strict; use CGI::Application; use CGI::Application::Plugin::Session; @TestAppSessionCookieName::ISA = qw(CGI::Application); sub cgiapp_init { my $self = shift; $self->session_config( { CGI_SESSION_OPTIONS => [ "driver:File", $self->query, { Directory => 't/' }, { name => 'foobar' } ], SEND_COOKIE => 1, DEFAULT_EXPIRY => '+1h' } ); } sub setup { my $self = shift; $self->start_mode( 'test_mode' ); $self->run_modes( [ qw( test_mode ) ] ); } sub test_mode { my $self = shift; my $session = $self->session; return "session: " . $session->id . "\n"; } 1; CGI-Application-Plugin-Session-1.05/t/TestAppSessionCookie.pm0000644000175000017500000000476312255350127022542 0ustar frewfrewpackage TestAppSessionCookie; use strict; use CGI::Application; use CGI::Application::Plugin::Session; @TestAppSessionCookie::ISA = qw(CGI::Application); sub cgiapp_init { my $self = shift; $self->session_config({ CGI_SESSION_OPTIONS => [ "driver:File", $self->query, {Directory=>'t/'} ], SEND_COOKIE => 1, DEFAULT_EXPIRY => '+1h', COOKIE_PARAMS => { -name => CGI::Session->name, -value => '1111', -path => '/testpath', -domain => 'mydomain.com', -expires => '', }, }); } sub setup { my $self = shift; $self->start_mode('test_mode'); $self->run_modes([qw(test_mode existing_session_cookie existing_session_cookie_plus_extra_cookie existing_extra_cookie)]); } sub test_mode { my $self = shift; my $output = ''; my $session = $self->session; $output .= $session->is_new ? "session created\n" : "session found\n"; $output .= "id=".$session->id."\n"; return $output; } sub existing_session_cookie { my $self = shift; my $output = ''; $self->header_add(-cookie => $self->query->cookie(-name => 'CGISESSID', -value => 'test'), ); my $session = $self->session; $output .= $session->is_new ? "session created\n" : "session found\n"; $output .= "id=".$session->id."\n"; return $output; } sub existing_session_cookie_plus_extra_cookie { my $self = shift; my $output = ''; $self->header_add(-cookie => [ $self->query->cookie(-name => 'CGISESSID', -value => 'test'), $self->query->cookie(-name => 'TESTCOOKIE', -value => 'testvalue'), ]); my $session = $self->session; $output .= $session->is_new ? "session created\n" : "session found\n"; $output .= "id=".$session->id."\n"; return $output; } sub existing_extra_cookie { my $self = shift; my $output = ''; $self->header_add(-cookie => $self->query->cookie(-name => 'TESTCOOKIE', -value => 'testvalue'), ); my $session = $self->session; $output .= $session->is_new ? "session created\n" : "session found\n"; $output .= "id=".$session->id."\n"; return $output; } 1; CGI-Application-Plugin-Session-1.05/t/TestAppDefaults.pm0000644000175000017500000000114712255350127021525 0ustar frewfrewpackage TestAppDefaults; use strict; use CGI::Application; use CGI::Application::Plugin::Session; @TestAppDefaults::ISA = qw(CGI::Application); sub setup { my $self = shift; $self->start_mode('test_mode'); $self->run_modes(test_mode => 'test_mode' ); } sub test_mode { my $self = shift; my $output = ''; my $session = $self->session; $output .= $session->is_new ? "session created\n" : "session found\n"; my $value = $session->param('value') || ""; $output .= "value=$value\n"; $output .= "id=".$session->id."\n"; $session->param('value' => 'test1'); return $output; } 1; CGI-Application-Plugin-Session-1.05/t/TestAppExpiry.pm0000644000175000017500000000130012255350127021225 0ustar frewfrewpackage TestAppExpiry; use strict; use CGI::Application; use CGI::Application::Plugin::Session; @TestAppExpiry::ISA = qw(CGI::Application); sub cgiapp_init { my $self = shift; my $sid = $self->query->cookie('CGISESSID'); $self->session_config( CGI_SESSION_OPTIONS => [ "driver:File", $sid, {Directory=>'t/'} ], DEFAULT_EXPIRY => $ENV{DEFAULT_EXPIRY}, ); } sub setup { my $self = shift; $self->start_mode('test_mode'); $self->run_modes(test_mode => 'test_mode' ); } sub test_mode { my $self = shift; my $output = ''; my $session = $self->session; $output .= "session expiry: (".$session->expires.")\n"; return $output; } 1; CGI-Application-Plugin-Session-1.05/t/05_sid.t0000644000175000017500000000275412255350127017374 0ustar frewfrewuse Test::More tests => 10; use File::Spec; BEGIN { use_ok('CGI::Application::Plugin::Session') }; use lib './t'; use strict; $ENV{CGI_APP_RETURN_ONLY} = 1; use CGI; use TestAppSid; my $t1_obj = TestAppSid->new(QUERY=>CGI->new()); my $t1_output = $t1_obj->run(); like($t1_output, qr/session created/, 'session created'); like($t1_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'session cookie set'); my ($id1) = $t1_output =~ /id=([a-zA-Z0-9]+)/s; ok($id1, 'found session id'); # Session object will not dissapear and be written # to disk until it is DESTROYed undef $t1_obj; # Set a cookie in $ENV{HTTP_COOKIE} $ENV{HTTP_COOKIE} = CGI::Session->name.'='.$id1; my $t2_obj = TestAppSid->new(QUERY=>CGI->new()); my $t2_output = $t2_obj->run(); like($t2_output, qr/session found/, 'session found'); like($t2_output, qr/value=test1/, 'session parameter retrieved'); unlike($t2_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'session cookie not set'); undef $t2_obj; unlink File::Spec->catdir('t', 'cgisess_'.$id1); # test with an expired cookie $ENV{HTTP_COOKIE} = CGI::Session->name.'=badsessionid'; my $t3_obj = TestAppSid->new(QUERY=>CGI->new()); my $t3_output = $t3_obj->run(); like($t3_output, qr/session created/, 'session created'); unlike($t3_output, qr/value=test1/, 'session parameter not found'); like($t3_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'session cookie set'); my ($id3) = $t3_output =~ /id=([a-zA-Z0-9]+)/s; undef $t3_obj; unlink File::Spec->catdir('t', 'cgisess_'.$id3); CGI-Application-Plugin-Session-1.05/t/release-pod-syntax.t0000644000175000017500000000045012255350127022024 0ustar frewfrew#!perl BEGIN { unless ($ENV{RELEASE_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for release candidate testing'); } } use Test::More; eval "use Test::Pod 1.41"; plan skip_all => "Test::Pod 1.41 required for testing POD" if $@; all_pod_files_ok(); CGI-Application-Plugin-Session-1.05/t/03_nocookie.t0000644000175000017500000000121112255350127020404 0ustar frewfrewuse Test::More tests => 4; use File::Spec; BEGIN { use_ok('CGI::Application::Plugin::Session') }; use lib './t'; use strict; $ENV{CGI_APP_RETURN_ONLY} = 1; use CGI; use TestAppNoCookie; my $t1_obj = TestAppNoCookie->new(QUERY=>CGI->new()); my $t1_output = $t1_obj->run(); like($t1_output, qr/session created/, 'session created'); unlike($t1_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'session cookie not set'); my ($id1) = $t1_output =~ /id=([a-zA-Z0-9]+)/s; ok($id1, 'found session id'); # Session object will not dissapear and be written # to disk until it is DESTROYed undef $t1_obj; unlink File::Spec->catdir('t', 'cgisess_'.$id1); CGI-Application-Plugin-Session-1.05/t/TestAppCGISimple.pm0000644000175000017500000000144512255350127021533 0ustar frewfrewpackage TestAppCGISimple; use strict; use CGI::Application; use CGI::Application::Plugin::Session; @TestAppCGISimple::ISA = qw(CGI::Application); sub cgiapp_init { my $self = shift; $self->session_config(CGI_SESSION_OPTIONS => [ "driver:File", $self->query, {Directory=>'t/'} ]); } sub setup { my $self = shift; $self->start_mode('test_mode'); $self->run_modes(test_mode => 'test_mode' ); } sub test_mode { my $self = shift; my $output = ''; my $session = $self->session; $output .= $session->is_new ? "session created\n" : "session found\n"; my $value = $session->param('value') || ""; $output .= "value=$value\n"; $output .= "id=".$session->id."\n"; $output .= "query=".ref($self->query)."\n"; $session->param('value' => 'test1'); return $output; } 1; CGI-Application-Plugin-Session-1.05/t/02_cookie.t0000644000175000017500000000155612255350127020062 0ustar frewfrewuse Test::More tests => 7; use File::Spec; BEGIN { use_ok('CGI::Application::Plugin::Session') }; use lib './t'; use strict; $ENV{CGI_APP_RETURN_ONLY} = 1; use CGI; use TestAppCookie; my $t1_obj = TestAppCookie->new(QUERY=>CGI->new()); my $t1_output = $t1_obj->run(); like($t1_output, qr/session created/, 'session created'); like($t1_output, qr/Set-Cookie: CGISESSID=[a-zA-Z0-9]+/, 'session cookie set'); my ($id1) = $t1_output =~ /id=([a-zA-Z0-9]+)/s; ok($id1, 'found session id'); # check domain like($t1_output, qr/domain=mydomain.com;/, 'domain found in cookie'); # check path like($t1_output, qr/path=\/testpath;/, 'path found in cookie'); # check domain like($t1_output, qr/expires=/, 'expires found in cookie'); # Session object will not disappear and be written # to disk until it is DESTROYed undef $t1_obj; unlink File::Spec->catdir('t', 'cgisess_'.$id1);