qubes: Clean up temporary files

Create a temporary dir before the conversion begins, and store every
file necessary for the conversion there. We are mostly concerned about
the second stage of the conversion, which runs in the host. The first
stage runs in a disposable qube and cleanup is implicit.

Fixes #575
Fixes #436
This commit is contained in:
Alex Pyrgiotis 2023-10-04 14:01:58 +03:00
parent f37d89f042
commit bdf3f8babc
No known key found for this signature in database
GPG key ID: B6C15EBA0357C9AA

View file

@ -33,11 +33,6 @@ from .base import (
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
CONVERTED_FILE_PATH = (
# FIXME won't work for parallel conversions (see #454)
"/tmp/safe-output-compressed.pdf"
)
# The maximum time a qube takes to start up. # The maximum time a qube takes to start up.
STARTUP_TIME_SECONDS = 5 * 60 # 5 minutes STARTUP_TIME_SECONDS = 5 * 60 # 5 minutes
@ -76,20 +71,12 @@ class Qubes(IsolationProvider):
def __convert( def __convert(
self, self,
document: Document, document: Document,
tempdir: str,
ocr_lang: Optional[str] = None, ocr_lang: Optional[str] = None,
) -> bool: ) -> bool:
success = False success = False
# FIXME won't work on windows, nor with multi-conversion Path(f"{tempdir}/dangerzone").mkdir()
out_dir = Path("/tmp/dangerzone")
if out_dir.exists():
shutil.rmtree(out_dir)
out_dir.mkdir()
# Reset hard-coded state
if os.path.exists(CONVERTED_FILE_PATH):
os.remove(CONVERTED_FILE_PATH)
percentage = 0.0 percentage = 0.0
with open(document.input_filename, "rb") as f: with open(document.input_filename, "rb") as f:
@ -136,11 +123,11 @@ class Qubes(IsolationProvider):
) )
# Wrapper code # Wrapper code
with open(f"/tmp/dangerzone/page-{page}.width", "w") as f_width: with open(f"{tempdir}/dangerzone/page-{page}.width", "w") as f_width:
f_width.write(str(width)) f_width.write(str(width))
with open(f"/tmp/dangerzone/page-{page}.height", "w") as f_height: with open(f"{tempdir}/dangerzone/page-{page}.height", "w") as f_height:
f_height.write(str(height)) f_height.write(str(height))
with open(f"/tmp/dangerzone/page-{page}.rgb", "wb") as f_rgb: with open(f"{tempdir}/dangerzone/page-{page}.rgb", "wb") as f_rgb:
f_rgb.write(untrusted_pixels) f_rgb.write(untrusted_pixels)
percentage += percentage_per_page percentage += percentage_per_page
@ -169,7 +156,7 @@ class Qubes(IsolationProvider):
converter = PixelsToPDF(progress_callback=print_progress_wrapper) converter = PixelsToPDF(progress_callback=print_progress_wrapper)
try: try:
asyncio.run(converter.convert(ocr_lang)) asyncio.run(converter.convert(ocr_lang, tempdir))
except (RuntimeError, TimeoutError, ValueError) as e: except (RuntimeError, TimeoutError, ValueError) as e:
raise errors.UnexpectedConversionError(str(e)) raise errors.UnexpectedConversionError(str(e))
finally: finally:
@ -181,7 +168,7 @@ class Qubes(IsolationProvider):
) )
log.info(text) log.info(text)
shutil.move(CONVERTED_FILE_PATH, document.output_filename) shutil.move(f"{tempdir}/safe-output-compressed.pdf", document.output_filename)
success = True success = True
return success return success
@ -192,7 +179,8 @@ class Qubes(IsolationProvider):
ocr_lang: Optional[str] = None, ocr_lang: Optional[str] = None,
) -> bool: ) -> bool:
try: try:
return self.__convert(document, ocr_lang) with tempfile.TemporaryDirectory() as t:
return self.__convert(document, t, ocr_lang)
except errors.InterruptedConversion: except errors.InterruptedConversion:
assert self.proc is not None assert self.proc is not None
error_code = self.proc.wait(3) error_code = self.proc.wait(3)