fix: use BufReader when reading .xdc files

This commit is contained in:
link2xt
2025-01-27 18:03:52 +00:00
committed by l
parent 28e3fbfebb
commit a563c4851c

View File

@@ -24,7 +24,7 @@ use std::path::Path;
use anyhow::{anyhow, bail, ensure, format_err, Context as _, Result}; use anyhow::{anyhow, bail, ensure, format_err, Context as _, Result};
use async_zip::tokio::read::fs::ZipFileReader as FsZipFileReader; use async_zip::tokio::read::seek::ZipFileReader as SeekZipFileReader;
use deltachat_contact_tools::sanitize_bidi_characters; use deltachat_contact_tools::sanitize_bidi_characters;
use deltachat_derive::FromSql; use deltachat_derive::FromSql;
use lettre_email::PartBuilder; use lettre_email::PartBuilder;
@@ -32,6 +32,7 @@ use rusqlite::OptionalExtension;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::Value; use serde_json::Value;
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
use tokio::{fs::File, io::BufReader};
use crate::chat::{self, Chat}; use crate::chat::{self, Chat};
use crate::constants::Chattype; use crate::constants::Chattype;
@@ -262,7 +263,8 @@ impl Context {
pub(crate) async fn ensure_sendable_webxdc_file(&self, path: &Path) -> Result<()> { pub(crate) async fn ensure_sendable_webxdc_file(&self, path: &Path) -> Result<()> {
let filename = path.to_str().unwrap_or_default(); let filename = path.to_str().unwrap_or_default();
let valid = match FsZipFileReader::new(path).await { let file = BufReader::new(File::open(path).await?);
let valid = match SeekZipFileReader::with_tokio(file).await {
Ok(archive) => { Ok(archive) => {
if find_zip_entry(archive.file(), "index.html").is_none() { if find_zip_entry(archive.file(), "index.html").is_none() {
warn!(self, "{} misses index.html", filename); warn!(self, "{} misses index.html", filename);
@@ -839,7 +841,7 @@ fn parse_webxdc_manifest(bytes: &[u8]) -> Result<WebxdcManifest> {
Ok(manifest) Ok(manifest)
} }
async fn get_blob(archive: &FsZipFileReader, name: &str) -> Result<Vec<u8>> { async fn get_blob(archive: &mut SeekZipFileReader<BufReader<File>>, name: &str) -> Result<Vec<u8>> {
let (i, _) = find_zip_entry(archive.file(), name) let (i, _) = find_zip_entry(archive.file(), name)
.ok_or_else(|| anyhow!("no entry found for {}", name))?; .ok_or_else(|| anyhow!("no entry found for {}", name))?;
let mut reader = archive.reader_with_entry(i).await?; let mut reader = archive.reader_with_entry(i).await?;
@@ -851,12 +853,16 @@ async fn get_blob(archive: &FsZipFileReader, name: &str) -> Result<Vec<u8>> {
impl Message { impl Message {
/// Get handle to a webxdc ZIP-archive. /// Get handle to a webxdc ZIP-archive.
/// To check for file existence use archive.by_name(), to read a file, use get_blob(archive). /// To check for file existence use archive.by_name(), to read a file, use get_blob(archive).
async fn get_webxdc_archive(&self, context: &Context) -> Result<FsZipFileReader> { async fn get_webxdc_archive(
&self,
context: &Context,
) -> Result<SeekZipFileReader<BufReader<File>>> {
let path = self let path = self
.get_file(context) .get_file(context)
.ok_or_else(|| format_err!("No webxdc instance file."))?; .ok_or_else(|| format_err!("No webxdc instance file."))?;
let path_abs = get_abs_path(context, &path); let path_abs = get_abs_path(context, &path);
let archive = FsZipFileReader::new(path_abs).await?; let file = BufReader::new(File::open(path_abs).await?);
let archive = SeekZipFileReader::with_tokio(file).await?;
Ok(archive) Ok(archive)
} }
@@ -879,10 +885,10 @@ impl Message {
name name
}; };
let archive = self.get_webxdc_archive(context).await?; let mut archive = self.get_webxdc_archive(context).await?;
if name == "index.html" { if name == "index.html" {
if let Ok(bytes) = get_blob(&archive, "manifest.toml").await { if let Ok(bytes) = get_blob(&mut archive, "manifest.toml").await {
if let Ok(manifest) = parse_webxdc_manifest(&bytes) { if let Ok(manifest) = parse_webxdc_manifest(&bytes) {
if let Some(min_api) = manifest.min_api { if let Some(min_api) = manifest.min_api {
if min_api > WEBXDC_API_VERSION { if min_api > WEBXDC_API_VERSION {
@@ -895,15 +901,15 @@ impl Message {
} }
} }
get_blob(&archive, name).await get_blob(&mut archive, name).await
} }
/// 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 archive = self.get_webxdc_archive(context).await?; let mut archive = self.get_webxdc_archive(context).await?;
let mut manifest = get_blob(&archive, "manifest.toml") let mut manifest = get_blob(&mut archive, "manifest.toml")
.await .await
.map(|bytes| parse_webxdc_manifest(&bytes).unwrap_or_default()) .map(|bytes| parse_webxdc_manifest(&bytes).unwrap_or_default())
.unwrap_or_default(); .unwrap_or_default();