Upstream commit: 9d1c75ab68435e4417337f768291e5f947686203 Enterprise-only files removed or emptied: 63 Enterprise-only snippets removed: 118 in 50 files Dangling module declarations removed: 5 Edits turning enterprise off: 25 Third-party code: 14 files, 0 not in THIRD-PARTY.md Verification: clean One snippet more than v0.16.22, in crates/common/src/auth/authentication.rs (3, was 2).
This commit is contained in:
@@ -14,7 +14,7 @@ pub enum Response<'x, T> {
|
||||
List(Vec<T>),
|
||||
Message {
|
||||
bytes: SliceRange<'x>,
|
||||
lines: u32,
|
||||
lines: Option<u32>,
|
||||
},
|
||||
Capability {
|
||||
mechanisms: Vec<Mechanism>,
|
||||
@@ -52,40 +52,65 @@ impl<'x, T: Display> Response<'x, T> {
|
||||
buf
|
||||
}
|
||||
Response::Message { bytes, lines } => {
|
||||
let mut buf = Vec::with_capacity(bytes.len() + 10);
|
||||
buf.extend_from_slice(b"+OK ");
|
||||
buf.extend_from_slice(bytes.len().to_string().as_bytes());
|
||||
buf.extend_from_slice(b" octets\r\n");
|
||||
|
||||
let mut line_count = 0;
|
||||
let mut last_byte = 0;
|
||||
let lines = *lines;
|
||||
let mut message = Vec::with_capacity(bytes.len() + 16);
|
||||
let mut octets = 0;
|
||||
let mut last_byte = b'\n';
|
||||
let mut in_headers = lines.is_some();
|
||||
let mut is_blank_line = true;
|
||||
let mut body_lines = 0;
|
||||
|
||||
// Transparency procedure
|
||||
for &byte in bytes.into_iter() {
|
||||
// POP3 requires that lines end with CRLF, do this check to ensure that
|
||||
if byte == b'\n' && last_byte != b'\r' {
|
||||
buf.push(b'\r');
|
||||
message.push(b'\r');
|
||||
octets += 1;
|
||||
}
|
||||
|
||||
if byte == b'.' && last_byte == b'\n' {
|
||||
buf.push(b'.');
|
||||
message.push(b'.');
|
||||
}
|
||||
buf.push(byte);
|
||||
message.push(byte);
|
||||
octets += 1;
|
||||
last_byte = byte;
|
||||
|
||||
if *lines > 0 && byte == b'\n' {
|
||||
line_count += 1;
|
||||
if line_count == *lines {
|
||||
break;
|
||||
match byte {
|
||||
b'\n' => {
|
||||
if in_headers {
|
||||
in_headers = !is_blank_line;
|
||||
} else {
|
||||
body_lines += 1;
|
||||
}
|
||||
if !in_headers && lines.is_some_and(|lines| body_lines >= lines) {
|
||||
break;
|
||||
}
|
||||
is_blank_line = true;
|
||||
}
|
||||
b'\r' => {}
|
||||
_ => {
|
||||
is_blank_line = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if last_byte != b'\n' {
|
||||
buf.extend_from_slice(b"\r\n");
|
||||
message.extend_from_slice(b"\r\n");
|
||||
octets += 2;
|
||||
}
|
||||
|
||||
buf.extend_from_slice(b".\r\n");
|
||||
if in_headers {
|
||||
message.extend_from_slice(b"\r\n");
|
||||
octets += 2;
|
||||
}
|
||||
|
||||
message.extend_from_slice(b".\r\n");
|
||||
|
||||
let mut buf = Vec::with_capacity(message.len() + 24);
|
||||
buf.extend_from_slice(b"+OK ");
|
||||
buf.extend_from_slice(octets.to_string().as_bytes());
|
||||
buf.extend_from_slice(b" octets\r\n");
|
||||
buf.extend_from_slice(&message);
|
||||
buf
|
||||
}
|
||||
Response::Capability { mechanisms, stls } => {
|
||||
@@ -206,9 +231,51 @@ mod tests {
|
||||
(
|
||||
Response::Message {
|
||||
bytes: SliceRange::Split(b"Subject: test\r\n\r\n.\r\n", b"test.\r\n.test\r\na"),
|
||||
lines: 0,
|
||||
lines: None,
|
||||
},
|
||||
"+OK 35 octets\r\nSubject: test\r\n\r\n..\r\ntest.\r\n..test\r\na\r\n.\r\n",
|
||||
"+OK 37 octets\r\nSubject: test\r\n\r\n..\r\ntest.\r\n..test\r\na\r\n.\r\n",
|
||||
),
|
||||
(
|
||||
Response::Message {
|
||||
bytes: SliceRange::Split(b"Subject: test\r\n\r\n.\r\n", b"test.\r\n.test\r\na"),
|
||||
lines: Some(0),
|
||||
},
|
||||
"+OK 17 octets\r\nSubject: test\r\n\r\n.\r\n",
|
||||
),
|
||||
(
|
||||
Response::Message {
|
||||
bytes: SliceRange::Split(b"Subject: test\r\n\r\n.\r\n", b"test.\r\n.test\r\na"),
|
||||
lines: Some(2),
|
||||
},
|
||||
"+OK 27 octets\r\nSubject: test\r\n\r\n..\r\ntest.\r\n.\r\n",
|
||||
),
|
||||
(
|
||||
Response::Message {
|
||||
bytes: SliceRange::Split(b"Subject: test\r\n\r\n.\r\n", b"test.\r\n.test\r\na"),
|
||||
lines: Some(100),
|
||||
},
|
||||
"+OK 37 octets\r\nSubject: test\r\n\r\n..\r\ntest.\r\n..test\r\na\r\n.\r\n",
|
||||
),
|
||||
(
|
||||
Response::Message {
|
||||
bytes: SliceRange::Single(b"Subject: test\n\nbody\n"),
|
||||
lines: None,
|
||||
},
|
||||
"+OK 23 octets\r\nSubject: test\r\n\r\nbody\r\n.\r\n",
|
||||
),
|
||||
(
|
||||
Response::Message {
|
||||
bytes: SliceRange::Single(b"Subject: test\n\n.leading dot\n"),
|
||||
lines: Some(1),
|
||||
},
|
||||
"+OK 31 octets\r\nSubject: test\r\n\r\n..leading dot\r\n.\r\n",
|
||||
),
|
||||
(
|
||||
Response::Message {
|
||||
bytes: SliceRange::Single(b".dot\r\nSubject: test\r\n"),
|
||||
lines: Some(3),
|
||||
},
|
||||
"+OK 23 octets\r\n..dot\r\nSubject: test\r\n\r\n.\r\n",
|
||||
),
|
||||
] {
|
||||
assert_eq!(expected, String::from_utf8(cmd.serialize()).unwrap());
|
||||
|
||||
Reference in New Issue
Block a user