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