ftpd 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- NmM2NzYzZmUzMDY2YzRiMGVmMWI5NTMxNjM0Y2Y1Zjk3MGZjYTUzMA==
5
- data.tar.gz: !binary |-
6
- MDEwOTRkNjJkY2QwMGVkNTg3NzU0ZGU1ZmE0ZDYzOWYzYWViNzJjMQ==
2
+ SHA1:
3
+ metadata.gz: 189a61ebfe79058fbf8ab5079be2e57dad494898
4
+ data.tar.gz: a4e2b09abc12890a8b2729e44a1e172aa4201fac
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- OTVlOTZiZmVjNTQ3OTRiMzE2M2FkMDZiZTIxMmY5ZDU4MDJkMjViZTk5OGNl
10
- NTRmODI4ZWU4MTJiMmFiN2Q3NDBkNmQ5NzhhZDE5OGMyNjZjY2E5NzhmMTM0
11
- ODc4OTA3M2VjMjc0YWY2NzJmMTM0NTI4ZmQ1ZWQ3ODc1ZDlmOWU=
12
- data.tar.gz: !binary |-
13
- MzU5MjIzOGZlZjE0ZGVhZGI2NGUxNmZlZDUzMDhkOWQwYjZhY2I0NWE0N2E0
14
- ZjQ3NTgyNjM2NTMzYTljZmIwMGZiYThlOTEwZmE4NzY5MTU4MDBjMjA1YTc0
15
- OWU4ODRiZmQ1OGU3NWRkZmVjZTk5MTY0OTAzMzY0YzA1NzhjOTE=
6
+ metadata.gz: ab7e3e91a03ce1c0c5ad9d116e5c88166a872351ee10c428ce57ae086380fbb2dcfa49cc9c486d23b5c82e6aa6e5a02f50be418cbc62eb09cd2457af840e2260
7
+ data.tar.gz: db4c4e093358a41d1c12194f440b413160ed4a9aa0fd5cfbdef7b7d52f29dc5ec1d0d0e08beecd713468b562ea19576e5571e779ee06de5bd78ec6ded3374bd0
data/Changelog.md CHANGED
@@ -2,6 +2,11 @@ This is the change log for the main branch of ftpd, which supports
2
2
  Ruby 1.9 and greater. For ruby 1.8.7, please use the latest version
3
3
  before 0.8.0.
4
4
 
5
+ ### development
6
+
7
+ * Added Server#exception_handler= (thanks akelmanson)
8
+ * Added Server#join (thanks akelmanson)
9
+
5
10
  ### 1.0.1
6
11
 
7
12
  * Less strict gem dependencies
data/Gemfile.lock CHANGED
@@ -3,7 +3,7 @@ GEM
3
3
  specs:
4
4
  addressable (2.3.6)
5
5
  builder (3.2.2)
6
- cucumber (1.3.16)
6
+ cucumber (1.3.17)
7
7
  builder (>= 2.1.2)
8
8
  diff-lcs (>= 1.1.3)
9
9
  gherkin (~> 2.12)
@@ -55,24 +55,24 @@ GEM
55
55
  rack (~> 1.2)
56
56
  rack (1.5.2)
57
57
  rake (10.3.2)
58
- rdoc (4.1.1)
58
+ rdoc (4.1.2)
59
59
  json (~> 1.4)
60
60
  redcarpet (3.1.2)
61
61
  rspec (3.1.0)
62
62
  rspec-core (~> 3.1.0)
63
63
  rspec-expectations (~> 3.1.0)
64
64
  rspec-mocks (~> 3.1.0)
65
- rspec-core (3.1.0)
65
+ rspec-core (3.1.4)
66
66
  rspec-support (~> 3.1.0)
67
- rspec-expectations (3.1.0)
67
+ rspec-expectations (3.1.2)
68
68
  diff-lcs (>= 1.2.0, < 2.0)
69
69
  rspec-support (~> 3.1.0)
70
70
  rspec-its (1.0.1)
71
71
  rspec-core (>= 2.99.0.beta1)
72
72
  rspec-expectations (>= 2.99.0.beta1)
73
- rspec-mocks (3.1.0)
73
+ rspec-mocks (3.1.2)
74
74
  rspec-support (~> 3.1.0)
75
- rspec-support (3.1.0)
75
+ rspec-support (3.1.1)
76
76
  thread_safe (0.3.4)
77
77
  timecop (0.7.1)
78
78
  yard (0.8.7.4)
data/README.md CHANGED
@@ -27,12 +27,6 @@ probability that it contains critical flaws (or even security
27
27
  vulnarabilities) that have not been discovered in its use as a test
28
28
  harness.
29
29
 
30
- In this 0.X.X release, the API is changing at least a little with
31
- almost every release. If you need to keep those changes from
32
- impacting you (or at least want to let many of them build up before
33
- you have to deal with them), then lock your Gemfile down to a minor
34
- release (e.g. :version => '~> 0.5.0').
35
-
36
30
  ## Hello World
37
31
 
38
32
  This is examples/hello_world.rb, a bare minimum FTP server. It allows
@@ -183,6 +177,7 @@ You can set any of these attributes before starting the server:
183
177
 
184
178
  * {Ftpd::FtpServer#allow_low_data_ports}
185
179
  * {Ftpd::FtpServer#auth_level}
180
+ * {Ftpd::FtpServer#exception_handler}
186
181
  * {Ftpd::FtpServer#failed_login_delay}
187
182
  * {Ftpd::FtpServer#list_formatter}
188
183
  * {Ftpd::FtpServer#log}
@@ -355,6 +350,7 @@ and granted permission to donate it to the community.
355
350
  Among those who have improved ftpd are:
356
351
 
357
352
  * Alfonso Cora
353
+ * André Aizim Kelmanson
358
354
  * Bjoern B. Dorra
359
355
  * Joshua Rutherford
360
356
  * Larry. W. Cashdollar
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.1
1
+ 1.1.0
data/ftpd.gemspec CHANGED
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: ftpd 1.0.1 ruby lib
5
+ # stub: ftpd 1.1.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "ftpd"
9
- s.version = "1.0.1"
9
+ s.version = "1.1.0"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib"]
13
13
  s.authors = ["Wayne Conrad"]
14
- s.date = "2014-09-05"
14
+ s.date = "2014-11-22"
15
15
  s.description = "ftpd is a pure Ruby FTP server library. It supports implicit and explicit TLS, IPV6, passive and active mode, and is unconditionally compliant per RFC-1123. It can be used as part of a test fixture or embedded in a program."
16
16
  s.email = "wconrad@yagni.com"
17
17
  s.extra_rdoc_files = [
@@ -197,6 +197,7 @@ Gem::Specification.new do |s|
197
197
  "lib/ftpd/file_info.rb",
198
198
  "lib/ftpd/file_system_helper.rb",
199
199
  "lib/ftpd/ftp_server.rb",
200
+ "lib/ftpd/gets_peer_address.rb",
200
201
  "lib/ftpd/insecure_certificate.rb",
201
202
  "lib/ftpd/list_format/eplf.rb",
202
203
  "lib/ftpd/list_format/ls.rb",
@@ -237,7 +238,7 @@ Gem::Specification.new do |s|
237
238
  ]
238
239
  s.homepage = "http://github.com/wconrad/ftpd"
239
240
  s.licenses = ["MIT"]
240
- s.rubygems_version = "2.2.2"
241
+ s.rubygems_version = "2.4.4"
241
242
  s.summary = "Pure Ruby FTP server library"
242
243
 
243
244
  if s.respond_to? :specification_version then
@@ -27,6 +27,9 @@ module Ftpd
27
27
  execute_command command, argument
28
28
  rescue FtpServerError => e
29
29
  reply e.message_with_code
30
+ rescue => e
31
+ reply "451 Requested action aborted. Local error in processing."
32
+ config.exception_handler.call(e) unless config.exception_handler.nil?
30
33
  end
31
34
  end
32
35
  rescue Errno::ECONNRESET, Errno::EPIPE
@@ -1,9 +1,13 @@
1
+ require_relative "gets_peer_address"
2
+
1
3
  module Ftpd
2
4
 
3
5
  # This class keeps track of connections
4
6
 
5
7
  class ConnectionTracker
6
8
 
9
+ include GetsPeerAddress
10
+
7
11
  def initialize
8
12
  @mutex = Mutex.new
9
13
  @connections = {}
@@ -18,7 +22,7 @@ module Ftpd
18
22
  end
19
23
  end
20
24
 
21
- # Return the number of connections for a socket
25
+ # Return the number of connections for a socket's peer IP
22
26
 
23
27
  def connections_for(socket)
24
28
  @mutex.synchronize do
@@ -39,18 +43,6 @@ module Ftpd
39
43
  end
40
44
  end
41
45
 
42
- # Return the number of known IPs. This exists for the benefit of
43
- # the test, so that it can know the tracker has properly forgotten
44
- # about an IP with no connections.
45
-
46
- def known_ip_count
47
- @mutex.synchronize do
48
- @connections.size
49
- end
50
- end
51
-
52
- private
53
-
54
46
  # Start tracking a connection
55
47
 
56
48
  def start_track(socket)
@@ -73,37 +65,17 @@ module Ftpd
73
65
  end
74
66
  end
75
67
 
76
- # Obtain the IP that the client connected _from_.
77
- #
78
- # How this is done depends upon which type of socket (SSL or not)
79
- # and what version of Ruby.
80
- #
81
- # * SSL socket
82
- # * #peeraddr. Uses BasicSocket.do_not_reverse_lookup.
83
- # * Ruby 1.8.7
84
- # * #peeraddr, which does not take the "reverse lookup"
85
- # argument, relying instead using
86
- # BasicSocket.do_not_reverse_lookup.
87
- # * #getpeername, which does not do a reverse lookup. It is a
88
- # little uglier than #peeraddr.
89
- # * Ruby >=1.9.3
90
- # * #peeraddr, which takes the "reverse lookup" argument.
91
- # * #getpeername - same as 1.8.7
92
-
93
- # @return [String] IP address
94
-
95
- def peer_ip(socket)
96
- if socket.respond_to?(:getpeername)
97
- # Non SSL
98
- sockaddr = socket.getpeername
99
- port, host = Socket.unpack_sockaddr_in(sockaddr)
100
- host
101
- else
102
- # SSL
103
- BasicSocket.do_not_reverse_lookup = true
104
- socket.peeraddr.last
68
+ # Return the number of known IPs. This exists for the benefit of
69
+ # the test, so that it can know the tracker has properly forgotten
70
+ # about an IP with no connections.
71
+
72
+ def known_ip_count
73
+ @mutex.synchronize do
74
+ @connections.size
105
75
  end
106
- end
76
+ end
77
+
78
+ private
107
79
 
108
80
  end
109
81
 
@@ -127,6 +127,22 @@ module Ftpd
127
127
 
128
128
  attr_accessor :session_timeout
129
129
 
130
+ # The exception handler. When there is an unknown exception,
131
+ # server replies 451 and calls exception_handler. If nil,
132
+ # then it's ignored.
133
+ #
134
+ # Set this before calling #start.
135
+ #
136
+ # @return [Proc]
137
+
138
+ attr_accessor :exception_handler
139
+
140
+ # Defines the exception_handler.
141
+
142
+ def on_exception(&block)
143
+ self.exception_handler = block
144
+ end
145
+
130
146
  # Create a new FTP server. The server won't start until the
131
147
  # #start method is called.
132
148
  #
@@ -183,6 +199,7 @@ module Ftpd
183
199
  config.server_version = @server_version
184
200
  config.session_timeout = @session_timeout
185
201
  config.tls = @tls
202
+ config.exception_handler = exception_handler
186
203
  session = Session.new(config, socket)
187
204
  session.run
188
205
  end
@@ -0,0 +1,41 @@
1
+ require_relative "gets_peer_address"
2
+
3
+ module Ftpd
4
+
5
+ module GetsPeerAddress
6
+
7
+ # Obtain the IP that the client connected _from_.
8
+ #
9
+ # How this is done depends upon which type of socket (SSL or not)
10
+ # and what version of Ruby.
11
+ #
12
+ # * SSL socket
13
+ # * #peeraddr. Uses BasicSocket.do_not_reverse_lookup.
14
+ # * Ruby 1.8.7
15
+ # * #peeraddr, which does not take the "reverse lookup"
16
+ # argument, relying instead using
17
+ # BasicSocket.do_not_reverse_lookup.
18
+ # * #getpeername, which does not do a reverse lookup. It is a
19
+ # little uglier than #peeraddr.
20
+ # * Ruby >=1.9.3
21
+ # * #peeraddr, which takes the "reverse lookup" argument.
22
+ # * #getpeername - same as 1.8.7
23
+ #
24
+ # @return [String] IP address
25
+
26
+ def peer_ip(socket)
27
+ if socket.respond_to?(:getpeername)
28
+ # Non SSL
29
+ sockaddr = socket.getpeername
30
+ port, host = Socket.unpack_sockaddr_in(sockaddr)
31
+ host
32
+ else
33
+ # SSL
34
+ BasicSocket.do_not_reverse_lookup = true
35
+ socket.peeraddr.last
36
+ end
37
+ end
38
+
39
+ end
40
+
41
+ end
data/lib/ftpd/server.rb CHANGED
@@ -37,6 +37,14 @@ module Ftpd
37
37
  @server_socket.addr[1]
38
38
  end
39
39
 
40
+ # The calling thread will suspend execution until the server is
41
+ # stopped.
42
+
43
+ def join
44
+ raise 'Server is not started!' if @server_thread.nil?
45
+ @server_thread.join
46
+ end
47
+
40
48
  # Start the server. This creates the server socket, and the
41
49
  # thread to service it.
42
50
 
@@ -98,6 +98,14 @@ module Ftpd
98
98
 
99
99
  attr_accessor :tls
100
100
 
101
+ # The exception handler. When there is an unknown exception,
102
+ # server replies 451 and calls exception_handler. If nil,
103
+ # then it's ignored.
104
+ #
105
+ # @return [Proc]
106
+
107
+ attr_accessor :exception_handler
108
+
101
109
  end
102
110
 
103
111
  end
@@ -17,53 +17,6 @@ module Ftpd
17
17
  socket
18
18
  end
19
19
 
20
- # Since the connection tracker only keeps track of a connection
21
- # until the block to which it yields returns, we need a way to
22
- # keep a block active.
23
-
24
- class Connector
25
-
26
- # Enable the rspec expect syntax in this class.
27
- # This uses an internal API of rspec-mock.
28
- # See: http://stackoverflow.com/q/25692786/238886
29
- RSpec::Mocks::Syntax.enable_expect self
30
-
31
- def initialize(connection_tracker)
32
- @connection_tracker = connection_tracker
33
- @tracked = Queue.new
34
- @end_session = Queue.new
35
- @session_ended = Queue.new
36
- end
37
-
38
- # Start tracking a connection. Does not return until it is
39
- # being tracked.
40
-
41
- def start_session(socket)
42
- Thread.new do
43
- @connection_tracker.track(socket) do
44
- @tracked.enq :go
45
- command = @end_session.deq
46
- if command == :close
47
- allow(socket).to receive(:getpeername)
48
- .and_raise(RuntimeError, "Socket closed")
49
- end
50
- end
51
- @session_ended.enq :go
52
- end
53
- @tracked.deq
54
- end
55
-
56
- # Stop tracking a connection. Does not return until it is no
57
- # longer tracked.
58
-
59
- def end_session(command = :normally)
60
- @end_session.enq command
61
- @session_ended.deq
62
- end
63
-
64
- end
65
-
66
- let(:connector) {Connector.new(connection_tracker)}
67
20
  subject(:connection_tracker) {ConnectionTracker.new}
68
21
 
69
22
  describe '#connections' do
@@ -74,21 +27,9 @@ module Ftpd
74
27
 
75
28
  it 'should track the total number of connection' do
76
29
  expect(connection_tracker.connections).to eq 0
77
- connector.start_session socket
30
+ connection_tracker.start_track socket
78
31
  expect(connection_tracker.connections).to eq 1
79
- connector.end_session
80
- expect(connection_tracker.connections).to eq 0
81
- end
82
-
83
- end
84
-
85
- context '(socket disconnected during session)' do
86
-
87
- it 'should track the total number of connection' do
88
- expect(connection_tracker.connections).to eq 0
89
- connector.start_session socket
90
- expect(connection_tracker.connections).to eq 1
91
- connector.end_session :close
32
+ connection_tracker.stop_track socket
92
33
  expect(connection_tracker.connections).to eq 0
93
34
  end
94
35
 
@@ -103,10 +44,10 @@ module Ftpd
103
44
  socket2 = socket_bound_to('127.0.0.2')
104
45
  expect(connection_tracker.connections_for(socket1)).to eq 0
105
46
  expect(connection_tracker.connections_for(socket2)).to eq 0
106
- connector.start_session socket1
47
+ connection_tracker.start_track socket1
107
48
  expect(connection_tracker.connections_for(socket1)).to eq 1
108
49
  expect(connection_tracker.connections_for(socket2)).to eq 0
109
- connector.end_session
50
+ connection_tracker.stop_track socket1
110
51
  expect(connection_tracker.connections_for(socket1)).to eq 0
111
52
  expect(connection_tracker.connections_for(socket2)).to eq 0
112
53
  end
@@ -119,14 +60,38 @@ module Ftpd
119
60
 
120
61
  it 'should forget about an IP that has no connection' do
121
62
  expect(connection_tracker.known_ip_count).to eq 0
122
- connector.start_session socket
63
+ connection_tracker.start_track socket
123
64
  expect(connection_tracker.known_ip_count).to eq 1
124
- connector.end_session
65
+ connection_tracker.stop_track socket
125
66
  expect(connection_tracker.known_ip_count).to eq 0
126
67
  end
127
68
 
128
69
  end
129
70
 
71
+ describe '#track' do
72
+
73
+ let(:socket) {socket_bound_to('127.0.0.1')}
74
+
75
+ context '(session ends normally)' do
76
+ specify do
77
+ expect(connection_tracker.connections_for(socket)).to eq 0
78
+ connection_tracker.track(socket) do
79
+ expect(connection_tracker.connections_for(socket)).to eq 1
80
+ end
81
+ expect(connection_tracker.connections_for(socket)).to eq 0
82
+ end
83
+ end
84
+
85
+ context '(session ends with exception)' do
86
+ specify do
87
+ expect(connection_tracker.connections_for(socket)).to eq 0
88
+ connection_tracker.track(socket) { raise } rescue
89
+ expect(connection_tracker.connections_for(socket)).to eq 0
90
+ end
91
+ end
92
+
93
+ end
94
+
130
95
  end
131
96
 
132
97
  end
data/spec/server_spec.rb CHANGED
@@ -4,6 +4,21 @@ module Ftpd
4
4
 
5
5
  describe Server do
6
6
 
7
+ describe '#join' do
8
+ it 'calls server_thread#join' do
9
+ expect_any_instance_of(Thread).to receive(:join)
10
+ server = Server.new
11
+ server.start
12
+ server.join
13
+ end
14
+ context 'when server is not started' do
15
+ it 'raises an error' do
16
+ server = Server.new
17
+ expect { server.join }.to raise_error('Server is not started!')
18
+ end
19
+ end
20
+ end
21
+
7
22
  describe 'reuse explicit port (github #23)' do
8
23
 
9
24
  # The bug being tested involves a race condition. Monkey patch
metadata CHANGED
@@ -1,153 +1,153 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ftpd
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wayne Conrad
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-05 00:00:00.000000000 Z
11
+ date: 2014-11-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: memoizer
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: cucumber
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '1.3'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.3'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: double-bag-ftps
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ~>
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0.1'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ~>
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0.1'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: jeweler
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ~>
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
61
  version: '2.0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ~>
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '2.0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ~>
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
75
  version: '10.3'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ~>
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '10.3'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: redcarpet
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ~>
87
+ - - "~>"
88
88
  - !ruby/object:Gem::Version
89
89
  version: '3.1'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ~>
94
+ - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: '3.1'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: rspec
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - ~>
101
+ - - "~>"
102
102
  - !ruby/object:Gem::Version
103
103
  version: '3.1'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - ~>
108
+ - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: '3.1'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: rspec-its
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - ~>
115
+ - - "~>"
116
116
  - !ruby/object:Gem::Version
117
117
  version: '1.0'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - ~>
122
+ - - "~>"
123
123
  - !ruby/object:Gem::Version
124
124
  version: '1.0'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: timecop
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - ~>
129
+ - - "~>"
130
130
  - !ruby/object:Gem::Version
131
131
  version: '0.7'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - ~>
136
+ - - "~>"
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0.7'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: yard
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
- - - ~>
143
+ - - "~>"
144
144
  - !ruby/object:Gem::Version
145
145
  version: 0.8.7
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
- - - ~>
150
+ - - "~>"
151
151
  - !ruby/object:Gem::Version
152
152
  version: 0.8.7
153
153
  description: ftpd is a pure Ruby FTP server library. It supports implicit and explicit
@@ -160,8 +160,8 @@ extra_rdoc_files:
160
160
  - LICENSE.md
161
161
  - README.md
162
162
  files:
163
- - .travis.yml
164
- - .yardopts
163
+ - ".travis.yml"
164
+ - ".yardopts"
165
165
  - Changelog.md
166
166
  - Gemfile
167
167
  - Gemfile.lock
@@ -338,6 +338,7 @@ files:
338
338
  - lib/ftpd/file_info.rb
339
339
  - lib/ftpd/file_system_helper.rb
340
340
  - lib/ftpd/ftp_server.rb
341
+ - lib/ftpd/gets_peer_address.rb
341
342
  - lib/ftpd/insecure_certificate.rb
342
343
  - lib/ftpd/list_format/eplf.rb
343
344
  - lib/ftpd/list_format/ls.rb
@@ -385,17 +386,17 @@ require_paths:
385
386
  - lib
386
387
  required_ruby_version: !ruby/object:Gem::Requirement
387
388
  requirements:
388
- - - ! '>='
389
+ - - ">="
389
390
  - !ruby/object:Gem::Version
390
391
  version: '0'
391
392
  required_rubygems_version: !ruby/object:Gem::Requirement
392
393
  requirements:
393
- - - ! '>='
394
+ - - ">="
394
395
  - !ruby/object:Gem::Version
395
396
  version: '0'
396
397
  requirements: []
397
398
  rubyforge_project:
398
- rubygems_version: 2.2.2
399
+ rubygems_version: 2.4.4
399
400
  signing_key:
400
401
  specification_version: 4
401
402
  summary: Pure Ruby FTP server library