+/* This function manages the command for decompressing a comic book */
+static gboolean
+comics_decompress_temp_dir (const gchar *command_decompress_tmp,
+ const gchar *command,
+ GError **error)
+{
+ gboolean success;
+ gchar *std_out;
+ GError *err = NULL;
+ gint retval;
+
+ success = g_spawn_command_line_sync (command_decompress_tmp, &std_out,
+ NULL, &retval, &err);
+ if (!success) {
+ g_set_error (error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+ _("Error launching the %s command for decompressing \
+ the comic book to the temporary directory -- %s."),
+ g_path_get_basename (command),
+ err->message);
+ g_error_free (err);
+ } else if (WIFEXITED (retval)) {
+ if (WEXITSTATUS (retval) == EXIT_SUCCESS) {
+ g_free (std_out);
+ return TRUE;
+ } else {
+ g_set_error (error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+ _("The command %s failed at decompressing the \
+ comic book in to temporary directory."),
+ g_path_get_basename (command));
+ g_warning ("%s output: %s", g_path_get_basename
+ (command), std_out);
+ g_free (std_out);
+ }
+ } else {
+ g_set_error (error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+ _("The command %s does not end normally."),
+ g_path_get_basename (command));
+ g_free (std_out);
+ }
+
+ return FALSE;
+}
+
+/* This function shows how to use the choosen command for decompressing a
+ * comic book file. It modifies fields of the ComicsDocument struct with
+ * this information */
+static gboolean
+comics_generate_command_lines (ComicsDocument *comics_document,
+ GError **error)
+{
+ gchar *quoted_file;
+ gchar *command_decompress_tmp;
+
+ quoted_file = g_shell_quote (comics_document->archive);
+
+ /* RARLabs software */
+ if (g_str_has_suffix (comics_document->selected_command, "unrar") &&
+ !comics_document->flag_FLOSS) {
+ comics_document->extract_command =
+ g_strdup_printf ("%s p -c- -ierr",
+ comics_document->selected_command);
+ comics_document->list_command =
+ g_strdup_printf ("%s vb -c- -- %s",
+ comics_document->selected_command, quoted_file);
+ comics_document->flag_temp = FALSE;
+ comics_document->regex_arg = FALSE;
+ g_free (quoted_file);
+ return TRUE;
+ }
+
+ /* Gna! unrar */
+ if (g_str_has_suffix (comics_document->selected_command, "unrar-free")
+ || (g_str_has_suffix (comics_document->selected_command,
+ "unrar") && comics_document->flag_FLOSS)) {
+
+ comics_document->flag_temp = TRUE;
+
+ comics_document->dir = g_build_filename (ev_tmp_dir (),
+ g_compute_checksum_for_string (G_CHECKSUM_MD5,
+ comics_document->archive, -1), NULL);
+
+ /* unrar-free can't create directories so we do it on its
+ * behalf */
+ if (g_mkdir_with_parents (comics_document->dir, 0700) != 0) {
+ g_set_error (error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+ _("Failed to create a directory on the \
+ temporary directory."));
+ g_warning ("Failed to create directory %s: %s",
+ comics_document->dir, g_strerror (errno));
+ g_free (quoted_file);
+ return FALSE;
+ }
+
+ command_decompress_tmp = g_strdup_printf ( "%s -xf %s %s",
+ comics_document->selected_command,
+ quoted_file,
+ comics_document->dir);
+
+ if (!comics_decompress_temp_dir (command_decompress_tmp,
+ comics_document->selected_command,
+ error)){
+ g_free (command_decompress_tmp);
+ g_free (quoted_file);
+ return FALSE;
+ } else {
+ comics_document->list_command =
+ g_strdup_printf ("%s t %s",
+ comics_document->selected_command,
+ quoted_file);
+ comics_document->regex_arg = TRUE;
+ g_free (command_decompress_tmp);
+ g_free (quoted_file);
+ return TRUE;
+ }
+ }
+
+ /* InfoZIP's unzip */
+ if (g_str_has_suffix (comics_document->selected_command,"unzip")) {
+ comics_document->extract_command =
+ g_strdup_printf ("%s -p -C",
+ comics_document->selected_command);
+ comics_document->list_command =
+ g_strdup_printf ("%s -Z -1 -- %s",
+ comics_document->selected_command,
+ quoted_file);
+ comics_document->flag_temp = FALSE;
+ comics_document->regex_arg = TRUE;
+ g_free (quoted_file);
+ return TRUE;
+ }
+
+ /* p7zip */
+ if (g_str_has_suffix (comics_document->selected_command,"7zr")) {
+ comics_document->extract_command =
+ g_strdup_printf ("%s x -so",
+ comics_document->selected_command);
+ comics_document->list_command =
+ g_strdup_printf ("%s l -- %s",
+ comics_document->selected_command,
+ quoted_file);
+ comics_document->flag_temp = FALSE;
+ comics_document->regex_arg = TRUE;
+ g_free (quoted_file);
+ return TRUE;
+
+ }
+ /* You are not supposed to get here ! */
+ g_set_error_literal (error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+ _("Internal error configuring the command for decompressing \
+ the comic book file"));
+ g_free (quoted_file);
+ return FALSE;
+}
+
+/* This function chooses an external command for decompressing a comic
+ * book based on its mime tipe. */
+static gboolean
+comics_check_decompress_command (gchar *mime_type,
+ ComicsDocument *comics_document,
+ GError **error)
+{
+ gboolean success;
+ gchar *std_out, *std_err;
+ gint retval;
+ GError *err = NULL;
+
+ /* FIXME, use proper cbr/cbz mime types once they're
+ * included in shared-mime-info */
+
+ if (!strcmp (mime_type, "application/x-cbr") ||
+ !strcmp (mime_type, "application/x-rar")) {
+ /* The RARLAB provides a no-charge proprietary (freeware)
+ * decompress-only client for Linux called unrar. Another
+ * option is a GPLv2-licensed command-line tool developed by
+ * the Gna! project. Confusingly enough, the free software RAR
+ * decoder is also named unrar. For this reason we need to add
+ * some lines for disambiguation. Sorry for the added the
+ * complexity but it's life :)
+ * Finally, some distributions, like Debian, rename this free
+ * option as unrar-free.
+ * */
+ comics_document->selected_command =
+ g_find_program_in_path ("unrar");
+ if (comics_document->selected_command) {
+ /* We only use std_err to avoid printing useless error
+ * messages on the terminal */
+ success = g_spawn_command_line_sync (
+ comics_document->selected_command,
+ &std_out, &std_err, &retval, &err);
+ if (!success) {
+ g_propagate_error (error, err);
+ g_error_free (err);
+ return FALSE;
+ /* I don't check retval status because RARLAB unrar
+ * doesn't have a way to return 0 without involving an
+ * operation with a file*/
+ } else if (WIFEXITED (retval)) {
+ if (g_strrstr (std_out,"freeware") != NULL)
+ /* The RARLAB freeware client */
+ comics_document->flag_FLOSS = FALSE;
+ else
+ /* The Gna! free software client */
+ comics_document->flag_FLOSS = TRUE;
+ g_free (std_out);
+ g_free (std_err);
+ return TRUE;
+ }
+ }
+ /* The Gna! free software client with Debian naming convention */
+ comics_document->selected_command =
+ g_find_program_in_path ("unrar-free");
+ if (comics_document->selected_command)
+ return TRUE;
+ } else if (!strcmp (mime_type, "application/x-cbz") ||
+ !strcmp (mime_type, "application/zip")) {
+ /* InfoZIP's unzip program */
+ comics_document->selected_command =
+ g_find_program_in_path ("unzip");
+ if (comics_document->selected_command)
+ return TRUE;
+ } else if (!strcmp (mime_type, "application/x-cb7") ||
+ !strcmp (mime_type, "application/x-7z-compressed")) {
+ /* 7zr is a light stand-alone executable that supports only
+ * 7z/LZMA/BCJ */
+ comics_document->selected_command =
+ g_find_program_in_path ("7zr");
+ if (comics_document->selected_command)
+ return TRUE;
+ } else {
+ g_set_error (error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+ _("Not a comic book MIME type: %s"),
+ mime_type);
+ return FALSE;
+ }
+ g_set_error_literal (error,
+ EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_INVALID,
+ ("I can't find an appropiate command for \
+ decompressing this type of comic book"));
+ return FALSE;
+}
+