* move Base::WithChecksum to build upon Basic.pm, avoid code duplication
[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
5ca52230 9our $VERSION = '0.18';
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);
c4a322ec 22
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};
c4a322ec 31
98ae09f0 32 my $checksum = $class->_digest_packed($data, @args);
33
c4a322ec 34 ($checksum eq $old_checksum)
98ae09f0 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:
54 # Canonicalize numbers to strings even if it
55 # mangles numbers inside strings. It really
56 # does not matter since its just the checksum
57 # anyway.
58 # - YK/SL
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};
06a66732 69
70 $digest_opts = [ $digest_opts ]
71 if !ref($digest_opts) or ref($digest_opts) ne 'ARRAY';
72
a6ebb4c8 73 my ( $d, @args ) = @$digest_opts;
98ae09f0 74
75 if ( ref $d ) {
76 if ( $d->can("clone") ) {
a6ebb4c8 77 return $d->clone;
06a66732 78 }
79 elsif ( $d->can("reset") ) {
98ae09f0 80 $d->reset;
a6ebb4c8 81 return $d;
06a66732 82 }
83 else {
98ae09f0 84 die "Can't clone or reset digest object: $d";
85 }
06a66732 86 }
87 else {
a6ebb4c8 88 return Digest->new($d || "SHA1", @args);
98ae09f0 89 }
98ae09f0 90}
91
c4a322ec 921;
93
94__END__
95
96=pod
97
98=head1 NAME
99
4fa64e86 100MooseX::Storage::Base::WithChecksum - A more secure serialization role
c4a322ec 101
102=head1 DESCRIPTION
103
c86a46cc 104This is an early implementation of a more secure Storage role,
105which does integrity checks on the data. It is still being
106developed so I recommend using it with caution.
107
108Any thoughts, ideas or suggestions on improving our technique
109are very welcome.
110
c4a322ec 111=head1 METHODS
112
113=over 4
114
115=item B<pack (?$salt)>
116
117=item B<unpack ($data, ?$salt)>
118
119=back
120
121=head2 Introspection
122
123=over 4
124
125=item B<meta>
126
127=back
128
129=head1 BUGS
130
131All complex software has bugs lurking in it, and this module is no
132exception. If you find a bug please either email me, or add the bug
133to cpan-RT.
134
135=head1 AUTHOR
136
137Stevan Little E<lt>stevan.little@iinteractive.comE<gt>
138
06a66732 139Yuval Kogman
140
c4a322ec 141=head1 COPYRIGHT AND LICENSE
142
1f3074ea 143Copyright 2007-2008 by Infinity Interactive, Inc.
c4a322ec 144
145L<http://www.iinteractive.com>
146
147This library is free software; you can redistribute it and/or modify
148it under the same terms as Perl itself.
149
150=cut