ftpd 2.0.1 → 2.0.2

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.
Files changed (141) hide show
  1. checksums.yaml +4 -4
  2. data/Changelog.md +6 -0
  3. data/Gemfile +2 -15
  4. data/Gemfile.lock +12 -51
  5. data/README.md +12 -0
  6. data/VERSION +1 -1
  7. data/bin/ftpdrb +17 -12
  8. data/examples/write_only.rb +61 -0
  9. data/ftpd.gemspec +59 -261
  10. data/lib/ftpd/session.rb +51 -51
  11. metadata +11 -153
  12. data/.travis.yml +0 -6
  13. data/features/example/eplf.feature +0 -14
  14. data/features/example/example.feature +0 -18
  15. data/features/example/read_only.feature +0 -63
  16. data/features/example/step_definitions/example_server.rb +0 -13
  17. data/features/ftp_server/abort.feature +0 -13
  18. data/features/ftp_server/allo.feature +0 -33
  19. data/features/ftp_server/append.feature +0 -94
  20. data/features/ftp_server/cdup.feature +0 -36
  21. data/features/ftp_server/command_errors.feature +0 -13
  22. data/features/ftp_server/concurrent_sessions.feature +0 -14
  23. data/features/ftp_server/delay_after_failed_login.feature +0 -23
  24. data/features/ftp_server/delete.feature +0 -60
  25. data/features/ftp_server/directory_navigation.feature +0 -59
  26. data/features/ftp_server/disconnect_after_failed_logins.feature +0 -25
  27. data/features/ftp_server/eprt.feature +0 -56
  28. data/features/ftp_server/epsv.feature +0 -37
  29. data/features/ftp_server/features.feature +0 -38
  30. data/features/ftp_server/file_structure.feature +0 -43
  31. data/features/ftp_server/get.feature +0 -80
  32. data/features/ftp_server/get_ipv6.feature +0 -46
  33. data/features/ftp_server/get_tls.feature +0 -23
  34. data/features/ftp_server/help.feature +0 -21
  35. data/features/ftp_server/implicit_tls.feature +0 -23
  36. data/features/ftp_server/invertability.feature +0 -15
  37. data/features/ftp_server/list.feature +0 -94
  38. data/features/ftp_server/list_tls.feature +0 -29
  39. data/features/ftp_server/logging.feature +0 -11
  40. data/features/ftp_server/login_auth_level_account.feature +0 -51
  41. data/features/ftp_server/login_auth_level_password.feature +0 -59
  42. data/features/ftp_server/login_auth_level_user.feature +0 -31
  43. data/features/ftp_server/max_connections.feature +0 -39
  44. data/features/ftp_server/mdtm.feature +0 -53
  45. data/features/ftp_server/mkdir.feature +0 -70
  46. data/features/ftp_server/mode.feature +0 -43
  47. data/features/ftp_server/name_list.feature +0 -77
  48. data/features/ftp_server/name_list_tls.feature +0 -30
  49. data/features/ftp_server/noop.feature +0 -17
  50. data/features/ftp_server/options.feature +0 -17
  51. data/features/ftp_server/pasv.feature +0 -30
  52. data/features/ftp_server/port.feature +0 -49
  53. data/features/ftp_server/put.feature +0 -79
  54. data/features/ftp_server/put_tls.feature +0 -23
  55. data/features/ftp_server/put_unique.feature +0 -56
  56. data/features/ftp_server/quit.feature +0 -23
  57. data/features/ftp_server/reinitialize.feature +0 -13
  58. data/features/ftp_server/rename.feature +0 -97
  59. data/features/ftp_server/rmdir.feature +0 -71
  60. data/features/ftp_server/site.feature +0 -13
  61. data/features/ftp_server/size.feature +0 -69
  62. data/features/ftp_server/status.feature +0 -18
  63. data/features/ftp_server/step_definitions/logging.rb +0 -10
  64. data/features/ftp_server/step_definitions/test_server.rb +0 -71
  65. data/features/ftp_server/structure_mount.feature +0 -13
  66. data/features/ftp_server/syntax_errors.feature +0 -18
  67. data/features/ftp_server/syst.feature +0 -18
  68. data/features/ftp_server/timeout.feature +0 -26
  69. data/features/ftp_server/type.feature +0 -59
  70. data/features/step_definitions/append.rb +0 -17
  71. data/features/step_definitions/client.rb +0 -27
  72. data/features/step_definitions/client_and_server_files.rb +0 -26
  73. data/features/step_definitions/client_files.rb +0 -16
  74. data/features/step_definitions/command.rb +0 -7
  75. data/features/step_definitions/connect.rb +0 -39
  76. data/features/step_definitions/delete.rb +0 -17
  77. data/features/step_definitions/directory_navigation.rb +0 -28
  78. data/features/step_definitions/error_replies.rb +0 -117
  79. data/features/step_definitions/features.rb +0 -23
  80. data/features/step_definitions/file_structure.rb +0 -18
  81. data/features/step_definitions/generic_send.rb +0 -11
  82. data/features/step_definitions/get.rb +0 -18
  83. data/features/step_definitions/help.rb +0 -20
  84. data/features/step_definitions/invalid_commands.rb +0 -13
  85. data/features/step_definitions/ipv6.rb +0 -11
  86. data/features/step_definitions/line_endings.rb +0 -9
  87. data/features/step_definitions/list.rb +0 -75
  88. data/features/step_definitions/login.rb +0 -84
  89. data/features/step_definitions/mkdir.rb +0 -11
  90. data/features/step_definitions/mode.rb +0 -17
  91. data/features/step_definitions/mtime.rb +0 -25
  92. data/features/step_definitions/noop.rb +0 -17
  93. data/features/step_definitions/options.rb +0 -11
  94. data/features/step_definitions/passive.rb +0 -10
  95. data/features/step_definitions/pending.rb +0 -5
  96. data/features/step_definitions/port.rb +0 -7
  97. data/features/step_definitions/put.rb +0 -31
  98. data/features/step_definitions/quit.rb +0 -17
  99. data/features/step_definitions/rename.rb +0 -13
  100. data/features/step_definitions/rmdir.rb +0 -11
  101. data/features/step_definitions/server_files.rb +0 -63
  102. data/features/step_definitions/server_title.rb +0 -14
  103. data/features/step_definitions/size.rb +0 -22
  104. data/features/step_definitions/status.rb +0 -11
  105. data/features/step_definitions/success_replies.rb +0 -9
  106. data/features/step_definitions/system.rb +0 -12
  107. data/features/step_definitions/timing.rb +0 -21
  108. data/features/step_definitions/type.rb +0 -17
  109. data/features/support/env.rb +0 -6
  110. data/features/support/example_server.rb +0 -69
  111. data/features/support/file_templates/ascii_unix +0 -4
  112. data/features/support/file_templates/ascii_windows +0 -4
  113. data/features/support/file_templates/binary +0 -0
  114. data/features/support/test_client.rb +0 -258
  115. data/features/support/test_file_templates.rb +0 -35
  116. data/features/support/test_server.rb +0 -304
  117. data/features/support/test_server_files.rb +0 -59
  118. data/rake_tasks/cucumber.rake +0 -9
  119. data/rake_tasks/default.rake +0 -1
  120. data/rake_tasks/jeweler.rake +0 -52
  121. data/rake_tasks/spec.rake +0 -3
  122. data/rake_tasks/test.rake +0 -2
  123. data/rake_tasks/yard.rake +0 -3
  124. data/spec/command_sequence_checker_spec.rb +0 -85
  125. data/spec/connection_throttle_spec.rb +0 -101
  126. data/spec/connection_tracker_spec.rb +0 -99
  127. data/spec/data_server_factory_spec.rb +0 -104
  128. data/spec/disk_file_system_spec.rb +0 -322
  129. data/spec/exception_translator_spec.rb +0 -38
  130. data/spec/file_info_spec.rb +0 -61
  131. data/spec/ftp_server_error_spec.rb +0 -15
  132. data/spec/list_format/eplf_spec.rb +0 -63
  133. data/spec/list_format/ls_spec.rb +0 -272
  134. data/spec/list_path_spec.rb +0 -23
  135. data/spec/null_logger_spec.rb +0 -26
  136. data/spec/protocols_spec.rb +0 -159
  137. data/spec/server_spec.rb +0 -83
  138. data/spec/spec_helper.rb +0 -17
  139. data/spec/telnet_spec.rb +0 -77
  140. data/spec/translate_exceptions_spec.rb +0 -42
  141. data/testlib/network.rb +0 -17
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- def unix_line_endings(exactly, s)
4
- return s if exactly
5
- s.gsub(/\r\n/, "\n")
6
- end
7
-
8
- Then /^the remote file "(.*?)" should( exactly)? match the local file$/ do
9
- |remote_path, exactly|
10
- local_path = File.basename(remote_path)
11
- remote_contents = server.file_contents(remote_path)
12
- local_contents = client.file_contents(local_path)
13
- remote_contents = unix_line_endings(exactly, remote_contents)
14
- local_contents = unix_line_endings(exactly, local_contents)
15
- expect(remote_contents).to eq local_contents
16
- end
17
-
18
- Then /^the local file "(.*?)" should( exactly)? match the remote file$/ do
19
- |local_path, exactly|
20
- remote_path = local_path
21
- remote_contents = server.file_contents(remote_path)
22
- local_contents = client.file_contents(local_path)
23
- remote_contents = unix_line_endings(exactly, remote_contents)
24
- local_contents = unix_line_endings(exactly, local_contents)
25
- expect(local_contents).to eq remote_contents
26
- end
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- Given /^the client has file "(.*?)"$/ do |local_path|
4
- client.add_file local_path
5
- end
6
-
7
- Then /^the local file "(.*?)" should have (unix|windows) line endings$/ do
8
- |local_path, line_ending_type|
9
- expect(line_ending_type(client.file_contents(local_path))).to eq \
10
- line_ending_type.to_sym
11
- end
12
-
13
- Then /^the local file "(.*?)" should match its template$/ do |local_path|
14
- expect(client.template(local_path)).to eq \
15
- client.file_contents(local_path)
16
- end
@@ -1,7 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- When /^the client sends command "(.*?)"$/ do |command|
4
- capture_error do
5
- client.raw command
6
- end
7
- end
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'double_bag_ftps'
4
- require 'net/ftp'
5
-
6
- When /^the( \w+)? client connects(?: with (\w+) TLS)?$/ do
7
- |client_name, tls_mode|
8
- tls_mode ||= 'off'
9
- client(client_name).tls_mode = tls_mode.to_sym
10
- client(client_name).start
11
- client(client_name).connect(server.host, server.port)
12
- end
13
-
14
- When /^the (\d+)rd client tries to connect$/ do |client_name|
15
- client(client_name).start
16
- capture_error do
17
- client(client_name).connect(server.host, server.port)
18
- end
19
- end
20
-
21
- When /^the (\S+) client connects from (\S+)$/ do
22
- |client_name, source_ip|
23
- client(client_name).connect_from(source_ip, server.host, server.port)
24
- end
25
-
26
- When /^the (\S+) client tries to connect from (\S+)$/ do
27
- |client_name, source_ip|
28
- capture_error do
29
- step "the #{client_name} client connects from #{source_ip}"
30
- end
31
- end
32
-
33
- Then /^the client should be connected$/ do
34
- expect(client).to be_connected
35
- end
36
-
37
- Then /^the client should not be connected$/ do
38
- expect(client).to_not be_connected
39
- end
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- When /^the client deletes "(.*?)"$/ do |path|
4
- capture_error do
5
- step %Q(the client successfully deletes "#{path}")
6
- end
7
- end
8
-
9
- When /^the client successfully deletes "(.*?)"$/ do |path|
10
- client.delete path
11
- end
12
-
13
- When /^the client deletes with no path$/ do
14
- capture_error do
15
- client.raw 'DELE'
16
- end
17
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- When /^the client cd's to "(.*?)"$/ do |path|
4
- capture_error do
5
- step %Q(the client successfully cd's to "#{path}")
6
- end
7
- end
8
-
9
- # As of Ruby 1.9.3-p125, Net::FTP#chdir('..') will send a CDUP.
10
- # However, that could conceivably change: The use of CDUP not
11
- # required by the FTP protocol. Therefore we use this step to
12
- # ensure that CDUP is sent and therefore tested.
13
-
14
- When /^the client successfully cd's up$/ do
15
- client.raw 'CDUP'
16
- end
17
-
18
- When /^the client successfully cd's to "(.*?)"$/ do |path|
19
- client.chdir path
20
- end
21
-
22
- Then /^the current directory should be "(.*?)"$/ do |path|
23
- expect(client.pwd).to eq path
24
- end
25
-
26
- Then /^the XPWD directory should be "(.*?)"$/ do |path|
27
- expect(client.xpwd).to eq path
28
- end
@@ -1,117 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- def capture_error
4
- yield
5
- @error = nil
6
- rescue Net::FTPError => e
7
- @error = e.message
8
- end
9
-
10
- Then /^the server returns no error$/ do
11
- expect(@error).to be_nil
12
- end
13
-
14
- Then /^the server returns a "(.*?)" error$/ do |error_message|
15
- expect(@error || '').to include error_message
16
- end
17
-
18
- Then /^the server returns a too many connections error$/ do
19
- step 'the server returns a "421 Too many connections" error'
20
- end
21
-
22
- Then /^the server returns a server unavailable error$/ do
23
- step 'the server returns a "421 server unavailable" error'
24
- end
25
-
26
- Then /^the server returns a not a directory error$/ do
27
- step 'the server returns a "550 Not a directory" error'
28
- end
29
-
30
- Then /^the server returns a login incorrect error$/ do
31
- step 'the server returns a "530 Login incorrect" error'
32
- end
33
-
34
- Then /^the server returns a not logged in error$/ do
35
- step 'the server returns a "530 Not logged in" error'
36
- end
37
-
38
- Then /^the server returns an access denied error$/ do
39
- step 'the server returns a "550 Access denied" error'
40
- end
41
-
42
- Then /^the server returns a path required error$/ do
43
- step 'the server returns a "501 Path required" error'
44
- end
45
-
46
- Then /^the server returns a not found error$/ do
47
- step 'the server returns a "550 No such file or directory" error'
48
- end
49
-
50
- Then /^the server returns a syntax error$/ do
51
- step 'the server returns a "501 Syntax error" error'
52
- end
53
-
54
- Then /^the server returns a bad option error$/ do
55
- step 'the server returns a "501 Unsupported option" error'
56
- end
57
-
58
- Then /^the server returns a mode not implemented error$/ do
59
- step 'the server returns a "504 Mode not implemented" error'
60
- end
61
-
62
- Then /^the server returns an invalid mode error$/ do
63
- step 'the server returns a "504 Invalid mode code" error'
64
- end
65
-
66
- Then /^the server returns a file structure not implemented error$/ do
67
- step 'the server returns a "504 Structure not implemented" error'
68
- end
69
-
70
- Then /^the server returns an invalid file structure error$/ do
71
- step 'the server returns a "504 Invalid structure code" error'
72
- end
73
-
74
- Then /^the server returns a bad sequence error$/ do
75
- step 'the server returns a "503 Bad sequence of commands" error'
76
- end
77
-
78
- Then /^the server returns a type not implemented error$/ do
79
- step 'the server returns a "504 Type not implemented" error'
80
- end
81
-
82
- Then /^the server returns an invalid type error$/ do
83
- step 'the server returns a "504 Invalid type code" error'
84
- end
85
-
86
- Then /^the server returns a format not implemented error$/ do
87
- step 'the server returns a "504 Format not implemented" error'
88
- end
89
-
90
- Then /^the server returns an unimplemented parameter error$/ do
91
- step('the server returns a "504 Command not '\
92
- 'implemented for that parameter" error')
93
- end
94
-
95
- Then /^the server returns a command unrecognized error$/ do
96
- step 'the server returns a "500 Syntax error, command unrecognized" error'
97
- end
98
-
99
- Then /^the server returns an unimplemented command error$/ do
100
- step 'the server returns a "502 Command not implemented" error'
101
- end
102
-
103
- Then /^the server returns an action not taken error$/ do
104
- step 'the server returns a "550 Unable to do it" error'
105
- end
106
-
107
- Then /^the server returns an already exists error$/ do
108
- step 'the server returns a "550 Already exists" error'
109
- end
110
-
111
- Then /^the server returns a network protocol not supported error$/ do
112
- step 'the server returns a "522 Network protocol" error'
113
- end
114
-
115
- Then /^the server sends a not allowed after epsv all error$/ do
116
- step 'the server returns a "501 Not allowed after EPSV ALL" error'
117
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- When /^the client successfully requests features$/ do
4
- @feature_reply = client.raw "FEAT"
5
- end
6
-
7
- def feature_regexp(feature)
8
- /^ #{feature}$/
9
- end
10
-
11
- Then /^the response should include feature "(.*?)"$/ do |feature|
12
- expect(@feature_reply).to match feature_regexp(feature)
13
- end
14
-
15
- Then /^the response should not include feature "(.*?)"$/ do |feature|
16
- expect(@feature_reply).to_not match feature_regexp(feature)
17
- end
18
-
19
- Then /^the response should( not)? include TLS features$/ do |neg|
20
- step %Q'the response should#{neg} include feature "AUTH TLS"'
21
- step %Q'the response should#{neg} include feature "PBSZ"'
22
- step %Q'the response should#{neg} include feature "PROT"'
23
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- When /^the client successfully sets file structure "(.*?)"$/ do
4
- |file_structure|
5
- client.raw 'STRU', file_structure
6
- end
7
-
8
- When /^the client sets file structure "(.*?)"$/ do |file_structure|
9
- capture_error do
10
- step %Q'the client successfully sets file structure "#{file_structure}"'
11
- end
12
- end
13
-
14
- When /^the client sets file structure with no parameter$/ do
15
- capture_error do
16
- client.raw 'STRU'
17
- end
18
- end
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- When /^the client successfully sends "(.*?)"$/ do |command|
4
- @reply = client.raw command
5
- end
6
-
7
- When /^the client sends "(.*?)"$/ do |command|
8
- capture_error do
9
- step %Q'the client successfully sends "#{command}"'
10
- end
11
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- When /^the client successfully gets (text|binary) "(.*?)"$/ \
4
- do |mode, remote_path|
5
- client.get mode, remote_path
6
- end
7
-
8
- When /^the client gets (\S+) "(.*?)"$/ do |mode, path|
9
- capture_error do
10
- step %Q(the client successfully gets #{mode} "#{path}")
11
- end
12
- end
13
-
14
- When /^the client gets with no path$/ do
15
- capture_error do
16
- client.raw 'RETR'
17
- end
18
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- When /^the client successfully asks for help(?: for "(.*?)")?$/ do
4
- |command|
5
- @help_reply = client.help(command)
6
- end
7
-
8
- Then /^the server should return a list of commands$/ do
9
- commands = @help_reply.scan(/\b([A-Z][A-Z]+)\b/).flatten
10
- expect(commands).to include 'NOOP'
11
- expect(commands).to include 'USER'
12
- end
13
-
14
- Then /^the server should return help for "(.*?)"$/ do |command|
15
- expect(@help_reply).to match /Command #{command} is recognized/
16
- end
17
-
18
- Then /^the server should return no help for "(.*?)"$/ do |command|
19
- expect(@help_reply).to match /Command #{command} is not recognized/
20
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- When /^the client sends an empty command$/ do
4
- capture_error do
5
- client.raw ''
6
- end
7
- end
8
-
9
- When /^the client sends a non-word command$/ do
10
- capture_error do
11
- client.raw '*'
12
- end
13
- end
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../../testlib/network"
4
-
5
- include TestLib::Network
6
-
7
- Given /^the stack supports ipv6$/ do
8
- unless ipv6_supported?
9
- pending "Test skipped: stack does not support ipv6"
10
- end
11
- end
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- def line_ending_type(s)
4
- if s =~ /\r\n/
5
- :windows
6
- else
7
- :unix
8
- end
9
- end
@@ -1,75 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class FileList
4
-
5
- def initialize(lines)
6
- @lines = lines
7
- end
8
-
9
- def filenames
10
- @lines.map(&:split).map(&:last)
11
- end
12
-
13
- def long_form?
14
- @lines.all? do |line|
15
- line =~ /^[rwxSst-]{10}/
16
- end
17
- end
18
-
19
- def short_form?
20
- !long_form?
21
- end
22
-
23
- def eplf_format?
24
- @lines.all? do |line|
25
- line =~ /^\+.*\t.*$/
26
- end
27
- end
28
-
29
- def empty?
30
- @lines.empty?
31
- end
32
-
33
- end
34
-
35
- When /^the client successfully lists the directory(?: "(.*?)")?$/ do |directory|
36
- @list = FileList.new(client.ls(*[directory].compact))
37
- end
38
-
39
- When /^the client lists the directory( "(?:.*?)")?$/ do |directory|
40
- capture_error do
41
- step "the client successfully lists the directory#{directory}"
42
- end
43
- end
44
-
45
- When /^the client successfully name-lists the directory(?: "(.*?)")?$/ do
46
- |directory|
47
- @list = FileList.new(client.nlst(*[directory].compact))
48
- end
49
-
50
- When /^the client name-lists the directory( "(?:.*?)")?$/ do |directory|
51
- capture_error do
52
- step "the client successfully name-lists the directory#{directory}"
53
- end
54
- end
55
-
56
- Then /^the file list should( not)? contain "(.*?)"$/ do |neg, filename|
57
- verb = if neg
58
- :to_not
59
- else
60
- :to
61
- end
62
- expect(@list.filenames).send(verb, include(filename))
63
- end
64
-
65
- Then /^the file list should be in (long|short) form$/ do |form|
66
- expect(@list).to send("be_#{form}_form")
67
- end
68
-
69
- Then /^the file list should be empty$/ do
70
- expect(@list).to be_empty
71
- end
72
-
73
- Then /^the list should be in EPLF format$/ do
74
- expect(@list).to be_eplf_format
75
- end