Merge upstream v0.16.23
Five conflicts, resolved: - crates/common/src/auth/authentication.rs: upstream's get_directory_for_token and JwtClaims replace extract_jwt_domain; the per-domain directory code (DIR-1, DIR-5 to DIR-7) is kept, and the token lookup routes through it. The release's one new Enterprise snippet was the body of get_directory_for_issuer, which stays returning None: a token naming no address gets the server default, as DIR-2 specifies and as v0.16.22 did. - crates/common/src/manager/application.rs: upstream's rewrite of the tests, with the temp directory names renamed again, and the 5(a) notice the name-purge change should have added. - crates/common/src/network/mta.rs: both sides' imports. - crates/main/Cargo.toml: the AGPL-only license kept, version 0.16.23. - Cargo.lock: upstream's, with the fork's crates added by Cargo.
This commit is contained in:
@@ -16,7 +16,7 @@ pub enum Response<'x, T> {
|
||||
List(Vec<T>),
|
||||
Message {
|
||||
bytes: SliceRange<'x>,
|
||||
lines: u32,
|
||||
lines: Option<u32>,
|
||||
},
|
||||
Capability {
|
||||
mechanisms: Vec<Mechanism>,
|
||||
@@ -54,40 +54,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 } => {
|
||||
@@ -208,9 +233,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