|
@@ -20,6 +20,7 @@ use reader::{EncryptedFileWriter, ProgressReporter, ProgressWriter};
|
|
use super::metadata::{
|
|
use super::metadata::{
|
|
Error as MetadataError,
|
|
Error as MetadataError,
|
|
Metadata as MetadataAction,
|
|
Metadata as MetadataAction,
|
|
|
|
+ MetadataResponse,
|
|
};
|
|
};
|
|
|
|
|
|
/// A file upload action to a Send server.
|
|
/// A file upload action to a Send server.
|
|
@@ -35,6 +36,10 @@ pub struct Download<'a> {
|
|
|
|
|
|
/// Check whether the file exists (recommended).
|
|
/// Check whether the file exists (recommended).
|
|
check_exists: bool,
|
|
check_exists: bool,
|
|
|
|
+
|
|
|
|
+ /// The metadata response to work with,
|
|
|
|
+ /// which will skip the internal metadata request.
|
|
|
|
+ metadata_response: Option<MetadataResponse>,
|
|
}
|
|
}
|
|
|
|
|
|
impl<'a> Download<'a> {
|
|
impl<'a> Download<'a> {
|
|
@@ -46,36 +51,43 @@ impl<'a> Download<'a> {
|
|
target: PathBuf,
|
|
target: PathBuf,
|
|
password: Option<String>,
|
|
password: Option<String>,
|
|
check_exists: bool,
|
|
check_exists: bool,
|
|
|
|
+ metadata_response: Option<MetadataResponse>,
|
|
) -> Self {
|
|
) -> Self {
|
|
Self {
|
|
Self {
|
|
file,
|
|
file,
|
|
target,
|
|
target,
|
|
password,
|
|
password,
|
|
check_exists,
|
|
check_exists,
|
|
|
|
+ metadata_response,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/// Invoke the download action.
|
|
/// Invoke the download action.
|
|
pub fn invoke(
|
|
pub fn invoke(
|
|
- self,
|
|
|
|
|
|
+ mut self,
|
|
client: &Client,
|
|
client: &Client,
|
|
reporter: Arc<Mutex<ProgressReporter>>,
|
|
reporter: Arc<Mutex<ProgressReporter>>,
|
|
) -> Result<(), Error> {
|
|
) -> Result<(), Error> {
|
|
// Create a key set for the file
|
|
// Create a key set for the file
|
|
let mut key = KeySet::from(self.file, self.password.as_ref());
|
|
let mut key = KeySet::from(self.file, self.password.as_ref());
|
|
|
|
|
|
- // Fetch the file metadata, update the input vector in the key set
|
|
|
|
- let metadata = MetadataAction::new(
|
|
|
|
- self.file,
|
|
|
|
- self.password.clone(),
|
|
|
|
- self.check_exists,
|
|
|
|
- )
|
|
|
|
- .invoke(&client)
|
|
|
|
- .map_err(|err| match err {
|
|
|
|
- MetadataError::PasswordRequired => Error::PasswordRequired,
|
|
|
|
- MetadataError::Expired => Error::Expired,
|
|
|
|
- _ => err.into(),
|
|
|
|
- })?;
|
|
|
|
|
|
+ // Get the metadata, or fetch the file metadata,
|
|
|
|
+ // then update the input vector in the key set
|
|
|
|
+ let metadata: MetadataResponse = if self.metadata_response.is_some() {
|
|
|
|
+ self.metadata_response.take().unwrap()
|
|
|
|
+ } else {
|
|
|
|
+ MetadataAction::new(
|
|
|
|
+ self.file,
|
|
|
|
+ self.password.clone(),
|
|
|
|
+ self.check_exists,
|
|
|
|
+ )
|
|
|
|
+ .invoke(&client)
|
|
|
|
+ .map_err(|err| match err {
|
|
|
|
+ MetadataError::PasswordRequired => Error::PasswordRequired,
|
|
|
|
+ MetadataError::Expired => Error::Expired,
|
|
|
|
+ _ => err.into(),
|
|
|
|
+ })?
|
|
|
|
+ };
|
|
key.set_iv(metadata.metadata().iv());
|
|
key.set_iv(metadata.metadata().iv());
|
|
|
|
|
|
// Decide what actual file target to use
|
|
// Decide what actual file target to use
|