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