epp-ruby 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +24 -0
  3. data/.simplecov +16 -0
  4. data/.travis.yml +11 -0
  5. data/.yardopts +4 -0
  6. data/CHANGELOG.md +31 -0
  7. data/Gemfile +20 -0
  8. data/Gemfile.lock +51 -0
  9. data/LICENSE +21 -0
  10. data/README.md +95 -0
  11. data/Rakefile +20 -0
  12. data/epp-ruby.gemspec +22 -0
  13. data/examples/contact_create.rb +28 -0
  14. data/examples/domain_check.rb +11 -0
  15. data/examples/domain_create.rb +19 -0
  16. data/examples/domain_info.rb +9 -0
  17. data/examples/host_create.rb +14 -0
  18. data/gemfiles/Gemfile.ruby18 +14 -0
  19. data/lib/epp-client/client.rb +172 -0
  20. data/lib/epp-client/commands/check.rb +11 -0
  21. data/lib/epp-client/commands/command.rb +24 -0
  22. data/lib/epp-client/commands/create.rb +11 -0
  23. data/lib/epp-client/commands/delete.rb +11 -0
  24. data/lib/epp-client/commands/info.rb +11 -0
  25. data/lib/epp-client/commands/login.rb +40 -0
  26. data/lib/epp-client/commands/logout.rb +11 -0
  27. data/lib/epp-client/commands/poll.rb +28 -0
  28. data/lib/epp-client/commands/read_write_command.rb +18 -0
  29. data/lib/epp-client/commands/renew.rb +11 -0
  30. data/lib/epp-client/commands/transfer.rb +25 -0
  31. data/lib/epp-client/commands/transfer_handshake.rb +43 -0
  32. data/lib/epp-client/commands/update.rb +11 -0
  33. data/lib/epp-client/contact/check.rb +23 -0
  34. data/lib/epp-client/contact/check_response.rb +41 -0
  35. data/lib/epp-client/contact/command.rb +106 -0
  36. data/lib/epp-client/contact/create.rb +34 -0
  37. data/lib/epp-client/contact/create_response.rb +14 -0
  38. data/lib/epp-client/contact/delete.rb +21 -0
  39. data/lib/epp-client/contact/delete_response.rb +9 -0
  40. data/lib/epp-client/contact/info.rb +21 -0
  41. data/lib/epp-client/contact/info_response.rb +74 -0
  42. data/lib/epp-client/contact/response.rb +34 -0
  43. data/lib/epp-client/contact/transfer.rb +21 -0
  44. data/lib/epp-client/contact/transfer_response.rb +26 -0
  45. data/lib/epp-client/contact/update.rb +80 -0
  46. data/lib/epp-client/contact/update_response.rb +9 -0
  47. data/lib/epp-client/domain/check.rb +23 -0
  48. data/lib/epp-client/domain/check_response.rb +41 -0
  49. data/lib/epp-client/domain/command.rb +92 -0
  50. data/lib/epp-client/domain/create.rb +75 -0
  51. data/lib/epp-client/domain/create_response.rb +29 -0
  52. data/lib/epp-client/domain/delete.rb +21 -0
  53. data/lib/epp-client/domain/delete_response.rb +9 -0
  54. data/lib/epp-client/domain/info.rb +21 -0
  55. data/lib/epp-client/domain/info_response.rb +72 -0
  56. data/lib/epp-client/domain/list.rb +36 -0
  57. data/lib/epp-client/domain/renew.rb +38 -0
  58. data/lib/epp-client/domain/renew_response.rb +14 -0
  59. data/lib/epp-client/domain/response.rb +34 -0
  60. data/lib/epp-client/domain/transfer.rb +37 -0
  61. data/lib/epp-client/domain/transfer_response.rb +29 -0
  62. data/lib/epp-client/domain/update.rb +81 -0
  63. data/lib/epp-client/domain/update_response.rb +9 -0
  64. data/lib/epp-client/host/check.rb +23 -0
  65. data/lib/epp-client/host/check_response.rb +41 -0
  66. data/lib/epp-client/host/command.rb +47 -0
  67. data/lib/epp-client/host/create.rb +24 -0
  68. data/lib/epp-client/host/create_response.rb +14 -0
  69. data/lib/epp-client/host/delete.rb +21 -0
  70. data/lib/epp-client/host/delete_response.rb +9 -0
  71. data/lib/epp-client/host/info.rb +21 -0
  72. data/lib/epp-client/host/info_response.rb +42 -0
  73. data/lib/epp-client/host/response.rb +34 -0
  74. data/lib/epp-client/host/update.rb +76 -0
  75. data/lib/epp-client/host/update_response.rb +9 -0
  76. data/lib/epp-client/old_server.rb +25 -0
  77. data/lib/epp-client/request.rb +51 -0
  78. data/lib/epp-client/requests/abstract.rb +30 -0
  79. data/lib/epp-client/requests/command.rb +28 -0
  80. data/lib/epp-client/requests/extension.rb +28 -0
  81. data/lib/epp-client/requests/hello.rb +12 -0
  82. data/lib/epp-client/response.rb +100 -0
  83. data/lib/epp-client/response_error.rb +15 -0
  84. data/lib/epp-client/response_helper.rb +25 -0
  85. data/lib/epp-client/server.rb +330 -0
  86. data/lib/epp-client/testing.rb +59 -0
  87. data/lib/epp-client/version.rb +3 -0
  88. data/lib/epp-client/xml_helper.rb +71 -0
  89. data/lib/epp-client.rb +103 -0
  90. data/lib/epp-ruby.rb +1 -0
  91. data/test/commands/test_check_command.rb +33 -0
  92. data/test/commands/test_create_command.rb +53 -0
  93. data/test/commands/test_delete_command.rb +28 -0
  94. data/test/commands/test_info_command.rb +28 -0
  95. data/test/commands/test_login_command.rb +56 -0
  96. data/test/commands/test_logout_command.rb +22 -0
  97. data/test/commands/test_poll_command.rb +54 -0
  98. data/test/commands/test_renew_command.rb +39 -0
  99. data/test/commands/test_transfer_command.rb +37 -0
  100. data/test/commands/test_update_command.rb +60 -0
  101. data/test/contact/test_contact_check.rb +33 -0
  102. data/test/contact/test_contact_check_response.rb +88 -0
  103. data/test/contact/test_contact_create.rb +71 -0
  104. data/test/contact/test_contact_create_response.rb +33 -0
  105. data/test/contact/test_contact_delete.rb +28 -0
  106. data/test/contact/test_contact_delete_response.rb +23 -0
  107. data/test/contact/test_contact_info.rb +28 -0
  108. data/test/contact/test_contact_info_response.rb +100 -0
  109. data/test/contact/test_contact_transfer.rb +28 -0
  110. data/test/contact/test_contact_transfer_response.rb +100 -0
  111. data/test/contact/test_contact_update.rb +84 -0
  112. data/test/contact/test_contact_update_response.rb +23 -0
  113. data/test/domain/test_domain_check.rb +33 -0
  114. data/test/domain/test_domain_check_response.rb +88 -0
  115. data/test/domain/test_domain_create.rb +108 -0
  116. data/test/domain/test_domain_create_response.rb +70 -0
  117. data/test/domain/test_domain_delete.rb +28 -0
  118. data/test/domain/test_domain_delete_response.rb +23 -0
  119. data/test/domain/test_domain_info.rb +28 -0
  120. data/test/domain/test_domain_info_response.rb +146 -0
  121. data/test/domain/test_domain_renew.rb +91 -0
  122. data/test/domain/test_domain_renew_response.rb +32 -0
  123. data/test/domain/test_domain_transfer.rb +89 -0
  124. data/test/domain/test_domain_transfer_response.rb +112 -0
  125. data/test/domain/test_domain_update.rb +73 -0
  126. data/test/domain/test_domain_update_response.rb +23 -0
  127. data/test/fixtures/responses/contact/check-single.xml +20 -0
  128. data/test/fixtures/responses/contact/check.xml +27 -0
  129. data/test/fixtures/responses/contact/create.xml +19 -0
  130. data/test/fixtures/responses/contact/delete.xml +12 -0
  131. data/test/fixtures/responses/contact/info.xml +49 -0
  132. data/test/fixtures/responses/contact/transfer-query.xml +23 -0
  133. data/test/fixtures/responses/contact/transfer-request.xml +23 -0
  134. data/test/fixtures/responses/contact/update.xml +12 -0
  135. data/test/fixtures/responses/domain/check-single.xml +20 -0
  136. data/test/fixtures/responses/domain/check.xml +27 -0
  137. data/test/fixtures/responses/domain/create-pending.xml +12 -0
  138. data/test/fixtures/responses/domain/create.xml +20 -0
  139. data/test/fixtures/responses/domain/delete.xml +12 -0
  140. data/test/fixtures/responses/domain/info-no-exDate.xml +38 -0
  141. data/test/fixtures/responses/domain/info-ns-hostAttr-name-only.xml +34 -0
  142. data/test/fixtures/responses/domain/info-ns-hostAttr.xml +38 -0
  143. data/test/fixtures/responses/domain/info.xml +40 -0
  144. data/test/fixtures/responses/domain/renew.xml +19 -0
  145. data/test/fixtures/responses/domain/transfer-query.xml +24 -0
  146. data/test/fixtures/responses/domain/transfer-request.xml +24 -0
  147. data/test/fixtures/responses/domain/update.xml +12 -0
  148. data/test/fixtures/responses/greeting.xml +25 -0
  149. data/test/fixtures/responses/host/check-single.xml +20 -0
  150. data/test/fixtures/responses/host/check.xml +27 -0
  151. data/test/fixtures/responses/host/create.xml +19 -0
  152. data/test/fixtures/responses/host/delete.xml +12 -0
  153. data/test/fixtures/responses/host/info.xml +30 -0
  154. data/test/fixtures/responses/host/update.xml +12 -0
  155. data/test/helper.rb +100 -0
  156. data/test/host/test_host_check.rb +33 -0
  157. data/test/host/test_host_check_response.rb +88 -0
  158. data/test/host/test_host_create.rb +37 -0
  159. data/test/host/test_host_create_response.rb +33 -0
  160. data/test/host/test_host_delete.rb +28 -0
  161. data/test/host/test_host_delete_response.rb +23 -0
  162. data/test/host/test_host_info.rb +28 -0
  163. data/test/host/test_host_info_response.rb +72 -0
  164. data/test/host/test_host_update.rb +68 -0
  165. data/test/host/test_host_update_response.rb +23 -0
  166. data/test/requests/test_command_request.rb +16 -0
  167. data/test/requests/test_extension_request.rb +55 -0
  168. data/test/requests/test_hello_request.rb +15 -0
  169. data/test/support/schemas/all.xsd +21 -0
  170. data/test/support/schemas/contact-1.0.xsd +387 -0
  171. data/test/support/schemas/domain-1.0.xsd +432 -0
  172. data/test/support/schemas/epp-1.0.xsd +403 -0
  173. data/test/support/schemas/eppcom-1.0.xsd +93 -0
  174. data/test/support/schemas/host-1.0.xsd +240 -0
  175. data/test/test_client.rb +64 -0
  176. data/test/test_request.rb +15 -0
  177. data/test/test_server.rb +67 -0
  178. metadata +322 -0
@@ -0,0 +1,80 @@
1
+ require File.expand_path('../command', __FILE__)
2
+
3
+ module EPP
4
+ module Contact
5
+ class Update < Command
6
+ ADD_REM_ORDER = [:status]
7
+ CHG_ORDER = [:postal_info, :voice, :fax, :email, :auth_info, :disclose]
8
+
9
+ # @option [Hash] :status A Hash of status value to text. Text may optionally be an array in the form ["Text", "lang"] if a custom language value needs to be set.
10
+ def initialize(id, options = {})
11
+ @id = id
12
+ @add = options.delete(:add) || {}
13
+ @rem = options.delete(:rem) || {}
14
+ @chg = options.delete(:chg) || {}
15
+
16
+ @add.delete_if { |k,_| !ADD_REM_ORDER.include?(k) }
17
+ @rem.delete_if { |k,_| !ADD_REM_ORDER.include?(k) }
18
+ @chg.delete_if { |k,_| !CHG_ORDER.include?(k) }
19
+ end
20
+
21
+ def name
22
+ 'update'
23
+ end
24
+
25
+ def to_xml
26
+ node = super
27
+ node << contact_node('id', @id)
28
+
29
+ unless @add.empty?
30
+ node << add = contact_node('add')
31
+ add_rem_to_xml(add, @add)
32
+ end
33
+
34
+ unless @rem.empty?
35
+ node << rem = contact_node('rem')
36
+ add_rem_to_xml(rem, @rem)
37
+ end
38
+
39
+ unless @chg.empty?
40
+ node << chg = contact_node('chg')
41
+ CHG_ORDER.each do |key|
42
+ value = @chg[key]
43
+ next if value.nil? || value.empty?
44
+
45
+ case key
46
+ when :postal_info
47
+ chg << postal_info_to_xml(value)
48
+ when :auth_info
49
+ chg << auth_info_to_xml(value)
50
+ when :disclose
51
+ chg << disclose_to_xml(value)
52
+ when :voice, :fax, :email
53
+ chg << contact_node(key.to_s, value)
54
+ end
55
+ end
56
+ end
57
+
58
+ node
59
+ end
60
+
61
+ protected
62
+ def add_rem_to_xml(node, hash)
63
+ ADD_REM_ORDER.each do |key|
64
+ value = hash[key]
65
+ next if value.nil? || value.empty?
66
+
67
+ case key
68
+ when :status
69
+ value.each do |status, text|
70
+ text, lang = Array(text)
71
+ node << s = contact_node('status', text)
72
+ s['lang'] = lang if lang
73
+ s['s'] = status.to_s
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,9 @@
1
+ require File.expand_path('../response', __FILE__)
2
+
3
+ module EPP
4
+ module Contact
5
+ class UpdateResponse < Response
6
+
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,23 @@
1
+ require File.expand_path('../command', __FILE__)
2
+
3
+ module EPP
4
+ module Domain
5
+ class Check < Command
6
+ def initialize(*names)
7
+ @names = names.flatten
8
+ end
9
+
10
+ def name
11
+ 'check'
12
+ end
13
+
14
+ def to_xml
15
+ node = super
16
+ @names.each do |name|
17
+ node << domain_node('name', name)
18
+ end
19
+ node
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,41 @@
1
+ require File.expand_path('../response', __FILE__)
2
+
3
+ module EPP
4
+ module Domain
5
+ class CheckResponse < Response
6
+ def available?(name = nil)
7
+ return availability[name] if name
8
+
9
+ if name.nil? && availability.count == 1
10
+ return availability.values.first
11
+ end
12
+
13
+ raise ArgumentError, "name must be specified if more than one domain checked"
14
+ end
15
+ def unavailable?(name = nil)
16
+ !available?(name)
17
+ end
18
+
19
+ def names
20
+ availability.keys
21
+ end
22
+
23
+ def name
24
+ raise "name unavailable when more than one domain checked, use #names" if count != 1
25
+ names.first
26
+ end
27
+
28
+ def count
29
+ availability.count
30
+ end
31
+
32
+ protected
33
+ def availability
34
+ @availability ||= nodes_for_xpath('//domain:name').inject({}) do |hash, node|
35
+ hash[node.content.strip] = node['avail'] == '1'
36
+ hash
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,92 @@
1
+ module EPP
2
+ module Domain
3
+ class Command
4
+ include XMLHelpers
5
+ attr_reader :namespaces
6
+
7
+ def set_namespaces(namespaces)
8
+ @namespaces = namespaces
9
+ end
10
+
11
+ def name
12
+ raise NotImplementedError, "#name must be implemented in subclasses"
13
+ end
14
+
15
+ def to_xml
16
+ @namespaces ||= {}
17
+ node = domain_node(name)
18
+
19
+ xattr = XML::Attr.new(node, "schemaLocation", SCHEMA_LOCATION)
20
+ xattr.namespaces.namespace = @namespaces['xsi'] || XML::Namespace.new(node, 'xsi', 'http://www.w3.org/2001/XMLSchema-instance')
21
+
22
+ node
23
+ end
24
+
25
+ protected
26
+ def domain_node(name, value = nil)
27
+ node = xml_node(name, value)
28
+ node.namespaces.namespace = domain_namespace(node)
29
+ node
30
+ end
31
+ def domain_namespace(node)
32
+ return @namespaces['domain'] if @namespaces.has_key?('domain')
33
+ @namespaces['domain'] = xml_namespace(node, 'domain', NAMESPACE)
34
+ end
35
+
36
+ def validate_period(period)
37
+ unit = period[-1,1].downcase
38
+ val = period.to_i
39
+
40
+ raise ArgumentError, "period suffix must either be 'm' or 'y'" unless %w(m y).include?(unit)
41
+ raise ArgumentError, "period value must be in the range 1-99" if val < 1 || val > 99
42
+
43
+ return val.to_s, unit
44
+ end
45
+
46
+ def auth_info_to_xml(auth_info)
47
+ a = domain_node('authInfo')
48
+
49
+ if auth_info.has_key?(:pw)
50
+ a << pw = domain_node('pw', auth_info[:pw])
51
+ pw['roid'] = auth_info[:roid] if auth_info.has_key?(:roid)
52
+ elsif auth_info.has_key?(:ext)
53
+ a << domain_node('ext', auth_info[:ext])
54
+ end
55
+
56
+ a
57
+ end
58
+
59
+ def nameservers_to_xml(nameservers)
60
+ ns = domain_node('ns')
61
+
62
+ nameservers.each do |nameserver|
63
+ case nameserver
64
+ when String
65
+ ns << domain_node('hostObj', nameserver)
66
+ when Hash
67
+ ns << hostAttr = domain_node('hostAttr')
68
+ hostAttr << domain_node('hostName', nameserver[:name])
69
+ Array(nameserver[:ipv4]).each do |addr|
70
+ hostAttr << a = domain_node('hostAddr', addr)
71
+ a['ip'] = 'v4'
72
+ end
73
+ Array(nameserver[:ipv6]).each do |addr|
74
+ hostAttr << a = domain_node('hostAddr', addr)
75
+ a['ip'] = 'v6'
76
+ end
77
+ end
78
+ end
79
+
80
+ ns
81
+ end
82
+ def contacts_to_xml(node, contacts)
83
+ return if contacts.nil?
84
+ contacts.each do |type, roid|
85
+ next unless %w(admin tech billing).include?(type.to_s)
86
+ node << c = domain_node('contact', roid)
87
+ c['type'] = type.to_s
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,75 @@
1
+ require File.expand_path('../command', __FILE__)
2
+
3
+ module EPP
4
+ module Domain
5
+ class Create < Command
6
+ # Domain creation command.
7
+ #
8
+ # @param [String] name Name of domain to create
9
+ # @param [Hash] options Options to use to create the domain
10
+ # @option options [String] period Years or months period to create the domain for
11
+ # @option options [Array<String,Hash>] Array or hash of nameservers
12
+ # @option options [String] registrant Contact handle to use as registrant
13
+ # @option options [Hash<Symbol,String>] contacts Hash of admin, tech, billing contacts
14
+ # @option options [Hash<Symbol,String>] auth_info Hash of auth info
15
+ # @return [EPP::Domain::Create]
16
+ #
17
+ # @example Create a domain
18
+ # command = EPP::Domain::Create.new('example.com',
19
+ # period: '1y', registrant: 'test9023742684',
20
+ # auth_info: { pw: 'domainpassword' },
21
+ # contacts: { admin: 'admin123', tech: 'admin123', billing: 'admin123' },
22
+ # nameservers: ['ns1.test.host', 'ns2.test.host']
23
+ # )
24
+ #
25
+ # @example Create a domain with nameserver glue
26
+ # command = EPP::Domain::Create.new('example.com',
27
+ # period: '1y', registrant: 'test9023742684',
28
+ # auth_info: { pw: 'domainpassword' },
29
+ # contacts: { admin: 'admin123', tech: 'admin123', billing: 'admin123' },
30
+ # nameservers: [
31
+ # {name: 'ns1.example.com', ipv4: '198.51.100.53'}
32
+ # {name: 'ns2.example.com', ipv4: '198.51.100.54'}
33
+ # ]
34
+ # )
35
+ def initialize(name, options = {})
36
+ @name = name
37
+ @period = options.delete(:period) || '1y'
38
+ @nameservers = Array(options.delete(:nameservers))
39
+ @registrant = options.delete(:registrant)
40
+ @contacts = options.delete(:contacts)
41
+ @auth_info = options.delete(:auth_info)
42
+
43
+ @period_val, @period_unit = validate_period(@period)
44
+ end
45
+
46
+ def name
47
+ 'create'
48
+ end
49
+
50
+ def to_xml
51
+ node = super
52
+ node << domain_node('name', @name)
53
+
54
+ if @period_val && @period_unit
55
+ p = domain_node('period', @period_val)
56
+ p['unit'] = @period_unit
57
+
58
+ node << p
59
+ end
60
+
61
+ unless @nameservers.empty?
62
+ node << nameservers_to_xml(@nameservers)
63
+ end
64
+
65
+ node << domain_node('registrant', @registrant) if @registrant
66
+
67
+ contacts_to_xml(node, @contacts)
68
+
69
+ node << auth_info_to_xml(@auth_info) unless @auth_info.empty?
70
+
71
+ node
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,29 @@
1
+ require File.expand_path('../response', __FILE__)
2
+
3
+ module EPP
4
+ module Domain
5
+ class CreateResponse < Response
6
+ # Return the name of the domain created if successful
7
+ #
8
+ # @return [String] Name of created domain
9
+ def name
10
+ return nil unless success?
11
+ @name ||= value_for_xpath('//domain:name')
12
+ end
13
+ # Return the creation/registration date of the domain if the request was successful.
14
+ #
15
+ # @return [Time] Registration time
16
+ def creation_date
17
+ return nil unless success?
18
+ @crdate ||= value_for_xpath('//domain:crDate') && Time.parse(value_for_xpath('//domain:crDate'))
19
+ end
20
+ # Return the expiration date of the domain if the request was successful.
21
+ #
22
+ # @return [Time] Expiration time
23
+ def expiration_date
24
+ return nil unless success?
25
+ @exdate ||= value_for_xpath('//domain:exDate') && Time.parse(value_for_xpath('//domain:exDate'))
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,21 @@
1
+ require File.expand_path('../command', __FILE__)
2
+
3
+ module EPP
4
+ module Domain
5
+ class Delete < Command
6
+ def initialize(name)
7
+ @name = name
8
+ end
9
+
10
+ def name
11
+ 'delete'
12
+ end
13
+
14
+ def to_xml
15
+ node = super
16
+ node << domain_node('name', @name)
17
+ node
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,9 @@
1
+ require File.expand_path('../response', __FILE__)
2
+
3
+ module EPP
4
+ module Domain
5
+ class DeleteResponse < Response
6
+
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,21 @@
1
+ require File.expand_path('../command', __FILE__)
2
+
3
+ module EPP
4
+ module Domain
5
+ class Info < Command
6
+ def initialize(name)
7
+ @name = name
8
+ end
9
+
10
+ def name
11
+ 'info'
12
+ end
13
+
14
+ def to_xml
15
+ node = super
16
+ node << domain_node('name', @name)
17
+ node
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,72 @@
1
+ require File.expand_path('../response', __FILE__)
2
+
3
+ module EPP
4
+ module Domain
5
+ class InfoResponse < Response
6
+ def name
7
+ @name ||= value_for_xpath('//domain:name')
8
+ end
9
+ def roid
10
+ @roid ||= value_for_xpath('//domain:roid')
11
+ end
12
+ def status
13
+ @status ||= values_for_xpath('//domain:status/@s')
14
+ end
15
+ def registrant
16
+ @registrant ||= value_for_xpath('//domain:registrant')
17
+ end
18
+ def contacts
19
+ @contacts ||= nodes_for_xpath('//domain:contact').inject({}) do |hash, node|
20
+ hash[node['type'].to_s] = node.content.strip
21
+ hash
22
+ end
23
+ end
24
+ def nameservers
25
+ @nameservers ||= nodes_for_xpath('//domain:ns').map do |ns_node|
26
+ ns = ns_node.find('domain:hostAttr', namespaces).map do |hostAttr|
27
+ name_node = hostAttr.find('domain:hostName').first
28
+ ipv4_node = hostAttr.find('domain:hostAddr[@ip="v4"]').first
29
+ ipv6_node = hostAttr.find('domain:hostAddr[@ip="v6"]').first
30
+
31
+ {}.tap do |result|
32
+ result['name']= name_node.content.strip if name_node
33
+ result['ipv4']= ipv4_node.content.strip if ipv4_node
34
+ result['ipv6']= ipv6_node.content.strip if ipv6_node
35
+ end
36
+ end
37
+
38
+ ns + ns_node.find('domain:hostObj').map { |n| { 'name' => n.content.strip } }
39
+ end.flatten
40
+ end
41
+ def hosts
42
+ @hosts ||= values_for_xpath('//domain:host')
43
+ end
44
+ def client_id
45
+ @clid ||= value_for_xpath('//domain:clID')
46
+ end
47
+ def creator_id
48
+ @crid ||= value_for_xpath('//domain:crID')
49
+ end
50
+ def created_date
51
+ @crdate ||= value_for_xpath('//domain:crDate') && Time.parse(value_for_xpath('//domain:crDate'))
52
+ end
53
+ def updator_id
54
+ @upid ||= value_for_xpath('//domain:upID')
55
+ end
56
+ def updated_date
57
+ @update ||= value_for_xpath('//domain:upDate') && Time.parse(value_for_xpath('//domain:upDate'))
58
+ end
59
+ def expiration_date
60
+ @exdate ||= value_for_xpath('//domain:exDate') && Time.parse(value_for_xpath('//domain:exDate'))
61
+ end
62
+ def transfer_date
63
+ @trdate ||= value_for_xpath('//domain:trDate') && Time.parse(value_for_xpath('//domain:trDate'))
64
+ end
65
+ def auth_info
66
+ @auth_info ||= begin
67
+ { 'pw' => value_for_xpath('//domain:authInfo/domain:pw') }
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,36 @@
1
+ require File.expand_path('../command', __FILE__)
2
+
3
+ module EPP
4
+ module Domain
5
+ class List < Command
6
+ def initialize(expire_date)
7
+ @expire_date = expire_date
8
+ end
9
+
10
+ def name
11
+ 'info'
12
+ end
13
+
14
+ def to_xml
15
+ @namespaces ||= {}
16
+ node = super
17
+ node << list_node
18
+ node
19
+ end
20
+
21
+ private
22
+
23
+ def list_node
24
+ node = xml_node('list')
25
+ node.namespaces.namespace = list_namespace(node)
26
+ node << xml_node('l:expiry', "#{@expire_date.year}-#{@expire_date.month}")
27
+ node
28
+ end
29
+
30
+ def list_namespace(node)
31
+ return @namespaces['l'] if @namespaces.has_key?('l')
32
+ @namespaces['l'] = xml_namespace(node, 'l', 'xmlns:l="http://www.nominet.org.uk/epp/xml/std-list-1.0')
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,38 @@
1
+ require File.expand_path('../command', __FILE__)
2
+
3
+ module EPP
4
+ module Domain
5
+ class Renew < Command
6
+ # @param [String] name Domain name to renew
7
+ # @param [Time,String] exp_date Expiration date of the domain
8
+ # @param [String] period Renewal period in XXy years or XXm months. XX must be between 1 and 99.
9
+ def initialize(name, exp_date, period = nil)
10
+ @name, @exp_date = name, exp_date
11
+ @exp_date = Time.parse(exp_date) if exp_date.kind_of?(String)
12
+
13
+ if period
14
+ @period_val, @period_unit = validate_period(period)
15
+ end
16
+ end
17
+
18
+ def name
19
+ 'renew'
20
+ end
21
+
22
+ def to_xml
23
+ node = super
24
+ node << domain_node('name', @name)
25
+ node << domain_node('curExpDate', @exp_date.strftime("%Y-%m-%d"))
26
+
27
+ if @period_val && @period_unit
28
+ p = domain_node('period', @period_val)
29
+ p['unit'] = @period_unit
30
+
31
+ node << p
32
+ end
33
+
34
+ node
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,14 @@
1
+ require File.expand_path('../response', __FILE__)
2
+
3
+ module EPP
4
+ module Domain
5
+ class RenewResponse < Response
6
+ def name
7
+ @name ||= value_for_xpath('//domain:name')
8
+ end
9
+ def expiration_date
10
+ @date ||= value_for_xpath('//domain:exDate') && Time.parse(value_for_xpath('//domain:exDate'))
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,34 @@
1
+ module EPP
2
+ module Domain
3
+ class Response
4
+ include ResponseHelper
5
+
6
+ def initialize(response)
7
+ @response = response
8
+ end
9
+
10
+ def method_missing(meth, *args, &block)
11
+ return super unless @response.respond_to?(meth)
12
+ @response.send(meth, *args, &block)
13
+ end
14
+
15
+ def respond_to_missing?(method, include_private)
16
+ @response.respond_to?(method, include_private)
17
+ end
18
+
19
+ unless RUBY_VERSION >= "1.9.2"
20
+ def respond_to?(method, include_private = false)
21
+ respond_to_missing?(method, include_private) || super
22
+ end
23
+ def method(sym)
24
+ respond_to_missing?(sym, true) ? @response.method(sym) : super
25
+ end
26
+ end
27
+
28
+ protected
29
+ def namespaces
30
+ {'domain' => NAMESPACE}
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,37 @@
1
+ require File.expand_path('../command', __FILE__)
2
+
3
+ module EPP
4
+ module Domain
5
+ class Transfer < Command
6
+ # @auth_info[:ext] should be an XML::Node with whatever is required
7
+ def initialize(name, period = nil, auth_info = {})
8
+ @name = name
9
+ @auth_info = auth_info
10
+
11
+ if period
12
+ @period_val, @period_unit = validate_period(period)
13
+ end
14
+ end
15
+
16
+ def name
17
+ 'transfer'
18
+ end
19
+
20
+ def to_xml
21
+ node = super
22
+ node << domain_node('name', @name)
23
+
24
+ if @period_val && @period_unit
25
+ p = domain_node('period', @period_val)
26
+ p['unit'] = @period_unit
27
+
28
+ node << p
29
+ end
30
+
31
+ node << auth_info_to_xml(@auth_info) unless @auth_info.empty?
32
+
33
+ node
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,29 @@
1
+ require File.expand_path('../response', __FILE__)
2
+
3
+ module EPP
4
+ module Domain
5
+ class TransferResponse < Response
6
+ def name
7
+ @name ||= value_for_xpath('//domain:name')
8
+ end
9
+ def status
10
+ @trStatus ||= value_for_xpath('//domain:trStatus')
11
+ end
12
+ def requested_id
13
+ @reID ||= value_for_xpath('//domain:reID')
14
+ end
15
+ def requested_date
16
+ @reDate ||= value_for_xpath('//domain:reDate') && Time.parse(value_for_xpath('//domain:reDate'))
17
+ end
18
+ def expiration_date
19
+ @exDate ||= value_for_xpath('//domain:exDate') && Time.parse(value_for_xpath('//domain:exDate'))
20
+ end
21
+ def action_id
22
+ @acID ||= value_for_xpath('//domain:acID')
23
+ end
24
+ def action_date
25
+ @acDate ||= value_for_xpath('//domain:acDate') && Time.parse(value_for_xpath('//domain:acDate'))
26
+ end
27
+ end
28
+ end
29
+ end