From 6e3ec71c10ff77f65a8dbfa0f8fac1fefaa6afec Mon Sep 17 00:00:00 2001 From: bjoern Date: Sun, 10 Apr 2022 12:16:28 +0200 Subject: [PATCH] show an error when a webxdc is written for a newer (future) api (#3206) * add min_api to manifest.toml, define WEBXDC_API_VERSION * return an error instead of index.html if the webxdc requires a newer api * add a test with an webxdc requiring a newer api * update CHANGELOG --- CHANGELOG.md | 1 + src/webxdc.rs | 64 ++++++++++++++++++++++++- test-data/webxdc/with-min-api-1001.xdc | Bin 0 -> 513 bytes 3 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 test-data/webxdc/with-min-api-1001.xdc diff --git a/CHANGELOG.md b/CHANGELOG.md index 76265b970..daf185250 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ - `dc_receive_imf` refactorings #3154 #3156 - add index to speedup deletion of expired ephemeral messages #3155 - muted chats stay archived on new messages #3184 +- support `min_api` from Webxdc manifests #3206 ### Fixes diff --git a/src/webxdc.rs b/src/webxdc.rs index 05dca9f28..82e84a255 100644 --- a/src/webxdc.rs +++ b/src/webxdc.rs @@ -19,6 +19,12 @@ use std::fs::File; use std::io::{Read, Seek, SeekFrom}; use zip::ZipArchive; +/// The current API version. +/// If `min_api` in manifest.toml is set to a larger value, +/// the Webxdc's index.html is replaced by an error message. +/// In the future, that may be useful to avoid new Webxdc being loaded on old Delta Chats. +const WEBXDC_API_VERSION: u32 = 1; + pub const WEBXDC_SUFFIX: &str = "xdc"; const WEBXDC_DEFAULT_ICON: &str = "__webxdc__/default-icon.png"; @@ -44,6 +50,7 @@ const WEBXDC_RECEIVING_LIMIT: u64 = 4194304; #[non_exhaustive] struct WebxdcManifest { name: Option, + min_api: Option, } /// Parsed information from WebxdcManifest and fallbacks. @@ -499,6 +506,21 @@ impl Message { }; let mut archive = self.get_webxdc_archive(context).await?; + + if name == "index.html" { + if let Ok(bytes) = get_blob(&mut archive, "manifest.toml").await { + if let Ok(manifest) = parse_webxdc_manifest(&bytes).await { + if let Some(min_api) = manifest.min_api { + if min_api > WEBXDC_API_VERSION { + return Ok(Vec::from( + "This Webxdc requires a newer Delta Chat version.", + )); + } + } + } + } + } + get_blob(&mut archive, name).await } @@ -511,10 +533,16 @@ impl Message { if let Ok(manifest) = parse_webxdc_manifest(&bytes).await { manifest } else { - WebxdcManifest { name: None } + WebxdcManifest { + name: None, + min_api: None, + } } } else { - WebxdcManifest { name: None } + WebxdcManifest { + name: None, + min_api: None, + } }; if let Some(ref name) = manifest.name { @@ -1295,6 +1323,38 @@ sth_for_the = "future""# ) .await?; assert_eq!(manifest.name, Some("foz".to_string())); + Ok(()) + } + + #[async_std::test] + async fn test_parse_webxdc_manifest_min_api() -> Result<()> { + let manifest = parse_webxdc_manifest(r#"min_api = 3"#.as_bytes()).await?; + assert_eq!(manifest.min_api, Some(3)); + + let result = parse_webxdc_manifest(r#"min_api = "1""#.as_bytes()).await; + assert!(result.is_err()); + + let result = parse_webxdc_manifest(r#"min_api = 1.2"#.as_bytes()).await; + assert!(result.is_err()); + + Ok(()) + } + + #[async_std::test] + async fn test_webxdc_min_api_too_large() -> Result<()> { + let t = TestContext::new_alice().await; + let chat_id = create_group_chat(&t, ProtectionStatus::Unprotected, "chat").await?; + let mut instance = create_webxdc_instance( + &t, + "with-min-api-1001.xdc", + include_bytes!("../test-data/webxdc/with-min-api-1001.xdc"), + ) + .await?; + send_msg(&t, chat_id, &mut instance).await?; + + let instance = t.get_last_msg().await; + let html = instance.get_webxdc_blob(&t, "index.html").await?; + assert!(String::from_utf8_lossy(&*html).contains("requires a newer Delta Chat version")); Ok(()) } diff --git a/test-data/webxdc/with-min-api-1001.xdc b/test-data/webxdc/with-min-api-1001.xdc new file mode 100644 index 0000000000000000000000000000000000000000..2e12e5c373e091ec341af03ecab8a99373e68e48 GIT binary patch literal 513 zcmWIWW@Zs#U}E54&}!)nk(E6*xrKp&VKoqQF~~4v=B1=o=w+1T=7ffDGB6v=3{3I> z;?fFk21b^zj0_Awy$lSdeH(=iDG0b!?|ZZ)Jc`?C@wKQM5kf_h1uZJaUBA3fb=iJ1 zsr>$$dot(SU%xG4I{z`T<)8GegB&X^3Eph_Jk6*`JzQ>k^~$=)GLf`4pLLU2e_wx4 z_FbnpOm~ICRgYcs+qMgCWl-JFo)IizXe^+Yt%C367K zA6!6xFfbSb{ZVEf_{S2+24P;HKXMcEGSgCvOY}