mirror of
https://github.com/chatmail/core.git
synced 2026-05-08 09:26:29 +03:00
avoid double ZIP-parsing in get_webxdc_info() and do not read blob for just checking existance of a file
This commit is contained in:
@@ -13,7 +13,9 @@ use lettre_email::PartBuilder;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
use zip::ZipArchive;
|
||||||
|
|
||||||
pub const WEBXDC_SUFFIX: &str = "xdc";
|
pub const WEBXDC_SUFFIX: &str = "xdc";
|
||||||
const WEBXDC_DEFAULT_ICON: &str = "__webxdc__/default-icon.png";
|
const WEBXDC_DEFAULT_ICON: &str = "__webxdc__/default-icon.png";
|
||||||
@@ -248,7 +250,25 @@ async fn parse_webxdc_manifest(bytes: &[u8]) -> Result<WebxdcManifest> {
|
|||||||
Ok(manifest)
|
Ok(manifest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_blob(archive: &mut ZipArchive<File>, name: &str) -> Result<Vec<u8>> {
|
||||||
|
let mut file = archive.by_name(name)?;
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
file.read_to_end(&mut buf)?;
|
||||||
|
Ok(buf)
|
||||||
|
}
|
||||||
|
|
||||||
impl Message {
|
impl Message {
|
||||||
|
/// Get handle to a webxdc ZIP-archive.
|
||||||
|
/// To check for file existance use archive.by_name(), to read a file, use get_blob(archive).
|
||||||
|
async fn get_webxdc_archive(&self, context: &Context) -> Result<ZipArchive<File>> {
|
||||||
|
let path = self
|
||||||
|
.get_file(context)
|
||||||
|
.ok_or_else(|| format_err!("No webxdc instance file."))?;
|
||||||
|
let file = dc_open_file_std(context, path)?;
|
||||||
|
let archive = zip::ZipArchive::new(file)?;
|
||||||
|
Ok(archive)
|
||||||
|
}
|
||||||
|
|
||||||
/// Return file form inside an archive.
|
/// Return file form inside an archive.
|
||||||
/// Currently, this works only if the message is an webxdc instance.
|
/// Currently, this works only if the message is an webxdc instance.
|
||||||
pub async fn get_webxdc_blob(&self, context: &Context, name: &str) -> Result<Vec<u8>> {
|
pub async fn get_webxdc_blob(&self, context: &Context, name: &str) -> Result<Vec<u8>> {
|
||||||
@@ -258,12 +278,6 @@ impl Message {
|
|||||||
return Ok(include_bytes!("../assets/icon-webxdc.png").to_vec());
|
return Ok(include_bytes!("../assets/icon-webxdc.png").to_vec());
|
||||||
}
|
}
|
||||||
|
|
||||||
let archive = self
|
|
||||||
.get_file(context)
|
|
||||||
.ok_or_else(|| format_err!("No webxdc instance file."))?;
|
|
||||||
let archive = dc_open_file_std(context, archive)?;
|
|
||||||
let mut archive = zip::ZipArchive::new(archive)?;
|
|
||||||
|
|
||||||
// ignore first slash.
|
// ignore first slash.
|
||||||
// this way, files can be accessed absolutely (`/index.html`) as well as relatively (`index.html`)
|
// this way, files can be accessed absolutely (`/index.html`) as well as relatively (`index.html`)
|
||||||
let name = if name.starts_with('/') {
|
let name = if name.starts_with('/') {
|
||||||
@@ -272,18 +286,16 @@ impl Message {
|
|||||||
name
|
name
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut file = archive.by_name(name)?;
|
let mut archive = self.get_webxdc_archive(context).await?;
|
||||||
|
get_blob(&mut archive, name).await
|
||||||
let mut buf = Vec::new();
|
|
||||||
file.read_to_end(&mut buf)?;
|
|
||||||
Ok(buf)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return info from manifest.toml or from fallbacks.
|
/// Return info from manifest.toml or from fallbacks.
|
||||||
pub async fn get_webxdc_info(&self, context: &Context) -> Result<WebxdcInfo> {
|
pub async fn get_webxdc_info(&self, context: &Context) -> Result<WebxdcInfo> {
|
||||||
ensure!(self.viewtype == Viewtype::Webxdc, "No webxdc instance.");
|
ensure!(self.viewtype == Viewtype::Webxdc, "No webxdc instance.");
|
||||||
|
let mut archive = self.get_webxdc_archive(context).await?;
|
||||||
|
|
||||||
let mut manifest = if let Ok(bytes) = self.get_webxdc_blob(context, "manifest.toml").await {
|
let mut manifest = if let Ok(bytes) = get_blob(&mut archive, "manifest.toml").await {
|
||||||
if let Ok(manifest) = parse_webxdc_manifest(&bytes).await {
|
if let Ok(manifest) = parse_webxdc_manifest(&bytes).await {
|
||||||
manifest
|
manifest
|
||||||
} else {
|
} else {
|
||||||
@@ -311,7 +323,7 @@ impl Message {
|
|||||||
if !icon.ends_with(".png") && !icon.ends_with(".jpg") {
|
if !icon.ends_with(".png") && !icon.ends_with(".jpg") {
|
||||||
warn!(context, "bad icon format \"{}\"; use .png or .jpg", icon);
|
warn!(context, "bad icon format \"{}\"; use .png or .jpg", icon);
|
||||||
manifest.icon = None;
|
manifest.icon = None;
|
||||||
} else if self.get_webxdc_blob(context, icon).await.is_err() {
|
} else if archive.by_name(icon).is_err() {
|
||||||
warn!(context, "cannot find icon \"{}\"", icon);
|
warn!(context, "cannot find icon \"{}\"", icon);
|
||||||
manifest.icon = None;
|
manifest.icon = None;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user