Blame SOURCES/compress-dialog-Add-support-for-encrypted-.zip.patch

8be0b6
From 98c79d46ab05bd86fc1309d9ae560edc19f62071 Mon Sep 17 00:00:00 2001
8be0b6
From: Ondrej Holy <oholy@redhat.com>
8be0b6
Date: Fri, 30 Jul 2021 10:52:55 +0200
8be0b6
Subject: [PATCH] compress-dialog: Add support for encrypted .zip
8be0b6
8be0b6
Currently, it is not possible to create encrypted archives over
8be0b6
Nautilus. Let's add support for encrypted .zip files to not have
8be0b6
to install a dedicated archive manager.
8be0b6
8be0b6
Fixes: https://gitlab.gnome.org/GNOME/nautilus/-/issues/822
8be0b6
---
8be0b6
 data/org.gnome.nautilus.gschema.xml          |   1 +
8be0b6
 meson.build                                  |   2 +-
8be0b6
 src/nautilus-compress-dialog-controller.c    | 136 +++++++++++++++++++
8be0b6
 src/nautilus-compress-dialog-controller.h    |   1 +
8be0b6
 src/nautilus-file-operations.c               |   8 +-
8be0b6
 src/nautilus-file-operations.h               |   1 +
8be0b6
 src/nautilus-file-undo-operations.c          |   7 +-
8be0b6
 src/nautilus-file-undo-operations.h          |   3 +-
8be0b6
 src/nautilus-files-view.c                    |  10 ++
8be0b6
 src/nautilus-global-preferences.h            |   3 +-
8be0b6
 src/resources/css/nautilus.css               |   9 ++
8be0b6
 src/resources/ui/nautilus-compress-dialog.ui |  57 ++++++++
8be0b6
 12 files changed, 233 insertions(+), 5 deletions(-)
8be0b6
8be0b6
diff --git a/data/org.gnome.nautilus.gschema.xml b/data/org.gnome.nautilus.gschema.xml
8be0b6
index 3f89466de..7585be8cd 100644
8be0b6
--- a/data/org.gnome.nautilus.gschema.xml
8be0b6
+++ b/data/org.gnome.nautilus.gschema.xml
8be0b6
@@ -65,6 +65,7 @@
8be0b6
     <value value="0" nick="zip"/>
8be0b6
     <value value="1" nick="tar.xz"/>
8be0b6
     <value value="2" nick="7z"/>
8be0b6
+    <value value="3" nick="encrypted_zip"/>
8be0b6
   </enum>
8be0b6
 
8be0b6
   <schema path="/org/gnome/nautilus/" id="org.gnome.nautilus" gettext-domain="nautilus">
8be0b6
diff --git a/meson.build b/meson.build
8be0b6
index d5316475d..446b25614 100644
8be0b6
--- a/meson.build
8be0b6
+++ b/meson.build
8be0b6
@@ -117,7 +117,7 @@ gio = dependency('gio-2.0', version: glib_ver)
8be0b6
 gio_unix = dependency('gio-unix-2.0', version: glib_ver)
8be0b6
 glib = dependency('glib-2.0', version: glib_ver)
8be0b6
 gmodule = dependency('gmodule-no-export-2.0', version: glib_ver)
8be0b6
-gnome_autoar = dependency('gnome-autoar-0', version: '>= 0.3.0')
8be0b6
+gnome_autoar = dependency('gnome-autoar-0', version: '>= 0.4.0')
8be0b6
 gnome_desktop = dependency('gnome-desktop-3.0', version: '>= 3.0.0')
8be0b6
 gtk = dependency('gtk+-3.0', version: '>= 3.22.27')
8be0b6
 libhandy = dependency('libhandy-1', version: '>= 1.1.90')
8be0b6
diff --git a/src/nautilus-compress-dialog-controller.c b/src/nautilus-compress-dialog-controller.c
8be0b6
index 154573c0f..e1ba5a803 100644
8be0b6
--- a/src/nautilus-compress-dialog-controller.c
8be0b6
+++ b/src/nautilus-compress-dialog-controller.c
8be0b6
@@ -32,17 +32,24 @@ struct _NautilusCompressDialogController
8be0b6
     NautilusFileNameWidgetController parent_instance;
8be0b6
 
8be0b6
     GtkWidget *compress_dialog;
8be0b6
+    GtkWidget *activate_button;
8be0b6
+    GtkWidget *error_label;
8be0b6
     GtkWidget *name_entry;
8be0b6
     GtkWidget *extension_stack;
8be0b6
     GtkWidget *zip_label;
8be0b6
+    GtkWidget *encrypted_zip_label;
8be0b6
     GtkWidget *tar_xz_label;
8be0b6
     GtkWidget *seven_zip_label;
8be0b6
     GtkWidget *extension_popover;
8be0b6
     GtkWidget *zip_checkmark;
8be0b6
+    GtkWidget *encrypted_zip_checkmark;
8be0b6
     GtkWidget *tar_xz_checkmark;
8be0b6
     GtkWidget *seven_zip_checkmark;
8be0b6
+    GtkWidget *passphrase_label;
8be0b6
+    GtkWidget *passphrase_entry;
8be0b6
 
8be0b6
     const char *extension;
8be0b6
+    gchar *passphrase;
8be0b6
 
8be0b6
     gulong response_handler_id;
8be0b6
 };
8be0b6
@@ -142,6 +149,7 @@ update_selected_format (NautilusCompressDialogController *self,
8be0b6
     const char *extension;
8be0b6
     GtkWidget *active_label;
8be0b6
     GtkWidget *active_checkmark;
8be0b6
+    gboolean show_passphrase = FALSE;
8be0b6
 
8be0b6
     switch (format)
8be0b6
     {
8be0b6
@@ -153,6 +161,15 @@ update_selected_format (NautilusCompressDialogController *self,
8be0b6
         }
8be0b6
         break;
8be0b6
 
8be0b6
+        case NAUTILUS_COMPRESSION_ENCRYPTED_ZIP:
8be0b6
+        {
8be0b6
+            extension = ".zip";
8be0b6
+            active_label = self->encrypted_zip_label;
8be0b6
+            active_checkmark = self->encrypted_zip_checkmark;
8be0b6
+            show_passphrase = TRUE;
8be0b6
+        }
8be0b6
+        break;
8be0b6
+
8be0b6
         case NAUTILUS_COMPRESSION_TAR_XZ:
8be0b6
         {
8be0b6
             extension = ".tar.xz";
8be0b6
@@ -178,12 +195,26 @@ update_selected_format (NautilusCompressDialogController *self,
8be0b6
 
8be0b6
     self->extension = extension;
8be0b6
 
8be0b6
+    gtk_widget_set_visible (self->passphrase_label, show_passphrase);
8be0b6
+    gtk_widget_set_visible (self->passphrase_entry, show_passphrase);
8be0b6
+    if (!show_passphrase)
8be0b6
+    {
8be0b6
+        gtk_entry_set_text (GTK_ENTRY (self->passphrase_entry), "");
8be0b6
+        gtk_entry_set_visibility (GTK_ENTRY (self->passphrase_entry), FALSE);
8be0b6
+        gtk_entry_set_icon_from_icon_name (GTK_ENTRY (self->passphrase_entry),
8be0b6
+                                           GTK_ENTRY_ICON_SECONDARY,
8be0b6
+                                           "view-conceal");
8be0b6
+    }
8be0b6
+
8be0b6
     gtk_stack_set_visible_child (GTK_STACK (self->extension_stack),
8be0b6
                                  active_label);
8be0b6
 
8be0b6
     gtk_image_set_from_icon_name (GTK_IMAGE (self->zip_checkmark),
8be0b6
                                   NULL,
8be0b6
                                   GTK_ICON_SIZE_BUTTON);
8be0b6
+    gtk_image_set_from_icon_name (GTK_IMAGE (self->encrypted_zip_checkmark),
8be0b6
+                                  NULL,
8be0b6
+                                  GTK_ICON_SIZE_BUTTON);
8be0b6
     gtk_image_set_from_icon_name (GTK_IMAGE (self->tar_xz_checkmark),
8be0b6
                                   NULL,
8be0b6
                                   GTK_ICON_SIZE_BUTTON);
8be0b6
@@ -200,6 +231,7 @@ update_selected_format (NautilusCompressDialogController *self,
8be0b6
     /* Since the extension changes when the button is toggled, force a
8be0b6
      * verification of the new file name by simulating an entry change
8be0b6
      */
8be0b6
+    gtk_widget_set_sensitive (self->activate_button, FALSE);
8be0b6
     g_signal_emit_by_name (self->name_entry, "changed");
8be0b6
 }
8be0b6
 
8be0b6
@@ -216,6 +248,19 @@ zip_row_on_activated (HdyActionRow *row,
8be0b6
                             NAUTILUS_COMPRESSION_ZIP);
8be0b6
 }
8be0b6
 
8be0b6
+static void
8be0b6
+encrypted_zip_row_on_activated (HdyActionRow *row,
8be0b6
+                                gpointer      user_data)
8be0b6
+{
8be0b6
+    NautilusCompressDialogController *controller;
8be0b6
+
8be0b6
+    controller = NAUTILUS_COMPRESS_DIALOG_CONTROLLER (user_data);
8be0b6
+
8be0b6
+    gtk_popover_popdown (GTK_POPOVER (controller->extension_popover));
8be0b6
+    update_selected_format (controller,
8be0b6
+                            NAUTILUS_COMPRESSION_ENCRYPTED_ZIP);
8be0b6
+}
8be0b6
+
8be0b6
 static void
8be0b6
 tar_xz_row_on_activated (HdyActionRow *row,
8be0b6
                          gpointer      user_data)
8be0b6
@@ -242,6 +287,67 @@ seven_zip_row_on_activated (HdyActionRow *row,
8be0b6
                             NAUTILUS_COMPRESSION_7ZIP);
8be0b6
 }
8be0b6
 
8be0b6
+static void
8be0b6
+passphrase_entry_on_changed (GtkEditable *editable,
8be0b6
+                             gpointer     user_data)
8be0b6
+{
8be0b6
+    NautilusCompressDialogController *self;
8be0b6
+    const gchar *error_message;
8be0b6
+
8be0b6
+    self = NAUTILUS_COMPRESS_DIALOG_CONTROLLER (user_data);
8be0b6
+
8be0b6
+    g_free (self->passphrase);
8be0b6
+    self->passphrase = g_strdup (gtk_entry_get_text (GTK_ENTRY (self->passphrase_entry)));
8be0b6
+
8be0b6
+    /* Simulate a change of the name_entry to ensure the correct sensitivity of
8be0b6
+     * the activate_button, but only if the name_entry is valid in order to
8be0b6
+     * avoid changes of the error_revealer.
8be0b6
+     */
8be0b6
+    error_message = gtk_label_get_text (GTK_LABEL (self->error_label));
8be0b6
+    if (error_message[0] == '\0')
8be0b6
+    {
8be0b6
+        gtk_widget_set_sensitive (self->activate_button, FALSE);
8be0b6
+        g_signal_emit_by_name (self->name_entry, "changed");
8be0b6
+    }
8be0b6
+}
8be0b6
+
8be0b6
+static void
8be0b6
+passphrase_entry_on_icon_press (GtkEntry             *entry,
8be0b6
+                                GtkEntryIconPosition  icon_pos,
8be0b6
+                                GdkEvent             *event,
8be0b6
+                                gpointer              user_data)
8be0b6
+{
8be0b6
+    NautilusCompressDialogController *self;
8be0b6
+    gboolean visibility;
8be0b6
+
8be0b6
+    self = NAUTILUS_COMPRESS_DIALOG_CONTROLLER (user_data);
8be0b6
+    visibility = gtk_entry_get_visibility (GTK_ENTRY (self->passphrase_entry));
8be0b6
+
8be0b6
+    gtk_entry_set_icon_from_icon_name (GTK_ENTRY (self->passphrase_entry),
8be0b6
+                                       GTK_ENTRY_ICON_SECONDARY,
8be0b6
+                                       visibility ? "view-conceal" : "view-reveal");
8be0b6
+    gtk_entry_set_visibility (GTK_ENTRY (self->passphrase_entry), !visibility);
8be0b6
+}
8be0b6
+
8be0b6
+static void
8be0b6
+activate_button_on_sensitive_notify (GObject    *gobject,
8be0b6
+                                     GParamSpec *pspec,
8be0b6
+                                     gpointer    user_data)
8be0b6
+{
8be0b6
+    NautilusCompressDialogController *self;
8be0b6
+    NautilusCompressionFormat format;
8be0b6
+
8be0b6
+    self = NAUTILUS_COMPRESS_DIALOG_CONTROLLER (user_data);
8be0b6
+    format = g_settings_get_enum (nautilus_compression_preferences,
8be0b6
+                                  NAUTILUS_PREFERENCES_DEFAULT_COMPRESSION_FORMAT);
8be0b6
+    if (format == NAUTILUS_COMPRESSION_ENCRYPTED_ZIP &&
8be0b6
+        (self->passphrase == NULL || self->passphrase[0] == '\0'))
8be0b6
+    {
8be0b6
+        /* Reset sensitivity of the activate_button if password is not set. */
8be0b6
+        gtk_widget_set_sensitive (self->activate_button, FALSE);
8be0b6
+    }
8be0b6
+}
8be0b6
+
8be0b6
 NautilusCompressDialogController *
8be0b6
 nautilus_compress_dialog_controller_new (GtkWindow         *parent_window,
8be0b6
                                          NautilusDirectory *destination_directory,
8be0b6
@@ -256,12 +362,16 @@ nautilus_compress_dialog_controller_new (GtkWindow         *parent_window,
8be0b6
     GtkWidget *activate_button;
8be0b6
     GtkWidget *extension_stack;
8be0b6
     GtkWidget *zip_label;
8be0b6
+    GtkWidget *encrypted_zip_label;
8be0b6
     GtkWidget *tar_xz_label;
8be0b6
     GtkWidget *seven_zip_label;
8be0b6
     GtkWidget *extension_popover;
8be0b6
     GtkWidget *zip_checkmark;
8be0b6
+    GtkWidget *encrypted_zip_checkmark;
8be0b6
     GtkWidget *tar_xz_checkmark;
8be0b6
     GtkWidget *seven_zip_checkmark;
8be0b6
+    GtkWidget *passphrase_label;
8be0b6
+    GtkWidget *passphrase_entry;
8be0b6
     NautilusCompressionFormat format;
8be0b6
 
8be0b6
     builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/ui/nautilus-compress-dialog.ui");
8be0b6
@@ -272,12 +382,16 @@ nautilus_compress_dialog_controller_new (GtkWindow         *parent_window,
8be0b6
     activate_button = GTK_WIDGET (gtk_builder_get_object (builder, "activate_button"));
8be0b6
     extension_stack = GTK_WIDGET (gtk_builder_get_object (builder, "extension_stack"));
8be0b6
     zip_label = GTK_WIDGET (gtk_builder_get_object (builder, "zip_label"));
8be0b6
+    encrypted_zip_label = GTK_WIDGET (gtk_builder_get_object (builder, "encrypted_zip_label"));
8be0b6
     tar_xz_label = GTK_WIDGET (gtk_builder_get_object (builder, "tar_xz_label"));
8be0b6
     seven_zip_label = GTK_WIDGET (gtk_builder_get_object (builder, "seven_zip_label"));
8be0b6
     extension_popover = GTK_WIDGET (gtk_builder_get_object (builder, "extension_popover"));
8be0b6
     zip_checkmark = GTK_WIDGET (gtk_builder_get_object (builder, "zip_checkmark"));
8be0b6
+    encrypted_zip_checkmark = GTK_WIDGET (gtk_builder_get_object (builder, "encrypted_zip_checkmark"));
8be0b6
     tar_xz_checkmark = GTK_WIDGET (gtk_builder_get_object (builder, "tar_xz_checkmark"));
8be0b6
     seven_zip_checkmark = GTK_WIDGET (gtk_builder_get_object (builder, "seven_zip_checkmark"));
8be0b6
+    passphrase_label = GTK_WIDGET (gtk_builder_get_object (builder, "passphrase_label"));
8be0b6
+    passphrase_entry = GTK_WIDGET (gtk_builder_get_object (builder, "passphrase_entry"));
8be0b6
 
8be0b6
     gtk_window_set_transient_for (GTK_WINDOW (compress_dialog),
8be0b6
                                   parent_window);
8be0b6
@@ -290,16 +404,22 @@ nautilus_compress_dialog_controller_new (GtkWindow         *parent_window,
8be0b6
                          "containing-directory", destination_directory, NULL);
8be0b6
 
8be0b6
     self->compress_dialog = compress_dialog;
8be0b6
+    self->activate_button = activate_button;
8be0b6
+    self->error_label = error_label;
8be0b6
     self->extension_stack = extension_stack;
8be0b6
     self->zip_label = zip_label;
8be0b6
+    self->encrypted_zip_label = encrypted_zip_label;
8be0b6
     self->tar_xz_label = tar_xz_label;
8be0b6
     self->seven_zip_label = seven_zip_label;
8be0b6
     self->name_entry = name_entry;
8be0b6
     self->extension_popover = extension_popover;
8be0b6
     self->zip_checkmark = zip_checkmark;
8be0b6
+    self->encrypted_zip_checkmark = encrypted_zip_checkmark;
8be0b6
     self->tar_xz_checkmark = tar_xz_checkmark;
8be0b6
     self->seven_zip_checkmark = seven_zip_checkmark;
8be0b6
     self->name_entry = name_entry;
8be0b6
+    self->passphrase_label = passphrase_label;
8be0b6
+    self->passphrase_entry = passphrase_entry;
8be0b6
 
8be0b6
     self->response_handler_id = g_signal_connect (compress_dialog,
8be0b6
                                                   "response",
8be0b6
@@ -309,10 +429,18 @@ nautilus_compress_dialog_controller_new (GtkWindow         *parent_window,
8be0b6
     gtk_builder_add_callback_symbols (builder,
8be0b6
                                       "zip_row_on_activated",
8be0b6
                                       G_CALLBACK (zip_row_on_activated),
8be0b6
+                                      "encrypted_zip_row_on_activated",
8be0b6
+                                      G_CALLBACK (encrypted_zip_row_on_activated),
8be0b6
                                       "tar_xz_row_on_activated",
8be0b6
                                       G_CALLBACK (tar_xz_row_on_activated),
8be0b6
                                       "seven_zip_row_on_activated",
8be0b6
                                       G_CALLBACK (seven_zip_row_on_activated),
8be0b6
+                                      "passphrase_entry_on_changed",
8be0b6
+                                      G_CALLBACK (passphrase_entry_on_changed),
8be0b6
+                                      "passphrase_entry_on_icon_press",
8be0b6
+                                      G_CALLBACK (passphrase_entry_on_icon_press),
8be0b6
+                                      "activate_button_on_sensitive_notify",
8be0b6
+                                      G_CALLBACK (activate_button_on_sensitive_notify),
8be0b6
                                       NULL);
8be0b6
     gtk_builder_connect_signals (builder, self);
8be0b6
 
8be0b6
@@ -350,6 +478,8 @@ nautilus_compress_dialog_controller_finalize (GObject *object)
8be0b6
         self->compress_dialog = NULL;
8be0b6
     }
8be0b6
 
8be0b6
+    g_free (self->passphrase);
8be0b6
+
8be0b6
     G_OBJECT_CLASS (nautilus_compress_dialog_controller_parent_class)->finalize (object);
8be0b6
 }
8be0b6
 
8be0b6
@@ -364,3 +494,9 @@ nautilus_compress_dialog_controller_class_init (NautilusCompressDialogController
8be0b6
     parent_class->get_new_name = nautilus_compress_dialog_controller_get_new_name;
8be0b6
     parent_class->name_is_valid = nautilus_compress_dialog_controller_name_is_valid;
8be0b6
 }
8be0b6
+
8be0b6
+const gchar *
8be0b6
+nautilus_compress_dialog_controller_get_passphrase (NautilusCompressDialogController *self)
8be0b6
+{
8be0b6
+    return self->passphrase;
8be0b6
+}
8be0b6
diff --git a/src/nautilus-compress-dialog-controller.h b/src/nautilus-compress-dialog-controller.h
8be0b6
index 2421b8115..6c96d68fa 100644
8be0b6
--- a/src/nautilus-compress-dialog-controller.h
8be0b6
+++ b/src/nautilus-compress-dialog-controller.h
8be0b6
@@ -31,3 +31,4 @@ G_DECLARE_FINAL_TYPE (NautilusCompressDialogController, nautilus_compress_dialog
8be0b6
 NautilusCompressDialogController * nautilus_compress_dialog_controller_new (GtkWindow         *parent_window,
8be0b6
                                                                             NautilusDirectory *destination_directory,
8be0b6
                                                                             gchar             *initial_name);
8be0b6
+const gchar * nautilus_compress_dialog_controller_get_passphrase (NautilusCompressDialogController *controller);
8be0b6
diff --git a/src/nautilus-file-operations.c b/src/nautilus-file-operations.c
8be0b6
index 59beecd7e..f909173f9 100644
8be0b6
--- a/src/nautilus-file-operations.c
8be0b6
+++ b/src/nautilus-file-operations.c
8be0b6
@@ -222,6 +222,7 @@ typedef struct
8be0b6
 
8be0b6
     AutoarFormat format;
8be0b6
     AutoarFilter filter;
8be0b6
+    gchar *passphrase;
8be0b6
 
8be0b6
     guint64 total_size;
8be0b6
     guint total_files;
8be0b6
@@ -8753,6 +8754,7 @@ compress_task_done (GObject      *source_object,
8be0b6
 
8be0b6
     g_object_unref (compress_job->output_file);
8be0b6
     g_list_free_full (compress_job->source_files, g_object_unref);
8be0b6
+    g_free (compress_job->passphrase);
8be0b6
 
8be0b6
     finalize_common ((CommonJob *) compress_job);
8be0b6
 
8be0b6
@@ -9027,6 +9029,7 @@ compress_task_thread_func (GTask        *task,
8be0b6
                                         compress_job->format,
8be0b6
                                         compress_job->filter,
8be0b6
                                         FALSE);
8be0b6
+    autoar_compressor_set_passphrase (compressor, compress_job->passphrase);
8be0b6
 
8be0b6
     autoar_compressor_set_output_is_dest (compressor, TRUE);
8be0b6
 
8be0b6
@@ -9057,6 +9060,7 @@ nautilus_file_operations_compress (GList                          *files,
8be0b6
                                    GFile                          *output,
8be0b6
                                    AutoarFormat                    format,
8be0b6
                                    AutoarFilter                    filter,
8be0b6
+                                   const gchar                    *passphrase,
8be0b6
                                    GtkWindow                      *parent_window,
8be0b6
                                    NautilusFileOperationsDBusData *dbus_data,
8be0b6
                                    NautilusCreateCallback          done_callback,
8be0b6
@@ -9072,6 +9076,7 @@ nautilus_file_operations_compress (GList                          *files,
8be0b6
     compress_job->output_file = g_object_ref (output);
8be0b6
     compress_job->format = format;
8be0b6
     compress_job->filter = filter;
8be0b6
+    compress_job->passphrase = g_strdup (passphrase);
8be0b6
     compress_job->done_callback = done_callback;
8be0b6
     compress_job->done_callback_data = done_callback_data;
8be0b6
 
8be0b6
@@ -9082,7 +9087,8 @@ nautilus_file_operations_compress (GList                          *files,
8be0b6
         compress_job->common.undo_info = nautilus_file_undo_info_compress_new (files,
8be0b6
                                                                                output,
8be0b6
                                                                                format,
8be0b6
-                                                                               filter);
8be0b6
+                                                                               filter,
8be0b6
+                                                                               passphrase);
8be0b6
     }
8be0b6
 
8be0b6
     task = g_task_new (NULL, compress_job->common.cancellable,
8be0b6
diff --git a/src/nautilus-file-operations.h b/src/nautilus-file-operations.h
8be0b6
index 8236e0e06..14d664f80 100644
8be0b6
--- a/src/nautilus-file-operations.h
8be0b6
+++ b/src/nautilus-file-operations.h
8be0b6
@@ -159,6 +159,7 @@ void nautilus_file_operations_compress (GList                          *files,
8be0b6
                                         GFile                          *output,
8be0b6
                                         AutoarFormat                    format,
8be0b6
                                         AutoarFilter                    filter,
8be0b6
+                                        const gchar                    *passphrase,
8be0b6
                                         GtkWindow                      *parent_window,
8be0b6
                                         NautilusFileOperationsDBusData *dbus_data,
8be0b6
                                         NautilusCreateCallback          done_callback,
8be0b6
diff --git a/src/nautilus-file-undo-operations.c b/src/nautilus-file-undo-operations.c
8be0b6
index a6a3b2025..64f9ce76c 100644
8be0b6
--- a/src/nautilus-file-undo-operations.c
8be0b6
+++ b/src/nautilus-file-undo-operations.c
8be0b6
@@ -2495,6 +2495,7 @@ struct _NautilusFileUndoInfoCompress
8be0b6
     GFile *output;
8be0b6
     AutoarFormat format;
8be0b6
     AutoarFilter filter;
8be0b6
+    gchar *passphrase;
8be0b6
 };
8be0b6
 
8be0b6
 G_DEFINE_TYPE (NautilusFileUndoInfoCompress, nautilus_file_undo_info_compress, NAUTILUS_TYPE_FILE_UNDO_INFO)
8be0b6
@@ -2562,6 +2563,7 @@ compress_redo_func (NautilusFileUndoInfo           *info,
8be0b6
                                        self->output,
8be0b6
                                        self->format,
8be0b6
                                        self->filter,
8be0b6
+                                       self->passphrase,
8be0b6
                                        parent_window,
8be0b6
                                        dbus_data,
8be0b6
                                        compress_callback,
8be0b6
@@ -2597,6 +2599,7 @@ nautilus_file_undo_info_compress_finalize (GObject *obj)
8be0b6
 
8be0b6
     g_list_free_full (self->sources, g_object_unref);
8be0b6
     g_clear_object (&self->output);
8be0b6
+    g_free (self->passphrase);
8be0b6
 
8be0b6
     G_OBJECT_CLASS (nautilus_file_undo_info_compress_parent_class)->finalize (obj);
8be0b6
 }
8be0b6
@@ -2618,7 +2621,8 @@ NautilusFileUndoInfo *
8be0b6
 nautilus_file_undo_info_compress_new (GList        *sources,
8be0b6
                                       GFile        *output,
8be0b6
                                       AutoarFormat  format,
8be0b6
-                                      AutoarFilter  filter)
8be0b6
+                                      AutoarFilter  filter,
8be0b6
+                                      const gchar  *passphrase)
8be0b6
 {
8be0b6
     NautilusFileUndoInfoCompress *self;
8be0b6
 
8be0b6
@@ -2631,6 +2635,7 @@ nautilus_file_undo_info_compress_new (GList        *sources,
8be0b6
     self->output = g_object_ref (output);
8be0b6
     self->format = format;
8be0b6
     self->filter = filter;
8be0b6
+    self->passphrase = g_strdup (passphrase);
8be0b6
 
8be0b6
     return NAUTILUS_FILE_UNDO_INFO (self);
8be0b6
 }
8be0b6
diff --git a/src/nautilus-file-undo-operations.h b/src/nautilus-file-undo-operations.h
8be0b6
index f96f2fe69..09ae17cef 100644
8be0b6
--- a/src/nautilus-file-undo-operations.h
8be0b6
+++ b/src/nautilus-file-undo-operations.h
8be0b6
@@ -226,4 +226,5 @@ G_DECLARE_FINAL_TYPE (NautilusFileUndoInfoCompress, nautilus_file_undo_info_comp
8be0b6
 NautilusFileUndoInfo * nautilus_file_undo_info_compress_new (GList        *sources,
8be0b6
                                                              GFile        *output,
8be0b6
                                                              AutoarFormat  format,
8be0b6
-                                                             AutoarFilter  filter);
8be0b6
+                                                             AutoarFilter  filter,
8be0b6
+                                                             const gchar  *passphrase);
8be0b6
diff --git a/src/nautilus-files-view.c b/src/nautilus-files-view.c
8be0b6
index b4a91226b..47aed3cc1 100644
8be0b6
--- a/src/nautilus-files-view.c
8be0b6
+++ b/src/nautilus-files-view.c
8be0b6
@@ -2235,6 +2235,7 @@ compress_dialog_controller_on_name_accepted (NautilusFileNameWidgetController *c
8be0b6
     NautilusFilesViewPrivate *priv;
8be0b6
     AutoarFormat format;
8be0b6
     AutoarFilter filter;
8be0b6
+    const gchar *passphrase = NULL;
8be0b6
 
8be0b6
     view = NAUTILUS_FILES_VIEW (callback_data->view);
8be0b6
     priv = nautilus_files_view_get_instance_private (view);
8be0b6
@@ -2280,6 +2281,14 @@ compress_dialog_controller_on_name_accepted (NautilusFileNameWidgetController *c
8be0b6
         }
8be0b6
         break;
8be0b6
 
8be0b6
+        case NAUTILUS_COMPRESSION_ENCRYPTED_ZIP:
8be0b6
+        {
8be0b6
+            format = AUTOAR_FORMAT_ZIP;
8be0b6
+            filter = AUTOAR_FILTER_NONE;
8be0b6
+            passphrase = nautilus_compress_dialog_controller_get_passphrase (priv->compress_controller);
8be0b6
+        }
8be0b6
+        break;
8be0b6
+
8be0b6
         case NAUTILUS_COMPRESSION_TAR_XZ:
8be0b6
         {
8be0b6
             format = AUTOAR_FORMAT_TAR;
8be0b6
@@ -2301,6 +2310,7 @@ compress_dialog_controller_on_name_accepted (NautilusFileNameWidgetController *c
8be0b6
     nautilus_file_operations_compress (source_files, output,
8be0b6
                                        format,
8be0b6
                                        filter,
8be0b6
+                                       passphrase,
8be0b6
                                        nautilus_files_view_get_containing_window (view),
8be0b6
                                        NULL,
8be0b6
                                        compress_done,
8be0b6
diff --git a/src/nautilus-global-preferences.h b/src/nautilus-global-preferences.h
8be0b6
index 8c482f7ce..2e8753b3c 100644
8be0b6
--- a/src/nautilus-global-preferences.h
8be0b6
+++ b/src/nautilus-global-preferences.h
8be0b6
@@ -77,7 +77,8 @@ typedef enum
8be0b6
 {
8be0b6
         NAUTILUS_COMPRESSION_ZIP = 0,
8be0b6
         NAUTILUS_COMPRESSION_TAR_XZ,
8be0b6
-        NAUTILUS_COMPRESSION_7ZIP
8be0b6
+        NAUTILUS_COMPRESSION_7ZIP,
8be0b6
+        NAUTILUS_COMPRESSION_ENCRYPTED_ZIP
8be0b6
 } NautilusCompressionFormat;
8be0b6
 
8be0b6
 /* Icon View */
8be0b6
diff --git a/src/resources/css/nautilus.css b/src/resources/css/nautilus.css
8be0b6
index 2e46b7abe..ee25a36a8 100644
8be0b6
--- a/src/resources/css/nautilus.css
8be0b6
+++ b/src/resources/css/nautilus.css
8be0b6
@@ -3,3 +3,12 @@
8be0b6
     padding-left: 5px;
8be0b6
     padding-right: 5px;
8be0b6
 }
8be0b6
+
8be0b6
+label.encrypted_zip,
8be0b6
+row.encrypted_zip label.title {
8be0b6
+    background-image: -gtk-icontheme('system-lock-screen-symbolic');
8be0b6
+    background-position: right center;
8be0b6
+    background-repeat: no-repeat;
8be0b6
+    background-size: 16px 16px;
8be0b6
+    padding-right: 24px;
8be0b6
+}
8be0b6
diff --git a/src/resources/ui/nautilus-compress-dialog.ui b/src/resources/ui/nautilus-compress-dialog.ui
8be0b6
index b36539294..a57765eed 100644
8be0b6
--- a/src/resources/ui/nautilus-compress-dialog.ui
8be0b6
+++ b/src/resources/ui/nautilus-compress-dialog.ui
8be0b6
@@ -28,6 +28,26 @@
8be0b6
             </child>
8be0b6
           </object>
8be0b6
         </child>
8be0b6
+        <child>
8be0b6
+          <object class="HdyActionRow" id="encrypted_zip_row">
8be0b6
+            <property name="visible">True</property>
8be0b6
+            <property name="activatable">True</property>
8be0b6
+            <property name="title" translatable="no">.zip</property>
8be0b6
+            <property name="subtitle" translatable="yes">Password protected .zip, must be installed on Windows and Mac.</property>
8be0b6
+            <signal name="activated" handler="encrypted_zip_row_on_activated"/>
8be0b6
+            <style>
8be0b6
+              <class name="encrypted_zip"/>
8be0b6
+            </style>
8be0b6
+            <child>
8be0b6
+              <object class="GtkImage" id="encrypted_zip_checkmark">
8be0b6
+                <property name="visible">True</property>
8be0b6
+                <property name="width-request">16</property>
8be0b6
+                <property name="margin-start">12</property>
8be0b6
+                <property name="margin-end">12</property>
8be0b6
+              </object>
8be0b6
+            </child>
8be0b6
+          </object>
8be0b6
+        </child>
8be0b6
         <child>
8be0b6
           <object class="HdyActionRow">
8be0b6
             <property name="visible">True</property>
8be0b6
@@ -129,6 +149,15 @@
8be0b6
                             <property name="xalign">0</property>
8be0b6
                           </object>
8be0b6
                         </child>
8be0b6
+                        <child>
8be0b6
+                          <object class="GtkLabel" id="encrypted_zip_label">
8be0b6
+                            <property name="label" translatable="no">.zip</property>
8be0b6
+                            <property name="xalign">0</property>
8be0b6
+                            <style>
8be0b6
+                              <class name="encrypted_zip"/>
8be0b6
+                            </style>
8be0b6
+                          </object>
8be0b6
+                        </child>
8be0b6
                         <child>
8be0b6
                           <object class="GtkLabel" id="tar_xz_label">
8be0b6
                             <property name="label" translatable="no">.tar.xz</property>
8be0b6
@@ -179,6 +208,33 @@
8be0b6
             <property name="position">3</property>
8be0b6
           </packing>
8be0b6
         </child>
8be0b6
+        <child>
8be0b6
+          <object class="GtkLabel" id="passphrase_label">
8be0b6
+            <property name="label" translatable="yes">Password</property>
8be0b6
+            <property name="margin-top">6</property>
8be0b6
+            <property name="xalign">0</property>
8be0b6
+          </object>
8be0b6
+          <packing>
8be0b6
+            <property name="expand">False</property>
8be0b6
+            <property name="fill">True</property>
8be0b6
+            <property name="position">4</property>
8be0b6
+          </packing>
8be0b6
+        </child>
8be0b6
+        <child>
8be0b6
+          <object class="GtkEntry" id="passphrase_entry">
8be0b6
+            <property name="placeholder-text" translatable="yes">Enter a password here.</property>
8be0b6
+            <property name="input-purpose">password</property>
8be0b6
+            <property name="visibility">False</property>
8be0b6
+            <property name="secondary-icon-name">view-conceal</property>
8be0b6
+            <signal name="changed" handler="passphrase_entry_on_changed"/>
8be0b6
+            <signal name="icon-press" handler="passphrase_entry_on_icon_press"/>
8be0b6
+          </object>
8be0b6
+          <packing>
8be0b6
+            <property name="expand">False</property>
8be0b6
+            <property name="fill">True</property>
8be0b6
+            <property name="position">5</property>
8be0b6
+          </packing>
8be0b6
+        </child>
8be0b6
       </object>
8be0b6
     </child>
8be0b6
     <child type="action">
8be0b6
@@ -197,6 +253,7 @@
8be0b6
         <property name="can_default">True</property>
8be0b6
         <property name="receives_default">True</property>
8be0b6
         <property name="sensitive">False</property>
8be0b6
+        <signal name="notify::sensitive" handler="activate_button_on_sensitive_notify"/>
8be0b6
       </object>
8be0b6
     </child>
8be0b6
     <action-widgets>
8be0b6
-- 
8be0b6
2.31.1
8be0b6