diff --git a/node/test/test.mjs b/node/test/test.mjs index a7ae73727..11e4703ad 100644 --- a/node/test/test.mjs +++ b/node/test/test.mjs @@ -8,7 +8,7 @@ import { EventId2EventName, C } from '../dist/constants.js' import { join } from 'path' import { statSync } from 'fs' import { Context } from '../dist/context.js' -import {fileURLToPath} from 'url'; +import { fileURLToPath } from 'url'; const __dirname = fileURLToPath(new URL('.', import.meta.url)); @@ -444,7 +444,7 @@ describe('Offline Tests with unconfigured account', function () { context.setChatProfileImage(chatId, imagePath) const blobPath = context.getChat(chatId).getProfileImage() expect(blobPath.startsWith(blobs)).to.be.true - expect(blobPath.includes('image')).to.be.true + expect(blobPath.includes('image')).to.be.false expect(blobPath.endsWith('.jpeg')).to.be.true context.setChatProfileImage(chatId, null) diff --git a/src/blob.rs b/src/blob.rs index ff1b13459..30e0e24dc 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -8,7 +8,7 @@ use std::iter::FusedIterator; use std::mem; use std::path::{Path, PathBuf}; -use anyhow::{format_err, Context as _, Result}; +use anyhow::{ensure, format_err, Context as _, Result}; use base64::Engine as _; use futures::StreamExt; use image::codecs::jpeg::JpegEncoder; @@ -139,7 +139,7 @@ impl<'a> BlobObject<'a> { let src_in_blobdir: &Path; let blobdir = context.get_blobdir(); - if src.starts_with(blobdir) || src.starts_with("$BLOBDIR/") { + if src.starts_with(blobdir) { src_in_blobdir = src; } else { info!( @@ -678,6 +678,10 @@ impl<'a> BlobObject<'a> { } fn file_hash(src: &Path) -> Result { + ensure!( + !src.starts_with("$BLOBDIR/"), + "Use `get_abs_path()` to get the absolute path of the blobfile" + ); let mut hasher = blake3::Hasher::new(); let mut src_file = std::fs::File::open(src) .with_context(|| format!("Failed to open file {}", src.display()))?; @@ -1221,7 +1225,7 @@ mod tests { let avatar_src = t.dir.path().join("avatar.png"); let avatar_bytes = include_bytes!("../test-data/image/avatar64x64.png"); fs::write(&avatar_src, avatar_bytes).await.unwrap(); - let avatar_blob = t.get_blobdir().join("avatar.png"); + let avatar_blob = t.get_blobdir().join("e9b6c7a78aa2e4f415644f55a553e73.png"); assert!(!avatar_blob.exists()); t.set_config(Config::Selfavatar, Some(avatar_src.to_str().unwrap())) .await diff --git a/src/chat.rs b/src/chat.rs index 5a6ca0b6f..13fcb4956 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -4170,7 +4170,11 @@ pub async fn set_chat_profile_image( msg.param.remove(Param::Arg); msg.text = stock_str::msg_grp_img_deleted(context, ContactId::SELF).await; } else { - let mut image_blob = BlobObject::new_from_path(context, Path::new(new_image)).await?; + let mut image_blob = BlobObject::create_and_deduplicate( + context, + Path::new(new_image), + Path::new(new_image), + )?; image_blob.recode_to_avatar_size(context).await?; chat.param.set(Param::ProfileImage, image_blob.as_name()); msg.param.set(Param::Arg, image_blob.as_name()); diff --git a/src/config.rs b/src/config.rs index 37c7eabbb..8ac186be7 100644 --- a/src/config.rs +++ b/src/config.rs @@ -764,7 +764,8 @@ impl Context { .await?; match value { Some(path) => { - let mut blob = BlobObject::new_from_path(self, path.as_ref()).await?; + let path = get_abs_path(self, Path::new(path)); + let mut blob = BlobObject::create_and_deduplicate(self, &path, &path)?; blob.recode_to_avatar_size(self).await?; self.sql .set_raw_config(key.as_ref(), Some(blob.as_name())) diff --git a/src/webxdc/integration.rs b/src/webxdc/integration.rs index fad7d2096..47120c5ac 100644 --- a/src/webxdc/integration.rs +++ b/src/webxdc/integration.rs @@ -1,3 +1,5 @@ +use std::path::Path; + use crate::chat::{send_msg, ChatId}; use crate::config::Config; use crate::contact::ContactId; @@ -13,7 +15,7 @@ impl Context { pub async fn set_webxdc_integration(&self, file: &str) -> Result<()> { let chat_id = ChatId::create_for_contact(self, ContactId::SELF).await?; let mut msg = Message::new(Viewtype::Webxdc); - msg.set_file(file, None); + msg.set_file_and_deduplicate(self, Path::new(&file), None, None)?; msg.hidden = true; msg.param.set_int(Param::WebxdcIntegration, 1); msg.param.set_int(Param::GuaranteeE2ee, 1); // needed to pass `internet_access` requirements