net-sftp 2.0.5 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +2 -0
  3. data/.gitignore +5 -0
  4. data/.travis.yml +20 -0
  5. data/{CHANGELOG.rdoc → CHANGES.txt} +18 -0
  6. data/Gemfile +15 -0
  7. data/LICENSE.txt +19 -0
  8. data/README.rdoc +23 -1
  9. data/Rakefile +44 -21
  10. data/lib/net/sftp/operations/dir.rb +3 -3
  11. data/lib/net/sftp/operations/download.rb +8 -7
  12. data/lib/net/sftp/operations/file.rb +30 -8
  13. data/lib/net/sftp/operations/upload.rb +14 -6
  14. data/lib/net/sftp/session.rb +9 -7
  15. data/lib/net/sftp/version.rb +63 -13
  16. data/lib/net/sftp.rb +12 -4
  17. data/net-sftp-public_cert.pem +20 -0
  18. data/net-sftp.gemspec +38 -24
  19. data.tar.gz.sig +0 -0
  20. metadata +110 -127
  21. metadata.gz.sig +0 -0
  22. data/test/common.rb +0 -172
  23. data/test/protocol/01/test_attributes.rb +0 -97
  24. data/test/protocol/01/test_base.rb +0 -210
  25. data/test/protocol/01/test_name.rb +0 -27
  26. data/test/protocol/02/test_base.rb +0 -26
  27. data/test/protocol/03/test_base.rb +0 -27
  28. data/test/protocol/04/test_attributes.rb +0 -148
  29. data/test/protocol/04/test_base.rb +0 -74
  30. data/test/protocol/04/test_name.rb +0 -53
  31. data/test/protocol/05/test_base.rb +0 -62
  32. data/test/protocol/06/test_attributes.rb +0 -124
  33. data/test/protocol/06/test_base.rb +0 -51
  34. data/test/protocol/test_base.rb +0 -42
  35. data/test/test_all.rb +0 -7
  36. data/test/test_dir.rb +0 -47
  37. data/test/test_download.rb +0 -252
  38. data/test/test_file.rb +0 -159
  39. data/test/test_file_factory.rb +0 -48
  40. data/test/test_packet.rb +0 -9
  41. data/test/test_protocol.rb +0 -17
  42. data/test/test_request.rb +0 -71
  43. data/test/test_response.rb +0 -53
  44. data/test/test_session.rb +0 -741
  45. data/test/test_upload.rb +0 -219
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 64f5637e6c346349fb65a3346258e6a87d55219d651d3b48d042dde87d502099
4
+ data.tar.gz: e84621e188f86616e5a702650c2cb96210bc08d814c0c28c3cc8960dc042a73f
5
+ SHA512:
6
+ metadata.gz: 04252f3c3448dac1a637e9623ed2a5af6dbfb482d738ae407d44006c7c8d32b82a5ef4e477bb28ab6c666cf651349cf1ee685b58304073db03a3d7317a927ee7
7
+ data.tar.gz: 0da6c4055f0f7f488e772e3c4914fcabb2ea893823a9e0ad1ff5b12e0cbe7ad6c72f494c417a70f92c7989e26bff0f486628e17ad278d42a7f716b05267be8aa
checksums.yaml.gz.sig ADDED
@@ -0,0 +1,2 @@
1
+ P6ޝ1먨���_���jEZN+�zA�q�3v��(��d�7d� t���-=PV���V�c N �M§:�*�P���t\tQ$Q�m�u}?��Ry�R�,U�̜ojz�<�^�dbs7� �be ����]���&�We[$��1E�vOF6LN��o(/�X�.�)����)���ӂf��a������l����(�\_����\)6
2
+ Y�Ws�a![��5����+��A�4}����6���*Ȣ|�shG^�
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ pkg
2
+ doc
3
+ coverage
4
+ ri
5
+ *.swp
data/.travis.yml ADDED
@@ -0,0 +1,20 @@
1
+ language: ruby
2
+ sudo: false
3
+ rvm:
4
+ - 2.3.7
5
+ - 2.4.5
6
+ - 2.5.3
7
+ - 2.6.5
8
+ - 2.7.1
9
+ - ruby-head
10
+ - jruby-head
11
+ - rbx-3.107
12
+
13
+ install: gem install net-ssh test-unit mocha
14
+
15
+ script: rake test
16
+
17
+ matrix:
18
+ allow_failures:
19
+ - rvm: jruby-head
20
+ - rvm: rbx-3.107
@@ -1,3 +1,21 @@
1
+ === 3.0.0
2
+
3
+ * Pass protocol version via Net::SFTP.start [#107]
4
+ * Net-ssh 6.0 support [#106]
5
+
6
+ === 2.1.2 / 07 May 2013
7
+
8
+ * Fix fragmentation download failure [accardi]
9
+
10
+ === 2.1.0 / 06 Feb 2013
11
+
12
+ * Added public cert. All gem releases are now signed. See INSTALL in readme.
13
+ * Remove self-require, it causes a warning in Ruby 1.9.2. [jbarnette]
14
+ * Allow for upload to use the filename of the local file by default [czarneckid]
15
+ * Properly handle receiving less data than requested. [thedarkone]
16
+ * Added option to create directory on directory upload [Pablo Merino]
17
+ * Remove a warnings in tests [kachick]
18
+
1
19
 
2
20
  === 2.0.5 / 19 Aug 2010
3
21
 
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in mygem.gemspec
4
+ gemspec
5
+
6
+ # TODO: add to gemspec
7
+ gem "bundler", "~> 2.1"
8
+ gem "rake", "~> 12.0"
9
+
10
+ gem 'byebug', group: %i[development test] if !Gem.win_platform? && RUBY_ENGINE == "ruby"
11
+
12
+ if ENV["CI"]
13
+ gem 'codecov', require: false, group: :test
14
+ gem 'simplecov', require: false, group: :test
15
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,19 @@
1
+ Copyright © 2008 Jamis Buck
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the ‘Software’), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/README.rdoc CHANGED
@@ -1,6 +1,15 @@
1
1
  = Net::SFTP
2
2
 
3
- * http://net-ssh.rubyforge.org/sftp
3
+ <em><b>Please note: this project is in maintenance mode. It is not under active development but pull requests are very much welcome. Just be sure to include tests! -- delano</b></em>
4
+
5
+
6
+ * Docs: http://net-ssh.github.com/net-sftp
7
+ * Issues: https://github.com/net-ssh/net-sftp/issues
8
+ * Codes: https://github.com/net-ssh/net-sftp
9
+ * Email: net-ssh@solutious.com
10
+
11
+ <em>As of v2.1.0, all gem releases are signed. See INSTALL.</em>
12
+
4
13
 
5
14
  == DESCRIPTION:
6
15
 
@@ -63,6 +72,19 @@ If you wish to run the tests, you'll need:
63
72
 
64
73
  * gem install net-sftp (might need sudo privileges)
65
74
 
75
+ However, in order to be sure the code you're installing hasn't been tampered with, it's recommended that you verify the signature[http://docs.rubygems.org/read/chapter/21]. To do this, you need to add my public key as a trusted certificate (you only need to do this once):
76
+
77
+ # Add the public key as a trusted certificate
78
+ # (You only need to do this once)
79
+ $ curl -O https://raw.github.com/net-ssh/net-ssh/master/gem-public_cert.pem
80
+ $ gem cert --add gem-public_cert.pem
81
+
82
+ Then, when install the gem, do so with high security:
83
+
84
+ $ gem install net-sftp -P HighSecurity
85
+
86
+ If you don't add the public key, you'll see an error like "Couldn't verify data signature". If you're still having trouble let me know and I'll give you a hand.
87
+
66
88
  Or, if you prefer to do it the hard way (sans Rubygems):
67
89
 
68
90
  * tar xzf net-ssh-*.tgz
data/Rakefile CHANGED
@@ -1,30 +1,53 @@
1
- $LOAD_PATH.unshift "../net-ssh/lib"
2
- require './lib/net/sftp/version'
1
+ require "rubygems"
2
+ require "rake"
3
+ require "rake/clean"
4
+ require "rdoc/task"
5
+ require "bundler/gem_tasks"
3
6
 
4
- begin
5
- require 'echoe'
6
- rescue LoadError
7
- abort "You'll need to have `echoe' installed to use Net::SFTP's Rakefile"
7
+ desc "When releasing make sure NET_SSH_BUILDGEM_SIGNED is set"
8
+ task :check_NET_SSH_BUILDGEM_SIGNED do
9
+ raise "NET_SSH_BUILDGEM_SIGNED should be set to release" unless ENV['NET_SSH_BUILDGEM_SIGNED']
8
10
  end
9
11
 
10
- version = Net::SFTP::Version::STRING.dup
11
- if ENV['SNAPSHOT'].to_i == 1
12
- version << "." << Time.now.utc.strftime("%Y%m%d%H%M%S")
13
- end
12
+ Rake::Task[:release].enhance [:check_NET_SSH_BUILDGEM_SIGNED]
13
+ Rake::Task[:release].prerequisites.unshift(:check_NET_SSH_BUILDGEM_SIGNED)
14
14
 
15
- Echoe.new('net-sftp', version) do |p|
16
- p.project = "net-ssh"
17
- p.changelog = "CHANGELOG.rdoc"
15
+ task :default => ["build"]
16
+ CLEAN.include [ 'pkg', 'rdoc' ]
17
+ name = "net-sftp"
18
18
 
19
- p.author = "Jamis Buck"
20
- p.email = "netsftp@solutious.com"
21
- p.summary = "A pure Ruby implementation of the SFTP client protocol"
22
- p.url = "http://net-ssh.rubyforge.org/sftp"
19
+ require_relative "lib/net/sftp/version"
20
+ version = Net::SFTP::Version::CURRENT
23
21
 
24
- p.dependencies = ["net-ssh >=2.0.9"]
22
+ namespace :cert do
23
+ desc "Update public cert from private - only run if public is expired"
24
+ task :update_public_when_expired do
25
+ require 'openssl'
26
+ require 'time'
27
+ raw = File.read "net-sftp-public_cert.pem"
28
+ certificate = OpenSSL::X509::Certificate.new raw
29
+ raise Exception, "Not yet expired: #{certificate.not_after}" unless certificate.not_after < Time.now
30
+ sh "gem cert --build netssh@solutious.com --days 365*5 --private-key /mnt/gem/net-ssh-private_key.pem"
31
+ sh "mv gem-public_cert.pem net-sftp-public_cert.pem"
32
+ sh "gem cert --add net-sftp-public_cert.pem"
33
+ end
34
+ end
25
35
 
26
- p.need_zip = true
27
- p.include_rakefile = true
36
+ require 'rake/testtask'
37
+ Rake::TestTask.new do |t|
38
+ t.libs = ["lib", "test"]
39
+ end
28
40
 
29
- p.rdoc_pattern = /^(lib|README.rdoc|CHANGELOG.rdoc)/
41
+ extra_files = %w[LICENSE.txt THANKS.txt CHANGES.txt ]
42
+ RDoc::Task.new do |rdoc|
43
+ rdoc.rdoc_dir = "rdoc"
44
+ rdoc.title = "#{name} #{version}"
45
+ rdoc.generator = 'hanna' # gem install hanna-nouveau
46
+ rdoc.main = 'README.rdoc'
47
+ rdoc.rdoc_files.include("README*")
48
+ rdoc.rdoc_files.include("bin/*.rb")
49
+ rdoc.rdoc_files.include("lib/**/*.rb")
50
+ extra_files.each { |file|
51
+ rdoc.rdoc_files.include(file) if File.exist?(file)
52
+ }
30
53
  end
@@ -57,10 +57,10 @@ module Net; module SFTP; module Operations
57
57
  # it should be able to handle modest numbers of files in each directory.
58
58
  def glob(path, pattern, flags=0)
59
59
  flags |= ::File::FNM_PATHNAME
60
- path = path.chop if path[-1,1] == "/"
60
+ path = path.chop if path.end_with?('/') && path != '/'
61
61
 
62
62
  results = [] unless block_given?
63
- queue = entries(path).reject { |e| e.name == "." || e.name == ".." }
63
+ queue = entries(path).reject { |e| %w(. ..).include?(e.name) }
64
64
  while queue.any?
65
65
  entry = queue.shift
66
66
 
@@ -90,4 +90,4 @@ module Net; module SFTP; module Operations
90
90
  end
91
91
  end
92
92
 
93
- end; end; end
93
+ end; end; end
@@ -81,6 +81,7 @@ module Net; module SFTP; module Operations
81
81
  # puts "creating directory #{args[0]}"
82
82
  # when :finish then
83
83
  # puts "all done!"
84
+ # end
84
85
  # end
85
86
  #
86
87
  # However, for more complex implementations (e.g., GUI interfaces and such)
@@ -255,7 +256,7 @@ module Net; module SFTP; module Operations
255
256
  # operation was successful.
256
257
  def on_opendir(response)
257
258
  entry = response.request[:entry]
258
- raise "opendir #{entry.remote}: #{response}" unless response.ok?
259
+ raise StatusException.new(response, "opendir #{entry.remote}") unless response.ok?
259
260
  entry.handle = response[:handle]
260
261
  request = sftp.readdir(response[:handle], &method(:on_readdir))
261
262
  request[:parent] = entry
@@ -270,7 +271,7 @@ module Net; module SFTP; module Operations
270
271
  request = sftp.close(entry.handle, &method(:on_closedir))
271
272
  request[:parent] = entry
272
273
  elsif !response.ok?
273
- raise "readdir #{entry.remote}: #{response}"
274
+ raise StatusException.new(response, "readdir #{entry.remote}")
274
275
  else
275
276
  response[:names].each do |item|
276
277
  next if item.name == "." || item.name == ".."
@@ -296,7 +297,7 @@ module Net; module SFTP; module Operations
296
297
  def on_closedir(response)
297
298
  @active -= 1
298
299
  entry = response.request[:parent]
299
- raise "close #{entry.remote}: #{response}" unless response.ok?
300
+ raise StatusException.new(response, "close #{entry.remote}") unless response.ok?
300
301
  process_next_entry
301
302
  end
302
303
 
@@ -304,7 +305,7 @@ module Net; module SFTP; module Operations
304
305
  # to initiate the data transfer.
305
306
  def on_open(response)
306
307
  entry = response.request[:entry]
307
- raise "open #{entry.remote}: #{response}" unless response.ok?
308
+ raise StatusException.new(response, "open #{entry.remote}") unless response.ok?
308
309
 
309
310
  entry.handle = response[:handle]
310
311
  entry.sink = entry.local.respond_to?(:write) ? entry.local : ::File.open(entry.local, "wb")
@@ -318,7 +319,6 @@ module Net; module SFTP; module Operations
318
319
  request = sftp.read(entry.handle, entry.offset, read_size, &method(:on_read))
319
320
  request[:entry] = entry
320
321
  request[:offset] = entry.offset
321
- entry.offset += read_size
322
322
  end
323
323
 
324
324
  # Called when a read from a file finishes. If the read was successful
@@ -333,8 +333,9 @@ module Net; module SFTP; module Operations
333
333
  request = sftp.close(entry.handle, &method(:on_close))
334
334
  request[:entry] = entry
335
335
  elsif !response.ok?
336
- raise "read #{entry.remote}: #{response}"
336
+ raise StatusException.new(response, "read #{entry.remote}")
337
337
  else
338
+ entry.offset += response[:data].bytesize
338
339
  update_progress(:get, entry, response.request[:offset], response[:data])
339
340
  entry.sink.write(response[:data])
340
341
  download_next_chunk(entry)
@@ -345,7 +346,7 @@ module Net; module SFTP; module Operations
345
346
  def on_close(response)
346
347
  @active -= 1
347
348
  entry = response.request[:entry]
348
- raise "close #{entry.remote}: #{response}" unless response.ok?
349
+ raise StatusException.new(response, "close #{entry.remote}") unless response.ok?
349
350
  process_next_entry
350
351
  end
351
352
 
@@ -1,5 +1,4 @@
1
1
  require 'net/ssh/loggable'
2
- require 'net/sftp/operations/file'
3
2
 
4
3
  module Net; module SFTP; module Operations
5
4
 
@@ -82,21 +81,35 @@ module Net; module SFTP; module Operations
82
81
  # Reads up to the next instance of +sep_string+ in the stream, and
83
82
  # returns the bytes read (including +sep_string+). If +sep_string+ is
84
83
  # omitted, it defaults to +$/+. If EOF is encountered before any data
85
- # could be read, #gets will return +nil+.
86
- def gets(sep_string=$/)
87
- delim = if sep_string.length == 0
84
+ # could be read, #gets will return +nil+. If the first argument is an
85
+ # integer, or optional second argument is given, the returning string
86
+ # would not be longer than the given value in bytes.
87
+ def gets(sep_or_limit=$/, limit=Float::INFINITY)
88
+ if sep_or_limit.is_a? Integer
89
+ sep_string = $/
90
+ lim = sep_or_limit
91
+ else
92
+ sep_string = sep_or_limit
93
+ lim = limit
94
+ end
95
+
96
+ delim = if sep_string && sep_string.length == 0
88
97
  "#{$/}#{$/}"
89
98
  else
90
99
  sep_string
91
100
  end
92
101
 
93
102
  loop do
94
- at = @buffer.index(delim)
103
+ at = @buffer.index(delim) if delim
95
104
  if at
96
- offset = at + delim.length
105
+ offset = [at + delim.length, lim].min
97
106
  @pos += offset
98
107
  line, @buffer = @buffer[0,offset], @buffer[offset..-1]
99
108
  return line
109
+ elsif lim < @buffer.length
110
+ @pos += lim
111
+ line, @buffer = @buffer[0,lim], @buffer[lim..-1]
112
+ return line
100
113
  elsif !fill
101
114
  return nil if @buffer.empty?
102
115
  @pos += @buffer.length
@@ -108,8 +121,8 @@ module Net; module SFTP; module Operations
108
121
 
109
122
  # Same as #gets, but raises EOFError if EOF is encountered before any
110
123
  # data could be read.
111
- def readline(sep_string=$/)
112
- line = gets(sep_string)
124
+ def readline(sep_or_limit=$/, limit=Float::INFINITY)
125
+ line = gets(sep_or_limit, limit)
113
126
  raise EOFError if line.nil?
114
127
  return line
115
128
  end
@@ -132,6 +145,15 @@ module Net; module SFTP; module Operations
132
145
  nil
133
146
  end
134
147
 
148
+ def size
149
+ stat.size
150
+ end
151
+
152
+ # Resets position to beginning of file
153
+ def rewind
154
+ self.pos = 0
155
+ end
156
+
135
157
  # Writes each argument to the stream, appending a newline to any item
136
158
  # that does not already end in a newline. Array arguments are flattened.
137
159
  def puts(*items)
@@ -30,6 +30,9 @@ module Net; module SFTP; module Operations
30
30
  # This will upload "/path/to/directory", it's contents, it's subdirectories,
31
31
  # and their contents, recursively, to "/path/to/remote" on the remote server.
32
32
  #
33
+ # For uploading a directory without creating it, do
34
+ # sftp.upload!("/path/to/directory", "/path/to/remote", :mkdir => false)
35
+ #
33
36
  # If you want to send data to a file on the remote server, but the data is
34
37
  # in memory, you can pass an IO object and upload it's contents:
35
38
  #
@@ -157,15 +160,20 @@ module Net; module SFTP; module Operations
157
160
  @remote_cwd = remote
158
161
 
159
162
  @active += 1
160
- sftp.mkdir(remote) do |response|
161
- @active -= 1
162
- raise StatusException.new(response, "mkdir `#{remote}'") unless response.ok?
163
- (options[:requests] || RECURSIVE_READERS).to_i.times do
164
- break unless process_next_entry
163
+ if @options[:mkdir]
164
+ sftp.mkdir(remote) do |response|
165
+ @active -= 1
166
+ raise StatusException.new(response, "mkdir `#{remote}'") unless response.ok?
167
+ (options[:requests] || RECURSIVE_READERS).to_i.times do
168
+ break unless process_next_entry
169
+ end
165
170
  end
171
+ else
172
+ @active -= 1
173
+ process_next_entry
166
174
  end
167
175
  else
168
- raise ArgumentError, "expected a file to upload" unless local.respond_to?(:read) || ::File.exists?(local)
176
+ raise ArgumentError, "expected a file to upload" unless local.respond_to?(:read) || ::File.exist?(local)
169
177
  @stack = [[local]]
170
178
  process_next_entry
171
179
  end
@@ -75,11 +75,13 @@ module Net; module SFTP
75
75
  #
76
76
  # sftp = Net::SFTP::Session.new(ssh)
77
77
  # sftp.loop { sftp.opening? }
78
- def initialize(session, &block)
78
+ def initialize(session, version = nil, &block)
79
79
  @session = session
80
+ @version = version
80
81
  @input = Net::SSH::Buffer.new
81
82
  self.logger = session.logger
82
83
  @state = :closed
84
+ @pending_requests = {}
83
85
 
84
86
  connect(&block)
85
87
  end
@@ -94,19 +96,19 @@ module Net; module SFTP
94
96
  #
95
97
  # uploader = sftp.upload("/local/path", "/remote/path")
96
98
  # uploader.wait
97
- def upload(local, remote, options={}, &block)
99
+ def upload(local, remote = File.basename(local), options={}, &block)
98
100
  Operations::Upload.new(self, local, remote, options, &block)
99
101
  end
100
102
 
101
103
  # Identical to #upload, but blocks until the upload is complete.
102
- def upload!(local, remote, options={}, &block)
104
+ def upload!(local, remote = File.basename(local), options={}, &block)
103
105
  upload(local, remote, options, &block).wait
104
106
  end
105
107
 
106
108
  # Initiates a download from +remote+ to +local+, asynchronously. This
107
109
  # method will return a new Net::SFTP::Operations::Download instance, and requires
108
110
  # that the event loop be run in order for the download to progress. See
109
- # Net::SFTP::Operations::Download for a full discussion of hos this method can be
111
+ # Net::SFTP::Operations::Download for a full discussion of how this method can be
110
112
  # used.
111
113
  #
112
114
  # download = sftp.download("/remote/path", "/local/path")
@@ -876,7 +878,7 @@ module Net; module SFTP
876
878
  channel.on_close(&method(:when_channel_closed))
877
879
  channel.on_process(&method(:when_channel_polled))
878
880
 
879
- send_packet(FXP_INIT, :long, HIGHEST_PROTOCOL_VERSION_SUPPORTED)
881
+ send_packet(FXP_INIT, :long, @version || HIGHEST_PROTOCOL_VERSION_SUPPORTED)
880
882
  end
881
883
 
882
884
  # Called when the SSH server closes the underlying channel.
@@ -898,7 +900,7 @@ module Net; module SFTP
898
900
  @packet_length = input.read_long
899
901
  end
900
902
 
901
- return unless input.length >= @packet_length
903
+ return unless input.length >= @packet_length + 4
902
904
  packet = Net::SFTP::Packet.new(input.read(@packet_length))
903
905
  input.consume!
904
906
  @packet_length = nil
@@ -949,4 +951,4 @@ module Net; module SFTP
949
951
  end
950
952
  end
951
953
 
952
- end; end
954
+ end; end
@@ -1,18 +1,68 @@
1
- require 'net/ssh/version'
1
+ module Net
2
+ module SFTP
3
+ # A class for describing the current version of a library. The version
4
+ # consists of three parts: the +major+ number, the +minor+ number, and the
5
+ # +tiny+ (or +patch+) number.
6
+ #
7
+ # Two Version instances may be compared, so that you can test that a version
8
+ # of a library is what you require:
9
+ #
10
+ # require 'net/sftp/version'
11
+ #
12
+ # if Net::SFTP::Version::CURRENT < Net::SFTP::Version[2,1,0]
13
+ # abort "your software is too old!"
14
+ # end
15
+ class Version
16
+ include Comparable
2
17
 
3
- module Net; module SFTP
18
+ # A convenience method for instantiating a new Version instance with the
19
+ # given +major+, +minor+, and +tiny+ components.
20
+ def self.[](major, minor, tiny, pre = nil)
21
+ new(major, minor, tiny, pre)
22
+ end
4
23
 
5
- # Describes the current version of the Net::SFTP library.
6
- class Version < Net::SSH::Version
7
- MAJOR = 2
8
- MINOR = 0
9
- TINY = 5
24
+ attr_reader :major, :minor, :tiny
10
25
 
11
- # The current version, as a Version instance
12
- CURRENT = new(MAJOR, MINOR, TINY)
26
+ # Create a new Version object with the given components.
27
+ def initialize(major, minor, tiny, pre = nil)
28
+ @major, @minor, @tiny, @pre = major, minor, tiny, pre
29
+ end
13
30
 
14
- # The current version, as a String instance
15
- STRING = CURRENT.to_s
16
- end
31
+ # Compare this version to the given +version+ object.
32
+ def <=>(version)
33
+ to_i <=> version.to_i
34
+ end
35
+
36
+ # Converts this version object to a string, where each of the three
37
+ # version components are joined by the '.' character. E.g., 2.0.0.
38
+ def to_s
39
+ @to_s ||= [@major, @minor, @tiny, @pre].compact.join(".")
40
+ end
41
+
42
+ # Converts this version to a canonical integer that may be compared
43
+ # against other version objects.
44
+ def to_i
45
+ @to_i ||= @major * 1_000_000 + @minor * 1_000 + @tiny
46
+ end
47
+
48
+ # The major component of this version of the Net::SFTP library
49
+ MAJOR = 3
50
+
51
+ # The minor component of this version of the Net::SFTP library
52
+ MINOR = 0
17
53
 
18
- end; end
54
+ # The tiny component of this version of the Net::SFTP library
55
+ TINY = 0
56
+
57
+ # The prerelease component of this version of the Net::SFTP library
58
+ # nil allowed
59
+ PRE = nil
60
+
61
+ # The current version of the Net::SFTP library as a Version instance
62
+ CURRENT = new(*[MAJOR, MINOR, TINY, PRE].compact)
63
+
64
+ # The current version of the Net::SFTP library as a String
65
+ STRING = CURRENT.to_s
66
+ end
67
+ end
68
+ end
data/lib/net/sftp.rb CHANGED
@@ -27,9 +27,17 @@ module Net
27
27
  # Net::SFTP.start("localhost", "user") do |sftp|
28
28
  # sftp.upload! "/local/file.tgz", "/remote/file.tgz"
29
29
  # end
30
- def self.start(host, user, options={}, &block)
31
- session = Net::SSH.start(host, user, options)
32
- sftp = Net::SFTP::Session.new(session, &block).connect!
30
+ #
31
+ # Extra parameters can be passed:
32
+ # - The Net::SSH connection options (see Net::SSH for more information)
33
+ # - The Net::SFTP connection options (only :version is supported, to let you
34
+ # set the SFTP protocol version to be used)
35
+ def self.start(host, user, ssh_options={}, sftp_options={}, &block)
36
+ session = Net::SSH.start(host, user, ssh_options)
37
+ # We only use a single option here, but this leaves room for more later
38
+ # without breaking the external API.
39
+ version = sftp_options.fetch(:version, nil)
40
+ sftp = Net::SFTP::Session.new(session, version, &block).connect!
33
41
 
34
42
  if block_given?
35
43
  sftp.loop
@@ -56,7 +64,7 @@ class Net::SSH::Connection::Session
56
64
  # SSH session. Blocks until the SFTP session is fully open, and then
57
65
  # returns the SFTP session.
58
66
  #
59
- # Net::SSH.start("localhost", "user", "password") do |ssh|
67
+ # Net::SSH.start("localhost", "user", :password => "password") do |ssh|
60
68
  # ssh.sftp.upload!("/local/file.tgz", "/remote/file.tgz")
61
69
  # ssh.exec! "cd /some/path && tar xf /remote/file.tgz && rm /remote/file.tgz"
62
70
  # end
@@ -0,0 +1,20 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDQDCCAiigAwIBAgIBATANBgkqhkiG9w0BAQsFADAlMSMwIQYDVQQDDBpuZXRz
3
+ c2gvREM9c29sdXRpb3VzL0RDPWNvbTAeFw0yMDA0MjYwNjI0NTFaFw0yMTA0MjYw
4
+ NjI0NTFaMCUxIzAhBgNVBAMMGm5ldHNzaC9EQz1zb2x1dGlvdXMvREM9Y29tMIIB
5
+ IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxieE22fR/qmdPKUHyYTyUx2g
6
+ wskLwrCkxay+Tvc97ZZUOwf85LDDDPqhQaTWLvRwnIOMgQE2nBPzwalVclK6a+pW
7
+ x/18KDeZY15vm3Qn5p42b0wi9hUxOqPm3J2hdCLCcgtENgdX21nVzejn39WVqFJO
8
+ lntgSDNW5+kCS8QaRsmIbzj17GKKkrsw39kiQw7FhWfJFeTjddzoZiWwc59KA/Bx
9
+ fBbmDnsMLAtAtauMOxORrbx3EOY7sHku/kSrMg3FXFay7jc6BkbbUij+MjJ/k82l
10
+ 4o8o0YO4BAnya90xgEmgOG0LCCxRhuXQFnMDuDjK2XnUe0h4/6NCn94C+z9GsQID
11
+ AQABo3sweTAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUBfKiwO2e
12
+ M4NEiRrVG793qEPLYyMwHwYDVR0RBBgwFoEUbmV0c3NoQHNvbHV0aW91cy5jb20w
13
+ HwYDVR0SBBgwFoEUbmV0c3NoQHNvbHV0aW91cy5jb20wDQYJKoZIhvcNAQELBQAD
14
+ ggEBAHZOpj9ZNefc4eoie/20zX4iOgk3i+Rmjo04sMYWEtj0+4zLHXqSjune7+hd
15
+ ruP+u5xmEy9ueGQ/0kcLlDDM+8eQo6gjCY4GIQtwAzVLsUVeejE4291/GyfPf24v
16
+ 1dLWRtPwth0nyN5EOwOPqeiYiLAr5lO3wHTgfIgFhvdZpcXG8zB6JojuFJjDpKvO
17
+ HBV0P82HXjocnjusBt1YykGCvK4cDnaRruZJh6w2XeYQJJjlbqbDfBSQVesg97yM
18
+ bwwLGaqsVz0cC6q3EpU57oyyTu529o0HnDatc94Cz8t9p6ogkKtSM+jwsnnC6wmI
19
+ MMzdZVhRg3QdHAGYfd+TfsS3Mps=
20
+ -----END CERTIFICATE-----