Skip to content

Commit

Permalink
fix(ffi): Generate correct temporary file names for media attachments
Browse files Browse the repository at this point in the history
  • Loading branch information
stefanceriu committed Apr 30, 2023
1 parent 034aa04 commit d4f2149
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 11 deletions.
8 changes: 7 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions bindings/matrix-sdk-ffi/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ impl Client {
pub fn get_media_file(
&self,
media_source: Arc<MediaSource>,
body: Option<String>,
mime_type: String,
) -> Result<Arc<MediaFileHandle>, ClientError> {
let client = self.client.clone();
Expand All @@ -206,6 +207,7 @@ impl Client {
.media()
.get_media_file(
&MediaRequest { source, format: MediaFormat::File },
body,
&mime_type,
true,
)
Expand Down
2 changes: 1 addition & 1 deletion crates/matrix-sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ matrix-sdk-common = { version = "0.6.0", path = "../matrix-sdk-common" }
matrix-sdk-indexeddb = { version = "0.2.0", path = "../matrix-sdk-indexeddb", default-features = false, optional = true }
matrix-sdk-sled = { version = "0.2.0", path = "../matrix-sdk-sled", default-features = false, optional = true }
mime = "0.3.16"
mime_guess = "2.0.4"
mime2ext = "0.1.52"
once_cell = { workspace = true }
pin-project-lite = "0.2.9"
rand = { version = "0.8.5", optional = true }
Expand Down
54 changes: 45 additions & 9 deletions crates/matrix-sdk/src/media.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
use std::io::Read;
#[cfg(not(target_arch = "wasm32"))]
use std::path::Path;
use std::time::Duration;
use std::{fs::File, time::Duration};

pub use matrix_sdk_base::media::*;
use mime::Mime;
#[cfg(not(target_arch = "wasm32"))]
use mime_guess;
use mime2ext;
use ruma::{
api::client::media::{create_content, get_content, get_content_thumbnail},
assign,
Expand Down Expand Up @@ -140,19 +140,55 @@ impl Media {
pub async fn get_media_file(
&self,
request: &MediaRequest,
body: Option<String>,
content_type: &Mime,
use_cache: bool,
) -> Result<MediaFileHandle> {
let data = self.get_media_content(request, use_cache).await?;

let mut suffix = String::from("");
if let Some(extension) =
mime_guess::get_mime_extensions(content_type).and_then(|a| a.first())
{
suffix = String::from(".") + extension;
}
let inferred_extension = mime2ext::mime2ext(content_type);

let body_path = body.as_ref().map(Path::new);
let filename = body_path.and_then(|f| f.file_name().and_then(|f| f.to_str()));
let filename_with_extension = body_path.and_then(|f| {
if f.extension().is_some() {
f.file_name().and_then(|f| f.to_str())
} else {
None
}
});

let file = match (filename, filename_with_extension, inferred_extension) {
// If the body is a file name and has an extension use that
(Some(_), Some(filename_with_extension), Some(_)) => {
// We're potentially using the same file name multiple times
// which might lead to tempfile() failing. Use `make` instead
// to avoid that
TempFileBuilder::new()
.prefix(filename_with_extension)
.rand_bytes(0)
.make(|path| File::create(path))?
}
// If the body is a file name but doesn't have an extension try inferring one for it
(Some(filename), None, Some(inferred_extension)) => {
// We're potentially using the same file name multiple times
// which might lead to tempfile() failing. Use `make` instead
// to avoid that
TempFileBuilder::new()
.prefix(filename)
.suffix(&(".".to_string() + inferred_extension))
.rand_bytes(0)
.make(|path| File::create(path))?
}
// If the only thing we have is an inferred extension then use that together with a
// randomly generated file name
(None, None, Some(inferred_extension)) => TempFileBuilder::new()
.suffix(&&(".".to_string() + inferred_extension))
.tempfile()?,
// Otherwise just use a completely random file name
_ => TempFileBuilder::new().tempfile()?,
};

let file = TempFileBuilder::new().suffix(&suffix).tempfile()?;
TokioFile::from_std(file.reopen()?).write_all(&data).await?;

Ok(MediaFileHandle { file })
Expand Down

0 comments on commit d4f2149

Please sign in to comment.