diff options
Diffstat (limited to 'src/fr-command-rar.c')
-rw-r--r-- | src/fr-command-rar.c | 215 |
1 files changed, 89 insertions, 126 deletions
diff --git a/src/fr-command-rar.c b/src/fr-command-rar.c index e2eb8df..6bb70cd 100644 --- a/src/fr-command-rar.c +++ b/src/fr-command-rar.c @@ -20,6 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#define _XOPEN_SOURCE 700 + #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -45,17 +47,31 @@ static void fr_command_rar_finalize (GObject *object); static FrCommandClass *parent_class = NULL; - /* rar 5.30 and later uses YYYY-MM-DD instead DD-MM-YY in the listing output */ static gboolean date_newstyle = FALSE; -static gboolean -have_rar (void) +static const struct { + const gchar *command; + FrCommandCaps capabilities; +} candidate_commands[] = { + { "rar", FR_COMMAND_CAN_READ_WRITE | FR_COMMAND_CAN_CREATE_VOLUMES }, + { "unrar", FR_COMMAND_CAN_READ }, + { "unrar-free", FR_COMMAND_CAN_READ } +}; + +static const gchar * +get_rar_command (void) { - return is_program_in_path ("rar"); -} + for (guint i = 0; i < G_N_ELEMENTS(candidate_commands); i++) { + if (is_program_in_path (candidate_commands[i].command)) + return candidate_commands[i].command; + } + /* this should never happen as we shouldn't get called if none of the + * candidate exist, but better safe than sorry */ + return "unrar"; +} /* -- list -- */ @@ -76,8 +92,6 @@ Details: RAR 4 ----------- --------- -------- ----- ---------- ----- -------- ---- 3165 1318 41% 2 - - // SAMPLE RAR VERSION 5.00 TO 5.21 LISTING OUTPUT: RAR 5.21 Copyright (c) 1993-2015 Alexander Roshal 15 Feb 2015 @@ -93,8 +107,6 @@ Details: RAR 4 ----------- --------- -------- ----- -------- ----- -------- ---- 3165 1318 41% 2 - - // SAMPLE RAR VERSION 4.20 AND OLDER LISTING OUTPUT: RAR 4.20 Copyright (c) 1993-2012 Alexander Roshal 9 Jun 2012 @@ -118,46 +130,19 @@ static time_t mktime_from_string (const char *date_s, const char *time_s) { - struct tm tm = {0, }; - char **fields; + struct tm tm = {0, }; + char *date_time_s; tm.tm_isdst = -1; - - /* date */ - - fields = g_strsplit (date_s, "-", 3); - if (fields[0] != NULL) { - if (date_newstyle) - tm.tm_year = atoi (fields[0]) - 1900; - else - tm.tm_mday = atoi (fields[0]); - if (fields[1] != NULL) { - tm.tm_mon = atoi (fields[1]) - 1; - if (fields[2] != NULL) { - if (date_newstyle) - tm.tm_mday = atoi (fields[2]); - else - tm.tm_year = 100 + atoi (fields[2]); - } - } - } - g_strfreev (fields); - - /* time */ - - fields = g_strsplit (time_s, ":", 2); - if (fields[0] != NULL) { - tm.tm_hour = atoi (fields[0]); - if (fields[1] != NULL) - tm.tm_min = atoi (fields[1]); - } - g_strfreev (fields); + date_time_s = g_strjoin (" ", date_s, time_s, NULL); + strptime (date_time_s, date_newstyle ? "%Y-%m-%d %H:%M" : "%d-%m-%y %H:%M", &tm); + g_free (date_time_s); return mktime (&tm); } static gboolean -attribute_field_with_space (char *line) +attribute_field_with_space (const char *line) { /* sometimes when the archive is encrypted the attributes field is * like this: "* ..A...." @@ -178,7 +163,7 @@ parse_name_field (char *line, fdata->encrypted = (line[0] == '*') ? TRUE : FALSE; - if (rar_comm->rar5) + if (rar_comm->output_type == FR_COMMAND_RAR_TYPE_RAR5) /* rar-5 output adds trailing spaces to short file names :( */ name_field = g_strchomp (g_strdup (get_last_field (line, attribute_field_with_space (line) ? 9 : 8))); else @@ -207,8 +192,8 @@ attr_field_is_dir (const char *attr_field, FrCommandRar *rar_comm) { if ((attr_field[0] == 'd') || - (rar_comm->rar5 && attr_field[3] == 'D') || - (!rar_comm->rar5 && attr_field[1] == 'D')) + (rar_comm->output_type == FR_COMMAND_RAR_TYPE_RAR5 && attr_field[3] == 'D') || + (rar_comm->output_type != FR_COMMAND_RAR_TYPE_RAR5 && attr_field[1] == 'D')) return TRUE; return FALSE; @@ -225,39 +210,27 @@ process_line (char *line, g_return_if_fail (line != NULL); if (! rar_comm->list_started) { - if (strncmp (line, "RAR ", 4) == 0) { - int version; - sscanf (line, "RAR %d.", &version); - rar_comm->rar5 = (version >= 5); - - if (version > 5) - date_newstyle = TRUE; - else if (version == 5) - { - sscanf (line, "RAR 5.%d ", &version); - if (version >= 30) - date_newstyle = TRUE; - } + int version = 0; - } - else if (strncmp (line, "UNRAR ", 6) == 0) { - int version; - sscanf (line, "UNRAR %d.", &version); - rar_comm->rar5 = (version >= 5); + if (sscanf (line, "RAR %d.", &version) == 1 || sscanf (line, "UNRAR %d.", &version) == 1) { + rar_comm->output_type = (version >= 5) ? FR_COMMAND_RAR_TYPE_RAR5 : FR_COMMAND_RAR_TYPE_RAR4; if (version > 5) date_newstyle = TRUE; - else if (version == 5) + else if (version == 5 && (sscanf (line, "RAR 5.%d ", &version) == 1 || + sscanf (line, "UNRAR 5.%d ", &version) == 1)) { - sscanf (line, "UNRAR 5.%d ", &version); if (version >= 30) date_newstyle = TRUE; } - + } + else if (g_str_has_prefix (line, "unrar-free ")) { + rar_comm->output_type = FR_COMMAND_RAR_TYPE_UNRAR_FREE; + date_newstyle = FALSE; } else if (strncmp (line, "--------", 8) == 0) { rar_comm->list_started = TRUE; - if (! rar_comm->rar5) + if (rar_comm->output_type != FR_COMMAND_RAR_TYPE_RAR5) rar_comm->rar4_odd_line = TRUE; } else if (strncmp (line, "Volume ", 7) == 0) @@ -270,35 +243,27 @@ process_line (char *line, return; } - if (rar_comm->rar4_odd_line || rar_comm->rar5) + if (rar_comm->rar4_odd_line || rar_comm->output_type == FR_COMMAND_RAR_TYPE_RAR5) parse_name_field (line, rar_comm); if (! rar_comm->rar4_odd_line) { FileData *fdata; const char *size_field, *ratio_field, *date_field, *time_field, *attr_field; + int n_fields; + + if (rar_comm->output_type == FR_COMMAND_RAR_TYPE_RAR5) + n_fields = 6 + (attribute_field_with_space (line) != 0); + else if (rar_comm->output_type == FR_COMMAND_RAR_TYPE_UNRAR_FREE) + n_fields = 4; + else + n_fields = 6; fdata = rar_comm->fdata; /* read file info. */ - fields = split_line (line, attribute_field_with_space (line) ? 7 : 6); - if (rar_comm->rar5) { - int offset = attribute_field_with_space (line) ? 1 : 0; - - size_field = fields[1+offset]; - ratio_field = fields[3+offset]; - date_field = fields[4+offset]; - time_field = fields[5+offset]; - attr_field = fields[0+offset]; - } - else { - size_field = fields[0]; - ratio_field = fields[2]; - date_field = fields[3]; - time_field = fields[4]; - attr_field = fields[5]; - } - if (g_strv_length (fields) < 6) { + fields = split_line (line, n_fields); + if (g_strv_length (fields) < (guint) n_fields) { /* wrong line format, treat this line as a filename line */ g_strfreev (fields); file_data_free (rar_comm->fdata); @@ -307,6 +272,30 @@ process_line (char *line, parse_name_field (line, rar_comm); } else { + if (rar_comm->output_type == FR_COMMAND_RAR_TYPE_RAR5) { + int offset = attribute_field_with_space (line) ? 1 : 0; + + size_field = fields[1+offset]; + ratio_field = fields[3+offset]; + date_field = fields[4+offset]; + time_field = fields[5+offset]; + attr_field = fields[0+offset]; + } + else if (rar_comm->output_type == FR_COMMAND_RAR_TYPE_UNRAR_FREE) { + size_field = fields[0]; + date_field = fields[1]; + time_field = fields[2]; + attr_field = fields[3]; + ratio_field = ""; + } + else { + size_field = fields[0]; + ratio_field = fields[2]; + date_field = fields[3]; + time_field = fields[4]; + attr_field = fields[5]; + } + if ((strcmp (ratio_field, "<->") == 0) || (strcmp (ratio_field, "<--") == 0)) { @@ -347,11 +336,10 @@ process_line (char *line, } } - if (! rar_comm->rar5) + if (rar_comm->output_type != FR_COMMAND_RAR_TYPE_RAR5) rar_comm->rar4_odd_line = ! rar_comm->rar4_odd_line; } - static void add_password_arg (FrCommand *comm, const char *password, @@ -367,7 +355,6 @@ add_password_arg (FrCommand *comm, fr_process_add_arg (comm->process, "-p-"); } - static void list__begin (gpointer data) { @@ -376,7 +363,6 @@ list__begin (gpointer data) comm->list_started = FALSE; } - static void fr_command_rar_list (FrCommand *comm) { @@ -384,10 +370,7 @@ fr_command_rar_list (FrCommand *comm) fr_process_set_out_line_func (comm->process, process_line, comm); - if (have_rar ()) - fr_process_begin_command (comm->process, "rar"); - else - fr_process_begin_command (comm->process, "unrar"); + fr_process_begin_command (comm->process, get_rar_command ()); fr_process_set_begin_func (comm->process, list__begin, comm); fr_process_add_arg (comm->process, "v"); fr_process_add_arg (comm->process, "-c-"); @@ -404,7 +387,6 @@ fr_command_rar_list (FrCommand *comm) fr_process_start (comm->process); } - static void parse_progress_line (FrCommand *comm, const char *prefix, @@ -415,7 +397,6 @@ parse_progress_line (FrCommand *comm, fr_command_progress (comm, (double) ++comm->n_file / (comm->n_files + 1)); } - static void process_line__add (char *line, gpointer data) @@ -451,7 +432,6 @@ process_line__add (char *line, parse_progress_line (comm, "Adding ", _("Adding file: "), line); } - static void fr_command_rar_add (FrCommand *comm, const char *from_file, @@ -508,7 +488,6 @@ fr_command_rar_add (FrCommand *comm, fr_process_end_command (comm->process); } - static void process_line__delete (char *line, gpointer data) @@ -529,7 +508,6 @@ process_line__delete (char *line, parse_progress_line (comm, "Deleting ", _("Removing file: "), line); } - static void fr_command_rar_delete (FrCommand *comm, const char *from_file, @@ -557,7 +535,6 @@ fr_command_rar_delete (FrCommand *comm, fr_process_end_command (comm->process); } - static void process_line__extract (char *line, gpointer data) @@ -578,7 +555,6 @@ process_line__extract (char *line, parse_progress_line (comm, "Extracting ", _("Extracting file: "), line); } - static void fr_command_rar_extract (FrCommand *comm, const char *from_file, @@ -595,10 +571,7 @@ fr_command_rar_extract (FrCommand *comm, process_line__extract, comm); - if (have_rar ()) - fr_process_begin_command (comm->process, "rar"); - else - fr_process_begin_command (comm->process, "unrar"); + fr_process_begin_command (comm->process, get_rar_command ()); fr_process_add_arg (comm->process, "x"); @@ -636,14 +609,10 @@ fr_command_rar_extract (FrCommand *comm, fr_process_end_command (comm->process); } - static void fr_command_rar_test (FrCommand *comm) { - if (have_rar ()) - fr_process_begin_command (comm->process, "rar"); - else - fr_process_begin_command (comm->process, "unrar"); + fr_process_begin_command (comm->process, get_rar_command ()); fr_process_add_arg (comm->process, "t"); @@ -659,7 +628,6 @@ fr_command_rar_test (FrCommand *comm) fr_process_end_command (comm->process); } - static void fr_command_rar_handle_error (FrCommand *comm, FrProcError *error) @@ -713,31 +681,31 @@ fr_command_rar_handle_error (FrCommand *comm, } } - const char *rar_mime_type[] = { "application/x-cbr", "application/x-rar", NULL }; - static const char ** fr_command_rar_get_mime_types (FrCommand *comm) { return rar_mime_type; } - -static FrCommandCap +static FrCommandCaps fr_command_rar_get_capabilities (FrCommand *comm, const char *mime_type, gboolean check_command) { - FrCommandCap capabilities; + FrCommandCaps capabilities; capabilities = FR_COMMAND_CAN_ARCHIVE_MANY_FILES | FR_COMMAND_CAN_ENCRYPT | FR_COMMAND_CAN_ENCRYPT_HEADER; - if (is_program_available ("rar", check_command)) - capabilities |= FR_COMMAND_CAN_READ_WRITE | FR_COMMAND_CAN_CREATE_VOLUMES; - else if (is_program_available ("unrar", check_command)) - capabilities |= FR_COMMAND_CAN_READ; + /* add command-specific capabilities depending on availability */ + for (guint i = 0; i < G_N_ELEMENTS (candidate_commands); i++) { + if (is_program_available (candidate_commands[i].command, check_command)) { + capabilities |= candidate_commands[i].capabilities; + break; + } + } /* multi-volumes are read-only */ if ((comm->files->len > 0) && comm->multi_volume && (capabilities & FR_COMMAND_CAN_WRITE)) @@ -746,15 +714,13 @@ fr_command_rar_get_capabilities (FrCommand *comm, return capabilities; } - static const char * fr_command_rar_get_packages (FrCommand *comm, const char *mime_type) { - return PACKAGES ("rar,unrar"); + return PACKAGES ("rar,unrar,unrar-free"); } - static void fr_command_rar_class_init (FrCommandRarClass *class) { @@ -777,7 +743,6 @@ fr_command_rar_class_init (FrCommandRarClass *class) afc->get_packages = fr_command_rar_get_packages; } - static void fr_command_rar_init (FrCommand *comm) { @@ -792,7 +757,6 @@ fr_command_rar_init (FrCommand *comm) comm->propListFromFile = TRUE; } - static void fr_command_rar_finalize (GObject *object) { @@ -804,7 +768,6 @@ fr_command_rar_finalize (GObject *object) G_OBJECT_CLASS (parent_class)->finalize (object); } - GType fr_command_rar_get_type () { |