fake_ftp 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|