File Coverage

blib/lib/Data/Serializer.pm
Criterion Covered Total %
statement 257 282 91.1
branch 66 94 70.2
condition 2 3 66.6
subroutine 44 46 95.6
pod 20 20 100.0
total 389 445 87.4


line stmt bran cond sub pod time code
1             package Data::Serializer;
2              
3 27     27   123377 use warnings;
  27         60  
  27         1415  
4 27     27   165 use strict;
  27         53  
  27         10513  
5 27     27   163 use vars qw($VERSION);
  27         167  
  27         1635  
6              
7 27     27   159 use Carp;
  27         48  
  27         130930  
8             require 5.004 ;
9              
10             $VERSION = '0.60';
11              
12             #Global cache of modules we've loaded
13             my %_MODULES;
14              
15             my %_fields = (
16             serializer => 'Data::Dumper',
17             digester => 'SHA-256',
18             cipher => 'Blowfish',
19             encoding => 'hex',
20             compressor => 'Compress::Zlib',
21             secret => undef,
22             portable => '1',
23             compress => '0',
24             raw => '0',
25             options => {},
26             serializer_token => '1',
27             );
28             sub new {
29 2384     2384 1 2812183 my ($class, %args) = @_;
30 2384         23734 my $dataref = {%_fields};
31 2384         13082 foreach my $field (keys %_fields) {
32 26224 100       62667 $dataref->{$field} = $args{$field} if exists $args{$field};
33             }
34 2384         6950 my $self = $dataref;
35 2384         7017 bless $self, $class;
36              
37             #preintitialize serializer object
38 2384         6456 $self->_serializer_obj();
39 2384         9948 return $self;
40             }
41              
42             sub _serializer_obj {
43 7156     7156   10088 my $self = (shift);
44 7156         10437 my $method = (shift);
45 7156         12514 my $reset = (shift);
46              
47 7156         12695 my $serializer = $self->{serializer};
48              
49             #remove cache if asked to
50 7156 100       20335 if ($reset) {
51 4         11 delete $self->{serializer_obj};
52             }
53              
54             #If we're given the same method that we are already using, nothing to change
55 7156 50 66     37248 if (defined $method && $method ne $serializer) {
56 0         0 $serializer = $method;
57             } else {
58             #safe to return our cached object if we have it
59 7156 100       27154 return $self->{serializer_obj} if (exists $self->{serializer_obj});
60             }
61              
62 2388         11965 $self->_module_loader($serializer,"Data::Serializer"); #load in serializer module if necessary
63 2388         3942 my $serializer_obj = {};
64 2388         9128 $serializer_obj->{options} = $self->{options};
65 2388         20411 bless $serializer_obj, "Data::Serializer::$serializer";
66              
67             #Cache it for later retrieval only if this is the default serializer for the object
68             #ugly logic to support legacy token method that would allow the base to have a different serializer
69             #than what it is reading
70              
71 2388 50       7087 if ($serializer eq $self->{serializer}) {
72 2388         4797 $self->{serializer_obj} = $serializer_obj;
73             }
74 2388         4162 return $serializer_obj;
75              
76             }
77              
78             sub _persistent_obj {
79 1190     1190   2132 my $self = (shift);
80 1190 100       9449 return $self->{persistent_obj} if (exists $self->{persistent_obj});
81 595         1592 $self->_module_loader('Data::Serializer::Persistent');
82 595         1749 my $persistent_obj = { parent => $self };
83 595         1947 bless $persistent_obj, "Data::Serializer::Persistent";
84 595         1162 $self->{persistent_obj} = $persistent_obj;
85 595         1321 return $persistent_obj;
86            
87             }
88              
89              
90              
91             sub serializer {
92 2503     2503 1 3737 my $self = (shift);
93 2503         3993 my $return = $self->{serializer};
94 2503 50       5697 if (@_) {
95 0         0 $self->{serializer} = (shift);
96             #Reinitialize object
97 0         0 $self->_serializer_obj($self->{serializer}, 1);
98             }
99 2503         5347 return $return;
100             }
101              
102             sub digester {
103 1190     1190 1 2323 my $self = (shift);
104 1190         2057 my $return = $self->{digester};
105 1190 100       2851 if (@_) {
106 238         330 my $value = (shift);
107 238         480 $self->{digester} = $value;
108             }
109 1190         2702 return $return;
110             }
111              
112             sub cipher {
113 952     952 1 1378 my $self = (shift);
114 952         1780 my $return = $self->{cipher};
115 952 50       2175 if (@_) {
116 0         0 $self->{cipher} = (shift);
117             }
118 952         1831 return $return;
119             }
120              
121             sub compressor {
122 4998     4998 1 9391 my $self = (shift);
123 4998         8253 my $return = $self->{compressor};
124 4998 100       13313 if (@_) {
125 833         1380 $self->{compressor} = (shift);
126             }
127 4998         13188 return $return;
128             }
129              
130             sub secret {
131 7386     7386 1 31177 my $self = (shift);
132 7386         12384 my $return = $self->{secret};
133 7386 100       16621 if (@_) {
134 952         1994 $self->{secret} = (shift);
135             }
136 7386         20129 return $return;
137             }
138              
139             sub encoding {
140 4054     4054 1 11219 my $self = (shift);
141 4054         6463 my $return = $self->{encoding};
142 4054 100       8526 if (@_) {
143 476         941 $self->{encoding} = (shift);
144             }
145 4054         7950 return $return;
146             }
147              
148             sub portable {
149 2741     2741 1 7953 my $self = (shift);
150 2741         5369 my $return = $self->{portable};
151 2741 100       7626 if (@_) {
152 476         990 $self->{portable} = (shift);
153             }
154 2741         8124 return $return;
155             }
156              
157             sub options {
158 4     4 1 72 my $self = (shift);
159 4         9 my $return = $self->{options};
160 4 50       10 if (@_) {
161 4         6 $self->{options} = (shift);
162             #Reinitialize object
163 4         11 $self->_serializer_obj($self->{serializer}, 1);
164             }
165 4         8 return $return;
166             }
167              
168             sub compress {
169 5363     5363 1 14117 my $self = (shift);
170 5363         9352 my $return = $self->{compress};
171 5363 100       12436 if (@_) {
172 833         1732 $self->{compress} = (shift);
173             }
174 5363         14271 return $return;
175             }
176              
177             sub raw {
178 4530     4530 1 6213 my $self = (shift);
179 4530         7666 my $return = $self->{raw};
180 4530 50       11403 if (@_) {
181 0         0 $self->{raw} = (shift);
182             }
183 4530         14169 return $return;
184             }
185              
186             sub serializer_token {
187 2265     2265 1 3164 my $self = (shift);
188 2265         4029 my $return = $self->{serializer_token};
189 2265 50       5763 if (@_) {
190 0         0 $self->{serializer_token} = (shift);
191             }
192 2265         6637 return $return;
193             }
194              
195             sub _module_loader {
196 14177     14177   21686 my $self = (shift);
197 14177         19940 my $module_name = (shift);
198 14177 50       29792 unless (defined $module_name) {
199 0         0 confess "Something wrong - module not defined! $! $@\n";
200             }
201 14177 100       38920 return if (exists $_MODULES{$module_name});
202 7170 100       15654 if (@_) {
203 7156         17826 $module_name = (shift) . "::$module_name";
204             }
205 7170         10188 my $package = $module_name;
206 7170         38460 $package =~ s|::|/|g;
207 7170         10488 $package .= ".pm";
208 7170         9467 eval { require $package };
  7170         241755  
209 7170 50       19573 if ($@) {
210 0         0 carp "Data::Serializer error: " .
211             "Please make sure $package is a properly installed package.\n";
212 0         0 return undef;
213             }
214 7170         19062 $_MODULES{$module_name} = 1;
215             }
216              
217              
218              
219              
220              
221             sub _serialize {
222 2384     2384   3241 my $self = (shift);
223 2384         2908 my @input = @{(shift)};#original @_
  2384         5584  
224 2384         3792 my $method = (shift);
225 2384         5251 $self->_module_loader($method,"Data::Serializer"); #load in serializer module if necessary
226 2384         7845 my $serializer_obj = $self->_serializer_obj($method);
227 2384         9950 return $serializer_obj->serialize(@input);
228             }
229              
230             sub _compress {
231 833     833   2654 my $self = (shift);
232 833         2114 $self->_module_loader($self->compressor);
233 833 50       2211 if ($self->compressor eq 'Compress::Zlib') {
    0          
234 833         3369 return Compress::Zlib::compress((shift));
235             } elsif ($self->compressor eq 'Compress::PPMd') {
236 0         0 my $compressor = Compress::PPMd::Encoder->new();
237 0         0 return $compressor->encode((shift));
238             }
239             }
240             sub _decompress {
241 833     833   1255 my $self = (shift);
242 833         2006 $self->_module_loader($self->compressor);
243 833 50       1901 if ($self->compressor eq 'Compress::Zlib') {
    0          
244 833         3486 return Compress::Zlib::uncompress((shift));
245             } elsif ($self->compressor eq 'Compress::PPMd') {
246 0         0 my $compressor = Compress::PPMd::Decoder->new();
247 0         0 return $compressor->decode((shift));
248             }
249             }
250              
251             sub _create_token {
252 2265     2265   2957 my $self = (shift);
253 2265         11566 return '^' . join('|', @_) . '^';
254             }
255             sub _get_token {
256 2265     2265   3325 my $self = (shift);
257 2265         3658 my $line = (shift);
258             #Should be anchored to beginning
259             #my ($token) = $line =~ /\^([^\^]+?)\^/;
260 2265         15167 my ($token) = $line =~ /^\^([^\^]{1,120}?)\^/;
261 2265         5554 return $token;
262             }
263             sub _extract_token {
264 2265     2265   3553 my $self = (shift);
265 2265         3763 my $token = (shift);
266 2265         23443 return split('\|',$token);
267             }
268             sub _remove_token {
269 2265     2265   3307 my $self = (shift);
270 2265         3434 my $line = (shift);
271 2265         12797 $line =~ s/^\^[^\^]{1,120}?\^//;
272 2265         5845 return $line;
273             }
274             sub _deserialize {
275 2384     2384   3571 my $self = (shift);
276 2384         4288 my $input = (shift);
277 2384         3370 my $method = (shift);
278 2384         5376 $self->_module_loader($method,"Data::Serializer"); #load in serializer module if necessary
279 2384         5873 my $serializer_obj = $self->_serializer_obj($method);
280 2384         9569 $serializer_obj->deserialize($input);
281             }
282              
283             sub _encrypt {
284 952     952   1291 my $self = (shift);
285 952         1732 my $value = (shift);
286 952         1719 my $cipher = (shift);
287 952         1391 my $digester = (shift);
288 952         2121 my $secret = $self->secret;
289 952 50       2450 croak "Cannot encrypt: No secret provided!" unless defined $secret;
290 952         2308 $self->_module_loader('Crypt::CBC');
291 952         3296 my $digest = $self->_endigest($value,$digester);
292 952         7010 my $cipher_obj = Crypt::CBC->new($secret,$cipher);
293 952         111361 return $cipher_obj->encrypt($digest);
294             }
295             sub _decrypt {
296 952     952   1563 my $self = (shift);
297 952         1500 my $input = (shift);
298 952         1321 my $cipher = (shift);
299 952         1360 my $digester = (shift);
300 952         1805 my $secret = $self->secret;
301 952 50       2403 croak "Cannot encrypt: No secret provided!" unless defined $secret;
302 952         2352 $self->_module_loader('Crypt::CBC');
303 952         5011 my $cipher_obj = Crypt::CBC->new($secret,$cipher);
304 952         91945 my $digest = $cipher_obj->decrypt($input);
305 952         439667 return $self->_dedigest($digest,$digester);
306             }
307             sub _endigest {
308 952     952   1778 my $self = (shift);
309 952         1605 my $input = (shift);
310 952         1237 my $digester = (shift);
311 952         2300 $self->_module_loader('Digest');
312 952         3026 my $digest = $self->_get_digest($input,$digester);
313 952         16557 return "$digest=$input";
314             }
315             sub _dedigest {
316 952     952   1821 my $self = (shift);
317 952         1361 my $input = (shift);
318 952         1578 my $digester = (shift);
319 952         2244 $self->_module_loader('Digest');
320             #my ($old_digest) = $input =~ /^([^=]+?)=/;
321 952         20329 $input =~ s/^([^=]+?)=//;
322 952         3431 my $old_digest = $1;
323 952 50       2439 return undef unless (defined $old_digest);
324 952         2412 my $new_digest = $self->_get_digest($input,$digester);
325 952 50       10419 return undef unless ($new_digest eq $old_digest);
326 952         7433 return $input;
327             }
328             sub _get_digest {
329 1904     1904   2907 my $self = (shift);
330 1904         3072 my $input = (shift);
331 1904         2614 my $digester = (shift);
332 1904         9944 my $ctx = Digest->new($digester);
333 1904         97557 $ctx->add($input);
334 1904         18434 return $ctx->hexdigest;
335             }
336             sub _enhex {
337 1313     1313   2315 my $self = (shift);
338 1313         11243 return join('',unpack 'H*',(shift));
339             }
340             sub _dehex {
341 1313     1313   1769 my $self = (shift);
342 1313         9948 return (pack'H*',(shift));
343             }
344              
345             sub _enb64 {
346 476     476   822 my $self = (shift);
347 476         1058 $self->_module_loader('MIME::Base64');
348 476         2442 my $b64 = MIME::Base64::encode_base64( (shift), '' );
349 476         1677 return $b64;
350             }
351              
352              
353             sub _deb64 {
354 476     476   724 my $self = (shift);
355 476         1025 $self->_module_loader('MIME::Base64');
356 476         2630 return MIME::Base64::decode_base64( (shift) );
357             }
358              
359             # do all 3 stages
360 0     0 1 0 sub freeze { (shift)->serialize(@_); }
361 0     0 1 0 sub thaw { (shift)->deserialize(@_); }
362              
363             sub serialize {
364 2265     2265 1 56742 my $self = (shift);
365 2265         5348 my ($serializer,$cipher,$digester,$encoding,$compressor) = ('','','','','');
366              
367 2265 50       5481 if ($self->raw) {
368 0         0 return $self->raw_serialize(@_);
369             }
370              
371             #we always serialize no matter what.
372              
373             #define serializer for token
374 2265         8524 $serializer = $self->serializer;
375 2265         7756 my $value = $self->_serialize(\@_,$serializer);
376              
377 2265 100       965772 if ($self->compress) {
378 833         2053 $compressor = $self->compressor;
379 833         2372 $value = $self->_compress($value);
380             }
381              
382 2265 100       290263 if (defined $self->secret) {
383             #define digester for token
384 952         2479 $digester = $self->digester;
385             #define cipher for token
386 952         2447 $cipher = $self->cipher;
387 952         3317 $value = $self->_encrypt($value,$cipher,$digester);
388             }
389 2265 100       1562757 if ($self->portable) {
390 1789         4360 $encoding = $self->encoding;
391 1789         5862 $value = $self->_encode($value);
392             }
393 2265 50       6919 if ($self->serializer_token) {
394 2265         11599 my $token = $self->_create_token($serializer,$cipher, $digester,$encoding,$compressor);
395 2265         6702 $value = $token . $value;
396             }
397 2265         18361 return $value;
398             }
399              
400             sub store {
401 595     595 1 39672 my $self = (shift);
402 595         1500 my $persistent = $self->_persistent_obj();
403 595         2446 $persistent->_store(@_);
404             }
405              
406             sub retrieve {
407 595     595 1 49429 my $self = (shift);
408 595         1701 my $persistent = $self->_persistent_obj();
409 595         2290 $persistent->_retrieve(@_);
410             }
411              
412             sub raw_serialize {
413 119     119 1 2659 my $self = (shift);
414 119         639 my $serializer = $self->serializer;
415 119         325 return $self->_serialize(\@_,$serializer);
416             }
417              
418             sub _encode {
419 1789     1789   2741 my $self = (shift);
420 1789         2698 my $value = (shift);
421 1789         3716 my $encoding = $self->encoding;
422 1789 100       5413 if ($encoding eq 'hex') {
    50          
423 1313         3710 return $self->_enhex($value);
424             } elsif ($encoding eq 'b64') {
425 476         1673 return $self->_enb64($value);
426             } else {
427 0         0 croak "Unknown encoding method $encoding\n";
428             }
429             }
430              
431             sub _decode {
432 2027     2027   2880 my $self = (shift);
433 2027         3155 my $value = (shift);
434 2027         3711 my $encoding = (shift);
435 2027 100       6250 if ($encoding eq 'hex') {
    100          
    50          
436 1313         3352 return $self->_dehex($value);
437             } elsif ($encoding eq 'b64') {
438 476         1464 return $self->_deb64($value);
439             } elsif ($encoding !~ /\S/) {
440             #quietly ignore empty encoding
441 238         796 return $value;
442             } else {
443 0         0 croak "Unknown encoding method $encoding\n";
444             }
445             }
446              
447             sub raw_deserialize {
448 119     119 1 49884 my $self = (shift);
449 119         306 my $serializer = $self->serializer;
450 119         320 return $self->_deserialize((shift),$serializer);
451             }
452              
453             sub deserialize {
454 2265     2265 1 9779 my $self = (shift);
455              
456 2265 50       5408 if ($self->raw) {
457 0         0 return $self->raw_deserialize(@_);
458             }
459              
460 2265         5172 my $value = (shift);
461 2265         6156 my $token = $self->_get_token($value);
462 2265         3739 my ($serializer,$cipher, $digester,$encoding, $compressor);
463 2265         7228 my $compress = $self->compress;
464 2265 50       5285 if (defined $token) {
465 2265         6346 ($serializer,$cipher, $digester,$encoding, $compressor) = $self->_extract_token($token);
466              
467             #if compressor is defined and has a value then we must decompress it
468 2265 100       6822 $compress = 1 if ($compressor);
469 2265         5900 $value = $self->_remove_token($value);
470             } else {
471 0         0 $serializer = $self->serializer;
472 0         0 $cipher = $self->cipher;
473 0         0 $digester = $self->digester;
474 0         0 $compressor = $self->compressor;
475 0 0       0 if ($self->portable) {
476 0         0 $encoding = $self->encoding;
477             }
478             }
479 2265 100       6152 if (defined $encoding) {
480 2027         12562 $value = $self->_decode($value,$encoding);
481             }
482 2265 100       6659 if (defined $self->secret) {
483 952         2829 $value = $self->_decrypt($value,$cipher,$digester);
484             }
485 2265 100       22240 if ($compress) {
486 833         2359 $value = $self->_decompress($value);
487             }
488             #we always deserialize no matter what.
489 2265         47674 my @return = $self->_deserialize($value,$serializer);
490 2265 50       2829839 return wantarray ? @return : $return[0];
491             }
492              
493             1;
494             __END__