fake_ftp 0.0.4 → 0.0.5
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.
- data/Gemfile.lock +1 -1
- data/README.markdown +3 -1
- data/lib/fake_ftp/file.rb +15 -4
- data/lib/fake_ftp/server.rb +60 -11
- data/lib/fake_ftp/version.rb +1 -1
- data/spec/models/fake_ftp/file_spec.rb +6 -0
- data/spec/models/fake_ftp/server_spec.rb +84 -1
- metadata +6 -6
data/Gemfile.lock
CHANGED
data/README.markdown
CHANGED
@@ -63,6 +63,7 @@ To test active upload:
|
|
63
63
|
|
64
64
|
server.stop
|
65
65
|
|
66
|
+
Note that many FTP clients default to active, unless specified otherwise.
|
66
67
|
|
67
68
|
References
|
68
69
|
----------
|
@@ -75,6 +76,7 @@ Contributors
|
|
75
76
|
|
76
77
|
* Eric Saxby
|
77
78
|
* Colin Shield
|
79
|
+
* liehann (https://github.com/liehann)
|
78
80
|
|
79
81
|
License
|
80
82
|
-------
|
@@ -99,4 +101,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
99
101
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
100
102
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
101
103
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
102
|
-
THE SOFTWARE.
|
104
|
+
THE SOFTWARE.
|
data/lib/fake_ftp/file.rb
CHANGED
@@ -2,11 +2,22 @@ module FakeFtp
|
|
2
2
|
class File
|
3
3
|
attr_accessor :bytes, :name
|
4
4
|
attr_writer :type
|
5
|
+
attr_accessor :data
|
6
|
+
attr_reader :created
|
5
7
|
|
6
|
-
def initialize(name = nil,
|
7
|
-
|
8
|
-
|
9
|
-
|
8
|
+
def initialize(name = nil, data = nil, type = nil)
|
9
|
+
@created = Time.now
|
10
|
+
@name = name
|
11
|
+
@data = data
|
12
|
+
data_is_bytes = (data.nil? || Integer === data)
|
13
|
+
@bytes = data_is_bytes ? data : data.length
|
14
|
+
@data = data_is_bytes ? nil : data
|
15
|
+
@type = type
|
16
|
+
end
|
17
|
+
|
18
|
+
def data=(data)
|
19
|
+
@data = data
|
20
|
+
@bytes = @data.nil? ? nil : data.length
|
10
21
|
end
|
11
22
|
|
12
23
|
def passive?
|
data/lib/fake_ftp/server.rb
CHANGED
@@ -7,7 +7,7 @@ module FakeFtp
|
|
7
7
|
attr_accessor :port, :passive_port
|
8
8
|
attr_reader :mode
|
9
9
|
|
10
|
-
CMDS = %w[acct cwd cdup pass pasv port pwd quit stor type user]
|
10
|
+
CMDS = %w[acct cwd cdup list nlst pass pasv port pwd quit stor retr type user]
|
11
11
|
LNBK = "\r\n"
|
12
12
|
|
13
13
|
def initialize(control_port = 21, data_port = nil, options = {})
|
@@ -29,6 +29,10 @@ module FakeFtp
|
|
29
29
|
@files.detect { |file| file.name == name }
|
30
30
|
end
|
31
31
|
|
32
|
+
def add_file(filename, data)
|
33
|
+
@files << FakeFtp::File.new(::File.basename(filename.to_s), data, @mode)
|
34
|
+
end
|
35
|
+
|
32
36
|
def start
|
33
37
|
@started = true
|
34
38
|
@server = ::TCPServer.new('127.0.0.1', port)
|
@@ -134,18 +138,13 @@ module FakeFtp
|
|
134
138
|
end
|
135
139
|
|
136
140
|
def _stor(filename)
|
137
|
-
if
|
138
|
-
respond_with('125 Do it!')
|
139
|
-
data_client = @data_server.accept
|
140
|
-
else
|
141
|
-
respond_with('425 Ain\'t no data port!') && return if @active_connection.nil?
|
142
|
-
respond_with('125 Do it!')
|
141
|
+
respond_with('425 Ain\'t no data port!') && return if active? && @active_connection.nil?
|
143
142
|
|
144
|
-
|
145
|
-
|
143
|
+
respond_with('125 Do it!')
|
144
|
+
data_client = active? ? @active_connection : @data_server.accept
|
146
145
|
|
147
146
|
data = data_client.recv(1024)
|
148
|
-
file = FakeFtp::File.new(::File.basename(filename.to_s), data
|
147
|
+
file = FakeFtp::File.new(::File.basename(filename.to_s), data, @mode)
|
149
148
|
@files << file
|
150
149
|
|
151
150
|
data_client.close
|
@@ -153,6 +152,52 @@ module FakeFtp
|
|
153
152
|
'226 Did it!'
|
154
153
|
end
|
155
154
|
|
155
|
+
def _retr(filename)
|
156
|
+
respond_with('501 No filename given') if filename.empty?
|
157
|
+
|
158
|
+
file = file(::File.basename(filename.to_s))
|
159
|
+
return respond_with('550 File not found') if file.nil?
|
160
|
+
|
161
|
+
respond_with('425 Ain\'t no data port!') && return if active? && @active_connection.nil?
|
162
|
+
|
163
|
+
respond_with('150 File status ok, about to open data connection')
|
164
|
+
data_client = active? ? @active_connection : @data_server.accept
|
165
|
+
|
166
|
+
data_client.write(file.data)
|
167
|
+
|
168
|
+
data_client.close
|
169
|
+
@active_connection = nil
|
170
|
+
'226 File transferred'
|
171
|
+
end
|
172
|
+
|
173
|
+
def _list(args)
|
174
|
+
respond_with('425 Ain\'t no data port!') && return if active? && @active_connection.nil?
|
175
|
+
|
176
|
+
respond_with('150 Listing status ok, about to open data connection')
|
177
|
+
data_client = active? ? @active_connection : @data_server.accept
|
178
|
+
|
179
|
+
data_client.write(@files.map do |f|
|
180
|
+
"-rw-r--r--\t1\towner\tgroup\t#{f.bytes}\t#{f.created.strftime('%b %d %H:%M')}\t#{f.name}"
|
181
|
+
end.join("\n"))
|
182
|
+
data_client.close
|
183
|
+
@active_connection = nil
|
184
|
+
|
185
|
+
'226 List information transferred'
|
186
|
+
end
|
187
|
+
|
188
|
+
def _nlst(args)
|
189
|
+
respond_with('425 Ain\'t no data port!') && return if active? && @active_connection.nil?
|
190
|
+
|
191
|
+
respond_with('150 Listing status ok, about to open data connection')
|
192
|
+
data_client = active? ? @active_connection : @data_server.accept
|
193
|
+
|
194
|
+
data_client.write(files.join("\n"))
|
195
|
+
data_client.close
|
196
|
+
@active_connection = nil
|
197
|
+
|
198
|
+
'226 List information transferred'
|
199
|
+
end
|
200
|
+
|
156
201
|
def _type(type = 'A')
|
157
202
|
case type.to_s
|
158
203
|
when 'A'
|
@@ -167,5 +212,9 @@ module FakeFtp
|
|
167
212
|
def _user(name = '')
|
168
213
|
(name.to_s == 'anonymous') ? '230 logged in' : '331 send your password'
|
169
214
|
end
|
215
|
+
|
216
|
+
def active?
|
217
|
+
@mode == :active
|
218
|
+
end
|
170
219
|
end
|
171
|
-
end
|
220
|
+
end
|
data/lib/fake_ftp/version.rb
CHANGED
@@ -15,6 +15,12 @@ describe FakeFtp::File do
|
|
15
15
|
@file.bytes = 87
|
16
16
|
@file.bytes.should == 87
|
17
17
|
end
|
18
|
+
|
19
|
+
it "has a data attribute" do
|
20
|
+
@file.data = 'some data'
|
21
|
+
@file.data.should == 'some data'
|
22
|
+
@file.bytes.should == 'some data'.length
|
23
|
+
end
|
18
24
|
end
|
19
25
|
|
20
26
|
context 'setup' do
|
@@ -311,6 +311,55 @@ describe FakeFtp::Server do
|
|
311
311
|
@server.files.should include('some_file')
|
312
312
|
@server.file('some_file').bytes.should == 10
|
313
313
|
end
|
314
|
+
|
315
|
+
it "does not accept RETR without a filename" do
|
316
|
+
@client.puts "RETR"
|
317
|
+
@client.gets.should == "501 No filename given\r\n"
|
318
|
+
end
|
319
|
+
|
320
|
+
it "does not serve files that do not exist" do
|
321
|
+
@client.puts "RETR some_file"
|
322
|
+
@client.gets.should == "550 File not found\r\n"
|
323
|
+
end
|
324
|
+
|
325
|
+
it "accepts RETR with a filename" do
|
326
|
+
@server.add_file('some_file', '1234567890')
|
327
|
+
@client.puts "RETR some_file"
|
328
|
+
@client.gets.should == "150 File status ok, about to open data connection\r\n"
|
329
|
+
@data_client = TCPSocket.open('127.0.0.1', 21213)
|
330
|
+
data = @data_client.read(1024)
|
331
|
+
@data_client.close
|
332
|
+
data.should == '1234567890'
|
333
|
+
@client.gets.should == "226 File transferred\r\n"
|
334
|
+
end
|
335
|
+
|
336
|
+
it "accepts a LIST command" do
|
337
|
+
@server.add_file('some_file', '1234567890')
|
338
|
+
@server.add_file('another_file', '1234567890')
|
339
|
+
@client.puts "LIST"
|
340
|
+
@client.gets.should == "150 Listing status ok, about to open data connection\r\n"
|
341
|
+
@data_client = TCPSocket.open('127.0.0.1', 21213)
|
342
|
+
data = @data_client.read(2048)
|
343
|
+
@data_client.close
|
344
|
+
data.should == [
|
345
|
+
"-rw-r--r--\t1\towner\tgroup\t10\t#{@server.file('some_file').created.strftime('%b %d %H:%M')}\tsome_file",
|
346
|
+
"-rw-r--r--\t1\towner\tgroup\t10\t#{@server.file('another_file').created.strftime('%b %d %H:%M')}\tanother_file",
|
347
|
+
].join("\n")
|
348
|
+
@client.gets.should == "226 List information transferred\r\n"
|
349
|
+
end
|
350
|
+
|
351
|
+
it "accepts an NLST command" do
|
352
|
+
@server.add_file('some_file', '1234567890')
|
353
|
+
@server.add_file('another_file', '1234567890')
|
354
|
+
@client.puts "NLST"
|
355
|
+
@client.gets.should == "150 Listing status ok, about to open data connection\r\n"
|
356
|
+
@data_client = TCPSocket.open('127.0.0.1', 21213)
|
357
|
+
data = @data_client.read(1024)
|
358
|
+
@data_client.close
|
359
|
+
data.should == "some_file\nanother_file"
|
360
|
+
@client.gets.should == "226 List information transferred\r\n"
|
361
|
+
end
|
362
|
+
|
314
363
|
end
|
315
364
|
|
316
365
|
context 'active' do
|
@@ -347,6 +396,40 @@ describe FakeFtp::Server do
|
|
347
396
|
@server.files.should include('some_other_file')
|
348
397
|
@server.file('some_other_file').bytes.should == 5
|
349
398
|
end
|
399
|
+
|
400
|
+
it "accepts RETR with a filename" do
|
401
|
+
@client.puts "PORT 127,0,0,1,82,224"
|
402
|
+
@client.gets.should == "200 Okay\r\n"
|
403
|
+
|
404
|
+
@server.add_file('some_file', '1234567890')
|
405
|
+
@client.puts "RETR some_file"
|
406
|
+
@client.gets.should == "150 File status ok, about to open data connection\r\n"
|
407
|
+
|
408
|
+
@data_connection.join
|
409
|
+
data = @server_client.read(1024)
|
410
|
+
@server_client.close
|
411
|
+
|
412
|
+
data.should == '1234567890'
|
413
|
+
@client.gets.should == "226 File transferred\r\n"
|
414
|
+
end
|
415
|
+
|
416
|
+
it "accepts an NLST command" do
|
417
|
+
@client.puts "PORT 127,0,0,1,82,224"
|
418
|
+
@client.gets.should == "200 Okay\r\n"
|
419
|
+
|
420
|
+
@server.add_file('some_file', '1234567890')
|
421
|
+
@server.add_file('another_file', '1234567890')
|
422
|
+
@client.puts "NLST"
|
423
|
+
@client.gets.should == "150 Listing status ok, about to open data connection\r\n"
|
424
|
+
|
425
|
+
@data_connection.join
|
426
|
+
data = @server_client.read(1024)
|
427
|
+
@server_client.close
|
428
|
+
|
429
|
+
data.should == "some_file\nanother_file"
|
430
|
+
@client.gets.should == "226 List information transferred\r\n"
|
431
|
+
end
|
432
|
+
|
350
433
|
end
|
351
434
|
end
|
352
435
|
end
|
@@ -415,4 +498,4 @@ describe FakeFtp::Server do
|
|
415
498
|
end
|
416
499
|
end
|
417
500
|
end
|
418
|
-
end
|
501
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fake_ftp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 21
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 5
|
10
|
+
version: 0.0.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Colin Shield
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2011-
|
19
|
+
date: 2011-05-12 00:00:00 -07:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
@@ -123,7 +123,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
123
123
|
requirements: []
|
124
124
|
|
125
125
|
rubyforge_project: fake_ftp
|
126
|
-
rubygems_version: 1.3
|
126
|
+
rubygems_version: 1.5.3
|
127
127
|
signing_key:
|
128
128
|
specification_version: 3
|
129
129
|
summary: Creates a fake FTP server for use in testing
|