From 0c3107bbc42745c2e45530a8d43ea7fccd881e6f Mon Sep 17 00:00:00 2001 From: infirit Date: Thu, 20 Nov 2014 15:57:29 +0100 Subject: Added a D-BUS service to create and extract archives. Initial commits from FR: f998fd8e33a08d686a1071db87d21f4a83963d99 4078d1a9e5ddae3357302791432fc61d82ff37e4 58c55b06f30014326f27bdf94c406ceee0897731 Improvements and fixes from FR: D-Bus service: added GetSupportedTypes method ace4f31c586641fcf7ad1de165cd7f27b5a371c1 1399b9a84b0d4f4a5015066b0d7cec7e048d59dc From: Paolo Bacchilega --- data/Makefile.am | 8 + data/org.mate.Engrampa.service.in | 3 + po/POTFILES.in | 5 +- src/Makefile.am | 33 +- src/actions.c | 2 +- src/dlg-batch-add.c | 2 +- src/dlg-extract.c | 2 +- src/dlg-new.c | 2 +- src/dlg-open-with.c | 2 +- src/dlg-package-installer.c | 2 +- src/dlg-update.c | 2 +- src/file-utils.c | 2 +- src/fr-archive.c | 2 +- src/fr-error.c | 2 +- src/fr-init.c | 666 +++++++++++++++++++++++++++++ src/fr-init.h | 74 ++++ src/fr-marshal.list | 1 + src/fr-window.c | 111 ++++- src/fr-window.h | 11 +- src/main.c | 860 +++++--------------------------------- src/main.h | 84 ---- src/preferences.c | 2 +- src/server.c | 481 +++++++++++++++++++++ src/test-server.c | 263 ++++++++++++ 24 files changed, 1753 insertions(+), 869 deletions(-) create mode 100644 data/org.mate.Engrampa.service.in create mode 100644 src/fr-init.c create mode 100644 src/fr-init.h delete mode 100644 src/main.h create mode 100644 src/server.c create mode 100644 src/test-server.c diff --git a/data/Makefile.am b/data/Makefile.am index 62cb8c8..1b88d56 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -10,6 +10,12 @@ desktop_DATA = $(desktop_in_files:.desktop.in=.desktop) matchdir = $(datadir)/engrampa match_DATA = packages.match +servicedir = $(datadir)/dbus-1/services +service_in_files = org.mate.Engrampa.service.in +service_DATA = $(service_in_files:.service.in=.service) +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) $(SED) -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + @INTLTOOL_XML_RULE@ appdatadir = $(datadir)/appdata appdata_in_files = engrampa.appdata.xml.in @@ -49,11 +55,13 @@ EXTRA_DIST = \ $(gsettingsschema_in_files) \ $(appdata_in_files) \ $(man_MANS) \ + $(service_in_files) \ $(NULL) DISTCLEANFILES = \ $(desktop_in_files) \ $(desktop_DATA) \ + $(service_DATA) \ $(NULL) CLEANFILES = \ diff --git a/data/org.mate.Engrampa.service.in b/data/org.mate.Engrampa.service.in new file mode 100644 index 0000000..210cfe9 --- /dev/null +++ b/data/org.mate.Engrampa.service.in @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=org.mate.Engrampa +Exec=@libexecdir@/engrampa-server diff --git a/po/POTFILES.in b/po/POTFILES.in index 27ed688..a7f5971 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -101,6 +101,8 @@ src/fr-command-zoo.c src/fr-command-zoo.h src/fr-error.c src/fr-error.h +src/fr-init.c +src/fr-init.h src/fr-list-model.c src/fr-list-model.h src/fr-proc-error.c @@ -120,7 +122,6 @@ src/gtk-utils.h src/java-utils.c src/java-utils.h src/main.c -src/main.h src/mkdtemp.c src/mkdtemp.h src/open-file.c @@ -129,5 +130,7 @@ src/preferences.c src/preferences.h src/rar-utils.c src/rar-utils.h +src/server.c +src/test-server.c src/typedefs.h src/ui.h diff --git a/src/Makefile.am b/src/Makefile.am index 450214f..c1f1a01 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,8 @@ SUBDIRS = commands sh bin_PROGRAMS = engrampa +libexec_PROGRAMS = engrampa-server +noinst_PROGRAMS = test-server if MKDTEMP_MISSING MKDTEMP_FILES=mkdtemp.c mkdtemp.h @@ -45,7 +47,7 @@ BUILT_SOURCES = \ fr-enum-types.h \ fr-enum-types.c -engrampa_SOURCES = \ +COMMON_SOURCES = \ actions.h \ actions.c \ dlg-add-files.c \ @@ -123,6 +125,8 @@ engrampa_SOURCES = \ fr-command-7z.h \ fr-error.c \ fr-error.h \ + fr-init.c \ + fr-init.h \ fr-list-model.c \ fr-list-model.h \ fr-stock.c \ @@ -141,8 +145,6 @@ engrampa_SOURCES = \ gtk-utils.h \ java-utils.c \ java-utils.h \ - main.c \ - main.h \ open-file.c \ open-file.h \ preferences.c \ @@ -155,7 +157,7 @@ engrampa_SOURCES = \ $(BUILT_SOURCES) if ENABLE_JSON_GLIB -engrampa_SOURCES += \ +COMMON_SOURCES += \ fr-command-unarchiver.h \ fr-command-unarchiver.c endif @@ -188,10 +190,25 @@ fr-enum-types.c: typedefs.h fr-enum-types.h && (cmp -s xgen-$(@F) fr-enum-types.c || cp xgen-$(@F) fr-enum-types.c ) \ && rm -f xgen-$(@F) ) -engrampa_LDADD = \ - $(top_builddir)/copy-n-paste/libeggsmclient.la \ - $(FR_LIBS) \ - ${JSON_GLIB_LIBS} +engrampa_SOURCES = \ + $(COMMON_SOURCES) \ + main.c + +engrampa_LDADD = \ + $(top_builddir)/copy-n-paste/libeggsmclient.la \ + $(FR_LIBS) \ + ${JSON_GLIB_LIBS} + +engrampa_server_SOURCES = \ + $(COMMON_SOURCES) \ + server.c + +engrampa_server_LDADD = \ + $(engrampa_LDADD) + +test_server_SOURCES = test-server.c +test_server_FLAGS = $(FR_CFLAGS) +test_server_LDADD = $(FR_LIBS) if ENABLE_MAGIC engrampa_LDADD += $(MAGIC_LIBS) diff --git a/src/actions.c b/src/actions.c index bf41c37..5754aea 100644 --- a/src/actions.c +++ b/src/actions.c @@ -40,7 +40,7 @@ #include "file-utils.h" #include "fr-process.h" #include "glib-utils.h" -#include "main.h" +#include "fr-init.h" #include "typedefs.h" diff --git a/src/dlg-batch-add.c b/src/dlg-batch-add.c index 0b56740..35190fc 100644 --- a/src/dlg-batch-add.c +++ b/src/dlg-batch-add.c @@ -33,7 +33,7 @@ #include "gtk-utils.h" #include "glib-utils.h" #include "preferences.h" -#include "main.h" +#include "fr-init.h" #define ARCHIVE_ICON_SIZE (48) diff --git a/src/dlg-extract.c b/src/dlg-extract.c index e92966b..9a04b68 100644 --- a/src/dlg-extract.c +++ b/src/dlg-extract.c @@ -26,7 +26,7 @@ #include #include "file-utils.h" #include "fr-stock.h" -#include "main.h" +#include "fr-init.h" #include "gtk-utils.h" #include "fr-window.h" #include "typedefs.h" diff --git a/src/dlg-new.c b/src/dlg-new.c index c5ead16..0f0e36e 100644 --- a/src/dlg-new.c +++ b/src/dlg-new.c @@ -29,7 +29,7 @@ #include "file-utils.h" #include "fr-stock.h" #include "gtk-utils.h" -#include "main.h" +#include "fr-init.h" #include "preferences.h" diff --git a/src/dlg-open-with.c b/src/dlg-open-with.c index 3d04889..319b8c1 100644 --- a/src/dlg-open-with.c +++ b/src/dlg-open-with.c @@ -27,7 +27,7 @@ #include "file-utils.h" #include "glib-utils.h" #include "gtk-utils.h" -#include "main.h" +#include "fr-init.h" #include "fr-window.h" diff --git a/src/dlg-package-installer.c b/src/dlg-package-installer.c index 34ea680..240924a 100644 --- a/src/dlg-package-installer.c +++ b/src/dlg-package-installer.c @@ -27,7 +27,7 @@ #include #include "dlg-package-installer.h" #include "gtk-utils.h" -#include "main.h" +#include "fr-init.h" typedef struct { diff --git a/src/dlg-update.c b/src/dlg-update.c index 6dfdecd..ddd3cac 100644 --- a/src/dlg-update.c +++ b/src/dlg-update.c @@ -27,7 +27,7 @@ #include "file-utils.h" #include "glib-utils.h" #include "gtk-utils.h" -#include "main.h" +#include "fr-init.h" #include "fr-window.h" diff --git a/src/file-utils.c b/src/file-utils.c index 7e1f170..e3e1fc3 100644 --- a/src/file-utils.c +++ b/src/file-utils.c @@ -38,7 +38,7 @@ #include #include "file-utils.h" #include "glib-utils.h" -#include "main.h" +#include "fr-init.h" #ifndef HAVE_MKDTEMP diff --git a/src/fr-archive.c b/src/fr-archive.c index fcd50f6..56a9918 100644 --- a/src/fr-archive.c +++ b/src/fr-archive.c @@ -40,7 +40,7 @@ #include "fr-marshal.h" #include "fr-proc-error.h" #include "fr-process.h" -#include "main.h" +#include "fr-init.h" #if ENABLE_MAGIC #include diff --git a/src/fr-error.c b/src/fr-error.c index a73df3a..2184f67 100644 --- a/src/fr-error.c +++ b/src/fr-error.c @@ -30,7 +30,7 @@ fr_error_quark (void) static GQuark quark; if (!quark) - quark = g_quark_from_static_string ("engrampa_error"); + quark = g_quark_from_static_string ("engrampa-error"); return quark; } diff --git a/src/fr-init.c b/src/fr-init.c new file mode 100644 index 0000000..567cb19 --- /dev/null +++ b/src/fr-init.c @@ -0,0 +1,666 @@ +/* -*- 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 . + */ + +#include +#include +#include "file-data.h" +#include "file-utils.h" +#include "glib-utils.h" +#include "fr-command.h" +#include "fr-command-ace.h" +#include "fr-command-alz.h" +#include "fr-command-ar.h" +#include "fr-command-arj.h" +#include "fr-command-cfile.h" +#include "fr-command-cpio.h" +#include "fr-command-dpkg.h" +#include "fr-command-iso.h" +#include "fr-command-jar.h" +#include "fr-command-lha.h" +#include "fr-command-rar.h" +#include "fr-command-rpm.h" +#include "fr-command-tar.h" +#if HAVE_JSON_GLIB + #include "fr-command-unarchiver.h" +#endif +#include "fr-command-unstuff.h" +#include "fr-command-zip.h" +#include "fr-command-zoo.h" +#include "fr-command-7z.h" +#include "fr-command-lrzip.h" +#include "fr-init.h" +#include "fr-process.h" +#include "fr-stock.h" +#include "fr-window.h" +#include "typedefs.h" +#include "preferences.h" + + +/* The capabilities are computed automatically in + * compute_supported_archive_types() so it's correct to initialize to 0 here. */ +FrMimeTypeDescription mime_type_desc[] = { + { "application/x-7z-compressed", ".7z", N_("7-Zip (.7z)"), 0 }, + { "application/x-7z-compressed-tar", ".tar.7z", N_("Tar compressed with 7z (.tar.7z)"), 0 }, + { "application/x-ace", ".ace", N_("Ace (.ace)"), 0 }, + { "application/x-alz", ".alz", NULL, 0 }, + { "application/x-ar", ".ar", N_("Ar (.ar)"), 0 }, + { "application/x-arj", ".arj", N_("Arj (.arj)"), 0 }, + { "application/x-bzip", ".bz2", NULL, 0 }, + { "application/x-bzip-compressed-tar", ".tar.bz2", N_("Tar compressed with bzip2 (.tar.bz2)"), 0 }, + { "application/x-bzip1", ".bz", NULL, 0 }, + { "application/x-bzip1-compressed-tar", ".tar.bz", N_("Tar compressed with bzip (.tar.bz)"), 0 }, + { "application/vnd.ms-cab-compressed", ".cab", N_("Cabinet (.cab)"), 0 }, + { "application/x-cbr", ".cbr", N_("Rar Archived Comic Book (.cbr)"), 0 }, + { "application/x-cbz", ".cbz", N_("Zip Archived Comic Book (.cbz)"), 0 }, + { "application/x-cd-image", ".iso", NULL, 0 }, + { "application/x-compress", ".Z", NULL, 0 }, + { "application/x-compressed-tar", ".tar.gz", N_("Tar compressed with gzip (.tar.gz)"), 0 }, + { "application/x-cpio", ".cpio", NULL, 0 }, + { "application/x-deb", ".deb", NULL, 0 }, + { "application/x-ear", ".ear", N_("Ear (.ear)"), 0 }, + { "application/x-ms-dos-executable", ".exe", N_("Self-extracting zip (.exe)"), 0 }, + { "application/x-gzip", ".gz", NULL, 0 }, + { "application/x-java-archive", ".jar", N_("Jar (.jar)"), 0 }, + { "application/x-lha", ".lzh", N_("Lha (.lzh)"), 0 }, + { "application/x-lrzip", ".lrz", N_("Lrzip (.lrz)"), 0}, + { "application/x-lrzip-compressed-tar", ".tar.lrz", N_("Tar compressed with lrzip (.tar.lrz)"), 0 }, + { "application/x-lzip", ".lz", NULL, 0 }, + { "application/x-lzip-compressed-tar", ".tar.lz", N_("Tar compressed with lzip (.tar.lz)"), 0 }, + { "application/x-lzma", ".lzma", NULL, 0 }, + { "application/x-lzma-compressed-tar", ".tar.lzma", N_("Tar compressed with lzma (.tar.lzma)"), 0 }, + { "application/x-lzop", ".lzo", NULL, 0 }, + { "application/x-lzop-compressed-tar", ".tar.lzo", N_("Tar compressed with lzop (.tar.lzo)"), 0 }, + { "application/x-ms-wim", ".wim", N_("Windows Imaging Format (.wim)"), 0 }, + { "application/x-rar", ".rar", N_("Rar (.rar)"), 0 }, + { "application/x-rpm", ".rpm", NULL, 0 }, + { "application/x-rzip", ".rz", NULL, 0 }, + { "application/x-tar", ".tar", N_("Tar uncompressed (.tar)"), 0 }, + { "application/x-tarz", ".tar.Z", N_("Tar compressed with compress (.tar.Z)"), 0 }, + { "application/x-stuffit", ".sit", NULL, 0 }, + { "application/x-war", ".war", N_("War (.war)"), 0 }, + { "application/x-xz", ".xz", N_("Xz (.xz)"), 0 }, + { "application/x-xz-compressed-tar", ".tar.xz", N_("Tar compressed with xz (.tar.xz)"), 0 }, + { "application/x-zoo", ".zoo", N_("Zoo (.zoo)"), 0 }, + { "application/zip", ".zip", N_("Zip (.zip)"), 0 }, + { NULL, NULL, NULL, 0 } +}; + +FrExtensionType file_ext_type[] = { + { ".7z", "application/x-7z-compressed" }, + { ".ace", "application/x-ace" }, + { ".alz", "application/x-alz" }, + { ".ar", "application/x-ar" }, + { ".arj", "application/x-arj" }, + { ".bin", "application/x-stuffit" }, + { ".bz", "application/x-bzip" }, + { ".bz2", "application/x-bzip" }, + { ".cab", "application/vnd.ms-cab-compressed" }, + { ".cbr", "application/x-cbr" }, + { ".cbz", "application/x-cbz" }, + { ".cpio", "application/x-cpio" }, + { ".deb", "application/x-deb" }, + { ".ear", "application/x-ear" }, + { ".exe", "application/x-ms-dos-executable" }, + { ".gz", "application/x-gzip" }, + { ".iso", "application/x-cd-image" }, + { ".jar", "application/x-java-archive" }, + { ".lha", "application/x-lha" }, + { ".lrz", "application/x-lrzip" }, + { ".lzh", "application/x-lha" }, + { ".lz", "application/x-lzip" }, + { ".lzma", "application/x-lzma" }, + { ".lzo", "application/x-lzop" }, + { ".rar", "application/x-rar" }, + { ".rpm", "application/x-rpm" }, + { ".rz", "application/x-rzip" }, + { ".sit", "application/x-stuffit" }, + { ".swm", "application/x-ms-wim" }, + { ".tar", "application/x-tar" }, + { ".tar.bz", "application/x-bzip-compressed-tar" }, + { ".tar.bz2", "application/x-bzip-compressed-tar" }, + { ".tar.gz", "application/x-compressed-tar" }, + { ".tar.lrz", "application/x-lrzip-compressed-tar" }, + { ".tar.lz", "application/x-lzip-compressed-tar" }, + { ".tar.lzma", "application/x-lzma-compressed-tar" }, + { ".tar.lzo", "application/x-lzop-compressed-tar" }, + { ".tar.7z", "application/x-7z-compressed-tar" }, + { ".tar.xz", "application/x-xz-compressed-tar" }, + { ".tar.Z", "application/x-tarz" }, + { ".taz", "application/x-tarz" }, + { ".tbz", "application/x-bzip-compressed-tar" }, + { ".tbz2", "application/x-bzip-compressed-tar" }, + { ".tgz", "application/x-compressed-tar" }, + { ".txz", "application/x-xz-compressed-tar" }, + { ".tlz", "application/x-lzip-compressed-tar" }, + { ".tzma", "application/x-lzma-compressed-tar" }, + { ".tzo", "application/x-lzop-compressed-tar" }, + { ".war", "application/x-war" }, + { ".wim", "application/x-ms-wim" }, + { ".xz", "application/x-xz" }, + { ".z", "application/x-gzip" }, + { ".Z", "application/x-compress" }, + { ".zip", "application/zip" }, + { ".zoo", "application/x-zoo" }, + { NULL, NULL } +}; + + +GList *WindowList; +GList *CommandList; +gint ForceDirectoryCreation; +GHashTable *ProgramsCache; +GPtrArray *Registered_Commands; +int single_file_save_type[64]; +int save_type[64]; +int open_type[64]; +int create_type[64]; + + +static void +migrate_options_directory (void) +{ + char *old_directory_path; + GFile *old_directory; + GFile *new_directory; + + old_directory_path = get_home_relative_path (".config/mate/engrampa/options"); + old_directory = g_file_new_for_path (old_directory_path); + new_directory = get_user_config_subdirectory (ADD_FOLDER_OPTIONS_DIR, FALSE); + if (g_file_query_exists (old_directory, NULL) && ! g_file_query_exists (new_directory, NULL)) { + GFile *parent; + + parent = g_file_get_parent (new_directory); + if (make_directory_tree (parent, 0700, NULL)) + g_file_move (old_directory, new_directory, 0, NULL, NULL, NULL, NULL); + + g_object_unref (parent); + } + + g_object_unref (new_directory); + g_object_unref (old_directory); + g_free (old_directory_path); +} + + +/* -- FrRegisteredCommand -- */ + + +FrRegisteredCommand * +fr_registered_command_new (GType command_type) +{ + FrRegisteredCommand *reg_com; + FrCommand *command; + const char **mime_types; + int i; + + reg_com = g_new0 (FrRegisteredCommand, 1); + reg_com->ref = 1; + reg_com->type = command_type; + reg_com->caps = g_ptr_array_new (); + reg_com->packages = g_ptr_array_new (); + + command = (FrCommand*) g_object_new (reg_com->type, NULL); + mime_types = fr_command_get_mime_types (command); + for (i = 0; mime_types[i] != NULL; i++) { + const char *mime_type; + FrMimeTypeCap *cap; + FrMimeTypePackages *packages; + + mime_type = get_static_string (mime_types[i]); + + cap = g_new0 (FrMimeTypeCap, 1); + cap->mime_type = mime_type; + cap->current_capabilities = fr_command_get_capabilities (command, mime_type, TRUE); + cap->potential_capabilities = fr_command_get_capabilities (command, mime_type, FALSE); + g_ptr_array_add (reg_com->caps, cap); + + packages = g_new0 (FrMimeTypePackages, 1); + packages->mime_type = mime_type; + packages->packages = fr_command_get_packages (command, mime_type); + g_ptr_array_add (reg_com->packages, packages); + } + + g_object_unref (command); + + return reg_com; +} + + +void +fr_registered_command_ref (FrRegisteredCommand *reg_com) +{ + reg_com->ref++; +} + + +void +fr_registered_command_unref (FrRegisteredCommand *reg_com) +{ + if (--(reg_com->ref) != 0) + return; + + g_ptr_array_foreach (reg_com->caps, (GFunc) g_free, NULL); + g_ptr_array_free (reg_com->caps, TRUE); + g_free (reg_com); +} + + +FrCommandCaps +fr_registered_command_get_capabilities (FrRegisteredCommand *reg_com, + const char *mime_type) +{ + int i; + + for (i = 0; i < reg_com->caps->len; i++) { + FrMimeTypeCap *cap; + + cap = g_ptr_array_index (reg_com->caps, i); + if (strcmp (mime_type, cap->mime_type) == 0) + return cap->current_capabilities; + } + + return FR_COMMAND_CAN_DO_NOTHING; +} + + +FrCommandCaps +fr_registered_command_get_potential_capabilities (FrRegisteredCommand *reg_com, + const char *mime_type) +{ + int i; + + if (mime_type == NULL) + return FR_COMMAND_CAN_DO_NOTHING; + + for (i = 0; i < reg_com->caps->len; i++) { + FrMimeTypeCap *cap; + + cap = g_ptr_array_index (reg_com->caps, i); + if ((cap->mime_type != NULL) && (strcmp (mime_type, cap->mime_type) == 0)) + return cap->potential_capabilities; + } + + return FR_COMMAND_CAN_DO_NOTHING; +} + + +void +register_command (GType command_type) +{ + if (Registered_Commands == NULL) + Registered_Commands = g_ptr_array_sized_new (5); + g_ptr_array_add (Registered_Commands, fr_registered_command_new (command_type)); +} + + +gboolean +unregister_command (GType command_type) +{ + int i; + + for (i = 0; i < Registered_Commands->len; i++) { + FrRegisteredCommand *command; + + command = g_ptr_array_index (Registered_Commands, i); + if (command->type == command_type) { + g_ptr_array_remove_index (Registered_Commands, i); + fr_registered_command_unref (command); + return TRUE; + } + } + + return FALSE; +} + + +static void +register_commands (void) +{ + /* The order here is important. Commands registered earlier have higher + * priority. However commands that can read and write a file format + * have higher priority over commands that can only read the same + * format, regardless of the registration order. */ + + register_command (FR_TYPE_COMMAND_TAR); + register_command (FR_TYPE_COMMAND_CFILE); + register_command (FR_TYPE_COMMAND_7Z); + register_command (FR_TYPE_COMMAND_DPKG); + + register_command (FR_TYPE_COMMAND_ACE); + register_command (FR_TYPE_COMMAND_ALZ); + register_command (FR_TYPE_COMMAND_AR); + register_command (FR_TYPE_COMMAND_ARJ); + register_command (FR_TYPE_COMMAND_CPIO); + register_command (FR_TYPE_COMMAND_ISO); + register_command (FR_TYPE_COMMAND_JAR); + register_command (FR_TYPE_COMMAND_LHA); + register_command (FR_TYPE_COMMAND_RAR); + register_command (FR_TYPE_COMMAND_RPM); + register_command (FR_TYPE_COMMAND_UNSTUFF); + register_command (FR_TYPE_COMMAND_ZIP); + register_command (FR_TYPE_COMMAND_LRZIP); + register_command (FR_TYPE_COMMAND_ZOO); +#if HAVE_JSON_GLIB + register_command (FR_TYPE_COMMAND_UNARCHIVER); +#endif +} + + +GType +get_command_type_from_mime_type (const char *mime_type, + FrCommandCaps requested_capabilities) +{ + int i; + + if (mime_type == NULL) + return 0; + + for (i = 0; i < Registered_Commands->len; i++) { + FrRegisteredCommand *command; + FrCommandCaps capabilities; + + command = g_ptr_array_index (Registered_Commands, i); + capabilities = fr_registered_command_get_capabilities (command, mime_type); + + /* the command must support all the requested capabilities */ + if (((capabilities ^ requested_capabilities) & requested_capabilities) == 0) + return command->type; + } + + return 0; +} + + +GType +get_preferred_command_for_mime_type (const char *mime_type, + FrCommandCaps requested_capabilities) +{ + int i; + + for (i = 0; i < Registered_Commands->len; i++) { + FrRegisteredCommand *command; + FrCommandCaps capabilities; + + command = g_ptr_array_index (Registered_Commands, i); + capabilities = fr_registered_command_get_potential_capabilities (command, mime_type); + + /* the command must support all the requested capabilities */ + if (((capabilities ^ requested_capabilities) & requested_capabilities) == 0) + return command->type; + } + + return 0; +} + + +void +update_registered_commands_capabilities (void) +{ + int i; + + g_hash_table_remove_all (ProgramsCache); + + for (i = 0; i < Registered_Commands->len; i++) { + FrRegisteredCommand *reg_com; + FrCommand *command; + int j; + + reg_com = g_ptr_array_index (Registered_Commands, i); + command = (FrCommand*) g_object_new (reg_com->type, NULL); + for (j = 0; j < reg_com->caps->len; j++) { + FrMimeTypeCap *cap = g_ptr_array_index (reg_com->caps, j); + + cap->current_capabilities = fr_command_get_capabilities (command, cap->mime_type, TRUE); + cap->potential_capabilities = fr_command_get_capabilities (command, cap->mime_type, FALSE); + } + + g_object_unref (command); + } +} + + +const char * +get_mime_type_from_extension (const char *ext) +{ + int i; + + if (ext == NULL) + return NULL; + + for (i = G_N_ELEMENTS (file_ext_type) - 1; i >= 0; i--) { + if (file_ext_type[i].ext == NULL) + continue; + if (strcasecmp (ext, file_ext_type[i].ext) == 0) + return get_static_string (file_ext_type[i].mime_type); + } + + return NULL; +} + + +const char * +get_archive_filename_extension (const char *filename) +{ + const char *ext; + int i; + + if (filename == NULL) + return NULL; + + ext = get_file_extension (filename); + if (ext == NULL) + return NULL; + + for (i = G_N_ELEMENTS (file_ext_type) - 1; i >= 0; i--) { + if (file_ext_type[i].ext == NULL) + continue; + if (strcasecmp (ext, file_ext_type[i].ext) == 0) + return ext; + } + + return NULL; +} + + +int +get_mime_type_index (const char *mime_type) +{ + int i; + + for (i = 0; mime_type_desc[i].mime_type != NULL; i++) + if (strcmp (mime_type_desc[i].mime_type, mime_type) == 0) + return i; + return -1; +} + + +static void +add_if_non_present (int *a, + int *n, + int o) +{ + int i; + + for (i = 0; i < *n; i++) { + if (a[i] == o) + return; + } + a[*n] = o; + *n = *n + 1; +} + + +static int +cmp_mime_type_by_extension (const void *p1, + const void *p2) +{ + int i1 = * (int*) p1; + int i2 = * (int*) p2; + + return strcmp (mime_type_desc[i1].default_ext, mime_type_desc[i2].default_ext); +} + + +static int +cmp_mime_type_by_description (const void *p1, + const void *p2) +{ + int i1 = * (int*) p1; + int i2 = * (int*) p2; + + return g_utf8_collate (_(mime_type_desc[i1].name), _(mime_type_desc[i2].name)); +} + + +static void +sort_mime_types (int *a, + int(*compar)(const void *, const void *)) +{ + int n = 0; + + while (a[n] != -1) + n++; + qsort (a, n, sizeof (int), compar); +} + + +void +sort_mime_types_by_extension (int *a) +{ + sort_mime_types (a, cmp_mime_type_by_extension); +} + + +void +sort_mime_types_by_description (int *a) +{ + sort_mime_types (a, cmp_mime_type_by_description); +} + + +static void +compute_supported_archive_types (void) +{ + int sf_i = 0, s_i = 0, o_i = 0, c_i = 0; + int i; + + for (i = 0; i < Registered_Commands->len; i++) { + FrRegisteredCommand *reg_com; + int j; + + reg_com = g_ptr_array_index (Registered_Commands, i); + for (j = 0; j < reg_com->caps->len; j++) { + FrMimeTypeCap *cap; + int idx; + + cap = g_ptr_array_index (reg_com->caps, j); + idx = get_mime_type_index (cap->mime_type); + if (idx < 0) { + g_warning ("mime type not recognized: %s", cap->mime_type); + continue; + } + mime_type_desc[idx].capabilities |= cap->current_capabilities; + if (cap->current_capabilities & FR_COMMAND_CAN_READ) + add_if_non_present (open_type, &o_i, idx); + if (cap->current_capabilities & FR_COMMAND_CAN_WRITE) { + if (cap->current_capabilities & FR_COMMAND_CAN_ARCHIVE_MANY_FILES) { + add_if_non_present (save_type, &s_i, idx); + if (cap->current_capabilities & FR_COMMAND_CAN_WRITE) + add_if_non_present (create_type, &c_i, idx); + } + add_if_non_present (single_file_save_type, &sf_i, idx); + } + } + } + + open_type[o_i] = -1; + save_type[s_i] = -1; + single_file_save_type[sf_i] = -1; + create_type[c_i] = -1; +} + + +static initialized = FALSE; + + +void +initialize_data (void) +{ + if (initialized) + return; + initialized = TRUE; + + ProgramsCache = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + NULL); + + migrate_options_directory (); + register_commands (); + compute_supported_archive_types (); + + fr_stock_init (); +} + + +static void +command_done (CommandData *cdata) +{ + if (cdata == NULL) + return; + + if ((cdata->temp_dir != NULL) && path_is_dir (cdata->temp_dir)) { + char *argv[4]; + + argv[0] = "rm"; + argv[1] = "-rf"; + argv[2] = cdata->temp_dir; + argv[3] = NULL; + g_spawn_sync (g_get_tmp_dir (), argv, NULL, + G_SPAWN_SEARCH_PATH, + NULL, NULL, + NULL, NULL, NULL, + NULL); + } + + g_free (cdata->command); + if (cdata->app != NULL) + g_object_unref (cdata->app); + path_list_free (cdata->file_list); + g_free (cdata->temp_dir); + if (cdata->process != NULL) + g_object_unref (cdata->process); + + CommandList = g_list_remove (CommandList, cdata); + g_free (cdata); +} + + +void +release_data (void) +{ + g_hash_table_destroy (ProgramsCache); + + while (CommandList != NULL) { + CommandData *cdata = CommandList->data; + command_done (cdata); + } +} diff --git a/src/fr-init.h b/src/fr-init.h new file mode 100644 index 0000000..b89e9c8 --- /dev/null +++ b/src/fr-init.h @@ -0,0 +1,74 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +/* + * Engrampa + * + * Copyright (C) 2010 The 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 . + */ + +#ifndef FR_INIT_H +#define FR_INIT_H + +#include "preferences.h" +#include "fr-process.h" +#include "fr-window.h" + +typedef struct { + FrWindow *window; + FrProcess *process; + char *filename; + char *e_filename; + char *temp_dir; +} ViewerData; + +typedef struct { + FrWindow *window; + FrProcess *process; + char *command; + GAppInfo *app; + GList *file_list; + char *temp_dir; +} CommandData; + +extern GList *WindowList; +extern GList *CommandList; +extern gint ForceDirectoryCreation; +extern GHashTable *ProgramsCache; +extern GPtrArray *Registered_Commands; +extern FrMimeTypeDescription mime_type_desc[]; +extern FrExtensionType file_ext_type[]; +extern int single_file_save_type[]; /* File types that can be saved when + * a single file is selected. + * Includes single file compressors + * such as gzip, compress, etc. */ +extern int save_type[]; /* File types that can be saved. */ +extern int open_type[]; /* File types that can be opened. */ +extern int create_type[]; /* File types that can be created. */ + +GType get_command_type_from_mime_type (const char *mime_type, + FrCommandCaps requested_capabilities); +GType get_preferred_command_for_mime_type (const char *mime_type, + FrCommandCaps requested_capabilities); +void update_registered_commands_capabilities (void); +const char * get_mime_type_from_extension (const char *ext); +const char * get_archive_filename_extension (const char *uri); +int get_mime_type_index (const char *mime_type); +void sort_mime_types_by_extension (int *a); +void sort_mime_types_by_description (int *a); +void initialize_data (void); +void release_data (void); + +#endif /* FR_INIT_H */ diff --git a/src/fr-marshal.list b/src/fr-marshal.list index 1629043..f3b2554 100644 --- a/src/fr-marshal.list +++ b/src/fr-marshal.list @@ -4,6 +4,7 @@ VOID:INT,BOXED VOID:POINTER VOID:VOID VOID:DOUBLE +VOID:DOUBLE,STRING VOID:STRING VOID:BOOL VOID:BOXED diff --git a/src/fr-window.c b/src/fr-window.c index ee4f47a..4277f70 100644 --- a/src/fr-window.c +++ b/src/fr-window.c @@ -47,7 +47,7 @@ #include "file-data.h" #include "file-utils.h" #include "glib-utils.h" -#include "main.h" +#include "fr-init.h" #include "gtk-utils.h" #include "open-file.h" #include "typedefs.h" @@ -245,6 +245,8 @@ fr_clipboard_data_set_password (FrClipboardData *clipboard_data, enum { ARCHIVE_LOADED, + PROGRESS, + READY, LAST_SIGNAL }; @@ -378,6 +380,9 @@ struct _FrWindowPrivateData { FrAction pd_last_action; char *pd_last_archive; char *working_archive; + double pd_last_fraction; + char *pd_last_message; + gboolean use_progress_dialog; /* update dialog data */ @@ -623,6 +628,7 @@ fr_window_free_private_data (FrWindow *window) fr_window_reset_current_batch_action (window); g_free (window->priv->pd_last_archive); + g_free (window->priv->pd_last_message); g_free (window->priv->extract_here_dir); g_free (window->priv->last_status_message); @@ -668,12 +674,14 @@ fr_window_finalize (GObject *object) gh_unref_pixbuf, NULL); g_hash_table_destroy (pixbuf_hash); + pixbuf_hash = NULL; } if (tree_pixbuf_hash != NULL) { g_hash_table_foreach (tree_pixbuf_hash, gh_unref_pixbuf, NULL); g_hash_table_destroy (tree_pixbuf_hash); + tree_pixbuf_hash = NULL; } gtk_main_quit (); @@ -735,6 +743,25 @@ fr_window_class_init (FrWindowClass *class) fr_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + fr_window_signals[PROGRESS] = + g_signal_new ("progress", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (FrWindowClass, progress), + NULL, NULL, + fr_marshal_VOID__DOUBLE_STRING, + G_TYPE_NONE, 2, + G_TYPE_DOUBLE, + G_TYPE_STRING); + fr_window_signals[READY] = + g_signal_new ("ready", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (FrWindowClass, ready), + NULL, NULL, + fr_marshal_VOID__POINTER, + G_TYPE_NONE, 1, + G_TYPE_POINTER); gobject_class = (GObjectClass*) class; gobject_class->finalize = fr_window_finalize; @@ -787,6 +814,7 @@ fr_window_init (FrWindow *window) window->priv->update_dropped_files = FALSE; window->priv->filter_mode = FALSE; window->priv->batch_title = NULL; + window->priv->use_progress_dialog = TRUE; g_signal_connect (window, "realize", @@ -2441,9 +2469,20 @@ fr_window_message_cb (FrCommand *command, if (g_utf8_validate (utf8_msg, -1, NULL)) gtk_label_set_text (GTK_LABEL (window->priv->pd_message), utf8_msg); + + g_free (window->priv->pd_last_message); + window->priv->pd_last_message = g_strdup (utf8_msg); + + g_signal_emit (G_OBJECT (window), + fr_window_signals[PROGRESS], + 0, + window->priv->pd_last_fraction, + window->priv->pd_last_message); + #ifdef LOG_PROGRESS g_print ("message > %s\n", utf8_msg); #endif + g_free (utf8_msg); } @@ -2618,7 +2657,7 @@ display_progress_dialog (gpointer data) if (window->priv->progress_timeout != 0) g_source_remove (window->priv->progress_timeout); - if (window->priv->progress_dialog != NULL) { + if (window->priv->use_progress_dialog && (window->priv->progress_dialog != NULL)) { gtk_dialog_set_response_sensitive (GTK_DIALOG (window->priv->progress_dialog), GTK_RESPONSE_OK, window->priv->stoppable); @@ -2707,6 +2746,14 @@ fr_window_progress_cb (FrArchive *archive, fr_command_message (archive->command, message); } + window->priv->pd_last_fraction = fraction; + + g_signal_emit (G_OBJECT (window), + fr_window_signals[PROGRESS], + 0, + window->priv->pd_last_fraction, + window->priv->pd_last_message); + #ifdef LOG_PROGRESS g_print ("progress > %2.2f\n", fraction); #endif @@ -2878,23 +2925,42 @@ error_dialog_response_cb (GtkDialog *dialog, if ((dialog_parent != NULL) && (gtk_widget_get_toplevel (GTK_WIDGET (dialog_parent)) != (GtkWidget*) dialog_parent)) gtk_window_set_modal (dialog_parent, TRUE); gtk_widget_destroy (GTK_WIDGET (dialog)); + if (window->priv->destroy_with_error_dialog) gtk_widget_destroy (GTK_WIDGET (window)); } static void -fr_window_show_error_dialog (FrWindow *window, - GtkWidget *dialog, - GtkWindow *dialog_parent) +fr_window_show_error_dialog (FrWindow *window, + GtkWidget *dialog, + GtkWindow *dialog_parent, + const char *details) { + if (window->priv->batch_mode && ! window->priv->use_progress_dialog) { + GError *error; + + error = g_error_new_literal (FR_ERROR, FR_PROC_ERROR_GENERIC, details ? details : _("Command exited abnormally.")); + g_signal_emit (window, + fr_window_signals[READY], + 0, + error); + + gtk_widget_destroy (GTK_WIDGET (window)); + + return; + } + close_progress_dialog (window, TRUE); + if (window->priv->batch_mode) + fr_window_destroy_with_error_dialog (window); + if (dialog_parent != NULL) gtk_window_set_modal (dialog_parent, FALSE); g_signal_connect (dialog, "response", - (window->priv->batch_mode) ? G_CALLBACK (gtk_main_quit) : G_CALLBACK (error_dialog_response_cb), + G_CALLBACK (error_dialog_response_cb), window); gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); gtk_widget_show (dialog); @@ -3031,7 +3097,7 @@ handle_errors (FrWindow *window, msg, ((details != NULL) ? "%s" : NULL), details); - fr_window_show_error_dialog (window, dialog, dialog_parent); + fr_window_show_error_dialog (window, dialog, dialog_parent, details); return FALSE; } @@ -5570,6 +5636,8 @@ fr_window_construct (FrWindow *window) window->priv->current_batch_action.free_func = NULL; window->priv->pd_last_archive = NULL; + window->priv->pd_last_message = NULL; + window->priv->pd_last_fraction = 0.0; /* Create the widgets. */ @@ -6835,18 +6903,22 @@ fr_window_archive_extract (FrWindow *window, } if (! do_not_extract && ! ensure_dir_exists (edata->extract_to_dir, 0755, &error)) { - GtkWidget *d; + GtkWidget *d; + char *details; + details = g_strdup_printf (_("Could not create the destination folder: %s."), error->message); d = _gtk_error_dialog_new (GTK_WINDOW (window), 0, NULL, _("Extraction not performed"), - _("Could not create the destination folder: %s."), - error->message); + "%s", + details); g_clear_error (&error); - fr_window_show_error_dialog (window, d, GTK_WINDOW (window)); + fr_window_show_error_dialog (window, d, GTK_WINDOW (window), details); fr_window_stop_batch (window); + g_free (details); + return; } } @@ -6862,7 +6934,7 @@ fr_window_archive_extract (FrWindow *window, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response (GTK_DIALOG (d), GTK_RESPONSE_OK); - fr_window_show_error_dialog (window, d, GTK_WINDOW (window)); + fr_window_show_error_dialog (window, d, GTK_WINDOW (window), _("Extraction not performed")); fr_window_stop_batch (window); return; @@ -8670,6 +8742,14 @@ fr_window_set_folders_visibility (FrWindow *window, } +void +fr_window_use_progress_dialog (FrWindow *window, + gboolean value) +{ + window->priv->use_progress_dialog = value; +} + + /* -- batch mode procedures -- */ @@ -8807,6 +8887,13 @@ fr_window_exec_batch_action (FrWindow *window, case FR_BATCH_ACTION_QUIT: debug (DEBUG_INFO, "[BATCH] QUIT\n"); + g_signal_emit (window, + fr_window_signals[READY], + 0, + NULL); + + if ((window->priv->progress_dialog != NULL) && (gtk_widget_get_parent (window->priv->progress_dialog) != GTK_WIDGET (window))) + gtk_widget_destroy (window->priv->progress_dialog); gtk_widget_destroy (GTK_WIDGET (window)); break; diff --git a/src/fr-window.h b/src/fr-window.h index 1b66d39..826dc33 100644 --- a/src/fr-window.h +++ b/src/fr-window.h @@ -93,8 +93,13 @@ struct _FrWindowClass /**/ - void (*archive_loaded) (FrWindow *window, - gboolean success); + void (*archive_loaded) (FrWindow *window, + gboolean success); + void (*progress) (FrWindow *window, + double fraction, + const char *msg); + void (*ready) (FrWindow *window, + GError *error); }; GType fr_window_get_type (void); @@ -272,6 +277,8 @@ void fr_window_set_statusbar_visibility (FrWindow *window, gboolean value); void fr_window_set_folders_visibility (FrWindow *window, gboolean value); +void fr_window_use_progress_dialog (FrWindow *window, + gboolean value); /* batch mode procedures. */ diff --git a/src/main.c b/src/main.c index fb15d70..5859318 100644 --- a/src/main.c +++ b/src/main.c @@ -25,53 +25,18 @@ #include #include #include +#include +#include #include -#include "file-utils.h" -#include "glib-utils.h" -#include "fr-command.h" -#include "fr-command-ace.h" -#include "fr-command-alz.h" -#include "fr-command-ar.h" -#include "fr-command-arj.h" -#include "fr-command-cfile.h" -#include "fr-command-cpio.h" -#include "fr-command-dpkg.h" -#include "fr-command-iso.h" -#include "fr-command-jar.h" -#include "fr-command-lha.h" -#include "fr-command-rar.h" -#include "fr-command-rpm.h" -#include "fr-command-tar.h" -#if HAVE_JSON_GLIB - #include "fr-command-unarchiver.h" -#endif -#include "fr-command-unstuff.h" -#include "fr-command-zip.h" -#include "fr-command-zoo.h" -#include "fr-command-7z.h" -#include "fr-command-lrzip.h" -#include "fr-process.h" -#include "fr-stock.h" -#include "fr-window.h" -#include "typedefs.h" -#include "preferences.h" -#include "file-data.h" -#include "main.h" #include "eggsmclient.h" -static void prepare_app (void); -static void initialize_data (void); -static void release_data (void); +#include "fr-init.h" GList *WindowList = NULL; -GList *CommandList = NULL; gint ForceDirectoryCreation; -GHashTable *ProgramsCache = NULL; -GPtrArray *Registered_Commands = NULL; static char **remaining_args; - static char *add_to = NULL; static int add; static char *extract_to = NULL; @@ -79,118 +44,10 @@ static int extract; static int extract_here; static char *default_url = NULL; -/* The capabilities are computed automatically in - * compute_supported_archive_types() so it's correct to initialize to 0 here. */ -FrMimeTypeDescription mime_type_desc[] = { - { "application/x-7z-compressed", ".7z", N_("7-Zip (.7z)"), 0 }, - { "application/x-7z-compressed-tar", ".tar.7z", N_("Tar compressed with 7z (.tar.7z)"), 0 }, - { "application/x-ace", ".ace", N_("Ace (.ace)"), 0 }, - { "application/x-alz", ".alz", NULL, 0 }, - { "application/x-ar", ".ar", N_("Ar (.ar)"), 0 }, - { "application/x-arj", ".arj", N_("Arj (.arj)"), 0 }, - { "application/x-bzip", ".bz2", NULL, 0 }, - { "application/x-bzip-compressed-tar", ".tar.bz2", N_("Tar compressed with bzip2 (.tar.bz2)"), 0 }, - { "application/x-bzip1", ".bz", NULL, 0 }, - { "application/x-bzip1-compressed-tar", ".tar.bz", N_("Tar compressed with bzip (.tar.bz)"), 0 }, - { "application/vnd.ms-cab-compressed", ".cab", N_("Cabinet (.cab)"), 0 }, - { "application/x-cbr", ".cbr", N_("Rar Archived Comic Book (.cbr)"), 0 }, - { "application/x-cbz", ".cbz", N_("Zip Archived Comic Book (.cbz)"), 0 }, - { "application/x-cd-image", ".iso", NULL, 0 }, - { "application/x-compress", ".Z", NULL, 0 }, - { "application/x-compressed-tar", ".tar.gz", N_("Tar compressed with gzip (.tar.gz)"), 0 }, - { "application/x-cpio", ".cpio", NULL, 0 }, - { "application/x-deb", ".deb", NULL, 0 }, - { "application/x-ear", ".ear", N_("Ear (.ear)"), 0 }, - { "application/x-ms-dos-executable", ".exe", N_("Self-extracting zip (.exe)"), 0 }, - { "application/x-gzip", ".gz", NULL, 0 }, - { "application/x-java-archive", ".jar", N_("Jar (.jar)"), 0 }, - { "application/x-lha", ".lzh", N_("Lha (.lzh)"), 0 }, - { "application/x-lrzip", ".lrz", N_("Lrzip (.lrz)"), 0}, - { "application/x-lrzip-compressed-tar", ".tar.lrz", N_("Tar compressed with lrzip (.tar.lrz)"), 0 }, - { "application/x-lzip", ".lz", NULL, 0 }, - { "application/x-lzip-compressed-tar", ".tar.lz", N_("Tar compressed with lzip (.tar.lz)"), 0 }, - { "application/x-lzma", ".lzma", NULL, 0 }, - { "application/x-lzma-compressed-tar", ".tar.lzma", N_("Tar compressed with lzma (.tar.lzma)"), 0 }, - { "application/x-lzop", ".lzo", NULL, 0 }, - { "application/x-lzop-compressed-tar", ".tar.lzo", N_("Tar compressed with lzop (.tar.lzo)"), 0 }, - { "application/x-ms-wim", ".wim", N_("Windows Imaging Format (.wim)"), 0 }, - { "application/x-rar", ".rar", N_("Rar (.rar)"), 0 }, - { "application/x-rpm", ".rpm", NULL, 0 }, - { "application/x-rzip", ".rz", NULL, 0 }, - { "application/x-tar", ".tar", N_("Tar uncompressed (.tar)"), 0 }, - { "application/x-tarz", ".tar.Z", N_("Tar compressed with compress (.tar.Z)"), 0 }, - { "application/x-stuffit", ".sit", NULL, 0 }, - { "application/x-war", ".war", N_("War (.war)"), 0 }, - { "application/x-xz", ".xz", N_("Xz (.xz)"), 0 }, - { "application/x-xz-compressed-tar", ".tar.xz", N_("Tar compressed with xz (.tar.xz)"), 0 }, - { "application/x-zoo", ".zoo", N_("Zoo (.zoo)"), 0 }, - { "application/zip", ".zip", N_("Zip (.zip)"), 0 }, - { NULL, NULL, NULL, 0 } -}; - -FrExtensionType file_ext_type[] = { - { ".7z", "application/x-7z-compressed" }, - { ".ace", "application/x-ace" }, - { ".alz", "application/x-alz" }, - { ".ar", "application/x-ar" }, - { ".arj", "application/x-arj" }, - { ".bin", "application/x-stuffit" }, - { ".bz", "application/x-bzip" }, - { ".bz2", "application/x-bzip" }, - { ".cab", "application/vnd.ms-cab-compressed" }, - { ".cbr", "application/x-cbr" }, - { ".cbz", "application/x-cbz" }, - { ".cpio", "application/x-cpio" }, - { ".deb", "application/x-deb" }, - { ".ear", "application/x-ear" }, - { ".exe", "application/x-ms-dos-executable" }, - { ".gz", "application/x-gzip" }, - { ".iso", "application/x-cd-image" }, - { ".jar", "application/x-java-archive" }, - { ".lha", "application/x-lha" }, - { ".lrz", "application/x-lrzip" }, - { ".lzh", "application/x-lha" }, - { ".lz", "application/x-lzip" }, - { ".lzma", "application/x-lzma" }, - { ".lzo", "application/x-lzop" }, - { ".rar", "application/x-rar" }, - { ".rpm", "application/x-rpm" }, - { ".rz", "application/x-rzip" }, - { ".sit", "application/x-stuffit" }, - { ".swm", "application/x-ms-wim" }, - { ".tar", "application/x-tar" }, - { ".tar.bz", "application/x-bzip-compressed-tar" }, - { ".tar.bz2", "application/x-bzip-compressed-tar" }, - { ".tar.gz", "application/x-compressed-tar" }, - { ".tar.lrz", "application/x-lrzip-compressed-tar" }, - { ".tar.lz", "application/x-lzip-compressed-tar" }, - { ".tar.lzma", "application/x-lzma-compressed-tar" }, - { ".tar.lzo", "application/x-lzop-compressed-tar" }, - { ".tar.7z", "application/x-7z-compressed-tar" }, - { ".tar.xz", "application/x-xz-compressed-tar" }, - { ".tar.Z", "application/x-tarz" }, - { ".taz", "application/x-tarz" }, - { ".tbz", "application/x-bzip-compressed-tar" }, - { ".tbz2", "application/x-bzip-compressed-tar" }, - { ".tgz", "application/x-compressed-tar" }, - { ".txz", "application/x-xz-compressed-tar" }, - { ".tlz", "application/x-lzip-compressed-tar" }, - { ".tzma", "application/x-lzma-compressed-tar" }, - { ".tzo", "application/x-lzop-compressed-tar" }, - { ".war", "application/x-war" }, - { ".wim", "application/x-ms-wim" }, - { ".xz", "application/x-xz" }, - { ".z", "application/x-gzip" }, - { ".Z", "application/x-compress" }, - { ".zip", "application/zip" }, - { ".zoo", "application/x-zoo" }, - { NULL, NULL } -}; +static guint startup_id = 0; -int single_file_save_type[64]; -int save_type[64]; -int open_type[64]; -int create_type[64]; +/* argv[0] from main(); used as the command to restart the program */ +static const char *program_argv0 = NULL; static const GOptionEntry options[] = { { "add-to", 'a', 0, G_OPTION_ARG_STRING, &add_to, @@ -228,584 +85,6 @@ static const GOptionEntry options[] = { { NULL } }; - -/* -- Main -- */ - - -static guint startup_id = 0; - -/* argv[0] from main(); used as the command to restart the program */ -static const char *program_argv0 = NULL; - - -static gboolean -startup_cb (gpointer data) -{ - g_source_remove (startup_id); - startup_id = 0; - - initialize_data (); - prepare_app (); - - return FALSE; -} - - -static void -fr_save_state (EggSMClient *client, GKeyFile *state, gpointer user_data) -{ - /* discard command is automatically set by EggSMClient */ - - GList *window; - const char *argv[2] = { NULL }; - guint i; - - /* restart command */ - argv[0] = program_argv0; - argv[1] = NULL; - - egg_sm_client_set_restart_command (client, 1, argv); - - /* state */ - for (window = WindowList, i = 0; window; window = window->next, i++) { - FrWindow *session = window->data; - gchar *key; - - key = g_strdup_printf ("archive%d", i); - if ((session->archive == NULL) || (session->archive->file == NULL)) { - g_key_file_set_string (state, "Session", key, ""); - } else { - gchar *uri; - - uri = g_file_get_uri (session->archive->file); - g_key_file_set_string (state, "Session", key, uri); - g_free (uri); - } - g_free (key); - } - - g_key_file_set_integer (state, "Session", "archives", i); -} - -int -main (int argc, char **argv) -{ - GError *error = NULL; - EggSMClient *client = NULL; - GOptionContext *context = NULL; - - program_argv0 = argv[0]; - - 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_main_entries (context, options, GETTEXT_PACKAGE); - - g_option_context_add_group (context, gtk_get_option_group (TRUE)); - g_option_context_add_group (context, egg_sm_client_get_option_group ()); - - 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"); - - client = egg_sm_client_get (); - g_signal_connect (client, "save-state", G_CALLBACK (fr_save_state), NULL); - - gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), - PKG_DATA_DIR G_DIR_SEPARATOR_S "icons"); - - fr_stock_init (); - /* init_session (argv); */ - startup_id = g_idle_add (startup_cb, NULL); - gtk_main (); - release_data (); - - return 0; -} - -/* Initialize application data. */ - - -static void -initialize_data (void) -{ - ProgramsCache = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - NULL); -} - -/* Free application data. */ - - -void -command_done (CommandData *cdata) -{ - if (cdata == NULL) - return; - - if ((cdata->temp_dir != NULL) && path_is_dir (cdata->temp_dir)) { - char *argv[4]; - - argv[0] = "rm"; - argv[1] = "-rf"; - argv[2] = cdata->temp_dir; - argv[3] = NULL; - g_spawn_sync (g_get_tmp_dir (), argv, NULL, - G_SPAWN_SEARCH_PATH, - NULL, NULL, - NULL, NULL, NULL, - NULL); - } - - g_free (cdata->command); - if (cdata->app != NULL) - g_object_unref (cdata->app); - path_list_free (cdata->file_list); - g_free (cdata->temp_dir); - if (cdata->process != NULL) - g_object_unref (cdata->process); - - CommandList = g_list_remove (CommandList, cdata); - g_free (cdata); -} - - -static void -release_data () -{ - if (! initialized) - return; - - while (CommandList != NULL) { - CommandData *cdata = CommandList->data; - command_done (cdata); - } -} - -/* -- FrRegisteredCommand -- */ - - -FrRegisteredCommand * -fr_registered_command_new (GType command_type) -{ - FrRegisteredCommand *reg_com; - FrCommand *command; - const char **mime_types; - int i; - - reg_com = g_new0 (FrRegisteredCommand, 1); - reg_com->ref = 1; - reg_com->type = command_type; - reg_com->caps = g_ptr_array_new (); - reg_com->packages = g_ptr_array_new (); - - command = (FrCommand*) g_object_new (reg_com->type, NULL); - mime_types = fr_command_get_mime_types (command); - for (i = 0; mime_types[i] != NULL; i++) { - const char *mime_type; - FrMimeTypeCap *cap; - FrMimeTypePackages *packages; - - mime_type = get_static_string (mime_types[i]); - - cap = g_new0 (FrMimeTypeCap, 1); - cap->mime_type = mime_type; - cap->current_capabilities = fr_command_get_capabilities (command, mime_type, TRUE); - cap->potential_capabilities = fr_command_get_capabilities (command, mime_type, FALSE); - g_ptr_array_add (reg_com->caps, cap); - - packages = g_new0 (FrMimeTypePackages, 1); - packages->mime_type = mime_type; - packages->packages = fr_command_get_packages (command, mime_type); - g_ptr_array_add (reg_com->packages, packages); - } - - g_object_unref (command); - - return reg_com; -} - - -void -fr_registered_command_ref (FrRegisteredCommand *reg_com) -{ - reg_com->ref++; -} - - -void -fr_registered_command_unref (FrRegisteredCommand *reg_com) -{ - if (--(reg_com->ref) != 0) - return; - - g_ptr_array_foreach (reg_com->caps, (GFunc) g_free, NULL); - g_ptr_array_free (reg_com->caps, TRUE); - g_free (reg_com); -} - - -FrCommandCaps -fr_registered_command_get_capabilities (FrRegisteredCommand *reg_com, - const char *mime_type) -{ - int i; - - for (i = 0; i < reg_com->caps->len; i++) { - FrMimeTypeCap *cap; - - cap = g_ptr_array_index (reg_com->caps, i); - if (strcmp (mime_type, cap->mime_type) == 0) - return cap->current_capabilities; - } - - return FR_COMMAND_CAN_DO_NOTHING; -} - - -FrCommandCaps -fr_registered_command_get_potential_capabilities (FrRegisteredCommand *reg_com, - const char *mime_type) -{ - int i; - - if (mime_type == NULL) - return FR_COMMAND_CAN_DO_NOTHING; - - for (i = 0; i < reg_com->caps->len; i++) { - FrMimeTypeCap *cap; - - cap = g_ptr_array_index (reg_com->caps, i); - if ((cap->mime_type != NULL) && (strcmp (mime_type, cap->mime_type) == 0)) - return cap->potential_capabilities; - } - - return FR_COMMAND_CAN_DO_NOTHING; -} - - -void -register_command (GType command_type) -{ - if (Registered_Commands == NULL) - Registered_Commands = g_ptr_array_sized_new (5); - g_ptr_array_add (Registered_Commands, fr_registered_command_new (command_type)); -} - - -gboolean -unregister_command (GType command_type) -{ - int i; - - for (i = 0; i < Registered_Commands->len; i++) { - FrRegisteredCommand *command; - - command = g_ptr_array_index (Registered_Commands, i); - if (command->type == command_type) { - g_ptr_array_remove_index (Registered_Commands, i); - fr_registered_command_unref (command); - return TRUE; - } - } - - return FALSE; -} - - -static void -register_commands (void) -{ - /* The order here is important. Commands registered earlier have higher - * priority. However commands that can read and write a file format - * have higher priority over commands that can only read the same - * format, regardless of the registration order. */ - - register_command (FR_TYPE_COMMAND_TAR); - register_command (FR_TYPE_COMMAND_CFILE); - register_command (FR_TYPE_COMMAND_7Z); - register_command (FR_TYPE_COMMAND_DPKG); - - register_command (FR_TYPE_COMMAND_ACE); - register_command (FR_TYPE_COMMAND_ALZ); - register_command (FR_TYPE_COMMAND_AR); - register_command (FR_TYPE_COMMAND_ARJ); - register_command (FR_TYPE_COMMAND_CPIO); - register_command (FR_TYPE_COMMAND_ISO); - register_command (FR_TYPE_COMMAND_JAR); - register_command (FR_TYPE_COMMAND_LHA); - register_command (FR_TYPE_COMMAND_RAR); - register_command (FR_TYPE_COMMAND_RPM); - register_command (FR_TYPE_COMMAND_UNSTUFF); - register_command (FR_TYPE_COMMAND_ZIP); - register_command (FR_TYPE_COMMAND_LRZIP); - register_command (FR_TYPE_COMMAND_ZOO); -#if HAVE_JSON_GLIB - register_command (FR_TYPE_COMMAND_UNARCHIVER); -#endif -} - - -GType -get_command_type_from_mime_type (const char *mime_type, - FrCommandCaps requested_capabilities) -{ - int i; - - if (mime_type == NULL) - return 0; - - for (i = 0; i < Registered_Commands->len; i++) { - FrRegisteredCommand *command; - FrCommandCaps capabilities; - - command = g_ptr_array_index (Registered_Commands, i); - capabilities = fr_registered_command_get_capabilities (command, mime_type); - - /* the command must support all the requested capabilities */ - if (((capabilities ^ requested_capabilities) & requested_capabilities) == 0) - return command->type; - } - - return 0; -} - - -GType -get_preferred_command_for_mime_type (const char *mime_type, - FrCommandCaps requested_capabilities) -{ - int i; - - for (i = 0; i < Registered_Commands->len; i++) { - FrRegisteredCommand *command; - FrCommandCaps capabilities; - - command = g_ptr_array_index (Registered_Commands, i); - capabilities = fr_registered_command_get_potential_capabilities (command, mime_type); - - /* the command must support all the requested capabilities */ - if (((capabilities ^ requested_capabilities) & requested_capabilities) == 0) - return command->type; - } - - return 0; -} - - -void -update_registered_commands_capabilities (void) -{ - int i; - - g_hash_table_remove_all (ProgramsCache); - - for (i = 0; i < Registered_Commands->len; i++) { - FrRegisteredCommand *reg_com; - FrCommand *command; - int j; - - reg_com = g_ptr_array_index (Registered_Commands, i); - command = (FrCommand*) g_object_new (reg_com->type, NULL); - for (j = 0; j < reg_com->caps->len; j++) { - FrMimeTypeCap *cap = g_ptr_array_index (reg_com->caps, j); - - cap->current_capabilities = fr_command_get_capabilities (command, cap->mime_type, TRUE); - cap->potential_capabilities = fr_command_get_capabilities (command, cap->mime_type, FALSE); - } - - g_object_unref (command); - } -} - - -const char * -get_mime_type_from_extension (const char *ext) -{ - int i; - - if (ext == NULL) - return NULL; - - for (i = G_N_ELEMENTS (file_ext_type) - 1; i >= 0; i--) { - if (file_ext_type[i].ext == NULL) - continue; - if (strcasecmp (ext, file_ext_type[i].ext) == 0) - return get_static_string (file_ext_type[i].mime_type); - } - - return NULL; -} - - -const char * -get_archive_filename_extension (const char *filename) -{ - const char *ext; - int i; - - if (filename == NULL) - return NULL; - - ext = get_file_extension (filename); - if (ext == NULL) - return NULL; - - for (i = G_N_ELEMENTS (file_ext_type) - 1; i >= 0; i--) { - if (file_ext_type[i].ext == NULL) - continue; - if (strcasecmp (ext, file_ext_type[i].ext) == 0) - return ext; - } - - return NULL; -} - - -int -get_mime_type_index (const char *mime_type) -{ - int i; - - for (i = 0; mime_type_desc[i].mime_type != NULL; i++) - if (strcmp (mime_type_desc[i].mime_type, mime_type) == 0) - return i; - return -1; -} - - -static void -add_if_non_present (int *a, - int *n, - int o) -{ - int i; - - for (i = 0; i < *n; i++) { - if (a[i] == o) - return; - } - a[*n] = o; - *n = *n + 1; -} - - -static int -cmp_mime_type_by_extension (const void *p1, - const void *p2) -{ - int i1 = * (int*) p1; - int i2 = * (int*) p2; - - return strcmp (mime_type_desc[i1].default_ext, mime_type_desc[i2].default_ext); -} - - -static int -cmp_mime_type_by_description (const void *p1, - const void *p2) -{ - int i1 = * (int*) p1; - int i2 = * (int*) p2; - - return g_utf8_collate (_(mime_type_desc[i1].name), _(mime_type_desc[i2].name)); -} - - -static void -sort_mime_types (int *a, - int(*compar)(const void *, const void *)) -{ - int n = 0; - - while (a[n] != -1) - n++; - qsort (a, n, sizeof (int), compar); -} - - -void -sort_mime_types_by_extension (int *a) -{ - sort_mime_types (a, cmp_mime_type_by_extension); -} - - -void -sort_mime_types_by_description (int *a) -{ - sort_mime_types (a, cmp_mime_type_by_description); -} - - -static void -compute_supported_archive_types (void) -{ - int sf_i = 0, s_i = 0, o_i = 0, c_i = 0; - int i; - - for (i = 0; i < Registered_Commands->len; i++) { - FrRegisteredCommand *reg_com; - int j; - - reg_com = g_ptr_array_index (Registered_Commands, i); - for (j = 0; j < reg_com->caps->len; j++) { - FrMimeTypeCap *cap; - int idx; - - cap = g_ptr_array_index (reg_com->caps, j); - idx = get_mime_type_index (cap->mime_type); - if (idx < 0) { - g_warning ("mime type not recognized: %s", cap->mime_type); - continue; - } - mime_type_desc[idx].capabilities |= cap->current_capabilities; - if (cap->current_capabilities & FR_COMMAND_CAN_READ) - add_if_non_present (open_type, &o_i, idx); - if (cap->current_capabilities & FR_COMMAND_CAN_WRITE) { - if (cap->current_capabilities & FR_COMMAND_CAN_ARCHIVE_MANY_FILES) { - add_if_non_present (save_type, &s_i, idx); - if (cap->current_capabilities & FR_COMMAND_CAN_WRITE) - add_if_non_present (create_type, &c_i, idx); - } - add_if_non_present (single_file_save_type, &sf_i, idx); - } - } - } - - open_type[o_i] = -1; - save_type[s_i] = -1; - single_file_save_type[sf_i] = -1; - create_type[c_i] = -1; -} - - -static char * -get_uri_from_command_line (const char *path) -{ - GFile *file; - char *uri; - - file = g_file_new_for_commandline_arg (path); - uri = g_file_get_uri (file); - g_object_unref (file); - - return uri; -} - - static void fr_restore_session (EggSMClient *client) { @@ -833,29 +112,17 @@ fr_restore_session (EggSMClient *client) } } -static void -migrate_options_directory (void) +static char * +get_uri_from_command_line (const char *path) { - char *old_directory_path; - GFile *old_directory; - GFile *new_directory; - - old_directory_path = get_home_relative_path (".config/mate/engrampa/options"); - old_directory = g_file_new_for_path (old_directory_path); - new_directory = get_user_config_subdirectory (ADD_FOLDER_OPTIONS_DIR, FALSE); - if (g_file_query_exists (old_directory, NULL) && ! g_file_query_exists (new_directory, NULL)) { - GFile *parent; - - parent = g_file_get_parent (new_directory); - if (make_directory_tree (parent, 0700, NULL)) - g_file_move (old_directory, new_directory, 0, NULL, NULL, NULL, NULL); + GFile *file; + char *uri; - g_object_unref (parent); - } + file = g_file_new_for_commandline_arg (path); + uri = g_file_get_uri (file); + g_object_unref (file); - g_object_unref (new_directory); - g_object_unref (old_directory); - g_free (old_directory_path); + return uri; } static void @@ -865,10 +132,6 @@ prepare_app (void) char *add_to_uri = NULL; EggSMClient *client = NULL; - migrate_options_directory (); - register_commands (); - compute_supported_archive_types (); - client = egg_sm_client_get (); if (egg_sm_client_is_resumed (client)) { fr_restore_session (client); @@ -966,3 +229,98 @@ prepare_app (void) g_free (add_to_uri); g_free (extract_to_uri); } + + +static gboolean +startup_cb (gpointer data) +{ + g_source_remove (startup_id); + startup_id = 0; + + initialize_data (); + prepare_app (); + + return FALSE; +} + + +static void +fr_save_state (EggSMClient *client, GKeyFile *state, gpointer user_data) +{ + /* discard command is automatically set by EggSMClient */ + + GList *window; + const char *argv[2] = { NULL }; + guint i; + + /* restart command */ + argv[0] = program_argv0; + argv[1] = NULL; + + egg_sm_client_set_restart_command (client, 1, argv); + + /* state */ + for (window = WindowList, i = 0; window; window = window->next, i++) { + FrWindow *session = window->data; + gchar *key; + + key = g_strdup_printf ("archive%d", i); + if ((session->archive == NULL) || (session->archive->file == NULL)) { + g_key_file_set_string (state, "Session", key, ""); + } else { + gchar *uri; + + uri = g_file_get_uri (session->archive->file); + g_key_file_set_string (state, "Session", key, uri); + g_free (uri); + } + g_free (key); + } + + g_key_file_set_integer (state, "Session", "archives", i); +} + +int +main (int argc, char **argv) +{ + GOptionContext *context = NULL; + GError *error = NULL; + EggSMClient *client = NULL; + + program_argv0 = argv[0]; + + 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_main_entries (context, options, GETTEXT_PACKAGE); + + g_option_context_add_group (context, gtk_get_option_group (TRUE)); + g_option_context_add_group (context, egg_sm_client_get_option_group ()); + + 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"); + + client = egg_sm_client_get (); + g_signal_connect (client, "save-state", G_CALLBACK (fr_save_state), NULL); + + gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), + PKG_DATA_DIR G_DIR_SEPARATOR_S "icons"); + + startup_id = g_idle_add (startup_cb, NULL); + gtk_main (); + release_data (); + + return 0; +} diff --git a/src/main.h b/src/main.h deleted file mode 100644 index 6d94172..0000000 --- a/src/main.h +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ - -/* - * Engrampa - * - * Copyright (C) 2001, 2008 The 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, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02110-1301, USA. - */ - -#ifndef MAIN_H -#define MAIN_H - - -#include -#include -#include -#include "preferences.h" -#include "fr-process.h" -#include "fr-window.h" - - -typedef struct { - FrWindow *window; - FrProcess *process; - char *filename; - char *e_filename; - char *temp_dir; -} ViewerData; - -typedef struct { - FrWindow *window; - FrProcess *process; - char *command; - GAppInfo *app; - GList *file_list; - char *temp_dir; -} CommandData; - - -void viewer_done (ViewerData *vdata); -void command_done (CommandData *cdata); - - -extern GList *WindowList; -extern GList *CommandList; -extern gint ForceDirectoryCreation; -extern GHashTable *ProgramsCache; -extern GPtrArray *Registered_Commands; - -extern FrMimeTypeDescription mime_type_desc[]; -extern FrExtensionType file_ext_type[]; -extern int single_file_save_type[]; /* File types that can be saved when - * a single file is selected. - * Includes single file compressors - * such as gzip, compress, etc. */ -extern int save_type[]; /* File types that can be saved. */ -extern int open_type[]; /* File types that can be opened. */ -extern int create_type[]; /* File types that can be created. */ - -GType get_command_type_from_mime_type (const char *mime_type, - FrCommandCaps requested_capabilities); -GType get_preferred_command_for_mime_type (const char *mime_type, - FrCommandCaps requested_capabilities); -void update_registered_commands_capabilities (void); -const char * get_mime_type_from_extension (const char *ext); -const char * get_archive_filename_extension (const char *uri); -int get_mime_type_index (const char *mime_type); -void sort_mime_types_by_extension (int *a); -void sort_mime_types_by_description (int *a); - -#endif /* MAIN_H */ diff --git a/src/preferences.c b/src/preferences.c index 7fbdf8f..b3c7de3 100644 --- a/src/preferences.c +++ b/src/preferences.c @@ -23,7 +23,7 @@ #include #include "typedefs.h" #include "preferences.h" -#include "main.h" +#include "fr-init.h" #include "file-utils.h" #include "fr-window.h" 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 . + */ + +#include +#include +#include +#include +#include +#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[] = + "" + " " + + /** + * 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. + */ + + " " + " " + " " + " " + + /** + * 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. + */ + + " " + " " + " " + " " + " " + + /** + * 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. + */ + + " " + " " + " " + " " + " " + + /** + * 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. + */ + + " " + " " + " " + " " + " " + + /** + * ExtractHere: + * + * Extract an archive in a specified location. + * + * Input arguments: + * + * @archive: + * The archive to extract. + * @use_progress_dialog: + * Whether to show the progress dialog. + */ + + " " + " " + " " + " " + + /** + * 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. + */ + + " " + " " + " " + " " + + " " + ""; + +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; +} diff --git a/src/test-server.c b/src/test-server.c new file mode 100644 index 0000000..a9dcb5f --- /dev/null +++ b/src/test-server.c @@ -0,0 +1,263 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +/* + * Engrampa + * + * Copyright (C) 2010 The 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 . + */ + +#include +#include + + +GMainLoop *loop; + + +static void +engrampa_getsupportedtypes_ready_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GDBusProxy *proxy; + GVariant *values; + GError *error = NULL; + + proxy = G_DBUS_PROXY (source_object); + values = g_dbus_proxy_call_finish (proxy, res, &error); + if (values == NULL) { + g_error ("%s\n", error->message); + g_clear_error (&error); + } + else { + GVariantIter argument_iter; + GVariant *array_of_types; + GVariantIter type_iter; + GVariant *supported_type; + int n = 0; + + g_variant_iter_init (&argument_iter, values); + array_of_types = g_variant_iter_next_value (&argument_iter); + + g_variant_iter_init (&type_iter, array_of_types); + while ((supported_type = g_variant_iter_next_value (&type_iter))) { + char *mime_type = NULL; + char *default_ext = NULL; + char *description = NULL; + char *key; + char *value; + GVariantIter value_iter; + + g_variant_iter_init (&value_iter, supported_type); + while (g_variant_iter_next (&value_iter, "{ss}", &key, &value)) { + if (g_strcmp0 (key, "mime-type") == 0) + mime_type = g_strdup (value); + else if (g_strcmp0 (key, "default-extension") == 0) + default_ext = g_strdup (value); + else if (g_strcmp0 (key, "description") == 0) + description = g_strdup (value); + + g_free (key); + g_free (value); + } + + n++; + g_print ("%d)\tmime-type: %s\n\tdefault-extension: %s\n\tdescription: %s\n", n, mime_type, default_ext, description); + + g_free (description); + g_free (default_ext); + g_free (mime_type); + g_variant_unref (supported_type); + } + + g_variant_unref (array_of_types); + } + + g_object_unref (proxy); + g_main_loop_quit (loop); +} + + +static void +engrampa_addtoarchive_ready_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GDBusProxy *proxy; + GVariant *values; + GError *error = NULL; + + proxy = G_DBUS_PROXY (source_object); + values = g_dbus_proxy_call_finish (proxy, res, &error); + if (values == NULL) { + g_error ("%s\n", error->message); + g_clear_error (&error); + } + + if (values != NULL) + g_variant_unref (values); + g_object_unref (proxy); + + g_main_loop_quit (loop); +} + + +static void +on_signal (GDBusProxy *proxy, + char *sender_name, + char *signal_name, + GVariant *parameters, + gpointer user_data) +{ + if (g_strcmp0 (signal_name, "Progress") == 0) { + double fraction; + char *details; + + g_variant_get (parameters, "(ds)", &fraction, &details); + g_print ("Progress: %f (%s)\n", fraction, details); + + g_free (details); + } +} + + +int +main (int argc, char *argv[]) +{ + GDBusConnection *connection; + GError *error = NULL; + + connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); + if (connection != NULL) { + GDBusProxy *proxy; + + proxy = g_dbus_proxy_new_sync (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "org.mate.Engrampa", + "/org/mate/Engrampa", + "org.mate.ArchiveManager", + NULL, + &error); + + if (proxy != NULL) { + + g_signal_connect (proxy, + "g-signal", + G_CALLBACK (on_signal), + NULL); + +#if 0 + /* -- GetSupportedTypes -- */ + + g_dbus_proxy_call (proxy, + "GetSupportedTypes", + g_variant_new ("(s)", "create"), + G_DBUS_CALL_FLAGS_NONE, + G_MAXINT, + NULL, + engrampa_getsupportedtypes_ready_cb, + NULL); +#endif + + /* -- AddToArchive -- */ + + char *archive; + char **files; + + archive = g_strdup ("file:///home/paolo/Scrivania/firefox-4.0b8pre.tar.gz"); + files = g_new0 (char *, 2); + files[0] = g_strdup ("file:///home/paolo/Scrivania/firefox-4.0b8pre"); + files[1] = NULL; + + g_dbus_proxy_call (proxy, + "AddToArchive", + g_variant_new ("(s^asb)", + archive, + files, + FALSE), + G_DBUS_CALL_FLAGS_NONE, + G_MAXINT, + NULL, + engrampa_addtoarchive_ready_cb, + NULL); + + g_free (archive); + g_strfreev (files); + +#if 0 + + /* -- Compress -- */ + + char **files; + char *destination; + + files = g_new0 (char *, 2); + files[0] = g_strdup ("file:///home/paolo/Scrivania/firefox-4.0b8pre"); + files[1] = NULL; + destination = g_strdup ("file:///home/paolo/Scrivania"); + + g_dbus_proxy_call (proxy, + "Compress", + g_variant_new ("(^assb)", + files, + destination, + TRUE), + G_DBUS_CALL_FLAGS_NONE, + G_MAXINT, + NULL, + engrampa_addtoarchive_ready_cb, + NULL); + + g_strfreev (files); + g_free (destination); + + /* -- Extract -- */ + + g_dbus_proxy_call (proxy, + "Extract", + g_variant_new ("(ssb)", + "file:///home/paolo/Scrivania/test.tar.gz", + "file:///home/paolo/Scrivania", + TRUE), + G_DBUS_CALL_FLAGS_NONE, + G_MAXINT, + NULL, + engrampa_addtoarchive_ready_cb, + NULL); + + /* -- ExtractHere -- */ + + g_dbus_proxy_call (proxy, + "ExtractHere", + g_variant_new ("(sb)", + "file:///home/paolo/Scrivania/test.tar.gz", + TRUE), + G_DBUS_CALL_FLAGS_NONE, + G_MAXINT, + NULL, + engrampa_addtoarchive_ready_cb, + NULL); + +#endif + + } + } + + loop = g_main_loop_new (NULL, FALSE); + g_main_loop_run (loop); + + return 0; +} -- cgit v1.2.1