File: Query.pm

package info (click to toggle)
libcpan-audit-perl 20250115.001-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 336 kB
  • sloc: perl: 905; makefile: 8
file content (121 lines) | stat: -rwxr-xr-x 2,691 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package CPAN::Audit::Query;
use strict;
use warnings;
use CPAN::Audit::Version;

our $VERSION = "1.001";

=encoding utf8

=head1 NAME

CPAN::Audit::Query - filter the database for advisories that interest you

=head1 SYNOPSIS

	use CPAN::Audit::Query;

	my $query = CPAN::Audit::Query->new( db => ... );
	my @advisories = $query->advisories_for( $dist_name, $version_range );

=head1 DESCRIPTION

=head2 Class methods

=over 4

=item * new(HASH)

The only parameter is the hash reference from L<CPAN::Audit::DB> or
L<CPANSA::DB>. With no C<db> parameter, it uses the empty hash, which
means that you'll find no advisories.

=cut

sub new {
	my($class, %params) = @_;
	$params{db} ||= {};
	my $self = bless {}, $class;
	$self->{db} = $params{db};
	return $self;
	}

=back

=head2 Instance methods

=over 4

=item * advisories_for( DISTNAME, VERSION_RANGE )

Returns a list of advisories for DISTNAME in VERSION_RANGE.

	my @advisories = $query->advisories_for( 'Business::ISBN', '1.23' );

	my @advisories = $query->advisories_for( 'Business::ISBN', '>1.23,<2.45' );

	my @advisories = $query->advisories_for( 'Business::ISBN', '<1.23' );

=cut

sub advisories_for {
	my( $self, $distname, $dist_version_range ) = @_;

	$dist_version_range = '>0' unless
		defined $dist_version_range && 0 < length $dist_version_range;

	my $dist = $self->{db}->{dists}->{$distname};
	return unless $dist;

	# select only the known distribution versions from the database,
	# ignoring all others. For example, if $dist_version_range is
	# ">5.1", we don't care about any versions less than or equal to 5.1.
	# If $dist_version_range is "5.1", that really means ">=5.1"
	my %advisories =
		map { $_->{id}, $_ }
		map	 {
			my $dist_version = $_;
			grep {
				my $affected = _includes( $_->{affected_versions}, $dist_version );
				my $f = $_->{fixed_versions};
				if( exists $_->{fixed_versions} and defined $f and length $f ) {
					my $fixed = _includes( $f, $dist_version );
					$fixed ? 0 : $affected
					}
				else { $affected }
				} @{ $dist->{advisories} };
		}
		grep { CPAN::Audit::Version->in_range( $_, $dist_version_range ) }
		map	 { $_->{version}}
		@{ $dist->{versions} };

	values %advisories;
}

sub _includes {
	my( $range, $version ) = @_;
	$range = [$range] unless ref $range;
	my $rc = 0;
	foreach my $r ( @$range ) {
		no warnings 'uninitialized';
	    $rc += CPAN::Audit::Version->in_range( $version, $r );
		}
	return $rc;
}

=back

=head1 LICENSE

Copyright (C) Viacheslav Tykhanovskyi.

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

=head1 AUTHOR

Viacheslav Tykhanovskyi E<lt>viacheslav.t@gmail.comE<gt>

=cut

1;