Add decompression support using the implode library
authorTJ <hacker@iam.tj>
Sat, 14 Nov 2015 01:04:28 +0000 (01:04 +0000)
committerTJ <hacker@iam.tj>
Sat, 14 Nov 2015 01:04:28 +0000 (01:04 +0000)
Makefile
common.h [new file with mode: 0755]
implode.c [new file with mode: 0755]
implode.h [new file with mode: 0755]
installshield_main.c
installshield_z.h
posix.h [new file with mode: 0755]

index 4946167..5136894 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,22 +1,36 @@
-EXE=isz
-DATA=DATA.Z
-SRC=installshield_main.c
-CFLAGS=$(CLFAGS) -g
+EXE = isz
+DATA = DATA.Z
+SRC = installshield_main.c implode.c
+OBJ = implode.o installshield_main.o
+CFLAGS = $(CLFAGS) -I. -Wall -g
 
-build:
-       gcc $(CFLAGS) -o $(EXE) $(SRC)
+#build: $(EXE)
+#      gcc $(CFLAGS) -o $(EXE) $(SRC)
 
-run: build
+$(EXE):        $(OBJ)
+       gcc -o $@ $(OBJ)
+
+$(OBJ): implode.h installshield_z.h
+
+.c.o:
+       $(CC) $(CFLAGS) -c $<
+
+run: $(EXE)
        ./$(EXE) $(DATA) -x
 
-debug: build
+debug: $(EXE)
        DEBUG=1 ./$(EXE) $(DATA) -x
 
-strace: build
-       DEBU=1 strace ./$(EXE) $(DATA) -x
+strace: $(EXE)
+       DEBUG=1 strace ./$(EXE) $(DATA) -x
 
 clean:
        rm -f $(EXE) *.o
+
+clean-data:
        rm -rf COMMON PDMAIN PDDOC
 
-PHONY: clean
+clean-all: clean clean-data
+
+PHONY: clean run debug strace
+
diff --git a/common.h b/common.h
new file mode 100755 (executable)
index 0000000..b99aa4c
--- /dev/null
+++ b/common.h
@@ -0,0 +1,75 @@
+/************************************************************************/\r
+/* File Name   : common.h                                               */\r
+/* Creator     : ax.minaduki@gmail.com                                  */\r
+/* Create Time : Nov 27th, 2008                                         */\r
+/* Module      : Common library                                         */\r
+/* Descript    : Common definations                                     */\r
+/************************************************************************/\r
+\r
+#ifndef __SD_COMMON_COMMON_H__\r
+#define __SD_COMMON_COMMON_H__\r
+\r
+/************************************************************************/\r
+\r
+/* #include <const.h> -- removed by Tony Lewis */\r
+\r
+#ifdef __cplusplus\r
+\r
+#include <ctime>\r
+#include <cstdio>\r
+#include <cctype>\r
+#include <cstring>\r
+#include <cstdlib>\r
+#include <cassert>\r
+\r
+#else\r
+\r
+#include <time.h>\r
+#include <stdio.h>\r
+#include <ctype.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include <assert.h>\r
+\r
+#endif\r
+\r
+/************************************************************************/\r
+\r
+#ifdef __cplusplus\r
+#define CAPI                   extern "C"\r
+#else\r
+#define CAPI\r
+#endif\r
+\r
+/************************************************************************/\r
+\r
+#define DCount(arr)                    (sizeof(arr) / sizeof((arr)[0]))\r
+#define DVarClr(var)           DMemClr(&(var), sizeof(var))\r
+#define DSwap(x, y)                    do { x ^= y; y ^= x; x ^=y; } while (0)\r
+#define DBetween(var, b, e)    ((var) >= (b) && (var) < (e))\r
+#define DBoolean(b)                    (!!(b))\r
+\r
+/************************************************************************/\r
+\r
+#ifdef WIN32\r
+#include <win32.h>\r
+#else\r
+#include "posix.h" /* changed from <posix.h> by Tony Lewis */\r
+#endif\r
+\r
+typedef VOID                   *VPTR;\r
+typedef CONST VOID             *VCPTR;\r
+\r
+typedef CHAR                   *STRPTR;\r
+typedef CONST CHAR             *STRCPTR;\r
+\r
+typedef BYTE                   *BUFPTR;\r
+typedef CONST BYTE             *BUFCPTR;\r
+\r
+/************************************************************************/\r
+\r
+CAPI extern STRCPTR DGetCwd(VOID);\r
+\r
+/************************************************************************/\r
+\r
+#endif /* __SD_COMMON_COMMON_H__ */\r
diff --git a/implode.c b/implode.c
new file mode 100755 (executable)
index 0000000..d6be47d
--- /dev/null
+++ b/implode.c
@@ -0,0 +1,674 @@
+/************************************************************************/\r
+/* File Name   : implode.c                                              */\r
+/* Creator     : ax.minaduki@gmail.com                                  */\r
+/* Create Time : May 23rd, 2010                                         */\r
+/* Module      : Lawine library                                         */\r
+/* Descript    : PKWare DCL implode compression API implementation      */\r
+/************************************************************************/\r
+\r
+#include "implode.h"\r
+\r
+/*\r
+  Extended characters removed by Tony Lewis\r
+*/\r
+\r
+/************************************************************************/\r
+\r
+/* Truncate value to a specified number of bits */\r
+#define TRUNCATE_VALUE(v, b)   ((v) & ((1 << (b)) - 1))\r
+\r
+/************************************************************************/\r
+\r
+/* Bit sequences used to represent literal bytes */\r
+static WORD s_ChCode[] = {\r
+       0x0490, 0x0fe0, 0x07e0, 0x0be0, 0x03e0, 0x0de0, 0x05e0, 0x09e0,\r
+       0x01e0, 0x00b8, 0x0062, 0x0ee0, 0x06e0, 0x0022, 0x0ae0, 0x02e0,\r
+       0x0ce0, 0x04e0, 0x08e0, 0x00e0, 0x0f60, 0x0760, 0x0b60, 0x0360,\r
+       0x0d60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0e60, 0x0660, 0x0a60,\r
+       0x000f, 0x0250, 0x0038, 0x0260, 0x0050, 0x0c60, 0x0390, 0x00d8,\r
+       0x0042, 0x0002, 0x0058, 0x01b0, 0x007c, 0x0029, 0x003c, 0x0098,\r
+       0x005c, 0x0009, 0x001c, 0x006c, 0x002c, 0x004c, 0x0018, 0x000c,\r
+       0x0074, 0x00e8, 0x0068, 0x0460, 0x0090, 0x0034, 0x00b0, 0x0710,\r
+       0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00a8,\r
+       0x0028, 0x0001, 0x0310, 0x0130, 0x003e, 0x0064, 0x001e, 0x002e,\r
+       0x0024, 0x0510, 0x000e, 0x0036, 0x0016, 0x0044, 0x0030, 0x00c8,\r
+       0x01d0, 0x00d0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088,\r
+       0x0fa0, 0x0007, 0x0026, 0x0006, 0x003a, 0x001b, 0x001a, 0x002a,\r
+       0x000a, 0x000b, 0x0210, 0x0004, 0x0013, 0x0032, 0x0003, 0x001d,\r
+       0x0012, 0x0190, 0x000d, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078,\r
+       0x00f0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07a0, 0x0ba0, 0x03a0,\r
+       0x0240, 0x1c40, 0x0c40, 0x1440, 0x0440, 0x1840, 0x0840, 0x1040,\r
+       0x0040, 0x1f80, 0x0f80, 0x1780, 0x0780, 0x1b80, 0x0b80, 0x1380,\r
+       0x0380, 0x1d80, 0x0d80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180,\r
+       0x0180, 0x1e80, 0x0e80, 0x1680, 0x0680, 0x1a80, 0x0a80, 0x1280,\r
+       0x0280, 0x1c80, 0x0c80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080,\r
+       0x0080, 0x1f00, 0x0f00, 0x1700, 0x0700, 0x1b00, 0x0b00, 0x1300,\r
+       0x0da0, 0x05a0, 0x09a0, 0x01a0, 0x0ea0, 0x06a0, 0x0aa0, 0x02a0,\r
+       0x0ca0, 0x04a0, 0x08a0, 0x00a0, 0x0f20, 0x0720, 0x0b20, 0x0320,\r
+       0x0d20, 0x0520, 0x0920, 0x0120, 0x0e20, 0x0620, 0x0a20, 0x0220,\r
+       0x0c20, 0x0420, 0x0820, 0x0020, 0x0fc0, 0x07c0, 0x0bc0, 0x03c0,\r
+       0x0dc0, 0x05c0, 0x09c0, 0x01c0, 0x0ec0, 0x06c0, 0x0ac0, 0x02c0,\r
+       0x0cc0, 0x04c0, 0x08c0, 0x00c0, 0x0f40, 0x0740, 0x0b40, 0x0340,\r
+       0x0300, 0x0d40, 0x1d00, 0x0d00, 0x1500, 0x0540, 0x0500, 0x1900,\r
+       0x0900, 0x0940, 0x1100, 0x0100, 0x1e00, 0x0e00, 0x0140, 0x1600,\r
+       0x0600, 0x1a00, 0x0e40, 0x0640, 0x0a40, 0x0a00, 0x1200, 0x0200,\r
+       0x1c00, 0x0c00, 0x1400, 0x0400, 0x1800, 0x0800, 0x1000, 0x0000,\r
+};\r
+\r
+/* Lengths of bit sequences used to represent literal bytes */\r
+static BYTE s_ChBits[] = {\r
+       0x0b, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x08, 0x07, 0x0c, 0x0c, 0x07, 0x0c, 0x0c,\r
+       0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,\r
+       0x04, 0x0a, 0x08, 0x0c, 0x0a, 0x0c, 0x0a, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08,\r
+       0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0c, 0x0b, 0x07, 0x09, 0x0b,\r
+       0x0c, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0b, 0x09, 0x06, 0x07, 0x06, 0x06,\r
+       0x07, 0x0b, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0b, 0x08, 0x0b, 0x09, 0x0c, 0x08,\r
+       0x0c, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0b, 0x07, 0x05, 0x06, 0x05, 0x05,\r
+       0x06, 0x0a, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0a, 0x0b, 0x0b, 0x0c, 0x0c, 0x0c,\r
+       0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,\r
+       0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,\r
+       0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,\r
+       0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,\r
+       0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,\r
+       0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,\r
+       0x0d, 0x0c, 0x0d, 0x0d, 0x0d, 0x0c, 0x0d, 0x0d, 0x0d, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0c, 0x0d,\r
+       0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,\r
+};\r
+\r
+/* Bit sequences used to represent the base values of the copy length */\r
+static BYTE s_LenCode[] = {\r
+       0x05, 0x03, 0x01, 0x06, 0x0a, 0x02, 0x0c, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00,\r
+};\r
+\r
+/* Lengths of bit sequences used to represent the base values of the copy length */\r
+static BYTE s_LenBits[] = {\r
+       0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07,\r
+};\r
+\r
+/* Base values used for the copy length */\r
+static WORD s_LenBase[] = {\r
+       0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,\r
+       0x000a, 0x000c, 0x0010, 0x0018, 0x0028, 0x0048, 0x0088, 0x0108,\r
+};\r
+\r
+/* Lengths of extra bits used to represent the copy length */\r
+static BYTE s_ExLenBits[] = {\r
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,\r
+};\r
+\r
+/* Bit sequences used to represent the most significant 6 bits of the copy offset */\r
+static BYTE s_OffsCode[] = {\r
+       0x03, 0x0d, 0x05, 0x19, 0x09, 0x11, 0x01, 0x3e, 0x1e, 0x2e, 0x0e, 0x36, 0x16, 0x26, 0x06, 0x3a,\r
+       0x1a, 0x2a, 0x0a, 0x32, 0x12, 0x22, 0x42, 0x02, 0x7c, 0x3c, 0x5c, 0x1c, 0x6c, 0x2c, 0x4c, 0x0c,\r
+       0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08,\r
+       0xf0, 0x70, 0xb0, 0x30, 0xd0, 0x50, 0x90, 0x10, 0xe0, 0x60, 0xa0, 0x20, 0xc0, 0x40, 0x80, 0x00,\r
+};\r
+\r
+/* Lengths of bit sequences used to represent the most significant 6 bits of the copy offset */\r
+static BYTE s_OffsBits[] = {\r
+       0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,\r
+       0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,\r
+       0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,\r
+       0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,\r
+};\r
+\r
+/************************************************************************/\r
+\r
+BOOL implode(INT type, INT dict, VCPTR src, UINT src_size, VPTR dest, UINT *dest_size)\r
+{\r
+       INT i;                                  // Index into tables\r
+       BYTE ch;                                // Byte from input buffer\r
+       INT max_copy_len;               // Length of longest duplicate data in the dictionary\r
+       BUFPTR max_copy_ptr;    // Pointer to longest duplicate data in the dictionary\r
+       INT copy_len;                   // Length of duplicate data in the dictionary\r
+       INT copy_off;                   // Offset used in actual compressed data\r
+       INT new_copy_off;               // Secondary offset used in actual compressed data\r
+       BUFPTR copy_ptr;                // Pointer to duplicate data in the dictionary\r
+       BUFPTR bak_copy_ptr;    // Temporarily holds previous value of copy_ptr\r
+       BUFCPTR new_rd_ptr;             // Secondary offset into input buffer\r
+       BUFPTR new_dict_ptr;    // Secondary offset into dictionary\r
+       BUFCPTR rd_ptr;                 // Current position in input buffer\r
+       BUFPTR wrt_ptr;                 // Current position in output buffer\r
+       BUFCPTR src_end_ptr;    // Pointer to the end of source buffer\r
+       BUFPTR dest_end_ptr;    // Pointer to the end of dest buffer\r
+       BYTE bit_num;                   // Number of bits in bit buffer\r
+       DWORD bit_buf;                  // Stores bits until there are enough to output a byte of data\r
+       BUFPTR dict_ptr;                // Position in dictionary\r
+       UINT dict_size;                 // Maximum size of dictionary\r
+       UINT cur_dict_size;             // Current size of dictionary\r
+       BYTE dict_buf[4096];    // Sliding dictionary used for compression and decompression\r
+\r
+       // Check for a valid compression type\r
+       if (type != IMPLODE_BINARY && type != IMPLODE_ASCII)\r
+               return FALSE;\r
+\r
+       // Only dictionary sizes of 1024, 2048, and 4096 are allowed.\r
+       // The values 4, 5, and 6 correspond with those sizes\r
+       switch (dict) {\r
+       case IMPLODE_DICT_1K:\r
+               // Store actual dictionary size\r
+               dict_size = 1024;\r
+               break;\r
+       case IMPLODE_DICT_2K:\r
+               // Store actual dictionary size\r
+               dict_size = 2048;\r
+               break;\r
+       case IMPLODE_DICT_4K:\r
+               // Store actual dictionary size\r
+               dict_size = 4096;\r
+               break;\r
+       default:\r
+               return FALSE;\r
+       }\r
+\r
+       // Initialize buffer positions\r
+       rd_ptr = src;\r
+       wrt_ptr = dest;\r
+       src_end_ptr = rd_ptr + src_size;\r
+       dest_end_ptr = wrt_ptr + *dest_size;\r
+\r
+       // Initialize dictionary position\r
+       dict_ptr = dict_buf;\r
+\r
+       // Initialize current dictionary size to zero\r
+       cur_dict_size = 0;\r
+\r
+       // If the output buffer size is less than 4, there\r
+       // is not enough room for the compressed data\r
+       if (*dest_size < 4 && !(src_size == 0 && *dest_size == 4))\r
+               return FALSE;\r
+\r
+       // Store compression type and dictionary size\r
+       *wrt_ptr++ = type;\r
+       *wrt_ptr++ = dict;\r
+\r
+       // Initialize bit buffer\r
+       bit_buf = 0;\r
+       bit_num = 0;\r
+\r
+       // Compress until input buffer is empty\r
+       while (rd_ptr < src_end_ptr) {\r
+\r
+               // Get a byte from the input buffer\r
+               ch = *rd_ptr++;\r
+               max_copy_len = 0;\r
+\r
+               // If the dictionary is not empty, search for duplicate data in the dictionary\r
+               if (cur_dict_size > 1 && src_end_ptr - rd_ptr > 1) {\r
+\r
+                       // Initialize offsets and lengths used in search\r
+                       copy_ptr = dict_buf;\r
+                       max_copy_ptr = copy_ptr;\r
+                       max_copy_len = 0;\r
+\r
+                       // Store position of last written dictionary byte\r
+                       new_dict_ptr = dict_ptr - 1;\r
+                       if (new_dict_ptr < dict_buf)\r
+                               new_dict_ptr = dict_buf + cur_dict_size - 1;\r
+\r
+                       // Search dictionary for duplicate data\r
+                       for (; copy_ptr < dict_buf + cur_dict_size; copy_ptr++) {\r
+\r
+                               // Check for a match with first byte\r
+                               if (ch != *copy_ptr)\r
+                                       continue;\r
+\r
+                               bak_copy_ptr = copy_ptr;\r
+                               copy_len = 0;\r
+                               new_rd_ptr = rd_ptr - 1;\r
+\r
+                               // If there was a match, check for additional duplicate bytes\r
+                               do {\r
+\r
+                                       // Increment pointers and length\r
+                                       copy_len++;\r
+                                       new_rd_ptr++;\r
+                                       copy_ptr++;\r
+\r
+                                       // Wrap around pointer to beginning of dictionary buffer if the end of the buffer was reached\r
+                                       if (copy_ptr >= dict_buf + dict_size)\r
+                                               copy_ptr = dict_buf;\r
+\r
+                                       // Wrap dictionary bytes if end of the dictionary was reached\r
+                                       if (copy_ptr == dict_ptr)\r
+                                               copy_ptr = bak_copy_ptr;\r
+\r
+                                       // Stop checking for additional bytes if there is no more input or maximum length was reached\r
+                                       if (copy_len >= 518 || new_rd_ptr >= src_end_ptr)\r
+                                               break;\r
+\r
+                               } while (*new_rd_ptr == *copy_ptr);\r
+\r
+                               // Return the pointer to the beginning of the matching data\r
+                               copy_ptr = bak_copy_ptr;\r
+\r
+                               // Copying less than two bytes from dictionary wastes space, so don't do it ;)\r
+                               if (copy_len < 2 || copy_len < max_copy_len)\r
+                                       continue;\r
+\r
+                               // Store the offset that will be outputted into the compressed data\r
+                               new_copy_off = (new_dict_ptr - (copy_ptr - cur_dict_size)) % cur_dict_size;\r
+\r
+                               // If the length is equal, check for a more efficient offset\r
+                               if (copy_len == max_copy_len) {\r
+\r
+                                       // Use the most efficient offset\r
+                                       if (new_copy_off < copy_off) {\r
+                                               copy_off = new_copy_off;\r
+                                               max_copy_ptr = copy_ptr;\r
+                                               max_copy_len = copy_len;\r
+                                       }\r
+                               }\r
+                               // Only use the most efficient length and offset in dictionary\r
+                               else {\r
+\r
+                                       // Store the offset that will be outputted into the compressed data\r
+                                       copy_off = new_copy_off;\r
+\r
+                                       // If the copy length is 2, check for a valid dictionary offset\r
+                                       if (copy_len > 2 || copy_off <= 255) {\r
+                                               max_copy_ptr = copy_ptr;\r
+                                               max_copy_len = copy_len;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       // If there were at least 2 matching bytes in the dictionary that were found, output the length/offset pair\r
+                       if (max_copy_len >= 2) {\r
+\r
+                               // Reset the input pointers to the bytes that will be added to the dictionary\r
+                               rd_ptr--;\r
+                               new_rd_ptr = rd_ptr + max_copy_len;\r
+\r
+                               while (rd_ptr < new_rd_ptr) {\r
+\r
+                                       // Add a byte to the dictionary\r
+                                       *dict_ptr++ = ch;\r
+\r
+                                       // If the dictionary is not full yet, increment the current dictionary size\r
+                                       if (cur_dict_size < dict_size)\r
+                                               cur_dict_size++;\r
+\r
+                                       // If the current end of the dictionary is past the end of the buffer,\r
+                                       // wrap around back to the start\r
+                                       if (dict_ptr >= dict_buf + dict_size)\r
+                                               dict_ptr = dict_buf;\r
+\r
+                                       // Get the next byte to be added\r
+                                       if (++rd_ptr < new_rd_ptr)\r
+                                               ch = *rd_ptr;\r
+                               }\r
+\r
+                               // Find bit code for the base value of the length from the table\r
+                               for (i = 0; i < 0x0F; i++) {\r
+\r
+                                       if (s_LenBase[i] <= max_copy_len && max_copy_len < s_LenBase[i + 1])\r
+                                               break;\r
+                               }\r
+\r
+                               // Store the base value of the length\r
+                               bit_buf += (1 + (s_LenCode[i] << 1)) << bit_num;\r
+                               bit_num += 1 + s_LenBits[i];\r
+\r
+                               // Store the extra bits for the length\r
+                               bit_buf += (max_copy_len - s_LenBase[i]) << bit_num;\r
+                               bit_num += s_ExLenBits[i];\r
+\r
+                               // Output the data from the bit buffer\r
+                               while (bit_num >= 8) {\r
+\r
+                                       // If output buffer has become full, stop immediately!\r
+                                       if (wrt_ptr >= dest_end_ptr)\r
+                                               return FALSE;\r
+\r
+                                       *wrt_ptr++ = (BYTE)bit_buf;\r
+                                       bit_buf >>= 8;\r
+                                       bit_num -= 8;\r
+                               }\r
+\r
+                               // The most significant 6 bits of the dictionary offset are encoded with a\r
+                               // bit sequence then the first 2 after that if the copy length is 2,\r
+                               // otherwise it is the first 4, 5, or 6 (based on the dictionary size)\r
+                               if (max_copy_len == 2) {\r
+\r
+                                       // Store most significant 6 bits of offset using bit sequence\r
+                                       bit_buf += s_OffsCode[copy_off >> 2] << bit_num;\r
+                                       bit_num += s_OffsBits[copy_off >> 2];\r
+\r
+                                       // Store the first 2 bits\r
+                                       bit_buf += (copy_off & 0x03) << bit_num;\r
+                                       bit_num += 2;\r
+                               }\r
+                               else {\r
+\r
+                                       // Store most significant 6 bits of offset using bit sequence\r
+                                       bit_buf += s_OffsCode[copy_off >> dict] << bit_num;\r
+                                       bit_num += s_OffsBits[copy_off >> dict];\r
+\r
+                                       // Store the first 4, 5, or 6 bits\r
+                                       bit_buf += TRUNCATE_VALUE(copy_off, dict) << bit_num;\r
+                                       bit_num += dict;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               // If the copy length was less than two, include the byte as a literal byte\r
+               if (max_copy_len < 2) {\r
+\r
+                       if (type == IMPLODE_BINARY) {\r
+\r
+                               // Store a fixed size literal byte\r
+                               bit_buf += ch << (bit_num + 1);\r
+                               bit_num += 9;\r
+                       }\r
+                       else {\r
+\r
+                               // Store a variable size literal byte\r
+                               bit_buf += s_ChCode[ch] << (bit_num + 1);\r
+                               bit_num += 1 + s_ChBits[ch];\r
+                       }\r
+\r
+                       // Add the byte into the dictionary\r
+                       *dict_ptr++ = ch;\r
+\r
+                       // If the dictionary is not full yet, increment the current dictionary size\r
+                       if (cur_dict_size < dict_size)\r
+                               cur_dict_size++;\r
+\r
+                       // If the current end of the dictionary is past the end of the buffer,\r
+                       // wrap around back to the start\r
+                       if (dict_ptr >= dict_buf + dict_size)\r
+                               dict_ptr = dict_buf;\r
+               }\r
+\r
+               // Write any whole bytes from the bit buffer into the output buffer\r
+               while (bit_num >= 8) {\r
+\r
+                       // If output buffer has become full, stop immediately!\r
+                       if (wrt_ptr >= dest_end_ptr)\r
+                               return FALSE;\r
+\r
+                       *wrt_ptr++ = (BYTE)bit_buf;\r
+                       bit_buf >>= 8;\r
+                       bit_num -= 8;\r
+               }\r
+       }\r
+\r
+       // Store the code for the end of the compressed data stream\r
+       bit_buf += (1 + (s_LenCode[0x0f] << 1)) << bit_num;\r
+       bit_num += 1 + s_LenBits[0x0f];\r
+\r
+       bit_buf += 0xff << bit_num;\r
+       bit_num += 8;\r
+\r
+       // Write any remaining bits from the bit buffer into the output buffer\r
+       while (bit_num > 0) {\r
+\r
+               // If output buffer has become full, stop immediately!\r
+               if (wrt_ptr >= dest_end_ptr)\r
+                       return FALSE;\r
+\r
+               *wrt_ptr++ = (BYTE)bit_buf;\r
+               bit_buf >>= 8;\r
+               if (bit_num >= 8)\r
+                       bit_num -= 8;\r
+               else\r
+                       bit_num = 0;\r
+       }\r
+\r
+       // Store the compressed size\r
+       *dest_size = wrt_ptr - (BUFPTR)dest;\r
+\r
+       return TRUE;\r
+}\r
+\r
+BOOL explode(VCPTR src, UINT src_size, VPTR dest, UINT *dest_size)\r
+{\r
+       INT i;                                  // Index into tables\r
+       INT copy_len;                   // Length of data to copy from the dictionary\r
+       BUFPTR copy_off;                // Offset to data to copy from the dictionary\r
+       BYTE type;                              // Specifies whether to use fixed or variable size literal bytes\r
+       BYTE dict;                              // Dictionary size; valid values are 4, 5, and 6 which represent 1024, 2048, and 4096 respectively\r
+       BUFCPTR rd_ptr;                 // Current position in input buffer\r
+       BUFPTR wrt_ptr;                 // Current position in output buffer\r
+       BUFCPTR src_end_ptr;    // Pointer to the end of source buffer\r
+       BUFPTR dest_end_ptr;    // Pointer to the end of dest buffer\r
+       BYTE bit_num;                   // Number of bits in bit buffer\r
+       DWORD bit_buf;                  // Stores bits until there are enough to output a byte of data\r
+       BUFPTR dict_ptr;                // Position in dictionary\r
+       UINT dict_size;                 // Maximum size of dictionary\r
+       UINT cur_dict_size;             // Current size of dictionary\r
+       BYTE dict_buf[0x1000];  // Sliding dictionary used for compression and decompression\r
+\r
+       // Compressed data cannot be less than 4 bytes;\r
+       // this is not possible in any case whatsoever\r
+       if (src_size < 4) {\r
+               *dest_size = 0;\r
+               return FALSE;\r
+       }\r
+\r
+       // Initialize buffer positions\r
+       rd_ptr = src;\r
+       wrt_ptr = dest;\r
+       src_end_ptr = rd_ptr + src_size;\r
+       dest_end_ptr = wrt_ptr + *dest_size;\r
+\r
+       // Get header from compressed data\r
+       type = *rd_ptr++;\r
+       dict = *rd_ptr++;\r
+\r
+       // Check for a valid compression type\r
+       if (type != IMPLODE_BINARY && type != IMPLODE_ASCII)\r
+               return FALSE;\r
+\r
+       // Only dictionary sizes of 1024, 2048, and 4096 are allowed.\r
+       // The values 4, 5, and 6 correspond with those sizes\r
+       switch (dict) {\r
+       case IMPLODE_DICT_1K:\r
+               // Store actual dictionary size\r
+               dict_size = 1024;\r
+               break;\r
+       case IMPLODE_DICT_2K:\r
+               // Store actual dictionary size\r
+               dict_size = 2048;\r
+               break;\r
+       case IMPLODE_DICT_4K:\r
+               // Store actual dictionary size\r
+               dict_size = 4096;\r
+               break;\r
+       default:\r
+               return FALSE;\r
+       }\r
+\r
+       // Initialize dictionary position\r
+       dict_ptr = dict_buf;\r
+\r
+       // Initialize current dictionary size to zero\r
+       cur_dict_size = 0;\r
+\r
+       // Get first 16 bits\r
+       bit_buf = *rd_ptr++;\r
+       bit_buf += *rd_ptr++ << 8;\r
+       bit_num = 16;\r
+\r
+       // Decompress until output buffer is full\r
+       while (wrt_ptr < dest_end_ptr) {\r
+\r
+               // Fill bit buffer with at least 16 bits\r
+               while (bit_num < 16) {\r
+\r
+                       // If input buffer is empty before end of stream, buffer is incomplete\r
+                       if (rd_ptr >= src_end_ptr) {\r
+\r
+                               // Store the current size of output\r
+                               *dest_size = wrt_ptr - (BUFPTR)dest;\r
+                               return FALSE;\r
+                       }\r
+\r
+                       bit_buf += *rd_ptr++ << bit_num;\r
+                       bit_num += 8;\r
+               }\r
+\r
+               // First bit is 1; copy from dictionary\r
+               if (bit_buf & 1) {\r
+\r
+                       // Remove first bit from bit buffer\r
+                       bit_buf >>= 1;\r
+                       bit_num--;\r
+\r
+                       // Find the base value for the copy length\r
+                       for (i = 0; i <= 0x0F; i++) {\r
+\r
+                               if (TRUNCATE_VALUE(bit_buf, s_LenBits[i]) == s_LenCode[i])\r
+                                       break;\r
+                       }\r
+\r
+                       // Remove value from bit buffer\r
+                       bit_buf >>= s_LenBits[i];\r
+                       bit_num -= s_LenBits[i];\r
+\r
+                       // Store the copy length\r
+                       copy_len = s_LenBase[i] + TRUNCATE_VALUE(bit_buf, s_ExLenBits[i]);\r
+\r
+                       // Remove the extra bits from the bit buffer\r
+                       bit_buf >>= s_ExLenBits[i];\r
+                       bit_num -= s_ExLenBits[i];\r
+\r
+                       // If copy length is 519, the end of the stream has been reached\r
+                       if (copy_len == 519)\r
+                               break;\r
+\r
+                       // Fill bit buffer with at least 14 bits\r
+                       while (bit_num < 14) {\r
+\r
+                               // If input buffer is empty before end of stream, buffer is incomplete\r
+                               if (rd_ptr >= src_end_ptr) {\r
+\r
+                                       // Store the current size of output\r
+                                       *dest_size = wrt_ptr - (BUFPTR)dest;\r
+                                       return FALSE;\r
+                               }\r
+\r
+                               bit_buf += *rd_ptr++ << bit_num;\r
+                               bit_num += 8;\r
+                       }\r
+\r
+                       // Find most significant 6 bits of offset into the dictionary\r
+                       for (i = 0; i <= 0x3f; i++) {\r
+\r
+                               if (TRUNCATE_VALUE(bit_buf, s_OffsBits[i]) == s_OffsCode[i])\r
+                                       break;\r
+                       }\r
+\r
+                       // Remove value from bit buffer\r
+                       bit_buf >>= s_OffsBits[i];\r
+                       bit_num -= s_OffsBits[i];\r
+\r
+                       // If the copy length is 2, there are only two more bits in the dictionary\r
+                       // offset; otherwise, there are 4, 5, or 6 bits left, depending on what\r
+                       // the dictionary size is\r
+                       if (copy_len == 2) {\r
+\r
+                               // Store the exact offset to a byte in the dictionary\r
+                               copy_off = dict_ptr - 1 - ((i << 2) + (bit_buf & 0x03));\r
+\r
+                               // Remove the rest of the dictionary offset from the bit buffer\r
+                               bit_buf >>= 2;\r
+                               bit_num -= 2;\r
+                       }\r
+                       else {\r
+\r
+                               // Store the exact offset to a byte in the dictionary\r
+                               copy_off = dict_ptr - 1 - ((i << dict) + TRUNCATE_VALUE(bit_buf, dict));\r
+\r
+                               // Remove the rest of the dictionary offset from the bit buffer\r
+                               bit_buf >>= dict;\r
+                               bit_num -= dict;\r
+                       }\r
+\r
+                       // While there are still bytes left, copy bytes from the dictionary\r
+                       while (copy_len-- > 0) {\r
+\r
+                               // If output buffer has become full, stop immediately!\r
+                               if (wrt_ptr >= dest_end_ptr) {\r
+\r
+                                       // Store the current size of output\r
+                                       *dest_size = wrt_ptr - (BUFPTR)dest;\r
+                                       return FALSE;\r
+                               }\r
+\r
+                               // Check whether the offset is a valid one into the dictionary\r
+                               while (copy_off < dict_buf)\r
+                                       copy_off += cur_dict_size;\r
+                               while (copy_off >= dict_buf + cur_dict_size)\r
+                                       copy_off -= cur_dict_size;\r
+\r
+                               // Copy the byte from the dictionary and add it to the end of the dictionary\r
+                               *dict_ptr++ = *wrt_ptr++ = *copy_off++;\r
+\r
+                               // If the dictionary is not full yet, increment the current dictionary size\r
+                               if (cur_dict_size < dict_size)\r
+                                       cur_dict_size++;\r
+\r
+                               // If the current end of the dictionary is past the end of the buffer,\r
+                               // wrap around back to the start\r
+                               if (dict_ptr >= dict_buf + dict_size)\r
+                                       dict_ptr = dict_buf;\r
+                       }\r
+               }\r
+\r
+               // First bit is 0; literal byte\r
+               else {\r
+\r
+                       // Fixed size literal byte\r
+                       if (type == IMPLODE_BINARY) {\r
+\r
+                               // Copy the byte and add it to the end of the dictionary\r
+                               *dict_ptr++ = (BYTE)(bit_buf >> 1);\r
+                               *wrt_ptr++ = (BYTE)(bit_buf >> 1);\r
+\r
+                               // Remove the byte from the bit buffer\r
+                               bit_buf >>= 9;\r
+                               bit_num -= 9;\r
+                       }\r
+\r
+                       // Variable size literal byte\r
+                       else {\r
+\r
+                               // Remove the first bit from the bit buffer\r
+                               bit_buf >>= 1;\r
+                               bit_num--;\r
+\r
+                               // Find the actual byte from the bit sequence\r
+                               for (i = 0; i <= 0xff; i++) {\r
+                                       if (TRUNCATE_VALUE(bit_buf, s_ChBits[i]) == s_ChCode[i])\r
+                                               break;\r
+                               }\r
+\r
+                               // Copy the byte and add it to the end of the dictionary\r
+                               *dict_ptr++ = i;\r
+                               *wrt_ptr++ = i;\r
+\r
+                               // Remove the byte from the bit buffer\r
+                               bit_buf >>= s_ChBits[i];\r
+                               bit_num -= s_ChBits[i];\r
+                       }\r
+\r
+                       // If the dictionary is not full yet, increment the current dictionary size\r
+                       if (cur_dict_size < dict_size)\r
+                               cur_dict_size++;\r
+\r
+                       // If the current end of the dictionary is past the end of the buffer,\r
+                       // wrap around back to the start\r
+                       if (dict_ptr >= dict_buf + dict_size)\r
+                               dict_ptr = dict_buf;\r
+               }\r
+       }\r
+\r
+       // Store the decompressed size\r
+       *dest_size = wrt_ptr - (BUFPTR)dest;\r
+\r
+       return TRUE;\r
+}\r
+\r
+/************************************************************************/\r
diff --git a/implode.h b/implode.h
new file mode 100755 (executable)
index 0000000..1ef2f29
--- /dev/null
+++ b/implode.h
@@ -0,0 +1,32 @@
+/************************************************************************/\r
+/* File Name   : implode.h                                              */\r
+/* Creator     : ax.minaduki@gmail.com                                  */\r
+/* Create Time : May 23rd, 2010                                         */\r
+/* Module      : Lawine library                                         */\r
+/* Descript    : PKWare DCL implode compression API definition          */\r
+/************************************************************************/\r
+\r
+#ifndef __SD_LAWINE_COMPRESS_IMPLODE_H__\r
+#define __SD_LAWINE_COMPRESS_IMPLODE_H__\r
+\r
+/************************************************************************/\r
+\r
+#include "common.h" /* changed from <common.h> by Tony Lewis */\r
+\r
+/************************************************************************/\r
+\r
+#define IMPLODE_BINARY         0                       /* Binary compression */\r
+#define IMPLODE_ASCII          1                       /* ASCII compression */\r
+\r
+#define IMPLODE_DICT_1K                4                       /* Dictionary size is 1KB */\r
+#define IMPLODE_DICT_2K                5                       /* Dictionary size is 2KB */\r
+#define IMPLODE_DICT_4K                6                       /* Dictionary size is 4KB */\r
+\r
+/************************************************************************/\r
+\r
+CAPI extern BOOL implode(INT type, INT dict, VCPTR src, UINT src_size, VPTR dest, UINT *dest_size);\r
+CAPI extern BOOL explode(VCPTR src, UINT src_size, VPTR dest, UINT *dest_size);\r
+\r
+/************************************************************************/\r
+\r
+#endif /* __SD_LAWINE_COMPRESS_IMPLODE_H__ */\r
index 9e95071..4b1fa8e 100644 (file)
@@ -16,6 +16,7 @@
 #include <errno.h>
 #include <string.h>
 
+#include "implode.h"
 #include "installshield_z.h"
 
 static const size_t BUFFER_SIZE = 0x4000;
@@ -64,7 +65,7 @@ headers_decode(int z_fd)
 
                        printf("Directory entries: %d ( %08x bytes @ 0x%08x)\n", header->directories_entries, header->directories_bytes, header->directories_offset);
 
-                       struct ll_dirents dirents[header->directories_entries];
+                       struct dirent dirents[header->directories_entries];
                        for (int i = 0; i < header->directories_entries; ++i) {
                                printf(" Entry %4d Size %x @ %08x    \"%s\"\n", i, p->entry_bytes, header->directories_offset + (uint32_t)((void *)p - (void *)dirent), p->name);
                                dirents[i].entry = p;
@@ -170,6 +171,39 @@ headers_decode(int z_fd)
                                                                                fprintf(stderr, "Error: whilst reading payload expected %d bytes but read %ld\n", q->payload_bytes, z_qty);
                                                                        close(pay_fd);
                                                                }
+                                                               if (q->payload_bytes >= 4) {
+                                                                       uint8_t comp_type = *(uint8_t *)buffer;
+                                                                       uint8_t dict_size = *(uint8_t *)(buffer + 1);
+                                                                       if (comp_type >= IMPLODE_BINARY && comp_type <= IMPLODE_ASCII && dict_size >= IMPLODE_DICT_1K && dict_size <= IMPLODE_DICT_4K) {
+                                                                               void * buffer_decomp;
+                                                                               if ((buffer_decomp = calloc(q->file_bytes, 1)) != 0) {
+                                                                                       uint32_t decomp_bytes = q->file_bytes;
+                                                                                       if (explode(buffer, q->payload_bytes, buffer_decomp, &decomp_bytes)) {
+                                                                                               if (decomp_bytes > q->file_bytes) {
+                                                                                                       fprintf(stderr, "Expected %d uncompressed bytes but got %d\n", q->file_bytes, decomp_bytes);
+                                                                                               }
+                                                                                               int decomp_fd;
+                                                                                               if ((decomp_fd = openat(dir_fd, q->name, O_WRONLY | O_CREAT | O_TRUNC, 0644))) {
+                                                                                                       ssize_t decomp_qty;
+                                                                                                       if (debug)
+                                                                                                               printf("Creating uncompressed file '%s/%s'\n",dir_name,  q->name);
+                                                                                                       if ((decomp_qty = write(decomp_fd, buffer_decomp, q->file_bytes)) != q->file_bytes)
+                                                                                                               fprintf(stderr, "Error: whilst writing decompressed data expected %d bytes but wrote %ld\n", q->file_bytes, decomp_qty);
+                                                                                                       close(decomp_fd);
+                                                                                               }
+                                                                                       } else {
+                                                                                               fprintf(stderr, "Error: failed to decompress '%s', payload: %d decompressed: %d\n", q->name, q->payload_bytes, decomp_bytes);
+                                                                                       }
+                                                                                       free(buffer_decomp);
+                                                                               } else {
+                                                                                       fprintf(stderr, "Error: unable to allocate %d bytes for decompression buffer\n", q->file_bytes);
+                                                                               }
+                                                                       } else {
+                                                                               fprintf(stderr, "Does not look like TTComp compressed data. header: %04x\n", *(uint16_t *)buffer);
+                                                                       }
+                                                               } else {
+                                                                       fprintf(stderr, "Error: payload %d bytes smaller than minimum allowed TTComp of 4\n", q->payload_bytes);
+                                                               }
                                                                free(buffer);
                                                        }
                                                } else {
index 8411347..d55277c 100644 (file)
@@ -40,7 +40,7 @@ struct __attribute__((packed)) dirent_prefix {
        uint16_t                        __flags;                        // 0x00
        uint16_t                        entry_bytes;            // 0x02
        uint16_t                        name_bytes;                     // 0x04
-       unsigned char           name[];                         // 0x06
+       char                            name[];                         // 0x06
 };
 
 struct __attribute__((packed)) dirent_suffix {
@@ -59,7 +59,7 @@ struct __attribute__((packed)) fileent_prefix {
        uint16_t                        entry_bytes;
        uint32_t                        __unknown01;
        uint8_t                         name_bytes;
-       unsigned char           name[];
+       char                            name[];
 };
 
 struct __attribute__((packed)) fileent_suffix {
@@ -68,9 +68,8 @@ struct __attribute__((packed)) fileent_suffix {
        uint32_t                        __unkown08;
 };
 
-struct ll_dirents {
+struct dirent {
        struct dirent_prefix *entry;
-       struct ll_dirents       *next;
        bool                            created;
 };
 
diff --git a/posix.h b/posix.h
new file mode 100755 (executable)
index 0000000..1939148
--- /dev/null
+++ b/posix.h
@@ -0,0 +1,30 @@
+/************************************************************************/
+/* File Name   : posix.h                                                */
+/* Creator     : tlewis@exelana.com                                     */
+/* Create Time : March 3, 2012                                          */
+/* Module      : TTDecomp                                               */
+/************************************************************************/
+
+#ifndef __POSIX_H__
+#define __POSIX_H__
+
+#define CONST const
+
+typedef void VOID;
+
+typedef char CHAR;
+typedef unsigned short WCHAR;
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned long DWORD;
+typedef unsigned int UINT;
+typedef unsigned long ULONG;
+typedef int INT;
+typedef long LONG;
+
+typedef int BOOL;
+typedef unsigned int SIZE_T;
+
+#define FALSE (0)
+#define TRUE (!FALSE)
+#endif /* __POSIX_H__ */