rewrite media key parser

Fixes a regression in e2cba15ed2 where the
Content-Type and Content-Disposition parts are extracted in the wrong
order.

Fixes a long-standing issue in b6d721374f
where the Content-Type part was allowed to be completely missing rather
than present and 0 bytes long.

Improves the error messages for various parsing failures to be unique
and more obvious.
This commit is contained in:
Charles Hall 2024-09-19 13:38:41 -07:00
parent 88b009a8d4
commit d388994657
No known key found for this signature in database
GPG key ID: 7B8E0645816E07CF

View file

@ -26,57 +26,67 @@ impl TryFrom<&MediaFileKey> for MediaFileKeyParts {
fn try_from(key: &MediaFileKey) -> Result<MediaFileKeyParts> {
let mut parts = key.as_bytes().split(|&b| b == 0xFF);
// Extract parts
let mxc_bytes = parts
.next()
.ok_or_else(|| Error::BadDatabase("Media ID in db is invalid."))?;
.ok_or_else(|| Error::BadDatabase("Missing MXC URI bytes"))?;
let thumbnail_size_bytes = parts.next().ok_or_else(|| {
Error::BadDatabase("Missing thumbnail size bytes")
})?;
let content_disposition_bytes = parts.next().ok_or_else(|| {
Error::BadDatabase("Missing Content-Disposition bytes")
})?;
let content_type_bytes = parts
.next()
.ok_or_else(|| Error::BadDatabase("Missing Content-Type bytes"))?;
if parts.next().is_some() {
return Err(Error::BadDatabase("Too many parts"));
}
// Parse parts
let mxc = utils::string_from_bytes(mxc_bytes)
.map_err(|_| {
Error::BadDatabase("Media MXC URI in db is invalid unicode.")
})?
.map_err(|_| Error::BadDatabase("Invalid unicode in MXC URI"))?
.into();
let thumbnail_size_bytes = parts
.next()
.ok_or_else(|| Error::BadDatabase("Media ID in db is invalid."))?;
let thumbnail_size_bytes: &[u8; 8] =
thumbnail_size_bytes.try_into().map_err(|_| {
Error::BadDatabase("Media ID thumbnail size in db is invalid")
})?;
let width = u32::from_be_bytes(
thumbnail_size_bytes[..4].try_into().expect("should be 4 bytes"),
);
let height = u32::from_be_bytes(
thumbnail_size_bytes[4..].try_into().expect("should be 4 bytes"),
);
let (width, height) = <&[u8; 8]>::try_from(thumbnail_size_bytes)
.map(|eight_bytes| {
let width = u32::from_be_bytes(
eight_bytes[..4].try_into().expect("should be 4 bytes"),
);
let height = u32::from_be_bytes(
eight_bytes[4..].try_into().expect("should be 4 bytes"),
);
let content_type = parts
.next()
.map(|bytes| {
utils::string_from_bytes(bytes).map_err(|_| {
Error::BadDatabase(
"Content type in mediaid_file is invalid unicode.",
)
})
(width, height)
})
.transpose()?;
let content_disposition_bytes = parts
.next()
.ok_or_else(|| Error::BadDatabase("Media ID in db is invalid."))?;
.map_err(|_| {
Error::BadDatabase("Wrong number of thumbnail size bytes")
})?;
let content_disposition = if content_disposition_bytes.is_empty() {
None
} else {
Some(utils::string_from_bytes(content_disposition_bytes).map_err(
|_| {
Error::BadDatabase(
"Content Disposition in mediaid_file is invalid \
unicode.",
)
Error::BadDatabase("Invalid unicode in Content-Disposition")
},
)?)
};
let content_type = if content_type_bytes.is_empty() {
None
} else {
Some(utils::string_from_bytes(content_type_bytes).map_err(
|_| Error::BadDatabase("Invalid unicode in Content-Type"),
)?)
};
Ok(MediaFileKeyParts {
mxc,
width,