Reimplement libimagmail for new libimagentryref interface
This commit is contained in:
parent
1153fb180b
commit
30ad7d89b1
4 changed files with 65 additions and 96 deletions
|
@ -26,6 +26,10 @@ error_chain! {
|
||||||
RefError(::libimagentryref::error::RefError, ::libimagentryref::error::RefErrorKind);
|
RefError(::libimagentryref::error::RefError, ::libimagentryref::error::RefErrorKind);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreign_links {
|
||||||
|
IoError(::std::io::Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
errors {
|
errors {
|
||||||
RefCreationError {
|
RefCreationError {
|
||||||
|
|
|
@ -1,81 +0,0 @@
|
||||||
//
|
|
||||||
// imag - the personal information management suite for the commandline
|
|
||||||
// Copyright (C) 2015-2018 Matthias Beyer <mail@beyermatthias.de> and contributors
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU Lesser General Public
|
|
||||||
// License as published by the Free Software Foundation; version
|
|
||||||
// 2.1 of the License.
|
|
||||||
//
|
|
||||||
// This library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
// Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public
|
|
||||||
// License along with this library; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
//
|
|
||||||
|
|
||||||
use std::io::Read;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use email::MimeMessage;
|
|
||||||
|
|
||||||
use libimagentryref::hasher::Hasher;
|
|
||||||
use libimagentryref::hasher::DefaultHasher;
|
|
||||||
use libimagentryref::error::RefErrorKind as REK;
|
|
||||||
use libimagentryref::error::ResultExt;
|
|
||||||
use libimagentryref::error::Result as RResult;
|
|
||||||
|
|
||||||
pub struct MailHasher {
|
|
||||||
defaulthasher: DefaultHasher,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MailHasher {
|
|
||||||
|
|
||||||
pub fn new() -> MailHasher {
|
|
||||||
MailHasher { defaulthasher: DefaultHasher::new() }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Hasher for MailHasher {
|
|
||||||
|
|
||||||
fn hash_name(&self) -> &'static str {
|
|
||||||
"default_mail_hasher"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_hash<R: Read>(&mut self, pb: &PathBuf, c: &mut R) -> RResult<String> {
|
|
||||||
use filters::filter::Filter;
|
|
||||||
use email::Header;
|
|
||||||
|
|
||||||
let mut s = String::new();
|
|
||||||
c.read_to_string(&mut s)?;
|
|
||||||
|
|
||||||
MimeMessage::parse(&s)
|
|
||||||
.chain_err(|| REK::RefHashingError)
|
|
||||||
.and_then(|mail| {
|
|
||||||
let has_key = |hdr: &Header, exp: &str| hdr.name == exp;
|
|
||||||
|
|
||||||
let subject_filter = |hdr: &Header| has_key(hdr, "Subject");
|
|
||||||
let from_filter = |hdr: &Header| has_key(hdr, "From");
|
|
||||||
let to_filter = |hdr: &Header| has_key(hdr, "To");
|
|
||||||
|
|
||||||
let filter = subject_filter.or(from_filter).or(to_filter);
|
|
||||||
|
|
||||||
let mut v : Vec<String> = vec![];
|
|
||||||
for hdr in mail.headers.iter().filter(|item| filter.filter(item)) {
|
|
||||||
let s = hdr
|
|
||||||
.get_value()
|
|
||||||
.chain_err(|| REK::RefHashingError)?;
|
|
||||||
|
|
||||||
v.push(s);
|
|
||||||
}
|
|
||||||
let s : String = v.join("");
|
|
||||||
|
|
||||||
self.defaulthasher.create_hash(pb, &mut s.as_bytes())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -45,7 +45,6 @@ extern crate libimagstore;
|
||||||
extern crate libimagentryref;
|
extern crate libimagentryref;
|
||||||
|
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod hasher;
|
|
||||||
pub mod iter;
|
pub mod iter;
|
||||||
pub mod mail;
|
pub mod mail;
|
||||||
|
|
||||||
|
|
|
@ -18,22 +18,75 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
use std::fs::OpenOptions;
|
||||||
|
use std::result::Result as RResult;
|
||||||
|
|
||||||
use libimagstore::store::Store;
|
use libimagstore::store::Store;
|
||||||
|
use libimagstore::storeid::StoreId;
|
||||||
use libimagstore::store::FileLockEntry;
|
use libimagstore::store::FileLockEntry;
|
||||||
use libimagentryref::reference::Ref;
|
use libimagentryref::reference::Ref;
|
||||||
use libimagentryref::flags::RefFlags;
|
|
||||||
use libimagentryref::refstore::RefStore;
|
use libimagentryref::refstore::RefStore;
|
||||||
|
use libimagentryref::refstore::UniqueRefPathGenerator;
|
||||||
|
|
||||||
use email::MimeMessage;
|
use email::MimeMessage;
|
||||||
use email::results::ParsingResult as EmailParsingResult;
|
use email::results::ParsingResult as EmailParsingResult;
|
||||||
|
|
||||||
use hasher::MailHasher;
|
|
||||||
use error::Result;
|
use error::Result;
|
||||||
use error::{ResultExt, MailErrorKind as MEK};
|
use error::{ResultExt, MailError as ME, MailErrorKind as MEK};
|
||||||
|
|
||||||
|
struct UniqueMailRefGenerator;
|
||||||
|
impl UniqueRefPathGenerator for UniqueMailRefGenerator {
|
||||||
|
type Error = ME;
|
||||||
|
|
||||||
|
/// The collection the `StoreId` should be created for
|
||||||
|
fn collection() -> &'static str {
|
||||||
|
"mail"
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A function which should generate a unique string for a Path
|
||||||
|
fn unique_hash<A: AsRef<Path>>(path: A) -> RResult<String, Self::Error> {
|
||||||
|
use filters::filter::Filter;
|
||||||
|
use email::Header;
|
||||||
|
|
||||||
|
let mut s = String::new();
|
||||||
|
let _ = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.write(false)
|
||||||
|
.create(false)
|
||||||
|
.open(path)?
|
||||||
|
.read_to_string(&mut s)?;
|
||||||
|
|
||||||
|
MimeMessage::parse(&s)
|
||||||
|
.chain_err(|| MEK::RefCreationError)
|
||||||
|
.and_then(|mail| {
|
||||||
|
let has_key = |hdr: &Header, exp: &str| hdr.name == exp;
|
||||||
|
|
||||||
|
let subject_filter = |hdr: &Header| has_key(hdr, "Subject");
|
||||||
|
let from_filter = |hdr: &Header| has_key(hdr, "From");
|
||||||
|
let to_filter = |hdr: &Header| has_key(hdr, "To");
|
||||||
|
|
||||||
|
let filter = subject_filter.or(from_filter).or(to_filter);
|
||||||
|
|
||||||
|
let mut v : Vec<String> = vec![];
|
||||||
|
for hdr in mail.headers.iter().filter(|item| filter.filter(item)) {
|
||||||
|
let s = hdr
|
||||||
|
.get_value()
|
||||||
|
.chain_err(|| MEK::RefCreationError)?;
|
||||||
|
|
||||||
|
v.push(s);
|
||||||
|
}
|
||||||
|
let s : String = v.join("");
|
||||||
|
Ok(s)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Postprocess the generated `StoreId` object
|
||||||
|
fn postprocess_storeid(sid: StoreId) -> RResult<StoreId, Self::Error> {
|
||||||
|
Ok(sid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct Buffer(String);
|
struct Buffer(String);
|
||||||
|
|
||||||
|
@ -56,15 +109,10 @@ impl<'a> Mail<'a> {
|
||||||
/// Imports a mail from the Path passed
|
/// Imports a mail from the Path passed
|
||||||
pub fn import_from_path<P: AsRef<Path>>(store: &Store, p: P) -> Result<Mail> {
|
pub fn import_from_path<P: AsRef<Path>>(store: &Store, p: P) -> Result<Mail> {
|
||||||
debug!("Importing Mail from path");
|
debug!("Importing Mail from path");
|
||||||
let h = MailHasher::new();
|
store.retrieve_ref::<UniqueMailRefGenerator, P>(p)
|
||||||
let f = RefFlags::default().with_content_hashing(true).with_permission_tracking(false);
|
|
||||||
let p = PathBuf::from(p.as_ref());
|
|
||||||
|
|
||||||
store.create_with_hasher(p, f, h)
|
|
||||||
.chain_err(|| MEK::RefCreationError)
|
|
||||||
.and_then(|reference| {
|
.and_then(|reference| {
|
||||||
debug!("Build reference file: {:?}", reference);
|
debug!("Build reference file: {:?}", reference);
|
||||||
reference.fs_file()
|
reference.get_path()
|
||||||
.chain_err(|| MEK::RefHandlingError)
|
.chain_err(|| MEK::RefHandlingError)
|
||||||
.and_then(|path| File::open(path).chain_err(|| MEK::IOError))
|
.and_then(|path| File::open(path).chain_err(|| MEK::IOError))
|
||||||
.and_then(|mut file| {
|
.and_then(|mut file| {
|
||||||
|
@ -81,19 +129,18 @@ impl<'a> Mail<'a> {
|
||||||
/// Opens a mail by the passed hash
|
/// Opens a mail by the passed hash
|
||||||
pub fn open<S: AsRef<str>>(store: &Store, hash: S) -> Result<Option<Mail>> {
|
pub fn open<S: AsRef<str>>(store: &Store, hash: S) -> Result<Option<Mail>> {
|
||||||
debug!("Opening Mail by Hash");
|
debug!("Opening Mail by Hash");
|
||||||
store.get_by_hash(String::from(hash.as_ref()))
|
store.get_ref::<UniqueMailRefGenerator, S>(hash)
|
||||||
.chain_err(|| MEK::FetchByHashError)
|
.chain_err(|| MEK::FetchByHashError)
|
||||||
.chain_err(|| MEK::FetchError)
|
.chain_err(|| MEK::FetchError)
|
||||||
.and_then(|o| match o {
|
.and_then(|o| match o {
|
||||||
Some(r) => Mail::from_fle(r).map(Some),
|
Some(r) => Mail::from_fle(r).map(Some),
|
||||||
None => Ok(None),
|
None => Ok(None),
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implement me as TryFrom as soon as it is stable
|
/// Implement me as TryFrom as soon as it is stable
|
||||||
pub fn from_fle(fle: FileLockEntry<'a>) -> Result<Mail<'a>> {
|
pub fn from_fle(fle: FileLockEntry<'a>) -> Result<Mail<'a>> {
|
||||||
fle.fs_file()
|
fle.get_path()
|
||||||
.chain_err(|| MEK::RefHandlingError)
|
.chain_err(|| MEK::RefHandlingError)
|
||||||
.and_then(|path| File::open(path).chain_err(|| MEK::IOError))
|
.and_then(|path| File::open(path).chain_err(|| MEK::IOError))
|
||||||
.and_then(|mut file| {
|
.and_then(|mut file| {
|
||||||
|
|
Loading…
Reference in a new issue