Record download checksums
This commit is contained in:
@@ -31,6 +31,17 @@ pub enum DownloadSecurity {
|
||||
DangerousExtension,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum DownloadChecksumAlgorithm {
|
||||
Sha256,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct DownloadChecksum {
|
||||
algorithm: DownloadChecksumAlgorithm,
|
||||
value: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct DownloadEntry {
|
||||
id: DownloadId,
|
||||
@@ -43,6 +54,7 @@ pub struct DownloadEntry {
|
||||
state: DownloadState,
|
||||
received_bytes: u64,
|
||||
total_bytes: Option<u64>,
|
||||
checksum: Option<DownloadChecksum>,
|
||||
started_at: SystemTime,
|
||||
}
|
||||
|
||||
@@ -137,6 +149,40 @@ impl DownloadSecurity {
|
||||
}
|
||||
}
|
||||
|
||||
impl DownloadChecksumAlgorithm {
|
||||
#[must_use]
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Sha256 => "sha256",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DownloadChecksum {
|
||||
pub fn sha256_hex(value: impl Into<String>) -> Result<Self, DomainError> {
|
||||
let value = value.into();
|
||||
let value = value.trim();
|
||||
if !is_sha256_hex(value) {
|
||||
return Err(DomainError::InvalidDownloadChecksum {
|
||||
algorithm: DownloadChecksumAlgorithm::Sha256.as_str(),
|
||||
value: value.to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
Ok(Self { algorithm: DownloadChecksumAlgorithm::Sha256, value: value.to_ascii_lowercase() })
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn algorithm(&self) -> &DownloadChecksumAlgorithm {
|
||||
&self.algorithm
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn value(&self) -> &str {
|
||||
&self.value
|
||||
}
|
||||
}
|
||||
|
||||
impl DownloadEntry {
|
||||
pub fn started(
|
||||
profile_id: ProfileId,
|
||||
@@ -165,6 +211,7 @@ impl DownloadEntry {
|
||||
state: DownloadState::InProgress,
|
||||
received_bytes: 0,
|
||||
total_bytes,
|
||||
checksum: None,
|
||||
started_at,
|
||||
})
|
||||
}
|
||||
@@ -215,6 +262,12 @@ impl DownloadEntry {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn record_checksum(&mut self, checksum: DownloadChecksum) -> Result<(), DomainError> {
|
||||
self.require_state("record checksum", &[DownloadState::Completed])?;
|
||||
self.checksum = Some(checksum);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn id(&self) -> &DownloadId {
|
||||
&self.id
|
||||
@@ -265,6 +318,11 @@ impl DownloadEntry {
|
||||
self.total_bytes
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn checksum(&self) -> Option<&DownloadChecksum> {
|
||||
self.checksum.as_ref()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn started_at(&self) -> SystemTime {
|
||||
self.started_at
|
||||
@@ -330,3 +388,7 @@ fn download_extension(file_name: &str) -> Option<&str> {
|
||||
fn is_dangerous_extension(extension: &str) -> bool {
|
||||
DANGEROUS_DOWNLOAD_EXTENSIONS.iter().any(|candidate| extension.eq_ignore_ascii_case(candidate))
|
||||
}
|
||||
|
||||
fn is_sha256_hex(value: &str) -> bool {
|
||||
value.len() == 64 && value.as_bytes().iter().all(u8::is_ascii_hexdigit)
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@ pub enum DomainError {
|
||||
#[error("invalid file name: {value}")]
|
||||
InvalidFileName { value: String },
|
||||
|
||||
#[error("invalid {algorithm} download checksum: {value}")]
|
||||
InvalidDownloadChecksum { algorithm: &'static str, value: String },
|
||||
|
||||
#[error("invalid download directory: {path}")]
|
||||
InvalidDownloadDirectory { path: String },
|
||||
|
||||
|
||||
@@ -13,7 +13,8 @@ mod url_text;
|
||||
pub use archive::{ArchiveSource, ArchivedTab};
|
||||
pub use command::{CommandIntent, CommandScope};
|
||||
pub use download::{
|
||||
DownloadDestination, DownloadEntry, DownloadPolicy, DownloadSecurity, DownloadState,
|
||||
DownloadChecksum, DownloadChecksumAlgorithm, DownloadDestination, DownloadEntry,
|
||||
DownloadPolicy, DownloadSecurity, DownloadState,
|
||||
};
|
||||
pub use error::DomainError;
|
||||
pub use history::HistoryEntry;
|
||||
|
||||
Reference in New Issue
Block a user