em-ftpd-memory 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +28 -18
- data/em-ftpd-memory.gemspec +1 -1
- data/lib/em/ftpd/memory/authenticator.rb +49 -3
- data/lib/em/ftpd/memory/driver.rb +13 -11
- data/lib/em/ftpd/memory/filesystem.rb +33 -7
- data/test/helper.rb +1 -0
- data/test/test_authenticator.rb +20 -5
- data/test/test_ftpd-memory.rb +20 -8
- data/test/test_memory_filesystem.rb +13 -11
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7c715cab895aa1f0db447b97d891e22c84cd52ae
|
4
|
+
data.tar.gz: 30665d3c15e7c72b9ad0f14cd0d621d2f2057e1d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 23d78443456ded147acc79c0c47063bc8bd295dedfc01c6099452e4bbfbfff4ecaafe416eb58ef106dd71542df51059553523205cb0ee828acfd22a7605b9aea
|
7
|
+
data.tar.gz: 4c4305f41b38491f6f206f253d9c2d7cb60a4c6fcff157ca974844b718bab40073ac19c2b4a01a289c1786c9b676bb470af80f05878c916aa0b201dee3132fbb
|
data/README.md
CHANGED
@@ -24,40 +24,50 @@ Or install it yourself as:
|
|
24
24
|
|
25
25
|
options = {
|
26
26
|
"filesystem_name" => "boss",
|
27
|
-
"authentication_realm" => "georgia"
|
28
|
-
"pwalgo" => "otp",
|
29
|
-
|
27
|
+
"authentication_realm" => "georgia"
|
30
28
|
}
|
31
|
-
|
32
|
-
auth = Authenticator.getAuthenticatorByRealm(options["authentication_realm"]
|
33
|
-
|
34
|
-
auth << User.new("test", "test1\ntest2\ntest3\ntest4\ntest5")
|
35
|
-
|
29
|
+
# set up the authentication
|
30
|
+
auth = Authenticator.getAuthenticatorByRealm(options["authentication_realm"])
|
31
|
+
# add a test user
|
32
|
+
auth << User.new(:name => "test", :algo => "otp", :credential => "test1\ntest2\ntest3\ntest4\ntest5")
|
33
|
+
# add an anonymous user, note: algo defaults to none if there are no credentials are specified
|
34
|
+
auth << User.new(:name => "anonymous")
|
35
|
+
# create the filesystem
|
36
36
|
fs = FileSystem.getFileSystem(options["filesystem_name"])
|
37
|
-
|
37
|
+
# add a pub folder
|
38
38
|
fs.create_dir("/pub", 'root')
|
39
|
-
|
39
|
+
# add a file to the pub folder as root
|
40
40
|
fs.create_file("/pub/helper.rb", "test/helper.rb", 'root')
|
41
|
-
|
41
|
+
# chmod 755 /pub
|
42
42
|
fs.set_permissions("/pub", 'rwxr.xr.x', "root")
|
43
|
-
|
43
|
+
# create /uploads as root
|
44
44
|
fs.create_dir("/uploads", 'root')
|
45
|
-
|
45
|
+
# chmod 777 /uploads
|
46
46
|
fs.set_permissions("/uploads", "rwxrwxrwx", "root")
|
47
47
|
# create /users as root
|
48
48
|
fs.create_dir("/users", 'root')
|
49
|
-
|
49
|
+
# chmod 755 /users
|
50
50
|
fs.set_permissions("/users", "rwxr.xr.x", "root")
|
51
|
-
|
51
|
+
# create a personal directory for hiro, miyako, and pilar, (and add their test user)
|
52
52
|
["hiro", "miyako", "pilar"].each do |username|
|
53
|
+
# create a home directory
|
53
54
|
fs.create_dir("/users/#{username}", 'root')
|
54
|
-
|
55
|
+
# set the permissions so that no one else can access it
|
55
56
|
fs.set_permissions("/users/#{username}", "rwx......", "root")
|
56
|
-
|
57
|
+
# set the owner to the user
|
57
58
|
fs.set_owner("/users/#{username}", username, 'root')
|
58
|
-
|
59
|
+
# add the user to the authentication realm
|
60
|
+
auth << User.new(:name => username, :algo => "plain", :credential => username, :groups => ["testing"])
|
59
61
|
end
|
60
62
|
|
63
|
+
# since hiro, miyako, and pilar are all in the "testing" group, I can
|
64
|
+
# create a shared folder for them, but the "test" user won't be able to access
|
65
|
+
fs.create_dir("/shared", 'root')
|
66
|
+
fs.set_permissions("/shared", 'rwxr.xr.x', 'root')
|
67
|
+
fs.create_dir("/shared/testing", 'root')
|
68
|
+
fs.set_group("/shared/testing", 'testing', 'root')
|
69
|
+
fs.set_permissions("/shared/testing", 'rwxrwx...', 'root')
|
70
|
+
|
61
71
|
EM.run {
|
62
72
|
EventMachine::start_server("0.0.0.0", 2021, EM::FTPD::Server, EM::FTPD::Memory::Driver, options)
|
63
73
|
}
|
data/em-ftpd-memory.gemspec
CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = "em-ftpd-memory"
|
7
|
-
spec.version = "0.0.
|
7
|
+
spec.version = "0.0.7"
|
8
8
|
spec.authors = ["chrislee35"]
|
9
9
|
spec.email = ["rubygems@chrislee.dhs.org"]
|
10
10
|
spec.summary = %q{Memory-based backing store for em-ftpd}
|
@@ -2,26 +2,43 @@ require 'em-ftpd'
|
|
2
2
|
require 'digest/md5'
|
3
3
|
|
4
4
|
module EM::FTPD::Memory
|
5
|
-
class User < Struct.new(:name, :algo, :credential); end
|
6
5
|
class InvalidPasswordAlgorithmError < StandardError; end
|
7
6
|
class NoSuchUserError < StandardError; end
|
8
7
|
class InvalidCredentialError < StandardError; end
|
9
8
|
class ExpiredCredentialError < StandardError; end
|
10
9
|
class MalformatedCredentialError < StandardError; end
|
10
|
+
class ReplayCredentialError < StandardError; end
|
11
11
|
class NoFurtherCredentialsAvailable < StandardError; end
|
12
|
+
|
13
|
+
class TimedToken < Struct.new(:time, :token); end
|
14
|
+
|
15
|
+
class User
|
16
|
+
ATTRS = [:name, :algo, :credential, :groups]
|
17
|
+
attr_accessor(*ATTRS)
|
18
|
+
|
19
|
+
def initialize(options)
|
20
|
+
options.each do |attr, value|
|
21
|
+
self.send("#{attr}=", value)
|
22
|
+
end
|
23
|
+
@algo ||= (@credential) ? 'plain' : 'none'
|
24
|
+
@groups ||= []
|
25
|
+
raise ArgumentError.new("User requires a :name") unless @name
|
26
|
+
end
|
27
|
+
end
|
12
28
|
|
13
29
|
class Authenticator
|
14
30
|
@@realms = Hash.new
|
31
|
+
TOKEN_VALIDITY_PERIOD = 300
|
15
32
|
def self.getAuthenticatorByRealm(realm)
|
16
33
|
if @@realms[realm].nil?
|
17
34
|
@@realms[realm] = Authenticator.new
|
18
35
|
end
|
19
|
-
#puts "returning Authenticator of realm #{realm}"
|
20
36
|
@@realms[realm]
|
21
37
|
end
|
22
38
|
|
23
39
|
def initialize
|
24
40
|
@users = Hash.new
|
41
|
+
@used_tokens = Array.new
|
25
42
|
end
|
26
43
|
|
27
44
|
def <<(user)
|
@@ -42,6 +59,11 @@ module EM::FTPD::Memory
|
|
42
59
|
end
|
43
60
|
self.send(@users[username].algo, username, credential)
|
44
61
|
end
|
62
|
+
|
63
|
+
# this can be used for anonymous accounts
|
64
|
+
def none_authentication(username, credential)
|
65
|
+
return true
|
66
|
+
end
|
45
67
|
|
46
68
|
def plain_authentication(username, credential)
|
47
69
|
if @users[username].credential != credential
|
@@ -56,10 +78,13 @@ module EM::FTPD::Memory
|
|
56
78
|
if hash.nil? or hash.length != 32
|
57
79
|
raise MalformatedCredentialError.new
|
58
80
|
end
|
59
|
-
if (time.to_i - Time.now.to_i).abs >
|
81
|
+
if (time.to_i - Time.now.to_i).abs > TOKEN_VALIDITY_PERIOD
|
60
82
|
raise ExpiredCredentialError.new
|
61
83
|
else
|
62
84
|
if Digest::MD5.hexdigest("#{seed}:#{time}:#{@users[username].credential}") == hash
|
85
|
+
unless check_and_set_token(time.to_i, seed)
|
86
|
+
raise ReplayCredentialError.new
|
87
|
+
end
|
63
88
|
return true
|
64
89
|
else
|
65
90
|
raise InvalidCredentialError.new
|
@@ -80,5 +105,26 @@ module EM::FTPD::Memory
|
|
80
105
|
raise InvalidCredentialError.new
|
81
106
|
end
|
82
107
|
end
|
108
|
+
|
109
|
+
def groups(username)
|
110
|
+
if @users[username].nil?
|
111
|
+
raise NoSuchUserError.new
|
112
|
+
end
|
113
|
+
@users[username].groups
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def check_and_set_token(time, token)
|
119
|
+
# clean up stale tokens
|
120
|
+
@used_tokens.reject! {|t| t.time < Time.now.to_i - TOKEN_VALIDITY_PERIOD}
|
121
|
+
# check if token is replayed
|
122
|
+
if @used_tokens.find {|t| t.time == time and t.token == token}
|
123
|
+
return false
|
124
|
+
end
|
125
|
+
# add new token
|
126
|
+
@used_tokens << TimedToken.new(time, token)
|
127
|
+
true
|
128
|
+
end
|
83
129
|
end
|
84
130
|
end
|
@@ -4,8 +4,9 @@ module EM::FTPD::Memory
|
|
4
4
|
filesystem_name = options["filesystem_name"] || "default"
|
5
5
|
realm = options["authentication_realm"] || "default"
|
6
6
|
@fs = FileSystem.getFileSystem(filesystem_name)
|
7
|
-
@authenticator = Authenticator.getAuthenticatorByRealm(realm
|
7
|
+
@authenticator = Authenticator.getAuthenticatorByRealm(realm)
|
8
8
|
@authenticated_user = nil
|
9
|
+
@authenticated_user_groups = []
|
9
10
|
@server = Kernel.caller[0]
|
10
11
|
begin
|
11
12
|
$stderr.puts @server
|
@@ -16,17 +17,18 @@ module EM::FTPD::Memory
|
|
16
17
|
end
|
17
18
|
|
18
19
|
def change_dir(path, &block)
|
19
|
-
yield @fs.change_dir(path, @authenticated_user)
|
20
|
+
yield @fs.change_dir(path, @authenticated_user, @authenticated_user_groups)
|
20
21
|
end
|
21
22
|
|
22
23
|
def dir_contents(path, &block)
|
23
|
-
yield @fs.list_files(path, @authenticated_user)
|
24
|
+
yield @fs.list_files(path, @authenticated_user, @authenticated_user_groups)
|
24
25
|
end
|
25
26
|
|
26
27
|
def authenticate(user, pass, &block)
|
27
28
|
begin
|
28
29
|
@authenticator.authenticate(user, pass)
|
29
30
|
@authenticated_user = user
|
31
|
+
@authenticated_user_groups = @authenticator.groups(user)
|
30
32
|
yield true
|
31
33
|
rescue Exception => e
|
32
34
|
#puts e.backtrace
|
@@ -35,35 +37,35 @@ module EM::FTPD::Memory
|
|
35
37
|
end
|
36
38
|
|
37
39
|
def bytes(path, &block)
|
38
|
-
yield @fs.file_size(path, @authenticated_user)
|
40
|
+
yield @fs.file_size(path, @authenticated_user, @authenticated_user_groups)
|
39
41
|
end
|
40
42
|
|
41
43
|
def get_file(path, &block)
|
42
|
-
yield @fs.file_contents(path, @authenticated_user)
|
44
|
+
yield @fs.file_contents(path, @authenticated_user, @authenticated_user_groups)
|
43
45
|
end
|
44
46
|
|
45
47
|
def put_file(path, data, &block)
|
46
|
-
yield @fs.create_file(path, data, @authenticated_user)
|
48
|
+
yield @fs.create_file(path, data, @authenticated_user, @authenticated_user_groups)
|
47
49
|
end
|
48
50
|
|
49
51
|
def delete_file(path, &block)
|
50
|
-
yield @fs.delete_file(path, @authenticated_user)
|
52
|
+
yield @fs.delete_file(path, @authenticated_user, @authenticated_user_groups)
|
51
53
|
end
|
52
54
|
|
53
55
|
def delete_dir(path, &block)
|
54
|
-
yield @fs.delete_dir(path, @authenticated_user)
|
56
|
+
yield @fs.delete_dir(path, @authenticated_user, @authenticated_user_groups)
|
55
57
|
end
|
56
58
|
|
57
59
|
def rename(from, to, &block)
|
58
|
-
yield @fs.rename(from, to, @authenticated_user)
|
60
|
+
yield @fs.rename(from, to, @authenticated_user, @authenticated_user_groups)
|
59
61
|
end
|
60
62
|
|
61
63
|
def make_dir(path, &block)
|
62
|
-
yield @fs.create_dir(path, @authenticated_user)
|
64
|
+
yield @fs.create_dir(path, @authenticated_user, @authenticated_user_groups)
|
63
65
|
end
|
64
66
|
|
65
67
|
def mtime(path, &block)
|
66
|
-
yield @fs.modified_time(path, @authenticated_user)
|
68
|
+
yield @fs.modified_time(path, @authenticated_user, @authenticated_user_groups)
|
67
69
|
end
|
68
70
|
|
69
71
|
end
|
@@ -23,7 +23,6 @@ module EM::FTPD::Memory
|
|
23
23
|
if @@filesystems[name].nil?
|
24
24
|
@@filesystems[name] = FileSystem.new
|
25
25
|
end
|
26
|
-
#puts "returning FileSystem named #{name}"
|
27
26
|
return @@filesystems[name]
|
28
27
|
end
|
29
28
|
|
@@ -42,7 +41,14 @@ module EM::FTPD::Memory
|
|
42
41
|
|
43
42
|
|
44
43
|
def initialize
|
45
|
-
@root = MemoryDirectoryItem.new(
|
44
|
+
@root = MemoryDirectoryItem.new(
|
45
|
+
:name => '/',
|
46
|
+
:owner => 'root',
|
47
|
+
:group => 'root',
|
48
|
+
:directory => true,
|
49
|
+
:permissions => "rwxr.xr.x",
|
50
|
+
:contents => Hash.new
|
51
|
+
)
|
46
52
|
end
|
47
53
|
|
48
54
|
def exist?(path)
|
@@ -113,7 +119,14 @@ module EM::FTPD::Memory
|
|
113
119
|
item.contents = contents
|
114
120
|
item.size = contents.length
|
115
121
|
else # create new
|
116
|
-
dir.contents[basename] = MemoryDirectoryItem.new(
|
122
|
+
dir.contents[basename] = MemoryDirectoryItem.new(
|
123
|
+
:name => basename,
|
124
|
+
:owner => user,
|
125
|
+
:group => groups.first || "nogroup",
|
126
|
+
:size => contents.length,
|
127
|
+
:contents => contents,
|
128
|
+
:permissions => permissions
|
129
|
+
)
|
117
130
|
end
|
118
131
|
return true
|
119
132
|
else
|
@@ -154,7 +167,13 @@ module EM::FTPD::Memory
|
|
154
167
|
basename = File.basename(path)
|
155
168
|
parent = get_item(dirname)
|
156
169
|
if parent and parent.directory
|
157
|
-
parent.contents[basename] = MemoryDirectoryItem.new(
|
170
|
+
parent.contents[basename] = MemoryDirectoryItem.new(
|
171
|
+
:name => basename,
|
172
|
+
:directory => true,
|
173
|
+
:owner => user,
|
174
|
+
:group => groups.first || "nogroup",
|
175
|
+
:contents => Hash.new
|
176
|
+
)
|
158
177
|
return true
|
159
178
|
end
|
160
179
|
end
|
@@ -184,7 +203,14 @@ module EM::FTPD::Memory
|
|
184
203
|
end
|
185
204
|
|
186
205
|
def destroy
|
187
|
-
@root = MemoryDirectoryItem.new(
|
206
|
+
@root = MemoryDirectoryItem.new(
|
207
|
+
:name => '/',
|
208
|
+
:owner => 'root',
|
209
|
+
:group => 'root',
|
210
|
+
:directory => true,
|
211
|
+
:permissions => "rwxr.xr.x",
|
212
|
+
:contents => Hash.new
|
213
|
+
)
|
188
214
|
GC.start
|
189
215
|
end
|
190
216
|
|
@@ -212,9 +238,9 @@ module EM::FTPD::Memory
|
|
212
238
|
def set_group(path, group, user = nil, groups = [])
|
213
239
|
item = get_item(path)
|
214
240
|
return false unless item and group and group.class == String
|
215
|
-
return false unless user and user == "root"
|
216
|
-
return false unless groups.index(group)
|
241
|
+
return false unless (user and user == "root") or groups.index(group)
|
217
242
|
item.group = group
|
243
|
+
true
|
218
244
|
end
|
219
245
|
|
220
246
|
#private
|
data/test/helper.rb
CHANGED
data/test/test_authenticator.rb
CHANGED
@@ -14,13 +14,13 @@ class TestAuthenticator < Minitest::Test
|
|
14
14
|
def test_invalid_pwalgo
|
15
15
|
assert_raises(InvalidPasswordAlgorithmError) do
|
16
16
|
auth = Authenticator.getAuthenticatorByRealm(__method__)
|
17
|
-
auth << User.new("test", "nogood", "test")
|
17
|
+
auth << User.new(:name => "test", :algo => "nogood", :credential => "test")
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
21
|
def test_plain_login
|
22
22
|
auth = Authenticator.getAuthenticatorByRealm(__method__)
|
23
|
-
auth << User.new("test", "plain", "test")
|
23
|
+
auth << User.new(:name => "test", :algo => "plain", :credential => "test")
|
24
24
|
assert_raises(NoSuchUserError) do
|
25
25
|
auth.authenticate("jerk", "noway")
|
26
26
|
end
|
@@ -34,7 +34,7 @@ class TestAuthenticator < Minitest::Test
|
|
34
34
|
|
35
35
|
def test_time_based_login
|
36
36
|
auth = Authenticator.getAuthenticatorByRealm(__method__)
|
37
|
-
auth << User.new("test", "timed_md5", "test")
|
37
|
+
auth << User.new(:name => "test", :algo => "timed_md5", :credential => "test")
|
38
38
|
assert_raises(NoSuchUserError) do
|
39
39
|
auth.authenticate("jerk", "noway")
|
40
40
|
end
|
@@ -59,7 +59,7 @@ class TestAuthenticator < Minitest::Test
|
|
59
59
|
time = Time.now.to_i
|
60
60
|
seed = "this is a random seed"
|
61
61
|
invalid_hash = Digest::MD5.hexdigest("#{seed}:#{time}:wrong")
|
62
|
-
invalid_cred = "#{seed}:#{time}:#{
|
62
|
+
invalid_cred = "#{seed}:#{time}:#{invalid_hash}"
|
63
63
|
|
64
64
|
assert_raises(InvalidCredentialError) do
|
65
65
|
auth.authenticate("test", invalid_cred)
|
@@ -71,11 +71,16 @@ class TestAuthenticator < Minitest::Test
|
|
71
71
|
valid_cred = "#{seed}:#{time}:#{valid_hash}"
|
72
72
|
|
73
73
|
assert(auth.authenticate("test", valid_cred))
|
74
|
+
|
75
|
+
assert_raises(ReplayCredentialError) do
|
76
|
+
auth.authenticate("test", valid_cred)
|
77
|
+
end
|
78
|
+
|
74
79
|
end
|
75
80
|
|
76
81
|
def test_otp_login
|
77
82
|
auth = Authenticator.getAuthenticatorByRealm(__method__)
|
78
|
-
auth << User.new("test", "otp", "test1\ntest2\ntest3\ntest4\ntest5")
|
83
|
+
auth << User.new(:name => "test", :algo => "otp", :credential => "test1\ntest2\ntest3\ntest4\ntest5")
|
79
84
|
assert_raises(NoSuchUserError) do
|
80
85
|
auth.authenticate("jerk", "noway")
|
81
86
|
end
|
@@ -97,4 +102,14 @@ class TestAuthenticator < Minitest::Test
|
|
97
102
|
auth.authenticate("test", "test5")
|
98
103
|
end
|
99
104
|
end
|
105
|
+
|
106
|
+
def test_anonymous_login
|
107
|
+
auth = Authenticator.getAuthenticatorByRealm(__method__)
|
108
|
+
auth << User.new(:name => "anonymous")
|
109
|
+
assert_raises(NoSuchUserError) do
|
110
|
+
auth.authenticate("jerk", "noway")
|
111
|
+
end
|
112
|
+
|
113
|
+
assert(auth.authenticate("anonymous","test@example.com"))
|
114
|
+
end
|
100
115
|
end
|
data/test/test_ftpd-memory.rb
CHANGED
@@ -14,12 +14,18 @@ include EM::FTPD::Memory
|
|
14
14
|
|
15
15
|
class TestFTPDMemory < Minitest::Test
|
16
16
|
def test_example
|
17
|
+
options = {
|
18
|
+
"filesystem_name" => "boss",
|
19
|
+
"authentication_realm" => "georgia"
|
20
|
+
}
|
17
21
|
# set up the authentication
|
18
|
-
auth = Authenticator.getAuthenticatorByRealm("
|
22
|
+
auth = Authenticator.getAuthenticatorByRealm(options["authentication_realm"])
|
19
23
|
# add a test user
|
20
|
-
auth << User.new("test", "otp", "test1\ntest2\ntest3\ntest4\ntest5")
|
24
|
+
auth << User.new(:name => "test", :algo => "otp", :credential => "test1\ntest2\ntest3\ntest4\ntest5")
|
25
|
+
# add an anonymous user, note: algo defaults to none if there are no credentials are specified
|
26
|
+
auth << User.new(:name => "anonymous")
|
21
27
|
# create the filesystem
|
22
|
-
fs = FileSystem.getFileSystem("
|
28
|
+
fs = FileSystem.getFileSystem(options["filesystem_name"])
|
23
29
|
# add a pub folder
|
24
30
|
fs.create_dir("/pub", 'root')
|
25
31
|
# add a file to the pub folder as root
|
@@ -36,18 +42,24 @@ class TestFTPDMemory < Minitest::Test
|
|
36
42
|
fs.set_permissions("/users", "rwxr.xr.x", "root")
|
37
43
|
# create a personal directory for hiro, miyako, and pilar, (and add their test user)
|
38
44
|
["hiro", "miyako", "pilar"].each do |username|
|
45
|
+
# create a home directory
|
39
46
|
fs.create_dir("/users/#{username}", 'root')
|
40
47
|
# set the permissions so that no one else can access it
|
41
48
|
fs.set_permissions("/users/#{username}", "rwx......", "root")
|
42
49
|
# set the owner to the user
|
43
50
|
fs.set_owner("/users/#{username}", username, 'root')
|
44
|
-
|
51
|
+
# add the user to the authentication realm
|
52
|
+
auth << User.new(:name => username, :algo => "plain", :credential => username, :groups => ["testing"])
|
45
53
|
end
|
46
54
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
55
|
+
# since hiro, miyako, and pilar are all in the "testing" group, I can
|
56
|
+
# create a shared folder for them, but the "test" user won't be able to access
|
57
|
+
fs.create_dir("/shared", 'root')
|
58
|
+
fs.set_permissions("/shared", 'rwxr.xr.x', 'root')
|
59
|
+
fs.create_dir("/shared/testing", 'root')
|
60
|
+
fs.set_group("/shared/testing", 'testing', 'root')
|
61
|
+
fs.set_permissions("/shared/testing", 'rwxrwx...', 'root')
|
62
|
+
|
51
63
|
EM.run {
|
52
64
|
EventMachine::start_server("0.0.0.0", 2021, EM::FTPD::Server, EM::FTPD::Memory::Driver, options)
|
53
65
|
EM::Timer.new(0.1) do
|
@@ -11,6 +11,8 @@ require_relative 'helper'
|
|
11
11
|
include EM::FTPD::Memory
|
12
12
|
|
13
13
|
class TestMemoryFilesystem < Minitest::Test
|
14
|
+
@@file_size = File.size("test/helper.rb")
|
15
|
+
|
14
16
|
def test_filesystem_instance_retrieval
|
15
17
|
fs = FileSystem.getFileSystem(__method__)
|
16
18
|
fs2 = FileSystem.getFileSystem(__method__)
|
@@ -28,7 +30,7 @@ class TestMemoryFilesystem < Minitest::Test
|
|
28
30
|
assert(fs.exist?("/helper.rb"))
|
29
31
|
refute(fs.is_dir?("/helper.rb"))
|
30
32
|
assert(fs.is_file?("/helper.rb"))
|
31
|
-
assert_equal(
|
33
|
+
assert_equal(@@file_size, fs.file_size("/helper.rb"))
|
32
34
|
FileSystem.destroyFileSystem(__method__)
|
33
35
|
end
|
34
36
|
|
@@ -39,7 +41,7 @@ class TestMemoryFilesystem < Minitest::Test
|
|
39
41
|
assert(fs.exist?("/helper.rb"))
|
40
42
|
refute(fs.is_dir?("/helper.rb"))
|
41
43
|
assert(fs.is_file?("/helper.rb"))
|
42
|
-
assert_equal(
|
44
|
+
assert_equal(@@file_size, fs.file_size("/helper.rb"))
|
43
45
|
assert(fs.delete_file("/helper.rb"))
|
44
46
|
refute(fs.exist?("/helper.rb"))
|
45
47
|
FileSystem.destroyFileSystem(__method__)
|
@@ -56,7 +58,7 @@ class TestMemoryFilesystem < Minitest::Test
|
|
56
58
|
|
57
59
|
assert(fs.create_file("/pub/helper.rb", "test/helper.rb"))
|
58
60
|
assert(fs.exist?("/pub/helper.rb"))
|
59
|
-
assert_equal(
|
61
|
+
assert_equal(@@file_size, fs.file_size("/pub/helper.rb"))
|
60
62
|
assert(fs.delete_file("/pub/helper.rb"))
|
61
63
|
refute(fs.exist?("/pub/helper.rb"))
|
62
64
|
FileSystem.destroyFileSystem(__method__)
|
@@ -72,7 +74,7 @@ class TestMemoryFilesystem < Minitest::Test
|
|
72
74
|
|
73
75
|
assert(fs.create_file("/pub/helper.rb", "test/helper.rb", "root"))
|
74
76
|
assert(fs.exist?("/pub/helper.rb"))
|
75
|
-
assert_equal(
|
77
|
+
assert_equal(@@file_size, fs.file_size("/pub/helper.rb", "root"))
|
76
78
|
refute(fs.delete_dir("/pub", "root"))
|
77
79
|
assert(fs.delete_file("/pub/helper.rb", "root"))
|
78
80
|
refute(fs.exist?("/pub/helper.rb"))
|
@@ -91,11 +93,11 @@ class TestMemoryFilesystem < Minitest::Test
|
|
91
93
|
|
92
94
|
assert(fs.create_file("/pub/helper.rb", "test/helper.rb"))
|
93
95
|
assert(fs.exist?("/pub/helper.rb"))
|
94
|
-
assert_equal(
|
96
|
+
assert_equal(@@file_size, fs.file_size("/pub/helper.rb"))
|
95
97
|
assert(fs.rename("/pub/helper.rb", "/pub/helper.txt"))
|
96
98
|
refute(fs.exist?("/pub/helper.rb"))
|
97
99
|
assert(fs.exist?("/pub/helper.txt"))
|
98
|
-
assert_equal(
|
100
|
+
assert_equal(@@file_size, fs.file_size("/pub/helper.txt"))
|
99
101
|
|
100
102
|
FileSystem.destroyFileSystem(__method__)
|
101
103
|
end
|
@@ -114,11 +116,11 @@ class TestMemoryFilesystem < Minitest::Test
|
|
114
116
|
|
115
117
|
assert(fs.create_file("/pub/helper.rb", "test/helper.rb"))
|
116
118
|
assert(fs.exist?("/pub/helper.rb"))
|
117
|
-
assert_equal(
|
119
|
+
assert_equal(@@file_size, fs.file_size("/pub/helper.rb"))
|
118
120
|
assert(fs.rename("/pub/helper.rb", "/pub2/helper.txt"))
|
119
121
|
refute(fs.exist?("/pub/helper.rb"))
|
120
122
|
assert(fs.exist?("/pub2/helper.txt"))
|
121
|
-
assert_equal(
|
123
|
+
assert_equal(@@file_size, fs.file_size("/pub2/helper.txt"))
|
122
124
|
|
123
125
|
FileSystem.destroyFileSystem(__method__)
|
124
126
|
end
|
@@ -138,7 +140,7 @@ class TestMemoryFilesystem < Minitest::Test
|
|
138
140
|
assert(fs.exist?("/pub3"))
|
139
141
|
refute(fs.is_dir?("/pub3"))
|
140
142
|
assert(fs.is_file?("/pub3"))
|
141
|
-
assert_equal(
|
143
|
+
assert_equal(@@file_size, fs.file_size("/pub3"))
|
142
144
|
|
143
145
|
refute(fs.rename("/pub", "/pub2"))
|
144
146
|
refute(fs.rename("/pub", "/pub3"))
|
@@ -176,14 +178,14 @@ class TestMemoryFilesystem < Minitest::Test
|
|
176
178
|
refute(fs.create_file("/pub/pub2/pub3/pub4/helper.rb", "test/helper.rb"))
|
177
179
|
assert(fs.create_file("/pub/pub2/pub3/pub4/helper.rb", "test/helper.rb", "root"))
|
178
180
|
refute(fs.file_size("/pub/pub2/pub3/pub4/helper.rb"))
|
179
|
-
assert_equal(
|
181
|
+
assert_equal(@@file_size, fs.file_size("/pub/pub2/pub3/pub4/helper.rb", "root"))
|
180
182
|
|
181
183
|
|
182
184
|
assert_equal(0, fs.list_files("/pub/pub2/pub3", "jem").length)
|
183
185
|
refute(fs.file_size("/pub/pub2/pub3/pub4/helper.rb", "jem"))
|
184
186
|
assert(fs.set_owner("/pub/pub2/pub3", "jem", "root"))
|
185
187
|
assert_equal(1, fs.list_files("/pub/pub2/pub3", "jem").length)
|
186
|
-
assert_equal(
|
188
|
+
assert_equal(@@file_size, fs.file_size("/pub/pub2/pub3/pub4/helper.rb", "jem"))
|
187
189
|
|
188
190
|
assert(fs.set_permissions("/pub/pub2", "rwx......", "root"))
|
189
191
|
# jem owns pub3, but should be denied since she can't traverse pub2
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: em-ftpd-memory
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- chrislee35
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-09-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: em-ftpd
|
@@ -121,7 +121,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
121
121
|
version: '0'
|
122
122
|
requirements: []
|
123
123
|
rubyforge_project:
|
124
|
-
rubygems_version: 2.
|
124
|
+
rubygems_version: 2.4.6
|
125
125
|
signing_key:
|
126
126
|
specification_version: 4
|
127
127
|
summary: Memory-based backing store for em-ftpd
|