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: Domain.pm,v 1.3 2011/12/03 11:44:52 gavin Exp $
6package Net::EPP::Frame::Command::Update::Domain;
7use base qw(Net::EPP::Frame::Command::Update);
8use Net::EPP::Frame::ObjectSpec;
9use strict;
10use warnings;
11
12our $DNSSEC_URN	= 'urn:ietf:params:xml:ns:secDNS-1.1';
13
14=pod
15
16=head1 NAME
17
18Net::EPP::Frame::Command::Update::Domain - an instance of L<Net::EPP::Frame::Command::Update>
19for domain names.
20
21=head1 SYNOPSIS
22
23	use Net::EPP::Frame::Command::Update::Domain;
24	use strict;
25
26	my $info = Net::EPP::Frame::Command::Update::Domain->new;
27	$info->setDomain('example.tld');
28
29	print $info->toString(1);
30
31This results in an XML document like this:
32
33	<?xml version="1.0" encoding="UTF-8"?>
34	<epp xmlns="urn:ietf:params:xml:ns:epp-1.0"
35	  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
36	  xsi:schemaLocation="urn:ietf:params:xml:ns:epp-1.0
37	  epp-1.0.xsd">
38	    <command>
39	      <update>
40	        <domain:update
41	          xmlns:domain="urn:ietf:params:xml:ns:domain-1.0"
42	          xsi:schemaLocation="urn:ietf:params:xml:ns:domain-1.0
43	          domain-1.0.xsd">
44	            <domain:name>example-1.tldE<lt>/domain:name>
45	        </domain:update>
46	      </update>
47	      <clTRID>0cf1b8f7e14547d26f03b7641660c641d9e79f45</clTRIDE<gt>
48	    </command>
49	</epp>
50
51=head1 OBJECT HIERARCHY
52
53    L<XML::LibXML::Node>
54    +----L<XML::LibXML::Document>
55        +----L<Net::EPP::Frame>
56            +----L<Net::EPP::Frame::Command>
57                +----L<Net::EPP::Frame::Command::Update>
58                    +----L<Net::EPP::Frame::Command::Update::Domain>
59
60=cut
61
62sub new {
63	my $package = shift;
64	my $self = bless($package->SUPER::new('update'), $package);
65
66	my $domain = $self->addObject(Net::EPP::Frame::ObjectSpec->spec('domain'));
67
68	foreach my $grp (qw(add rem chg)) {
69		my $el = $self->createElement(sprintf('domain:%s', $grp));
70		$self->getNode('update')->getChildNodes->shift->appendChild($el);
71	}
72
73	return $self;
74}
75
76=pod
77
78=head1 METHODS
79
80	$frame->setDomain($domain_name);
81
82This specifies the domain name to be updated.
83
84=cut
85
86sub setDomain {
87	my ($self, $domain) = @_;
88
89	my $name = $self->createElement('domain:name');
90	$name->appendText($domain);
91
92	my $n = $self->getNode('update')->getChildNodes->shift;
93	$n->insertBefore( $name, $n->firstChild );
94
95	return 1;
96}
97
98=pod
99
100	$frame->addStatus($type, $info);
101
102Add a status of $type with the optional extra $info.
103
104=cut
105
106sub addStatus {
107	my ($self, $type, $info) = @_;
108	my $status = $self->createElement('domain:status');
109	$status->setAttribute('s', $type);
110	$status->setAttribute('lang', 'en');
111	if ($info) {
112		$status->appendText($info);
113	}
114	$self->getElementsByLocalName('domain:add')->shift->appendChild($status);
115	return 1;
116}
117
118=pod
119
120	$frame->remStatus($type);
121
122Remove a status of $type.
123
124=cut
125
126sub remStatus {
127	my ($self, $type) = @_;
128	my $status = $self->createElement('domain:status');
129	$status->setAttribute('s', $type);
130	$self->getElementsByLocalName('domain:rem')->shift->appendChild($status);
131	return 1;
132}
133
134=pod
135
136	$frame->addContact($type, $contact);
137
138Add a contact of $type.
139
140=cut
141
142sub addContact {
143	my ($self, $type, $contact_id) = @_;
144
145	my $contact = $self->createElement('domain:contact');
146	$contact->setAttribute('type', $type);
147	$contact->appendText($contact_id);
148
149	$self->getElementsByLocalName('domain:add')->shift->appendChild($contact);
150	return 1;
151}
152
153=pod
154
155	$frame->remContact($type, $contact);
156
157Remove a contact of $type.
158
159=cut
160
161sub remContact {
162	my ($self, $type, $contact_id) = @_;
163
164	my $contact = $self->createElement('domain:contact');
165	$contact->setAttribute('type', $type);
166	$contact->appendText($contact_id);
167
168	$self->getElementsByLocalName('domain:rem')->shift->appendChild($contact);
169	return 1;
170}
171
172=pod
173
174	$frame->chgAuthinfo($auth);
175
176Change the authinfo.
177
178=cut
179
180sub chgAuthInfo {
181	my ($self,$authInfo) = @_;
182
183	my $el = $self->createElement('domain:authInfo');
184	my $pw = $self->createElement('domain:pw');
185	$pw->appendText($authInfo);
186	$el->appendChild($pw);
187
188	$self->getElementsByLocalName('domain:chg')->shift->appendChild($el);
189	return 1;
190}
191
192=pod
193
194	$frame->chgRegistrant($registrant);
195
196Change the authinfo.
197
198=cut
199
200sub chgRegistrant {
201	my ($self,$contact) = @_;
202
203	my $registrant = $self->createElement('domain:registrant');
204	$registrant->appendText($contact);
205
206	$self->getElementsByLocalName('domain:chg')->shift->appendChild($registrant);
207	return 1;
208}
209
210=pod
211
212	$frame->addNS('ns0.example.com'); # host object mode
213
214	$frame->addNS({'name' => 'ns0.example.com', 'addrs' => [ { 'addr' => '127.0.0.1', 'type' => 4 } ] }); # host attribute mode
215
216=cut 
217
218sub addNS {
219	my ($self, @ns) = @_;
220
221	if ( ref $ns[0] eq 'HASH' ) {
222		$self->addHostAttrNS(@ns);
223	}
224	else {
225		$self->addHostObjNS(@ns);
226	}
227	return 1;
228}
229
230
231sub addHostAttrNS {
232	my ($self, @ns) = @_;
233
234	my $ns = $self->createElement('domain:ns');
235
236	# Adding attributes
237	foreach my $host (@ns) {
238		my $hostAttr = $self->createElement('domain:hostAttr');
239
240		# Adding NS name
241		my $hostName = $self->createElement('domain:hostName');
242		$hostName->appendText($host->{name});
243		$hostAttr->appendChild($hostName);
244
245		# Adding IP addresses
246		if ( exists $host->{addrs} && ref $host->{addrs} eq 'ARRAY' ) {
247			foreach my $addr ( @{ $host->{addrs} } ) {
248				my $hostAddr = $self->createElement('domain:hostAddr');
249				$hostAddr->appendText($addr->{addr});
250				$hostAddr->setAttribute(ip => $addr->{version});
251				$hostAttr->appendChild($hostAddr);
252			}
253		}
254
255		# Adding host info to frame
256		$ns->appendChild($hostAttr);
257	}
258
259	$self->getElementsByLocalName('domain:add')->shift->appendChild($ns);
260	return 1;
261}
262
263
264sub addHostObjNS {
265	my ($self, @ns) = @_;
266
267	my $ns = $self->createElement('domain:ns');
268	foreach my $host (@ns) {
269		my $el = $self->createElement('domain:hostObj');
270		$el->appendText($host);
271		$ns->appendChild($el);
272	}
273
274	$self->getElementsByLocalName('domain:add')->shift->appendChild($ns);
275	return 1;
276}
277
278=pod
279
280	$frame->remNS('ns0.example.com'); # host object mode
281
282	$frame->remNS({'name' => 'ns0.example.com', 'addrs' => [ { 'addr' => '127.0.0.1', 'type' => 4 } ] }); # host attribute mode
283
284=cut 
285
286sub remNS {
287	my ($self, @ns) = @_;
288
289	if ( ref $ns[0] eq 'HASH' ) {
290		$self->remHostAttrNS(@ns);
291	}
292	else {
293		$self->remHostObjNS(@ns);
294	}
295	return 1;
296}
297
298
299sub remHostAttrNS {
300	my ($self, @ns) = @_;
301
302	my $ns = $self->createElement('domain:ns');
303
304	# Adding attributes
305	foreach my $host (@ns) {
306		my $hostAttr = $self->createElement('domain:hostAttr');
307
308		# Adding NS name
309		my $hostName = $self->createElement('domain:hostName');
310		$hostName->appendText($host->{name});
311		$hostAttr->appendChild($hostName);
312
313		# Adding IP addresses
314		if ( exists $host->{addrs} && ref $host->{addrs} eq 'ARRAY' ) {
315			foreach my $addr ( @{ $host->{addrs} } ) {
316				my $hostAddr = $self->createElement('domain:hostAddr');
317				$hostAddr->appendText($addr->{addr});
318				$hostAddr->setAttribute(ip => $addr->{version});
319				$hostAttr->appendChild($hostAddr);
320			}
321		}
322
323		# Adding host info to frame
324		$ns->appendChild($hostAttr);
325	}
326
327	$self->getElementsByLocalName('domain:rem')->shift->appendChild($ns);
328	return 1;
329}
330
331
332sub remHostObjNS {
333	my ($self, @ns) = @_;
334
335	my $ns = $self->createElement('domain:ns');
336	foreach my $host (@ns) {
337		my $el = $self->createElement('domain:hostObj');
338		$el->appendText($host);
339		$ns->appendChild($el);
340	}
341
342	$self->getElementsByLocalName('domain:rem')->shift->appendChild($ns);
343	return 1;
344}
345
346=pod
347
348=head2 DNSSEC methods
349
350=cut
351
352sub _get_dnsssec {
353	my $self = shift;
354	my $tag = shift;
355
356	my $el = self->getElementsByTagNameNS($DNSSEC_URN, $tag);
357	return $el if $el;
358
359	my $ext = $self->getNode('extension');
360	$ext = $self->getNode('command')->addNewChild(undef, 'extension')
361	    if not defined $ext;
362
363	my $upd = $ext->addNewChild($DNSSEC_URN, 'secDNS:update');
364	$upd->addNewChild($DNSSEC_URN, 'secDNS:add');
365	$upd->addNewChild($DNSSEC_URN, 'secDNS:rem');
366
367	return $self->_get_dnssec($tag);
368}
369
370=pod
371
372=head1 AUTHOR
373
374CentralNic Ltd (http://www.centralnic.com/), with contributions from United Domains AG (http://www.united-domains.de/).
375
376=head1 COPYRIGHT
377
378This module is (c) 2016 CentralNic Ltd. This module is free software; you can
379redistribute it and/or modify it under the same terms as Perl itself.
380
381=head1 SEE ALSO
382
383=over
384
385=item * L<Net::EPP::Frame>
386
387=back
388
389=cut
390
3911;
392