line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package CGI::Session::Driver; |
2
|
|
|
|
|
|
|
|
3
|
25
|
|
|
25
|
|
2971
|
use strict; |
|
25
|
|
|
|
|
48
|
|
|
25
|
|
|
|
|
1007
|
|
4
|
|
|
|
|
|
|
# |
5
|
|
|
|
|
|
|
|
6
|
25
|
|
|
25
|
|
135
|
use Carp; |
|
25
|
|
|
|
|
44
|
|
|
25
|
|
|
|
|
1524
|
|
7
|
25
|
|
|
25
|
|
911
|
use CGI::Session::ErrorHandler; |
|
25
|
|
|
|
|
47
|
|
|
25
|
|
|
|
|
14448
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
$CGI::Session::Driver::VERSION = '4.43'; |
10
|
|
|
|
|
|
|
@CGI::Session::Driver::ISA = qw(CGI::Session::ErrorHandler); |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
sub new { |
13
|
37
|
|
|
37
|
0
|
86
|
my $class = shift; |
14
|
37
|
|
50
|
|
|
142
|
my $args = shift || {}; |
15
|
|
|
|
|
|
|
|
16
|
37
|
50
|
|
|
|
360
|
unless ( ref $args ) { |
17
|
0
|
|
|
|
|
0
|
croak "$class->new(): Invalid argument type passed to driver"; |
18
|
|
|
|
|
|
|
} |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
# Set defaults. |
21
|
|
|
|
|
|
|
|
22
|
37
|
100
|
|
|
|
230
|
if (! $args->{TableName}) { |
23
|
26
|
|
|
|
|
150
|
$args->{TableName} = 'sessions'; |
24
|
|
|
|
|
|
|
} |
25
|
|
|
|
|
|
|
|
26
|
37
|
100
|
|
|
|
138
|
if (! $args->{IdColName}) { |
27
|
26
|
|
|
|
|
64
|
$args->{IdColName} = 'id'; |
28
|
|
|
|
|
|
|
} |
29
|
|
|
|
|
|
|
|
30
|
37
|
100
|
|
|
|
117
|
if (! $args->{DataColName}) { |
31
|
26
|
|
|
|
|
103
|
$args->{DataColName} = 'a_session'; |
32
|
|
|
|
|
|
|
} |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# perform a shallow copy of $args, to prevent modification |
35
|
37
|
|
|
|
|
395
|
my $self = bless ({%$args}, $class); |
36
|
37
|
50
|
|
|
|
366
|
return $self if $self->init(); |
37
|
0
|
|
|
|
|
|
return $self->set_error( "$class->init() returned false"); |
38
|
|
|
|
|
|
|
} |
39
|
|
|
|
|
|
|
|
40
|
0
|
|
|
0
|
1
|
|
sub init { 1 } |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
sub retrieve { |
43
|
0
|
|
|
0
|
1
|
|
croak "retrieve(): " . ref($_[0]) . " failed to implement this method!"; |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
sub store { |
47
|
0
|
|
|
0
|
1
|
|
croak "store(): " . ref($_[0]) . " failed to implement this method!"; |
48
|
|
|
|
|
|
|
} |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
sub remove { |
51
|
0
|
|
|
0
|
1
|
|
croak "remove(): " . ref($_[0]) . " failed to implement this method!"; |
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
sub traverse { |
55
|
0
|
|
|
0
|
1
|
|
croak "traverse(): " . ref($_[0]) . " failed to implement this method!"; |
56
|
|
|
|
|
|
|
} |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
sub dump { |
59
|
0
|
|
|
0
|
0
|
|
require Data::Dumper; |
60
|
0
|
|
|
|
|
|
my $d = Data::Dumper->new([$_[0]], [ref $_[0]]); |
61
|
0
|
|
|
|
|
|
return $d->Dump; |
62
|
|
|
|
|
|
|
} |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
1; |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
__END__; |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
=pod |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
=head1 NAME |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
CGI::Session::Driver - CGI::Session driver specifications |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=head1 SYNOPSIS |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
require CGI::Session::Driver; |
78
|
|
|
|
|
|
|
@ISA = qw( CGI::Session::Driver ); |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
=head1 DESCRIPTION |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
CGI::Session::Driver is a base class for all CGI::Session's native drivers. It also documents driver specifications for those willing to write drivers for different databases not currently supported by CGI::Session. |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
=head1 WHAT IS A DRIVER |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
Driver is a piece of code that helps CGI::Session library to talk to specific database engines, or storage mechanisms. To be more precise, driver is a F<.pm> file that inherits from CGI::Session::Driver and defines L<retrieve()|/"retrieve($self, $sid)">, L<store()|/"store($self, $sid, $datastr)"> and L<remove()|/"remove($self, $sid)"> methods. |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
=head2 BLUEPRINT |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
The best way of learning the specs is to look at a blueprint of a driver: |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
package CGI::Session::Driver::your_driver_name; |
93
|
|
|
|
|
|
|
use strict; |
94
|
|
|
|
|
|
|
use base qw( CGI::Session::Driver CGI::Session::ErrorHandler ); |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
sub init { |
97
|
|
|
|
|
|
|
my ($self) = @_; |
98
|
|
|
|
|
|
|
# optional |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
sub DESTROY { |
102
|
|
|
|
|
|
|
my ($self) = @_; |
103
|
|
|
|
|
|
|
# optional |
104
|
|
|
|
|
|
|
} |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
sub store { |
107
|
|
|
|
|
|
|
my ($self, $sid, $datastr) = @_; |
108
|
|
|
|
|
|
|
# Store $datastr, which is an already serialized string of data. |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
sub retrieve { |
112
|
|
|
|
|
|
|
my ($self, $sid) = @_; |
113
|
|
|
|
|
|
|
# Return $datastr, which was previously stored using above store() method. |
114
|
|
|
|
|
|
|
# Return $datastr if $sid was found. Return 0 or "" if $sid doesn't exist |
115
|
|
|
|
|
|
|
} |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
sub remove { |
118
|
|
|
|
|
|
|
my ($self, $sid) = @_; |
119
|
|
|
|
|
|
|
# Remove storage associated with $sid. Return any true value indicating success, |
120
|
|
|
|
|
|
|
# or undef on failure. |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
sub traverse { |
124
|
|
|
|
|
|
|
my ($self, $coderef) = @_; |
125
|
|
|
|
|
|
|
# execute $coderef for each session id passing session id as the first and the only |
126
|
|
|
|
|
|
|
# argument |
127
|
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
1; |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
All the attributes passed as the second argument to CGI::Session's new() or load() methods will automatically |
132
|
|
|
|
|
|
|
be made driver's object attributes. For example, if session object was initialized as following: |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
$s = CGI::Session->new("driver:your_driver_name", undef, {Directory=>'/tmp/sessions'}); |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
You can access value of 'Directory' from within your driver like so: |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
sub store { |
139
|
|
|
|
|
|
|
my ($self, $sid, $datastr) = @_; |
140
|
|
|
|
|
|
|
my $dir = $self->{Directory}; # <-- in this example will be '/tmp/sessions' |
141
|
|
|
|
|
|
|
} |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
Optionally, you can define C<init()> method within your driver to do driver specific global initialization. C<init()> method will be invoked only once during the lifecycle of your driver, which is the same as the lifecycle of a session object. |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
For examples of C<init()> look into the source code of native CGI::Session drivers. |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
=head1 METHODS |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
This section lists and describes all driver methods. All the driver methods will receive driver object ($self) as the first argument. Methods that pertain to an individual session (such as C<retrieve()>, C<store()> and C<remove()>) will also receive session id ($sid) as the second argument. |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
Following list describes every driver method, including its argument list and what step of session's life they will be invoked. Understanding this may help driver authors. |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
=over 4 |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
=item retrieve($self, $sid) |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
Called whenever a specific session is requested either via C<< CGI::Session->new() >> or C<< CGI::Session->load() >> syntax. Method should try to retrieve data associated with C< $sid > and return it. In case no data could be retrieved for C< $sid > 0 (zero) or "" should be returned. undef must be returned only to signal error. Error message should be set via set_error(), which can be inherited from L<CGI::Session::ErrorHandler|CGI::Session::ErrorHandler>. |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
Tip: set_error() always returns undef. Use it for your advantage. |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
=item store($self, $sid, $datastr) |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
Called whenever modified session data is to be stored back to disk. This happens whenever CGI::Session->flush() is called on modified session. Since CGI::Session->DESTROY() calls flush(), store() gets requested each time session object is to be terminated. |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
C< store() > is called both to store new sessions and to update already stored sessions. It's driver author's job to figure out which operation needs to be performed. |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
$datastr, which is passed as the third argument to represents B<already serialized> session data that needs to be saved. |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
store() can return any true value indicating success or undef on failure. Error message should be passed to set_error() |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
=item remove($self, $sid) |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
Called whenever session data is to be deleted, which is when CGI::Session->delete() is called. Should return any true value indicating success, undef on failure. Error message should be logged in set_error(). |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
=item traverse($self, \&coderef) |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
Called only from within CGI::Session->find(). Job of traverse() is to call \&coderef for every single session stored in disk passing session's id as the first and only argument: C<< $coderef->( $sid ) >> |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=item init($self) |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
Optional. Called whenever driver object is to be initialized, which happens only once during the lifecycle of CGI::Session object. Here you can do driver-wide initialization, such as to open connection to a database server. |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
=item DESTROY($self) |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
Optional. Perl automatically calls this method on objects just before they are to be terminated. This gives your driver chance to close any database connections or close any open file handles. |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
=back |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
=head2 NOTES |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
=over 4 |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
=item * |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
All driver F<.pm> files must be lowercase! |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
=item * |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
DBI-related drivers are better off using L<CGI::Session::Driver::DBI|CGI::Session::Driver::DBI> as base, but don't have to. |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
=back |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
=head1 BACKWARDS COMPATIBILITY |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
Version 4.0 of CGI::Session's driver specification is B<NOT> backward |
206
|
|
|
|
|
|
|
compatible with the previous specification. If you already have a driver |
207
|
|
|
|
|
|
|
developed to work with the previous version you're highly encouraged to upgrade |
208
|
|
|
|
|
|
|
your driver code to make it compatible with the current version. Fortunately, |
209
|
|
|
|
|
|
|
current driver specs are a lot easier to adapt to. |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
For support information see L<CGI::Session|CGI::Session> |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
=head1 LICENSING |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
For support and licensing see L<CGI::Session|CGI::Session>. |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
=cut |