You've already forked OpenIntegrations
mirror of
https://github.com/Bayselonarrend/OpenIntegrations.git
synced 2025-10-08 22:51:57 +02:00
Доработка тестов, рефакторинг SFTP
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
"MAIN ---"
|
||||
linux-vdso.so.1 (0x00007ffe131f6000)
|
||||
libssl.so.3 => /lib64/libssl.so.3 (0x00007fda26200000)
|
||||
libcrypto.so.3 => /lib64/libcrypto.so.3 (0x00007fda25a00000)
|
||||
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fda25600000)
|
||||
libc.so.6 => /lib64/libc.so.6 (0x00007fda25200000)
|
||||
libdl.so.2 => /lib64/libdl.so.2 (0x00007fda24e00000)
|
||||
/lib64/ld-linux-x86-64.so.2 (0x00007fda26600000)
|
||||
libz.so.1 => /lib64/libz.so.1 (0x00007fda24a00000)
|
||||
linux-vdso.so.1 (0x00007fff486f1000)
|
||||
libssl.so.3 => /lib64/libssl.so.3 (0x00007bad3de00000)
|
||||
libcrypto.so.3 => /lib64/libcrypto.so.3 (0x00007bad3d600000)
|
||||
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007bad3d200000)
|
||||
libc.so.6 => /lib64/libc.so.6 (0x00007bad3ce00000)
|
||||
libdl.so.2 => /lib64/libdl.so.2 (0x00007bad3ca00000)
|
||||
/lib64/ld-linux-x86-64.so.2 (0x00007bad3e200000)
|
||||
libz.so.1 => /lib64/libz.so.1 (0x00007bad3c600000)
|
||||
GLIBC_2.2.5
|
||||
GLIBC_2.3
|
||||
GLIBC_2.3.4
|
||||
|
@@ -1,15 +1,12 @@
|
||||
mod methods;
|
||||
mod ssh_settings;
|
||||
mod sftp;
|
||||
mod sftp_methods;
|
||||
mod ssh_methods;
|
||||
|
||||
use std::io::Read;
|
||||
use std::path::Path;
|
||||
use addin1c::{name, Variant};
|
||||
use serde_json::json;
|
||||
use crate::core::getset;
|
||||
use ssh2::{MethodType, Session, Sftp};
|
||||
use crate::component::ssh_settings::{SshAuthTypes, SshConf};
|
||||
use common_tcp::tcp_establish::create_tcp_connection;
|
||||
use ssh2::{Session, Sftp};
|
||||
use crate::component::ssh_settings::SshConf;
|
||||
|
||||
// МЕТОДЫ КОМПОНЕНТЫ -------------------------------------------------------------------------------
|
||||
|
||||
@@ -28,7 +25,9 @@ pub const METHODS: &[&[u16]] = &[
|
||||
name!("UploadFile"),
|
||||
name!("UploadData"),
|
||||
name!("RemoveFile"),
|
||||
name!("IsSFTP")
|
||||
name!("IsSFTP"),
|
||||
name!("DownloadToFile"),
|
||||
name!("DownloadToBuffer"),
|
||||
];
|
||||
|
||||
// Число параметров функций компоненты
|
||||
@@ -48,6 +47,8 @@ pub fn get_params_amount(num: usize) -> usize {
|
||||
11 => 2,
|
||||
12 => 1,
|
||||
13 => 0,
|
||||
14 => 2,
|
||||
15 => 1,
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
@@ -118,6 +119,22 @@ pub fn cal_func(obj: &mut AddIn, num: usize, params: &mut [Variant]) -> Box<dyn
|
||||
},
|
||||
13 => {
|
||||
Box::new(obj.sftp.is_some())
|
||||
},
|
||||
14 => {
|
||||
|
||||
let path = params[0].get_string().unwrap_or("".to_string());
|
||||
let filepath = params[1].get_string().unwrap_or("".to_string());
|
||||
|
||||
Box::new(obj.download_to_file(&path, &filepath))
|
||||
},
|
||||
|
||||
15 => {
|
||||
let path = params[0].get_string().unwrap_or("".to_string());
|
||||
|
||||
match obj.download_to_vec(&path) {
|
||||
Ok(v) => Box::new(v),
|
||||
Err(e) => Box::new(e)
|
||||
}
|
||||
}
|
||||
_ => Box::new(false), // Неверный номер команды
|
||||
}
|
||||
@@ -138,7 +155,7 @@ pub struct AddIn {
|
||||
}
|
||||
|
||||
impl AddIn {
|
||||
/// Создает новый объект
|
||||
|
||||
pub fn new() -> Self {
|
||||
AddIn {
|
||||
inner: None,
|
||||
@@ -147,285 +164,6 @@ impl AddIn {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_settings(&mut self, settings: String) -> String{
|
||||
|
||||
let mut conf = self.conf.take().unwrap_or_else(|| SshConf::new());
|
||||
|
||||
match conf.set_settings(settings) {
|
||||
Ok(_) => {
|
||||
self.conf = Some(conf);
|
||||
json!({"result": true}).to_string()
|
||||
},
|
||||
Err(e) => format_json_error(&e),
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn set_proxy(&mut self, proxy: String) -> String{
|
||||
|
||||
let mut conf = self.conf.take().unwrap_or_else(|| SshConf::new());
|
||||
|
||||
match conf.set_proxy(proxy) {
|
||||
Ok(_) => {
|
||||
self.conf = Some(conf);
|
||||
json!({"result": true}).to_string()
|
||||
},
|
||||
Err(e) => format_json_error(&e),
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn initialize(&mut self) -> String {
|
||||
|
||||
let conf_data = match &self.conf{
|
||||
Some(conf_data) => conf_data,
|
||||
None => return format_json_error("No configuration found")
|
||||
};
|
||||
|
||||
let settings = match &conf_data.set {
|
||||
Some(settings) => settings,
|
||||
None => return format_json_error("No settings found")
|
||||
};
|
||||
|
||||
let username= &settings.username;
|
||||
let password = settings.password.as_deref().unwrap_or("");
|
||||
let passphrase = &settings.passphrase;
|
||||
let key_path = &settings.key_path;
|
||||
let pub_path = &settings.pub_path;
|
||||
let proxy = &conf_data.proxy;
|
||||
|
||||
let tcp = match create_tcp_connection(&settings.host, settings.port, proxy){
|
||||
Ok(tcp) => tcp,
|
||||
Err(e) => return format_json_error(format!("TCP error: {}", e.to_string()).as_str())
|
||||
};
|
||||
|
||||
ssh2::init();
|
||||
|
||||
let mut identities = vec![];
|
||||
let methods;
|
||||
let banner;
|
||||
let kex;
|
||||
|
||||
let mut sess = match Session::new(){
|
||||
Ok(sess) => {
|
||||
methods = sess.auth_methods(username).unwrap_or("").to_string();
|
||||
banner = sess.banner().unwrap_or("").to_string();
|
||||
kex = sess.methods(MethodType::Kex).unwrap_or("").to_string();
|
||||
|
||||
sess
|
||||
},
|
||||
Err(e) => return format_json_error(format!("Session error: {}", e.to_string()).as_str())
|
||||
};
|
||||
|
||||
match sess.agent(){
|
||||
Ok(agent) => {
|
||||
match agent.identities(){
|
||||
Ok(idents) => {
|
||||
for ident in idents{
|
||||
identities.push(ident.comment().to_string());
|
||||
}
|
||||
}
|
||||
Err(e) => identities.push(e.to_string())
|
||||
}
|
||||
}
|
||||
Err(e) => identities.push(e.to_string())
|
||||
};
|
||||
|
||||
sess.set_tcp_stream(tcp);
|
||||
|
||||
if let Err(e) = sess.handshake() {
|
||||
return json!({
|
||||
"result": false,
|
||||
"error": format!("Handshake error: {}", e.to_string()),
|
||||
"identities": identities,
|
||||
"methods": methods,
|
||||
"banner": banner,
|
||||
"kex_methods": kex
|
||||
}).to_string();
|
||||
};
|
||||
|
||||
let auth_success = match settings.auth_type {
|
||||
|
||||
SshAuthTypes::Password => sess.userauth_password(username, password),
|
||||
SshAuthTypes::Agent => sess.userauth_agent(username),
|
||||
SshAuthTypes::PrivateKey => {
|
||||
|
||||
let path = match key_path{
|
||||
Some(key_path) => key_path.as_ref(),
|
||||
None => return format_json_error("No key path provided with PK auth type")
|
||||
};
|
||||
|
||||
let pub_path = match pub_path{
|
||||
Some(pub_path) => Some(Path::new(pub_path)),
|
||||
None => None
|
||||
};
|
||||
|
||||
sess.userauth_pubkey_file(username, pub_path, path, passphrase.as_deref())
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
if let Err(e) = auth_success{
|
||||
return format_json_error(format!("Auth error: {}", e.to_string()).as_str());
|
||||
};
|
||||
|
||||
if !sess.authenticated(){
|
||||
return format_json_error("Authentication failed with no errors");
|
||||
}
|
||||
|
||||
self.inner = Some(sess);
|
||||
|
||||
json!({"result": true}).to_string()
|
||||
|
||||
}
|
||||
|
||||
pub fn execute(&self, command: &str) -> String {
|
||||
|
||||
let session = match &self.inner{
|
||||
Some(sess) => sess,
|
||||
None => return format_json_error("No session"),
|
||||
};
|
||||
|
||||
let mut channel = match session.channel_session(){
|
||||
Ok(channel) => channel,
|
||||
Err(e) => return format_json_error(&e.to_string())
|
||||
};
|
||||
|
||||
if let Err(e) = channel.exec(command){
|
||||
return format_json_error(&e.to_string());
|
||||
};
|
||||
|
||||
let mut stdout = String::new();
|
||||
if let Err(e) = channel.read_to_string(&mut stdout).map_err(|e| e.to_string()){
|
||||
stdout = e.to_string();
|
||||
};
|
||||
|
||||
let mut stderr = String::new();
|
||||
if let Err(e) = channel.stderr().read_to_string(&mut stderr).map_err(|e| e.to_string()){
|
||||
stderr = e.to_string();
|
||||
};
|
||||
|
||||
let exit_code = match channel.wait_close(){
|
||||
Ok(_) => channel.exit_status().map_err(|e| e.to_string()),
|
||||
Err(e) => Err(e.to_string())
|
||||
};
|
||||
|
||||
let code = match exit_code{
|
||||
Ok(code) => code.to_string(),
|
||||
Err(e) => e.to_string()
|
||||
};
|
||||
|
||||
json!({"result": true, "exit_code": code, "stdout": stdout, "stderr": stderr}).to_string()
|
||||
|
||||
}
|
||||
|
||||
pub fn get_configuration(&mut self) -> String{
|
||||
|
||||
let conf = match &self.conf{
|
||||
Some(conf) => conf,
|
||||
None => return format_json_error("No configuration found")
|
||||
};
|
||||
|
||||
json!({"result": true, "conf": conf}).to_string()
|
||||
}
|
||||
|
||||
// SFTP
|
||||
|
||||
pub fn make_sftp(&mut self) -> String {
|
||||
match &self.inner{
|
||||
Some(sess) => {
|
||||
self.sftp = match sftp::make_sftp(sess){
|
||||
Ok(sftp) => Some(sftp),
|
||||
Err(e) => return e.to_string()
|
||||
};
|
||||
json!({"result": true}).to_string()
|
||||
},
|
||||
None => json!({"result": false, "error": "Init SSH connection first"}).to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_directory(&mut self, path: &str, mode: i32) -> String {
|
||||
match &self.sftp{
|
||||
Some(s) => {
|
||||
match sftp::make_directory(s, path, mode){
|
||||
Ok(_) => json!({"result": true}).to_string(),
|
||||
Err(e) => format_json_error(&e.to_string())
|
||||
}
|
||||
},
|
||||
None => json!({"result": false, "error": "Init SFTP first"}).to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove_directory(&mut self, path: &str) -> String {
|
||||
match &self.sftp{
|
||||
Some(s) => {
|
||||
match sftp::remove_directory(s, path){
|
||||
Ok(_) => json!({"result": true}).to_string(),
|
||||
Err(e) => format_json_error(&e.to_string())
|
||||
}
|
||||
},
|
||||
None => json!({"result": false, "error": "Init SFTP first"}).to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn list_directory(&mut self, path: &str) -> String {
|
||||
match &self.sftp{
|
||||
Some(s) => {
|
||||
match sftp::list_directory(s, path){
|
||||
Ok(d) => json!({"result": true, "data": d}).to_string(),
|
||||
Err(e) => format_json_error(&e.to_string())
|
||||
}
|
||||
},
|
||||
None => json!({"result": false, "error": "Init SFTP first"}).to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn upload_file(&mut self, file: &str, path: &str) -> String {
|
||||
|
||||
match &self.sftp{
|
||||
Some(s) => {
|
||||
match sftp::upload_file(s, file, path){
|
||||
Ok(d) => json!({"result": true, "bytes": d}).to_string(),
|
||||
Err(e) => format_json_error(&e.to_string())
|
||||
}
|
||||
},
|
||||
None => json!({"result": false, "error": "Init SFTP first"}).to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn upload_data(&mut self, data: &[u8], path: &str) -> String {
|
||||
match &self.sftp{
|
||||
Some(s) => {
|
||||
match sftp::upload_data(s, data, path){
|
||||
Ok(d) => json!({"result": true, "bytes": d}).to_string(),
|
||||
Err(e) => format_json_error(&e.to_string())
|
||||
}
|
||||
},
|
||||
None => json!({"result": false, "error": "Init SFTP first"}).to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delete_file(&mut self, path: &str) -> String {
|
||||
match &self.sftp{
|
||||
Some(s) => {
|
||||
match sftp::remove_file(s, path){
|
||||
Ok(_) => json!({"result": true}).to_string(),
|
||||
Err(e) => format_json_error(&e.to_string())
|
||||
}
|
||||
},
|
||||
None => json!({"result": false, "error": "Init SFTP first"}).to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn disconnect(&mut self) -> String{
|
||||
if let Some(_conn) = self.inner.take() {
|
||||
self.sftp.take();
|
||||
json!({"result": true}).to_string()
|
||||
} else {
|
||||
json!({"result": false, "error": "No session"}).to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_field_ptr(&self, index: usize) -> *const dyn getset::ValueType {
|
||||
match index {
|
||||
_ => panic!("Index out of bounds"),
|
||||
@@ -442,7 +180,6 @@ pub fn format_json_error(error: &str) -> String {
|
||||
|
||||
// УНИЧТОЖЕНИЕ ОБЪЕКТА -----------------------------------------------------------------------------
|
||||
|
||||
// Обработка удаления объекта
|
||||
impl Drop for AddIn {
|
||||
fn drop(&mut self) {}
|
||||
}
|
@@ -1,110 +0,0 @@
|
||||
use std::io::{BufReader, Cursor, Read, copy};
|
||||
use serde_json::{json, Value};
|
||||
use ssh2::{Session, Sftp};
|
||||
|
||||
pub fn make_sftp(session: &Session) -> Result<Sftp, String> {
|
||||
session.sftp().map_err( |err| err.to_string() )
|
||||
}
|
||||
|
||||
pub fn make_directory(sftp: &Sftp, path: &str, mode: i32) -> Result<(), String> {
|
||||
let mode_oct = oct(mode)?;
|
||||
sftp.mkdir(path.as_ref(), mode_oct).map_err(|err| err.to_string())
|
||||
}
|
||||
|
||||
pub fn remove_directory(sftp: &Sftp, path: &str) -> Result<(), String> {
|
||||
sftp.rmdir(path.as_ref()).map_err(|err| err.to_string())
|
||||
}
|
||||
|
||||
pub fn list_directory(sftp: &Sftp, path: &str) -> Result<Vec<Value>, String> {
|
||||
|
||||
let mut data = vec![];
|
||||
|
||||
match sftp.readdir(path) {
|
||||
Ok(contents) => {
|
||||
for item in contents {
|
||||
|
||||
let object_pb = item.0;
|
||||
let object_path = object_pb.to_str().unwrap_or("").to_string();
|
||||
let object_info = &item.1;
|
||||
let object_perm = object_info.perm.unwrap_or(0);
|
||||
|
||||
let object_filename = object_pb
|
||||
.file_name()
|
||||
.unwrap_or("".as_ref())
|
||||
.to_str()
|
||||
.unwrap_or("")
|
||||
.to_string();
|
||||
|
||||
let object_ext = object_pb
|
||||
.extension()
|
||||
.unwrap_or("".as_ref())
|
||||
.to_str()
|
||||
.unwrap_or("")
|
||||
.to_string();
|
||||
|
||||
data.push(json!({
|
||||
"uid": object_info.uid,
|
||||
"gid": object_info.gid,
|
||||
"is_directory": is_directory(object_perm),
|
||||
"is_symlink": object_pb.is_symlink(),
|
||||
"modified": object_info.mtime,
|
||||
"accessed": object_info.atime,
|
||||
"name": object_filename,
|
||||
"size": object_info.size,
|
||||
"path": object_path,
|
||||
"permissions": format!("{:o}", object_perm),
|
||||
"extension": object_ext,
|
||||
}));
|
||||
}
|
||||
|
||||
Ok(data)
|
||||
},
|
||||
Err(err) => Err(err.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn upload_data(sftp: &Sftp, data: &[u8], path: &str) -> Result<u64, String> {
|
||||
let mut cursor = Cursor::new(data);
|
||||
upload_from_reader(sftp, path, &mut cursor)
|
||||
}
|
||||
|
||||
pub fn upload_file(sftp: &Sftp, filepath: &str, path: &str) -> Result<u64, String> {
|
||||
|
||||
let file = match std::fs::File::open(filepath) {
|
||||
Ok(f) => f,
|
||||
Err(e) => return Err(format!("File error: {}", e))
|
||||
};
|
||||
|
||||
let mut buf_reader = BufReader::new(file);
|
||||
|
||||
upload_from_reader(sftp, path, &mut buf_reader)
|
||||
|
||||
}
|
||||
|
||||
pub fn remove_file(sftp: &Sftp, path: &str) -> Result<(), String> {
|
||||
sftp.unlink(path.as_ref()).map_err(|err| err.to_string())
|
||||
}
|
||||
|
||||
fn is_directory(mode: u32) -> bool {
|
||||
const S_IFMT: u32 = 0o170000; // маска типа файла
|
||||
const S_IFDIR: u32 = 0o040000; // биты для каталога
|
||||
(mode & S_IFMT) == S_IFDIR
|
||||
}
|
||||
|
||||
fn oct(o: i32) -> Result<i32, String> {
|
||||
i32::from_str_radix(&o.to_string(), 8).map_err(|err| err.to_string())
|
||||
}
|
||||
|
||||
fn upload_from_reader<R: Read>(sftp: &Sftp, path: &str, reader: &mut R) -> Result<u64, String> {
|
||||
|
||||
let mut remote = match sftp.create(path.as_ref()) {
|
||||
Ok(remote) => remote,
|
||||
Err(e) => return Err(format!("File access error: {}", e))
|
||||
};
|
||||
|
||||
match copy(reader, &mut remote) {
|
||||
Ok(b) => Ok(b),
|
||||
Err(e) => Err(format!("Upload error: {}", &e.to_string()))
|
||||
}
|
||||
|
||||
}
|
233
src/addins/ssh/src/component/sftp_methods.rs
Normal file
233
src/addins/ssh/src/component/sftp_methods.rs
Normal file
@@ -0,0 +1,233 @@
|
||||
use std::io::{BufReader, Cursor, Read, copy, Write};
|
||||
use std::path::Path;
|
||||
use serde_json::{json};
|
||||
use ssh2::{Sftp};
|
||||
use crate::component::{AddIn};
|
||||
use crate::component::format_json_error;
|
||||
|
||||
impl AddIn{
|
||||
|
||||
pub fn make_sftp(&mut self) -> String {
|
||||
match &self.inner{
|
||||
Some(sess) => {
|
||||
|
||||
let result = sess.sftp().map_err( |err| err.to_string() );
|
||||
|
||||
self.sftp = match result{
|
||||
Ok(sftp) => Some(sftp),
|
||||
Err(e) => return e.to_string()
|
||||
};
|
||||
json!({"result": true}).to_string()
|
||||
},
|
||||
None => json!({"result": false, "error": "Init SSH connection first"}).to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_directory(&mut self, path: &str, mode: i32) -> String {
|
||||
match &self.sftp{
|
||||
Some(s) => {
|
||||
|
||||
let mode_oct = match oct(mode){
|
||||
Ok(mode) => mode,
|
||||
Err(e) => return format_json_error(&e.to_string())
|
||||
};
|
||||
|
||||
let result = s.mkdir(path.as_ref(), mode_oct).map_err(|err| err.to_string());
|
||||
|
||||
match result{
|
||||
Ok(_) => json!({"result": true}).to_string(),
|
||||
Err(e) => format_json_error(&e.to_string())
|
||||
}
|
||||
},
|
||||
None => json!({"result": false, "error": "Init SFTP first"}).to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove_directory(&mut self, path: &str) -> String {
|
||||
match &self.sftp{
|
||||
Some(s) => {
|
||||
match s.rmdir(path.as_ref()) {
|
||||
Ok(_) => json!({"result": true}).to_string(),
|
||||
Err(e) => format_json_error(&e.to_string())
|
||||
}
|
||||
},
|
||||
None => json!({"result": false, "error": "Init SFTP first"}).to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn list_directory(&mut self, path: &str) -> String {
|
||||
|
||||
let sftp = match &self.sftp {
|
||||
Some(s) => s,
|
||||
None => return json!({"result": false, "error": "Init SFTP first"}).to_string()
|
||||
};
|
||||
|
||||
let mut data = vec![];
|
||||
|
||||
match sftp.readdir(path) {
|
||||
Ok(contents) => {
|
||||
for item in contents {
|
||||
|
||||
let object_pb = item.0;
|
||||
let object_path = object_pb.to_str().unwrap_or("").to_string();
|
||||
let object_info = &item.1;
|
||||
let object_perm = object_info.perm.unwrap_or(0);
|
||||
|
||||
let object_filename = object_pb
|
||||
.file_name()
|
||||
.unwrap_or("".as_ref())
|
||||
.to_str()
|
||||
.unwrap_or("")
|
||||
.to_string();
|
||||
|
||||
let object_ext = object_pb
|
||||
.extension()
|
||||
.unwrap_or("".as_ref())
|
||||
.to_str()
|
||||
.unwrap_or("")
|
||||
.to_string();
|
||||
|
||||
data.push(json!({
|
||||
"uid": object_info.uid,
|
||||
"gid": object_info.gid,
|
||||
"is_directory": is_directory(object_perm),
|
||||
"is_symlink": object_pb.is_symlink(),
|
||||
"modified": object_info.mtime,
|
||||
"accessed": object_info.atime,
|
||||
"name": object_filename,
|
||||
"size": object_info.size,
|
||||
"path": object_path,
|
||||
"permissions": format!("{:o}", object_perm),
|
||||
"extension": object_ext,
|
||||
}));
|
||||
}
|
||||
|
||||
json!({"result": true, "data": data}).to_string()
|
||||
},
|
||||
Err(err) => format_json_error(&err.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn upload_file(&mut self, file: &str, path: &str) -> String {
|
||||
|
||||
match &self.sftp{
|
||||
Some(s) => {
|
||||
|
||||
let file = match std::fs::File::open(file) {
|
||||
Ok(f) => f,
|
||||
Err(e) => return format_json_error(format!("File error: {}", e).as_str())
|
||||
};
|
||||
|
||||
let mut buf_reader = BufReader::new(file);
|
||||
let result = upload_from_reader(s, path, &mut buf_reader);
|
||||
|
||||
match result{
|
||||
Ok(d) => json!({"result": true, "bytes": d}).to_string(),
|
||||
Err(e) => format_json_error(&e.to_string())
|
||||
}
|
||||
},
|
||||
None => json!({"result": false, "error": "Init SFTP first"}).to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn upload_data(&mut self, data: &[u8], path: &str) -> String {
|
||||
match &self.sftp{
|
||||
Some(s) => {
|
||||
|
||||
let mut cursor = Cursor::new(data);
|
||||
let result = upload_from_reader(s, path, &mut cursor);
|
||||
|
||||
match result{
|
||||
Ok(d) => json!({"result": true, "bytes": d}).to_string(),
|
||||
Err(e) => format_json_error(&e.to_string())
|
||||
}
|
||||
},
|
||||
None => json!({"result": false, "error": "Init SFTP first"}).to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delete_file(&mut self, path: &str) -> String {
|
||||
match &self.sftp{
|
||||
Some(s) => {
|
||||
match s.unlink(path.as_ref()){
|
||||
Ok(_) => json!({"result": true}).to_string(),
|
||||
Err(e) => format_json_error(&e.to_string())
|
||||
}
|
||||
},
|
||||
None => json!({"result": false, "error": "Init SFTP first"}).to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn download_to_file(&mut self, path: &str, file_path: &str) -> String {
|
||||
|
||||
let sftp = match &self.sftp {
|
||||
Some(s) => s,
|
||||
None => return json!({"result": false, "error": "Init SFTP first"}).to_string()
|
||||
};
|
||||
|
||||
let mut file = match std::fs::File::create(file_path){
|
||||
Ok(f) => f,
|
||||
Err(e) => return format_json_error(format!("File error: {}", e).as_str())
|
||||
};
|
||||
|
||||
match download_to_writer(sftp, path, &mut file){
|
||||
Ok(b) => json!({"result": true, "bytes": b, "filepath": file_path}).to_string(),
|
||||
Err(e) => format_json_error(&e)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn download_to_vec(&mut self, path: &str) -> Result<Vec<u8>, String> {
|
||||
|
||||
match &self.sftp{
|
||||
Some(s) => {
|
||||
|
||||
let mut buffer = Vec::new();
|
||||
|
||||
match download_to_writer(s, path, &mut buffer){
|
||||
Ok(_) => Ok(buffer),
|
||||
Err(e) => Err(format_json_error(&e))
|
||||
}
|
||||
|
||||
},
|
||||
None => Err(json!({"result": false, "error": "Init SFTP first"}).to_string())
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn is_directory(mode: u32) -> bool {
|
||||
const S_IFMT: u32 = 0o170000;
|
||||
const S_IFDIR: u32 = 0o040000;
|
||||
(mode & S_IFMT) == S_IFDIR
|
||||
}
|
||||
|
||||
fn oct(o: i32) -> Result<i32, String> {
|
||||
i32::from_str_radix(&o.to_string(), 8).map_err(|err| err.to_string())
|
||||
}
|
||||
|
||||
fn upload_from_reader<R: Read>(sftp: &Sftp, path: &str, reader: &mut R) -> Result<u64, String> {
|
||||
|
||||
let mut remote = match sftp.create(path.as_ref()) {
|
||||
Ok(remote) => remote,
|
||||
Err(e) => return Err(format!("Remote file access error: {}", e))
|
||||
};
|
||||
|
||||
match copy(reader, &mut remote) {
|
||||
Ok(b) => Ok(b),
|
||||
Err(e) => Err(format!("Upload error: {}", &e.to_string()))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn download_to_writer<W: Write>(sftp: &Sftp, path: &str, writer: &mut W, ) -> Result<u64, String> {
|
||||
|
||||
let mut remote = match sftp.open(Path::new(path)) {
|
||||
Ok(remote) => remote,
|
||||
Err(e) => return Err(format!("Remote file access error: {}", e))
|
||||
};
|
||||
|
||||
match copy(&mut remote, writer) {
|
||||
Ok(b) => Ok(b),
|
||||
Err(e) => Err(format!("Upload error: {}", &e.to_string()))
|
||||
}
|
||||
}
|
201
src/addins/ssh/src/component/ssh_methods.rs
Normal file
201
src/addins/ssh/src/component/ssh_methods.rs
Normal file
@@ -0,0 +1,201 @@
|
||||
use std::io::Read;
|
||||
use std::path::Path;
|
||||
use common_tcp::tcp_establish::create_tcp_connection;
|
||||
use serde_json::json;
|
||||
use ssh2::{MethodType, Session};
|
||||
use crate::component::{format_json_error, AddIn};
|
||||
use crate::component::ssh_settings::{SshAuthTypes, SshConf};
|
||||
|
||||
impl AddIn{
|
||||
|
||||
pub fn set_settings(&mut self, settings: String) -> String{
|
||||
|
||||
let mut conf = self.conf.take().unwrap_or_else(|| SshConf::new());
|
||||
|
||||
match conf.set_settings(settings) {
|
||||
Ok(_) => {
|
||||
self.conf = Some(conf);
|
||||
json!({"result": true}).to_string()
|
||||
},
|
||||
Err(e) => format_json_error(&e),
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn set_proxy(&mut self, proxy: String) -> String{
|
||||
|
||||
let mut conf = self.conf.take().unwrap_or_else(|| SshConf::new());
|
||||
|
||||
match conf.set_proxy(proxy) {
|
||||
Ok(_) => {
|
||||
self.conf = Some(conf);
|
||||
json!({"result": true}).to_string()
|
||||
},
|
||||
Err(e) => format_json_error(&e),
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn initialize(&mut self) -> String {
|
||||
|
||||
let conf_data = match &self.conf{
|
||||
Some(conf_data) => conf_data,
|
||||
None => return format_json_error("No configuration found")
|
||||
};
|
||||
|
||||
let settings = match &conf_data.set {
|
||||
Some(settings) => settings,
|
||||
None => return format_json_error("No settings found")
|
||||
};
|
||||
|
||||
let username= &settings.username;
|
||||
let password = settings.password.as_deref().unwrap_or("");
|
||||
let passphrase = &settings.passphrase;
|
||||
let key_path = &settings.key_path;
|
||||
let pub_path = &settings.pub_path;
|
||||
let proxy = &conf_data.proxy;
|
||||
|
||||
let tcp = match create_tcp_connection(&settings.host, settings.port, proxy){
|
||||
Ok(tcp) => tcp,
|
||||
Err(e) => return format_json_error(format!("TCP error: {}", e.to_string()).as_str())
|
||||
};
|
||||
|
||||
ssh2::init();
|
||||
|
||||
let mut identities = vec![];
|
||||
let methods;
|
||||
let banner;
|
||||
let kex;
|
||||
|
||||
let mut sess = match Session::new(){
|
||||
Ok(sess) => {
|
||||
methods = sess.auth_methods(username).unwrap_or("").to_string();
|
||||
banner = sess.banner().unwrap_or("").to_string();
|
||||
kex = sess.methods(MethodType::Kex).unwrap_or("").to_string();
|
||||
|
||||
sess
|
||||
},
|
||||
Err(e) => return format_json_error(format!("Session error: {}", e.to_string()).as_str())
|
||||
};
|
||||
|
||||
match sess.agent(){
|
||||
Ok(agent) => {
|
||||
match agent.identities(){
|
||||
Ok(idents) => {
|
||||
for ident in idents{
|
||||
identities.push(ident.comment().to_string());
|
||||
}
|
||||
}
|
||||
Err(e) => identities.push(e.to_string())
|
||||
}
|
||||
}
|
||||
Err(e) => identities.push(e.to_string())
|
||||
};
|
||||
|
||||
sess.set_tcp_stream(tcp);
|
||||
|
||||
if let Err(e) = sess.handshake() {
|
||||
return json!({
|
||||
"result": false,
|
||||
"error": format!("Handshake error: {}", e.to_string()),
|
||||
"identities": identities,
|
||||
"methods": methods,
|
||||
"banner": banner,
|
||||
"kex_methods": kex
|
||||
}).to_string();
|
||||
};
|
||||
|
||||
let auth_success = match settings.auth_type {
|
||||
|
||||
SshAuthTypes::Password => sess.userauth_password(username, password),
|
||||
SshAuthTypes::Agent => sess.userauth_agent(username),
|
||||
SshAuthTypes::PrivateKey => {
|
||||
|
||||
let path = match key_path{
|
||||
Some(key_path) => key_path.as_ref(),
|
||||
None => return format_json_error("No key path provided with PK auth type")
|
||||
};
|
||||
|
||||
let pub_path = match pub_path{
|
||||
Some(pub_path) => Some(Path::new(pub_path)),
|
||||
None => None
|
||||
};
|
||||
|
||||
sess.userauth_pubkey_file(username, pub_path, path, passphrase.as_deref())
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
if let Err(e) = auth_success{
|
||||
return format_json_error(format!("Auth error: {}", e.to_string()).as_str());
|
||||
};
|
||||
|
||||
if !sess.authenticated(){
|
||||
return format_json_error("Authentication failed with no errors");
|
||||
}
|
||||
|
||||
self.inner = Some(sess);
|
||||
|
||||
json!({"result": true}).to_string()
|
||||
|
||||
}
|
||||
|
||||
pub fn execute(&self, command: &str) -> String {
|
||||
|
||||
let session = match &self.inner{
|
||||
Some(sess) => sess,
|
||||
None => return format_json_error("No session"),
|
||||
};
|
||||
|
||||
let mut channel = match session.channel_session(){
|
||||
Ok(channel) => channel,
|
||||
Err(e) => return format_json_error(&e.to_string())
|
||||
};
|
||||
|
||||
if let Err(e) = channel.exec(command){
|
||||
return format_json_error(&e.to_string());
|
||||
};
|
||||
|
||||
let mut stdout = String::new();
|
||||
if let Err(e) = channel.read_to_string(&mut stdout).map_err(|e| e.to_string()){
|
||||
stdout = e.to_string();
|
||||
};
|
||||
|
||||
let mut stderr = String::new();
|
||||
if let Err(e) = channel.stderr().read_to_string(&mut stderr).map_err(|e| e.to_string()){
|
||||
stderr = e.to_string();
|
||||
};
|
||||
|
||||
let exit_code = match channel.wait_close(){
|
||||
Ok(_) => channel.exit_status().map_err(|e| e.to_string()),
|
||||
Err(e) => Err(e.to_string())
|
||||
};
|
||||
|
||||
let code = match exit_code{
|
||||
Ok(code) => code.to_string(),
|
||||
Err(e) => e.to_string()
|
||||
};
|
||||
|
||||
json!({"result": true, "exit_code": code, "stdout": stdout, "stderr": stderr}).to_string()
|
||||
|
||||
}
|
||||
|
||||
pub fn get_configuration(&mut self) -> String{
|
||||
|
||||
let conf = match &self.conf{
|
||||
Some(conf) => conf,
|
||||
None => return format_json_error("No configuration found")
|
||||
};
|
||||
|
||||
json!({"result": true, "conf": conf}).to_string()
|
||||
}
|
||||
|
||||
pub fn disconnect(&mut self) -> String{
|
||||
if let Some(_conn) = self.inner.take() {
|
||||
self.sftp.take();
|
||||
json!({"result": true}).to_string()
|
||||
} else {
|
||||
json!({"result": false, "error": "No session"}).to_string()
|
||||
}
|
||||
}
|
||||
}
|
BIN
src/en/OInt/addins/OPI_SSH.zip
vendored
BIN
src/en/OInt/addins/OPI_SSH.zip
vendored
Binary file not shown.
Binary file not shown.
BIN
src/ru/OInt/addins/OPI_SSH.zip
vendored
BIN
src/ru/OInt/addins/OPI_SSH.zip
vendored
Binary file not shown.
@@ -448,6 +448,103 @@
|
||||
|
||||
КонецФункции
|
||||
|
||||
// Сохранить файл
|
||||
// Сохраняет файл с сервера по указанному пути
|
||||
//
|
||||
// Параметры:
|
||||
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
|
||||
// Путь - Строка - Путь файла на сервере - path
|
||||
// ИмяФайла - Строка - Путь для сохранения файла на диске - file
|
||||
//
|
||||
// Возвращаемое значение:
|
||||
// Соответствие Из КлючИЗначение - Результат обработки
|
||||
Функция СохранитьФайл(Знач Соединение, Знач Путь, Знач ИмяФайла) Экспорт
|
||||
|
||||
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
|
||||
|
||||
Если Не ЭтоКоннектор(Соединение) Тогда
|
||||
Возврат Соединение;
|
||||
Иначе
|
||||
|
||||
OPI_ПреобразованиеТипов.ПолучитьСтроку(Путь);
|
||||
OPI_ПреобразованиеТипов.ПолучитьСтроку(ИмяФайла);
|
||||
|
||||
OPI_Инструменты.ВернутьУправляющиеПоследовательности(ИмяФайла);
|
||||
|
||||
Результат = Соединение.DownloadToFile(Путь, ИмяФайла);
|
||||
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
|
||||
|
||||
КонецЕсли;
|
||||
|
||||
Если ЗакрыватьСоединение Тогда
|
||||
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
|
||||
КонецЕсли;
|
||||
|
||||
Возврат Результат;
|
||||
|
||||
КонецФункции
|
||||
|
||||
// Получить данные файла !NOCLI
|
||||
// Получает файл с сервера как двоичные данные
|
||||
//
|
||||
// Параметры:
|
||||
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
|
||||
// Путь - Строка - Путь файла на сервере - path
|
||||
//
|
||||
// Возвращаемое значение:
|
||||
// Соответствие Из КлючИЗначение, ДвоичныеДанные - Данные файла или информация об ошибке
|
||||
Функция ПолучитьДанныеФайла(Знач Соединение, Знач Путь) Экспорт
|
||||
|
||||
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
|
||||
|
||||
Если Не ЭтоКоннектор(Соединение) Тогда
|
||||
Возврат Соединение;
|
||||
Иначе
|
||||
|
||||
OPI_ПреобразованиеТипов.ПолучитьСтроку(Путь);
|
||||
|
||||
Если OPI_Компоненты.ТребуетсяПередачаЧерезФайл() Тогда
|
||||
|
||||
// BSLLS:MissingTemporaryFileDeletion-off
|
||||
|
||||
//@skip-check missing-temporary-file-deletion
|
||||
ИВФ = ПолучитьИмяВременногоФайла();
|
||||
|
||||
// BSLLS:MissingTemporaryFileDeletion-on
|
||||
|
||||
Результат = Соединение.DownloadToFile(Путь, ИВФ);
|
||||
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
|
||||
|
||||
Если Результат["result"] Тогда
|
||||
|
||||
Данные = Новый ДвоичныеДанные(ИВФ);
|
||||
OPI_Инструменты.УдалитьФайлВПопытке(ИВФ, "Не удалось удалить временный файл после загрузки");
|
||||
Возврат Данные;
|
||||
|
||||
КонецЕсли;
|
||||
|
||||
Иначе
|
||||
|
||||
Данные = Соединение.DownloadToBuffer(Путь);
|
||||
|
||||
Если ТипЗнч(Данные) = Тип("Строка") Тогда
|
||||
Результат = OPI_Инструменты.JsonВСтруктуру(Данные);
|
||||
Иначе
|
||||
Возврат Данные;
|
||||
КонецЕсли;
|
||||
|
||||
КонецЕсли;
|
||||
|
||||
КонецЕсли;
|
||||
|
||||
Если ЗакрыватьСоединение Тогда
|
||||
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
|
||||
КонецЕсли;
|
||||
|
||||
Возврат Результат;
|
||||
|
||||
КонецФункции
|
||||
|
||||
#КонецОбласти
|
||||
|
||||
#КонецОбласти
|
||||
|
@@ -11756,6 +11756,41 @@
|
||||
|
||||
КонецФункции
|
||||
|
||||
Функция Проверка_SFTP_СохранитьФайл(Знач Результат, Знач Вариант, РазмерРезультата = "", РазмерПроверки = "")
|
||||
|
||||
Если СтрНайти(Вариант, "Размер файла") > 0 Тогда
|
||||
ОжидаетЧто(Результат).Равно(РазмерРезультата);
|
||||
ОжидаетЧто(Результат).Равно(РазмерПроверки);
|
||||
Иначе
|
||||
ОжидаетЧто(Результат["result"]).Равно(Истина);
|
||||
КонецЕсли;
|
||||
|
||||
Если СтрНайти(Вариант, "HTTP") Тогда
|
||||
OPI_Инструменты.Пауза(2);
|
||||
КонецЕсли;
|
||||
|
||||
Возврат Результат;
|
||||
|
||||
КонецФункции
|
||||
|
||||
Функция Проверка_SFTP_ПолучитьДанныеФайла(Знач Результат, Знач Вариант, РазмерПроверки = "")
|
||||
|
||||
Если СтрНайти(Вариант, "Размер файла") > 0 Тогда
|
||||
ОжидаетЧто(Результат).Равно(РазмерПроверки);
|
||||
ИначеЕсли СтрНайти(Вариант, "Размер") > 0 Тогда
|
||||
ОжидаетЧто(Результат["result"]).Равно(Истина);
|
||||
Иначе
|
||||
ОжидаетЧто(Результат).ИмеетТип("ДвоичныеДанные");
|
||||
КонецЕсли;
|
||||
|
||||
Если СтрНайти(Вариант, "HTTP") Тогда
|
||||
OPI_Инструменты.Пауза(2);
|
||||
КонецЕсли;
|
||||
|
||||
Возврат Результат;
|
||||
|
||||
КонецФункции
|
||||
|
||||
#КонецОбласти
|
||||
|
||||
#Область ReportPortal
|
||||
|
172
src/ru/OPI/src/CommonModules/OPI_Тесты/Module.bsl
vendored
172
src/ru/OPI/src/CommonModules/OPI_Тесты/Module.bsl
vendored
@@ -3020,6 +3020,8 @@
|
||||
Для Каждого ПараметрыТеста Из МассивВариантов Цикл
|
||||
|
||||
SFTP_ЗагрузитьФайл(ПараметрыТеста);
|
||||
SFTP_ПолучитьДанныеФайла(ПараметрыТеста);
|
||||
SFTP_СохранитьФайл(ПараметрыТеста);
|
||||
SFTP_УдалитьФайл(ПараметрыТеста);
|
||||
|
||||
КонецЦикла;
|
||||
@@ -22376,7 +22378,7 @@
|
||||
Результат = OPI_FTP.СохранитьФайл(Соединение, Путь, ИмяФайла);
|
||||
|
||||
Если Не Результат["result"] Тогда
|
||||
Обработать(РазмерФайла, "FTP", "СохранитьФайл", "Множественный, " + Постфикс);
|
||||
Обработать(Результат, "FTP", "СохранитьФайл", "Множественный, " + Постфикс);
|
||||
КонецЕсли;
|
||||
|
||||
КонецЦикла;
|
||||
@@ -22453,7 +22455,7 @@
|
||||
Результат = OPI_FTP.ПолучитьДанныеФайла(Соединение, Путь);
|
||||
|
||||
Если Не ТипЗнч(Результат) = Тип("ДвоичныеДанные") Тогда
|
||||
Обработать(Размер, "FTP", "ПолучитьДанныеФайла", "Множественный, " + Постфикс);
|
||||
Обработать(Результат, "FTP", "ПолучитьДанныеФайла", "Множественный, " + Постфикс);
|
||||
КонецЕсли;
|
||||
|
||||
КонецЦикла;
|
||||
@@ -24000,6 +24002,172 @@
|
||||
|
||||
КонецПроцедуры
|
||||
|
||||
Процедура SFTP_СохранитьФайл(ПараметрыФункции)
|
||||
|
||||
Постфикс = ПараметрыФункции["Postfix"]; // SKIP
|
||||
|
||||
Хост = ПараметрыФункции["SSH_Host"];
|
||||
Порт = ПараметрыФункции["SSH_Port"];
|
||||
|
||||
ИспользоватьПрокси = Истина;
|
||||
НастройкиПрокси = Неопределено;
|
||||
ВидАвторизации = "По логину и паролю";
|
||||
|
||||
ИспользоватьПрокси = ПараметрыФункции["Proxy"]; // SKIP
|
||||
ВидАвторизации = ПараметрыФункции["AuthType"]; // SKIP
|
||||
|
||||
Если ВидАвторизации = "По логину и паролю" Тогда
|
||||
|
||||
Логин = ПараметрыФункции["SSH_User"];
|
||||
Пароль = ПараметрыФункции["SSH_Password"];
|
||||
|
||||
НастройкиSSH = OPI_SFTP.ПолучитьНастройкиЛогинПароль(Хост, Порт, Логин, Пароль);
|
||||
|
||||
ИначеЕсли ВидАвторизации = "По ключу" Тогда
|
||||
|
||||
Логин = ПараметрыФункции["SSH_User"];
|
||||
ПриватныйКлюч = "./ssh_key";
|
||||
ПубличныйКлюч = "./ssh_key.pub";
|
||||
|
||||
ПриватныйКлюч = ПараметрыФункции["SSH_Key"]; // SKIP
|
||||
ПубличныйКлюч = ПараметрыФункции["SSH_Pub"]; // SKIP
|
||||
|
||||
НастройкиSSH = OPI_SFTP.ПолучитьНастройкиПриватныйКлюч(Хост, Порт, Логин, ПриватныйКлюч, ПубличныйКлюч);
|
||||
|
||||
Иначе
|
||||
|
||||
Логин = ПараметрыФункции["SSH_User"];
|
||||
НастройкиSSH = OPI_SFTP.ПолучитьНастройкиЧерезАгента(Хост, Порт, Логин);
|
||||
|
||||
КонецЕсли;
|
||||
|
||||
Если ИспользоватьПрокси Тогда
|
||||
|
||||
ТипПрокси = ПараметрыФункции["Proxy_Type"]; // http, socks5, socks4
|
||||
|
||||
АдресПрокси = ПараметрыФункции["Proxy_IP"];
|
||||
ПортПрокси = ПараметрыФункции["Proxy_Port"];
|
||||
ЛогинПрокси = ПараметрыФункции["Proxy_User"];
|
||||
ПарольПрокси = ПараметрыФункции["Proxy_Password"];
|
||||
|
||||
НастройкиПрокси = OPI_SFTP.ПолучитьНастройкиПрокси(АдресПрокси, ПортПрокси, ТипПрокси, ЛогинПрокси, ПарольПрокси);
|
||||
|
||||
КонецЕсли;
|
||||
|
||||
Соединение = OPI_SFTP.ОткрытьСоединение(НастройкиSSH, НастройкиПрокси);
|
||||
|
||||
Если OPI_SFTP.ЭтоКоннектор(Соединение) Тогда
|
||||
|
||||
Путь = "pic_from_disk.png";
|
||||
ИмяФайла = ПолучитьИмяВременногоФайла("bin");
|
||||
|
||||
Результат = OPI_SFTP.СохранитьФайл(Соединение, Путь, ИмяФайла);
|
||||
|
||||
Иначе
|
||||
Результат = Соединение; // Ошибка соединения
|
||||
КонецЕсли;
|
||||
|
||||
// END
|
||||
|
||||
Обработать(Результат, "SSH", "СохранитьФайл", Постфикс);
|
||||
|
||||
Путь = "files_folder/pic_from_binary.png";
|
||||
|
||||
Для Н = 1 По 20 Цикл
|
||||
|
||||
Результат = OPI_SFTP.СохранитьФайл(Соединение, Путь, ИмяФайла);
|
||||
|
||||
Если Не Результат["result"] Тогда
|
||||
Обработать(Результат, "FTP", "СохранитьФайл", "Множественный, " + Постфикс);
|
||||
КонецЕсли;
|
||||
|
||||
КонецЦикла;
|
||||
|
||||
OPI_Инструменты.УдалитьФайлВПопытке(ИмяФайла, "Не удалось удалить временный файл после теста!");
|
||||
|
||||
КонецПроцедуры
|
||||
|
||||
Процедура SFTP_ПолучитьДанныеФайла(ПараметрыФункции)
|
||||
|
||||
Постфикс = ПараметрыФункции["Postfix"]; // SKIP
|
||||
|
||||
Хост = ПараметрыФункции["SSH_Host"];
|
||||
Порт = ПараметрыФункции["SSH_Port"];
|
||||
|
||||
ИспользоватьПрокси = Истина;
|
||||
НастройкиПрокси = Неопределено;
|
||||
ВидАвторизации = "По логину и паролю";
|
||||
|
||||
ИспользоватьПрокси = ПараметрыФункции["Proxy"]; // SKIP
|
||||
ВидАвторизации = ПараметрыФункции["AuthType"]; // SKIP
|
||||
|
||||
Если ВидАвторизации = "По логину и паролю" Тогда
|
||||
|
||||
Логин = ПараметрыФункции["SSH_User"];
|
||||
Пароль = ПараметрыФункции["SSH_Password"];
|
||||
|
||||
НастройкиSSH = OPI_SFTP.ПолучитьНастройкиЛогинПароль(Хост, Порт, Логин, Пароль);
|
||||
|
||||
ИначеЕсли ВидАвторизации = "По ключу" Тогда
|
||||
|
||||
Логин = ПараметрыФункции["SSH_User"];
|
||||
ПриватныйКлюч = "./ssh_key";
|
||||
ПубличныйКлюч = "./ssh_key.pub";
|
||||
|
||||
ПриватныйКлюч = ПараметрыФункции["SSH_Key"]; // SKIP
|
||||
ПубличныйКлюч = ПараметрыФункции["SSH_Pub"]; // SKIP
|
||||
|
||||
НастройкиSSH = OPI_SFTP.ПолучитьНастройкиПриватныйКлюч(Хост, Порт, Логин, ПриватныйКлюч, ПубличныйКлюч);
|
||||
|
||||
Иначе
|
||||
|
||||
Логин = ПараметрыФункции["SSH_User"];
|
||||
НастройкиSSH = OPI_SFTP.ПолучитьНастройкиЧерезАгента(Хост, Порт, Логин);
|
||||
|
||||
КонецЕсли;
|
||||
|
||||
Если ИспользоватьПрокси Тогда
|
||||
|
||||
ТипПрокси = ПараметрыФункции["Proxy_Type"]; // http, socks5, socks4
|
||||
|
||||
АдресПрокси = ПараметрыФункции["Proxy_IP"];
|
||||
ПортПрокси = ПараметрыФункции["Proxy_Port"];
|
||||
ЛогинПрокси = ПараметрыФункции["Proxy_User"];
|
||||
ПарольПрокси = ПараметрыФункции["Proxy_Password"];
|
||||
|
||||
НастройкиПрокси = OPI_SFTP.ПолучитьНастройкиПрокси(АдресПрокси, ПортПрокси, ТипПрокси, ЛогинПрокси, ПарольПрокси);
|
||||
|
||||
КонецЕсли;
|
||||
|
||||
Соединение = OPI_SFTP.ОткрытьСоединение(НастройкиSSH, НастройкиПрокси);
|
||||
|
||||
Если OPI_SFTP.ЭтоКоннектор(Соединение) Тогда
|
||||
|
||||
Путь = "pic_from_disk.png";
|
||||
Результат = OPI_FTP.ПолучитьДанныеФайла(Соединение, Путь);
|
||||
|
||||
Иначе
|
||||
Результат = Соединение; // Ошибка соединения
|
||||
КонецЕсли;
|
||||
|
||||
// END
|
||||
|
||||
Обработать(Результат, "SFTP", "ПолучитьДанныеФайла", Постфикс);
|
||||
|
||||
Путь = "files_folder/pic_from_binary.png";
|
||||
|
||||
Для Н = 1 По 20 Цикл
|
||||
|
||||
Результат = OPI_SFTP.ПолучитьДанныеФайла(Соединение, Путь);
|
||||
|
||||
Если Не ТипЗнч(Результат) = Тип("ДвоичныеДанные") Тогда
|
||||
Обработать(Результат, "SFTP", "ПолучитьДанныеФайла", "Множественный, " + Постфикс);
|
||||
КонецЕсли;
|
||||
|
||||
КонецЦикла;
|
||||
|
||||
КонецПроцедуры
|
||||
|
||||
#КонецОбласти
|
||||
|
||||
#КонецОбласти
|
||||
|
Binary file not shown.
Reference in New Issue
Block a user