This commit is contained in:
Quentin 2023-07-14 19:12:34 +02:00
parent 662d82aee9
commit a95095ed5d
Signed by: quentin
GPG key ID: E9602264D639FF68
6 changed files with 165 additions and 2 deletions

View file

@ -20,3 +20,4 @@ pub mod trace;
// MIME related // MIME related
pub mod mime; pub mod mime;
pub mod encoding; pub mod encoding;
pub mod part;

49
src/fragments/part.rs Normal file
View file

@ -0,0 +1,49 @@
use nom::{
IResult,
bytes::complete::tag,
sequence::tuple,
combinator::opt,
};
use crate::fragments::mime::{Mechanism, Type};
use crate::fragments::model::MessageId;
use crate::fragments::misc_token::Unstructured;
use crate::fragments::whitespace::perm_crlf;
#[derive(Debug, PartialEq, Default)]
pub struct PartHeader<'a> {
pub content_type: Option<&'a Type<'a>>,
pub content_transfer_encoding: Option<&'a Mechanism<'a>>,
pub content_id: Option<&'a MessageId<'a>>,
pub content_description: Option<&'a Unstructured>,
}
#[derive(Debug, PartialEq)]
pub enum PartNode<'a> {
Discrete(PartHeader<'a>, &'a [u8]),
Composite(PartHeader<'a>, Vec<PartNode<'a>>),
}
pub enum Delimiter {
Next,
Last
}
pub fn boundary(boundary: &[u8]) -> impl Fn(&[u8]) -> IResult<&[u8], Delimiter> {
|input: &[u8]| {
let (_, _, _, last, _) = tuple((perm_crlf, tag(b"--"), tag(boundary), opt(tag(b"--")), perm_crlf))(input)?;
match last {
Some(_) => Delimiter::Last,
None => Delimiter::Next,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_boundary() {
}
}

View file

@ -0,0 +1,17 @@
use crate::fragments::part;
use crate::fragments::section::Section;
use crate::multipass::header_section;
#[derive(Debug, PartialEq)]
pub struct Parsed<'a> {
pub fields: Section<'a>,
pub body: part::PartNode<'a>,
}
pub fn new<'a>(p: &'a header_section::Parsed<'a>) -> Parsed<'a> {
todo!();
/*Parsed {
fields: p.fields,
body: p.body,
}*/
}

View file

@ -1,5 +1,5 @@
use crate::fragments::section::Section; use crate::fragments::section::Section;
use crate::multipass::field_eager; use crate::multipass::{field_eager, body_structure};
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct Parsed<'a> { pub struct Parsed<'a> {
@ -14,6 +14,12 @@ pub fn new<'a>(p: &'a field_eager::Parsed<'a>) -> Parsed<'a> {
} }
} }
impl<'a> Parsed<'a> {
pub fn body_structure(&self) -> body_structure::Parsed<'a> {
todo!()
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View file

@ -4,3 +4,4 @@ pub mod field_lazy;
pub mod guess_charset; pub mod guess_charset;
pub mod header_section; pub mod header_section;
pub mod segment; pub mod segment;
pub mod body_structure;

View file

@ -1,5 +1,5 @@
use chrono::{FixedOffset, TimeZone}; use chrono::{FixedOffset, TimeZone};
use imf_codec::fragments::{misc_token, model, section, trace}; use imf_codec::fragments::{misc_token, model, section, part, trace};
use imf_codec::multipass; use imf_codec::multipass;
use std::collections::HashMap; use std::collections::HashMap;
@ -246,3 +246,92 @@ for all folk to come=
); );
}) })
} }
fn parser_bodystruct<'a, F>(input: &'a [u8], func: F) -> ()
where
F: FnOnce(&part::PartNode) -> (),
{
let seg = multipass::segment::new(input).unwrap();
let charset = seg.charset();
let fields = charset.fields().unwrap();
let field_names = fields.names();
let field_body = field_names.body();
let section = field_body.section();
let bodystruct = section.body_structure();
func(&bodystruct.body);
}
#[test]
fn test_multipart() {
let fullmail: &[u8] = r#"Date: Sat, 8 Jul 2023 07:14:29 +0200
From: Grrrnd Zero <grrrndzero@example.org>
To: John Doe <jdoe@machine.example>
Subject: Re: Saying Hello
Message-ID: <NTAxNzA2AC47634Y366BAMTY4ODc5MzQyODY0ODY5@www.grrrndzero.org>
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="b1_e376dc71bafc953c0b0fdeb9983a9956"
Content-Transfer-Encoding: 7bit
This is a multi-part message in MIME format.
--b1_e376dc71bafc953c0b0fdeb9983a9956
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable
GZ
OoOoO
oOoOoOoOo
oOoOoOoOoOoOoOoOo
oOoOoOoOoOoOoOoOoOoOoOo
oOoOoOoOoOoOoOoOoOoOoOoOoOoOo
OoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoO
--b1_e376dc71bafc953c0b0fdeb9983a9956
Content-Type: text/html; charset=us-ascii
<div style="text-align: center;"><strong>GZ</strong><br />
OoOoO<br />
oOoOoOoOo<br />
oOoOoOoOoOoOoOoOo<br />
oOoOoOoOoOoOoOoOoOoOoOo<br />
oOoOoOoOoOoOoOoOoOoOoOoOoOoOo<br />
OoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoO<br />
--b1_e376dc71bafc953c0b0fdeb9983a9956--
"#.as_bytes();
parser_bodystruct(fullmail, |part| {
assert_eq!(part, &part::PartNode::Composite(
part::PartHeader {
..part::PartHeader::default()
},
vec![
part::PartNode::Discrete(
part::PartHeader {
..part::PartHeader::default()
},
r#"GZ
OoOoO
oOoOoOoOo
oOoOoOoOoOoOoOoOo
oOoOoOoOoOoOoOoOoOoOoOo
oOoOoOoOoOoOoOoOoOoOoOoOoOoOo
OoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoO"#.as_bytes()
),
part::PartNode::Discrete(
part::PartHeader {
..part::PartHeader::default()
},
r#"<div style="text-align: center;"><strong>GZ</strong><br />
OoOoO<br />
oOoOoOoOo<br />
oOoOoOoOoOoOoOoOo<br />
oOoOoOoOoOoOoOoOoOoOoOo<br />
oOoOoOoOoOoOoOoOoOoOoOoOoOoOo<br />
OoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoO<br />"#.as_bytes()
),
]));
});
}