net-ftp 0.1.3 → 0.3.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 +44 -47
- 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: 6da1dd16a259cb0b9da3833be6087725451c66020a77484962ce512ebe76bd86
|
4
|
+
data.tar.gz: 5baf86565938970ff01dca9f6c85d8ae5afa57493ca96c35e8ccb30184f8fd96
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b634e82e54a09c1ad7174bafa5049f77f4878c5bf8b5d9fe4f43626c75d83831b91968a211075f5e36c7514c29d7dd2f8834134dc08f4f63def4b6e5a266b991
|
7
|
+
data.tar.gz: 4b124cb421ad550f889fd5dce46efb22cb726516a1e245131a4d0c5c125c0eb229b8041e952df0c85abed0a8e82697ea3116ef7c1eae1db7ebd09f45ea854355
|
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@v4
|
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.3.0"
|
89
89
|
FTP_PORT = 21
|
90
90
|
CRLF = "\r\n"
|
91
91
|
DEFAULT_BLOCKSIZE = BufferedIO::BUFSIZE
|
@@ -106,6 +106,11 @@ module Net
|
|
106
106
|
# to +$stdout+. Default: +false+.
|
107
107
|
attr_accessor :debug_mode
|
108
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
|
+
|
109
114
|
# Sets or retrieves the +resume+ status, which decides whether incomplete
|
110
115
|
# transfers are resumed or restarted. Default: +false+.
|
111
116
|
attr_accessor :resume
|
@@ -195,6 +200,8 @@ module Net
|
|
195
200
|
# as parameters.
|
196
201
|
# private_data_connection:: If true, TLS is used for data connections.
|
197
202
|
# Default: +true+ when +options+[:ssl] is true.
|
203
|
+
# implicit_ftps:: If true, TLS is established on initial connection.
|
204
|
+
# Default: +false+
|
198
205
|
# username:: Username for login. If +options+[:username] is the string
|
199
206
|
# "anonymous" and the +options+[:password] is +nil+,
|
200
207
|
# "anonymous@" is used as a password.
|
@@ -248,6 +255,11 @@ module Net
|
|
248
255
|
else
|
249
256
|
@private_data_connection = options[:private_data_connection]
|
250
257
|
end
|
258
|
+
if options[:implicit_ftps].nil?
|
259
|
+
@implicit_ftps = false
|
260
|
+
else
|
261
|
+
@implicit_ftps = options[:implicit_ftps]
|
262
|
+
end
|
251
263
|
else
|
252
264
|
@ssl_context = nil
|
253
265
|
if options[:private_data_connection]
|
@@ -255,6 +267,11 @@ module Net
|
|
255
267
|
"private_data_connection can be set to true only when ssl is enabled"
|
256
268
|
end
|
257
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
|
258
275
|
end
|
259
276
|
@binary = true
|
260
277
|
if options[:passive].nil?
|
@@ -267,6 +284,7 @@ module Net
|
|
267
284
|
else
|
268
285
|
@debug_mode = options[:debug_mode]
|
269
286
|
end
|
287
|
+
@debug_output = $stdout
|
270
288
|
@resume = false
|
271
289
|
@bare_sock = @sock = NullSocket.new
|
272
290
|
@logged_in = false
|
@@ -338,19 +356,14 @@ module Net
|
|
338
356
|
# SOCKS_SERVER, then a SOCKSSocket is returned, else a Socket is
|
339
357
|
# returned.
|
340
358
|
def open_socket(host, port) # :nodoc:
|
341
|
-
|
342
|
-
|
343
|
-
|
359
|
+
return Timeout.timeout(@open_timeout, OpenTimeout) {
|
360
|
+
if defined? SOCKSSocket and ENV["SOCKS_SERVER"]
|
361
|
+
@passive = true
|
344
362
|
SOCKSSocket.open(host, port)
|
363
|
+
else
|
364
|
+
Socket.tcp(host, port)
|
345
365
|
end
|
346
|
-
|
347
|
-
begin
|
348
|
-
Socket.tcp host, port, nil, nil, connect_timeout: @open_timeout
|
349
|
-
rescue Errno::ETIMEDOUT #raise Net:OpenTimeout instead for compatibility with previous versions
|
350
|
-
raise Net::OpenTimeout, "Timeout to open TCP connection to "\
|
351
|
-
"#{host}:#{port} (exceeds #{@open_timeout} seconds)"
|
352
|
-
end
|
353
|
-
end
|
366
|
+
}
|
354
367
|
end
|
355
368
|
private :open_socket
|
356
369
|
|
@@ -378,19 +391,17 @@ module Net
|
|
378
391
|
# <tt>Errno::ECONNREFUSED</tt>) if the connection cannot be established.
|
379
392
|
#
|
380
393
|
def connect(host, port = FTP_PORT)
|
381
|
-
|
382
|
-
print "connect: ", host, ", ", port, "\n"
|
383
|
-
end
|
394
|
+
debug_print "connect: #{host}:#{port}"
|
384
395
|
synchronize do
|
385
396
|
@host = host
|
386
397
|
@bare_sock = open_socket(host, port)
|
387
|
-
@sock = BufferedSocket.new(@bare_sock, read_timeout: @read_timeout)
|
388
|
-
voidresp
|
389
398
|
if @ssl_context
|
390
399
|
begin
|
391
|
-
|
392
|
-
|
393
|
-
|
400
|
+
unless @implicit_ftps
|
401
|
+
set_socket(BufferedSocket.new(@bare_sock, read_timeout: @read_timeout))
|
402
|
+
voidcmd("AUTH TLS")
|
403
|
+
end
|
404
|
+
set_socket(BufferedSSLSocket.new(start_tls_session(@bare_sock), read_timeout: @read_timeout), @implicit_ftps)
|
394
405
|
if @private_data_connection
|
395
406
|
voidcmd("PBSZ 0")
|
396
407
|
voidcmd("PROT P")
|
@@ -399,6 +410,8 @@ module Net
|
|
399
410
|
@sock.close
|
400
411
|
raise
|
401
412
|
end
|
413
|
+
else
|
414
|
+
set_socket(BufferedSocket.new(@bare_sock, read_timeout: @read_timeout))
|
402
415
|
end
|
403
416
|
end
|
404
417
|
end
|
@@ -430,9 +443,7 @@ module Net
|
|
430
443
|
# Ensures that +line+ has a control return / line feed (CRLF) and writes
|
431
444
|
# it to the socket.
|
432
445
|
def putline(line) # :nodoc:
|
433
|
-
|
434
|
-
print "put: ", sanitize(line), "\n"
|
435
|
-
end
|
446
|
+
debug_print "put: #{sanitize(line)}"
|
436
447
|
if /[\r\n]/ =~ line
|
437
448
|
raise ArgumentError, "A line must not contain CR or LF"
|
438
449
|
end
|
@@ -445,9 +456,7 @@ module Net
|
|
445
456
|
def getline # :nodoc:
|
446
457
|
line = @sock.readline # if get EOF, raise EOFError
|
447
458
|
line.sub!(/(\r\n|\n|\r)\z/n, "")
|
448
|
-
|
449
|
-
print "get: ", sanitize(line), "\n"
|
450
|
-
end
|
459
|
+
debug_print "get: #{sanitize(line)}"
|
451
460
|
return line
|
452
461
|
end
|
453
462
|
private :getline
|
@@ -545,7 +554,6 @@ module Net
|
|
545
554
|
host, port = parse227(sendcmd("PASV"))
|
546
555
|
else
|
547
556
|
host, port = parse229(sendcmd("EPSV"))
|
548
|
-
# host, port = parse228(sendcmd("LPSV"))
|
549
557
|
end
|
550
558
|
return host, port
|
551
559
|
end
|
@@ -1248,7 +1256,7 @@ module Net
|
|
1248
1256
|
#
|
1249
1257
|
def abort
|
1250
1258
|
line = "ABOR" + CRLF
|
1251
|
-
|
1259
|
+
debug_print "put: ABOR"
|
1252
1260
|
@sock.send(line, Socket::MSG_OOB)
|
1253
1261
|
resp = getmultiline
|
1254
1262
|
unless ["426", "226", "225"].include?(resp[0, 3])
|
@@ -1268,7 +1276,7 @@ module Net
|
|
1268
1276
|
if /[\r\n]/ =~ line
|
1269
1277
|
raise ArgumentError, "A line must not contain CR or LF"
|
1270
1278
|
end
|
1271
|
-
|
1279
|
+
debug_print "put: #{line}"
|
1272
1280
|
@sock.send(line + CRLF, Socket::MSG_OOB)
|
1273
1281
|
return getresp
|
1274
1282
|
end
|
@@ -1401,24 +1409,6 @@ module Net
|
|
1401
1409
|
end
|
1402
1410
|
private :parse227
|
1403
1411
|
|
1404
|
-
# handler for response code 228
|
1405
|
-
# (Entering Long Passive Mode)
|
1406
|
-
#
|
1407
|
-
# Returns host and port.
|
1408
|
-
def parse228(resp) # :nodoc:
|
1409
|
-
if !resp.start_with?("228")
|
1410
|
-
raise FTPReplyError, resp
|
1411
|
-
end
|
1412
|
-
if m = /\(4,4,(?<host>\d+(?:,\d+){3}),2,(?<port>\d+,\d+)\)/.match(resp)
|
1413
|
-
return parse_pasv_ipv4_host(m["host"]), parse_pasv_port(m["port"])
|
1414
|
-
elsif m = /\(6,16,(?<host>\d+(?:,\d+){15}),2,(?<port>\d+,\d+)\)/.match(resp)
|
1415
|
-
return parse_pasv_ipv6_host(m["host"]), parse_pasv_port(m["port"])
|
1416
|
-
else
|
1417
|
-
raise FTPProtoError, resp
|
1418
|
-
end
|
1419
|
-
end
|
1420
|
-
private :parse228
|
1421
|
-
|
1422
1412
|
def parse_pasv_ipv4_host(s)
|
1423
1413
|
return s.tr(",", ".")
|
1424
1414
|
end
|
@@ -1466,6 +1456,13 @@ module Net
|
|
1466
1456
|
end
|
1467
1457
|
private :parse257
|
1468
1458
|
|
1459
|
+
#
|
1460
|
+
# Writes debug message to the debug output stream
|
1461
|
+
#
|
1462
|
+
def debug_print(msg)
|
1463
|
+
@debug_output << msg + "\n" if @debug_mode && @debug_output
|
1464
|
+
end
|
1465
|
+
|
1469
1466
|
# :stopdoc:
|
1470
1467
|
class NullSocket
|
1471
1468
|
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.3.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: 2023-12-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.5.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__)
|