Preserve FTP password and filename whitespace
This commit is contained in:
+7
-2
@@ -64,7 +64,9 @@ fn names_a_conflict(text: &str) -> bool {
|
||||
.collect();
|
||||
words.contains(&"exists")
|
||||
|| words.contains(&"nonempty")
|
||||
|| words.windows(2).any(|pair| matches!(pair, ["not" | "non", "empty"]))
|
||||
|| words
|
||||
.windows(2)
|
||||
.any(|pair| matches!(pair, ["not" | "non", "empty"]))
|
||||
}
|
||||
|
||||
/// What the first reply to a transfer command means. A transfer answers with
|
||||
@@ -255,7 +257,10 @@ mod tests {
|
||||
));
|
||||
// The same two conditions as other servers phrase them.
|
||||
assert!(matches!(
|
||||
refusal(550, "550 Cannot create a file when that file already exists."),
|
||||
refusal(
|
||||
550,
|
||||
"550 Cannot create a file when that file already exists."
|
||||
),
|
||||
Err(ErrorCode::Conflict)
|
||||
));
|
||||
assert!(matches!(
|
||||
|
||||
+23
-1
@@ -31,10 +31,11 @@ struct Ftp;
|
||||
|
||||
fn text(setting: Option<&Setting>) -> Option<String> {
|
||||
match setting {
|
||||
Some(Setting::Text(value)) | Some(Setting::Secret(value)) => {
|
||||
Some(Setting::Text(value)) => {
|
||||
let value = value.trim().to_owned();
|
||||
(!value.is_empty()).then_some(value)
|
||||
}
|
||||
Some(Setting::Secret(value)) => Some(value.clone()),
|
||||
Some(Setting::Toggle(_)) | None => None,
|
||||
}
|
||||
}
|
||||
@@ -394,3 +395,24 @@ impl Guest for Ftp {
|
||||
}
|
||||
|
||||
memona_plugin_sdk::export!(Ftp);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::text;
|
||||
use memona_plugin_sdk::Setting;
|
||||
|
||||
#[tokio::test]
|
||||
async fn secret_credentials_preserve_significant_whitespace() {
|
||||
for password in [" ftp fixture secret ", " ", ""] {
|
||||
assert_eq!(
|
||||
text(Some(&Setting::Secret(password.to_owned()))),
|
||||
Some(password.to_owned())
|
||||
);
|
||||
}
|
||||
assert_eq!(
|
||||
text(Some(&Setting::Text(" server.example ".to_owned()))),
|
||||
Some("server.example".to_owned())
|
||||
);
|
||||
assert_eq!(text(Some(&Setting::Text(" ".to_owned()))), None);
|
||||
}
|
||||
}
|
||||
|
||||
+15
-1
@@ -12,7 +12,6 @@ struct Facts<'a> {
|
||||
|
||||
fn facts(line: &str) -> Option<Facts<'_>> {
|
||||
let (facts, name) = line.split_once(' ')?;
|
||||
let name = name.trim();
|
||||
if name.is_empty() {
|
||||
return None;
|
||||
}
|
||||
@@ -106,6 +105,21 @@ mod tests {
|
||||
use super::{machine_entry, machine_info, page};
|
||||
use memona_plugin_sdk::{EntryKind, ErrorCode};
|
||||
|
||||
#[tokio::test]
|
||||
async fn listing_names_preserve_significant_whitespace()
|
||||
-> Result<(), ErrorCode> {
|
||||
let listing = b"type=file;size=1; report.md \r\ntype=dir; spaced folder \r\ntype=file;size=2; \r\n";
|
||||
let listed = page(listing, 0, 10)?;
|
||||
let names: Vec<&str> = listed
|
||||
.entries
|
||||
.iter()
|
||||
.map(|entry| entry.name.as_str())
|
||||
.collect();
|
||||
assert_eq!(names, [" report.md ", " spaced folder ", " "]);
|
||||
assert!(listed.cursor.is_none());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reads_kind_and_size_and_skips_the_directory_itself()
|
||||
-> Result<(), &'static str> {
|
||||
|
||||
Reference in New Issue
Block a user