head	1.1;
access;
symbols
	RELEASE_8_3_0:1.1;
locks; strict;
comment	@# @;


1.1
date	2012.01.18.03.00.40;	author danfe;	state Exp;
branches;
next	;


desc
@@


1.1
log
@- Add support for new InstallShield header format instead of calling abort()
  (sic!) on such files.  When header format could not be detected, try to use
  the newest algorithm instead the oldest one; this should make the port more
  "future proof"
- Allow to specify header format via command line (-i <version>) to override
  default detection logic
- Bump port revision and reformat Makefile header while I am here

Obtained from:	SynCE bug tracker at sf.net (ID: 3163039)
Approved by:	maintainer (sunpoet)
@
text
@--- lib/component.c.orig
+++ lib/component.c
@@@@ -40,11 +40,13 @@@@
     case 7:
     case 8:
     case 9:
+    case 10:
+    case 11:
+    case 12:
+    case 13:
+    default:
       p += 0x6b;
       break;
-
-    default:
-      abort();
   }
 
   self->file_group_count = READ_UINT16(p); p += 2;
--- lib/file.c.orig
+++ lib/file.c
@@@@ -77,6 +77,11 @@@@
     case 7:
     case 8:
     case 9:
+    case 10:
+    case 11:
+    case 12:
+    case 13:
+    default:
       saved_p = p = header->data +
           header->common.cab_descriptor_offset +
           header->cab.file_table_offset +
@@@@ -117,10 +122,6 @@@@
 
       assert((p - saved_p) == 0x57);
       break;
-
-    default:
-      unshield_error("Unknown major version: %i", header->major_version);
-      abort();
   }
 
   if (!(fd->flags & FILE_COMPRESSED) &&
@@@@ -363,6 +364,11 @@@@
     case 7:
     case 8:
     case 9:
+    case 10:
+    case 11:
+    case 12:
+    case 13:
+    default:
       {
         uint8_t six_header[VOLUME_HEADER_SIZE_V6];
         uint8_t* p = six_header;
@@@@ -389,10 +395,6 @@@@
         reader->volume_header.last_file_size_compressed_high    = READ_UINT32(p); p += 4;
       }
       break;
-
-    default:
-      abort();
-      goto exit;
   }
   
 #if VERBOSE >= 2
--- lib/libunshield.c.orig
+++ lib/libunshield.c
@@@@ -205,7 +205,7 @@@@
 /**
   Read all header files
  */
-static bool unshield_read_headers(Unshield* unshield)/*{{{*/
+static bool unshield_read_headers(Unshield* unshield, int version)/*{{{*/
 {
   int i;
   bool iterate = true;
@@@@ -268,8 +268,21 @@@@
         unshield_error("Failed to read common header from header file %i", i);
         goto error;
       }
-      
-      header->major_version = (header->common.version >> 12) & 0xf;
+
+      if (version != -1)
+      {
+        header->major_version = version;
+      }
+      else if (header->common.version >> 24 == 1)
+      {
+        header->major_version = (header->common.version >> 12) & 0xf;
+      }
+      else if (header->common.version >> 24 == 2)
+      {
+        header->major_version = (header->common.version & 0xffff);
+        if (header->major_version != 0)
+          header->major_version = header->major_version / 100;
+      }
 
 #if 0
       if (header->major_version < 5)
@@@@ -326,6 +339,11 @@@@
 
 Unshield* unshield_open(const char* filename)/*{{{*/
 {
+  unshield_open_force_version(filename, -1);
+}/*}}}*/
+
+Unshield* unshield_open_force_version(const char* filename, int version)/*{{{*/
+{
   Unshield* unshield = NEW1(Unshield);
   if (!unshield)
   {
@@@@ -339,7 +357,7 @@@@
     goto error;
   }
 
-  if (!unshield_read_headers(unshield))
+  if (!unshield_read_headers(unshield, version))
   {
     unshield_error("Failed to read header files");
     goto error;
--- lib/libunshield.h.orig
+++ lib/libunshield.h
@@@@ -33,6 +33,7 @@@@
  */
 
 Unshield* unshield_open(const char* filename);
+Unshield* unshield_open_force_version(const char* filename, int version);
 void unshield_close(Unshield* unshield);
 
 /*
--- man/unshield.1.orig
+++ man/unshield.1
@@@@ -2,7 +2,7 @@@@
 .SH NAME
 unshield \- extract CAB files from an InstallShield installer archive
 .SH SYNOPSIS
-unshield [\-c COMPONENT] [\-d DIRECTORY] [\-D LEVEL] [\-g GROUP] [\-h] [\-j] [\-L] [\-n] [\-o] [\-O] [\-r] [\-v] [\-V] c|g|l|t|x CABFILE
+unshield [\-c COMPONENT] [\-d DIRECTORY] [\-D LEVEL] [\-g GROUP] [\-h] [\-i VERSION] [\-j] [\-L] [\-n] [\-o] [\-O] [\-r] [\-v] [\-V] c|g|l|t|x CABFILE
 .SH DESCRIPTION
 Unshield extracts CAB files from InstallShield installers, used to 
 install software on Microsoft Windows based machines.
@@@@ -27,6 +27,11 @@@@
 \fB\-h\fR
 Show help message
 .TP
+\fB\-i\fR VERSION
+Force InstallShield version number (don't autodetect)\n
+.br
+Use this option if you have a very old archive (generated with InstallShield <= 4) and / or the automatic detection fails
+.TP
 \fB\-j\fR
 Junk paths (do not make directories)
 .TP
--- src/unshield.c.orig
+++ src/unshield.c
@@@@ -58,6 +58,7 @@@@
 static int log_level                  = UNSHIELD_LOG_LEVEL_LOWEST;
 static int exit_status                = 0;
 static FORMAT format                  = FORMAT_NEW;
+static int is_version                 = -1;
 
 static bool make_sure_directory_exists(const char* directory)/*{{{*/
 {
@@@@ -108,7 +109,7 @@@@
   fprintf(stderr,
       "Syntax:\n"
       "\n"
-      "\t%s [-c COMPONENT] [-d DIRECTORY] [-D LEVEL] [-g GROUP] [-GhlOrV] c|g|l|t|x CABFILE\n"
+      "\t%s [-c COMPONENT] [-d DIRECTORY] [-D LEVEL] [-g GROUP] [-i VERSION] [-GhlOrV] c|g|l|t|x CABFILE\n"
       "\n"
       "Options:\n"
       "\t-c COMPONENT  Only list/extract this component\n"
@@@@ -120,6 +121,7 @@@@
       "\t                3 - Errors, warnings and debug messages\n"
       "\t-g GROUP      Only list/extract this file group\n"
       "\t-h            Show this help message\n"
+      "\t-i VERSION    Force InstallShield version number (don't autodetect)\n"
       "\t-j            Junk paths (do not make directories)\n"
       "\t-L            Make file and directory names lowercase\n"
       "\t-O            Use old compression\n"
@@@@ -152,7 +154,7 @@@@
 {
 	int c;
 
-	while ((c = getopt(argc, argv, "c:d:D:g:hjLnoOrV")) != -1)
+	while ((c = getopt(argc, argv, "c:d:D:g:hi:jLnoOrV")) != -1)
 	{
 		switch (c)
     {
@@@@ -172,6 +174,10 @@@@
         file_group_name = optarg;
         break;
 
+      case 'i':
+        is_version = atoi(optarg);
+        break;
+
       case 'j':
         junk_paths = true;
         break;
@@@@ -532,7 +538,7 @@@@
 
   cabfile = argv[last_optind];
 
-  unshield = unshield_open(cabfile);
+  unshield = unshield_open_force_version(cabfile, is_version);
   if (!unshield)
   {
     fprintf(stderr, "Failed to open %s as an InstallShield Cabinet File\n", cabfile);
@
