net-ftp 0.1.2 → 0.2.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/.github/dependabot.yml +6 -0
- data/.github/workflows/test.yml +2 -2
- data/lib/net/ftp.rb +52 -37
- data/net-ftp.gemspec +2 -4
- metadata +6 -7
- data/bin/console +0 -14
- data/bin/setup +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cf9d2560e8bb495195915b83e2fa701ff039c328b06934515ac50f1309025769
|
4
|
+
data.tar.gz: 2231a3b5311f57b6fee02282e8cb41fd717b79cc1f2186d76483db8fd873ff47
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 52f5676aecc77cc97286bbbe6c6649ff9a966e7e161674643593db4cdb1aacdd6080fa25d8f8e3e379b9649125a5dd1167b3292401268141f0924bf618e4e0ad
|
7
|
+
data.tar.gz: 19212687975c12da4fee59c30e620ead52ad0e5a8beccf178de4c74809e43fc662c6cf5a5e084d3b222c19d5bacc4c352bdebb7b2d18939f9762600f9c43b60d
|
data/.github/workflows/test.yml
CHANGED
@@ -7,11 +7,11 @@ jobs:
|
|
7
7
|
name: build (${{ matrix.ruby }} / ${{ matrix.os }})
|
8
8
|
strategy:
|
9
9
|
matrix:
|
10
|
-
ruby: [ '3.0', 2.7, 2.6
|
10
|
+
ruby: [ head, '3.1', '3.0', '2.7', '2.6' ]
|
11
11
|
os: [ ubuntu-latest, macos-latest ]
|
12
12
|
runs-on: ${{ matrix.os }}
|
13
13
|
steps:
|
14
|
-
- uses: actions/checkout@
|
14
|
+
- uses: actions/checkout@v3
|
15
15
|
- name: Set up Ruby
|
16
16
|
uses: ruby/setup-ruby@v1
|
17
17
|
with:
|
data/lib/net/ftp.rb
CHANGED
@@ -85,7 +85,7 @@ module Net
|
|
85
85
|
end
|
86
86
|
|
87
87
|
# :stopdoc:
|
88
|
-
VERSION = "0.
|
88
|
+
VERSION = "0.2.0"
|
89
89
|
FTP_PORT = 21
|
90
90
|
CRLF = "\r\n"
|
91
91
|
DEFAULT_BLOCKSIZE = BufferedIO::BUFSIZE
|
@@ -98,10 +98,19 @@ module Net
|
|
98
98
|
# When +true+, the connection is in passive mode. Default: +true+.
|
99
99
|
attr_accessor :passive
|
100
100
|
|
101
|
+
# When +true+, use the IP address in PASV responses. Otherwise, it uses
|
102
|
+
# the same IP address for the control connection. Default: +false+.
|
103
|
+
attr_accessor :use_pasv_ip
|
104
|
+
|
101
105
|
# When +true+, all traffic to and from the server is written
|
102
106
|
# to +$stdout+. Default: +false+.
|
103
107
|
attr_accessor :debug_mode
|
104
108
|
|
109
|
+
# Sets or retrieves the output stream for debugging.
|
110
|
+
# Output stream will be used only when +debug_mode+ is set to true.
|
111
|
+
# The default value is +$stdout+.
|
112
|
+
attr_accessor :debug_output
|
113
|
+
|
105
114
|
# Sets or retrieves the +resume+ status, which decides whether incomplete
|
106
115
|
# transfers are resumed or restarted. Default: +false+.
|
107
116
|
attr_accessor :resume
|
@@ -191,6 +200,8 @@ module Net
|
|
191
200
|
# as parameters.
|
192
201
|
# private_data_connection:: If true, TLS is used for data connections.
|
193
202
|
# Default: +true+ when +options+[:ssl] is true.
|
203
|
+
# implicit_ftps:: If true, TLS is established on initial connection.
|
204
|
+
# Default: +false+
|
194
205
|
# username:: Username for login. If +options+[:username] is the string
|
195
206
|
# "anonymous" and the +options+[:password] is +nil+,
|
196
207
|
# "anonymous@" is used as a password.
|
@@ -206,6 +217,9 @@ module Net
|
|
206
217
|
# handshake.
|
207
218
|
# See Net::FTP#ssl_handshake_timeout for
|
208
219
|
# details. Default: +nil+.
|
220
|
+
# use_pasv_ip:: When +true+, use the IP address in PASV responses.
|
221
|
+
# Otherwise, it uses the same IP address for the control
|
222
|
+
# connection. Default: +false+.
|
209
223
|
# debug_mode:: When +true+, all traffic to and from the server is
|
210
224
|
# written to +$stdout+. Default: +false+.
|
211
225
|
#
|
@@ -241,6 +255,11 @@ module Net
|
|
241
255
|
else
|
242
256
|
@private_data_connection = options[:private_data_connection]
|
243
257
|
end
|
258
|
+
if options[:implicit_ftps].nil?
|
259
|
+
@implicit_ftps = false
|
260
|
+
else
|
261
|
+
@implicit_ftps = options[:implicit_ftps]
|
262
|
+
end
|
244
263
|
else
|
245
264
|
@ssl_context = nil
|
246
265
|
if options[:private_data_connection]
|
@@ -248,6 +267,11 @@ module Net
|
|
248
267
|
"private_data_connection can be set to true only when ssl is enabled"
|
249
268
|
end
|
250
269
|
@private_data_connection = false
|
270
|
+
if options[:implicit_ftps]
|
271
|
+
raise ArgumentError,
|
272
|
+
"implicit_ftps can be set to true only when ssl is enabled"
|
273
|
+
end
|
274
|
+
@implicit_ftps = false
|
251
275
|
end
|
252
276
|
@binary = true
|
253
277
|
if options[:passive].nil?
|
@@ -260,12 +284,14 @@ module Net
|
|
260
284
|
else
|
261
285
|
@debug_mode = options[:debug_mode]
|
262
286
|
end
|
287
|
+
@debug_output = $stdout
|
263
288
|
@resume = false
|
264
289
|
@bare_sock = @sock = NullSocket.new
|
265
290
|
@logged_in = false
|
266
291
|
@open_timeout = options[:open_timeout]
|
267
292
|
@ssl_handshake_timeout = options[:ssl_handshake_timeout]
|
268
293
|
@read_timeout = options[:read_timeout] || 60
|
294
|
+
@use_pasv_ip = options[:use_pasv_ip] || false
|
269
295
|
if host
|
270
296
|
connect(host, options[:port] || FTP_PORT)
|
271
297
|
if options[:username]
|
@@ -370,19 +396,17 @@ module Net
|
|
370
396
|
# <tt>Errno::ECONNREFUSED</tt>) if the connection cannot be established.
|
371
397
|
#
|
372
398
|
def connect(host, port = FTP_PORT)
|
373
|
-
|
374
|
-
print "connect: ", host, ", ", port, "\n"
|
375
|
-
end
|
399
|
+
debug_print "connect: #{host}:#{port}"
|
376
400
|
synchronize do
|
377
401
|
@host = host
|
378
402
|
@bare_sock = open_socket(host, port)
|
379
|
-
@sock = BufferedSocket.new(@bare_sock, read_timeout: @read_timeout)
|
380
|
-
voidresp
|
381
403
|
if @ssl_context
|
382
404
|
begin
|
383
|
-
|
384
|
-
|
385
|
-
|
405
|
+
unless @implicit_ftps
|
406
|
+
set_socket(BufferedSocket.new(@bare_sock, read_timeout: @read_timeout))
|
407
|
+
voidcmd("AUTH TLS")
|
408
|
+
end
|
409
|
+
set_socket(BufferedSSLSocket.new(start_tls_session(@bare_sock), read_timeout: @read_timeout), @implicit_ftps)
|
386
410
|
if @private_data_connection
|
387
411
|
voidcmd("PBSZ 0")
|
388
412
|
voidcmd("PROT P")
|
@@ -391,6 +415,8 @@ module Net
|
|
391
415
|
@sock.close
|
392
416
|
raise
|
393
417
|
end
|
418
|
+
else
|
419
|
+
set_socket(BufferedSocket.new(@bare_sock, read_timeout: @read_timeout))
|
394
420
|
end
|
395
421
|
end
|
396
422
|
end
|
@@ -422,9 +448,7 @@ module Net
|
|
422
448
|
# Ensures that +line+ has a control return / line feed (CRLF) and writes
|
423
449
|
# it to the socket.
|
424
450
|
def putline(line) # :nodoc:
|
425
|
-
|
426
|
-
print "put: ", sanitize(line), "\n"
|
427
|
-
end
|
451
|
+
debug_print "put: #{sanitize(line)}"
|
428
452
|
if /[\r\n]/ =~ line
|
429
453
|
raise ArgumentError, "A line must not contain CR or LF"
|
430
454
|
end
|
@@ -437,9 +461,7 @@ module Net
|
|
437
461
|
def getline # :nodoc:
|
438
462
|
line = @sock.readline # if get EOF, raise EOFError
|
439
463
|
line.sub!(/(\r\n|\n|\r)\z/n, "")
|
440
|
-
|
441
|
-
print "get: ", sanitize(line), "\n"
|
442
|
-
end
|
464
|
+
debug_print "get: #{sanitize(line)}"
|
443
465
|
return line
|
444
466
|
end
|
445
467
|
private :getline
|
@@ -537,7 +559,6 @@ module Net
|
|
537
559
|
host, port = parse227(sendcmd("PASV"))
|
538
560
|
else
|
539
561
|
host, port = parse229(sendcmd("EPSV"))
|
540
|
-
# host, port = parse228(sendcmd("LPSV"))
|
541
562
|
end
|
542
563
|
return host, port
|
543
564
|
end
|
@@ -1240,7 +1261,7 @@ module Net
|
|
1240
1261
|
#
|
1241
1262
|
def abort
|
1242
1263
|
line = "ABOR" + CRLF
|
1243
|
-
|
1264
|
+
debug_print "put: ABOR"
|
1244
1265
|
@sock.send(line, Socket::MSG_OOB)
|
1245
1266
|
resp = getmultiline
|
1246
1267
|
unless ["426", "226", "225"].include?(resp[0, 3])
|
@@ -1260,7 +1281,7 @@ module Net
|
|
1260
1281
|
if /[\r\n]/ =~ line
|
1261
1282
|
raise ArgumentError, "A line must not contain CR or LF"
|
1262
1283
|
end
|
1263
|
-
|
1284
|
+
debug_print "put: #{line}"
|
1264
1285
|
@sock.send(line + CRLF, Socket::MSG_OOB)
|
1265
1286
|
return getresp
|
1266
1287
|
end
|
@@ -1381,31 +1402,18 @@ module Net
|
|
1381
1402
|
raise FTPReplyError, resp
|
1382
1403
|
end
|
1383
1404
|
if m = /\((?<host>\d+(?:,\d+){3}),(?<port>\d+,\d+)\)/.match(resp)
|
1384
|
-
|
1405
|
+
if @use_pasv_ip
|
1406
|
+
host = parse_pasv_ipv4_host(m["host"])
|
1407
|
+
else
|
1408
|
+
host = @bare_sock.remote_address.ip_address
|
1409
|
+
end
|
1410
|
+
return host, parse_pasv_port(m["port"])
|
1385
1411
|
else
|
1386
1412
|
raise FTPProtoError, resp
|
1387
1413
|
end
|
1388
1414
|
end
|
1389
1415
|
private :parse227
|
1390
1416
|
|
1391
|
-
# handler for response code 228
|
1392
|
-
# (Entering Long Passive Mode)
|
1393
|
-
#
|
1394
|
-
# Returns host and port.
|
1395
|
-
def parse228(resp) # :nodoc:
|
1396
|
-
if !resp.start_with?("228")
|
1397
|
-
raise FTPReplyError, resp
|
1398
|
-
end
|
1399
|
-
if m = /\(4,4,(?<host>\d+(?:,\d+){3}),2,(?<port>\d+,\d+)\)/.match(resp)
|
1400
|
-
return parse_pasv_ipv4_host(m["host"]), parse_pasv_port(m["port"])
|
1401
|
-
elsif m = /\(6,16,(?<host>\d+(?:,\d+){15}),2,(?<port>\d+,\d+)\)/.match(resp)
|
1402
|
-
return parse_pasv_ipv6_host(m["host"]), parse_pasv_port(m["port"])
|
1403
|
-
else
|
1404
|
-
raise FTPProtoError, resp
|
1405
|
-
end
|
1406
|
-
end
|
1407
|
-
private :parse228
|
1408
|
-
|
1409
1417
|
def parse_pasv_ipv4_host(s)
|
1410
1418
|
return s.tr(",", ".")
|
1411
1419
|
end
|
@@ -1453,6 +1461,13 @@ module Net
|
|
1453
1461
|
end
|
1454
1462
|
private :parse257
|
1455
1463
|
|
1464
|
+
#
|
1465
|
+
# Writes debug message to the debug output stream
|
1466
|
+
#
|
1467
|
+
def debug_print(msg)
|
1468
|
+
@debug_output << msg + "\n" if @debug_mode && @debug_output
|
1469
|
+
end
|
1470
|
+
|
1456
1471
|
# :stopdoc:
|
1457
1472
|
class NullSocket
|
1458
1473
|
def read_timeout=(sec)
|
data/net-ftp.gemspec
CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.summary = %q{Support for the File Transfer Protocol.}
|
17
17
|
spec.description = %q{Support for the File Transfer Protocol.}
|
18
18
|
spec.homepage = "https://github.com/ruby/net-ftp"
|
19
|
-
spec.required_ruby_version = Gem::Requirement.new(">= 2.
|
19
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
|
20
20
|
spec.licenses = ["Ruby", "BSD-2-Clause"]
|
21
21
|
|
22
22
|
spec.metadata["homepage_uri"] = spec.homepage
|
@@ -25,10 +25,8 @@ Gem::Specification.new do |spec|
|
|
25
25
|
# Specify which files should be added to the gem when it is released.
|
26
26
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
27
27
|
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
28
|
-
`git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
28
|
+
`git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(bin|test|spec|features)/}) }
|
29
29
|
end
|
30
|
-
spec.bindir = "exe"
|
31
|
-
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
32
30
|
spec.require_paths = ["lib"]
|
33
31
|
|
34
32
|
spec.add_dependency "net-protocol"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: net-ftp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shugo Maeda
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-10-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: net-protocol
|
@@ -45,14 +45,13 @@ executables: []
|
|
45
45
|
extensions: []
|
46
46
|
extra_rdoc_files: []
|
47
47
|
files:
|
48
|
+
- ".github/dependabot.yml"
|
48
49
|
- ".github/workflows/test.yml"
|
49
50
|
- ".gitignore"
|
50
51
|
- Gemfile
|
51
52
|
- LICENSE.txt
|
52
53
|
- README.md
|
53
54
|
- Rakefile
|
54
|
-
- bin/console
|
55
|
-
- bin/setup
|
56
55
|
- lib/net/ftp.rb
|
57
56
|
- net-ftp.gemspec
|
58
57
|
homepage: https://github.com/ruby/net-ftp
|
@@ -70,14 +69,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
70
69
|
requirements:
|
71
70
|
- - ">="
|
72
71
|
- !ruby/object:Gem::Version
|
73
|
-
version: 2.
|
72
|
+
version: 2.6.0
|
74
73
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
74
|
requirements:
|
76
75
|
- - ">="
|
77
76
|
- !ruby/object:Gem::Version
|
78
77
|
version: '0'
|
79
78
|
requirements: []
|
80
|
-
rubygems_version: 3.
|
79
|
+
rubygems_version: 3.4.0.dev
|
81
80
|
signing_key:
|
82
81
|
specification_version: 4
|
83
82
|
summary: Support for the File Transfer Protocol.
|
data/bin/console
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require "bundler/setup"
|
4
|
-
require "net/ftp"
|
5
|
-
|
6
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
-
# with your gem easier. You can also use a different console, if you like.
|
8
|
-
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
# require "pry"
|
11
|
-
# Pry.start
|
12
|
-
|
13
|
-
require "irb"
|
14
|
-
IRB.start(__FILE__)
|