Net-EPP-0.19/000755 000765 000024 00000000000 11745236100 013061 5ustar00gavinstaff000000 000000 Net-EPP-0.19/COPYING000644 000765 000024 00000043131 11062500101 014101 0ustar00gavinstaff000000 000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. Net-EPP-0.19/lib/000755 000765 000024 00000000000 11745236100 013627 5ustar00gavinstaff000000 000000 Net-EPP-0.19/Makefile.PL000644 000765 000024 00000000401 11575403770 015040 0ustar00gavinstaff000000 000000 #!/usr/bin/perl # $Id$ use ExtUtils::MakeMaker; use strict; WriteMakefile( 'NAME' => 'Net::EPP', 'VERSION_FROM' => 'lib/Net/EPP.pm', 'PREREQ_PM' => { 'IO::Socket::SSL' => 0, 'XML::LibXML' => 0, 'Time::HiRes' => 0, 'Digest::SHA' => 0, }, ); Net-EPP-0.19/README000644 000765 000024 00000000553 11605321672 013750 0ustar00gavinstaff000000 000000 INSTALLATION To install this module type the following: perl Makefile.PL make make test make install COPYRIGHT AND LICENCE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. Copyright (C) 2011 CentralNic Ltd. All rights reserved. -- $Id: README,v 1.1.1.1 2005/03/07 11:31:58 gavin Exp $ Net-EPP-0.19/t/000755 000765 000024 00000000000 11745236100 013324 5ustar00gavinstaff000000 000000 Net-EPP-0.19/t/use.t000644 000765 000024 00000000153 11135604113 014300 0ustar00gavinstaff000000 000000 #!/usr/bin/env perl -w # $Id$ use strict; use Test; BEGIN { plan tests => 1 } use Net::EPP; ok(1); exit; Net-EPP-0.19/lib/Net/000755 000765 000024 00000000000 11745236100 014355 5ustar00gavinstaff000000 000000 Net-EPP-0.19/lib/Net/EPP/000755 000765 000024 00000000000 11745236100 015001 5ustar00gavinstaff000000 000000 Net-EPP-0.19/lib/Net/EPP.pm000644 000765 000024 00000004773 11745236005 015356 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id$ package Net::EPP; use vars qw($VERSION); use Net::EPP::Client; use Net::EPP::Frame; use Net::EPP::Protocol; use Net::EPP::ResponseCodes; use Net::EPP::Simple; use strict; our $VERSION = '0.19'; 1; __END__ =pod =head1 NAME C - a Perl library for the Extensible Provisioning Protocol (EPP) =head1 DESCRIPTION EPP is the Extensible Provisioning Protocol. EPP (defined in RFC 5730) is an application layer client-server protocol for the provisioning and management of objects stored in a shared central repository. Specified in XML, the protocol defines generic object management operations and an extensible framework that maps protocol operations to objects. As of writing, its only well-developed application is the provisioning of Internet domain names, hosts, and related contact details. This project offers a number of Perl modules which implement various EPP-related functions: =over =item * a low level protocol implementation (L) =item * a low-level client (L) =item * a high-level client (L) =item * an EPP frame builder (L) =item * a utility library to export EPP responde codes (L) =back These modules were originally created and maintained by CentralNic for use by their own registrars, but since their original release have become widely used by registrars and registries of all kinds. CentralNic has chosen to create this project to allow interested third parties to contribute to the development of these libraries, and to guarantee their long-term stability and maintenance. =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/), with the assistance of other contributors around the world, including (but not limited to): =over =item Rick Jansen =item Mike Kefeder =item Sage Weil =item Eberhard Lisse =item Yulya Shtyryakova =item Ilya Chesnokov =item Simon Cozens =item Patrick Mevzek =item Alexander Biehl and Christian Maile, united-domains AG =back =head1 REPORTING BUGS Please email any bug reports to L. =head1 SEE ALSO =over =item * Google Code Project page: L =back =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut Net-EPP-0.19/lib/Net/EPP/Client.pm000755 000765 000024 00000023262 11745236005 016571 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Client.pm,v 1.17 2011/01/23 12:23:16 gavin Exp $ package Net::EPP::Client; use bytes; use Net::EPP::Protocol; use Carp; use IO::Socket; use IO::Socket::SSL; use vars qw($XMLDOM $EPPFRAME); use strict; use warnings; =pod =head1 NAME Net::EPP::Client - a client library for the TCP transport for EPP, the Extensible Provisioning Protocol =head1 SYNOPSIS #!/usr/bin/perl use Net::EPP::Client; use strict; my $epp = Net::EPP::Client->new( host => 'epp.nic.tld', port => 700, ssl => 1, frames => 1, ); my $greeting = $epp->connect; $epp->send_frame('login.xml'); my $answer = $epp->get_frame; $epp->send_frame(''); my $answer = $epp->get_frame; =head1 DESCRIPTION EPP is the Extensible Provisioning Protocol. EPP (defined in RFC 4930) is an application layer client-server protocol for the provisioning and management of objects stored in a shared central repository. Specified in XML, the protocol defines generic object management operations and an extensible framework that maps protocol operations to objects. As of writing, its only well-developed application is the provisioning of Internet domain names, hosts, and related contact details. RFC 4934 defines a TCP based transport model for EPP, and this module implements a client for that model. You can establish and manage EPP connections and send and receive responses over this connection. C also provides some time-saving features, such as being able to provide request and response frames as C objects. =cut BEGIN { our $XMLDOM = 0; our $EPPFRAME = 0; eval { require XML::LibXML; $XMLDOM = 1; }; eval { require Net::EPP::Frame; $EPPFRAME = 1; }; } =pod =head1 CONSTRUCTOR my $epp = Net::EPP::Client->new(PARAMS); The constructor method creates a new EPP client object. It accepts a number of parameters: =over =item * host C specifies the computer to connect to. This may be a DNS hostname or an IP address. =item * port C specifies the TCP port to connect to. This is usually 700. =item * ssl If the C parameter is defined, then C will be used to provide an encrypted connection. If not, then a plaintext connection will be created. =item * dom (deprecated) If the C parameter is defined, then all response frames will be returned as C objects. =item * frames If the C parameter is defined, then all response frames will be returned as C objects (actually, C objects reblessed as C objects). =back =cut sub new { my ($package, %params) = @_; my $self; if (defined($params{'sock'})) { $self = { 'sock' => $params{'sock'}, ssl => 0, 'dom' => (defined($params{'dom'}) ? 1 : 0), 'frames' => (defined($params{'frames'}) ? 1 : 0), } } else { croak("missing hostname") if (!defined($params{'host'})); croak("missing port") if (!defined($params{'port'})); $self = { 'host' => $params{'host'}, 'port' => $params{'port'}, 'ssl' => (defined($params{'ssl'}) ? 1 : 0), 'dom' => (defined($params{'dom'}) ? 1 : 0), 'frames' => (defined($params{'frames'}) ? 1 : 0), }; } if ($self->{'frames'} == 1) { if ($EPPFRAME == 0) { croak("Frames requested but Net::EPP::Frame isn't available"); } else { $self->{'parser'} = XML::LibXML->new; $self->{'class'} = 'Net::EPP::Frame'; } } elsif ($self->{'dom'} == 1) { if ($XMLDOM == 0) { croak("DOM requested but XML::LibXML isn't available"); } else { $self->{'parser'} = XML::LibXML->new; $self->{'class'} = 'XML::LibXML::Document'; } } else { # for well-formedness checking: $self->{'parser'} = XML::LibXML->new; } return bless($self, $package); } =pod =head1 METHODS =head2 Connecting to a server: my $greeting = $epp->connect(%PARAMS); This method establishes the TCP connection. You can use the C<%PARAMS> hash to specify arguments that will be passed on to the constructors for C (such as a timeout) or C (such as certificate information). See the relevant manpage for examples. This method will C if connection fails, so be sure to use C if you want to catch the error. By default, the return value for C will be the EPP EgreetingE frame returned by the server. Please note that the same caveat about blocking applies to this method as to C (see below). If you want to get the greeting yourself, set C<$params{no_greeting}>. =cut sub connect { my ($self, %params) = @_; if (defined($self->{'sock'})) { $self->_connect_unix(%params); } else { $self->_connect_tcp(%params); } return ($params{'no_greeting'} ? 1 : $self->get_frame); } sub _connect_tcp { my ($self, %params) = @_; my $SocketClass = ($self->{'ssl'} == 1 ? 'IO::Socket::SSL' : 'IO::Socket::INET'); $self->{'connection'} = $SocketClass->new( PeerAddr => $self->{'host'}, PeerPort => $self->{'port'}, Proto => 'tcp', Type => SOCK_STREAM, %params ); if (!defined($self->{'connection'}) || ($@ && $@ ne '')) { chomp($@); $@ =~ s/^$SocketClass:? ?//; croak("Connection to $self->{'host'}:$self->{'port'} failed: $@") }; return 1; } sub _connect_unix { my ($self, %params) = @_; $self->{'connection'} = IO::Socket::UNIX->new( Peer => $self->{'sock'}, Type => SOCK_STREAM, %params ); croak("Connection to $self->{'host'}:$self->{'port'} failed: $@") if (!defined($self->{'connection'}) || ($@ && $@ ne '')); return 1; } =pod =head2 Communicating with the server: my $answer = $epp->request($question); This is a simple wrapper around C and C (see below). This method accepts a "question" frame as an argument, sends it to the server, and then returns the next frame the server sends back. =cut sub request { my ($self, $frame) = @_; return $self->get_frame if ($self->send_frame($frame)); } =pod =head2 Getting a frame from the server: my $frame = $epp->get_frame; This method returns an EPP response frame from the server. This may either be a scalar filled with XML, an C object (or an C object), depending on whether you defined the C parameter to the constructor. B: this method will block your program until it receives the full frame from the server. That could be a bad thing for your program, so you might want to consider using the C function to apply a timeout, like so: my $timeout = 10; # ten seconds eval { local $SIG{ALRM} = sub { die "alarm\n" }; alarm($timeout); my $frame = $epp->get_frame; alarm(0); }; if ($@ ne '') { alarm(0); print "timed out\n"; } If the connection to the server closes before the response can be received, or the server returned a mal-formed frame, this method will C. =cut sub get_frame { my $self = shift; return $self->get_return_value(Net::EPP::Protocol->get_frame($self->{'connection'})); } sub get_return_value { my ($self, $xml) = @_; if (!defined($self->{'class'})) { return $xml; } else { my $document; eval { $document = $self->{'parser'}->parse_string($xml) }; if (!defined($document) || $@ ne '') { chomp($@); croak(sprintf("Frame from server wasn't well formed: %s\n\nThe XML looks like this:\n\n%s\n\n", $@, $xml)); return undef; } else { my $class = $self->{'class'}; return bless($document, $class); } } } =pod =head2 Sending a frame to the server: $epp->send_frame($frame, $wfcheck); This sends a request frame to the server. C<$frame> may be one of: =over =item * a scalar containing XML =item * a scalar containing a filename =item * an C object (or an instance of a subclass) =item * an C object (or an instance of a subclass) =back Unless C<$wfcheck> is false, the first two of these will be checked for well-formedness. If the XML data is broken, then this method will croak. =cut sub send_frame { my ($self, $frame, $wfcheck) = @_; my $xml; if (ref($frame) ne '' && ($frame->isa('XML::DOM::Document') || $frame->isa('XML::LibXML::Document'))) { $xml = $frame->toString; $wfcheck = 0; } elsif ($frame !~ /); close(FRAME); $wfcheck = 1; } } else { $xml = $frame; $wfcheck = ($wfcheck ? 1 : 0); } if ($wfcheck == 1) { eval { $self->{'parser'}->parse_string($xml) }; if ($@ ne '') { chomp($@); croak(sprintf("Frame from server wasn't well formed: %s\n\nThe XML looks like this:\n\n%s\n\n", $@, $xml)); } } return Net::EPP::Protocol->send_frame($self->{'connection'}, $xml); } =pod =head2 Disconnecting from the server: $epp->disconnect; This closes the connection. An EPP server should always close a connection after a ElogoutE frame has been received and acknowledged; this method is provided to allow you to clean up on the client side, or close the connection out of sync with the server. =cut sub disconnect { my $self = shift; $self->{'connection'}->close; return 1; } =pod =head1 AUTHOR CentralNic Ltd (L). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =item * L =item * RFCs 4930 and RFC 4934, available from L. =item * The CentralNic EPP site at L. =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/000755 000765 000024 00000000000 11745236100 016033 5ustar00gavinstaff000000 000000 Net-EPP-0.19/lib/Net/EPP/Frame.pm000755 000765 000024 00000021043 11745236005 016400 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Frame.pm,v 1.17 2011/01/23 12:26:24 gavin Exp $ package Net::EPP::Frame; use Carp; use Net::EPP::Frame::Command; use Net::EPP::Frame::Greeting; use Net::EPP::Frame::Hello; use Net::EPP::Frame::ObjectSpec; use Net::EPP::Frame::Response; use POSIX qw(strftime); use XML::LibXML; use base qw(XML::LibXML::Document); use vars qw($EPP_URN $SCHEMA_URI); use strict; our $EPP_URN = 'urn:ietf:params:xml:ns:epp-1.0'; our $SCHEMA_URI = 'http://www.w3.org/2001/XMLSchema-instance'; =pod =head1 NAME Net::EPP::Frame - An EPP XML frame system built on top of L. =head1 SYNOPSIS #!/usr/bin/perl use Net::EPP::Client; use Net::EPP::Frame; use Net::EPP::ObjectSpec; use Digest::MD5 qw(md5_hex); use Time::HiRes qw(time); use strict; # # establish a connection to an EPP server: # my $epp = Net::EPP::Client->new( host => 'epp.registry.tld', port => 700, ssl => 1, dom => 1, ); my $greeting = $epp->connect; # # log in: # my $login = Net::EPP::Frame::Command::Login->new; $login->clID->appendText($userid); $login->pw->appendText($passwd); # # set the client transaction ID: # $login->clTRID->appendText(md5_hex(Time::HiRes::time().$$)); # # check the response from the log in: # my $answer = $epp->request($login); my $result = ($answer->getElementsByTagName('result'))[0]; if ($result->getAttribute('code') != 1000) { die("Login failed!"); } # # OK, let's do a domain name check: # my $check = Net::EPP::Frame::Command::Check->new; # # get the spec from L: # my @spec = Net::EPP::Frame::ObjectSpec->spec('domain'); # # create a domain object using the spec: # my $domain = $check->addObject(@spec); # # set the domain name we want to check: # my $name = $check->createElement('domain:name'); $name->appendText('example.tld'); # # set the client transaction ID: # $check->clTRID->appendText(md5_hex(time().$$)); # # assemble the frame: # $domain->addChild($name); # # send the request: # my $answer = $epp->request($check); # and so on... =head1 DESCRIPTION EPP is the Extensible Provisioning Protocol. EPP (defined in RFC 4930) is an application layer client-server protocol for the provisioning and management of objects stored in a shared central repository. Specified in XML, the protocol defines generic object management operations and an extensible framework that maps protocol operations to objects. As of writing, its only well-developed application is the provisioning of Internet domain names, hosts, and related contact details. EPP uses XML documents called "frames" send data to and from clients and servers. This module implements a subclass of the L module that simplifies the process of creation of these frames. It is designed to be used alongside the L module. =head1 OBJECT HIERARCHY L +----L +----L =head1 USAGE As a rule, you will not need to create Net::EPP::Frame objects directly. Instead, you should use one of the subclasses included with the distribution. The subclasses all inherit from Net::EPP::Frame. Net::EPP::Frame is itself a subclass of L so all the methods available from that class are also available to instances of Net::EPP::Frame. The available subclasses of Net::EPP::Frame exist to add any additional elements required by the EPP specification. For example, the EloginE frame must contain the EclIDE and EpwE frames, so when you create a new L object, you get these already defined. These classes also have convenience methods, so for the above example, you can call the C<$login-EclID> and C<$login-Epw> methods to get the L objects correesponding to those elements. =head2 RATIONALE You could just as easily construct your EPP frames from templates or just lots of C calls. But using a programmatic approach such as this strongly couples the validity of your XML to the validity of your program. If the process by which your XML is built is broken, I. This has to be a win. =cut sub new { my ($package, $type) = @_; if (!$type) { my @parts = split(/::/, $package); $type = lc(pop(@parts)); } if ($type !~ /^(hello|greeting|command|response)$/) { croak("'type' parameter to Net::EPP::Frame::new() must be one of: hello, greeting, command, response ('$type' given)."); return undef; } my $self = $package->SUPER::new('1.0', 'UTF-8'); bless($self, $package); my $epp = $self->createElementNS($EPP_URN, 'epp'); $epp->setNamespace($SCHEMA_URI, 'xsi', 0); $epp->setAttributeNS($SCHEMA_URI, 'schemaLocation', "$EPP_URN epp-1.0.xsd"); $self->addChild($epp); my $el = $self->createElement($type); $epp->addChild($el); $self->_addExtraElements; return $self; } sub _addExtraElements { } =pod =head1 ADDITIONAL METHODS my $str = $frame->formatTimeStamp($timestamp); This method returns a scalar in the required format (defined in RFC 3339). This is a convenience method. =cut sub formatTimeStamp { my ($self, $stamp) = @_; return strftime('%Y-%m-%dT%H:%M:%S.0Z', gmtime($stamp)); } =pod my $node = $frame->getNode($id); my $node = $frame->getNode($ns, $id); This is another convenience method. It uses C<$id> with the I method to get a list of nodes with that element name, and simply returns the first L from the list. If C<$ns> is provided, then I is used. =cut sub getNode { my ($self, @args) = @_; if (scalar(@args) == 2) { return ($self->getElementsByTagNameNS(@args))[0]; } elsif (scalar(@args) == 1) { return ($self->getElementsByTagName($args[0]))[0]; } else { croak('Invalid number of arguments to getNode()'); } } =pod my $binary = $frame->header; Returns a scalar containing the frame length packed into binary. This is only useful for low-level protocol stuff. =cut sub header { my $self = shift; return pack('N', length($self->toString) + 4); } =pod my $data = $frame->frame; Returns a scalar containing the frame header (see the I method above) concatenated with the XML frame itself. This is only useful for low-level protocol stuff. =cut sub frame { my $self = shift; return $self->header.$self->toString; } =pod =head1 AVAILABLE SUBCLASSES =over =item L, the base class =item L, for EPP client command frames =item L, for EPP EcheckE client commands =item L, for EPP EcreateE client commands =item L, for EPP EdeleteE client commands =item L, for EPP EinfoE client commands =item L, for EPP EloginE client commands =item L, for EPP ElogoutE client commands =item L, for EPP EpollE client commands =item L, for EPP ErenewE client commands =item L, for EPP EtransferE client commands =item L, for EupdateE client commands =item L, for EPP server greetings =item L, for EPP client greetings =item L, for EPP server response frames =back Each subclass has its own subclasses for various objects, for example L creates CcheckE> frame for domain names. Coverage for all combinations of command and object type is not complete, but work is ongoing. =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L, the Perl bindings to the libxml library =item * The libxml website at L =item * the L module, for communicating with EPP servers. =item * the L module, for managing EP object metadata. =item * RFCs 4930 and RFC 4934, available from L. =item * The CentralNic EPP site at L. =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Protocol.pm000644 000765 000024 00000007171 11745236005 017152 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. package Net::EPP::Protocol; use bytes; use Carp; use strict; =pod =head1 NAME Net::EPP::Protocol - Low-level functions useful for both EPP clients and servers. =head1 SYNOPSIS #!/usr/bin/perl use Net::EPP::Protocol; use IO::Socket; use strict; # create a socket: my $socket = IO::Socket::INET->new( ... ); # send a frame down the socket: Net::EPP::Protocol->send_frame($socket, $xml); # get a frame from the socket: my $xml = Net::EPP::Protocol->get_frame($socket); =head1 DESCRIPTION EPP is the Extensible Provisioning Protocol. EPP (defined in RFC 4930) is an application layer client-server protocol for the provisioning and management of objects stored in a shared central repository. Specified in XML, the protocol defines generic object management operations and an extensible framework that maps protocol operations to objects. As of writing, its only well-developed application is the provisioning of Internet domain names, hosts, and related contact details. This module implements functions that are common to both EPP clients and servers that implement the TCP transport as defined in RFC 4934. The main consumer of this module is currently L. =head1 METHODS my $xml = Net::EPP::Protocol->get_frame($socket); This method reads a frame from the socket and returns a scalar containing the XML. C<$socket> must be an L or one of its subclasses (ie C). If the transmission fails for whatever reason, this method will C, so be sure to enclose it in an C. =cut sub get_frame { my ($class, $fh) = @_; my $hdr; if (!defined($fh->read($hdr, 4))) { croak("Got a bad frame length from peer - connection closed?"); } else { my $length = (unpack('N', $hdr) - 4); if ($length < 0) { croak("Got a bad frame length from peer - connection closed?"); } elsif (0 == $length) { croak('Frame length is zero'); } else { my $xml = ''; my $buffer; while (length($xml) < $length) { $buffer = ''; $fh->read($buffer, ($length - length($xml))); last if (length($buffer) == 0); # in case the socket has closed $xml .= $buffer; } return $xml; } } } =pod Net::EPP::Protocol->send_frame($socket, $xml); This method prepares an RFC 4934 compliant EPP frame and transmits it to the remote peer. C<$socket> must be an L or one of its subclasses (ie C). If the transmission fails for whatever reason, this method will C, so be sure to enclose it in an C. Otherwise, it will return a true value. =cut sub send_frame { my ($class, $fh, $xml) = @_; $fh->print($class->prep_frame($xml)); $fh->flush; return 1; } =pod my $frame = Net::EPP::Protocol->prep_frame($xml); This method returns the XML frame in "wire format" with the protocol header prepended to it. The return value can be printed directly to an open socket, for example: print STDOUT Net::EPP::Protocol->prep_frame($frame->toString); =cut sub prep_frame { my ($class, $xml) = @_; return pack('N', length($xml) + 4).$xml; } =pod =head1 AUTHOR CentralNic Ltd (L). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =item * RFCs 4930 and RFC 4934, available from L. =item * The CentralNic EPP site at L. =back =cut 1; Net-EPP-0.19/lib/Net/EPP/ResponseCodes.pm000644 000765 000024 00000013764 11745236005 020132 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: ResponseCodes.pm,v 1.2 2011/01/04 10:37:33 gavin Exp $ package Net::EPP::ResponseCodes; use base qw(Exporter); use vars qw(@EXPORT); use strict; =head1 NAME Net::EPP::ResponseCodes - a module to export some constants that correspond to EPP response codes =head1 SYNOPSIS use Net::EPP::ResponseCodes; use Net::EPP::Simple; use strict; my $epp = Net::EPP::Simple->new( host => 'epp.nic.tld', user => 'my-id', pass => 'my-password', ); my $result = $epp->domain_transfer_request('example.tld', 'foobar', 1); if ($result) { print "Transfer initiated OK\n"; } else { if ($Net::EPP::Simple::Code == OBJECT_PENDING_TRANSFER) { print "Error: domain is already pending transfer\n"; } elsif ($Net::EPP::Simple::Code == INVALID_AUTH_INFO) { print "Error: invalid authcode provided\n"; } elsif ($Net::EPP::Simple::Code == OBJECT_DOES_NOT_EXIST) { print "Error: domain not found\n"; } elsif ($Net::EPP::Simple::Code == STATUS_PROHIBITS_OP) { print "Error: domain cannot be transferred\n"; } else { print "Error code $Net::EPP::Simple::Code\n"; } } =head1 DESCRIPTION EPP is the Extensible Provisioning Protocol. EPP (defined in RFC 4930) is an application layer client-server protocol for the provisioning and management of objects stored in a shared central repository. Specified in XML, the protocol defines generic object management operations and an extensible framework that maps protocol operations to objects. As of writing, its only well-developed application is the provisioning of Internet domain names, hosts, and related contact details. Every response sent to the client by an EPP server contains a CresultE> element that has a C attribute. This is a four-digit numeric code that describes the result of the request. This module exports a set of constants that provide handy mnemonics for each of the defined codes. =head1 EXPORTS C exports the following constants. The number in brackets is the integer value associated with the constant. =head2 Successful command completion responses (1nnn) =over =item OK (1000) =item OK_PENDING (1001) =item OK_NO_MESSAGES (1300) =item OK_MESSAGES (1301) =item OK_BYE (1500) =back =head2 Command error responses (2nnn) =head3 Protocol Syntax =over =item UNKNOWN_COMMAND (2011) =item SYNTAX_ERROR (2011) =item USE_ERROR (2011) =item MISSING_PARAM (2011) =item PARAM_RANGE_ERROR (2011) =item PARAM_SYNTAX_ERROR (2011) =back =head3 Implementation-specific Rules =over =item UNIMPLEMENTED_VERSION (2100) =item UNIMPLEMENTED_COMMAND (2101) =item UNIMPLEMENTED_OPTION (2102) =item UNIMPLEMENTED_EXTENSION (2103) =item BILLING_FAILURE (2104) =item NOT_RENEWABLE (2105) =item NOT_TRANSFERRABLE (2106) =back =head3 Security (22nn) =over =item AUTHENTICATION_ERROR (2200) =item AUTHORISATION_ERROR (2201) =item AUTHORIZATION_ERROR (2201) =item INVALID_AUTH_INFO (2202) =back =head3 Data Management (23nn) =over =item OBJECT_PENDING_TRANSFER (2300) =item OBJECT_NOT_PENDING_TRANSFER (2301) =item OBJECT_EXISTS (2302) =item OBJECT_DOES_NOT_EXIST (2303) =item STATUS_PROHIBITS_OP (2304) =item ASSOC_PROHIBITS_OP (2305) =item PARAM_POLICY_ERROR (2306) =item UNIMPLEMENTED_OBJECT_SERVICE (2307) =item DATA_MGMT_POLICY_VIOLATION (2308) =back =head3 Server System (24nn) =over =item COMMAND_FAILED (2400) =back =head3 Connection Management (25nn) =over =item COMMAND_FAILED_BYE (2500) =item AUTH_FAILED_BYE (2501) =item SESSION_LIMIT_EXCEEDED_BYE (2502) =back =head1 AUTHOR CentralNic Ltd (L). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =item * L =item * L =item * RFCs 4930 and RFC 4934, available from L. =item * The CentralNic EPP site at L. =back =cut # # Successful command completion responses: # use constant OK => 1000; use constant OK_PENDING => 1001; use constant OK_NO_MESSAGES => 1300; use constant OK_MESSAGES => 1301; use constant OK_BYE => 1500; # # Command error responses: # # Protocol Syntax: use constant UNKNOWN_COMMAND => 2011; use constant SYNTAX_ERROR => 2011; use constant USE_ERROR => 2011; use constant MISSING_PARAM => 2011; use constant PARAM_RANGE_ERROR => 2011; use constant PARAM_SYNTAX_ERROR => 2011; # Implementation-specific Rules: use constant UNIMPLEMENTED_VERSION => 2100; use constant UNIMPLEMENTED_COMMAND => 2101; use constant UNIMPLEMENTED_OPTION => 2102; use constant UNIMPLEMENTED_EXTENSION => 2103; use constant BILLING_FAILURE => 2104; use constant NOT_RENEWABLE => 2105; use constant NOT_TRANSFERRABLE => 2106; # Security: use constant AUTHENTICATION_ERROR => 2200; use constant AUTHORISATION_ERROR => 2201; use constant AUTHORIZATION_ERROR => 2201; use constant INVALID_AUTH_INFO => 2202; # Data Management: use constant OBJECT_PENDING_TRANSFER => 2300; use constant OBJECT_NOT_PENDING_TRANSFER => 2301; use constant OBJECT_EXISTS => 2302; use constant OBJECT_DOES_NOT_EXIST => 2303; use constant STATUS_PROHIBITS_OP => 2304; use constant ASSOC_PROHIBITS_OP => 2305; use constant PARAM_POLICY_ERROR => 2306; use constant UNIMPLEMENTED_OBJECT_SERVICE => 2307; use constant DATA_MGMT_POLICY_VIOLATION => 2308; # Server System: use constant COMMAND_FAILED => 2400; # Connection Management: use constant COMMAND_FAILED_BYE => 2500; use constant AUTH_FAILED_BYE => 2501; use constant SESSION_LIMIT_EXCEEDED_BYE => 2502; our @EXPORT; my $package = __PACKAGE__; foreach my $constant (keys(%constant::declared)) { if ($constant =~ /^$package/) { $constant =~ s/^$package\:\://; push(@EXPORT, $constant); } } 1; Net-EPP-0.19/lib/Net/EPP/Simple.pm000644 000765 000024 00000144352 11745236005 016605 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Simple.pm,v 1.10 2011/04/08 12:57:11 gavin Exp $ package Net::EPP::Simple; use Carp; use Digest::SHA qw(sha1_hex); use Net::EPP::Frame; use Net::EPP::ResponseCodes; use Time::HiRes qw(time); use base qw(Net::EPP::Client); use constant EPP_XMLNS => 'urn:ietf:params:xml:ns:epp-1.0'; use vars qw($Error $Code $Message @Log); use strict; use warnings; our $Error = ''; our $Code = OK; our $Message = ''; our @Log = (); =pod =head1 Name Net::EPP::Simple - a simple EPP client interface for the most common jobs =head1 Synopsis #!/usr/bin/perl use Net::EPP::Simple; use strict; my $epp = Net::EPP::Simple->new( host => 'epp.nic.tld', user => 'my-id', pass => 'my-password', ); my $domain = 'example.tld'; if ($epp->check_domain($domain) == 1) { print "Domain is available\n" ; } else { my $info = $epp->domain_info($domain); printf("Domain was registered on %s by %s\n", $info->{crDate}, $info->{crID}); } =head1 Description EPP is the Extensible Provisioning Protocol. EPP (defined in RFC 4930) is an application layer client-server protocol for the provisioning and management of objects stored in a shared central repository. Specified in XML, the protocol defines generic object management operations and an extensible framework that maps protocol operations to objects. As of writing, its only well-developed application is the provisioning of Internet domain names, hosts, and related contact details. This module provides a high level interface to the EPP protocol. It hides all the boilerplate of connecting, logging in, building request frames and parsing response frames behind a simple, Perlish interface. It is based on the C module and uses C to build request frames. =head1 Constructor The constructor for C has the same general form as the one for C, but with the following exceptions: =over =item * Unless otherwise set, C defaults to 700 =item * Unless the C parameter is set, SSL is always on =item * You can use the C and C parameters to supply authentication information. =item * The C parameter controls how long the client waits for a response from the server before returning an error. =item * if C is set, C will output verbose debugging information on C, including all frames sent to and received from the server. =item * C can be used to disable automatic reconnection (it is enabled by default). Before sending a frame to the server, C will send a ChelloE> to check that the connection is up, if not, it will try to reconnect, aborting after the Ith time, where I is the value of C (the default is 3). =item * C can be used to disable automatic logins. If you set it to C<0>, you can manually log in using the C<$epp->_login()> method. =back The constructor will establish a connection to the server and retrieve the greeting (which is available via $epp-E{greeting}) and then send a EloginE request. If the login fails, the constructor will return C and set C<$Net::EPP::Simple::Error> and C<$Net::EPP::Simple::Code>. =head2 Client and Server SSL options RFC 5730 requires that all EPP instances must be protected using "mutual, strong client-server authentication". In practice, this means that both client and server must present an SSL certificate, and that they must both verify the certificate of their peer. =head3 Server Certificate Verification C will verify the certificate presented by a server if the C, and either C or C are passed to the constructor: my $epp = Net::EPP::Simple->new( host => 'epp.nic.tld', user => 'my-id', pass => 'my-password', verify => 1, ca_file => '/etc/pki/tls/certs/ca-bundle.crt', ca_path => '/etc/pki/tls/certs', ); C will fail to connect to the server if the certificate is not valid. =head3 SSL Cipher Selection You can restrict the ciphers that you will use to connect to the server by passing a C parameter to the constructor. This is a colon- separated list of cipher names and aliases. See L for further details. As an example, the following cipher list is suggested for clients who wish to ensure high-security connections to servers: HIGH:!ADH:!MEDIUM:!LOW:!SSLv2:!EXP =head3 Client Certificates If you are connecting to an EPP server which requires a client certificate, you can configure C to use one as follows: my $epp = Net::EPP::Simple->new( host => 'epp.nic.tld', user => 'my-id', pass => 'my-password', key => '/path/to/my.key', cert => '/path/to/my.crt', passphrase => 'foobar123', ); C is the filename of the private key, C is the filename of the certificate. If the private key is encrypted, the C parameter will be used to decrypt it. =head2 Configuration File C supports the use of a simple configuration file. To use this feature, you need to install the L module. When starting up, C will look for C<$HOME/.net-epp-simple-rc>. This file is an ini-style configuration file. =head3 Default Options You can specify default options for all EPP servers using the C<[default]> section: [default] default=epp.nic.tld debug=1 =head3 Server Specific Options You can specify options for for specific EPP servers by giving each EPP server its own section: [epp.nic.tld] user=abc123 pass=foo2bar port=777 ssl=0 This means that when you write a script that uses C, you can do the following: # config file has a default server: my $epp = Net::EPP::Simple->new; # config file has connection options for this EPP server: my $epp = Net::EPP:Simple->new('host' => 'epp.nic.tld'); Any parameters provided to the constructor will override those in the config file. =cut sub new { my ($package, %params) = @_; $params{dom} = 1; my $load_config = (defined($params{load_config}) ? $params{load_config} : 1); $package->_load_config(\%params) if ($load_config); $params{port} = (defined($params{port}) && int($params{port}) > 0 ? $params{port} : 700); $params{ssl} = ($params{no_ssl} ? undef : 1); my $self = $package->SUPER::new(%params); $self->{user} = $params{user}; $self->{pass} = $params{pass}; $self->{debug} = (defined($params{debug}) ? int($params{debug}) : undef); $self->{timeout} = (defined($params{timeout}) && int($params{timeout}) > 0 ? $params{timeout} : 5); $self->{reconnect} = (defined($params{reconnect}) ? int($params{reconnect}) : 3); $self->{connected} = undef; $self->{authenticated} = undef; $self->{connect} = (exists($params{connect}) ? $params{connect} : 1); $self->{login} = (exists($params{login}) ? $params{login} : 1); $self->{key} = $params{key}; $self->{cert} = $params{cert}; $self->{passphrase} = $params{passphrase}; $self->{verify} = $params{verify}; $self->{ca_file} = $params{ca_file}; $self->{ca_path} = $params{ca_path}; $self->{ciphers} = $params{ciphers}; bless($self, $package); if ($self->{connect}) { return ($self->_connect($self->{login}) ? $self : undef); } else { return $self; } } sub _load_config { my ($package, $params_ref) = @_; eval 'use Config::Simple'; if (!$@) { # we have Config::Simple, so let's try to parse the RC file: my $rcfile = $ENV{'HOME'}.'/.net-epp-simple-rc'; if (-e $rcfile) { my $config = Config::Simple->new($rcfile); # if no host was defined in the constructor, use the default (if specified): if (!defined($params_ref->{'host'}) && $config->param('default.default')) { $params_ref->{'host'} = $config->param('default.default'); } # if no debug level was defined in the constructor, use the default (if specified): if (!defined($params_ref->{'debug'}) && $config->param('default.debug')) { $params_ref->{'debug'} = $config->param('default.debug'); } # grep through the file's values for settings for the selected host: my %vars = $config->vars; foreach my $key (grep { /^$params_ref->{'host'}\./ } keys(%vars)) { my $value = $vars{$key}; $key =~ s/^$params_ref->{'host'}\.//; $params_ref->{$key} = $value unless (defined($params_ref->{$key})); } } } } sub _connect { my ($self, $login) = @_; my %params; $params{SSL_cipher_list} = $self->{ciphers} if (defined($self->{ssl}) && defined($self->{ciphers})); if (defined($self->{key}) && defined($self->{cert}) && defined($self->{ssl})) { $self->debug('configuring client certificate parameters'); $params{SSL_key_file} = $self->{key}; $params{SSL_cert_file} = $self->{cert}; $params{SSL_passwd_cb} = sub { $self->{passphrase} }; } if (defined($self->{ssl}) && defined($self->{verify})) { $self->debug('configuring server verification'); $params{SSL_verify_mode} = 0x01; $params{SSL_ca_file} = $self->{ca_file}; $params{SSL_ca_path} = $self->{ca_path}; } $self->debug(sprintf('Attempting to connect to %s:%d', $self->{host}, $self->{port})); eval { $params{no_greeting} = 1; $self->connect(%params); }; if ($@ ne '') { chomp($@); $@ =~ s/ at .+ line .+$//; $self->debug($@); $Code = COMMAND_FAILED; $Error = $Message = "Error connecting: ".$@; return undef; } else { $self->debug('Connected OK, retrieving greeting frame'); $self->{greeting} = $self->get_frame; if (ref($self->{greeting}) ne 'Net::EPP::Frame::Response') { $Code = COMMAND_FAILED; $Error = $Message = "Error retrieving greeting: ".$@; return undef; } else { $self->debug('greeting frame retrieved OK'); } } $self->{connected} = 1; map { $self->debug('S: '.$_) } split(/\n/, $self->{greeting}->toString(1)); if ($login) { $self->debug('attempting login'); return $self->_login; } else { return 1; } } sub _login { my $self = shift; $self->debug(sprintf("Attempting to login as client ID '%s'", $self->{user})); my $response = $self->request( $self->_prepare_login_frame() ); if (!$response) { $Error = $Message = "Error getting response to login request: ".$Error; return undef; } else { $Code = $self->_get_response_code($response); $Message = $self->_get_message($response); $self->debug(sprintf('%04d: %s', $Code, $Message)); if ($Code > 1999) { $Error = "Error logging in (response code $Code)"; return undef; } else { $self->{authenticated} = 1; return 1; } } } sub _prepare_login_frame { my $self = shift; $self->debug('preparing login frame'); my $login = Net::EPP::Frame::Command::Login->new; $login->clID->appendText($self->{user}); $login->pw->appendText($self->{pass}); $login->version->appendText($self->{greeting}->getElementsByTagNameNS(EPP_XMLNS, 'version')->shift->firstChild->data); $login->lang->appendText($self->{greeting}->getElementsByTagNameNS(EPP_XMLNS, 'lang')->shift->firstChild->data); my $objects = $self->{greeting}->getElementsByTagNameNS(EPP_XMLNS, 'objURI'); while (my $object = $objects->shift) { my $el = $login->createElement('objURI'); $el->appendText($object->firstChild->data); $login->svcs->appendChild($el); } $objects = $self->{greeting}->getElementsByTagNameNS(EPP_XMLNS, 'extURI'); my $svcext; if ($objects->size) { $svcext = $login->createElement('svcExtension'); $login->svcs->appendChild($svcext); } while (my $object = $objects->shift) { my $el = $login->createElement('extURI'); $el->appendText($object->firstChild->data); $svcext->appendChild($el); } return $login; } =pod =head1 Availability Checks You can do a simple CcheckE> request for an object like so: my $result = $epp->check_domain($domain); my $result = $epp->check_host($host); my $result = $epp->check_contact($contact); Each of these methods has the same profile. They will return one of the following: =over =item * C in the case of an error (check C<$Net::EPP::Simple::Error> and C<$Net::EPP::Simple::Code>). =item * C<0> if the object is already provisioned. =item * C<1> if the object is available. =back =cut sub check_domain { my ($self, $domain) = @_; return $self->_check('domain', $domain); } sub check_host { my ($self, $host) = @_; return $self->_check('host', $host); } sub check_contact { my ($self, $contact) = @_; return $self->_check('contact', $contact); } sub _check { my ($self, $type, $identifier) = @_; my $frame; if ($type eq 'domain') { $frame = Net::EPP::Frame::Command::Check::Domain->new; $frame->addDomain($identifier); } elsif ($type eq 'contact') { $frame = Net::EPP::Frame::Command::Check::Contact->new; $frame->addContact($identifier); } elsif ($type eq 'host') { $frame = Net::EPP::Frame::Command::Check::Host->new; $frame->addHost($identifier); } else { $Error = "Unknown object type '$type'"; return undef; } my $response = $self->_request($frame); if (!$response) { return undef; } else { $Code = $self->_get_response_code($response); $Message = $self->_get_message($response); if ($Code > 1999) { $Error = $self->_get_error_message($response); return undef; } else { my $xmlns = (Net::EPP::Frame::ObjectSpec->spec($type))[1]; my $key; if ($type eq 'domain' || $type eq 'host') { $key = 'name'; } elsif ($type eq 'contact') { $key = 'id'; } return $response->getNode($xmlns, $key)->getAttribute('avail'); } } } =pod =head1 Retrieving Object Information You can retrieve information about an object by using one of the following: my $info = $epp->domain_info($domain, $authInfo, $follow); my $info = $epp->host_info($host); my $info = $epp->contact_info($contact, $authInfo); C will construct an CinfoE> frame and send it to the server, then parse the response into a simple hash ref. The layout of the hash ref depends on the object in question. If there is an error, these methods will return C, and you can then check C<$Net::EPP::Simple::Error> and C<$Net::EPP::Simple::Code>. If C<$authInfo> is defined, it will be sent to the server as per RFC 5731, Section 3.1.2 and RFC 5733, Section 3.1.2. If the supplied authInfo code is validated by the registry, additional information will appear in the response. If it is invalid, you should get an error. If the C<$follow> parameter is true, then C will also retrieve the relevant host and contact details for a domain: instead of returning an object name or ID for the domain's registrant, contact associations, DNS servers or subordinate hosts, the values will be replaced with the return value from the appropriate C or C command (unless there was an error, in which case the original object ID will be used instead). =cut sub domain_info { my ($self, $domain, $authInfo, $follow) = @_; my $result = $self->_info('domain', $domain, $authInfo); return $result if (ref($result) ne 'HASH' || !$follow); if (defined($result->{'ns'}) && ref($result->{'ns'}) eq 'ARRAY') { for (my $i = 0 ; $i < scalar(@{$result->{'ns'}}) ; $i++) { my $info = $self->host_info($result->{'ns'}->[$i]); $result->{'ns'}->[$i] = $info if (ref($info) eq 'HASH'); } } if (defined($result->{'hosts'}) && ref($result->{'hosts'}) eq 'ARRAY') { for (my $i = 0 ; $i < scalar(@{$result->{'hosts'}}) ; $i++) { my $info = $self->host_info($result->{'hosts'}->[$i]); $result->{'hosts'}->[$i] = $info if (ref($info) eq 'HASH'); } } my $info = $self->contact_info($result->{'registrant'}); $result->{'registrant'} = $info if (ref($info) eq 'HASH'); foreach my $type (keys(%{$result->{'contacts'}})) { my $info = $self->contact_info($result->{'contacts'}->{$type}); $result->{'contacts'}->{$type} = $info if (ref($info) eq 'HASH'); } return $result; } sub host_info { my ($self, $host) = @_; return $self->_info('host', $host); } sub contact_info { my ($self, $contact, $authInfo) = @_; return $self->_info('contact', $contact, $authInfo); } sub _info { my ($self, $type, $identifier, $authInfo) = @_; my $frame; if ($type eq 'domain') { $frame = Net::EPP::Frame::Command::Info::Domain->new; $frame->setDomain($identifier); } elsif ($type eq 'contact') { $frame = Net::EPP::Frame::Command::Info::Contact->new; $frame->setContact($identifier); } elsif ($type eq 'host') { $frame = Net::EPP::Frame::Command::Info::Host->new; $frame->setHost($identifier); } else { $Error = "Unknown object type '$type'"; return undef; } if (defined($authInfo) && $authInfo ne '') { $self->debug('adding authInfo element to request frame'); my $el = $frame->createElement((Net::EPP::Frame::ObjectSpec->spec($type))[0].':authInfo'); my $pw = $frame->createElement((Net::EPP::Frame::ObjectSpec->spec($type))[0].':pw'); $pw->appendChild($frame->createTextNode($authInfo)); $el->appendChild($pw); $frame->getNode((Net::EPP::Frame::ObjectSpec->spec($type))[1], 'info')->appendChild($el); } my $response = $self->_request($frame); if (!$response) { return undef; } else { $Code = $self->_get_response_code($response); $Message = $self->_get_message($response); if ($Code > 1999) { $Error = $self->_get_error_message($response); return undef; } else { return $self->parse_object_info($type, $response); } } } # An easy-to-subclass method for parsing object info sub parse_object_info { my ($self, $type, $response) = @_; my $infData = $response->getNode((Net::EPP::Frame::ObjectSpec->spec($type))[1], 'infData'); if ($type eq 'domain') { return $self->_domain_infData_to_hash($infData); } elsif ($type eq 'contact') { return $self->_contact_infData_to_hash($infData); } elsif ($type eq 'host') { return $self->_host_infData_to_hash($infData); } else { $Error = "Unknown object type '$type'"; return undef; } } sub _get_common_properties_from_infData { my ($self, $infData, @extra) = @_; my $hash = {}; my @default = qw(roid clID crID crDate upID upDate trDate); foreach my $name (@default, @extra) { my $els = $infData->getElementsByLocalName($name); $hash->{$name} = $els->shift->textContent if ($els->size > 0); } my $codes = $infData->getElementsByLocalName('status'); while (my $code = $codes->shift) { push(@{$hash->{status}}, $code->getAttribute('s')); } return $hash; } =pod =head2 Domain Information The hash ref returned by C will usually look something like this: $info = { 'contacts' => { 'admin' => 'contact-id' 'tech' => 'contact-id' 'billing' => 'contact-id' }, 'registrant' => 'contact-id', 'clID' => 'registrar-id', 'roid' => 'tld-12345', 'status' => [ 'ok' ], 'authInfo' => 'abc-12345', 'name' => 'example.tld', 'trDate' => '2011-01-18T11:08:03.0Z', 'ns' => [ 'ns0.example.com', 'ns1.example.com', ], 'crDate' => '2011-02-16T12:06:31.0Z', 'exDate' => '2011-02-16T12:06:31.0Z', 'crID' => 'registrar-id', 'upDate' => '2011-08-29T04:02:12.0Z', hosts => [ 'ns0.example.tld', 'ns1.example.tld', ], }; Members of the C hash ref may be strings or, if there are multiple associations of the same type, an anonymous array of strings. If the server uses the "hostAttr" model instead of "hostObj", then the C member will look like this: $info->{ns} = [ { name => 'ns0.example.com', addrs => [ type => 'v4', addr => '10.0.0.1', ], }, { name => 'ns1.example.com', addrs => [ type => 'v4', addr => '10.0.0.2', ], }, ]; Note that there may be multiple members in the C section and that the C attribute is optional. =cut sub _domain_infData_to_hash { my ($self, $infData) = @_; my $hash = $self->_get_common_properties_from_infData($infData, 'registrant', 'name', 'exDate'); my $contacts = $infData->getElementsByLocalName('contact'); while (my $contact = $contacts->shift) { my $type = $contact->getAttribute('type'); my $id = $contact->textContent; if (ref($hash->{contacts}->{$type}) eq 'STRING') { $hash->{contacts}->{$type} = [ $hash->{contacts}->{$type}, $id ]; } elsif (ref($hash->{contacts}->{$type}) eq 'ARRAY') { push(@{$hash->{contacts}->{$type}}, $id); } else { $hash->{contacts}->{$type} = $id; } } my $ns = $infData->getElementsByLocalName('ns'); if ($ns->size == 1) { my $el = $ns->shift; my $hostObjs = $el->getElementsByLocalName('hostObj'); while (my $hostObj = $hostObjs->shift) { push(@{$hash->{ns}}, $hostObj->textContent); } my $hostAttrs = $el->getElementsByLocalName('hostAttr'); while (my $hostAttr = $hostAttrs->shift) { my $host = {}; $host->{name} = $hostAttr->getElementsByLocalName('hostName')->shift->textContent; my $addrs = $hostAttr->getElementsByLocalName('hostAddr'); while (my $addr = $addrs->shift) { push(@{$host->{addrs}}, { version => $addr->getAttribute('ip'), addr => $addr->textContent }); } push(@{$hash->{ns}}, $host); } } my $hosts = $infData->getElementsByLocalName('host'); while (my $host = $hosts->shift) { push(@{$hash->{hosts}}, $host->textContent); } my $auths = $infData->getElementsByLocalName('authInfo'); if ($auths->size == 1) { my $authInfo = $auths->shift; my $pw = $authInfo->getElementsByLocalName('pw'); $hash->{authInfo} = $pw->shift->textContent if ($pw->size == 1); } return $hash; } =pod =head2 Host Information The hash ref returned by C will usually look something like this: $info = { 'crDate' => '2011-09-17T15:38:56.0Z', 'clID' => 'registrar-id', 'crID' => 'registrar-id', 'roid' => 'tld-12345', 'status' => [ 'linked', 'serverDeleteProhibited', ], 'name' => 'ns0.example.tld', 'addrs' => [ { 'version' => 'v4', 'addr' => '10.0.0.1' } ] }; Note that hosts may have multiple addresses, and that C is optional. =cut sub _host_infData_to_hash { my ($self, $infData) = @_; my $hash = $self->_get_common_properties_from_infData($infData, 'name'); my $addrs = $infData->getElementsByLocalName('addr'); while (my $addr = $addrs->shift) { push(@{$hash->{addrs}}, { version => $addr->getAttribute('ip'), addr => $addr->textContent }); } return $hash; } =pod =head2 Contact Information The hash ref returned by C will usually look something like this: $VAR1 = { 'id' => 'contact-id', 'postalInfo' => { 'int' => { 'name' => 'John Doe', 'org' => 'Example Inc.', 'addr' => { 'street' => [ '123 Example Dr.' 'Suite 100' ], 'city' => 'Dulles', 'sp' => 'VA', 'pc' => '20116-6503' 'cc' => 'US', } } }, 'clID' => 'registrar-id', 'roid' => 'CNIC-HA321983', 'status' => [ 'linked', 'serverDeleteProhibited' ], 'voice' => '+1.7035555555x1234', 'fax' => '+1.7035555556', 'email' => 'jdoe@example.com', 'crDate' => '2011-09-23T03:51:29.0Z', 'upDate' => '1999-11-30T00:00:00.0Z' }; There may be up to two members of the C hash, corresponding to the C and C internationalised and localised types. =cut sub _contact_infData_to_hash { my ($self, $infData) = @_; my $hash = $self->_get_common_properties_from_infData($infData, 'email', 'id'); # remove this as it gets in the way: my $els = $infData->getElementsByLocalName('disclose'); if ($els->size > 0) { while (my $el = $els->shift) { $el->parentNode->removeChild($el); } } foreach my $name ('voice', 'fax') { my $els = $infData->getElementsByLocalName($name); if (defined($els) && $els->size == 1) { my $el = $els->shift; if (defined($el)) { $hash->{$name} = $el->textContent; $hash->{$name} .= 'x'.$el->getAttribute('x') if (defined($el->getAttribute('x')) && $el->getAttribute('x') ne ''); } } } my $postalInfo = $infData->getElementsByLocalName('postalInfo'); while (my $info = $postalInfo->shift) { my $ref = {}; foreach my $name (qw(name org)) { my $els = $info->getElementsByLocalName($name); $ref->{$name} = $els->shift->textContent if ($els->size == 1); } my $addrs = $info->getElementsByLocalName('addr'); if ($addrs->size == 1) { my $addr = $addrs->shift; foreach my $child ($addr->childNodes) { if ($child->localName eq 'street') { push(@{$ref->{addr}->{$child->localName}}, $child->textContent); } else { $ref->{addr}->{$child->localName} = $child->textContent; } } } $hash->{postalInfo}->{$info->getAttribute('type')} = $ref; } my $auths = $infData->getElementsByLocalName('authInfo'); if ($auths->size == 1) { my $authInfo = $auths->shift; my $pw = $authInfo->getElementsByLocalName('pw'); $hash->{authInfo} = $pw->shift->textContent if ($pw->size == 1); } return $hash; } =pod =head1 Object Transfers The EPP CtransferE> command suppots five different operations: query, request, cancel, approve, and reject. C makes these available using the following methods: # For domain objects: $epp->domain_transfer_query($domain); $epp->domain_transfer_cancel($domain); $epp->domain_transfer_request($domain, $authInfo, $period); $epp->domain_transfer_approve($domain); $epp->domain_transfer_reject($domain); # For contact objects: $epp->contact_transfer_query($contact); $epp->contact_transfer_cancel($contact); $epp->contact_transfer_request($contact, $authInfo); $epp->contact_transfer_approve($contact); $epp->contact_transfer_reject($contact); Most of these methods will just set the value of C<$Net::EPP::Simple::Code> and return either true or false. However, the C, C, C and C methods will return a hash ref that looks like this: my $trnData = { 'name' => 'example.tld', 'reID' => 'losing-registrar', 'acDate' => '2011-12-04T12:24:53.0Z', 'acID' => 'gaining-registrar', 'reDate' => '2011-11-29T12:24:53.0Z', 'trStatus' => 'pending' }; =cut sub _transfer_request { my ($self, $op, $type, $identifier, $authInfo, $period) = @_; my $class = sprintf('Net::EPP::Frame::Command::Transfer::%s', ucfirst(lc($type))); my $frame; eval("\$frame = $class->new"); if ($@ || ref($frame) ne $class) { $Error = "Error building request frame: $@"; $Code = COMMAND_FAILED; return undef; } else { $frame->setOp($op); if ($type eq 'domain') { $frame->setDomain($identifier); } elsif ($type eq 'contact') { $frame->setContact($identifier); } if ($op eq 'request' || $op eq 'query') { $frame->setAuthInfo($authInfo) if ($authInfo ne ''); } $frame->setPeriod(int($period)) if ($op eq 'request'); } my $response = $self->_request($frame); if (!$response) { return undef; } else { $Code = $self->_get_response_code($response); $Message = $self->_get_message($response); if ($Code > 1999) { $Error = $response->msg; return undef; } elsif ($op eq 'query' || $op eq 'request') { my $trnData = $response->getElementsByLocalName('trnData')->shift; my $hash = {}; foreach my $child ($trnData->childNodes) { $hash->{$child->localName} = $child->textContent; } return $hash; } else { return 1; } } } sub domain_transfer_query { return $_[0]->_transfer_request('query', 'domain', $_[1]); } sub domain_transfer_cancel { return $_[0]->_transfer_request('cancel', 'domain', $_[1]); } sub domain_transfer_request { return $_[0]->_transfer_request('request', 'domain', $_[1], $_[2], $_[3]); } sub domain_transfer_approve { return $_[0]->_transfer_request('approve', 'domain', $_[1]); } sub domain_transfer_reject { return $_[0]->_transfer_request('reject', 'domain', $_[1]); } sub contact_transfer_query { return $_[0]->_transfer_request('query', 'contact', $_[1]); } sub contact_transfer_cancel { return $_[0]->_transfer_request('cancel', 'contact', $_[1]); } sub contact_transfer_request { return $_[0]->_transfer_request('request', 'contact', $_[1], $_[2]); } sub contact_transfer_approve { return $_[0]->_transfer_request('approve', 'contact', $_[1]); } sub contact_transfer_reject { return $_[0]->_transfer_request('reject', 'contact', $_[1]); } =pod =head1 Creating Objects The following methods can be used to create a new object at the server: $epp->create_domain($domain); $epp->create_host($host); $epp->create_contact($contact); The argument for these methods is a hash ref of the same format as that returned by the info methods above. As a result, cloning an existing object is as simple as the following: my $info = $epp->contact_info($contact); # set a new contact ID to avoid clashing with the existing object $info->{id} = $new_contact; # randomize authInfo: $info->{authInfo} = $random_string; $epp->create_contact($info); C will ignore object properties that it does not recognise, and those properties (such as server-managed status codes) that clients are not permitted to set. =head2 Creating New Domains When creating a new domain object, you may also specify a C key, like so: my $domain = { 'name' => 'example.tld', 'period' => 2, 'registrant' => 'contact-id', 'contacts' => { 'tech' => 'contact-id', 'admin' => 'contact-id', 'billing' => 'contact-id', }, 'status' => [ 'clientTransferProhibited', ], 'ns' => { 'ns0.example.com', 'ns1.example.com', }, }; $epp->create_domain($domain); The C key is assumed to be in years rather than months. C assumes the registry uses the host object model rather than the host attribute model. =cut sub create_domain { my ($self, $domain) = @_; return $self->_get_response_result( $self->_request( $self->_prepare_create_domain_frame($domain) ) ); } sub _prepare_create_domain_frame { my ($self, $domain) = @_; my $frame = Net::EPP::Frame::Command::Create::Domain->new; $frame->setDomain($domain->{'name'}); $frame->setPeriod($domain->{'period'}); $frame->setNS(@{$domain->{'ns'}}) if $domain->{'ns'} and @{$domain->{'ns'}}; $frame->setRegistrant($domain->{'registrant'}); $frame->setContacts($domain->{'contacts'}); $frame->setAuthInfo($domain->{authInfo}) if ($domain->{authInfo} ne ''); return $frame; } =head2 Creating Hosts my $host = { name => 'ns1.example.tld', addrs => [ { ip => '123.45.67.89', version => 'v4' }, { ip => '98.76.54.32', version => 'v4' }, ], }; $epp->create_host($host); =cut sub create_host { my ($self, $host) = @_; return $self->_get_response_result( $self->_request( $self->_prepare_create_host_frame($host) ) ); } sub _prepare_create_host_frame { my ($self, $host) = @_; my $frame = Net::EPP::Frame::Command::Create::Host->new; $frame->setHost($host->{name}); $frame->setAddr(@{$host->{addrs}}); return $frame; } sub create_contact { my ($self, $contact) = @_; return $self->_get_response_result( $self->_request( $self->_prepare_create_contact_frame($contact) ) ); } sub _prepare_create_contact_frame { my ($self, $contact) = @_; my $frame = Net::EPP::Frame::Command::Create::Contact->new; $frame->setContact($contact->{id}); if (ref($contact->{postalInfo}) eq 'HASH') { foreach my $type (keys(%{$contact->{postalInfo}})) { $frame->addPostalInfo( $type, $contact->{postalInfo}->{$type}->{name}, $contact->{postalInfo}->{$type}->{org}, $contact->{postalInfo}->{$type}->{addr} ); } } $frame->setVoice($contact->{voice}) if ($contact->{voice} ne ''); $frame->setFax($contact->{fax}) if ($contact->{fax} ne ''); $frame->setEmail($contact->{email}); $frame->setAuthInfo($contact->{authInfo}) if ($contact->{authInfo} ne ''); if (ref($contact->{status}) eq 'ARRAY') { foreach my $status (grep { /^client/ } @{$contact->{status}}) { $frame->appendStatus($status); } } return $frame; } # Process response code and return result sub _get_response_result { my ($self, $response) = @_; return undef if !$response; # If there was a response... $Code = $self->_get_response_code($response); $Message = $self->_get_message($response); if ($Code > 1999) { $Error = $response->msg; return undef; } return 1; } =head1 Updating Objects The following methods can be used to update an object at the server: $epp->update_domain($domain); $epp->update_host($host); $epp->update_contact($contact); Each of these methods has the same profile. They will return one of the following: =over =item * undef in the case of an error (check C<$Net::EPP::Simple::Error> and C<$Net::EPP::Simple::Code>). =item * 1 if the update request was accepted. =back You may wish to check the value of $Net::EPP::Simple::Code to determine whether the response code was 1000 (OK) or 1001 (action pending). =cut =head2 Updating Domains Use update_domain() method to update domains' data. The update info parameter may look like: $update_info = { name => $domain, chg => { registrant => $new_registrant_id, authInfo => $new_domain_password, }, add => { # DNS info with "hostObj" or "hostAttr" model, see create_domain() ns => [ ns1.example.com ns2.example.com ], contacts => { tech => 'contact-id', billing => 'contact-id', admin => 'contact-id', }, # Status info, simple form: status => [ qw/ clientUpdateProhibited clientHold / ], # Status info may be in more detailed form: # status => { # clientUpdateProbhibited => 'Avoid accidental change', # clientHold => 'This domain is not delegated', # }, }, rem => { ns => [ ... ], contacts => { tech => 'old_tech_id', billing => 'old_billing_id', admin => 'old_admin_id', }, status => [ qw/ clientTransferProhibited ... / ], }, } All fields except 'name' in $update_info hash are optional. =cut sub update_domain { my ($self, $domain) = @_; return $self->_update('domain', $domain); } =head2 Updating Contacts Use update_contact() method to update contact's data. The $update_info for contacts may look like this: $update_info = { id => $contact_id, add => { status => [ qw/ clientDeleteProhibited / ], # OR # status => { # clientDeleteProhibited => 'Avoid accidental removal', # }, }, rem => { status => [ qw/ clientUpdateProhibited / ], }, chg => { postalInfo => { int => { name => 'John Doe', org => 'Example Inc.', addr => { street => [ '123 Example Dr.' 'Suite 100' ], city => 'Dulles', sp => 'VA', pc => '20116-6503' cc => 'US', }, }, }, voice => '+1.7035555555x1234', fax => '+1.7035555556', email => 'jdoe@example.com', authInfo => 'new-contact-password', }, } All fields except 'id' in $update_info hash are optional. =cut sub update_contact { my ($self, $contact) = @_; return $self->_update('contact', $contact); } =head2 Updating Hosts Use update_host() method to update EPP hosts. The $update_info for hosts may look like this: $update_info = { name => 'ns1.example.com', add => { status => [ qw/ clientDeleteProhibited / ], # OR # status => { # clientDeleteProhibited => 'Avoid accidental removal', # }, addrs => [ { ip => '123.45.67.89', version => 'v4' }, { ip => '98.76.54.32', version => 'v4' }, ], }, rem => { status => [ qw/ clientUpdateProhibited / ], addrs => [ { ip => '1.2.3.4', version => 'v4' }, { ip => '5.6.7.8', version => 'v4' }, ], }, chg => { name => 'ns2.example.com', }, } All fields except first 'name' in $update_info hash are optional. =cut sub update_host { my ($self, $host) = @_; return $self->_update('host', $host); } # Update domain/contact/host information sub _update { my ($self, $type, $info) = @_; my %frame_generator = ( 'domain' => \&_generate_update_domain_frame, 'contact' => \&_generate_update_contact_frame, 'host' => \&_generate_update_host_frame, ); if ( !exists $frame_generator{$type} ) { $Error = "Unknown object type: '$type'"; return undef; } my $generator = $frame_generator{$type}; my $frame = $self->$generator($info); return $self->_get_response_result( $self->request($frame) ); } sub _generate_update_domain_frame { my ($self, $info) = @_; my $frame = Net::EPP::Frame::Command::Update::Domain->new; $frame->setDomain( $info->{name} ); # 'add' element if ( exists $info->{add} && ref $info->{add} eq 'HASH' ) { my $add = $info->{add}; # Add DNS if ( exists $add->{ns} && ref $add->{ns} eq 'ARRAY' ) { $frame->addNS( @{ $add->{ns} } ); } # Add contacts if ( exists $add->{contacts} && ref $add->{contacts} eq 'HASH' ) { my $contacts = $add->{contacts}; foreach my $type ( keys %{ $contacts } ) { $frame->addContact( $type, $contacts->{$type} ); } } # Add status info if ( exists $add->{status} && ref $add->{status} ) { if ( ref $add->{status} eq 'HASH' ) { while ( my ($type, $info) = each %{ $add->{status} } ) { $frame->addStatus($type, $info); } } elsif ( ref $add->{status} eq 'ARRAY' ) { $frame->addStatus($_) for @{ $add->{status} }; } } } # 'rem' element if ( exists $info->{rem} && ref $info->{rem} eq 'HASH' ) { my $rem = $info->{rem}; # DNS if ( exists $rem->{ns} && ref $rem->{ns} eq 'ARRAY' ) { $frame->remNS( @{ $rem->{ns} } ); } # Contacts if ( exists $rem->{contacts} && ref $rem->{contacts} eq 'HASH' ) { my $contacts = $rem->{contacts}; foreach my $type ( keys %{ $contacts } ) { $frame->remContact( $type, $contacts->{$type} ); } } # Status info if ( exists $rem->{status} && ref $rem->{status} eq 'ARRAY' ) { $frame->remStatus($_) for @{ $rem->{status} }; } } # 'chg' element if ( exists $info->{chg} && ref $info->{chg} eq 'HASH' ) { my $chg = $info->{chg}; if ( defined $chg->{registrant} ) { $frame->chgRegistrant( $chg->{registrant} ); } if ( defined $chg->{authInfo} ) { $frame->chgAuthInfo( $chg->{authInfo} ); } } return $frame; } sub _generate_update_contact_frame { my ($self, $info) = @_; my $frame = Net::EPP::Frame::Command::Update::Contact->new; $frame->setContact( $info->{id} ); # Add if ( exists $info->{add} && ref $info->{add} eq 'HASH' ) { my $add = $info->{add}; if ( exists $add->{status} && ref $add->{status} ) { if ( ref $add->{status} eq 'HASH' ) { while ( my ($type, $info) = each %{ $add->{status} } ) { $frame->addStatus($type, $info); } } elsif ( ref $add->{status} eq 'ARRAY' ) { $frame->addStatus($_) for @{ $add->{status} }; } } } # Remove if ( exists $info->{rem} && ref $info->{rem} eq 'HASH' ) { my $rem = $info->{rem}; if ( exists $rem->{status} && ref $rem->{status} eq 'ARRAY' ) { $frame->remStatus($_) for @{ $rem->{status} }; } } # Change if ( exists $info->{chg} && ref $info->{chg} eq 'HASH' ) { my $chg = $info->{chg}; # Change postal info if ( ref $chg->{postalInfo} eq 'HASH' ) { foreach my $type ( keys %{ $chg->{postalInfo} } ) { $frame->chgPostalInfo( $type, $chg->{postalInfo}->{$type}->{name}, $chg->{postalInfo}->{$type}->{org}, $chg->{postalInfo}->{$type}->{addr} ); } } # Change voice / fax / email for my $contact_type ( qw/ voice fax email / ) { if ( defined $chg->{$contact_type} ) { my $el = $frame->createElement("contact:$contact_type"); $el->appendText( $chg->{$contact_type} ); $frame->chg->appendChild($el); } } # Change auth info if ( $chg->{authInfo} ) { $frame->chgAuthInfo( $chg->{authInfo} ); } # 'disclose' option is still unimplemented } return $frame; } sub _generate_update_host_frame { my ($self, $info) = @_; my $frame = Net::EPP::Frame::Command::Update::Host->new; $frame->setHost($info->{name}); if ( exists $info->{add} && ref $info->{add} eq 'HASH' ) { my $add = $info->{add}; # Process addresses if ( exists $add->{addrs} && ref $add->{addrs} eq 'ARRAY' ) { $frame->addAddr( @{ $add->{addrs} } ); } # Process statuses if ( exists $add->{status} && ref $add->{status} ) { if ( ref $add->{status} eq 'HASH' ) { while ( my ($type, $info) = each %{ $add->{status} } ) { $frame->addStatus($type, $info); } } elsif ( ref $add->{status} eq 'ARRAY' ) { $frame->addStatus($_) for @{ $add->{status} }; } } } if ( exists $info->{rem} && ref $info->{rem} eq 'HASH' ) { my $rem = $info->{rem}; # Process addresses if ( exists $rem->{addrs} && ref $rem->{addrs} eq 'ARRAY' ) { $frame->remAddr( @{ $rem->{addrs} } ); } # Process statuses if ( exists $rem->{status} && ref $rem->{status} ) { if ( ref $rem->{status} eq 'HASH' ) { while ( my ($type, $info) = each %{ $rem->{status} } ) { $frame->remStatus($type, $info); } } elsif ( ref $rem->{status} eq 'ARRAY' ) { $frame->remStatus($_) for @{ $rem->{status} }; } } } if ( exists $info->{chg} && ref $info->{chg} eq 'HASH' ) { if ( $info->{chg}->{name} ) { $frame->chgName( $info->{chg}->{name} ); } } return $frame; } =pod =head1 Deleting Objects The following methods can be used to delete an object at the server: $epp->delete_domain($domain); $epp->delete_host($host); $epp->delete_contact($contact); Each of these methods has the same profile. They will return one of the following: =over =item * undef in the case of an error (check C<$Net::EPP::Simple::Error> and C<$Net::EPP::Simple::Code>). =item * 1 if the deletion request was accepted. =back You may wish to check the value of $Net::EPP::Simple::Code to determine whether the response code was 1000 (OK) or 1001 (action pending). =cut sub delete_domain { my ($self, $domain) = @_; return $self->_delete('domain', $domain); } sub delete_host { my ($self, $host) = @_; return $self->_delete('host', $host); } sub delete_contact { my ($self, $contact) = @_; return $self->_delete('contact', $contact); } sub _delete { my ($self, $type, $identifier) = @_; my $frame; if ($type eq 'domain') { $frame = Net::EPP::Frame::Command::Delete::Domain->new; $frame->setDomain($identifier); } elsif ($type eq 'contact') { $frame = Net::EPP::Frame::Command::Delete::Contact->new; $frame->setContact($identifier); } elsif ($type eq 'host') { $frame = Net::EPP::Frame::Command::Delete::Host->new; $frame->setHost($identifier); } else { $Error = "Unknown object type '$type'"; return undef; } my $response = $self->_request($frame); if (!$response) { return undef; } else { $Code = $self->_get_response_code($response); $Message = $self->_get_message($response); if ($Code > 1999) { $Error = $self->_get_error_message($response); return undef; } else { return 1; } } } =head1 Domain Renewal You can extend the validity period of the domain object by issuing a renew_domain() command. my $result = $epp->renew_domain({ name => 'example.com', cur_exp_date => '2011-02-05', # current expiration date period => 2, # prolongation period in years }); Return value is C<1> on success and C on error. In the case of error C<$Net::EPP::Simple::Error> contains the appropriate error message. =cut sub renew_domain { my ($self, $info) = @_; return $self->_get_response_result( $self->request( $self->_generate_renew_domain_frame($info) ) ); } sub _generate_renew_domain_frame { my ($self, $info) = @_; my $frame = Net::EPP::Frame::Command::Renew::Domain->new; $frame->setDomain( $info->{name} ); $frame->setCurExpDate( $info->{cur_exp_date} ); $frame->setPeriod( $info->{period} ) if $info->{period}; return $frame; } =pod =head1 Miscellaneous Methods =cut sub error { $Error } sub code { $Code } sub message { $Message } =pod my $greeting = $epp->greeting; Returns the a C object representing the greeting returned by the server. =cut sub greeting { $_[0]->{greeting} } =pod $epp->ping; Checks that the connection is up by sending a ChelloE> to the server. Returns false if no response is received. =cut sub ping { my $self = shift; my $hello = Net::EPP::Frame::Hello->new; my $response = $self->request($hello); return (UNIVERSAL::isa($response, 'XML::LibXML::Document') ? 1 : undef); } sub _request { my ($self, $frame) = @_; if ($self->{reconnect} > 0) { $self->debug("reconnect is $self->{reconnect}, pinging"); if (!$self->ping) { $self->debug('connection seems dead, trying to reconnect'); for (1..$self->{reconnect}) { $self->debug("attempt #$_"); if ($self->_connect) { $self->debug("attempt #$_ succeeded"); return $self->request($frame); } else { $self->debug("attempt #$_ failed, sleeping"); sleep($self->{timeout}); } } $self->debug('unable to reconnect!'); return undef; } else { $self->debug("Connection is up, sending frame"); return $self->request($frame); } } else { return $self->request($frame); } } =pod =head1 Overridden Methods From C C overrides some methods inherited from C. These are described below: =head2 The C Method C overrides this method so it can automatically populate the CclTRIDE> element with a unique string. It then passes the frame back up to C. =cut sub request { my ($self, $frame) = @_; # Make sure we start with blank variables $Code = undef; $Error = ''; $Message = ''; $frame->clTRID->appendText(sha1_hex(ref($self).time().$$)) if (UNIVERSAL::isa($frame, 'Net::EPP::Frame::Command')); $self->debug(sprintf('sending a %s to the server', ref($frame))); if (UNIVERSAL::isa($frame, 'XML::LibXML::Document')) { map { $self->debug('C: '.$_) } split(/\n/, $frame->toString(1)); } else { map { $self->debug('C: '.$_) } split(/\n/, $frame); } my $response = $self->SUPER::request($frame); map { $self->debug('S: '.$_) } split(/\n/, $response->toString(1)) if (UNIVERSAL::isa($response, 'XML::LibXML::Document')); return $response; } =pod =head2 The C Method C overrides this method so it can catch timeouts and network errors. If such an error occurs it will return C. =cut sub get_frame { my $self = shift; my $frame; $self->debug(sprintf('reading frame, waiting %d seconds before timeout', $self->{timeout})); eval { local $SIG{ALRM} = sub { die 'timeout' }; $self->debug('setting timeout alarm for receiving frame'); alarm($self->{timeout}); $frame = $self->SUPER::get_frame(); $self->debug('unsetting timeout alarm after successful receive'); alarm(0); }; if ($@ ne '') { chomp($@); $@ =~ s/ at .+ line .+$//; $self->debug("unsetting timeout alarm after alarm was triggered ($@)"); alarm(0); $Code = COMMAND_FAILED; if ($@ =~ /^timeout/) { $Error = $Message = "get_frame() timed out after $self->{timeout} seconds"; } else { $Error = $Message = "get_frame() received an error: $@"; } return undef; } else { return bless($frame, 'Net::EPP::Frame::Response'); } } # Get details error description including code, message and reason sub _get_error_message { my ($self, $doc) = @_; my $code = $self->_get_response_code($doc); my $error = "Error $code"; my $message = $self->_get_message($doc); if ( $message ) { $error .= ": $message"; } my $reason = $self->_get_reason($doc); if ( $reason ) { $error .= " ($reason)"; } return $error; } sub _get_response_code { my ($self, $doc) = @_; my $els = $doc->getElementsByTagNameNS(EPP_XMLNS, 'result'); if (defined($els)) { my $el = $els->shift; if (defined($el)) { return $el->getAttribute('code'); } } return 2400; } sub _get_message { my ($self, $doc) = @_; my $msgs = $doc->getElementsByTagNameNS(EPP_XMLNS, 'msg'); if (defined($msgs)) { my $msg = $msgs->shift; if (defined($msg)) { return $msg->textContent; } } return ''; } sub _get_reason { my ($self, $doc) = @_; my $reasons = $doc->getElementsByTagNameNS(EPP_XMLNS, 'reason'); if (defined($reasons)) { my $reason = $reasons->shift; if (defined($reason)) { return $reason->textContent; } } return ''; } sub logout { my $self = shift; if (defined($self->{authenticated}) && 1 == $self->{authenticated}) { $self->debug('logging out'); my $response = $self->request(Net::EPP::Frame::Command::Logout->new); return undef if (!$response); } $self->debug('disconnecting from server'); $self->disconnect; $self->{connected} = 0; return 1; } sub DESTROY { my $self = shift; $self->debug('DESTROY() method called'); $self->logout if (defined($self->{connected}) && 1 == $self->{connected}); } sub debug { my ($self, $msg) = @_; my $log = sprintf("%s (%d): %s", scalar(localtime()), $$, $msg); push(@Log, $log); print STDERR $log."\n" if (defined($self->{debug}) && $self->{debug} == 1); } =pod =head1 Package Variables =head2 $Net::EPP::Simple::Error This variable contains an english text message explaining the last error to occur. This is may be due to invalid parameters being passed to a method, a network error, or an error response being returned by the server. =head2 $Net::EPP::Simple::Message This variable contains the contains the text content of the CmsgE> element in the response frame for the last transaction. =head2 $Net::EPP::Simple::Code This variable contains the integer result code returned by the server for the last transaction. A successful transaction will always return an error code of 1999 or lower, for an unsuccessful transaction it will be 2011 or more. If there is an internal client error (due to invalid parameters being passed to a method, or a network error) then this will be set to 2400 (C). See L for more information about thes codes. =head1 Author CentralNic Ltd (L). =head1 Copyright This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =item * L =item * L =item * RFCs 5730 and RFC 4934, available from L. =item * The CentralNic EPP site at L. =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/000755 000765 000024 00000000000 11745236100 017411 5ustar00gavinstaff000000 000000 Net-EPP-0.19/lib/Net/EPP/Frame/Command.pm000755 000765 000024 00000006543 11745236005 017766 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Command.pm,v 1.4 2011/12/03 11:44:51 gavin Exp $ package Net::EPP::Frame::Command; use Net::EPP::Frame::Command::Check; use Net::EPP::Frame::Command::Create; use Net::EPP::Frame::Command::Delete; use Net::EPP::Frame::Command::Info; use Net::EPP::Frame::Command::Login; use Net::EPP::Frame::Command::Logout; use Net::EPP::Frame::Command::Poll; use Net::EPP::Frame::Command::Renew; use Net::EPP::Frame::Command::Transfer; use Net::EPP::Frame::Command::Update; use base qw(Net::EPP::Frame); use strict; =pod =head1 NAME Net::EPP::Frame::Command - an instance of L for client commands =head1 DESCRIPTION This module is a base class for the Net::EPP::Frame::* subclasses, you should never need to access it directly. =head1 OBJECT HIERARCHY L +----L +----L +----L =cut sub new { my $package = shift; my $self = $package->SUPER::new('command'); return bless($self, $package); } sub addObject() { my ($self, $object, $ns, $schema) = @_; my $obj = $self->createElement($self->getCommandType); $obj->setNamespace($ns, $object); $self->getNode($self->getCommandType)->addChild($obj); $obj->setAttributeNS($Net::EPP::Frame::SCHEMA_URI, 'schemaLocation', $schema); return $obj; } sub _addExtraElements { my $self = shift; $self->command->addChild($self->createElement($self->getCommandType)) if ($self->getCommandType ne ''); $self->command->addChild($self->createElement('clTRID')); $self->_addCommandElements; return 1; } sub _addCommandElements { } =pod =head1 METHODS my $object = $frame->addObject(@spec); This method creates and returns a new element corresponding to the data in C<@spec>, and appends it to the "command" element (as returned by the C method below). The L module can be used to quickly retrieve EPP object specifications. my $type = $frame->getCommandType; This method returns a scalar containing the command type (eg L<'create'>). my $type = $frame->getCommandNode; This method returns the L object corresponding to the command in question, eg the CcreateE> element (for a L object). It is within this element that EPP objects are placed. my $node = $frame->command; This method returns the L object corresponding to the CcommandE> element. my $node = $frame->clTRID; This method returns the L object corresponding to the CclTRIDE> element. =cut sub getCommandType { my $self = shift; my $type = ref($self); my $me = __PACKAGE__; $type =~ s/^$me\:+//; $type =~ s/\:{2}.+//; return lc($type); } sub getCommandNode { my $self = shift; return $self->getNode($self->getCommandType); } sub command { $_[0]->getNode('command') } sub clTRID { $_[0]->getNode('clTRID') } =pod =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Greeting.pm000755 000765 000024 00000004722 11745236005 020151 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Greeting.pm,v 1.3 2011/12/03 11:44:51 gavin Exp $ package Net::EPP::Frame::Greeting; use base qw(Net::EPP::Frame); =pod =head1 NAME Net::EPP::Frame::Greeting - an instance of L for server greetings =head1 DESCRIPTION This module is a subclass of L that represents EPP server greetings. According to the EPP RFC, the server must transmit an EPP greeting frame to the client upon connection, and in response to an EPP ChelloE> command. The CgreetingE> frame provides information about the server, including the server time, access control rules, and a list of the object types that are provisioned by the server. =head1 OBJECT HIERARCHY L +----L +----L +----L =cut sub _addExtraElements { my $self = shift; $self->greeting->addChild($self->createElement('svID')); $self->greeting->addChild($self->createElement('svDate')); $self->greeting->addChild($self->createElement('svcMenu')); $self->greeting->addChild($self->createElement('dcp')); return 1; } =pod =head1 METHODS my $node = $frame->greeting; This method returns the L object corresponding to the CgreetingE> element. my $node = $frame->svID; This method returns the L object corresponding to the CsvIDE> element. my $node = $frame->svDate; This method returns the L object corresponding to the CsvDateE> element. my $node = $frame->svcMenu; This method returns the L object corresponding to the CsvcMenuE> element. my $node = $frame->dcp; This method returns the L object corresponding to the CdcpE> element. =cut sub greeting { $_[0]->getNode('greeting') } sub svID { $_[0]->getNode('svID') } sub svDate { $_[0]->getNode('svDate') } sub svcMenu { $_[0]->getNode('svcMenu') } sub dcp { $_[0]->getNode('dcp') } =pod =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Hello.pm000755 000765 000024 00000002715 11745236005 017450 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Hello.pm,v 1.4 2011/12/03 11:44:51 gavin Exp $ package Net::EPP::Frame::Hello; use base qw(Net::EPP::Frame); =pod =head1 NAME Net::EPP::Frame::Hello - an instance of L for client greetings =head1 DESCRIPTION This module is a subclass of L that represents EPP client greetings. Clients can send a greeting to an EPP server at any time during a session. According to the EPP RFC, the server must transmit an EPP greeting frame to the client upon connection, and in response to an EPP ChelloE> command. The CgreetingE> frame provides information about the server, including the server time, access control rules, and a list of the object types that are provisioned by the server. =head1 OBJECT HIERARCHY L +----L +----L +----L =head1 METHODS This module does not define any methods in addition to those it inherits from its ancestors. =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/ObjectSpec.pm000755 000765 000024 00000006174 11115770273 020432 0ustar00gavinstaff000000 000000 #! $Id: ObjectSpec.pm,v 1.2 2007/12/03 11:44:51 gavin Exp $ package Net::EPP::Frame::ObjectSpec; use vars qw($SPEC); use strict; our $SPEC = { 'domain' => [ 'urn:ietf:params:xml:ns:domain-1.0', 'urn:ietf:params:xml:ns:domain-1.0 domain-1.0.xsd' ], 'contact' => [ 'urn:ietf:params:xml:ns:contact-1.0', 'urn:ietf:params:xml:ns:contact-1.0 contact-1.0.xsd' ], 'host' => [ 'urn:ietf:params:xml:ns:host-1.0', 'urn:ietf:params:xml:ns:host-1.0 host-1.0.xsd' ], 'secDNS' => [ 'urn:ietf:params:xml:ns:secDNS-1.0', 'urn:ietf:params:xml:ns:secDNS-1.0 secDNS-1.0.xsd' ], }; sub spec { my $type = $_[1]; return (!defined($SPEC->{$type}) ? undef : ($type, @{$SPEC->{$type}})); } =pod =head1 NAME Net::EPP::Frame::ObjectSpec - metadata about EPP object types =head1 SYNOPSIS use Net::EPP::Frame; use strict; # create an EPP frame: my $check = Net::EPP::Frame::Command::Check->new; # get the spec: my @spec = Net::EPP::Frame::ObjectSpec->spec('domain'); # create an object: my $domain = $check->addObject(@spec); # set the attributes: my $name = $check->createElement('domain:name'); $name->addText('example.tld'); # assemble the frame: $domain->appendChild($name); $check->getCommandNode->appendChild($domain); print $check->toString; =head1 DESCRIPTION EPP is the Extensible Provisioning Protocol. EPP (defined in RFC 4930) is an application layer client-server protocol for the provisioning and management of objects stored in a shared central repository. Specified in XML, the protocol defines generic object management operations and an extensible framework that maps protocol operations to objects. As of writing, its only well-developed application is the provisioning of Internet domain names, hosts, and related contact details. Net::EPP::Frame::ObjectSpec is a simple module designed to provide easy access to metadata for the object types defined in the EPP specification. =head1 USAGE my @spec = Net::EPP::Frame::ObjectSpec->spec($type); This function returns an array containing metadata for the given object type. If no metadata is registered then the function returns undef. The array contains three members: @spec = ( $type, $xmlns, $schemaLocation, ); C<$type> is the same as the supplied argument, and the other two members correspond to the XML attributes used to specify the object in an EPP CcommandE> or CresponseE> frame. The objects currently registered are: =over =item * C, for domain names. =item * C, for DNS server hosts. =item * C, for contact objects. =item * C, for DNSSEC information. =back =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2007 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * the L module, for constructing valid EPP frames. =item * the L module, for communicating with EPP servers. =item * RFCs 4930 and RFC 4934, available from L. =item * The CentralNic EPP site at L. =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Response.pm000755 000765 000024 00000006560 11745236005 020205 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Response.pm,v 1.9 2011/07/04 09:48:51 gavin Exp $ package Net::EPP::Frame::Response; use Net::EPP::ResponseCodes; use base qw(Net::EPP::Frame); =pod =head1 NAME Net::EPP::Frame::Response - an instance of L for server responses =head1 DESCRIPTION This module is a subclass of L that represents EPP server responses. Responses are sent back to clients when the server receives a CcommandE> frame. =head1 OBJECT HIERARCHY L +----L +----L +----L =cut sub new { my $package = shift; my $self = $package->SUPER::new('response'); return bless($self, $package); } sub _addExtraElements { my $self = shift; my $result = $self->createElement('result'); $result->appendChild($self->createElement('msg')); $self->response->addChild($result); $self->result->setAttribute('code' => COMMAND_FAILED); $self->response->addChild($self->createElement('resData')); my $trID = $self->createElement('trID'); $trID->addChild($self->createElement('clTRID')); $trID->addChild($self->createElement('svTRID')); $self->response->addChild($trID); return 1; } =pod =head1 METHODS my $node = $frame->response; This method returns the L object corresponding to the CcommandE> element. my $node = $frame->result; This method returns the L object corresponding to the CresultE> element. my $node = $frame->msg; This method returns the L object corresponding to the CmsgE> element. my $node = $frame->resData; This method returns the L object corresponding to the CresDataE> element. my $node = $frame->trID; This method returns the L object corresponding to the CtrIDE> element. my $node = $frame->clTRID; This method returns the L object corresponding to the CclTRIDE> element. my $node = $frame->svTRID; This method returns the L object corresponding to the CsvTRIDE> element. =cut sub response {$_[0]->getNode('response') } sub result {$_[0]->getNode('result') } sub resData {$_[0]->getNode('resData') } sub trID {$_[0]->getNode('trID') } sub clTRID {$_[0]->getNode('clTRID') } sub svTRID {$_[0]->getNode('svTRID') } =pod my $msg = $frame->code; This method returns the code attribute of the CresultE> element. =cut sub code { my $self = shift; my $result = $self->result; if ($result) { return $result->getAttribute('code'); } return COMMAND_FAILED; } =pod my $msg = $frame->msg; This method returns a string containing the text content of the CmsgE> element. =cut sub msg { my $self = shift; my $msgs = $self->getElementsByLocalName('msg'); return $msgs->shift->textContent if ($msgs->size == 1); } =pod =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Check/000755 000765 000024 00000000000 11745236100 020426 5ustar00gavinstaff000000 000000 Net-EPP-0.19/lib/Net/EPP/Frame/Command/Check.pm000755 000765 000024 00000002300 11745236005 020766 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Check.pm,v 1.5 2011/12/03 11:44:52 gavin Exp $ package Net::EPP::Frame::Command::Check; use base qw(Net::EPP::Frame::Command); use Net::EPP::Frame::Command::Check::Domain; use Net::EPP::Frame::Command::Check::Contact; use Net::EPP::Frame::Command::Check::Host; use strict; =pod =head1 NAME Net::EPP::Frame::Command::Check - an instance of L for the EPP CcheckE> command. =head1 OBJECT HIERARCHY L +----L +----L +----L +----L =head1 METHODS This module does not define any methods in addition to those it inherits from its ancestors. =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Create/000755 000765 000024 00000000000 11745236100 020614 5ustar00gavinstaff000000 000000 Net-EPP-0.19/lib/Net/EPP/Frame/Command/Create.pm000755 000765 000024 00000002310 11745236005 021155 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Create.pm,v 1.4 2011/12/03 11:44:52 gavin Exp $ package Net::EPP::Frame::Command::Create; use base qw(Net::EPP::Frame::Command); use Net::EPP::Frame::Command::Create::Domain; use Net::EPP::Frame::Command::Create::Host; use Net::EPP::Frame::Command::Create::Contact; use strict; =pod =head1 NAME Net::EPP::Frame::Command::Create - an instance of L for the EPP CcreateE> command. =head1 OBJECT HIERARCHY L +----L +----L +----L +----L =head1 METHODS This module does not define any methods in addition to those it inherits from its ancestors. =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Delete/000755 000765 000024 00000000000 11745236100 020613 5ustar00gavinstaff000000 000000 Net-EPP-0.19/lib/Net/EPP/Frame/Command/Delete.pm000755 000765 000024 00000002310 11745236005 021154 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Delete.pm,v 1.5 2011/12/03 11:44:52 gavin Exp $ package Net::EPP::Frame::Command::Delete; use base qw(Net::EPP::Frame::Command); use Net::EPP::Frame::Command::Delete::Contact; use Net::EPP::Frame::Command::Delete::Domain; use Net::EPP::Frame::Command::Delete::Host; use strict; =pod =head1 NAME Net::EPP::Frame::Command::Delete - an instance of L for the EPP CdeleteE> command. =head1 OBJECT HIERARCHY L +----L +----L +----L +----L =head1 METHODS This module does not define any methods in addition to those it inherits from its ancestors. =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Info/000755 000765 000024 00000000000 11745236100 020304 5ustar00gavinstaff000000 000000 Net-EPP-0.19/lib/Net/EPP/Frame/Command/Info.pm000755 000765 000024 00000002270 11745236005 020652 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Info.pm,v 1.7 2011/12/03 11:44:52 gavin Exp $ package Net::EPP::Frame::Command::Info; use Net::EPP::Frame::Command::Info::Contact; use Net::EPP::Frame::Command::Info::Domain; use Net::EPP::Frame::Command::Info::Host; use base qw(Net::EPP::Frame::Command); use strict; =pod =head1 NAME Net::EPP::Frame::Command::Info - an instance of L for the EPP CinfoE> command. =head1 OBJECT HIERARCHY L +----L +----L +----L +----L =head1 METHODS This module does not define any methods in addition to those it inherits from its ancestors. =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Login.pm000755 000765 000024 00000005140 11745236005 021026 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Login.pm,v 1.5 2011/12/03 11:44:52 gavin Exp $ package Net::EPP::Frame::Command::Login; use base qw(Net::EPP::Frame::Command); use strict; =pod =head1 NAME Net::EPP::Frame::Command::Login - an instance of L for the EPP CloginE> command. =head1 OBJECT HIERARCHY L +----L +----L +----L +----L =cut sub _addCommandElements { my $self = shift; $self->getNode('login')->addChild($self->createElement('clID')); $self->getNode('login')->addChild($self->createElement('pw')); $self->getNode('login')->addChild($self->createElement('options')); $self->getNode('options')->addChild($self->createElement('version')); $self->getNode('options')->addChild($self->createElement('lang')); $self->getNode('login')->addChild($self->createElement('svcs')); } =pod =head1 METHODS my $node = $frame->clID; This method returns the L object corresponding to the CclIDE> element. my $node = $frame->pw; This method returns the L object corresponding to the CpwE> element. my $node = $frame->newPW; This method returns the L object corresponding to the CnewPWE> element. my $node = $frame->svcs; This method returns the L object corresponding to the CsvcsE> element. my $node = $frame->options; This method returns the L object corresponding to the CoptionsE> element. my $node = $frame->version; This method returns the L object corresponding to the CversionE> element. my $node = $frame->lang; This method returns the L object corresponding to the ClangE> element. =cut sub clID { $_[0]->getNode('clID') } sub pw { $_[0]->getNode('pw') } sub newPW { $_[0]->getNode('newPW') } sub svcs { $_[0]->getNode('svcs') } sub options { $_[0]->getNode('options') } sub version { $_[0]->getNode('version') } sub lang { $_[0]->getNode('lang') } =pod =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Logout.pm000755 000765 000024 00000002077 11745236005 021235 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Logout.pm,v 1.4 2011/12/03 11:44:52 gavin Exp $ package Net::EPP::Frame::Command::Logout; use base qw(Net::EPP::Frame::Command); use strict; =pod =head1 NAME Net::EPP::Frame::Command::Logout - an instance of L for the EPP ClogoutE> command. =head1 OBJECT HIERARCHY L +----L +----L +----L +----L =head1 METHODS This module does not define any methods in addition to those it inherits from its ancestors. =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Poll/000755 000765 000024 00000000000 11745236100 020317 5ustar00gavinstaff000000 000000 Net-EPP-0.19/lib/Net/EPP/Frame/Command/Poll.pm000755 000765 000024 00000002207 11745236005 020665 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Poll.pm,v 1.4 2011/12/03 11:44:52 gavin Exp $ package Net::EPP::Frame::Command::Poll; use Net::EPP::Frame::Command::Poll::Req; use Net::EPP::Frame::Command::Poll::Ack; use base qw(Net::EPP::Frame::Command); use strict; =pod =head1 NAME Net::EPP::Frame::Command::Poll - an instance of L for the EPP CPollE> command. =head1 OBJECT HIERARCHY L +----L +----L +----L +----L =head1 METHODS This module does not define any methods in addition to those it inherits from its ancestors. =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Renew/000755 000765 000024 00000000000 11745236100 020471 5ustar00gavinstaff000000 000000 Net-EPP-0.19/lib/Net/EPP/Frame/Command/Renew.pm000755 000765 000024 00000002147 11745236005 021042 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Renew.pm,v 1.3 2011/12/03 11:44:52 gavin Exp $ package Net::EPP::Frame::Command::Renew; use Net::EPP::Frame::Command::Renew::Domain; use base qw(Net::EPP::Frame::Command); use strict; =pod =head1 NAME Net::EPP::Frame::Command::Renew - an instance of L for the EPP CrenewE> command. =head1 OBJECT HIERARCHY L +----L +----L +----L +----L =head1 METHODS This module does not define any methods in addition to those it inherits from its ancestors. =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Transfer/000755 000765 000024 00000000000 11745236100 021175 5ustar00gavinstaff000000 000000 Net-EPP-0.19/lib/Net/EPP/Frame/Command/Transfer.pm000755 000765 000024 00000002257 11745236005 021550 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Transfer.pm,v 1.3 2011/12/03 11:44:52 gavin Exp $ package Net::EPP::Frame::Command::Transfer; use Net::EPP::Frame::Command::Transfer::Contact; use Net::EPP::Frame::Command::Transfer::Domain; use base qw(Net::EPP::Frame::Command); use strict; =pod =head1 NAME Net::EPP::Frame::Command::Transfer - an instance of L for the EPP CtransferE> command. =head1 OBJECT HIERARCHY L +----L +----L +----L +----L =head1 METHODS =cut sub setOp { my ($self, $op) = @_; $self->getCommandNode->setAttribute('op', $op); } =pod =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Update/000755 000765 000024 00000000000 11745236100 020633 5ustar00gavinstaff000000 000000 Net-EPP-0.19/lib/Net/EPP/Frame/Command/Update.pm000755 000765 000024 00000003672 11745236005 021210 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Update.pm,v 1.5 2011/12/14 12:02:08 gavin Exp $ package Net::EPP::Frame::Command::Update; use Net::EPP::Frame::Command::Update::Contact; use Net::EPP::Frame::Command::Update::Domain; use Net::EPP::Frame::Command::Update::Host; use base qw(Net::EPP::Frame::Command); use strict; =pod =head1 NAME Net::EPP::Frame::Command::Update - an instance of L for the EPP CupdateE> command. =head1 OBJECT HIERARCHY L +----L +----L +----L +----L =head1 METHODS =cut sub add { my $self = shift; foreach my $el ($self->getNode('update')->getChildNodes->shift->getChildNodes) { my (undef, $name) = split(/:/, $el->localName, 2); return $el if ($name eq 'add'); } } sub rem { my $self = shift; foreach my $el ($self->getNode('update')->getChildNodes->shift->getChildNodes) { my (undef, $name) = split(/:/, $el->localName, 2); return $el if ($name eq 'rem'); } } sub chg { my $self = shift; foreach my $el ($self->getNode('update')->getChildNodes->shift->getChildNodes) { my (undef, $name) = split(/:/, $el->localName, 2); return $el if ($name eq 'chg'); } } =pod my $el = $frame->add; my $el = $frame->rem; my $el = $frame->chg; These methods return the elements that should be used to contain the changes to be made to the object (ie C, C, C). =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Update/Contact.pm000644 000765 000024 00000011006 11745236005 022566 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Contact.pm,v 1.3 2011/12/03 11:44:52 gavin Exp $ package Net::EPP::Frame::Command::Update::Contact; use base qw(Net::EPP::Frame::Command::Update); use Net::EPP::Frame::ObjectSpec; use strict; =pod =head1 NAME Net::EPP::Frame::Command::Update::Contact - an instance of L for contact objects. =head1 SYNOPSIS use Net::EPP::Frame::Command::Update::Contact; use strict; my $info = Net::EPP::Frame::Command::Update::Contact->new; $info->setContact('REG-12345'); print $info->toString(1); This results in an XML document like this: REG-12345 example-1.tldE/contact:id> 0cf1b8f7e14547d26f03b7641660c641d9e79f45 =head1 OBJECT HIERARCHY L +----L +----L +----L +----L +----L =cut sub new { my $package = shift; my $self = bless($package->SUPER::new('update'), $package); my $contact = $self->addObject(Net::EPP::Frame::ObjectSpec->spec('contact')); foreach my $grp (qw(add rem chg)) { my $el = $self->createElement(sprintf('contact:%s', $grp)); $self->getNode('update')->getChildNodes->shift->appendChild($el); } return $self; } =pod =head1 METHODS $frame->setContact($id); This specifies the contact object to be updated. =cut sub setContact { my ($self, $id) = @_; my $el = $self->createElement('contact:id'); $el->appendText($id); my $n = $self->getNode('update')->getChildNodes->shift; $n->insertBefore( $el, $n->firstChild ); return 1; } =pod $frame->addStatus($type, $info); Add a status of $type with the optional extra $info. =cut sub addStatus { my ($self, $type, $info) = @_; my $status = $self->createElement('contact:status'); $status->setAttribute('s', $type); $status->setAttribute('lang', 'en'); if ($info) { $status->appendText($info); } $self->getElementsByLocalName('contact:add')->shift->appendChild($status); return 1; } =pod $frame->remStatus($type); Remove a status of $type. =cut sub remStatus { my ($self, $type) = @_; my $status = $self->createElement('contact:status'); $status->setAttribute('s', $type); $self->getElementsByLocalName('contact:rem')->shift->appendChild($status); return 1; } sub chgPostalInfo { my ($self, $type, $name, $org, $addr) = @_; my $el = $self->createElement('contact:postalInfo'); $el->setAttribute('type', $type); my $nel = $self->createElement('contact:name'); $nel->appendText($name); my $oel = $self->createElement('contact:org'); $oel->appendText($org); my $ael = $self->createElement('contact:addr'); if (ref($addr->{street}) eq 'ARRAY') { foreach my $street (@{$addr->{street}}) { my $sel = $self->createElement('contact:street'); $sel->appendText($street); $ael->appendChild($sel); } } foreach my $name (qw(city sp pc cc)) { my $vel = $self->createElement('contact:'.$name); $vel->appendText($addr->{$name}); $ael->appendChild($vel); } $el->appendChild($nel); $el->appendChild($oel) if $org; $el->appendChild($ael); $self->getElementsByLocalName('contact:chg')->shift->appendChild($el); return $el; } =pod $frame->chgAuthinfo($auth); Change the authinfo. =cut sub chgAuthInfo { my ($self,$authInfo) = @_; my $el = $self->createElement('contact:authInfo'); my $pw = $self->createElement('contact:pw'); $pw->appendText($authInfo); $el->appendChild($pw); $self->getElementsByLocalName('contact:chg')->shift->appendChild($el); return 1; } =pod =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Update/Domain.pm000644 000765 000024 00000017201 11745236005 022405 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Domain.pm,v 1.3 2011/12/03 11:44:52 gavin Exp $ package Net::EPP::Frame::Command::Update::Domain; use base qw(Net::EPP::Frame::Command::Update); use Net::EPP::Frame::ObjectSpec; use strict; =pod =head1 NAME Net::EPP::Frame::Command::Update::Domain - an instance of L for domain names. =head1 SYNOPSIS use Net::EPP::Frame::Command::Update::Domain; use strict; my $info = Net::EPP::Frame::Command::Update::Domain->new; $info->setDomain('example.tld'); print $info->toString(1); This results in an XML document like this: example-1.tldE/domain:name> 0cf1b8f7e14547d26f03b7641660c641d9e79f45 =head1 OBJECT HIERARCHY L +----L +----L +----L +----L +----L =cut sub new { my $package = shift; my $self = bless($package->SUPER::new('update'), $package); my $domain = $self->addObject(Net::EPP::Frame::ObjectSpec->spec('domain')); foreach my $grp (qw(add rem chg)) { my $el = $self->createElement(sprintf('domain:%s', $grp)); $self->getNode('update')->getChildNodes->shift->appendChild($el); } return $self; } =pod =head1 METHODS $frame->setDomain($domain_name); This specifies the domain name to be updated. =cut sub setDomain { my ($self, $domain) = @_; my $name = $self->createElement('domain:name'); $name->appendText($domain); my $n = $self->getNode('update')->getChildNodes->shift; $n->insertBefore( $name, $n->firstChild ); return 1; } =pod $frame->addStatus($type, $info); Add a status of $type with the optional extra $info. =cut sub addStatus { my ($self, $type, $info) = @_; my $status = $self->createElement('domain:status'); $status->setAttribute('s', $type); $status->setAttribute('lang', 'en'); if ($info) { $status->appendText($info); } $self->getElementsByLocalName('domain:add')->shift->appendChild($status); return 1; } =pod $frame->remStatus($type); Remove a status of $type. =cut sub remStatus { my ($self, $type) = @_; my $status = $self->createElement('domain:status'); $status->setAttribute('s', $type); $self->getElementsByLocalName('domain:rem')->shift->appendChild($status); return 1; } =pod $frame->addContact($type, $contact); Add a contact of $type. =cut sub addContact { my ($self, $type, $contact_id) = @_; my $contact = $self->createElement('domain:contact'); $contact->setAttribute('type', $type); $contact->appendText($contact_id); $self->getElementsByLocalName('domain:add')->shift->appendChild($contact); return 1; } =pod $frame->remContact($type, $contact); Remove a contact of $type. =cut sub remContact { my ($self, $type, $contact_id) = @_; my $contact = $self->createElement('domain:contact'); $contact->setAttribute('type', $type); $contact->appendText($contact_id); $self->getElementsByLocalName('domain:rem')->shift->appendChild($contact); return 1; } =pod $frame->chgAuthinfo($auth); Change the authinfo. =cut sub chgAuthInfo { my ($self,$authInfo) = @_; my $el = $self->createElement('domain:authInfo'); my $pw = $self->createElement('domain:pw'); $pw->appendText($authInfo); $el->appendChild($pw); $self->getElementsByLocalName('domain:chg')->shift->appendChild($el); return 1; } =pod $frame->chgRegistrant($registrant); Change the authinfo. =cut sub chgRegistrant { my ($self,$contact) = @_; my $registrant = $self->createElement('domain:registrant'); $registrant->appendText($contact); $self->getElementsByLocalName('domain:chg')->shift->appendChild($registrant); return 1; } =pod $frame->addNS('ns0.example.com'); # host object mode $frame->addNS({'name' => 'ns0.example.com', 'addrs' => [ { 'addr' => '127.0.0.1', 'type' => 4 } ] }); # host attribute mode =cut sub addNS { my ($self, @ns) = @_; if ( ref $ns[0] eq 'HASH' ) { $self->addHostAttrNS(@ns); } else { $self->addHostObjNS(@ns); } return 1; } sub addHostAttrNS { my ($self, @ns) = @_; my $ns = $self->createElement('domain:ns'); # Adding attributes foreach my $host (@ns) { my $hostAttr = $self->createElement('domain:hostAttr'); # Adding NS name my $hostName = $self->createElement('domain:hostName'); $hostName->appendText($host->{name}); $hostAttr->appendChild($hostName); # Adding IP addresses if ( exists $host->{addrs} && ref $host->{addrs} eq 'ARRAY' ) { foreach my $addr ( @{ $host->{addrs} } ) { my $hostAddr = $self->createElement('domain:hostAddr'); $hostAddr->appendText($addr->{addr}); $hostAddr->setAttribute(ip => $addr->{version}); $hostAttr->appendChild($hostAddr); } } # Adding host info to frame $ns->appendChild($hostAttr); } $self->getElementsByLocalName('domain:add')->shift->appendChild($ns); return 1; } sub addHostObjNS { my ($self, @ns) = @_; my $ns = $self->createElement('domain:ns'); foreach my $host (@ns) { my $el = $self->createElement('domain:hostObj'); $el->appendText($host); $ns->appendChild($el); } $self->getElementsByLocalName('domain:add')->shift->appendChild($ns); return 1; } =pod $frame->remNS('ns0.example.com'); # host object mode $frame->remNS({'name' => 'ns0.example.com', 'addrs' => [ { 'addr' => '127.0.0.1', 'type' => 4 } ] }); # host attribute mode =cut sub remNS { my ($self, @ns) = @_; if ( ref $ns[0] eq 'HASH' ) { $self->remHostAttrNS(@ns); } else { $self->remHostObjNS(@ns); } return 1; } sub remHostAttrNS { my ($self, @ns) = @_; my $ns = $self->createElement('domain:ns'); # Adding attributes foreach my $host (@ns) { my $hostAttr = $self->createElement('domain:hostAttr'); # Adding NS name my $hostName = $self->createElement('domain:hostName'); $hostName->appendText($host->{name}); $hostAttr->appendChild($hostName); # Adding IP addresses if ( exists $host->{addrs} && ref $host->{addrs} eq 'ARRAY' ) { foreach my $addr ( @{ $host->{addrs} } ) { my $hostAddr = $self->createElement('domain:hostAddr'); $hostAddr->appendText($addr->{addr}); $hostAddr->setAttribute(ip => $addr->{version}); $hostAttr->appendChild($hostAddr); } } # Adding host info to frame $ns->appendChild($hostAttr); } $self->getElementsByLocalName('domain:rem')->shift->appendChild($ns); return 1; } sub remHostObjNS { my ($self, @ns) = @_; my $ns = $self->createElement('domain:ns'); foreach my $host (@ns) { my $el = $self->createElement('domain:hostObj'); $el->appendText($host); $ns->appendChild($el); } $self->getElementsByLocalName('domain:rem')->shift->appendChild($ns); return 1; } =pot =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/), with contributions from United Domains AG (http://www.united-domains.de/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Update/Host.pm000644 000765 000024 00000011441 11745236005 022113 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Host.pm,v 1.3 2011/01/23 12:26:24 gavin Exp $ package Net::EPP::Frame::Command::Update::Host; use base qw(Net::EPP::Frame::Command::Update); use Net::EPP::Frame::ObjectSpec; use strict; =pod =head1 NAME Net::EPP::Frame::Command::Update::Host - an instance of L for host objects. =head1 SYNOPSIS use Net::EPP::Frame::Command::Update::Host; use strict; my $info = Net::EPP::Frame::Command::Update::Host->new; $info->setHost('ns0.example.tld'); print $info->toString(1); This results in an XML document like this: example-1.tldE/host:name> 0cf1b8f7e14547d26f03b7641660c641d9e79f45 =head1 OBJECT HIERARCHY L +----L +----L +----L +----L +----L =cut sub new { my $package = shift; my $self = bless($package->SUPER::new('update'), $package); my $host = $self->addObject(Net::EPP::Frame::ObjectSpec->spec('host')); # 'chg' element's contents are not optional for hosts, so we'll add # this element only when we plan to use it (accessor is overriden) foreach my $grp (qw(add rem)) { my $el = $self->createElement(sprintf('host:%s', $grp)); $self->getNode('update')->getChildNodes->shift->appendChild($el); } return $self; } =pod =head1 METHODS $frame->setHost($host_name); This specifies the host object to be updated. =cut sub setHost { my ($self, $host) = @_; my $name = $self->createElement('host:name'); $name->appendText($host); my $n = $self->getNode('update')->getChildNodes->shift; $n->insertBefore($name, $n->firstChild); return 1; } =pod $frame->addStatus($type, $info); Add a status of $type with the optional extra $info. =cut sub addStatus { my ($self, $type, $info) = @_; my $status = $self->createElement('host:status'); $status->setAttribute('s', $type); $status->setAttribute('lang', 'en'); if ($info) { $status->appendText($info); } $self->getElementsByLocalName('host:add')->shift->appendChild($status); return 1; } =pod $frame->remStatus($type); Remove a status of $type. =cut sub remStatus { my ($self, $type) = @_; my $status = $self->createElement('host:status'); $status->setAttribute('s', $type); $self->getElementsByLocalName('host:rem')->shift->appendChild($status); return 1; } =pod $frame->addAddr({ 'ip' => '10.0.0.1', 'version' => 'v4' }); Add a set of IP addresses to the host object. EPP supports multiple addresses of different versions. =cut sub addAddr { my ($self, @addr) = @_; foreach my $ip (@addr) { my $el = $self->createElement('host:addr'); $el->appendText($ip->{ip}); $el->setAttribute('ip', $ip->{version}); $self->getElementsByLocalName('host:add')->shift->appendChild($el); } return 1; } =pod $frame->remAddr({ 'ip' => '10.0.0.2', 'version' => 'v4' }); Remove a set of IP addresses from the host object. EPP supports multiple addresses of different versions. =cut sub remAddr { my ($self, @addr) = @_; foreach my $ip (@addr) { my $el = $self->createElement('host:addr'); $el->appendText($ip->{ip}); $el->setAttribute('ip', $ip->{version}); $self->getElementsByLocalName('host:rem')->shift->appendChild($el); } return 1; } =pod my $el = $frame->chg; Lazy-building of 'host:chg'element. =cut sub chg { my $self = shift; my $chg = $self->getElementsByLocalName('host:chg')->shift; if ( $chg ) { return $chg; } else { my $el = $self->createElement('host:chg'); $self->getNode('update')->getChildNodes->shift->appendChild($el); return $el; } } =pod $frame->chgName('ns2.example.com'); Change a name of host. =cut sub chgName { my ($self, $name) = @_; my $el = $self->createElement('host:name'); $el->appendText($name); $self->chg->appendChild($el); } =pod =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Transfer/Contact.pm000644 000765 000024 00000005547 11745236005 023145 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Contact.pm,v 1.1 2011/12/03 11:44:52 gavin Exp $ package Net::EPP::Frame::Command::Transfer::Contact; use base qw(Net::EPP::Frame::Command::Transfer); use Net::EPP::Frame::ObjectSpec; use strict; =pod =head1 NAME Net::EPP::Frame::Command::Transfer::Contact - an instance of L for contact objects. =head1 SYNOPSIS use Net::EPP::Frame::Command::Transfer::Contact; use strict; my $info = Net::EPP::Frame::Command::Transfer::Contact->new; $info->setOp('query'); $info->setContact('REG-12345'); print $info->toString(1); This results in an XML document like this: REG-12345E/contact:id> 0cf1b8f7e14547d26f03b7641660c641d9e79f45 =head1 OBJECT HIERARCHY L +----L +----L +----L +----L +----L =cut sub new { my $package = shift; my $self = bless($package->SUPER::new('transfer'), $package); my $contact = $self->addObject(Net::EPP::Frame::ObjectSpec->spec('contact')); return $self; } =pod =head1 METHODS $frame->setContact($contactID); This specifies the contact object for the transfer. =cut sub setContact { my ($self, $id) = @_; my $name = $self->createElement('contact:id'); $name->appendText($id); $self->getNode('transfer')->getChildNodes->shift->appendChild($name); return 1; } =pod $frame->setAuthInfo($pw); This sets the authInfo code for the transfer. =cut sub setAuthInfo { my ($self, $code) = @_; my $pw = $self->createElement('contact:pw'); $pw->appendText($code); my $authInfo = $self->createElement('contact:authInfo'); $authInfo->appendChild($pw); $self->getNode('transfer')->getChildNodes->shift->appendChild($authInfo); return 1; } =pod =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Transfer/Domain.pm000644 000765 000024 00000006307 11745236005 022754 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Domain.pm,v 1.1 2011/12/03 11:44:52 gavin Exp $ package Net::EPP::Frame::Command::Transfer::Domain; use base qw(Net::EPP::Frame::Command::Transfer); use Net::EPP::Frame::ObjectSpec; use strict; =pod =head1 NAME Net::EPP::Frame::Command::Transfer::Domain - an instance of L for domain objects. =head1 SYNOPSIS use Net::EPP::Frame::Command::Transfer::Domain; use strict; my $info = Net::EPP::Frame::Command::Transfer::Domain->new; $info->setOp('query'); $info->setDomain('example.tld'); print $info->toString(1); This results in an XML document like this: example.tldE/domain:name> 0cf1b8f7e14547d26f03b7641660c641d9e79f45 =head1 OBJECT HIERARCHY L +----L +----L +----L +----L +----L =cut sub new { my $package = shift; my $self = bless($package->SUPER::new('transfer'), $package); my $domain = $self->addObject(Net::EPP::Frame::ObjectSpec->spec('domain')); return $self; } =pod =head1 METHODS $frame->setDomain('example.tld'); This method specifies the domain name for the transfer. =cut sub setDomain { my ($self, $domain) = @_; my $name = $self->createElement('domain:name'); $name->appendText($domain); $self->getNode('transfer')->getChildNodes->shift->appendChild($name); return 1; } =pod $frame->period($years); This sets the optional renewal period for the transfer. =cut sub setPeriod { my ($self, $years) = @_; my $period = $self->createElement('domain:period'); $period->setAttribute('unit', 'y'); $period->appendText($years); $self->getNode('transfer')->getChildNodes->shift->appendChild($period); return 1; } =pod $frame->setAuthInfo($pw); This sets the authInfo code for the transfer. =cut sub setAuthInfo { my ($self, $code) = @_; my $pw = $self->createElement('domain:pw'); $pw->appendText($code); my $authInfo = $self->createElement('domain:authInfo'); $authInfo->appendChild($pw); $self->getNode('transfer')->getChildNodes->shift->appendChild($authInfo); return 1; } =pod =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Renew/Domain.pm000644 000765 000024 00000006025 11745236005 022245 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Domain.pm,v 1.1 2011/12/03 11:44:52 gavin Exp $ package Net::EPP::Frame::Command::Renew::Domain; use base qw(Net::EPP::Frame::Command::Renew); use Net::EPP::Frame::ObjectSpec; use strict; =pod =head1 NAME Net::EPP::Frame::Command::Renew::Domain - an instance of L for domain objects. =head1 SYNOPSIS use Net::EPP::Frame::Command::Renew::Domain; use strict; my $info = Net::EPP::Frame::Command::Renew::Domain->new; $info->setDomain('example.tld'); print $info->toString(1); This results in an XML document like this: example.tldE/domain:name> 0cf1b8f7e14547d26f03b7641660c641d9e79f45 =head1 OBJECT HIERARCHY L +----L +----L +----L +----L +----L =cut sub new { my $package = shift; my $self = bless($package->SUPER::new('renew'), $package); my $domain = $self->addObject(Net::EPP::Frame::ObjectSpec->spec('domain')); return $self; } =pod =head1 METHODS $frame->setDomain('example.tld'); This method specifies the domain name for the renew. =cut sub setDomain { my ($self, $domain) = @_; my $name = $self->createElement('domain:name'); $name->appendText($domain); $self->getNode('renew')->getChildNodes->shift->appendChild($name); return 1; } =pod $frame->period($years); This sets the optional renewal period. =cut sub setPeriod { my ($self, $years) = @_; my $period = $self->createElement('domain:period'); $period->setAttribute('unit', 'y'); $period->appendText($years); $self->getNode('renew')->getChildNodes->shift->appendChild($period); return 1; } =pod $frame->setCurExpDate($date) This sets the current expiry date for the domain. =cut sub setCurExpDate { my ($self, $date) = @_; my $cur = $self->createElement('domain:curExpDate'); $cur->appendText($date); $self->getNode('renew')->getChildNodes->shift->appendChild($cur); return 1; } =pod =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Poll/Ack.pm000644 000765 000024 00000002663 11745236005 021366 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Ack.pm,v 1.2 2011/12/03 11:44:52 gavin Exp $ package Net::EPP::Frame::Command::Poll::Ack; use base qw(Net::EPP::Frame::Command::Poll); use strict; =pod =head1 NAME Net::EPP::Frame::Command::Poll::Ack - an instance of L for the EPP CPollE> acknowledge command. =head1 OBJECT HIERARCHY L +----L +----L +----L +----L =cut sub new { my $package = shift; my $self = bless($package->SUPER::new('poll'), $package); $self->getCommandNode->setAttribute('op' => 'ack'); return $self; } =pod =head1 METHODS $frame->setMsgID($id); This method sets the C attribute on the CpollE> element that is used to specify the message ID being acknowleged. =cut sub setMsgID { my ($self, $id) = @_; $self->getCommandNode->setAttribute('msgID' => $id); return 1; } =pod =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Poll/Req.pm000644 000765 000024 00000002364 11745236005 021415 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Req.pm,v 1.3 2011/12/03 11:44:52 gavin Exp $ package Net::EPP::Frame::Command::Poll::Req; use base qw(Net::EPP::Frame::Command::Poll); use strict; =pod =head1 NAME Net::EPP::Frame::Command::Poll::Req - an instance of L for the EPP CPollE> request command. =head1 OBJECT HIERARCHY L +----L +----L +----L +----L =cut sub new { my $package = shift; my $self = bless($package->SUPER::new('poll'), $package); $self->getCommandNode->setAttribute('op' => 'req'); return $self; } =head1 METHODS This module does not define any methods in addition to those it inherits from its ancestors. =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Info/Contact.pm000644 000765 000024 00000004646 11745236005 022253 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Contact.pm,v 1.4 2011/12/03 11:44:52 gavin Exp $ package Net::EPP::Frame::Command::Info::Contact; use base qw(Net::EPP::Frame::Command::Info); use Net::EPP::Frame::ObjectSpec; use strict; =pod =head1 NAME Net::EPP::Frame::Command::Info::Contact - an instance of L for contact objects. =head1 SYNOPSIS use Net::EPP::Frame::Command::Info::Contact; use strict; my $info = Net::EPP::Frame::Command::Info::Contact->new; $info->setContact('REG-12345'); print $info->toString(1); This results in an XML document like this: REG-12345E/contact:id> 0cf1b8f7e14547d26f03b7641660c641d9e79f45 =head1 OBJECT HIERARCHY L +----L +----L +----L +----L +----L =cut sub new { my $package = shift; my $self = bless($package->SUPER::new('info'), $package); my $contact = $self->addObject(Net::EPP::Frame::ObjectSpec->spec('contact')); return $self; } =pod =head1 METHODS $frame->setContact($contactID); This specifies the contact object for which information is being requested. =cut sub setContact { my ($self, $id) = @_; my $name = $self->createElement('contact:id'); $name->appendText($id); $self->getNode('info')->getChildNodes->shift->appendChild($name); return 1; } =pod =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Info/Domain.pm000644 000765 000024 00000004642 11745236005 022063 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Domain.pm,v 1.3 2011/12/03 11:44:52 gavin Exp $ package Net::EPP::Frame::Command::Info::Domain; use base qw(Net::EPP::Frame::Command::Info); use Net::EPP::Frame::ObjectSpec; use strict; =pod =head1 NAME Net::EPP::Frame::Command::Info::Domain - an instance of L for domain names. =head1 SYNOPSIS use Net::EPP::Frame::Command::Info::Domain; use strict; my $info = Net::EPP::Frame::Command::Info::Domain->new; $info->setDomain('example.tld'); print $info->toString(1); This results in an XML document like this: example-1.tldE/domain:name> 0cf1b8f7e14547d26f03b7641660c641d9e79f45 =head1 OBJECT HIERARCHY L +----L +----L +----L +----L +----L =cut sub new { my $package = shift; my $self = bless($package->SUPER::new('info'), $package); my $domain = $self->addObject(Net::EPP::Frame::ObjectSpec->spec('domain')); return $self; } =pod =head1 METHODS $frame->setDomain($domain_name); This specifies the domain name for which information is being requested. =cut sub setDomain { my ($self, $domain) = @_; my $name = $self->createElement('domain:name'); $name->appendText($domain); $self->getNode('info')->getChildNodes->shift->appendChild($name); return 1; } =pod =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Info/Host.pm000644 000765 000024 00000004571 11745236005 021572 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Host.pm,v 1.2 2011/12/03 11:44:52 gavin Exp $ package Net::EPP::Frame::Command::Info::Host; use base qw(Net::EPP::Frame::Command::Info); use Net::EPP::Frame::ObjectSpec; use strict; =pod =head1 NAME Net::EPP::Frame::Command::Info::Host - an instance of L for host objects. =head1 SYNOPSIS use Net::EPP::Frame::Command::Info::Host; use strict; my $info = Net::EPP::Frame::Command::Info::Host->new; $info->setHost('ns0.example.tld'); print $info->toString(1); This results in an XML document like this: ns0.example-1.tldE/host:name> 0cf1b8f7e14547d26f03b7641660c641d9e79f45 =head1 OBJECT HIERARCHY L +----L +----L +----L +----L +----L =cut sub new { my $package = shift; my $self = bless($package->SUPER::new('info'), $package); my $host = $self->addObject(Net::EPP::Frame::ObjectSpec->spec('host')); return $self; } =pod =head1 METHODS $frame->setHost($host_name); This specifies the hostname for which information is being requested. =cut sub setHost { my ($self, $host) = @_; my $name = $self->createElement('host:name'); $name->appendText($host); $self->getNode('info')->getChildNodes->shift->appendChild($name); return 1; } =pod =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Delete/Contact.pm000644 000765 000024 00000004665 11745236005 022563 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Contact.pm,v 1.3 2011/01/23 12:26:24 gavin Exp $ package Net::EPP::Frame::Command::Delete::Contact; use base qw(Net::EPP::Frame::Command::Delete); use Net::EPP::Frame::ObjectSpec; use strict; =pod =head1 NAME Net::EPP::Frame::Command::Delete::Contact - an instance of L for contact objects. =head1 SYNOPSIS use Net::EPP::Frame::Command::Delete::Contact; use strict; my $delete = Net::EPP::Frame::Command::Delete::Contact->new; $delete->setContact('contact-id'); print $delete->toString(1); This results in an XML document like this: contact-idE/contact:name> 0cf1b8f7e14547d26f03b7641660c641d9e79f45 =head1 OBJECT HIERARCHY L +----L +----L +----L +----L +----L =cut sub new { my $package = shift; my $self = bless($package->SUPER::new('delete'), $package); my $contact = $self->addObject(Net::EPP::Frame::ObjectSpec->spec('contact')); return $self; } =pod =head1 METHODS $frame->setContact($domain_name); This specifies the contact object to be deleted. =cut sub setContact { my ($self, $id) = @_; my $name = $self->createElement('contact:id'); $name->appendText($id); $self->getNode('delete')->getChildNodes->shift->appendChild($name); return 1; } =pod =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Delete/Domain.pm000644 000765 000024 00000004647 11745236005 022377 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Domain.pm,v 1.2 2011/12/03 11:44:52 gavin Exp $ package Net::EPP::Frame::Command::Delete::Domain; use base qw(Net::EPP::Frame::Command::Delete); use Net::EPP::Frame::ObjectSpec; use strict; =pod =head1 NAME Net::EPP::Frame::Command::Delete::Domain - an instance of L for domain names. =head1 SYNOPSIS use Net::EPP::Frame::Command::Delete::Domain; use strict; my $delete = Net::EPP::Frame::Command::Delete::Domain->new; $delete->setDomain('example.tld'); print $delete->toString(1); This results in an XML document like this: example.tldE/domain:name> 0cf1b8f7e14547d26f03b7641660c641d9e79f45 =head1 OBJECT HIERARCHY L +----L +----L +----L +----L +----L =cut sub new { my $package = shift; my $self = bless($package->SUPER::new('delete'), $package); my $domain = $self->addObject(Net::EPP::Frame::ObjectSpec->spec('domain')); return $self; } =pod =head1 METHODS $frame->setDomain($domain_name); This specifies the domain name to be deleted. =cut sub setDomain { my ($self, $domain) = @_; my $name = $self->createElement('domain:name'); $name->appendText($domain); $self->getNode('delete')->getChildNodes->shift->appendChild($name); return 1; } =pod =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Delete/Host.pm000644 000765 000024 00000004575 11745236005 022105 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Host.pm,v 1.3 2011/01/23 12:26:24 gavin Exp $ package Net::EPP::Frame::Command::Delete::Host; use base qw(Net::EPP::Frame::Command::Delete); use Net::EPP::Frame::ObjectSpec; use strict; =pod =head1 NAME Net::EPP::Frame::Command::Delete::Host - an instance of L for host objects. =head1 SYNOPSIS use Net::EPP::Frame::Command::Delete::Host; use strict; my $delete = Net::EPP::Frame::Command::Delete::Host->new; $delete->setHost('example.tld'); print $delete->toString(1); This results in an XML document like this: ns0.example.tldE/host:name> 0cf1b8f7e14547d26f03b7641660c641d9e79f45 =head1 OBJECT HIERARCHY L +----L +----L +----L +----L +----L =cut sub new { my $package = shift; my $self = bless($package->SUPER::new('delete'), $package); my $host = $self->addObject(Net::EPP::Frame::ObjectSpec->spec('host')); return $self; } =pod =head1 METHODS $frame->setHost($host_name); This specifies the host object to be deleted. =cut sub setHost { my ($self, $host) = @_; my $name = $self->createElement('host:name'); $name->appendText($host); $self->getNode('delete')->getChildNodes->shift->appendChild($name); return 1; } =pod =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Create/Contact.pm000644 000765 000024 00000007577 11745236005 022571 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Contact.pm,v 1.3 2011/12/14 12:02:08 gavin Exp $ package Net::EPP::Frame::Command::Create::Contact; use base qw(Net::EPP::Frame::Command::Create); use Net::EPP::Frame::ObjectSpec; use strict; =pod =head1 NAME Net::EPP::Frame::Command::Create::Contact - an instance of L for contact objects. =head1 SYNOPSIS use Net::EPP::Frame::Command::Create::Contact; use strict; my $create = Net::EPP::Frame::Command::Create::Contact->new; $create->setContact('contact-id); print $create->toString(1); This results in an XML document like this: example-1.tldE/contact:id> 0cf1b8f7e14547d26f03b7641660c641d9e79f45 =head1 OBJECT HIERARCHY L +----L +----L +----L +----L +----L =cut sub new { my $package = shift; my $self = bless($package->SUPER::new('create'), $package); $self->addObject(Net::EPP::Frame::ObjectSpec->spec('contact')); return $self; } =pod =head1 METHODS my $element = $frame->setContact($contact_id); This sets the contact ID of the object to be created. Returns the Ccontact:nameE> element. =cut sub setContact { my ($self, $id) = @_; return $self->addEl('id', $id); } sub setVoice { my ($self, $voice) = @_; return $self->addEl('voice', $voice); } sub setFax { my ($self, $fax) = @_; return $self->addEl('fax', $fax); } sub setEmail { my ($self, $email) = @_; return $self->addEl('email', $email); } sub setAuthInfo { my ($self, $authInfo) = @_; my $el = $self->addEl('authInfo'); my $pw = $self->createElement('contact:pw'); $pw->appendText($authInfo); $el->appendChild($pw); return $el; } sub addPostalInfo { my ($self, $type, $name, $org, $addr) = @_; my $el = $self->addEl('postalInfo'); $el->setAttribute('type', $type); my $nel = $self->createElement('contact:name'); $nel->appendText($name); my $oel = $self->createElement('contact:org'); $oel->appendText($org); my $ael = $self->createElement('contact:addr'); if (ref($addr->{street}) eq 'ARRAY') { foreach my $street (@{$addr->{street}}) { my $sel = $self->createElement('contact:street'); $sel->appendText($street); $ael->appendChild($sel); } } foreach my $name (qw(city sp pc cc)) { my $vel = $self->createElement('contact:'.$name); $vel->appendText($addr->{$name}); $ael->appendChild($vel); } $el->appendChild($nel); $el->appendChild($oel) if $org; $el->appendChild($ael); return $el; } sub appendStatus { my ($self, $status) = @_; return $self->addEl('status', $status); } sub addEl { my ($self, $name, $value) = @_; my $el = $self->createElement('contact:'.$name); $el->appendText($value) if defined($value); $self->getNode('create')->getChildNodes->shift->appendChild($el); return $el; } =pod =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Create/Domain.pm000644 000765 000024 00000013555 11745236005 022376 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id$ package Net::EPP::Frame::Command::Create::Domain; use base qw(Net::EPP::Frame::Command::Create); use Net::EPP::Frame::ObjectSpec; use strict; =pod =head1 NAME Net::EPP::Frame::Command::Create::Domain - an instance of L for domain objects. =head1 SYNOPSIS use Net::EPP::Frame::Command::Create::Domain; use strict; my $create = Net::EPP::Frame::Command::Create::Domain->new; $create->setDomain('example.uk.com); print $create->toString(1); This results in an XML document like this: example-1.tldE/domain:name> 0cf1b8f7e14547d26f03b7641660c641d9e79f45 =head1 OBJECT HIERARCHY L +----L +----L +----L +----L +----L =cut sub new { my $package = shift; my $self = bless($package->SUPER::new('create'), $package); $self->addObject(Net::EPP::Frame::ObjectSpec->spec('domain')); return $self; } =pod =head1 METHODS my $element = $frame->setDomain($domain_name); This sets the name of the object to be created. Returns the Cdomain:nameE> element. =cut sub setDomain { my ($self, $domain) = @_; my $name = $self->createElement('domain:name'); $name->appendText($domain); $self->getNode('create')->getChildNodes->shift->appendChild($name); return 1; } sub setPeriod { my ($self, $period, $unit) = @_; $unit = 'y' if (!defined($unit) || $unit eq ''); my $el = $self->createElement('domain:period'); $el->setAttribute('unit', $unit); $el->appendText(int($period)); $self->getNode('create')->getChildNodes->shift->appendChild($el); return 1; } sub setRegistrant { my ($self, $contact) = @_; my $registrant = $self->createElement('domain:registrant'); $registrant->appendText($contact); $self->getNode('create')->getChildNodes->shift->appendChild($registrant); return 1; } sub setContacts { my ($self, $contacts) = @_; foreach my $type (keys(%{$contacts})) { my $contact = $self->createElement('domain:contact'); $contact->setAttribute('type', $type); $contact->appendText($contacts->{$type}); $self->getNode('create')->getChildNodes->shift->appendChild($contact); } return 1; } # # Type of elements of @ns depends on NS model used by EPP server. # hostObj model: # each element is a name of NS host object # hostAttr model: # each element is a hashref: # { # name => 'ns1.example.com, # addrs => [ # { version => 'v4', addr => '192.168.0.10', }, # { version => 'v4', addr => '192.168.0.20', }, # ... # ]; # } # sub setNS { my ($self, @ns) = @_; if ( ref $ns[0] eq 'HASH' ) { $self->addHostAttrNS(@ns); } else { $self->addHostObjNS(@ns); } return 1; } sub addHostAttrNS { my ($self, @ns) = @_; my $ns = $self->createElement('domain:ns'); # Adding attributes foreach my $host (@ns) { my $hostAttr = $self->createElement('domain:hostAttr'); # Adding NS name my $hostName = $self->createElement('domain:hostName'); $hostName->appendText( $host->{name} ); $hostAttr->appendChild($hostName); # Adding IP addresses if ( exists $host->{addrs} && ref $host->{addrs} eq 'ARRAY' ) { foreach my $addr ( @{ $host->{addrs} } ) { my $hostAddr = $self->createElement('domain:hostAddr'); $hostAddr->appendText( $addr->{addr} ); $hostAddr->setAttribute( ip => $addr->{version} ); $hostAttr->appendChild($hostAddr); } } # Adding host info to frame $ns->appendChild($hostAttr); } $self->getNode('create')->getChildNodes->shift->appendChild($ns); return 1; } sub addHostObjNS { my ($self, @ns) = @_; my $ns = $self->createElement('domain:ns'); foreach my $host (@ns) { my $el = $self->createElement('domain:hostObj'); $el->appendText($host); $ns->appendChild($el); } $self->getNode('create')->getChildNodes->shift->appendChild($ns); return 1; } sub setAuthInfo { my ($self, $authInfo) = @_; my $el = $self->addEl('authInfo'); my $pw = $self->createElement('domain:pw'); $pw->appendText($authInfo); $el->appendChild($pw); return $el; } sub appendStatus { my ($self, $status) = @_; return $self->addEl('status', $status); } sub addEl { my ($self, $name, $value) = @_; my $el = $self->createElement('domain:'.$name); $el->appendText($value) if defined($value); $self->getNode('create')->getChildNodes->shift->appendChild($el); return $el; } =pod =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Create/Host.pm000644 000765 000024 00000005731 11745236005 022101 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id$ package Net::EPP::Frame::Command::Create::Host; use base qw(Net::EPP::Frame::Command::Create); use Net::EPP::Frame::ObjectSpec; use strict; =pod =head1 NAME Net::EPP::Frame::Command::Create::Host - an instance of L for host objects. =head1 SYNOPSIS use Net::EPP::Frame::Command::Create::Host; use strict; my $create = Net::EPP::Frame::Command::Create::Host->new; $create->setHost('ns1.example.uk.com); print $create->toString(1); This results in an XML document like this: ns1.example.uk.com 0cf1b8f7e14547d26f03b7641660c641d9e79f45 =head1 OBJECT HIERARCHY L +----L +----L +----L +----L +----L =cut sub new { my $package = shift; my $self = bless($package->SUPER::new('create'), $package); $self->addObject(Net::EPP::Frame::ObjectSpec->spec('host')); return $self; } =pod =head1 METHODS my $element = $frame->setHost($host_name); This sets the name of the object to be created. Returns the host:nameE> element. =cut sub setHost { my ($self, $host) = @_; my $name = $self->createElement('host:name'); $name->appendText($host); $self->getNode('create')->getChildNodes->shift->appendChild($name); return 1; } =pod $frame->setAddr({ 'ip' => '10.0.0.1', 'version' => 'v4' }); This adds an IP address to the host object. EPP supports multiple addresses of different versions. =cut sub setAddr { my ($self, @addr) = @_; foreach my $ip (@addr) { my $hostAttr = $self->createElement('host:addr'); $hostAttr->appendText($ip->{ip}); $hostAttr->setAttribute('ip', $ip->{version}); $self->getNode('create')->getChildNodes->shift->appendChild($hostAttr); } return 1; } =pod =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). United Domains AG (http://www.united-domains.de/) provided the original version of Net::EPP::Frame::Command::Create::Host. =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Check/Contact.pm000644 000765 000024 00000005152 11745236005 022366 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Contact.pm,v 1.3 2011/12/03 11:44:52 gavin Exp $ package Net::EPP::Frame::Command::Check::Contact; use base qw(Net::EPP::Frame::Command::Check); use Net::EPP::Frame::ObjectSpec; use strict; =pod =head1 NAME Net::EPP::Frame::Command::Check::Contact - an instance of L for contact objects. =head1 SYNOPSIS use Net::EPP::Frame::Command::Check::Contact; use strict; my $check = Net::EPP::Frame::Command::Check::Contact->new; $check->addContact('contact-id-01'); $check->addContact('contact-id-02'); $check->addContact('contact-id-03'); print $check->toString(1); This results in an XML document like this: contact-id-01E/contact:id> contact-id-02E/contact:id> contact-id-03E/contact:id> 0cf1b8f7e14547d26f03b7641660c641d9e79f45 =head1 OBJECT HIERARCHY L +----L +----L +----L +----L +----L =cut sub new { my $package = shift; my $self = bless($package->SUPER::new('check'), $package); $self->addObject(Net::EPP::Frame::ObjectSpec->spec('contact')); return $self; } =pod =head1 METHODS $frame->addContact($contact_id); This adds a contact ID to the list of contacts to be checked. =cut sub addContact { my ($self, $contact) = @_; my $name = $self->createElement('contact:id'); $name->appendText($contact); $self->getNode('check')->getChildNodes->shift->appendChild($name); return 1; } =pod =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Check/Domain.pm000644 000765 000024 00000005133 11745236005 022201 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Domain.pm,v 1.4 2011/12/03 11:44:52 gavin Exp $ package Net::EPP::Frame::Command::Check::Domain; use base qw(Net::EPP::Frame::Command::Check); use Net::EPP::Frame::ObjectSpec; use strict; =pod =head1 NAME Net::EPP::Frame::Command::Check::Domain - an instance of L for domain names. =head1 SYNOPSIS use Net::EPP::Frame::Command::Check::Domain; use strict; my $check = Net::EPP::Frame::Command::Check::Domain->new; $check->addDomain('example-1.tld'); $check->addDomain('example-2.tld'); $check->addDomain('example-2.tld'); print $check->toString(1); This results in an XML document like this: example-1.tldE/domain:name> example-2.tldE/domain:name> example-3.tldE/domain:name> 0cf1b8f7e14547d26f03b7641660c641d9e79f45 =head1 OBJECT HIERARCHY L +----L +----L +----L +----L +----L =cut sub new { my $package = shift; my $self = bless($package->SUPER::new('check'), $package); $self->addObject(Net::EPP::Frame::ObjectSpec->spec('domain')); return $self; } =pod =head1 METHODS $frame->addDomain($domain_name); This adds a domain name to the list of domains to be checked. =cut sub addDomain { my ($self, $domain) = @_; my $name = $self->createElement('domain:name'); $name->appendText($domain); $self->getNode('check')->getChildNodes->shift->appendChild($name); return 1; } =pod =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1; Net-EPP-0.19/lib/Net/EPP/Frame/Command/Check/Host.pm000644 000765 000024 00000005052 11745236005 021707 0ustar00gavinstaff000000 000000 # Copyright (c) 2012 CentralNic Ltd. All rights reserved. This program is # free software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # $Id: Host.pm,v 1.3 2011/12/03 11:44:52 gavin Exp $ package Net::EPP::Frame::Command::Check::Host; use base qw(Net::EPP::Frame::Command::Check); use Net::EPP::Frame::ObjectSpec; use strict; =pod =head1 NAME Net::EPP::Frame::Command::Check::Host - an instance of L for host objects. =head1 SYNOPSIS use Net::EPP::Frame::Command::Check::Host; use strict; my $check = Net::EPP::Frame::Command::Check::Host->new; $check->addHost('example-1.tld'); $check->addHost('example-2.tld'); $check->addHost('example-2.tld'); print $check->toString(1); This results in an XML document like this: ns0.example-1.tldE/host:name> ns1.example-2.tldE/host:name> ns2.example-3.tldE/host:name> 0cf1b8f7e14547d26f03b7641660c641d9e79f45 =head1 OBJECT HIERARCHY L +----L +----L +----L +----L +----L =cut sub new { my $package = shift; my $self = bless($package->SUPER::new('check'), $package); $self->addObject(Net::EPP::Frame::ObjectSpec->spec('host')); return $self; } =pod =head1 METHODS $frame->addHost($host_name); This adds a hostname to the list of hosts to be checked. =cut sub addHost { my ($self, $host) = @_; my $name = $self->createElement('host:name'); $name->appendText($host); $self->getNode('check')->getChildNodes->shift->appendChild($name); return 1; } =pod =head1 AUTHOR CentralNic Ltd (http://www.centralnic.com/). =head1 COPYRIGHT This module is (c) 2012 CentralNic Ltd. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO =over =item * L =back =cut 1;