From c7bc454e7c553b0e47013199a372572d6e72f72f Mon Sep 17 00:00:00 2001 From: Maximiliano Sandoval R Date: Thu, 4 Feb 2021 19:28:31 +0100 Subject: [PATCH 1/3] attachment_warning: Use sandboxed tmp --- passwordsafe/attachment_warning_dialog.py | 31 ++++++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/passwordsafe/attachment_warning_dialog.py b/passwordsafe/attachment_warning_dialog.py index 079da0c25..c58780b16 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,23 @@ 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() + self.__unlocked_database.scheduled_tmpfiles_deletion.append(gfile) + 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) -- GitLab From 732cd58c3ce93345760b08b4ecd0318c913173d2 Mon Sep 17 00:00:00 2001 From: Maximiliano Sandoval R Date: Thu, 4 Feb 2021 19:53:39 +0100 Subject: [PATCH 2/3] unlocked_db: Clear tmp files in a simpler way When using the local cache we can just delete the entire directory. There is no need to use /tmp anymore. --- flatpak/org.gnome.PasswordSafe.json | 1 - passwordsafe/attachment_warning_dialog.py | 1 - passwordsafe/unlocked_database.py | 30 ++++++----------------- 3 files changed, 7 insertions(+), 25 deletions(-) diff --git a/flatpak/org.gnome.PasswordSafe.json b/flatpak/org.gnome.PasswordSafe.json index a546e4d13..8f1c41b4d 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 c58780b16..ef5a141e8 100644 --- a/passwordsafe/attachment_warning_dialog.py +++ b/passwordsafe/attachment_warning_dialog.py @@ -61,7 +61,6 @@ class AttachmentWarningDialog(Gtk.MessageDialog): ) output_stream.write_bytes(GLib.Bytes.new(bytes_buffer)) output_stream.close() - self.__unlocked_database.scheduled_tmpfiles_deletion.append(gfile) 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/unlocked_database.py b/passwordsafe/unlocked_database.py index d287214b7..feeed621c 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. -- GitLab From d7badf0cd2f4601db2d9818748cf8ed46121fb61 Mon Sep 17 00:00:00 2001 From: Maximiliano Sandoval R Date: Thu, 4 Feb 2021 20:24:07 +0100 Subject: [PATCH 3/3] unlock_database: Store backups in user's cache --- README.md | 2 +- passwordsafe/unlock_database.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 11e61e441..ebfc472c5 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/passwordsafe/unlock_database.py b/passwordsafe/unlock_database.py index 05d30619b..d1528b2cc 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) -- GitLab