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,100 @@
1
+ module EPP
2
+ # An EPP XML Response
3
+ class Response
4
+ # Creates an instance of an EPP::Response
5
+ #
6
+ # @param [String] xml_string XML Response
7
+ def initialize(xml_string)
8
+ @xml = XML::Parser.string(xml_string).parse
9
+ @xml.root.namespaces.default_prefix = 'e'
10
+ end
11
+
12
+ # Indicates if the response is successful.
13
+ # @return [Boolean] if the response is successful
14
+ def success?
15
+ code == 1000
16
+ end
17
+
18
+ def pending?
19
+ code == 1001
20
+ end
21
+
22
+ # Response code
23
+ # @return [Integer] response code
24
+ def code
25
+ @code ||= result['code'].to_i
26
+ end
27
+
28
+ # Response message
29
+ # @return [String] response message
30
+ def message
31
+ @message ||= result.find('e:msg/text()').first.content.strip
32
+ end
33
+
34
+ # Descriptive Error Information
35
+ # @return [XML::Node] error information
36
+ def error_value
37
+ @error_value ||= result.find('e:extValue/e:value/node()').first
38
+ end
39
+
40
+ # Error reason
41
+ # @return [String] error reason
42
+ def error_reason
43
+ unless defined?(@error_reason)
44
+ reason = result.find('e:extValue/e:reason/text()').first
45
+ @error_reason = reason && reason.content.strip
46
+ end
47
+
48
+ @error_reason
49
+ end
50
+
51
+ # Response data
52
+ # @return [XML::Node, Array<XML::Node>] response data
53
+ def data
54
+ @data ||= begin
55
+ list = @xml.find('/e:epp/e:response/e:resData/node()').reject { |n| n.empty? }
56
+ list.size > 1 ? list : list[0]
57
+ end
58
+ end
59
+
60
+ # Response Message Queue
61
+ # @return [XML::Node] message queue
62
+ def msgQ
63
+ @msgQ ||= @xml.find('/e:epp/e:response/e:msgQ').first
64
+ end
65
+
66
+ # Response extension block
67
+ # @return [XML::Node, Array<XML::Node>] extension
68
+ def extension
69
+ @extension ||= begin
70
+ list = @xml.find('/e:epp/e:response/e:extension/node()').reject { |n| n.empty? }
71
+ list.size > 1 ? list : list[0]
72
+ end
73
+ end
74
+
75
+ # @see Object#inspect
76
+ def inspect
77
+ @xml.inspect
78
+ end
79
+
80
+ # Returns the XML response document
81
+ # @return [XML::Document] XML response document
82
+ def to_xml
83
+ @xml
84
+ end
85
+
86
+ # Convert the receiver to a string
87
+ #
88
+ # @param [Hash] opts Formatting options, passed to the XML::Document
89
+ # @return [String] formatted XML response
90
+ def to_s(opts = {})
91
+ @xml.to_s({:indent => false}.merge(opts))
92
+ end
93
+
94
+ private
95
+ # @return [XML::Node] Result node
96
+ def result
97
+ @result ||= @xml.find('/e:epp/e:response/e:result').first
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,15 @@
1
+ module EPP
2
+ # Error response
3
+ class ResponseError < RuntimeError
4
+ attr_accessor :code, :xml
5
+ # Create new ResponseError
6
+ def initialize(code, msg, xml)
7
+ super(msg)
8
+ @code, @xml = code, xml
9
+ end
10
+ # @return [String] Formatted Response error
11
+ def message
12
+ "#{to_s} (code #{code})"
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,25 @@
1
+ module EPP
2
+ module ResponseHelper
3
+ def value_for_xpath(xpath, base = nil, &block)
4
+ values_for_xpath(xpath, base, &block).first
5
+ end
6
+ def values_for_xpath(xpath, base = nil)
7
+ nodes_for_xpath(xpath, base).map do |node|
8
+ if block_given?
9
+ yield node
10
+ else
11
+ case node
12
+ when XML::Node
13
+ node.content.strip
14
+ when XML::Attr
15
+ node.value
16
+ end
17
+ end
18
+ end
19
+ end
20
+ def nodes_for_xpath(xpath, base = nil)
21
+ base ||= @response.data
22
+ base.find(xpath, namespaces)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,330 @@
1
+ module EPP
2
+ # A server error
3
+ class ServerError < Error; end
4
+
5
+ # A connection error
6
+ class ConnectionError < Error
7
+ attr_reader :error, :addr, :peeraddr
8
+ def initialize(message, addr, peeraddr, error)
9
+ super(message)
10
+ @error = error
11
+ @addr = addr
12
+ @peeraddr = peeraddr
13
+ end
14
+ end
15
+
16
+ # Handles sending and receiving data to EPP servers.
17
+ # Supports new style EPP servers which include length of payloads in transmission.
18
+ class Server
19
+ # @!attribute DEFAULT_SERVICES
20
+ # Provided for legacy clients who might be using it.
21
+ # The constant has been moved into the EPP::Client class which
22
+ # is the primary client facing API.
23
+ #
24
+ # @deprecated please use EPP::Client::DEFAULT_SERVICES
25
+ # @see EPP::Client::DEFAULT_SERVICES
26
+
27
+ # Handles emitting warnings for deprecated constants.
28
+ #
29
+ # @private
30
+ # @param [Symbol] const_name Name of the missing constant
31
+ # @see Module.const_missing
32
+ def self.const_missing(const_name)
33
+ case const_name
34
+ when :DEFAULT_SERVICES
35
+ warn "EPP::Server::DEFAULT_SERVICES has been deprecated, please use EPP::Client::DEFAULT_SERVICES"
36
+ EPP::Client::DEFAULT_SERVICES
37
+ else
38
+ super
39
+ end
40
+ end
41
+
42
+ # Default connection options
43
+ DEFAULTS = { :port => 700, :compatibility => false, :lang => 'en', :version => '1.0',
44
+ :extensions => [], :services => EPP::Client::DEFAULT_SERVICES, :address_family => nil }
45
+
46
+ # Receive frame header length
47
+ # @private
48
+ HEADER_LEN = 4
49
+
50
+ # @param [String] tag EPP Tag
51
+ # @param [String] passwd EPP Tag password
52
+ # @param [String] host EPP Server address
53
+ # @param [Hash] options configuration options
54
+ # @option options [Integer] :port EPP Port number, default 700
55
+ # @option options [OpenSSL::SSL::SSLContext] :ssl_context For client certificate auth
56
+ # @option options [Boolean] :compatibility Compatibility mode, default false
57
+ # @option options [String] :lang EPP Language code, default 'en'
58
+ # @option options [String] :version EPP protocol version, default '1.0'
59
+ # @option options [Array<String>] :extensions EPP Extension URNs
60
+ # @option options [Array<String>] :services EPP Service URNs
61
+ # @option options [String] :address_family 'AF_INET' or 'AF_INET6' or either of the
62
+ # appropriate socket constants. Will cause connections to be
63
+ # limited to this address family. Default try all addresses.
64
+
65
+ def initialize(tag, passwd, host, options = {})
66
+ @tag, @passwd, @host = tag, passwd, host
67
+ @options = DEFAULTS.merge(options)
68
+ end
69
+
70
+ # Sends a Hello Request to the server
71
+ # @return [Boolean] True if greeting was returned
72
+ def hello
73
+ hello = EPP::Requests::Hello.new
74
+ request = EPP::Request.new(hello)
75
+ send_frame(request)
76
+ return true if recv_frame =~ /<greeting>/
77
+ false
78
+ end
79
+
80
+ # Send request to server
81
+ #
82
+ # @overload request(command, payload)
83
+ # @param [String, #to_s] command EPP Command to call
84
+ # @param [XML::Node, XML::Document, String] payload EPP XML Payload
85
+ # @overload request(command)
86
+ # @param [String, #to_s] command EPP Command to call
87
+ # @yield [xml] block to construct payload
88
+ # @yieldparam [XML::Node] xml XML Node of the command
89
+ # for the payload to be added into
90
+ # @return [Response] EPP Response object
91
+ # def request(command, payload = nil, extension = nil, &block)
92
+ # @req = if payload.nil? && block_given?
93
+ # Request.new(command, req_tid, &block)
94
+ # else
95
+ # Request.new(command, payload, extension, req_tid)
96
+ # end
97
+ #
98
+ # @resp = send_recv_frame(@req)
99
+ # end
100
+
101
+ # @note Primarily an internal method, exposed to enable testing
102
+ # @param [] command
103
+ # @param [] extension
104
+ # @return [EPP::Request]
105
+ # @see request
106
+ def prepare_request(command, extension = nil)
107
+ cmd = EPP::Requests::Command.new(req_tid, command, extension)
108
+ EPP::Request.new(cmd)
109
+ end
110
+
111
+ def request(command, extension = nil)
112
+ @req = command.is_a?(EPP::Request) ? command :
113
+ prepare_request(command, extension)
114
+
115
+ @resp = send_recv_frame(@req)
116
+ end
117
+
118
+ # Return the Request object created by the last call to #request
119
+ #
120
+ # @return [Request] Last created EPP Request object
121
+ def last_request
122
+ @req
123
+ end
124
+ # Return the Response object created by the last call to #request
125
+ #
126
+ # @return [Response] Last created EPP Response object
127
+ def last_response
128
+ @resp
129
+ end
130
+ # Return the error from the last login or logout request
131
+ #
132
+ # @return [ResponseError] last error from login or logout
133
+ def last_error
134
+ @error
135
+ end
136
+ # Return the options the receiver was initialized with
137
+ #
138
+ # @return [Hash] configuration options
139
+ def options
140
+ @options
141
+ end
142
+ # Return the greeting XML received during the last connection
143
+ #
144
+ # @return [String]
145
+ def greeting
146
+ @greeting
147
+ end
148
+
149
+ # Runs a block while logged into the receiver
150
+ #
151
+ # @yield logged in EPP server session
152
+ # @example typical usage
153
+ # connection do
154
+ # with_login do
155
+ # # .. do stuff with logged in session ..
156
+ # end
157
+ # end
158
+ def with_login
159
+ login!
160
+
161
+ begin
162
+ yield
163
+ ensure
164
+ logout!
165
+ end
166
+ end
167
+
168
+ # EPP Server Connection
169
+ #
170
+ # @yield connected session
171
+ # @example typical usage
172
+ # connection do
173
+ # # .. do stuff with logged in session ..
174
+ # end
175
+ # @example usage with with_login
176
+ # connection do
177
+ # with_login do
178
+ # # .. do stuff with logged in session ..
179
+ # end
180
+ # end
181
+ def connection
182
+ @connection_errors = []
183
+ addrinfo.each do |_,port,_,addr,_,_,_|
184
+ retried = false
185
+ begin
186
+ @conn = TCPSocket.new(addr, port)
187
+ rescue Errno::EINVAL => e
188
+ if retried
189
+ message = e.message.split(" - ")[1]
190
+ @connection_errors << Errno::EINVAL.new(
191
+ "#{message}: TCPSocket.new(#{addr.inspect}, #{port.inspect})")
192
+ next
193
+ end
194
+
195
+ retried = true
196
+ retry
197
+ end
198
+
199
+ args = [@conn]
200
+ args << options[:ssl_context] if options[:ssl_context]
201
+ @sock = OpenSSL::SSL::SSLSocket.new(*args)
202
+ @sock.sync_close = true
203
+
204
+ begin
205
+ @sock.connect
206
+ @greeting = recv_frame # Perform initial recv
207
+
208
+ return yield
209
+ rescue Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::EHOSTUNREACH => e
210
+ @connection_errors << e
211
+ next # try the next address in the list
212
+ rescue OpenSSL::SSL::SSLError => e
213
+ # Connection error, most likely the IP isn't in the allow list
214
+ if e.message =~ /returned=5 errno=0/
215
+ @connection_errors << ConnectionError.new("SSL Connection error, IP may not be permitted to connect to #{@host}",
216
+ @conn.addr, @conn.peeraddr, e)
217
+ next
218
+ else
219
+ raise e
220
+ end
221
+ ensure
222
+ @sock.close # closes @conn
223
+ @conn = @sock = nil
224
+ end
225
+ end
226
+
227
+ # Should only get here if we didn't return from the block above
228
+
229
+ addrinfo(true) # Update our addrinfo in case the DNS has changed
230
+ raise @connection_errors.last unless @connection_errors.empty?
231
+ raise Errno::EHOSTUNREACH, "Failed to connect to host #{@host}"
232
+ end
233
+ private
234
+ def addrinfo(refresh = false)
235
+ @addrinfo = nil if refresh
236
+ @addrinfo ||= resolve_addrinfo
237
+ end
238
+ def resolve_addrinfo
239
+ family = case @options[:address_family]
240
+ when 'AF_INET', Socket::AF_INET then Socket::AF_INET
241
+ when 'AF_INET6', Socket::AF_INET6 then Socket::AF_INET6
242
+ else nil end
243
+
244
+ Socket.getaddrinfo(@host, @options[:port], family, Socket::SOCK_STREAM)
245
+ end
246
+
247
+ # @return [String] next transaction id
248
+ def req_tid
249
+ @req_tid ||= 0
250
+ @req_tid += 1
251
+ date = Time.now.strftime("%Y%m%d")
252
+ "%s-%s%06d" % [@tag, date, @req_tid]
253
+ end
254
+
255
+ # @return [String] next auth transaction id
256
+ def auth_tid
257
+ @auth_tid ||= 0
258
+ @auth_tid += 1
259
+ date = Time.now.strftime("%Y%m%d")
260
+ "%s-AUTH-%s%06d" % [@tag, date, @auth_tid]
261
+ end
262
+
263
+ # Perform login
264
+ #
265
+ # @return [true] login successful
266
+ # @raise [ResponseError] login failed
267
+ # @see login_request
268
+ def login!
269
+ @error = nil
270
+ login = EPP::Commands::Login.new(@tag, @passwd, @options)
271
+ command = EPP::Requests::Command.new(auth_tid, login)
272
+ request = EPP::Request.new(command)
273
+ response = send_recv_frame(request)
274
+
275
+ return true if response.code == 1000
276
+ raise @error = ResponseError.new(response.code, response.message, response.to_xml)
277
+ end
278
+
279
+ # Perform logout
280
+ #
281
+ # @return [true] logout successful
282
+ # @raise [ResponseError] logout failed
283
+ # @see logout_request
284
+ def logout!
285
+ logout = EPP::Commands::Logout.new
286
+ command = EPP::Requests::Command.new(auth_tid, logout)
287
+ request = EPP::Request.new(command)
288
+ response = send_recv_frame(request)
289
+
290
+ return true if response.code == 1500
291
+ raise @error = ResponseError.new(response.code, response.message, response.to_xml)
292
+ end
293
+
294
+ # Send a frame and receive its response
295
+ #
296
+ # @param [String] xml XML Payload to send
297
+ # @return [Response] EPP Response
298
+ # @see send_frame
299
+ # @see recv_frame
300
+ def send_recv_frame(xml)
301
+ send_frame(xml)
302
+ Response.new(recv_frame)
303
+ end
304
+
305
+ # Send XML frame
306
+ # @param [String,Request] xml Payload to send
307
+ # @return [Integer] number of bytes written
308
+ def send_frame(xml)
309
+ xml = xml.to_s if xml.kind_of?(Request)
310
+ @sock.write([xml.size + HEADER_LEN].pack("N") + xml)
311
+ end
312
+
313
+ # Receive XML frame
314
+ # @return [String] XML response
315
+ def recv_frame
316
+ header = @sock.read(HEADER_LEN)
317
+
318
+ if header.nil? && @sock.eof?
319
+ raise ServerError, "Connection terminated by remote host"
320
+ elsif header.nil?
321
+ raise ServerError, "Failed to read header from remote host"
322
+ else
323
+ len = header.unpack('N')[0]
324
+
325
+ raise ServerError, "Bad frame header from server, should be greater than #{HEADER_LEN}" unless len > HEADER_LEN
326
+ @sock.read(len - HEADER_LEN)
327
+ end
328
+ end
329
+ end
330
+ end
@@ -0,0 +1,59 @@
1
+ require 'epp-client'
2
+
3
+ module EPP
4
+ class Client
5
+ # Request Preparation Methods
6
+ def check_prepare(payload, extension = nil)
7
+ check = EPP::Commands::Check.new(payload)
8
+ prepare_request(check, extension)
9
+ end
10
+
11
+ def create_prepare(payload, extension = nil)
12
+ create = EPP::Commands::Create.new(payload)
13
+ prepare_request(create, extension)
14
+ end
15
+
16
+ def delete_prepare(payload, extension = nil)
17
+ delete = EPP::Commands::Delete.new(payload)
18
+ prepare_request(delete, extension)
19
+ end
20
+
21
+ def info_prepare(payload, extension = nil)
22
+ info = EPP::Commands::Info.new(payload)
23
+ prepare_request(info, extension)
24
+ end
25
+
26
+ def renew_prepare(payload, extension = nil)
27
+ renew = EPP::Commands::Renew.new(payload)
28
+ prepare_request(renew, extension)
29
+ end
30
+
31
+ def transfer_prepare(op, payload, extension = nil)
32
+ transfer = EPP::Commands::Transfer.new(op, payload)
33
+ prepare_request(transfer, extension)
34
+ end
35
+
36
+ def update_prepare(payload, extension = nil)
37
+ update = EPP::Commands::Update.new(payload)
38
+ prepare_request(update, extension)
39
+ end
40
+
41
+ def poll_prepare
42
+ poll = EPP::Commands::Poll.new
43
+ prepare_request(poll)
44
+ end
45
+ def ack_prepare(msgID)
46
+ ack = EPP::Commands::Poll.new(msgID)
47
+ prepare_request(ack)
48
+ end
49
+
50
+ def prepare_request(cmd, extension = nil)
51
+ @conn.prepare_request(cmd, extension)
52
+ end
53
+
54
+ # Response Preparation Methods
55
+ def load_response(xml_data)
56
+ EPP::Response.new(xml_data)
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,3 @@
1
+ module EPP
2
+ VERSION = '3.0.0'
3
+ end
@@ -0,0 +1,71 @@
1
+ module EPP
2
+ module XMLHelpers
3
+ # Creates and returns an instance of the EPP 1.0 namespace
4
+ #
5
+ # @param [XML::Node] node to create the namespace on
6
+ # @param [String, nil] Name to give the namespace
7
+ # @return [XML::Namespace] EPP 1.0 namespace
8
+ def epp_namespace(node, name = nil, namespaces = {})
9
+ return namespaces['epp'] if namespaces.has_key?('epp')
10
+ xml_namespace(node, name, 'urn:ietf:params:xml:ns:epp-1.0')
11
+ end
12
+
13
+ # Creates and returns a new node in the EPP 1.0 namespace
14
+ #
15
+ # @param [String] name of the node to create
16
+ # @param [String,XML::Node,nil] value of the node
17
+ # @return [XML::Node]
18
+ def epp_node(name, value = nil, namespaces = {})
19
+ value, namespaces = nil, value if value.kind_of?(Hash)
20
+
21
+ node = xml_node(name, value)
22
+ node.namespaces.namespace = epp_namespace(node, nil, namespaces)
23
+ node
24
+ end
25
+
26
+ # Creates and returns a new XML node
27
+ #
28
+ # @param [String] name of the node to create
29
+ # @param [String,XML::Node,nil] value of the node
30
+ # @return [XML::Node]
31
+ def xml_node(name, value = nil)
32
+ XML::Node.new(name, value)
33
+ end
34
+
35
+ # Creates and returns a new XML namespace
36
+ #
37
+ # @param [XML::Node] node XML node to add the namespace to
38
+ # @param [String] name Name of the namespace to create
39
+ # @param [String] uri URI of the namespace to create
40
+ # @return [XML::Namespace]
41
+ def xml_namespace(node, name, uri, namespaces = {})
42
+ XML::Namespace.new(node, name, uri)
43
+ end
44
+
45
+ # Creates and returns a new XML document
46
+ #
47
+ # @param [XML::Document,String] obj Object to create the document with
48
+ # @return [XML::Document]
49
+ def xml_document(obj)
50
+ case obj
51
+ when XML::Document
52
+ XML::Document.document(obj)
53
+ else
54
+ XML::Document.new('1.0')
55
+ end
56
+ end
57
+
58
+ def as_xml(obj)
59
+ return obj.to_xml if obj.respond_to?(:to_xml)
60
+
61
+ case obj
62
+ when String
63
+ XML::Document.string(obj).root
64
+ when XML::Node
65
+ obj
66
+ when XML::Document
67
+ obj.root
68
+ end
69
+ end
70
+ end
71
+ end