CPE
view release on metacpan or search on metacpan
) {
my $sub = sub {
die "method '$accessor_name' takes 0 or 1 arguments, not " . scalar(@_ - 1) if @_ > 2;
my ($self, $new) = @_;
my $old = $self->{$accessor_name};
if (@_ == 2) {
my $validator = $accessor_name eq 'cpe_version' ? qr/\A2\.3\z/
: $accessor_name eq 'part'? qr/\A[aoh]\z/
: qr/\A[a-z0-9\._\-~%]*\z/;
die "invalid value '$new' for '$accessor_name'"
unless $new =~ $validator;
$self->{$accessor_name} = $new;
}
return $old;
};
{ no strict 'refs'; *$accessor_name = $sub; }
}
sub is_equal { die 'TODO' }
sub is_subset { die 'TODO' }
sub is_superset { die 'TODO' }
sub is_disjoint { die 'TODO' }
sub as_string { die 'TODO' }
sub as_wfn { die 'TODO' }
sub as_uri { die 'TODO' }
sub new {
my ($class, @args) = @_;
my $self = @args == 1 ? _from_string($args[0]) : _from_hash(@args);
return bless $self, $class;
}
sub _from_string {
my ($str) = @_;
if ($str =~ m{cpe:/
(?<part>[aoh])?
(?: \: (?<vendor> [^:]*) )?
(?: \: (?<product> [^:]*) )?
(?: \: (?<version> [^:]*) )?
(?: \: (?<update> [^:]*) )?
(?: \: (?<edition> [^:]*) )?
(?: \: (?<language> [^:]*) )?
(?: \: (?<sw_edition> [^:]*) )?
(?: \: (?<target_sw> [^:]*) )?
(?: \: (?<target_hw> [^:]*) )?
(?: \: (?<other> [^:]*) )?
}ix
) {
my %data = %+;
foreach my $k (keys %data) {
if ($data{$k} eq '') {
$data{$k} = 'ANY';
}
elsif ($data{$k} eq '-') {
$data{$k} = 'NA';
}
elsif ($data{$k} =~ /\%/) {
# URI CPEs may have percent-encoded special characters
# which must be decoded to proper values.
my %decoded = (
'21' => '!', '22' => '"', '23' => '#', '24' => '$',
'25' => '%', '26' => '&', '27' => q('), '28' => '(',
'29' => ')', '2a' => '*', '2b' => '+', '2c' => ',',
'2f' => '/', '3a' => ':', '3b' => ';', '3c' => '<',
'3d' => '=', '3e' => '>', '3f' => '?', '40' => '@',
'5b' => '[', '5c' => '\\', '5d' => ']', '5e' => '^',
'60' => '`', '7b' => '{', '7c' => '|', '7d' => '}',
'7e' => '~',
);
$data{$k} =~ s{\%01}{?}g if index($data{$k}, '%01') >= 0;
$data{$k} =~ s{\%02}{*}g if index($data{$k}, '%02') >= 0;
foreach my $special (keys %decoded) {
if (index($data{$k}, '%' . $special) >= 0) {
$data{$k} =~ s{\%$special}{\\$decoded{$special}}ig;
}
}
}
}
# this is a compatibility layer between CPE 2.2 and 2.3.
# URIs using 2.3 format will have the 'edition' field starting
# with a '~' and with '~' dividing all the new 2.3 fields within.
# In 2.2 this is not done, and those fields don't exist.
if (defined $data{edition} && substr($data{edition}, 0, 1) eq '~') {
(undef,
$data{edition},
$data{sw_edition},
$data{target_sw},
$data{target_hw},
$data{other},
) = map { $_ eq '' ? 'ANY' : $_ eq '-' ? 'NA' : $_ }
# split() ignores empty values unless there is a defined
# value afterwards, so we add an extra '!' element to the list
# and ignore it:
split /\~/ => $data{edition} . '~!';
}
return _from_hash(cpe_version => 2.3, %data);
}
die 'sorry, only URI CPEs can be parsed at this point. Patches welcome!';
}
sub _from_hash {
my (%args) = @_;
my $self = { cpe_version => '2.3', part => 'ANY' };
foreach my $key (qw(vendor product version update edition
language sw_edition target_sw target_hw other)
) {
if (!exists $args{$key}) {
$self->{$key} = 'ANY';
next;
}
Carp::croak "invalid characters '$args{$key}' in '$key' field."
unless $args{$key} =~ m/\A(?:[
a-z 0-9 \. _ # regular characters
\- \~ # special meaning characters
\* \? # quantifiers
# or any of the following special characters:
! " \# \$ \% \& ' \( \) \+ , \/ \:
; \< \= \> \@ \[ \\ \] \^ \` \{ \| \}
( run in 1.032 second using v1.01-cache-2.11-cpan-39bf76dae61 )