diff --git a/Cargo.lock b/Cargo.lock index 30d951a7..20082187 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1203,9 +1203,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" @@ -2232,7 +2232,7 @@ dependencies = [ [[package]] name = "ruma" version = "0.10.1" -source = "git+https://github.com/ruma/ruma#fec2152d879a6c6c2bccce984d4b8f424f460cb2" +source = "git+https://github.com/ruma/ruma#82417e394076440089cd8ada87485d9a44cc4ba0" dependencies = [ "assign", "js_int", @@ -2253,7 +2253,7 @@ dependencies = [ [[package]] name = "ruma-appservice-api" version = "0.10.0" -source = "git+https://github.com/ruma/ruma#fec2152d879a6c6c2bccce984d4b8f424f460cb2" +source = "git+https://github.com/ruma/ruma#82417e394076440089cd8ada87485d9a44cc4ba0" dependencies = [ "js_int", "ruma-common", @@ -2265,7 +2265,7 @@ dependencies = [ [[package]] name = "ruma-client-api" version = "0.18.0" -source = "git+https://github.com/ruma/ruma#fec2152d879a6c6c2bccce984d4b8f424f460cb2" +source = "git+https://github.com/ruma/ruma#82417e394076440089cd8ada87485d9a44cc4ba0" dependencies = [ "as_variant", "assign", @@ -2288,7 +2288,7 @@ dependencies = [ [[package]] name = "ruma-common" version = "0.13.0" -source = "git+https://github.com/ruma/ruma#fec2152d879a6c6c2bccce984d4b8f424f460cb2" +source = "git+https://github.com/ruma/ruma#82417e394076440089cd8ada87485d9a44cc4ba0" dependencies = [ "as_variant", "base64 0.22.1", @@ -2318,7 +2318,7 @@ dependencies = [ [[package]] name = "ruma-events" version = "0.28.1" -source = "git+https://github.com/ruma/ruma#fec2152d879a6c6c2bccce984d4b8f424f460cb2" +source = "git+https://github.com/ruma/ruma#82417e394076440089cd8ada87485d9a44cc4ba0" dependencies = [ "as_variant", "indexmap 2.2.6", @@ -2334,15 +2334,22 @@ dependencies = [ "thiserror", "tracing", "url", + "web-time", "wildmatch", ] [[package]] name = "ruma-federation-api" version = "0.9.0" -source = "git+https://github.com/ruma/ruma#fec2152d879a6c6c2bccce984d4b8f424f460cb2" +source = "git+https://github.com/ruma/ruma#82417e394076440089cd8ada87485d9a44cc4ba0" dependencies = [ + "bytes", + "http 1.1.0", + "httparse", "js_int", + "memchr", + "mime", + "rand", "ruma-common", "ruma-events", "serde", @@ -2352,7 +2359,7 @@ dependencies = [ [[package]] name = "ruma-identifiers-validation" version = "0.9.5" -source = "git+https://github.com/ruma/ruma#fec2152d879a6c6c2bccce984d4b8f424f460cb2" +source = "git+https://github.com/ruma/ruma#82417e394076440089cd8ada87485d9a44cc4ba0" dependencies = [ "js_int", "thiserror", @@ -2361,7 +2368,7 @@ dependencies = [ [[package]] name = "ruma-identity-service-api" version = "0.9.0" -source = "git+https://github.com/ruma/ruma#fec2152d879a6c6c2bccce984d4b8f424f460cb2" +source = "git+https://github.com/ruma/ruma#82417e394076440089cd8ada87485d9a44cc4ba0" dependencies = [ "js_int", "ruma-common", @@ -2371,7 +2378,7 @@ dependencies = [ [[package]] name = "ruma-macros" version = "0.13.0" -source = "git+https://github.com/ruma/ruma#fec2152d879a6c6c2bccce984d4b8f424f460cb2" +source = "git+https://github.com/ruma/ruma#82417e394076440089cd8ada87485d9a44cc4ba0" dependencies = [ "once_cell", "proc-macro-crate", @@ -2386,7 +2393,7 @@ dependencies = [ [[package]] name = "ruma-push-gateway-api" version = "0.9.0" -source = "git+https://github.com/ruma/ruma#fec2152d879a6c6c2bccce984d4b8f424f460cb2" +source = "git+https://github.com/ruma/ruma#82417e394076440089cd8ada87485d9a44cc4ba0" dependencies = [ "js_int", "ruma-common", @@ -2398,7 +2405,7 @@ dependencies = [ [[package]] name = "ruma-server-util" version = "0.3.0" -source = "git+https://github.com/ruma/ruma#fec2152d879a6c6c2bccce984d4b8f424f460cb2" +source = "git+https://github.com/ruma/ruma#82417e394076440089cd8ada87485d9a44cc4ba0" dependencies = [ "headers", "http 1.1.0", @@ -2411,7 +2418,7 @@ dependencies = [ [[package]] name = "ruma-signatures" version = "0.15.0" -source = "git+https://github.com/ruma/ruma#fec2152d879a6c6c2bccce984d4b8f424f460cb2" +source = "git+https://github.com/ruma/ruma#82417e394076440089cd8ada87485d9a44cc4ba0" dependencies = [ "base64 0.22.1", "ed25519-dalek", @@ -2427,7 +2434,7 @@ dependencies = [ [[package]] name = "ruma-state-res" version = "0.11.0" -source = "git+https://github.com/ruma/ruma#fec2152d879a6c6c2bccce984d4b8f424f460cb2" +source = "git+https://github.com/ruma/ruma#82417e394076440089cd8ada87485d9a44cc4ba0" dependencies = [ "itertools", "js_int", diff --git a/src/api/client_server/media.rs b/src/api/client_server/media.rs index 10890f93..803d516e 100644 --- a/src/api/client_server/media.rs +++ b/src/api/client_server/media.rs @@ -4,12 +4,15 @@ use std::time::Duration; use crate::{service::media::FileMeta, services, utils, Error, Result, Ruma}; -use ruma::api::client::{ - error::ErrorKind, - media::{ - create_content, get_content, get_content_as_filename, get_content_thumbnail, - get_media_config, +use ruma::{ + api::client::{ + error::ErrorKind, + media::{ + create_content, get_content, get_content_as_filename, get_content_thumbnail, + get_media_config, + }, }, + http_headers::{ContentDisposition, ContentDispositionType}, }; const MXC_LENGTH: usize = 32; @@ -44,10 +47,10 @@ pub async fn create_content_route( .media .create( mxc.clone(), - body.filename - .as_ref() - .map(|filename| "inline; filename=".to_owned() + filename) - .as_deref(), + Some( + ContentDisposition::new(ContentDispositionType::Inline) + .with_filename(body.filename.clone()), + ), body.content_type.as_deref(), &body.file, ) @@ -82,7 +85,7 @@ pub async fn get_remote_content( .media .create( mxc.to_owned(), - content_response.content_disposition.as_deref(), + content_response.content_disposition.clone(), content_response.content_type.as_deref(), &content_response.file, ) @@ -110,7 +113,7 @@ pub async fn get_content_route( Ok(get_content::v3::Response { file, content_type, - content_disposition, + content_disposition: Some(content_disposition), cross_origin_resource_policy: Some("cross-origin".to_owned()), }) } else if &*body.server_name != services().globals.server_name() && body.allow_remote { @@ -145,7 +148,10 @@ pub async fn get_content_as_filename_route( Ok(get_content_as_filename::v3::Response { file, content_type, - content_disposition: Some(format!("inline; filename={}", body.filename)), + content_disposition: Some( + ContentDisposition::new(ContentDispositionType::Inline) + .with_filename(Some(body.filename.clone())), + ), cross_origin_resource_policy: Some("cross-origin".to_owned()), }) } else if &*body.server_name != services().globals.server_name() && body.allow_remote { @@ -153,7 +159,10 @@ pub async fn get_content_as_filename_route( get_remote_content(&mxc, &body.server_name, body.media_id.clone()).await?; Ok(get_content_as_filename::v3::Response { - content_disposition: Some(format!("inline: filename={}", body.filename)), + content_disposition: Some( + ContentDisposition::new(ContentDispositionType::Inline) + .with_filename(Some(body.filename.clone())), + ), content_type: remote_content_response.content_type, file: remote_content_response.file, cross_origin_resource_policy: Some("cross-origin".to_owned()), @@ -216,7 +225,6 @@ pub async fn get_content_thumbnail_route( .media .upload_thumbnail( mxc, - None, get_thumbnail_response.content_type.as_deref(), body.width.try_into().expect("all UInts are valid u32s"), body.height.try_into().expect("all UInts are valid u32s"), diff --git a/src/database/key_value/media.rs b/src/database/key_value/media.rs index 6abe5ba5..52a8e79e 100644 --- a/src/database/key_value/media.rs +++ b/src/database/key_value/media.rs @@ -1,4 +1,4 @@ -use ruma::api::client::error::ErrorKind; +use ruma::{api::client::error::ErrorKind, http_headers::ContentDisposition}; use crate::{database::KeyValueDatabase, service, utils, Error, Result}; @@ -8,7 +8,7 @@ impl service::media::Data for KeyValueDatabase { mxc: String, width: u32, height: u32, - content_disposition: Option<&str>, + content_disposition: &ContentDisposition, content_type: Option<&str>, ) -> Result> { let mut key = mxc.as_bytes().to_vec(); @@ -16,12 +16,7 @@ impl service::media::Data for KeyValueDatabase { key.extend_from_slice(&width.to_be_bytes()); key.extend_from_slice(&height.to_be_bytes()); key.push(0xff); - key.extend_from_slice( - content_disposition - .as_ref() - .map(|f| f.as_bytes()) - .unwrap_or_default(), - ); + key.extend_from_slice(content_disposition.to_string().as_bytes()); key.push(0xff); key.extend_from_slice( content_type @@ -40,7 +35,7 @@ impl service::media::Data for KeyValueDatabase { mxc: String, width: u32, height: u32, - ) -> Result<(Option, Option, Vec)> { + ) -> Result<(ContentDisposition, Option, Vec)> { let mut prefix = mxc.as_bytes().to_vec(); prefix.push(0xff); prefix.extend_from_slice(&width.to_be_bytes()); @@ -68,15 +63,9 @@ impl service::media::Data for KeyValueDatabase { .next() .ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?; - let content_disposition = if content_disposition_bytes.is_empty() { - None - } else { - Some( - utils::string_from_bytes(content_disposition_bytes).map_err(|_| { - Error::bad_database("Content Disposition in mediaid_file is invalid unicode.") - })?, - ) - }; + let content_disposition = content_disposition_bytes + .try_into() + .map_err(|_| Error::bad_database("Content Disposition in mediaid_file is invalid."))?; Ok((content_disposition, content_type, key)) } } diff --git a/src/service/media/data.rs b/src/service/media/data.rs index 75a682cb..844aa995 100644 --- a/src/service/media/data.rs +++ b/src/service/media/data.rs @@ -1,3 +1,5 @@ +use ruma::http_headers::ContentDisposition; + use crate::Result; pub trait Data: Send + Sync { @@ -6,7 +8,7 @@ pub trait Data: Send + Sync { mxc: String, width: u32, height: u32, - content_disposition: Option<&str>, + content_disposition: &ContentDisposition, content_type: Option<&str>, ) -> Result>; @@ -16,5 +18,5 @@ pub trait Data: Send + Sync { mxc: String, width: u32, height: u32, - ) -> Result<(Option, Option, Vec)>; + ) -> Result<(ContentDisposition, Option, Vec)>; } diff --git a/src/service/media/mod.rs b/src/service/media/mod.rs index 1a80400c..a7ac9d50 100644 --- a/src/service/media/mod.rs +++ b/src/service/media/mod.rs @@ -2,6 +2,7 @@ mod data; use std::io::Cursor; pub use data::Data; +use ruma::http_headers::{ContentDisposition, ContentDispositionType}; use crate::{services, Result}; use image::imageops::FilterType; @@ -12,7 +13,7 @@ use tokio::{ }; pub struct FileMeta { - pub content_disposition: Option, + pub content_disposition: ContentDisposition, pub content_type: Option, pub file: Vec, } @@ -26,14 +27,17 @@ impl Service { pub async fn create( &self, mxc: String, - content_disposition: Option<&str>, + content_disposition: Option, content_type: Option<&str>, file: &[u8], ) -> Result<()> { + let content_disposition = + content_disposition.unwrap_or(ContentDisposition::new(ContentDispositionType::Inline)); + // Width, Height = 0 if it's not a thumbnail let key = self .db - .create_file_metadata(mxc, 0, 0, content_disposition, content_type)?; + .create_file_metadata(mxc, 0, 0, &content_disposition, content_type)?; let path = services().globals.get_media_file(&key); let mut f = File::create(path).await?; @@ -46,15 +50,18 @@ impl Service { pub async fn upload_thumbnail( &self, mxc: String, - content_disposition: Option<&str>, content_type: Option<&str>, width: u32, height: u32, file: &[u8], ) -> Result<()> { - let key = - self.db - .create_file_metadata(mxc, width, height, content_disposition, content_type)?; + let key = self.db.create_file_metadata( + mxc, + width, + height, + &ContentDisposition::new(ContentDispositionType::Inline), + content_type, + )?; let path = services().globals.get_media_file(&key); let mut f = File::create(path).await?; @@ -198,7 +205,7 @@ impl Service { mxc, width, height, - content_disposition.as_deref(), + &content_disposition, content_type.as_deref(), )?;