ftpd 0.0.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of ftpd might be problematic. Click here for more details.
- data/Gemfile +9 -0
- data/Gemfile.lock +43 -0
- data/LICENSE.md +9 -0
- data/README.md +57 -0
- data/Rakefile +8 -0
- data/VERSION +1 -0
- data/features/command_errors.feature +33 -0
- data/features/delete.feature +34 -0
- data/features/directory_navigation.feature +34 -0
- data/features/file_structure.feature +40 -0
- data/features/get.feature +62 -0
- data/features/list.feature +77 -0
- data/features/login.feature +54 -0
- data/features/mode.feature +40 -0
- data/features/name_list.feature +77 -0
- data/features/noop.feature +14 -0
- data/features/port.feature +25 -0
- data/features/put.feature +65 -0
- data/features/quit.feature +20 -0
- data/features/step_definitions/client_and_server_files.rb +24 -0
- data/features/step_definitions/client_files.rb +9 -0
- data/features/step_definitions/command.rb +5 -0
- data/features/step_definitions/connect.rb +15 -0
- data/features/step_definitions/delete.rb +15 -0
- data/features/step_definitions/directories.rb +22 -0
- data/features/step_definitions/error.rb +87 -0
- data/features/step_definitions/file_structure.rb +16 -0
- data/features/step_definitions/get.rb +16 -0
- data/features/step_definitions/invalid_commands.rb +11 -0
- data/features/step_definitions/line_endings.rb +7 -0
- data/features/step_definitions/list.rb +46 -0
- data/features/step_definitions/login.rb +69 -0
- data/features/step_definitions/mode.rb +15 -0
- data/features/step_definitions/noop.rb +13 -0
- data/features/step_definitions/passive.rb +3 -0
- data/features/step_definitions/port.rb +5 -0
- data/features/step_definitions/put.rb +16 -0
- data/features/step_definitions/quit.rb +15 -0
- data/features/step_definitions/server.rb +7 -0
- data/features/step_definitions/server_files.rb +18 -0
- data/features/step_definitions/type.rb +15 -0
- data/features/support/env.rb +4 -0
- data/features/support/file_templates/ascii_unix +4 -0
- data/features/support/file_templates/ascii_windows +4 -0
- data/features/support/file_templates/binary +0 -0
- data/features/support/test_client.rb +89 -0
- data/features/support/test_file_templates.rb +33 -0
- data/features/support/test_server.rb +52 -0
- data/features/syntax_errors.feature +15 -0
- data/features/type.feature +53 -0
- data/ftpd.gemspec +112 -0
- data/insecure-test-cert.pem +29 -0
- data/lib/ftpd.rb +6 -0
- data/lib/ftpd/FakeFtpServer.rb +736 -0
- data/lib/ftpd/FakeServer.rb +57 -0
- data/lib/ftpd/FakeTlsServer.rb +52 -0
- data/lib/ftpd/ObjectUtil.rb +66 -0
- data/lib/ftpd/TempDir.rb +54 -0
- data/lib/ftpd/q.rb +92 -0
- data/rake_tasks/cucumber.rake +7 -0
- data/rake_tasks/jeweler.rake +25 -0
- metadata +164 -0
@@ -0,0 +1,40 @@
|
|
1
|
+
Feature: Mode
|
2
|
+
|
3
|
+
As a client
|
4
|
+
I want to set the file transfer mode
|
5
|
+
So that can optimize the transfer
|
6
|
+
|
7
|
+
Scenario: Stream
|
8
|
+
Given a successful login
|
9
|
+
And the server has file "ascii_unix"
|
10
|
+
When the client successfully sets mode "S"
|
11
|
+
And the client successfully gets text "ascii_unix"
|
12
|
+
Then the remote file "ascii_unix" should match the local file
|
13
|
+
|
14
|
+
Scenario: Block
|
15
|
+
Given a successful login
|
16
|
+
And the server has file "ascii_unix"
|
17
|
+
When the client sets mode "B"
|
18
|
+
Then the server returns a mode not implemented error
|
19
|
+
|
20
|
+
Scenario: Compressed
|
21
|
+
Given a successful login
|
22
|
+
And the server has file "ascii_unix"
|
23
|
+
When the client sets mode "C"
|
24
|
+
Then the server returns a mode not implemented error
|
25
|
+
|
26
|
+
Scenario: Invalid
|
27
|
+
Given a successful login
|
28
|
+
And the server has file "ascii_unix"
|
29
|
+
When the client sets mode "*"
|
30
|
+
Then the server returns an invalid mode error
|
31
|
+
|
32
|
+
Scenario: Not logged in
|
33
|
+
Given a successful connection
|
34
|
+
When the client sets mode "S"
|
35
|
+
Then the server returns a not logged in error
|
36
|
+
|
37
|
+
Scenario: Missing parameter
|
38
|
+
Given a successful login
|
39
|
+
When the client sets mode with no parameter
|
40
|
+
Then the server returns a syntax error
|
@@ -0,0 +1,77 @@
|
|
1
|
+
Feature: Name List
|
2
|
+
|
3
|
+
As a client
|
4
|
+
I want to list file names
|
5
|
+
So that I can see what file to transfer
|
6
|
+
|
7
|
+
Scenario: List implicit
|
8
|
+
Given a successful login
|
9
|
+
And the server has file "foo"
|
10
|
+
And the server has file "bar"
|
11
|
+
When the client name lists the directory
|
12
|
+
Then the file list should be in short form
|
13
|
+
And the file list should contain "foo"
|
14
|
+
And the file list should contain "bar"
|
15
|
+
|
16
|
+
Scenario: List root
|
17
|
+
Given a successful login
|
18
|
+
And the server has file "foo"
|
19
|
+
And the server has file "bar"
|
20
|
+
When the client name lists the directory "/"
|
21
|
+
Then the file list should be in short form
|
22
|
+
And the file list should contain "foo"
|
23
|
+
And the file list should contain "bar"
|
24
|
+
|
25
|
+
Scenario: List subdir
|
26
|
+
Given a successful login
|
27
|
+
And the server has file "subdir/foo"
|
28
|
+
When the client name lists the directory "subdir"
|
29
|
+
Then the file list should be in short form
|
30
|
+
And the file list should contain "foo"
|
31
|
+
|
32
|
+
Scenario: List glob
|
33
|
+
Given a successful login
|
34
|
+
And the server has file "foo"
|
35
|
+
And the server has file "bar"
|
36
|
+
When the client name lists the directory "f*"
|
37
|
+
Then the file list should be in short form
|
38
|
+
And the file list should contain "foo"
|
39
|
+
And the file list should not contain "bar"
|
40
|
+
|
41
|
+
Scenario: Passive
|
42
|
+
Given a successful login
|
43
|
+
And the server has file "foo"
|
44
|
+
And the server has file "bar"
|
45
|
+
And the client is in passive mode
|
46
|
+
When the client name lists the directory
|
47
|
+
Then the file list should be in short form
|
48
|
+
And the file list should contain "foo"
|
49
|
+
And the file list should contain "bar"
|
50
|
+
|
51
|
+
Scenario: TLS
|
52
|
+
pending "TLS not supported in active mode (see README)"
|
53
|
+
|
54
|
+
Scenario: TLS, Passive
|
55
|
+
Given a successful login with TLS
|
56
|
+
And the server has file "foo"
|
57
|
+
And the server has file "bar"
|
58
|
+
And the client is in passive mode
|
59
|
+
When the client name lists the directory
|
60
|
+
Then the file list should be in short form
|
61
|
+
And the file list should contain "foo"
|
62
|
+
And the file list should contain "bar"
|
63
|
+
|
64
|
+
Scenario: Path outside tree
|
65
|
+
Given a successful login
|
66
|
+
When the client name lists the directory ".."
|
67
|
+
Then the server returns an access denied error
|
68
|
+
|
69
|
+
Scenario: Missing file
|
70
|
+
Given a successful login
|
71
|
+
When the client name lists the directory "missing/file"
|
72
|
+
Then the server returns a no such file error
|
73
|
+
|
74
|
+
Scenario: Not logged in
|
75
|
+
Given a successful connection
|
76
|
+
When the client name lists the directory
|
77
|
+
Then the server returns a not logged in error
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Feature: No Operation
|
2
|
+
|
3
|
+
As a client
|
4
|
+
I want to keep the connection alive
|
5
|
+
So that I don't have to log in so often
|
6
|
+
|
7
|
+
Scenario: NOP
|
8
|
+
Given a successful connection
|
9
|
+
Then the client successfully does nothing
|
10
|
+
|
11
|
+
Scenario: With a parameter
|
12
|
+
Given a successful connection
|
13
|
+
When the client does nothing with a parameter
|
14
|
+
Then the server returns a syntax error
|
@@ -0,0 +1,25 @@
|
|
1
|
+
Feature: Port
|
2
|
+
|
3
|
+
As a programmer
|
4
|
+
I want good error messages
|
5
|
+
So that I can correct problems
|
6
|
+
|
7
|
+
Scenario: Not logged in
|
8
|
+
Given a successful connection
|
9
|
+
When the client sends PORT "1,2,3,4,5,6"
|
10
|
+
Then the server returns a not logged in error
|
11
|
+
|
12
|
+
Scenario: Incorrect number of bytes
|
13
|
+
Given a successful login
|
14
|
+
When the client sends PORT "1,2,3,4,5"
|
15
|
+
Then the server returns a syntax error
|
16
|
+
|
17
|
+
Scenario: Ill formatted byte
|
18
|
+
Given a successful login
|
19
|
+
When the client sends PORT "1,2,3,4,5,0006"
|
20
|
+
Then the server returns a syntax error
|
21
|
+
|
22
|
+
Scenario: Byte out of range
|
23
|
+
Given a successful login
|
24
|
+
When the client sends PORT "1,2,3,4,5,256"
|
25
|
+
Then the server returns a syntax error
|
@@ -0,0 +1,65 @@
|
|
1
|
+
Feature: Put
|
2
|
+
|
3
|
+
As a client
|
4
|
+
I want to put a file
|
5
|
+
So that someone else can have it
|
6
|
+
|
7
|
+
Scenario: ASCII file with *nix line endings
|
8
|
+
Given a successful login
|
9
|
+
And the client has file "ascii_unix"
|
10
|
+
When the client successfully puts text "ascii_unix"
|
11
|
+
Then the remote file "ascii_unix" should match the local file
|
12
|
+
And the remote file "ascii_unix" should have unix line endings
|
13
|
+
|
14
|
+
Scenario: ASCII file with windows line endings
|
15
|
+
Given a successful login
|
16
|
+
And the client has file "ascii_windows"
|
17
|
+
When the client successfully puts text "ascii_windows"
|
18
|
+
Then the remote file "ascii_windows" should match the local file
|
19
|
+
And the remote file "ascii_windows" should have unix line endings
|
20
|
+
|
21
|
+
Scenario: Binary file
|
22
|
+
Given a successful login
|
23
|
+
And the client has file "binary"
|
24
|
+
When the client successfully puts binary "binary"
|
25
|
+
Then the remote file "binary" should exactly match the local file
|
26
|
+
|
27
|
+
Scenario: Passive
|
28
|
+
Given a successful login
|
29
|
+
And the client has file "ascii_unix"
|
30
|
+
And the client is in passive mode
|
31
|
+
When the client successfully puts text "ascii_unix"
|
32
|
+
Then the remote file "ascii_unix" should match the local file
|
33
|
+
|
34
|
+
Scenario: TLS
|
35
|
+
pending "TLS not supported in active mode (see README)"
|
36
|
+
|
37
|
+
Scenario: TLS, Passive
|
38
|
+
Given a successful login with TLS
|
39
|
+
And the client has file "ascii_unix"
|
40
|
+
And the client is in passive mode
|
41
|
+
When the client successfully puts text "ascii_unix"
|
42
|
+
Then the remote file "ascii_unix" should match the local file
|
43
|
+
|
44
|
+
Scenario: Path outside tree
|
45
|
+
Given a successful login
|
46
|
+
And the client has file "foo"
|
47
|
+
When the client puts text "../foo"
|
48
|
+
Then the server returns an access denied error
|
49
|
+
|
50
|
+
Scenario: Missing directory
|
51
|
+
Given a successful login
|
52
|
+
And the client has file "bar"
|
53
|
+
When the client puts text "foo/bar"
|
54
|
+
Then the server returns a no such file error
|
55
|
+
|
56
|
+
Scenario: Not logged in
|
57
|
+
Given a successful connection
|
58
|
+
And the client has file "foo"
|
59
|
+
When the client puts text "foo"
|
60
|
+
Then the server returns a not logged in error
|
61
|
+
|
62
|
+
Scenario: Missing path
|
63
|
+
Given a successful login
|
64
|
+
When the client puts with no path
|
65
|
+
Then the server returns a syntax error
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Feature: Quit
|
2
|
+
|
3
|
+
As a client
|
4
|
+
In order to free up resources
|
5
|
+
I want to close the connection
|
6
|
+
|
7
|
+
Scenario: Logged in
|
8
|
+
Given a successful login
|
9
|
+
When the client successfully quits
|
10
|
+
Then the client should not be logged in
|
11
|
+
|
12
|
+
Scenario: With a parameter
|
13
|
+
Given a successful connection
|
14
|
+
When the client quits with a parameter
|
15
|
+
Then the server returns a syntax error
|
16
|
+
|
17
|
+
Scenario: Not logged in
|
18
|
+
Given a successful connection
|
19
|
+
When the client quits
|
20
|
+
Then the server returns a not logged in error
|
@@ -0,0 +1,24 @@
|
|
1
|
+
def unix_line_endings(exactly, s)
|
2
|
+
return s if exactly
|
3
|
+
s.gsub(/\r\n/, "\n")
|
4
|
+
end
|
5
|
+
|
6
|
+
Then /^the remote file "(.*?)" should( exactly)? match the local file$/ do
|
7
|
+
|remote_path, exactly|
|
8
|
+
local_path = File.basename(remote_path)
|
9
|
+
remote_contents = @server.file_contents(remote_path)
|
10
|
+
local_contents = @client.file_contents(local_path)
|
11
|
+
remote_contents = unix_line_endings(exactly, remote_contents)
|
12
|
+
local_contents = unix_line_endings(exactly, local_contents)
|
13
|
+
remote_contents.should == local_contents
|
14
|
+
end
|
15
|
+
|
16
|
+
Then /^the local file "(.*?)" should( exactly)? match the remote file$/ do
|
17
|
+
|local_path, exactly|
|
18
|
+
remote_path = local_path
|
19
|
+
remote_contents = @server.file_contents(remote_path)
|
20
|
+
local_contents = @client.file_contents(local_path)
|
21
|
+
remote_contents = unix_line_endings(exactly, remote_contents)
|
22
|
+
local_contents = unix_line_endings(exactly, local_contents)
|
23
|
+
local_contents.should == remote_contents
|
24
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
Given /^the client has file "(.*?)"$/ do |local_path|
|
2
|
+
@client.add_file local_path
|
3
|
+
end
|
4
|
+
|
5
|
+
Then /^the local file "(.*?)" should have (unix|windows) line endings$/ do
|
6
|
+
|local_path, line_ending_type|
|
7
|
+
line_ending_type(@client.file_contents(local_path)).should ==
|
8
|
+
line_ending_type.to_sym
|
9
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'double_bag_ftps'
|
2
|
+
require 'net/ftp'
|
3
|
+
|
4
|
+
When /^the client connects( with TLS)?$/ do |with_tls|
|
5
|
+
@client = TestClient.new(:tls => with_tls)
|
6
|
+
@client.connect(@server.host, @server.port)
|
7
|
+
end
|
8
|
+
|
9
|
+
Then /^the connection is closed$/ do
|
10
|
+
@client.should be_closed
|
11
|
+
end
|
12
|
+
|
13
|
+
Then /^the connection is open$/ do
|
14
|
+
@client.should be_open
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
When /^the client deletes "(.*?)"$/ do |path|
|
2
|
+
capture_error do
|
3
|
+
step %Q(the client successfully deletes "#{path}")
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
When /^the client successfully deletes "(.*?)"$/ do |path|
|
8
|
+
@client.delete path
|
9
|
+
end
|
10
|
+
|
11
|
+
When /^the client deletes with no path$/ do
|
12
|
+
capture_error do
|
13
|
+
@client.raw 'DELE'
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
When /^the client cd's to "(.*?)"$/ do |path|
|
2
|
+
capture_error do
|
3
|
+
step %Q(the client successfully cd's to "#{path}")
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
# As of Ruby 1.9.3-p125, Net::FTP#chdir('..') will send a CDUP.
|
8
|
+
# However, that could conceivably change: The use of CDUP not
|
9
|
+
# required by the FTP protocol. Therefore we use this step to
|
10
|
+
# ensure that CDUP is sent and therefore tested.
|
11
|
+
|
12
|
+
When /^the client successfully cd's up$/ do
|
13
|
+
@client.raw 'CDUP'
|
14
|
+
end
|
15
|
+
|
16
|
+
When /^the client successfully cd's to "(.*?)"$/ do |path|
|
17
|
+
@client.chdir path
|
18
|
+
end
|
19
|
+
|
20
|
+
Then /^the current directory should be "(.*?)"$/ do |path|
|
21
|
+
@client.pwd.should == path
|
22
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
def capture_error
|
2
|
+
yield
|
3
|
+
@error = nil
|
4
|
+
rescue Net::FTPError => e
|
5
|
+
@error = e.message
|
6
|
+
end
|
7
|
+
|
8
|
+
Then /^the server returns no error$/ do
|
9
|
+
@error.should be_nil
|
10
|
+
end
|
11
|
+
|
12
|
+
Then /^the server returns a "(.*?)" error$/ do |error_message|
|
13
|
+
@error.should include error_message
|
14
|
+
end
|
15
|
+
|
16
|
+
Then /^the server returns a no such file error$/ do
|
17
|
+
step 'the server returns a "550 No such file or directory" error'
|
18
|
+
end
|
19
|
+
|
20
|
+
Then /^the server returns a login incorrect error$/ do
|
21
|
+
step 'the server returns a "530 Login incorrect" error'
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
Then /^the server returns a not logged in error$/ do
|
26
|
+
step 'the server returns a "530 Not logged in" error'
|
27
|
+
end
|
28
|
+
|
29
|
+
Then /^the server returns an access denied error$/ do
|
30
|
+
step 'the server returns a "550 Access denied" error'
|
31
|
+
end
|
32
|
+
|
33
|
+
Then /^the server returns a path required error$/ do
|
34
|
+
step 'the server returns a "501 Path required" error'
|
35
|
+
end
|
36
|
+
|
37
|
+
Then /^the server returns a not found error$/ do
|
38
|
+
step 'the server returns a "450 No such file or directory" error'
|
39
|
+
end
|
40
|
+
|
41
|
+
Then /^the server returns a syntax error$/ do
|
42
|
+
step 'the server returns a "501 Syntax error" error'
|
43
|
+
end
|
44
|
+
|
45
|
+
Then /^the server returns a mode not implemented error$/ do
|
46
|
+
step 'the server returns a "504 Mode not implemented" error'
|
47
|
+
end
|
48
|
+
|
49
|
+
Then /^the server returns an invalid mode error$/ do
|
50
|
+
step 'the server returns a "504 Invalid mode code" error'
|
51
|
+
end
|
52
|
+
|
53
|
+
Then /^the server returns a file structure not implemented error$/ do
|
54
|
+
step 'the server returns a "504 Structure not implemented" error'
|
55
|
+
end
|
56
|
+
|
57
|
+
Then /^the server returns an invalid file structure error$/ do
|
58
|
+
step 'the server returns a "504 Invalid structure code" error'
|
59
|
+
end
|
60
|
+
|
61
|
+
Then /^the server returns a bad sequence error$/ do
|
62
|
+
step 'the server returns a "503 Bad sequence of commands" error'
|
63
|
+
end
|
64
|
+
|
65
|
+
Then /^the server returns a type not implemented error$/ do
|
66
|
+
step 'the server returns a "504 Type not implemented" error'
|
67
|
+
end
|
68
|
+
|
69
|
+
Then /^the server returns an invalid type error$/ do
|
70
|
+
step 'the server returns a "504 Invalid type code" error'
|
71
|
+
end
|
72
|
+
|
73
|
+
Then /^the server returns a format not implemented error$/ do
|
74
|
+
step 'the server returns a "504 Format not implemented" error'
|
75
|
+
end
|
76
|
+
|
77
|
+
Then /^the server returns an invalid format error$/ do
|
78
|
+
step 'the server returns a "504 Invalid format code" error'
|
79
|
+
end
|
80
|
+
|
81
|
+
Then /^the server returns a command unrecognized error$/ do
|
82
|
+
step 'the server returns a "500 Syntax error, command unrecognized" error'
|
83
|
+
end
|
84
|
+
|
85
|
+
Then /^the server returns an unimplemented command error$/ do
|
86
|
+
step 'the server returns a "502 Command not implemented" error'
|
87
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
When /^the client successfully sets file structure "(.*?)"$/ do
|
2
|
+
|file_structure|
|
3
|
+
@client.raw 'STRU', file_structure
|
4
|
+
end
|
5
|
+
|
6
|
+
When /^the client sets file structure "(.*?)"$/ do |file_structure|
|
7
|
+
capture_error do
|
8
|
+
step %Q'the client successfully sets file structure "#{file_structure}"'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
When /^the client sets file structure with no parameter$/ do
|
13
|
+
capture_error do
|
14
|
+
@client.raw 'STRU'
|
15
|
+
end
|
16
|
+
end
|