diff --git a/src/client_server/media.rs b/src/client_server/media.rs index 0c23488428c409814134e2b821e7e58f10a0fe2f..e6bd182b981189a854fc6e923b335a67c846c05a 100644 --- a/src/client_server/media.rs +++ b/src/client_server/media.rs @@ -66,7 +66,7 @@ pub async fn get_content_route( { Ok(get_content::Response { file, - content_type: Some(content_type), + content_type, content_disposition: filename, } .into()) @@ -116,11 +116,7 @@ pub async fn get_content_thumbnail_route( .try_into() .map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Width is invalid."))?, )? { - Ok(get_content_thumbnail::Response { - file, - content_type: Some(content_type), - } - .into()) + Ok(get_content_thumbnail::Response { file, content_type }.into()) } else if &*body.server_name != db.globals.server_name() && body.allow_remote { let get_thumbnail_response = server_server::send_request( &db.globals, diff --git a/src/client_server/membership.rs b/src/client_server/membership.rs index 849fb7e2a38bc49d9f7eb4f500df95257fc5ceff..47fcde1ae94001d3a9917b0ed1ceab05cdf7bf7b 100644 --- a/src/client_server/membership.rs +++ b/src/client_server/membership.rs @@ -510,8 +510,7 @@ async fn join_room_by_id_helper( .expect("event is valid, we just created it"), ); - // TODO fixup CanonicalJsonValue - // use that instead of serde_json::Map... maybe? + // Convert `serde_json;:Value` to `CanonicalJsonObj` for hashing/signing let mut canon_json_stub: BTreeMap<_, ruma::signatures::CanonicalJsonValue> = serde_json::from_value(join_event_stub_value).expect("json Value is canonical JSON"); diff --git a/src/database/media.rs b/src/database/media.rs index bfc6207874dee888002ee2e655fe2b3bb91be1b1..89d48e16f2f8880cd32791443987c98f8db4d821 100644 --- a/src/database/media.rs +++ b/src/database/media.rs @@ -5,7 +5,7 @@ pub struct FileMeta { pub filename: Option<String>, - pub content_type: String, + pub content_type: Option<String>, pub file: Vec<u8>, } @@ -83,12 +83,14 @@ pub fn get(&self, mxc: &str) -> Result<Option<FileMeta>> { let (key, file) = r?; let mut parts = key.rsplit(|&b| b == 0xff); - let content_type = utils::string_from_bytes( - parts - .next() - .ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?, - ) - .map_err(|_| Error::bad_database("Content type in mediaid_file is invalid unicode."))?; + let content_type = parts + .next() + .map(|bytes| { + Ok::<_, Error>(utils::string_from_bytes(bytes).map_err(|_| { + Error::bad_database("Content type in mediaid_file is invalid unicode.") + })?) + }) + .transpose()?; let filename_bytes = parts .next() @@ -158,12 +160,14 @@ pub fn get_thumbnail(&self, mxc: String, width: u32, height: u32) -> Result<Opti let (key, file) = r?; let mut parts = key.rsplit(|&b| b == 0xff); - let content_type = utils::string_from_bytes( - parts - .next() - .ok_or_else(|| Error::bad_database("Invalid Media ID in db"))?, - ) - .map_err(|_| Error::bad_database("Content type in mediaid_file is invalid unicode."))?; + let content_type = parts + .next() + .map(|bytes| { + Ok::<_, Error>(utils::string_from_bytes(bytes).map_err(|_| { + Error::bad_database("Content type in mediaid_file is invalid unicode.") + })?) + }) + .transpose()?; let filename_bytes = parts .next() @@ -189,12 +193,14 @@ pub fn get_thumbnail(&self, mxc: String, width: u32, height: u32) -> Result<Opti let (key, file) = r?; let mut parts = key.rsplit(|&b| b == 0xff); - let content_type = utils::string_from_bytes( - parts - .next() - .ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?, - ) - .map_err(|_| Error::bad_database("Content type in mediaid_file is invalid unicode."))?; + let content_type = parts + .next() + .map(|bytes| { + Ok::<_, Error>(utils::string_from_bytes(bytes).map_err(|_| { + Error::bad_database("Content type in mediaid_file is invalid unicode.") + })?) + }) + .transpose()?; let filename_bytes = parts .next() diff --git a/src/database/rooms.rs b/src/database/rooms.rs index 3d5b890b890fc73d39e359fc1d73f8d9fe7b76a2..a95587cc27b5bba8f572cedf78ea66fbff2caee3 100644 --- a/src/database/rooms.rs +++ b/src/database/rooms.rs @@ -499,7 +499,6 @@ pub fn replace_pdu_leaves(&self, room_id: &RoomId, event_id: &EventId) -> Result Ok(()) } - #[allow(clippy::too_many_arguments)] /// Creates a new persisted data unit and adds it to a room. /// /// By this point the incoming event should be fully authenticated, no auth happens @@ -856,9 +855,8 @@ pub fn build_and_append_pdu( }; // Hash and sign - let mut pdu_json: BTreeMap<String, ruma::serde::CanonicalJsonValue> = - serde_json::from_value(serde_json::json!(&pdu)) - .expect("event is valid, we just created it"); + let mut pdu_json = + utils::to_canonical_object(&pdu).expect("event is valid, we just created it"); pdu_json.remove("event_id"); diff --git a/src/utils.rs b/src/utils.rs index edcf48a10470115954fed196e67a6a08115d5650..c82e6feb8f26ebc1924053227a1b02cf7b7a55a2 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,6 +1,7 @@ use argon2::{Config, Variant}; use cmp::Ordering; use rand::prelude::*; +use ruma::serde::{try_from_json_map, CanonicalJsonError, CanonicalJsonObject}; use sled::IVec; use std::{ cmp, @@ -94,3 +95,19 @@ pub fn common_elements( .all(|b| b) })) } + +/// Fallible conversion from any value that implements `Serialize` to a `CanonicalJsonObject`. +/// +/// `value` must serialize to an `serde_json::Value::Object`. +pub fn to_canonical_object<T: serde::Serialize>( + value: T, +) -> Result<CanonicalJsonObject, CanonicalJsonError> { + use serde::ser::Error; + + match serde_json::to_value(value).map_err(CanonicalJsonError::SerDe)? { + serde_json::Value::Object(map) => try_from_json_map(map), + _ => Err(CanonicalJsonError::SerDe(serde_json::Error::custom( + "Value must be an object", + ))), + } +}