fix: old media used spaces in content disposition without quotes

This commit is contained in:
Timo Kösters 2024-09-04 13:01:23 +02:00
parent e4d6202840
commit 3df21e8257
No known key found for this signature in database
GPG key ID: 0B25E636FBA7E4CB
2 changed files with 67 additions and 8 deletions

View file

@ -188,11 +188,11 @@ async fn get_content(
) -> Result<get_content::v1::Response, Error> { ) -> Result<get_content::v1::Response, Error> {
let mxc = format!("mxc://{}/{}", server_name, media_id); let mxc = format!("mxc://{}/{}", server_name, media_id);
if let Some(FileMeta { if let Ok(Some(FileMeta {
content_disposition, content_disposition,
content_type, content_type,
file, file,
}) = services().media.get(mxc.clone()).await? })) = services().media.get(mxc.clone()).await
{ {
Ok(get_content::v1::Response { Ok(get_content::v1::Response {
file, file,
@ -264,9 +264,9 @@ async fn get_content_as_filename(
) -> Result<get_content_as_filename::v1::Response, Error> { ) -> Result<get_content_as_filename::v1::Response, Error> {
let mxc = format!("mxc://{}/{}", server_name, media_id); let mxc = format!("mxc://{}/{}", server_name, media_id);
if let Some(FileMeta { if let Ok(Some(FileMeta {
file, content_type, .. file, content_type, ..
}) = services().media.get(mxc.clone()).await? })) = services().media.get(mxc.clone()).await
{ {
Ok(get_content_as_filename::v1::Response { Ok(get_content_as_filename::v1::Response {
file, file,
@ -348,9 +348,9 @@ async fn get_content_thumbnail(
) -> Result<get_content_thumbnail::v1::Response, Error> { ) -> Result<get_content_thumbnail::v1::Response, Error> {
let mxc = format!("mxc://{}/{}", server_name, media_id); let mxc = format!("mxc://{}/{}", server_name, media_id);
if let Some(FileMeta { if let Ok(Some(FileMeta {
file, content_type, .. file, content_type, ..
}) = services() })) = services()
.media .media
.get_thumbnail( .get_thumbnail(
mxc.clone(), mxc.clone(),
@ -361,7 +361,7 @@ async fn get_content_thumbnail(
.try_into() .try_into()
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Width is invalid."))?, .map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Width is invalid."))?,
) )
.await? .await
{ {
Ok(get_content_thumbnail::v1::Response { file, content_type }) Ok(get_content_thumbnail::v1::Response { file, content_type })
} else if server_name != services().globals.server_name() && allow_remote { } else if server_name != services().globals.server_name() && allow_remote {

View file

@ -6,6 +6,7 @@ use crate::{
SERVICES, SERVICES,
}; };
use abstraction::{KeyValueDatabaseEngine, KvTree}; use abstraction::{KeyValueDatabaseEngine, KvTree};
use base64::{engine::general_purpose, Engine};
use directories::ProjectDirs; use directories::ProjectDirs;
use lru_cache::LruCache; use lru_cache::LruCache;
@ -424,7 +425,7 @@ impl KeyValueDatabase {
} }
// If the database has any data, perform data migrations before starting // If the database has any data, perform data migrations before starting
let latest_database_version = 13; let latest_database_version = 14;
if services().users.count()? > 0 { if services().users.count()? > 0 {
// MIGRATIONS // MIGRATIONS
@ -941,6 +942,64 @@ impl KeyValueDatabase {
warn!("Migration: 12 -> 13 finished"); warn!("Migration: 12 -> 13 finished");
} }
if services().globals.database_version()? < 14 {
// Reconstruct all media using the filesystem
db.mediaid_file.clear().unwrap();
for file in fs::read_dir(services().globals.get_media_folder()).unwrap() {
let file = file.unwrap();
let mediaid = general_purpose::URL_SAFE_NO_PAD
.decode(file.file_name().into_string().unwrap())
.unwrap();
let mut parts = mediaid.rsplit(|&b| b == 0xff);
let mut removed_bytes = 0;
let content_type_bytes = parts.next().unwrap();
removed_bytes += content_type_bytes.len() + 1;
let content_disposition_bytes = parts
.next()
.ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?;
removed_bytes += content_disposition_bytes.len();
let mut content_disposition =
utils::string_from_bytes(content_disposition_bytes).map_err(|_| {
Error::bad_database("Content Disposition in mediaid_file is invalid.")
})?;
if content_disposition.contains("filename=")
&& !content_disposition.contains("filename=\"")
{
println!("{}", &content_disposition);
content_disposition =
content_disposition.replacen("filename=", "filename=\"", 1);
content_disposition.push('"');
println!("{}", &content_disposition);
let mut new_key = mediaid[..(mediaid.len() - removed_bytes)].to_vec();
assert!(*new_key.last().unwrap() == 0xff);
new_key.extend_from_slice(content_disposition.to_string().as_bytes());
new_key.push(0xff);
new_key.extend_from_slice(content_type_bytes);
// Some file names are too long. Ignore those.
let _ = fs::rename(
services().globals.get_media_file(&mediaid),
services().globals.get_media_file(&new_key),
);
db.mediaid_file.insert(&new_key, &[])?;
} else {
db.mediaid_file.insert(&mediaid, &[])?;
}
}
services().globals.bump_database_version(14)?;
warn!("Migration: 13 -> 14 finished");
}
assert_eq!( assert_eq!(
services().globals.database_version().unwrap(), services().globals.database_version().unwrap(),
latest_database_version latest_database_version