Fix IMAP: Pipelined STORE and EXPUNGE can execute out of order
This commit is contained in:
@@ -30,11 +30,14 @@ impl<T: SessionStream> Session<T> {
|
||||
let mut bytes = bytes.iter();
|
||||
let mut requests = Vec::with_capacity(2);
|
||||
let mut needs_literal = None;
|
||||
let mut has_expunge = false;
|
||||
|
||||
loop {
|
||||
match self.receiver.parse(&mut bytes) {
|
||||
Ok(request) => match self.is_allowed(request).await {
|
||||
Ok(request) => {
|
||||
has_expunge |=
|
||||
matches!(request.command, Command::Expunge(_) | Command::Close);
|
||||
requests.push(request);
|
||||
}
|
||||
Err(err) => {
|
||||
@@ -140,7 +143,7 @@ impl<T: SessionStream> Session<T> {
|
||||
.await
|
||||
.map(|_| SessionResult::Continue),
|
||||
Command::Store(is_uid) => self
|
||||
.handle_store(request, is_uid)
|
||||
.handle_store(request, is_uid, !has_expunge)
|
||||
.await
|
||||
.map(|_| SessionResult::Continue),
|
||||
Command::Copy(is_uid) => self
|
||||
|
||||
@@ -43,6 +43,7 @@ impl<T: SessionStream> Session<T> {
|
||||
&mut self,
|
||||
request: Request<Command>,
|
||||
is_uid: bool,
|
||||
spawn: bool,
|
||||
) -> trc::Result<()> {
|
||||
// Validate access
|
||||
self.assert_has_permission(Permission::ImapStore)?;
|
||||
@@ -52,13 +53,21 @@ impl<T: SessionStream> Session<T> {
|
||||
let (data, mailbox) = self.state.select_data();
|
||||
let is_condstore = self.is_condstore || mailbox.is_condstore;
|
||||
|
||||
spawn_op!(data, {
|
||||
if spawn {
|
||||
spawn_op!(data, {
|
||||
let response = data
|
||||
.store(arguments, mailbox, is_uid, is_condstore, op_start)
|
||||
.await?;
|
||||
|
||||
data.write_bytes(response).await
|
||||
})
|
||||
} else {
|
||||
let response = data
|
||||
.store(arguments, mailbox, is_uid, is_condstore, op_start)
|
||||
.await?;
|
||||
|
||||
data.write_bytes(response).await
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user