Import upstream v0.16.22, stripped
Upstream commit: 474dd0229cb20cf513036619781ed97bd8073c3f Enterprise-only files removed or emptied: 63 Enterprise-only snippets removed: 117 in 50 files Dangling module declarations removed: 5 Cargo edits turning enterprise off: 14 Verification: clean Enterprise feature gates left for rebuilt features: 19 in 18 files Produced by tools/fork/strip.py. The full report is in docs/fork/strip-reports/ on main.
This commit is contained in:
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use crate::{ResponseCode, StatusResponse};
|
||||
|
||||
use super::{ImapResponse, ObjectId, Sequence, list::ListItem};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Arguments {
|
||||
pub tag: String,
|
||||
pub mailbox_name: String,
|
||||
pub condstore: bool,
|
||||
pub qresync: Option<QResync>,
|
||||
pub objectid: Option<ObjectId>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct QResync {
|
||||
pub uid_validity: u32,
|
||||
pub modseq: u64,
|
||||
pub known_uids: Option<Sequence>,
|
||||
pub seq_match: Option<(Sequence, Sequence)>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct HighestModSeq(u64);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Response {
|
||||
pub mailbox: ListItem,
|
||||
pub total_messages: usize,
|
||||
pub recent_messages: usize,
|
||||
pub unseen_seq: u32,
|
||||
pub uid_validity: u32,
|
||||
pub uid_next: u32,
|
||||
pub is_rev2: bool,
|
||||
pub is_utf8: bool,
|
||||
pub closed_previous: bool,
|
||||
pub highest_modseq: Option<HighestModSeq>,
|
||||
pub objectid: Option<ObjectId>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Exists {
|
||||
pub total_messages: usize,
|
||||
}
|
||||
|
||||
impl ImapResponse for Response {
|
||||
fn serialize(self) -> Vec<u8> {
|
||||
let mut buf = Vec::with_capacity(100);
|
||||
if self.closed_previous {
|
||||
buf = StatusResponse::ok("Closed previous mailbox")
|
||||
.with_code(ResponseCode::Closed)
|
||||
.serialize(buf);
|
||||
}
|
||||
buf.extend_from_slice(b"* ");
|
||||
buf.extend_from_slice(self.total_messages.to_string().as_bytes());
|
||||
if !self.is_rev2 && self.recent_messages > 0 {
|
||||
buf.extend_from_slice(
|
||||
b" EXISTS\r\n* FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft \\Recent)\r\n",
|
||||
);
|
||||
} else {
|
||||
buf.extend_from_slice(
|
||||
b" EXISTS\r\n* FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft)\r\n",
|
||||
);
|
||||
}
|
||||
if self.is_rev2 {
|
||||
self.mailbox
|
||||
.serialize(&mut buf, self.is_rev2, self.is_utf8, false);
|
||||
} else {
|
||||
buf.extend_from_slice(b"* ");
|
||||
buf.extend_from_slice(self.recent_messages.to_string().as_bytes());
|
||||
buf.extend_from_slice(b" RECENT\r\n");
|
||||
if self.unseen_seq > 0 {
|
||||
buf.extend_from_slice(b"* OK [UNSEEN ");
|
||||
buf.extend_from_slice(self.unseen_seq.to_string().as_bytes());
|
||||
buf.extend_from_slice(b"] Unseen messages\r\n");
|
||||
}
|
||||
}
|
||||
buf.extend_from_slice(
|
||||
b"* OK [PERMANENTFLAGS (\\Deleted \\Seen \\Answered \\Flagged \\Draft \\*)] All allowed\r\n",
|
||||
);
|
||||
buf.extend_from_slice(b"* OK [UIDVALIDITY ");
|
||||
buf.extend_from_slice(self.uid_validity.to_string().as_bytes());
|
||||
buf.extend_from_slice(b"] UIDs valid\r\n* OK [UIDNEXT ");
|
||||
buf.extend_from_slice(self.uid_next.to_string().as_bytes());
|
||||
buf.extend_from_slice(b"] Next predicted UID\r\n");
|
||||
if let Some(highest_modseq) = self.highest_modseq {
|
||||
highest_modseq.serialize(&mut buf);
|
||||
}
|
||||
if let Some(objectid) = &self.objectid {
|
||||
buf.extend_from_slice(b"* OK [");
|
||||
objectid.serialize(&mut buf);
|
||||
buf.extend_from_slice(b"] Object identifiers\r\n");
|
||||
}
|
||||
buf
|
||||
}
|
||||
}
|
||||
|
||||
impl HighestModSeq {
|
||||
pub fn new(modseq: u64) -> Self {
|
||||
Self(modseq)
|
||||
}
|
||||
|
||||
pub fn serialize(&self, buf: &mut Vec<u8>) {
|
||||
buf.extend_from_slice(b"* OK [HIGHESTMODSEQ ");
|
||||
buf.extend_from_slice(self.0.to_string().as_bytes());
|
||||
buf.extend_from_slice(b"] Highest Modseq\r\n");
|
||||
}
|
||||
|
||||
pub fn into_bytes(self) -> Vec<u8> {
|
||||
let mut buf = Vec::with_capacity(40);
|
||||
self.serialize(&mut buf);
|
||||
buf
|
||||
}
|
||||
}
|
||||
|
||||
impl Exists {
|
||||
pub fn serialize(&self, buf: &mut Vec<u8>) {
|
||||
buf.extend_from_slice(b"* ");
|
||||
buf.extend_from_slice(self.total_messages.to_string().as_bytes());
|
||||
buf.extend_from_slice(b" EXISTS\r\n");
|
||||
}
|
||||
|
||||
pub fn into_bytes(self) -> Vec<u8> {
|
||||
let mut buf = Vec::with_capacity(15);
|
||||
self.serialize(&mut buf);
|
||||
buf
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::protocol::{ImapResponse, ObjectId, list::ListItem};
|
||||
use types::id::Id;
|
||||
|
||||
use super::HighestModSeq;
|
||||
|
||||
#[test]
|
||||
fn serialize_select() {
|
||||
let objectid = ObjectId {
|
||||
mailbox_id: Some(Id::from(1u32)),
|
||||
account_id: Some(Id::from(2u32)),
|
||||
..Default::default()
|
||||
};
|
||||
let mut objectid_line = b"* OK [".to_vec();
|
||||
objectid.serialize(&mut objectid_line);
|
||||
objectid_line.extend_from_slice(b"] Object identifiers\r\n");
|
||||
let objectid_line = String::from_utf8(objectid_line).unwrap();
|
||||
|
||||
for (mut response, _tag, expected_v2, expected_v1) in [
|
||||
(
|
||||
super::Response {
|
||||
mailbox: ListItem::new("INBOX"),
|
||||
total_messages: 172,
|
||||
recent_messages: 5,
|
||||
unseen_seq: 3,
|
||||
uid_validity: 3857529045,
|
||||
uid_next: 4392,
|
||||
closed_previous: false,
|
||||
is_rev2: true,
|
||||
is_utf8: true,
|
||||
highest_modseq: HighestModSeq::new(100).into(),
|
||||
objectid: Some(objectid.clone()),
|
||||
},
|
||||
"A142",
|
||||
format!(
|
||||
concat!(
|
||||
"* 172 EXISTS\r\n",
|
||||
"* FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft)\r\n",
|
||||
"* LIST () \"/\" \"INBOX\"\r\n",
|
||||
"* OK [PERMANENTFLAGS (\\Deleted \\Seen \\Answered \\Flagged \\Draft \\*)] All allowed\r\n",
|
||||
"* OK [UIDVALIDITY 3857529045] UIDs valid\r\n",
|
||||
"* OK [UIDNEXT 4392] Next predicted UID\r\n",
|
||||
"* OK [HIGHESTMODSEQ 100] Highest Modseq\r\n",
|
||||
"{}"
|
||||
),
|
||||
objectid_line
|
||||
),
|
||||
format!(
|
||||
concat!(
|
||||
"* 172 EXISTS\r\n",
|
||||
"* FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft \\Recent)\r\n",
|
||||
"* 5 RECENT\r\n",
|
||||
"* OK [UNSEEN 3] Unseen messages\r\n",
|
||||
"* OK [PERMANENTFLAGS (\\Deleted \\Seen \\Answered \\Flagged \\Draft \\*)] All allowed\r\n",
|
||||
"* OK [UIDVALIDITY 3857529045] UIDs valid\r\n",
|
||||
"* OK [UIDNEXT 4392] Next predicted UID\r\n",
|
||||
"* OK [HIGHESTMODSEQ 100] Highest Modseq\r\n",
|
||||
"{}"
|
||||
),
|
||||
objectid_line
|
||||
),
|
||||
),
|
||||
(
|
||||
super::Response {
|
||||
mailbox: ListItem::new("~peter/mail/台北/日本語"),
|
||||
total_messages: 172,
|
||||
recent_messages: 5,
|
||||
unseen_seq: 3,
|
||||
uid_validity: 3857529045,
|
||||
uid_next: 4392,
|
||||
closed_previous: true,
|
||||
is_rev2: true,
|
||||
is_utf8: true,
|
||||
highest_modseq: None,
|
||||
objectid: Some(objectid.clone()),
|
||||
},
|
||||
"A142",
|
||||
format!(
|
||||
concat!(
|
||||
"* OK [CLOSED] Closed previous mailbox\r\n",
|
||||
"* 172 EXISTS\r\n",
|
||||
"* FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft)\r\n",
|
||||
"* LIST () \"/\" \"~peter/mail/台北/日本語\" (\"OLDNAME\" ",
|
||||
"(\"~peter/mail/&U,BTFw-/&ZeVnLIqe-\"))\r\n",
|
||||
"* OK [PERMANENTFLAGS (\\Deleted \\Seen \\Answered \\Flagged \\Draft \\*)] All allowed\r\n",
|
||||
"* OK [UIDVALIDITY 3857529045] UIDs valid\r\n",
|
||||
"* OK [UIDNEXT 4392] Next predicted UID\r\n",
|
||||
"{}"
|
||||
),
|
||||
objectid_line
|
||||
),
|
||||
format!(
|
||||
concat!(
|
||||
"* OK [CLOSED] Closed previous mailbox\r\n",
|
||||
"* 172 EXISTS\r\n",
|
||||
"* FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft \\Recent)\r\n",
|
||||
"* 5 RECENT\r\n",
|
||||
"* OK [UNSEEN 3] Unseen messages\r\n",
|
||||
"* OK [PERMANENTFLAGS (\\Deleted \\Seen \\Answered \\Flagged \\Draft \\*)] All allowed\r\n",
|
||||
"* OK [UIDVALIDITY 3857529045] UIDs valid\r\n",
|
||||
"* OK [UIDNEXT 4392] Next predicted UID\r\n",
|
||||
"{}"
|
||||
),
|
||||
objectid_line
|
||||
),
|
||||
),
|
||||
] {
|
||||
let response_v2 = String::from_utf8(response.clone().serialize()).unwrap();
|
||||
response.is_rev2 = false;
|
||||
let response_v1 = String::from_utf8(response.serialize()).unwrap();
|
||||
|
||||
assert_eq!(response_v2, expected_v2);
|
||||
assert_eq!(response_v1, expected_v1);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user