diff --git a/Cargo.lock b/Cargo.lock index 78af3a1d..277236b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2958,7 +2958,7 @@ dependencies = [ [[package]] name = "ruma" version = "0.10.1" -source = "git+https://github.com/girlbossceo/ruwuma?rev=d23a8412bd8f875cf81bbd7e20cefa03263fcd0e#d23a8412bd8f875cf81bbd7e20cefa03263fcd0e" +source = "git+https://github.com/girlbossceo/ruwuma?rev=25fbd64b968c5d5088c07750aaa4873e072831b0#25fbd64b968c5d5088c07750aaa4873e072831b0" dependencies = [ "assign", "js_int", @@ -2980,7 +2980,7 @@ dependencies = [ [[package]] name = "ruma-appservice-api" version = "0.10.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=d23a8412bd8f875cf81bbd7e20cefa03263fcd0e#d23a8412bd8f875cf81bbd7e20cefa03263fcd0e" +source = "git+https://github.com/girlbossceo/ruwuma?rev=25fbd64b968c5d5088c07750aaa4873e072831b0#25fbd64b968c5d5088c07750aaa4873e072831b0" dependencies = [ "js_int", "ruma-common", @@ -2992,7 +2992,7 @@ dependencies = [ [[package]] name = "ruma-client-api" version = "0.18.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=d23a8412bd8f875cf81bbd7e20cefa03263fcd0e#d23a8412bd8f875cf81bbd7e20cefa03263fcd0e" +source = "git+https://github.com/girlbossceo/ruwuma?rev=25fbd64b968c5d5088c07750aaa4873e072831b0#25fbd64b968c5d5088c07750aaa4873e072831b0" dependencies = [ "as_variant", "assign", @@ -3015,7 +3015,7 @@ dependencies = [ [[package]] name = "ruma-common" version = "0.13.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=d23a8412bd8f875cf81bbd7e20cefa03263fcd0e#d23a8412bd8f875cf81bbd7e20cefa03263fcd0e" +source = "git+https://github.com/girlbossceo/ruwuma?rev=25fbd64b968c5d5088c07750aaa4873e072831b0#25fbd64b968c5d5088c07750aaa4873e072831b0" dependencies = [ "as_variant", "base64 0.22.1", @@ -3045,7 +3045,7 @@ dependencies = [ [[package]] name = "ruma-events" version = "0.28.1" -source = "git+https://github.com/girlbossceo/ruwuma?rev=d23a8412bd8f875cf81bbd7e20cefa03263fcd0e#d23a8412bd8f875cf81bbd7e20cefa03263fcd0e" +source = "git+https://github.com/girlbossceo/ruwuma?rev=25fbd64b968c5d5088c07750aaa4873e072831b0#25fbd64b968c5d5088c07750aaa4873e072831b0" dependencies = [ "as_variant", "indexmap 2.4.0", @@ -3069,7 +3069,7 @@ dependencies = [ [[package]] name = "ruma-federation-api" version = "0.9.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=d23a8412bd8f875cf81bbd7e20cefa03263fcd0e#d23a8412bd8f875cf81bbd7e20cefa03263fcd0e" +source = "git+https://github.com/girlbossceo/ruwuma?rev=25fbd64b968c5d5088c07750aaa4873e072831b0#25fbd64b968c5d5088c07750aaa4873e072831b0" dependencies = [ "bytes", "http", @@ -3087,7 +3087,7 @@ dependencies = [ [[package]] name = "ruma-identifiers-validation" version = "0.9.5" -source = "git+https://github.com/girlbossceo/ruwuma?rev=d23a8412bd8f875cf81bbd7e20cefa03263fcd0e#d23a8412bd8f875cf81bbd7e20cefa03263fcd0e" +source = "git+https://github.com/girlbossceo/ruwuma?rev=25fbd64b968c5d5088c07750aaa4873e072831b0#25fbd64b968c5d5088c07750aaa4873e072831b0" dependencies = [ "js_int", "thiserror", @@ -3096,7 +3096,7 @@ dependencies = [ [[package]] name = "ruma-identity-service-api" version = "0.9.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=d23a8412bd8f875cf81bbd7e20cefa03263fcd0e#d23a8412bd8f875cf81bbd7e20cefa03263fcd0e" +source = "git+https://github.com/girlbossceo/ruwuma?rev=25fbd64b968c5d5088c07750aaa4873e072831b0#25fbd64b968c5d5088c07750aaa4873e072831b0" dependencies = [ "js_int", "ruma-common", @@ -3106,7 +3106,7 @@ dependencies = [ [[package]] name = "ruma-macros" version = "0.13.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=d23a8412bd8f875cf81bbd7e20cefa03263fcd0e#d23a8412bd8f875cf81bbd7e20cefa03263fcd0e" +source = "git+https://github.com/girlbossceo/ruwuma?rev=25fbd64b968c5d5088c07750aaa4873e072831b0#25fbd64b968c5d5088c07750aaa4873e072831b0" dependencies = [ "once_cell", "proc-macro-crate", @@ -3121,7 +3121,7 @@ dependencies = [ [[package]] name = "ruma-push-gateway-api" version = "0.9.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=d23a8412bd8f875cf81bbd7e20cefa03263fcd0e#d23a8412bd8f875cf81bbd7e20cefa03263fcd0e" +source = "git+https://github.com/girlbossceo/ruwuma?rev=25fbd64b968c5d5088c07750aaa4873e072831b0#25fbd64b968c5d5088c07750aaa4873e072831b0" dependencies = [ "js_int", "ruma-common", @@ -3133,7 +3133,7 @@ dependencies = [ [[package]] name = "ruma-server-util" version = "0.3.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=d23a8412bd8f875cf81bbd7e20cefa03263fcd0e#d23a8412bd8f875cf81bbd7e20cefa03263fcd0e" +source = "git+https://github.com/girlbossceo/ruwuma?rev=25fbd64b968c5d5088c07750aaa4873e072831b0#25fbd64b968c5d5088c07750aaa4873e072831b0" dependencies = [ "headers", "http", @@ -3146,7 +3146,7 @@ dependencies = [ [[package]] name = "ruma-signatures" version = "0.15.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=d23a8412bd8f875cf81bbd7e20cefa03263fcd0e#d23a8412bd8f875cf81bbd7e20cefa03263fcd0e" +source = "git+https://github.com/girlbossceo/ruwuma?rev=25fbd64b968c5d5088c07750aaa4873e072831b0#25fbd64b968c5d5088c07750aaa4873e072831b0" dependencies = [ "base64 0.22.1", "ed25519-dalek", @@ -3162,7 +3162,7 @@ dependencies = [ [[package]] name = "ruma-state-res" version = "0.11.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=d23a8412bd8f875cf81bbd7e20cefa03263fcd0e#d23a8412bd8f875cf81bbd7e20cefa03263fcd0e" +source = "git+https://github.com/girlbossceo/ruwuma?rev=25fbd64b968c5d5088c07750aaa4873e072831b0#25fbd64b968c5d5088c07750aaa4873e072831b0" dependencies = [ "itertools 0.12.1", "js_int", diff --git a/Cargo.toml b/Cargo.toml index 2826c440..15007081 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -311,7 +311,7 @@ version = "0.1.2" [workspace.dependencies.ruma] git = "https://github.com/girlbossceo/ruwuma" #branch = "conduwuit-changes" -rev = "d23a8412bd8f875cf81bbd7e20cefa03263fcd0e" +rev = "25fbd64b968c5d5088c07750aaa4873e072831b0" features = [ "compat", "rand", diff --git a/src/admin/media/commands.rs b/src/admin/media/commands.rs index 7906d951..577d5aba 100644 --- a/src/admin/media/commands.rs +++ b/src/admin/media/commands.rs @@ -15,7 +15,10 @@ pub(super) async fn delete( if let Some(mxc) = mxc { debug!("Got MXC URL: {mxc}"); - self.services.media.delete(mxc.as_ref()).await?; + self.services + .media + .delete(&mxc.as_str().try_into()?) + .await?; return Ok(RoomMessageEventContent::text_plain( "Deleted the MXC from our database and on our filesystem.", @@ -123,7 +126,10 @@ pub(super) async fn delete( } for mxc_url in mxc_urls { - self.services.media.delete(&mxc_url).await?; + self.services + .media + .delete(&mxc_url.as_str().try_into()?) + .await?; mxc_deletion_count = mxc_deletion_count.saturating_add(1); } @@ -157,7 +163,7 @@ pub(super) async fn delete_list(&self) -> Result { for mxc in mxc_list { debug!("Deleting MXC {mxc} in bulk"); - self.services.media.delete(mxc).await?; + self.services.media.delete(&mxc.try_into()?).await?; mxc_deletion_count = mxc_deletion_count .checked_add(1) .expect("mxc_deletion_count should not get this high"); diff --git a/src/api/client/media.rs b/src/api/client/media.rs index 0326568f..9553d425 100644 --- a/src/api/client/media.rs +++ b/src/api/client/media.rs @@ -7,8 +7,12 @@ use conduit::{ utils::{self, content_disposition::make_content_disposition, math::ruma_from_usize}, Err, Result, }; -use ruma::api::client::media::{ - create_content, get_content, get_content_as_filename, get_content_thumbnail, get_media_config, get_media_preview, +use ruma::{ + api::client::media::{ + create_content, get_content, get_content_as_filename, get_content_thumbnail, get_media_config, + get_media_preview, + }, + Mxc, }; use service::media::{FileMeta, MXC_LENGTH}; @@ -106,16 +110,17 @@ pub(crate) async fn create_content_route( body: Ruma, ) -> Result { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); - - let mxc = format!("mxc://{}/{}", services.globals.server_name(), utils::random_string(MXC_LENGTH)); - let content_disposition = make_content_disposition(None, body.content_type.as_deref(), body.filename.as_deref()); + let mxc = Mxc { + server_name: services.globals.server_name(), + media_id: &utils::random_string(MXC_LENGTH), + }; services .media .create( - Some(sender_user.clone()), &mxc, + Some(sender_user), Some(&content_disposition), body.content_type.as_deref(), &body.file, @@ -123,7 +128,7 @@ pub(crate) async fn create_content_route( .await?; Ok(create_content::v3::Response { - content_uri: mxc.into(), + content_uri: mxc.to_string().into(), blurhash: None, }) } @@ -161,7 +166,10 @@ pub(crate) async fn get_content_route( State(services): State, InsecureClientIp(client): InsecureClientIp, body: Ruma, ) -> Result { - let mxc = format!("mxc://{}/{}", body.server_name, body.media_id); + let mxc = Mxc { + server_name: &body.server_name, + media_id: &body.media_id, + }; if let Some(FileMeta { content, @@ -181,13 +189,7 @@ pub(crate) async fn get_content_route( } else if !services.globals.server_is_ours(&body.server_name) && body.allow_remote { let response = services .media - .fetch_remote_content( - &mxc, - &body.server_name, - body.media_id.clone(), - body.allow_redirect, - body.timeout_ms, - ) + .fetch_remote_content_legacy(&mxc, body.allow_redirect, body.timeout_ms) .await .map_err(|e| err!(Request(NotFound(debug_warn!(%mxc, "Fetching media failed: {e:?}")))))?; @@ -241,7 +243,10 @@ pub(crate) async fn get_content_as_filename_route( State(services): State, InsecureClientIp(client): InsecureClientIp, body: Ruma, ) -> Result { - let mxc = format!("mxc://{}/{}", body.server_name, body.media_id); + let mxc = Mxc { + server_name: &body.server_name, + media_id: &body.media_id, + }; if let Some(FileMeta { content, @@ -262,13 +267,7 @@ pub(crate) async fn get_content_as_filename_route( } else if !services.globals.server_is_ours(&body.server_name) && body.allow_remote { let response = services .media - .fetch_remote_content( - &mxc, - &body.server_name, - body.media_id.clone(), - body.allow_redirect, - body.timeout_ms, - ) + .fetch_remote_content_legacy(&mxc, body.allow_redirect, body.timeout_ms) .await .map_err(|e| err!(Request(NotFound(debug_warn!(%mxc, "Fetching media failed: {e:?}")))))?; @@ -322,7 +321,10 @@ pub(crate) async fn get_content_thumbnail_route( State(services): State, InsecureClientIp(client): InsecureClientIp, body: Ruma, ) -> Result { - let mxc = format!("mxc://{}/{}", body.server_name, body.media_id); + let mxc = Mxc { + server_name: &body.server_name, + media_id: &body.media_id, + }; if let Some(FileMeta { content, @@ -353,7 +355,7 @@ pub(crate) async fn get_content_thumbnail_route( } else if !services.globals.server_is_ours(&body.server_name) && body.allow_remote { let response = services .media - .fetch_remote_thumbnail(&mxc, &body) + .fetch_remote_thumbnail_legacy(&body) .await .map_err(|e| err!(Request(NotFound(debug_warn!(%mxc, "Fetching media failed: {e:?}")))))?; diff --git a/src/core/error/mod.rs b/src/core/error/mod.rs index 9797c741..92dbdfe3 100644 --- a/src/core/error/mod.rs +++ b/src/core/error/mod.rs @@ -98,6 +98,8 @@ pub enum Error { #[error(transparent)] IntoHttp(#[from] ruma::api::error::IntoHttpError), #[error(transparent)] + Mxc(#[from] ruma::MxcUriError), + #[error(transparent)] Mxid(#[from] ruma::IdParseError), #[error("from {0}: {1}")] Redaction(ruma::OwnedServerName, ruma::canonical_json::RedactionError), diff --git a/src/service/media/data.rs b/src/service/media/data.rs index 222d28b5..f5de2bbe 100644 --- a/src/service/media/data.rs +++ b/src/service/media/data.rs @@ -1,8 +1,12 @@ use std::sync::Arc; -use conduit::{debug, debug_info, utils::string_from_bytes, Error, Result}; +use conduit::{ + debug, debug_info, trace, + utils::{str_from_bytes, string_from_bytes}, + Err, Error, Result, +}; use database::{Database, Map}; -use ruma::{api::client::error::ErrorKind, http_headers::ContentDisposition}; +use ruma::{api::client::error::ErrorKind, http_headers::ContentDisposition, Mxc, UserId}; use super::preview::UrlPreviewData; @@ -29,10 +33,12 @@ impl Data { } pub(super) fn create_file_metadata( - &self, sender_user: Option<&str>, mxc: &str, width: u32, height: u32, + &self, mxc: &Mxc<'_>, user: Option<&UserId>, width: u32, height: u32, content_disposition: Option<&ContentDisposition>, content_type: Option<&str>, ) -> Result> { - let mut key = mxc.as_bytes().to_vec(); + let mut key: Vec = Vec::new(); + key.extend_from_slice(mxc.server_name.as_bytes()); + key.extend_from_slice(mxc.media_id.as_bytes()); key.push(0xFF); key.extend_from_slice(&width.to_be_bytes()); key.extend_from_slice(&height.to_be_bytes()); @@ -53,8 +59,10 @@ impl Data { self.mediaid_file.insert(&key, &[])?; - if let Some(user) = sender_user { - let key = mxc.as_bytes().to_vec(); + if let Some(user) = user { + let mut key: Vec = Vec::new(); + key.extend_from_slice(mxc.server_name.as_bytes()); + key.extend_from_slice(mxc.media_id.as_bytes()); let user = user.as_bytes().to_vec(); self.mediaid_user.insert(&key, &user)?; } @@ -62,22 +70,23 @@ impl Data { Ok(key) } - pub(super) fn delete_file_mxc(&self, mxc: &str) -> Result<()> { - debug!("MXC URI: {:?}", mxc); + pub(super) fn delete_file_mxc(&self, mxc: &Mxc<'_>) -> Result<()> { + debug!("MXC URI: {mxc}"); - let mut prefix = mxc.as_bytes().to_vec(); + let mut prefix: Vec = Vec::new(); + prefix.extend_from_slice(mxc.server_name.as_bytes()); + prefix.extend_from_slice(mxc.media_id.as_bytes()); prefix.push(0xFF); - debug!("MXC db prefix: {prefix:?}"); - - for (key, _) in self.mediaid_file.scan_prefix(prefix) { + trace!("MXC db prefix: {prefix:?}"); + for (key, _) in self.mediaid_file.scan_prefix(prefix.clone()) { debug!("Deleting key: {:?}", key); self.mediaid_file.remove(&key)?; } - for (key, value) in self.mediaid_user.scan_prefix(mxc.as_bytes().to_vec()) { - if key == mxc.as_bytes().to_vec() { - let user = string_from_bytes(&value).unwrap_or_default(); + for (key, value) in self.mediaid_user.scan_prefix(prefix.clone()) { + if key.starts_with(&prefix) { + let user = str_from_bytes(&value).unwrap_or_default(); debug_info!("Deleting key \"{key:?}\" which was uploaded by user {user}"); self.mediaid_user.remove(&key)?; @@ -88,10 +97,12 @@ impl Data { } /// Searches for all files with the given MXC - pub(super) fn search_mxc_metadata_prefix(&self, mxc: &str) -> Result>> { - debug!("MXC URI: {:?}", mxc); + pub(super) fn search_mxc_metadata_prefix(&self, mxc: &Mxc<'_>) -> Result>> { + debug!("MXC URI: {mxc}"); - let mut prefix = mxc.as_bytes().to_vec(); + let mut prefix: Vec = Vec::new(); + prefix.extend_from_slice(mxc.server_name.as_bytes()); + prefix.extend_from_slice(mxc.media_id.as_bytes()); prefix.push(0xFF); let keys: Vec> = self @@ -101,18 +112,18 @@ impl Data { .collect(); if keys.is_empty() { - return Err(Error::bad_database( - "Failed to find any keys in database with the provided MXC.", - )); + return Err!(Database("Failed to find any keys in database for `{mxc}`",)); } - debug!("Got the following keys: {:?}", keys); + debug!("Got the following keys: {keys:?}"); Ok(keys) } - pub(super) fn search_file_metadata(&self, mxc: &str, width: u32, height: u32) -> Result { - let mut prefix = mxc.as_bytes().to_vec(); + pub(super) fn search_file_metadata(&self, mxc: &Mxc<'_>, width: u32, height: u32) -> Result { + let mut prefix: Vec = Vec::new(); + prefix.extend_from_slice(mxc.server_name.as_bytes()); + prefix.extend_from_slice(mxc.media_id.as_bytes()); prefix.push(0xFF); prefix.extend_from_slice(&width.to_be_bytes()); prefix.extend_from_slice(&height.to_be_bytes()); diff --git a/src/service/media/mod.rs b/src/service/media/mod.rs index b63dc141..c8f8ad72 100644 --- a/src/service/media/mod.rs +++ b/src/service/media/mod.rs @@ -10,7 +10,7 @@ use async_trait::async_trait; use base64::{engine::general_purpose, Engine as _}; use conduit::{debug, debug_error, err, error, trace, utils, utils::MutexMap, Err, Result, Server}; use data::{Data, Metadata}; -use ruma::{http_headers::ContentDisposition, OwnedMxcUri, OwnedUserId}; +use ruma::{http_headers::ContentDisposition, Mxc, OwnedMxcUri, UserId}; use tokio::{ fs, io::{AsyncReadExt, AsyncWriteExt, BufReader}, @@ -68,17 +68,13 @@ impl crate::Service for Service { impl Service { /// Uploads a file. pub async fn create( - &self, sender_user: Option, mxc: &str, content_disposition: Option<&ContentDisposition>, + &self, mxc: &Mxc<'_>, user: Option<&UserId>, content_disposition: Option<&ContentDisposition>, content_type: Option<&str>, file: &[u8], ) -> Result<()> { // Width, Height = 0 if it's not a thumbnail - let key = if let Some(user) = sender_user { - self.db - .create_file_metadata(Some(user.as_str()), mxc, 0, 0, content_disposition, content_type)? - } else { - self.db - .create_file_metadata(None, mxc, 0, 0, content_disposition, content_type)? - }; + let key = self + .db + .create_file_metadata(mxc, user, 0, 0, content_disposition, content_type)?; //TODO: Dangling metadata in database if creation fails let mut f = self.create_media_file(&key).await?; @@ -88,7 +84,7 @@ impl Service { } /// Deletes a file in the database and from the media directory via an MXC - pub async fn delete(&self, mxc: &str) -> Result<()> { + pub async fn delete(&self, mxc: &Mxc<'_>) -> Result<()> { if let Ok(keys) = self.db.search_mxc_metadata_prefix(mxc) { for key in keys { trace!(?mxc, ?key, "Deleting from filesystem"); @@ -111,7 +107,7 @@ impl Service { } /// Downloads a file. - pub async fn get(&self, mxc: &str) -> Result> { + pub async fn get(&self, mxc: &Mxc<'_>) -> Result> { if let Ok(Metadata { content_disposition, content_type, @@ -213,6 +209,7 @@ impl Service { debug!("Deleting media now in the past {user_duration:?}."); let mut deletion_count: usize = 0; for mxc in remote_mxcs { + let mxc: Mxc<'_> = mxc.as_str().try_into()?; debug!("Deleting MXC {mxc} from database and filesystem"); self.delete(&mxc).await?; deletion_count = deletion_count.saturating_add(1); diff --git a/src/service/media/preview.rs b/src/service/media/preview.rs index ac24d81a..5704075e 100644 --- a/src/service/media/preview.rs +++ b/src/service/media/preview.rs @@ -4,6 +4,7 @@ use conduit::{debug, utils, warn, Err, Result}; use conduit_core::implement; use image::ImageReader as ImgReader; use ipaddress::IPAddress; +use ruma::Mxc; use serde::Serialize; use url::Url; use webpage::HTML; @@ -44,13 +45,12 @@ pub async fn set_url_preview(&self, url: &str, data: &UrlPreviewData) -> Result< pub async fn download_image(&self, url: &str) -> Result { let client = &self.services.client.url_preview; let image = client.get(url).send().await?.bytes().await?; - let mxc = format!( - "mxc://{}/{}", - self.services.globals.server_name(), - utils::random_string(MXC_LENGTH) - ); + let mxc = Mxc { + server_name: self.services.globals.server_name(), + media_id: &utils::random_string(MXC_LENGTH), + }; - self.create(None, &mxc, None, None, &image).await?; + self.create(&mxc, None, None, None, &image).await?; let (width, height) = match ImgReader::new(Cursor::new(&image)).with_guessed_format() { Err(_) => (None, None), @@ -61,7 +61,7 @@ pub async fn download_image(&self, url: &str) -> Result { }; Ok(UrlPreviewData { - image: Some(mxc), + image: Some(mxc.to_string()), image_size: Some(image.len()), image_width: width, image_height: height, diff --git a/src/service/media/remote.rs b/src/service/media/remote.rs index c07ded76..d4c458e2 100644 --- a/src/service/media/remote.rs +++ b/src/service/media/remote.rs @@ -1,25 +1,25 @@ use std::time::Duration; use conduit::{debug_warn, err, implement, utils::content_disposition::make_content_disposition, Err, Error, Result}; -use ruma::{ - api::client::media::{get_content, get_content_thumbnail}, - ServerName, -}; +use ruma::{api::client::media, Mxc}; #[implement(super::Service)] #[allow(deprecated)] -pub async fn fetch_remote_thumbnail( - &self, mxc: &str, body: &get_content_thumbnail::v3::Request, -) -> Result { - let server_name = &body.server_name; - self.check_fetch_authorized(mxc, server_name)?; +pub async fn fetch_remote_thumbnail_legacy( + &self, body: &media::get_content_thumbnail::v3::Request, +) -> Result { + let mxc = Mxc { + server_name: &body.server_name, + media_id: &body.media_id, + }; + self.check_fetch_authorized(&mxc)?; let reponse = self .services .sending .send_federation_request( - server_name, - get_content_thumbnail::v3::Request { + mxc.server_name, + media::get_content_thumbnail::v3::Request { allow_remote: body.allow_remote, height: body.height, width: body.width, @@ -34,8 +34,8 @@ pub async fn fetch_remote_thumbnail( .await?; self.upload_thumbnail( + &mxc, None, - mxc, None, reponse.content_type.as_deref(), body.width @@ -53,20 +53,19 @@ pub async fn fetch_remote_thumbnail( #[implement(super::Service)] #[allow(deprecated)] -pub async fn fetch_remote_content( - &self, mxc: &str, server_name: &ServerName, media_id: String, allow_redirect: bool, timeout_ms: Duration, -) -> Result { - self.check_fetch_authorized(mxc, server_name)?; - +pub async fn fetch_remote_content_legacy( + &self, mxc: &Mxc<'_>, allow_redirect: bool, timeout_ms: Duration, +) -> Result { + self.check_fetch_authorized(mxc)?; let response = self .services .sending .send_federation_request( - server_name, - get_content::v3::Request { + mxc.server_name, + media::get_content::v3::Request { allow_remote: true, - server_name: server_name.to_owned(), - media_id, + server_name: mxc.server_name.into(), + media_id: mxc.media_id.into(), timeout_ms, allow_redirect, }, @@ -77,8 +76,8 @@ pub async fn fetch_remote_content( make_content_disposition(response.content_disposition.as_ref(), response.content_type.as_deref(), None); self.create( - None, mxc, + None, Some(&content_disposition), response.content_type.as_deref(), &response.file, @@ -89,14 +88,14 @@ pub async fn fetch_remote_content( } #[implement(super::Service)] -fn check_fetch_authorized(&self, mxc: &str, server_name: &ServerName) -> Result<()> { +fn check_fetch_authorized(&self, mxc: &Mxc<'_>) -> Result<()> { if self .services .server .config .prevent_media_downloads_from .iter() - .any(|entry| entry == server_name) + .any(|entry| entry == mxc.server_name) { // we'll lie to the client and say the blocked server's media was not found and // log. the client has no way of telling anyways so this is a security bonus. diff --git a/src/service/media/thumbnail.rs b/src/service/media/thumbnail.rs index 7a1eef6c..3aadcfc0 100644 --- a/src/service/media/thumbnail.rs +++ b/src/service/media/thumbnail.rs @@ -2,7 +2,7 @@ use std::{cmp, io::Cursor, num::Saturating as Sat}; use conduit::{checked, Result}; use image::{imageops::FilterType, DynamicImage}; -use ruma::{http_headers::ContentDisposition, OwnedUserId}; +use ruma::{http_headers::ContentDisposition, Mxc, UserId}; use tokio::{ fs, io::{AsyncReadExt, AsyncWriteExt}, @@ -14,16 +14,12 @@ impl super::Service { /// Uploads or replaces a file thumbnail. #[allow(clippy::too_many_arguments)] pub async fn upload_thumbnail( - &self, sender_user: Option, mxc: &str, content_disposition: Option<&ContentDisposition>, + &self, mxc: &Mxc<'_>, user: Option<&UserId>, content_disposition: Option<&ContentDisposition>, content_type: Option<&str>, width: u32, height: u32, file: &[u8], ) -> Result<()> { - let key = if let Some(user) = sender_user { - self.db - .create_file_metadata(Some(user.as_str()), mxc, width, height, content_disposition, content_type)? - } else { - self.db - .create_file_metadata(None, mxc, width, height, content_disposition, content_type)? - }; + let key = self + .db + .create_file_metadata(mxc, user, width, height, content_disposition, content_type)?; //TODO: Dangling metadata in database if creation fails let mut f = self.create_media_file(&key).await?; @@ -46,7 +42,7 @@ impl super::Service { /// For width,height <= 96 the server uses another thumbnailing algorithm /// which crops the image afterwards. #[tracing::instrument(skip(self), name = "thumbnail", level = "debug")] - pub async fn get_thumbnail(&self, mxc: &str, width: u32, height: u32) -> Result> { + pub async fn get_thumbnail(&self, mxc: &Mxc<'_>, width: u32, height: u32) -> Result> { // 0, 0 because that's the original file let (width, height, crop) = thumbnail_properties(width, height).unwrap_or((0, 0, false)); @@ -76,7 +72,7 @@ impl super::Service { /// Generate a thumbnail #[tracing::instrument(skip(self), name = "generate", level = "debug")] async fn get_thumbnail_generate( - &self, mxc: &str, width: u32, height: u32, crop: bool, data: Metadata, + &self, mxc: &Mxc<'_>, width: u32, height: u32, crop: bool, data: Metadata, ) -> Result> { let mut content = Vec::new(); let path = self.get_media_file(&data.key); @@ -100,8 +96,8 @@ impl super::Service { // Save thumbnail in database so we don't have to generate it again next time let thumbnail_key = self.db.create_file_metadata( - None, mxc, + None, width, height, data.content_disposition.as_ref(),