convert to Dist::Zilla
[gitmo/MooseX-Storage.git] / lib / MooseX / Storage / Base / WithChecksum.pm
CommitLineData
c4a322ec 1package MooseX::Storage::Base::WithChecksum;
2use Moose::Role;
3
298cda98 4with 'MooseX::Storage::Basic';
5
06a66732 6use Digest ();
34dcaa5d 7use Data::Dumper ();
8
72a40e08 9our $DIGEST_MARKER = '__DIGEST__';
88651e76 10
298cda98 11around pack => sub {
12 my $orig = shift;
13 my $self = shift;
14 my @args = @_;
98ae09f0 15
298cda98 16 my $collapsed = $self->$orig( @args );
c4a322ec 17
88651e76 18 $collapsed->{$DIGEST_MARKER} = $self->_digest_packed($collapsed, @args);
ec725183 19
c4a322ec 20 return $collapsed;
298cda98 21};
c4a322ec 22
298cda98 23around unpack => sub {
24 my ($orig, $class, $data, @args) = @_;
c4a322ec 25
26 # check checksum on data
34dcaa5d 27 my $old_checksum = delete $data->{$DIGEST_MARKER};
ec725183 28
98ae09f0 29 my $checksum = $class->_digest_packed($data, @args);
30
c4a322ec 31 ($checksum eq $old_checksum)
ec725183 32 || confess "Bad Checksum got=($checksum) expected=($old_checksum)";
c4a322ec 33
298cda98 34 $class->$orig( $data, @args );
35};
c4a322ec 36
98ae09f0 37
38sub _digest_packed {
39 my ( $self, $collapsed, @args ) = @_;
40
a6ebb4c8 41 my $d = $self->_digest_object(@args);
42
a6ebb4c8 43 {
06a66732 44 local $Data::Dumper::Indent = 0;
34dcaa5d 45 local $Data::Dumper::Sortkeys = 1;
b7e2e91b 46 local $Data::Dumper::Terse = 1;
47 local $Data::Dumper::Useqq = 0;
48 local $Data::Dumper::Deparse = 0; # FIXME?
49 my $str = Data::Dumper::Dumper($collapsed);
a7f358fb 50 # NOTE:
ec725183 51 # Canonicalize numbers to strings even if it
52 # mangles numbers inside strings. It really
a7f358fb 53 # does not matter since its just the checksum
54 # anyway.
55 # - YK/SL
ec725183 56 $str =~ s/(?<! ['"] ) \b (\d+) \b (?! ['"] )/'$1'/gx;
b7e2e91b 57 $d->add( $str );
a6ebb4c8 58 }
59
60 return $d->hexdigest;
61}
62
63sub _digest_object {
64 my ( $self, %options ) = @_;
65 my $digest_opts = $options{digest};
ec725183 66
67 $digest_opts = [ $digest_opts ]
06a66732 68 if !ref($digest_opts) or ref($digest_opts) ne 'ARRAY';
ec725183 69
a6ebb4c8 70 my ( $d, @args ) = @$digest_opts;
98ae09f0 71
72 if ( ref $d ) {
73 if ( $d->can("clone") ) {
a6ebb4c8 74 return $d->clone;
ec725183 75 }
06a66732 76 elsif ( $d->can("reset") ) {
98ae09f0 77 $d->reset;
a6ebb4c8 78 return $d;
ec725183 79 }
06a66732 80 else {
98ae09f0 81 die "Can't clone or reset digest object: $d";
82 }
ec725183 83 }
06a66732 84 else {
7d5ab57c 85 return Digest->new($d || "SHA-1", @args);
98ae09f0 86 }
98ae09f0 87}
88
f82612bc 89no Moose::Role;
90
c4a322ec 911;
92
93__END__
94
95=pod
96
97=head1 NAME
98
4fa64e86 99MooseX::Storage::Base::WithChecksum - A more secure serialization role
c4a322ec 100
101=head1 DESCRIPTION
102
ec725183 103This is an early implementation of a more secure Storage role,
104which does integrity checks on the data. It is still being
105developed so I recommend using it with caution.
c86a46cc 106
ec725183 107Any thoughts, ideas or suggestions on improving our technique
c86a46cc 108are very welcome.
109
c4a322ec 110=head1 METHODS
111
112=over 4
113
114=item B<pack (?$salt)>
115
116=item B<unpack ($data, ?$salt)>
117
118=back
119
120=head2 Introspection
121
122=over 4
123
124=item B<meta>
125
126=back
127
128=head1 BUGS
129
ec725183 130All complex software has bugs lurking in it, and this module is no
c4a322ec 131exception. If you find a bug please either email me, or add the bug
132to cpan-RT.
133
134=head1 AUTHOR
135
136Stevan Little E<lt>stevan.little@iinteractive.comE<gt>
137
06a66732 138Yuval Kogman
139
c4a322ec 140=head1 COPYRIGHT AND LICENSE
141
1f3074ea 142Copyright 2007-2008 by Infinity Interactive, Inc.
c4a322ec 143
144L<http://www.iinteractive.com>
145
146This library is free software; you can redistribute it and/or modify
147it under the same terms as Perl itself.
148
149=cut