diff options
author | Felipe Borges <felipeborges@gnome.org> | 2020-01-07 09:43:22 +0100 |
---|---|---|
committer | Ondrej Holy <oholy@redhat.com> | 2021-02-12 16:08:04 +0000 |
commit | 197bc1667f1abdfde81f96257592814562a0b117 (patch) | |
tree | 26054a1bfe02c1aafa14bcfb21180b61467250cd /src/nautilus-file-operations.c | |
parent | 6e3298165c05d7f1d2591f44b29887e22e7a9cb6 (diff) | |
download | nautilus-197bc1667f1abdfde81f96257592814562a0b117.tar.gz |
file-operations: Add support for password protected archives
This implementation launches a GtkDialog for users to enter a password
when gnome-autoar reports that a given archive is password protected.
We use an additional GMainContext to block the execution until a password
string can be passed to AutoarExtractor's "passphrase-request" signal. This
solution is an alternative to gtk_dialog_run(), which is not available
in GTK4. See https://ondrej.holych.net/how-to-call-asynchronous-function-synchronously/
Fixes https://gitlab.gnome.org/GNOME/nautilus/-/issues/327
Diffstat (limited to 'src/nautilus-file-operations.c')
-rw-r--r-- | src/nautilus-file-operations.c | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/src/nautilus-file-operations.c b/src/nautilus-file-operations.c index bb1d04acc..a9ef90f86 100644 --- a/src/nautilus-file-operations.c +++ b/src/nautilus-file-operations.c @@ -8356,6 +8356,94 @@ extract_job_on_completed (AutoarExtractor *extractor, nautilus_file_changes_queue_file_added (output_file); } +typedef struct +{ + GMainLoop *loop; + ExtractJob *extract_job; +} PassphraseRequestData; + +static void +on_request_passphrase_cb (GtkDialog *dialog, + gint response_id, + gpointer user_data) +{ + PassphraseRequestData *data = user_data; + + if (response_id == GTK_RESPONSE_CANCEL || + response_id == GTK_RESPONSE_DELETE_EVENT) + { + abort_job ((CommonJob *) data->extract_job); + } + + g_main_loop_quit (data->loop); +} + +static gchar * +extract_job_on_request_passphrase (AutoarExtractor *extractor, + gpointer user_data) +{ + PassphraseRequestData data; + g_autoptr (GMainContext) context = NULL; + g_autoptr (GMainLoop) loop = NULL; + ExtractJob *extract_job = user_data; + g_autofree gchar *label_str = NULL; + g_autofree gchar *basename = NULL; + GtkWidget *dialog; + GtkWidget *entry; + GtkWidget *label; + GtkWidget *box; + GFile *source_file; + gchar *passphrase; + + context = g_main_context_new (); + loop = g_main_loop_new (context, FALSE); + g_main_context_push_thread_default (context); + + data.extract_job = extract_job; + data.loop = loop; + dialog = gtk_dialog_new_with_buttons (_("Password Required"), + extract_job->common.parent_window, + GTK_DIALOG_USE_HEADER_BAR | GTK_DIALOG_MODAL, + _("Cancel"), GTK_RESPONSE_CANCEL, + _("Extract"), GTK_RESPONSE_OK, + NULL); + gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); + source_file = autoar_extractor_get_source_file (extractor); + basename = get_basename (source_file); + + box = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); + gtk_widget_set_margin_start (box, 20); + gtk_widget_set_margin_end (box, 20); + gtk_widget_set_margin_top (box, 20); + gtk_widget_set_margin_bottom (box, 20); + + label_str = g_strdup_printf (_("“%s” is password-protected."), basename); + label = gtk_label_new (label_str); + gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); + gtk_label_set_max_width_chars (GTK_LABEL (label), 60); + gtk_container_add (GTK_CONTAINER (box), label); + + entry = gtk_entry_new (); + gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE); + gtk_widget_set_valign (entry, GTK_ALIGN_END); + gtk_widget_set_vexpand (entry, TRUE); + gtk_entry_set_placeholder_text (GTK_ENTRY (entry), _("Enter password…")); + gtk_entry_set_visibility (GTK_ENTRY (entry), FALSE); + gtk_entry_set_input_purpose (GTK_ENTRY (entry), GTK_INPUT_PURPOSE_PASSWORD); + gtk_container_add (GTK_CONTAINER (box), entry); + + g_signal_connect (dialog, "response", G_CALLBACK (on_request_passphrase_cb), &data); + gtk_widget_show_all (dialog); + + g_main_loop_run (loop); + passphrase = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry))); + + g_main_context_pop_thread_default (context); + gtk_widget_destroy (GTK_WIDGET (dialog)); + + return passphrase; +} + static void extract_job_on_scanned (AutoarExtractor *extractor, guint total_files, @@ -8516,6 +8604,9 @@ extract_task_thread_func (GTask *task, g_signal_connect (extractor, "completed", G_CALLBACK (extract_job_on_completed), extract_job); + g_signal_connect (extractor, "request-passphrase", + G_CALLBACK (extract_job_on_request_passphrase), + extract_job); extract_job->archive_compressed_size = archive_compressed_sizes[i]; |