mirror of
https://github.com/chatmail/core.git
synced 2026-04-05 23:22:11 +03:00
feat: Store blobs in subdirs with random names (#4309)
Recently there was an accident with a chatbot that replaced its avatar set from the command line with an unrelated avatar of a contact. Both the `selfavatar` setting and the contact avatar `i` param pointed to `$BLOBDIR/avatar.png` at the time it was detected. How this happened is unclear, but it is possible that `avatar.png` was removed, unmounted or otherwise not detected by the core, and the core stored avatar received from the contact as `avatar.png`, while `selfavatar` config still pointed to `$BLOBDIR/avatar.png`. Such bugs are unavoidable even if the core itself has no bugs as we cannot rely on blobdir not reside on the faulty network filesystem, being incorrectly backed up and restored etc., so we should assume that files may be randomly removed. Then there may be dangling `$BLOBDIR/...` references in the database which may accidentally point to unrelated files, could even be an `avatar.png` file sent to the bot in private. To prevent such bugs, store blobs in blobdir subdirs with random names. Also this helps when we receive multiple attachments having the same name -- before, random filename suffixes were added to subsequent attachments, now attachments preserve their filenames which is important if they are opened in external programs.
This commit is contained in:
@@ -108,7 +108,7 @@ class Message:
|
||||
|
||||
@props.with_doc
|
||||
def filename(self):
|
||||
"""filename if there was an attachment, otherwise empty string."""
|
||||
"""file path if there was an attachment, otherwise empty string."""
|
||||
return from_dc_charpointer(lib.dc_msg_get_file(self._dc_msg))
|
||||
|
||||
def set_file(self, path, mime_type=None):
|
||||
@@ -121,7 +121,6 @@ class Message:
|
||||
@props.with_doc
|
||||
def basename(self) -> str:
|
||||
"""basename of the attachment if it exists, otherwise empty string."""
|
||||
# FIXME, it does not return basename
|
||||
return from_dc_charpointer(lib.dc_msg_get_filename(self._dc_msg))
|
||||
|
||||
@props.with_doc
|
||||
|
||||
@@ -181,14 +181,12 @@ def test_send_file_twice_unicode_filename_mangling(tmp_path, acfactory, lp):
|
||||
msg = send_and_receive_message()
|
||||
assert msg.text == "withfile"
|
||||
assert open(msg.filename).read() == "some data"
|
||||
msg.filename.index(basename)
|
||||
assert msg.filename.endswith(ext)
|
||||
assert msg.filename.endswith(basename + ext)
|
||||
|
||||
msg2 = send_and_receive_message()
|
||||
assert msg2.text == "withfile"
|
||||
assert open(msg2.filename).read() == "some data"
|
||||
msg2.filename.index(basename)
|
||||
assert msg2.filename.endswith(ext)
|
||||
assert msg2.filename.endswith(basename + ext)
|
||||
assert msg.filename != msg2.filename
|
||||
|
||||
|
||||
@@ -214,8 +212,7 @@ def test_send_file_html_attachment(tmp_path, acfactory, lp):
|
||||
msg = ac2.get_message_by_id(ev.data2)
|
||||
|
||||
assert open(msg.filename).read() == content
|
||||
msg.filename.index(basename)
|
||||
assert msg.filename.endswith(ext)
|
||||
assert msg.filename.endswith(basename + ext)
|
||||
|
||||
|
||||
def test_html_message(acfactory, lp):
|
||||
|
||||
@@ -50,8 +50,8 @@ class TestOnlineInCreation:
|
||||
src = tmp_path / "file.txt"
|
||||
src.write_text("hello there\n")
|
||||
msg = chat.send_file(str(src))
|
||||
assert msg.filename.startswith(os.path.join(ac1.get_blobdir(), "file"))
|
||||
assert msg.filename.endswith(".txt")
|
||||
assert msg.filename.startswith(ac1.get_blobdir())
|
||||
assert msg.filename.endswith("file.txt")
|
||||
|
||||
def test_forward_increation(self, acfactory, data, lp):
|
||||
ac1, ac2 = acfactory.get_online_accounts(2)
|
||||
|
||||
Reference in New Issue
Block a user