From 7f165e5bbe7011f55beb76460b168e410dc34eac Mon Sep 17 00:00:00 2001 From: Trash Panda Date: Sun, 1 Mar 2026 01:41:55 -0700 Subject: [PATCH] fix: Refactor and block media downloads larger than max_request_size --- src/service/media/preview.rs | 69 ++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 26 deletions(-) diff --git a/src/service/media/preview.rs b/src/service/media/preview.rs index 783269f1..88e8bb15 100644 --- a/src/service/media/preview.rs +++ b/src/service/media/preview.rs @@ -10,6 +10,8 @@ use std::time::SystemTime; use conduwuit::{Err, Result, debug, err, utils::response::LimitReadExt}; use conduwuit_core::implement; use ipaddress::IPAddress; +#[cfg(feature = "url_preview")] +use ruma::OwnedMxcUri; use serde::Serialize; use url::Url; @@ -181,22 +183,12 @@ pub async fn download_video( url: &str, preview_data: Option, ) -> Result { - use conduwuit::utils::random_string; - use ruma::Mxc; - let mut preview_data = preview_data.unwrap_or_default(); if self.services.globals.url_preview_allow_audio_video() { - let video = self.services.client.url_preview.get(url).send().await?; - let video = video.bytes().await?; - let mxc = Mxc { - server_name: self.services.globals.server_name(), - media_id: &random_string(super::MXC_LENGTH), - }; - - self.create(&mxc, None, None, None, &video).await?; - - preview_data.video = Some(mxc.to_string()); + let (url, size) = self.download_media(url).await?; + preview_data.video = Some(url.to_string()); + preview_data.video_size = Some(size); } Ok(preview_data) @@ -209,27 +201,46 @@ pub async fn download_audio( url: &str, preview_data: Option, ) -> Result { - use conduwuit::utils::random_string; - use ruma::Mxc; - let mut preview_data = preview_data.unwrap_or_default(); if self.services.globals.url_preview_allow_audio_video() { - let audio = self.services.client.url_preview.get(url).send().await?; - let audio = audio.bytes().await?; - let mxc = Mxc { - server_name: self.services.globals.server_name(), - media_id: &random_string(super::MXC_LENGTH), - }; - - self.create(&mxc, None, None, None, &audio).await?; - - preview_data.video = Some(mxc.to_string()); + let (url, size) = self.download_media(url).await?; + preview_data.audio = Some(url.to_string()); + preview_data.audio_size = Some(size); } Ok(preview_data) } +#[cfg(feature = "url_preview")] +#[implement(Service)] +pub async fn download_media(&self, url: &str) -> Result<(OwnedMxcUri, usize)> { + use conduwuit::utils::random_string; + use ruma::Mxc; + + let max_request_size = self.services.server.config.max_request_size.try_into()?; + + let media = self.services.client.url_preview.get(url).send().await?; + if media + .content_length() + .is_none_or(|len| len > max_request_size) + { + return Err!(Request(TooLarge( + "Content length not given or greater than max_request_size" + ))); + } + + let media = media.bytes().await?; + let mxc = Mxc { + server_name: self.services.globals.server_name(), + media_id: &random_string(super::MXC_LENGTH), + }; + + self.create(&mxc, None, None, None, &media).await?; + + return Ok((OwnedMxcUri::from(mxc.to_string()), media.len())); +} + #[cfg(not(feature = "url_preview"))] #[implement(Service)] pub async fn download_image( @@ -260,6 +271,12 @@ pub async fn download_audio( Err!(FeatureDisabled("url_preview")) } +#[cfg(not(feature = "url_preview"))] +#[implement(Service)] +pub async fn download_media(&self, _url: &str) -> Result { + Err!(FeatureDisabled("url_preview")) +} + #[cfg(feature = "url_preview")] #[implement(Service)] async fn download_html(&self, url: &str) -> Result {