melib/imap: detect tag (\* flag) support

This commit is contained in:
Manos Pitsidianakis 2019-12-02 01:09:23 +02:00
parent fdb42cfc0c
commit dab9b39f4d
No known key found for this signature in database
GPG Key ID: 73627C2F690DF710
3 changed files with 32 additions and 13 deletions

View File

@ -41,7 +41,7 @@ use crate::conf::AccountSettings;
use crate::email::*;
use crate::error::{MeliError, Result};
use fnv::{FnvHashMap, FnvHashSet};
use std::collections::hash_map::DefaultHasher;
use std::collections::{hash_map::DefaultHasher, BTreeMap};
use std::hash::Hasher;
use std::str::FromStr;
use std::sync::{Arc, Mutex, RwLock};
@ -128,6 +128,8 @@ pub struct ImapType {
connection: Arc<Mutex<ImapConnection>>,
server_conf: ImapServerConf,
uid_store: Arc<UIDStore>,
can_create_flags: Arc<Mutex<bool>>,
tag_index: Arc<RwLock<BTreeMap<u64, String>>>,
folders: Arc<RwLock<FnvHashMap<FolderHash, ImapFolder>>>,
}
@ -151,6 +153,7 @@ impl MailBackend for ImapType {
let handle = {
let tx = w.tx();
let uid_store = self.uid_store.clone();
let can_create_flags = self.can_create_flags.clone();
let folder_path = folder.path().to_string();
let folder_hash = folder.hash();
let (permissions, folder_exists) = {
@ -176,6 +179,7 @@ impl MailBackend for ImapType {
let examine_response = protocol_parser::select_response(&response);
exit_on_error!(&tx, examine_response);
let examine_response = examine_response.unwrap();
*can_create_flags.lock().unwrap() = examine_response.can_create_flags;
debug!(
"folder: {} examine_response: {:?}",
folder_path, examine_response
@ -445,6 +449,14 @@ impl MailBackend for ImapType {
fn as_any(&self) -> &dyn::std::any::Any {
self
}
fn tags(&self) -> Option<Arc<RwLock<BTreeMap<u64, String>>>> {
if *self.can_create_flags.lock().unwrap() {
Some(self.tag_index.clone())
} else {
None
}
}
}
impl ImapType {
@ -481,6 +493,8 @@ impl ImapType {
server_conf,
is_subscribed: Arc::new(IsSubscribedFn(is_subscribed)),
can_create_flags: Arc::new(Mutex::new(false)),
tag_index: Arc::new(RwLock::new(Default::default())),
folders: Arc::new(RwLock::new(Default::default())),
connection: Arc::new(Mutex::new(connection)),
uid_store: Arc::new(UIDStore {

View File

@ -302,6 +302,8 @@ pub struct SelectResponse {
pub uidvalidity: usize,
pub uidnext: usize,
pub permanentflags: Flag,
/// if SELECT returns \* we can set arbritary flags permanently.
pub can_create_flags: bool,
pub read_only: bool,
}
@ -332,27 +334,23 @@ pub fn select_response(input: &str) -> Result<SelectResponse> {
let mut ret = SelectResponse::default();
for l in input.split("\r\n") {
if l.starts_with("* ") && l.ends_with(" EXISTS") {
ret.exists = usize::from_str(&l["* ".len()..l.len() - " EXISTS".len()]).unwrap();
ret.exists = usize::from_str(&l["* ".len()..l.len() - " EXISTS".len()])?;
} else if l.starts_with("* ") && l.ends_with(" RECENT") {
ret.recent = usize::from_str(&l["* ".len()..l.len() - " RECENT".len()]).unwrap();
ret.recent = usize::from_str(&l["* ".len()..l.len() - " RECENT".len()])?;
} else if l.starts_with("* FLAGS (") {
ret.flags = flags(&l["* FLAGS (".len()..l.len() - ")".len()])
.to_full_result()
.unwrap();
ret.flags = flags(&l["* FLAGS (".len()..l.len() - ")".len()]).to_full_result()?;
} else if l.starts_with("* OK [UNSEEN ") {
ret.unseen =
usize::from_str(&l["* OK [UNSEEN ".len()..l.find(']').unwrap()]).unwrap();
ret.unseen = usize::from_str(&l["* OK [UNSEEN ".len()..l.find(']').unwrap()])?;
} else if l.starts_with("* OK [UIDVALIDITY ") {
ret.uidvalidity =
usize::from_str(&l["* OK [UIDVALIDITY ".len()..l.find(']').unwrap()]).unwrap();
usize::from_str(&l["* OK [UIDVALIDITY ".len()..l.find(']').unwrap()])?;
} else if l.starts_with("* OK [UIDNEXT ") {
ret.uidnext =
usize::from_str(&l["* OK [UIDNEXT ".len()..l.find(']').unwrap()]).unwrap();
ret.uidnext = usize::from_str(&l["* OK [UIDNEXT ".len()..l.find(']').unwrap()])?;
} else if l.starts_with("* OK [PERMANENTFLAGS (") {
ret.permanentflags =
flags(&l["* OK [PERMANENTFLAGS (".len()..l.find(')').unwrap()])
.to_full_result()
.unwrap();
.to_full_result()?;
ret.can_create_flags = l.contains("\\*");
} else if l.contains("OK [READ-WRITE]") {
ret.read_only = false;
} else if l.contains("OK [READ-ONLY]") {

View File

@ -144,6 +144,13 @@ impl From<native_tls::Error> for MeliError {
}
}
impl From<std::num::ParseIntError> for MeliError {
#[inline]
fn from(kind: std::num::ParseIntError) -> MeliError {
MeliError::new(format!("{}", kind))
}
}
impl From<&str> for MeliError {
#[inline]
fn from(kind: &str) -> MeliError {