diff --git a/Cargo.lock b/Cargo.lock index e34261325..2da17b2df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3460,6 +3460,22 @@ dependencies = [ "web-sys", ] +[[package]] +name = "matrix-sdk-contentscanner" +version = "0.18.0" +dependencies = [ + "assert_matches2", + "matrix-sdk", + "matrix-sdk-crypto", + "matrix-sdk-test", + "ruma", + "serde", + "tokio", + "tracing", + "uniffi", + "wiremock", +] + [[package]] name = "matrix-sdk-crypto" version = "0.18.0" @@ -3561,6 +3577,7 @@ dependencies = [ "matrix-sdk", "matrix-sdk-base", "matrix-sdk-common", + "matrix-sdk-contentscanner", "matrix-sdk-ffi-macros", "matrix-sdk-ui", "mime", diff --git a/Cargo.toml b/Cargo.toml index 797e4f9f6..f50585761 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -129,6 +129,7 @@ zeroize = { version = "1.8.2", default-features = false } matrix-sdk = { path = "crates/matrix-sdk", version = "0.18.0", default-features = false } matrix-sdk-base = { path = "crates/matrix-sdk-base", version = "0.18.0" } matrix-sdk-common = { path = "crates/matrix-sdk-common", version = "0.18.0" } +matrix-sdk-contentscanner = { path = "crates/matrix-sdk-contentscanner", version = "0.18.0" } matrix-sdk-crypto = { path = "crates/matrix-sdk-crypto", version = "0.18.0" } matrix-sdk-ffi-macros = { path = "bindings/matrix-sdk-ffi-macros", version = "0.7.0" } matrix-sdk-indexeddb = { path = "crates/matrix-sdk-indexeddb", version = "0.18.0", default-features = false } diff --git a/crates/matrix-sdk-contentscanner/Cargo.toml b/crates/matrix-sdk-contentscanner/Cargo.toml new file mode 100644 index 000000000..3edfbbc1b --- /dev/null +++ b/crates/matrix-sdk-contentscanner/Cargo.toml @@ -0,0 +1,30 @@ +[package] +authors = ["Jorge Martín Espinosa "] +description = "Optional crate used to allow scanning the contents of media to prevent malware infections" +name = "matrix-sdk-contentscanner" +version = "0.18.0" +edition = "2024" +license = "Apache-2.0" +rust-version.workspace = true + +[features] +uniffi = ["dep:uniffi", "matrix-sdk/uniffi"] + +[dependencies] +assert_matches2.workspace = true +matrix-sdk = { workspace = true, features = ["testing", "e2e-encryption"] } +matrix-sdk-crypto.workspace = true +ruma = { workspace = true, features = ["client-api"] } +serde.workspace = true +tracing.workspace = true +uniffi = { workspace = true, optional = true } + +[dev-dependencies] +tokio = { workspace = true, features = ["macros"] } + +[target.'cfg(not(target_family = "wasm"))'.dependencies] +matrix-sdk-test.workspace = true +wiremock.workspace = true + +[lints] +workspace = true diff --git a/crates/matrix-sdk-contentscanner/src/lib.rs b/crates/matrix-sdk-contentscanner/src/lib.rs new file mode 100644 index 000000000..ce7a2ffa9 --- /dev/null +++ b/crates/matrix-sdk-contentscanner/src/lib.rs @@ -0,0 +1,64 @@ +// Copyright 2026 The Matrix.org Foundation C.I.C. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::sync::Arc; + +use matrix_sdk::locks::Mutex; +use matrix_sdk::{ + BoxFuture, Client, Error, IdParseError, + locks::Mutex, + media::{MediaFetcher, MediaRequestParameters}, +}; + +#[cfg(feature = "uniffi")] +uniffi::setup_scaffolding!(); + + +/// A helper component to download and scan media from a content scanner server. +#[derive(Debug)] +pub struct ContentScanner { + scanner_url: String, + public_server_key: Arc>>, +} + +impl ContentScanner { + /// Instantiate a new [`ContentScanner`] using the `scanner_url`. + pub fn new(scanner_url: impl Into) -> Self { + Self { scanner_url: scanner_url.into(), public_server_key: Arc::new(Mutex::new(None)) } + } + +/// A media fetcher that uses the content scanner to download and scan media. +pub struct ContentScannerMediaFetcher { + pub content_scanner: ContentScanner, +} + +impl ContentScannerMediaFetcher { + /// Instantiate a new [`MediaFetcher`] using the provided `scanner_url`. + pub fn new(scanner_url: impl Into) -> Self { + Self { content_scanner: ContentScanner::new(scanner_url.into()) } + } +} + +impl MediaFetcher for ContentScannerMediaFetcher { + fn fetch_media_content<'a>( + &'a self, + _client: &'a Client, + _request: &'a MediaRequestParameters, + ) -> BoxFuture<'a, matrix_sdk::Result, Error>> { + Box::pin(async move { + todo!("Implement fetch_media_content") + }) + } +} +} diff --git a/crates/matrix-sdk-contentscanner/uniffi.toml b/crates/matrix-sdk-contentscanner/uniffi.toml new file mode 100644 index 000000000..b4d6f5c0f --- /dev/null +++ b/crates/matrix-sdk-contentscanner/uniffi.toml @@ -0,0 +1,5 @@ +[bindings.kotlin] +android_cleaner = true +# Checksums are incorrectly failing for users with 32bit (and sometimes 64bit?) devices at the moment +# Remove once https://github.com/mozilla/uniffi-rs/issues/2740 is fixed or JNI is used instead of JNA +omit_checksums = true