epp-client-hostmaster 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .idea
19
+ .DS_Store
20
+ dev
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in epp-client.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Yuriy Kolodovskyy
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,144 @@
1
+ # Hostmaster.UA EPP client library
2
+
3
+ EPP (Extensible Provisioning Protocol) client library based on [epp-client-base](https://rubygems.org/gems/epp-client-base) gem.
4
+ Full specification see at [Hostmaster.UA EPP Project](https://epp.hostmaster.ua).
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'epp-client-hostmaster'
11
+
12
+ or this line:
13
+
14
+ gem 'epp-client-hostmaster', git: 'https://github.com/kolodovskyy/epp-client-hostmaster.git'
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install epp-client-hostmaster
23
+
24
+ ## Usage (example)
25
+
26
+ require "epp-client/hostmaster"
27
+
28
+ #ENV['EPP_CLIENT_DEBUG'] = 'yes'
29
+
30
+ c = EPPClient::Hostmaster.new(
31
+ client_id: 'LOGIN',
32
+ password: 'PASSWORD',
33
+ ssl_cert: 'epp.crt',
34
+ ssl_key: 'epp.key'
35
+ )
36
+
37
+ begin
38
+ c.open_connection
39
+ c.login
40
+ c.hello
41
+
42
+ c.contact_check 'test1', 'test2'
43
+ puts c.contact_info 'test1'
44
+
45
+ c.contact_create(
46
+ id: 'test2',
47
+ postalInfo: {
48
+ loc: {
49
+ name: 'Test name',
50
+ org: 'Test organization',
51
+ addr: {
52
+ street: [ 'Test street' ],
53
+ city: 'Kiev',
54
+ pc: '00000',
55
+ cc: 'UA'
56
+ }
57
+ }
58
+ },
59
+ voice: '+380.441234567',
60
+ fax: '+380.441234567',
61
+ email: 'test@test.com',
62
+ authInfo: 'testpassword'
63
+ )
64
+
65
+ c.contact_update(
66
+ id: 'test',
67
+ chg: {
68
+ fax: '+380.447654321'
69
+ }
70
+ )
71
+
72
+ c.contact_delete 'test2'
73
+
74
+ c.host_check 'ns1.test.epp.ua', 'ns2.test.epp.ua'
75
+ c.host_info 'ns1.test.epp.ua'
76
+ c.host_create name: 'ns2.test.epp.ua', addrv4: [ '8.8.8.8' ]
77
+ c.host_update(
78
+ name: 'ns2.test.epp.ua',
79
+ rem: {
80
+ addrv4: '8.8.8.8'
81
+ },
82
+ add: {
83
+ addrv4: '8.8.8.8'
84
+ }
85
+ )
86
+ c.host_delete 'ns2.test.epp.ua'
87
+
88
+ puts c.domain_check 'test1.epp.ua', 'test2.epp.ua'
89
+ puts c.domain_info 'test1.epp.ua'
90
+ c.domain_create(
91
+ name: 'test3.epp.ua',
92
+ period: {
93
+ unit: 'y',
94
+ number: '1'
95
+ },
96
+ ns: [ 'ns1.test.epp.ua' ],
97
+ registrant: 'test',
98
+ contacts: {
99
+ admin: [ 'test' ],
100
+ tech: [ 'test' ]
101
+ }
102
+ )
103
+
104
+ puts c.domain_renew(
105
+ name: 'test.epp.ua',
106
+ curExpDate: '2013-11-19',
107
+ period: {
108
+ unit: 'y',
109
+ number: '1'
110
+ }
111
+ )
112
+
113
+ c.domain_delete('test.epp.ua')
114
+ c.domain_restore('test.epp.ua')
115
+
116
+ c.domain_update(
117
+ name: 'test.epp.ua',
118
+ chg: {
119
+ registrant: 'test1'
120
+ }
121
+ )
122
+
123
+ puts c.poll_req
124
+ puts c.poll_ack
125
+
126
+ puts c.transfer_request name: 'test-transfer.epp.ua', authInfo: '111'
127
+ puts c.transfer_cancel 'test-transfer.epp.ua'
128
+ puts c.transfer_query 'test-transfer.epp.ua'
129
+
130
+ c.logout
131
+ rescue => error
132
+ puts error.to_s
133
+ puts error.backtrace
134
+ ensure
135
+ c.close_connection
136
+ end
137
+
138
+ ## Maintainers and Authors
139
+
140
+ Yuriy Kolodovskyy (https://github.com/kolodovskyy)
141
+
142
+ ## License
143
+
144
+ MIT License. Copyright 2012 [Yuriy Kolodovskyy](http://twitter.com/kolodovskyy)
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'epp-client'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "epp-client-hostmaster"
8
+ gem.version = EPPClient::Hostmaster::VERSION
9
+ gem.authors = ["Yuriy Kolodovskyy"]
10
+ gem.email = %w{kolodovskyy@ukrindex.com}
11
+ gem.description = %q{Hostmaster.UA EPP client library}
12
+ gem.summary = %q{Hostmaster.UA EPP client library}
13
+ gem.homepage = "https://github.com/kolodovskyy/epp-client-hostmaster"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = %w{lib}
19
+
20
+ gem.add_development_dependency "bundler"
21
+ gem.add_dependency('epp-client-base', '~> 0.11.0')
22
+ gem.add_dependency('builder', '~> 3.1.4')
23
+ end
@@ -0,0 +1,9 @@
1
+ module EPPClient
2
+ module HostmasterConnection
3
+ def send_frame(xml)
4
+ @sent_frame = xml
5
+ @socket.write([xml.bytesize + 4].pack("N") + xml)
6
+ sent_frame_to_xml
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,149 @@
1
+ module EPPClient
2
+ module HostmasterContact
3
+ def contact_check_xml(*contacts)
4
+ command do |xml|
5
+ xml.check do
6
+ xml.contact :check, 'xmlns:contact' => EPPClient::SCHEMAS_URL['contact-1.1'] do
7
+ contacts.each { |c| xml.contact :id, c }
8
+ end
9
+ end
10
+ end
11
+ end
12
+
13
+ def contact_info_xml(args)
14
+ command do |xml|
15
+ xml.info do
16
+ xml.contact :info, 'xmlns:contact' => EPPClient::SCHEMAS_URL['contact-1.1'] do
17
+ xml.contact :id, args[:id]
18
+ if args.key? :authInfo
19
+ xml.contact :authInfo do
20
+ xml.contact :pw, args[:authInfo]
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ def contact_create_xml(contact)
29
+ command do |xml|
30
+ xml.create do
31
+ xml.contact :create, 'xmlns:contact' => EPPClient::SCHEMAS_URL['contact-1.1'] do
32
+ if contact.key?(:id)
33
+ xml.contact :id, contact[:id]
34
+ else
35
+ xml.contact :id, 'autonic'
36
+ end
37
+ contact[:postalInfo].each do |type,infos|
38
+ xml.contact :postalInfo, type: type do
39
+ xml.contact :name, infos[:name]
40
+ xml.contact :org, infos[:org] if infos.key?(:org)
41
+ xml.contact :addr do
42
+ infos[:addr][:street].each do |street|
43
+ xml.contact :street, street
44
+ end
45
+ xml.contact :city, infos[:addr][:city]
46
+ xml.contact :sp, infos[:addr][:sp] if infos[:addr].key? :sp
47
+ xml.contact :pc, infos[:addr][:pc] if infos[:addr].key? :pc
48
+ xml.contact :cc, infos[:addr][:cc]
49
+ end
50
+ end
51
+ end
52
+ xml.contact :voice, contact[:voice] if contact.key? :voice
53
+ xml.contact :fax, contact[:fax] if contact.key? :fax
54
+ xml.contact :email, contact[:email]
55
+ xml.contact :authInfo do
56
+ xml.contact :pw, contact[:authInfo]
57
+ end
58
+ if contact.key?(:disclose)
59
+ xml.contact :disclose, flag: '1' do # TODO: parameter for flag need
60
+ contact[:disclose].each do |disc|
61
+ if disc.key?(:type)
62
+ xml.contact disc[:name], type: disc[:type]
63
+ else
64
+ xml.contact disc[:name]
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ def contact_delete_xml(contact)
75
+ command do |xml|
76
+ xml.delete do
77
+ xml.contact :delete, 'xmlns:contact' => EPPClient::SCHEMAS_URL['contact-1.1'] do
78
+ xml.contact :id, contact
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ def contact_update_xml(args)
85
+ command do |xml|
86
+ xml.update do
87
+ xml.contact :update, 'xmlns:contact' => EPPClient::SCHEMAS_URL['contact-1.1'] do
88
+ xml.contact :id, args[:id]
89
+ if args.key?(:add) && args[:add].key?(:status)
90
+ xml.contact :add do
91
+ args[:add][:status].each do |s|
92
+ xml.contact :status, s: s
93
+ end
94
+ end
95
+ end
96
+ if args.key?(:rem) && args[:rem].key?(:status)
97
+ xml.contact :rem do
98
+ args[:rem][:status].each do |s|
99
+ xml.contact :status, s: s
100
+ end
101
+ end
102
+ end
103
+ if args.key?(:chg)
104
+ contact = args[:chg]
105
+ xml.contact :chg do
106
+ if contact.key?(:postalInfo)
107
+ contact[:postalInfo].each do |type,infos|
108
+ xml.contact :postalInfo, type: type do
109
+ xml.contact :name, infos[:name]
110
+ xml.contact :org, infos[:org] if infos.key? :org
111
+ xml.contact :addr do
112
+ infos[:addr][:street].each do |street|
113
+ xml.contact :street, street
114
+ end
115
+ xml.contact :city, infos[:addr][:city]
116
+ xml.contact :sp, infos[:addr][:sp] if infos[:addr].key? :sp
117
+ xml.contact :pc, infos[:addr][:pc] if infos[:addr].key? :pc
118
+ xml.contact :cc, infos[:addr][:cc]
119
+ end
120
+ end
121
+ end
122
+ end
123
+ [:voice, :fax, :email].each do |val|
124
+ xml.contact val, contact[val] if contact.key? val
125
+ end
126
+ if contact.key?(:authInfo)
127
+ xml.contact :authInfo do
128
+ xml.contact :pw, contact[:authInfo]
129
+ end
130
+ end
131
+ if contact.key?(:disclose)
132
+ xml.contact :disclose, flag: '1' do # TODO: parameter for flag need
133
+ contact[:disclose].each do |disc|
134
+ if disc.key?(:type)
135
+ xml.contact disc[:name], type: disc[:type]
136
+ else
137
+ xml.contact disc[:name]
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,183 @@
1
+ module EPPClient
2
+ module HostmasterDomain
3
+ def domain_check_xml(*domains) # :nodoc:
4
+ command do |xml|
5
+ xml.check do
6
+ xml.domain :check, 'xmlns:domain' => EPPClient::SCHEMAS_URL['domain-1.1'] do
7
+ domains.each {|domain| xml.domain :name, domain}
8
+ end
9
+ end
10
+ end
11
+ end
12
+
13
+ def domain_info_xml(args)
14
+ command do |xml|
15
+ xml.info do
16
+ xml.domain :info, 'xmlns:domain' => EPPClient::SCHEMAS_URL['domain-1.1'] do
17
+ xml.domain :name, args[:name]
18
+ if args.key? :authInfo
19
+ xml.domain :authInfo do
20
+ xml.domain :pw, args[:authInfo]
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ def domain_nss_xml(xml, nss)
29
+ xml.domain :ns do
30
+ if nss.first.is_a? Hash
31
+ nss.each do |ns|
32
+ xml.domain :hostAttr do
33
+ xml.domain :hostName, ns[:hostName]
34
+ if ns.key?(:hostAddrv4)
35
+ ns[:hostAddrv4].each do |v4|
36
+ xml.domain :hostAddr, {:ip => :v4}, v4
37
+ end
38
+ end
39
+ if ns.key?(:hostAddrv6)
40
+ ns[:hostAddrv6].each do |v6|
41
+ xml.domain :hostAddr, {:ip => :v6}, v6
42
+ end
43
+ end
44
+ end
45
+ end
46
+ else
47
+ nss.each do |ns|
48
+ xml.domain :hostObj, ns
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ def domain_contacts_xml(xml, args)
55
+ args.each do |type,contacts|
56
+ contacts.each do |c|
57
+ xml.domain :contact, { type: type }, c
58
+ end
59
+ end
60
+ end
61
+
62
+ def domain_period_xml(xml, period)
63
+ xml.domain :period, { unit: period[:unit] }, period[:number]
64
+ end
65
+
66
+ def domain_create_xml(args) #:nodoc:
67
+ command do |xml|
68
+ xml.create do
69
+ xml.domain :create, 'xmlns:domain' => EPPClient::SCHEMAS_URL['domain-1.1'] do
70
+ xml.domain :name, args[:name]
71
+ domain_period_xml(xml, args[:period]) if args.key?(:period)
72
+ domain_nss_xml(xml, args[:ns]) if args.key? :ns
73
+ xml.domain :registrant, args[:registrant]
74
+ domain_contacts_xml(xml, args[:contacts])
75
+ xml.domain :license, args[:license] if args.key? :license
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ def domain_create_process(xml) #:nodoc:
82
+ dom = xml.xpath('epp:resData/domain:creData', EPPClient::SCHEMAS_URL)
83
+ ret = {
84
+ name: dom.xpath('domain:name', EPPClient::SCHEMAS_URL).text,
85
+ crDate: DateTime.parse(dom.xpath('domain:crDate', EPPClient::SCHEMAS_URL).text),
86
+ exDate: DateTime.parse(dom.xpath('domain:exDate', EPPClient::SCHEMAS_URL).text),
87
+ }
88
+ end
89
+
90
+
91
+ def domain_delete_xml(domain) #:nodoc:
92
+ command do |xml|
93
+ xml.delete do
94
+ xml.domain :delete, 'xmlns:domain' => EPPClient::SCHEMAS_URL['domain-1.1'] do
95
+ xml.domain :name, domain
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ def domain_renew_xml(domain)
102
+ command do |xml|
103
+ xml.renew do
104
+ xml.domain :renew, 'xmlns:domain' => EPPClient::SCHEMAS_URL['domain-1.1'] do
105
+ xml.domain :name, domain[:name]
106
+ xml.domain :curExpDate, domain[:curExpDate].strftime('%Y-%m-%d')
107
+ domain_period_xml(xml, domain[:period])
108
+ end
109
+ end
110
+ end
111
+ end
112
+
113
+ # Renew a domain
114
+ #
115
+ # Takes a hash as an argument, containing the following keys :
116
+ #
117
+ # [<tt>:name</tt>] the domain name
118
+ # [<tt>:period</tt>]
119
+ # an optionnal hash containing the period for withch the domain is
120
+ # registered with the following keys :
121
+ # [<tt>:unit</tt>] the unit of time, either "m"onth or "y"ear.
122
+ # [<tt>:number</tt>] the number of unit of time.
123
+ # [<tt>:curExpDate</tt>]
124
+ # the date identifying the current end of the domain object
125
+ # registration period.
126
+ # Returns a hash with the following keys :
127
+ #
128
+ # [<tt>:name</tt>] the fully qualified name of the domain object.
129
+ # [<tt>:exDate</tt>]
130
+ # the date and time identifying the end of the domain object's
131
+ # registration period.
132
+ def domain_renew(domain)
133
+ domain[:curExpDate] = DateTime.parse(domain[:curExpDate]) unless domain[:curExpDate].is_a? DateTime
134
+ response = send_request(domain_renew_xml(domain))
135
+ get_result(:xml => response, :callback => :domain_renew_process)
136
+ end
137
+
138
+ def domain_renew_process(xml) #:nodoc:
139
+ dom = xml.xpath('epp:resData/domain:renData', EPPClient::SCHEMAS_URL)
140
+ ret = {
141
+ name: dom.xpath('domain:name', EPPClient::SCHEMAS_URL).text,
142
+ exDate: DateTime.parse(dom.xpath('domain:exDate', EPPClient::SCHEMAS_URL).text)
143
+ }
144
+ end
145
+
146
+ def domain_update_xml(args) #:nodoc:
147
+ command do |xml|
148
+ xml.update do
149
+ xml.domain :update, 'xmlns:domain' => EPPClient::SCHEMAS_URL['domain-1.1'] do
150
+ xml.domain :name, args[:name]
151
+ [:add, :rem].each do |ar|
152
+ next unless args.key?(ar) && (args[ar].key?(:ns) || args[ar].key?(:contacts) || args[ar].key?(:status))
153
+ xml.domain ar do
154
+ domain_nss_xml(xml, args[ar][:ns]) if args[ar].key? :ns
155
+ domain_contacts_xml(xml, args[ar][:contacts]) if args[ar].key? :contacts
156
+ if args[ar].key? :status
157
+ args[ar][:status].each do |st,text|
158
+ if text.nil?
159
+ xml.domain :status, s: st
160
+ else
161
+ xml.domain :status, { s: st }, text
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
167
+ if args.key?(:chg) && (args[:chg].key?(:registrant) || args[:chg].key?(:authInfo))
168
+ xml.domain :chg do
169
+ xml.domain :registrant, args[:chg][:registrant] if args[:chg].key? :registrant
170
+ if args[:chg].key? :authInfo
171
+ xml.domain :authInfo do
172
+ xml.domain :pw, args[:chg][:authInfo]
173
+ end
174
+ end
175
+ end
176
+ end
177
+ end
178
+ end
179
+ end
180
+ end
181
+
182
+ end
183
+ end
@@ -0,0 +1,223 @@
1
+ require "ipaddr"
2
+
3
+ module EPPClient
4
+ module HostmasterHost
5
+ def host_check_xml(*hosts) #:nodoc:
6
+ command do |xml|
7
+ xml.check do
8
+ xml.host :check, 'xmlns:host' => EPPClient::SCHEMAS_URL['host-1.1'] do
9
+ hosts.each { |host| xml.host :name, host }
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ # Check the availability of hosts
16
+ #
17
+ # takes list of hosts as arguments
18
+ #
19
+ # returns an array of hashes containing three fields :
20
+ # [<tt>:name</tt>] the host name
21
+ # [<tt>:avail</tt>] availability
22
+ # [<tt>:reason</tt>]
23
+ # the server-specific text to help explain why the object cannot be
24
+ # provisioned.
25
+ #
26
+ def host_check(*hosts)
27
+ hosts.flatten!
28
+
29
+ response = send_request(host_check_xml(*hosts))
30
+ get_result(:xml => response, :callback => :host_check_process)
31
+ end
32
+
33
+ def host_check_process(xml) #:nodoc:
34
+ xml.xpath('epp:resData/host:chkData/host:cd', EPPClient::SCHEMAS_URL).map do |dom|
35
+ ret = {
36
+ name: dom.xpath('host:name', EPPClient::SCHEMAS_URL).text,
37
+ avail: dom.xpath('host:name', EPPClient::SCHEMAS_URL).attr('avail').value == '1',
38
+ }
39
+ unless (reason = dom.xpath('host:reason', EPPClient::SCHEMAS_URL).text).empty?
40
+ ret[:reason] = reason
41
+ end
42
+ ret
43
+ end
44
+ end
45
+
46
+ def host_info_xml(args) #:nodoc:
47
+ command do |xml|
48
+ xml.info do
49
+ xml.host :info, 'xmlns:host' => EPPClient::SCHEMAS_URL['host-1.1'] do
50
+ xml.host :name, args[:name]
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ # Returns the informations about a host
57
+ #
58
+ # Takes either a unique argument, either
59
+ # a string, representing the host name
60
+ # or a hash with the following keys :
61
+ # [<tt>:name</tt>] the host name
62
+ #
63
+ # Returned is a hash mapping:
64
+ # [<tt>:name</tt>] host name.
65
+ # [<tt>:roid</tt>]
66
+ # the Repository Object IDentifier assigned to the host object when
67
+ # the object was created.
68
+ # [<tt>:status</tt>] the status or array of statuses of the host object.
69
+ # [<tt>:addrv4</tt>] array with IPv4 addresses.
70
+ # [<tt>:addrv6</tt>] array with IPv6 addresses.
71
+ # [<tt>:clID</tt>] the identifier of the sponsoring client.
72
+ # [<tt>:crID</tt>]
73
+ # the identifier of the client that created the host object.
74
+ # [<tt>:crDate</tt>] the date and time of host object creation.
75
+ # [<tt>:upID</tt>]
76
+ # the optional identifier of the client that last updated the host
77
+ # object.
78
+ # [<tt>:upDate</tt>]
79
+ # the optional date and time of the most recent host object
80
+ # modification.
81
+ # [<tt>:trDate</tt>]
82
+ # the optional date and time of the most recent successful host object
83
+ # transfer.
84
+ def host_info(args)
85
+ args = { name: args } if args.is_a? String
86
+ response = send_request(host_info_xml(args))
87
+ get_result(:xml => response, :callback => :host_info_process)
88
+ end
89
+
90
+ def host_info_process(xml) #:nodoc:
91
+ host = xml.xpath('epp:resData/host:infData', EPPClient::SCHEMAS_URL)
92
+ ret = {
93
+ name: host.xpath('host:name', EPPClient::SCHEMAS_URL).text,
94
+ roid: host.xpath('host:roid', EPPClient::SCHEMAS_URL).text,
95
+ }
96
+ if (status = host.xpath('host:status', EPPClient::SCHEMAS_URL)).size > 0
97
+ ret[:status] = status.map {|s| s.attr('s')}
98
+ end
99
+
100
+ if (value = host.xpath('host:addr', EPPClient::SCHEMAS_URL, ip: 'v4')).size > 0
101
+ ret[:addrv4] = value.map {|ip| IPAddr.new(ip.text)}
102
+ end
103
+ if (value = host.xpath('host:addr', EPPClient::SCHEMAS_URL, ip: 'v6')).size > 0
104
+ ret[:addrv6] = value.map {|ip| IPAddr.new(ip.text)}
105
+ end
106
+
107
+ %w(clID crID upID).each do |val|
108
+ if (value = host.xpath("host:#{val}", EPPClient::SCHEMAS_URL)).size > 0
109
+ ret[val.to_sym] = value.text
110
+ end
111
+ end
112
+ %w(crDate upDate trDate).each do |val|
113
+ if (date = host.xpath("host:#{val}", EPPClient::SCHEMAS_URL)).size > 0
114
+ ret[val.to_sym] = DateTime.parse(date.text)
115
+ end
116
+ end
117
+ ret
118
+ end
119
+
120
+ def host_create_xml(host) #:nodoc:
121
+ command do |xml|
122
+ xml.create do
123
+ xml.host :create, 'xmlns:host' => EPPClient::SCHEMAS_URL['host-1.1'] do
124
+ xml.host :name, host[:name]
125
+ %w(addrv4 addrv6).each do |type|
126
+ next unless host.key? type
127
+ host[type].each {|ip| xml.host :addr, ip}
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
133
+
134
+ # Creates a host
135
+ #
136
+ # Takes a hash as an argument containing the following keys :
137
+ # [<tt>:name</tt>] host name.
138
+ # [<tt>:addrv4</tt>] array with IPv4 addresses.
139
+ # [<tt>:addrv6</tt>] array with IPv6 addresses.
140
+ def host_create(host)
141
+ %w(addrv4 addrv6).each do |type|
142
+ next unless host.key? type
143
+ host[type] = [ host[type] ] unless host[type].is_a? Array
144
+ end
145
+ response = send_request(host_create_xml(host))
146
+ get_result(:xml => response, :callback => :host_create_process)
147
+ end
148
+
149
+ def host_create_process(xml) #:nodoc:
150
+ host = xml.xpath('epp:resData/host:creData', EPPClient::SCHEMAS_URL)
151
+ {
152
+ name: host.xpath('host:name', EPPClient::SCHEMAS_URL).text,
153
+ crDate: DateTime.parse(host.xpath('host:crDate', EPPClient::SCHEMAS_URL).text)
154
+ }
155
+ end
156
+
157
+ def host_delete_xml(host) #:nodoc:
158
+ command do |xml|
159
+ xml.delete do
160
+ xml.host :delete, 'xmlns:host' => EPPClient::SCHEMAS_URL['host-1.1'] do
161
+ xml.host :name, host
162
+ end
163
+ end
164
+ end
165
+ end
166
+
167
+ # Deletes a host
168
+ #
169
+ # Takes a single host for argument.
170
+ #
171
+ # Returns true on success, or raises an exception.
172
+ def host_delete(host)
173
+ response = send_request(host_delete_xml(host))
174
+ get_result(response)
175
+ end
176
+
177
+ def host_update_xml(args) #:nodoc:
178
+ command do |xml|
179
+ xml.update do
180
+ xml.host :update, 'xmlns:host' => EPPClient::SCHEMAS_URL['host-1.1'] do
181
+ xml.host :name, args[:name]
182
+ [:add, :rem].each do |operation|
183
+ if args.key? operation
184
+ xml.host operation do
185
+ args[operation][:status].each {|s| xml.host :status, s: s} if args[operation].key? :status
186
+ %w(addrv4 addrv6).each do |type|
187
+ next unless args[operation].key? type
188
+ args[operation][type].each {|a| xml.host type, a}
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
194
+ end
195
+ end
196
+ end
197
+
198
+ # Updates a host
199
+ #
200
+ # Takes a hash with the name, and at least one of the following keys :
201
+ # [<tt>:name</tt>]
202
+ # the server-unique identifier of the host object to be updated.
203
+ # [<tt>:add</tt>/<tt>:rem</tt>]
204
+ # adds or removes the following data from the host object :
205
+ # [<tt>:addrv4</tt>] an array of IPv4 addresses.
206
+ # [<tt>:addrv6</tt>] an array of IPv6 addresses.
207
+ # [<tt>:status</tt>] an array of status to add to/remove from the object.
208
+ #
209
+ # Returns true on success, or raises an exception.
210
+ def host_update(args)
211
+ [:add, :rem].each do |operation|
212
+ next unless args.key?(operation)
213
+ %w(addrv4 addrv6).each do |type|
214
+ next unless args[operation].key? type
215
+ args[operation][type] = [ args[operation[type]] ] unless args[operation][type].is_a? Array
216
+ end
217
+ end
218
+ response = send_request(host_update_xml(args))
219
+ get_result(response)
220
+ end
221
+
222
+ end
223
+ end
@@ -0,0 +1,27 @@
1
+ module EPPClient
2
+ module HostmasterRGP
3
+ def domain_restore_xml(domain)
4
+ command do |xml|
5
+ xml.update do
6
+ xml.domain :update, 'xmlns:domain' => EPPClient::SCHEMAS_URL['domain-1.1'] do
7
+ xml.domain :name, domain
8
+ end
9
+ end
10
+ xml.extension do
11
+ xml.rgp :update, 'xmlns:rgp' => EPPClient::SCHEMAS_URL['rgp-1.1'] do
12
+ xml.rgp :restore, op: 'request'
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ # Restore a domain
19
+ # Takes a single fully qualified domain name for argument.:
20
+ #
21
+ # Returns an array of rgpStatus.
22
+ def domain_restore(domain)
23
+ response = send_request(domain_restore_xml(domain))
24
+ get_result(:xml => response)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,42 @@
1
+ module EPPClient
2
+ module HostmasterTransfer
3
+ def transfer_xml(domain, op)
4
+ command do |xml|
5
+ xml.transfer op: op do
6
+ xml.domain :transfer, 'xmlns:domain' => EPPClient::SCHEMAS_URL['domain-1.1'] do
7
+ xml.domain :name, domain[:name]
8
+ domain_period_xml(xml, domain[:period]) if domain.key? :period
9
+ if domain.key? :authInfo
10
+ xml.domain :authInfo do
11
+ xml.domain :pw, domain[:authInfo]
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ def transfer(domain, op)
20
+ domain = { name: domain } if domain.is_a? String
21
+ response = send_request(transfer_xml(domain, op))
22
+ get_result(:xml => response, :callback => :transfer_process)
23
+ end
24
+
25
+ %w(request cancel approve reject query).each do |op|
26
+ define_method("transfer_#{op}") { |domain| transfer(domain, op.to_sym) }
27
+ end
28
+
29
+ def transfer_process(xml)
30
+ trn = xml.xpath('epp:resData/domain:trnData', EPPClient::SCHEMAS_URL)
31
+ {
32
+ name: trn.xpath('domain:name', EPPClient::SCHEMAS_URL).text,
33
+ trStatus: trn.xpath('domain:trStatus', EPPClient::SCHEMAS_URL).text,
34
+ reID: trn.xpath('domain:reID', EPPClient::SCHEMAS_URL).text,
35
+ reDate: DateTime.parse(trn.xpath('domain:reDate', EPPClient::SCHEMAS_URL).text),
36
+ acID: trn.xpath('domain:acID', EPPClient::SCHEMAS_URL).text,
37
+ acDate: DateTime.parse(trn.xpath('domain:acDate', EPPClient::SCHEMAS_URL).text),
38
+ exDate: DateTime.parse(trn.xpath('domain:exDate', EPPClient::SCHEMAS_URL).text)
39
+ }
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,7 @@
1
+ module EPPClient
2
+ module HostmasterXML
3
+ def hello
4
+ send_request(builder {|xml| xml.hello})
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,41 @@
1
+ require "epp-client/base"
2
+ require "epp-client/hostmaster-xml"
3
+ require "epp-client/hostmaster-connection"
4
+ require "epp-client/hostmaster-domain"
5
+ require "epp-client/hostmaster-contact"
6
+ require "epp-client/hostmaster-host"
7
+ require "epp-client/hostmaster-rgp"
8
+ require "epp-client/hostmaster-transfer"
9
+
10
+ module EPPClient
11
+ class Hostmaster < Base
12
+ VERSION = '0.2.0'
13
+
14
+ SCHEMAS = %w(domain-1.1 host-1.1 contact-1.1 rgp-1.1)
15
+
16
+ EPPClient::SCHEMAS_URL.merge!(SCHEMAS.inject({}) do |a,s|
17
+ a[s.sub(/-1\.1$/, '')] = "http://hostmaster.ua/epp/#{s}" if s =~ /-1\.1$/
18
+ a[s] = "http://hostmaster.ua/epp/#{s}"
19
+ a
20
+ end)
21
+
22
+ include EPPClient::HostmasterXML
23
+ include EPPClient::HostmasterConnection
24
+ include EPPClient::HostmasterDomain
25
+ include EPPClient::HostmasterContact
26
+ include EPPClient::HostmasterHost
27
+ include EPPClient::HostmasterRGP
28
+ include EPPClient::HostmasterTransfer
29
+
30
+ def initialize(attrs)
31
+ unless attrs.key?(:client_id) && attrs.key?(:password) && attrs.key?(:ssl_cert) && attrs.key?(:ssl_key)
32
+ raise ArgumentError, "client_id, password, ssl_cert and ssl_key are required"
33
+ end
34
+ attrs[:server] ||= 'epp.hostmaster.ua'
35
+ attrs[:port] ||= 700
36
+ attrs[:version] ||= '1.0'
37
+ @services = EPPClient::SCHEMAS_URL.values_at('domain', 'host', 'contact')
38
+ super(attrs)
39
+ end
40
+ end
41
+ end
data/lib/epp-client.rb ADDED
@@ -0,0 +1 @@
1
+ require "epp-client/hostmaster"
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: epp-client-hostmaster
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Yuriy Kolodovskyy
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-19 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: epp-client-base
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 0.11.0
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 0.11.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: builder
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 3.1.4
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 3.1.4
62
+ description: Hostmaster.UA EPP client library
63
+ email:
64
+ - kolodovskyy@ukrindex.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - Gemfile
71
+ - LICENSE.txt
72
+ - README.md
73
+ - Rakefile
74
+ - epp-client-hostmaster.gemspec
75
+ - lib/epp-client.rb
76
+ - lib/epp-client/hostmaster-connection.rb
77
+ - lib/epp-client/hostmaster-contact.rb
78
+ - lib/epp-client/hostmaster-domain.rb
79
+ - lib/epp-client/hostmaster-host.rb
80
+ - lib/epp-client/hostmaster-rgp.rb
81
+ - lib/epp-client/hostmaster-transfer.rb
82
+ - lib/epp-client/hostmaster-xml.rb
83
+ - lib/epp-client/hostmaster.rb
84
+ homepage: https://github.com/kolodovskyy/epp-client-hostmaster
85
+ licenses: []
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 1.8.24
105
+ signing_key:
106
+ specification_version: 3
107
+ summary: Hostmaster.UA EPP client library
108
+ test_files: []