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

memfd
Manos Pitsidianakis 2019-12-02 01:09:23 +02:00
parent fdb42cfc0c
commit dab9b39f4d
Signed by: Manos Pitsidianakis
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::email::*;
use crate::error::{MeliError, Result}; use crate::error::{MeliError, Result};
use fnv::{FnvHashMap, FnvHashSet}; use fnv::{FnvHashMap, FnvHashSet};
use std::collections::hash_map::DefaultHasher; use std::collections::{hash_map::DefaultHasher, BTreeMap};
use std::hash::Hasher; use std::hash::Hasher;
use std::str::FromStr; use std::str::FromStr;
use std::sync::{Arc, Mutex, RwLock}; use std::sync::{Arc, Mutex, RwLock};
@ -128,6 +128,8 @@ pub struct ImapType {
connection: Arc<Mutex<ImapConnection>>, connection: Arc<Mutex<ImapConnection>>,
server_conf: ImapServerConf, server_conf: ImapServerConf,
uid_store: Arc<UIDStore>, uid_store: Arc<UIDStore>,
can_create_flags: Arc<Mutex<bool>>,
tag_index: Arc<RwLock<BTreeMap<u64, String>>>,
folders: Arc<RwLock<FnvHashMap<FolderHash, ImapFolder>>>, folders: Arc<RwLock<FnvHashMap<FolderHash, ImapFolder>>>,
} }
@ -151,6 +153,7 @@ impl MailBackend for ImapType {
let handle = { let handle = {
let tx = w.tx(); let tx = w.tx();
let uid_store = self.uid_store.clone(); 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_path = folder.path().to_string();
let folder_hash = folder.hash(); let folder_hash = folder.hash();
let (permissions, folder_exists) = { let (permissions, folder_exists) = {
@ -176,6 +179,7 @@ impl MailBackend for ImapType {
let examine_response = protocol_parser::select_response(&response); let examine_response = protocol_parser::select_response(&response);
exit_on_error!(&tx, examine_response); exit_on_error!(&tx, examine_response);
let examine_response = examine_response.unwrap(); let examine_response = examine_response.unwrap();
*can_create_flags.lock().unwrap() = examine_response.can_create_flags;
debug!( debug!(
"folder: {} examine_response: {:?}", "folder: {} examine_response: {:?}",
folder_path, examine_response folder_path, examine_response
@ -445,6 +449,14 @@ impl MailBackend for ImapType {
fn as_any(&self) -> &dyn::std::any::Any { fn as_any(&self) -> &dyn::std::any::Any {
self 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 { impl ImapType {
@ -481,6 +493,8 @@ impl ImapType {
server_conf, server_conf,
is_subscribed: Arc::new(IsSubscribedFn(is_subscribed)), 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())), folders: Arc::new(RwLock::new(Default::default())),
connection: Arc::new(Mutex::new(connection)), connection: Arc::new(Mutex::new(connection)),
uid_store: Arc::new(UIDStore { uid_store: Arc::new(UIDStore {

View File

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