diff options
author | Manos Pitsidianakis <el13635@mail.ntua.gr> | 2019-08-23 21:32:32 +0300 |
---|---|---|
committer | Manos Pitsidianakis <el13635@mail.ntua.gr> | 2019-08-25 10:48:01 +0300 |
commit | 76909a1959ca2a0bc39e91ae22f401d6e756e975 (patch) | |
tree | d3c68216a78ef8f5074ca46354476792cddf8fd9 /melib | |
parent | b39b2857111e3632e7f25bc1b77fd34816b6d3bd (diff) |
add folder subscriptions
Diffstat (limited to 'melib')
-rw-r--r-- | melib/src/backends.rs | 9 | ||||
-rw-r--r-- | melib/src/backends/maildir.rs | 52 | ||||
-rw-r--r-- | melib/src/backends/maildir/backend.rs | 63 | ||||
-rw-r--r-- | melib/src/conf.rs | 5 |
4 files changed, 101 insertions, 28 deletions
diff --git a/melib/src/backends.rs b/melib/src/backends.rs index 21c3a66b..cdc6da1c 100644 --- a/melib/src/backends.rs +++ b/melib/src/backends.rs @@ -248,9 +248,8 @@ impl BackendOp for ReadOnlyOp { pub trait BackendFolder: Debug { fn hash(&self) -> FolderHash; fn name(&self) -> &str; - fn path(&self) -> &str { - self.name() - } + /// Path of folder within the mailbox hierarchy, with `/` as separator. + fn path(&self) -> &str; fn change_name(&mut self, new_name: &str); fn clone(&self) -> Folder; fn children(&self) -> &Vec<FolderHash>; @@ -271,6 +270,10 @@ impl BackendFolder for DummyFolder { "" } + fn path(&self) -> &str { + "" + } + fn change_name(&mut self, _s: &str) {} fn clone(&self) -> Folder { diff --git a/melib/src/backends/maildir.rs b/melib/src/backends/maildir.rs index be6de086..e346bd90 100644 --- a/melib/src/backends/maildir.rs +++ b/melib/src/backends/maildir.rs @@ -177,6 +177,7 @@ impl<'a> BackendOp for MaildirOp { pub struct MaildirFolder { hash: FolderHash, name: String, + fs_path: PathBuf, path: PathBuf, parent: Option<FolderHash>, children: Vec<FolderHash>, @@ -188,26 +189,62 @@ impl MaildirFolder { file_name: String, parent: Option<FolderHash>, children: Vec<FolderHash>, + settings: &AccountSettings, ) -> Result<Self> { - let pathbuf = PathBuf::from(path); + macro_rules! strip_slash { + ($v:expr) => { + if $v.ends_with("/") { + &$v[..$v.len() - 1] + } else { + $v + } + }; + } + let pathbuf = PathBuf::from(&path); let mut h = DefaultHasher::new(); pathbuf.hash(&mut h); + /* Check if folder path (Eg `INBOX/Lists/luddites`) is included in the subscribed + * mailboxes in user configuration */ + let fname = if let Ok(fname) = pathbuf.strip_prefix( + PathBuf::from(&settings.root_folder) + .parent() + .unwrap_or_else(|| &Path::new("/")), + ) { + if fname.components().count() != 0 + && !settings + .subscribed_folders + .iter() + .any(|x| x == strip_slash!(fname.to_str().unwrap())) + { + return Err(MeliError::new(format!( + "Folder with name `{}` is not included in configured subscribed mailboxes", + fname.display() + ))); + } + Some(fname) + } else { + None + }; + let ret = MaildirFolder { hash: h.finish(), name: file_name, - path: pathbuf, + path: fname.unwrap().to_path_buf(), + fs_path: pathbuf, parent, children, }; ret.is_valid()?; Ok(ret) } - pub fn path(&self) -> &Path { - self.path.as_path() + + pub fn fs_path(&self) -> &Path { + self.fs_path.as_path() } + fn is_valid(&self) -> Result<()> { - let path = self.path(); + let path = self.fs_path(); let mut p = PathBuf::from(path); for d in &["cur", "new", "tmp"] { p.push(d); @@ -231,6 +268,10 @@ impl BackendFolder for MaildirFolder { &self.name } + fn path(&self) -> &str { + self.path.to_str().unwrap_or(self.name()) + } + fn change_name(&mut self, s: &str) { self.name = s.to_string(); } @@ -243,6 +284,7 @@ impl BackendFolder for MaildirFolder { Box::new(MaildirFolder { hash: self.hash, name: self.name.clone(), + fs_path: self.fs_path.clone(), path: self.path.clone(), children: self.children.clone(), parent: self.parent, diff --git a/melib/src/backends/maildir/backend.rs b/melib/src/backends/maildir/backend.rs index db027109..1b7c47f8 100644 --- a/melib/src/backends/maildir/backend.rs +++ b/melib/src/backends/maildir/backend.rs @@ -467,7 +467,7 @@ impl MailBackend for MaildirType { fn save(&self, bytes: &[u8], folder: &str) -> Result<()> { for f in self.folders.values() { if f.name == folder { - let mut path = f.path.clone(); + let mut path = f.fs_path.clone(); path.push("cur"); { let mut rand_buf = [0u8; 16]; @@ -508,10 +508,11 @@ impl MailBackend for MaildirType { } impl MaildirType { - pub fn new(f: &AccountSettings) -> Self { + pub fn new(settings: &AccountSettings) -> Self { let mut folders: FnvHashMap<FolderHash, MaildirFolder> = Default::default(); fn recurse_folders<P: AsRef<Path>>( folders: &mut FnvHashMap<FolderHash, MaildirFolder>, + settings: &AccountSettings, p: P, ) -> Vec<FolderHash> { if !p.as_ref().exists() || !p.as_ref().is_dir() { @@ -535,13 +536,14 @@ impl MaildirType { continue 'entries; } if path.is_dir() { - let path_children = recurse_folders(folders, &path); - if let Ok(f) = MaildirFolder::new( + if let Ok(mut f) = MaildirFolder::new( path.to_str().unwrap().to_string(), path.file_name().unwrap().to_str().unwrap().to_string(), None, - path_children, + Vec::new(), + &settings, ) { + f.children = recurse_folders(folders, settings, &path); f.children .iter() .map(|c| folders.get_mut(c).map(|f| f.parent = Some(f.hash))) @@ -555,28 +557,49 @@ impl MaildirType { } children }; - let path = PathBuf::from(f.root_folder()); - if path.is_dir() { - if let Ok(f) = MaildirFolder::new( - path.to_str().unwrap().to_string(), - path.file_name().unwrap().to_str().unwrap().to_string(), - None, - Vec::with_capacity(0), - ) { - let l: MaildirFolder = f; - folders.insert(l.hash, l); + let root_path = PathBuf::from(settings.root_folder()); + if !root_path.exists() { + eprintln!( + "Configuration error ({}): root_path `{}` is not a valid directory.", + settings.name(), + settings.root_folder.as_str() + ); + std::process::exit(1); + } else if !root_path.is_dir() { + eprintln!( + "Configuration error ({}): root_path `{}` is not a directory.", + settings.name(), + settings.root_folder.as_str() + ); + std::process::exit(1); + } + + match MaildirFolder::new( + root_path.to_str().unwrap().to_string(), + root_path.file_name().unwrap().to_str().unwrap().to_string(), + None, + Vec::with_capacity(0), + settings, + ) { + Ok(f) => { + folders.insert(f.hash, f); + } + Err(e) => { + eprint!("{}: ", settings.name()); + eprintln!("{}", e.to_string()); + std::process::exit(1); } } if folders.is_empty() { - let children = recurse_folders(&mut folders, &path); + let children = recurse_folders(&mut folders, settings, &root_path); children .iter() .map(|c| folders.get_mut(c).map(|f| f.parent = None)) .count(); } else { let root_hash = *folders.keys().nth(0).unwrap(); - let children = recurse_folders(&mut folders, &path); + let children = recurse_folders(&mut folders, settings, &root_path); children .iter() .map(|c| folders.get_mut(c).map(|f| f.parent = Some(root_hash))) @@ -601,10 +624,10 @@ impl MaildirType { } } MaildirType { - name: f.name().to_string(), + name: settings.name().to_string(), folders, hash_indexes, - path: PathBuf::from(f.root_folder()), + path: PathBuf::from(settings.root_folder()), } } fn owned_folder_idx(&self, folder: &Folder) -> FolderHash { @@ -626,7 +649,7 @@ impl MaildirType { let folder: &MaildirFolder = &self.folders[&self.owned_folder_idx(folder)]; let folder_hash = folder.hash(); let tx_final = w.tx(); - let path: PathBuf = folder.path().into(); + let path: PathBuf = folder.fs_path().into(); let name = format!("parsing {:?}", folder.name()); let root_path = self.path.to_path_buf(); let map = self.hash_indexes.clone(); diff --git a/melib/src/conf.rs b/melib/src/conf.rs index 40ed6771..5614bf92 100644 --- a/melib/src/conf.rs +++ b/melib/src/conf.rs @@ -28,6 +28,7 @@ pub struct AccountSettings { pub identity: String, pub read_only: bool, pub display_name: Option<String>, + pub subscribed_folders: Vec<String>, } impl AccountSettings { @@ -52,4 +53,8 @@ impl AccountSettings { pub fn display_name(&self) -> Option<&String> { self.display_name.as_ref() } + + pub fn subscribed_folders(&self) -> &Vec<String> { + &self.subscribed_folders + } } |