mirror of
https://github.com/chatmail/core.git
synced 2026-05-03 13:26:28 +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
|
### Changes
|
||||||
- Validate signatures in try_decrypt() even if the message isn't encrypted #3859
|
- Validate signatures in try_decrypt() even if the message isn't encrypted #3859
|
||||||
- Don't parse the message again after detached signatures validation #3862
|
- Don't parse the message again after detached signatures validation #3862
|
||||||
|
- Move format=flowed support to a separate crate #3869
|
||||||
|
|
||||||
### API-Changes
|
### API-Changes
|
||||||
|
|
||||||
|
|||||||
5
Cargo.lock
generated
5
Cargo.lock
generated
@@ -887,6 +887,7 @@ dependencies = [
|
|||||||
"encoded-words",
|
"encoded-words",
|
||||||
"escaper",
|
"escaper",
|
||||||
"fast-socks5",
|
"fast-socks5",
|
||||||
|
"format-flowed",
|
||||||
"futures",
|
"futures",
|
||||||
"futures-lite",
|
"futures-lite",
|
||||||
"hex",
|
"hex",
|
||||||
@@ -1445,6 +1446,10 @@ dependencies = [
|
|||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "format-flowed"
|
||||||
|
version = "1.0.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures"
|
name = "futures"
|
||||||
version = "0.3.25"
|
version = "0.3.25"
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ panic = 'abort'
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
deltachat_derive = { path = "./deltachat_derive" }
|
deltachat_derive = { path = "./deltachat_derive" }
|
||||||
|
format-flowed = { path = "./format-flowed" }
|
||||||
|
|
||||||
ansi_term = { version = "0.12.1", optional = true }
|
ansi_term = { version = "0.12.1", optional = true }
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
@@ -99,7 +100,8 @@ members = [
|
|||||||
"deltachat-ffi",
|
"deltachat-ffi",
|
||||||
"deltachat_derive",
|
"deltachat_derive",
|
||||||
"deltachat-jsonrpc",
|
"deltachat-jsonrpc",
|
||||||
"deltachat-rpc-server"
|
"deltachat-rpc-server",
|
||||||
|
"format-flowed",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[example]]
|
[[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
|
/// RFC 2646 technique is used to insert soft line breaks, so DelSp
|
||||||
/// SHOULD be set to "no" when sending.
|
/// 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();
|
let mut result = String::new();
|
||||||
|
|
||||||
for line in text.split('\n') {
|
for line in text.split('\n') {
|
||||||
@@ -147,8 +147,6 @@ pub fn unformat_flowed(text: &str, delsp: bool) -> String {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::test_utils::TestContext;
|
|
||||||
use anyhow::Result;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_format_flowed() {
|
fn test_format_flowed() {
|
||||||
@@ -220,51 +218,4 @@ mod tests {
|
|||||||
> unwrapped on the receiver";
|
> unwrapped on the receiver";
|
||||||
assert_eq!(format_flowed_quote(quote), expected);
|
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;
|
mod scheduler;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod job;
|
mod job;
|
||||||
mod format_flowed;
|
|
||||||
pub mod key;
|
pub mod key;
|
||||||
mod keyring;
|
mod keyring;
|
||||||
pub mod location;
|
pub mod location;
|
||||||
|
|||||||
@@ -2340,4 +2340,51 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(Viewtype::Webxdc, Viewtype::from_i32(80).unwrap());
|
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 anyhow::{bail, ensure, Context as _, Result};
|
||||||
use chrono::TimeZone;
|
use chrono::TimeZone;
|
||||||
|
use format_flowed::{format_flowed, format_flowed_quote};
|
||||||
use lettre_email::{mime, Address, Header, MimeMultipartType, PartBuilder};
|
use lettre_email::{mime, Address, Header, MimeMultipartType, PartBuilder};
|
||||||
use tokio::fs;
|
use tokio::fs;
|
||||||
|
|
||||||
@@ -15,7 +16,6 @@ use crate::contact::Contact;
|
|||||||
use crate::context::{get_version_str, Context};
|
use crate::context::{get_version_str, Context};
|
||||||
use crate::e2ee::EncryptHelper;
|
use crate::e2ee::EncryptHelper;
|
||||||
use crate::ephemeral::Timer as EphemeralTimer;
|
use crate::ephemeral::Timer as EphemeralTimer;
|
||||||
use crate::format_flowed::{format_flowed, format_flowed_quote};
|
|
||||||
use crate::html::new_html_mimepart;
|
use crate::html::new_html_mimepart;
|
||||||
use crate::location;
|
use crate::location;
|
||||||
use crate::message::{self, Message, MsgId, Viewtype};
|
use crate::message::{self, Message, MsgId, Viewtype};
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ use std::str;
|
|||||||
|
|
||||||
use anyhow::{bail, Context as _, Result};
|
use anyhow::{bail, Context as _, Result};
|
||||||
use deltachat_derive::{FromSql, ToSql};
|
use deltachat_derive::{FromSql, ToSql};
|
||||||
|
use format_flowed::unformat_flowed;
|
||||||
use lettre_email::mime::{self, Mime};
|
use lettre_email::mime::{self, Mime};
|
||||||
use mailparse::{addrparse_header, DispositionType, MailHeader, MailHeaderMap, SingleInfo};
|
use mailparse::{addrparse_header, DispositionType, MailHeader, MailHeaderMap, SingleInfo};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
@@ -24,7 +25,6 @@ use crate::decrypt::{
|
|||||||
};
|
};
|
||||||
use crate::dehtml::dehtml;
|
use crate::dehtml::dehtml;
|
||||||
use crate::events::EventType;
|
use crate::events::EventType;
|
||||||
use crate::format_flowed::unformat_flowed;
|
|
||||||
use crate::headerdef::{HeaderDef, HeaderDefMap};
|
use crate::headerdef::{HeaderDef, HeaderDefMap};
|
||||||
use crate::key::{DcKey, Fingerprint, SignedPublicKey, SignedSecretKey};
|
use crate::key::{DcKey, Fingerprint, SignedPublicKey, SignedSecretKey};
|
||||||
use crate::keyring::Keyring;
|
use crate::keyring::Keyring;
|
||||||
|
|||||||
Reference in New Issue
Block a user