From 14790d2d45e43643ff6b11cde1b1bb53cc4ea9ac Mon Sep 17 00:00:00 2001 From: raveit65 Date: Mon, 7 Oct 2013 12:33:37 +0200 Subject: add support for rar-5.0x --- src/fr-command-rar.c | 168 ++++++++++++++++++++++++++++++++++++++------------- src/fr-command-rar.h | 3 +- 2 files changed, 128 insertions(+), 43 deletions(-) diff --git a/src/fr-command-rar.c b/src/fr-command-rar.c index 6ef0859..631d58a 100644 --- a/src/fr-command-rar.c +++ b/src/fr-command-rar.c @@ -56,8 +56,8 @@ have_rar (void) static time_t -mktime_from_string (char *date_s, - char *time_s) +mktime_from_string (const char *date_s, + const char *time_s) { struct tm tm = {0, }; char **fields; @@ -90,6 +90,84 @@ mktime_from_string (char *date_s, return mktime (&tm); } +/* Sample rar-5 listing output: + +RAR 5.00 beta 8 Copyright (c) 1993-2013 Alexander Roshal 22 Aug 2013 +Trial version Type RAR -? for help + +Archive: test.rar +Details: RAR 4 + + Attributes Size Packed Ratio Date Time Checksum Name +----------- --------- -------- ----- -------- ----- -------- ---- + -rw-r--r-- 453 304 67% 05-09-13 09:55 56DA5EF3 loremipsum.txt +----------- --------- -------- ----- -------- ----- -------- ---- + 453 304 67% 1 + + * + * Sample rar-4 listing output: + * + +RAR 4.20 Copyright (c) 1993-2012 Alexander Roshal 9 Jun 2012 +Trial version Type RAR -? for help + +Archive test.rar + +Pathname/Comment + Size Packed Ratio Date Time Attr CRC Meth Ver +------------------------------------------------------------------------------- + loremipsum.txt + 453 304 67% 05-09-13 09:55 -rw-r--r-- 56DA5EF3 m3b 2.9 +------------------------------------------------------------------------------- + 1 453 304 67% + + */ + +static void +parse_name_field (char *line, + FrCommandRar *rar_comm) +{ + char *name_field; + FileData *fdata; + + rar_comm->fdata = fdata = file_data_new (); + + /* read file name. */ + + fdata->encrypted = (line[0] == '*') ? TRUE : FALSE; + + if (rar_comm->rar5) + /* rar-5 output adds trailing spaces to short file names :( */ + name_field = g_strchomp (g_strdup (get_last_field (line, 8))); + else + name_field = g_strdup (line + 1); + + if (*name_field == '/') { + fdata->full_path = g_strdup (name_field); + fdata->original_path = fdata->full_path; + } + else { + fdata->full_path = g_strconcat ("/", name_field, NULL); + fdata->original_path = fdata->full_path + 1; + } + + fdata->link = NULL; + fdata->path = remove_level_from_path (fdata->full_path); + + g_free (name_field); +} + +static gboolean +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')) + return TRUE; + + return FALSE; +} static void process_line (char *line, @@ -98,14 +176,24 @@ process_line (char *line, FrCommand *comm = FR_COMMAND (data); FrCommandRar *rar_comm = FR_COMMAND_RAR (comm); char **fields; - const char *name_field; g_return_if_fail (line != NULL); if (! rar_comm->list_started) { - if (strncmp (line, "--------", 8) == 0) { + if (strncmp (line, "RAR ", 4) == 0) { + int version; + sscanf (line, "RAR %d.", &version); + rar_comm->rar5 = (version >= 5); + } + else if (strncmp (line, "UNRAR ", 6) == 0) { + int version; + sscanf (line, "UNRAR %d.", &version); + rar_comm->rar5 = (version >= 5); + } + else if (strncmp (line, "--------", 8) == 0) { rar_comm->list_started = TRUE; - rar_comm->odd_line = TRUE; + if (! rar_comm->rar5) + rar_comm->rar4_odd_line = TRUE; } else if (strncmp (line, "Volume ", 7) == 0) comm->multi_volume = TRUE; @@ -117,24 +205,43 @@ process_line (char *line, return; } - if (! rar_comm->odd_line) { - FileData *fdata; + if (rar_comm->rar4_odd_line || rar_comm->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; fdata = rar_comm->fdata; /* read file info. */ fields = split_line (line, 6); + if (rar_comm->rar5) { + size_field = fields[1]; + ratio_field = fields[3]; + date_field = fields[4]; + time_field = fields[5]; + attr_field = fields[0]; + } + 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) { /* wrong line format, treat this line as a filename line */ g_strfreev (fields); file_data_free (rar_comm->fdata); rar_comm->fdata = NULL; - rar_comm->odd_line = TRUE; + rar_comm->rar4_odd_line = TRUE; + parse_name_field (line, rar_comm); } else { - if ((strcmp (fields[2], "<->") == 0) - || (strcmp (fields[2], "<--") == 0)) + if ((strcmp (ratio_field, "<->") == 0) + || (strcmp (ratio_field, "<--") == 0)) { /* ignore files that span more volumes */ @@ -142,10 +249,10 @@ process_line (char *line, rar_comm->fdata = NULL; } else { - fdata->size = g_ascii_strtoull (fields[0], NULL, 10); - fdata->modified = mktime_from_string (fields[3], fields[4]); + fdata->size = g_ascii_strtoull (size_field, NULL, 10); + fdata->modified = mktime_from_string (date_field, time_field); - if ((fields[5][1] == 'D') || (fields[5][0] == 'd')) { + if (attr_field_is_dir (attr_field, rar_comm)) { char *tmp; tmp = fdata->full_path; @@ -159,8 +266,11 @@ process_line (char *line, fdata->name = dir_name_from_path (fdata->full_path); fdata->dir = TRUE; } - else + else { fdata->name = g_strdup (file_name_from_path (fdata->full_path)); + if (attr_field[0] == 'l') + fdata->link = g_strdup (file_name_from_path (fdata->full_path)); + } fr_command_add_file (comm, fdata); rar_comm->fdata = NULL; @@ -170,34 +280,8 @@ process_line (char *line, } } - if (rar_comm->odd_line) { - FileData *fdata; - - rar_comm->fdata = fdata = file_data_new (); - - /* read file name. */ - - fdata->encrypted = (line[0] == '*') ? TRUE : FALSE; - - name_field = line + 1; - - if (*name_field == '/') { - fdata->full_path = g_strdup (name_field); - fdata->original_path = fdata->full_path; - } - else { - fdata->full_path = g_strconcat ("/", name_field, NULL); - fdata->original_path = fdata->full_path + 1; - } - - fdata->link = NULL; - fdata->path = remove_level_from_path (fdata->full_path); - } - else { - - } - - rar_comm->odd_line = ! rar_comm->odd_line; + if (! rar_comm->rar5) + rar_comm->rar4_odd_line = ! rar_comm->rar4_odd_line; } diff --git a/src/fr-command-rar.h b/src/fr-command-rar.h index e2a5e12..c86fec5 100644 --- a/src/fr-command-rar.h +++ b/src/fr-command-rar.h @@ -43,7 +43,8 @@ struct _FrCommandRar FrCommand __parent; gboolean list_started; - gboolean odd_line; + gboolean rar4_odd_line; + gboolean rar5; FileData *fdata; }; -- cgit v1.2.1