Skip to content

Commit

Permalink
feat: Store blobs in subdirs with random names (#4309)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
iequidoo committed Oct 5, 2024
1 parent b7be0b7 commit d2e299d
Show file tree
Hide file tree
Showing 11 changed files with 234 additions and 211 deletions.
3 changes: 1 addition & 2 deletions python/src/deltachat/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def set_html(self, html_text):

@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):
Expand All @@ -121,7 +121,6 @@ def set_file(self, path, mime_type=None):
@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
Expand Down
9 changes: 3 additions & 6 deletions python/tests/test_1_online.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,14 +181,12 @@ def send_and_receive_message():
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


Expand All @@ -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):
Expand Down
4 changes: 2 additions & 2 deletions python/tests/test_2_increation.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ def test_no_increation_copies_to_blobdir(self, tmp_path, acfactory, lp):
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)
Expand Down
Loading

0 comments on commit d2e299d

Please sign in to comment.