rest-ftp-daemon-remote-sftp 0.0.1
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 +7 -0
- data/Gemfile +3 -0
- data/README.md +1 -0
- data/Rakefile +18 -0
- data/lib/plugins/rest-ftp-daemon/remote/remote_sftp.rb +158 -0
- data/rest-ftp-daemon-remote-s3.gemspec +32 -0
- metadata +138 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3bb96f905d1eb45cc56f7c8a8a62ef3e71eaf0ab
|
4
|
+
data.tar.gz: 1c4080c35b01ed4e06566a141baa14dce2518c36
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ff8c7a982685dae01ee53cd9aee901cf6a777b21278e217fd80f66361e2c8f729ccc08bec8f224276fbfcc3ea4a5105689c2a775a10a641d116fb0b3198bad76
|
7
|
+
data.tar.gz: 2d2a2046f30da6b2e2aa93012f7253626b222bf40e7405f6f2b0f88727e76df78519ce67278e67d2d8cdcd3cc02dca3453cc1158b15583707207cc48c05ccf7e
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# rest-ftp-daemon-remote-sftp
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
require "rubygems"
|
4
|
+
|
5
|
+
require "rspec/core/rake_task"
|
6
|
+
RSpec::Core::RakeTask.new(:spec)
|
7
|
+
|
8
|
+
require "rubocop/rake_task"
|
9
|
+
RuboCop::RakeTask.new(:rubocop) do |task|
|
10
|
+
task.fail_on_error = false
|
11
|
+
end
|
12
|
+
|
13
|
+
# Load my own tasks
|
14
|
+
Dir.glob('lib/tasks/*.rake').each { |r| import r }
|
15
|
+
|
16
|
+
# Run specs by default
|
17
|
+
desc "Run all tests"
|
18
|
+
task default: [:spec, :rubocop]
|
@@ -0,0 +1,158 @@
|
|
1
|
+
# Dependencies
|
2
|
+
require "net/sftp"
|
3
|
+
require "rbnacl"
|
4
|
+
require "bcrypt_pbkdf"
|
5
|
+
|
6
|
+
# Register this handler
|
7
|
+
module URI
|
8
|
+
class SFTP < Generic
|
9
|
+
DEFAULT_PORT = 22
|
10
|
+
end
|
11
|
+
@@schemes["SFTP"] = SFTP
|
12
|
+
end
|
13
|
+
|
14
|
+
# Handle sFTP transfers for Remote class
|
15
|
+
module RestFtpDaemon::Remote
|
16
|
+
class RemoteSFTP < RemoteBase
|
17
|
+
|
18
|
+
# Class options
|
19
|
+
attr_reader :sftp
|
20
|
+
|
21
|
+
# URI schemes handled by this plugin
|
22
|
+
def self.handles
|
23
|
+
[URI::SFTP]
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize target, job, config
|
27
|
+
# Call daddy's initialize() first
|
28
|
+
super
|
29
|
+
end
|
30
|
+
|
31
|
+
def connect
|
32
|
+
super
|
33
|
+
|
34
|
+
# Debug level
|
35
|
+
if debug_enabled
|
36
|
+
verbosity = Logger::DEBUG
|
37
|
+
else
|
38
|
+
verbosity = false
|
39
|
+
end
|
40
|
+
|
41
|
+
# Connect remote server
|
42
|
+
@sftp = Net::SFTP.start(@target.host.to_s, @target.user.to_s,
|
43
|
+
password: @target.password.to_s,
|
44
|
+
verbose: verbosity,
|
45
|
+
port: @target.port,
|
46
|
+
non_interactive: true,
|
47
|
+
timeout: DEFAULT_SFTP_TIMEOUT
|
48
|
+
)
|
49
|
+
# rescue NotImplementedError => exception
|
50
|
+
# raise RemoteConnectError, "RemoteConnectError: #{exception.class}: #{exception.message}"
|
51
|
+
|
52
|
+
rescue Exception => exception
|
53
|
+
raise RemoteConnectError, "#{exception.class}: #{exception.message}"
|
54
|
+
end
|
55
|
+
|
56
|
+
def size_if_exists target
|
57
|
+
log_debug "size_if_exists [#{target.name}]"
|
58
|
+
stat = @sftp.stat! target.path_abs
|
59
|
+
|
60
|
+
rescue Net::SFTP::StatusException
|
61
|
+
return false
|
62
|
+
else
|
63
|
+
return stat.size
|
64
|
+
end
|
65
|
+
|
66
|
+
def remote_try_delete target
|
67
|
+
log_debug "remote_try_delete [#{target.name}]"
|
68
|
+
@sftp.remove target.path_abs
|
69
|
+
|
70
|
+
rescue Net::SFTP::StatusException
|
71
|
+
log_debug "#{LOG_INDENT}[#{target.name}] file not found"
|
72
|
+
else
|
73
|
+
log_debug "#{LOG_INDENT}[#{target.name}] removed"
|
74
|
+
end
|
75
|
+
|
76
|
+
def mkdir directory
|
77
|
+
log_debug "mkdir [#{directory}]"
|
78
|
+
@sftp.mkdir! directory
|
79
|
+
|
80
|
+
rescue StandardError => ex
|
81
|
+
raise TargetPermissionError, ex.message
|
82
|
+
end
|
83
|
+
|
84
|
+
def chdir_or_create directory, mkdir = false
|
85
|
+
# Init, extract my parent name and my own name
|
86
|
+
log_debug "chdir_or_create mkdir[#{mkdir}] dir[#{directory}]"
|
87
|
+
parent, _current = split_path(directory)
|
88
|
+
|
89
|
+
# Access this directory
|
90
|
+
begin
|
91
|
+
@sftp.opendir! directory
|
92
|
+
|
93
|
+
rescue Net::SFTP::StatusException => _e
|
94
|
+
# If not allowed to create path, that's over, we're stuck
|
95
|
+
return false unless mkdir
|
96
|
+
|
97
|
+
# Recurse upward
|
98
|
+
chdir_or_create parent, mkdir
|
99
|
+
|
100
|
+
# Now I was able to chdir into my parent, create the current directory
|
101
|
+
mkdir directory
|
102
|
+
|
103
|
+
# Finally retry the chdir
|
104
|
+
retry
|
105
|
+
else
|
106
|
+
return true
|
107
|
+
end
|
108
|
+
|
109
|
+
# We should never get here
|
110
|
+
raise JobTargetShouldBeDirectory
|
111
|
+
end
|
112
|
+
|
113
|
+
def push source, target, &callback
|
114
|
+
# Push init
|
115
|
+
raise RestFtpDaemon::AssertionFailed, "push/sftp" if @sftp.nil?
|
116
|
+
|
117
|
+
# Do the transfer
|
118
|
+
@sftp.upload! source.path_abs, target.path_abs do |event, _uploader, *args|
|
119
|
+
case event
|
120
|
+
when :open then
|
121
|
+
# args[0] : file metadata
|
122
|
+
when :put then
|
123
|
+
# args[0] : file metadata
|
124
|
+
# args[1] : byte offset in remote file
|
125
|
+
# args[2] : data being written (as string)
|
126
|
+
# puts "writing #{args[2].length} bytes to #{args[0].remote} starting at #{args[1]}"
|
127
|
+
|
128
|
+
# Update job status after this block transfer
|
129
|
+
yield args[2].length, target.name
|
130
|
+
|
131
|
+
when :close then
|
132
|
+
# args[0] : file metadata
|
133
|
+
when :mkdir
|
134
|
+
# args[0] : remote path name
|
135
|
+
when :finish
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def move source, target
|
142
|
+
@sftp.rename! source.path_abs, target.path_abs, 0x00000001
|
143
|
+
end
|
144
|
+
|
145
|
+
def close
|
146
|
+
log_debug "remote close"
|
147
|
+
end
|
148
|
+
|
149
|
+
def connected?
|
150
|
+
@sftp && !@sftp.closed?
|
151
|
+
end
|
152
|
+
|
153
|
+
def debug_enabled
|
154
|
+
@config[:debug_sftp]
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
Gem::Specification.new do |spec|
|
3
|
+
|
4
|
+
# Project version
|
5
|
+
spec.version = "0.0.1"
|
6
|
+
|
7
|
+
# Project description
|
8
|
+
spec.name = "rest-ftp-daemon-remote-sftp"
|
9
|
+
spec.authors = ["Bruno MEDICI"]
|
10
|
+
spec.email = "rftpd-project@bmconseil.com"
|
11
|
+
spec.description = "rest-ftp-daemon plugin: sFTP"
|
12
|
+
spec.summary = "rest-ftp-daemon plugin: transfer files with sFTP"
|
13
|
+
spec.homepage = "http://github.com/bmedici/#{spec.name}"
|
14
|
+
spec.licenses = ["MIT"]
|
15
|
+
spec.date = Time.now.strftime("%Y-%m-%d")
|
16
|
+
|
17
|
+
# List files and executables
|
18
|
+
spec.files = `git ls-files -z`.split("\x0")
|
19
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
spec.required_ruby_version = ">= 2.3"
|
22
|
+
|
23
|
+
# Runtime dependencies
|
24
|
+
spec.add_runtime_dependency "net-sftp"
|
25
|
+
spec.add_runtime_dependency "rbnacl", '>= 3.2', '< 5.0'
|
26
|
+
spec.add_runtime_dependency "rbnacl-libsodium"
|
27
|
+
spec.add_runtime_dependency "bcrypt_pbkdf"
|
28
|
+
|
29
|
+
# Development dependencies
|
30
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
31
|
+
spec.add_development_dependency "rake"
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rest-ftp-daemon-remote-sftp
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Bruno MEDICI
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-07-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: net-sftp
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rbnacl
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.2'
|
34
|
+
- - "<"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '5.0'
|
37
|
+
type: :runtime
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '3.2'
|
44
|
+
- - "<"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '5.0'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rbnacl-libsodium
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: bcrypt_pbkdf
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
type: :runtime
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: bundler
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '1.6'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '1.6'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: rake
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
description: 'rest-ftp-daemon plugin: sFTP'
|
104
|
+
email: rftpd-project@bmconseil.com
|
105
|
+
executables: []
|
106
|
+
extensions: []
|
107
|
+
extra_rdoc_files: []
|
108
|
+
files:
|
109
|
+
- Gemfile
|
110
|
+
- README.md
|
111
|
+
- Rakefile
|
112
|
+
- lib/plugins/rest-ftp-daemon/remote/remote_sftp.rb
|
113
|
+
- rest-ftp-daemon-remote-s3.gemspec
|
114
|
+
homepage: http://github.com/bmedici/rest-ftp-daemon-remote-sftp
|
115
|
+
licenses:
|
116
|
+
- MIT
|
117
|
+
metadata: {}
|
118
|
+
post_install_message:
|
119
|
+
rdoc_options: []
|
120
|
+
require_paths:
|
121
|
+
- lib
|
122
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '2.3'
|
127
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
requirements: []
|
133
|
+
rubyforge_project:
|
134
|
+
rubygems_version: 2.5.1
|
135
|
+
signing_key:
|
136
|
+
specification_version: 4
|
137
|
+
summary: 'rest-ftp-daemon plugin: transfer files with sFTP'
|
138
|
+
test_files: []
|