epp-client-base 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog ADDED
@@ -0,0 +1,5 @@
1
+ 2010-05-14 mat
2
+ * first release
3
+
4
+ 2010-05-04 mat
5
+ * Initial commit
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'http://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in epp-client.gemspec
4
+ Dir['*.gemspec'].each do |i|
5
+ gemspec :name => i.sub(/\.gemspec$/, '')
6
+ end
data/MIT-LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (C) 2010 Mathieu Arnold, Absolight
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/README ADDED
@@ -0,0 +1,5 @@
1
+ An extensible EPP client library
2
+
3
+ When possible, the objects that are received via EPP are translated to their
4
+ equivalent in ruby, that is, dates in Date object, timestamps in DateTime
5
+ objects.
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env rake
2
+ require 'rake'
3
+ require 'rdoc/task'
4
+ require 'rubygems/package_task'
5
+ require "bundler/gem_helper"
6
+
7
+ MY_GEMS = Dir['*.gemspec'].map {|g| g.sub(/.*-(.*)\.gemspec/, '\1')}
8
+
9
+ MY_GEMS.each do |g|
10
+ namespace g do
11
+ Bundler::GemHelper.new(Dir.pwd, "epp-client-#{g}").install
12
+ end
13
+ end
14
+
15
+ namespace :all do
16
+ task :build => MY_GEMS.map { |f| "#{f}:build" }
17
+ task :install => MY_GEMS.map { |f| "#{f}:install" }
18
+ task :release => MY_GEMS.map { |f| "#{f}:release" }
19
+ end
20
+
21
+ task :build => 'all:build'
22
+ task :install => 'all:install'
23
+ task :release => 'all:release'
24
+
25
+ desc "Generate documentation for the Rails framework"
26
+ Rake::RDocTask.new do |rdoc|
27
+ rdoc.rdoc_dir = 'doc/rdoc'
28
+ rdoc.title = "Documentation"
29
+
30
+ rdoc.options << '--line-numbers' << '--inline-source'
31
+ rdoc.options << '--charset' << 'utf-8'
32
+
33
+ rdoc.rdoc_files.include('README')
34
+ rdoc.rdoc_files.include('ChangeLog')
35
+ rdoc.rdoc_files.include('lib/**/*.rb')
36
+ end
37
+
@@ -0,0 +1,54 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/epp-client/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = 'epp-client-base'
6
+ gem.version = EPPClient::VERSION
7
+ gem.date = '2010-05-14'
8
+ gem.authors = ['Mathieu Arnold']
9
+ gem.email = ['m@absolight.fr']
10
+ gem.description = 'An extensible EPP client library.'
11
+ gem.summary = 'An extensible EPP client library'
12
+ gem.homepage = "https://github.com/Absolight/epp-client"
13
+
14
+ gem.required_ruby_version = '>= 1.8.7'
15
+ gem.required_rubygems_version = ">= 1.3.6"
16
+
17
+ gem.files = [
18
+ 'ChangeLog',
19
+ 'Gemfile',
20
+ 'MIT-LICENSE',
21
+ 'README',
22
+ 'Rakefile',
23
+ 'epp-client-base.gemspec',
24
+ 'lib/epp-client/base.rb',
25
+ 'lib/epp-client/connection.rb',
26
+ 'lib/epp-client/contact.rb',
27
+ 'lib/epp-client/domain.rb',
28
+ 'lib/epp-client/exceptions.rb',
29
+ 'lib/epp-client/poll.rb',
30
+ 'lib/epp-client/session.rb',
31
+ 'lib/epp-client/ssl.rb',
32
+ 'lib/epp-client/version.rb',
33
+ 'lib/epp-client/xml.rb',
34
+ 'vendor/ietf/contact-1.0.xsd',
35
+ 'vendor/ietf/domain-1.0.xsd',
36
+ 'vendor/ietf/epp-1.0.xsd',
37
+ 'vendor/ietf/eppcom-1.0.xsd',
38
+ 'vendor/ietf/host-1.0.xsd',
39
+ 'vendor/ietf/rfc4310.txt',
40
+ 'vendor/ietf/rfc5730.txt',
41
+ 'vendor/ietf/rfc5731.txt',
42
+ 'vendor/ietf/rfc5732.txt',
43
+ 'vendor/ietf/rfc5733.txt',
44
+ 'vendor/ietf/rfc5734.txt',
45
+ 'vendor/ietf/rfc5910.txt',
46
+ ]
47
+
48
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
49
+ gem.require_paths = ['lib']
50
+
51
+ gem.add_development_dependency "bundler", ">= 1.0.0"
52
+ gem.add_dependency('nokogiri', '~> 1.4')
53
+ gem.add_dependency('builder', '>= 2.1.2')
54
+ end
@@ -0,0 +1,113 @@
1
+ require 'openssl'
2
+ require 'socket'
3
+ require 'nokogiri'
4
+ require 'builder'
5
+ require 'date'
6
+ require "epp-client/version"
7
+ require 'epp-client/xml'
8
+ require 'epp-client/session'
9
+ require 'epp-client/connection'
10
+ require 'epp-client/exceptions'
11
+ require 'epp-client/ssl'
12
+ require 'epp-client/poll'
13
+ require 'epp-client/domain'
14
+ require 'epp-client/contact'
15
+
16
+ module EPPClient
17
+ class Base
18
+
19
+ SCHEMAS = %w[
20
+ epp-1.0
21
+ domain-1.0
22
+ host-1.0
23
+ contact-1.0
24
+ ]
25
+ SCHEMAS_EXT_IETF = %w[
26
+ rgp-1.0
27
+ ]
28
+
29
+ EPPClient::SCHEMAS_URL = SCHEMAS.inject({}) do |a,s|
30
+ a[s.sub(/-1\.0$/, '')] = "urn:ietf:params:xml:ns:#{s}" if s =~ /-1\.0$/
31
+ a[s] = "urn:ietf:params:xml:ns:#{s}"
32
+ a
33
+ end.merge!(SCHEMAS_EXT_IETF.inject({}) do |a,s|
34
+ a[s.sub(/-1\.0$/, '')] = "urn:ietf:params:xml:ns:#{s}" if s =~ /-1\.0$/
35
+ a[s] = "urn:ietf:params:xml:ns:#{s}"
36
+ a
37
+ end)
38
+
39
+ include EPPClient::XML
40
+ include EPPClient::Session
41
+ include EPPClient::Connection
42
+ include EPPClient::SSL
43
+ include EPPClient::Poll # keep before object definition modules.
44
+ include EPPClient::Domain
45
+ include EPPClient::Contact
46
+
47
+ attr_accessor :client_id, :password, :server, :port, :services, :lang, :extensions, :version, :context
48
+ attr_writer :clTRID
49
+
50
+ # ==== Required Attributes
51
+ #
52
+ # [<tt>:server</tt>] The EPP server to connect to
53
+ # [<tt>:client_id</tt>]
54
+ # The tag or username used with <tt><login></tt> requests.
55
+ # [<tt>:password</tt>] The password used with <tt><login></tt> requests.
56
+ #
57
+ # ==== Optional Attributes
58
+ #
59
+ # [<tt>:port</tt>]
60
+ # The EPP standard port is 700. However, you can choose a different port to
61
+ # use.
62
+ # [<tt>:clTRID</tt>]
63
+ # The client transaction identifier is an element that EPP specifies MAY be
64
+ # used to uniquely identify the command to the server. The string
65
+ # "-<index>" will be added to it, index being incremented at each command.
66
+ # Defaults to "test-<pid>-<random>"
67
+ # [<tt>:lang</tt>] Set custom language attribute. Default is 'en'.
68
+ # [<tt>:services</tt>]
69
+ # Use custom EPP services in the <login> frame. The defaults use the EPP
70
+ # standard domain, contact and host 1.0 services.
71
+ # [<tt>:extensions</tt>]
72
+ # URLs to custom extensions to standard EPP. Use these to extend the
73
+ # standard EPP (e.g., AFNIC, smallregistry uses extensions). Defaults to
74
+ # none.
75
+ # [<tt>:version</tt>] Set the EPP version. Defaults to "1.0".
76
+ # [<tt>:ssl_cert</tt>] The file containing the client certificate.
77
+ # [<tt>:ssl_key</tt>] The file containing the key of the certificate.
78
+ def initialize(attrs)
79
+ unless attrs.key?(:server) && attrs.key?(:client_id) && attrs.key?(:password)
80
+ raise ArgumentError, "server, client_id and password are required"
81
+ end
82
+
83
+ attrs.each do |k,v|
84
+ begin
85
+ self.send("#{k}=", v)
86
+ rescue NoMethodError
87
+ raise ArgumentError, "there is no #{k} argument"
88
+ end
89
+ end
90
+
91
+ @port ||= 700
92
+ @lang ||= "en"
93
+ @services ||= EPPClient::SCHEMAS_URL.values_at('domain', 'contact', 'host')
94
+ @extensions ||= []
95
+ @version ||= "1.0"
96
+ @clTRID ||= "test-#{$$}-#{rand(1000)}"
97
+ @clTRID_index = 0
98
+
99
+ @context ||= OpenSSL::SSL::SSLContext.new
100
+
101
+ @logged_in = false
102
+ end
103
+
104
+ def clTRID # :nodoc:
105
+ @clTRID_index += 1
106
+ @clTRID + "-#{@clTRID_index}"
107
+ end
108
+
109
+ def debug
110
+ $DEBUG || ENV['EPP_CLIENT_DEBUG']
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,78 @@
1
+ module EPPClient
2
+ module Connection
3
+
4
+ attr_reader :sent_frame, :recv_frame, :srv_version, :srv_lang, :srv_ns, :srv_ext
5
+
6
+ # Establishes the connection to the server, if successful, will return the
7
+ # greeting frame.
8
+ def open_connection
9
+ @tcpserver = TCPSocket.new(server, port)
10
+ @socket = OpenSSL::SSL::SSLSocket.new(@tcpserver, @context)
11
+
12
+ # Synchronously close the connection & socket
13
+ @socket.sync_close
14
+
15
+ # Connect
16
+ @socket.connect
17
+
18
+ # Get the initial greeting frame
19
+ greeting_process(get_frame)
20
+ end
21
+
22
+ def greeting_process(xml)
23
+ @srv_version = xml.xpath('epp:epp/epp:greeting/epp:svcMenu/epp:version', EPPClient::SCHEMAS_URL).map {|n| n.text}
24
+ @srv_lang = xml.xpath('epp:epp/epp:greeting/epp:svcMenu/epp:lang', EPPClient::SCHEMAS_URL).map {|n| n.text}
25
+ @srv_ns = xml.xpath('epp:epp/epp:greeting/epp:svcMenu/epp:objURI', EPPClient::SCHEMAS_URL).map {|n| n.text}
26
+ if (ext = xml.xpath('epp:epp/epp:greeting/epp:svcMenu/epp:svcExtension/epp:extURI', EPPClient::SCHEMAS_URL)).size > 0
27
+ @srv_ext = ext.map {|n| n.text}
28
+ end
29
+
30
+ return xml
31
+ end
32
+
33
+ # Gracefully close the connection
34
+ def close_connection
35
+ if defined?(@socket) and @socket.is_a?(OpenSSL::SSL::SSLSocket)
36
+ @socket.close
37
+ @socket = nil
38
+ end
39
+
40
+ if defined?(@tcpserver) and @tcpserver.is_a?(TCPSocket)
41
+ @tcpserver.close
42
+ @tcpserver = nil
43
+ end
44
+
45
+ return true if @tcpserver.nil? and @socket.nil?
46
+ end
47
+
48
+ # Sends a frame and returns the server's answer
49
+ def send_request(xml)
50
+ send_frame(xml)
51
+ get_frame
52
+ end
53
+
54
+ # sends a frame
55
+ def send_frame(xml)
56
+ @sent_frame = xml
57
+ @socket.write([xml.size + 4].pack("N") + xml)
58
+ sent_frame_to_xml
59
+ return
60
+ end
61
+
62
+ # gets a frame from the socket and returns the parsed response.
63
+ def get_frame
64
+ size = @socket.read(4)
65
+ if size.nil?
66
+ if @socket.eof?
67
+ raise SocketError, "Connection closed by remote server"
68
+ else
69
+ raise SocketError, "Error reading frame from remote server"
70
+ end
71
+ else
72
+ size = size.unpack('N')[0]
73
+ @recv_frame = @socket.read(size - 4)
74
+ recv_frame_to_xml
75
+ end
76
+ end
77
+ end
78
+ end