# Copyright (c) 2024-2025 Löwenfelsen UG (haftungsbeschränkt) # licensed under Artistic License 2.0 (see LICENSE file) # ABSTRACT: generic module for extracting information from filesystems package File::Information::VerifyTestResult; use v5.10; use strict; use warnings; use parent 'File::Information::VerifyBase'; use Carp; our $VERSION = v0.06; use constant { CLASS_METADATA => 'meatdata', CLASS_WEAK => 'weak', CLASS_STRONG => 'strong', }; my %supported_tests = ( (map { 'get_'.$_ => { class => CLASS_METADATA, cb => \&_test_get, key => $_, }, } qw(size mediatype)), (map { 'digest_'.($_ =~ tr/-/_/r) => { class => CLASS_STRONG, cb => \&_test_digest, digest => $_, }, } grep {$_ ne 'sha-2-512'} map {'sha-2-'.$_, 'sha-3-'.$_} qw(224 256 384 512)), # all of SHA-2 and SHA-3 but SHA-2-512 (map { 'digest_'.($_ =~ tr/-/_/r) => { class => CLASS_WEAK, cb => \&_test_digest, digest => $_, }, } qw(md-4-128 md-5-128 sha-1-160 ripemd-1-160 tiger-1-192 tiger-2-192)), # all the others basically inode => { class => CLASS_STRONG, cb => \&_test_inode, }, ); # ---------------- sub _new { my ($pkg, %opts) = @_; my $self = $pkg->SUPER::_new(%opts); my $test = $supported_tests{$opts{test}} // croak 'Unsupported test'; my $res; $self->{status} = $res = eval {$test->{cb}->($self, $test)} // $pkg->STATUS_ERROR; if (ref($res) && $res->isa('File::Information::VerifyBase')) { return $res; } if (defined(my $digest = $test->{digest}) && $test->{class} eq CLASS_STRONG) { my $info = $self->instance->digest_info($digest); $self->{class} = CLASS_WEAK if $info->{unsafe}; } return $self; } sub _supported_tests { return keys %supported_tests; } sub _class { my ($self) = @_; return $self->{class} // $supported_tests{$self->{test}}{class}; } sub _test_get { my ($self, $test) = @_; my $key = $test->{key}; my $from = $self->base_from->get($key, lifecycle => $self->{lifecycle_from}, default => undef, as => 'Data::Identifier'); my $to = $self->base_to->get($key, lifecycle => $self->{lifecycle_to}, default => undef, as => 'Data::Identifier'); if (defined($from) && defined($to)) { #warn sprintf('key=<%s>, %s -> %s: from=<%s>, to=<%s>', $test->{key}, $self->{lifecycle_from}, $self->{lifecycle_to}, $from // '', $to // '') if $key eq 'mediatype'; return $self->STATUS_PASSED if $from->eq($to); } $from = $self->base_from->get($key, lifecycle => $self->{lifecycle_from}, default => undef, as => 'raw'); $to = $self->base_to->get($key, lifecycle => $self->{lifecycle_to}, default => undef, as => 'raw'); #warn sprintf('key=<%s>, %s -> %s: from=<%s>, to=<%s>', $test->{key}, $self->{lifecycle_from}, $self->{lifecycle_to}, $from // '', $to // '') if $key eq 'mediatype'; return $self->STATUS_NO_DATA unless defined($from) && defined($to); return $from eq $to ? $self->STATUS_PASSED : $self->STATUS_FAILED; } sub _test_digest { my ($self, $test) = @_; my $from = $self->base_from->digest($test->{digest}, lifecycle => $self->{lifecycle_from}, default => undef, as => 'hex'); my $to = $self->base_to->digest($test->{digest}, lifecycle => $self->{lifecycle_to}, default => undef, as => 'hex'); return $self->STATUS_NO_DATA unless defined($from) && defined($to); #warn sprintf('key=<%s>, %s -> %s: from=<%s>, to=<%s>', $test->{digest}, $self->{lifecycle_from}, $self->{lifecycle_to}, $from // '', $to // ''); return $from eq $to ? $self->STATUS_PASSED : $self->STATUS_FAILED; } sub _test_inode { my ($self, $test) = @_; my $base_from = $self->base_from; my $base_to = $self->base_to; my $inode_from = $base_from->can('inode') ? $base_from->inode : $base_from->isa('File::Information::Remote') ? $base_from : undef; my $inode_to = $base_to->can('inode') ? $base_to->inode : $base_to->isa('File::Information::Remote') ? $base_to : undef; if (defined($inode_from) && defined($inode_to)) { if ($base_from != $inode_from || $base_to != $inode_to) { return $inode_from->verify(lifecycle_from => $self->{lifecycle_from}, lifecycle_to => $self->{lifecycle_to}, base_to => $inode_to); } } return $self->STATUS_NO_DATA; } 1; __END__ =pod =encoding UTF-8 =head1 NAME File::Information::VerifyTestResult - generic module for extracting information from filesystems =head1 VERSION version v0.06 =head1 SYNOPSIS use File::Information; my File::Information::Inode $inode = ...; my File::Information::VerifyResult $result = $inode->verify; my $passed = $base->has_passed; This package inherits from L<File::Information::VerifyBase>. =head1 METHODS =head1 AUTHOR Löwenfelsen UG (haftungsbeschränkt) <support@loewenfelsen.net> =head1 COPYRIGHT AND LICENSE This software is Copyright (c) 2024-2025 by Löwenfelsen UG (haftungsbeschränkt) <support@loewenfelsen.net>. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) =cut