mirror of
https://github.com/chatmail/core.git
synced 2026-04-20 23:16:30 +03:00
Move format_flowed to a separate crate
This makes it possible to fuzz test the functions without exposing the module interface in the deltachat core interface. Also ensure that format_flowed will not grow a dependency on deltachat core types.
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
### Changes
|
||||
- Validate signatures in try_decrypt() even if the message isn't encrypted #3859
|
||||
- Don't parse the message again after detached signatures validation #3862
|
||||
- Move format=flowed support to a separate crate #3869
|
||||
|
||||
### API-Changes
|
||||
|
||||
|
||||
5
Cargo.lock
generated
5
Cargo.lock
generated
@@ -887,6 +887,7 @@ dependencies = [
|
||||
"encoded-words",
|
||||
"escaper",
|
||||
"fast-socks5",
|
||||
"format-flowed",
|
||||
"futures",
|
||||
"futures-lite",
|
||||
"hex",
|
||||
@@ -1445,6 +1446,10 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "format-flowed"
|
||||
version = "1.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.25"
|
||||
|
||||
@@ -19,6 +19,7 @@ panic = 'abort'
|
||||
|
||||
[dependencies]
|
||||
deltachat_derive = { path = "./deltachat_derive" }
|
||||
format-flowed = { path = "./format-flowed" }
|
||||
|
||||
ansi_term = { version = "0.12.1", optional = true }
|
||||
anyhow = "1"
|
||||
@@ -99,7 +100,8 @@ members = [
|
||||
"deltachat-ffi",
|
||||
"deltachat_derive",
|
||||
"deltachat-jsonrpc",
|
||||
"deltachat-rpc-server"
|
||||
"deltachat-rpc-server",
|
||||
"format-flowed",
|
||||
]
|
||||
|
||||
[[example]]
|
||||
|
||||
11
format-flowed/Cargo.toml
Normal file
11
format-flowed/Cargo.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "format-flowed"
|
||||
version = "1.0.0"
|
||||
description = "format=flowed support"
|
||||
edition = "2021"
|
||||
license = "MPL-2.0"
|
||||
|
||||
keywords = ["email"]
|
||||
categories = ["email"]
|
||||
|
||||
[dependencies]
|
||||
@@ -62,7 +62,7 @@ fn format_line_flowed(line: &str, prefix: &str) -> String {
|
||||
///
|
||||
/// RFC 2646 technique is used to insert soft line breaks, so DelSp
|
||||
/// SHOULD be set to "no" when sending.
|
||||
pub(crate) fn format_flowed(text: &str) -> String {
|
||||
pub fn format_flowed(text: &str) -> String {
|
||||
let mut result = String::new();
|
||||
|
||||
for line in text.split('\n') {
|
||||
@@ -147,8 +147,6 @@ pub fn unformat_flowed(text: &str, delsp: bool) -> String {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::test_utils::TestContext;
|
||||
use anyhow::Result;
|
||||
|
||||
#[test]
|
||||
fn test_format_flowed() {
|
||||
@@ -220,51 +218,4 @@ mod tests {
|
||||
> unwrapped on the receiver";
|
||||
assert_eq!(format_flowed_quote(quote), expected);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_send_quotes() -> Result<()> {
|
||||
let alice = TestContext::new_alice().await;
|
||||
let bob = TestContext::new_bob().await;
|
||||
let chat = alice.create_chat(&bob).await;
|
||||
|
||||
let sent = alice.send_text(chat.id, "> First quote").await;
|
||||
let received = bob.recv_msg(&sent).await;
|
||||
assert_eq!(received.text.as_deref(), Some("> First quote"));
|
||||
assert!(received.quoted_text().is_none());
|
||||
assert!(received.quoted_message(&bob).await?.is_none());
|
||||
|
||||
let sent = alice.send_text(chat.id, "> Second quote").await;
|
||||
let received = bob.recv_msg(&sent).await;
|
||||
assert_eq!(received.text.as_deref(), Some("> Second quote"));
|
||||
assert!(received.quoted_text().is_none());
|
||||
assert!(received.quoted_message(&bob).await?.is_none());
|
||||
|
||||
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(())
|
||||
}
|
||||
}
|
||||
@@ -74,7 +74,6 @@ pub mod imex;
|
||||
mod scheduler;
|
||||
#[macro_use]
|
||||
mod job;
|
||||
mod format_flowed;
|
||||
pub mod key;
|
||||
mod keyring;
|
||||
pub mod location;
|
||||
|
||||
@@ -2340,4 +2340,51 @@ mod tests {
|
||||
);
|
||||
assert_eq!(Viewtype::Webxdc, Viewtype::from_i32(80).unwrap());
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_send_quotes() -> Result<()> {
|
||||
let alice = TestContext::new_alice().await;
|
||||
let bob = TestContext::new_bob().await;
|
||||
let chat = alice.create_chat(&bob).await;
|
||||
|
||||
let sent = alice.send_text(chat.id, "> First quote").await;
|
||||
let received = bob.recv_msg(&sent).await;
|
||||
assert_eq!(received.text.as_deref(), Some("> First quote"));
|
||||
assert!(received.quoted_text().is_none());
|
||||
assert!(received.quoted_message(&bob).await?.is_none());
|
||||
|
||||
let sent = alice.send_text(chat.id, "> Second quote").await;
|
||||
let received = bob.recv_msg(&sent).await;
|
||||
assert_eq!(received.text.as_deref(), Some("> Second quote"));
|
||||
assert!(received.quoted_text().is_none());
|
||||
assert!(received.quoted_message(&bob).await?.is_none());
|
||||
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ use std::convert::TryInto;
|
||||
|
||||
use anyhow::{bail, ensure, Context as _, Result};
|
||||
use chrono::TimeZone;
|
||||
use format_flowed::{format_flowed, format_flowed_quote};
|
||||
use lettre_email::{mime, Address, Header, MimeMultipartType, PartBuilder};
|
||||
use tokio::fs;
|
||||
|
||||
@@ -15,7 +16,6 @@ use crate::contact::Contact;
|
||||
use crate::context::{get_version_str, Context};
|
||||
use crate::e2ee::EncryptHelper;
|
||||
use crate::ephemeral::Timer as EphemeralTimer;
|
||||
use crate::format_flowed::{format_flowed, format_flowed_quote};
|
||||
use crate::html::new_html_mimepart;
|
||||
use crate::location;
|
||||
use crate::message::{self, Message, MsgId, Viewtype};
|
||||
|
||||
@@ -9,6 +9,7 @@ use std::str;
|
||||
|
||||
use anyhow::{bail, Context as _, Result};
|
||||
use deltachat_derive::{FromSql, ToSql};
|
||||
use format_flowed::unformat_flowed;
|
||||
use lettre_email::mime::{self, Mime};
|
||||
use mailparse::{addrparse_header, DispositionType, MailHeader, MailHeaderMap, SingleInfo};
|
||||
use once_cell::sync::Lazy;
|
||||
@@ -24,7 +25,6 @@ use crate::decrypt::{
|
||||
};
|
||||
use crate::dehtml::dehtml;
|
||||
use crate::events::EventType;
|
||||
use crate::format_flowed::unformat_flowed;
|
||||
use crate::headerdef::{HeaderDef, HeaderDefMap};
|
||||
use crate::key::{DcKey, Fingerprint, SignedPublicKey, SignedSecretKey};
|
||||
use crate::keyring::Keyring;
|
||||
|
||||
Reference in New Issue
Block a user