File Coverage

blib/lib/CGI/Session/Serialize/default.pm
Criterion Covered Total %
statement 58 64 90.6
branch 17 26 65.3
condition 2 8 25.0
subroutine 11 11 100.0
pod 2 2 100.0
total 90 111 81.0


line stmt bran cond sub pod time code
1             package CGI::Session::Serialize::default;
2              
3             # $Id$
4              
5 21     21   123 use strict;
  21         29  
  21         654  
6 21     21   8977 use Safe;
  21         188386  
  21         642  
7 21     21   9291 use Data::Dumper;
  21         119829  
  21         1275  
8 21     21   129 use CGI::Session::ErrorHandler;
  21         44  
  21         496  
9 21     21   105 use Scalar::Util qw(blessed reftype refaddr);
  21         28  
  21         967  
10 21     21   87 use Carp "croak";
  21         42  
  21         730  
11 21     21   89 use vars qw( %overloaded );
  21         36  
  21         12048  
12             require overload;
13              
14             @CGI::Session::Serialize::default::ISA = ( "CGI::Session::ErrorHandler" );
15             $CGI::Session::Serialize::default::VERSION = '4.43';
16              
17              
18             sub freeze {
19 27     27 1 68 my ($class, $data) = @_;
20            
21 27         210 my $d =
22             new Data::Dumper([$data], ["D"]);
23 27         789 $d->Indent( 0 );
24 27         403 $d->Purity( 1 );
25 27         150 $d->Useqq( 0 );
26 27         140 $d->Deepcopy( 0 );
27 27         142 $d->Quotekeys( 1 );
28 27         169 $d->Terse( 0 );
29            
30             # ;$D added to make certain we get our data structure back when we thaw
31 27         151 return $d->Dump() . ';$D';
32             }
33              
34             sub thaw {
35 13     13 1 29 my ($class, $string) = @_;
36              
37             # To make -T happy
38 13         74 my ($safe_string) = $string =~ m/^(.*)$/s;
39 13         116 my $rv = Safe->new->reval( $safe_string );
40 13 50       18344 if ( $@ ) {
41 0         0 return $class->set_error("thaw(): couldn't thaw. $@");
42             }
43 13         1068 __walk($rv);
44 13         56 return $rv;
45             }
46              
47             sub __walk {
48 13     13   22 my %seen;
49 13         91 my @filter = __scan(shift);
50 13         23 local %overloaded;
51              
52             # We allow the value assigned to a key to be undef.
53             # Hence the defined() test is not in the while().
54              
55 13         30 while (@filter) {
56 138 100       196 defined(my $x = shift @filter) or next;
57 136 100 100     376 $seen{refaddr $x || ''}++ and next;
58            
59 45 100       109 my $r = reftype $x or next;
60 32 100 0     61 if ($r eq "HASH") {
    50          
    0          
61             # we use this form to make certain we have aliases
62             # to the values in %$x and not copies
63 23         50 push @filter, __scan(@{$x}{keys %$x});
  23         68  
64             } elsif ($r eq "ARRAY") {
65 9         14 push @filter, __scan(@$x);
66             } elsif ($r eq "SCALAR" || $r eq "REF") {
67 0         0 push @filter, __scan($$x);
68             }
69             }
70             }
71              
72             # we need to do this because the values we get back from the safe compartment
73             # will have packages defined from the safe compartment's *main instead of
74             # the one we use
75             sub __scan {
76             # $_ gets aliased to each value from @_ which are aliases of the values in
77             # the current data structure
78 45     45   69 for (@_) {
79 138 100       193 if (blessed $_) {
80 7 100       14 if (overload::Overloaded($_)) {
81 3         76 my $address = refaddr $_;
82              
83             # if we already rebuilt and reblessed this item, use the cached
84             # copy so our ds is consistent with the one we serialized
85 3 100       8 if (exists $overloaded{$address}) {
86 1         88 $_ = $overloaded{$address};
87             } else {
88 2         3 my $reftype = reftype $_;
89 2 50 0     4 if ($reftype eq "HASH") {
    0          
    0          
90 2         12 $_ = $overloaded{$address} = bless { %$_ }, ref $_;
91             } elsif ($reftype eq "ARRAY") {
92 0         0 $_ = $overloaded{$address} = bless [ @$_ ], ref $_;
93             } elsif ($reftype eq "SCALAR" || $reftype eq "REF") {
94 0         0 $_ = $overloaded{$address} = bless \do{my $o = $$_},ref $_;
  0         0  
95             } else {
96 0         0 croak "Do not know how to reconstitute blessed object of base type $reftype";
97             }
98             }
99             } else {
100 4         123 bless $_, ref $_;
101             }
102             }
103             }
104 45         119 return @_;
105             }
106              
107              
108             1;
109              
110             __END__;