IO::EPP::Base
use Data::Dumper; use IO::EPP::Base; sub make_request { my ( $action, $params ) = @_; unless ( $params->{conn} ) { # need to connect my %sock_params = ( PeerHost => 'epp.example.com', PeerPort => 700, SSL_key_file => 'key.pem', SSL_cert_file => 'cert.pem', Timeout => 30, ); $params->{user} = 'login'; $params->{pass} = 'xxxxx'; $params->{sock_params} = \%sock_params; $params->{test_mode} = 1; # use emulator # $params->{no_log} = 1; # 1 if no logging # enter a name if you need to specify a file for the log # $params->{log_name} = '/var/log/comm_epp_example.log'; # use our function for logging $params->{log_fn} = sub { print "epp.example.com logger:\n$_[0]\n" }; } return IO::EPP::Base::make_request( $action, $params ); } my ( $answ, $msg, $conn_obj ) = make_request( 'check_domains', { domains => [ 'xyz.com', 'com.xyz', 'reged.xyz' ] } ); print Dumper $answ;
Result:
$VAR1 = { 'msg' => 'Command completed successfully.', 'xyz.com' => { 'avail' => '1' }, 'reged.xyz' => { 'reason' => 'in use', 'avail' => '0' }, 'code' => '1000', 'com.xyz' => { 'avail' => '1' } }; }
Module for common EPP-functions, without extension (dnssec only).
The module can be used to work with any provider, if the requests do not use extensions and the provider does not have its own features
It has two options: using a separate function call or working as an object
See IO:EPP for description
An example of working with functions is presented in the synopsis
Work checked on CentralNic server
INPUT:
action name;
parameters of query
OUTPUT:
io::epp object
or, in list context:
( full answer with code and message, string with code and message, io::epp object )
An Example:
my ( $answer, $message, $conn_object ) = make_request( 'hello', \%login_params );
Gereration ID for contacts
no params
new id
Authinfo Generation
length of authInfo, default 16 symbols
new authInfo
Create new IO::EPP object, аutomatically connects to the provider and logins.
Example of a call
# Parameters for L<IO::Socket::SSL> my %sock_params = ( PeerHost => 'epp.example.com', PeerPort => 700, SSL_key_file => $path_to_ssl_key_file, SSL_cert_file => $path_to_ssl_cert_file, Timeout => 30, ); # initialization of an object, during which login is called my $o = IO::EPP::Base->new( { sock_params => \%sock_params, user => $login_name, pass => $login_password, log_name => '/var/log/comm_epp_registry_name', } ); # call check of domains my ( $answ, $code, $msg ) = $o->check_domains( { domains => [ 'kalinka.realty' ] } ); undef $o; # call logout() и DESTROY() of object
package name, parameters.
Connection parameters:
user – login;
user
pass – password;
pass
tld – zone for providers that have a binding in it, for example, verisign;
tld
server – server name if the registry has different servers with different extensions, for example, pir/afilias for afilias;
server
sock_params – hashref with IO::Socket::SSL parameters;
sock_params
test_mode – use a real connection or registry emulator.
test_mode
Parameters for logging:
no_log – do not write anything to the log;
no_log
log_name – write log in this file, not in STDOUT;
log_name
log_fn – ref on functions to write to the log.
log_fn
io::epp object or array ( object, login code, login message )
If the connection or authorization failed, the response will contain zero instead of an object
Writes data to the log or calls the function specified when creating the object
By default, the log is written: date and time, pid of the process, name and body of the request:
Thu Jan 1 01:00:00 1111 pid: 12345 check_domains request: <?xml version="1.0" encoding="UTF-8"?> <epp xmlns="urn:ietf:params:xml:ns:epp-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd"> <command> <check> <domain:check xmlns:domain="urn:ietf:params:xml:ns:domain-1.0" xsi:schemaLocation="urn:ietf:params:xml:ns:domain-1.0 domain-1.0.xsd"> <domain:name>xyz.com</domain:name><domain:name>com.xyz</domain:name><domain:name>reged.xyz</domain:name> </domain:check> </check> <clTRID>50df482a1e928a00fa0e7fce3fe68f0f</clTRID> </command> </epp> Thu Feb 2 02:02:22 2222 pid: 12345 check_domains answer: <?xml version="1.0" encoding="UTF-8" standalone="no"?> <epp xmlns="urn:ietf:params:xml:ns:epp-1.0"> <response> <result code="1000"> <msg>Command completed successfully.</msg> </result> <resData><domain:chkData xmlns:domain="urn:ietf:params:xml:ns:domain-1.0"> <domain:cd><domain:name avail="1">xyz.com</domain:name></domain:cd> <domain:cd><domain:name avail="1">com.xyz</domain:name></domain:cd> <domain:cd><domain:name avail="0">reged.xyz</domain:name><domain:reason>in use</domain:reason></domain:cd> </domain:chkData></resData><trID> <clTRID>50df482a1e928a00fa0e7fce3fe68f0f</clTRID><svTRID>TEST-2979E52890117206AAA1639725F4E862</svTRID> </trID> </response> </epp>
For replace "req" in test mode
Request to registry
out_data – body of request;
out_data
info – name of request for log.
info
OUTPUT: answer from registry.
Universal handler for simple answer
request body;
request name;
check or not epp poll, default is 0
answer, may contain the object's name, id, creation and/or expiration date, client-side transaction id, and registry id;
answer code;
answer message, if there is an error in the response, an additional reason for the error may be passed along with the message.
# answer for create_contact: { 'msg' => 'Command completed successfully.', 'cont_id' => 'sxsup8ehs000', 'cre_date' => '2020-01-01 01:01:01', 'cltrid' => 'd0a528a4816ea4e16c3f56e25bf11111', 'code' => 1000, 'svtrid' => 'CNIC-22E5B2CBBD6C04169AEC9228FB0677FA173D76487AF8BA8734AF3C11111' }; # answer with error, "1.2.3.4 addr not found" is reason: { 'msg' => 'Parameter value policy error; 1.2.3.4 addr not found', 'cltrid' => 'd0e2a9c2af427264847b0a6e59b60000', 'code' => 2306, 'svtrid' => '4586654601-1579115463111' };
Authorization on the server. The function is automatically called from new. A separate call is only needed to change the password.
password;
addition standard parameters (<objURI>xxxxx-1.0</objURI>);
extensions (<extURI>yyyyyy-1.0</extURI>);
new password if need.
OUTPUT: see "simple_request".
Get greeting, ping analog.
No input parameters.
Sample response:
{ 'msg' => '<?xml version="1.0" encoding="UTF-8" standalone="no"?> <epp xmlns="urn:ietf:params:xml:ns:epp-1.0"><greeting> <svID>CentralNic EPP server EPP.CENTRALNIC.COM</svID> <svDate>2020-20-20T20:20:20.0Z</svDate> <svcMenu> <version>1.0</version><lang>en</lang> <objURI>urn:ietf:params:xml:ns:domain-1.0</objURI> <objURI>urn:ietf:params:xml:ns:contact-1.0</objURI> <objURI>urn:ietf:params:xml:ns:host-1.0</objURI> <svcExtension> <extURI>urn:ietf:params:xml:ns:rgp-1.0</extURI> <extURI>urn:ietf:params:xml:ns:secDNS-1.1</extURI> <extURI>urn:ietf:params:xml:ns:idn-1.0</extURI> <extURI>urn:ietf:params:xml:ns:fee-0.4</extURI> <extURI>urn:ietf:params:xml:ns:fee-0.5</extURI> <extURI>urn:ietf:params:xml:ns:launch-1.0</extURI> <extURI>urn:ietf:params:xml:ns:regtype-0.1</extURI> <extURI>urn:ietf:params:xml:ns:auxcontact-0.1</extURI> <extURI>urn:ietf:params:xml:ns:artRecord-0.2</extURI> <extURI>http://www.nic.coop/contactCoopExt-1.0</extURI> </svcExtension> </svcMenu> <dcp> <access><all></all></access> <statement> <purpose><admin></admin><prov></prov></purpose> <recipient><ours></ours><public></public></recipient> <retention><stated></stated></retention> </statement> </dcp></greeting></epp>', 'code' => 1000 };
Check whether there are contacts with such IDs
INPUT: params with key: contacts -- arrayref on contact id list.
contacts
Request:
my ( $answ, $msg ) = make_request( 'check_contacts', { contacts => [ 'H1234567', 'nfjkrek-fre8fm' ] } ); print Dumper $answ;
Answer:
$VAR1 = { 'msg' => 'Command completed successfully.', 'nfjkrek-fre8fm' => { 'avail' => '1' }, 'H1234567' => { 'avail' => '0' }, 'code' => '1000' };
Covertor contact user date to epp xml
for create/update_contact functions
Create contact extensions, for overwriting in child classes
Register a contact
Hash with parameters:
cont_id – some providers create contact ID automatically;
cont_id
name or first_name, last_name, patronymic, family_name – full name in one field or first, last, patronymic, family names separately;
name
first_name
last_name
patronymic
family_name
org – organization if necessary, some registries require a zero-length string, while others require undef;
org
undef
addr – street, house, building, apartment;
addr
city – city, town;
city
state – state, region, province, republic, optional field;
state
postcode – zip code;
postcode
country_code – two-character country code;
country_code
phone – the phone number in international format;
phone
fax – usually only required for legal entities;
fax
email;
email
authinfo – the key is to transfer your contacts, but usually the contacts are transferred automatically together with a domain.
authinfo
If only the int type of contacts is passed, it can be omitted.
int
An Example, one type (by default this is int):
( $answ, $code, $msg ) = $conn->create_contact( { cont_id => '123qwerty', first_name => 'Test', last_name => 'Testov', org => 'Private Person', addr => 'Vagnera 11-22', city => 'Donetsk', state => 'Donetskaya', postcode => '83061', country_code => 'DN', phone => '+380.501234567', fax => '', email => 'reg1010@yandex.com', authinfo => 'Q2+qqqqqqqqqqqqqqqqqqqqqqqqqq', }, );
Contact with two types
( $answ, $code, $msg ) = $conn->create_contact( { cont_id => '123qwerty', int => { first_name => 'Test', last_name => 'Testov', org => 'Private Person', addr => 'Vagnera 11-22', city => 'Donetsk', state => 'Donetskaya', postcode => '83061', country_code => 'DN', }, loc => { first_name => 'Тест', last_name => 'Тестов', org => 'Частное лицо', addr => 'Вагнера 11/22', city => 'Донецк', state => 'Донецкая обл.', postcode => '83061', country_code => 'DN', }, phone => '+380.501234567', fax => '', email => 'reg1010@yandex.com', authinfo => 'Q2+qqqqqqqqqqqqqqqqqqqqqqqqqq', } );
Covertor contact epp xml data to hash
for get_contact_info, overwritten in some child modules
Providers extension, replaced in provider modules
Returns an empty hashref here
Get information on the specified contact
cont_id – contact id
extension – epp extensions in xml
extension
my ( $answer, $code, $msg ) = $conn->get_contact_info( { cont_id => 'H12345' } ); # $answer: { 'owner' => 'H2220222', 'int' => { 'city' => 'Moscow', 'org' => 'My Ltd', 'country_code' => 'RU', 'name' => 'Igor Igorev', 'postcode' => '123456', 'addr' => 'Igoreva str, 3', 'state' => 'Igorevskya obl.' }, 'roid' => 'C2222888-CNIC', 'cre_date' => '2012-12-12 12:12:12', 'phone' => [ '+7.4952334455' ], 'pp_flag' => 1, 'email' => [ 'mail@igor.ru' ], 'upd_date' => '2012-12-12 12:12:12', 'cont_id' => 'H12345', 'fax' => [ '+7.4952334455' ], 'creater' => 'H2220222', 'statuses' => { 'serverDeleteProhibited' => '+', 'serverTransferProhibited' => '+', 'linked' => '+' } };
Part of update_* functions
To update contact information
params with keys:
add, rem – only contact statuses can be added or deleted, , such as clientUpdateProhibited
add
rem
chg – modify data, see fields in "create_contact"
chg
An Example, change data, one type (by default this is int):
( $answ, $code, $msg ) = $conn->update_contact( { cont_id => '123qwerty', chg => { first_name => 'Test', last_name => 'Testov', org => 'Private Person', addr => 'Vagnera 11-22', city => 'Donetsk', state => 'Donetskaya', postcode => '83061', country_code => 'DN', phone => '+380.501234567', fax => '', email => 'reg1010@yandex.com', authinfo => 'Q2+qqqqqqqqqqqqqqqqqqqqqqqqqq', } }, );
Delete the specified contact. Usually this function is not needed because the registry itself deletes unused contacts.
cont_id – contact id.
extension – extensions for some providers, empty by default
my ( $answ, $msg ) = make_request( 'delete_contact', { cont_id => 'H12345', %conn_params } );
Check that the nameserver is registered
nss – list with nameservers
nss
my ( $a, $m, $o ) = make_request( 'check_nss', { nss => [ 'ns99.cnic.com', 'ns1.godaddy.com' ] } ); # answer: { 'msg' => 'Command completed successfully.', 'ns1.godaddy.com' => { 'reason' => 'in use', 'avail' => '0' }, 'ns99.cnic.com' => { 'avail' => '1' }, 'code' => '1000' };
Registering a nameserver
ns – name server
ns
ips – array with IP, IPv4 and IPv6, IP must be specified only we register nameserver based on the domain of the same registry
ips
OUTPUT: see "simple_request"
my ( $h, $m, $o ) = make_request( 'create_ns', { ns => 'ns111.sssllll.info', %conn_params } ); # check answer ( $a, $m ) = make_request( 'create_ns', { ns => 'ns222.ssslll.com', ips => ['1.2.3.4', 'fe80::aa00:bb11' ], conn => $o } ); # check answer
Covertor NS xml resData data to hash.
Can be overwritten in a child module.
Get information about the specified nameserver
ns – name server;
extension – extensions for some providers, empty by default.
hash with ns data: statuses, dates, ips and other
owner – the account where the name server is located;
owner
create – the account where the name server was registered;
create
cre_date – name server registration date;
cre_date
roid – name server id in the registry;
roid
ips – list of IP addresses, IPv4 and IPv6;
linked – this status indicates that the name server is being used by some domain.
linked
my ( $answer, $msg, $conn ) = make_request( 'get_ns_info', { ns => 'ns1.sss.ru.com', %conn_params } ); # answer: { 'msg' => 'Command completed successfully.', 'owner' => 'H2220222', 'roid' => 'H370000-CNIC', 'cre_date' => '2013-09-05 18:42:49', 'name' => 'ns1.sss.ru.com', 'ips' => [ '2A00:3B00:0:0:0:0:0:25' ], 'creater' => 'H2220222', 'statuses' => { 'ok' => '+', 'linked' => '+' }, 'code' => '1000' };
Change the data of the specified name server
INPUT
add, rem – adding or removing the name server parameters listed below:
ips – IPv4 and IPv6 addresses;
statuses – clientUpdateProhibited and other client*;
statuses
chg – change the server name, this is used to move the name server to a different domain.
no_empty_chg – some registries prohibit passing an empty chg parameter – <host:chg/>
no_empty_chg
<host:chg/>
An Example
my ( $answ, $msg, $conn ) = make_request( 'update_ns', { ns => 'ns1.sss.ru.com', rem => { ips => [ '2A00:3B00:0:0:0:0:0:25' ] }, add => { ips => [ '176.99.13.11' ] }, %conn_params, } ); ( $answ, $msg ) = make_request( 'update_ns', { ns => 'ns1.sss.ru.com', chg => { new_name => 'ns1.sss.xyz' }, conn => $conn, } );
Remove nameserver from the registry.
It is usually forbidden to delete a name server that has the linked status.
my ( $answ, $msg ) = make_request( 'delete_ns', { ns => 'ns1.sss.ru.com', %conn_params } );
Parses resData in the registry response
Check that the domain is available for registration
domains – list of domains to check;
domains
hash with domains, each domain has an avail parameter, if avail == 0, the reason parameter is usually added
avail
reason
my ( $answer, $code, $msg ) = $conn->check_domains( { tld => 'com', domains => [ 'qwerty.com', 'bjdwferbkre3jd0hf.net', 'xn--xx.com', 'hiebw.info' ], } ); # answer: { 'qwerty.com' => { 'reason' => 'Domain exists', 'avail' => '0' }, 'bjdwferbkre3jd0hf.net' => { 'avail' => '1' }, 'hiebw.info' => { 'reason' => 'Not an authoritative TLD', 'avail' => '0' }, 'xn--xx.com' => { 'reason' => 'Invalid punycode encoding', 'avail' => '0' } };
Generating a list of ns-s for domain registration.
authinfo block for domain registration.
Block with the DNSSEC extension for domain registration
Domain registration.
dname – domain name;
dname
period – domain registration period, usually the default value is 1 year, registration for several months is not implemented – this is a very rare case;
period
reg_id, admin_id, tech_id, billing_id – id of registrant, administrator, technical and billing contacts, at least one contact is required, usually the registrant;
reg_id
admin_id
tech_id
billing_id
dnssec -- hash for DNSSEC params: keytag, alg, digtype, digest, for details see https://tools.ietf.org/html/rfc5910;
dnssec
keytag
alg
digtype
digest
nss – array with nameservers;
my ( $answ, $msg ) = make_request( 'create_domain', { dname => "sss.ru.com", reg_id => 'jp1g8fcv30fq', admin_id => 'jp1g8fcv31fq', tech_id => 'jp1g8fcv32fq', billing_id => 'jp1g8fcv33fq', authinfo => 'jp1g8fcv30fq+jp1g8fcv31fq', nss => [ 'dns1.yandex.net','dns2.yandex.net' ], period => 1, }, );
Covertor domains xml resData data to hash.
Parse special data in resData from provider.
For overwritten in a child module.
In this module, the function does nothing
Parse special data in extension from provider.
The main information on the domain
dname;
roid – domain id if registry;
owner – the account where the domain is located now;
create – the account where the domain was registered;
cre_date – domain registration date;
trans_date – domain last transfer date;
trans_date
upd_date – domain last update date;
upd_date
exp_date – domain expiration date;
exp_date
reg_id, admin_id, tech_id, billing_id – domain contact IDs;
nss – list of domain name servers;
statuses – hash where keys is status flags, values is status expiration date, if any, or other information;
hosts – list with name servers based on this domain.
hosts
There can also be extension parameters.
my ( $answer, $msg, $conn ) = make_request( 'get_domain_info', { dname => 'sss.ru.com', %conn_params } ); # answer: { 'hosts' => [ 'ns1.sss.ru.com', 'ns2.sss.ru.com' ], 'roid' => 'D888888-CNIC', 'cre_date' => '1212-12-12 12:12:12', 'upd_date' => '2020-02-02 20:02:20', 'trans_date' => '2012-12-12 12:12:12', 'creater' => 'H12345', 'tech_id' => '1iuhajppwsjp', 'reg_id' => 'H12346', 'owner' => 'H2220222', 'exp_date' => '2022-12-12 23:59:59', 'billing_id' => 'H12347', 'nss' => [ 'ns1.sss.ru.com' 'ns1.mmm.ru.com' ], 'dname' => 'sss.ru.com', 'admin_id' => 'H12348', 'statuses' => { 'renewPeriod' => '+', 'clientTransferProhibited' => '+' } };
Domain registration renewal for N years.
period – the domain renewal period in years, by default, will be prologed for 1 year;
exp_date – current expiration date, without specifying the time;
my ( $a, $m ) = make_request( 'renew_domain', { dname => 'datada.net', period => 1, exp_date => '2022-22-22' } );
Part of the update_domain function.
Can be overwritten in a child module, example, in IO::EPP::DrsUa
In this function this module contains the DNSSEC extension
To update domain data: contact ids, authinfo, nss, statuses.
dname – domain name
add, rem – hashes for adding and deleting data:
admin_id, tech_id, billing_id – contact IDs;
nss – list with name servers;
statuses – various client* statuses;
dnssec – DNSSEC extension parameters.
chg – hash for changeable data:
reg_id – registrant contact id;
authinfo – new key for domain;
Examples:
my ( $a, $m, $c ) = make_request( 'update_domain', { dname => 'example.com', chg => { authinfo => 'fnjkfrekrejkfrenkfrenjkfren' }, rem => { nss => [ 'ns1.qqfklnqq.com', 'ns2.qqfklnqq.com' ] }, add => { nss => [ 'ns1.web.name', 'ns2.web.name' ] }, %conn_params, } ); ( $a, $m ) = make_request( 'update_domain', { dname => 'example.com', rem => { statuses => [ 'clientUpdateProhibited','clientDeleteProhibited' ] }, add => { statuses => [ 'clientHold' ] }, conn => $c, } );
Domain transfers: to us, from us, reject transfers.
op – operation, possible variants: request, query, accept, cancel, reject;
op
request
query
accept
cancel
reject
authinfo – key for alien domain;
period – if the transfer with renew, you can specify the extension period for some registries, undef and zero have different values;
extension – extensions for some registries in xml format;
addition – special parameters for very original providers.
addition
It depends very much on the operation and on the registry
my ( $answ, $code, $msg ) = $conn->transfer( { op => 'request', dname => 'reclick.realty', authinfo => '123qweRTY{*}', period => 1 } ); ( $answ, $code, $msg ) = $conn->transfer( { op => 'query', dname => 'reclick.realty', authinfo => '123qweRTY{*}' } ); # answer from the CentralNic { 'exp_date' => '2021-01-18 23:59:59', 'cltrid' => '9d7e6ec767ec7d9d9d40fc518a5', 'trstatus' => 'pending', # transfer status 'requestors_id' => 'H2220222', # this we 'dname' => 'reclick.realty', 'senders_id' => 'H3105376', # godaddy 'send_date' => '2020-01-15 21:14:26', 'svtrid' => 'CNIC-82A2E9B355020697D1B3EF6FDE9D822D4CCE1D1616412EF53', 'request_date' => '2020-01-10 21:14:26' }; ( $answ, $code, $msg ) = $conn->transfer( { op => 'approve', dname => 'reclick.realty' } ); ( $answ, $code, $msg ) = $conn->transfer( { op => 'reject', dname => 'reclick.realty', authinfo => '123qweRTY{*}' } ); ( $answ, $code, $msg ) = $conn->transfer( { op => 'cancel', dname => 'reclick.realty', authinfo => '123qweRTY{*}' } );
Deleting a domain.
extension – extensions for some registries in xml format
my ( $a, $m ) = make_request( 'delete_domain', { dname => 'ssslll.ru.com', %conn_params } );
Parse resData from req poll
Can be overwritten in a child module
Parse req poll extension
Empty, for overwriting in children modules
Get and parse top message from poll
No input params.
Еach provider has a lot of different types of messages. Only domain transfer messages are similar. They have something like this format:
{ 'code' => '1301', 'msg' => 'Command completed successfully; ack to dequeue', 'count' => '1', 'id' => '456789', 'date' => '2020-02-02 20:02:02', 'qmsg' => 'Transfer Requested.', 'transfer' => { 'dname' => 'example.com', 'status' => 'pending', 'senders_id' => '1111'. 'requestors_id' => '999', 'request_date' => '2001-01-01 01:01:01', 'send_date' => '2001-01-06 01:01:01' }, 'svtrid' => '4569552848-1578703988000', 'cltrid' => '1f80c34195a936dfb0d2bd0c414141414' };
requestors_id – the registrar who made the transfer request;
requestors_id
senders_id – the registrar from which the domain is transferred;
senders_id
request_date – the start date of the transfer
request_date
send_date – date when the transfer is completed, unless it is canceled or the domain is released;
send_date
status – the status of the transfer, the most common meaning: pending, serverApproved, clientRejected, clientApproved.
status
pending
serverApproved
clientRejected
clientApproved
Delete message from poll by id
msg_id – id of the message to be removed from the queue.
msg_id
Close session, disconnect
Vadim Likhota <vadiml@cpan.org>, some edits were made by Andrey Voyshko, Victor Efimov
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
To install IO::EPP::TCI, copy and paste the appropriate command in to your terminal.
cpanm
cpanm IO::EPP::TCI
CPAN shell
perl -MCPAN -e shell install IO::EPP::TCI
For more information on module installation, please visit the detailed CPAN module installation guide.