diff --git a/Cargo.lock b/Cargo.lock index 669e23cdb..33b7c4b79 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1372,6 +1372,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "sha-1", + "sha2", "shadowsocks", "smallvec", "strum", diff --git a/Cargo.toml b/Cargo.toml index 03cac0c81..abfd53801 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -92,6 +92,7 @@ serde_json = { workspace = true } serde_urlencoded = "0.7.1" serde = { workspace = true, features = ["derive"] } sha-1 = "0.10" +sha2 = "0.10" shadowsocks = { version = "1.21.0", default-features = false, features = ["aead-cipher-2022"] } smallvec = "1.13.2" strum = "0.26" diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index 36bf24607..55235216b 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -4197,6 +4197,7 @@ char* dc_msg_get_webxdc_blob (const dc_msg_t* msg, const char* * true if the Webxdc should get full internet access, including Webrtc. * currently, this is only true for encrypted Webxdc's in the self chat * that have requested internet access in the manifest. + * - self_addr: address to be used for `window.webxdc.selfAddr` in JS land. * * @memberof dc_msg_t * @param msg The webxdc instance. diff --git a/deltachat-jsonrpc/src/api/types/webxdc.rs b/deltachat-jsonrpc/src/api/types/webxdc.rs index 71db9ed93..28f0f384b 100644 --- a/deltachat-jsonrpc/src/api/types/webxdc.rs +++ b/deltachat-jsonrpc/src/api/types/webxdc.rs @@ -35,6 +35,8 @@ pub struct WebxdcMessageInfo { source_code_url: Option, /// True if full internet access should be granted to the app. internet_access: bool, + /// Address to be used for `window.webxdc.selfAddr` in JS land. + self_addr: String, } impl WebxdcMessageInfo { @@ -50,6 +52,7 @@ impl WebxdcMessageInfo { summary, source_code_url, internet_access, + self_addr, } = message.get_webxdc_info(context).await?; Ok(Self { @@ -59,6 +62,7 @@ impl WebxdcMessageInfo { summary: maybe_empty_string_to_option(summary), source_code_url: maybe_empty_string_to_option(source_code_url), internet_access, + self_addr, }) } } diff --git a/deltachat-rpc-client/tests/test_webxdc.py b/deltachat-rpc-client/tests/test_webxdc.py index 3c5715731..e189251df 100644 --- a/deltachat-rpc-client/tests/test_webxdc.py +++ b/deltachat-rpc-client/tests/test_webxdc.py @@ -24,6 +24,7 @@ def test_webxdc(acfactory) -> None: "name": "Chess Board", "sourceCodeUrl": None, "summary": None, + "selfAddr": webxdc_info["selfAddr"], } status_updates = message.get_webxdc_status_updates() diff --git a/src/summary.rs b/src/summary.rs index 4881b0a67..72bf3395d 100644 --- a/src/summary.rs +++ b/src/summary.rs @@ -289,7 +289,7 @@ mod tests { use super::*; use crate::chat::ChatId; use crate::param::Param; - use crate::test_utils as test; + use crate::test_utils::TestContext; async fn assert_summary_texts(msg: &Message, ctx: &Context, expected: &str) { assert_eq!(msg.get_summary_text(ctx).await, expected); @@ -298,7 +298,7 @@ mod tests { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_get_summary_text() { - let d = test::TestContext::new().await; + let d = TestContext::new_alice().await; let ctx = &d.ctx; let chat_id = ChatId::create_for_contact(ctx, ContactId::SELF) .await diff --git a/src/webxdc.rs b/src/webxdc.rs index 8dacd778c..c19bbebd3 100644 --- a/src/webxdc.rs +++ b/src/webxdc.rs @@ -30,12 +30,14 @@ use lettre_email::PartBuilder; use rusqlite::OptionalExtension; use serde::{Deserialize, Serialize}; use serde_json::Value; +use sha2::{Digest, Sha256}; use crate::chat::{self, Chat}; use crate::constants::Chattype; use crate::contact::ContactId; use crate::context::Context; use crate::events::EventType; +use crate::key::{load_self_public_key, DcKey}; use crate::message::{Message, MessageState, MsgId, Viewtype}; use crate::mimefactory::wrapped_base64_encode; use crate::mimeparser::SystemMessage; @@ -97,6 +99,9 @@ pub struct WebxdcInfo { /// It should request access, be encrypted /// and sent to self for this. pub internet_access: bool, + + /// Address to be used for `window.webxdc.selfAddr` in JS land. + pub self_addr: String, } /// Status Update ID. @@ -872,6 +877,8 @@ impl Message { && self.chat_id.is_self_talk(context).await.unwrap_or_default() && self.get_showpadlock(); + let self_addr = self.get_webxdc_self_addr(context).await?; + Ok(WebxdcInfo { name: if let Some(name) = manifest.name { name @@ -904,8 +911,16 @@ impl Message { "".to_string() }, internet_access, + self_addr, }) } + + async fn get_webxdc_self_addr(&self, context: &Context) -> Result { + let fingerprint = load_self_public_key(context).await?.dc_fingerprint().hex(); + let data = format!("{}-{}", fingerprint, self.rfc724_mid); + let hash = Sha256::digest(data.as_bytes()); + Ok(format!("{:x}", hash)) + } } #[cfg(test)] @@ -2288,6 +2303,23 @@ sth_for_the = "future""# Ok(()) } + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] + async fn test_get_webxdc_self_addr() -> Result<()> { + let t = TestContext::new_alice().await; + let chat_id = create_group_chat(&t, ProtectionStatus::Unprotected, "foo").await?; + + let instance = send_webxdc_instance(&t, chat_id).await?; + let info1 = instance.get_webxdc_info(&t).await?; + let instance = send_webxdc_instance(&t, chat_id).await?; + let info2 = instance.get_webxdc_info(&t).await?; + + let real_addr = t.get_primary_self_addr().await?; + assert!(!info1.self_addr.contains(&real_addr)); + assert_ne!(info1.self_addr, info2.self_addr); + + Ok(()) + } + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_webxdc_info_summary() -> Result<()> { let alice = TestContext::new_alice().await;