ftpd 0.8.0 → 0.9.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 +7 -0
- data/Changelog.md +8 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +34 -4
- data/README.md +64 -40
- data/VERSION +1 -1
- data/doc/rfc-compliance.md +2 -2
- data/examples/example.rb +14 -6
- data/examples/example_spec.rb +93 -0
- data/features/ftp_server/eprt.feature +54 -0
- data/features/ftp_server/epsv.feature +36 -0
- data/features/ftp_server/get_ipv6.feature +43 -0
- data/features/ftp_server/list.feature +9 -0
- data/features/ftp_server/name_list.feature +9 -0
- data/features/ftp_server/pasv.feature +23 -0
- data/features/ftp_server/port.feature +7 -1
- data/features/ftp_server/step_definitions/test_server.rb +4 -0
- data/features/step_definitions/connect.rb +1 -1
- data/features/step_definitions/error_replies.rb +8 -0
- data/features/support/test_server.rb +2 -1
- data/ftpd.gemspec +16 -7
- data/lib/ftpd.rb +2 -0
- data/lib/ftpd/list_path.rb +28 -0
- data/lib/ftpd/protocols.rb +60 -0
- data/lib/ftpd/session.rb +76 -10
- data/lib/ftpd/tls_server.rb +19 -1
- data/spec/list_path_spec.rb +21 -0
- data/spec/protocols_spec.rb +139 -0
- data/spec/spec_helper.rb +1 -0
- metadata +34 -48
data/lib/ftpd/tls_server.rb
CHANGED
@@ -47,7 +47,8 @@ module Ftpd
|
|
47
47
|
def accept
|
48
48
|
socket = @server_socket.accept
|
49
49
|
if tls_enabled?
|
50
|
-
|
50
|
+
add_missing_methods_to_socket socket
|
51
|
+
add_tls_methods_to_socket socket
|
51
52
|
end
|
52
53
|
socket
|
53
54
|
end
|
@@ -66,18 +67,35 @@ module Ftpd
|
|
66
67
|
end
|
67
68
|
memoize :ssl_context
|
68
69
|
|
70
|
+
# Add to the TLS socket some methods that regular socket has, but TLS socket is missing
|
71
|
+
|
72
|
+
def add_missing_methods_to_socket(socket)
|
73
|
+
|
74
|
+
def socket.local_address
|
75
|
+
@io.local_address
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
# Add to the TLS sockets some methods of our own invention that
|
81
|
+
# make life a little easier.
|
82
|
+
|
69
83
|
def add_tls_methods_to_socket(socket)
|
70
84
|
context = @ssl_context
|
71
85
|
class << socket
|
86
|
+
|
72
87
|
def ssl_context
|
73
88
|
context
|
74
89
|
end
|
90
|
+
|
75
91
|
def encrypted?
|
76
92
|
!!cipher
|
77
93
|
end
|
94
|
+
|
78
95
|
def encrypt
|
79
96
|
accept
|
80
97
|
end
|
98
|
+
|
81
99
|
end
|
82
100
|
end
|
83
101
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.expand_path('spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
module Ftpd
|
4
|
+
describe ListPath do
|
5
|
+
|
6
|
+
include ListPath
|
7
|
+
|
8
|
+
it 'should replace a missing path with "."' do
|
9
|
+
expect(list_path(nil)).to eq('.')
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should replace a switch with nothing' do
|
13
|
+
expect(list_path('-a')).to eq('')
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should preserve a filename with a dash in it' do
|
17
|
+
expect(list_path('foo-bar')).to eq('foo-bar')
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require File.expand_path('spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
module Ftpd
|
4
|
+
describe Protocols do
|
5
|
+
|
6
|
+
# A fake server that returns a connected server-side socket.
|
7
|
+
|
8
|
+
class TestServer
|
9
|
+
|
10
|
+
# The socket upon which the server is listening
|
11
|
+
|
12
|
+
attr_reader :listening_socket
|
13
|
+
|
14
|
+
# Returns the connected server-side socket
|
15
|
+
|
16
|
+
attr_reader :connected_socket
|
17
|
+
|
18
|
+
# @param bind_address [String] The address to which to bind the
|
19
|
+
# server socket.
|
20
|
+
# @param connect_address [String] The address to which the
|
21
|
+
# client socket should connect.
|
22
|
+
|
23
|
+
def initialize(bind_address, connect_address)
|
24
|
+
queue = Queue.new
|
25
|
+
@listening_socket = TCPServer.new(bind_address, 0)
|
26
|
+
port = @listening_socket.addr[1]
|
27
|
+
Thread.new do
|
28
|
+
queue.enq @listening_socket.accept
|
29
|
+
end
|
30
|
+
client_socket = TCPSocket.new(connect_address, port)
|
31
|
+
@connected_socket = queue.deq
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'IPV4 server' do
|
37
|
+
|
38
|
+
let(:bind_address) {'127.0.0.1'}
|
39
|
+
let(:connect_address) {'127.0.0.1'}
|
40
|
+
let(:connected_socket) do
|
41
|
+
TestServer.new(bind_address, connect_address).connected_socket
|
42
|
+
end
|
43
|
+
subject(:protocols) {Protocols.new(connected_socket)}
|
44
|
+
|
45
|
+
it 'should support IPV4' do
|
46
|
+
expect(protocols.supports_protocol?(Protocols::IPV4)).to be_true
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should not support IPV6' do
|
50
|
+
expect(protocols.supports_protocol?(Protocols::IPV6)).to be_false
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should list the supported protocols' do
|
54
|
+
expect(protocols.protocol_codes).to eq [
|
55
|
+
Protocols::IPV4,
|
56
|
+
]
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'IPV6 server, IPV6 connection' do
|
62
|
+
|
63
|
+
let(:bind_address) {'::1'}
|
64
|
+
let(:connect_address) {'::1'}
|
65
|
+
let(:connected_socket) do
|
66
|
+
TestServer.new(bind_address, connect_address).connected_socket
|
67
|
+
end
|
68
|
+
subject(:protocols) {Protocols.new(connected_socket)}
|
69
|
+
|
70
|
+
it 'should not support IPV4' do
|
71
|
+
expect(protocols.supports_protocol?(Protocols::IPV4)).to be_false
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should support IPV6' do
|
75
|
+
expect(protocols.supports_protocol?(Protocols::IPV6)).to be_true
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'should list the supported protocols' do
|
79
|
+
expect(protocols.protocol_codes).to eq [
|
80
|
+
Protocols::IPV6,
|
81
|
+
]
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'wildcard server, IPV4 connection' do
|
87
|
+
|
88
|
+
let(:bind_address) {'::'}
|
89
|
+
let(:connect_address) {'127.0.0.1'}
|
90
|
+
let(:connected_socket) do
|
91
|
+
TestServer.new(bind_address, connect_address).connected_socket
|
92
|
+
end
|
93
|
+
subject(:protocols) {Protocols.new(connected_socket)}
|
94
|
+
|
95
|
+
it 'should support IPV4' do
|
96
|
+
expect(protocols.supports_protocol?(Protocols::IPV4)).to be_true
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should support IPV6' do
|
100
|
+
expect(protocols.supports_protocol?(Protocols::IPV6)).to be_true
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'should list the supported protocols' do
|
104
|
+
expect(protocols.protocol_codes).to eq [
|
105
|
+
Protocols::IPV4,
|
106
|
+
Protocols::IPV6,
|
107
|
+
]
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
context 'wildcard server, IPV6 connection' do
|
113
|
+
|
114
|
+
let(:bind_address) {'::'}
|
115
|
+
let(:connect_address) {'::1'}
|
116
|
+
let(:connected_socket) do
|
117
|
+
TestServer.new(bind_address, connect_address).connected_socket
|
118
|
+
end
|
119
|
+
subject(:protocols) {Protocols.new(connected_socket)}
|
120
|
+
|
121
|
+
it 'should support IPV4' do
|
122
|
+
expect(protocols.supports_protocol?(Protocols::IPV4)).to be_true
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'should support IPV6' do
|
126
|
+
expect(protocols.supports_protocol?(Protocols::IPV6)).to be_true
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'should list the supported protocols' do
|
130
|
+
expect(protocols.protocol_codes).to eq [
|
131
|
+
Protocols::IPV4,
|
132
|
+
Protocols::IPV6,
|
133
|
+
]
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,20 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ftpd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.9.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Wayne Conrad
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-
|
11
|
+
date: 2013-10-01 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: memoizer
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
17
|
- - ~>
|
20
18
|
- !ruby/object:Gem::Version
|
@@ -22,7 +20,6 @@ dependencies:
|
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
24
|
- - ~>
|
28
25
|
- !ruby/object:Gem::Version
|
@@ -30,129 +27,113 @@ dependencies:
|
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: cucumber
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - '>='
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :development
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - '>='
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: double-bag-ftps
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - '>='
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '0'
|
54
48
|
type: :development
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - '>='
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: '0'
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
56
|
name: jeweler
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
|
-
- - '
|
59
|
+
- - '>='
|
68
60
|
- !ruby/object:Gem::Version
|
69
|
-
version:
|
61
|
+
version: '0'
|
70
62
|
type: :development
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
|
-
- - '
|
66
|
+
- - '>='
|
76
67
|
- !ruby/object:Gem::Version
|
77
|
-
version:
|
68
|
+
version: '0'
|
78
69
|
- !ruby/object:Gem::Dependency
|
79
70
|
name: rake
|
80
71
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
72
|
requirements:
|
83
|
-
- -
|
73
|
+
- - '>='
|
84
74
|
- !ruby/object:Gem::Version
|
85
75
|
version: '0'
|
86
76
|
type: :development
|
87
77
|
prerelease: false
|
88
78
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
79
|
requirements:
|
91
|
-
- -
|
80
|
+
- - '>='
|
92
81
|
- !ruby/object:Gem::Version
|
93
82
|
version: '0'
|
94
83
|
- !ruby/object:Gem::Dependency
|
95
84
|
name: redcarpet
|
96
85
|
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
86
|
requirements:
|
99
|
-
- -
|
87
|
+
- - '>='
|
100
88
|
- !ruby/object:Gem::Version
|
101
89
|
version: '0'
|
102
90
|
type: :development
|
103
91
|
prerelease: false
|
104
92
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
93
|
requirements:
|
107
|
-
- -
|
94
|
+
- - '>='
|
108
95
|
- !ruby/object:Gem::Version
|
109
96
|
version: '0'
|
110
97
|
- !ruby/object:Gem::Dependency
|
111
98
|
name: rspec
|
112
99
|
requirement: !ruby/object:Gem::Requirement
|
113
|
-
none: false
|
114
100
|
requirements:
|
115
|
-
- -
|
101
|
+
- - '>='
|
116
102
|
- !ruby/object:Gem::Version
|
117
103
|
version: '0'
|
118
104
|
type: :development
|
119
105
|
prerelease: false
|
120
106
|
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
107
|
requirements:
|
123
|
-
- -
|
108
|
+
- - '>='
|
124
109
|
- !ruby/object:Gem::Version
|
125
110
|
version: '0'
|
126
111
|
- !ruby/object:Gem::Dependency
|
127
112
|
name: timecop
|
128
113
|
requirement: !ruby/object:Gem::Requirement
|
129
|
-
none: false
|
130
114
|
requirements:
|
131
|
-
- -
|
115
|
+
- - '>='
|
132
116
|
- !ruby/object:Gem::Version
|
133
117
|
version: '0'
|
134
118
|
type: :development
|
135
119
|
prerelease: false
|
136
120
|
version_requirements: !ruby/object:Gem::Requirement
|
137
|
-
none: false
|
138
121
|
requirements:
|
139
|
-
- -
|
122
|
+
- - '>='
|
140
123
|
- !ruby/object:Gem::Version
|
141
124
|
version: '0'
|
142
125
|
- !ruby/object:Gem::Dependency
|
143
126
|
name: yard
|
144
127
|
requirement: !ruby/object:Gem::Requirement
|
145
|
-
none: false
|
146
128
|
requirements:
|
147
|
-
- -
|
129
|
+
- - '>='
|
148
130
|
- !ruby/object:Gem::Version
|
149
131
|
version: '0'
|
150
132
|
type: :development
|
151
133
|
prerelease: false
|
152
134
|
version_requirements: !ruby/object:Gem::Requirement
|
153
|
-
none: false
|
154
135
|
requirements:
|
155
|
-
- -
|
136
|
+
- - '>='
|
156
137
|
- !ruby/object:Gem::Version
|
157
138
|
version: '0'
|
158
139
|
description: ftpd is a pure Ruby FTP server library. It supports implicit and explicit
|
@@ -177,6 +158,7 @@ files:
|
|
177
158
|
- doc/references.md
|
178
159
|
- doc/rfc-compliance.md
|
179
160
|
- examples/example.rb
|
161
|
+
- examples/example_spec.rb
|
180
162
|
- examples/hello_world.rb
|
181
163
|
- features/example/eplf.feature
|
182
164
|
- features/example/example.feature
|
@@ -192,9 +174,12 @@ files:
|
|
192
174
|
- features/ftp_server/delete.feature
|
193
175
|
- features/ftp_server/directory_navigation.feature
|
194
176
|
- features/ftp_server/disconnect_after_failed_logins.feature
|
177
|
+
- features/ftp_server/eprt.feature
|
178
|
+
- features/ftp_server/epsv.feature
|
195
179
|
- features/ftp_server/features.feature
|
196
180
|
- features/ftp_server/file_structure.feature
|
197
181
|
- features/ftp_server/get.feature
|
182
|
+
- features/ftp_server/get_ipv6.feature
|
198
183
|
- features/ftp_server/get_tls.feature
|
199
184
|
- features/ftp_server/help.feature
|
200
185
|
- features/ftp_server/implicit_tls.feature
|
@@ -212,6 +197,7 @@ files:
|
|
212
197
|
- features/ftp_server/name_list_tls.feature
|
213
198
|
- features/ftp_server/noop.feature
|
214
199
|
- features/ftp_server/options.feature
|
200
|
+
- features/ftp_server/pasv.feature
|
215
201
|
- features/ftp_server/port.feature
|
216
202
|
- features/ftp_server/put.feature
|
217
203
|
- features/ftp_server/put_tls.feature
|
@@ -292,7 +278,9 @@ files:
|
|
292
278
|
- lib/ftpd/insecure_certificate.rb
|
293
279
|
- lib/ftpd/list_format/eplf.rb
|
294
280
|
- lib/ftpd/list_format/ls.rb
|
281
|
+
- lib/ftpd/list_path.rb
|
295
282
|
- lib/ftpd/null_logger.rb
|
283
|
+
- lib/ftpd/protocols.rb
|
296
284
|
- lib/ftpd/read_only_disk_file_system.rb
|
297
285
|
- lib/ftpd/server.rb
|
298
286
|
- lib/ftpd/session.rb
|
@@ -315,36 +303,34 @@ files:
|
|
315
303
|
- spec/file_system_error_translator_spec.rb
|
316
304
|
- spec/list_format/eplf_spec.rb
|
317
305
|
- spec/list_format/ls_spec.rb
|
306
|
+
- spec/list_path_spec.rb
|
318
307
|
- spec/null_logger_spec.rb
|
308
|
+
- spec/protocols_spec.rb
|
319
309
|
- spec/spec_helper.rb
|
320
310
|
- spec/telnet_spec.rb
|
321
311
|
- spec/translate_exceptions_spec.rb
|
322
312
|
homepage: http://github.com/wconrad/ftpd
|
323
313
|
licenses:
|
324
314
|
- MIT
|
315
|
+
metadata: {}
|
325
316
|
post_install_message:
|
326
317
|
rdoc_options: []
|
327
318
|
require_paths:
|
328
319
|
- lib
|
329
320
|
required_ruby_version: !ruby/object:Gem::Requirement
|
330
|
-
none: false
|
331
321
|
requirements:
|
332
|
-
- -
|
322
|
+
- - '>='
|
333
323
|
- !ruby/object:Gem::Version
|
334
324
|
version: '0'
|
335
|
-
segments:
|
336
|
-
- 0
|
337
|
-
hash: 351587119
|
338
325
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
339
|
-
none: false
|
340
326
|
requirements:
|
341
|
-
- -
|
327
|
+
- - '>='
|
342
328
|
- !ruby/object:Gem::Version
|
343
329
|
version: '0'
|
344
330
|
requirements: []
|
345
331
|
rubyforge_project:
|
346
|
-
rubygems_version:
|
332
|
+
rubygems_version: 2.0.0
|
347
333
|
signing_key:
|
348
|
-
specification_version:
|
334
|
+
specification_version: 4
|
349
335
|
summary: Pure Ruby FTP server library
|
350
336
|
test_files: []
|