Do not trim leading spaces from message lines

This commit is contained in:
link2xt
2022-12-25 19:55:53 +00:00
parent 942f64f04d
commit 6f7bb8a777
2 changed files with 49 additions and 4 deletions

View File

@@ -9,6 +9,7 @@
### Fixes ### Fixes
- Do not add an error if the message is encrypted but not signed #3860 - Do not add an error if the message is encrypted but not signed #3860
- Do not strip leading spaces from message lines #3867
## 1.104.0 ## 1.104.0

View File

@@ -28,6 +28,10 @@ fn format_line_flowed(line: &str, prefix: &str) -> String {
for c in line.chars() { for c in line.chars() {
if c == ' ' { if c == ' ' {
if buffer.is_empty() {
// Space stuffing, see RFC 3676
buffer.push(' ');
}
buffer.push(c); buffer.push(c);
after_space = true; after_space = true;
} else if c == '>' { } else if c == '>' {
@@ -66,16 +70,18 @@ pub(crate) fn format_flowed(text: &str) -> String {
result += "\r\n"; result += "\r\n";
} }
let line_no_prefix = line.strip_prefix('>'); let line_no_prefix = line
.strip_prefix('>')
.map(|line| line.strip_prefix(' ').unwrap_or(line));
let is_quote = line_no_prefix.is_some(); let is_quote = line_no_prefix.is_some();
let line = line_no_prefix.unwrap_or(line).trim(); let line = line_no_prefix.unwrap_or(line).trim_end();
let prefix = if is_quote { "> " } else { "" }; let prefix = if is_quote { "> " } else { "" };
if prefix.len() + line.len() > 78 { if prefix.len() + line.len() > 78 {
result += &format_line_flowed(line, prefix); result += &format_line_flowed(line, prefix);
} else { } else {
result += prefix; result += prefix;
if prefix.is_empty() && line.starts_with('>') { if prefix.is_empty() && (line.starts_with('>') || line.starts_with(' ')) {
// Space stuffing, see RFC 3676 // Space stuffing, see RFC 3676
result.push(' '); result.push(' ');
} }
@@ -142,6 +148,7 @@ pub fn unformat_flowed(text: &str, delsp: bool) -> String {
mod tests { mod tests {
use super::*; use super::*;
use crate::test_utils::TestContext; use crate::test_utils::TestContext;
use anyhow::Result;
#[test] #[test]
fn test_format_flowed() { fn test_format_flowed() {
@@ -170,6 +177,13 @@ mod tests {
> To decrypt and use your key, open the message in an Autocrypt-compliant \r\n\ > To decrypt and use your key, open the message in an Autocrypt-compliant \r\n\
> client and enter the setup code presented on the generating device."; > client and enter the setup code presented on the generating device.";
assert_eq!(format_flowed(text), expected); assert_eq!(format_flowed(text), expected);
// Test space stuffing of spaces.
let text = " Foo bar baz";
assert_eq!(format_flowed(text), " Foo bar baz");
let text = " Foo bar baz";
assert_eq!(format_flowed(text), " Foo bar baz");
} }
#[test] #[test]
@@ -180,6 +194,10 @@ mod tests {
"this is a very long message that should be wrapped using format=flowed and \ "this is a very long message that should be wrapped using format=flowed and \
unwrapped on the receiver"; unwrapped on the receiver";
assert_eq!(unformat_flowed(text, false), expected); assert_eq!(unformat_flowed(text, false), expected);
let text = " Foo bar";
let expected = " Foo bar";
assert_eq!(unformat_flowed(text, false), expected);
} }
#[test] #[test]
@@ -204,7 +222,7 @@ mod tests {
} }
#[tokio::test(flavor = "multi_thread", worker_threads = 2)] #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_send_quotes() -> anyhow::Result<()> { async fn test_send_quotes() -> Result<()> {
let alice = TestContext::new_alice().await; let alice = TestContext::new_alice().await;
let bob = TestContext::new_bob().await; let bob = TestContext::new_bob().await;
let chat = alice.create_chat(&bob).await; let chat = alice.create_chat(&bob).await;
@@ -223,4 +241,30 @@ mod tests {
Ok(()) Ok(())
} }
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_format_flowed_round_trip() -> Result<()> {
let alice = TestContext::new_alice().await;
let bob = TestContext::new_bob().await;
let chat = alice.create_chat(&bob).await;
let text = " Foo bar";
let sent = alice.send_text(chat.id, text).await;
let received = bob.recv_msg(&sent).await;
assert_eq!(received.text.as_deref(), Some(text));
let text = "Foo bar baz";
let sent = alice.send_text(chat.id, text).await;
let received = bob.recv_msg(&sent).await;
assert_eq!(received.text.as_deref(), Some(text));
let python_program = "\
def hello():
return 'Hello, world!'";
let sent = alice.send_text(chat.id, python_program).await;
let received = bob.recv_msg(&sent).await;
assert_eq!(received.text.as_deref(), Some(python_program));
Ok(())
}
} }