File Coverage

blib/lib/Net/EPP/Frame.pm
Criterion Covered Total %
statement 33 59 55.9
branch 0 8 0.0
condition n/a
subroutine 11 17 64.7
pod 1 5 20.0
total 45 89 50.5


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