diff --git a/dangerzone/container.py b/dangerzone/container.py index 053371f..8eaf7fa 100644 --- a/dangerzone/container.py +++ b/dangerzone/container.py @@ -282,6 +282,9 @@ def convert( ) shutil.move(container_output_filename, document.output_filename) + if document.archive_after_conversion: + document.archive() + # We did it success = True diff --git a/dangerzone/document.py b/dangerzone/document.py index acd056b..955f6f2 100644 --- a/dangerzone/document.py +++ b/dangerzone/document.py @@ -13,6 +13,7 @@ import appdirs from . import errors SAFE_EXTENSION = "-safe.pdf" +ARCHIVE_SUBDIR = "unsafe" log = logging.getLogger(__name__) @@ -35,12 +36,14 @@ class Document: input_filename: str = None, output_filename: str = None, suffix: str = SAFE_EXTENSION, + archive: bool = False, ) -> None: # NOTE: See https://github.com/freedomofpress/dangerzone/pull/216#discussion_r1015449418 self.id = secrets.token_urlsafe(6)[0:6] self._input_filename: Optional[str] = None self._output_filename: Optional[str] = None + self._archive = False self._suffix = suffix if input_filename: @@ -51,6 +54,8 @@ class Document: self.state = Document.STATE_UNCONVERTED + self.archive_after_conversion = archive + @staticmethod def normalize_filename(filename: str) -> str: return os.path.abspath(filename) @@ -113,6 +118,33 @@ class Document: else: raise errors.SuffixNotApplicableException() + @property + def archive_after_conversion(self) -> bool: + return self._archive + + @archive_after_conversion.setter + def archive_after_conversion(self, enabled: bool) -> None: + if enabled: + self._archive = True + else: + self._archive = False + + def archive(self) -> None: + """ + Moves the original document to a subdirectory. Prevents the user from + mistakenly opening the unsafe (original) document. + """ + archive_dir = self.default_archive_dir + old_file_path = Path(self.input_filename) + new_file_path = archive_dir / old_file_path.name + log.debug(f"Archiving doc {self.id} to {new_file_path}") + Path.mkdir(archive_dir, exist_ok=True) + old_file_path.rename(new_file_path) + + @property + def default_archive_dir(self) -> Path: + return Path(self.input_filename).parent / ARCHIVE_SUBDIR + @property def default_output_filename(self) -> str: return f"{os.path.splitext(self.input_filename)[0]}{self.suffix}" diff --git a/dangerzone/gui/main_window.py b/dangerzone/gui/main_window.py index 85f5793..d08c332 100644 --- a/dangerzone/gui/main_window.py +++ b/dangerzone/gui/main_window.py @@ -355,9 +355,8 @@ class SettingsWidget(QtWidgets.QWidget): save_group_box_layout.setContentsMargins(20, 0, 0, 0) save_group_box_layout.addWidget(save_group_box) self.radio_move_untrusted = QtWidgets.QRadioButton( - "Move unsafe PDFs to 'unsafe' subdirectory" + "Move original documents to 'unsafe' subdirectory" ) - self.radio_move_untrusted.setChecked(True) save_group_box_innner_layout.addWidget(self.radio_move_untrusted) self.radio_save_to = QtWidgets.QRadioButton() self.save_label.clicked.connect( @@ -433,6 +432,11 @@ class SettingsWidget(QtWidgets.QWidget): else: self.safe_extension.setText(SAFE_EXTENSION) + if self.dangerzone.settings.get("archive"): + self.radio_move_untrusted.setChecked(True) + else: + self.radio_save_to.setChecked(True) + if self.dangerzone.settings.get("ocr"): self.ocr_checkbox.setCheckState(QtCore.Qt.Checked) else: @@ -524,23 +528,29 @@ class SettingsWidget(QtWidgets.QWidget): self.save_location.setText(selected_dir) def start_button_clicked(self) -> None: - if self.save_checkbox.checkState() == QtCore.Qt.Unchecked: - # If not saving, then save it to a temp file instead - for document in self.dangerzone.get_unconverted_documents(): + for document in self.dangerzone.get_unconverted_documents(): + if self.save_checkbox.isChecked(): + # If we're saving the document, set the suffix that the user chose. Then + # check if we should to store the document in the same directory, and + # move the original document to an 'unsafe' subdirectory, or save the + # document to another directory. + document.suffix = self.safe_extension.text() + if self.radio_move_untrusted.isChecked(): + document.archive_after_conversion = True + elif self.radio_save_to.isChecked(): + if self.output_dir: + document.set_output_dir(self.output_dir) # type: ignore [unreachable] + else: + # If not saving, then save it to a temp file instead (_, tmp) = tempfile.mkstemp(suffix=".pdf", prefix="dangerzone_") document.output_filename = tmp - else: - for document in self.dangerzone.get_unconverted_documents(): - document.suffix = self.safe_extension.text() - - if self.output_dir: - document.set_output_dir(self.output_dir) # type: ignore [unreachable] # Update settings self.dangerzone.settings.set( "save", self.save_checkbox.checkState() == QtCore.Qt.Checked ) self.dangerzone.settings.set("safe_extension", self.safe_extension.text()) + self.dangerzone.settings.set("archive", self.radio_move_untrusted.isChecked()) self.dangerzone.settings.set( "ocr", self.ocr_checkbox.checkState() == QtCore.Qt.Checked ) diff --git a/dangerzone/settings.py b/dangerzone/settings.py index 22fa1ea..a312146 100644 --- a/dangerzone/settings.py +++ b/dangerzone/settings.py @@ -21,6 +21,7 @@ class Settings: ) self.default_settings: Dict[str, Any] = { "save": True, + "archive": True, "ocr": True, "ocr_language": "English", "open": True,