File Coverage

blib/lib/Apache/Session/Wrapper.pm
Criterion Covered Total %
statement 172 225 76.4
branch 53 118 44.9
condition 21 56 37.5
subroutine 27 31 87.1
pod 3 7 42.8
total 276 437 63.1


line stmt bran cond sub pod time code
1             package Apache::Session::Wrapper;
2              
3 2     2   31646 use strict;
  2         2  
  2         56  
4              
5 2     2   6 use vars qw($VERSION);
  2         2  
  2         99  
6              
7             $VERSION = '0.33_01';
8             $VERSION = eval $VERSION;
9              
10 2     2   16 use base qw(Class::Container);
  2         2  
  2         1127  
11              
12 2     2   21481 use Apache::Session 1.81;
  2         1214  
  2         70  
13              
14 2         21 use Exception::Class ( 'Apache::Session::Wrapper::Exception::NonExistentSessionID' =>
15             { description => 'A non-existent session id was used',
16             fields => [ 'session_id' ] },
17             'Apache::Session::Wrapper::Exception::Params' =>
18             { description => 'An invalid parameter or set of parameters was given',
19             alias => 'param_error' },
20 2     2   852 );
  2         12327  
21              
22 2     2   836 use Params::Validate 0.70;
  2         40  
  2         100  
23 2     2   7 use Params::Validate qw( validate SCALAR UNDEF BOOLEAN ARRAYREF OBJECT );
  2         2  
  2         146  
24             Params::Validate::validation_options( on_fail => sub { param_error( join '', @_ ) } );
25              
26 2     2   7 use Scalar::Util ();
  2         3  
  2         5040  
27              
28              
29             my $MOD_PERL = _find_mp_version();
30             sub _find_mp_version
31             {
32 2 50   2   8 return 0 unless $ENV{MOD_PERL};
33              
34             return
35 0 0       0 ( $ENV{MOD_PERL} =~ /(?:1\.9|2\.\d)/
36             ? 2
37             : 1
38             );
39             }
40              
41             my @HeaderMethods = qw( err_headers_out headers_out );
42              
43             my %params =
44             ( always_write =>
45             { type => BOOLEAN,
46             default => 1,
47             descr => 'Whether or not to force a write before the session goes out of scope' },
48              
49             allow_invalid_id =>
50             { type => BOOLEAN,
51             default => 1,
52             descr => 'Whether or not to allow a failure to find an existing session id' },
53              
54             param_name =>
55             { type => SCALAR,
56             optional => 1,
57             depends => 'param_object',
58             descr => 'Name of the parameter to use for session tracking' },
59              
60             param_object =>
61             { type => OBJECT,
62             optional => 1,
63             can => 'param',
64             descr => 'Object which has a "param" method, to be used for getting the session id from a query string or POST argument' },
65              
66             use_cookie =>
67             { type => BOOLEAN,
68             default => 0,
69             descr => 'Whether or not to use a cookie to track the session' },
70              
71             cookie_name =>
72             { type => SCALAR,
73             default => 'Apache-Session-Wrapper-cookie',
74             descr => 'Name of cookie used by this module' },
75              
76             cookie_expires =>
77             { type => UNDEF | SCALAR,
78             default => '+1d',
79             descr => 'Expiration time for cookies' },
80              
81             cookie_domain =>
82             { type => UNDEF | SCALAR,
83             optional => 1,
84             descr => 'Domain parameter for cookies' },
85              
86             cookie_path =>
87             { type => SCALAR,
88             default => '/',
89             descr => 'Path for cookies' },
90              
91             cookie_secure =>
92             { type => BOOLEAN,
93             default => 0,
94             descr => 'Are cookies sent only for SSL connections?' },
95              
96             cookie_resend =>
97             { type => BOOLEAN,
98             default => 1,
99             descr => 'Resend the cookie on each request?' },
100              
101             header_object =>
102             { type => OBJECT,
103             callbacks =>
104             { 'has a method to set headers' =>
105             sub { grep { $_[0]->can($_) } @HeaderMethods } },
106             optional => 1,
107             descr => 'An object that can be used to send cookies with' },
108              
109             class =>
110             { type => SCALAR,
111             descr => 'An Apache::Session class to use for sessions' },
112              
113             data_source =>
114             { type => SCALAR,
115             optional => 1,
116             descr => 'The data source when using MySQL or PostgreSQL' },
117              
118             user_name =>
119             { type => UNDEF | SCALAR,
120             optional => 1,
121             descr => 'The user name to be used when connecting to a database' },
122              
123             password =>
124             { type => UNDEF | SCALAR,
125             default => undef,
126             descr => 'The password to be used when connecting to a database' },
127              
128             table_name =>
129             { type => UNDEF | SCALAR,
130             optional => 1,
131             descr => 'The table in which sessions are saved' },
132              
133             lock_data_source =>
134             { type => SCALAR,
135             optional => 1,
136             descr => 'The data source when using MySQL or PostgreSQL' },
137              
138             lock_user_name =>
139             { type => UNDEF | SCALAR,
140             optional => 1,
141             descr => 'The user name to be used when connecting to a database' },
142              
143             lock_password =>
144             { type => UNDEF | SCALAR,
145             default => undef,
146             descr => 'The password to be used when connecting to a database' },
147              
148             handle =>
149             { type => OBJECT,
150             optional => 1,
151             descr => 'An existing database handle to use' },
152              
153             lock_handle =>
154             { type => OBJECT,
155             optional => 1,
156             descr => 'An existing database handle to use' },
157              
158             commit =>
159             { type => BOOLEAN,
160             default => 1,
161             descr => 'Whether or not to auto-commit changes to the database' },
162              
163             transaction =>
164             { type => BOOLEAN,
165             default => 0,
166             descr => 'The Transaction flag for Apache::Session' },
167              
168             directory =>
169             { type => SCALAR,
170             optional => 1,
171             descr => 'A directory to use when storing sessions' },
172              
173             lock_directory =>
174             { type => SCALAR,
175             optional => 1,
176             descr => 'A directory to use for locking when storing sessions' },
177              
178             file_name =>
179             { type => SCALAR,
180             optional => 1,
181             descr => 'A DB_File to use' },
182              
183             store =>
184             { type => SCALAR,
185             optional => 1,
186             descr => 'A storage class to use with the Flex module' },
187              
188             lock =>
189             { type => SCALAR,
190             optional => 1,
191             descr => 'A locking class to use with the Flex module' },
192              
193             generate =>
194             { type => SCALAR,
195             default => 'MD5',
196             descr => 'A session generator class to use with the Flex module' },
197              
198             serialize =>
199             { type => SCALAR,
200             optional => 1,
201             descr => 'A serialization class to use with the Flex module' },
202              
203             textsize =>
204             { type => SCALAR,
205             optional => 1,
206             descr => 'A parameter for the Sybase storage module' },
207              
208             long_read_len =>
209             { type => SCALAR,
210             optional => 1,
211             descr => 'A parameter for the Oracle storage module' },
212              
213             n_sems =>
214             { type => SCALAR,
215             optional => 1,
216             descr => 'A parameter for the Semaphore locking module' },
217              
218             semaphore_key =>
219             { type => SCALAR,
220             optional => 1,
221             descr => 'A parameter for the Semaphore locking module' },
222              
223             mod_usertrack_cookie_name =>
224             { type => SCALAR,
225             optional => 1,
226             descr => 'The cookie name used by mod_usertrack' },
227              
228             save_path =>
229             { type => SCALAR,
230             optional => 1,
231             descr => 'Path used by Apache::Session::PHP' },
232              
233             session_id =>
234             { type => SCALAR,
235             optional => 1,
236             descr => 'Try this session id first when making a session' },
237             );
238              
239             # What set of parameters are required for each session class.
240             # Multiple array refs represent multiple possible sets of parameters
241             my %ApacheSessionParams =
242             ( Flex => [ [ qw( store lock generate serialize ) ] ],
243             MySQL => [ [ qw( data_source user_name
244             lock_data_source lock_user_name ) ],
245             [ qw( handle lock_handle ) ] ],
246             Postgres => [ [ qw( data_source user_name commit ) ],
247             [ qw( handle commit ) ] ],
248             File => [ [ qw( directory lock_directory ) ] ],
249             DB_File => [ [ qw( file_name lock_directory ) ] ],
250              
251             PHP => [ [ qw( save_path ) ] ],
252             );
253              
254             @ApacheSessionParams{ qw( Informix Oracle Sybase ) } =
255             ( $ApacheSessionParams{Postgres} ) x 3;
256              
257             my %OptionalApacheSessionParams =
258             ( MySQL => [ [ qw( table_name password lock_password ) ] ],
259             Postgres => [ [ qw( table_name password ) ] ],
260             Informix => [ [ qw( table_name password ) ] ],
261             Oracle => [ [ qw( long_read_len table_name password ) ] ],
262             Sybase => [ [ qw( textsize table_name password ) ] ],
263             );
264              
265             my %ApacheSessionFlexParams =
266             ( store =>
267             { MySQL => [ [ qw( data_source user_name ) ],
268             [ qw( handle ) ] ],
269             Postgres => $ApacheSessionParams{Postgres},
270             File => [ [ qw( directory ) ] ],
271             DB_File => [ [ qw( file_name ) ] ],
272             PHP => $ApacheSessionParams{PHP},
273             },
274             lock =>
275             { MySQL => [ [ qw( lock_data_source lock_user_name ) ],
276             [ qw( lock_handle ) ] ],
277             File => [ [ ] ],
278             Null => [ [ ] ],
279             Semaphore => [ [ ] ],
280             },
281             generate =>
282             { MD5 => [ [ ] ],
283             ModUniqueId => [ [ ] ],
284             ModUsertrack => [ [ qw( mod_usertrack_cookie_name ) ] ],
285             },
286             serialize =>
287             { Storable => [ [ ] ],
288             Base64 => [ [ ] ],
289             Sybase => [ [ ] ],
290             UUEncode => [ [ ] ],
291             PHP => [ [ ] ],
292             },
293             );
294              
295             @{ $ApacheSessionFlexParams{store} }{ qw( Informix Oracle Sybase ) } =
296             ( $ApacheSessionFlexParams{store}{Postgres} ) x 3;
297              
298             my %OptionalApacheSessionFlexParams =
299             ( store => { map { $_ => $OptionalApacheSessionParams{$_} }
300             qw( MySQL Postgres Informix Oracle Sybase ) },
301             );
302              
303             sub _SetValidParams {
304 7     7   7 my $class = shift;
305              
306 7         7 my %extra;
307 7         19 for my $hash ( \%ApacheSessionParams,
308             \%OptionalApacheSessionParams,
309             @ApacheSessionFlexParams{ qw( store lock generate serialize ) },
310             @OptionalApacheSessionFlexParams{ qw( store lock generate serialize ) },
311             )
312             {
313 70         81 for my $p ( map { @$_ } map { @$_ } values %$hash )
  383         307  
  303         233  
314             {
315 668         343 my $h;
316 668 50       796 if ( ref $p ) {
    100          
317             # we assume its a hash of names/parameter specifications
318 0         0 $h = $p;
319             } elsif (!$params{$p}) {
320             # its a new parameter defined by a scalar, default to SCALAR value
321 21         31 $h = { $p => { optional => 1, type => SCALAR } };
322             } else {
323             # its a scalar option we already know.
324 647         435 next;
325             }
326             # now expand the options
327 21         24 foreach my $name (keys %$h) {
328 21 50       31 next if $params{$name};
329 21         37 $extra{$p} = $h->{$name};
330             }
331             }
332             }
333              
334 7         68 $class->valid_params( %extra, %params );
335 7         147 $class->SetStudlyForms();
336             }
337             __PACKAGE__->_SetValidParams();
338              
339             my %StudlyForm;
340             sub SetStudlyForms
341             {
342             %StudlyForm =
343 668         646 ( map { $_ => _studly_form($_) }
344 383 50       403 map { ref $_ ? @$_ :$_ }
345 303         194 map { @$_ }
346             ( values %ApacheSessionParams ),
347             ( values %OptionalApacheSessionParams ),
348 28         15 ( map { values %{ $ApacheSessionFlexParams{$_} } }
  28         45  
349             keys %ApacheSessionFlexParams ),
350 7     7 0 19 ( map { values %{ $OptionalApacheSessionFlexParams{$_} } }
  28         17  
  28         26  
351             keys %OptionalApacheSessionFlexParams ),
352             );
353              
354             # why Apache::Session does this I do not know
355 7         102 $StudlyForm{textsize} = 'textsize';
356             }
357              
358             sub _studly_form
359             {
360 668     668   413 my $string = shift;
361 668         1907 $string =~ s/(?:^|_)(\w)/\U$1/g;
362 668         1017 return $string;
363             }
364              
365             sub RegisterClass {
366 3     3 0 1547 my $class = shift;
367 3         98 my %p = validate( @_, { name => { type => SCALAR },
368             required => { type => SCALAR | ARRAYREF, default => [ [ ] ] },
369             optional => { type => SCALAR | ARRAYREF, default => [ ] },
370             },
371             );
372              
373 3         18 $p{name} =~ s/^Apache::Session:://;
374              
375             $ApacheSessionParams{ $p{name} } =
376             ( ref $p{required}
377             ? $p{required}
378             : $ApacheSessionParams{ $p{required} }
379 3 100       13 );
380              
381             $OptionalApacheSessionParams{ $p{name} } =
382             ( ref $p{optional}
383             ? [ $p{optional} ]
384             : $OptionalApacheSessionParams{ $p{optional} }
385 3 50       10 );
386              
387 3         6 $class->_SetValidParams();
388             }
389              
390             sub RegisterFlexClass {
391 2     2 0 642 my $class = shift;
392 2         51 my %p = validate( @_, { type => { type => SCALAR,
393             regex => qr/^(?:store|lock|generate|serialize)/,
394             },
395             name => { type => SCALAR },
396             required => { type => SCALAR | ARRAYREF, default => [ [ ] ] },
397             optional => { type => SCALAR | ARRAYREF, default => [ ] },
398             },
399             );
400              
401 2         41 $p{name} =~ s/^Apache::Session:://;
402 2         20 $p{name} =~ s/^\Q$p{type}\E:://i;
403              
404             $ApacheSessionFlexParams{ $p{type} }{ $p{name} } =
405             ( ref $p{required}
406             ? $p{required}
407             : $ApacheSessionFlexParams{ $p{type} }{ $p{required} }
408 2 50       9 );
409              
410             $OptionalApacheSessionFlexParams{ $p{type} }{ $p{name} } =
411             ( ref $p{optional}
412             ? [ $p{optional} ]
413             : $OptionalApacheSessionFlexParams{ $p{type} }{ $p{optional} }
414 2 50       6 );
415              
416 2         3 $class->_SetValidParams();
417             }
418              
419             sub new
420             {
421 25     25 1 14363 my $class = shift;
422 25         78 my %p = @_;
423              
424 25         104 my $self = $class->SUPER::new(%p);
425              
426 24         3172 $self->_check_session_params;
427 20         31 $self->_set_session_params;
428              
429 20 50 0     37 if ( $self->{use_cookie} && ! ( $ENV{MOD_PERL} || $self->{header_object} ) )
      33        
430             {
431 0         0 param_error
432             "The header_object parameter is required in order to use cookies outside of mod_perl";
433             }
434              
435 20         28 my $session_class = "Apache::Session::$self->{session_class_piece}";
436 20 100       135 unless ( $session_class->can('TIEHASH') )
437             {
438 3         161 eval "require $session_class";
439 3 100       1201 die $@ if $@;
440             }
441              
442 18         39 $self->_make_session( $p{session_id} );
443              
444             $self->_bake_cookie
445 18 50 33     40 if $self->{use_cookie} && ! $self->{cookie_is_baked};
446              
447 18         45 return $self;
448             }
449              
450             sub _check_session_params
451             {
452 24     24   39 my $self = shift;
453              
454 24         49 $self->{session_class_piece} = $self->{class};
455 24         29 $self->{session_class_piece} =~ s/^Apache::Session:://;
456              
457             my $sets = $ApacheSessionParams{ $self->{session_class_piece} }
458 24 50       55 or param_error "Invalid session class: $self->{class}";
459              
460             $self->_check_sets( $sets, 'session', $self->{class} )
461 24 50       30 if grep { @$_ } @$sets;
  30         85  
462              
463 20 100       37 if ( $self->{session_class_piece} eq 'Flex' )
464             {
465 13         23 foreach my $key ( keys %ApacheSessionFlexParams )
466             {
467 52         36 my $subclass = $self->{$key};
468 52 50       81 my $sets = $ApacheSessionFlexParams{$key}{$subclass}
469             or param_error "Invalid class for $key: $self->{$key}";
470              
471             $self->_check_sets( $sets, $key, $subclass )
472 52 100       38 if grep { @$_ } @$sets;
  53         154  
473             }
474             }
475             }
476              
477             sub _check_sets
478             {
479 38     38   31 my $self = shift;
480 38         29 my $sets = shift;
481 38         27 my $type = shift;
482 38         24 my $class = shift;
483              
484 38         40 my @missing;
485 38         38 foreach my $set (@$sets)
486             {
487 42         45 my @matched = grep { exists $self->{$_} } @$set;
  95         142  
488              
489 42 100       95 return if @matched == @$set;
490              
491 8         10 @missing = grep { ! exists $self->{$_} } @$set;
  16         28  
492             }
493              
494 4         23 param_error "Some or all of the required parameters for your chosen $type class ($class) were provided."
495             . " The following parameters were missing: @missing\n";
496             }
497              
498             sub _set_session_params
499             {
500 20     20   17 my $self = shift;
501              
502 20         15 my %params;
503              
504             $self->_sets_to_params
505             ( $ApacheSessionParams{ $self->{session_class_piece} },
506 20         45 \%params );
507              
508             $self->_sets_to_params
509             ( $OptionalApacheSessionParams{ $self->{session_class_piece} },
510 20         40 \%params );
511              
512              
513 20 100       38 if ( $self->{session_class_piece} eq 'Flex' )
514             {
515 13         19 foreach my $key ( keys %ApacheSessionFlexParams )
516             {
517 52         39 my $subclass = $self->{$key};
518 52         46 $params{ $StudlyForm{$key} } = $subclass;
519              
520             $self->_sets_to_params
521 52         56 ( $ApacheSessionFlexParams{$key}{$subclass},
522             \%params );
523              
524             $self->_sets_to_params
525 52         80 ( $OptionalApacheSessionFlexParams{$key}{$subclass},
526             \%params );
527             }
528             }
529              
530 20         22 $self->{params} = \%params;
531              
532             $self->_set_cookie_fields
533 20 50       36 if $self->{use_cookie};
534             }
535              
536             sub _set_cookie_fields
537             {
538 0     0   0 my $self = shift;
539              
540 0         0 my $cookie_class;
541 0 0       0 if ($MOD_PERL)
542             {
543 0 0       0 $cookie_class =
544             $MOD_PERL == 2 ? 'Apache2::Cookie' : 'Apache::Cookie';
545              
546 0 0       0 eval "require $cookie_class"
547             unless $cookie_class->can('new');
548             }
549              
550 0 0 0     0 unless ( $cookie_class && $cookie_class->can('new' ) )
551             {
552 0         0 require CGI::Cookie;
553 0         0 $cookie_class = 'CGI::Cookie';
554             }
555              
556 0         0 $self->{cookie_class} = $cookie_class;
557              
558 0 0       0 if ( $self->{cookie_class} eq 'CGI::Cookie' )
559             {
560 0         0 $self->{new_cookie_args} = [];
561 0         0 $self->{fetch_cookie_args} = [];
562             }
563             else
564             {
565             $self->{new_cookie_args} =
566 0 0       0 [ $MOD_PERL == 2
567             ? Apache2::RequestUtil->request
568             : Apache->request
569             ];
570              
571             $self->{fetch_cookie_args} =
572             ( $MOD_PERL == 2
573             ? $self->{new_cookie_args}
574 0 0       0 : []
575             );
576             $self->{bake_cookie_args} =
577             ( $MOD_PERL == 2
578             ? $self->{new_cookie_args}
579 0 0       0 : []
580             );
581             }
582             }
583              
584             sub _sets_to_params
585             {
586 144     144   97 my $self = shift;
587 144         98 my $sets = shift;
588 144         101 my $params = shift;
589              
590 144         148 foreach my $set (@$sets)
591             {
592 87         68 foreach my $key (@$set)
593             {
594 98 100       128 if ( exists $self->{$key} )
595             {
596             $params->{ $StudlyForm{$key} } =
597 86         139 $self->{$key};
598             }
599             }
600             }
601             }
602              
603             sub _make_session
604             {
605 29     29   26 my $self = shift;
606 29         26 my $session_id = shift;
607              
608             return if
609 29 100 100     58 defined $session_id && $self->_try_session_id( $session_id );
610              
611 18         22 my $id = $self->_get_session_id;
612 18 50 33     27 return if defined $id && $self->_try_session_id($id);
613              
614 18 50       27 if ( defined $self->{param_name} )
615             {
616 0         0 my $id = $self->_get_session_id_from_args;
617              
618 0 0 0     0 return if defined $id && $self->_try_session_id($id);
619             }
620              
621 18 50       27 if ( $self->{use_cookie} )
622             {
623 0         0 my $id = $self->_get_session_id_from_cookie;
624              
625 0 0 0     0 if ( defined $id && $self->_try_session_id($id) )
626             {
627             $self->{cookie_is_baked} = 1
628 0 0       0 unless $self->{cookie_resend};
629              
630 0         0 return;
631             }
632             }
633              
634             # make a new session id
635 18         26 $self->_try_session_id(undef);
636             }
637              
638             # for subclasses
639 18     18   16 sub _get_session_id { return }
640              
641             sub _get_session_id_from_args
642             {
643 0     0   0 my $self = shift;
644              
645 0         0 return $self->{param_object}->param( $self->{param_name} );
646             }
647              
648             sub _get_session_id_from_cookie
649             {
650 0     0   0 my $self = shift;
651              
652 0 0       0 if ( $MOD_PERL == 2 )
653             {
654 0         0 my $jar = Apache2::Cookie::Jar->new( @{ $self->{fetch_cookie_args} } );
  0         0  
655 0         0 my $c = $jar->cookies( $self->{cookie_name} );
656 0 0       0 return $c->value if $c;
657             }
658             else
659             {
660 0         0 my %c = $self->{cookie_class}->fetch( @{ $self->{fetch_cookie_args} } );
  0         0  
661              
662             return $c{ $self->{cookie_name} }->value
663 0 0       0 if exists $c{ $self->{cookie_name} };
664             }
665 0         0 return undef;
666             }
667              
668             sub _try_session_id
669             {
670 31     31   36 my $self = shift;
671 31         22 my $session_id = shift;
672              
673             return 1 if ( $self->{session} &&
674             defined $session_id &&
675 31 100 100     104 $self->{session_id} eq $session_id );
      100        
676              
677 29         24 my %s;
678             {
679 29         22 local $SIG{__DIE__};
  29         59  
680             eval
681 29         22 {
682             tie %s, "Apache::Session::$self->{session_class_piece}",
683 29         123 $session_id, $self->{params};
684             };
685              
686 29 50 66     6310 if ( $@ || ! tied %s || ! $s{_session_id} )
      66        
687             {
688 3         7 $self->_handle_tie_error( $@, $session_id );
689 2         10 return;
690             }
691             }
692              
693 26 100       216 untie %{ $self->{session} } if $self->{session};
  8         26  
694              
695 26         199 $self->{session} = \%s;
696 26         56 $self->{session_id} = $s{_session_id};
697              
698 26         113 $self->{cookie_is_baked} = 0;
699              
700 26         49 return 1;
701             }
702              
703             sub _handle_tie_error
704             {
705 3     3   3 my $self = shift;
706 3         4 my $err = shift;
707 3         3 my $session_id = shift;
708              
709 3 50 33     16 if ( $err =~ /Object does not exist/ && defined $session_id )
710             {
711 3 100       7 return if $self->{allow_invalid_id};
712              
713 1         16 Apache::Session::Wrapper::Exception::NonExistentSessionID->throw
714             ( error => "Invalid session id: $session_id",
715             session_id => $session_id );
716             }
717             else
718             {
719 0 0       0 my $error =
720             $err ? $err : "Tying to Apache::Session::$self->{session_class_piece} failed but did not throw an exception";
721 0         0 die $error;
722             }
723             }
724              
725             sub _bake_cookie
726             {
727 0     0   0 my $self = shift;
728              
729 0   0     0 my $expires = shift || $self->{cookie_expires};
730 0 0 0     0 $expires = undef if defined $expires && $expires =~ /^session$/i;
731              
732 0         0 my $domain = $self->{cookie_domain};
733              
734             my $cookie =
735             $self->{cookie_class}->new
736 0         0 ( @{ $self->{new_cookie_args} },
737             -name => $self->{cookie_name},
738             # Apache2::Cookie will return undef if we pass undef for
739             # -value.
740             -value => ( $self->{session_id} || '' ),
741             ( defined $expires
742             ? ( -expires => $expires )
743             : ()
744             ),
745             ( defined $domain
746             ? ( -domain => $domain )
747             : ()
748             ),
749             -path => $self->{cookie_path},
750             -secure => $self->{cookie_secure},
751 0 0 0     0 );
    0          
752              
753             # If not running under mod_perl, CGI::Cookie->bake() will call
754             # print() to send a cookie header right now, which may not be what
755             # the user wants.
756 0 0 0     0 if ( $cookie->can('bake') && ! $cookie->isa('CGI::Cookie') )
757             {
758 0         0 $cookie->bake( @{ $self->{bake_cookie_args} } );
  0         0  
759             }
760             else
761             {
762 0         0 my $header_object = $self->{header_object};
763 0         0 for my $meth (@HeaderMethods)
764             {
765 0 0       0 if ( $header_object->can($meth) )
766             {
767 0         0 $header_object->$meth->add( 'Set-Cookie' => $cookie );
768 0         0 last;
769             }
770             }
771             }
772              
773             # always set this even if we skipped actually setting the cookie
774             # to avoid resending it. this keeps us from entering this method
775             # over and over
776             $self->{cookie_is_baked} = 1
777 0 0       0 unless $self->{cookie_resend};
778             }
779              
780             sub session
781             {
782 15     15 1 87 my $self = shift;
783 15         248 my %p = validate( @_,
784             { session_id =>
785             { type => SCALAR,
786             optional => 1,
787             },
788             } );
789              
790 15 100 100     99 if ( ! $self->{session} || %p )
791             {
792 12         19 $self->_make_session( $p{session_id} );
793              
794             $self->_bake_cookie
795 11 50 33     21 if $self->{use_cookie} && ! $self->{cookie_is_baked};
796             }
797              
798 14         54 return $self->{session};
799             }
800              
801             sub delete_session
802             {
803 1     1 1 9 my $self = shift;
804              
805 1 50       3 return unless $self->{session};
806              
807 1         2 my $session = delete $self->{session};
808              
809 1         8 (tied %$session)->delete;
810              
811 1         96 delete $self->{session_id};
812              
813 1 50       6 $self->_bake_cookie('-1d') if $self->{use_cookie};
814             }
815              
816             sub cleanup_session
817             {
818 24     24 0 23 my $self = shift;
819              
820 24 100       43 if ( $self->{always_write} )
821             {
822 22 100       74 if ( $self->{session}->{___force_a_write___} )
823             {
824 2         19 $self->{session}{___force_a_write___} = 0;
825             }
826             else
827             {
828 20         102 $self->{session}{___force_a_write___} = 1;
829             }
830             }
831              
832 24         217 undef $self->{session};
833             }
834              
835 24     24   5838 sub DESTROY { $_[0]->cleanup_session }
836              
837              
838             1;
839              
840             __END__