New ftp_put and ftp_put_in_memory commands

This commit is contained in:
sagie gur ari 2020-06-30 21:23:59 +00:00
parent 4dcd6d08ad
commit f495200258
11 changed files with 336 additions and 0 deletions

View file

@ -2,6 +2,8 @@
### v0.5.1
* New ftp_put command.
* New fpt_put_in_memory command.
* New ftp_get command.
* New ftp_get_in_memory command.
* New ftp_list command.

View file

@ -115,6 +115,8 @@
* [std::net::ftp::GetInMemory (ftp_get_in_memory)](#std__net__ftp__GetInMemory)
* [std::net::ftp::List (ftp_list)](#std__net__ftp__List)
* [std::net::ftp::NLst (ftp_nlst)](#std__net__ftp__NLst)
* [std::net::ftp::Put (ftp_put)](#std__net__ftp__Put)
* [std::net::ftp::PutInMemory (ftp_put_in_memory)](#std__net__ftp__PutInMemory)
* [std::process::Execute (exec)](#std__process__Execute)
* [std::process::Exit (exit, quit, q)](#std__process__Exit)
* [std::process::ProcessID (pid, process_id)](#std__process__ProcessID)
@ -4281,6 +4283,72 @@ end
#### Aliases:
ftp_nlst
<a name="std__net__ftp__Put"></a>
## std::net::ftp::Put
```sh
result = ftp_put --host <hostname> [--port 21] [--username <user name>] [--password <password>] [--path <path>] [--type <A/I>] --remote-file <file name> --local-file <file name>
```
Invokes the FTP PUT command from the given connection and file details.
#### Parameters
* --host - The host name or IP to connect to
* --port - Optional port number to use (by default 21)
* --username - Optional user name used to login (if not user or password provided, no login operation will be invoked)
* --password - Optional password used to login (if not user or password provided, no login operation will be invoked)
* --path - Optional path on the remote server to invoke operation on
* --type - Optional setting of the transfer type as A (ascii) I (image, binary)
* --remote-file - The remote file to upload
* --local-file - The source local file to upload
#### Return Value
true if operation was completed.
#### Examples
```sh
ftp_put --host myhost --username someuser --password 12345 --remote-file README.md --local-file README.md
```
#### Aliases:
ftp_put
<a name="std__net__ftp__PutInMemory"></a>
## std::net::ftp::PutInMemory
```sh
result = ftp_put_in_memory --host <hostname> [--port 21] [--username <user name>] [--password <password>] [--path <path>] [--type <A/I>] --remote-file <file name> --content <content>
```
Invokes the FTP PUT command from the given connection and file details.
#### Parameters
* --host - The host name or IP to connect to
* --port - Optional port number to use (by default 21)
* --username - Optional user name used to login (if not user or password provided, no login operation will be invoked)
* --password - Optional password used to login (if not user or password provided, no login operation will be invoked)
* --path - Optional path on the remote server to invoke operation on
* --type - Optional setting of the transfer type as A (ascii) I (image, binary)
* --remote-file - The remote file to upload
* --content - The textual content to upload
#### Return Value
true if operation was completed.
#### Examples
```sh
ftp_put_in_memory --host myhost --username someuser --password 12345 --remote-file README.md --content "This is the README content"
```
#### Aliases:
ftp_put_in_memory
<a name="std__process__Execute"></a>
## std::process::Execute
```sh

View file

@ -2,6 +2,8 @@ mod get;
mod get_in_memory;
mod list;
mod nlst;
mod put;
mod put_in_memory;
use crate::utils::pckg;
use duckscript::types::command::{CommandResult, Commands};
@ -18,6 +20,8 @@ pub(crate) fn load(commands: &mut Commands, parent: &str) -> Result<(), ScriptEr
commands.set(get_in_memory::create(&package))?;
commands.set(list::create(&package))?;
commands.set(nlst::create(&package))?;
commands.set(put::create(&package))?;
commands.set(put_in_memory::create(&package))?;
Ok(())
}
@ -40,6 +44,7 @@ pub(crate) struct Options {
transfer_type: Option<TransferType>,
remote_file: Option<String>,
local_file: Option<String>,
content: Option<String>,
}
impl Options {
@ -53,6 +58,7 @@ impl Options {
transfer_type: None,
remote_file: None,
local_file: None,
content: None,
}
}
}
@ -67,6 +73,7 @@ enum LookingFor {
TransferType,
RemoteFile,
LocalFile,
Content,
}
pub(crate) fn run_with_connection(
@ -112,6 +119,7 @@ fn parse_common_options(arguments: &Vec<String>) -> Result<Options, String> {
"--type" => looking_for = LookingFor::TransferType,
"--remote-file" => looking_for = LookingFor::RemoteFile,
"--local-file" => looking_for = LookingFor::LocalFile,
"--content" => looking_for = LookingFor::Content,
_ => (),
},
LookingFor::Host => {
@ -174,6 +182,12 @@ fn parse_common_options(arguments: &Vec<String>) -> Result<Options, String> {
}
looking_for = LookingFor::Flag;
}
LookingFor::Content => {
if !argument.is_empty() {
options.content = Some(argument.to_string());
}
looking_for = LookingFor::Flag;
}
}
}

View file

@ -0,0 +1,26 @@
```sh
result = ftp_put --host <hostname> [--port 21] [--username <user name>] [--password <password>] [--path <path>] [--type <A/I>] --remote-file <file name> --local-file <file name>
```
Invokes the FTP PUT command from the given connection and file details.
#### Parameters
* --host - The host name or IP to connect to
* --port - Optional port number to use (by default 21)
* --username - Optional user name used to login (if not user or password provided, no login operation will be invoked)
* --password - Optional password used to login (if not user or password provided, no login operation will be invoked)
* --path - Optional path on the remote server to invoke operation on
* --type - Optional setting of the transfer type as A (ascii) I (image, binary)
* --remote-file - The remote file to upload
* --local-file - The source local file to upload
#### Return Value
true if operation was completed.
#### Examples
```sh
ftp_put --host myhost --username someuser --password 12345 --remote-file README.md --local-file README.md
```

View file

@ -0,0 +1,81 @@
use crate::sdk::std::net::ftp::{validate_and_run_with_connection, Options};
use crate::utils::pckg;
use duckscript::types::command::{Command, CommandResult};
use fsio::path::as_path::AsPath;
use ftp::FtpStream;
use std::fs::File;
#[cfg(test)]
#[path = "./mod_test.rs"]
mod mod_test;
#[derive(Clone)]
pub(crate) struct CommandImpl {
package: String,
}
impl Command for CommandImpl {
fn name(&self) -> String {
pckg::concat(&self.package, "Put")
}
fn aliases(&self) -> Vec<String> {
vec!["ftp_put".to_string()]
}
fn help(&self) -> String {
include_str!("help.md").to_string()
}
fn clone_and_box(&self) -> Box<dyn Command> {
Box::new((*self).clone())
}
fn run(&self, arguments: Vec<String>) -> CommandResult {
validate_and_run_with_connection(
&arguments,
&|options: &Options| -> Result<(), String> {
if options.remote_file.is_none() {
Err("Missing remote file name".to_string())
} else {
let options_clone = options.clone();
match options_clone.local_file {
Some(local_file) => {
let file_path = local_file.as_path();
if file_path.exists() {
if file_path.is_file() {
Ok(())
} else {
Err("Local path is a directory.".to_string())
}
} else {
Err("Local file not found.".to_string())
}
}
None => Err("Missing local file name.".to_string()),
}
}
},
&mut |options: &Options, ftp_stream: &mut FtpStream| -> CommandResult {
let options_clone = options.clone();
let remote_file = options_clone.remote_file.unwrap();
let local_file = options_clone.local_file.unwrap();
match File::open(local_file) {
Ok(mut file) => match ftp_stream.put(&remote_file, &mut file) {
Ok(_) => CommandResult::Continue(Some(true.to_string())),
Err(error) => CommandResult::Error(error.to_string()),
},
Err(error) => CommandResult::Error(error.to_string()),
}
},
)
}
}
pub(crate) fn create(package: &str) -> Box<dyn Command> {
Box::new(CommandImpl {
package: package.to_string(),
})
}

View file

@ -0,0 +1,12 @@
use super::*;
use crate::test;
#[test]
fn common_functions() {
test::test_common_command_functions(create(""));
}
#[test]
fn run_no_args() {
test::run_script_and_error(vec![create("")], "out = ftp_put", "out");
}

View file

@ -0,0 +1,26 @@
```sh
result = ftp_put_in_memory --host <hostname> [--port 21] [--username <user name>] [--password <password>] [--path <path>] [--type <A/I>] --remote-file <file name> --content <content>
```
Invokes the FTP PUT command from the given connection and file details.
#### Parameters
* --host - The host name or IP to connect to
* --port - Optional port number to use (by default 21)
* --username - Optional user name used to login (if not user or password provided, no login operation will be invoked)
* --password - Optional password used to login (if not user or password provided, no login operation will be invoked)
* --path - Optional path on the remote server to invoke operation on
* --type - Optional setting of the transfer type as A (ascii) I (image, binary)
* --remote-file - The remote file to upload
* --content - The textual content to upload
#### Return Value
true if operation was completed.
#### Examples
```sh
ftp_put_in_memory --host myhost --username someuser --password 12345 --remote-file README.md --content "This is the README content"
```

View file

@ -0,0 +1,64 @@
use crate::sdk::std::net::ftp::{validate_and_run_with_connection, Options};
use crate::utils::pckg;
use duckscript::types::command::{Command, CommandResult};
use ftp::FtpStream;
use std::io::Cursor;
#[cfg(test)]
#[path = "./mod_test.rs"]
mod mod_test;
#[derive(Clone)]
pub(crate) struct CommandImpl {
package: String,
}
impl Command for CommandImpl {
fn name(&self) -> String {
pckg::concat(&self.package, "PutInMemory")
}
fn aliases(&self) -> Vec<String> {
vec!["ftp_put_in_memory".to_string()]
}
fn help(&self) -> String {
include_str!("help.md").to_string()
}
fn clone_and_box(&self) -> Box<dyn Command> {
Box::new((*self).clone())
}
fn run(&self, arguments: Vec<String>) -> CommandResult {
validate_and_run_with_connection(
&arguments,
&|options: &Options| -> Result<(), String> {
if options.remote_file.is_none() {
Err("Missing remote file name".to_string())
} else if options.content.is_none() {
Err("Missing content".to_string())
} else {
Ok(())
}
},
&mut |options: &Options, ftp_stream: &mut FtpStream| -> CommandResult {
let options_clone = options.clone();
let remote_file = options_clone.remote_file.unwrap();
let content = options_clone.content.unwrap();
let mut reader = Cursor::new(content.as_bytes());
match ftp_stream.put(&remote_file, &mut reader) {
Ok(_) => CommandResult::Continue(Some(true.to_string())),
Err(error) => CommandResult::Error(error.to_string()),
}
},
)
}
}
pub(crate) fn create(package: &str) -> Box<dyn Command> {
Box::new(CommandImpl {
package: package.to_string(),
})
}

View file

@ -0,0 +1,12 @@
use super::*;
use crate::test;
#[test]
fn common_functions() {
test::test_common_command_functions(create(""));
}
#[test]
fn run_no_args() {
test::run_script_and_error(vec![create("")], "out = ftp_put_in_memory", "out");
}

View file

@ -0,0 +1,14 @@
fn test_auth_error
test_enabled = equals ${TEST_FTP_PUT} true
if ${test_enabled}
ftp_put_in_memory --host test.rebex.net --username demo --password password --remote-file readme2.txt --content "test content"
assert_false ${result}
last_error = get_last_error
found = contains "${last_error}" 550
assert ${found}
end
end

View file

@ -0,0 +1,17 @@
fn test_auth_error
test_enabled = equals ${TEST_FTP_PUT} true
if ${test_enabled}
filename = set ./target/_duckscript_test/net/ftp/put/readme.txt
writefile ${filename} "test content"
result = ftp_put --host test.rebex.net --username demo --password password --remote-file readme2.txt --local-file ${filename}
assert_false ${result}
last_error = get_last_error
found = contains "${last_error}" 550
assert ${found}
end
end