File Coverage

blib/lib/PHP/Session.pm
Criterion Covered Total %
statement 84 84 100.0
branch 12 14 85.7
condition 4 5 80.0
subroutine 26 26 100.0
pod 0 12 0.0
total 126 141 89.3


line stmt bran cond sub pod time code
1             package PHP::Session;
2              
3 15     15   573838 use strict;
  15         35  
  15         595  
4 15     15   83 use vars qw($VERSION);
  15         29  
  15         1010  
5             $VERSION = '0.27';
6              
7 15     15   75 use vars qw(%SerialImpl);
  15         29  
  15         719  
8             %SerialImpl = (
9             php => 'PHP::Session::Serializer::PHP',
10             );
11              
12 15     15   84 use Fcntl qw(:flock);
  15         29  
  15         1905  
13 15     15   6213 use FileHandle;
  15         109008  
  15         95  
14 15     15   6279 use File::Spec;
  15         31  
  15         386  
15 15     15   14381 use UNIVERSAL::require;
  15         32685  
  15         158  
16              
17 2     2   18 sub _croak { require Carp; Carp::croak(@_) }
  2         441  
18 1     1   13 sub _carp { require Carp; Carp::carp(@_) }
  1         313  
19              
20             sub new {
21 37     37 0 403018 my($class, $sid, $opt) = @_;
22 37         215 my %default = (
23             save_path => '/tmp',
24             serialize_handler => 'php',
25             create => 0,
26             auto_save => 0,
27             );
28 37   100     123 $opt ||= {};
29 37         373 my $self = bless {
30             %default,
31             %$opt,
32             _sid => $sid,
33             _data => {},
34             _changed => 0,
35             }, $class;
36 37         159 $self->_validate_sid;
37 36         96 $self->_parse_session;
38 35         362 return $self;
39             }
40              
41             # accessors, public methods
42              
43 105     105 0 4754 sub id { shift->{_sid} }
44              
45             sub get {
46 26     26 0 2009 my($self, $key) = @_;
47 26         254 return $self->{_data}->{$key};
48             }
49              
50             sub set {
51 16     16 0 147 my($self, $key, $value) = @_;
52 16         290 $self->{_changed}++;
53 16         70 $self->{_data}->{$key} = $value;
54             }
55              
56             sub unregister {
57 1     1 0 1240 my($self, $key) = @_;
58 1         5 delete $self->{_data}->{$key};
59             }
60              
61             sub unset {
62 1     1 0 2 my $self = shift;
63 1         4 $self->{_data} = {};
64             }
65              
66             sub is_registered {
67 1     1 0 3 my($self, $key) = @_;
68 1         7 return exists $self->{_data}->{$key};
69             }
70              
71             sub decode {
72 35     35 0 60 my($self, $data) = @_;
73 35         97 $self->serializer->decode($data);
74             }
75              
76             sub encode {
77 14     14 0 27 my($self, $data) = @_;
78 14         40 $self->serializer->encode($data);
79             }
80              
81             sub save {
82 14     14 0 63 my $self = shift;
83 14 50       40 my $handle = FileHandle->new("> " . $self->_file_path)
84             or _croak("can't write session file: $!");
85 14         179619 flock $handle, LOCK_EX;
86 14         101 $handle->print($self->encode($self->{_data}));
87 14         626 $handle->close;
88 14         776 $self->{_changed} = 0; # init
89             }
90              
91             sub destroy {
92 14     14 0 12393 my $self = shift;
93 14         43 unlink $self->_file_path;
94             }
95              
96             sub DESTROY {
97 37     37   6641 my $self = shift;
98 37 100       1859 if ($self->{_changed}) {
99 2 100       7 if ($self->{auto_save}) {
100 1         4 $self->save;
101             } else {
102 1 50       9 _carp("PHP::Session: some keys are changed but not saved.") if $^W;
103             }
104             }
105             }
106              
107             # private methods
108              
109             sub _validate_sid {
110 37     37   63 my $self = shift;
111 37         110 my($id) = $self->id =~ /^([0-9a-zA-Z]*)$/; # untaint
112 37 100       127 defined $id or _croak("Invalid session id: ", $self->id);
113 36         95 $self->{_sid} = $id;
114             }
115              
116             sub _parse_session {
117 36     36   56 my $self = shift;
118 36         104 my $cont = $self->_slurp_content;
119 36 100 66     1233 if (!$cont && !$self->{create}) {
120 1         3 _croak($self->_file_path, ": $!");
121             }
122 35         123 $self->{_data} = $self->decode($cont);
123             }
124              
125             sub serializer {
126 49     49 0 78 my $self = shift;
127 49         127 my $impl = $SerialImpl{$self->{serialize_handler}};
128 49         360 $impl->require;
129 49         1442 return $impl->new;
130             }
131              
132             sub _file_path {
133 65     65   86 my $self = shift;
134 65         209 return File::Spec->catfile($self->{save_path}, 'sess_' . $self->id);
135             }
136              
137             sub _slurp_content {
138 36     36   52 my $self = shift;
139              
140 36 100       98 my $handle = FileHandle->new($self->_file_path) or return;
141 23         1831 binmode $handle;
142 23         269 flock $handle, LOCK_SH;
143 23         103 local $/ = undef;
144 23         730 my $data = <$handle>;
145 23         119 $handle->close;
146              
147 23         461 return $data;
148             }
149              
150             1;
151             __END__