| Filename | /usr/share/perl5/CGI/Session.pm |
| Statements | Executed 491 statements in 7.49ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 3 | 1 | 1 | 1.85ms | 4.32ms | CGI::Session::_load_pluggables |
| 3 | 1 | 1 | 694µs | 1.06ms | CGI::Session::parse_dsn |
| 3 | 1 | 1 | 320µs | 6.70ms | CGI::Session::load |
| 1 | 1 | 1 | 315µs | 410µs | CGI::Session::BEGIN@7 |
| 3 | 1 | 1 | 286µs | 40.8ms | CGI::Session::flush |
| 3 | 1 | 1 | 220µs | 7.26ms | CGI::Session::new |
| 5 | 5 | 2 | 215µs | 280µs | CGI::Session::param |
| 8 | 4 | 2 | 105µs | 150µs | CGI::Session::id |
| 3 | 1 | 1 | 91µs | 331µs | CGI::Session::_driver |
| 13 | 2 | 1 | 70µs | 70µs | CGI::Session::CORE:match (opcode) |
| 17 | 4 | 1 | 58µs | 58µs | CGI::Session::_test_status |
| 7 | 2 | 1 | 57µs | 57µs | CGI::Session::_set_status |
| 19 | 2 | 1 | 54µs | 54µs | CGI::Session::dataref |
| 3 | 1 | 1 | 44µs | 44µs | CGI::Session::_unset_status |
| 3 | 3 | 2 | 36µs | 40.8ms | CGI::Session::DESTROY |
| 4 | 1 | 1 | 36µs | 36µs | CGI::Session::name |
| 2 | 1 | 1 | 34µs | 689µs | CGI::Session::query |
| 3 | 1 | 1 | 33µs | 33µs | CGI::Session::_serializer |
| 3 | 1 | 1 | 25µs | 25µs | CGI::Session::_id_generator |
| 3 | 1 | 1 | 20µs | 20µs | CGI::Session::_set_query_or_sid |
| 1 | 1 | 1 | 19µs | 23µs | CGI::Session::BEGIN@5 |
| 1 | 1 | 1 | 12µs | 60µs | CGI::Session::BEGIN@6 |
| 1 | 1 | 1 | 7µs | 7µs | CGI::Session::remote_addr |
| 1 | 1 | 1 | 7µs | 7µs | CGI::Session::import |
| 0 | 0 | 0 | 0s | 0s | CGI::Session::__ANON__[:451] |
| 0 | 0 | 0 | 0s | 0s | CGI::Session::_ip_matches |
| 0 | 0 | 0 | 0s | 0s | CGI::Session::_reset_status |
| 0 | 0 | 0 | 0s | 0s | CGI::Session::_str2seconds |
| 0 | 0 | 0 | 0s | 0s | CGI::Session::atime |
| 0 | 0 | 0 | 0s | 0s | CGI::Session::clear |
| 0 | 0 | 0 | 0s | 0s | CGI::Session::close |
| 0 | 0 | 0 | 0s | 0s | CGI::Session::cookie |
| 0 | 0 | 0 | 0s | 0s | CGI::Session::ctime |
| 0 | 0 | 0 | 0s | 0s | CGI::Session::delete |
| 0 | 0 | 0 | 0s | 0s | CGI::Session::dump |
| 0 | 0 | 0 | 0s | 0s | CGI::Session::etime |
| 0 | 0 | 0 | 0s | 0s | CGI::Session::expire |
| 0 | 0 | 0 | 0s | 0s | CGI::Session::find |
| 0 | 0 | 0 | 0s | 0s | CGI::Session::http_header |
| 0 | 0 | 0 | 0s | 0s | CGI::Session::is_empty |
| 0 | 0 | 0 | 0s | 0s | CGI::Session::is_expired |
| 0 | 0 | 0 | 0s | 0s | CGI::Session::is_new |
| 0 | 0 | 0 | 0s | 0s | CGI::Session::load_param |
| 0 | 0 | 0 | 0s | 0s | CGI::Session::save_param |
| 0 | 0 | 0 | 0s | 0s | CGI::Session::trace |
| 0 | 0 | 0 | 0s | 0s | CGI::Session::tracemsg |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package CGI::Session; | ||||
| 2 | |||||
| 3 | # $Id: Session.pm 459 2009-03-21 02:00:17Z markstos $ | ||||
| 4 | |||||
| 5 | 3 | 28µs | 2 | 27µs | # spent 23µs (19+4) within CGI::Session::BEGIN@5 which was called:
# once (19µs+4µs) by C4::Auth::BEGIN@25 at line 5 # spent 23µs making 1 call to CGI::Session::BEGIN@5
# spent 4µs making 1 call to strict::import |
| 6 | 3 | 31µs | 2 | 108µs | # spent 60µs (12+48) within CGI::Session::BEGIN@6 which was called:
# once (12µs+48µs) by C4::Auth::BEGIN@25 at line 6 # spent 60µs making 1 call to CGI::Session::BEGIN@6
# spent 48µs making 1 call to Exporter::import |
| 7 | 3 | 4.50ms | 2 | 414µs | # spent 410µs (315+95) within CGI::Session::BEGIN@7 which was called:
# once (315µs+95µs) by C4::Auth::BEGIN@25 at line 7 # spent 410µs making 1 call to CGI::Session::BEGIN@7
# spent 4µs making 1 call to UNIVERSAL::import |
| 8 | |||||
| 9 | 1 | 16µs | @CGI::Session::ISA = qw( CGI::Session::ErrorHandler ); | ||
| 10 | 1 | 800ns | $CGI::Session::VERSION = '4.41'; | ||
| 11 | 1 | 500ns | $CGI::Session::NAME = 'CGISESSID'; | ||
| 12 | 1 | 200ns | $CGI::Session::IP_MATCH = 0; | ||
| 13 | |||||
| 14 | sub STATUS_UNSET () { 1 << 0 } # denotes session that's resetted | ||||
| 15 | sub STATUS_NEW () { 1 << 1 } # denotes session that's just created | ||||
| 16 | sub STATUS_MODIFIED () { 1 << 2 } # denotes session that needs synchronization | ||||
| 17 | sub STATUS_DELETED () { 1 << 3 } # denotes session that needs deletion | ||||
| 18 | sub STATUS_EXPIRED () { 1 << 4 } # denotes session that was expired. | ||||
| 19 | |||||
| 20 | # spent 7µs within CGI::Session::import which was called:
# once (7µs+0s) by C4::Auth::BEGIN@25 at line 25 of /usr/share/koha/lib/C4/Auth.pm | ||||
| 21 | 2 | 18µs | 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 7.26ms (220µs+7.04) within CGI::Session::new which was called 3 times, avg 2.42ms/call:
# 3 times (220µs+7.04ms) by C4::Auth::get_session at line 1522 of /usr/share/koha/lib/C4/Auth.pm, avg 2.42ms/call | ||||
| 35 | 45 | 193µs | my ($class, @args) = @_; | ||
| 36 | |||||
| 37 | my $self; | ||||
| 38 | 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 | 3 | 71µs | $class->set_error(''); # spent 71µs making 3 calls to CGI::Session::ErrorHandler::set_error, avg 24µs/call | ||
| 63 | |||||
| 64 | 3 | 6.70ms | $self = $class->load( @args ); # spent 6.70ms making 3 calls to CGI::Session::load, avg 2.23ms/call | ||
| 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 | 9 | 260µs | my $id = $self->_id_generator()->generate_id( # spent 229µs making 3 calls to CGI::Session::ID::md5::generate_id, avg 76µs/call
# spent 25µs making 3 calls to CGI::Session::_id_generator, avg 8µs/call
# spent 6µs making 3 calls to Digest::MD5::DESTROY, avg 2µs/call | ||
| 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 | 3 | 23µs | $self->_set_status( STATUS_NEW ); # spent 23µs making 3 calls to CGI::Session::_set_status, avg 8µs/call | ||
| 91 | } | ||||
| 92 | return $self; | ||||
| 93 | } | ||||
| 94 | |||||
| 95 | 3 | 43µs | 3 | 40.8ms | # spent 40.8ms (36µs+40.8) within CGI::Session::DESTROY which was called 3 times, avg 13.6ms/call:
# once (14µs+33.2ms) by C4::Auth::get_template_and_user at line 365 of /usr/share/koha/lib/C4/Auth.pm
# once (12µs+4.05ms) by C4::Auth::checkauth at line 805 of /usr/share/koha/lib/C4/Auth.pm
# once (11µs+3.57ms) by main::RUNTIME at line 690 of /usr/share/koha/opac/cgi-bin/opac/opac-search.pl # spent 40.8ms making 3 calls to CGI::Session::flush, avg 13.6ms/call |
| 96 | sub close { $_[0]->flush() } | ||||
| 97 | |||||
| 98 | 1 | 3µs | *param_hashref = \&dataref; | ||
| 99 | 1 | 2µs | my $avoid_single_use_warning = *param_hashref; | ||
| 100 | 19 | 87µs | sub dataref { $_[0]->{_DATA} } | ||
| 101 | |||||
| 102 | sub is_empty { !defined($_[0]->id) } | ||||
| 103 | |||||
| 104 | sub is_expired { $_[0]->_test_status( STATUS_EXPIRED ) } | ||||
| 105 | |||||
| 106 | sub is_new { $_[0]->_test_status( STATUS_NEW ) } | ||||
| 107 | |||||
| 108 | 8 | 85µs | 16 | 45µs | # spent 150µs (105+45) within CGI::Session::id which was called 8 times, avg 19µs/call:
# 3 times (52µs+25µs) by CGI::Session::flush at line 227, avg 25µs/call
# 3 times (28µs+12µs) by CGI::Session::flush at line 253, avg 13µs/call
# once (14µs+5µs) by C4::Auth::checkauth at line 811 of /usr/share/koha/lib/C4/Auth.pm
# once (12µs+4µs) by C4::Auth::checkauth at line 809 of /usr/share/koha/lib/C4/Auth.pm # spent 45µs making 16 calls to CGI::Session::dataref, avg 3µs/call |
| 109 | |||||
| 110 | # Last Access Time | ||||
| 111 | sub atime { return defined($_[0]->dataref) ? $_[0]->dataref->{_SESSION_ATIME} : undef } | ||||
| 112 | |||||
| 113 | # Creation Time | ||||
| 114 | sub ctime { return defined($_[0]->dataref) ? $_[0]->dataref->{_SESSION_CTIME} : undef } | ||||
| 115 | |||||
| 116 | # spent 331µs (91+240) within CGI::Session::_driver which was called 3 times, avg 110µs/call:
# 3 times (91µs+240µs) by CGI::Session::flush at line 237, avg 110µs/call | ||||
| 117 | 15 | 97µs | my $self = shift; | ||
| 118 | defined($self->{_OBJECTS}->{driver}) and return $self->{_OBJECTS}->{driver}; | ||||
| 119 | my $pm = "CGI::Session::Driver::" . $self->{_DSN}->{driver}; | ||||
| 120 | 3 | 240µs | defined($self->{_OBJECTS}->{driver} = $pm->new( $self->{_DRIVER_ARGS} )) # spent 240µs making 3 calls to CGI::Session::Driver::new, avg 80µs/call | ||
| 121 | or die $pm->errstr(); | ||||
| 122 | return $self->{_OBJECTS}->{driver}; | ||||
| 123 | } | ||||
| 124 | |||||
| 125 | # spent 33µs within CGI::Session::_serializer which was called 3 times, avg 11µs/call:
# 3 times (33µs+0s) by CGI::Session::flush at line 238, avg 11µs/call | ||||
| 126 | 9 | 37µ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 | |||||
| 132 | # spent 25µs within CGI::Session::_id_generator which was called 3 times, avg 8µs/call:
# 3 times (25µs+0s) by CGI::Session::new at line 80, avg 8µs/call | ||||
| 133 | 9 | 30µs | 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 | |||||
| 138 | sub _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 1.06ms (694µs+364µs) within CGI::Session::parse_dsn which was called 3 times, avg 353µs/call:
# 3 times (694µs+364µs) by CGI::Session::load at line 688, avg 353µs/call | ||||
| 147 | 33 | 631µs | my $self = shift; | ||
| 148 | my $dsn_str = shift; | ||||
| 149 | croak "parse_dsn(): usage error" unless $dsn_str; | ||||
| 150 | |||||
| 151 | require Text::Abbrev; | ||||
| 152 | 3 | 364µs | my $abbrev = Text::Abbrev::abbrev( "driver", "serializer", "id" ); # spent 364µs making 3 calls to Text::Abbrev::abbrev, avg 121µs/call | ||
| 153 | 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 | |||||
| 158 | # spent 689µs (34+655) within CGI::Session::query which was called 2 times, avg 345µs/call:
# 2 times (34µs+655µs) by CGI::Session::load at line 705, avg 345µs/call | ||||
| 159 | 8 | 35µs | 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 | 2 | 655µs | return $self->{_QUERY} = CGI->new(); # spent 655µs making 2 calls to CGI::new, avg 328µs/call | ||
| 168 | } | ||||
| 169 | |||||
| 170 | |||||
| 171 | # spent 36µs within CGI::Session::name which was called 4 times, avg 9µs/call:
# 4 times (36µs+0s) by CGI::Session::load at line 707, avg 9µs/call | ||||
| 172 | 12 | 46µs | 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 | |||||
| 186 | sub 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 | sub _set_status { | ||||
| 197 | 21 | 60µs | my $self = shift; | ||
| 198 | croak "_set_status(): usage error" unless @_; | ||||
| 199 | $self->{_STATUS} |= $_[0]; | ||||
| 200 | } | ||||
| 201 | |||||
| 202 | |||||
| 203 | # spent 44µs within CGI::Session::_unset_status which was called 3 times, avg 15µs/call:
# 3 times (44µs+0s) by CGI::Session::flush at line 255, avg 15µs/call | ||||
| 204 | 9 | 46µs | my $self = shift; | ||
| 205 | croak "_unset_status(): usage error" unless @_; | ||||
| 206 | $self->{_STATUS} &= ~$_[0]; | ||||
| 207 | } | ||||
| 208 | |||||
| 209 | |||||
| 210 | sub _reset_status { | ||||
| 211 | $_[0]->{_STATUS} = STATUS_UNSET; | ||||
| 212 | } | ||||
| 213 | |||||
| 214 | # spent 58µs within CGI::Session::_test_status which was called 17 times, avg 3µs/call:
# 6 times (14µs+0s) by CGI::Session::flush at line 232, avg 2µs/call
# 5 times (24µs+0s) by CGI::Session::param at line 266, avg 5µs/call
# 3 times (11µs+0s) by CGI::Session::flush at line 240, avg 4µs/call
# 3 times (8µs+0s) by CGI::Session::flush at line 248, avg 3µs/call | ||||
| 215 | 17 | 92µs | return $_[0]->{_STATUS} & $_[1]; | ||
| 216 | } | ||||
| 217 | |||||
| 218 | |||||
| 219 | # spent 40.8ms (286µs+40.5) within CGI::Session::flush which was called 3 times, avg 13.6ms/call:
# 3 times (286µs+40.5ms) by CGI::Session::DESTROY at line 95, avg 13.6ms/call | ||||
| 220 | 39 | 215µ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 | 3 | 76µs | return unless $self->id; # <-- empty session # spent 76µs making 3 calls to CGI::Session::id, avg 25µs/call | ||
| 228 | |||||
| 229 | # neither new, nor deleted nor modified | ||||
| 230 | return if !defined($self->{_STATUS}) or $self->{_STATUS} == STATUS_UNSET; | ||||
| 231 | |||||
| 232 | 6 | 14µs | if ( $self->_test_status(STATUS_NEW) && $self->_test_status(STATUS_DELETED) ) { # spent 14µs making 6 calls to CGI::Session::_test_status, avg 2µs/call | ||
| 233 | $self->{_DATA} = {}; | ||||
| 234 | return $self->_unset_status(STATUS_NEW | STATUS_DELETED); | ||||
| 235 | } | ||||
| 236 | |||||
| 237 | 3 | 331µs | my $driver = $self->_driver(); # spent 331µs making 3 calls to CGI::Session::_driver, avg 110µs/call | ||
| 238 | 3 | 33µs | my $serializer = $self->_serializer(); # spent 33µs making 3 calls to CGI::Session::_serializer, avg 11µs/call | ||
| 239 | |||||
| 240 | 3 | 11µs | if ( $self->_test_status(STATUS_DELETED) ) { # spent 11µs making 3 calls to CGI::Session::_test_status, avg 4µs/call | ||
| 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 | |||||
| 248 | 3 | 8µs | if ( $self->_test_status(STATUS_NEW | STATUS_MODIFIED) ) { # spent 8µs making 3 calls to CGI::Session::_test_status, avg 3µs/call | ||
| 249 | 6 | 491µs | my $datastr = $serializer->freeze( $self->dataref ); # spent 482µs making 3 calls to CGI::Session::Serialize::yaml::freeze, avg 161µs/call
# spent 9µs making 3 calls to CGI::Session::dataref, avg 3µs/call | ||
| 250 | unless ( defined $datastr ) { | ||||
| 251 | return $self->set_error( "flush(): couldn't freeze data: " . $serializer->errstr ); | ||||
| 252 | } | ||||
| 253 | 6 | 39.5ms | defined( $driver->store($self->id, $datastr) ) or # spent 39.5ms making 3 calls to CGI::Session::Driver::mysql::store, avg 13.2ms/call
# spent 39µs making 3 calls to CGI::Session::id, avg 13µs/call | ||
| 254 | return $self->set_error( "flush(): couldn't store datastr: " . $driver->errstr); | ||||
| 255 | 3 | 44µs | $self->_unset_status(STATUS_NEW | STATUS_MODIFIED); # spent 44µs making 3 calls to CGI::Session::_unset_status, avg 15µs/call | ||
| 256 | } | ||||
| 257 | return 1; | ||||
| 258 | } | ||||
| 259 | |||||
| 260 | sub trace {} | ||||
| 261 | sub tracemsg {} | ||||
| 262 | |||||
| 263 | # spent 280µs (215+65) within CGI::Session::param which was called 5 times, avg 56µs/call:
# once (64µs+15µs) by C4::Auth::checkauth at line 1025 of /usr/share/koha/lib/C4/Auth.pm
# once (56µs+14µs) by C4::Auth::checkauth at line 1023 of /usr/share/koha/lib/C4/Auth.pm
# once (41µs+24µs) by C4::Auth::checkauth at line 1024 of /usr/share/koha/lib/C4/Auth.pm
# once (34µs+7µs) by main::RUNTIME at line 692 of /usr/share/koha/opac/cgi-bin/opac/opac-search.pl
# once (20µs+6µs) by C4::Auth::get_template_and_user at line 367 of /usr/share/koha/lib/C4/Auth.pm | ||||
| 264 | 63 | 240µs | my ($self, @args) = @_; | ||
| 265 | |||||
| 266 | 5 | 24µs | if ($self->_test_status( STATUS_DELETED )) { # spent 24µs making 5 calls to CGI::Session::_test_status, avg 5µ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 | ||||
| 304 | if ((@args % 2) == 0) { | ||||
| 305 | my $modified_cnt = 0; | ||||
| 306 | ARG_PAIR: | ||||
| 307 | while (my ($name, $val) = each %args) { | ||||
| 308 | 4 | 7µs | if ( $name =~ m/^_SESSION_/) { # spent 7µs making 4 calls to CGI::Session::CORE:match, avg 2µs/call | ||
| 309 | carp "param(): attempt to write to private parameter"; | ||||
| 310 | next ARG_PAIR; | ||||
| 311 | } | ||||
| 312 | $self->{_DATA}->{ $name } = $val; | ||||
| 313 | ++$modified_cnt; | ||||
| 314 | } | ||||
| 315 | 4 | 34µs | $self->_set_status(STATUS_MODIFIED); # spent 34µs making 4 calls to CGI::Session::_set_status, avg 9µs/call | ||
| 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 | |||||
| - - | |||||
| 326 | sub delete { $_[0]->_set_status( STATUS_DELETED ) } | ||||
| 327 | |||||
| 328 | |||||
| 329 | 1 | 800ns | *header = \&http_header; | ||
| 330 | 1 | 600ns | my $avoid_single_use_warning_again = *header; | ||
| 331 | sub http_header { | ||||
| 332 | my $self = shift; | ||||
| 333 | return $self->query->header(-cookie=>$self->cookie, -type=>'text/html', @_); | ||||
| 334 | } | ||||
| 335 | |||||
| 336 | sub 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 | |||||
| - - | |||||
| 358 | sub 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 | |||||
| - - | |||||
| 378 | sub 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 | |||||
| 391 | sub 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 | |||||
| 409 | sub 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 459 2009-03-21 02:00:17Z markstos $ | ||||
| 459 | |||||
| 460 | =pod | ||||
| 461 | |||||
| - - | |||||
| 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 6.70ms (320µs+6.38) within CGI::Session::load which was called 3 times, avg 2.23ms/call:
# 3 times (320µs+6.38ms) by CGI::Session::new at line 64, avg 2.23ms/call | ||||
| 634 | 56 | 268µ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) | ||||
| 662 | 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 | 3 | 1.06ms | if ( defined $dsn ) { # <-- to avoid 'Uninitialized value...' warnings # spent 1.06ms making 3 calls to CGI::Session::parse_dsn, avg 353µs/call | ||
| 689 | $self->{_DSN} = $self->parse_dsn($dsn); | ||||
| 690 | } | ||||
| 691 | 3 | 20µs | $self->_set_query_or_sid($query_or_sid); # spent 20µs making 3 calls to CGI::Session::_set_query_or_sid, avg 7µs/call | ||
| 692 | |||||
| 693 | # load($dsn, $query, \%dsn_args); | ||||
| 694 | |||||
| 695 | $self->{_DRIVER_ARGS} = $dsn_args if defined $dsn_args; | ||||
| 696 | |||||
| 697 | } | ||||
| 698 | |||||
| 699 | 3 | 4.32ms | $self->_load_pluggables(); # spent 4.32ms making 3 calls to CGI::Session::_load_pluggables, avg 1.44ms/call | ||
| 700 | |||||
| 701 | # Did load_pluggable fail? If so, return undef, just like $class->set_error() would | ||||
| 702 | 3 | 38µs | return undef if $class->errstr; # spent 38µs making 3 calls to CGI::Session::ErrorHandler::errstr, avg 13µs/call | ||
| 703 | |||||
| 704 | if (not defined $self->{_CLAIMED_ID}) { | ||||
| 705 | 2 | 689µs | my $query = $self->query(); # spent 689µs making 2 calls to CGI::Session::query, avg 345µs/call | ||
| 706 | eval { | ||||
| 707 | 8 | 252µs | $self->{_CLAIMED_ID} = $query->cookie( $self->name ) || $query->param( $self->name ); # spent 186µs making 2 calls to CGI::cookie, avg 93µs/call
# spent 36µs making 4 calls to CGI::Session::name, avg 9µs/call
# spent 30µs making 2 calls to CGI::param, avg 15µs/call | ||
| 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(); | ||||
| 719 | my $raw_data = $driver->retrieve( $self->{_CLAIMED_ID} ); | ||||
| 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(); | ||||
| 728 | $self->{_DATA} = $serializer->thaw($raw_data); | ||||
| 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 | ||||
| 769 | if ( ! defined $update_atime ) { | ||||
| 770 | $self->{_DATA}->{_SESSION_ATIME} = time(); # <-- updating access time | ||||
| 771 | $self->_set_status( STATUS_MODIFIED ); # <-- access time modified above | ||||
| 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 20µs within CGI::Session::_set_query_or_sid which was called 3 times, avg 7µs/call:
# 3 times (20µs+0s) by CGI::Session::load at line 691, avg 7µs/call | ||||
| 780 | 12 | 23µs | my $self = shift; | ||
| 781 | my $query_or_sid = shift; | ||||
| 782 | if ( ref $query_or_sid){ $self->{_QUERY} = $query_or_sid } | ||||
| 783 | else { $self->{_CLAIMED_ID} = $query_or_sid } | ||||
| 784 | } | ||||
| 785 | |||||
| 786 | |||||
| 787 | # spent 4.32ms (1.85+2.47) within CGI::Session::_load_pluggables which was called 3 times, avg 1.44ms/call:
# 3 times (1.85ms+2.47ms) by CGI::Session::load at line 699, avg 1.44ms/call | ||||
| 788 | 90 | 631µ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) { | ||||
| 802 | my $mod_name = $dsn->{ $plug }; | ||||
| 803 | if (not defined $mod_name) { | ||||
| 804 | $mod_name = $DEFAULT_FOR{ $plug }; | ||||
| 805 | } | ||||
| 806 | 9 | 63µs | if ($mod_name =~ /^(\w+)$/) { # spent 63µs making 9 calls to CGI::Session::CORE:match, avg 7µs/call | ||
| 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 | ||||
| 816 | eval "require $mod_name"; # spent 119µs executing statements in 3 string evals (merged)
# spent 113µs executing statements in 3 string evals (merged)
# spent 111µs executing statements in 3 string evals (merged) | ||||
| 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 | |||||
| - - | |||||
| 962 | 1 | 500ns | *expires = \&expire; | ||
| 963 | 1 | 400ns | my $prevent_warning = \&expires; | ||
| 964 | sub etime { $_[0]->expire() } | ||||
| 965 | sub 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 | |||||
| 1012 | sub _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 | |||||
| - - | |||||
| 1179 | 1 | 13µs | # spent 7µs within CGI::Session::remote_addr which was called:
# once (7µs+0s) by C4::Auth::checkauth at line 1023 of /usr/share/koha/lib/C4/Auth.pm | ||
| 1180 | |||||
| 1181 | =pod | ||||
| 1182 | |||||
| - - | |||||
| 1472 | 1 | 14µs | 1; | ||
| 1473 | |||||
sub CGI::Session::CORE:match; # opcode |