File Coverage

blib/lib/CGI/Session.pm
Criterion Covered Total %
statement 243 314 77.3
branch 116 170 68.2
condition 33 64 51.5
subroutine 38 45 84.4
pod 23 29 79.3
total 453 622 72.8


line stmt bran cond sub pod time code
1             package CGI::Session;
2 29     29   828964 use strict;
  29         467  
  29         1331  
3 29     29   210 use Carp;
  29         66  
  29         3205  
4 29     29   31334 use CGI::Session::ErrorHandler;
  29         155  
  29         194171  
5              
6             @CGI::Session::ISA = qw( CGI::Session::ErrorHandler );
7             $CGI::Session::VERSION = '4.48';
8             $CGI::Session::NAME = 'CGISESSID';
9             $CGI::Session::IP_MATCH = 0;
10              
11             sub STATUS_UNSET () { 1 << 0 } # denotes session that's resetted
12             sub STATUS_NEW () { 1 << 1 } # denotes session that's just created
13             sub STATUS_MODIFIED () { 1 << 2 } # denotes session that needs synchronization
14             sub STATUS_DELETED () { 1 << 3 } # denotes session that needs deletion
15             sub STATUS_EXPIRED () { 1 << 4 } # denotes session that was expired.
16              
17             sub import {
18 29     29   448 my ($class, @args) = @_;
19              
20 29 100       21593 return unless @args;
21              
22             ARG:
23 6         20 for my $arg (@args) {
24 6 50       4811 if ($arg eq '-ip_match') {
25 0         0 $CGI::Session::IP_MATCH = 1;
26 0         0 last ARG;
27             }
28             }
29             }
30              
31             sub new {
32 38     38 1 27502 my ($class, @args) = @_;
33              
34 38         86 my $self;
35 38 100       162 if (ref $class) {
36             #
37             # Called as an object method as in $session->new()...
38             #
39 1         28 $self = bless { %$class }, ref( $class );
40 1         6 $class = ref $class;
41 1         12 $self->_reset_status();
42             #
43             # Object may still have public data associated with it, but we
44             # don't care about that, since we want to leave that to the
45             # client's disposal. However, if new() was requested on an
46             # expired session, we already know that '_DATA' table is
47             # empty, since it was the job of flush() to empty '_DATA'
48             # after deleting. How do we know flush() was already called on
49             # an expired session? Because load() - constructor always
50             # calls flush() on all to-be expired sessions
51             #
52             }
53             else {
54             #
55             # Called as a class method as in CGI::Session->new()
56             #
57              
58             # Start fresh with error reporting. Errors in past objects shouldn't affect this one.
59 37         352 $class->set_error('');
60              
61 37         220 $self = $class->load( @args );
62 37 100       186 if (not defined $self) {
63 6         46 return $class->set_error( "new(): failed: " . $class->errstr );
64             }
65             }
66              
67 32         98 my $dataref = $self->{_DATA};
68 32 100       154 unless ($dataref->{_SESSION_ID}) {
69             #
70             # Absence of '_SESSION_ID' can only signal:
71             # * Expired session: Because load() - constructor is required to
72             # empty contents of _DATA - table
73             # * Unavailable session: Such sessions are the ones that don't
74             # exist on datastore, but are requested by client
75             # * New session: When no specific session is requested to be loaded
76             #
77 27         147 my $id = $self->_id_generator()->generate_id(
78             $self->{_DRIVER_ARGS},
79             $self->{_CLAIMED_ID}
80             );
81 27 50       128 unless (defined $id) {
82 0         0 return $self->set_error( "Couldn't generate new SESSION-ID" );
83             }
84 27         73 $dataref->{_SESSION_ID} = $id;
85 27         99 $dataref->{_SESSION_CTIME} = $dataref->{_SESSION_ATIME} = time();
86 27   100     241 $dataref->{_SESSION_REMOTE_ADDR} = $ENV{REMOTE_ADDR} || "";
87 27         140 $self->_set_status( STATUS_NEW );
88             }
89 32         514 return $self;
90             }
91              
92 50     50   16672 sub DESTROY { $_[0]->flush() }
93 1     1 1 6 sub close { $_[0]->flush() }
94              
95             *param_hashref = \&dataref;
96             my $avoid_single_use_warning = *param_hashref;
97 332     332 1 2010 sub dataref { $_[0]->{_DATA} }
98              
99 4     4 1 19 sub is_empty { !defined($_[0]->id) }
100              
101 7     7 1 36 sub is_expired { $_[0]->_test_status( STATUS_EXPIRED ) }
102              
103 3     3 1 1047 sub is_new { $_[0]->_test_status( STATUS_NEW ) }
104              
105 147 100   147 1 11212 sub id { return defined($_[0]->dataref) ? $_[0]->dataref->{_SESSION_ID} : undef }
106              
107             # Last Access Time
108 6 50   6 1 24 sub atime { return defined($_[0]->dataref) ? $_[0]->dataref->{_SESSION_ATIME} : undef }
109              
110             # Creation Time
111 6 50   6 1 22 sub ctime { return defined($_[0]->dataref) ? $_[0]->dataref->{_SESSION_CTIME} : undef }
112              
113             sub _driver {
114 58     58   134 my $self = shift;
115 58 100       347 defined($self->{_OBJECTS}->{driver}) and return $self->{_OBJECTS}->{driver};
116 36         226 my $pm = "CGI::Session::Driver::" . $self->{_DSN}->{driver};
117 36 50       629 defined($self->{_OBJECTS}->{driver} = $pm->new( $self->{_DRIVER_ARGS} ))
118             or die $pm->errstr();
119 36         121 return $self->{_OBJECTS}->{driver};
120             }
121              
122             sub _serializer {
123 44     44   84 my $self = shift;
124 44 100       199 defined($self->{_OBJECTS}->{serializer}) and return $self->{_OBJECTS}->{serializer};
125 34         280 return $self->{_OBJECTS}->{serializer} = "CGI::Session::Serialize::" . $self->{_DSN}->{serializer};
126             }
127              
128              
129             sub _id_generator {
130 27     27   62 my $self = shift;
131 27 50       179 defined($self->{_OBJECTS}->{id}) and return $self->{_OBJECTS}->{id};
132 27         422 return $self->{_OBJECTS}->{id} = "CGI::Session::ID::" . $self->{_DSN}->{id};
133             }
134              
135             sub ip_matches {
136 0     0 0 0 return ( $_[0]->{_DATA}->{_SESSION_REMOTE_ADDR} eq $ENV{REMOTE_ADDR} );
137             }
138              
139              
140             # parses the DSN string and returns it as a hash.
141             # Notably: Allows unique abbreviations of the keys: driver, serializer and 'id'.
142             # Also, keys and values of the returned hash are lower-cased.
143             sub parse_dsn {
144 31     31 0 191 my $self = shift;
145 31         61 my $dsn_str = shift;
146 31 50       237 croak "parse_dsn(): usage error" unless $dsn_str;
147              
148 31         22168 require Text::Abbrev;
149 31         998 my $abbrev = Text::Abbrev::abbrev( "driver", "serializer", "id" );
150 31         3433 my %dsn_map = map { split /:/ } (split /;/, $dsn_str);
  53         248  
151 31         123 my %dsn = map { $abbrev->{lc $_}, lc $dsn_map{$_} } keys %dsn_map;
  51         497  
152 31         340 return \%dsn;
153             }
154              
155             sub query {
156 29     29 1 67 my $self = shift;
157              
158 29 100       139 if ( $self->{_QUERY} ) {
159 9         59 return $self->{_QUERY};
160             }
161             # require CGI::Session::Query;
162             # return $self->{_QUERY} = CGI::Session::Query->new();
163 20         78408 require CGI;
164 20         325503 return $self->{_QUERY} = CGI->new();
165             }
166              
167              
168             sub name {
169 55     55 1 120412 my $self = shift;
170 55         112 my $name = shift;
171            
172 55 100       241 if (ref $self) {
173 52 50       184 unless ( defined $name ) {
174 52   33     1015 return $self->{_NAME} || $CGI::Session::NAME;
175             }
176 0         0 return $self->{_NAME} = $name;
177             }
178            
179 3 100       9 $CGI::Session::NAME = $name if defined $name;
180 3         13 return $CGI::Session::NAME;
181             }
182              
183              
184             sub dump {
185 0     0 1 0 my $self = shift;
186              
187 0         0 require Data::Dumper;
188 0         0 my $d = Data::Dumper->new([$self], [ref $self]);
189 0         0 $d->Deepcopy(1);
190 0         0 return $d->Dump();
191             }
192              
193              
194             sub _set_status {
195 86     86   163 my $self = shift;
196 86 50       232 croak "_set_status(): usage error" unless @_;
197 86         311 $self->{_STATUS} |= $_[0];
198             }
199              
200              
201             sub _unset_status {
202 35     35   93 my $self = shift;
203 35 50       152 croak "_unset_status(): usage error" unless @_;
204 35         258 $self->{_STATUS} &= ~$_[0];
205             }
206              
207              
208             sub _reset_status {
209 1     1   6 $_[0]->{_STATUS} = STATUS_UNSET;
210             }
211              
212             sub _test_status {
213 227     227   995 return $_[0]->{_STATUS} & $_[1];
214             }
215              
216              
217             sub flush {
218 63     63 1 164 my $self = shift;
219              
220             # Would it be better to die or err if something very basic is wrong here?
221             # I'm trying to address the DESTROY related warning
222             # from: http://rt.cpan.org/Ticket/Display.html?id=17541
223             # return unless defined $self;
224              
225 63 100       215 return unless $self->id; # <-- empty session
226            
227             # neither new, nor deleted nor modified
228 47 100 66     577 return if !defined($self->{_STATUS}) or $self->{_STATUS} == STATUS_UNSET;
229              
230 36 100 100     387 if ( $self->_test_status(STATUS_NEW) && $self->_test_status(STATUS_DELETED) ) {
231 7         22 $self->{_DATA} = {};
232 7         50 return $self->_unset_status(STATUS_NEW | STATUS_DELETED);
233             }
234              
235 29         134 my $driver = $self->_driver();
236 29         117 my $serializer = $self->_serializer();
237              
238 29 100       185 if ( $self->_test_status(STATUS_DELETED) ) {
239 6 50       22 defined($driver->remove($self->id)) or
240             return $self->set_error( "flush(): couldn't remove session data: " . $driver->errstr );
241 6         25 $self->{_DATA} = {}; # <-- removing all the data, making sure
242             # it won't be accessible after flush()
243 6         57 return $self->_unset_status(STATUS_DELETED);
244             }
245              
246 23 100       75 if ( $self->_test_status(STATUS_NEW | STATUS_MODIFIED) ) {
247 22         121 my $datastr = $serializer->freeze( $self->dataref );
248 22 50       2329 unless ( defined $datastr ) {
249 0         0 return $self->set_error( "flush(): couldn't freeze data: " . $serializer->errstr );
250             }
251 22 50       78 defined( $driver->store($self->id, $datastr) ) or
252             return $self->set_error( "flush(): couldn't store datastr: " . $driver->errstr);
253 22         137 $self->_unset_status(STATUS_NEW | STATUS_MODIFIED);
254             }
255 23         165 return 1;
256             }
257              
258 0     0 0 0 sub trace {}
259 0     0 0 0 sub tracemsg {}
260              
261             sub param {
262 102     102 1 530 my ($self, @args) = @_;
263              
264 102 50       297 if ($self->_test_status( STATUS_DELETED )) {
265 0         0 carp "param(): attempt to read/write deleted session";
266             }
267              
268             # USAGE: $s->param();
269             # DESC: Returns all the /public/ parameters
270 102 100       360 if (@args == 0) {
    100          
271 5         7 return grep { !/^_SESSION_/ } keys %{ $self->{_DATA} };
  35         180  
  5         23  
272             }
273             # USAGE: $s->param( $p );
274             # DESC: returns a specific session parameter
275             elsif (@args == 1) {
276 70         812 return $self->{_DATA}->{ $args[0] }
277             }
278              
279              
280             # USAGE: $s->param( -name => $n, -value => $v );
281             # DESC: Updates session data using CGI.pm's 'named param' syntax.
282             # Only public records can be set!
283 27         101 my %args = @args;
284 27         78 my ($name, $value) = @args{ qw(-name -value) };
285 27 100 100     141 if (defined $name && defined $value) {
286 6 50       28 if ($name =~ m/^_SESSION_/) {
287              
288 0         0 carp "param(): attempt to write to private parameter";
289 0         0 return undef;
290             }
291 6         26 $self->_set_status( STATUS_MODIFIED );
292 6         34 return $self->{_DATA}->{ $name } = $value;
293             }
294              
295             # USAGE: $s->param(-name=>$n);
296             # DESC: access to session data (public & private) using CGI.pm's 'named parameter' syntax.
297 21 100       120 return $self->{_DATA}->{ $args{'-name'} } if defined $args{'-name'};
298              
299             # USAGE: $s->param($name, $value);
300             # USAGE: $s->param($name1 => $value1, $name2 => $value2 [,...]);
301             # DESC: updates one or more **public** records using simple syntax
302 17 50       77 if ((@args % 2) == 0) {
303 17         31 my $modified_cnt = 0;
304             ARG_PAIR:
305 17         120 while (my ($name, $val) = each %args) {
306 25 50       84 if ( $name =~ m/^_SESSION_/) {
307 0         0 carp "param(): attempt to write to private parameter";
308 0         0 next ARG_PAIR;
309             }
310 25         68 $self->{_DATA}->{ $name } = $val;
311 25         92 ++$modified_cnt;
312             }
313 17         89 $self->_set_status(STATUS_MODIFIED);
314 17         63 return $modified_cnt;
315             }
316              
317             # If we reached this far none of the expected syntax were
318             # detected. Syntax error
319 0         0 croak "param(): usage error. Invalid syntax";
320             }
321              
322              
323              
324 13     13 1 1299 sub delete { $_[0]->_set_status( STATUS_DELETED ) }
325              
326              
327             *header = \&http_header;
328             my $avoid_single_use_warning_again = *header;
329             sub http_header {
330 2     2 0 8252 my $self = shift;
331 2         8 return $self->query->header(-cookie=>$self->cookie, -type=>'text/html', @_);
332             }
333              
334             sub cookie {
335 2     2 1 3 my $self = shift;
336              
337 2         5 my $query = $self->query();
338 2         4 my $cookie= undef;
339              
340 2 50       7 if ( $self->is_expired ) {
    50          
341 0         0 $cookie = $query->cookie( -name=>$self->name, -value=>$self->id, -expires=> '-1d', @_ );
342             }
343             elsif ( my $t = $self->expire ) {
344 0         0 $cookie = $query->cookie( -name=>$self->name, -value=>$self->id, -expires=> '+' . $t . 's', @_ );
345             }
346             else {
347 2         7 $cookie = $query->cookie( -name=>$self->name, -value=>$self->id, @_ );
348             }
349 2         539 return $cookie;
350             }
351              
352              
353              
354              
355              
356             sub save_param {
357 0     0 1 0 my $self = shift;
358 0         0 my ($query, $params) = @_;
359              
360 0   0     0 $query ||= $self->query();
361 0   0     0 $params ||= [ $query->param ];
362              
363 0         0 for my $p ( @$params ) {
364 0 0       0 my @values = $query->param($p) or next;
365 0 0       0 if ( @values > 1 ) {
366 0         0 $self->param($p, \@values);
367             } else {
368 0         0 $self->param($p, $values[0]);
369             }
370             }
371 0         0 $self->_set_status( STATUS_MODIFIED );
372             }
373              
374              
375              
376             sub load_param {
377 0     0 1 0 my $self = shift;
378 0         0 my ($query, $params) = @_;
379              
380 0   0     0 $query ||= $self->query();
381 0   0     0 $params ||= [ $self->param ];
382              
383 0         0 for ( @$params ) {
384 0         0 $query->param(-name=>$_, -value=>$self->param($_));
385             }
386             }
387              
388              
389             sub clear {
390 0     0 1 0 my $self = shift;
391 0         0 my $params = shift;
392             #warn ref($params);
393 0 0       0 if (defined $params) {
394 0 0       0 $params = [ $params ] unless ref $params;
395             }
396             else {
397 0         0 $params = [ $self->param ];
398             }
399              
400 0         0 for ( grep { ! /^_SESSION_/ } @$params ) {
  0         0  
401 0         0 delete $self->{_DATA}->{$_};
402             }
403 0         0 $self->_set_status( STATUS_MODIFIED );
404             }
405              
406              
407             sub find {
408 1     1 1 14 my $class = shift;
409 1         2 my ($dsn, $coderef, $dsn_args);
410              
411             # find( \%code )
412 1 50       5 if ( @_ == 1 ) {
413 0         0 $coderef = $_[0];
414             }
415             # find( $dsn, \&code, \%dsn_args )
416             else {
417 1         3 ($dsn, $coderef, $dsn_args) = @_;
418             }
419              
420 1 50 33     17 unless ( $coderef && ref($coderef) && (ref $coderef eq 'CODE') ) {
      33        
421 0         0 croak "find(): usage error.";
422             }
423              
424 1         3 my $driver;
425 1 50       4 if ( $dsn ) {
426 0         0 my $hashref = $class->parse_dsn( $dsn );
427 0         0 $driver = $hashref->{driver};
428             }
429 1   50     7 $driver ||= "file";
430 1         8 my $pm = "CGI::Session::Driver::" . ($driver =~ /(.*)/)[0];
431 1         88 eval "require $pm";
432 1 50       8 if (my $errmsg = $@ ) {
433 0         0 return $class->set_error( "find(): couldn't load driver." . $errmsg );
434             }
435              
436 1         11 my $driver_obj = $pm->new( $dsn_args );
437 1 50       5 unless ( $driver_obj ) {
438 0         0 return $class->set_error( "find(): couldn't create driver object. " . $pm->errstr );
439             }
440              
441             # Read-only isn't the perfect name here. In read-only mode, we skip the ip_match check,
442             # and don't update the atime. We *do* still delete expired sessions and session params.
443 1         3 my $read_only = 1;
444             my $driver_coderef = sub {
445 1     1   5 my ($sid) = @_;
446 1         7 my $session = $class->load( $dsn, $sid, $dsn_args, $read_only );
447 1 50       4 unless ( $session ) {
448 1         7 return $class->set_error( "find(): couldn't load session '$sid'. " . $class->errstr );
449             }
450 0         0 $coderef->( $session );
451 1         8 };
452              
453 1 50       7 defined($driver_obj->traverse( $driver_coderef ))
454             or return $class->set_error( "find(): traverse seems to have failed. " . $driver_obj->errstr );
455 1         10 return 1;
456             }
457              
458             # $Id$
459              
460             =pod
461              
462             =head1 NAME
463              
464             CGI::Session - persistent session data in CGI applications
465              
466             =head1 SYNOPSIS
467              
468             # Object initialization:
469             use CGI::Session;
470             $session = CGI::Session->new();
471              
472             $CGISESSID = $session->id();
473              
474             # Send proper HTTP header with cookies:
475             print $session->header();
476              
477             # Storing data in the session:
478             $session->param('f_name', 'Sherzod');
479             # or
480             $session->param(-name=>'l_name', -value=>'Ruzmetov');
481              
482             # Flush the data from memory to the storage driver at least before your
483             # program finishes since auto-flushing can be unreliable.
484             $session->flush();
485              
486             # Retrieving data:
487             my $f_name = $session->param('f_name');
488             # or
489             my $l_name = $session->param(-name=>'l_name');
490              
491             # Clearing a certain session parameter:
492             $session->clear(["l_name", "f_name"]);
493              
494             # Expire '_is_logged_in' flag after 10 idle minutes:
495             $session->expire('is_logged_in', '+10m')
496              
497             # Expire the session itself after 1 idle hour:
498             $session->expire('+1h');
499              
500             # Delete the session for good:
501             $session->delete();
502             $session->flush(); # Recommended practice says use flush() after delete().
503              
504             =head1 DESCRIPTION
505              
506             CGI::Session provides an easy, reliable and modular session management system across HTTP requests.
507              
508             =head1 METHODS
509              
510             Following is the overview of all the available methods accessible via CGI::Session object.
511              
512             =head2 new()
513              
514             =head2 new( $sid )
515              
516             =head2 new( $query )
517              
518             =head2 new( $dsn, $query||$sid )
519              
520             =head2 new( $dsn, $query||$sid, \%dsn_args )
521              
522             =head2 new( $dsn, $query||$sid, \%dsn_args, \%session_params )
523              
524             Constructor. Returns new session object, or undef on failure. Error message is accessible through L<errstr() - class method|CGI::Session::ErrorHandler/"errstr()">. If called on an already initialized session will re-initialize the session based on already configured object. This is only useful after a call to L<load()|/"load()">.
525              
526             Can accept up to three arguments, $dsn - Data Source Name, $query||$sid - query object OR a string representing session id, and finally, \%dsn_args, arguments used by $dsn components.
527              
528             If called without any arguments, $dsn defaults to I<driver:file;serializer:default;id:md5>, $query||$sid defaults to C<< CGI->new() >>, and C<\%dsn_args> defaults to I<undef>.
529              
530             If called with a single argument, it will be treated either as C<$query> object, or C<$sid>, depending on its type. If argument is a string , C<new()> will treat it as session id and will attempt to retrieve the session from data store. If it fails, will create a new session id, which will be accessible through L<id() method|/"id">. If argument is an object, L<cookie()|CGI/cookie> and L<param()|CGI/param> methods will be called on that object to recover a potential C<$sid> and retrieve it from data store. If it fails, C<new()> will create a new session id, which will be accessible through L<id() method|/"id">. C<name()> will define the name of the query parameter and/or cookie name to be requested, defaults to I<CGISESSID>.
531              
532             If called with two arguments first will be treated as $dsn, and second will be treated as $query or $sid or undef, depending on its type. Some examples of this syntax are:
533              
534             $s = CGI::Session->new("driver:mysql", undef);
535             $s = CGI::Session->new("driver:sqlite", $sid);
536             $s = CGI::Session->new("driver:db_file", $query);
537             $s = CGI::Session->new("serializer:storable;id:incr", $sid);
538             # etc...
539              
540             Briefly, C<new()> will return an initialized session object with a valid id, whereas C<load()> may return
541             an empty session object with an undefined id.
542              
543             Tests are provided (t/new_with_undef.t and t/load_with_undef.t) to clarify the result of calling C<new()> and C<load()>
544             with undef, or with an initialized CGI object with an undefined or fake CGISESSID.
545              
546             You are strongly advised to run the old-fashioned 'make test TEST_FILES=t/new_with_undef.t TEST_VERBOSE=1'
547             or the new-fangled 'prove -v t/new_with_undef.t', for both new*.t and load*.t, and examine the output.
548              
549             Following data source components are supported:
550              
551             =over 4
552              
553             =item *
554              
555             B<driver> - CGI::Session driver. Available drivers are L<file|CGI::Session::Driver::file>, L<db_file|CGI::Session::Driver::db_file>, L<mysql|CGI::Session::Driver::mysql> and L<sqlite|CGI::Session::Driver::sqlite>. Third party drivers are welcome. For driver specs consider L<CGI::Session::Driver|CGI::Session::Driver>
556              
557             =item *
558              
559             B<serializer> - serializer to be used to encode the data structure before saving
560             in the disk. Available serializers are L<storable|CGI::Session::Serialize::storable>, L<freezethaw|CGI::Session::Serialize::freezethaw> and L<default|CGI::Session::Serialize::default>. Default serializer will use L<Data::Dumper|Data::Dumper>.
561              
562             =item *
563              
564             B<id> - ID generator to use when new session is to be created. Available ID generator is L<md5|CGI::Session::ID::md5>
565              
566             =back
567              
568             For example, to get CGI::Session store its data using DB_File and serialize data using FreezeThaw:
569              
570             $s = CGI::Session->new("driver:DB_File;serializer:FreezeThaw", undef);
571              
572             If called with three arguments, first two will be treated as in the previous example, and third argument will be C<\%dsn_args>, which will be passed to C<$dsn> components (namely, driver, serializer and id generators) for initialization purposes. Since all the $dsn components must initialize to some default value, this third argument should not be required for most drivers to operate properly.
573              
574             If called with four arguments, the first three match previous examples. The fourth argument must be a hash reference with parameters to be used by the CGI::Session object. (see \%session_params above )
575              
576             The following is a list of the current keys:
577              
578             =over
579              
580             =item *
581              
582             B<name> - Name to use for the cookie/query parameter name. This defaults to CGISESSID. This can be altered or accessed by the C<name> accessor.
583              
584             =back
585              
586             undef is acceptable as a valid placeholder to any of the above arguments, which will force default behavior.
587              
588             =head2 load()
589              
590             =head2 load( $query||$sid )
591              
592             =head2 load( $dsn, $query||$sid )
593              
594             =head2 load( $dsn, $query, \%dsn_args )
595              
596             =head2 load( $dsn, $query, \%dsn_args, \%session_params )
597              
598             Accepts the same arguments as new(), and also returns a new session object, or
599             undef on failure. The difference is, L<new()|/"new()"> can create a new session if
600             it detects expired and non-existing sessions, but C<load()> does not.
601              
602             C<load()> is useful to detect expired or non-existing sessions without forcing the library to create new sessions. So now you can do something like this:
603              
604             $s = CGI::Session->load() or die CGI::Session->errstr();
605             if ( $s->is_expired ) {
606             print $s->header(),
607             $cgi->start_html(),
608             $cgi->p("Your session timed out! Refresh the screen to start new session!")
609             $cgi->end_html();
610             exit(0);
611             }
612              
613             if ( $s->is_empty ) {
614             $s = $s->new() or die $s->errstr;
615             }
616              
617             Notice: All I<expired> sessions are empty, but not all I<empty> sessions are expired!
618              
619             Briefly, C<new()> will return an initialized session object with a valid id, whereas C<load()> may return
620             an empty session object with an undefined id.
621              
622             Tests are provided (t/new_with_undef.t and t/load_with_undef.t) to clarify the result of calling C<new()> and C<load()>
623             with undef, or with an initialized CGI object with an undefined or fake CGISESSID.
624              
625             You are strongly advised to run the old-fashioned 'make test TEST_FILES=t/new_with_undef.t TEST_VERBOSE=1'
626             or the new-fangled 'prove -v t/new_with_undef.t', for both new*.t and load*.t, and examine the output.
627              
628             =cut
629              
630             # pass a true value as the fourth parameter if you want to skip the changing of
631             # access time This isn't documented more formally, because it only called by
632             # find().
633             sub load {
634 50     50 1 1313 my $class = shift;
635 50 100       234 return $class->set_error( "called as instance method") if ref $class;
636 49 50       196 return $class->set_error( "Too many arguments provided to load()") if @_ > 5;
637              
638 49   100     1308 my $self = bless {
639             _DATA => {
640             _SESSION_ID => undef,
641             _SESSION_CTIME => undef,
642             _SESSION_ATIME => undef,
643             _SESSION_REMOTE_ADDR => $ENV{REMOTE_ADDR} || "",
644             #
645             # Following two attributes may not exist in every single session, and declaring
646             # them now will force these to get serialized into database, wasting space. But they
647             # are here to remind the coder of their purpose
648             #
649             # _SESSION_ETIME => undef,
650             # _SESSION_EXPIRE_LIST => {}
651             }, # session data
652             _DSN => {}, # parsed DSN params
653             _OBJECTS => {}, # keeps necessary objects
654             _DRIVER_ARGS=> {}, # arguments to be passed to driver
655             _CLAIMED_ID => undef, # id **claimed** by client
656             _STATUS => STATUS_UNSET,# status of the session object
657             _QUERY => undef # query object
658             }, $class;
659              
660 49         114 my ($dsn,$query_or_sid,$dsn_args,$read_only,$params);
661             # load($query||$sid)
662 49 100       261 if ( @_ == 1 ) {
    100          
663 8         38 $self->_set_query_or_sid($_[0]);
664             }
665             # Two or more args passed:
666             # load($dsn, $query||$sid)
667             elsif ( @_ > 1 ) {
668 32         110 ($dsn, $query_or_sid, $dsn_args,$read_only) = @_;
669              
670             # Make it backwards-compatible (update_atime is an undocumented key in %$params).
671             # In fact, update_atime as a key is not used anywhere in the code as yet.
672             # This patch is part of the patch for RT#33437.
673 32 50 33     176 if ( ref $read_only and ref $read_only eq 'HASH' ) {
674 0         0 $params = {%$read_only};
675 0         0 $read_only = $params->{'read_only'};
676              
677 0 0       0 if ($params->{'name'}) {
678 0         0 $self->{_NAME} = $params->{'name'};
679             }
680             }
681              
682             # Since $read_only is not part of the public API
683             # we ignore any value but the one we use internally: 1.
684 32 100 100     141 if (defined $read_only and $read_only != '1') {
685 1         14 return $class->set_error( "Too many arguments to load(). First extra argument was: $read_only");
686             }
687              
688 31 100       102 if ( defined $dsn ) { # <-- to avoid 'Uninitialized value...' warnings
689 27         140 $self->{_DSN} = $self->parse_dsn($dsn);
690             }
691 31         147 $self->_set_query_or_sid($query_or_sid);
692              
693             # load($dsn, $query, \%dsn_args);
694              
695 31 50       129 $self->{_DRIVER_ARGS} = $dsn_args if defined $dsn_args;
696              
697             }
698              
699 48         210 $self->_load_pluggables();
700              
701             # Did load_pluggable fail? If so, return undef, just like $class->set_error() would
702 48 100       744 return undef if $class->errstr;
703              
704 47 100       259 if (not defined $self->{_CLAIMED_ID}) {
705 25         125 my $query = $self->query();
706 25         104804 eval {
707 25   66     151 $self->{_CLAIMED_ID} = $query->cookie( $self->name ) || $query->param( $self->name );
708             };
709 25 50       852 if ( my $errmsg = $@ ) {
710 0         0 return $class->set_error( "query object $query does not support cookie() and param() methods: " . $errmsg );
711             }
712             }
713              
714             # No session is being requested. Just return an empty session
715 47 100       260 return $self unless $self->{_CLAIMED_ID};
716              
717             # Attempting to load the session
718 24         199 my $driver = $self->_driver();
719 24         143 my $raw_data = $driver->retrieve( $self->{_CLAIMED_ID} );
720 24 50       95 unless ( defined $raw_data ) {
721 0         0 return $self->set_error( "load(): couldn't retrieve data: " . $driver->errstr );
722             }
723            
724             # Requested session couldn't be retrieved
725 24 100       99 return $self unless $raw_data;
726              
727 15         139 my $serializer = $self->_serializer();
728 15         150 $self->{_DATA} = $serializer->thaw($raw_data);
729 15 100       402 unless ( defined $self->{_DATA} ) {
730             #die $raw_data . "\n";
731 8         178 return $self->set_error( "load(): couldn't thaw() data using $serializer:" .
732             $serializer->errstr );
733             }
734 7 50 33     116 unless (defined($self->{_DATA}) && ref ($self->{_DATA}) && (ref $self->{_DATA} eq 'HASH') &&
      33        
      33        
735             defined($self->{_DATA}->{_SESSION_ID}) ) {
736 0         0 return $self->set_error( "Invalid data structure returned from thaw()" );
737             }
738              
739              
740             # checking for expiration ticker
741 7 100       103 if ( $self->{_DATA}->{_SESSION_ETIME} ) {
742 3 100       17 if ( ($self->{_DATA}->{_SESSION_ATIME} + $self->{_DATA}->{_SESSION_ETIME}) <= time() ) {
743 1         8 $self->_set_status( STATUS_EXPIRED | # <-- so client can detect expired sessions
744             STATUS_DELETED ); # <-- session should be removed from database
745 1         5 $self->flush(); # <-- flush() will do the actual removal!
746 1         8 return $self;
747             }
748             }
749              
750             # checking expiration tickers of individuals parameters, if any:
751 6         17 my @expired_params = ();
752 6 50       25 if ( $self->{_DATA}->{_SESSION_EXPIRE_LIST} ) {
753 0         0 while (my ($param, $max_exp_interval) = each %{ $self->{_DATA}->{_SESSION_EXPIRE_LIST} } ) {
  0         0  
754 0 0       0 if ( ($self->{_DATA}->{_SESSION_ATIME} + $max_exp_interval) <= time() ) {
755 0         0 push @expired_params, $param;
756             }
757             }
758             }
759 6 50       28 $self->clear(\@expired_params) if @expired_params;
760              
761              
762              
763 6 50       22 if (not defined $read_only) {
764             # checking if previous session ip matches current ip
765 6 50       21 if($CGI::Session::IP_MATCH) {
766 0 0       0 unless($self->ip_matches) {
767 0         0 $self->_set_status( STATUS_DELETED );
768 0         0 $self->flush;
769 0         0 return $self;
770             }
771             }
772              
773 6         14 $self->{_DATA}->{_SESSION_ATIME} = time(); # <-- updating access time
774 6         27 $self->_set_status( STATUS_MODIFIED ); # <-- access time modified above
775             }
776            
777 6         21 return $self;
778             }
779              
780              
781             # set the input as a query object or session ID, depending on what it looks like.
782             sub _set_query_or_sid {
783 39     39   93 my $self = shift;
784 39         76 my $query_or_sid = shift;
785 39 100       175 if ( ref $query_or_sid){ $self->{_QUERY} = $query_or_sid }
  5         16  
786 34         127 else { $self->{_CLAIMED_ID} = $query_or_sid }
787             }
788              
789              
790             sub _load_pluggables {
791 48     48   97 my ($self) = @_;
792              
793 48         538 my %DEFAULT_FOR = (
794             driver => "file",
795             serializer => "default",
796             id => "md5",
797             );
798 48         202 my %SUBDIR_FOR = (
799             driver => "Driver",
800             serializer => "Serialize",
801             id => "ID",
802             );
803 48         191 my $dsn = $self->{_DSN};
804 48         166 for my $plug (qw(driver serializer id)) {
805 144         389 my $mod_name = $dsn->{ $plug };
806 144 100       537 if (not defined $mod_name) {
807 99         250 $mod_name = $DEFAULT_FOR{ $plug };
808             }
809 144 50       1205 if ($mod_name =~ /^(\w+)$/) {
810              
811             # Looks good. Put it into the dsn hash
812 144         662 $dsn->{ $plug } = $mod_name = $1;
813              
814             # Put together the actual module name to load
815 144         625 my $prefix = join '::', (__PACKAGE__, $SUBDIR_FOR{ $plug }, q{});
816 144         337 $mod_name = $prefix . $mod_name;
817              
818             ## See if we can load load it
819 144         9791 eval "require $mod_name";
820 144 50       1073 if ($@) {
821 0         0 my $msg = $@;
822 0         0 return $self->set_error("couldn't load $mod_name: " . $msg);
823             }
824             }
825             else {
826             # do something here about bad name for a pluggable
827             }
828             }
829 48         596 return;
830             }
831              
832             =pod
833              
834             =head2 id()
835              
836             Returns effective ID for a session. Since effective ID and claimed ID can differ, valid session id should always
837             be retrieved using this method.
838              
839             =head2 param($name)
840              
841             =head2 param(-name=E<gt>$name)
842              
843             Used in either of the above syntax returns a session parameter set to $name or undef if it doesn't exist. If it's called on a deleted method param() will issue a warning but return value is not defined.
844              
845             =head2 param($name, $value)
846              
847             =head2 param(-name=E<gt>$name, -value=E<gt>$value)
848              
849             Used in either of the above syntax assigns a new value to $name parameter,
850             which can later be retrieved with previously introduced param() syntax. C<$value>
851             may be a scalar, arrayref or hashref.
852              
853             Attempts to set parameter names that start with I<_SESSION_> will trigger
854             a warning and undef will be returned.
855              
856             =head2 param_hashref()
857              
858             B<Deprecated>. Use L<dataref()|/"dataref()"> instead.
859              
860             =head2 dataref()
861              
862             Returns reference to session's data table:
863              
864             $params = $s->dataref();
865             $sid = $params->{_SESSION_ID};
866             $name= $params->{name};
867             # etc...
868              
869             Useful for having all session data in a hashref, but too risky to update.
870              
871             =head2 save_param()
872              
873             =head2 save_param($query)
874              
875             =head2 save_param($query, \@list)
876              
877             Saves query parameters to session object. In other words, it's the same as calling L<param($name, $value)|/"param($name)"> for every single query parameter returned by C<< $query->param() >>. The first argument, if present, should be either CGI object or any object which can provide param() method. If it's undef, defaults to the return value of L<query()|/"query()">, which returns C<< CGI->new >>. If second argument is present and is a reference to an array, only those query parameters found in the array will be stored in the session. undef is a valid placeholder for any argument to force default behavior.
878              
879             =head2 load_param()
880              
881             =head2 load_param($query)
882              
883             =head2 load_param($query, \@list)
884              
885             Loads session parameters into a query object. The first argument, if present, should be query object, or any other object which can provide param() method. If second argument is present and is a reference to an array, only parameters found in that array will be loaded to the query object.
886              
887             =head2 clear()
888              
889             =head2 clear('field')
890              
891             =head2 clear(\@list)
892              
893             Clears parameters from the session object.
894              
895             With no parameters, all fields are cleared. If passed a single parameter or a
896             reference to an array, only the named parameters are cleared.
897              
898             =head2 flush()
899              
900             Synchronizes data in memory with the copy serialized by the driver. Call flush()
901             if you need to access the session from outside the current session object. You should
902             call flush() sometime before your program exits.
903              
904             As a last resort, CGI::Session will automatically call flush for you just
905             before the program terminates or session object goes out of scope. Automatic
906             flushing has proven to be unreliable, and in some cases is now required
907             in places that worked with CGI::Session 3.x.
908              
909             Always explicitly calling C<flush()> on the session before the
910             program exits is recommended. For extra safety, call it immediately after
911             every important session update.
912              
913             Also see L<A Warning about Auto-flushing>
914              
915             =head2 atime()
916              
917             Read-only method. Returns the last access time of the session in seconds from epoch. This time is used internally while
918             auto-expiring sessions and/or session parameters.
919              
920             =head2 ctime()
921              
922             Read-only method. Returns the time when the session was first created in seconds from epoch.
923              
924             =head2 expire()
925              
926             =head2 expire($time)
927              
928             =head2 expire($param, $time)
929              
930             Sets expiration interval relative to L<atime()|/"atime()">.
931              
932             If used with no arguments, returns the expiration interval if it was ever set. If no expiration was ever set, returns undef. For backwards compatibility, a method named C<etime()> does the same thing.
933              
934             Second form sets an expiration time. This value is checked when previously stored session is asked to be retrieved, and if its expiration interval has passed, it will be expunged from the disk immediately. Passing 0 cancels expiration.
935              
936             By using the third syntax you can set the expiration interval for a particular
937             session parameter, say I<~logged-in>. This would cause the library call clear()
938             on the parameter when its time is up. Note it only makes sense to set this value to
939             something I<earlier> than when the whole session expires. Passing 0 cancels expiration.
940              
941             All the time values should be given in the form of seconds. Following keywords are also supported for your convenience:
942              
943             +-----------+---------------+
944             | alias | meaning |
945             +-----------+---------------+
946             | s | Second |
947             | m | Minute |
948             | h | Hour |
949             | d | Day |
950             | w | Week |
951             | M | Month |
952             | y | Year |
953             +-----------+---------------+
954              
955             Examples:
956              
957             $session->expire("2h"); # expires in two hours
958             $session->expire(0); # cancel expiration
959             $session->expire("~logged-in", "10m"); # expires '~logged-in' parameter after 10 idle minutes
960              
961             Note: all the expiration times are relative to session's last access time, not to its creation time. To expire a session immediately, call L<delete()|/"delete">. To expire a specific session parameter immediately, call L<clear([$name])|/"clear">.
962              
963             =cut
964              
965             *expires = \&expire;
966             my $prevent_warning = \&expires;
967 9     9 0 31 sub etime { $_[0]->expire() }
968             sub expire {
969 41     41 1 592 my $self = shift;
970              
971             # no params, just return the expiration time.
972 41 100       160 if (not @_) {
    100          
973 25         197 return $self->{_DATA}->{_SESSION_ETIME};
974             }
975             # We have just a time
976             elsif ( @_ == 1 ) {
977 14         27 my $time = $_[0];
978             # If 0 is passed, cancel expiration
979 14 100 66     156 if ( defined $time && ($time =~ m/^\d$/) && ($time == 0) ) {
      100        
980 1         3 $self->{_DATA}->{_SESSION_ETIME} = undef;
981 1         3 $self->_set_status( STATUS_MODIFIED );
982             }
983             # set the expiration to this time
984             else {
985 13         54 $self->{_DATA}->{_SESSION_ETIME} = $self->_str2seconds( $time );
986 13         46 $self->_set_status( STATUS_MODIFIED );
987             }
988             }
989             # If we get this far, we expect expire($param,$time)
990             # ( This would be a great use of a Perl6 multi sub! )
991             else {
992 2         4 my ($param, $time) = @_;
993 2 100 66     16 if ( ($time =~ m/^\d$/) && ($time == 0) ) {
994 1         4 delete $self->{_DATA}->{_SESSION_EXPIRE_LIST}->{ $param };
995 1         7 $self->_set_status( STATUS_MODIFIED );
996             } else {
997 1         4 $self->{_DATA}->{_SESSION_EXPIRE_LIST}->{ $param } = $self->_str2seconds( $time );
998 1         3 $self->_set_status( STATUS_MODIFIED );
999             }
1000             }
1001 16         42 return 1;
1002             }
1003              
1004             # =head2 _str2seconds()
1005             #
1006             # my $secs = $self->_str2seconds('1d')
1007             #
1008             # Takes a CGI.pm-style time representation and returns an equivalent number
1009             # of seconds.
1010             #
1011             # See the docs of expire() for more detail.
1012             #
1013             # =cut
1014              
1015             sub _str2seconds {
1016 23     23   3168 my $self = shift;
1017 23         46 my ($str) = @_;
1018              
1019 23 50       64 return unless defined $str;
1020 23 100       138 return $str if $str =~ m/^[-+]?\d+$/;
1021              
1022 19         121 my %_map = (
1023             s => 1,
1024             m => 60,
1025             h => 3600,
1026             d => 86400,
1027             w => 604800,
1028             M => 2592000,
1029             y => 31536000
1030             );
1031              
1032 19         90 my ($koef, $d) = $str =~ m/^([+-]?\d+)([smhdwMy])$/;
1033 19 50 33     134 unless ( defined($koef) && defined($d) ) {
1034 0         0 die "_str2seconds(): couldn't parse '$str' into \$koef and \$d parts. Possible invalid syntax";
1035             }
1036 19         122 return $koef * $_map{ $d };
1037             }
1038              
1039              
1040             =pod
1041              
1042             =head2 is_new()
1043              
1044             Returns true only for a brand new session.
1045              
1046             =head2 is_expired()
1047              
1048             Tests whether session initialized using L<load()|/"load"> is to be expired. This method works only on sessions initialized with load():
1049              
1050             $s = CGI::Session->load() or die CGI::Session->errstr;
1051             if ( $s->is_expired ) {
1052             die "Your session expired. Please refresh";
1053             }
1054             if ( $s->is_empty ) {
1055             $s = $s->new() or die $s->errstr;
1056             }
1057              
1058              
1059             =head2 is_empty()
1060              
1061             Returns true for sessions that are empty. It's preferred way of testing whether requested session was loaded successfully or not:
1062              
1063             $s = CGI::Session->load($sid);
1064             if ( $s->is_empty ) {
1065             $s = $s->new();
1066             }
1067              
1068             Actually, the above code is nothing but waste. The same effect could've been achieved by saying:
1069              
1070             $s = CGI::Session->new( $sid );
1071              
1072             L<is_empty()|/"is_empty"> is useful only if you wanted to catch requests for expired sessions, and create new session afterwards. See L<is_expired()|/"is_expired"> for an example.
1073              
1074             =head2 ip_match()
1075              
1076             Returns true if $ENV{REMOTE_ADDR} matches the remote address stored in the session.
1077              
1078             If you have an application where you are sure your users' IPs are constant
1079             during a session, you can consider enabling an option to make this check:
1080              
1081             use CGI::Session '-ip_match';
1082              
1083             Usually you don't call ip_match() directly, but by using the above method. It is useful
1084             only if you want to call it inside of coderef passed to the L<find()|/"find( \&code )"> method.
1085              
1086             =head2 delete()
1087              
1088             Sets the objects status to be "deleted". Subsequent read/write requests on the
1089             same object will fail. To physically delete it from the data store you need to call L<flush()|/"flush()">.
1090             CGI::Session attempts to do this automatically when the object is being destroyed (usually as
1091             the script exits), but see L<A Warning about Auto-flushing>.
1092              
1093             =head2 find( \&code )
1094              
1095             =head2 find( $dsn, \&code )
1096              
1097             =head2 find( $dsn, \&code, \%dsn_args )
1098              
1099             Experimental feature. Executes \&code for every session object stored in disk, passing initialized CGI::Session object as the first argument of \&code. Useful for housekeeping purposes, such as for removing expired sessions. Following line, for instance, will remove sessions already expired, but are still in disk:
1100              
1101             The following line, for instance, will remove sessions already expired, but which are still on disk:
1102              
1103             CGI::Session->find( sub {} );
1104              
1105             Notice, above \&code didn't have to do anything, because load(), which is called to initialize sessions inside L<find()|/"find( \&code )">, will automatically remove expired sessions. Following example will remove all the objects that are 10+ days old:
1106              
1107             CGI::Session->find( \&purge );
1108             sub purge {
1109             my ($session) = @_;
1110             next if $session->is_empty; # <-- already expired?!
1111             if ( ($session->ctime + 3600*240) <= time() ) {
1112             $session->delete();
1113             $session->flush(); # Recommended practice says use flush() after delete().
1114             }
1115             }
1116              
1117             B<Note>: find will not change the modification or access times on the sessions it returns.
1118              
1119             Explanation of the 3 parameters to C<find()>:
1120              
1121             =over 4
1122              
1123             =item $dsn
1124              
1125             This is the DSN (Data Source Name) used by CGI::Session to control what type of
1126             sessions you previously created and what type of sessions you now wish method
1127             C<find()> to pass to your callback.
1128              
1129             The default value is defined above, in the docs for method C<new()>, and is
1130             'driver:file;serializer:default;id:md5'.
1131              
1132             Do not confuse this DSN with the DSN arguments mentioned just below, under \%dsn_args.
1133              
1134             =item \&code
1135              
1136             This is the callback provided by you (i.e. the caller of method C<find()>)
1137             which is called by CGI::Session once for each session found by method C<find()>
1138             which matches the given $dsn.
1139              
1140             There is no default value for this coderef.
1141              
1142             When your callback is actually called, the only parameter is a session. If you
1143             want to call a subroutine you already have with more parameters, you can
1144             achieve this by creating an anonymous subroutine that calls your subroutine
1145             with the parameters you want. For example:
1146              
1147             CGI::Session->find($dsn, sub { my_subroutine( @_, 'param 1', 'param 2' ) } );
1148             CGI::Session->find($dsn, sub { $coderef->( @_, $extra_arg ) } );
1149            
1150             Or if you wish, you can define a sub generator as such:
1151              
1152             sub coderef_with_args {
1153             my ( $coderef, @params ) = @_;
1154             return sub { $coderef->( @_, @params ) };
1155             }
1156            
1157             CGI::Session->find($dsn, coderef_with_args( $coderef, 'param 1', 'param 2' ) );
1158              
1159             =item \%dsn_args
1160              
1161             If your $dsn uses file-based storage, then this hashref might contain keys such as:
1162              
1163             {
1164             Directory => Value 1,
1165             NoFlock => Value 2,
1166             UMask => Value 3
1167             }
1168              
1169             If your $dsn uses db-based storage, then this hashref contains (up to) 3 keys, and looks like:
1170              
1171             {
1172             DataSource => Value 1,
1173             User => Value 2,
1174             Password => Value 3
1175             }
1176              
1177             These 3 form the DSN, username and password used by DBI to control access to your database server,
1178             and hence are only relevant when using db-based sessions.
1179              
1180             The default value of this hashref is undef.
1181              
1182             =back
1183              
1184             B<Note:> find() is meant to be convenient, not necessarily efficient. It's best suited in cron scripts.
1185              
1186             =head2 name($new_name)
1187              
1188             The $new_name parameter is optional. If supplied it sets the query or cookie parameter name to be used.
1189              
1190             It defaults to I<$CGI::Session::NAME>, which defaults to I<CGISESSID>.
1191              
1192             You are strongly discouraged from using the global variable I<$CGI::Session::NAME>, since it is
1193             deprecated (as are all global variables) and will be removed in a future version of this module.
1194              
1195             Return value: The current query or cookie parameter name.
1196              
1197             =head1 MISCELLANEOUS METHODS
1198              
1199             =head2 remote_addr()
1200              
1201             Returns the remote address of the user who created the session for the first time. Returns undef if variable REMOTE_ADDR wasn't present in the environment when the session was created.
1202              
1203             =cut
1204              
1205 3     3 1 14 sub remote_addr { return $_[0]->{_DATA}->{_SESSION_REMOTE_ADDR} }
1206              
1207             =pod
1208              
1209             =head2 errstr()
1210              
1211             Class method. Returns last error message from the library.
1212              
1213             =head2 dump()
1214              
1215             Returns a dump of the session object. Useful for debugging purposes only.
1216              
1217             =head2 header()
1218              
1219             A wrapper for C<CGI>'s header() method. Calling this method
1220             is equivalent to something like this:
1221              
1222             $cookie = CGI::Cookie->new(-name=>$session->name, -value=>$session->id);
1223             print $cgi->header(-cookie=>$cookie, @_);
1224              
1225             You can minimize the above into:
1226              
1227             print $session->header();
1228              
1229             It will retrieve the name of the session cookie from C<$session->name()> which defaults to C<$CGI::Session::NAME>. If you want to use a different name for your session cookie, do something like this before creating session object:
1230              
1231             CGI::Session->name("MY_SID");
1232             $session = CGI::Session->new(undef, $cgi, \%attrs);
1233              
1234             Now, $session->header() uses "MY_SID" as the name for the session cookie. For all additional options that can
1235             be passed, see the C<header()> docs in C<CGI>.
1236              
1237             =head2 query()
1238              
1239             Returns query object associated with current session object. Default query object class is C<CGI>.
1240              
1241             =head2 DEPRECATED METHODS
1242              
1243             These methods exist solely for for compatibility with CGI::Session 3.x.
1244              
1245             =head3 close()
1246              
1247             Closes the session. Using flush() is recommended instead, since that's exactly what a call
1248             to close() does now.
1249              
1250             =head1 DISTRIBUTION
1251              
1252             CGI::Session consists of several components such as L<drivers|"DRIVERS">, L<serializers|"SERIALIZERS"> and L<id generators|"ID GENERATORS">. This section lists what is available.
1253              
1254             =head2 DRIVERS
1255              
1256             The following drivers are included in the standard distribution:
1257              
1258             =over 4
1259              
1260             =item *
1261              
1262             L<file|CGI::Session::Driver::file> - default driver for storing session data in plain files. Full name: B<CGI::Session::Driver::file>
1263              
1264             =item *
1265              
1266             L<db_file|CGI::Session::Driver::db_file> - for storing session data in BerkelyDB. Requires: L<DB_File>.
1267             Full name: B<CGI::Session::Driver::db_file>
1268              
1269             =item *
1270              
1271             L<mysql|CGI::Session::Driver::mysql> - for storing session data in MySQL tables. Requires L<DBI|DBI> and L<DBD::mysql|DBD::mysql>.
1272             Full name: B<CGI::Session::Driver::mysql>
1273              
1274             =item *
1275              
1276             L<sqlite|CGI::Session::Driver::sqlite> - for storing session data in SQLite. Requires L<DBI|DBI> and L<DBD::SQLite|DBD::SQLite>.
1277             Full name: B<CGI::Session::Driver::sqlite>
1278              
1279             =back
1280              
1281             Other drivers are available from CPAN.
1282              
1283             =head2 SERIALIZERS
1284              
1285             =over 4
1286              
1287             =item *
1288              
1289             L<default|CGI::Session::Serialize::default> - default data serializer. Uses standard L<Data::Dumper|Data::Dumper>.
1290             Full name: B<CGI::Session::Serialize::default>.
1291              
1292             =item *
1293              
1294             L<storable|CGI::Session::Serialize::storable> - serializes data using L<Storable>. Requires L<Storable>.
1295             Full name: B<CGI::Session::Serialize::storable>.
1296              
1297             =item *
1298              
1299             L<freezethaw|CGI::Session::Serialize::freezethaw> - serializes data using L<FreezeThaw>. Requires L<FreezeThaw>.
1300             Full name: B<CGI::Session::Serialize::freezethaw>
1301              
1302             =item *
1303              
1304             L<yaml|CGI::Session::Serialize::yaml> - serializes data using YAML. Requires L<YAML> or L<YAML::Syck>.
1305             Full name: B<CGI::Session::Serialize::yaml>
1306              
1307             =back
1308              
1309             =head2 ID GENERATORS
1310              
1311             The following ID generators are included in the standard distribution.
1312              
1313             =over 4
1314              
1315             =item *
1316              
1317             L<md5|CGI::Session::ID::md5> - generates 32 character long hexadecimal string. Requires L<Digest::MD5|Digest::MD5>.
1318             Full name: B<CGI::Session::ID::md5>.
1319              
1320             =item *
1321              
1322             L<incr|CGI::Session::ID::incr> - generates incremental session ids.
1323              
1324             =item *
1325              
1326             L<static|CGI::Session::ID::static> - generates static session ids. B<CGI::Session::ID::static>
1327              
1328             =back
1329              
1330             =head1 A Warning about Auto-flushing
1331              
1332             Auto-flushing can be unreliable for the following reasons. Explicit flushing
1333             after key session updates is recommended.
1334              
1335             =over 4
1336              
1337             =item If the C<DBI> handle goes out of scope before the session variable
1338              
1339             For database-stored sessions, if the C<DBI> handle has gone out of scope before
1340             the auto-flushing happens, auto-flushing will fail.
1341              
1342             =item Circular references
1343              
1344             If the calling code contains a circular reference, it's possible that your
1345             C<CGI::Session> object will not be destroyed until it is too late for
1346             auto-flushing to work. You can find circular references with a tool like
1347             L<Devel::Cycle>.
1348              
1349             In particular, these modules are known to contain circular references which
1350             lead to this problem:
1351              
1352             =over 4
1353              
1354             =item CGI::Application::Plugin::DebugScreen V 0.06
1355              
1356             =item CGI::Application::Plugin::ErrorPage before version 1.20
1357              
1358             =back
1359              
1360             =item Signal handlers
1361              
1362             If your application may receive signals, there is an increased chance that the
1363             signal will arrive after the session was updated but before it is auto-flushed
1364             at object destruction time.
1365              
1366             =back
1367              
1368             =head1 A Warning about UTF8
1369              
1370             You are strongly encouraged to refer to, at least, the first of these articles, for help with UTF8.
1371              
1372             L<http://en.wikibooks.org/wiki/Perl_Programming/Unicode_UTF-8>
1373              
1374             L<http://perl.bristolbath.org/blog/lyle/2008/12/giving-cgiapplication-internationalization-i18n.html>
1375              
1376             L<http://metsankulma.homelinux.net/cgi-bin/l10n_example_4/main.cgi>
1377              
1378             L<http://rassie.org/archives/247>
1379              
1380             L<http://www.di-mgt.com.au/cryptoInternational2.html>
1381              
1382             Briefly, these are the issues:
1383              
1384             =over 4
1385              
1386             =item The file containing the source code of your program
1387              
1388             Consider "use utf8;" or "use encoding 'utf8';".
1389              
1390             =item Influencing the encoding of the program's input
1391              
1392             Use:
1393              
1394             binmode STDIN, ":encoding(utf8)";.
1395              
1396             Of course, the program can get input from other sources, e.g. HTML template files, not just STDIN.
1397              
1398             =item Influencing the encoding of the program's output
1399              
1400             Use:
1401              
1402             binmode STDOUT, ":encoding(utf8)";
1403              
1404             When using CGI.pm, you can use $q->charset('UTF-8'). This is the same as passing 'UTF-8' to CGI's C<header()> method.
1405              
1406             Alternately, when using CGI::Session, you can use $session->header(charset => 'utf-8'), which will be
1407             passed to the query object's C<header()> method. Clearly this is preferable when the query object might not be
1408             of type CGI.
1409              
1410             See L</header()> for a fuller discussion of the use of the C<header()> method in conjunction with cookies.
1411              
1412             =back
1413              
1414             =head1 TRANSLATIONS
1415              
1416             This document is also available in Japanese.
1417              
1418             =over 4
1419              
1420             =item o
1421              
1422             Translation based on 4.14: http://digit.que.ne.jp/work/index.cgi?Perldoc/ja
1423              
1424             =item o
1425              
1426             Translation based on 3.11, including Cookbook and Tutorial: http://perldoc.jp/docs/modules/CGI-Session-3.11/
1427              
1428             =back
1429              
1430             =head1 CREDITS
1431              
1432             CGI::Session evolved to what it is today with the help of following developers. The list doesn't follow any strict order, but somewhat chronological. Specifics can be found in F<Changes> file
1433              
1434             =over 4
1435              
1436             =item Andy Lester
1437              
1438             =item Brian King E<lt>mrbbking@mac.comE<gt>
1439              
1440             =item Olivier Dragon E<lt>dragon@shadnet.shad.caE<gt>
1441              
1442             =item Adam Jacob E<lt>adam@sysadminsith.orgE<gt>
1443              
1444             =item Igor Plisco E<lt>igor@plisco.ruE<gt>
1445              
1446             =item Mark Stosberg
1447              
1448             =item Matt LeBlanc E<lt>mleblanc@cpan.orgE<gt>
1449              
1450             =item Shawn Sorichetti
1451              
1452             =item Ron Savage
1453              
1454             =item Rhesa Rozendaal
1455              
1456             He suggested Devel::Cycle to help debugging.
1457              
1458             =back
1459              
1460             Also, many people on the CGI::Application and CGI::Session mailing lists have contributed ideas and
1461             suggestions, and battled publicly with bugs, all of which has helped.
1462              
1463             =head1 COPYRIGHT
1464              
1465             Copyright (C) 2001-2005 Sherzod Ruzmetov E<lt>sherzodr@cpan.orgE<gt>. All rights reserved.
1466             This library is free software. You can modify and or distribute it under the same terms as Perl itself.
1467              
1468             =head1 PUBLIC CODE REPOSITORY
1469              
1470             You can see what the developers have been up to since the last release by
1471             checking out the code repository. You can browse the git repository from here:
1472              
1473             http://github.com/cromedome/cgi-session/tree/master
1474              
1475             Or check out the code with:
1476              
1477             git clone git://github.com/cromedome/cgi-session.git
1478              
1479             =head1 SUPPORT
1480              
1481             If you need help using CGI::Session, ask on the mailing list. You can ask the
1482             list by sending your questions to cgi-session-user@lists.sourceforge.net .
1483              
1484             You can subscribe to the mailing list at https://lists.sourceforge.net/lists/listinfo/cgi-session-user .
1485              
1486             Bug reports can be submitted at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=CGI-Session
1487              
1488             =head1 AUTHOR
1489              
1490             Sherzod Ruzmetov C<sherzodr@cpan.org>
1491              
1492             Mark Stosberg became a co-maintainer during the development of 4.0. C<markstos@cpan.org>.
1493              
1494             Ron Savage became a co-maintainer during the development of 4.30. C<rsavage@cpan.org>.
1495              
1496             If you would like support, ask on the mailing list as describe above. The
1497             maintainers and other users are subscribed to it.
1498              
1499             =head1 SEE ALSO
1500              
1501             To learn more both about the philosophy and CGI::Session programming style,
1502             consider the following:
1503              
1504             =over 4
1505              
1506             =item *
1507              
1508             L<CGI::Session::Tutorial|CGI::Session::Tutorial> - extended CGI::Session manual. Also includes library architecture and driver specifications.
1509              
1510             =item *
1511              
1512             We also provide mailing lists for CGI::Session users. To subscribe to the list
1513             or browse the archives visit
1514             https://lists.sourceforge.net/lists/listinfo/cgi-session-user
1515              
1516             =item * B<RFC 2109> - The primary spec for cookie handing in use, defining the "Cookie:" and "Set-Cookie:" HTTP headers.
1517             Available at L<http://www.ietf.org/rfc/rfc2109.txt>. A newer spec, RFC 2965 is meant to obsolete it with "Set-Cookie2"
1518             and "Cookie2" headers, but even of 2008, the newer spec is not widely supported. See L<http://www.ietf.org/rfc/rfc2965.txt>
1519              
1520             =item *
1521              
1522             L<Apache::Session|Apache::Session> - an alternative to CGI::Session.
1523              
1524             =back
1525              
1526             =cut
1527              
1528             1;
1529