mirror of
https://github.com/chatmail/core.git
synced 2026-04-28 02:46:29 +03:00
Fix long filenames containing dots (#3098)
This commit is contained in:
@@ -18,6 +18,8 @@
|
||||
- keep track of securejoin joiner status in database to survive restarts #2920
|
||||
- remove never used `SentboxMove` option #3111
|
||||
|
||||
### Fixes
|
||||
- Fix a bug where sometimes the file extension of a long filename containing a dot was cropped #3098
|
||||
|
||||
## 1.76.0
|
||||
|
||||
|
||||
19
src/blob.rs
19
src/blob.rs
@@ -345,13 +345,30 @@ impl<'a> BlobObject<'a> {
|
||||
};
|
||||
|
||||
let clean = sanitize_filename::sanitize_with_options(name, opts);
|
||||
// Let's take the tricky filename
|
||||
// "file.with_lots_of_characters_behind_point_and_double_ending.tar.gz" as an example.
|
||||
// Split it into "file" and "with_lots_of_characters_behind_point_and_double_ending.tar.gz":
|
||||
let mut iter = clean.splitn(2, '.');
|
||||
|
||||
let stem: String = iter.next().unwrap_or_default().chars().take(64).collect();
|
||||
let ext: String = iter.next().unwrap_or_default().chars().take(32).collect();
|
||||
// stem == "file"
|
||||
|
||||
let ext_chars = iter.next().unwrap_or_default().chars();
|
||||
let ext: String = ext_chars
|
||||
.rev()
|
||||
.take(32)
|
||||
.collect::<Vec<_>>()
|
||||
.iter()
|
||||
.rev()
|
||||
.collect();
|
||||
// ext == "d_point_and_double_ending.tar.gz"
|
||||
|
||||
if ext.is_empty() {
|
||||
(stem, "".to_string())
|
||||
} else {
|
||||
(stem, format!(".{}", ext).to_lowercase())
|
||||
// Return ("file", ".d_point_and_double_ending.tar.gz")
|
||||
// which is not perfect but acceptable.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2333,6 +2333,9 @@ async fn add_or_lookup_contact_by_addr(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use async_std::fs::{self, File};
|
||||
use async_std::io::WriteExt;
|
||||
|
||||
use super::*;
|
||||
|
||||
use crate::chat::get_chat_contacts;
|
||||
@@ -2340,7 +2343,7 @@ mod tests {
|
||||
use crate::chatlist::Chatlist;
|
||||
use crate::constants::{DC_CONTACT_ID_INFO, DC_GCL_NO_SPECIALS};
|
||||
use crate::message::Message;
|
||||
use crate::test_utils::{get_chat_msg, TestContext};
|
||||
use crate::test_utils::{get_chat_msg, TestContext, TestContextManager};
|
||||
|
||||
#[test]
|
||||
fn test_hex_hash() {
|
||||
@@ -4968,4 +4971,59 @@ Reply from different address
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_long_filenames() -> Result<()> {
|
||||
let mut tcm = TestContextManager::new().await;
|
||||
let alice = tcm.alice().await;
|
||||
let bob = tcm.bob().await;
|
||||
|
||||
for filename_sent in &[
|
||||
"foo.bar very long file name test baz.tar.gz",
|
||||
"foobarabababababababbababababverylongfilenametestbaz.tar.gz",
|
||||
"fooo...tar.gz",
|
||||
"foo. .tar.gz",
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.tar.gz",
|
||||
"a.tar.gz",
|
||||
"a.a..a.a.a.a.tar.gz",
|
||||
] {
|
||||
let attachment = alice.blobdir.join(filename_sent);
|
||||
let content = format!("File content of {}", filename_sent);
|
||||
File::create(&attachment)
|
||||
.await?
|
||||
.write_all(content.as_bytes())
|
||||
.await?;
|
||||
|
||||
let mut msg_alice = Message::new(Viewtype::File);
|
||||
msg_alice.set_file(attachment.to_str().unwrap(), None);
|
||||
let alice_chat = alice.create_chat(&bob).await;
|
||||
let sent = alice.send_msg(alice_chat.id, &mut msg_alice).await;
|
||||
println!("{}", sent.payload());
|
||||
|
||||
bob.recv_msg(&sent).await;
|
||||
let msg_bob = bob.get_last_msg().await;
|
||||
|
||||
async fn check_message(msg: &Message, t: &TestContext, content: &str) {
|
||||
assert_eq!(msg.get_viewtype(), Viewtype::File);
|
||||
let resulting_filename = msg.get_filename().unwrap();
|
||||
let path = msg.get_file(t).unwrap();
|
||||
assert!(
|
||||
resulting_filename.ends_with(".tar.gz"),
|
||||
"{:?} doesn't end with .tar.gz, path: {:?}",
|
||||
resulting_filename,
|
||||
path
|
||||
);
|
||||
assert!(
|
||||
path.to_str().unwrap().ends_with(".tar.gz"),
|
||||
"path {:?} doesn't end with .tar.gz",
|
||||
path
|
||||
);
|
||||
assert_eq!(fs::read_to_string(path).await.unwrap(), content);
|
||||
}
|
||||
check_message(&msg_alice, &alice, &content).await;
|
||||
check_message(&msg_bob, &bob, &content).await;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user