File Coverage

blib/lib/Net/EPP/Frame.pm
Criterion Covered Total %
statement 22 24 91.6
branch n/a
condition n/a
subroutine 8 8 100.0
pod n/a
total 30 32 93.7


line stmt bran cond sub pod time code
1             # Copyright (c) 2016 CentralNic Ltd. All rights reserved. This program is
2             # free software; you can redistribute it and/or modify it under the same
3             # terms as Perl itself.
4             #
5             # $Id: Frame.pm,v 1.17 2011/01/23 12:26:24 gavin Exp $
6             package Net::EPP::Frame;
7 1     1   3 use Carp;
  1         1  
  1         45  
8 1     1   346 use Net::EPP::Frame::Command;
  1         2  
  1         28  
9 1     1   327 use Net::EPP::Frame::Greeting;
  1         2  
  1         55  
10 1     1   307 use Net::EPP::Frame::Hello;
  1         1  
  1         46  
11 1     1   4 use Net::EPP::Frame::ObjectSpec;
  1         1  
  1         20  
12 1     1   294 use Net::EPP::Frame::Response;
  1         2  
  1         51  
13 1     1   3 use POSIX qw(strftime);
  1         1  
  1         6  
14 1     1   1018 use XML::LibXML;
  0            
  0            
15             use base qw(XML::LibXML::Document);
16             use vars qw($EPP_URN $SCHEMA_URI);
17             use strict;
18              
19             our $EPP_URN = 'urn:ietf:params:xml:ns:epp-1.0';
20             our $SCHEMA_URI = 'http://www.w3.org/2001/XMLSchema-instance';
21              
22             =pod
23              
24             =head1 NAME
25              
26             Net::EPP::Frame - An EPP XML frame system built on top of L.
27              
28             =head1 SYNOPSIS
29              
30             #!/usr/bin/perl
31             use Net::EPP::Client;
32             use Net::EPP::Frame;
33             use Net::EPP::ObjectSpec;
34             use Digest::MD5 qw(md5_hex);
35             use Time::HiRes qw(time);
36             use strict;
37              
38             #
39             # establish a connection to an EPP server:
40             #
41             my $epp = Net::EPP::Client->new(
42             host => 'epp.registry.tld',
43             port => 700,
44             ssl => 1,
45             dom => 1,
46             );
47              
48             my $greeting = $epp->connect;
49              
50             #
51             # log in:
52             #
53             my $login = Net::EPP::Frame::Command::Login->new;
54              
55             $login->clID->appendText($userid);
56             $login->pw->appendText($passwd);
57              
58             #
59             # set the client transaction ID:
60             #
61             $login->clTRID->appendText(md5_hex(Time::HiRes::time().$$));
62              
63             #
64             # check the response from the log in:
65             #
66             my $answer = $epp->request($login);
67              
68             my $result = ($answer->getElementsByTagName('result'))[0];
69             if ($result->getAttribute('code') != 1000) {
70             die("Login failed!");
71             }
72              
73             #
74             # OK, let's do a domain name check:
75             #
76             my $check = Net::EPP::Frame::Command::Check->new;
77              
78             #
79             # get the spec from L:
80             #
81             my @spec = Net::EPP::Frame::ObjectSpec->spec('domain');
82              
83             #
84             # create a domain object using the spec:
85             #
86             my $domain = $check->addObject(@spec);
87              
88             #
89             # set the domain name we want to check:
90             #
91             my $name = $check->createElement('domain:name');
92             $name->appendText('example.tld');
93              
94             #
95             # set the client transaction ID:
96             #
97             $check->clTRID->appendText(md5_hex(time().$$));
98              
99             #
100             # assemble the frame:
101             #
102             $domain->addChild($name);
103              
104             #
105             # send the request:
106             #
107             my $answer = $epp->request($check);
108              
109             # and so on...
110              
111             =head1 DESCRIPTION
112              
113             EPP is the Extensible Provisioning Protocol. EPP (defined in RFC 4930) is an
114             application layer client-server protocol for the provisioning and management of
115             objects stored in a shared central repository. Specified in XML, the protocol
116             defines generic object management operations and an extensible framework that
117             maps protocol operations to objects. As of writing, its only well-developed
118             application is the provisioning of Internet domain names, hosts, and related
119             contact details.
120              
121             EPP uses XML documents called "frames" send data to and from clients
122             and servers. This module implements a subclass of the L
123             module that simplifies the process of creation of these frames. It is designed
124             to be used alongside the L module.
125              
126             =head1 OBJECT HIERARCHY
127              
128             L
129             +----L
130             +----L
131              
132              
133             =head1 USAGE
134              
135             As a rule, you will not need to create Net::EPP::Frame objects directly.
136             Instead, you should use one of the subclasses included with the distribution.
137             The subclasses all inherit from Net::EPP::Frame.
138              
139             Net::EPP::Frame is itself a subclass of L so all the
140             methods available from that class are also available to instances of
141             Net::EPP::Frame.
142              
143             The available subclasses of Net::EPP::Frame exist to add any additional
144             elements required by the EPP specification. For example, the EloginE
145             frame must contain the EclIDE and EpwE frames, so when you
146             create a new L object, you get these already
147             defined.
148              
149             These classes also have convenience methods, so for the above example, you can
150             call the C<$login-EclID> and C<$login-Epw> methods to get the
151             L objects correesponding to those elements.
152              
153             =head2 RATIONALE
154              
155             You could just as easily construct your EPP frames from templates or just lots
156             of C calls. But using a programmatic approach such as this strongly
157             couples the validity of your XML to the validity of your program. If the
158             process by which your XML is built is broken, I. This
159             has to be a win.
160              
161             =cut
162              
163             sub new {
164             my ($package, $type) = @_;
165              
166             if (!$type) {
167             my @parts = split(/::/, $package);
168             $type = lc(pop(@parts));
169             }
170              
171             if ($type !~ /^(hello|greeting|command|response)$/) {
172             croak("'type' parameter to Net::EPP::Frame::new() must be one of: hello, greeting, command, response ('$type' given).");
173             return undef;
174             }
175              
176             my $self = $package->SUPER::new('1.0', 'UTF-8');
177             bless($self, $package);
178              
179             my $epp = $self->createElementNS($EPP_URN, 'epp');
180             $self->addChild($epp);
181              
182             my $el = $self->createElement($type);
183             $epp->addChild($el);
184              
185             $self->_addExtraElements;
186              
187             return $self;
188             }
189              
190             sub _addExtraElements {
191             }
192              
193             =pod
194              
195             =head1 ADDITIONAL METHODS
196              
197             my $str = $frame->formatTimeStamp($timestamp);
198              
199             This method returns a scalar in the required format (defined in RFC 3339). This
200             is a convenience method.
201              
202             =cut
203              
204             sub formatTimeStamp {
205             my ($self, $stamp) = @_;
206             return strftime('%Y-%m-%dT%H:%M:%S.0Z', gmtime($stamp));
207             }
208              
209             =pod
210              
211             my $node = $frame->getNode($id);
212             my $node = $frame->getNode($ns, $id);
213              
214             This is another convenience method. It uses C<$id> with the
215             I method to get a list of nodes with that element name,
216             and simply returns the first L from the list.
217              
218             If C<$ns> is provided, then I is used.
219              
220             =cut
221              
222             sub getNode {
223             my ($self, @args) = @_;
224             if (scalar(@args) == 2) {
225             return ($self->getElementsByTagNameNS(@args))[0];
226              
227             } elsif (scalar(@args) == 1) {
228             return ($self->getElementsByTagName($args[0]))[0];
229              
230             } else {
231             croak('Invalid number of arguments to getNode()');
232              
233             }
234             }
235              
236             =pod
237              
238             my $binary = $frame->header;
239              
240             Returns a scalar containing the frame length packed into binary. This is
241             only useful for low-level protocol stuff.
242              
243             =cut
244              
245             sub header {
246             my $self = shift;
247             return pack('N', length($self->toString) + 4);
248             }
249              
250             =pod
251              
252             my $data = $frame->frame;
253              
254             Returns a scalar containing the frame header (see the I method
255             above) concatenated with the XML frame itself. This is only useful for
256             low-level protocol stuff.
257              
258             =cut
259              
260             sub frame {
261             my $self = shift;
262             return $self->header.$self->toString;
263             }
264              
265             =pod
266              
267             =head1 AVAILABLE SUBCLASSES
268              
269             =over
270              
271             =item L, the base class
272              
273             =item L, for EPP client command frames
274              
275             =item L, for EPP EcheckE client commands
276              
277             =item L, for EPP EcreateE client commands
278              
279             =item L, for EPP EdeleteE client commands
280              
281             =item L, for EPP EinfoE client commands
282              
283             =item L, for EPP EloginE client commands
284              
285             =item L, for EPP ElogoutE client commands
286              
287             =item L, for EPP EpollE client commands
288              
289             =item L, for EPP ErenewE client commands
290              
291             =item L, for EPP EtransferE client commands
292              
293             =item L, for EupdateE client commands
294              
295             =item L, for EPP server greetings
296              
297             =item L, for EPP client greetings
298              
299             =item L, for EPP server response frames
300              
301             =back
302              
303             Each subclass has its own subclasses for various objects, for example L creates CcheckE> frame for domain names.
304              
305             Coverage for all combinations of command and object type is not complete, but work is ongoing.
306              
307             =head1 AUTHOR
308              
309             CentralNic Ltd (http://www.centralnic.com/).
310              
311             =head1 COPYRIGHT
312              
313             This module is (c) 2016 CentralNic Ltd. This module is free software; you can
314             redistribute it and/or modify it under the same terms as Perl itself.
315              
316             =head1 SEE ALSO
317              
318             =over
319              
320             =item * L, the Perl bindings to the libxml library
321              
322             =item * The libxml website at L
323              
324             =item * the L module, for communicating with EPP servers.
325              
326             =item * the L module, for managing EP object metadata.
327              
328             =item * RFCs 4930 and RFC 4934, available from L.
329              
330             =item * The CentralNic EPP site at L.
331              
332             =back
333              
334             =cut
335              
336             1;