← Index
Performance Profile   « block view • line view • sub view »
For /home/chris/git/koha.git/cataloguing/addbiblio.pl
  Run on Tue Aug 25 11:37:23 2009
Reported on Tue Aug 25 11:37:52 2009

File /usr/share/perl5/CGI/Session.pm
Statements Executed 225
Total Time 0.0028512 seconds
Subroutines — ordered by exclusive time
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
1118.23ms16.9msCGI::Session::::_load_pluggablesCGI::Session::_load_pluggables
111551µs790µsCGI::Session::::parse_dsnCGI::Session::parse_dsn
1891315µs524µsCGI::Session::::paramCGI::Session::param
2141234µs234µsCGI::Session::::_test_statusCGI::Session::_test_status
111104µs20.3msCGI::Session::::loadCGI::Session::load
72182µs82µsCGI::Session::::datarefCGI::Session::dataref
11171µs20.7msCGI::Session::::newCGI::Session::new
33256µs127µsCGI::Session::::idCGI::Session::id
22149µs142µsCGI::Session::::_driverCGI::Session::_driver
11145µs39.2msCGI::Session::::flushCGI::Session::flush
22135µs35µsCGI::Session::::_serializerCGI::Session::_serializer
22131µs31µsCGI::Session::::_set_statusCGI::Session::_set_status
11122µs22µsCGI::Session::::_unset_statusCGI::Session::_unset_status
11118µs18µsCGI::Session::::_set_query_or_sidCGI::Session::_set_query_or_sid
0000s0sCGI::Session::::BEGINCGI::Session::BEGIN
0000s0sCGI::Session::::DESTROYCGI::Session::DESTROY
0000s0sCGI::Session::::__ANON__[:451]CGI::Session::__ANON__[:451]
0000s0sCGI::Session::::_id_generatorCGI::Session::_id_generator
0000s0sCGI::Session::::_ip_matchesCGI::Session::_ip_matches
0000s0sCGI::Session::::_reset_statusCGI::Session::_reset_status
0000s0sCGI::Session::::_str2secondsCGI::Session::_str2seconds
0000s0sCGI::Session::::atimeCGI::Session::atime
0000s0sCGI::Session::::clearCGI::Session::clear
0000s0sCGI::Session::::closeCGI::Session::close
0000s0sCGI::Session::::cookieCGI::Session::cookie
0000s0sCGI::Session::::ctimeCGI::Session::ctime
0000s0sCGI::Session::::deleteCGI::Session::delete
0000s0sCGI::Session::::dumpCGI::Session::dump
0000s0sCGI::Session::::etimeCGI::Session::etime
0000s0sCGI::Session::::expireCGI::Session::expire
0000s0sCGI::Session::::findCGI::Session::find
0000s0sCGI::Session::::http_headerCGI::Session::http_header
0000s0sCGI::Session::::importCGI::Session::import
0000s0sCGI::Session::::is_emptyCGI::Session::is_empty
0000s0sCGI::Session::::is_expiredCGI::Session::is_expired
0000s0sCGI::Session::::is_newCGI::Session::is_new
0000s0sCGI::Session::::load_paramCGI::Session::load_param
0000s0sCGI::Session::::nameCGI::Session::name
0000s0sCGI::Session::::queryCGI::Session::query
0000s0sCGI::Session::::remote_addrCGI::Session::remote_addr
0000s0sCGI::Session::::save_paramCGI::Session::save_param
0000s0sCGI::Session::::traceCGI::Session::trace
0000s0sCGI::Session::::tracemsgCGI::Session::tracemsg
LineStmts.Exclusive
Time
Avg.Code
1package CGI::Session;
2
3# $Id: Session.pm 454 2008-12-16 01:20:54Z markstos $
4
5use strict;
6use Carp;
7use CGI::Session::ErrorHandler;
8
9@CGI::Session::ISA = qw( CGI::Session::ErrorHandler );
10$CGI::Session::VERSION = '4.39';
11$CGI::Session::NAME = 'CGISESSID';
12$CGI::Session::IP_MATCH = 0;
13
14sub STATUS_UNSET () { 1 << 0 } # denotes session that's resetted
15sub STATUS_NEW () { 1 << 1 } # denotes session that's just created
16sub STATUS_MODIFIED () { 1 << 2 } # denotes session that needs synchronization
17sub STATUS_DELETED () { 1 << 3 } # denotes session that needs deletion
18sub STATUS_EXPIRED () { 1 << 4 } # denotes session that was expired.
19
20sub import {
21 my ($class, @args) = @_;
22
23 return unless @args;
24
25 ARG:
26 foreach my $arg (@args) {
27 if ($arg eq '-ip_match') {
28 $CGI::Session::IP_MATCH = 1;
29 last ARG;
30 }
31 }
32}
33
34
# spent 20.7ms (71µs+20.7) within CGI::Session::new which was called # once (71µs+20.7ms) by C4::Auth::get_session at line 1226 of /home/chris/git/koha.git/C4/Auth.pm
sub new {
3559µs2µs my ($class, @args) = @_;
36
37 my $self;
38487µs22µs if (ref $class) {
39 #
40 # Called as an object method as in $session->new()...
41 #
42 $self = bless { %$class }, ref( $class );
43 $class = ref $class;
44 $self->_reset_status();
45 #
46 # Object may still have public data associated with it, but we
47 # don't care about that, since we want to leave that to the
48 # client's disposal. However, if new() was requested on an
49 # expired session, we already know that '_DATA' table is
50 # empty, since it was the job of flush() to empty '_DATA'
51 # after deleting. How do we know flush() was already called on
52 # an expired session? Because load() - constructor always
53 # calls flush() on all to-be expired sessions
54 #
55 }
56 else {
57 #
58 # Called as a class method as in CGI::Session->new()
59 #
60
61 # Start fresh with error reporting. Errors in past objects shouldn't affect this one.
62 $class->set_error('');
# spent 183µs making 1 call to CGI::Session::ErrorHandler::set_error
63
64 $self = $class->load( @args );
# spent 20.3ms making 1 call to CGI::Session::load
65 if (not defined $self) {
66 return $class->set_error( "new(): failed: " . $class->errstr );
67 }
68 }
69
70 my $dataref = $self->{_DATA};
71 unless ($dataref->{_SESSION_ID}) {
72 #
73 # Absence of '_SESSION_ID' can only signal:
74 # * Expired session: Because load() - constructor is required to
75 # empty contents of _DATA - table
76 # * Unavailable session: Such sessions are the ones that don't
77 # exist on datastore, but are requested by client
78 # * New session: When no specific session is requested to be loaded
79 #
80 my $id = $self->_id_generator()->generate_id(
81 $self->{_DRIVER_ARGS},
82 $self->{_CLAIMED_ID}
83 );
84 unless (defined $id) {
85 return $self->set_error( "Couldn't generate new SESSION-ID" );
86 }
87 $dataref->{_SESSION_ID} = $id;
88 $dataref->{_SESSION_CTIME} = $dataref->{_SESSION_ATIME} = time();
89 $dataref->{_SESSION_REMOTE_ADDR} = $ENV{REMOTE_ADDR} || "";
90 $self->_set_status( STATUS_NEW );
91 }
92 return $self;
93}
94
95117µs17µssub DESTROY { $_[0]->flush() }
# spent 39.2ms making 1 call to CGI::Session::flush
96sub close { $_[0]->flush() }
97
98*param_hashref = \&dataref;
99my $avoid_single_use_warning = *param_hashref;
100715µs2µs
# spent 82µs within CGI::Session::dataref which was called 7 times, avg 12µs/call: # 6 times (70µs+0s) by CGI::Session::id at line 108, avg 12µs/call # once (11µs+0s) by CGI::Session::flush at line 249
sub dataref { $_[0]->{_DATA} }
101
102sub is_empty { !defined($_[0]->id) }
103
104sub is_expired { $_[0]->_test_status( STATUS_EXPIRED ) }
105
106sub is_new { $_[0]->_test_status( STATUS_NEW ) }
107
108375µs25µs
# spent 127µs (56+70) within CGI::Session::id which was called 3 times, avg 42µs/call: # once (21µs+26µs) by C4::Auth::checkauth at line 604 of /home/chris/git/koha.git/C4/Auth.pm # once (16µs+24µs) by CGI::Session::flush at line 227 # once (19µs+20µs) by CGI::Session::flush at line 253
sub id { return defined($_[0]->dataref) ? $_[0]->dataref->{_SESSION_ID} : undef }
# spent 70µs making 6 calls to CGI::Session::dataref, avg 12µs/call
109
110# Last Access Time
111sub atime { return defined($_[0]->dataref) ? $_[0]->dataref->{_SESSION_ATIME} : undef }
112
113# Creation Time
114sub ctime { return defined($_[0]->dataref) ? $_[0]->dataref->{_SESSION_CTIME} : undef }
115
116
# spent 142µs (49+94) within CGI::Session::_driver which was called 2 times, avg 71µs/call: # once (33µs+94µs) by CGI::Session::load at line 718 # once (16µs+0s) by CGI::Session::flush at line 237
sub _driver {
117738µs5µs my $self = shift;
118 defined($self->{_OBJECTS}->{driver}) and return $self->{_OBJECTS}->{driver};
119 my $pm = "CGI::Session::Driver::" . $self->{_DSN}->{driver};
120 defined($self->{_OBJECTS}->{driver} = $pm->new( $self->{_DRIVER_ARGS} ))
# spent 94µs making 1 call to CGI::Session::Driver::new
121 or die $pm->errstr();
122 return $self->{_OBJECTS}->{driver};
123}
124
125
# spent 35µs within CGI::Session::_serializer which was called 2 times, avg 17µs/call: # once (19µs+0s) by CGI::Session::load at line 727 # once (15µs+0s) by CGI::Session::flush at line 238
sub _serializer {
126512µs2µs my $self = shift;
127 defined($self->{_OBJECTS}->{serializer}) and return $self->{_OBJECTS}->{serializer};
128 return $self->{_OBJECTS}->{serializer} = "CGI::Session::Serialize::" . $self->{_DSN}->{serializer};
129}
130
131
132sub _id_generator {
133 my $self = shift;
134 defined($self->{_OBJECTS}->{id}) and return $self->{_OBJECTS}->{id};
135 return $self->{_OBJECTS}->{id} = "CGI::Session::ID::" . $self->{_DSN}->{id};
136}
137
138sub _ip_matches {
139 return ( $_[0]->{_DATA}->{_SESSION_REMOTE_ADDR} eq $ENV{REMOTE_ADDR} );
140}
141
142
143# parses the DSN string and returns it as a hash.
144# Notably: Allows unique abbreviations of the keys: driver, serializer and 'id'.
145# Also, keys and values of the returned hash are lower-cased.
146
# spent 790µs (551+239) within CGI::Session::parse_dsn which was called # once (551µs+239µs) by CGI::Session::load at line 688
sub parse_dsn {
1479862µs96µs my $self = shift;
148 my $dsn_str = shift;
149 croak "parse_dsn(): usage error" unless $dsn_str;
150
151 require Text::Abbrev;
152 my $abbrev = Text::Abbrev::abbrev( "driver", "serializer", "id" );
# spent 72µs making 1 call to Text::Abbrev::abbrev
15332µs800ns my %dsn_map = map { split /:/ } (split /;/, $dsn_str);
154 my %dsn = map { $abbrev->{lc $_}, lc $dsn_map{$_} } keys %dsn_map;
155 return \%dsn;
156}
157
158sub query {
159 my $self = shift;
160
161 if ( $self->{_QUERY} ) {
162 return $self->{_QUERY};
163 }
164# require CGI::Session::Query;
165# return $self->{_QUERY} = CGI::Session::Query->new();
166 require CGI;
167 return $self->{_QUERY} = CGI->new();
168}
169
170
171sub name {
172 my $self = shift;
173
174 if (ref $self) {
175 unless ( @_ ) {
176 return $self->{_NAME} || $CGI::Session::NAME;
177 }
178 return $self->{_NAME} = $_[0];
179 }
180
181 $CGI::Session::NAME = $_[0] if @_;
182 return $CGI::Session::NAME;
183}
184
185
186sub dump {
187 my $self = shift;
188
189 require Data::Dumper;
190 my $d = Data::Dumper->new([$self], [ref $self]);
191 $d->Deepcopy(1);
192 return $d->Dump();
193}
194
195
196
# spent 31µs within CGI::Session::_set_status which was called 2 times, avg 16µs/call: # once (18µs+0s) by CGI::Session::load at line 771 # once (14µs+0s) by CGI::Session::param at line 315
sub _set_status {
19768µs1µs my $self = shift;
198 croak "_set_status(): usage error" unless @_;
199 $self->{_STATUS} |= $_[0];
200}
201
202
203
# spent 22µs within CGI::Session::_unset_status which was called # once (22µs+0s) by CGI::Session::flush at line 255
sub _unset_status {
20435µs2µs my $self = shift;
205 croak "_unset_status(): usage error" unless @_;
206 $self->{_STATUS} &= ~$_[0];
207}
208
209
210sub _reset_status {
211 $_[0]->{_STATUS} = STATUS_UNSET;
212}
213
214
# spent 234µs within CGI::Session::_test_status which was called 21 times, avg 11µs/call: # 18 times (196µs+0s) by CGI::Session::param at line 266, avg 11µs/call # once (14µs+0s) by CGI::Session::flush at line 232 # once (12µs+0s) by CGI::Session::flush at line 248 # once (12µs+0s) by CGI::Session::flush at line 240
sub _test_status {
2152148µs2µs return $_[0]->{_STATUS} & $_[1];
216}
217
218
219
# spent 39.2ms (45µs+39.2) within CGI::Session::flush which was called # once (45µs+39.2ms) by CGI::Session::DESTROY at line 95
sub flush {
220980µs9µs my $self = shift;
221
222 # Would it be better to die or err if something very basic is wrong here?
223 # I'm trying to address the DESTORY related warning
224 # from: http://rt.cpan.org/Ticket/Display.html?id=17541
225 # return unless defined $self;
226
227 return unless $self->id; # <-- empty session
# spent 40µs making 1 call to CGI::Session::id
228
229 # neither new, nor deleted nor modified
230 return if !defined($self->{_STATUS}) or $self->{_STATUS} == STATUS_UNSET;
231
232 if ( $self->_test_status(STATUS_NEW) && $self->_test_status(STATUS_DELETED) ) {
# spent 14µs making 1 call to CGI::Session::_test_status
233 $self->{_DATA} = {};
234 return $self->_unset_status(STATUS_NEW | STATUS_DELETED);
235 }
236
237 my $driver = $self->_driver();
# spent 16µs making 1 call to CGI::Session::_driver
238 my $serializer = $self->_serializer();
# spent 15µs making 1 call to CGI::Session::_serializer
239
240 if ( $self->_test_status(STATUS_DELETED) ) {
# spent 12µs making 1 call to CGI::Session::_test_status
241 defined($driver->remove($self->id)) or
242 return $self->set_error( "flush(): couldn't remove session data: " . $driver->errstr );
243 $self->{_DATA} = {}; # <-- removing all the data, making sure
244 # it won't be accessible after flush()
245 return $self->_unset_status(STATUS_DELETED);
246 }
247
248477µs19µs if ( $self->_test_status(STATUS_NEW | STATUS_MODIFIED) ) {
# spent 12µs making 1 call to CGI::Session::_test_status
249 my $datastr = $serializer->freeze( $self->dataref );
# spent 469µs making 1 call to CGI::Session::Serialize::yaml::freeze # spent 11µs making 1 call to CGI::Session::dataref
250 unless ( defined $datastr ) {
251 return $self->set_error( "flush(): couldn't freeze data: " . $serializer->errstr );
252 }
253 defined( $driver->store($self->id, $datastr) ) or
# spent 38.5ms making 1 call to CGI::Session::Driver::mysql::store # spent 39µs making 1 call to CGI::Session::id
254 return $self->set_error( "flush(): couldn't store datastr: " . $driver->errstr);
255 $self->_unset_status(STATUS_NEW | STATUS_MODIFIED);
# spent 22µs making 1 call to CGI::Session::_unset_status
256 }
257 return 1;
258}
259
260sub trace {}
261sub tracemsg {}
262
263
# spent 524µs (315+210) within CGI::Session::param which was called 18 times, avg 29µs/call: # 10 times (162µs+104µs) by C4::Auth::checkauth at line 547 of /home/chris/git/koha.git/C4/Auth.pm, avg 27µs/call # once (37µs+24µs) by C4::Auth::checkauth at line 605 of /home/chris/git/koha.git/C4/Auth.pm # once (15µs+19µs) by C4::Auth::checkauth at line 556 of /home/chris/git/koha.git/C4/Auth.pm # once (16µs+13µs) by C4::Auth::checkauth at line 554 of /home/chris/git/koha.git/C4/Auth.pm # once (16µs+13µs) by C4::Auth::checkauth at line 560 of /home/chris/git/koha.git/C4/Auth.pm # once (18µs+10µs) by C4::Auth::checkauth at line 561 of /home/chris/git/koha.git/C4/Auth.pm # once (17µs+9µs) by C4::Auth::checkauth at line 559 of /home/chris/git/koha.git/C4/Auth.pm # once (16µs+9µs) by C4::Auth::checkauth at line 558 of /home/chris/git/koha.git/C4/Auth.pm # once (16µs+9µs) by C4::Auth::checkauth at line 555 of /home/chris/git/koha.git/C4/Auth.pm
sub param {
26459277µs5µs my ($self, @args) = @_;
265
266 if ($self->_test_status( STATUS_DELETED )) {
# spent 196µs making 18 calls to CGI::Session::_test_status, avg 11µs/call
267 carp "param(): attempt to read/write deleted session";
268 }
269
270 # USAGE: $s->param();
271 # DESC: Returns all the /public/ parameters
272 if (@args == 0) {
273 return grep { !/^_SESSION_/ } keys %{ $self->{_DATA} };
274 }
275 # USAGE: $s->param( $p );
276 # DESC: returns a specific session parameter
277 elsif (@args == 1) {
278 return $self->{_DATA}->{ $args[0] }
279 }
280
281
282 # USAGE: $s->param( -name => $n, -value => $v );
283 # DESC: Updates session data using CGI.pm's 'named param' syntax.
284 # Only public records can be set!
285 my %args = @args;
286 my ($name, $value) = @args{ qw(-name -value) };
287 if (defined $name && defined $value) {
288 if ($name =~ m/^_SESSION_/) {
289
290 carp "param(): attempt to write to private parameter";
291 return undef;
292 }
293 $self->_set_status( STATUS_MODIFIED );
294 return $self->{_DATA}->{ $name } = $value;
295 }
296
297 # USAGE: $s->param(-name=>$n);
298 # DESC: access to session data (public & private) using CGI.pm's 'named parameter' syntax.
299 return $self->{_DATA}->{ $args{'-name'} } if defined $args{'-name'};
300
301 # USAGE: $s->param($name, $value);
302 # USAGE: $s->param($name1 => $value1, $name2 => $value2 [,...]);
303 # DESC: updates one or more **public** records using simple syntax
304418µs4µs if ((@args % 2) == 0) {
305 my $modified_cnt = 0;
306 ARG_PAIR:
30733µs933ns while (my ($name, $val) = each %args) {
30812µs2µs if ( $name =~ m/^_SESSION_/) {
309 carp "param(): attempt to write to private parameter";
310 next ARG_PAIR;
311 }
312 $self->{_DATA}->{ $name } = $val;
313 ++$modified_cnt;
314 }
315 $self->_set_status(STATUS_MODIFIED);
# spent 14µs making 1 call to CGI::Session::_set_status
316 return $modified_cnt;
317 }
318
319 # If we reached this far none of the expected syntax were
320 # detected. Syntax error
321 croak "param(): usage error. Invalid syntax";
322}
323
324
325
326sub delete { $_[0]->_set_status( STATUS_DELETED ) }
327
328
329*header = \&http_header;
330my $avoid_single_use_warning_again = *header;
331sub http_header {
332 my $self = shift;
333 return $self->query->header(-cookie=>$self->cookie, -type=>'text/html', @_);
334}
335
336sub cookie {
337 my $self = shift;
338
339 my $query = $self->query();
340 my $cookie= undef;
341
342 if ( $self->is_expired ) {
343 $cookie = $query->cookie( -name=>$self->name, -value=>$self->id, -expires=> '-1d', @_ );
344 }
345 elsif ( my $t = $self->expire ) {
346 $cookie = $query->cookie( -name=>$self->name, -value=>$self->id, -expires=> '+' . $t . 's', @_ );
347 }
348 else {
349 $cookie = $query->cookie( -name=>$self->name, -value=>$self->id, @_ );
350 }
351 return $cookie;
352}
353
354
355
356
357
358sub save_param {
359 my $self = shift;
360 my ($query, $params) = @_;
361
362 $query ||= $self->query();
363 $params ||= [ $query->param ];
364
365 for my $p ( @$params ) {
366 my @values = $query->param($p) or next;
367 if ( @values > 1 ) {
368 $self->param($p, \@values);
369 } else {
370 $self->param($p, $values[0]);
371 }
372 }
373 $self->_set_status( STATUS_MODIFIED );
374}
375
376
377
378sub load_param {
379 my $self = shift;
380 my ($query, $params) = @_;
381
382 $query ||= $self->query();
383 $params ||= [ $self->param ];
384
385 for ( @$params ) {
386 $query->param(-name=>$_, -value=>$self->param($_));
387 }
388}
389
390
391sub clear {
392 my $self = shift;
393 my $params = shift;
394 #warn ref($params);
395 if (defined $params) {
396 $params = [ $params ] unless ref $params;
397 }
398 else {
399 $params = [ $self->param ];
400 }
401
402 for ( grep { ! /^_SESSION_/ } @$params ) {
403 delete $self->{_DATA}->{$_};
404 }
405 $self->_set_status( STATUS_MODIFIED );
406}
407
408
409sub find {
410 my $class = shift;
411 my ($dsn, $coderef, $dsn_args);
412
413 # find( \%code )
414 if ( @_ == 1 ) {
415 $coderef = $_[0];
416 }
417 # find( $dsn, \&code, \%dsn_args )
418 else {
419 ($dsn, $coderef, $dsn_args) = @_;
420 }
421
422 unless ( $coderef && ref($coderef) && (ref $coderef eq 'CODE') ) {
423 croak "find(): usage error.";
424 }
425
426 my $driver;
427 if ( $dsn ) {
428 my $hashref = $class->parse_dsn( $dsn );
429 $driver = $hashref->{driver};
430 }
431 $driver ||= "file";
432 my $pm = "CGI::Session::Driver::" . ($driver =~ /(.*)/)[0];
433 eval "require $pm";
434 if (my $errmsg = $@ ) {
435 return $class->set_error( "find(): couldn't load driver." . $errmsg );
436 }
437
438 my $driver_obj = $pm->new( $dsn_args );
439 unless ( $driver_obj ) {
440 return $class->set_error( "find(): couldn't create driver object. " . $pm->errstr );
441 }
442
443 my $dont_update_atime = 0;
444 my $driver_coderef = sub {
445 my ($sid) = @_;
446 my $session = $class->load( $dsn, $sid, $dsn_args, $dont_update_atime );
447 unless ( $session ) {
448 return $class->set_error( "find(): couldn't load session '$sid'. " . $class->errstr );
449 }
450 $coderef->( $session );
451 };
452
453 defined($driver_obj->traverse( $driver_coderef ))
454 or return $class->set_error( "find(): traverse seems to have failed. " . $driver_obj->errstr );
455 return 1;
456}
457
458# $Id: Session.pm 454 2008-12-16 01:20:54Z markstos $
459
460=pod
461
462=head1 NAME
463
464CGI::Session - persistent session data in CGI applications
465
466=head1 SYNOPSIS
467
468 # Object initialization:
469 use CGI::Session;
470 $session = new CGI::Session();
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
506CGI::Session provides an easy, reliable and modular session management system across HTTP requests.
507
508=head1 METHODS
509
510Following 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
524Constructor. 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
526Can 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
528If 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
530If 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
532If 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
540Briefly, C<new()> will return an initialized session object with a valid id, whereas C<load()> may return
541an empty session object with an undefined id.
542
543Tests are provided (t/new_with_undef.t and t/load_with_undef.t) to clarify the result of calling C<new()> and C<load()>
544with undef, or with an initialized CGI object with an undefined or fake CGISESSID.
545
546You are strongly advised to run the old-fashioned 'make test TEST_FILES=t/new_with_undef.t TEST_VERBOSE=1'
547or the new-fangled 'prove -v t/new_with_undef.t', for both new*.t and load*.t, and examine the output.
548
549Following data source components are supported:
550
551=over 4
552
553=item *
554
555B<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
559B<serializer> - serializer to be used to encode the data structure before saving
560in 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
564B<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
568For example, to get CGI::Session store its data using DB_File and serialize data using FreezeThaw:
569
570 $s = new CGI::Session("driver:DB_File;serializer:FreezeThaw", undef);
571
572If 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
574If 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
576The following is a list of the current keys:
577
578=over
579
580=item *
581
582B<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
586undef 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
598Accepts the same arguments as new(), and also returns a new session object, or
599undef on failure. The difference is, L<new()|/"new"> can create a new session if
600it detects expired and non-existing sessions, but C<load()> does not.
601
602C<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
617Notice: All I<expired> sessions are empty, but not all I<empty> sessions are expired!
618
619Briefly, C<new()> will return an initialized session object with a valid id, whereas C<load()> may return
620an empty session object with an undefined id.
621
622Tests are provided (t/new_with_undef.t and t/load_with_undef.t) to clarify the result of calling C<new()> and C<load()>
623with undef, or with an initialized CGI object with an undefined or fake CGISESSID.
624
625You are strongly advised to run the old-fashioned 'make test TEST_FILES=t/new_with_undef.t TEST_VERBOSE=1'
626or 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
# spent 20.3ms (104µs+20.2) within CGI::Session::load which was called # once (104µs+20.2ms) by CGI::Session::new at line 64
sub load {
63425155µs6µs my $class = shift;
635 return $class->set_error( "called as instance method") if ref $class;
636 return $class->set_error( "Too many arguments provided to load()") if @_ > 5;
637
638 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 my ($dsn,$query_or_sid,$dsn_args,$update_atime,$params);
661 # load($query||$sid)
662635µs6µs if ( @_ == 1 ) {
663 $self->_set_query_or_sid($_[0]);
664 }
665 # Two or more args passed:
666 # load($dsn, $query||$sid)
667 elsif ( @_ > 1 ) {
668 ($dsn, $query_or_sid, $dsn_args,$update_atime) = @_;
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 if ( ref $update_atime and ref $update_atime eq 'HASH' ) {
674 $params = {%$update_atime};
675 $update_atime = $params->{'update_atime'};
676
677 if ($params->{'name'}) {
678 $self->{_NAME} = $params->{'name'};
679 }
680 }
681
682 # Since $update_atime is not part of the public API
683 # we ignore any value but the one we use internally: 0.
684 if (defined $update_atime and $update_atime ne '0') {
685 return $class->set_error( "Too many arguments to load(). First extra argument was: $update_atime");
686 }
687
688 if ( defined $dsn ) { # <-- to avoid 'Uninitialized value...' warnings
# spent 790µs making 1 call to CGI::Session::parse_dsn
689 $self->{_DSN} = $self->parse_dsn($dsn);
690 }
691 $self->_set_query_or_sid($query_or_sid);
# spent 18µs making 1 call to CGI::Session::_set_query_or_sid
692
693 # load($dsn, $query, \%dsn_args);
694
695 $self->{_DRIVER_ARGS} = $dsn_args if defined $dsn_args;
696
697 }
698
699 $self->_load_pluggables();
# spent 16.9ms making 1 call to CGI::Session::_load_pluggables
700
701 # Did load_pluggable fail? If so, return undef, just like $class->set_error() would
702 return undef if $class->errstr;
# spent 25µs making 1 call to CGI::Session::ErrorHandler::errstr
703
704 if (not defined $self->{_CLAIMED_ID}) {
705 my $query = $self->query();
706 eval {
707 $self->{_CLAIMED_ID} = $query->cookie( $self->name ) || $query->param( $self->name );
708 };
709 if ( my $errmsg = $@ ) {
710 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 return $self unless $self->{_CLAIMED_ID};
716
717 # Attempting to load the session
718 my $driver = $self->_driver();
# spent 126µs making 1 call to CGI::Session::_driver
719 my $raw_data = $driver->retrieve( $self->{_CLAIMED_ID} );
# spent 1.53ms making 1 call to CGI::Session::Driver::DBI::retrieve
720 unless ( defined $raw_data ) {
721 return $self->set_error( "load(): couldn't retrieve data: " . $driver->errstr );
722 }
723
724 # Requested session couldn't be retrieved
725 return $self unless $raw_data;
726
727 my $serializer = $self->_serializer();
# spent 19µs making 1 call to CGI::Session::_serializer
728 $self->{_DATA} = $serializer->thaw($raw_data);
# spent 835µs making 1 call to CGI::Session::Serialize::yaml::thaw
729 unless ( defined $self->{_DATA} ) {
730 #die $raw_data . "\n";
731 return $self->set_error( "load(): couldn't thaw() data using $serializer:" .
732 $serializer->errstr );
733 }
734 unless (defined($self->{_DATA}) && ref ($self->{_DATA}) && (ref $self->{_DATA} eq 'HASH') &&
735 defined($self->{_DATA}->{_SESSION_ID}) ) {
736 return $self->set_error( "Invalid data structure returned from thaw()" );
737 }
738
739 # checking if previous session ip matches current ip
740 if($CGI::Session::IP_MATCH) {
741 unless($self->_ip_matches) {
742 $self->_set_status( STATUS_DELETED );
743 $self->flush;
744 return $self;
745 }
746 }
747
748 # checking for expiration ticker
749 if ( $self->{_DATA}->{_SESSION_ETIME} ) {
750 if ( ($self->{_DATA}->{_SESSION_ATIME} + $self->{_DATA}->{_SESSION_ETIME}) <= time() ) {
751 $self->_set_status( STATUS_EXPIRED | # <-- so client can detect expired sessions
752 STATUS_DELETED ); # <-- session should be removed from database
753 $self->flush(); # <-- flush() will do the actual removal!
754 return $self;
755 }
756 }
757
758 # checking expiration tickers of individuals parameters, if any:
759 my @expired_params = ();
760 while (my ($param, $max_exp_interval) = each %{ $self->{_DATA}->{_SESSION_EXPIRE_LIST} } ) {
761 if ( ($self->{_DATA}->{_SESSION_ATIME} + $max_exp_interval) <= time() ) {
762 push @expired_params, $param;
763 }
764 }
765 $self->clear(\@expired_params) if @expired_params;
766
767 # We update the atime by default, but if this (otherwise undocoumented)
768 # parameter is explicitly set to false, we'll turn the behavior off
769217µs9µs if ( ! defined $update_atime ) {
770 $self->{_DATA}->{_SESSION_ATIME} = time(); # <-- updating access time
771 $self->_set_status( STATUS_MODIFIED ); # <-- access time modified above
# spent 18µs making 1 call to CGI::Session::_set_status
772 }
773
774 return $self;
775}
776
777
778# set the input as a query object or session ID, depending on what it looks like.
779
# spent 18µs within CGI::Session::_set_query_or_sid which was called # once (18µs+0s) by CGI::Session::load at line 691
sub _set_query_or_sid {
78034µs1µs my $self = shift;
781 my $query_or_sid = shift;
78211µs1µs if ( ref $query_or_sid){ $self->{_QUERY} = $query_or_sid }
783 else { $self->{_CLAIMED_ID} = $query_or_sid }
784}
785
786
787
# spent 16.9ms (8.23+8.63) within CGI::Session::_load_pluggables which was called # once (8.23ms+8.63ms) by CGI::Session::load at line 699
sub _load_pluggables {
788613µs2µs my ($self) = @_;
789
790 my %DEFAULT_FOR = (
791 driver => "file",
792 serializer => "default",
793 id => "md5",
794 );
795 my %SUBDIR_FOR = (
796 driver => "Driver",
797 serializer => "Serialize",
798 id => "ID",
799 );
800 my $dsn = $self->{_DSN};
801 foreach my $plug qw(driver serializer id) {
802926µs3µs my $mod_name = $dsn->{ $plug };
803 if (not defined $mod_name) {
804 $mod_name = $DEFAULT_FOR{ $plug };
805 }
80618271µs15µs if ($mod_name =~ /^(\w+)$/) {
807
808 # Looks good. Put it into the dsn hash
809 $dsn->{ $plug } = $mod_name = $1;
810
811 # Put together the actual module name to load
812 my $prefix = join '::', (__PACKAGE__, $SUBDIR_FOR{ $plug }, q{});
813 $mod_name = $prefix . $mod_name;
814
815 ## See if we can load load it
8161694µs694µs eval "require $mod_name";
817 if ($@) {
818 my $msg = $@;
819 return $self->set_error("couldn't load $mod_name: " . $msg);
820 }
821 }
822 else {
823 # do something here about bad name for a pluggable
824 }
825 }
826 return;
827}
828
829=pod
830
831=head2 id()
832
833Returns effective ID for a session. Since effective ID and claimed ID can differ, valid session id should always
834be retrieved using this method.
835
836=head2 param($name)
837
838=head2 param(-name=E<gt>$name)
839
840Used 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.
841
842=head2 param($name, $value)
843
844=head2 param(-name=E<gt>$name, -value=E<gt>$value)
845
846Used in either of the above syntax assigns a new value to $name parameter,
847which can later be retrieved with previously introduced param() syntax. C<$value>
848may be a scalar, arrayref or hashref.
849
850Attempts to set parameter names that start with I<_SESSION_> will trigger
851a warning and undef will be returned.
852
853=head2 param_hashref()
854
855B<Deprecated>. Use L<dataref()|/"dataref"> instead.
856
857=head2 dataref()
858
859Returns reference to session's data table:
860
861 $params = $s->dataref();
862 $sid = $params->{_SESSION_ID};
863 $name= $params->{name};
864 # etc...
865
866Useful for having all session data in a hashref, but too risky to update.
867
868=head2 save_param()
869
870=head2 save_param($query)
871
872=head2 save_param($query, \@list)
873
874Saves query parameters to session object. In other words, it's the same as calling L<param($name, $value)|/"param"> 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.
875
876=head2 load_param()
877
878=head2 load_param($query)
879
880=head2 load_param($query, \@list)
881
882Loads 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.
883
884=head2 clear()
885
886=head2 clear('field')
887
888=head2 clear(\@list)
889
890Clears parameters from the session object.
891
892With no parameters, all fields are cleared. If passed a single parameter or a
893reference to an array, only the named parameters are cleared.
894
895=head2 flush()
896
897Synchronizes data in memory with the copy serialized by the driver. Call flush()
898if you need to access the session from outside the current session object. You should
899call flush() sometime before your program exits.
900
901As a last resort, CGI::Session will automatically call flush for you just
902before the program terminates or session object goes out of scope. Automatic
903flushing has proven to be unreliable, and in some cases is now required
904in places that worked with CGI::Session 3.x.
905
906Always explicitly calling C<flush()> on the session before the
907program exits is recommended. For extra safety, call it immediately after
908every important session update.
909
910Also see L<A Warning about Auto-flushing>
911
912=head2 atime()
913
914Read-only method. Returns the last access time of the session in seconds from epoch. This time is used internally while
915auto-expiring sessions and/or session parameters.
916
917=head2 ctime()
918
919Read-only method. Returns the time when the session was first created in seconds from epoch.
920
921=head2 expire()
922
923=head2 expire($time)
924
925=head2 expire($param, $time)
926
927Sets expiration interval relative to L<atime()|/"atime">.
928
929If 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.
930
931Second 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.
932
933By using the third syntax you can set the expiration interval for a particular
934session parameter, say I<~logged-in>. This would cause the library call clear()
935on the parameter when its time is up. Note it only makes sense to set this value to
936something I<earlier> than when the whole session expires. Passing 0 cancels expiration.
937
938All the time values should be given in the form of seconds. Following keywords are also supported for your convenience:
939
940 +-----------+---------------+
941 | alias | meaning |
942 +-----------+---------------+
943 | s | Second |
944 | m | Minute |
945 | h | Hour |
946 | d | Day |
947 | w | Week |
948 | M | Month |
949 | y | Year |
950 +-----------+---------------+
951
952Examples:
953
954 $session->expire("2h"); # expires in two hours
955 $session->expire(0); # cancel expiration
956 $session->expire("~logged-in", "10m"); # expires '~logged-in' parameter after 10 idle minutes
957
958Note: 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">.
959
960=cut
961
962*expires = \&expire;
963my $prevent_warning = \&expires;
964sub etime { $_[0]->expire() }
965sub expire {
966 my $self = shift;
967
968 # no params, just return the expiration time.
969 if (not @_) {
970 return $self->{_DATA}->{_SESSION_ETIME};
971 }
972 # We have just a time
973 elsif ( @_ == 1 ) {
974 my $time = $_[0];
975 # If 0 is passed, cancel expiration
976 if ( defined $time && ($time =~ m/^\d$/) && ($time == 0) ) {
977 $self->{_DATA}->{_SESSION_ETIME} = undef;
978 $self->_set_status( STATUS_MODIFIED );
979 }
980 # set the expiration to this time
981 else {
982 $self->{_DATA}->{_SESSION_ETIME} = $self->_str2seconds( $time );
983 $self->_set_status( STATUS_MODIFIED );
984 }
985 }
986 # If we get this far, we expect expire($param,$time)
987 # ( This would be a great use of a Perl6 multi sub! )
988 else {
989 my ($param, $time) = @_;
990 if ( ($time =~ m/^\d$/) && ($time == 0) ) {
991 delete $self->{_DATA}->{_SESSION_EXPIRE_LIST}->{ $param };
992 $self->_set_status( STATUS_MODIFIED );
993 } else {
994 $self->{_DATA}->{_SESSION_EXPIRE_LIST}->{ $param } = $self->_str2seconds( $time );
995 $self->_set_status( STATUS_MODIFIED );
996 }
997 }
998 return 1;
999}
1000
1001# =head2 _str2seconds()
1002#
1003# my $secs = $self->_str2seconds('1d')
1004#
1005# Takes a CGI.pm-style time representation and returns an equivalent number
1006# of seconds.
1007#
1008# See the docs of expire() for more detail.
1009#
1010# =cut
1011
1012sub _str2seconds {
1013 my $self = shift;
1014 my ($str) = @_;
1015
1016 return unless defined $str;
1017 return $str if $str =~ m/^[-+]?\d+$/;
1018
1019 my %_map = (
1020 s => 1,
1021 m => 60,
1022 h => 3600,
1023 d => 86400,
1024 w => 604800,
1025 M => 2592000,
1026 y => 31536000
1027 );
1028
1029 my ($koef, $d) = $str =~ m/^([+-]?\d+)([smhdwMy])$/;
1030 unless ( defined($koef) && defined($d) ) {
1031 die "_str2seconds(): couldn't parse '$str' into \$koef and \$d parts. Possible invalid syntax";
1032 }
1033 return $koef * $_map{ $d };
1034}
1035
1036
1037=pod
1038
1039=head2 is_new()
1040
1041Returns true only for a brand new session.
1042
1043=head2 is_expired()
1044
1045Tests whether session initialized using L<load()|/"load"> is to be expired. This method works only on sessions initialized with load():
1046
1047 $s = CGI::Session->load() or die CGI::Session->errstr;
1048 if ( $s->is_expired ) {
1049 die "Your session expired. Please refresh";
1050 }
1051 if ( $s->is_empty ) {
1052 $s = $s->new() or die $s->errstr;
1053 }
1054
1055
1056=head2 is_empty()
1057
1058Returns true for sessions that are empty. It's preferred way of testing whether requested session was loaded successfully or not:
1059
1060 $s = CGI::Session->load($sid);
1061 if ( $s->is_empty ) {
1062 $s = $s->new();
1063 }
1064
1065Actually, the above code is nothing but waste. The same effect could've been achieved by saying:
1066
1067 $s = CGI::Session->new( $sid );
1068
1069L<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.
1070
1071=head2 delete()
1072
1073Sets the objects status to be "deleted". Subsequent read/write requests on the
1074same object will fail. To physically delete it from the data store you need to call L<flush()>.
1075CGI::Session attempts to do this automatically when the object is being destroyed (usually as
1076the script exits), but see L<A Warning about Auto-flushing>.
1077
1078=head2 find( \&code )
1079
1080=head2 find( $dsn, \&code )
1081
1082=head2 find( $dsn, \&code, \%dsn_args )
1083
1084Experimental 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:
1085
1086The following line, for instance, will remove sessions already expired, but which are still on disk:
1087
1088 CGI::Session->find( sub {} );
1089
1090Notice, above \&code didn't have to do anything, because load(), which is called to initialize sessions inside find(), will automatically remove expired sessions. Following example will remove all the objects that are 10+ days old:
1091
1092 CGI::Session->find( \&purge );
1093 sub purge {
1094 my ($session) = @_;
1095 next if $session->is_empty; # <-- already expired?!
1096 if ( ($session->ctime + 3600*240) <= time() ) {
1097 $session->delete();
1098 $session->flush(); # Recommended practice says use flush() after delete().
1099 }
1100 }
1101
1102B<Note>: find will not change the modification or access times on the sessions it returns.
1103
1104Explanation of the 3 parameters to C<find()>:
1105
1106=over 4
1107
1108=item $dsn
1109
1110This is the DSN (Data Source Name) used by CGI::Session to control what type of
1111sessions you previously created and what type of sessions you now wish method
1112C<find()> to pass to your callback.
1113
1114The default value is defined above, in the docs for method C<new()>, and is
1115'driver:file;serializer:default;id:md5'.
1116
1117Do not confuse this DSN with the DSN arguments mentioned just below, under \%dsn_args.
1118
1119=item \&code
1120
1121This is the callback provided by you (i.e. the caller of method C<find()>)
1122which is called by CGI::Session once for each session found by method C<find()>
1123which matches the given $dsn.
1124
1125There is no default value for this coderef.
1126
1127When your callback is actually called, the only parameter is a session. If you
1128want to call a subroutine you already have with more parameters, you can
1129achieve this by creating an anonymous subroutine that calls your subroutine
1130with the parameters you want. For example:
1131
1132 CGI::Session->find($dsn, sub { my_subroutine( @_, 'param 1', 'param 2' ) } );
1133 CGI::Session->find($dsn, sub { $coderef->( @_, $extra_arg ) } );
1134
1135Or if you wish, you can define a sub generator as such:
1136
1137 sub coderef_with_args {
1138 my ( $coderef, @params ) = @_;
1139 return sub { $coderef->( @_, @params ) };
1140 }
1141
1142 CGI::Session->find($dsn, coderef_with_args( $coderef, 'param 1', 'param 2' ) );
1143
1144=item \%dsn_args
1145
1146If your $dsn uses file-based storage, then this hashref might contain keys such as:
1147
1148 {
1149 Directory => Value 1,
1150 NoFlock => Value 2,
1151 UMask => Value 3
1152 }
1153
1154If your $dsn uses db-based storage, then this hashref contains (up to) 3 keys, and looks like:
1155
1156 {
1157 DataSource => Value 1,
1158 User => Value 2,
1159 Password => Value 3
1160 }
1161
1162These 3 form the DSN, username and password used by DBI to control access to your database server,
1163and hence are only relevant when using db-based sessions.
1164
1165The default value of this hashref is undef.
1166
1167=back
1168
1169B<Note:> find() is meant to be convenient, not necessarily efficient. It's best suited in cron scripts.
1170
1171=head1 MISCELLANEOUS METHODS
1172
1173=head2 remote_addr()
1174
1175Returns 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.
1176
1177=cut
1178
1179sub remote_addr { return $_[0]->{_DATA}->{_SESSION_REMOTE_ADDR} }
1180
1181=pod
1182
1183=head2 errstr()
1184
1185Class method. Returns last error message from the library.
1186
1187=head2 dump()
1188
1189Returns a dump of the session object. Useful for debugging purposes only.
1190
1191=head2 header()
1192
1193Replacement for L<CGI.pm|CGI>'s header() method. Without this method, you usually need to create a CGI::Cookie object and send it as part of the HTTP header:
1194
1195 $cookie = CGI::Cookie->new(-name=>$session->name, -value=>$session->id);
1196 print $cgi->header(-cookie=>$cookie);
1197
1198You can minimize the above into:
1199
1200 print $session->header();
1201
1202It 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 following before creating session object:
1203
1204 CGI::Session->name("MY_SID");
1205 $session = new CGI::Session(undef, $cgi, \%attrs);
1206
1207Now, $session->header() uses "MY_SID" as a name for the session cookie.
1208
1209=head2 query()
1210
1211Returns query object associated with current session object. Default query object class is L<CGI.pm|CGI>.
1212
1213=head2 DEPRECATED METHODS
1214
1215These methods exist solely for for compatibility with CGI::Session 3.x.
1216
1217=head3 close()
1218
1219Closes the session. Using flush() is recommended instead, since that's exactly what a call
1220to close() does now.
1221
1222=head1 DISTRIBUTION
1223
1224CGI::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.
1225
1226=head2 DRIVERS
1227
1228Following drivers are included in the standard distribution:
1229
1230=over 4
1231
1232=item *
1233
1234L<file|CGI::Session::Driver::file> - default driver for storing session data in plain files. Full name: B<CGI::Session::Driver::file>
1235
1236=item *
1237
1238L<db_file|CGI::Session::Driver::db_file> - for storing session data in BerkelyDB. Requires: L<DB_File>.
1239Full name: B<CGI::Session::Driver::db_file>
1240
1241=item *
1242
1243L<mysql|CGI::Session::Driver::mysql> - for storing session data in MySQL tables. Requires L<DBI|DBI> and L<DBD::mysql|DBD::mysql>.
1244Full name: B<CGI::Session::Driver::mysql>
1245
1246=item *
1247
1248L<sqlite|CGI::Session::Driver::sqlite> - for storing session data in SQLite. Requires L<DBI|DBI> and L<DBD::SQLite|DBD::SQLite>.
1249Full name: B<CGI::Session::Driver::sqlite>
1250
1251=back
1252
1253=head2 SERIALIZERS
1254
1255=over 4
1256
1257=item *
1258
1259L<default|CGI::Session::Serialize::default> - default data serializer. Uses standard L<Data::Dumper|Data::Dumper>.
1260Full name: B<CGI::Session::Serialize::default>.
1261
1262=item *
1263
1264L<storable|CGI::Session::Serialize::storable> - serializes data using L<Storable>. Requires L<Storable>.
1265Full name: B<CGI::Session::Serialize::storable>.
1266
1267=item *
1268
1269L<freezethaw|CGI::Session::Serialize::freezethaw> - serializes data using L<FreezeThaw>. Requires L<FreezeThaw>.
1270Full name: B<CGI::Session::Serialize::freezethaw>
1271
1272=item *
1273
1274L<yaml|CGI::Session::Serialize::yaml> - serializes data using YAML. Requires L<YAML> or L<YAML::Syck>.
1275Full name: B<CGI::Session::Serialize::yaml>
1276
1277=back
1278
1279=head2 ID GENERATORS
1280
1281Following ID generators are available:
1282
1283=over 4
1284
1285=item *
1286
1287L<md5|CGI::Session::ID::md5> - generates 32 character long hexadecimal string. Requires L<Digest::MD5|Digest::MD5>.
1288Full name: B<CGI::Session::ID::md5>.
1289
1290=item *
1291
1292L<incr|CGI::Session::ID::incr> - generates incremental session ids.
1293
1294=item *
1295
1296L<static|CGI::Session::ID::static> - generates static session ids. B<CGI::Session::ID::static>
1297
1298=back
1299
1300=head1 A Warning about Auto-flushing
1301
1302Auto-flushing can be unreliable for the following reasons. Explict flushing
1303after key session updates is recommended.
1304
1305=over 4
1306
1307=item If the C<DBI> handle goes out of scope before the session variable
1308
1309For database-stored sessions, if the C<DBI> handle has gone out of scope before
1310the auto-flushing happens, auto-flushing will fail.
1311
1312=item Circular references
1313
1314If the calling code contains a circular reference, it's possible that your
1315C<CGI::Session> object will not be destroyed until it is too late for
1316auto-flushing to work. You can find circular references with a tool like
1317L<Devel::Cycle>.
1318
1319In particular, these modules are known to contain circular references which
1320lead to this problem:
1321
1322=over 4
1323
1324=item CGI::Application::Plugin::DebugScreen V 0.06
1325
1326=item CGI::Application::Plugin::ErrorPage before version 1.20
1327
1328=back
1329
1330=item Signal handlers
1331
1332If your application may receive signals, there is an increased chance that the
1333signal will arrive after the session was updated but before it is auto-flushed
1334at object destruction time.
1335
1336=back
1337
1338=head1 A Warning about UTF8
1339
1340Trying to use UTF8 in a program which uses CGI::Session has lead to problems. See RT#21981 and RT#28516.
1341
1342In the first case the user tried "use encoding 'utf8';" in the program, and in the second case the user tried
1343"$dbh->do(qq|set names 'utf8'|);".
1344
1345Until this problem is understood and corrected, users are advised to avoid UTF8 in conjunction with CGI::Session.
1346
1347For details, see: http://rt.cpan.org/Public/Bug/Display.html?id=28516 (and ...id=21981).
1348
1349=head1 TRANSLATIONS
1350
1351This document is also available in Japanese.
1352
1353=over 4
1354
1355=item o
1356
1357Translation based on 4.14: http://digit.que.ne.jp/work/index.cgi?Perldoc/ja
1358
1359=item o
1360
1361Translation based on 3.11, including Cookbook and Tutorial: http://perldoc.jp/docs/modules/CGI-Session-3.11/
1362
1363=back
1364
1365=head1 CREDITS
1366
1367CGI::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
1368
1369=over 4
1370
1371=item Andy Lester
1372
1373=item Brian King E<lt>mrbbking@mac.comE<gt>
1374
1375=item Olivier Dragon E<lt>dragon@shadnet.shad.caE<gt>
1376
1377=item Adam Jacob E<lt>adam@sysadminsith.orgE<gt>
1378
1379=item Igor Plisco E<lt>igor@plisco.ruE<gt>
1380
1381=item Mark Stosberg
1382
1383=item Matt LeBlanc E<lt>mleblanc@cpan.orgE<gt>
1384
1385=item Shawn Sorichetti
1386
1387=item Ron Savage
1388
1389=item Rhesa Rozendaal
1390
1391He suggested Devel::Cycle to help debugging.
1392
1393=back
1394
1395Also, many people on the CGI::Application and CGI::Session mailing lists have contributed ideas and
1396suggestions, and battled publicly with bugs, all of which has helped.
1397
1398=head1 COPYRIGHT
1399
1400Copyright (C) 2001-2005 Sherzod Ruzmetov E<lt>sherzodr@cpan.orgE<gt>. All rights reserved.
1401This library is free software. You can modify and or distribute it under the same terms as Perl itself.
1402
1403=head1 PUBLIC CODE REPOSITORY
1404
1405You can see what the developers have been up to since the last release by
1406checking out the code repository. You can browse the Subversion repository from here:
1407
1408 http://svn.cromedome.net/repos/CGI-Session
1409
1410Or check it directly with C<svn> from here:
1411
1412 https://svn.cromedome.net/repos/CGI-Session
1413
1414=head1 SUPPORT
1415
1416If you need help using CGI::Session consider the mailing list. You can ask the list by sending your questions to
1417cgi-session-user@lists.sourceforge.net .
1418
1419You can subscribe to the mailing list at https://lists.sourceforge.net/lists/listinfo/cgi-session-user .
1420
1421Bug reports can be submitted at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=CGI-Session
1422
1423=head1 AUTHOR
1424
1425Sherzod Ruzmetov E<lt>sherzodr@cpan.orgE<gt>, http://author.handalak.com/
1426
1427Mark Stosberg became a co-maintainer during the development of 4.0. C<markstos@cpan.org>.
1428Ron Savage became a co-maintainer during the development of 4.30. C<rsavage@cpan.org>.
1429
1430=head1 SEE ALSO
1431
1432To learn more both about the philosophy and CGI::Session programming style,
1433consider the following:
1434
1435=over 4
1436
1437=item *
1438
1439L<CGI::Session::Tutorial|CGI::Session::Tutorial> - extended CGI::Session manual. Also includes library architecture and driver specifications.
1440
1441=item *
1442
1443We also provide mailing lists for CGI::Session users. To subscribe to the list
1444or browse the archives visit
1445https://lists.sourceforge.net/lists/listinfo/cgi-session-user
1446
1447=item * B<RFC 2109> - The primary spec for cookie handing in use, defining the "Cookie:" and "Set-Cookie:" HTTP headers.
1448Available at L<http://www.ietf.org/rfc/rfc2109.txt>. A newer spec, RFC 2965 is meant to obsolete it with "Set-Cookie2"
1449and "Cookie2" headers, but even of 2008, the newer spec is not widely supported. See L<http://www.ietf.org/rfc/rfc2965.txt>
1450
1451=item *
1452
1453L<Apache::Session|Apache::Session> - an alternative to CGI::Session.
1454
1455=back
1456
1457=cut
1458
14591;
1460