wip
This commit is contained in:
parent
662d82aee9
commit
a95095ed5d
6 changed files with 165 additions and 2 deletions
|
@ -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
49
src/fragments/part.rs
Normal 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() {
|
||||||
|
}
|
||||||
|
}
|
17
src/multipass/body_structure.rs
Normal file
17
src/multipass/body_structure.rs
Normal 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,
|
||||||
|
}*/
|
||||||
|
}
|
|
@ -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::*;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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()
|
||||||
|
),
|
||||||
|
]));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue