diff options
Diffstat (limited to 'src/fr-command.c')
-rw-r--r-- | src/fr-command.c | 826 |
1 files changed, 826 insertions, 0 deletions
diff --git a/src/fr-command.c b/src/fr-command.c new file mode 100644 index 0000000..873c02d --- /dev/null +++ b/src/fr-command.c @@ -0,0 +1,826 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +/* + * File-Roller + * + * Copyright (C) 2001 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 02111-1307, USA. + */ + +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <glib.h> +#include "file-data.h" +#include "file-utils.h" +#include "fr-command.h" +#include "fr-enum-types.h" +#include "fr-marshal.h" +#include "fr-process.h" +#include "glib-utils.h" + +#define INITIAL_SIZE 256 + + +/* Signals */ +enum { + START, + DONE, + PROGRESS, + MESSAGE, + WORKING_ARCHIVE, + LAST_SIGNAL +}; + +/* Properties */ +enum { + PROP_0, + PROP_FILENAME, + PROP_MIME_TYPE, + PROP_PROCESS, + PROP_PASSWORD, + PROP_ENCRYPT_HEADER, + PROP_COMPRESSION, + PROP_VOLUME_SIZE +}; + +static GObjectClass *parent_class = NULL; +static guint fr_command_signals[LAST_SIGNAL] = { 0 }; + +static void fr_command_class_init (FrCommandClass *class); +static void fr_command_init (FrCommand *afile); +static void fr_command_finalize (GObject *object); + +char *action_names[] = { "NONE", + "CREATING_NEW_ARCHIVE", + "LOADING_ARCHIVE", + "LISTING_CONTENT", + "DELETING_FILES", + "TESTING_ARCHIVE", + "GETTING_FILE_LIST", + "COPYING_FILES_FROM_REMOTE", + "ADDING_FILES", + "EXTRACTING_FILES", + "COPYING_FILES_TO_REMOTE", + "CREATING_ARCHIVE", + "SAVING_REMOTE_ARCHIVE" }; + +GType +fr_command_get_type () +{ + static GType type = 0; + + if (! type) { + GTypeInfo type_info = { + sizeof (FrCommandClass), + NULL, + NULL, + (GClassInitFunc) fr_command_class_init, + NULL, + NULL, + sizeof (FrCommand), + 0, + (GInstanceInitFunc) fr_command_init + }; + + type = g_type_register_static (G_TYPE_OBJECT, + "FRCommand", + &type_info, + 0); + } + + return type; +} + + +static void +base_fr_command_list (FrCommand *comm) +{ +} + + +static void +base_fr_command_add (FrCommand *comm, + const char *from_file, + GList *file_list, + const char *base_dir, + gboolean update, + gboolean recursive) +{ +} + + +static void +base_fr_command_delete (FrCommand *comm, + const char *from_file, + GList *file_list) +{ +} + + +static void +base_fr_command_extract (FrCommand *comm, + const char *from_file, + GList *file_list, + const char *dest_dir, + gboolean overwrite, + gboolean skip_older, + gboolean junk_paths) +{ +} + + +static void +base_fr_command_test (FrCommand *comm) +{ +} + + +static void +base_fr_command_uncompress (FrCommand *comm) +{ +} + + +static void +base_fr_command_recompress (FrCommand *comm) +{ +} + + +static void +base_fr_command_handle_error (FrCommand *comm, + FrProcError *error) +{ +} + + +const char **void_mime_types = { NULL }; + + +const char ** +base_fr_command_get_mime_types (FrCommand *comm) +{ + return void_mime_types; +} + + +FrCommandCap +base_fr_command_get_capabilities (FrCommand *comm, + const char *mime_type, + gboolean check_command) +{ + return FR_COMMAND_CAN_DO_NOTHING; +} + + +static void +base_fr_command_set_mime_type (FrCommand *comm, + const char *mime_type) +{ + comm->mime_type = get_static_string (mime_type); + fr_command_update_capabilities (comm); +} + + +static const char * +base_fr_command_get_packages (FrCommand *comm, + const char *mime_type) +{ + return NULL; +} + + +static void +fr_command_start (FrProcess *process, + gpointer data) +{ + FrCommand *comm = FR_COMMAND (data); + + g_signal_emit (G_OBJECT (comm), + fr_command_signals[START], + 0, + comm->action); +} + + +static void +fr_command_done (FrProcess *process, + gpointer data) +{ + FrCommand *comm = FR_COMMAND (data); + + comm->process->restart = FALSE; + fr_command_handle_error (comm, &process->error); + + if (comm->process->restart) { + fr_process_start (comm->process); + return; + } + + if (comm->action == FR_ACTION_LISTING_CONTENT) { + /* order the list by name to speed up search */ + g_ptr_array_sort (comm->files, file_data_compare_by_path); + } + + g_signal_emit (G_OBJECT (comm), + fr_command_signals[DONE], + 0, + comm->action, + &process->error); +} + + +static void +fr_command_set_process (FrCommand *comm, + FrProcess *process) +{ + if (comm->process != NULL) { + g_signal_handlers_disconnect_matched (G_OBJECT (comm->process), + G_SIGNAL_MATCH_DATA, + 0, + 0, NULL, + 0, + comm); + g_object_unref (G_OBJECT (comm->process)); + comm->process = NULL; + } + + if (process == NULL) + return; + + g_object_ref (G_OBJECT (process)); + comm->process = process; + g_signal_connect (G_OBJECT (comm->process), + "start", + G_CALLBACK (fr_command_start), + comm); + g_signal_connect (G_OBJECT (comm->process), + "done", + G_CALLBACK (fr_command_done), + comm); +} + + +static void +fr_command_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + FrCommand *comm; + + comm = FR_COMMAND (object); + + switch (prop_id) { + case PROP_PROCESS: + fr_command_set_process (comm, g_value_get_object (value)); + break; + case PROP_FILENAME: + fr_command_set_filename (comm, g_value_get_string (value)); + break; + case PROP_MIME_TYPE: + fr_command_set_mime_type (comm, g_value_get_string (value)); + break; + case PROP_PASSWORD: + g_free (comm->password); + comm->password = g_strdup (g_value_get_string (value)); + break; + case PROP_ENCRYPT_HEADER: + comm->encrypt_header = g_value_get_boolean (value); + break; + case PROP_COMPRESSION: + comm->compression = g_value_get_enum (value); + break; + case PROP_VOLUME_SIZE: + comm->volume_size = g_value_get_uint (value); + break; + default: + break; + } +} + + +static void +fr_command_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + FrCommand *comm; + + comm = FR_COMMAND (object); + + switch (prop_id) { + case PROP_PROCESS: + g_value_set_object (value, comm->process); + break; + case PROP_FILENAME: + g_value_set_string (value, comm->filename); + break; + case PROP_MIME_TYPE: + g_value_set_static_string (value, comm->mime_type); + break; + case PROP_PASSWORD: + g_value_set_string (value, comm->password); + break; + case PROP_ENCRYPT_HEADER: + g_value_set_boolean (value, comm->encrypt_header); + break; + case PROP_COMPRESSION: + g_value_set_enum (value, comm->compression); + break; + case PROP_VOLUME_SIZE: + g_value_set_uint (value, comm->volume_size); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +static void +fr_command_class_init (FrCommandClass *class) +{ + GObjectClass *gobject_class; + + parent_class = g_type_class_peek_parent (class); + + gobject_class = G_OBJECT_CLASS (class); + + /* virtual functions */ + + gobject_class->finalize = fr_command_finalize; + gobject_class->set_property = fr_command_set_property; + gobject_class->get_property = fr_command_get_property; + + class->list = base_fr_command_list; + class->add = base_fr_command_add; + class->delete = base_fr_command_delete; + class->extract = base_fr_command_extract; + class->test = base_fr_command_test; + class->uncompress = base_fr_command_uncompress; + class->recompress = base_fr_command_recompress; + class->handle_error = base_fr_command_handle_error; + class->get_mime_types = base_fr_command_get_mime_types; + class->get_capabilities = base_fr_command_get_capabilities; + class->set_mime_type = base_fr_command_set_mime_type; + class->get_packages = base_fr_command_get_packages; + class->start = NULL; + class->done = NULL; + class->progress = NULL; + class->message = NULL; + + /* signals */ + + fr_command_signals[START] = + g_signal_new ("start", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (FrCommandClass, start), + NULL, NULL, + fr_marshal_VOID__INT, + G_TYPE_NONE, + 1, G_TYPE_INT); + fr_command_signals[DONE] = + g_signal_new ("done", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (FrCommandClass, done), + NULL, NULL, + fr_marshal_VOID__INT_POINTER, + G_TYPE_NONE, 2, + G_TYPE_INT, + G_TYPE_POINTER); + fr_command_signals[PROGRESS] = + g_signal_new ("progress", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (FrCommandClass, progress), + NULL, NULL, + fr_marshal_VOID__DOUBLE, + G_TYPE_NONE, 1, + G_TYPE_DOUBLE); + fr_command_signals[MESSAGE] = + g_signal_new ("message", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (FrCommandClass, message), + NULL, NULL, + fr_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + fr_command_signals[WORKING_ARCHIVE] = + g_signal_new ("working_archive", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (FrCommandClass, working_archive), + NULL, NULL, + fr_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + + /* properties */ + + g_object_class_install_property (gobject_class, + PROP_PROCESS, + g_param_spec_object ("process", + "Process", + "The process object used by the command", + FR_TYPE_PROCESS, + G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, + PROP_FILENAME, + g_param_spec_string ("filename", + "Filename", + "The archive filename", + NULL, + G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, + PROP_MIME_TYPE, + g_param_spec_string ("mime-type", + "Mime type", + "The file mime-type", + NULL, + G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, + PROP_PASSWORD, + g_param_spec_string ("password", + "Password", + "The archive password", + NULL, + G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, + PROP_ENCRYPT_HEADER, + g_param_spec_boolean ("encrypt-header", + "Encrypt header", + "Whether to encrypt the archive header when creating the archive", + FALSE, + G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, + PROP_COMPRESSION, + g_param_spec_enum ("compression", + "Compression type", + "The compression type to use when creating the archive", + FR_TYPE_COMPRESSION, + FR_COMPRESSION_NORMAL, + G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, + PROP_VOLUME_SIZE, + g_param_spec_uint ("volume-size", + "Volume size", + "The size of each volume or 0 to not use volumes", + 0L, + G_MAXUINT, + 0, + G_PARAM_READWRITE)); +} + + +static void +fr_command_init (FrCommand *comm) +{ + comm->files = g_ptr_array_sized_new (INITIAL_SIZE); + + comm->password = NULL; + comm->encrypt_header = FALSE; + comm->compression = FR_COMPRESSION_NORMAL; + comm->volume_size = 0; + comm->filename = NULL; + comm->e_filename = NULL; + comm->fake_load = FALSE; + + comm->propAddCanUpdate = FALSE; + comm->propAddCanReplace = FALSE; + comm->propAddCanStoreFolders = FALSE; + comm->propExtractCanAvoidOverwrite = FALSE; + comm->propExtractCanSkipOlder = FALSE; + comm->propExtractCanJunkPaths = FALSE; + comm->propPassword = FALSE; + comm->propTest = FALSE; + comm->propCanExtractAll = TRUE; + comm->propCanDeleteNonEmptyFolders = TRUE; + comm->propCanExtractNonEmptyFolders = TRUE; + comm->propListFromFile = FALSE; +} + + +static void +fr_command_finalize (GObject *object) +{ + FrCommand* comm; + + g_return_if_fail (object != NULL); + g_return_if_fail (FR_IS_COMMAND (object)); + + comm = FR_COMMAND (object); + + g_free (comm->filename); + g_free (comm->e_filename); + g_free (comm->password); + if (comm->files != NULL) + g_ptr_array_free_full (comm->files, (GFunc) file_data_free, NULL); + fr_command_set_process (comm, NULL); + + /* Chain up */ + if (G_OBJECT_CLASS (parent_class)->finalize) + G_OBJECT_CLASS (parent_class)->finalize (object); +} + + +void +fr_command_set_filename (FrCommand *comm, + const char *filename) +{ + g_return_if_fail (FR_IS_COMMAND (comm)); + + if (comm->filename != NULL) { + g_free (comm->filename); + comm->filename = NULL; + } + + if (comm->e_filename != NULL) { + g_free (comm->e_filename); + comm->e_filename = NULL; + } + + if (filename != NULL) { + if (! g_path_is_absolute (filename)) { + char *current_dir; + + current_dir = g_get_current_dir (); + comm->filename = g_strconcat (current_dir, + "/", + filename, + NULL); + g_free (current_dir); + } + else + comm->filename = g_strdup (filename); + + comm->e_filename = g_shell_quote (comm->filename); + + debug (DEBUG_INFO, "filename : %s\n", comm->filename); + debug (DEBUG_INFO, "e_filename : %s\n", comm->e_filename); + } + + fr_command_working_archive (comm, comm->filename); +} + + +void +fr_command_set_multi_volume (FrCommand *comm, + const char *filename) +{ + comm->multi_volume = TRUE; + fr_command_set_filename (comm, filename); +} + + +void +fr_command_list (FrCommand *comm) +{ + g_return_if_fail (FR_IS_COMMAND (comm)); + + fr_command_progress (comm, -1.0); + + if (comm->files != NULL) { + g_ptr_array_free_full (comm->files, (GFunc) file_data_free, NULL); + comm->files = g_ptr_array_sized_new (INITIAL_SIZE); + } + + comm->action = FR_ACTION_LISTING_CONTENT; + fr_process_set_out_line_func (comm->process, NULL, NULL); + fr_process_set_err_line_func (comm->process, NULL, NULL); + fr_process_use_standard_locale (comm->process, TRUE); + comm->multi_volume = FALSE; + + if (! comm->fake_load) + FR_COMMAND_GET_CLASS (G_OBJECT (comm))->list (comm); + else + g_signal_emit (G_OBJECT (comm), + fr_command_signals[DONE], + 0, + comm->action, + &comm->process->error); +} + + +void +fr_command_add (FrCommand *comm, + const char *from_file, + GList *file_list, + const char *base_dir, + gboolean update, + gboolean recursive) +{ + fr_command_progress (comm, -1.0); + + comm->action = FR_ACTION_ADDING_FILES; + fr_process_set_out_line_func (FR_COMMAND (comm)->process, NULL, NULL); + fr_process_set_err_line_func (FR_COMMAND (comm)->process, NULL, NULL); + + FR_COMMAND_GET_CLASS (G_OBJECT (comm))->add (comm, + from_file, + file_list, + base_dir, + update, + recursive); +} + + +void +fr_command_delete (FrCommand *comm, + const char *from_file, + GList *file_list) +{ + fr_command_progress (comm, -1.0); + + comm->action = FR_ACTION_DELETING_FILES; + fr_process_set_out_line_func (FR_COMMAND (comm)->process, NULL, NULL); + fr_process_set_err_line_func (FR_COMMAND (comm)->process, NULL, NULL); + + FR_COMMAND_GET_CLASS (G_OBJECT (comm))->delete (comm, from_file, file_list); +} + + +void +fr_command_extract (FrCommand *comm, + const char *from_file, + GList *file_list, + const char *dest_dir, + gboolean overwrite, + gboolean skip_older, + gboolean junk_paths) +{ + fr_command_progress (comm, -1.0); + + comm->action = FR_ACTION_EXTRACTING_FILES; + fr_process_set_out_line_func (FR_COMMAND (comm)->process, NULL, NULL); + fr_process_set_err_line_func (FR_COMMAND (comm)->process, NULL, NULL); + + FR_COMMAND_GET_CLASS (G_OBJECT (comm))->extract (comm, + from_file, + file_list, + dest_dir, + overwrite, + skip_older, + junk_paths); +} + + +void +fr_command_test (FrCommand *comm) +{ + fr_command_progress (comm, -1.0); + + comm->action = FR_ACTION_TESTING_ARCHIVE; + fr_process_set_out_line_func (FR_COMMAND (comm)->process, NULL, NULL); + fr_process_set_err_line_func (FR_COMMAND (comm)->process, NULL, NULL); + + FR_COMMAND_GET_CLASS (G_OBJECT (comm))->test (comm); +} + + +void +fr_command_uncompress (FrCommand *comm) +{ + fr_command_progress (comm, -1.0); + FR_COMMAND_GET_CLASS (G_OBJECT (comm))->uncompress (comm); +} + + +void +fr_command_recompress (FrCommand *comm) +{ + fr_command_progress (comm, -1.0); + FR_COMMAND_GET_CLASS (G_OBJECT (comm))->recompress (comm); +} + + +const char ** +fr_command_get_mime_types (FrCommand *comm) +{ + return FR_COMMAND_GET_CLASS (G_OBJECT (comm))->get_mime_types (comm); +} + + +void +fr_command_update_capabilities (FrCommand *comm) +{ + comm->capabilities = fr_command_get_capabilities (comm, comm->mime_type, TRUE); +} + + +FrCommandCap +fr_command_get_capabilities (FrCommand *comm, + const char *mime_type, + gboolean check_command) +{ + return FR_COMMAND_GET_CLASS (G_OBJECT (comm))->get_capabilities (comm, mime_type, check_command); +} + + +gboolean +fr_command_is_capable_of (FrCommand *comm, + FrCommandCaps requested_capabilities) +{ + return (((comm->capabilities ^ requested_capabilities) & requested_capabilities) == 0); +} + + +const char * +fr_command_get_packages (FrCommand *comm, + const char *mime_type) +{ + return FR_COMMAND_GET_CLASS (G_OBJECT (comm))->get_packages (comm, mime_type); +} + + +/* fraction == -1 means : I don't known how much time the current operation + * will take, the dialog will display this info pulsing + * the progress bar. + * fraction in [0.0, 1.0] means the amount of work, in percentage, + * accomplished. + */ +void +fr_command_progress (FrCommand *comm, + double fraction) +{ + g_signal_emit (G_OBJECT (comm), + fr_command_signals[PROGRESS], + 0, + fraction); +} + + +void +fr_command_message (FrCommand *comm, + const char *msg) +{ + g_signal_emit (G_OBJECT (comm), + fr_command_signals[MESSAGE], + 0, + msg); +} + + +void +fr_command_working_archive (FrCommand *comm, + const char *archive_name) +{ + g_signal_emit (G_OBJECT (comm), + fr_command_signals[WORKING_ARCHIVE], + 0, + archive_name); +} + + +void +fr_command_set_n_files (FrCommand *comm, + int n_files) +{ + comm->n_files = n_files; + comm->n_file = 0; +} + + +void +fr_command_add_file (FrCommand *comm, + FileData *fdata) +{ + file_data_update_content_type (fdata); + g_ptr_array_add (comm->files, fdata); + if (! fdata->dir) + comm->n_regular_files++; +} + + +void +fr_command_set_mime_type (FrCommand *comm, + const char *mime_type) +{ + FR_COMMAND_GET_CLASS (G_OBJECT (comm))->set_mime_type (comm, mime_type); +} + + +void +fr_command_handle_error (FrCommand *comm, + FrProcError *error) +{ + FR_COMMAND_GET_CLASS (G_OBJECT (comm))->handle_error (comm, error); +} |