File Coverage

blib/lib/CGI/Easy/Session.pm
Criterion Covered Total %
statement 48 49 97.9
branch 6 8 75.0
condition 8 9 88.8
subroutine 10 10 100.0
pod 2 2 100.0
total 74 78 94.8


line stmt bran cond sub pod time code
1             package CGI::Easy::Session;
2              
3 3     3   6085 use warnings;
  3         6  
  3         90  
4 3     3   16 use strict;
  3         5  
  3         77  
5 3     3   14 use Carp;
  3         6  
  3         159  
6              
7 3     3   13 use version; our $VERSION = qv('1.0.0'); # REMINDER: update Changes
  3         4  
  3         17  
8              
9             # REMINDER: update dependencies in Makefile.PL
10 3     3   2676 use Data::UUID;
  3         4138  
  3         224  
11 3     3   530 use CGI::Easy::Util qw( quote_list unquote_hash );
  3         6  
  3         23  
12              
13 3     3   1932 use constant SESSION_EXPIRE => 365*24*60*60; # 1 year
  3         6  
  3         1503  
14              
15             my $UG;
16              
17              
18             sub new {
19 11     11 1 77 my ($class, $r, $h) = @_;
20 11         51 my $self = {
21             id => undef,
22             perm => undef,
23             temp => undef,
24             _r => $r,
25             _h => $h,
26             };
27 11         29 bless $self, $class;
28 11         26 $self->_init;
29 11         264 return $self;
30             }
31              
32             sub _init {
33 11     11   14 my ($self) = @_;
34 11         25 my $r = $self->{_r};
35 11         16 my $c = $r->{cookie};
36 11 50       26 if ($c->{sid}) {
37 0         0 $self->{id} = $c->{sid};
38             }
39             else {
40 11   100     53 my $referer = $r->{ENV}{HTTP_REFERER} || q{};
41 11 100       154 if ($referer !~ m{\A\w+://\Q$r->{host}\E[:/]}xms) {
42 10   66     228 $UG ||= Data::UUID->new();
43 10         269 $self->{id} = $UG->create_b64();
44             }
45             }
46 11 100       32 if ($self->{id}) {
47 10         71 $self->{_h}->add_cookie({
48             name => 'sid',
49             value => $self->{id},
50             expires => time + SESSION_EXPIRE,
51             });
52             }
53 11   100     50 $self->{perm} = unquote_hash($c->{perm}) || {};
54 11   100     46 $self->{temp} = unquote_hash($c->{temp}) || {};
55 11         25 return;
56             }
57              
58             sub save {
59 2     2 1 900 my ($self) = @_;
60 2         5 my $h = $self->{_h};
61 2 50       20 my @other_cookies = grep {$_->{name} ne 'perm' && $_->{name} ne 'temp'}
  2         5  
62 2         4 @{ $h->{'Set-Cookie'} };
63 2         17 $h->{'Set-Cookie'} = [
64             @other_cookies,
65             {
66             name => 'perm',
67 2         10 value => quote_list(%{ $self->{perm} }),
68             expires => time + SESSION_EXPIRE,
69             },
70             {
71             name => 'temp',
72 2         7 value => quote_list(%{ $self->{temp} }),
73             },
74             ];
75 2         8 return;
76             }
77              
78              
79             1; # Magic true value required at end of module
80             __END__
81              
82             =encoding utf8
83              
84             =head1 NAME
85              
86             CGI::Easy::Session - Support unique session ID and session data in cookies
87              
88              
89             =head1 SYNOPSIS
90              
91             use CGI::Easy::Request;
92             use CGI::Easy::Headers;
93             use CGI::Easy::Session;
94              
95             my $r = CGI::Easy::Request->new();
96             my $h = CGI::Easy::Headers->new();
97             my $sess = CGI::Easy::Session->new($r, $h);
98              
99             if (defined $sess->{id}) {
100             printf "Session ID: %s\n", $sess->{id};
101             } else {
102             print "User has no cookie support\n";
103             }
104             printf "Permanent var 'a': %s\n", $sess->{perm}{a};
105             printf "Temporary var 'a': %s\n", $sess->{temp}{a};
106              
107             $sess->{perm}{b} = 'data';
108             $sess->{temp}{answer} = 42;
109             $sess->save(); # BEFORE $h->compose()
110              
111              
112             =head1 DESCRIPTION
113              
114             Manage session for CGI applications.
115              
116             Detect is user has cookie support.
117             Generate unique session ID for each user.
118             Store persistent and temporary (until browser closes) data in cookies.
119              
120             This module will set cookies C< sid >, C< perm > and C< temp >, so you
121             shouldn't use cookies with these names if you using this module.
122              
123              
124             =head1 INTERFACE
125              
126             =over
127              
128             =item new( $r, $h )
129              
130             Take $r (CGI::Easy::Request object) and $h (CGI::Easy::Headers object)
131             and create new CGI::Easy::Session object with these public fields:
132              
133             id STRING (unique session ID or undef if no cookie support)
134             perm HASHREF (simple hash with scalar-only values)
135             temp HASHREF (simple hash with scalar-only values)
136              
137             You can both read existing session data in {perm} and {temp} and
138             add/update new data there, but keep in mind overall cookie size is limited
139             (usual limit is few kilobytes and it differ between browsers).
140             After changing {perm} or {temp} don't forget to call save().
141              
142             Complex data structures in {perm} and {temp} doesn't supported (you can
143             manually pack/unpack them using any data serialization tool).
144              
145             Will set cookie "sid" (with session ID) in 'Set-Cookie' header, which will
146             expire in 1 YEAR after last visit.
147              
148             Return created CGI::Easy::Session object.
149              
150              
151             =item save()
152              
153             Set/update 'Set-Cookie' header with current {perm} and {temp} values.
154             Should be called before sending reply to user (with C<< $h->compose() >>)
155             if {perm} or {temp} was modified.
156              
157             Cookie "perm" (with hash {perm} data) will expire in 1 YEAR after last visit.
158             Cookie "temp" (with hash {temp} data) will expire when browser will be closed.
159              
160             Return nothing.
161              
162              
163             =back
164              
165              
166             =head1 BUGS AND LIMITATIONS
167              
168             No bugs have been reported.
169              
170              
171             =head1 SUPPORT
172              
173             Please report any bugs or feature requests through the web interface at
174             L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=CGI-Easy>.
175             I will be notified, and then you'll automatically be notified of progress
176             on your bug as I make changes.
177              
178             You can also look for information at:
179              
180             =over
181              
182             =item * RT: CPAN's request tracker
183              
184             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=CGI-Easy>
185              
186             =item * AnnoCPAN: Annotated CPAN documentation
187              
188             L<http://annocpan.org/dist/CGI-Easy>
189              
190             =item * CPAN Ratings
191              
192             L<http://cpanratings.perl.org/d/CGI-Easy>
193              
194             =item * Search CPAN
195              
196             L<http://search.cpan.org/dist/CGI-Easy/>
197              
198             =back
199              
200              
201             =head1 AUTHOR
202              
203             Alex Efros C<< <powerman-asdf@ya.ru> >>
204              
205              
206             =head1 LICENSE AND COPYRIGHT
207              
208             Copyright 2009-2010 Alex Efros <powerman-asdf@ya.ru>.
209              
210             This program is distributed under the MIT (X11) License:
211             L<http://www.opensource.org/licenses/mit-license.php>
212              
213             Permission is hereby granted, free of charge, to any person
214             obtaining a copy of this software and associated documentation
215             files (the "Software"), to deal in the Software without
216             restriction, including without limitation the rights to use,
217             copy, modify, merge, publish, distribute, sublicense, and/or sell
218             copies of the Software, and to permit persons to whom the
219             Software is furnished to do so, subject to the following
220             conditions:
221              
222             The above copyright notice and this permission notice shall be
223             included in all copies or substantial portions of the Software.
224              
225             THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
226             EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
227             OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
228             NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
229             HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
230             WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
231             FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
232             OTHER DEALINGS IN THE SOFTWARE.
233