ftpd 0.10.0 → 0.11.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 +4 -4
- data/.travis.yml +2 -1
- data/Changelog.md +12 -0
- data/README.md +3 -1
- data/VERSION +1 -1
- data/doc/rfc-compliance.md +4 -4
- data/examples/example_spec.rb +2 -2
- data/features/ftp_server/features.feature +12 -0
- data/features/ftp_server/mdtm.feature +53 -0
- data/features/ftp_server/size.feature +69 -0
- data/features/step_definitions/mtime.rb +23 -0
- data/features/step_definitions/server_files.rb +7 -0
- data/features/step_definitions/size.rb +20 -0
- data/features/support/test_client.rb +59 -10
- data/features/support/test_server_files.rb +5 -0
- data/ftpd.gemspec +10 -6
- data/lib/ftpd/server.rb +6 -0
- data/lib/ftpd/session.rb +40 -4
- data/spec/spec_helper.rb +4 -0
- metadata +30 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 131edbd4d2cff04d60c36f8fb0ae07adea821823
|
4
|
+
data.tar.gz: 9b43256518b4844af2a76306ce48943999ddde08
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: becd885798f77294b84ef32815c018b2ac0dc15f467a72ae338b06e507f0dc91a464e56f405c5612897e3ec8bd24322ab98220d4c60815be70b5db75f8626274
|
7
|
+
data.tar.gz: 30b34af9047acf54b926e9f55803004003ba95bd269a120749a55cbfd329682eb42d579be6823634abd34679fc837641181ac0d65d629a6888c5775b73693d3e
|
data/.travis.yml
CHANGED
data/Changelog.md
CHANGED
@@ -2,6 +2,18 @@ This is the change log for the main branch of ftpd, which supports
|
|
2
2
|
Ruby 1.9 and greater. For ruby 1.8.7, please use the latest version
|
3
3
|
before 0.8.0.
|
4
4
|
|
5
|
+
### 0.11.0
|
6
|
+
|
7
|
+
Bug fixes
|
8
|
+
|
9
|
+
* Fix Bad file descriptor exception on stop (issue #20)
|
10
|
+
* CWD returns 250, not 257 (issue #18)
|
11
|
+
|
12
|
+
#Enhancements
|
13
|
+
|
14
|
+
* MDTM command (issue #19)
|
15
|
+
* SIZE command (issue #19)
|
16
|
+
|
5
17
|
### 0.10.0
|
6
18
|
|
7
19
|
Bug fixes
|
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# Ftpd [](https://codeclimate.com/github/wconrad/ftpd) [](https://travis-ci.org/wconrad/ftpd)
|
2
2
|
|
3
3
|
ftpd is a pure Ruby FTP server library. It supports implicit and
|
4
|
-
explicit TLS, passive and active mode, and is unconditionally
|
4
|
+
explicit TLS, IPV6, passive and active mode, and is unconditionally
|
5
5
|
compliant per [RFC-1123][1]. It can be used as part of a test fixture
|
6
6
|
or embedded in a program.
|
7
7
|
|
@@ -330,8 +330,10 @@ Among those who have improved ftpd are:
|
|
330
330
|
|
331
331
|
* Alfonso Cora
|
332
332
|
* Bjoern B. Dorra
|
333
|
+
* Joshua Rutherford
|
333
334
|
* Larry. W. Cashdollar
|
334
335
|
* Michael de Silva
|
336
|
+
* cransom
|
335
337
|
|
336
338
|
Thank you!
|
337
339
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.11.0
|
data/doc/rfc-compliance.md
CHANGED
@@ -252,7 +252,7 @@ LANG command No ---
|
|
252
252
|
UNICODE No ---
|
253
253
|
</pre>
|
254
254
|
|
255
|
-
RFC-3659 - Extensions to FTP
|
255
|
+
## RFC-3659 - Extensions to FTP
|
256
256
|
|
257
257
|
Four new commands are added: "SIZE", "MDTM", "MLST", and "MLSD". The existing command "REST" is modified.
|
258
258
|
|
@@ -262,13 +262,13 @@ Four new commands are added: "SIZE", "MDTM", "MLST", and "MLSD". The existing co
|
|
262
262
|
* [link](http://tools.ietf.org/rfc/rfc3659.txt)
|
263
263
|
|
264
264
|
<pre>
|
265
|
-
MDTM command
|
265
|
+
MDTM command Yes --- Get file's last modification time
|
266
266
|
MLSD command No --- Get directory list in a standardized form.
|
267
267
|
MLST command No --- Get file information in a standardized form.
|
268
|
-
SIZE command
|
268
|
+
SIZE command Yes --- Get file size.
|
269
269
|
TVSF mechanism No --- Unix-like file system naming conventions
|
270
270
|
Min. MLST facts No ---
|
271
|
-
GMT timestamps
|
271
|
+
GMT timestamps Yes ---
|
272
272
|
</pre>
|
273
273
|
|
274
274
|
##RFC-4217 - Securing FTP with TLS
|
data/examples/example_spec.rb
CHANGED
@@ -23,7 +23,7 @@ require 'tmpdir'
|
|
23
23
|
module Fetcher
|
24
24
|
|
25
25
|
# This is the code under test, a simple fetcher that logs into an
|
26
|
-
# FTP site, changes to a
|
26
|
+
# FTP site, changes to a directory, and gets a list of files.
|
27
27
|
|
28
28
|
class FTPFetcher
|
29
29
|
|
@@ -58,7 +58,7 @@ end
|
|
58
58
|
describe Fetcher::FTPFetcher do
|
59
59
|
|
60
60
|
# This `Driver` tells Ftpd how to authenticate and how to interact
|
61
|
-
# with the file
|
61
|
+
# with the file system. In this example, the file system is
|
62
62
|
# read-only and contains a single file.
|
63
63
|
|
64
64
|
class Driver
|
@@ -24,3 +24,15 @@ Feature: Features
|
|
24
24
|
And the client connects
|
25
25
|
When the client sends "FEAT FOO"
|
26
26
|
Then the server returns a syntax error
|
27
|
+
|
28
|
+
Scenario: IPV6 Extensions
|
29
|
+
Given the test server is started
|
30
|
+
When the client successfully requests features
|
31
|
+
Then the response should include feature "EPRT"
|
32
|
+
And the response should include feature "EPSV"
|
33
|
+
|
34
|
+
Scenario: RFC 3659 Extensions
|
35
|
+
Given the test server is started
|
36
|
+
When the client successfully requests features
|
37
|
+
Then the response should include feature "SIZE"
|
38
|
+
Then the response should include feature "MDTM"
|
@@ -0,0 +1,53 @@
|
|
1
|
+
Feature: MDTM
|
2
|
+
|
3
|
+
As a client
|
4
|
+
I want to get a file's modification time
|
5
|
+
So that I can detect when it changes
|
6
|
+
|
7
|
+
Background:
|
8
|
+
Given the test server is started
|
9
|
+
|
10
|
+
Scenario: File in current directory
|
11
|
+
Given a successful login
|
12
|
+
And the server has file "ascii_unix"
|
13
|
+
And the file "ascii_unix" has mtime "2014-01-02 13:14:15.123456"
|
14
|
+
When the client successfully gets mtime of "ascii_unix"
|
15
|
+
Then the reported mtime should be "20140102131415"
|
16
|
+
|
17
|
+
Scenario: File in subdirectory
|
18
|
+
Given a successful login
|
19
|
+
And the server has file "foo/ascii_unix"
|
20
|
+
Then the client successfully gets mtime of "foo/ascii_unix"
|
21
|
+
|
22
|
+
Scenario: Non-root working directory
|
23
|
+
Given a successful login
|
24
|
+
And the server has file "foo/ascii_unix"
|
25
|
+
And the client successfully cd's to "foo"
|
26
|
+
Then the client successfully gets mtime of "ascii_unix"
|
27
|
+
|
28
|
+
Scenario: Access denied
|
29
|
+
Given a successful login
|
30
|
+
When the client gets mtime of "forbidden"
|
31
|
+
Then the server returns an access denied error
|
32
|
+
|
33
|
+
Scenario: Missing file
|
34
|
+
Given a successful login
|
35
|
+
When the client gets mtime of "foo"
|
36
|
+
Then the server returns a not found error
|
37
|
+
|
38
|
+
Scenario: Not logged in
|
39
|
+
Given a successful connection
|
40
|
+
When the client gets mtime of "foo"
|
41
|
+
Then the server returns a not logged in error
|
42
|
+
|
43
|
+
Scenario: Missing path
|
44
|
+
Given a successful login
|
45
|
+
When the client gets mtime with no path
|
46
|
+
Then the server returns a syntax error
|
47
|
+
|
48
|
+
Scenario: List not enabled
|
49
|
+
Given the test server lacks list
|
50
|
+
And a successful login
|
51
|
+
And the server has file "foo"
|
52
|
+
When the client gets mtime of "foo"
|
53
|
+
Then the server returns an unimplemented command error
|
@@ -0,0 +1,69 @@
|
|
1
|
+
Feature: Size
|
2
|
+
|
3
|
+
As a client
|
4
|
+
I want to know the size of a file
|
5
|
+
So that I can tell how long it will take to get it
|
6
|
+
|
7
|
+
Background:
|
8
|
+
Given the test server is started
|
9
|
+
|
10
|
+
Scenario: ASCII file with *nix line endings
|
11
|
+
Given a successful login
|
12
|
+
And the server has file "ascii_unix"
|
13
|
+
When the client successfully gets size of text "ascii_unix"
|
14
|
+
Then the reported size should be "83"
|
15
|
+
|
16
|
+
Scenario: ASCII file with windows line endings
|
17
|
+
Given a successful login
|
18
|
+
And the server has file "ascii_windows"
|
19
|
+
When the client successfully gets size of text "ascii_windows"
|
20
|
+
Then the reported size should be "83"
|
21
|
+
|
22
|
+
Scenario: Binary file
|
23
|
+
Given a successful login
|
24
|
+
And the server has file "binary"
|
25
|
+
When the client successfully gets size of binary "binary"
|
26
|
+
Then the reported size should be "256"
|
27
|
+
|
28
|
+
Scenario: File in subdirectory
|
29
|
+
Given a successful login
|
30
|
+
And the server has file "foo/ascii_unix"
|
31
|
+
Then the client successfully gets size of text "foo/ascii_unix"
|
32
|
+
|
33
|
+
Scenario: Non-root working directory
|
34
|
+
Given a successful login
|
35
|
+
And the server has file "foo/ascii_unix"
|
36
|
+
And the client successfully cd's to "foo"
|
37
|
+
Then the client successfully gets size of text "ascii_unix"
|
38
|
+
|
39
|
+
Scenario: Access denied
|
40
|
+
Given a successful login
|
41
|
+
When the client gets size of text "forbidden"
|
42
|
+
Then the server returns an access denied error
|
43
|
+
|
44
|
+
Scenario: Missing file
|
45
|
+
Given a successful login
|
46
|
+
When the client gets size of text "foo"
|
47
|
+
Then the server returns a not found error
|
48
|
+
|
49
|
+
Scenario: Not logged in
|
50
|
+
Given a successful connection
|
51
|
+
When the client gets size of text "foo"
|
52
|
+
Then the server returns a not logged in error
|
53
|
+
|
54
|
+
Scenario: Missing path
|
55
|
+
Given a successful login
|
56
|
+
When the client gets size with no path
|
57
|
+
Then the server returns a syntax error
|
58
|
+
|
59
|
+
Scenario: File system error
|
60
|
+
Given a successful login
|
61
|
+
When the client gets size of text "unable"
|
62
|
+
Then the server returns an action not taken error
|
63
|
+
|
64
|
+
Scenario: Read not enabled
|
65
|
+
Given the test server lacks read
|
66
|
+
And a successful login
|
67
|
+
And the server has file "foo"
|
68
|
+
When the client gets size of text "foo"
|
69
|
+
Then the server returns an unimplemented command error
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
When /^the client successfully gets mtime of "(.*?)"$/ \
|
4
|
+
do |remote_path|
|
5
|
+
@mtime = client.get_mtime remote_path
|
6
|
+
end
|
7
|
+
|
8
|
+
When /^the client gets mtime of "(.*?)"$/ do |path|
|
9
|
+
capture_error do
|
10
|
+
step %Q(the client successfully gets mtime of "#{path}")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
When /^the client gets mtime with no path$/ do
|
15
|
+
capture_error do
|
16
|
+
client.raw 'MDTM'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
Then(/^the reported mtime should be "(.*?)"$/) do |mtime|
|
21
|
+
expected_time = DateTime.parse(mtime).to_time.utc
|
22
|
+
@mtime.should eq expected_time
|
23
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
1
3
|
Given /^the server has directory "(.*?)"$/ do |remote_path|
|
2
4
|
server.add_directory remote_path
|
3
5
|
end
|
@@ -6,6 +8,11 @@ Given /^the server has file "(.*?)"$/ do |remote_path|
|
|
6
8
|
server.add_file remote_path
|
7
9
|
end
|
8
10
|
|
11
|
+
Given(/^the file "(.*?)" has mtime "(.*?)"$/) do |remote_path, mtime|
|
12
|
+
mtime = DateTime.parse(mtime).to_time.utc
|
13
|
+
server.set_mtime remote_path, mtime
|
14
|
+
end
|
15
|
+
|
9
16
|
Then /^the server should( not)? have file "(.*?)"$/ do |neg, path|
|
10
17
|
matcher = if neg
|
11
18
|
:be_false
|
@@ -0,0 +1,20 @@
|
|
1
|
+
When /^the client successfully gets size of (text|binary) "(.*?)"$/ \
|
2
|
+
do |mode, remote_path|
|
3
|
+
@size = client.get_size mode, remote_path
|
4
|
+
end
|
5
|
+
|
6
|
+
When /^the client gets size of (\S+) "(.*?)"$/ do |mode, path|
|
7
|
+
capture_error do
|
8
|
+
step %Q(the client successfully gets size of #{mode} "#{path}")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
When /^the client gets size with no path$/ do
|
13
|
+
capture_error do
|
14
|
+
client.raw 'SIZE'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
Then(/^the reported size should be "(.*?)"$/) do |size|
|
19
|
+
@size.should eq size.to_i
|
20
|
+
end
|
@@ -71,6 +71,18 @@ class TestClient
|
|
71
71
|
@ftp.send method, local_path(remote_path), remote_path
|
72
72
|
end
|
73
73
|
|
74
|
+
def get_size(mode, remote_path)
|
75
|
+
raise unless ['binary', 'text'].include?(mode)
|
76
|
+
@ftp.binary = mode == 'binary'
|
77
|
+
override_with_binary do
|
78
|
+
@ftp.size(remote_path)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def get_mtime(remote_path)
|
83
|
+
@ftp.mtime(remote_path)
|
84
|
+
end
|
85
|
+
|
74
86
|
def add_file(path)
|
75
87
|
full_path = temp_path(path)
|
76
88
|
mkdir_p File.dirname(full_path)
|
@@ -141,16 +153,19 @@ class TestClient
|
|
141
153
|
end
|
142
154
|
|
143
155
|
def make_ftp
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
156
|
+
ftp =
|
157
|
+
case @tls_mode
|
158
|
+
when :off
|
159
|
+
make_non_tls_ftp
|
160
|
+
when :implicit
|
161
|
+
make_tls_ftp(:implicit)
|
162
|
+
when :explicit
|
163
|
+
make_tls_ftp(:explicit)
|
164
|
+
else
|
165
|
+
raise "Unknown TLS mode: #{@tls_mode}"
|
166
|
+
end
|
167
|
+
allow_size_in_ascii_mode ftp
|
168
|
+
ftp
|
154
169
|
end
|
155
170
|
|
156
171
|
def make_tls_ftp(ftps_mode)
|
@@ -167,6 +182,40 @@ class TestClient
|
|
167
182
|
Net::FTP.new
|
168
183
|
end
|
169
184
|
|
185
|
+
# Ruby FTP client forces binary mode when doing a SIZE command. Our
|
186
|
+
# tests want to check that the server's SIZE command works correctly
|
187
|
+
# in ASCII mode as well, so we'll monkey-patch the FTP client.
|
188
|
+
|
189
|
+
def allow_size_in_ascii_mode(ftp)
|
190
|
+
|
191
|
+
class << ftp
|
192
|
+
|
193
|
+
attr_accessor :override_with_binary
|
194
|
+
|
195
|
+
alias :orig_with_binary :with_binary
|
196
|
+
|
197
|
+
def with_binary(*args, &block)
|
198
|
+
if @override_with_binary
|
199
|
+
block.call
|
200
|
+
else
|
201
|
+
return orig_with_binary(*args, &block)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
208
|
+
|
209
|
+
def override_with_binary
|
210
|
+
orig = @ftp.override_with_binary
|
211
|
+
begin
|
212
|
+
@ftp.override_with_binary = true
|
213
|
+
yield
|
214
|
+
ensure
|
215
|
+
@ftp.override_with_binary = orig
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
170
219
|
# Ruby 2.0's Ftp class is expecting a TCPSocket, not a Socket. The
|
171
220
|
# trouble comes with Ftp#close, which closes sockets by first doing
|
172
221
|
# a shutdown, setting the read timeout, and doing a read. Plain
|
data/ftpd.gemspec
CHANGED
@@ -2,16 +2,17 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: ftpd 0.
|
5
|
+
# stub: ftpd 0.11.0 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "ftpd"
|
9
|
-
s.version = "0.
|
9
|
+
s.version = "0.11.0"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
|
+
s.require_paths = ["lib"]
|
12
13
|
s.authors = ["Wayne Conrad"]
|
13
|
-
s.date = "
|
14
|
-
s.description = "ftpd is a pure Ruby FTP server library. It supports implicit and explicit TLS, passive and active mode, and is unconditionally compliant per [RFC-1123][1]. It can be used as part of a test fixture or embedded in a program."
|
14
|
+
s.date = "2014-03-16"
|
15
|
+
s.description = "ftpd is a pure Ruby FTP server library. It supports implicit and explicit TLS, IPV6, passive and active mode, and is unconditionally compliant per [RFC-1123][1]. It can be used as part of a test fixture or embedded in a program."
|
15
16
|
s.email = "wconrad@yagni.com"
|
16
17
|
s.extra_rdoc_files = [
|
17
18
|
"LICENSE.md",
|
@@ -64,6 +65,7 @@ Gem::Specification.new do |s|
|
|
64
65
|
"features/ftp_server/login_auth_level_password.feature",
|
65
66
|
"features/ftp_server/login_auth_level_user.feature",
|
66
67
|
"features/ftp_server/max_connections.feature",
|
68
|
+
"features/ftp_server/mdtm.feature",
|
67
69
|
"features/ftp_server/mkdir.feature",
|
68
70
|
"features/ftp_server/mode.feature",
|
69
71
|
"features/ftp_server/name_list.feature",
|
@@ -80,6 +82,7 @@ Gem::Specification.new do |s|
|
|
80
82
|
"features/ftp_server/rename.feature",
|
81
83
|
"features/ftp_server/rmdir.feature",
|
82
84
|
"features/ftp_server/site.feature",
|
85
|
+
"features/ftp_server/size.feature",
|
83
86
|
"features/ftp_server/status.feature",
|
84
87
|
"features/ftp_server/step_definitions/logging.rb",
|
85
88
|
"features/ftp_server/step_definitions/test_server.rb",
|
@@ -108,6 +111,7 @@ Gem::Specification.new do |s|
|
|
108
111
|
"features/step_definitions/login.rb",
|
109
112
|
"features/step_definitions/mkdir.rb",
|
110
113
|
"features/step_definitions/mode.rb",
|
114
|
+
"features/step_definitions/mtime.rb",
|
111
115
|
"features/step_definitions/noop.rb",
|
112
116
|
"features/step_definitions/options.rb",
|
113
117
|
"features/step_definitions/passive.rb",
|
@@ -119,6 +123,7 @@ Gem::Specification.new do |s|
|
|
119
123
|
"features/step_definitions/rmdir.rb",
|
120
124
|
"features/step_definitions/server_files.rb",
|
121
125
|
"features/step_definitions/server_title.rb",
|
126
|
+
"features/step_definitions/size.rb",
|
122
127
|
"features/step_definitions/status.rb",
|
123
128
|
"features/step_definitions/success_replies.rb",
|
124
129
|
"features/step_definitions/system.rb",
|
@@ -186,8 +191,7 @@ Gem::Specification.new do |s|
|
|
186
191
|
]
|
187
192
|
s.homepage = "http://github.com/wconrad/ftpd"
|
188
193
|
s.licenses = ["MIT"]
|
189
|
-
s.
|
190
|
-
s.rubygems_version = "2.1.3"
|
194
|
+
s.rubygems_version = "2.2.1"
|
191
195
|
s.summary = "Pure Ruby FTP server library"
|
192
196
|
|
193
197
|
if s.respond_to? :specification_version then
|
data/lib/ftpd/server.rb
CHANGED
@@ -25,6 +25,7 @@ module Ftpd
|
|
25
25
|
def initialize
|
26
26
|
@interface = '127.0.0.1'
|
27
27
|
@port = 0
|
28
|
+
@stopping = false
|
28
29
|
end
|
29
30
|
|
30
31
|
# The port the server is bound to. Must not be called until after
|
@@ -48,6 +49,7 @@ module Ftpd
|
|
48
49
|
# stops the thread.
|
49
50
|
|
50
51
|
def stop
|
52
|
+
@stopping = true
|
51
53
|
@server_socket.close
|
52
54
|
end
|
53
55
|
|
@@ -68,6 +70,10 @@ module Ftpd
|
|
68
70
|
IO.select([@server_socket])
|
69
71
|
sleep(0.2)
|
70
72
|
retry
|
73
|
+
rescue Errno::EBADF
|
74
|
+
raise unless @stopping
|
75
|
+
@stopping = false
|
76
|
+
break
|
71
77
|
end
|
72
78
|
start_session socket
|
73
79
|
rescue IOError
|
data/lib/ftpd/session.rb
CHANGED
@@ -277,7 +277,7 @@ module Ftpd
|
|
277
277
|
ensure_exists path
|
278
278
|
ensure_directory path
|
279
279
|
@name_prefix = path
|
280
|
-
pwd
|
280
|
+
pwd 250
|
281
281
|
end
|
282
282
|
alias cmd_xcwd :cmd_cwd
|
283
283
|
|
@@ -368,7 +368,7 @@ module Ftpd
|
|
368
368
|
|
369
369
|
def cmd_pwd(argument)
|
370
370
|
ensure_logged_in
|
371
|
-
pwd
|
371
|
+
pwd 257
|
372
372
|
end
|
373
373
|
alias cmd_xpwd :cmd_pwd
|
374
374
|
|
@@ -528,6 +528,36 @@ module Ftpd
|
|
528
528
|
end
|
529
529
|
end
|
530
530
|
|
531
|
+
def cmd_mdtm(path)
|
532
|
+
ensure_logged_in
|
533
|
+
ensure_file_system_supports :dir
|
534
|
+
ensure_file_system_supports :file_info
|
535
|
+
syntax_error unless path
|
536
|
+
path = File.expand_path(path, @name_prefix)
|
537
|
+
ensure_accessible(path)
|
538
|
+
ensure_exists(path)
|
539
|
+
info = @file_system.file_info(path)
|
540
|
+
mtime = info.mtime.utc
|
541
|
+
# We would like to report fractional seconds, too. Sadly, the
|
542
|
+
# spec declares that we may not report more precision than is
|
543
|
+
# actually there, and there is no spec or API to tell us how
|
544
|
+
# many fractional digits are significant.
|
545
|
+
mtime = mtime.strftime("%Y%m%d%H%M%S")
|
546
|
+
reply "213 #{mtime}"
|
547
|
+
end
|
548
|
+
|
549
|
+
def cmd_size(path)
|
550
|
+
ensure_logged_in
|
551
|
+
ensure_file_system_supports :read
|
552
|
+
syntax_error unless path
|
553
|
+
path = File.expand_path(path, @name_prefix)
|
554
|
+
ensure_accessible(path)
|
555
|
+
ensure_exists(path)
|
556
|
+
contents = @file_system.read(path)
|
557
|
+
contents = (@data_type == 'A') ? unix_to_nvt_ascii(contents) : contents
|
558
|
+
reply "213 #{contents.bytesize}"
|
559
|
+
end
|
560
|
+
|
531
561
|
unimplemented :abor
|
532
562
|
unimplemented :rein
|
533
563
|
unimplemented :rest
|
@@ -538,6 +568,7 @@ module Ftpd
|
|
538
568
|
[
|
539
569
|
(TLS_EXTENSIONS if tls_enabled?),
|
540
570
|
IPV6_EXTENSIONS,
|
571
|
+
RFC_3659_EXTENSIONS,
|
541
572
|
].flatten.compact
|
542
573
|
end
|
543
574
|
|
@@ -552,14 +583,19 @@ module Ftpd
|
|
552
583
|
'EPSV',
|
553
584
|
]
|
554
585
|
|
586
|
+
RFC_3659_EXTENSIONS = [
|
587
|
+
'MDTM',
|
588
|
+
'SIZE',
|
589
|
+
]
|
590
|
+
|
555
591
|
def supported_commands
|
556
592
|
private_methods.map do |method|
|
557
593
|
method.to_s[/^cmd_(\w+)$/, 1]
|
558
594
|
end.compact.map(&:upcase)
|
559
595
|
end
|
560
596
|
|
561
|
-
def pwd
|
562
|
-
reply %Q(
|
597
|
+
def pwd(status_code)
|
598
|
+
reply %Q(#{status_code} "#{@name_prefix}" is current directory)
|
563
599
|
end
|
564
600
|
|
565
601
|
TRANSMISSION_MODES = {
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,143 +1,143 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ftpd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wayne Conrad
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-03-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: memoizer
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 1.0.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 1.0.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: cucumber
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: double-bag-ftps
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: jeweler
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rake
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: redcarpet
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- -
|
94
|
+
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: rspec
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- -
|
101
|
+
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: '0'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- -
|
108
|
+
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: timecop
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
|
-
- -
|
115
|
+
- - ">="
|
116
116
|
- !ruby/object:Gem::Version
|
117
117
|
version: '0'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
|
-
- -
|
122
|
+
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: yard
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
|
-
- -
|
129
|
+
- - ">="
|
130
130
|
- !ruby/object:Gem::Version
|
131
131
|
version: '0'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
|
-
- -
|
136
|
+
- - ">="
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0'
|
139
139
|
description: ftpd is a pure Ruby FTP server library. It supports implicit and explicit
|
140
|
-
TLS, passive and active mode, and is unconditionally compliant per [RFC-1123][1]. It
|
140
|
+
TLS, IPV6, passive and active mode, and is unconditionally compliant per [RFC-1123][1]. It
|
141
141
|
can be used as part of a test fixture or embedded in a program.
|
142
142
|
email: wconrad@yagni.com
|
143
143
|
executables: []
|
@@ -146,8 +146,8 @@ extra_rdoc_files:
|
|
146
146
|
- LICENSE.md
|
147
147
|
- README.md
|
148
148
|
files:
|
149
|
-
- .travis.yml
|
150
|
-
- .yardopts
|
149
|
+
- ".travis.yml"
|
150
|
+
- ".yardopts"
|
151
151
|
- Changelog.md
|
152
152
|
- Gemfile
|
153
153
|
- Gemfile.lock
|
@@ -192,6 +192,7 @@ files:
|
|
192
192
|
- features/ftp_server/login_auth_level_password.feature
|
193
193
|
- features/ftp_server/login_auth_level_user.feature
|
194
194
|
- features/ftp_server/max_connections.feature
|
195
|
+
- features/ftp_server/mdtm.feature
|
195
196
|
- features/ftp_server/mkdir.feature
|
196
197
|
- features/ftp_server/mode.feature
|
197
198
|
- features/ftp_server/name_list.feature
|
@@ -208,6 +209,7 @@ files:
|
|
208
209
|
- features/ftp_server/rename.feature
|
209
210
|
- features/ftp_server/rmdir.feature
|
210
211
|
- features/ftp_server/site.feature
|
212
|
+
- features/ftp_server/size.feature
|
211
213
|
- features/ftp_server/status.feature
|
212
214
|
- features/ftp_server/step_definitions/logging.rb
|
213
215
|
- features/ftp_server/step_definitions/test_server.rb
|
@@ -236,6 +238,7 @@ files:
|
|
236
238
|
- features/step_definitions/login.rb
|
237
239
|
- features/step_definitions/mkdir.rb
|
238
240
|
- features/step_definitions/mode.rb
|
241
|
+
- features/step_definitions/mtime.rb
|
239
242
|
- features/step_definitions/noop.rb
|
240
243
|
- features/step_definitions/options.rb
|
241
244
|
- features/step_definitions/passive.rb
|
@@ -247,6 +250,7 @@ files:
|
|
247
250
|
- features/step_definitions/rmdir.rb
|
248
251
|
- features/step_definitions/server_files.rb
|
249
252
|
- features/step_definitions/server_title.rb
|
253
|
+
- features/step_definitions/size.rb
|
250
254
|
- features/step_definitions/status.rb
|
251
255
|
- features/step_definitions/success_replies.rb
|
252
256
|
- features/step_definitions/system.rb
|
@@ -321,17 +325,17 @@ require_paths:
|
|
321
325
|
- lib
|
322
326
|
required_ruby_version: !ruby/object:Gem::Requirement
|
323
327
|
requirements:
|
324
|
-
- -
|
328
|
+
- - ">="
|
325
329
|
- !ruby/object:Gem::Version
|
326
330
|
version: '0'
|
327
331
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
328
332
|
requirements:
|
329
|
-
- -
|
333
|
+
- - ">="
|
330
334
|
- !ruby/object:Gem::Version
|
331
335
|
version: '0'
|
332
336
|
requirements: []
|
333
337
|
rubyforge_project:
|
334
|
-
rubygems_version: 2.1
|
338
|
+
rubygems_version: 2.2.1
|
335
339
|
signing_key:
|
336
340
|
specification_version: 4
|
337
341
|
summary: Pure Ruby FTP server library
|