diff --git a/README.md b/README.md index 11e61e441e7303e6b0882e12039769fea1a00fcf..ebfc472c5e199049f9122d4703ad9dcbccfa8596 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ You can find everything you need at: [l10n.gnome.org/module/PasswordSafe/](https # Data protection Please be careful when using development versions. Create enough backups if you're using a production database with a Password Safe development version. It is possible that data loss will occur, though I give my best that this will never happen. -Development versions create a backup of your database on unlocking by default. These can be found at ```~/.cache/passwordsafe/backup/``` where every backup is named by database name and date. If you don't want this behavior you can turn it off via dconf: +Development versions create a backup of your database on unlocking by default. These can be found at ```$XDG_CACHE_HOME/passwordsafe/backup/``` (or `~/.var/app/org.gnome.PasswordSafe/cache/passwordsafe/backup` for Flatpak users) where every backup is named by database name and date. If you don't want this behavior you can turn it off via dconf: ``` gsettings set org.gnome.PasswordSafe development-backup-mode false ``` diff --git a/flatpak/org.gnome.PasswordSafe.json b/flatpak/org.gnome.PasswordSafe.json index a546e4d132149527b204fc6182ac0d0c8b337fa1..8f1c41b4d8387b383a262d0778962e27c5a144c2 100644 --- a/flatpak/org.gnome.PasswordSafe.json +++ b/flatpak/org.gnome.PasswordSafe.json @@ -15,7 +15,6 @@ "--socket=fallback-x11", "--socket=wayland", "--filesystem=xdg-run/gvfs", - "--filesystem=/tmp", "--metadata=X-DConf=migrate-path=/org/gnome/PasswordSafeDevel/", "--talk-name=org.gtk.vfs", "--talk-name=org.gtk.vfs.*" diff --git a/passwordsafe/attachment_warning_dialog.py b/passwordsafe/attachment_warning_dialog.py index 079da0c25576dfb4e22f732e0291d6268f20446b..ef5a141e8cbbeb817c3dd7955bab85119dc28df2 100644 --- a/passwordsafe/attachment_warning_dialog.py +++ b/passwordsafe/attachment_warning_dialog.py @@ -1,10 +1,11 @@ # SPDX-License-Identifier: GPL-3.0-only from __future__ import annotations -import subprocess +import logging +import os import typing -from gi.repository import Gio, GLib, Gtk +from gi.repository import Gdk, Gio, GLib, Gtk if typing.TYPE_CHECKING: from pykeepass.attachment import Attachment @@ -22,6 +23,7 @@ class AttachmentWarningDialog(Gtk.MessageDialog): :param entry_page: entry page """ super().__init__() + self.__unlocked_database = entry_page.unlocked_database self.__attachment = attachment @@ -43,8 +45,22 @@ class AttachmentWarningDialog(Gtk.MessageDialog): ) def __open_tmp_file(self, bytes_buffer, filename): - (file, stream) = Gio.File.new_tmp(filename + ".XXXXXX") - stream.get_output_stream().write_bytes(GLib.Bytes.new(bytes_buffer)) - stream.close() - self.__unlocked_database.scheduled_tmpfiles_deletion.append(file) - subprocess.run(["xdg-open", file.get_path()], check=True) + try: + cache_dir = os.path.join( + GLib.get_user_cache_dir(), "passwordsafe", "tmp" + ) + file_path = os.path.join(cache_dir, filename) + if not os.path.exists(cache_dir): + os.makedirs(cache_dir) + + gfile = Gio.File.new_for_path(file_path) + output_stream = gfile.replace( + None, False, + Gio.FileCreateFlags.PRIVATE + | Gio.FileCreateFlags.REPLACE_DESTINATION, None + ) + output_stream.write_bytes(GLib.Bytes.new(bytes_buffer)) + output_stream.close() + Gtk.show_uri_on_window(None, gfile.get_uri(), Gdk.CURRENT_TIME) + except GLib.Error as err: + logging.debug("Could not load attachment %s: %s", filename, err) diff --git a/passwordsafe/unlock_database.py b/passwordsafe/unlock_database.py index 05d30619b4a20d8b7aff8e25da6a0728079db894..d1528b2ccad62b8e65e23d305e0714569a4499ba 100644 --- a/passwordsafe/unlock_database.py +++ b/passwordsafe/unlock_database.py @@ -430,7 +430,9 @@ class UnlockDatabase: passwordsafe.config_manager.set_last_opened_database(opened.get_uri()) if passwordsafe.config_manager.get_development_backup_mode(): - cache_dir = os.path.expanduser("~") + "/.cache/passwordsafe/backup" + cache_dir = os.path.join( + GLib.get_user_cache_dir(), "passwordsafe", "backup" + ) if not os.path.exists(cache_dir): os.makedirs(cache_dir) diff --git a/passwordsafe/unlocked_database.py b/passwordsafe/unlocked_database.py index d287214b7ce320e07713cf7efcec95119189cc32..feeed621c5592eeaad04cf91d4cacf4ff2d19ace 100644 --- a/passwordsafe/unlocked_database.py +++ b/passwordsafe/unlocked_database.py @@ -1,6 +1,8 @@ # SPDX-License-Identifier: GPL-3.0-only from __future__ import annotations +import os +import shutil import logging import threading import typing @@ -48,7 +50,6 @@ class UnlockedDatabase(GObject.GObject): # Objects builder = NotImplemented - scheduled_tmpfiles_deletion: list[Gio.File] = [] clipboard = NotImplemented clipboard_timer_handler: int | None = None _current_element: SafeElement | None = None @@ -528,18 +529,7 @@ class UnlockedDatabase(GObject.GObject): def _on_database_lock_changed(self, _database_manager, _value): locked = self.database_manager.props.locked if locked: - self.cleanup(False) - - for tmpfile in self.scheduled_tmpfiles_deletion: - try: - tmpfile.delete() - except GLib.Error as exc: - logging.warning( - "Skipping deletion of tmpfile %s: %s", - tmpfile.get_path(), - exc.message, - ) - + self.cleanup() if passwordsafe.config_manager.get_save_automatically(): self.save_database() @@ -560,13 +550,12 @@ class UnlockedDatabase(GObject.GObject): # Helper Methods # - def cleanup(self, delete_tmp_file: bool = True) -> None: + def cleanup(self) -> None: """Stop all ongoing operations: * stop the save loop * cancel all timers * unregistrer from dbus - * delete all temporary file is delete_tmp_file is True :param bool show_save_dialog: chooe to delete temporary files """ @@ -590,14 +579,9 @@ class UnlockedDatabase(GObject.GObject): GLib.source_remove(self.save_loop) self.save_loop = None - if not delete_tmp_file: - return - - for tmpfile in self.scheduled_tmpfiles_deletion: - try: - tmpfile.delete() - except Gio.Error: - logging.warning("Skipping deletion of tmpfile...") + # Cleanup temporal files created when opening attachments. + cache_dir = os.path.join(GLib.get_user_cache_dir(), "passwordsafe", "tmp") + shutil.rmtree(cache_dir, ignore_errors=True) def save_database(self, notification: bool = False) -> None: """Save the database.