mirror of
https://github.com/chatmail/core.git
synced 2026-05-16 21:36:30 +03:00
Do not trim leading spaces from message lines
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user