summaryrefslogtreecommitdiff
path: root/src/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/server.c')
-rw-r--r--src/server.c481
1 files changed, 481 insertions, 0 deletions
diff --git a/src/server.c b/src/server.c
new file mode 100644
index 0000000..9ff3656
--- /dev/null
+++ b/src/server.c
@@ -0,0 +1,481 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Engrampa
+ *
+ * Copyright (C) 2010 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <glib/gi18n.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include "file-utils.h"
+#include "fr-init.h"
+
+
+#define FR_SERVICE_NAME "org.mate.Engrampa"
+#define FR_SERVICE_PATH "/org/mate/Engrampa"
+
+
+static const char introspection_xml[] =
+ "<node>"
+ " <interface name='org.mate.ArchiveManager'>"
+
+ /**
+ * GetSupportedTypes:
+ *
+ * Returns the supported archive types for a specific action.
+ *
+ * Input arguments:
+ *
+ * @action:
+ * Can be one of the following values:
+ * *) create: create an archive that can contain many files.
+ * *) create_single_file: create an archive that can contain a single file.
+ * *) extract: extract the content of an archive.
+ *
+ * Output arguments:
+ *
+ * @types:
+ * The supported archive types described as an array of hash tables,
+ * where each hash table has the following keys:
+ * *) mime-type: the mime type relative to the archive type.
+ * *) default-extension: the extension to use for newly created archives.
+ * *) description: a human readable description of the archive type.
+ */
+
+ " <method name='GetSupportedTypes'>"
+ " <arg name='action' type='s' direction='in'/>"
+ " <arg name='types' type='aa{ss}' direction='out'/>"
+ " </method>"
+
+ /**
+ * AddToArchive:
+ *
+ * Adds the specified files to an archive. If the archive already
+ * exists the archive is updated.
+ *
+ * Input arguments:
+ *
+ * @archive:
+ * The archive URI.
+ * @files:
+ * The files to add to the archive, as an array of URIs.
+ * @use_progress_dialog:
+ * Whether to show the progress dialog.
+ */
+
+ " <method name='AddToArchive'>"
+ " <arg name='archive' type='s' direction='in'/>"
+ " <arg name='files' type='as' direction='in'/>"
+ " <arg name='use_progress_dialog' type='b' direction='in'/>"
+ " </method>"
+
+ /**
+ * Compress:
+ *
+ * Compresses a series of files in an archive. The user is asked to
+ * enter an archive name, archive type and other options. In this case
+ * it's used the same dialog used by the "Compress..." command from the
+ * Nautilus context menu.
+ * If the user chooses an existing archive, the archive is updated.
+ *
+ * Input arguments:
+ *
+ * @files:
+ * The files to add to the archive, as an array of URIs.
+ * @destination:
+ * An optional destination, if not specified the folder of the first
+ * file in @files is used.
+ * @use_progress_dialog:
+ * Whether to show the progress dialog.
+ */
+
+ " <method name='Compress'>"
+ " <arg name='files' type='as' direction='in'/>"
+ " <arg name='destination' type='s' direction='in'/>"
+ " <arg name='use_progress_dialog' type='b' direction='in'/>"
+ " </method>"
+
+ /**
+ * Extract:
+ *
+ * Extract an archive in a specified location.
+ *
+ * Input arguments:
+ *
+ * @archive:
+ * The archive to extract.
+ * @destination:
+ * The location where to extract the archive.
+ * @use_progress_dialog:
+ * Whether to show the progress dialog.
+ */
+
+ " <method name='Extract'>"
+ " <arg name='archive' type='s' direction='in'/>"
+ " <arg name='destination' type='s' direction='in'/>"
+ " <arg name='use_progress_dialog' type='b' direction='in'/>"
+ " </method>"
+
+ /**
+ * ExtractHere:
+ *
+ * Extract an archive in a specified location.
+ *
+ * Input arguments:
+ *
+ * @archive:
+ * The archive to extract.
+ * @use_progress_dialog:
+ * Whether to show the progress dialog.
+ */
+
+ " <method name='ExtractHere'>"
+ " <arg name='archive' type='s' direction='in'/>"
+ " <arg name='use_progress_dialog' type='b' direction='in'/>"
+ " </method>"
+
+ /**
+ * Progress (signal)
+ *
+ * Arguments:
+ *
+ * @fraction:
+ * number from 0.0 to 100.0 that indicates the percentage of
+ * completion of the operation.
+ * @details:
+ * text message that describes the current operation.
+ */
+
+ " <signal name='Progress'>"
+ " <arg name='fraction' type='d'/>"
+ " <arg name='details' type='s'/>"
+ " </signal>"
+
+ " </interface>"
+ "</node>";
+
+static GDBusNodeInfo *introspection_data = NULL;
+
+
+static void
+window_ready_cb (GtkWidget *widget,
+ GError *error,
+ gpointer user_data)
+{
+ if (error == NULL)
+ g_dbus_method_invocation_return_value ((GDBusMethodInvocation *) user_data, NULL);
+ else
+ g_dbus_method_invocation_return_error ((GDBusMethodInvocation *) user_data,
+ error->domain,
+ error->code,
+ "%s",
+ error->message);
+}
+
+
+static gboolean
+window_progress_cb (FrWindow *window,
+ double fraction,
+ char *details,
+ gpointer user_data)
+{
+ GDBusConnection *connection = user_data;
+
+ g_dbus_connection_emit_signal (connection,
+ NULL,
+ FR_SERVICE_PATH,
+ "org.mate.ArchiveManager",
+ "Progress",
+ g_variant_new ("(ds)",
+ fraction,
+ details),
+ NULL);
+
+ return TRUE;
+}
+
+
+static void
+handle_method_call (GDBusConnection *connection,
+ const char *sender,
+ const char *object_path,
+ const char *interface_name,
+ const char *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ update_registered_commands_capabilities ();
+
+ if (g_strcmp0 (method_name, "GetSupportedTypes") == 0) {
+ char *action;
+ int *supported_types = NULL;
+
+ g_variant_get (parameters, "(s)", &action);
+
+ if (g_strcmp0 (action, "create") == 0) {
+ supported_types = save_type;
+ }
+ else if (g_strcmp0 (action, "create_single_file") == 0) {
+ supported_types = single_file_save_type;
+ }
+ else if (g_strcmp0 (action, "extract") == 0) {
+ supported_types = open_type;
+ }
+
+ if (supported_types == NULL) {
+ g_dbus_method_invocation_return_error (invocation,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ "Action not valid %s, valid values are: create, create_single_file, extract",
+ action);
+ }
+ else {
+ GVariantBuilder builder;
+ int i;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("(aa{ss})"));
+ g_variant_builder_open (&builder, G_VARIANT_TYPE ("aa{ss}"));
+ for (i = 0; supported_types[i] != -1; i++) {
+ g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{ss}"));
+ g_variant_builder_add (&builder, "{ss}",
+ "mime-type",
+ mime_type_desc[supported_types[i]].mime_type);
+ g_variant_builder_add (&builder, "{ss}",
+ "default-extension",
+ mime_type_desc[supported_types[i]].default_ext);
+ g_variant_builder_add (&builder, "{ss}",
+ "description",
+ _(mime_type_desc[supported_types[i]].name));
+ g_variant_builder_close (&builder);
+ }
+ g_variant_builder_close (&builder);
+
+ g_dbus_method_invocation_return_value (invocation, g_variant_builder_end (&builder));
+ }
+
+ g_free (action);
+ }
+ else if (g_strcmp0 (method_name, "AddToArchive") == 0) {
+ char *archive;
+ char **files;
+ gboolean use_progress_dialog;
+ int i;
+ GList *file_list = NULL;
+ GtkWidget *window;
+
+ g_variant_get (parameters, "(s^asb)", &archive, &files, &use_progress_dialog);
+
+ for (i = 0; files[i] != NULL; i++)
+ file_list = g_list_prepend (file_list, files[i]);
+ file_list = g_list_reverse (file_list);
+
+ window = fr_window_new ();
+ fr_window_use_progress_dialog (FR_WINDOW (window), use_progress_dialog);
+
+ g_signal_connect (window, "progress", G_CALLBACK (window_progress_cb), connection);
+ g_signal_connect (window, "ready", G_CALLBACK (window_ready_cb), invocation);
+
+ fr_window_new_batch (FR_WINDOW (window));
+ fr_window_set_batch__add (FR_WINDOW (window), archive, file_list);
+ fr_window_append_batch_action (FR_WINDOW (window), FR_BATCH_ACTION_QUIT, NULL, NULL);
+ fr_window_start_batch (FR_WINDOW (window));
+
+ g_free (archive);
+
+ gtk_main ();
+ }
+ else if (g_strcmp0 (method_name, "Compress") == 0) {
+ char **files;
+ char *destination;
+ gboolean use_progress_dialog;
+ int i;
+ GList *file_list = NULL;
+ GtkWidget *window;
+
+ g_variant_get (parameters, "(^assb)", &files, &destination, &use_progress_dialog);
+
+ for (i = 0; files[i] != NULL; i++)
+ file_list = g_list_prepend (file_list, files[i]);
+ file_list = g_list_reverse (file_list);
+
+ if ((destination == NULL) || (strcmp (destination, "") == 0))
+ destination = remove_level_from_path (file_list->data);
+
+ window = fr_window_new ();
+ fr_window_use_progress_dialog (FR_WINDOW (window), use_progress_dialog);
+ fr_window_set_default_dir (FR_WINDOW (window), destination, TRUE);
+
+ g_signal_connect (window, "progress", G_CALLBACK (window_progress_cb), connection);
+ g_signal_connect (window, "ready", G_CALLBACK (window_ready_cb), invocation);
+
+ fr_window_new_batch (FR_WINDOW (window));
+ fr_window_set_batch__add (FR_WINDOW (window), NULL, file_list);
+ fr_window_append_batch_action (FR_WINDOW (window), FR_BATCH_ACTION_QUIT, NULL, NULL);
+ fr_window_start_batch (FR_WINDOW (window));
+
+ g_free (destination);
+
+ gtk_main ();
+ }
+ else if (g_strcmp0 (method_name, "Extract") == 0) {
+ char *archive;
+ char *destination;
+ gboolean use_progress_dialog;
+ GtkWidget *window;
+
+ g_variant_get (parameters, "(ssb)", &archive, &destination, &use_progress_dialog);
+
+ window = fr_window_new ();
+ fr_window_use_progress_dialog (FR_WINDOW (window), use_progress_dialog);
+ if ((destination != NULL) & (strcmp (destination, "") != 0))
+ fr_window_set_default_dir (FR_WINDOW (window), destination, TRUE);
+
+ g_signal_connect (window, "progress", G_CALLBACK (window_progress_cb), connection);
+ g_signal_connect (window, "ready", G_CALLBACK (window_ready_cb), invocation);
+
+ fr_window_new_batch (FR_WINDOW (window));
+ fr_window_set_batch__extract (FR_WINDOW (window), archive, destination);
+ fr_window_append_batch_action (FR_WINDOW (window), FR_BATCH_ACTION_QUIT, NULL, NULL);
+ fr_window_start_batch (FR_WINDOW (window));
+
+ g_free (destination);
+ g_free (archive);
+
+ gtk_main ();
+ }
+ else if (g_strcmp0 (method_name, "ExtractHere") == 0) {
+ char *archive;
+ gboolean use_progress_dialog;
+ GtkWidget *window;
+
+ g_variant_get (parameters, "(sb)", &archive, &use_progress_dialog);
+
+ window = fr_window_new ();
+ fr_window_use_progress_dialog (FR_WINDOW (window), use_progress_dialog);
+
+ g_signal_connect (window, "progress", G_CALLBACK (window_progress_cb), connection);
+ g_signal_connect (window, "ready", G_CALLBACK (window_ready_cb), invocation);
+
+ fr_window_new_batch (FR_WINDOW (window));
+ fr_window_set_batch__extract_here (FR_WINDOW (window), archive);
+ fr_window_append_batch_action (FR_WINDOW (window), FR_BATCH_ACTION_QUIT, NULL, NULL);
+ fr_window_start_batch (FR_WINDOW (window));
+
+ g_free (archive);
+
+ gtk_main ();
+ }
+}
+
+
+static const GDBusInterfaceVTable interface_vtable = {
+ handle_method_call,
+ NULL, /* handle_get_property */
+ NULL /* handle_set_property */
+};
+
+
+static void
+on_bus_acquired (GDBusConnection *connection,
+ const char *name,
+ gpointer user_data)
+{
+ guint registration_id;
+
+ registration_id = g_dbus_connection_register_object (connection,
+ FR_SERVICE_PATH,
+ introspection_data->interfaces[0],
+ &interface_vtable,
+ NULL,
+ NULL, /* user_data_free_func */
+ NULL); /* GError** */
+ g_assert (registration_id > 0);
+
+ initialize_data ();
+}
+
+
+static void
+on_name_acquired (GDBusConnection *connection,
+ const char *name,
+ gpointer user_data)
+{
+}
+
+
+static void
+on_name_lost (GDBusConnection *connection,
+ const char *name,
+ gpointer user_data)
+{
+ gtk_main_quit ();
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ GOptionContext *context = NULL;
+ GError *error = NULL;
+ guint owner_id;
+
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ context = g_option_context_new (N_("- Create and modify an archive"));
+ g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
+ g_option_context_add_group (context, gtk_get_option_group (TRUE));
+
+ if (! g_option_context_parse (context, &argc, &argv, &error)) {
+ g_critical ("Failed to parse arguments: %s", error->message);
+ g_error_free (error);
+ g_option_context_free (context);
+ return EXIT_FAILURE;
+ }
+
+ g_option_context_free (context);
+
+ g_set_application_name (_("Engrampa"));
+ gtk_window_set_default_icon_name ("engrampa");
+
+ gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),
+ PKG_DATA_DIR G_DIR_SEPARATOR_S "icons");
+
+ introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
+ g_assert (introspection_data != NULL);
+
+ owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
+ FR_SERVICE_NAME,
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ on_bus_acquired,
+ on_name_acquired,
+ on_name_lost,
+ NULL,
+ NULL);
+
+ gtk_main ();
+
+ g_bus_unown_name (owner_id);
+ g_dbus_node_info_unref (introspection_data);
+
+ return 0;
+}