Commit graph

552 commits

Author SHA1 Message Date
deeplow
e5dbe25abb
Replace 'convert' with PyMuPDF for images
PyMuPDF can also convert images of the types we already support so we
don't need ImageMagick's 'convert'.
2024-01-03 12:58:34 +00:00
deeplow
77d5ea5940
Add PyMuPDF in pixels_to_pdf replacing old logic
Adding PyMuPDF essentially make the code much simpler since it can do
everything that we'd need multiple programs for. It also includes
tesseract-OCR integration, which this commit makes use of.
2024-01-03 12:56:33 +00:00
deeplow
ba17016643
Doc_to_pixels: remove unneeded timeout
Timeout can no longer be used since we're not calling a subprocess. We
could still implement it, but it's more worthy to reply in
yet-to-implement client-side timeouts (in containers).
2024-01-03 12:40:45 +00:00
deeplow
317deadbe4
Replace pdfinfo logic (get # pages) with PyMuPDF 2024-01-03 12:40:45 +00:00
deeplow
327ab8791f
Replace pdftoppm logic with PyMuPDF (native python)
Use PyMuPDF (AGPL-licensed) within the container conversion to replace
the pdf conversion to RGB. This massively simplifies the code since
PyMuPDF is a native python library.
2024-01-03 12:40:45 +00:00
Alex Pyrgiotis
5bf7549b55
Fix typo 2023-12-29 18:30:48 +02:00
Moon Sungjoon
63aea4cb45
Enable HWP conversion on MacOS (Apple silicon CPU)
This PR reverts the patch that disables HWP / HWPX conversion on MacOS M1.
It does not fix conversion on Qubes OS (#494).

Previously, HWP / HWPX conversion didn't work on MacOS (Apple silicon CPU) (#498)
because libreoffice wasn't built with Java support on Alpine Linux for ARM (aarch64).

Gratefully, the Alpine team has enabled Java support on the aarch64
system [1], so we can enable it again for ARM architectures.
And this patch is included in Alpine 3.19

This commit was included in #541 and reverted on #562 due to a stability issue.

Fixes #498

[1]: 74d443f479
2023-12-13 12:57:22 +02:00
Garrett Robinson
53115b3ffa
Use more descriptive button labels in update check prompt 2023-10-31 12:52:34 +00:00
Alex Pyrgiotis
ba5adb33c0
Fix a bug in "Change Selection"
Fix a bug in the "Change Selection" action, whereby changing your
selection and picking files from another directory results in:

    "Dangerzone does not support adding documents from multiple
    locations. The newly added documents were ignored."

To fix this, change the output directory when we change selection as
well.
2023-10-13 22:45:11 +03:00
Alex Pyrgiotis
edfba0c783
Qubes: Fix progress in first stage of Qubes conversion 2023-10-13 22:44:37 +03:00
deeplow
186ddd6b1e
Allow user to override update checking on Linux
The original intention of leaving the update checkbox in the hamburger
menu was to let non-supported Linux distros (e.g. compiled from source)
to check for updates. However, on Linux it ended up being disabled
forcefully by default on startup.

This takes into account an overriden update checkbox.

Fixes #596
2023-10-13 17:01:53 +01:00
Alex Pyrgiotis
3daf0e2cb7
Do not show file previews in case of exceptions
If a Qubes conversion encounters an exception that is not a subclass of
ConversionException, it will still show a preview of a file that does
not exist.

Send an error progress report in that case, so that the GUI code can
detect that an error occurred and not open a file preview

Fixes #581
2023-10-05 11:11:42 +03:00
Alex Pyrgiotis
bdf3f8babc
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
2023-10-04 14:05:23 +03:00
Alex Pyrgiotis
f37d89f042
conversion: Allow using a temp dir other than /tmp
Extend the PixelsToPDF converter by adding an additional `tempdir`
argument. This argument can be used to make the conversion use a
different temporary directory other than `/tmp`.

For containers, this extra arguments makes no difference, as it won't be
used. For Qubes, this argument will allow storing files in a temporary
dir that will be cleaned up once the conversion completes. Previously,
these files would linger in the user's `/tmp`.

Refs #575
2023-10-04 14:00:53 +03:00
Alex Pyrgiotis
4f66353639
Add dark mode logic in our dialogs
Make our dialogs set the OSColorMode CSS property, so that we can
properly style them.

Refs #528
2023-10-02 16:34:56 +03:00
Alex Pyrgiotis
6232062146
Add missing newline char 2023-10-02 15:41:29 +03:00
Alex Pyrgiotis
b7b76174ab
qubes: Log captured output for the second stage
Log the captured command output during the second stage, only in dev
environments. This follows what we have already done for the first
stage.
2023-10-02 15:41:29 +03:00
Alex Pyrgiotis
16603875d6
qubes: Display all errors in second stage
If a command encounters an error or times out during the second stage of
the conversion in Qubes, handle it the same way as we would have handled
it in the first stage:

1. Get its error message.
2. Throw an UnexpectedConversionError exception, with the original
   message.

Note that, because the second stage takes place locally, users will see
the original content of the error.

Refs #567
Closes #430
2023-10-02 15:41:17 +03:00
Alex Pyrgiotis
2016965c84
Revert "Enable HWP conversion on MacOS M1"
This reverts commit 214ce9720d. The
rationale is that we want to wait until the LibreOffice package that
allows HWP conversion in Alpine Linux lands in `alpine:latest`.

For more info, read
https://github.com/freedomofpress/dangerzone/issues/498#issuecomment-1739894100
2023-10-02 14:22:47 +03:00
deeplow
7daeccdfea
Prevent PDF from overwriting num_pages in Qubes
This should only affect the alpha version of Qubes OS (in containers
it only allows the attacker to control the timeout). In short, an
attacker could have PDF metadata that would show before "Pages:" in
the `pdfinfo` command output and this would essentially override the
number of pages measured in the server. This could enable the attacker
to shorten the number of pages of a document for example.

Fixes #565
2023-10-02 12:18:12 +01:00
deeplow
dabdf6c286
FIXUP: rename to QubesQrexecFailed instead 2023-10-02 12:06:18 +01:00
deeplow
eb488b16c5
FIXUP: rename QubesNotEnoughRAMError to QubesConversionStartFailed 2023-10-02 11:51:55 +01:00
deeplow
9cfac7ac2a
Generalize "out of RAM" error to reflect other issues
When qrexec-client-vm fails, it could be a symptom of various issues:
  - the system being out of RAM
  - dz-dvm not existing

The exit code is the same in all cases (126), which makes it
particularly tricky to solve in the client application. For this reason
the approach is now to tell the user to see the qubes error notification
on the top right of their screen.
2023-10-02 11:06:17 +01:00
Alex Pyrgiotis
ccf4132ea0
conversion: Add sanity check for page count
Add a sanity check at the end of the conversion from doc to pixels, to
ensure that the resulting document will have the same number of pages as
the original one.

Refs #560
2023-09-28 22:50:54 +03:00
Alex Pyrgiotis
b4e5cf5be7
qubes: Stream page data in real time
Stream page data back to the caller, immediately after we read them from
pdftoppm. This way, we have more accurate progress reports and timeouts.

Fixes #557
2023-09-28 22:50:54 +03:00
Alex Pyrgiotis
4bb959f220
conversion: Add anchor points for streaming page data/metadata
Introduce 4 new methods that can be overloaded by the Qubes isolation
provider to stream page data/metadata back to the caller. For the time
being, these methods do what they did before, i.e., write this info in
files within the pixels directory.
2023-09-28 22:50:53 +03:00
Alex Pyrgiotis
6012cd1491
Improve EOF detection when reading command output
Do not read a line from the command output and then check if
we are at EOF, because it's possible that the writer immediately exited
after writing the last line of output. Instead, switch the order of
actions.

This is a very serious bug that can lead to Dangerzone excluding the
last page of the document. It should have bit us right from the start
(see aeeed411a0), but it seems that the
small period of time it takes the kernel to close the file descriptors
was hiding this bug.

Fixes #560
2023-09-28 22:50:53 +03:00
Garrett Robinson
46f978e6f0
Detect OS color mode and set as property for stylesheets
Sets the detected OS color mode (dark/light) as a property on the
QApplication so it can be referenced in stylesheets to select style
rules suited to the OS color mode.
2023-09-28 17:20:34 +03:00
deeplow
0a6b33ebed
Qubes: detect qube failing to start (missing RAM)
In Qubes OS it's often the case that the user doesn't have enough
RAM to start the conversion. In this case it raises BrokenPipeException
and exits with code 126.

It didn't seem possible to distinguish this kind of failure to one
where the user has misconfigured qrexec policies.

NOTE: this approach is not ideal UX-wise. After the first doc failing
the next one will also try and fail. Upon first failure we should
inform the user that they need to close some programs or qubes.
2023-09-28 11:08:50 +01:00
deeplow
63f03d5bcd
Add limit and test to max width and height of docs 2023-09-28 11:08:47 +01:00
deeplow
54b8ffbf96
Add page limit of 10000
Theoretically the max pages would be 65536 (2byte unsigned int.
However this limit is much higher than practical documents have
and larger ones can lead to unforseen problems, for example RAM
limitations.

We thus opted to use a lower limit of 10K. The limit must be
detected client-side, given that the server is distrusted. However
we also check it in the server, just as a fail-early mechanism.
2023-09-28 11:01:14 +01:00
Alex Pyrgiotis
18b73d94b0
qubes: Find out reason of interrupted conversions
If a conversion has been interrupted (usually due to an EOF), figure out
why this happened by checking the exit code of the spawned process.
2023-09-26 17:35:26 +03:00
Alex Pyrgiotis
30196ff35b
errors: Add error for interrupted conversions
Add an error for interrupted conversions, in order to better
differentiate this scenario from other ValueErrors that may be raised
throughout the code's lifetime.
2023-09-26 17:35:26 +03:00
Alex Pyrgiotis
0273522fb1
qubes: Store the process for the spawned qube
Store, in an instance attribute, the process that we have started for
the spawned disposable qube. In subsequent commits, we will use it from
other places as well, aside from the `_convert` method.

Note that this commit does not alter the conversion logic, and only does
the following:
1. Renames `p.` to `self.proc.`
2. Adds an `__init__` method to the Qubes isolation provider, and
   initializes the `self.proc` attribute to `None`.
3. Adds an assert that `self.proc` is not `None` after it's spawned, to
   placate Mypy.
2023-09-26 17:35:25 +03:00
deeplow
e08b6defc3
Round conversion progress from float to int
Fixes #553
2023-09-26 15:20:41 +01:00
deeplow
8d37ff15e0
Remove duplicated Qubes message: "Safe PDF Created"
Fixes #555.  This is a leftover from when we didn't have progress
reports from the second stage conversion (AKA. pixels to PDF) in #429.
2023-09-26 12:16:48 +01:00
Alex Pyrgiotis
e64d1da61f
qubes: Pass OCR parameters properly
Pass OCR parameters to conversion functions as arguments, instead of
setting environment variables.

Fixes #455
2023-09-20 18:04:40 +03:00
Alex Pyrgiotis
8a0c0a4673
Make parameter actually optional 2023-09-20 17:58:39 +03:00
Alex Pyrgiotis
20157bef58
Fix typo 2023-09-20 17:45:44 +03:00
Alex Pyrgiotis
99dd5f5139
qubes: Add client-side timeouts
Extend the client-side capabilities of the Qubes isolation provider, by
adding client-side timeout logic.

This implementation brings the same logic that we used server-side to
the client, by taking into account the original file size and the number
of pages that the server returns.

Since the code does not have the exact same insight as the server has,
the calculated timeouts are in two places:

1. The timeout for getting the number of pages. This timeout takes into
   account:
   * the disposable qube startup time, and
   * the time it takes to convert a file type to PDF
2. The total timeout for converting the PDF into pixels, in the same way
   that we do it on the server-side.

Besides these changes, we also ensure that partial reads (e.g., due to
EOF) are detected (see exact=... argument)

Some things that are not resolved in this commit are:
* We have both client-side and server-side timeouts for the first phase
  of the conversion. Once containers can stream data back to the
  application (see #443), these server-side timeouts can be removed.
* We do not show a proper error message when a timeout occurs. This will
  be part of the error handling PR (see #430)

Fixes #446
Refs #443
Refs #430
2023-09-20 17:32:42 +03:00
Alex Pyrgiotis
55a4491ced
Consolidate import statements 2023-09-20 17:14:24 +03:00
Alex Pyrgiotis
c547ffc3b4
conversion: Factor out calculate_timeout
Factor out the logic behind the calculate_timeout() method, used in
Dangerzone conversions, so that isolation providers can call it
directly.
2023-09-20 17:14:24 +03:00
Alex Pyrgiotis
fea193e935
Add non-blocking read utility
Add a function that can read data from non-blocking fds, which we will
used later on to read from standard streams with a timeout.
2023-09-20 17:14:24 +03:00
Alex Pyrgiotis
344d6f7bfa
Add Stopwatch implementation
Add a simple stopwatch implementation to track the elapsed time since an
event, or the remaining time until a timeout.
2023-09-20 17:14:23 +03:00
deeplow
94f569cdf5
Add error code for unexpected errors in conversion 2023-09-19 15:52:47 +01:00
deeplow
8e4f04a52e
Shift to conversion exit codes by 128
Distinguish from podman or other errors in called binaries by shifting
the error codes by 128.
2023-09-19 15:34:00 +01:00
deeplow
b4c3e07d36
Remove attacker-controlled error messages
Creates exceptions in the server code to be shared with the client via an
identifying exit code. These exceptions are then reconstructed in the
client.

Refs #456 but does not completely fix it. Unexpected exceptions and
progress descriptions are still passed in Containers.
2023-09-19 15:33:20 +01:00
Moon Sungjoon
214ce9720d
Enable HWP conversion on MacOS M1
This PR reverts the patch that disables HWP / HWPX conversion on MacOS
M1. It does not fix conversion on Qubes OS (#494)

Previously, HWP / HWPX conversion didn't work on MacOS M1 systems (#498)
because libreoffice wasn't built with Java support on Alpine Linux for
ARM (aarch64).

Gratefully, the Alpine team has enabled Java support on the aarch64
system [1], so we can enable it again for ARM architectures.

Fixes #498

[1]: 74d443f479
2023-09-06 13:10:18 +03:00
deeplow
8ae88eb10a
Ensure updates checkbox updated after updates accepted
Ensure the status of the toggle updates checkbox is updated, after the user is
prompted to enable updates.
2023-08-23 16:46:45 +01:00
deeplow
8221a56c7d
Revert "Propagate "update check" prompt to UI checkbox"
This reverts commit 3915a86642502b673aa0e47931823acbe66f1043.
2023-08-23 16:46:44 +01:00
deeplow
1695cc7a6c
Propagate "update check" prompt to UI checkbox
The "check for updates" button wasn't showing up immediately as checked
as soon as the user is prompted for checking updates. This fixes that.

Fixes #513
2023-08-23 16:46:33 +01:00
deeplow
9ec9cc5f87
Replace armor guards that indicate isolated output 2023-08-22 16:11:41 +01:00
deeplow
fa215063ee
Add logging for second container 2023-08-22 16:11:38 +01:00
deeplow
75369cf621
Adapt code so it works for reporting script
Reporting script now parses JunitXML instead of a series of
".container_log" files. The script in in changed submodule.

Additionally it makes failed tests actually fail so that this is
recorded in the JunitXML report.
2023-08-22 16:11:36 +01:00
deeplow
eb16285790
Replace container output command prefix ">>>"
In the junitxml this prefix would look ugly ("&gt&gt&gt") because it has
to escape any non-xml tags.
2023-08-22 16:11:35 +01:00
deeplow
48b2e7bc3c
Log command to debug log for traceback purposes
Log commands so we can trace back which errors / outputs are from each
command.
2023-08-22 16:11:34 +01:00
deeplow
f41cefde1d
Add "armor" around conversion log
Add GPG-styled "armor" around conversion logs

    -----CONVERSION LOG START-----
    Creator:         Writer
    Producer:        LibreOffice 6.4
    [...]
    -----CONVERSION LOG END-----
2023-08-22 16:11:28 +01:00
deeplow
9f1abe2836
Replace non-printable ascii in conversion log
Certain characters may be abused. Particularly ANSI escape codes.
Solution inspired by Qubes OS's hardening of ther RPC mechanism [1]:

> Terminal control characters are a security issue, which in worst case
> amount to arbitrary command execution. In the simplest case this
> requires two often found codes: terminal title setting (which puts
> arbitrary string in the window title) and title repo reporting (which
> puts that string on the shell's standard input. [sic]
>
>  -- qvm-run.rst [2]

[1]: e005836286
[2]: c70da44702/doc/manpages/qvm-run.rst (L126)
2023-08-22 16:11:27 +01:00
deeplow
95cef8cf0a
Containers: capture conversion logs
Store the conversion log to a file (captured-output.txt) in the
container and when in development mode, have its output displayed on the
terminal output.
2023-08-22 16:11:26 +01:00
deeplow
d6bce4dec5
Qubes: close qrexec stdin and stout
Ensure a server cannon keep the client hannging if more data than
necessary is sent. This applies to container and the Qubes
implmentation.
2023-08-22 16:11:23 +01:00
deeplow
874b8865e2
Qubes: strategy for capturing conversion logs
Use qrexec stdout to send conversion data (pixels) and stderr to send
conversion progress at the end of the conversion. This happens
regardless of whether or not the conversion is in developer mode or not.

It's the client that decides if it reads the debug data from stderr or
not. In this case, it only reads it if developer mode is enabled.
2023-08-22 16:11:20 +01:00
deeplow
e512ba2b6a
Updater dialog: make "yes" the default button
Fixes #507
2023-08-21 13:07:05 +01:00
deeplow
e8b28d6f87
Explicitly import html.parser for Cx_Freeze to build
The markdown dependency uses importlib to monkeypatch 'html.parser'
[1]. Due to this approach 'html.parser' is never explicitly stated
as a dependency. This works fine in most cases, since it's part of
the python standard lib. But on Windows the build tool (CxFreeze)
ships in the .exe only the modules needed. And because html.parser
is never mentioned, it fails with an error (see issue #501).

Fixes #501

[1]: https://github.com/Python-Markdown/markdown/blob/master/markdown/htmlparser.py#L29
2023-08-05 17:09:42 +01:00
Alex Pyrgiotis
e3a8a651f1
Disable HWP / HWPX conversion on MacOS M1 / Qubes
The HWP / HWPX conversion feature does not work on the following
platforms:

* MacOS with Apple Silicon CPU
* Native Qubes OS

For this reason, we need to:

1. Disable it on the GUI side, by not allowing the user to select these
   files.
2. Throw an error on the isolation provider side, in case the user
   directly attempts to convert the file (either through CLI or via
   "Open With").

Refs #494
Refs #498
2023-08-05 16:50:49 +01:00
Alex Pyrgiotis
bc83341d2a
conversion: Detect when LibreOffice silently fails
Sometimes, LibreOffice returns with status code 0, but in reality, it
fails. It doesn't create a file, and Dangerzone does not detect this.
What happens next is that it fails in the next command, and throws an
unrelated error.

Detect that LibreOffice fails, by checking if the output file exists,
after the PDF conversion.
2023-08-05 16:50:47 +01:00
Alex Pyrgiotis
6736fb0153
Factor out MIME type detection
Factor out the MIME type detection logic, so that we can use it both in
Qubes and containers.
2023-08-05 16:50:35 +01:00
Moon Sungjoon
fa22e96af7
Clean up HWP/HWPX MIME types
Use the MIME types actually used by the `file` command, which was
recently changed for the detection of the HWPX format [1].

application/hwp+zip -> application/x-hwp+zip

But the HWPX format includes a 'mimetype' file, which contains the
MIME type string "application/hwp+zip", so that was left so because
it may be possible to detect it as "application/hwp+zip".

[1]: ceef7ead3a
2023-08-01 14:35:28 +01:00
Moon Sungjoon
a453c890a0
Fix dynamic loading of LibreOffice extensions
HWPX MIME type is recognized as 'application/zip' with current version of file command (file-5.44).
It will be recognized as 'application/hwp+zip' when new version of file is released.

For a temporary fix, when MIME type of file is 'application/zip',
check the file type again (without the MIME option).
And then check if it's 'Zip data (MIME type "application/hwp+zip"?)' or not.
2023-08-01 14:28:36 +01:00
deeplow
d16961bed6
Security: Dynamically load libreoffice extension (PoC)
Only load the LibreOffice extension for opening hwp/hwpx when it is
actually needed. Adding an extension to libreoffice may allow for it to
run arbitrary code. This makes it trust more scalable by trusting
LibreOffice extensions only for the filetypes which they target.

Reasoning
---------

Assuming a malicious `.oxt` extension this means that the extension has
arbitrary code execution in the container. While this is not an
existential threat in itself, we should not expose every Dangerzone user
to it. This is achieved by dynamically loading the extension at runtime
only when needed.

This ensures that a compromised extension will in its least malicious
form be able to modify the visual content of any hancom office files but
not *every file*. In the more malicious version, if the code execution
manages to do a container escape, this will only affect users that have
converted a Hancom office file.
2023-08-01 14:28:34 +01:00
Moon Sungjoon
3e895adbab
Add hwp hwpx support
hwp/hwpx has several custom MIME types

.hwp:
 - application/x-hwp
 - application/haansofthwp
 - application/vnd.hancom.hwp

.hwpx:
 - application/haansofthwpx
 - application/vnd.hancom.hwpx,
 - application/hwp+zip

Fixes #243
2023-08-01 14:27:18 +01:00
Alex Pyrgiotis
6c374d8a7e
qubes: Mark Dangerzone messages as trusted
Mark the messages that Dangerzone creates once a conversion step
finishes as trusted, since they do not contain any string not controlled
by us.
2023-08-01 14:43:49 +03:00
deeplow
72536a05ac
container: Improve parsing of progress reports
Improve the `parse_progress()` method of the container isolation
provider in the following ways:

1. Make sure that the fields of the progress report have the expected
   type.
2. In case of a JSON parsing error, sanitize the invalid string so that
   it doesn't contain escape sequences, or the user considers it as
   trusted.
2023-08-01 14:43:49 +03:00
Alex Pyrgiotis
9410b68c1d
Sanitize progress reports in a provider-agnostic way
Update the common `print_progress()` method in the base
`IsolationProvider` class, with two extra features:

1. Always sanitize the provided text argument.
2. Mark the sanitized text argument as untrusted.

This is default behavior from now on, since this function is commonly
used to parse progress reports from the conversion sandbox.
2023-08-01 14:43:48 +03:00
Alex Pyrgiotis
cfa0c01d8f
Sanitize filenames before logging them
Sanitize filenames in various places in the code, before we write them
to the user's terminal. Filenames, especially in Linux, can contain
virtually any character except for '\0' and '/', so it's important to
sanitize them.
2023-08-01 14:43:48 +03:00
deeplow
3788139d26
Add utility for sanitizing strings
Add `replace_control_chars()` function in `util.py`, which can be used
to sanitize strings from ANSI escape sequences or weird Unicode symbols.
2023-08-01 14:43:48 +03:00
Alex Pyrgiotis
cb08c198ad
Force rendering of error messages as plain text
Make the `error_label` widget always render messages as plain text,
instead of auto discovering if the text is rich. We need this because
the error message may contain input from the sandbox, which we consider
untrusted.
2023-08-01 14:43:48 +03:00
Alex Pyrgiotis
77f4b8115c
Add missing reset ANSI sequence
Do not forget to reset the red text once we print an error string to the
terminal
2023-08-01 14:38:32 +03:00
Alex Pyrgiotis
81811e0aac
Add collapsible dialog for errors
Move the error message from a text browser to a collapsible widget.
2023-08-01 14:29:27 +03:00
deeplow
53ec1cad63
Add update error red dot to hamburger menu 2023-08-01 14:29:11 +03:00
Alex Pyrgiotis
c9eac42855
Improve updater messages
Improve the wording of updater messages for better UX.
2023-08-01 14:29:10 +03:00
Alex Pyrgiotis
d5ca6bb422
updater: Move "Ok" button to the right
Move the "Ok" button in the prompt that asks users if they want to
enable update checks to the right, to further reinforce that this is
the default action.
2023-07-28 19:57:46 +03:00
Alex Pyrgiotis
bc4bba4fa1
tests: Add full test coverage for updater checks
Fully test the update check logic, by introducing several Qt tests.
Also, improve the `UpdaterThread.get_letest_info()` method, that gets
the latest version and changelog from GitHub, with several checks.
These checks are also tested in our newly added tests.
2023-07-28 12:18:59 +03:00
Alex Pyrgiotis
fdc53efc35
tests: Test our own custom QApplication
By default, `pytest-qt` initializes the default QApplication class that
PySide offers. Dangerzone, however, defines its own QApplication
subclass.

Create a `qapp_cls` fixture that will force `pytest-qt` to use this
subclass. For more info, see:
https://pytest-qt.readthedocs.io/en/latest/qapplication.html#testing-custom-qapplications
2023-07-28 12:18:58 +03:00
Alex Pyrgiotis
24ba914cc8
updater: Differentiate between "X" and "Cancel"
We want to differentiate between the user clicking on "Cancel" and
clicking on "X", since in the second case, we want to remind them again
on the next run.
2023-07-28 11:50:44 +03:00
Alex Pyrgiotis
f6b5e1293d
gui: Add references to dialog buttons
Add references to dialog buttons, so that we can click on them from our
GUI tests.
2023-07-28 11:50:44 +03:00
Alex Pyrgiotis
a2177bfd34
Remove some stale FIXMEs 2023-07-28 11:50:44 +03:00
Alex Pyrgiotis
8d86b0a15f
Rename "Changelog" to "What's new" 2023-07-28 11:50:43 +03:00
deeplow
1ab14dbd86
Use containers in Qubes until Beta
Reverse the logic in Qubes to run in containers by default and only
perform the conversion with VMs when explicitly set by the env var
QUBES_CONVERSION=1. This will avoid surprises when someone installs
Dangerzone on Qubes expecting it to work out of the box just like any
other Linux.

Fixes #451
2023-07-26 14:02:06 +01:00
deeplow
9ca27fd6fe
Add unit test to document change button
Fixes #428
2023-07-25 15:00:29 +01:00
deeplow
250a481f31
Store ref file_selection dialog
Allow an outside module (e.g. tests) to be able to "grab" the document
selection dialog.
2023-07-25 15:00:27 +01:00
deeplow
2bd97a036a
Add logic to handle documents removal
This implements the backend part of changing documents.
2023-07-25 15:00:12 +01:00
deeplow
d0c86fbbe2
Add change docs button to settings window
Implements the GUI logic necessary to change the selected document. When
"Change Selection" is clicked, it opens a File Dialog on the directory
of the previously selected files (if any)

Fixes #428
2023-07-25 13:44:26 +01:00
Alex Pyrgiotis
77b380e7df
Fix proper signal type for UpdateReport
Change the signal type in `UpdaterThread.check_for_updates()` from
`dict` to `UpdateReport`. The `dict` parameter is stale and should have
never been used.
2023-07-25 14:52:49 +03:00
Moon Sungjoon
494f498d17
Remove pipes module and use shlex instead
Thanks: https://github.com/tox-dev/tox/pull/2418/files

Closes #373
2023-07-24 18:13:00 +03:00
Alex Pyrgiotis
5b17f75047
Inform the user for new updates
Add a hamburger button in the main window of Dangerzone, that will be
the entry point for update information. Whenever a new update is
released, users will see a green notification bubble. If an update error
happens, they will see a red notification bubble.

In the hamburger menu, users have the option to enable or disable update
checks. Depending on the update check status, users will see in a pop-up
dialog more info about the new update or the error.

Closes #189
2023-07-24 16:49:25 +03:00
Alex Pyrgiotis
58c5fc846a
gui: Add Update Dialog
Add a dialog that we will show for update-related tasks. This dialog has
a different layout than the Alert class: it has a message, followed by
a widget that the user chooses (can be a text box or collapsible
element), and then one last message.
2023-07-24 14:22:28 +03:00
Alex Pyrgiotis
64ca90c92f
Add a Qt widget for creating collapsible sections
Add a Qt widget called "CollapsibleBox", in order to build sections that
you can hide/show with a single click. There is no native widget for
this functionality, so we borrow some code from a StackOverflow user:
https://stackoverflow.com/a/52617714
2023-07-24 14:22:27 +03:00
Alex Pyrgiotis
20a25f1dd4
Allow more types of dialogs
Factor out some parts of the Alert class into a more generic dialog
class. This class will be used for a new type of dialog that we will
introduce in a subsequent commit.

Note that this commit does not alter the functionality of the Alert
class.
2023-07-24 14:22:27 +03:00
Alex Pyrgiotis
5ae8b871b6
Add UpdaterThread class
Add a new Python module called "updater", which contains the logic for
prompting the user to enable updates, and checking our GitHub releases
for new updates.

This class has some light dependency to Qt functionality, since it needs
to:

* Show a prompt to the user,
* Run update checks asynchronously in a Qt thread,
* Provide the main window with the result of the update check

Refs #189
2023-07-24 14:22:27 +03:00
Alex Pyrgiotis
0ad489f80b
Get default settings without Settings instance
Get the default settings of Dangezone for the current version, without
having to instantiate the Settings class. Note that instantiating the
Settings class also writes the settings to the underlying
`settings.json` file, and there are cases where we don't want this
behavior.
2023-07-24 14:22:26 +03:00
Alex Pyrgiotis
266addb5b7
Make it easier to get and save updater settings
Add the following two features in the Settings class:

1. Add a way to save the settings, if the contents of a key have
   changed.
2. Add a way to get all the updater settings, by getting fetching the
   keys that start with `"updater_"`.
2023-07-24 14:22:26 +03:00
Alex Pyrgiotis
2df459bcfc
Add default settings for Dangerzone updater
Add some settings prefixed with `"updater_"`, which will be used for
updates later on.
2023-07-24 14:22:26 +03:00
deeplow
ef41cab76e
Add progress reports on Qubes (GUI)
Fixes #429
2023-07-13 12:57:23 +01:00
deeplow
bf38c24d99
Merge stdout_callback with print_progress
stdout_callback is used to flow progress information from the conversion
to some front-end. It was always used in tandem with printing to the
terminal (which is kind of a front-end). So it made sense to put them
always together.
2023-07-13 12:57:04 +01:00
deeplow
5191556dcd
Use the Qubes isolation provider from CLI/GUI
Autodetect in the CLI/GUI if we should run the conversion in disposable
qubes.
2023-06-21 11:46:43 +03:00
deeplow
baeab9d7eb
Add Qubes isolation provider
Add an isolation provider for Qubes, that performs the document
conversion as follows:

Document to pixels phase
------------------------

1. Starts a disposable qube by calling either the dz.Convert or the
   dz.ConvertDev RPC call, depending on the execution context.
2. Sends the file to disposable qube through its stdin.
   * If we call the conversion from the development environment, also
     pass the conversion module as a Python zipfile, before the
     suspicious document.
3. Reads the number of pages, their dimensions, and the page data.

Pixels to PDF phase
-------------------

1. Writes the page data under /tmp/dangerzone, so that the
   `pixels_to_pdf` module can read them.
2. Pass OCR parameters as envvars.
3. Call the `pixels_to_pdf` main function, as if it was running within a
   container. Wait until the PDF gets created.
4. Move the resulting PDF to the proper directory.

Fixes #414
2023-06-21 11:46:34 +03:00
deeplow
a83f5dfc7a
Add Qubes-specific code for disposable VMs
The "document to pixels" code assumes that the client has called it with
some mount points in which it can write files. This is true for the
container isolation provider, but not for Qubes, who can communicate
with the client only via stdin/stdout.

Add a Qubes wrapper for this code that reads the suspicious document
from stdin and writes the pages to stdout. The on-wire format is the
same as the one that TrustedPDF uses.
2023-06-21 11:45:04 +03:00
Alex Pyrgiotis
cfdaec23c5
Support multiple Python libraries for libmagic
It seems that there are at least two Python libraries with libmagic
support:

* PyPI: python-magic (https://pypi.org/project/python-magic/)
  On Fedora it's `python3-magic`
* PyPI: filemagic (https://pypi.org/project/filemagic/)
  On Fedora it's `python3-file-magic`

The first package corresponds to the `py3-magic` package on Alpine
Linux, and it's the one we install in the container. The second package
uses a different API, and it's the only one we can use on Qubes.

To make matters worse, we:

* Can't install the first package on Fedora, because it installs the
  second under the hood:
  https://bugzilla.redhat.com/show_bug.cgi?id=1899279
* Can't install the second package on Alpine Linux (untested), due to
  Musl being used instead of libC:
  https://stackoverflow.com/a/53936722

Ultimately, we need to support both, by trying the first API, and on
failure using the other API.
2023-06-21 11:45:00 +03:00
deeplow
9410da762c
Check if conversion code runs on Qubes
Add a way to check if the code runs (or should run) on Qubes.

Refs #451
2023-06-21 11:44:58 +03:00
deeplow
a0d1a68302
Use /tmp/dangerzone for Qubes compatibility
For using in containers, creating a /dangerzone directory is fine but it
is more standard to do this in /tmp.
2023-06-21 11:44:53 +03:00
deeplow
814d533c3b
Restructure container code
The files in `container/` no longer make sense to have that name since
the "document to pixels" part will run in Qubes OS in its own virtual
machine.

To adapt to this, this PR does the following:
- Moves all the files in `container` to `dangerzone/conversion`
- Splits the old `container/dangerzone.py` into its two components
  `dangerzone/conversion/{doc_to_pixels,pixels_to_pdf}.py` with a
  `common.py` file for shared functions
- Moves the Dockerfile to the project root and adapts it to the new
  container code location
- Updates the CircleCI config to properly cache Docker images.
- Updates our install scripts to properly build Docker images.
- Adds the new conversion module to the container image, so that it can
  be imported as a package.
- Adapts the container isolation provider to use the new way of calling
  the code.

NOTE: We have made zero changes to the conversion code in this commit,
except for necessary imports in order to factor out some common parts.
Any changes necessary for Qubes integration follow in the subsequent
commits.
2023-06-21 11:44:47 +03:00
sudwhiwdh
f8f9cf304e
fix gui typo 2023-05-08 12:53:09 +01:00
Alex Pyrgiotis
8b846820d2
Update typing hints for Mypy 1.1.1
Due to a bump in our Python dependencies, we now install Mypy 1.1.1
instead of 0.982. This change triggered the following errors:

* Incompatible default for argument <a> (default has type
  None, argument has type <t>):

  Mypy further explains here that PEP 484 prohibits implicit Optional,
  so we need to make these types explicit Optional.

* Unused "type: ignore" comment, use narrower [method-assign] instead of
  [assignment]:

  Mypy has specialized some of its lints, meaning that we should switch
  to the newer variants.

Also, it detected several other small inconsistencies. We fix all of
these errors in this commit.
2023-03-27 15:19:43 +03:00
Alex Pyrgiotis
1f308e9cc5
Reformat code with Black 23
Due to a bump in our Python dependencies, we now install Black 23
instead of 22, which detects some of our files as badly formatted.
2023-03-27 15:17:23 +03:00
deeplow
bc50917362
Sort OCR languages when loading them from json
Because now the ocr-languages.json is sorted by tesseract language arg
name, we'll want to sort the languages the user sees alphabetically.
2023-03-16 14:23:31 +00:00
deeplow
e840c7a18c
Fix "Choose..." dialog not opening on Qt6
When clicking on the "Choose..." button nothing would happen visually
and it would show the error:

  Traceback (most recent call last):
    File "/home/user/dangerzone/dangerzone/gui/main_window.py", line 614, in select_output_directory
      dialog.setFileMode(QtWidgets.QFileDialog.DirectoryOnly)

According to the PySide docs, QFileDialog.DirectoryOnly has been
deprecated in Qt4.6 [1]. This was not an issue probably on PySide2
because it must have used an earlier Qt version.

Fixes #360

[1]: https://doc.qt.io/qtforpython-5/PySide2/QtWidgets/QFileDialog.html#PySide2.QtWidgets.PySide2.QtWidgets.QFileDialog.FileMode
2023-03-01 12:49:46 +00:00
Alex Pyrgiotis
79ccd14d5d
Fix PySide2 issue for Ubuntu Focal
Provide a fallback for QRegularExpressionValidator specifically for
Ubuntu Focal, because it's not present in PySide2 5.14. Instead,
fallback to QRegExpValidator if it doesn't exist.

Fixes #339
2023-02-21 20:17:05 +02:00
Alex Pyrgiotis
2042591964
container: Copy files before mounting them
Copy input files in a temporary dir before mounting them, thereby
changing their permissions, without affecting the original files. This
way, we can avoid cases where a file is accessible to the user only due
to a supplemental user group, which does not work for containers.

Fixes #157
Fixes #260
Fixes #335
2023-02-17 01:15:08 +02:00
Alex Pyrgiotis
ea73f5d820
container: Take SELinux labels into account
Take SELinux labels into account when mounting a file to the Dangerzone
container. Use the `:Z` flag (which is a no-op in non-SELinux systems)
to clear the existing SELinux label for a file, and apply one that
matches the container's.

Refs #335
2023-02-17 01:15:08 +02:00
Alex Pyrgiotis
d733890ca0
container: Do not leave stale temporary dirs
Do not leave stale temporary directories when conversion fails
unexpectedly. Instead, wrap the conversion operation in a context
manager that wipes the temporary dir afterwards.

Fixes #317
2023-02-17 01:15:08 +02:00
Alex Pyrgiotis
44c324f9ac
Separate config dirs from temp dirs
Do not store temporary directories in the Dangerzone's config directory.
There are two reasons for that:

1. They are ephemeral, and they need a temporary place to be stored,
   preferably RAM-backed.
2. We need to set them while running our CI tests.
2023-02-17 01:06:44 +02:00
deeplow
9b3d98b20b
Build arm64 docker image for arm-based Macs
Remove --patform args completely so that by default we build natively
on each platform.

Partial fix for #50
2023-02-16 10:59:00 +00:00
Alex Pyrgiotis
93a06d72f0
Allow users to disable timeouts
Allow users to disable timeouts via the CLI, with the
`--disable-timeouts` argument. By default, the timeouts are always
enabled.

This option applies both to the CLI version of Dangerzone, and the GUI
one. For the latter, the user must start the GUI from their CLI (i.e.,
`dangerzone --disable-timeouts ...`)
2023-02-15 23:48:36 +02:00
deeplow
275df80484
GUI: exit with 1 when some conversion failed
Fixes: #318
2023-02-08 17:24:55 +00:00
deeplow
81e9ccf30a
Add PySide6 dependency for Windows and MacOS
We're not yet adding them to Linux, since PySide6 is not yet available
in Linux distros' packages, whereas with Linux and macOS our packaging
process includes the shipped binaries.

Fixes #211
2023-01-30 11:42:18 +00:00
deeplow
ab2f9ead9a
Replace PySide2-stubs with types-PySide2
Replace PySide2-stubs with types-PySide2, both of which are projects
that provide PySide2 typing hints, for the following reasons:

1. types-PySide2 is more complete and allows us to ditch some 'type:
   ignore' comments for Mypy.
2. PySide2-stubs also brings PySide2 as a dependency, which cannot be
   installed in MacOS M1 machines.

Refs #177
2023-01-30 11:42:09 +00:00
deeplow
56b5b98f1e
Report exceptions raised in document conversion
Exceptions raised during the document conversion process would be
silently hidden. This was because ThreadPoolExecuter in logic.py created
various contexts and hid any exceptions raised.

Fixes #309
2023-01-26 18:53:20 +00:00
deeplow
724dd2a71f
Make container-specific methods static
Make these methods callable without having to create an instance of the
Container class. This was needed to make pytest-wrapper.py cleaner.
2023-01-25 14:55:43 +00:00
deeplow
f5c4847af2
De-duplicate print_progress() logic 2023-01-25 14:53:28 +00:00
deeplow
a339eff648
Add dummy conversion to GUI 2023-01-25 14:53:26 +00:00
deeplow
da0cb6b3c5
Add dummy isolation provider to CLI
When enabled, the conversion part does nothing but print some simulated
output. This can be useful for testing non-conversion code (e.g. GUI).

Activated with the hidden flag --unsafe-dummy-conversion.
2023-01-25 14:51:50 +00:00
deeplow
538df18709
Split isolation providers into their own .py files
Provides more clear code organization having each provider in their own
python file rather than a single one.
2023-01-25 14:19:05 +00:00
deeplow
7ed1fd6b59
Isolation-provider-specific methods in _convert()
All isolation providers will some similar steps when convert() is
called. For this reason, all the common parts are captured in convert()
and then each isolation provider implements its own specific conversion
process in _convert() (which is called from the convert() method).
2023-01-25 13:10:39 +00:00
deeplow
a4f27afdc6
Abstract container into an IsolationProvider
Encapsulate container logic into an implementation of
AbstractIsolationProvider. This flexibility will allow for other types
of isolation managers, such as a Dummy one.
2023-01-24 11:03:39 +00:00
deeplow
1114a0dfa1
Rename container.py to isolation_provider.py
First step in encapsulating the isolation provider.
2023-01-24 11:03:36 +00:00
deeplow
b9dc882663
CLI: prefix non-INFO logs with log type
In non-development mode, the CLI shows the user information via the INFO
log level. The message is shown directly without [INFO] as a prefix.
Otherwise it would quickly get annoying to the user seeing [INFO] on
every line of a CLI application.

However, if an error happens it's important for the user to recognize
it's an error or a warning. This commit prints the log level in these
cases.
2023-01-16 14:58:13 +00:00
deeplow
c442c443df
CLI: add missing logging format to non-dev env 2023-01-16 14:50:10 +00:00
deeplow
ad908f5d16
CLI: increase logging from ERROR to INFO level
ERROR level would only show errors and criticals and miss out on all
info-level logging.
2023-01-16 14:50:08 +00:00
deeplow
eb3fd5ae16
CLI: don't print DEBUG logs
The CLI version was mistakenly printing debug logs.
2023-01-16 14:50:06 +00:00
deeplow
c406c95cec
GUI: Add version to header bar
Fixes #219
2023-01-16 14:39:27 +00:00
deeplow
fb3cb98793
Add --version flag 2023-01-16 14:39:24 +00:00
deeplow
aa1476d59b
Replace exit() with sys.exit() to work on Windows
Windows was complaining that 'exit' is not defined.
2022-12-01 15:03:34 +00:00
deeplow
766c455929
Windows: persist "Open safe documents after converting" setting
Now that safe PDFs can open on Windows right after conversion
(implemented in commit 5b2fefd), we need to save/load the "Open safe
documents after converting" setting.
2022-12-01 15:02:31 +00:00
deeplow
7e42994f81
Prevent user from adding files from multiple dirs
Allowing this would lead to several UI edge-cases related to where the
files would be saved. Avoiding this is the easiest solution at the
moment.

In the future we should consider other options.
2022-11-30 12:49:20 +00:00
deeplow
06797ab626
Prevent adding duplicate documents
It was possible that users would add duplicate documents via 'open with
Dangerzone'. This would lead to unexpected situations and preventing it
both in the CLI and the GUI solves those issues.
2022-11-30 12:49:18 +00:00
deeplow
65d0b7a0d0
Allow adding more docs via 'open_with' while in settings
Handle the case where a user has already added some documents (either
through 'open with' or via Dangerzone 'select documents' button) and
then they want to add some more via the 'open_with' dialog.

It updates the settings to reflect the newly added documents and blocks
the user from adding them if a conversion is already in progress.
2022-11-30 12:49:17 +00:00
deeplow
cb68ba7d1c
Centralize 'document adding' in ContentWidget
Makes the ContentWidget a choke-point, where we can allow or prevent
adding more documents and where we can ensure that newly selected
documents are added immediately to the DangerzoneGui class.

Logically, the application flow should not change in any way.
2022-11-30 12:49:16 +00:00
deeplow
ce5558b5a2
Fix "open with" on macOS for single files
Fixes partially #268
2022-11-30 12:49:14 +00:00
deeplow
af5f7c70d3
Quit dangerzone on macOS when window is closed
Closing windows on macOS would not actually close Dangerzone. Now that
it is a single-window program, it makes sense for it to close
immediately.

Fixes #271
2022-11-29 16:01:27 +00:00
deeplow
466d83129e
Increase minimum window width for macOS
The save group box would get partially trimmed when running in macOS
this appears to be due to differences in rendering fonts and widget
sizes.

Refs #270
2022-11-29 15:56:09 +00:00