mirror of
https://github.com/chatmail/core.git
synced 2026-06-27 01:56:36 +03:00
Compare commits
10 Commits
fix597
...
mmime-type
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c6df6dbf6 | ||
|
|
416a1751a2 | ||
|
|
475ad0f93a | ||
|
|
625bc90c30 | ||
|
|
347a4d110a | ||
|
|
50ca75398f | ||
|
|
c18bdc39e5 | ||
|
|
8aa1a0cb3a | ||
|
|
c78753e8fa | ||
|
|
2abfd037ca |
@@ -50,10 +50,7 @@ pub unsafe fn display_mime(mut mime: *mut Mailmime) {
|
||||
}
|
||||
MAILMIME_MESSAGE => {
|
||||
if !(*mime).mm_data.mm_message.mm_fields.is_null() {
|
||||
if !(*(*(*mime).mm_data.mm_message.mm_fields).fld_list)
|
||||
.first
|
||||
.is_null()
|
||||
{
|
||||
if !(*(*mime).mm_data.mm_message.mm_fields).0.is_empty() {
|
||||
println!("headers begin");
|
||||
display_fields((*mime).mm_data.mm_message.mm_fields);
|
||||
println!("headers end");
|
||||
@@ -207,115 +204,66 @@ unsafe fn display_mime_fields(mut fields: *mut mailmime_fields) {
|
||||
unsafe fn display_date_time(mut d: *mut mailimf_date_time) {
|
||||
print!(
|
||||
"{:02}/{:02}/{:02} {:02}:{:02}:{:02} +{:04}",
|
||||
(*d).dt_day,
|
||||
(*d).dt_month,
|
||||
(*d).dt_year,
|
||||
(*d).dt_hour,
|
||||
(*d).dt_min,
|
||||
(*d).dt_sec,
|
||||
(*d).dt_zone,
|
||||
(*d).day,
|
||||
(*d).month,
|
||||
(*d).year,
|
||||
(*d).hour,
|
||||
(*d).min,
|
||||
(*d).sec,
|
||||
(*d).zone,
|
||||
);
|
||||
}
|
||||
|
||||
unsafe fn display_orig_date(mut orig_date: *mut mailimf_orig_date) {
|
||||
display_date_time((*orig_date).dt_date_time);
|
||||
}
|
||||
unsafe fn display_mailbox(mut mb: *mut mailimf_mailbox) {
|
||||
if !(*mb).mb_display_name.is_null() {
|
||||
print!(
|
||||
"{}",
|
||||
CStr::from_ptr((*mb).mb_display_name).to_str().unwrap()
|
||||
);
|
||||
if !(*mb).display_name.is_null() {
|
||||
print!("{}", CStr::from_ptr((*mb).display_name).to_str().unwrap());
|
||||
}
|
||||
print!("<{}>", CStr::from_ptr((*mb).mb_addr_spec).to_str().unwrap());
|
||||
print!("<{}>", CStr::from_ptr((*mb).addr_spec).to_str().unwrap());
|
||||
}
|
||||
unsafe fn display_mailbox_list(mut mb_list: *mut mailimf_mailbox_list) {
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
cur = (*(*mb_list).mb_list).first;
|
||||
while !cur.is_null() {
|
||||
let mut mb: *mut mailimf_mailbox = 0 as *mut mailimf_mailbox;
|
||||
mb = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailimf_mailbox;
|
||||
display_mailbox(mb);
|
||||
if !if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
.is_null()
|
||||
{
|
||||
for (i, mb) in (*mb_list).0.iter().enumerate() {
|
||||
display_mailbox(*mb);
|
||||
if i < (*mb_list).0.len() - 1 {
|
||||
print!(", ");
|
||||
}
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn display_group(mut group: *mut mailimf_group) {
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
print!(
|
||||
"{}: ",
|
||||
CStr::from_ptr((*group).grp_display_name).to_str().unwrap()
|
||||
CStr::from_ptr((*group).display_name).to_str().unwrap()
|
||||
);
|
||||
cur = (*(*(*group).grp_mb_list).mb_list).first;
|
||||
while !cur.is_null() {
|
||||
let mut mb: *mut mailimf_mailbox = 0 as *mut mailimf_mailbox;
|
||||
mb = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailimf_mailbox;
|
||||
display_mailbox(mb);
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
for mb in &(*(*group).mb_list).0 {
|
||||
display_mailbox(*mb);
|
||||
}
|
||||
print!("; ");
|
||||
}
|
||||
unsafe fn display_address(mut a: *mut mailimf_address) {
|
||||
match (*a).ad_type {
|
||||
2 => {
|
||||
display_group((*a).ad_data.ad_group);
|
||||
|
||||
unsafe fn display_address(a: *mut mailimf_address) {
|
||||
match *a {
|
||||
mailimf_address::Group(data) => {
|
||||
display_group(data);
|
||||
}
|
||||
1 => {
|
||||
display_mailbox((*a).ad_data.ad_mailbox);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
unsafe fn display_address_list(mut addr_list: *mut mailimf_address_list) {
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
cur = (*(*addr_list).ad_list).first;
|
||||
while !cur.is_null() {
|
||||
let mut addr: *mut mailimf_address = 0 as *mut mailimf_address;
|
||||
addr = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailimf_address;
|
||||
display_address(addr);
|
||||
if !if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
.is_null()
|
||||
{
|
||||
print!(", ");
|
||||
}
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
mailimf_address::Mailbox(data) => {
|
||||
display_mailbox(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn display_address_list(addr_list: *mut mailimf_address_list) {
|
||||
for (i, addr) in (*addr_list).0.iter().enumerate() {
|
||||
display_address(*addr);
|
||||
if i < (*addr_list).0.len() - 1 {
|
||||
print!(", ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn display_from(mut from: *mut mailimf_from) {
|
||||
display_mailbox_list((*from).frm_mb_list);
|
||||
}
|
||||
@@ -328,59 +276,44 @@ unsafe fn display_cc(mut cc: *mut mailimf_cc) {
|
||||
unsafe fn display_subject(mut subject: *mut mailimf_subject) {
|
||||
print!("{}", CStr::from_ptr((*subject).sbj_value).to_str().unwrap());
|
||||
}
|
||||
unsafe fn display_field(mut field: *mut mailimf_field) {
|
||||
match (*field).fld_type {
|
||||
9 => {
|
||||
unsafe fn display_field(field: &mailimf_field) {
|
||||
match *field {
|
||||
mailimf_field::OrigDate(date) => {
|
||||
print!("Date: ");
|
||||
display_orig_date((*field).fld_data.fld_orig_date);
|
||||
display_orig_date(date);
|
||||
println!("");
|
||||
}
|
||||
10 => {
|
||||
mailimf_field::From(from) => {
|
||||
print!("From: ");
|
||||
display_from((*field).fld_data.fld_from);
|
||||
display_from(from);
|
||||
println!("");
|
||||
}
|
||||
13 => {
|
||||
mailimf_field::To(to) => {
|
||||
print!("To: ");
|
||||
display_to((*field).fld_data.fld_to);
|
||||
display_to(to);
|
||||
println!("");
|
||||
}
|
||||
14 => {
|
||||
mailimf_field::Cc(cc) => {
|
||||
print!("Cc: ");
|
||||
display_cc((*field).fld_data.fld_cc);
|
||||
display_cc(cc);
|
||||
println!("");
|
||||
}
|
||||
19 => {
|
||||
mailimf_field::Subject(subject) => {
|
||||
print!("Subject: ");
|
||||
display_subject((*field).fld_data.fld_subject);
|
||||
display_subject(subject);
|
||||
println!("");
|
||||
}
|
||||
16 => {
|
||||
mailimf_field::MessageId(message_id) => {
|
||||
println!(
|
||||
"Message-ID: {}",
|
||||
CStr::from_ptr((*(*field).fld_data.fld_message_id).mid_value)
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
CStr::from_ptr((*message_id).mid_value).to_str().unwrap(),
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
unsafe fn display_fields(mut fields: *mut mailimf_fields) {
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
cur = (*(*fields).fld_list).first;
|
||||
while !cur.is_null() {
|
||||
let mut f: *mut mailimf_field = 0 as *mut mailimf_field;
|
||||
f = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailimf_field;
|
||||
unsafe fn display_fields(fields: *mut mailimf_fields) {
|
||||
for f in &(*fields).0 {
|
||||
display_field(f);
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,43 +1,20 @@
|
||||
use crate::clist::*;
|
||||
use crate::mailimf::types::*;
|
||||
use crate::other::*;
|
||||
|
||||
/*
|
||||
this function creates a new mailimf_fields structure with no fields
|
||||
*/
|
||||
pub unsafe fn mailimf_fields_new_empty() -> *mut mailimf_fields {
|
||||
let mut list: *mut clist = 0 as *mut clist;
|
||||
let mut fields_list: *mut mailimf_fields = 0 as *mut mailimf_fields;
|
||||
list = clist_new();
|
||||
if list.is_null() {
|
||||
return 0 as *mut mailimf_fields;
|
||||
}
|
||||
fields_list = mailimf_fields_new(list);
|
||||
if fields_list.is_null() {
|
||||
return 0 as *mut mailimf_fields;
|
||||
}
|
||||
return fields_list;
|
||||
mailimf_fields_new(Vec::new())
|
||||
}
|
||||
|
||||
/*
|
||||
this function adds a field to the mailimf_fields structure
|
||||
|
||||
@return MAILIMF_NO_ERROR will be returned on success,
|
||||
other code will be returned otherwise
|
||||
*/
|
||||
pub unsafe fn mailimf_fields_add(
|
||||
mut fields: *mut mailimf_fields,
|
||||
mut field: *mut mailimf_field,
|
||||
) -> libc::c_int {
|
||||
let mut r: libc::c_int = 0;
|
||||
r = clist_insert_after(
|
||||
(*fields).fld_list,
|
||||
(*(*fields).fld_list).last,
|
||||
field as *mut libc::c_void,
|
||||
);
|
||||
if r < 0i32 {
|
||||
return MAILIMF_ERROR_MEMORY as libc::c_int;
|
||||
}
|
||||
return MAILIMF_NO_ERROR as libc::c_int;
|
||||
pub unsafe fn mailimf_fields_add(fields: *mut mailimf_fields, field: mailimf_field) {
|
||||
(*fields).0.push(field)
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -47,43 +24,11 @@ pub unsafe fn mailimf_fields_add(
|
||||
@param value should be allocated with malloc()
|
||||
*/
|
||||
pub unsafe fn mailimf_field_new_custom(
|
||||
mut name: *mut libc::c_char,
|
||||
mut value: *mut libc::c_char,
|
||||
) -> *mut mailimf_field {
|
||||
let mut opt_field: *mut mailimf_optional_field = 0 as *mut mailimf_optional_field;
|
||||
let mut field: *mut mailimf_field = 0 as *mut mailimf_field;
|
||||
opt_field = mailimf_optional_field_new(name, value);
|
||||
if !opt_field.is_null() {
|
||||
field = mailimf_field_new(
|
||||
MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int,
|
||||
0 as *mut mailimf_return,
|
||||
0 as *mut mailimf_orig_date,
|
||||
0 as *mut mailimf_from,
|
||||
0 as *mut mailimf_sender,
|
||||
0 as *mut mailimf_to,
|
||||
0 as *mut mailimf_cc,
|
||||
0 as *mut mailimf_bcc,
|
||||
0 as *mut mailimf_message_id,
|
||||
0 as *mut mailimf_orig_date,
|
||||
0 as *mut mailimf_from,
|
||||
0 as *mut mailimf_sender,
|
||||
0 as *mut mailimf_reply_to,
|
||||
0 as *mut mailimf_to,
|
||||
0 as *mut mailimf_cc,
|
||||
0 as *mut mailimf_bcc,
|
||||
0 as *mut mailimf_message_id,
|
||||
0 as *mut mailimf_in_reply_to,
|
||||
0 as *mut mailimf_references,
|
||||
0 as *mut mailimf_subject,
|
||||
0 as *mut mailimf_comments,
|
||||
0 as *mut mailimf_keywords,
|
||||
opt_field,
|
||||
);
|
||||
if field.is_null() {
|
||||
mailimf_optional_field_free(opt_field);
|
||||
} else {
|
||||
return field;
|
||||
}
|
||||
}
|
||||
return 0 as *mut mailimf_field;
|
||||
name: *mut libc::c_char,
|
||||
value: *mut libc::c_char,
|
||||
) -> mailimf_field {
|
||||
let opt_field = mailimf_optional_field_new(name, value);
|
||||
assert!(!opt_field.is_null(), "failed memory allocation");
|
||||
|
||||
mailimf_field::OptionalField(opt_field)
|
||||
}
|
||||
|
||||
@@ -166,35 +166,19 @@ pub unsafe fn mailimf_fields_write_driver(
|
||||
mut do_write: Option<
|
||||
unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int,
|
||||
>,
|
||||
mut data: *mut libc::c_void,
|
||||
mut col: *mut libc::c_int,
|
||||
mut fields: *mut mailimf_fields,
|
||||
data: *mut libc::c_void,
|
||||
col: *mut libc::c_int,
|
||||
fields: *mut mailimf_fields,
|
||||
) -> libc::c_int {
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
cur = (*(*fields).fld_list).first;
|
||||
while !cur.is_null() {
|
||||
let mut r: libc::c_int = 0;
|
||||
r = mailimf_field_write_driver(
|
||||
do_write,
|
||||
data,
|
||||
col,
|
||||
(if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailimf_field,
|
||||
);
|
||||
for cur in &(*fields).0 {
|
||||
let r = mailimf_field_write_driver(do_write, data, col, cur);
|
||||
if r != MAILIMF_NO_ERROR as libc::c_int {
|
||||
return r;
|
||||
}
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
return MAILIMF_NO_ERROR as libc::c_int;
|
||||
MAILIMF_NO_ERROR as libc::c_int
|
||||
}
|
||||
|
||||
/*
|
||||
mailimf_field_write writes a field to a given stream
|
||||
|
||||
@@ -207,118 +191,38 @@ pub unsafe fn mailimf_field_write_driver(
|
||||
mut do_write: Option<
|
||||
unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int,
|
||||
>,
|
||||
mut data: *mut libc::c_void,
|
||||
mut col: *mut libc::c_int,
|
||||
mut field: *mut mailimf_field,
|
||||
data: *mut libc::c_void,
|
||||
col: *mut libc::c_int,
|
||||
field: &mailimf_field,
|
||||
) -> libc::c_int {
|
||||
let mut r: libc::c_int = 0;
|
||||
match (*field).fld_type {
|
||||
1 => {
|
||||
r = mailimf_return_write_driver(do_write, data, col, (*field).fld_data.fld_return_path)
|
||||
}
|
||||
2 => {
|
||||
r = mailimf_resent_date_write_driver(
|
||||
do_write,
|
||||
data,
|
||||
col,
|
||||
(*field).fld_data.fld_resent_date,
|
||||
)
|
||||
}
|
||||
3 => {
|
||||
r = mailimf_resent_from_write_driver(
|
||||
do_write,
|
||||
data,
|
||||
col,
|
||||
(*field).fld_data.fld_resent_from,
|
||||
)
|
||||
}
|
||||
4 => {
|
||||
r = mailimf_resent_sender_write_driver(
|
||||
do_write,
|
||||
data,
|
||||
col,
|
||||
(*field).fld_data.fld_resent_sender,
|
||||
)
|
||||
}
|
||||
5 => {
|
||||
r = mailimf_resent_to_write_driver(do_write, data, col, (*field).fld_data.fld_resent_to)
|
||||
}
|
||||
6 => {
|
||||
r = mailimf_resent_cc_write_driver(do_write, data, col, (*field).fld_data.fld_resent_cc)
|
||||
}
|
||||
7 => {
|
||||
r = mailimf_resent_bcc_write_driver(
|
||||
do_write,
|
||||
data,
|
||||
col,
|
||||
(*field).fld_data.fld_resent_bcc,
|
||||
)
|
||||
}
|
||||
8 => {
|
||||
r = mailimf_resent_msg_id_write_driver(
|
||||
do_write,
|
||||
data,
|
||||
col,
|
||||
(*field).fld_data.fld_resent_msg_id,
|
||||
)
|
||||
}
|
||||
9 => {
|
||||
r = mailimf_orig_date_write_driver(do_write, data, col, (*field).fld_data.fld_orig_date)
|
||||
}
|
||||
10 => r = mailimf_from_write_driver(do_write, data, col, (*field).fld_data.fld_from),
|
||||
11 => r = mailimf_sender_write_driver(do_write, data, col, (*field).fld_data.fld_sender),
|
||||
12 => {
|
||||
r = mailimf_reply_to_write_driver(do_write, data, col, (*field).fld_data.fld_reply_to)
|
||||
}
|
||||
13 => r = mailimf_to_write_driver(do_write, data, col, (*field).fld_data.fld_to),
|
||||
14 => r = mailimf_cc_write_driver(do_write, data, col, (*field).fld_data.fld_cc),
|
||||
15 => r = mailimf_bcc_write_driver(do_write, data, col, (*field).fld_data.fld_bcc),
|
||||
16 => {
|
||||
r = mailimf_message_id_write_driver(
|
||||
do_write,
|
||||
data,
|
||||
col,
|
||||
(*field).fld_data.fld_message_id,
|
||||
)
|
||||
}
|
||||
17 => {
|
||||
r = mailimf_in_reply_to_write_driver(
|
||||
do_write,
|
||||
data,
|
||||
col,
|
||||
(*field).fld_data.fld_in_reply_to,
|
||||
)
|
||||
}
|
||||
18 => {
|
||||
r = mailimf_references_write_driver(
|
||||
do_write,
|
||||
data,
|
||||
col,
|
||||
(*field).fld_data.fld_references,
|
||||
)
|
||||
}
|
||||
19 => r = mailimf_subject_write_driver(do_write, data, col, (*field).fld_data.fld_subject),
|
||||
20 => {
|
||||
r = mailimf_comments_write_driver(do_write, data, col, (*field).fld_data.fld_comments)
|
||||
}
|
||||
21 => {
|
||||
r = mailimf_keywords_write_driver(do_write, data, col, (*field).fld_data.fld_keywords)
|
||||
}
|
||||
22 => {
|
||||
r = mailimf_optional_field_write_driver(
|
||||
do_write,
|
||||
data,
|
||||
col,
|
||||
(*field).fld_data.fld_optional_field,
|
||||
)
|
||||
}
|
||||
_ => r = MAILIMF_ERROR_INVAL as libc::c_int,
|
||||
use mailimf_field::*;
|
||||
|
||||
match field {
|
||||
ReturnPath(path) => mailimf_return_write_driver(do_write, data, col, *path),
|
||||
ResentDate(date) => mailimf_resent_date_write_driver(do_write, data, col, *date),
|
||||
ResentFrom(from) => mailimf_resent_from_write_driver(do_write, data, col, *from),
|
||||
ResentSender(sender) => mailimf_resent_sender_write_driver(do_write, data, col, *sender),
|
||||
ResentTo(to) => mailimf_resent_to_write_driver(do_write, data, col, *to),
|
||||
ResentCc(cc) => mailimf_resent_cc_write_driver(do_write, data, col, *cc),
|
||||
ResentBcc(bcc) => mailimf_resent_bcc_write_driver(do_write, data, col, *bcc),
|
||||
ResentMsgId(id) => mailimf_resent_msg_id_write_driver(do_write, data, col, *id),
|
||||
OrigDate(date) => mailimf_orig_date_write_driver(do_write, data, col, *date),
|
||||
From(from) => mailimf_from_write_driver(do_write, data, col, *from),
|
||||
Sender(sender) => mailimf_sender_write_driver(do_write, data, col, *sender),
|
||||
ReplyTo(to) => mailimf_reply_to_write_driver(do_write, data, col, *to),
|
||||
To(to) => mailimf_to_write_driver(do_write, data, col, *to),
|
||||
Cc(cc) => mailimf_cc_write_driver(do_write, data, col, *cc),
|
||||
Bcc(bcc) => mailimf_bcc_write_driver(do_write, data, col, *bcc),
|
||||
MessageId(id) => mailimf_message_id_write_driver(do_write, data, col, *id),
|
||||
InReplyTo(to) => mailimf_in_reply_to_write_driver(do_write, data, col, *to),
|
||||
References(refs) => mailimf_references_write_driver(do_write, data, col, *refs),
|
||||
Subject(s) => mailimf_subject_write_driver(do_write, data, col, *s),
|
||||
Comments(c) => mailimf_comments_write_driver(do_write, data, col, *c),
|
||||
Keywords(k) => mailimf_keywords_write_driver(do_write, data, col, *k),
|
||||
OptionalField(f) => mailimf_optional_field_write_driver(do_write, data, col, *f),
|
||||
}
|
||||
if r != MAILIMF_NO_ERROR as libc::c_int {
|
||||
return r;
|
||||
}
|
||||
return MAILIMF_NO_ERROR as libc::c_int;
|
||||
}
|
||||
|
||||
unsafe fn mailimf_optional_field_write_driver(
|
||||
mut do_write: Option<
|
||||
unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int,
|
||||
@@ -328,16 +232,10 @@ unsafe fn mailimf_optional_field_write_driver(
|
||||
mut field: *mut mailimf_optional_field,
|
||||
) -> libc::c_int {
|
||||
let mut r: libc::c_int = 0;
|
||||
if strlen((*field).fld_name).wrapping_add(2i32 as libc::size_t) > 998i32 as libc::size_t {
|
||||
if strlen((*field).name).wrapping_add(2i32 as libc::size_t) > 998i32 as libc::size_t {
|
||||
return MAILIMF_ERROR_INVAL as libc::c_int;
|
||||
}
|
||||
r = mailimf_string_write_driver(
|
||||
do_write,
|
||||
data,
|
||||
col,
|
||||
(*field).fld_name,
|
||||
strlen((*field).fld_name),
|
||||
);
|
||||
r = mailimf_string_write_driver(do_write, data, col, (*field).name, strlen((*field).name));
|
||||
if r != MAILIMF_NO_ERROR as libc::c_int {
|
||||
return r;
|
||||
}
|
||||
@@ -355,8 +253,8 @@ unsafe fn mailimf_optional_field_write_driver(
|
||||
do_write,
|
||||
data,
|
||||
col,
|
||||
(*field).fld_value,
|
||||
strlen((*field).fld_value),
|
||||
(*field).value,
|
||||
strlen((*field).value),
|
||||
);
|
||||
if r != MAILIMF_NO_ERROR as libc::c_int {
|
||||
return r;
|
||||
@@ -684,7 +582,7 @@ unsafe fn mailimf_references_write_driver(
|
||||
if r != MAILIMF_NO_ERROR as libc::c_int {
|
||||
return r;
|
||||
}
|
||||
r = mailimf_msg_id_list_write_driver(do_write, data, col, (*references).mid_list);
|
||||
r = mailimf_msg_id_list_write_driver(do_write, data, col, &(*references).0);
|
||||
if r != MAILIMF_NO_ERROR as libc::c_int {
|
||||
return r;
|
||||
}
|
||||
@@ -701,28 +599,19 @@ unsafe fn mailimf_references_write_driver(
|
||||
return MAILIMF_NO_ERROR as libc::c_int;
|
||||
}
|
||||
unsafe fn mailimf_msg_id_list_write_driver(
|
||||
mut do_write: Option<
|
||||
do_write: Option<
|
||||
unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int,
|
||||
>,
|
||||
mut data: *mut libc::c_void,
|
||||
mut col: *mut libc::c_int,
|
||||
mut mid_list: *mut clist,
|
||||
data: *mut libc::c_void,
|
||||
col: *mut libc::c_int,
|
||||
mid_list: &Vec<*mut libc::c_char>,
|
||||
) -> libc::c_int {
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
let mut r: libc::c_int = 0;
|
||||
let mut first: libc::c_int = 0;
|
||||
first = 1i32;
|
||||
cur = (*mid_list).first;
|
||||
while !cur.is_null() {
|
||||
let mut msgid: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut len: size_t = 0;
|
||||
msgid = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut libc::c_char;
|
||||
len = strlen(msgid);
|
||||
if 0 == first {
|
||||
let mut r = 0;
|
||||
let mut first = true;
|
||||
|
||||
for msgid in mid_list {
|
||||
let len = strlen(*msgid);
|
||||
if !first {
|
||||
if *col > 1i32 {
|
||||
if (*col as libc::size_t).wrapping_add(len) >= 72i32 as libc::size_t {
|
||||
r = mailimf_string_write_driver(
|
||||
@@ -735,11 +624,11 @@ unsafe fn mailimf_msg_id_list_write_driver(
|
||||
if r != MAILIMF_NO_ERROR as libc::c_int {
|
||||
return r;
|
||||
}
|
||||
first = 1i32
|
||||
first = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if 0 == first {
|
||||
if !first {
|
||||
r = mailimf_string_write_driver(
|
||||
do_write,
|
||||
data,
|
||||
@@ -751,7 +640,7 @@ unsafe fn mailimf_msg_id_list_write_driver(
|
||||
return r;
|
||||
}
|
||||
} else {
|
||||
first = 0i32
|
||||
first = false;
|
||||
}
|
||||
r = mailimf_string_write_driver(
|
||||
do_write,
|
||||
@@ -763,7 +652,7 @@ unsafe fn mailimf_msg_id_list_write_driver(
|
||||
if r != MAILIMF_NO_ERROR as libc::c_int {
|
||||
return r;
|
||||
}
|
||||
r = mailimf_string_write_driver(do_write, data, col, msgid, len);
|
||||
r = mailimf_string_write_driver(do_write, data, col, *msgid, len);
|
||||
if r != MAILIMF_NO_ERROR as libc::c_int {
|
||||
return r;
|
||||
}
|
||||
@@ -777,14 +666,11 @@ unsafe fn mailimf_msg_id_list_write_driver(
|
||||
if r != MAILIMF_NO_ERROR as libc::c_int {
|
||||
return r;
|
||||
}
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
return MAILIMF_NO_ERROR as libc::c_int;
|
||||
|
||||
MAILIMF_NO_ERROR as libc::c_int
|
||||
}
|
||||
|
||||
unsafe fn mailimf_in_reply_to_write_driver(
|
||||
mut do_write: Option<
|
||||
unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int,
|
||||
@@ -804,7 +690,7 @@ unsafe fn mailimf_in_reply_to_write_driver(
|
||||
if r != MAILIMF_NO_ERROR as libc::c_int {
|
||||
return r;
|
||||
}
|
||||
r = mailimf_msg_id_list_write_driver(do_write, data, col, (*in_reply_to).mid_list);
|
||||
r = mailimf_msg_id_list_write_driver(do_write, data, col, &(*in_reply_to).0);
|
||||
if r != MAILIMF_NO_ERROR as libc::c_int {
|
||||
return r;
|
||||
}
|
||||
@@ -930,14 +816,8 @@ pub unsafe fn mailimf_address_list_write_driver(
|
||||
let mut r: libc::c_int = 0;
|
||||
let mut first: libc::c_int = 0;
|
||||
first = 1i32;
|
||||
cur = (*(*addr_list).ad_list).first;
|
||||
while !cur.is_null() {
|
||||
let mut addr: *mut mailimf_address = 0 as *mut mailimf_address;
|
||||
addr = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailimf_address;
|
||||
|
||||
for addr in &(*addr_list).0 {
|
||||
if 0 == first {
|
||||
r = mailimf_string_write_driver(
|
||||
do_write,
|
||||
@@ -952,18 +832,14 @@ pub unsafe fn mailimf_address_list_write_driver(
|
||||
} else {
|
||||
first = 0i32
|
||||
}
|
||||
r = mailimf_address_write_driver(do_write, data, col, addr);
|
||||
r = mailimf_address_write_driver(do_write, data, col, *addr);
|
||||
if r != MAILIMF_NO_ERROR as libc::c_int {
|
||||
return r;
|
||||
}
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
return MAILIMF_NO_ERROR as libc::c_int;
|
||||
MAILIMF_NO_ERROR as libc::c_int
|
||||
}
|
||||
|
||||
unsafe fn mailimf_address_write_driver(
|
||||
mut do_write: Option<
|
||||
unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int,
|
||||
@@ -972,24 +848,24 @@ unsafe fn mailimf_address_write_driver(
|
||||
mut col: *mut libc::c_int,
|
||||
mut addr: *mut mailimf_address,
|
||||
) -> libc::c_int {
|
||||
let mut r: libc::c_int = 0;
|
||||
match (*addr).ad_type {
|
||||
1 => {
|
||||
r = mailimf_mailbox_write_driver(do_write, data, col, (*addr).ad_data.ad_mailbox);
|
||||
match *addr {
|
||||
mailimf_address::Mailbox(mb_data) => {
|
||||
let r = mailimf_mailbox_write_driver(do_write, data, col, mb_data);
|
||||
if r != MAILIMF_NO_ERROR as libc::c_int {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
2 => {
|
||||
r = mailimf_group_write_driver(do_write, data, col, (*addr).ad_data.ad_group);
|
||||
mailimf_address::Group(gr_data) => {
|
||||
let r = mailimf_group_write_driver(do_write, data, col, gr_data);
|
||||
if r != MAILIMF_NO_ERROR as libc::c_int {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
return MAILIMF_NO_ERROR as libc::c_int;
|
||||
|
||||
MAILIMF_NO_ERROR as libc::c_int
|
||||
}
|
||||
|
||||
unsafe fn mailimf_group_write_driver(
|
||||
mut do_write: Option<
|
||||
unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int,
|
||||
@@ -1003,8 +879,8 @@ unsafe fn mailimf_group_write_driver(
|
||||
do_write,
|
||||
data,
|
||||
col,
|
||||
(*group).grp_display_name,
|
||||
strlen((*group).grp_display_name),
|
||||
(*group).display_name,
|
||||
strlen((*group).display_name),
|
||||
);
|
||||
if r != MAILIMF_NO_ERROR as libc::c_int {
|
||||
return r;
|
||||
@@ -1019,8 +895,8 @@ unsafe fn mailimf_group_write_driver(
|
||||
if r != MAILIMF_NO_ERROR as libc::c_int {
|
||||
return r;
|
||||
}
|
||||
if !(*group).grp_mb_list.is_null() {
|
||||
r = mailimf_mailbox_list_write_driver(do_write, data, col, (*group).grp_mb_list);
|
||||
if !(*group).mb_list.is_null() {
|
||||
r = mailimf_mailbox_list_write_driver(do_write, data, col, (*group).mb_list);
|
||||
if r != MAILIMF_NO_ERROR as libc::c_int {
|
||||
return r;
|
||||
}
|
||||
@@ -1050,14 +926,8 @@ pub unsafe fn mailimf_mailbox_list_write_driver(
|
||||
let mut r: libc::c_int = 0;
|
||||
let mut first: libc::c_int = 0;
|
||||
first = 1i32;
|
||||
cur = (*(*mb_list).mb_list).first;
|
||||
while !cur.is_null() {
|
||||
let mut mb: *mut mailimf_mailbox = 0 as *mut mailimf_mailbox;
|
||||
mb = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailimf_mailbox;
|
||||
|
||||
for mb in &(*mb_list).0 {
|
||||
if 0 == first {
|
||||
r = mailimf_string_write_driver(
|
||||
do_write,
|
||||
@@ -1072,18 +942,14 @@ pub unsafe fn mailimf_mailbox_list_write_driver(
|
||||
} else {
|
||||
first = 0i32
|
||||
}
|
||||
r = mailimf_mailbox_write_driver(do_write, data, col, mb);
|
||||
r = mailimf_mailbox_write_driver(do_write, data, col, *mb);
|
||||
if r != MAILIMF_NO_ERROR as libc::c_int {
|
||||
return r;
|
||||
}
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
return MAILIMF_NO_ERROR as libc::c_int;
|
||||
MAILIMF_NO_ERROR as libc::c_int
|
||||
}
|
||||
|
||||
unsafe fn mailimf_mailbox_write_driver(
|
||||
mut do_write: Option<
|
||||
unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int,
|
||||
@@ -1094,21 +960,21 @@ unsafe fn mailimf_mailbox_write_driver(
|
||||
) -> libc::c_int {
|
||||
let mut r: libc::c_int = 0;
|
||||
let mut do_fold: libc::c_int = 0;
|
||||
if !(*mb).mb_display_name.is_null() {
|
||||
if 0 != is_atext((*mb).mb_display_name) {
|
||||
if !(*mb).display_name.is_null() {
|
||||
if 0 != is_atext((*mb).display_name) {
|
||||
r = mailimf_header_string_write_driver(
|
||||
do_write,
|
||||
data,
|
||||
col,
|
||||
(*mb).mb_display_name,
|
||||
strlen((*mb).mb_display_name),
|
||||
(*mb).display_name,
|
||||
strlen((*mb).display_name),
|
||||
);
|
||||
if r != MAILIMF_NO_ERROR as libc::c_int {
|
||||
return r;
|
||||
}
|
||||
} else {
|
||||
if !(*mb).mb_display_name.is_null() {
|
||||
if (*col as libc::size_t).wrapping_add(strlen((*mb).mb_display_name))
|
||||
if !(*mb).display_name.is_null() {
|
||||
if (*col as libc::size_t).wrapping_add(strlen((*mb).display_name))
|
||||
>= 72i32 as libc::size_t
|
||||
{
|
||||
r = mailimf_string_write_driver(
|
||||
@@ -1123,15 +989,15 @@ unsafe fn mailimf_mailbox_write_driver(
|
||||
}
|
||||
}
|
||||
}
|
||||
if strlen((*mb).mb_display_name) > (998i32 / 2i32) as libc::size_t {
|
||||
if strlen((*mb).display_name) > (998i32 / 2i32) as libc::size_t {
|
||||
return MAILIMF_ERROR_INVAL as libc::c_int;
|
||||
}
|
||||
r = mailimf_quoted_string_write_driver(
|
||||
do_write,
|
||||
data,
|
||||
col,
|
||||
(*mb).mb_display_name,
|
||||
strlen((*mb).mb_display_name),
|
||||
(*mb).display_name,
|
||||
strlen((*mb).display_name),
|
||||
);
|
||||
if r != MAILIMF_NO_ERROR as libc::c_int {
|
||||
return r;
|
||||
@@ -1140,7 +1006,7 @@ unsafe fn mailimf_mailbox_write_driver(
|
||||
do_fold = 0i32;
|
||||
if *col > 1i32 {
|
||||
if (*col as libc::size_t)
|
||||
.wrapping_add(strlen((*mb).mb_addr_spec))
|
||||
.wrapping_add(strlen((*mb).addr_spec))
|
||||
.wrapping_add(3i32 as libc::size_t)
|
||||
>= 72i32 as libc::size_t
|
||||
{
|
||||
@@ -1181,8 +1047,8 @@ unsafe fn mailimf_mailbox_write_driver(
|
||||
do_write,
|
||||
data,
|
||||
col,
|
||||
(*mb).mb_addr_spec,
|
||||
strlen((*mb).mb_addr_spec),
|
||||
(*mb).addr_spec,
|
||||
strlen((*mb).addr_spec),
|
||||
);
|
||||
if r != MAILIMF_NO_ERROR as libc::c_int {
|
||||
return r;
|
||||
@@ -1198,8 +1064,7 @@ unsafe fn mailimf_mailbox_write_driver(
|
||||
return r;
|
||||
}
|
||||
} else {
|
||||
if (*col as libc::size_t).wrapping_add(strlen((*mb).mb_addr_spec)) >= 72i32 as libc::size_t
|
||||
{
|
||||
if (*col as libc::size_t).wrapping_add(strlen((*mb).addr_spec)) >= 72i32 as libc::size_t {
|
||||
r = mailimf_string_write_driver(
|
||||
do_write,
|
||||
data,
|
||||
@@ -1215,8 +1080,8 @@ unsafe fn mailimf_mailbox_write_driver(
|
||||
do_write,
|
||||
data,
|
||||
col,
|
||||
(*mb).mb_addr_spec,
|
||||
strlen((*mb).mb_addr_spec),
|
||||
(*mb).addr_spec,
|
||||
strlen((*mb).addr_spec),
|
||||
);
|
||||
if r != MAILIMF_NO_ERROR as libc::c_int {
|
||||
return r;
|
||||
@@ -1581,22 +1446,18 @@ unsafe fn mailimf_date_time_write_driver(
|
||||
mut col: *mut libc::c_int,
|
||||
mut date_time: *mut mailimf_date_time,
|
||||
) -> libc::c_int {
|
||||
let wday = dayofweek(
|
||||
(*date_time).dt_year,
|
||||
(*date_time).dt_month,
|
||||
(*date_time).dt_day,
|
||||
);
|
||||
let wday = dayofweek((*date_time).year, (*date_time).month, (*date_time).day);
|
||||
|
||||
let date_str = format!(
|
||||
"{}, {} {} {} {:02}:{:02}:{:02} {:+05}",
|
||||
week_of_day_str[wday as usize],
|
||||
(*date_time).dt_day,
|
||||
month_str[((*date_time).dt_month - 1i32) as usize],
|
||||
(*date_time).dt_year,
|
||||
(*date_time).dt_hour,
|
||||
(*date_time).dt_min,
|
||||
(*date_time).dt_sec,
|
||||
(*date_time).dt_zone,
|
||||
wday,
|
||||
(*date_time).day,
|
||||
month_str[((*date_time).month - 1) as usize],
|
||||
(*date_time).year,
|
||||
(*date_time).hour,
|
||||
(*date_time).min,
|
||||
(*date_time).sec,
|
||||
(*date_time).zone,
|
||||
);
|
||||
let date_str_c = std::ffi::CString::new(date_str).unwrap();
|
||||
let r = mailimf_string_write_driver(
|
||||
@@ -1611,27 +1472,16 @@ unsafe fn mailimf_date_time_write_driver(
|
||||
}
|
||||
return MAILIMF_NO_ERROR as libc::c_int;
|
||||
}
|
||||
static mut month_str: [&'static str; 12] = [
|
||||
static mut month_str: [&str; 12] = [
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
|
||||
];
|
||||
static mut week_of_day_str: [&'static str; 7] = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
||||
/* 0 = Sunday */
|
||||
/* y > 1752 */
|
||||
unsafe fn dayofweek(
|
||||
mut year: libc::c_int,
|
||||
mut month: libc::c_int,
|
||||
mut day: libc::c_int,
|
||||
) -> libc::c_int {
|
||||
static mut offset: [libc::c_int; 12] = [
|
||||
0i32, 3i32, 2i32, 5i32, 0i32, 3i32, 5i32, 1i32, 4i32, 6i32, 2i32, 4i32,
|
||||
];
|
||||
year -= (month < 3i32) as libc::c_int;
|
||||
return (year + year / 4i32 - year / 100i32
|
||||
+ year / 400i32
|
||||
+ offset[(month - 1i32) as usize]
|
||||
+ day)
|
||||
% 7i32;
|
||||
|
||||
fn dayofweek(year: i32, month: u32, day: u32) -> String {
|
||||
chrono::NaiveDate::from_ymd(year, month, day)
|
||||
.format("%a")
|
||||
.to_string()
|
||||
}
|
||||
|
||||
unsafe fn mailimf_resent_msg_id_write_driver(
|
||||
mut do_write: Option<
|
||||
unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int,
|
||||
|
||||
@@ -1243,30 +1243,21 @@ unsafe fn mailmime_preamble_parse(
|
||||
*indx = cur_token;
|
||||
return MAILIMF_NO_ERROR as libc::c_int;
|
||||
}
|
||||
unsafe fn remove_unparsed_mime_headers(mut fields: *mut mailimf_fields) {
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
cur = (*(*fields).fld_list).first;
|
||||
while !cur.is_null() {
|
||||
let mut field: *mut mailimf_field = 0 as *mut mailimf_field;
|
||||
let mut delete: libc::c_int = 0;
|
||||
field = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailimf_field;
|
||||
match (*field).fld_type {
|
||||
22 => {
|
||||
delete = 0i32;
|
||||
unsafe fn remove_unparsed_mime_headers(fields: *mut mailimf_fields) {
|
||||
(*fields).0.retain(|field| {
|
||||
let mut delete = false;
|
||||
|
||||
match field {
|
||||
mailimf_field::OptionalField(data) => {
|
||||
delete = false;
|
||||
if strncasecmp(
|
||||
(*(*field).fld_data.fld_optional_field).fld_name,
|
||||
(**data).name,
|
||||
b"Content-\x00" as *const u8 as *const libc::c_char,
|
||||
8i32 as libc::size_t,
|
||||
) == 0i32
|
||||
{
|
||||
let mut name: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
name = (*(*field).fld_data.fld_optional_field)
|
||||
.fld_name
|
||||
.offset(8isize);
|
||||
name = (**data).name.offset(8isize);
|
||||
if strcasecmp(name, b"Type\x00" as *const u8 as *const libc::c_char) == 0i32
|
||||
|| strcasecmp(
|
||||
name,
|
||||
@@ -1280,35 +1271,22 @@ unsafe fn remove_unparsed_mime_headers(mut fields: *mut mailimf_fields) {
|
||||
|| strcasecmp(name, b"Language\x00" as *const u8 as *const libc::c_char)
|
||||
== 0i32
|
||||
{
|
||||
delete = 1i32
|
||||
delete = true;
|
||||
}
|
||||
} else if strcasecmp(
|
||||
(*(*field).fld_data.fld_optional_field).fld_name,
|
||||
(**data).name,
|
||||
b"MIME-Version\x00" as *const u8 as *const libc::c_char,
|
||||
) == 0i32
|
||||
{
|
||||
delete = 1i32
|
||||
}
|
||||
if 0 != delete {
|
||||
cur = clist_delete((*fields).fld_list, cur);
|
||||
mailimf_field_free(field);
|
||||
} else {
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
delete = true;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// retain keeps everything true
|
||||
!delete
|
||||
});
|
||||
}
|
||||
|
||||
pub unsafe fn mailmime_extract_boundary(
|
||||
|
||||
@@ -684,8 +684,8 @@ unsafe fn mailmime_mechanism_parse(
|
||||
}
|
||||
|
||||
pub unsafe fn mailmime_field_parse(
|
||||
mut field: *mut mailimf_optional_field,
|
||||
mut result: *mut *mut mailmime_field,
|
||||
field: *mut mailimf_optional_field,
|
||||
result: *mut *mut mailmime_field,
|
||||
) -> libc::c_int {
|
||||
let mut name: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut value: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
@@ -702,8 +702,8 @@ pub unsafe fn mailmime_field_parse(
|
||||
let mut location: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut res: libc::c_int = 0;
|
||||
let mut r: libc::c_int = 0;
|
||||
name = (*field).fld_name;
|
||||
value = (*field).fld_value;
|
||||
name = (*field).name;
|
||||
value = (*field).value;
|
||||
cur_token = 0i32 as size_t;
|
||||
content = 0 as *mut mailmime_content;
|
||||
encoding = 0 as *mut mailmime_mechanism;
|
||||
@@ -1068,8 +1068,6 @@ pub unsafe fn mailmime_fields_parse(
|
||||
mut fields: *mut mailimf_fields,
|
||||
mut result: *mut *mut mailmime_fields,
|
||||
) -> libc::c_int {
|
||||
let mut current_block: u64;
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
let mut mime_fields: *mut mailmime_fields = 0 as *mut mailmime_fields;
|
||||
let mut list: *mut clist = 0 as *mut clist;
|
||||
let mut r: libc::c_int = 0;
|
||||
@@ -1078,58 +1076,27 @@ pub unsafe fn mailmime_fields_parse(
|
||||
if list.is_null() {
|
||||
res = MAILIMF_ERROR_MEMORY as libc::c_int
|
||||
} else {
|
||||
cur = (*(*fields).fld_list).first;
|
||||
loop {
|
||||
if cur.is_null() {
|
||||
current_block = 1109700713171191020;
|
||||
break;
|
||||
}
|
||||
let mut field: *mut mailimf_field = 0 as *mut mailimf_field;
|
||||
let mut mime_field: *mut mailmime_field = 0 as *mut mailmime_field;
|
||||
field = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailimf_field;
|
||||
if (*field).fld_type == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int {
|
||||
r = mailmime_field_parse((*field).fld_data.fld_optional_field, &mut mime_field);
|
||||
for field in &(*fields).0 {
|
||||
let mut mime_field = 0 as *mut mailmime_field;
|
||||
|
||||
if let mailimf_field::OptionalField(opt_field) = field {
|
||||
r = mailmime_field_parse(*opt_field, &mut mime_field);
|
||||
|
||||
if r == MAILIMF_NO_ERROR as libc::c_int {
|
||||
r = clist_insert_after(list, (*list).last, mime_field as *mut libc::c_void);
|
||||
if r < 0i32 {
|
||||
mailmime_field_free(mime_field);
|
||||
res = MAILIMF_ERROR_MEMORY as libc::c_int;
|
||||
current_block = 17592539310030730040;
|
||||
break;
|
||||
}
|
||||
} else if !(r == MAILIMF_ERROR_PARSE as libc::c_int) {
|
||||
/* do nothing */
|
||||
res = r;
|
||||
current_block = 17592539310030730040;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
match current_block {
|
||||
1109700713171191020 => {
|
||||
if (*list).first.is_null() {
|
||||
res = MAILIMF_ERROR_PARSE as libc::c_int
|
||||
} else {
|
||||
mime_fields = mailmime_fields_new(list);
|
||||
if mime_fields.is_null() {
|
||||
res = MAILIMF_ERROR_MEMORY as libc::c_int
|
||||
} else {
|
||||
*result = mime_fields;
|
||||
return MAILIMF_NO_ERROR as libc::c_int;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
clist_foreach(
|
||||
list,
|
||||
::std::mem::transmute::<Option<unsafe fn(_: *mut mailmime_field) -> ()>, clist_func>(
|
||||
|
||||
@@ -705,7 +705,7 @@ pub unsafe fn mailmime_new(
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
return mime;
|
||||
mime
|
||||
}
|
||||
|
||||
pub unsafe fn mailmime_new_simple(
|
||||
|
||||
1087
mmime/src/other.rs
1087
mmime/src/other.rs
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,4 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::ffi::CStr;
|
||||
use std::str::FromStr;
|
||||
use std::{fmt, str};
|
||||
|
||||
@@ -7,6 +6,7 @@ use mmime::mailimf::types::*;
|
||||
|
||||
use crate::constants::*;
|
||||
use crate::contact::*;
|
||||
use crate::dc_tools::as_str;
|
||||
use crate::key::*;
|
||||
|
||||
/// Possible values for encryption preference
|
||||
@@ -69,24 +69,13 @@ impl Aheader {
|
||||
}
|
||||
|
||||
let mut fine_header = None;
|
||||
let mut cur = unsafe { (*(*header).fld_list).first };
|
||||
|
||||
while !cur.is_null() {
|
||||
let field = unsafe { (*cur).data as *mut mailimf_field };
|
||||
if !field.is_null()
|
||||
&& unsafe { (*field).fld_type } == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int
|
||||
{
|
||||
let optional_field = unsafe { (*field).fld_data.fld_optional_field };
|
||||
for field in unsafe { &(*header).0 } {
|
||||
if let mailimf_field::OptionalField(optional_field) = *field {
|
||||
if !optional_field.is_null()
|
||||
&& unsafe { !(*optional_field).fld_name.is_null() }
|
||||
&& unsafe { CStr::from_ptr((*optional_field).fld_name).to_str().unwrap() }
|
||||
== "Autocrypt"
|
||||
&& unsafe { !(*optional_field).name.is_null() }
|
||||
&& unsafe { as_str((*optional_field).name) } == "Autocrypt"
|
||||
{
|
||||
let value = unsafe {
|
||||
CStr::from_ptr((*optional_field).fld_value)
|
||||
.to_str()
|
||||
.unwrap()
|
||||
};
|
||||
let value = unsafe { as_str((*optional_field).value) };
|
||||
|
||||
match Self::from_str(value) {
|
||||
Ok(test) => {
|
||||
@@ -103,8 +92,6 @@ impl Aheader {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cur = unsafe { (*cur).next };
|
||||
}
|
||||
|
||||
fine_header
|
||||
|
||||
101
src/context.rs
101
src/context.rs
@@ -1,7 +1,5 @@
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::OsString;
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::{Arc, Condvar, Mutex, RwLock};
|
||||
|
||||
@@ -10,7 +8,6 @@ use libc::uintptr_t;
|
||||
use crate::chat::*;
|
||||
use crate::constants::*;
|
||||
use crate::contact::*;
|
||||
use crate::dc_tools::{dc_copy_file, dc_derive_safe_stem_ext};
|
||||
use crate::error::*;
|
||||
use crate::events::Event;
|
||||
use crate::imap::*;
|
||||
@@ -23,7 +20,6 @@ use crate::message::{self, Message};
|
||||
use crate::param::Params;
|
||||
use crate::smtp::*;
|
||||
use crate::sql::Sql;
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
/// Callback function type for [Context]
|
||||
///
|
||||
@@ -162,57 +158,6 @@ impl Context {
|
||||
self.blobdir.as_path()
|
||||
}
|
||||
|
||||
pub fn copy_to_blobdir(&self, orig_filename: impl AsRef<str>) -> Result<String> {
|
||||
// return a $BLOBDIR/<filename> with the content of orig_filename
|
||||
// copied into it. The <filename> will be safely derived from
|
||||
// orig_filename, and will not clash with existing filenames.
|
||||
let dest = self.new_blob_file(&orig_filename, b"")?;
|
||||
if dc_copy_file(
|
||||
&self,
|
||||
PathBuf::from(orig_filename.as_ref()),
|
||||
PathBuf::from(&dest),
|
||||
) {
|
||||
Ok(dest)
|
||||
} else {
|
||||
bail!("could not copy {} to {}", orig_filename.as_ref(), dest);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_blob_file(&self, orig_filename: impl AsRef<str>, data: &[u8]) -> Result<String> {
|
||||
// return a $BLOBDIR/<FILENAME> string which corresponds to the
|
||||
// respective file in the blobdir, and which contains the data.
|
||||
// FILENAME is computed by looking and possibly mangling the
|
||||
// basename of orig_filename. The resulting filenames are meant
|
||||
// to be human-readable.
|
||||
let (stem, ext) = dc_derive_safe_stem_ext(orig_filename.as_ref());
|
||||
|
||||
// ext starts with "." or is empty string, so we can always resconstruct
|
||||
|
||||
for i in 0..3 {
|
||||
let candidate_basename = match i {
|
||||
// first a try to just use the (possibly mangled) original basename
|
||||
0 => format!("{}{}", stem, ext),
|
||||
|
||||
// otherwise extend stem with random numbers
|
||||
_ => {
|
||||
let mut rng = thread_rng();
|
||||
let random_id: u32 = rng.gen();
|
||||
format!("{}-{}{}", stem, random_id, ext)
|
||||
}
|
||||
};
|
||||
let path = self.get_blobdir().join(&candidate_basename);
|
||||
if let Ok(mut file) = fs::OpenOptions::new()
|
||||
.create_new(true)
|
||||
.write(true)
|
||||
.open(&path)
|
||||
{
|
||||
file.write_all(data)?;
|
||||
return Ok(format!("$BLOBDIR/{}", candidate_basename));
|
||||
}
|
||||
}
|
||||
bail!("out of luck to create new blob file");
|
||||
}
|
||||
|
||||
pub fn call_cb(&self, event: Event) -> uintptr_t {
|
||||
(*self.cb)(self, event)
|
||||
}
|
||||
@@ -493,7 +438,6 @@ pub fn get_version_str() -> &'static str {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use crate::dc_tools::*;
|
||||
use crate::test_utils::*;
|
||||
|
||||
#[test]
|
||||
@@ -531,51 +475,6 @@ mod tests {
|
||||
assert!(res.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new_blob_file() {
|
||||
let t = dummy_context();
|
||||
let context = t.ctx;
|
||||
let x = &context.new_blob_file("hello", b"data").unwrap();
|
||||
assert!(dc_file_exist(&context, x));
|
||||
assert!(x.starts_with("$BLOBDIR"));
|
||||
assert!(dc_read_file(&context, x).unwrap() == b"data");
|
||||
|
||||
let y = &context.new_blob_file("hello", b"data").unwrap();
|
||||
assert!(dc_file_exist(&context, y));
|
||||
assert!(y.starts_with("$BLOBDIR/hello-"));
|
||||
|
||||
let x = &context.new_blob_file("xyz/hello.png", b"data").unwrap();
|
||||
assert!(dc_file_exist(&context, x));
|
||||
assert_eq!(x, "$BLOBDIR/hello.png");
|
||||
|
||||
let y = &context.new_blob_file("hello\\world.png", b"data").unwrap();
|
||||
assert!(dc_file_exist(&context, y));
|
||||
assert_eq!(y, "$BLOBDIR/world.png");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new_blob_file_long_names() {
|
||||
let t = dummy_context();
|
||||
let context = t.ctx;
|
||||
let s = "12312312039182039182039812039810293810293810293810293801293801293123123";
|
||||
let x = &context.new_blob_file(s, b"data").unwrap();
|
||||
println!("blobfilename '{}'", x);
|
||||
println!("xxxxfilename '{}'", s);
|
||||
assert!(x.len() < s.len());
|
||||
assert!(dc_file_exist(&context, x));
|
||||
assert!(x.starts_with("$BLOBDIR"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new_blob_file_unicode() {
|
||||
let t = dummy_context();
|
||||
let context = t.ctx;
|
||||
let s = "helloäworld.qwe";
|
||||
let x = &context.new_blob_file(s, b"data").unwrap();
|
||||
assert_eq!(x, "$BLOBDIR/hello-world.qwe");
|
||||
assert_eq!(dc_read_file(&context, x).unwrap(), b"data");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sqlite_parent_not_exists() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
|
||||
@@ -31,7 +31,7 @@ pub struct MimeParser<'a> {
|
||||
pub context: &'a Context,
|
||||
pub parts: Vec<Part>,
|
||||
pub mimeroot: *mut Mailmime,
|
||||
pub header: HashMap<String, *mut mailimf_field>,
|
||||
pub header: HashMap<String, mailimf_field>,
|
||||
pub header_root: *mut mailimf_fields,
|
||||
pub header_protected: *mut mailimf_fields,
|
||||
pub subject: Option<String>,
|
||||
@@ -124,8 +124,8 @@ impl<'a> MimeParser<'a> {
|
||||
self.parse_mime_recursive(self.mimeroot);
|
||||
|
||||
if let Some(field) = self.lookup_field("Subject") {
|
||||
if (*field).fld_type == MAILIMF_FIELD_SUBJECT as libc::c_int {
|
||||
let subj = (*(*field).fld_data.fld_subject).sbj_value;
|
||||
if let mailimf_field::Subject(subject) = *field {
|
||||
let subj = (*subject).sbj_value;
|
||||
|
||||
self.subject = as_opt_str(subj).map(dc_decode_header_words_safe);
|
||||
}
|
||||
@@ -289,12 +289,9 @@ impl<'a> MimeParser<'a> {
|
||||
{
|
||||
if let Some(dn_to_addr) = mailimf_find_first_addr(mb_list) {
|
||||
if let Some(from_field) = self.lookup_field("From") {
|
||||
if (*from_field).fld_type == MAILIMF_FIELD_FROM as libc::c_int
|
||||
&& !(*from_field).fld_data.fld_from.is_null()
|
||||
{
|
||||
let from_addr = mailimf_find_first_addr(
|
||||
(*(*from_field).fld_data.fld_from).frm_mb_list,
|
||||
);
|
||||
if let mailimf_field::From(from) = *from_field {
|
||||
let from_addr =
|
||||
mailimf_find_first_addr((*from).frm_mb_list);
|
||||
if let Some(from_addr) = from_addr {
|
||||
if from_addr == dn_to_addr {
|
||||
if let Some(part_4) = self.get_last_nonmeta() {
|
||||
@@ -333,44 +330,24 @@ impl<'a> MimeParser<'a> {
|
||||
|
||||
/* the following functions can be used only after a call to parse() */
|
||||
|
||||
pub fn lookup_field(&self, field_name: &str) -> Option<*mut mailimf_field> {
|
||||
match self.header.get(field_name) {
|
||||
Some(v) => {
|
||||
if v.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(*v)
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
pub fn lookup_field(&self, field_name: &str) -> Option<&mailimf_field> {
|
||||
self.header.get(field_name)
|
||||
}
|
||||
|
||||
pub fn lookup_optional_field(&self, field_name: &str) -> Option<String> {
|
||||
if let Some(field) = self.lookup_field_typ(field_name, MAILIMF_FIELD_OPTIONAL_FIELD) {
|
||||
let val = unsafe { (*field).fld_data.fld_optional_field };
|
||||
if val.is_null() {
|
||||
return None;
|
||||
} else {
|
||||
return Some(unsafe { to_string_lossy((*val).fld_value) });
|
||||
if let Some(field) = self.lookup_field(field_name) {
|
||||
if let mailimf_field::OptionalField(val) = *field {
|
||||
if val.is_null() {
|
||||
return None;
|
||||
} else {
|
||||
return Some(unsafe { to_string_lossy((*val).value) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub fn lookup_field_typ(&self, name: &str, typ: u32) -> Option<*const mailimf_field> {
|
||||
if let Some(field) = self.lookup_field(name) {
|
||||
if unsafe { (*field).fld_type } == typ as libc::c_int {
|
||||
Some(field)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn parse_mime_recursive(&mut self, mime: *mut Mailmime) -> bool {
|
||||
if mime.is_null() {
|
||||
return false;
|
||||
@@ -776,34 +753,28 @@ impl<'a> MimeParser<'a> {
|
||||
decoded_data: &[u8],
|
||||
desired_filename: &str,
|
||||
) {
|
||||
/* write decoded data to new blob file */
|
||||
let bpath = match self.context.new_blob_file(desired_filename, decoded_data) {
|
||||
Ok(path) => path,
|
||||
Err(err) => {
|
||||
error!(
|
||||
self.context,
|
||||
"Could not add blob for mime part {}, error {}", desired_filename, err
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
/* create a free file name to use */
|
||||
let path_filename = dc_get_fine_path_filename(self.context, "$BLOBDIR", desired_filename);
|
||||
|
||||
let mut part = Part::default();
|
||||
part.typ = msg_type;
|
||||
part.mimetype = mime_type;
|
||||
part.bytes = decoded_data.len() as libc::c_int;
|
||||
part.param.set(Param::File, bpath);
|
||||
if let Some(raw_mime) = raw_mime {
|
||||
part.param.set(Param::MimeType, raw_mime);
|
||||
}
|
||||
|
||||
if mime_type == DC_MIMETYPE_IMAGE {
|
||||
if let Ok((width, height)) = dc_get_filemeta(decoded_data) {
|
||||
part.param.set_int(Param::Width, width as i32);
|
||||
part.param.set_int(Param::Height, height as i32);
|
||||
/* copy data to file */
|
||||
if dc_write_file(self.context, &path_filename, decoded_data) {
|
||||
let mut part = Part::default();
|
||||
part.typ = msg_type;
|
||||
part.mimetype = mime_type;
|
||||
part.bytes = decoded_data.len() as libc::c_int;
|
||||
part.param.set(Param::File, path_filename.to_string_lossy());
|
||||
if let Some(raw_mime) = raw_mime {
|
||||
part.param.set(Param::MimeType, raw_mime);
|
||||
}
|
||||
|
||||
if mime_type == DC_MIMETYPE_IMAGE {
|
||||
if let Ok((width, height)) = dc_get_filemeta(decoded_data) {
|
||||
part.param.set_int(Param::Width, width as i32);
|
||||
part.param.set_int(Param::Height, height as i32);
|
||||
}
|
||||
}
|
||||
self.do_add_single_part(part);
|
||||
}
|
||||
self.do_add_single_part(part);
|
||||
}
|
||||
|
||||
fn do_add_single_part(&mut self, mut part: Part) {
|
||||
@@ -835,31 +806,22 @@ impl<'a> MimeParser<'a> {
|
||||
}
|
||||
|
||||
let mut sender_equals_recipient = false;
|
||||
let mut fld_from: *const mailimf_from = ptr::null();
|
||||
|
||||
/* get From: and check there is exactly one sender */
|
||||
let fld = mailimf_find_field(self.header_root, MAILIMF_FIELD_FROM as libc::c_int);
|
||||
if !(fld.is_null()
|
||||
|| {
|
||||
fld_from = (*fld).fld_data.fld_from;
|
||||
fld_from.is_null()
|
||||
}
|
||||
|| (*fld_from).frm_mb_list.is_null()
|
||||
|| (*(*fld_from).frm_mb_list).mb_list.is_null()
|
||||
|| (*(*(*fld_from).frm_mb_list).mb_list).count != 1i32)
|
||||
{
|
||||
let mb = (if !(*(*(*fld_from).frm_mb_list).mb_list).first.is_null() {
|
||||
(*(*(*(*fld_from).frm_mb_list).mb_list).first).data
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}) as *mut mailimf_mailbox;
|
||||
if let Some(fld_from) = mailimf_find_from_field(self.header_root) {
|
||||
if (*fld_from).frm_mb_list.is_null() || (*(*(*fld_from).frm_mb_list).0).len() != 1 {
|
||||
let mb = (*(*(*fld_from).frm_mb_list).0)
|
||||
.first()
|
||||
.map(|v| *v)
|
||||
.unwrap_or_else(|| ptr::null_mut());
|
||||
|
||||
if !mb.is_null() {
|
||||
let from_addr_norm = addr_normalize(as_str((*mb).mb_addr_spec));
|
||||
let recipients = mailimf_get_recipients(self.header_root);
|
||||
if recipients.len() == 1 {
|
||||
if recipients.contains(from_addr_norm) {
|
||||
sender_equals_recipient = true;
|
||||
if !mb.is_null() {
|
||||
let from_addr_norm = addr_normalize(as_str((*mb).addr_spec));
|
||||
let recipients = mailimf_get_recipients(self.header_root);
|
||||
if recipients.len() == 1 {
|
||||
if recipients.contains(from_addr_norm) {
|
||||
sender_equals_recipient = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -883,11 +845,10 @@ impl<'a> MimeParser<'a> {
|
||||
|
||||
pub fn get_rfc724_mid(&mut self) -> Option<String> {
|
||||
// get Message-ID from header
|
||||
if let Some(field) = self.lookup_field_typ("Message-ID", MAILIMF_FIELD_MESSAGE_ID) {
|
||||
unsafe {
|
||||
let fld_message_id = (*field).fld_data.fld_message_id;
|
||||
if !fld_message_id.is_null() {
|
||||
return Some(to_string((*fld_message_id).mid_value));
|
||||
if let Some(field) = self.lookup_field("Message-ID") {
|
||||
if let mailimf_field::MessageId(id) = *field {
|
||||
if !id.is_null() {
|
||||
return Some(unsafe { to_string((*id).mid_value) });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -922,10 +883,10 @@ pub fn mailimf_find_first_addr(mb_list: *const mailimf_mailbox_list) -> Option<S
|
||||
return None;
|
||||
}
|
||||
|
||||
for cur in unsafe { (*(*mb_list).mb_list).into_iter() } {
|
||||
let mb = cur as *mut mailimf_mailbox;
|
||||
if !mb.is_null() && !unsafe { (*mb).mb_addr_spec.is_null() } {
|
||||
let addr = unsafe { as_str((*mb).mb_addr_spec) };
|
||||
for mb in unsafe { &(*mb_list).0 } {
|
||||
let mb = *mb;
|
||||
if !mb.is_null() && !unsafe { (*mb).addr_spec.is_null() } {
|
||||
let addr = unsafe { as_str((*mb).addr_spec) };
|
||||
return Some(addr_normalize(addr).to_string());
|
||||
}
|
||||
}
|
||||
@@ -933,31 +894,28 @@ pub fn mailimf_find_first_addr(mb_list: *const mailimf_mailbox_list) -> Option<S
|
||||
None
|
||||
}
|
||||
|
||||
unsafe fn hash_header(out: &mut HashMap<String, *mut mailimf_field>, in_0: *const mailimf_fields) {
|
||||
unsafe fn hash_header(out: &mut HashMap<String, mailimf_field>, in_0: *const mailimf_fields) {
|
||||
if in_0.is_null() {
|
||||
return;
|
||||
}
|
||||
|
||||
for cur in (*(*in_0).fld_list).into_iter() {
|
||||
let field = cur as *mut mailimf_field;
|
||||
// TODO match on enums /rtn
|
||||
|
||||
let key = match (*field).fld_type as libc::c_uint {
|
||||
MAILIMF_FIELD_RETURN_PATH => Some("Return-Path".to_string()),
|
||||
MAILIMF_FIELD_ORIG_DATE => Some("Date".to_string()),
|
||||
MAILIMF_FIELD_FROM => Some("From".to_string()),
|
||||
MAILIMF_FIELD_SENDER => Some("Sender".to_string()),
|
||||
MAILIMF_FIELD_REPLY_TO => Some("Reply-To".to_string()),
|
||||
MAILIMF_FIELD_TO => Some("To".to_string()),
|
||||
MAILIMF_FIELD_CC => Some("Cc".to_string()),
|
||||
MAILIMF_FIELD_BCC => Some("Bcc".to_string()),
|
||||
MAILIMF_FIELD_MESSAGE_ID => Some("Message-ID".to_string()),
|
||||
MAILIMF_FIELD_IN_REPLY_TO => Some("In-Reply-To".to_string()),
|
||||
MAILIMF_FIELD_REFERENCES => Some("References".to_string()),
|
||||
MAILIMF_FIELD_SUBJECT => Some("Subject".to_string()),
|
||||
MAILIMF_FIELD_OPTIONAL_FIELD => {
|
||||
for field in &(*in_0).0 {
|
||||
use mailimf_field::*;
|
||||
let key = match *field {
|
||||
ReturnPath(_) => Some("Return-Path".to_string()),
|
||||
OrigDate(_) => Some("Date".to_string()),
|
||||
From(_) => Some("From".to_string()),
|
||||
Sender(_) => Some("Sender".to_string()),
|
||||
ReplyTo(_) => Some("Reply-To".to_string()),
|
||||
To(_) => Some("To".to_string()),
|
||||
Cc(_) => Some("Cc".to_string()),
|
||||
Bcc(_) => Some("Bcc".to_string()),
|
||||
MessageId(_) => Some("Message-ID".to_string()),
|
||||
InReplyTo(_) => Some("In-Reply-To".to_string()),
|
||||
References(_) => Some("References".to_string()),
|
||||
Subject(_) => Some("Subject".to_string()),
|
||||
OptionalField(optional_field) => {
|
||||
// MAILIMF_FIELD_OPTIONAL_FIELD
|
||||
let optional_field = (*field).fld_data.fld_optional_field;
|
||||
// XXX the optional field sometimes contains invalid UTF8
|
||||
// which should not happen (according to the mime standard).
|
||||
// This might point to a bug in our mime parsing/processing
|
||||
@@ -965,7 +923,7 @@ unsafe fn hash_header(out: &mut HashMap<String, *mut mailimf_field>, in_0: *cons
|
||||
// anyway we just use a lossy conversion.
|
||||
|
||||
if !optional_field.is_null() {
|
||||
Some(to_string_lossy((*optional_field).fld_name))
|
||||
Some(to_string_lossy((*optional_field).name))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -974,9 +932,9 @@ unsafe fn hash_header(out: &mut HashMap<String, *mut mailimf_field>, in_0: *cons
|
||||
};
|
||||
if let Some(key) = key {
|
||||
if !out.contains_key(&key) || // key already exists, only overwrite known types (protected headers)
|
||||
(*field).fld_type != MAILIMF_FIELD_OPTIONAL_FIELD as i32 || key.starts_with("Chat-")
|
||||
field.is_optional_field() || key.starts_with("Chat-")
|
||||
{
|
||||
out.insert(key, field);
|
||||
out.insert(key, *field);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1221,29 +1179,16 @@ pub fn mailimf_get_recipients(imffields: *mut mailimf_fields) -> HashSet<String>
|
||||
/* returned addresses are normalized. */
|
||||
let mut recipients: HashSet<String> = Default::default();
|
||||
|
||||
for cur in unsafe { (*(*imffields).fld_list).into_iter() } {
|
||||
let fld = cur as *mut mailimf_field;
|
||||
|
||||
let fld_to: *mut mailimf_to;
|
||||
let fld_cc: *mut mailimf_cc;
|
||||
|
||||
for fld in unsafe { &(*imffields).0 } {
|
||||
let mut addr_list: *mut mailimf_address_list = ptr::null_mut();
|
||||
if fld.is_null() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let fld = unsafe { *fld };
|
||||
|
||||
// TODO match on enums /rtn
|
||||
match fld.fld_type {
|
||||
13 => {
|
||||
fld_to = unsafe { fld.fld_data.fld_to };
|
||||
match *fld {
|
||||
mailimf_field::To(fld_to) => {
|
||||
if !fld_to.is_null() {
|
||||
addr_list = unsafe { (*fld_to).to_addr_list };
|
||||
}
|
||||
}
|
||||
14 => {
|
||||
fld_cc = unsafe { fld.fld_data.fld_cc };
|
||||
mailimf_field::Cc(fld_cc) => {
|
||||
if !fld_cc.is_null() {
|
||||
addr_list = unsafe { (*fld_cc).cc_addr_list };
|
||||
}
|
||||
@@ -1252,26 +1197,20 @@ pub fn mailimf_get_recipients(imffields: *mut mailimf_fields) -> HashSet<String>
|
||||
}
|
||||
|
||||
if !addr_list.is_null() {
|
||||
for cur2 in unsafe { &(*(*addr_list).ad_list) } {
|
||||
let adr = cur2 as *mut mailimf_address;
|
||||
|
||||
for adr in unsafe { &(*(*addr_list).0) } {
|
||||
if adr.is_null() {
|
||||
continue;
|
||||
}
|
||||
let adr = unsafe { *adr };
|
||||
|
||||
if adr.ad_type == MAILIMF_ADDRESS_MAILBOX as libc::c_int {
|
||||
mailimf_get_recipients_add_addr(&mut recipients, unsafe {
|
||||
adr.ad_data.ad_mailbox
|
||||
});
|
||||
} else if adr.ad_type == MAILIMF_ADDRESS_GROUP as libc::c_int {
|
||||
let group = unsafe { adr.ad_data.ad_group };
|
||||
if !group.is_null() && unsafe { !(*group).grp_mb_list.is_null() } {
|
||||
for cur3 in unsafe { &(*(*(*group).grp_mb_list).mb_list) } {
|
||||
mailimf_get_recipients_add_addr(
|
||||
&mut recipients,
|
||||
cur3 as *mut mailimf_mailbox,
|
||||
);
|
||||
match unsafe { &**adr } {
|
||||
mailimf_address::Mailbox(mailbox) => {
|
||||
mailimf_get_recipients_add_addr(&mut recipients, *mailbox);
|
||||
}
|
||||
mailimf_address::Group(group) => {
|
||||
if !group.is_null() && unsafe { !(**group).mb_list.is_null() } {
|
||||
for mb in unsafe { &((*(**group).mb_list).0) } {
|
||||
mailimf_get_recipients_add_addr(&mut recipients, *mb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1284,35 +1223,37 @@ pub fn mailimf_get_recipients(imffields: *mut mailimf_fields) -> HashSet<String>
|
||||
|
||||
fn mailimf_get_recipients_add_addr(recipients: &mut HashSet<String>, mb: *mut mailimf_mailbox) {
|
||||
if !mb.is_null() {
|
||||
let addr_norm = addr_normalize(as_str(unsafe { (*mb).mb_addr_spec }));
|
||||
let addr_norm = addr_normalize(as_str(unsafe { (*mb).addr_spec }));
|
||||
recipients.insert(addr_norm.into());
|
||||
}
|
||||
}
|
||||
|
||||
/*the result is a pointer to mime, must not be freed*/
|
||||
pub fn mailimf_find_field(
|
||||
header: *mut mailimf_fields,
|
||||
wanted_fld_type: libc::c_int,
|
||||
) -> *mut mailimf_field {
|
||||
pub fn mailimf_find_from_field(header: *mut mailimf_fields) -> Option<*mut mailimf_from> {
|
||||
if header.is_null() {
|
||||
return ptr::null_mut();
|
||||
return None;
|
||||
}
|
||||
|
||||
let header = unsafe { (*header) };
|
||||
if header.fld_list.is_null() {
|
||||
return ptr::null_mut();
|
||||
}
|
||||
|
||||
for cur in unsafe { &(*header.fld_list) } {
|
||||
let field = cur as *mut mailimf_field;
|
||||
if !field.is_null() {
|
||||
if unsafe { (*field).fld_type } == wanted_fld_type {
|
||||
return field;
|
||||
}
|
||||
unsafe { (*header).0.iter() }.find_map(|field| {
|
||||
if let mailimf_field::From(f) = field {
|
||||
Some(*f)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn mailimf_find_orig_date_field(header: *mut mailimf_fields) -> Option<*mut mailimf_orig_date> {
|
||||
if header.is_null() {
|
||||
return None;
|
||||
}
|
||||
|
||||
ptr::null_mut()
|
||||
unsafe { (*header).0.iter() }.find_map(|field| {
|
||||
if let mailimf_field::OrigDate(d) = field {
|
||||
Some(*d)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/*the result is a pointer to mime, must not be freed*/
|
||||
@@ -1341,18 +1282,15 @@ pub unsafe fn mailimf_find_optional_field(
|
||||
header: *mut mailimf_fields,
|
||||
wanted_fld_name: *const libc::c_char,
|
||||
) -> *mut mailimf_optional_field {
|
||||
if header.is_null() || (*header).fld_list.is_null() {
|
||||
if header.is_null() {
|
||||
return ptr::null_mut();
|
||||
}
|
||||
for cur_data in (*(*header).fld_list).into_iter() {
|
||||
let field: *mut mailimf_field = cur_data as *mut _;
|
||||
|
||||
if (*field).fld_type == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int {
|
||||
let optional_field: *mut mailimf_optional_field = (*field).fld_data.fld_optional_field;
|
||||
for field in &(*header).0 {
|
||||
if let mailimf_field::OptionalField(optional_field) = *field {
|
||||
if !optional_field.is_null()
|
||||
&& !(*optional_field).fld_name.is_null()
|
||||
&& !(*optional_field).fld_value.is_null()
|
||||
&& strcasecmp((*optional_field).fld_name, wanted_fld_name) == 0i32
|
||||
&& !(*optional_field).name.is_null()
|
||||
&& !(*optional_field).value.is_null()
|
||||
&& strcasecmp((*optional_field).name, wanted_fld_name) == 0i32
|
||||
{
|
||||
return optional_field;
|
||||
}
|
||||
@@ -1367,7 +1305,6 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::test_utils::*;
|
||||
use proptest::prelude::*;
|
||||
use std::ffi::CStr;
|
||||
|
||||
#[test]
|
||||
fn test_mailmime_parse() {
|
||||
@@ -1390,19 +1327,9 @@ mod tests {
|
||||
);
|
||||
|
||||
assert!(!of_a.is_null());
|
||||
assert!(!(*of_a).fld_value.is_null());
|
||||
assert_eq!(
|
||||
CStr::from_ptr((*of_a).fld_name as *const libc::c_char)
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
"FieldA",
|
||||
);
|
||||
assert_eq!(
|
||||
CStr::from_ptr((*of_a).fld_value as *const libc::c_char)
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
"ValueA",
|
||||
);
|
||||
assert!(!(*of_a).value.is_null());
|
||||
assert_eq!(as_str((*of_a).name), "FieldA");
|
||||
assert_eq!(as_str((*of_a).value), "ValueA");
|
||||
|
||||
of_a = mailimf_find_optional_field(
|
||||
fields,
|
||||
@@ -1410,33 +1337,18 @@ mod tests {
|
||||
);
|
||||
|
||||
assert!(!of_a.is_null());
|
||||
assert!(!(*of_a).fld_value.is_null());
|
||||
assert_eq!(
|
||||
CStr::from_ptr((*of_a).fld_name as *const libc::c_char)
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
"FieldA",
|
||||
);
|
||||
assert_eq!(
|
||||
CStr::from_ptr((*of_a).fld_value as *const libc::c_char)
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
"ValueA",
|
||||
);
|
||||
assert!(!(*of_a).value.is_null());
|
||||
assert_eq!(as_str((*of_a).name), "FieldA");
|
||||
assert_eq!(as_str((*of_a).value), "ValueA");
|
||||
|
||||
let of_b: *mut mailimf_optional_field = mailimf_find_optional_field(
|
||||
let of_b = mailimf_find_optional_field(
|
||||
fields,
|
||||
b"FieldB\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
|
||||
assert!(!of_b.is_null());
|
||||
assert!(!(*of_b).fld_value.is_null());
|
||||
assert_eq!(
|
||||
CStr::from_ptr((*of_b).fld_value as *const libc::c_char)
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
"ValueB",
|
||||
);
|
||||
assert!(!(*of_b).value.is_null());
|
||||
assert_eq!(as_str((*of_b).value), "ValueB");
|
||||
|
||||
mailmime_free(mime);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ use std::ptr;
|
||||
|
||||
use itertools::join;
|
||||
use libc::{free, strcmp, strlen};
|
||||
use mmime::clist::*;
|
||||
use mmime::mailimf::types::*;
|
||||
use mmime::mailimf::*;
|
||||
use mmime::mailmime::content::*;
|
||||
@@ -119,61 +118,65 @@ pub unsafe fn dc_receive_imf(
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(field) = mime_parser.lookup_field_typ("Date", MAILIMF_FIELD_ORIG_DATE) {
|
||||
let orig_date = (*field).fld_data.fld_orig_date;
|
||||
if !orig_date.is_null() {
|
||||
// is not yet checked against bad times! we do this later if we have the database information.
|
||||
sent_timestamp = dc_timestamp_from_date((*orig_date).dt_date_time)
|
||||
if let Some(field) = mime_parser.lookup_field("Date") {
|
||||
if let mailimf_field::OrigDate(orig_date) = *field {
|
||||
if !orig_date.is_null() {
|
||||
// is not yet checked against bad times! we do this later if we have the database information.
|
||||
sent_timestamp = dc_timestamp_from_date((*orig_date).dt_date_time)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get From: and check if it is known (for known From:'s we add the other To:/Cc: in the 3rd pass)
|
||||
// or if From: is equal to SELF (in this case, it is any outgoing messages,
|
||||
// we do not check Return-Path any more as this is unreliable, see issue #150
|
||||
if let Some(field) = mime_parser.lookup_field_typ("From", MAILIMF_FIELD_FROM) {
|
||||
let fld_from = (*field).fld_data.fld_from;
|
||||
if !fld_from.is_null() {
|
||||
let mut check_self = 0;
|
||||
let mut from_list = Vec::with_capacity(16);
|
||||
dc_add_or_lookup_contacts_by_mailbox_list(
|
||||
context,
|
||||
(*fld_from).frm_mb_list,
|
||||
Origin::IncomingUnknownFrom,
|
||||
&mut from_list,
|
||||
&mut check_self,
|
||||
);
|
||||
if 0 != check_self {
|
||||
incoming = 0;
|
||||
if mime_parser.sender_equals_recipient() {
|
||||
from_id = DC_CONTACT_ID_SELF;
|
||||
if let Some(field) = mime_parser.lookup_field("From") {
|
||||
if let mailimf_field::From(fld_from) = *field {
|
||||
if !fld_from.is_null() {
|
||||
let mut check_self = 0;
|
||||
let mut from_list = Vec::with_capacity(16);
|
||||
dc_add_or_lookup_contacts_by_mailbox_list(
|
||||
context,
|
||||
(*fld_from).frm_mb_list,
|
||||
Origin::IncomingUnknownFrom,
|
||||
&mut from_list,
|
||||
&mut check_self,
|
||||
);
|
||||
if 0 != check_self {
|
||||
incoming = 0;
|
||||
if mime_parser.sender_equals_recipient() {
|
||||
from_id = DC_CONTACT_ID_SELF;
|
||||
}
|
||||
} else if from_list.len() >= 1 {
|
||||
// if there is no from given, from_id stays 0 which is just fine. These messages
|
||||
// are very rare, however, we have to add them to the database (they go to the
|
||||
// "deaddrop" chat) to avoid a re-download from the server. See also [**]
|
||||
from_id = from_list[0];
|
||||
incoming_origin =
|
||||
Contact::get_origin_by_id(context, from_id, &mut from_id_blocked)
|
||||
}
|
||||
} else if from_list.len() >= 1 {
|
||||
// if there is no from given, from_id stays 0 which is just fine. These messages
|
||||
// are very rare, however, we have to add them to the database (they go to the
|
||||
// "deaddrop" chat) to avoid a re-download from the server. See also [**]
|
||||
from_id = from_list[0];
|
||||
incoming_origin = Contact::get_origin_by_id(context, from_id, &mut from_id_blocked)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure, to_ids starts with the first To:-address (Cc: is added in the loop below pass)
|
||||
if let Some(field) = mime_parser.lookup_field_typ("To", MAILIMF_FIELD_TO) {
|
||||
let fld_to = (*field).fld_data.fld_to;
|
||||
if !fld_to.is_null() {
|
||||
dc_add_or_lookup_contacts_by_address_list(
|
||||
context,
|
||||
(*fld_to).to_addr_list,
|
||||
if 0 == incoming {
|
||||
Origin::OutgoingTo
|
||||
} else if incoming_origin.is_verified() {
|
||||
Origin::IncomingTo
|
||||
} else {
|
||||
Origin::IncomingUnknownTo
|
||||
},
|
||||
&mut to_ids,
|
||||
&mut to_self,
|
||||
);
|
||||
if let Some(field) = mime_parser.lookup_field("To") {
|
||||
if let mailimf_field::To(fld_to) = *field {
|
||||
if !fld_to.is_null() {
|
||||
dc_add_or_lookup_contacts_by_address_list(
|
||||
context,
|
||||
(*fld_to).to_addr_list,
|
||||
if 0 == incoming {
|
||||
Origin::OutgoingTo
|
||||
} else if incoming_origin.is_verified() {
|
||||
Origin::IncomingTo
|
||||
} else {
|
||||
Origin::IncomingUnknownTo
|
||||
},
|
||||
&mut to_ids,
|
||||
&mut to_self,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,22 +330,23 @@ unsafe fn add_parts(
|
||||
// collect the rest information, CC: is added to the to-list, BCC: is ignored
|
||||
// (we should not add BCC to groups as this would split groups. We could add them as "known contacts",
|
||||
// however, the benefit is very small and this may leak data that is expected to be hidden)
|
||||
if let Some(field) = mime_parser.lookup_field_typ("Cc", MAILIMF_FIELD_CC) {
|
||||
let fld_cc = (*field).fld_data.fld_cc;
|
||||
if !fld_cc.is_null() {
|
||||
dc_add_or_lookup_contacts_by_address_list(
|
||||
context,
|
||||
(*fld_cc).cc_addr_list,
|
||||
if 0 == incoming {
|
||||
Origin::OutgoingCc
|
||||
} else if incoming_origin.is_verified() {
|
||||
Origin::IncomingCc
|
||||
} else {
|
||||
Origin::IncomingUnknownCc
|
||||
},
|
||||
to_ids,
|
||||
std::ptr::null_mut(),
|
||||
);
|
||||
if let Some(field) = mime_parser.lookup_field("Cc") {
|
||||
if let mailimf_field::Cc(fld_cc) = *field {
|
||||
if !fld_cc.is_null() {
|
||||
dc_add_or_lookup_contacts_by_address_list(
|
||||
context,
|
||||
(*fld_cc).cc_addr_list,
|
||||
if 0 == incoming {
|
||||
Origin::OutgoingCc
|
||||
} else if incoming_origin.is_verified() {
|
||||
Origin::IncomingCc
|
||||
} else {
|
||||
Origin::IncomingUnknownCc
|
||||
},
|
||||
to_ids,
|
||||
std::ptr::null_mut(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -583,23 +587,25 @@ unsafe fn add_parts(
|
||||
// if the mime-headers should be saved, find out its size
|
||||
// (the mime-header ends with an empty line)
|
||||
let save_mime_headers = context.sql.get_config_bool(context, "save_mime_headers");
|
||||
if let Some(field) = mime_parser.lookup_field_typ("In-Reply-To", MAILIMF_FIELD_IN_REPLY_TO) {
|
||||
let fld_in_reply_to = (*field).fld_data.fld_in_reply_to;
|
||||
if !fld_in_reply_to.is_null() {
|
||||
mime_in_reply_to = dc_str_from_clist(
|
||||
(*(*field).fld_data.fld_in_reply_to).mid_list,
|
||||
b" \x00" as *const u8 as *const libc::c_char,
|
||||
)
|
||||
if let Some(field) = mime_parser.lookup_field("In-Reply-To") {
|
||||
if let mailimf_field::InReplyTo(fld_in_reply_to) = *field {
|
||||
if !fld_in_reply_to.is_null() {
|
||||
mime_in_reply_to = dc_str_from_vec(
|
||||
&(*fld_in_reply_to).0,
|
||||
b" \x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(field) = mime_parser.lookup_field_typ("References", MAILIMF_FIELD_REFERENCES) {
|
||||
let fld_references = (*field).fld_data.fld_references;
|
||||
if !fld_references.is_null() {
|
||||
mime_references = dc_str_from_clist(
|
||||
(*(*field).fld_data.fld_references).mid_list,
|
||||
b" \x00" as *const u8 as *const libc::c_char,
|
||||
)
|
||||
if let Some(field) = mime_parser.lookup_field("References") {
|
||||
if let mailimf_field::References(fld_references) = *field {
|
||||
if !fld_references.is_null() {
|
||||
mime_references = dc_str_from_vec(
|
||||
&(*fld_references).0,
|
||||
b" \x00" as *const u8 as *const libc::c_char,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -818,16 +824,16 @@ unsafe fn handle_reports(
|
||||
b"Original-Message-ID\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
if !of_disposition.is_null()
|
||||
&& !(*of_disposition).fld_value.is_null()
|
||||
&& !(*of_disposition).value.is_null()
|
||||
&& !of_org_msgid.is_null()
|
||||
&& !(*of_org_msgid).fld_value.is_null()
|
||||
&& !(*of_org_msgid).value.is_null()
|
||||
{
|
||||
let mut rfc724_mid_0 = std::ptr::null_mut();
|
||||
dummy = 0;
|
||||
|
||||
if mailimf_msg_id_parse(
|
||||
(*of_org_msgid).fld_value,
|
||||
strlen((*of_org_msgid).fld_value),
|
||||
(*of_org_msgid).value,
|
||||
strlen((*of_org_msgid).value),
|
||||
&mut dummy,
|
||||
&mut rfc724_mid_0,
|
||||
) == MAIL_NO_ERROR as libc::c_int
|
||||
@@ -1022,38 +1028,36 @@ unsafe fn create_or_lookup_group(
|
||||
}
|
||||
|
||||
if grpid.is_empty() {
|
||||
if let Some(field) = mime_parser.lookup_field_typ("Message-ID", MAILIMF_FIELD_MESSAGE_ID) {
|
||||
let fld_message_id = (*field).fld_data.fld_message_id;
|
||||
if !fld_message_id.is_null() {
|
||||
if let Some(extracted_grpid) =
|
||||
dc_extract_grpid_from_rfc724_mid(as_str((*fld_message_id).mid_value))
|
||||
{
|
||||
grpid = extracted_grpid.to_string();
|
||||
} else {
|
||||
grpid = "".to_string();
|
||||
if let Some(field) = mime_parser.lookup_field("Message-ID") {
|
||||
if let mailimf_field::MessageId(fld_message_id) = *field {
|
||||
if !fld_message_id.is_null() {
|
||||
if let Some(extracted_grpid) =
|
||||
dc_extract_grpid_from_rfc724_mid(as_str((*fld_message_id).mid_value))
|
||||
{
|
||||
grpid = extracted_grpid.to_string();
|
||||
} else {
|
||||
grpid = "".to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if grpid.is_empty() {
|
||||
if let Some(field) =
|
||||
mime_parser.lookup_field_typ("In-Reply-To", MAILIMF_FIELD_IN_REPLY_TO)
|
||||
{
|
||||
let fld_in_reply_to = (*field).fld_data.fld_in_reply_to;
|
||||
if !fld_in_reply_to.is_null() {
|
||||
grpid = to_string(dc_extract_grpid_from_rfc724_mid_list(
|
||||
(*fld_in_reply_to).mid_list,
|
||||
));
|
||||
if let Some(field) = mime_parser.lookup_field("In-Reply-To") {
|
||||
if let mailimf_field::InReplyTo(fld_in_reply_to) = *field {
|
||||
if !fld_in_reply_to.is_null() {
|
||||
grpid =
|
||||
to_string(dc_extract_grpid_from_rfc724_mid_list(&(*fld_in_reply_to).0));
|
||||
}
|
||||
}
|
||||
}
|
||||
if grpid.is_empty() {
|
||||
if let Some(field) =
|
||||
mime_parser.lookup_field_typ("References", MAILIMF_FIELD_REFERENCES)
|
||||
{
|
||||
let fld_references = (*field).fld_data.fld_references;
|
||||
if !fld_references.is_null() {
|
||||
grpid = to_string(dc_extract_grpid_from_rfc724_mid_list(
|
||||
(*fld_references).mid_list,
|
||||
));
|
||||
if let Some(field) = mime_parser.lookup_field("References") {
|
||||
if let mailimf_field::References(fld_references) = *field {
|
||||
if !fld_references.is_null() {
|
||||
grpid = to_string(dc_extract_grpid_from_rfc724_mid_list(
|
||||
&(*fld_references).0,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1706,13 +1710,9 @@ unsafe fn dc_is_reply_to_known_message(context: &Context, mime_parser: &MimePars
|
||||
}
|
||||
|
||||
if let Some(field) = mime_parser.lookup_field("In-Reply-To") {
|
||||
if (*field).fld_type == MAILIMF_FIELD_IN_REPLY_TO as libc::c_int {
|
||||
let fld_in_reply_to = (*field).fld_data.fld_in_reply_to;
|
||||
if let mailimf_field::InReplyTo(fld_in_reply_to) = *field {
|
||||
if !fld_in_reply_to.is_null() {
|
||||
if is_known_rfc724_mid_in_list(
|
||||
context,
|
||||
(*(*field).fld_data.fld_in_reply_to).mid_list,
|
||||
) {
|
||||
if is_known_rfc724_mid_in_list(context, &(*fld_in_reply_to).0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -1720,13 +1720,9 @@ unsafe fn dc_is_reply_to_known_message(context: &Context, mime_parser: &MimePars
|
||||
}
|
||||
|
||||
if let Some(field) = mime_parser.lookup_field("References") {
|
||||
if (*field).fld_type == MAILIMF_FIELD_REFERENCES as libc::c_int {
|
||||
let fld_references = (*field).fld_data.fld_references;
|
||||
if let mailimf_field::References(fld_references) = *field {
|
||||
if !fld_references.is_null() {
|
||||
if is_known_rfc724_mid_in_list(
|
||||
context,
|
||||
(*(*field).fld_data.fld_references).mid_list,
|
||||
) {
|
||||
if is_known_rfc724_mid_in_list(context, &(*fld_references).0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -1736,13 +1732,12 @@ unsafe fn dc_is_reply_to_known_message(context: &Context, mime_parser: &MimePars
|
||||
0
|
||||
}
|
||||
|
||||
unsafe fn is_known_rfc724_mid_in_list(context: &Context, mid_list: *const clist) -> bool {
|
||||
if mid_list.is_null() {
|
||||
return false;
|
||||
}
|
||||
|
||||
for data in &*mid_list {
|
||||
if 0 != is_known_rfc724_mid(context, data.cast()) {
|
||||
unsafe fn is_known_rfc724_mid_in_list(
|
||||
context: &Context,
|
||||
mid_list: &Vec<*mut libc::c_char>,
|
||||
) -> bool {
|
||||
for data in mid_list {
|
||||
if 0 != is_known_rfc724_mid(context, *data) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1778,13 +1773,9 @@ unsafe fn dc_is_reply_to_messenger_message(
|
||||
- no check for the Chat-* headers (function is only called if it is no messenger message itself) */
|
||||
|
||||
if let Some(field) = mime_parser.lookup_field("In-Reply-To") {
|
||||
if (*field).fld_type == MAILIMF_FIELD_IN_REPLY_TO as libc::c_int {
|
||||
let fld_in_reply_to = (*field).fld_data.fld_in_reply_to;
|
||||
if let mailimf_field::InReplyTo(fld_in_reply_to) = *field {
|
||||
if !fld_in_reply_to.is_null() {
|
||||
if 0 != is_msgrmsg_rfc724_mid_in_list(
|
||||
context,
|
||||
(*(*field).fld_data.fld_in_reply_to).mid_list,
|
||||
) {
|
||||
if 0 != is_msgrmsg_rfc724_mid_in_list(context, &(*fld_in_reply_to).0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -1792,13 +1783,9 @@ unsafe fn dc_is_reply_to_messenger_message(
|
||||
}
|
||||
|
||||
if let Some(field) = mime_parser.lookup_field("References") {
|
||||
if (*field).fld_type == MAILIMF_FIELD_REFERENCES as libc::c_int {
|
||||
let fld_references: *mut mailimf_references = (*field).fld_data.fld_references;
|
||||
if let mailimf_field::References(fld_references) = *field {
|
||||
if !fld_references.is_null() {
|
||||
if 0 != is_msgrmsg_rfc724_mid_in_list(
|
||||
context,
|
||||
(*(*field).fld_data.fld_references).mid_list,
|
||||
) {
|
||||
if 0 != is_msgrmsg_rfc724_mid_in_list(context, &(*fld_references).0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -1808,25 +1795,13 @@ unsafe fn dc_is_reply_to_messenger_message(
|
||||
0
|
||||
}
|
||||
|
||||
unsafe fn is_msgrmsg_rfc724_mid_in_list(context: &Context, mid_list: *const clist) -> libc::c_int {
|
||||
if !mid_list.is_null() {
|
||||
let mut cur: *mut clistiter = (*mid_list).first;
|
||||
while !cur.is_null() {
|
||||
if 0 != is_msgrmsg_rfc724_mid(
|
||||
context,
|
||||
if !cur.is_null() {
|
||||
as_str((*cur).data as *const libc::c_char)
|
||||
} else {
|
||||
""
|
||||
},
|
||||
) {
|
||||
return 1;
|
||||
}
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}
|
||||
unsafe fn is_msgrmsg_rfc724_mid_in_list(
|
||||
context: &Context,
|
||||
mid_list: &Vec<*mut libc::c_char>,
|
||||
) -> libc::c_int {
|
||||
for cur in mid_list {
|
||||
if 0 != is_msgrmsg_rfc724_mid(context, if !cur.is_null() { as_str(*cur) } else { "" }) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
0
|
||||
@@ -1856,43 +1831,36 @@ unsafe fn dc_add_or_lookup_contacts_by_address_list(
|
||||
if adr_list.is_null() {
|
||||
return;
|
||||
}
|
||||
let mut cur: *mut clistiter = (*(*adr_list).ad_list).first;
|
||||
while !cur.is_null() {
|
||||
let adr: *mut mailimf_address = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}) as *mut mailimf_address;
|
||||
if !adr.is_null() {
|
||||
if (*adr).ad_type == MAILIMF_ADDRESS_MAILBOX as libc::c_int {
|
||||
let mb: *mut mailimf_mailbox = (*adr).ad_data.ad_mailbox;
|
||||
|
||||
for adr in &(*(*adr_list).0) {
|
||||
if adr.is_null() {
|
||||
continue;
|
||||
}
|
||||
|
||||
match **adr {
|
||||
mailimf_address::Mailbox(mb) => {
|
||||
if !mb.is_null() {
|
||||
add_or_lookup_contact_by_addr(
|
||||
context,
|
||||
(*mb).mb_display_name,
|
||||
(*mb).mb_addr_spec,
|
||||
origin,
|
||||
ids,
|
||||
check_self,
|
||||
);
|
||||
}
|
||||
} else if (*adr).ad_type == MAILIMF_ADDRESS_GROUP as libc::c_int {
|
||||
let group: *mut mailimf_group = (*adr).ad_data.ad_group;
|
||||
if !group.is_null() && !(*group).grp_mb_list.is_null() {
|
||||
dc_add_or_lookup_contacts_by_mailbox_list(
|
||||
context,
|
||||
(*group).grp_mb_list,
|
||||
(*mb).display_name,
|
||||
(*mb).addr_spec,
|
||||
origin,
|
||||
ids,
|
||||
check_self,
|
||||
);
|
||||
}
|
||||
}
|
||||
mailimf_address::Group(group) => {
|
||||
if !group.is_null() && !(*group).mb_list.is_null() {
|
||||
dc_add_or_lookup_contacts_by_mailbox_list(
|
||||
context,
|
||||
(*group).mb_list,
|
||||
origin,
|
||||
ids,
|
||||
check_self,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1907,28 +1875,18 @@ unsafe fn dc_add_or_lookup_contacts_by_mailbox_list(
|
||||
if mb_list.is_null() {
|
||||
return;
|
||||
}
|
||||
let mut cur: *mut clistiter = (*(*mb_list).mb_list).first;
|
||||
while !cur.is_null() {
|
||||
let mb: *mut mailimf_mailbox = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}) as *mut mailimf_mailbox;
|
||||
for mb in &(*mb_list).0 {
|
||||
let mb = *mb;
|
||||
if !mb.is_null() {
|
||||
add_or_lookup_contact_by_addr(
|
||||
context,
|
||||
(*mb).mb_display_name,
|
||||
(*mb).mb_addr_spec,
|
||||
(*mb).display_name,
|
||||
(*mb).addr_spec,
|
||||
origin,
|
||||
ids,
|
||||
check_self,
|
||||
);
|
||||
}
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
247
src/dc_tools.rs
247
src/dc_tools.rs
@@ -1,9 +1,8 @@
|
||||
//! Some tools and enhancements to the used libraries, there should be
|
||||
//! no references to Context and other "larger" entities here.
|
||||
|
||||
use core::cmp::max;
|
||||
use std::borrow::Cow;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::ffi::{CStr, CString, OsString};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str::FromStr;
|
||||
use std::time::SystemTime;
|
||||
@@ -11,7 +10,6 @@ use std::{fmt, fs, ptr};
|
||||
|
||||
use chrono::{Local, TimeZone};
|
||||
use libc::{memcpy, strlen};
|
||||
use mmime::clist::*;
|
||||
use mmime::mailimf::types::*;
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
@@ -150,46 +148,26 @@ pub(crate) fn dc_truncate(buf: &str, approx_chars: usize, do_unwrap: bool) -> Co
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn dc_str_from_clist(
|
||||
list: *const clist,
|
||||
pub(crate) unsafe fn dc_str_from_vec(
|
||||
list: &Vec<*mut libc::c_char>,
|
||||
delimiter: *const libc::c_char,
|
||||
) -> *mut libc::c_char {
|
||||
let mut res = String::new();
|
||||
|
||||
if !list.is_null() {
|
||||
let mut cur: *mut clistiter = (*list).first;
|
||||
while !cur.is_null() {
|
||||
let rfc724_mid = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}) as *const libc::c_char;
|
||||
|
||||
if !rfc724_mid.is_null() {
|
||||
if !res.is_empty() && !delimiter.is_null() {
|
||||
res += as_str(delimiter);
|
||||
}
|
||||
res += as_str(rfc724_mid);
|
||||
}
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
for val in list {
|
||||
if !val.is_null() {
|
||||
if !res.is_empty() && !delimiter.is_null() {
|
||||
res += as_str(delimiter);
|
||||
}
|
||||
res += as_str(*val);
|
||||
}
|
||||
}
|
||||
|
||||
res.strdup()
|
||||
}
|
||||
|
||||
pub(crate) fn dc_str_to_clist(str: &str, delimiter: &str) -> *mut clist {
|
||||
unsafe {
|
||||
let list: *mut clist = clist_new();
|
||||
for cur in str.split(&delimiter) {
|
||||
clist_insert_after(list, (*list).last, cur.strdup().cast());
|
||||
}
|
||||
list
|
||||
}
|
||||
pub(crate) fn dc_str_to_vec(s: &str, delimiter: &str) -> Vec<*mut libc::c_char> {
|
||||
s.split(&delimiter).map(|s| unsafe { s.strdup() }).collect()
|
||||
}
|
||||
|
||||
/* the colors must fulfill some criterions as:
|
||||
@@ -220,24 +198,24 @@ pub(crate) fn dc_str_to_color(s: impl AsRef<str>) -> u32 {
|
||||
/* the result is UTC or DC_INVALID_TIMESTAMP */
|
||||
pub(crate) fn dc_timestamp_from_date(date_time: *mut mailimf_date_time) -> i64 {
|
||||
assert!(!date_time.is_null());
|
||||
let dt = unsafe { *date_time };
|
||||
let dt = unsafe { &*date_time };
|
||||
|
||||
let sec = dt.dt_sec;
|
||||
let min = dt.dt_min;
|
||||
let hour = dt.dt_hour;
|
||||
let day = dt.dt_day;
|
||||
let month = dt.dt_month;
|
||||
let year = dt.dt_year;
|
||||
let sec = dt.sec;
|
||||
let min = dt.min;
|
||||
let hour = dt.hour;
|
||||
let day = dt.day;
|
||||
let month = dt.month;
|
||||
let year = dt.year;
|
||||
|
||||
let ts = chrono::NaiveDateTime::new(
|
||||
chrono::NaiveDate::from_ymd(year, month as u32, day as u32),
|
||||
chrono::NaiveTime::from_hms(hour as u32, min as u32, sec as u32),
|
||||
chrono::NaiveDate::from_ymd(year, month, day),
|
||||
chrono::NaiveTime::from_hms(hour, min, sec),
|
||||
);
|
||||
|
||||
let (zone_hour, zone_min) = if dt.dt_zone >= 0 {
|
||||
(dt.dt_zone / 100, dt.dt_zone % 100)
|
||||
let (zone_hour, zone_min) = if dt.zone >= 0 {
|
||||
(dt.zone / 100, dt.zone % 100)
|
||||
} else {
|
||||
(-(-dt.dt_zone / 100), -(-dt.dt_zone % 100))
|
||||
(-(-dt.zone / 100), -(-dt.zone % 100))
|
||||
};
|
||||
|
||||
ts.timestamp() - (zone_hour * 3600 + zone_min * 60) as i64
|
||||
@@ -393,15 +371,15 @@ pub(crate) fn dc_extract_grpid_from_rfc724_mid(mid: &str) -> Option<&str> {
|
||||
None
|
||||
}
|
||||
|
||||
pub(crate) fn dc_extract_grpid_from_rfc724_mid_list(list: *const clist) -> *mut libc::c_char {
|
||||
if !list.is_null() {
|
||||
unsafe {
|
||||
for cur in (*list).into_iter() {
|
||||
let mid = as_str(cur as *const libc::c_char);
|
||||
pub(crate) fn dc_extract_grpid_from_rfc724_mid_list(
|
||||
list: &Vec<*mut libc::c_char>,
|
||||
) -> *mut libc::c_char {
|
||||
unsafe {
|
||||
for cur in list {
|
||||
let mid = as_str(*cur);
|
||||
|
||||
if let Some(grpid) = dc_extract_grpid_from_rfc724_mid(mid) {
|
||||
return grpid.strdup();
|
||||
}
|
||||
if let Some(grpid) = dc_extract_grpid_from_rfc724_mid(mid) {
|
||||
return grpid.strdup();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -416,41 +394,12 @@ pub(crate) fn dc_ensure_no_slash_safe(path: &str) -> &str {
|
||||
path
|
||||
}
|
||||
|
||||
// Function returns a sanitized basename that does not contain
|
||||
// win/linux path separators and also not any non-ascii chars
|
||||
fn get_safe_basename(filename: &str) -> String {
|
||||
// return the (potentially mangled) basename of the input filename
|
||||
// this might be a path that comes in from another operating system
|
||||
let mut index: usize = 0;
|
||||
|
||||
if let Some(unix_index) = filename.rfind("/") {
|
||||
index = unix_index + 1;
|
||||
}
|
||||
if let Some(win_index) = filename.rfind("\\") {
|
||||
index = max(index, win_index + 1);
|
||||
}
|
||||
if index >= filename.len() {
|
||||
"nobasename".to_string()
|
||||
} else {
|
||||
// we don't allow any non-ascii to be super-safe
|
||||
filename[index..].replace(|c: char| !c.is_ascii() || c == ':', "-")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dc_derive_safe_stem_ext(filename: &str) -> (String, String) {
|
||||
let basename = get_safe_basename(&filename);
|
||||
let (mut stem, mut ext) = if let Some(index) = basename.rfind(".") {
|
||||
(
|
||||
basename[0..index].to_string(),
|
||||
basename[index..].to_string(),
|
||||
)
|
||||
} else {
|
||||
(basename, "".to_string())
|
||||
};
|
||||
// limit length of stem and ext
|
||||
stem.truncate(32);
|
||||
ext.truncate(32);
|
||||
(stem, ext)
|
||||
/// Function modifies the given buffer and replaces all characters not valid in filenames by a "-".
|
||||
fn validate_filename(filename: &str) -> String {
|
||||
filename
|
||||
.replace('/', "-")
|
||||
.replace('\\', "-")
|
||||
.replace(':', "-")
|
||||
}
|
||||
|
||||
// the returned suffix is lower-case
|
||||
@@ -596,24 +545,49 @@ pub fn dc_read_file<P: AsRef<std::path::Path>>(
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn dc_get_next_backup_path(
|
||||
pub(crate) fn dc_get_fine_path_filename(
|
||||
context: &Context,
|
||||
folder: impl AsRef<Path>,
|
||||
backup_time: i64,
|
||||
) -> Result<PathBuf, Error> {
|
||||
let folder = PathBuf::from(folder.as_ref());
|
||||
let stem = chrono::NaiveDateTime::from_timestamp(backup_time, 0)
|
||||
.format("delta-chat-%Y-%m-%d")
|
||||
.to_string();
|
||||
desired_filename_suffix: impl AsRef<str>,
|
||||
) -> PathBuf {
|
||||
let now = time();
|
||||
|
||||
// 64 backup files per day should be enough for everyone
|
||||
for i in 0..64 {
|
||||
let mut path = folder.clone();
|
||||
path.push(format!("{}-{}.bak", stem, i));
|
||||
if !path.exists() {
|
||||
return Ok(path);
|
||||
let folder = PathBuf::from(folder.as_ref());
|
||||
// XXX sanitize desired_filename eg using
|
||||
// https://github.com/kardeiz/sanitize-filename/blob/master/src/lib.rs
|
||||
let suffix = validate_filename(desired_filename_suffix.as_ref());
|
||||
let file_name = PathBuf::from(suffix);
|
||||
let extension = file_name.extension().map(|c| c.clone());
|
||||
|
||||
for i in 0..100_000 {
|
||||
let ret = if i == 0 {
|
||||
let mut folder = folder.clone();
|
||||
folder.push(&file_name);
|
||||
folder
|
||||
} else {
|
||||
let idx = if i < 100 { i } else { now + i };
|
||||
let file_name = if let Some(stem) = file_name.file_stem() {
|
||||
let mut stem = stem.to_os_string();
|
||||
stem.push(format!("-{}", idx));
|
||||
stem
|
||||
} else {
|
||||
OsString::from(idx.to_string())
|
||||
};
|
||||
let mut folder = folder.clone();
|
||||
folder.push(file_name);
|
||||
if let Some(ext) = extension {
|
||||
folder.set_extension(&ext);
|
||||
}
|
||||
folder
|
||||
};
|
||||
|
||||
if !dc_file_exist(context, &ret) {
|
||||
// fine filename found
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
bail!("could not create backup file, disk full?");
|
||||
|
||||
panic!("Something is really wrong, you need to clean up your disk");
|
||||
}
|
||||
|
||||
pub(crate) fn dc_is_blobdir_path(context: &Context, path: impl AsRef<str>) -> bool {
|
||||
@@ -641,10 +615,13 @@ pub(crate) fn dc_make_rel_and_copy(context: &Context, path: &mut String) -> bool
|
||||
dc_make_rel_path(context, path);
|
||||
return true;
|
||||
}
|
||||
if let Ok(blobdir_path) = context.copy_to_blobdir(&path) {
|
||||
*path = blobdir_path;
|
||||
let blobdir_path = dc_get_fine_path_filename(context, "$BLOBDIR", &path);
|
||||
if dc_copy_file(context, &path, &blobdir_path) {
|
||||
*path = blobdir_path.to_string_lossy().to_string();
|
||||
dc_make_rel_path(context, path);
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
@@ -1131,21 +1108,6 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
/* calls free() for each item content */
|
||||
unsafe fn clist_free_content(haystack: *const clist) {
|
||||
let mut iter = (*haystack).first;
|
||||
|
||||
while !iter.is_null() {
|
||||
free((*iter).data);
|
||||
(*iter).data = ptr::null_mut();
|
||||
iter = if !iter.is_null() {
|
||||
(*iter).next
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn strndup(s: *const libc::c_char, n: libc::c_ulong) -> *mut libc::c_char {
|
||||
if s.is_null() {
|
||||
return std::ptr::null_mut();
|
||||
@@ -1161,35 +1123,6 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dc_str_to_clist_1() {
|
||||
unsafe {
|
||||
let list = dc_str_to_clist("", " ");
|
||||
assert_eq!((*list).count, 1);
|
||||
clist_free_content(list);
|
||||
clist_free(list);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dc_str_to_clist_4() {
|
||||
unsafe {
|
||||
let list: *mut clist = dc_str_to_clist("foo bar test", " ");
|
||||
assert_eq!((*list).count, 3);
|
||||
let str: *mut libc::c_char =
|
||||
dc_str_from_clist(list, b" \x00" as *const u8 as *const libc::c_char);
|
||||
|
||||
assert_eq!(
|
||||
CStr::from_ptr(str as *const libc::c_char).to_str().unwrap(),
|
||||
"foo bar test"
|
||||
);
|
||||
|
||||
clist_free_content(list);
|
||||
clist_free(list);
|
||||
free(str as *mut libc::c_void);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dc_create_id() {
|
||||
let buf = dc_create_id();
|
||||
@@ -1439,19 +1372,6 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_file_get_safe_basename() {
|
||||
assert_eq!(get_safe_basename("12312/hello"), "hello");
|
||||
assert_eq!(get_safe_basename("12312\\hello"), "hello");
|
||||
assert_eq!(get_safe_basename("//12312\\hello"), "hello");
|
||||
assert_eq!(get_safe_basename("//123:12\\hello"), "hello");
|
||||
assert_eq!(get_safe_basename("//123:12/\\\\hello"), "hello");
|
||||
assert_eq!(get_safe_basename("//123:12//hello"), "hello");
|
||||
assert_eq!(get_safe_basename("//123:12//"), "nobasename");
|
||||
assert_eq!(get_safe_basename("//123:12/"), "nobasename");
|
||||
assert!(get_safe_basename("123\x012.hello").ends_with(".hello"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_file_handling() {
|
||||
let t = dummy_context();
|
||||
@@ -1486,7 +1406,6 @@ mod tests {
|
||||
assert!(dc_file_exist(context, &abs_path));
|
||||
|
||||
assert!(dc_copy_file(context, "$BLOBDIR/foobar", "$BLOBDIR/dada",));
|
||||
|
||||
assert_eq!(dc_get_filebytes(context, "$BLOBDIR/dada",), 7);
|
||||
|
||||
let buf = dc_read_file(context, "$BLOBDIR/dada").unwrap();
|
||||
@@ -1499,12 +1418,14 @@ mod tests {
|
||||
assert!(dc_create_folder(context, "$BLOBDIR/foobar-folder"));
|
||||
assert!(dc_file_exist(context, "$BLOBDIR/foobar-folder",));
|
||||
assert!(!dc_delete_file(context, "$BLOBDIR/foobar-folder"));
|
||||
let fn0 = dc_get_fine_path_filename(context, "$BLOBDIR", "foobar.dadada");
|
||||
assert_eq!(fn0, PathBuf::from("$BLOBDIR/foobar.dadada"));
|
||||
|
||||
let fn0 = "$BLOBDIR/data.data";
|
||||
assert!(dc_write_file(context, &fn0, b"content"));
|
||||
let fn1 = dc_get_fine_path_filename(context, "$BLOBDIR", "foobar.dadada");
|
||||
assert_eq!(fn1, PathBuf::from("$BLOBDIR/foobar-1.dadada"));
|
||||
|
||||
assert!(dc_delete_file(context, &fn0));
|
||||
assert!(!dc_file_exist(context, &fn0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
60
src/e2ee.rs
60
src/e2ee.rs
@@ -5,7 +5,6 @@ use std::ptr;
|
||||
use std::str::FromStr;
|
||||
|
||||
use libc::strlen;
|
||||
use mmime::clist::*;
|
||||
use mmime::mailimf::types::*;
|
||||
use mmime::mailimf::types_helper::*;
|
||||
use mmime::mailimf::*;
|
||||
@@ -167,19 +166,16 @@ impl EncryptHelper {
|
||||
}
|
||||
|
||||
// memoryhole headers: move some headers into encrypted part
|
||||
// XXX note we can't use clist's into_iter() because the loop body also removes items
|
||||
let mut cur = (*(*imffields_unprotected).fld_list).first;
|
||||
while !cur.is_null() {
|
||||
let field = (*cur).data as *mut mailimf_field;
|
||||
(*imffields_unprotected).0.retain(|field| {
|
||||
let mut move_to_encrypted = false;
|
||||
|
||||
if !field.is_null() {
|
||||
if (*field).fld_type == MAILIMF_FIELD_SUBJECT as libc::c_int {
|
||||
match *field {
|
||||
mailimf_field::Subject(_) => {
|
||||
move_to_encrypted = true;
|
||||
} else if (*field).fld_type == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int {
|
||||
let opt_field = (*field).fld_data.fld_optional_field;
|
||||
if !opt_field.is_null() && !(*opt_field).fld_name.is_null() {
|
||||
let fld_name = to_string_lossy((*opt_field).fld_name);
|
||||
}
|
||||
mailimf_field::OptionalField(opt_field) => {
|
||||
if !opt_field.is_null() && !(*opt_field).name.is_null() {
|
||||
let fld_name = to_string_lossy((*opt_field).name);
|
||||
if fld_name.starts_with("Secure-Join")
|
||||
|| (fld_name.starts_with("Chat-") && fld_name != "Chat-Version")
|
||||
{
|
||||
@@ -187,18 +183,19 @@ impl EncryptHelper {
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if move_to_encrypted {
|
||||
mailimf_fields_add(imffields_encrypted, field);
|
||||
cur = clist_delete((*imffields_unprotected).fld_list, cur);
|
||||
mailimf_fields_add(imffields_encrypted, *field);
|
||||
false
|
||||
} else {
|
||||
cur = (*cur).next;
|
||||
true
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let subject = mailimf_subject_new("...".strdup());
|
||||
mailimf_fields_add(imffields_unprotected, mailimf_field_new_subject(subject));
|
||||
mailimf_fields_add(imffields_unprotected, mailimf_field::Subject(subject));
|
||||
|
||||
wrapmime::append_ct_param(
|
||||
(*part_to_encrypt).mm_content_type,
|
||||
@@ -280,17 +277,12 @@ pub fn try_decrypt(
|
||||
|
||||
// XXX do wrapmime:: helper for the next block
|
||||
if !(in_out_message.is_null() || imffields.is_null()) {
|
||||
let mut field = mailimf_find_field(imffields, MAILIMF_FIELD_FROM as libc::c_int);
|
||||
|
||||
if !field.is_null() && unsafe { !(*field).fld_data.fld_from.is_null() } {
|
||||
let mb_list = unsafe { (*(*field).fld_data.fld_from).frm_mb_list };
|
||||
if let Some(field) = mailimf_find_from_field(imffields) {
|
||||
let mb_list = unsafe { (*field).frm_mb_list };
|
||||
from = mailimf_find_first_addr(mb_list);
|
||||
}
|
||||
|
||||
field = mailimf_find_field(imffields, MAILIMF_FIELD_ORIG_DATE as libc::c_int);
|
||||
if !field.is_null() && unsafe { !(*field).fld_data.fld_orig_date.is_null() } {
|
||||
let orig_date = unsafe { (*field).fld_data.fld_orig_date };
|
||||
|
||||
if let Some(orig_date) = mailimf_find_orig_date_field(imffields) {
|
||||
if !orig_date.is_null() {
|
||||
let dt = unsafe { (*orig_date).dt_date_time };
|
||||
message_time = dc_timestamp_from_date(dt);
|
||||
@@ -460,25 +452,15 @@ fn update_gossip_peerstates(
|
||||
let mut recipients: Option<HashSet<String>> = None;
|
||||
let mut gossipped_addr: HashSet<String> = Default::default();
|
||||
|
||||
for cur_data in unsafe { (*(*gossip_headers).fld_list).into_iter() } {
|
||||
let field = cur_data as *mut mailimf_field;
|
||||
if field.is_null() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let field = unsafe { *field };
|
||||
|
||||
if field.fld_type == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int {
|
||||
let optional_field = unsafe { field.fld_data.fld_optional_field };
|
||||
for field in unsafe { &(*gossip_headers).0 } {
|
||||
if let mailimf_field::OptionalField(optional_field) = *field {
|
||||
if optional_field.is_null() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let optional_field = unsafe { *optional_field };
|
||||
if !optional_field.fld_name.is_null()
|
||||
&& as_str(optional_field.fld_name) == "Autocrypt-Gossip"
|
||||
{
|
||||
let value = to_string_lossy(optional_field.fld_value);
|
||||
let optional_field = unsafe { &*optional_field };
|
||||
if !optional_field.name.is_null() && as_str(optional_field.name) == "Autocrypt-Gossip" {
|
||||
let value = to_string_lossy(optional_field.value);
|
||||
let gossip_header = Aheader::from_str(&value);
|
||||
|
||||
if let Ok(ref header) = gossip_header {
|
||||
|
||||
20
src/imex.rs
20
src/imex.rs
@@ -129,15 +129,14 @@ pub fn initiate_key_transfer(context: &Context) -> Result<String> {
|
||||
.unwrap()
|
||||
.shall_stop_ongoing
|
||||
{
|
||||
let setup_file_name = context.new_blob_file(
|
||||
"autocrypt-setup-message.html",
|
||||
setup_file_content.as_bytes(),
|
||||
)?;
|
||||
{
|
||||
let setup_file_name =
|
||||
dc_get_fine_path_filename(context, "$BLOBDIR", "autocrypt-setup-message.html");
|
||||
if dc_write_file(context, &setup_file_name, setup_file_content.as_bytes()) {
|
||||
if let Ok(chat_id) = chat::create_by_contact_id(context, 1) {
|
||||
msg = Message::default();
|
||||
msg.type_0 = Viewtype::File;
|
||||
msg.param.set(Param::File, setup_file_name);
|
||||
msg.param
|
||||
.set(Param::File, setup_file_name.to_string_lossy());
|
||||
|
||||
msg.param
|
||||
.set(Param::MimeType, "application/autocrypt-setup");
|
||||
@@ -574,10 +573,13 @@ fn export_backup(context: &Context, dir: impl AsRef<Path>) -> Result<()> {
|
||||
|
||||
let mut delete_dest_file: libc::c_int = 0;
|
||||
// get a fine backup file name (the name includes the date so that multiple backup instances are possible)
|
||||
// FIXME: we should write to a temporary file first and rename it on success. this would guarantee the backup is complete.
|
||||
// let dest_path_filename = dc_get_next_backup_file(context, dir, res);
|
||||
// FIXME: we should write to a temporary file first and rename it on success. this would guarantee the backup is complete. however, currently it is not clear it the import exists in the long run (may be replaced by a restore-from-imap)
|
||||
let now = time();
|
||||
let dest_path_filename = dc_get_next_backup_path(dir, now)?;
|
||||
let res = chrono::NaiveDateTime::from_timestamp(now as i64, 0)
|
||||
.format("delta-chat-%Y-%m-%d.bak")
|
||||
.to_string();
|
||||
|
||||
let dest_path_filename = dc_get_fine_path_filename(context, dir, res);
|
||||
|
||||
sql::housekeeping(context);
|
||||
|
||||
|
||||
54
src/job.rs
54
src/job.rs
@@ -965,39 +965,41 @@ fn send_mdn(context: &Context, msg_id: u32) {
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn add_smtp_job(context: &Context, action: Action, mimefactory: &MimeFactory) -> libc::c_int {
|
||||
let mut success: libc::c_int = 0i32;
|
||||
let mut param = Params::new();
|
||||
let path_filename = dc_get_fine_path_filename(context, "$BLOBDIR", &mimefactory.rfc724_mid);
|
||||
let bytes = unsafe {
|
||||
std::slice::from_raw_parts(
|
||||
(*mimefactory.out).str_0 as *const u8,
|
||||
(*mimefactory.out).len,
|
||||
)
|
||||
};
|
||||
let bpath = match context.new_blob_file(&mimefactory.rfc724_mid, bytes) {
|
||||
Ok(path) => path,
|
||||
Err(err) => {
|
||||
error!(
|
||||
context,
|
||||
"Could not write {} smtp-message, error {}", mimefactory.rfc724_mid, err
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
info!(context, "add_smtp_job file written: {:?}", bpath);
|
||||
let recipients = mimefactory.recipients_addr.join("\x1e");
|
||||
param.set(Param::File, &bpath);
|
||||
param.set(Param::Recipients, &recipients);
|
||||
job_add(
|
||||
context,
|
||||
action,
|
||||
(if mimefactory.loaded == Loaded::Message {
|
||||
mimefactory.msg.id
|
||||
} else {
|
||||
0
|
||||
}) as libc::c_int,
|
||||
param,
|
||||
0,
|
||||
);
|
||||
1
|
||||
if !dc_write_file(context, &path_filename, bytes) {
|
||||
error!(
|
||||
context,
|
||||
"Could not write message <{}> to \"{}\".",
|
||||
mimefactory.rfc724_mid,
|
||||
path_filename.display(),
|
||||
);
|
||||
} else {
|
||||
info!(context, "add_smtp_job file written: {:?}", path_filename);
|
||||
let recipients = mimefactory.recipients_addr.join("\x1e");
|
||||
param.set(Param::File, path_filename.to_string_lossy());
|
||||
param.set(Param::Recipients, &recipients);
|
||||
job_add(
|
||||
context,
|
||||
action,
|
||||
(if mimefactory.loaded == Loaded::Message {
|
||||
mimefactory.msg.id
|
||||
} else {
|
||||
0
|
||||
}) as libc::c_int,
|
||||
param,
|
||||
0,
|
||||
);
|
||||
success = 1;
|
||||
}
|
||||
success
|
||||
}
|
||||
|
||||
pub fn job_add(
|
||||
|
||||
@@ -153,7 +153,7 @@ impl<'a> MimeFactory<'a> {
|
||||
/* create basic mail
|
||||
*************************************************************************/
|
||||
|
||||
let from: *mut mailimf_mailbox_list = mailimf_mailbox_list_new_empty();
|
||||
let from = mailimf_mailbox_list_new_empty();
|
||||
mailimf_mailbox_list_add(
|
||||
from,
|
||||
mailimf_mailbox_new(
|
||||
@@ -165,7 +165,7 @@ impl<'a> MimeFactory<'a> {
|
||||
self.from_addr.strdup(),
|
||||
),
|
||||
);
|
||||
let mut to: *mut mailimf_address_list = ptr::null_mut();
|
||||
let mut to = ptr::null_mut();
|
||||
if !self.recipients_names.is_empty() && !self.recipients_addr.is_empty() {
|
||||
to = mailimf_address_list_new_empty();
|
||||
let name_iter = self.recipients_names.iter();
|
||||
@@ -173,31 +173,21 @@ impl<'a> MimeFactory<'a> {
|
||||
for (name, addr) in name_iter.zip(addr_iter) {
|
||||
mailimf_address_list_add(
|
||||
to,
|
||||
mailimf_address_new(
|
||||
MAILIMF_ADDRESS_MAILBOX as libc::c_int,
|
||||
mailimf_mailbox_new(
|
||||
if !name.is_empty() {
|
||||
dc_encode_header_words(&name).strdup()
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
},
|
||||
addr.strdup(),
|
||||
),
|
||||
ptr::null_mut(),
|
||||
),
|
||||
mailimf_address_new_mailbox(mailimf_mailbox_new(
|
||||
if !name.is_empty() {
|
||||
dc_encode_header_words(&name).strdup()
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
},
|
||||
addr.strdup(),
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
let references_list = if !self.references.is_empty() {
|
||||
dc_str_to_clist(&self.references, " ")
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
};
|
||||
let in_reply_to_list = if !self.in_reply_to.is_empty() {
|
||||
dc_str_to_clist(&self.in_reply_to, " ")
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
};
|
||||
let references_list = dc_str_to_vec(&self.references, " ");
|
||||
|
||||
let in_reply_to_list = dc_str_to_vec(&self.in_reply_to, " ");
|
||||
|
||||
let imf_fields = mailimf_fields_new_with_data_all(
|
||||
mailimf_get_date(self.timestamp as i64),
|
||||
from,
|
||||
@@ -617,31 +607,9 @@ impl<'a> MimeFactory<'a> {
|
||||
|
||||
mailimf_fields_add(
|
||||
imf_fields,
|
||||
mailimf_field_new(
|
||||
MAILIMF_FIELD_SUBJECT as libc::c_int,
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
mailimf_subject_new(dc_encode_header_words(subject_str).strdup()),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
),
|
||||
mailimf_field::Subject(mailimf_subject_new(
|
||||
dc_encode_header_words(subject_str).strdup(),
|
||||
)),
|
||||
);
|
||||
|
||||
/*just a pointer into mailmime structure, must not be freed*/
|
||||
|
||||
@@ -180,11 +180,7 @@ pub fn add_filename_part(
|
||||
pub fn new_custom_field(fields: *mut mailimf_fields, name: &str, value: &str) {
|
||||
unsafe {
|
||||
let field = mailimf_field_new_custom(name.strdup(), value.strdup());
|
||||
let res = mailimf_fields_add(fields, field);
|
||||
assert!(
|
||||
res as u32 == MAILIMF_NO_ERROR,
|
||||
"could not create mailimf field"
|
||||
);
|
||||
mailimf_fields_add(fields, field);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user