ftpd 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +6 -0
- data/Changelog.md +6 -0
- data/README.md +27 -4
- data/VERSION +1 -1
- data/examples/example.rb +27 -12
- data/ftpd.gemspec +3 -2
- data/lib/ftpd/disk_file_system.rb +21 -14
- data/rake_tasks/yard.rake +0 -1
- metadata +4 -3
data/.yardopts
ADDED
data/Changelog.md
CHANGED
data/README.md
CHANGED
@@ -5,6 +5,12 @@ explicit TLS, passive and active mode, and most of the commands
|
|
5
5
|
specified in RFC 969. It an be used as part of a test fixture or
|
6
6
|
embedded in a program.
|
7
7
|
|
8
|
+
## A note about this README
|
9
|
+
|
10
|
+
This readme, and the other files, contains Yardoc markup, especially
|
11
|
+
for links to the API docs. You'll find a properly rendered version
|
12
|
+
{http://rubydoc.info/gems/ftpd on rubydoc.info}
|
13
|
+
|
8
14
|
## HELLO WORLD
|
9
15
|
|
10
16
|
This is examples/hello_world.rb, a bare minimum FTP server. It allows
|
@@ -50,12 +56,15 @@ the authenticate method to decide who can log in. Once someone is
|
|
50
56
|
logged on, it calls the file_system method to obtain a file system
|
51
57
|
driver for that user.
|
52
58
|
|
53
|
-
There is no base class for a driver. Any
|
54
|
-
will do.
|
59
|
+
There is no base class for a driver. Any object that quacks like a
|
60
|
+
driver will do. Here are the methods your driver needs:
|
61
|
+
|
62
|
+
* {Example::Driver#authenticate authenticate}
|
63
|
+
* {Example::Driver#file_system file_system}
|
55
64
|
|
56
65
|
## FILE SYSTEM
|
57
66
|
|
58
|
-
The file system object that the driver supplies to Ftpd is
|
67
|
+
The file system object that the driver supplies to Ftpd is Ftpd's
|
59
68
|
gateway to the logical file system. Ftpd doesn't know or care whether
|
60
69
|
it's serving files from disk, memory, or any other means.
|
61
70
|
|
@@ -66,7 +75,21 @@ not supported and causes a "502 Command not implemented" response to
|
|
66
75
|
the client.
|
67
76
|
|
68
77
|
The canonical and commented example of an Ftpd file system is
|
69
|
-
Ftpd::DiskFileSystem.
|
78
|
+
{Ftpd::DiskFileSystem}. You can use it as a template for creating
|
79
|
+
your own, and its comments are the official specification for an Ftpd
|
80
|
+
file system.
|
81
|
+
|
82
|
+
Here are the methods a file system may expose:
|
83
|
+
|
84
|
+
* {Ftpd::DiskFileSystem::Accessors#accessible? accessible?}
|
85
|
+
* {Ftpd::DiskFileSystem::Accessors#exists? exists?}
|
86
|
+
* {Ftpd::DiskFileSystem::Accessors#directory? directory?}
|
87
|
+
* {Ftpd::DiskFileSystem::Write#write write}
|
88
|
+
* {Ftpd::DiskFileSystem::Mkdir#mkdir mkdir}
|
89
|
+
* {Ftpd::DiskFileSystem::Rmdir#rmdir rmdir}
|
90
|
+
* {Ftpd::DiskFileSystem::List#file_info file_info}
|
91
|
+
* {Ftpd::DiskFileSystem::List#dir dir}
|
92
|
+
* {Ftpd::DiskFileSystem::Rename#rename rename}
|
70
93
|
|
71
94
|
## DEBUGGING
|
72
95
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.2
|
data/examples/example.rb
CHANGED
@@ -8,6 +8,9 @@ require 'ftpd'
|
|
8
8
|
require 'optparse'
|
9
9
|
|
10
10
|
module Example
|
11
|
+
|
12
|
+
# Command-line option parser
|
13
|
+
|
11
14
|
class Arguments
|
12
15
|
|
13
16
|
attr_reader :eplf
|
@@ -54,27 +57,31 @@ module Example
|
|
54
57
|
# The FTP server requires and instance of a _driver_ which can
|
55
58
|
# authenticate users and create a file system drivers for a given
|
56
59
|
# user. You can use this as a template for creating your own
|
57
|
-
# driver.
|
58
|
-
# base class.
|
60
|
+
# driver.
|
59
61
|
|
60
62
|
class Driver
|
61
63
|
|
62
|
-
|
63
|
-
|
64
|
+
# Your driver's initialize method can be anything you need. Ftpd
|
65
|
+
# does not create an instance of your driver.
|
64
66
|
|
65
|
-
def initialize(data_dir)
|
67
|
+
def initialize(user, password, data_dir)
|
68
|
+
@user = user
|
69
|
+
@password = password
|
66
70
|
@data_dir = data_dir
|
67
|
-
@expected_user = ENV['LOGNAME']
|
68
|
-
@expected_password = ''
|
69
71
|
end
|
70
72
|
|
71
|
-
# Return true if the user
|
73
|
+
# Return true if the user should be allowed to log in.
|
74
|
+
# @param user [String]
|
75
|
+
# @param password [String]
|
76
|
+
# @return [Boolean]
|
72
77
|
|
73
78
|
def authenticate(user, password)
|
74
|
-
user == @
|
79
|
+
user == @user && password == @password
|
75
80
|
end
|
76
81
|
|
77
82
|
# Return the file system to use for a user.
|
83
|
+
# @param user [String]
|
84
|
+
# @return A file system driver that quacks like {Ftpd::DiskFileSystem}
|
78
85
|
|
79
86
|
def file_system(user)
|
80
87
|
Ftpd::DiskFileSystem.new(@data_dir)
|
@@ -92,7 +99,7 @@ module Example
|
|
92
99
|
@args = Arguments.new(argv)
|
93
100
|
@data_dir = Ftpd::TempDir.make
|
94
101
|
create_files
|
95
|
-
@driver = Driver.new(@data_dir)
|
102
|
+
@driver = Driver.new(user, password, @data_dir)
|
96
103
|
@server = Ftpd::FtpServer.new(@driver)
|
97
104
|
@server.interface = @args.interface
|
98
105
|
@server.port = @args.port
|
@@ -131,8 +138,8 @@ module Example
|
|
131
138
|
def display_connection_info
|
132
139
|
puts "Interface: #{@server.interface}"
|
133
140
|
puts "Port: #{@server.bound_port}"
|
134
|
-
puts "User: #{
|
135
|
-
puts "Pass: #{
|
141
|
+
puts "User: #{user}"
|
142
|
+
puts "Pass: #{password}"
|
136
143
|
puts "TLS: #{@args.tls}"
|
137
144
|
puts "Directory: #{@data_dir}"
|
138
145
|
puts "URI: ftp://#{HOST}:#{@server.bound_port}"
|
@@ -158,6 +165,14 @@ module Example
|
|
158
165
|
end
|
159
166
|
end
|
160
167
|
|
168
|
+
def user
|
169
|
+
ENV['LOGNAME']
|
170
|
+
end
|
171
|
+
|
172
|
+
def password
|
173
|
+
''
|
174
|
+
end
|
175
|
+
|
161
176
|
end
|
162
177
|
end
|
163
178
|
|
data/ftpd.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "ftpd"
|
8
|
-
s.version = "0.3.
|
8
|
+
s.version = "0.3.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Wayne Conrad"]
|
12
|
-
s.date = "2013-03-
|
12
|
+
s.date = "2013-03-05"
|
13
13
|
s.description = "ftpd is a pure Ruby FTP server library. It supports implicit and explicit TLS, passive and active mode, and most of the commands specified in RFC 969. It an be used as part of a test fixture or embedded in a program."
|
14
14
|
s.email = "wconrad@yagni.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -17,6 +17,7 @@ Gem::Specification.new do |s|
|
|
17
17
|
"README.md"
|
18
18
|
]
|
19
19
|
s.files = [
|
20
|
+
".yardopts",
|
20
21
|
"Changelog.md",
|
21
22
|
"Gemfile",
|
22
23
|
"Gemfile.lock",
|
@@ -38,6 +38,8 @@ module Ftpd
|
|
38
38
|
# Return true if the path is accessible to the user. This will be
|
39
39
|
# called for put, get and directory lists, so the file or
|
40
40
|
# directory named by the path may not exist.
|
41
|
+
# @param ftp_path [String] The virtual path
|
42
|
+
# @return [Boolean]
|
41
43
|
#
|
42
44
|
# Called for:
|
43
45
|
# * STOR
|
@@ -55,6 +57,8 @@ module Ftpd
|
|
55
57
|
end
|
56
58
|
|
57
59
|
# Return true if the file or directory path exists.
|
60
|
+
# @param ftp_path [String] The virtual path
|
61
|
+
# @return [Boolean]
|
58
62
|
#
|
59
63
|
# Called for:
|
60
64
|
# * STOR (with directory)
|
@@ -68,6 +72,8 @@ module Ftpd
|
|
68
72
|
end
|
69
73
|
|
70
74
|
# Return true if the path exists and is a directory.
|
75
|
+
# @param ftp_path [String] The virtual path
|
76
|
+
# @return [Boolean]
|
71
77
|
#
|
72
78
|
# Called for:
|
73
79
|
# * CWD
|
@@ -89,6 +95,7 @@ module Ftpd
|
|
89
95
|
include TranslateExceptions
|
90
96
|
|
91
97
|
# Remove a file.
|
98
|
+
# @param ftp_path [String] The virtual path
|
92
99
|
#
|
93
100
|
# Called for:
|
94
101
|
# * DELE
|
@@ -112,6 +119,7 @@ module Ftpd
|
|
112
119
|
include TranslateExceptions
|
113
120
|
|
114
121
|
# Read a file into memory.
|
122
|
+
# @param ftp_path [String] The virtual path
|
115
123
|
#
|
116
124
|
# Called for:
|
117
125
|
# * RETR
|
@@ -135,6 +143,8 @@ module Ftpd
|
|
135
143
|
include TranslateExceptions
|
136
144
|
|
137
145
|
# Write a file to disk.
|
146
|
+
# @param ftp_path [String] The virtual path
|
147
|
+
# @contents [String] The file's contents
|
138
148
|
#
|
139
149
|
# Called for:
|
140
150
|
# * STOR
|
@@ -161,6 +171,7 @@ module Ftpd
|
|
161
171
|
include TranslateExceptions
|
162
172
|
|
163
173
|
# Create a directory.
|
174
|
+
# @param ftp_path [String] The virtual path
|
164
175
|
#
|
165
176
|
# Called for:
|
166
177
|
# * MKD
|
@@ -185,6 +196,7 @@ module Ftpd
|
|
185
196
|
include TranslateExceptions
|
186
197
|
|
187
198
|
# Remove a directory.
|
199
|
+
# @param ftp_path [String] The virtual path
|
188
200
|
#
|
189
201
|
# Called for:
|
190
202
|
# * RMD
|
@@ -209,20 +221,20 @@ module Ftpd
|
|
209
221
|
include TranslateExceptions
|
210
222
|
|
211
223
|
# Get information about a single file or directory.
|
224
|
+
# @param ftp_path [String] The virtual path
|
225
|
+
# @return [FileInfo]
|
212
226
|
#
|
213
227
|
# Should follow symlinks (per
|
214
228
|
# {http://cr.yp.to/ftp/list/eplf.html}, "lstat() is not a good
|
215
229
|
# idea for FTP directory listings").
|
216
230
|
#
|
217
|
-
# @return [FileInfo]
|
218
|
-
#
|
219
231
|
# Called for:
|
220
232
|
# * LIST
|
221
233
|
#
|
222
234
|
# If missing, then these commands are not supported.
|
223
235
|
|
224
|
-
def file_info(
|
225
|
-
stat = File.stat(expand_ftp_path(
|
236
|
+
def file_info(ftp_path)
|
237
|
+
stat = File.stat(expand_ftp_path(ftp_path))
|
226
238
|
FileInfo.new(:ftype => stat.ftype,
|
227
239
|
:group => gid_name(stat.gid),
|
228
240
|
:identifier => identifier(stat),
|
@@ -230,20 +242,15 @@ module Ftpd
|
|
230
242
|
:mtime => stat.mtime,
|
231
243
|
:nlink => stat.nlink,
|
232
244
|
:owner => uid_name(stat.uid),
|
233
|
-
:path =>
|
245
|
+
:path => ftp_path,
|
234
246
|
:size => stat.size)
|
235
247
|
end
|
236
248
|
translate_exceptions :file_info
|
237
249
|
|
238
250
|
# Expand a path that may contain globs into a list of paths of
|
239
251
|
# matching files and directories.
|
240
|
-
#
|
241
|
-
#
|
242
|
-
#
|
243
|
-
# * If the path has no glob and matches a directory, then the
|
244
|
-
# list contains only that directory.
|
245
|
-
#
|
246
|
-
# * If the patch has a glob, it may return multiple entries.
|
252
|
+
# @param ftp_path [String] The virtual path
|
253
|
+
# @return [Array<String>]
|
247
254
|
#
|
248
255
|
# The paths returned are fully qualified, relative to the root
|
249
256
|
# of the virtual file system.
|
@@ -269,8 +276,8 @@ module Ftpd
|
|
269
276
|
#
|
270
277
|
# If missing, then these commands are not supported.
|
271
278
|
|
272
|
-
def dir(
|
273
|
-
Dir[expand_ftp_path(
|
279
|
+
def dir(ftp_path)
|
280
|
+
Dir[expand_ftp_path(ftp_path)].map do |path|
|
274
281
|
path.sub(/^#{@data_dir}/, '')
|
275
282
|
end
|
276
283
|
end
|
data/rake_tasks/yard.rake
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ftpd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-03-
|
12
|
+
date: 2013-03-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: memoizer
|
@@ -165,6 +165,7 @@ extra_rdoc_files:
|
|
165
165
|
- LICENSE.md
|
166
166
|
- README.md
|
167
167
|
files:
|
168
|
+
- .yardopts
|
168
169
|
- Changelog.md
|
169
170
|
- Gemfile
|
170
171
|
- Gemfile.lock
|
@@ -300,7 +301,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
300
301
|
version: '0'
|
301
302
|
segments:
|
302
303
|
- 0
|
303
|
-
hash:
|
304
|
+
hash: 286911087
|
304
305
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
305
306
|
none: false
|
306
307
|
requirements:
|