Fix: Folders that contain a & can't be used (#90)

This commit is contained in:
mdecimus 2023-09-16 11:06:52 +02:00
parent 216fcf2d73
commit bb7f43ecab
6 changed files with 71 additions and 34 deletions

View file

@ -22,8 +22,12 @@
*/ */
use crate::{ use crate::{
protocol::acl::{self, ModRights, ModRightsOp, Rights}, protocol::{
acl::{self, ModRights, ModRightsOp, Rights},
ProtocolVersion,
},
receiver::Request, receiver::Request,
utf7::utf7_maybe_decode,
Command, Command,
}; };
@ -45,7 +49,7 @@ use super::PushUnique;
*/ */
impl Request<Command> { impl Request<Command> {
pub fn parse_acl(self) -> crate::Result<acl::Arguments> { pub fn parse_acl(self, version: ProtocolVersion) -> crate::Result<acl::Arguments> {
let (has_identifier, has_mod_rights) = match self.command { let (has_identifier, has_mod_rights) = match self.command {
Command::SetAcl => (true, true), Command::SetAcl => (true, true),
Command::DeleteAcl | Command::ListRights => (true, false), Command::DeleteAcl | Command::ListRights => (true, false),
@ -53,11 +57,14 @@ impl Request<Command> {
_ => unreachable!(), _ => unreachable!(),
}; };
let mut tokens = self.tokens.into_iter(); let mut tokens = self.tokens.into_iter();
let mailbox_name = tokens let mailbox_name = utf7_maybe_decode(
.next() tokens
.ok_or((self.tag.as_str(), "Missing mailbox name."))? .next()
.unwrap_string() .ok_or((self.tag.as_str(), "Missing mailbox name."))?
.map_err(|v| (self.tag.as_str(), v))?; .unwrap_string()
.map_err(|v| (self.tag.as_str(), v))?,
version,
);
let identifier = if has_identifier { let identifier = if has_identifier {
tokens tokens
.next() .next()
@ -138,7 +145,10 @@ impl ModRights {
mod tests { mod tests {
use crate::{ use crate::{
protocol::acl::{self, ModRights, ModRightsOp, Rights}, protocol::{
acl::{self, ModRights, ModRightsOp, Rights},
ProtocolVersion,
},
receiver::Receiver, receiver::Receiver,
}; };
@ -222,7 +232,7 @@ mod tests {
receiver receiver
.parse(&mut command.as_bytes().iter()) .parse(&mut command.as_bytes().iter())
.unwrap() .unwrap()
.parse_acl() .parse_acl(ProtocolVersion::Rev1)
.unwrap(), .unwrap(),
arguments, arguments,
"{:?}", "{:?}",

View file

@ -24,9 +24,10 @@
use crate::{ use crate::{
protocol::{ protocol::{
append::{self, Message}, append::{self, Message},
Flag, Flag, ProtocolVersion,
}, },
receiver::{Request, Token}, receiver::{Request, Token},
utf7::utf7_maybe_decode,
Command, Command,
}; };
@ -40,17 +41,20 @@ enum State {
} }
impl Request<Command> { impl Request<Command> {
pub fn parse_append(self) -> crate::Result<append::Arguments> { pub fn parse_append(self, version: ProtocolVersion) -> crate::Result<append::Arguments> {
match self.tokens.len() { match self.tokens.len() {
0 | 1 => Err(self.into_error("Missing arguments.")), 0 | 1 => Err(self.into_error("Missing arguments.")),
_ => { _ => {
// Obtain mailbox name // Obtain mailbox name
let mut tokens = self.tokens.into_iter().peekable(); let mut tokens = self.tokens.into_iter().peekable();
let mailbox_name = tokens let mailbox_name = utf7_maybe_decode(
.next() tokens
.unwrap() .next()
.unwrap_string() .unwrap()
.map_err(|v| (self.tag.as_str(), v))?; .unwrap_string()
.map_err(|v| (self.tag.as_str(), v))?,
version,
);
let mut messages = Vec::new(); let mut messages = Vec::new();
while tokens.peek().is_some() { while tokens.peek().is_some() {
@ -166,7 +170,7 @@ mod tests {
use crate::{ use crate::{
protocol::{ protocol::{
append::{self, Message}, append::{self, Message},
Flag, Flag, ProtocolVersion,
}, },
receiver::{Error, Receiver}, receiver::{Error, Receiver},
}; };
@ -265,7 +269,7 @@ mod tests {
receiver receiver
.parse(&mut command.as_bytes().iter()) .parse(&mut command.as_bytes().iter())
.expect(command) .expect(command)
.parse_append() .parse_append(ProtocolVersion::Rev1)
.expect(command), .expect(command),
arguments, arguments,
"{:?}", "{:?}",
@ -298,7 +302,7 @@ mod tests {
match receiver.parse(&mut line.as_bytes().iter()) { match receiver.parse(&mut line.as_bytes().iter()) {
Ok(request) => { Ok(request) => {
assert_eq!( assert_eq!(
request.parse_append().unwrap(), request.parse_append(ProtocolVersion::Rev1).unwrap(),
append::Arguments { append::Arguments {
tag: "A003".to_string(), tag: "A003".to_string(),
mailbox_name: "saved-messages".to_string(), mailbox_name: "saved-messages".to_string(),

View file

@ -21,12 +21,17 @@
* for more details. * for more details.
*/ */
use crate::{protocol::copy_move, receiver::Request, Command}; use crate::{
protocol::{copy_move, ProtocolVersion},
receiver::Request,
utf7::utf7_maybe_decode,
Command,
};
use super::parse_sequence_set; use super::parse_sequence_set;
impl Request<Command> { impl Request<Command> {
pub fn parse_copy_move(self) -> crate::Result<copy_move::Arguments> { pub fn parse_copy_move(self, version: ProtocolVersion) -> crate::Result<copy_move::Arguments> {
if self.tokens.len() > 1 { if self.tokens.len() > 1 {
let mut tokens = self.tokens.into_iter(); let mut tokens = self.tokens.into_iter();
@ -38,11 +43,14 @@ impl Request<Command> {
.unwrap_bytes(), .unwrap_bytes(),
) )
.map_err(|v| (self.tag.as_str(), v))?, .map_err(|v| (self.tag.as_str(), v))?,
mailbox_name: tokens mailbox_name: utf7_maybe_decode(
.next() tokens
.ok_or((self.tag.as_str(), "Missing mailbox name."))? .next()
.unwrap_string() .ok_or((self.tag.as_str(), "Missing mailbox name."))?
.map_err(|v| (self.tag.as_str(), v))?, .unwrap_string()
.map_err(|v| (self.tag.as_str(), v))?,
version,
),
tag: self.tag, tag: self.tag,
}) })
} else { } else {
@ -54,7 +62,7 @@ impl Request<Command> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{ use crate::{
protocol::{copy_move, Sequence}, protocol::{copy_move, ProtocolVersion, Sequence},
receiver::Receiver, receiver::Receiver,
}; };
@ -66,7 +74,7 @@ mod tests {
receiver receiver
.parse(&mut "A003 COPY 2:4 MEETING\r\n".as_bytes().iter()) .parse(&mut "A003 COPY 2:4 MEETING\r\n".as_bytes().iter())
.unwrap() .unwrap()
.parse_copy_move() .parse_copy_move(ProtocolVersion::Rev1)
.unwrap(), .unwrap(),
copy_move::Arguments { copy_move::Arguments {
sequence_set: Sequence::Range { sequence_set: Sequence::Range {
@ -77,5 +85,20 @@ mod tests {
tag: "A003".to_string(), tag: "A003".to_string(),
} }
); );
assert_eq!(
receiver
.parse(&mut "A003 COPY 2:4 \"You &- Me\"\r\n".as_bytes().iter())
.unwrap()
.parse_copy_move(ProtocolVersion::Rev1)
.unwrap(),
copy_move::Arguments {
sequence_set: Sequence::Range {
start: 2.into(),
end: 4.into(),
},
mailbox_name: "You & Me".to_string(),
tag: "A003".to_string(),
}
);
} }
} }

View file

@ -51,7 +51,7 @@ use crate::core::{MailboxId, Session, SessionData};
impl<T: AsyncRead> Session<T> { impl<T: AsyncRead> Session<T> {
pub async fn handle_get_acl(&mut self, request: Request<Command>) -> crate::OpResult { pub async fn handle_get_acl(&mut self, request: Request<Command>) -> crate::OpResult {
match request.parse_acl() { match request.parse_acl(self.version) {
Ok(arguments) => { Ok(arguments) => {
let data = self.state.session_data(); let data = self.state.session_data();
let is_rev2 = self.version.is_rev2(); let is_rev2 = self.version.is_rev2();
@ -165,7 +165,7 @@ impl<T: AsyncRead> Session<T> {
} }
pub async fn handle_my_rights(&mut self, request: Request<Command>) -> crate::OpResult { pub async fn handle_my_rights(&mut self, request: Request<Command>) -> crate::OpResult {
match request.parse_acl() { match request.parse_acl(self.version) {
Ok(arguments) => { Ok(arguments) => {
let data = self.state.session_data(); let data = self.state.session_data();
let is_rev2 = self.version.is_rev2(); let is_rev2 = self.version.is_rev2();
@ -265,7 +265,7 @@ impl<T: AsyncRead> Session<T> {
pub async fn handle_set_acl(&mut self, request: Request<Command>) -> crate::OpResult { pub async fn handle_set_acl(&mut self, request: Request<Command>) -> crate::OpResult {
let command = request.command; let command = request.command;
match request.parse_acl() { match request.parse_acl(self.version) {
Ok(arguments) => { Ok(arguments) => {
let data = self.state.session_data(); let data = self.state.session_data();
@ -489,7 +489,7 @@ impl<T: AsyncRead> Session<T> {
} }
pub async fn handle_list_rights(&mut self, request: Request<Command>) -> crate::OpResult { pub async fn handle_list_rights(&mut self, request: Request<Command>) -> crate::OpResult {
match request.parse_acl() { match request.parse_acl(self.version) {
Ok(arguments) => { Ok(arguments) => {
self.write_bytes( self.write_bytes(
StatusResponse::completed(Command::ListRights) StatusResponse::completed(Command::ListRights)

View file

@ -36,7 +36,7 @@ use crate::core::{MailboxId, SelectedMailbox, Session, SessionData};
impl<T: AsyncRead> Session<T> { impl<T: AsyncRead> Session<T> {
pub async fn handle_append(&mut self, request: Request<Command>) -> crate::OpResult { pub async fn handle_append(&mut self, request: Request<Command>) -> crate::OpResult {
match request.parse_append() { match request.parse_append(self.version) {
Ok(arguments) => { Ok(arguments) => {
let (data, selected_mailbox) = self.state.session_mailbox_state(); let (data, selected_mailbox) = self.state.session_mailbox_state();

View file

@ -48,7 +48,7 @@ impl<T: AsyncRead> Session<T> {
is_move: bool, is_move: bool,
is_uid: bool, is_uid: bool,
) -> crate::OpResult { ) -> crate::OpResult {
match request.parse_copy_move() { match request.parse_copy_move(self.version) {
Ok(arguments) => { Ok(arguments) => {
let (data, src_mailbox) = self.state.mailbox_state(); let (data, src_mailbox) = self.state.mailbox_state();