ftpd 1.0.1 → 1.1.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.
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