Net::DRI ======== A Perl library to access Domain Name Registries/Registrars Copyright (c) 2005,2006,2007 Patrick Mevzek with help and bugfix from various individuals (see Changes file) DRI stands for Domain Registry Interface and aims to be, for domain name registries/registrars/resellers what Perl DBI is for databases. Net::DRI offers a uniform API to access services. It can be used by registrars to access registries. It can be used by clients to access registrars and/or resellers. It can be used by anonyone to do whois or DAS queries. It is an OO framework that can be easily extended to handle various protocols (RRP, EPP, custom protocols) and various transports methods (TCP, TLS, SOAP, email, etc...). Specific policies for each registry are handled in a Net::DRI::DRD subclass, DRD standing for Domain Registry Driver with registry being used broadly to describe a service offering domain names and related things, which can be provided by a true domain name registry, a registrar or a reseller at any level in the chain. Net::DRI standardizes as much as possible on EPP which is the current standard for domain name activities, for example for status codes. It has been used to help conduct IETF interoperability tests, and is used in production by various organizations with success. Currently Net::DRI ships with - a full RRP implementation (RFC 2832 & 3632) - a full EPP implementation (RFC 3730/3731/3732/3733/3734/3735), including poll messages - many EPP extensions: * GracePeriod (RFC 3915) * E164 for ENUM (RFC 4114) * SecDNS for DNSSEC (RFC 4310) * Infrastructure ENUM in Austria * NSgroup (used by .BE and .EU) * Domain/Contact/Host extensions needed for extra services in various TLD: .EU .COM .NET .MOBI .AERO .CAT .US .PL .SE .BE .AT .COOP - a full DAS (Domain Availability Service) implementation for .BE & .EU - a full Whois implementation (RFC3912) for thin and thick registries : support included for domain names in .COM .NET .ORG .BIZ .INFO .AERO .EU - a TCP/TLS transport - a SOAP transport (HTTP/HTTPS) - a Web scraping ``transport'' - an SMTP transport - a Net::DRI::DRD::EURid covering EURid for .EU (with EPP & EPP extensions) - a Net::DRI::DRD::VNDS covering Verisign Naming & Directory Services for .COM & .NET (with RRP or EPP) - Net::DRI::DRD::* modules for : .WS .SE .PL .US .CAT .BE .MOBI .INFO .ORG .AT .LU .BIZ - a Net::DRI::DRD::AFNIC covering AFNIC registry for .FR (only domain_check through web services and all operations by email) - a Net::DRI::DRD::Gandi covering Gandi registrar for .COM/.NET/.ORG/.BIZ/ .INFO/.NAME/.BE (only domain_update for nameservers through web site, disabled for now) Work is underway to provide full support for asynchronous registries, as well as advanced features such as defered send. If you are a registry/registrar/reseller, we would welcome the opportunity to be able to test Net::DRI against your system. Please drop a note to the authors of Net::DRI and do not hesitate to provide this framework to your clients (see license file). Perl modules needed ------------------- Make sure to use at least Perl 5.8.4 as earlier versions have issues with utf8 handling which will cause errors for EPP. You also need the following modules: Carp (Perl internal) DateTime (*) DateTime::Duration (*) DateTime::Format::Strptime DateTime::Format::ISO8601 (>=0.06) DateTime::TimeZone Class::Accessor Class::Accessor::Chained Time::HiRes Email::Valid IO::Socket::INET IO::Socket::SSL (>=0.90) SOAP::Lite WWW::Mechanize XML::LibXML MIME::Entity Net::SMTP (*) all dates and durations exchanged with Net::DRI should be DateTime or DateTime::Duration objects Install ------- Use the standard procedure: perl Makefile.PL ; make ; make test ; make install Or just copy the content of the lib/ directory somewhere in your path. You can use tests available in t/ to make sure everything is well. (all tests are done locally and do not require a network connection) How to use ---------- You can find examples in the eg subdirectory: vnds_rrp.pl : as registrar, to connect to Verisign systems using RRP afnic_ws.pl : as AFNIC member, to use AFNIC web services afnic_email.pl : as AFNIC member, to use the email robot gandi_web.pl : as Gandi client, to change nameservers for your domain, through the web interface ws_rrp.pl : as registrar, to connect to .WS using RRP eurid_epp.pl : as registrar, connect to EURid test systems cat_epp.pl : as registrar, connect to .CAT test systems coop_epp.pl : as registrar, connect to .COOP test systems eurid_das.pl : for anyone, to check domain availability in .EU whois.pl : for anyone, to do whois queries for some TLDs. In the t subdirectory, the test files can also be studied for insight of all the API available. All errors trigger an exception using die and a specific class (Net::DRI::Exception). Thus all calls to Net::DRI methods should be put in an eval() to easily trap exceptions. Please see Net::DRI::Exception for details about information available when an exception is raised. Net::DRI uses an internal cache (in the future many different backends will be available for this service), and you can provide the global time to live of objects in it when you create the Net::DRI object. A negative ttl means no cache at all. It is recommended not to completely disable the cache, and to have a ttl of at least of few seconds : it will cut down the use of checks and related verifications done at registry, especially for complex operations. Typical use of this library would go along those lines: - $dri=Net::DRI->new(...) to create the global object. Save the output, everything will be done with methods applied on this object - $dri->add_registry(...) to add a new registry driver First argument is the registry class name (Net::DRI::DRD:: will be added if no :: is found), second argument is an hash ref setting information : you should have at least a clid key whose value is the client identifier at this registry for the client connecting (this is needed for the various _is_mine() methods - see below) You can attach as many registry drivers as you need to a single dri object this would enable you to easily operate on multiple registries at the same time Use $dri->target('registry name') to set the current registry, the one which will receive all future calls. The target method returns the $dri object, thus can be chained with other calls. Besides the registry name you can also pass a domain name or a TLD, and the library will try to find the correct registry. This will work only if you have no overlap between your TLDs among various registries - $dri->new_profile('profilename','transport class',[transport params],'protocol class',[protocol params]) (or new_current_profile with same parameters as in new_profile and it will also set the default profile to the one being created) OR $dri->new_profile('profilename',[transport params],[protocol params]) to use registry driver default (see transport_protocol_default in each DRD) for transport & protocol classes, in which case the two params can also be empty. Each registry driver is used through a specific profile. Each driver can have at the same time as many profiles as needed. A profile is: - a name - a transport, with specific parameters - a protocol, with specific parameters This enables you to be connected to the same registries with different credentials at the same time, or through different transports, if the registry provides for example access by email and by TCP at the same time. You switch profile using the $dri->target('registry name','profile name') call. new_profile() and new_current_profile() return a Net::DRI::Protocol::ResultStatus in all cases, and this should be tested with ->is_success() to be sure the profile has been created correctly. They may also die for some other internal errors. Optionnally, you can use an auto target function: by providing details about which profile to use for each given action, Net::DRI can switch to the profile needed automatically, thus you will not need anymore to call target() by yourself. To do that, you will need to provide information by calling: $dri->set_auto_target('profile','type','action') Profile is the profile name to use when doing action 'action' (check, info, create, etc...) on object type 'type' (domain, host, contact). The profile must exist before calling set_auto_target() A default profile can be specified when type and/or action is undef. - after registries and profiles have been created (others can be added at any time), you can apply many methods (see below) to the $dri object You can change the current registry and/or current profile at any time using $dri->target(...,...) You get back for most of the calls an object representing the status. It is an instance of Net::DRI::Protocol::ResultStatus, please see its documentation. You can also always use: result_is_success() result_code() result_native_code() result_message() result_lang() result_is_pending() result_trid() methods to get back the same information (if not given by the methods or if you want to discard output) Information that has been sent by registry will be available through $dri->get_info(...) with a specific key. The key to use depends on the operation, but should be registry-independent. get_info() get back information related to the latest operation. If you use target() and later get_info() you will get information related to the latest operation for the registry/profile specified in the target() call. See below the list of methods you can call, and information available after each in get_info() - when you are finished, call $dri->end() to deallocate ressources and close any open connections. If using the Socket transport, you can make sure the connection is still open by using the ping() method, such as : $dri->transport()->ping() It will return 1 if the connection is still there, 0 otherwise. If you pass a true value to ping(), it will automatically reconnect if the connection is broken. Available API ------------- * root_servers() gives list of root servers or domain name of root servers (in scalar context) for the current registry [ Will probably disappear in future versions ] * is_thick() gives 1 if the current registry stores contacts (thick registry) [DEPRECATED, use has_object('contact')] * has_object($type) gives 1 if the registry manages objects of type $type (domain, ns, contact, etc...) * periods() gives the list of all registration periods allowed by the current registry. Periods are given as DateTime::Duration objects. * is_my_tld() with a domain name as argument, returns 1 if the current registry handles this domain name (TLD of domain name is handled by registry) * cache_clear() completely delete cache for current registry and current profile * verify_name_domain() verify_name_host() gives 0 if the given argument is a correct name for a domain name or an hostname at the current registry. * verify_duration_create() verify_duration_renew() verify_duration_transfer() called internally at various stages in Net::DRI to verify that we can add/renew/transfer a domain name * domain_create_only() Create a domain at the current registry and current profile. A domain name and an hash ref should be provided. The hash ref can have a ``duration'' key with its value being a DateTime::Duration object, and a ``ns'' key with its value being a Net::DRI::Data::Hosts object. If nameservers are given, they must already exist at registry. You may use get_info with the following keys to get more information: - exDate : for the current expiration date (a DateTime object) - status : for the current status of domain name * domain_create() Same thing as before but 1) we separate nameservers : those being inside domain name being created, those being outside 2) we test outside nameservers for existence at registry, and if it fails, we try to create them 3) we create domain 4) we create nameservers that are inside domain 5) we update domain to add nameservers created at step 4. 6) if a status key exists in hash ref given, we try to change status of newly created domain name (For thick registries, we would also test contacts, and add them if necessary) In scalar context we get back the last status (which can be the one at any step, if it does not succeed) of the list of all status for each step in array context. * domain_delete_only() Delete a domain at the current registry and current profile. A domain name should be provided. * domain_delete() Same as previous method except: 1) we find the current list of nameservers for this domain 2) we remove all nameservers from this domain 3) we delete the domain name (which can fail if some nameservers use the domain name in their FQDN, we should try to rename them first, it is planned for later) See domain_create() for information on what we get back. * domain_info() Ask for all information on a given domain name at the current registry and current profile. A second optional parameter is an hash ref. It can include an auth key, for EPP registries for example. You may use get_info with the following keys to get more information: - ns : a Net::DRI::Data::Hosts object representing the nameservers of the domain - status : a Net::DRI::Data::StatusList object representing the current status list of the domain queried - exDate, crDate, upDate, trDate : DateTime objects representing the expiration, creation, last update, and transfer date for the domain queried - clID, crID, upID : (strings) local registry ID of the current sponsoring registrar, the registrar having created, and the registrar (or registry) having last modified the domain queried * domain_check() Check if a domain name exists or not at the current registry and current profile. $dri->get_info('exist') returns 0 or 1 * domain_check_multi() Check if the given list of domain names exist or not at the current registry and current profile. $dri->get_info('exist','domain',$domain) returns 0 or 1 for the given domain name in $domain (the cache ttl must be positive and large enough (few seconds) for that to work) * domain_exist() Same as previous, but we get back 0 or 1 if the domain does not exist/exist or undef if we do not know. * domain_update() Update the domain name given as argument at the current registry and current profile. Most of the time you should use the following more specific methods. * domain_update_ns() Update nameservers of the domain name given as argument at the current registry and current profile. Most of the time you should use the following more specific methods. * domain_update_ns_add() For the given domain name as first argument, add the nameservers given as second argument (being a Net::DRI::Data::Hosts object). * domain_update_ns_del() Same as previous to delete nameservers * domain_update_ns_set() Same as previous to set the current list of nameservers, irrespective to what they are now. * domain_update_status() Update statuses of the domain name given as argument at the current registry and current profile. Most of the time you should use the following more specific methods. * domain_update_status_add() For the given domain name as first argument, add the statuses given as second argument. To create the second argument, call $dri->create_status()->no() with up to three parameters : - first one is a string among renew, update, transfer, publish, delete (choices depending on the registry), which sets what is forbidden, - second (optional) one is a message (ex: Payment overdue), - third (optional, default to 'en') is the language of the previous message. The call to ->create_status() creates a new object from a class which is a subclass of Net::DRI::Data::StatusList, that can be used in all functions related to statuses. * domain_update_status_del() Same as previous to delete statuses. * domain_update_status_set() Same as previous to set the current list of status, irrespective to what they are now. * domain_update_contact() Update contacts of the domain name given as argument at the current registry and current profile. Most of the time you should use the following more specific methods. * domain_update_contact_add() For the given domain name as first argument, add the contacts given as second argument which is a Net::DRI::Data::ContactSet instance. * domain_update_contact_del() Same as previous to delete contacts. * domain_update_contact_set() Same as previous to set the current list of contacts, irrespective to what they are now. * domain_renew() Renew the domain name provided as first argument, with optionnally the duration as second argument, and current expiration as third. You may use get_info() to retrieve the same information as after domain_create_only() * domain_transfer() Various operations related to transfers of domain names. Most of the time you should use the following more specific methods. * domain_transfer_start() Start the transfer of the given domain name as first argument. A second optional argument is an hash ref that can include for example an auth key for authorization information. * domain_transfer_stop() Stop the transfer of the given domain name as first argument (used by the registrar having started the transfer). A second optional argument is an hash ref that can include for example an auth key for authorization information. * domain_transfer_query() Query the state of the ongoing transfer for the given domain name as first argument. A second optional argument is an hash ref that can include for example an auth key for authorization information. * domain_transfer_accept() Accept the transfer of the given domain name as first argument (used by the registrar currently sponsoring the domain name). A second optional argument is an hash ref that can include for example an auth key for authorization information. * domain_transfer_refuse() Refuse the transfer of the given domain name as first argument (used by the registrar currently sponsoring the domain name). A second optional argument is an hash ref that can include for example an auth key for authorization information. * domain_can() For the domain name given as first argument, and for the operation given as second (being either 'renew','update','delete' or 'tranfer'), returns 1 if we can do the requested operation at the current registry and current profile. We check the domain name status, and if possible who sponsors currently the domain name, and if the action requested needs sponsorship. * domain_status_allows() Check if the current status of the domain name given as first argument allows for a specific operation. Most of the time you should use the following more specific methods. * domain_status_allows_delete() Returns 1 if we can delete the domain name given as first argument at the current registry and current profile. Else, 0. * domain_status_allows_update() Same for update. * domain_status_allows_renew() Same for renew. * domain_status_allows_transfer() Same for transfer. * domain_current_status() Returns the status of the domain name given as first argument at the current registry and current profile. (status is a Net::DRI::Data::StatusList or subclass object) * domain_is_mine() Returns 1 if we are the current sponsor of the domain name given as first argument at the current registry and current profile. Else, 0. * host_create() Create a new nameserver. The first and only argument should be a Net::DRI::Data::Host object. * host_delete() Delete a nameserver. The first and only argument should be a Net::DRI::Data::Host object or a string. * host_info() Retrieve information about a namserver. The first and only argument should be a Net::DRI::Data::Host object or a string. You may use get_info with the following keys to get more information: - self : a Net::DRI::Data::Host for the nameserver itself (name + IP addresses) - exDate, crDate, upDate, trDate, clID, crID, upID : see domain_info() * host_check() * host_check_multi() * host_exist() * host_update() * host_update_ip() * host_update_ip_add() * host_update_ip_del() * host_update_ip_set() * host_update_status() * host_update_status_add() * host_update_status_del() * host_update_status_set() * host_update_name_set() * host_current_status() * host_is_mine() See corresponding domain_* methods. * contact_create() Create a new contact at registry. The first and only argument should be a Net::DRI::Data::Contact object. * contact_delete() * contact_info() * contact_check() * contact_check_multi() * contact_exist() * contact_update() * contact_update_status() * contact_update_status_add() * contact_update_status_del() * contact_update_status_set() * contact_transfer() * contact_transfer_start() * contact_transfer_stop() * contact_transfer_query() * contact_transfer_accept() * contact_transfer_refuse() * contact_is_mine() See above methods. * message_retrieve() message_delete() message_waiting() message_count() : to handle registry messages (see t/601vnds_epp.t) * all other operations For objects other than domain/contact/hosts or for other actions on domain/contact/hosts another API must be used. For example, to do action foobar on an object of type zorglub, here is what to do: my $ro=$dri->remote_object('zorglub'); my $rc=$ro->foobar(...specific parameters...); Please see the test files for more examples.