summaryrefslogtreecommitdiffstats
path: root/melib
diff options
context:
space:
mode:
authorManos Pitsidianakis <el13635@mail.ntua.gr>2019-08-23 21:32:32 +0300
committerManos Pitsidianakis <el13635@mail.ntua.gr>2019-08-25 10:48:01 +0300
commit76909a1959ca2a0bc39e91ae22f401d6e756e975 (patch)
treed3c68216a78ef8f5074ca46354476792cddf8fd9 /melib
parentb39b2857111e3632e7f25bc1b77fd34816b6d3bd (diff)
add folder subscriptions
Diffstat (limited to 'melib')
-rw-r--r--melib/src/backends.rs9
-rw-r--r--melib/src/backends/maildir.rs52
-rw-r--r--melib/src/backends/maildir/backend.rs63
-rw-r--r--melib/src/conf.rs5
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
+ }
}