The Perl and Raku Conference 2025: Greenville, South Carolina - June 27-29 Learn more

use Carp;
use File::Basename qw(basename);
use vars qw($UA $REGISTRY @EXPORT);
use constant {
RDAP_TYPE_NOTICE_OR_REMARK_TYPE => 'notice and remark type', #
RDAP_TYPE_STATUS => 'status', # these values are defined in
RDAP_TYPE_ROLE => 'role', # RFC 7483, section 10.2.
RDAP_TYPE_EVENT_ACTION => 'event action', #
RDAP_TYPE_DOMAIN_VARIANT_RELATION => 'domain variant relation', #
RDAP_REDACTED_EXPRESSION_LANGUAGE => 'redacted expression language', # these values are defined in
RDAP_REDACTED_NAME => 'redacted name', # RFC 9537
CACHE_TTL => 86400, # this registry is fairly stable
};
use base qw(Exporter);
use strict;
#
# export these symbols
#
our @EXPORT = qw(
RDAP_TYPE_NOTICE_OR_REMARK_TYPE
RDAP_TYPE_STATUS
RDAP_TYPE_ROLE
RDAP_TYPE_EVENT_ACTION
RDAP_TYPE_DOMAIN_VARIANT_RELATION
RDAP_REDACTED_EXPRESSION_LANGUAGE
RDAP_REDACTED_NAME
);
our ($UA, $REGISTRY);
=pod
=head1 NAME
L<Net::RDAP::Values> - a module which provides interface to the RDAP values
registry.
=head1 DESCRIPTION
The RDAP JSON Values Registry was defined in RFC 7483 and lists the
permitted values of certain RDAP object properties. This class implements
an interface to that registry.
Ironically, since the registry is only available in CSV and XML formats,
this module has to use L<XML::LibXML> in order to access the registry data
that it retrieves from the IANA web server.
=head1 METHODS
=head2 check()
Net::RDAP::Values->check($value, $type);
Net::RDAP::Values->check('add period', RDAP_TYPE_STATUS);
Net::RDAP::Values->check('registration', RDAP_TYPE_EVENT_ACTION);
The C<check()> function allows you to determine if a given value is present
in the registry. You must also specify the type of the value using one of
the C<RDAP_TYPE_*> constants.
If the value is registered in the registry, this method returns a true
value, otherwise it returns C<undef>.
=cut
sub check {
my ($self, $value, $type) = @_;
foreach my $registered ($self->values($type)) {
return 1 if ($registered eq $value);
}
return undef;
}
=pod
=head2 values()
@values = Net::RDAP::Values->values($type);
@values = Net::RDAP::Values->values(RDAP_TYPE_ROLE);
The C<values()> function returns a list of the permitted values for the
given value type. If you specify an invalid type, an exception is raised.
=cut
sub values {
my ($self, $type) = @_;
$REGISTRY = load_registry() unless ($REGISTRY);
if (!defined($REGISTRY->{'values_by_type'}->{$type})) {
croak(sprintf("'%s' is not a permitted value type", $type));
} else {
return sort @{$REGISTRY->{'values_by_type'}->{$type}};
}
}
=pod
=head2 types()
@types = Net::RDAP::Values->types;
The C<types()> function returns a list of all possible RDAP value types.
=cut
sub types {
return (
RDAP_TYPE_NOTICE_OR_REMARK_TYPE,
RDAP_TYPE_STATUS,
RDAP_TYPE_ROLE,
RDAP_TYPE_EVENT_ACTION,
RDAP_TYPE_DOMAIN_VARIANT_RELATION,
RDAP_REDACTED_EXPRESSION_LANGUAGE,
RDAP_REDACTED_NAME,
);
}
=pod
=head2 description()
$description = Net::RDAP::Values->description($value, $type);
$description = Net::RDAP::Values->description('registration', RDAP_TYPE_EVENT_ACTION);
use Net::RDAP::EPPStatusMap;
$description = Net::RDAP::Values->description(epp2rdap('serverHold'), RDAP_TYPE_STATUS);
The C<description()> function returns a textual description (in English) of the value
in the registry, suitable for display to the user.
=cut
sub description {
my ($self, $value, $type) = @_;
$REGISTRY = load_registry() unless ($REGISTRY);
return $REGISTRY->{'descriptions'}->{$type}->{$value};
}
sub load_registry {
my $package = shift;
my $file = sprintf('%s/%s-%s', File::Spec->tmpdir, $package, basename(IANA_REGISTRY_URL));
#
# $UA may have been injected by Net::RDAP->ua()
#
$UA = Net::RDAP::UA->new unless(defined($UA));
$UA->mirror(IANA_REGISTRY_URL, $file, CACHE_TTL);
return undef unless (-e $file);
my $doc = XML::LibXML->load_xml('location' => $file, 'no_blanks' => 1);
my $registry = {};
foreach my $record ($doc->getElementsByTagName('record')) {
my $value = $record->getElementsByTagName('value')->shift->textContent;
my $type = $record->getElementsByTagName('type')->shift->textContent;
my $description = $record->getElementsByTagName('description')->shift->textContent;
push(@{$registry->{'value_types'}->{$value}}, $type);
push(@{$registry->{'values_by_type'}->{$type}}, $value);
$registry->{'descriptions'}->{$type}->{$value} = $description;
}
return $registry;
}
1;
__END__
=pod
=head1 EXPORTED CONSTANTS
L<Net::RDAP::Values> exports the following constants, which correspond
to the permitted types of RDAP values:
=over
=item * C<RDAP_TYPE_NOTICE_OR_REMARK_TYPE>
=item * C<RDAP_TYPE_STATUS>
=item * C<RDAP_TYPE_ROLE>
=item * C<RDAP_TYPE_EVENT_ACTION>
=item * C<RDAP_TYPE_DOMAIN_VARIANT_RELATION>
=item * C<RDAP_REDACTED_NAME>
=back
=head1 COPYRIGHT
Copyright 2018-2023 CentralNic Ltd, 2024-2025 Gavin Brown. For licensing information,
please see the C<LICENSE> file in the L<Net::RDAP> distribution.
=cut