| 1 | /* |
|---|
| 2 | * explode.c -- explode function of PKWARE data compression library. |
|---|
| 3 | * |
|---|
| 4 | * Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de> |
|---|
| 5 | * |
|---|
| 6 | * This source was adepted from the C++ version of pkware.cpp included |
|---|
| 7 | * in stormlib. The C++ version belongs to the following authors, |
|---|
| 8 | * |
|---|
| 9 | * Ladislav Zezula <ladik.zezula.net> |
|---|
| 10 | * |
|---|
| 11 | * This program is free software; you can redistribute it and/or modify |
|---|
| 12 | * it under the terms of the GNU General Public License as published by |
|---|
| 13 | * the Free Software Foundation; either version 2 of the License, or |
|---|
| 14 | * (at your option) any later version. |
|---|
| 15 | * |
|---|
| 16 | * This program is distributed in the hope that it will be useful, |
|---|
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 19 | * GNU General Public License for more details. |
|---|
| 20 | * |
|---|
| 21 | * You should have received a copy of the GNU General Public License |
|---|
| 22 | * along with this program; if not, write to the Free Software |
|---|
| 23 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|---|
| 24 | */ |
|---|
| 25 | |
|---|
| 26 | #include <assert.h> |
|---|
| 27 | #include <string.h> |
|---|
| 28 | |
|---|
| 29 | #include "mpq.h" |
|---|
| 30 | #include "explode.h" |
|---|
| 31 | |
|---|
| 32 | /* Tables */ |
|---|
| 33 | static unsigned char pkzip_dist_bits[] = { |
|---|
| 34 | 0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, |
|---|
| 35 | 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, |
|---|
| 36 | 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, |
|---|
| 37 | 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 |
|---|
| 38 | }; |
|---|
| 39 | |
|---|
| 40 | static unsigned char pkzip_dist_code[] = { |
|---|
| 41 | 0x03, 0x0D, 0x05, 0x19, 0x09, 0x11, 0x01, 0x3E, 0x1E, 0x2E, 0x0E, 0x36, 0x16, 0x26, 0x06, 0x3A, |
|---|
| 42 | 0x1A, 0x2A, 0x0A, 0x32, 0x12, 0x22, 0x42, 0x02, 0x7C, 0x3C, 0x5C, 0x1C, 0x6C, 0x2C, 0x4C, 0x0C, |
|---|
| 43 | 0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08, |
|---|
| 44 | 0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20, 0xC0, 0x40, 0x80, 0x00 |
|---|
| 45 | }; |
|---|
| 46 | |
|---|
| 47 | static unsigned char pkzip_clen_bits[] = { |
|---|
| 48 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 |
|---|
| 49 | }; |
|---|
| 50 | |
|---|
| 51 | static unsigned short pkzip_len_base[] = { |
|---|
| 52 | 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, |
|---|
| 53 | 0x0008, 0x000A, 0x000E, 0x0016, 0x0026, 0x0046, 0x0086, 0x0106 |
|---|
| 54 | }; |
|---|
| 55 | |
|---|
| 56 | static unsigned char pkzip_slen_bits[] = { |
|---|
| 57 | 0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07 |
|---|
| 58 | }; |
|---|
| 59 | |
|---|
| 60 | static unsigned char pkzip_len_code[] = { |
|---|
| 61 | 0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00 |
|---|
| 62 | }; |
|---|
| 63 | |
|---|
| 64 | static unsigned char pkzip_bits_asc[] = { |
|---|
| 65 | 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x07, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, |
|---|
| 66 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, |
|---|
| 67 | 0x04, 0x0A, 0x08, 0x0C, 0x0A, 0x0C, 0x0A, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08, |
|---|
| 68 | 0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0C, 0x0B, 0x07, 0x09, 0x0B, |
|---|
| 69 | 0x0C, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0B, 0x09, 0x06, 0x07, 0x06, 0x06, |
|---|
| 70 | 0x07, 0x0B, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0B, 0x08, 0x0B, 0x09, 0x0C, 0x08, |
|---|
| 71 | 0x0C, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0B, 0x07, 0x05, 0x06, 0x05, 0x05, |
|---|
| 72 | 0x06, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C, |
|---|
| 73 | 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, |
|---|
| 74 | 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, |
|---|
| 75 | 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, |
|---|
| 76 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, |
|---|
| 77 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, |
|---|
| 78 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, |
|---|
| 79 | 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, |
|---|
| 80 | 0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D |
|---|
| 81 | }; |
|---|
| 82 | |
|---|
| 83 | static unsigned short pkzip_code_asc[] = { |
|---|
| 84 | 0x0490, 0x0FE0, 0x07E0, 0x0BE0, 0x03E0, 0x0DE0, 0x05E0, 0x09E0, |
|---|
| 85 | 0x01E0, 0x00B8, 0x0062, 0x0EE0, 0x06E0, 0x0022, 0x0AE0, 0x02E0, |
|---|
| 86 | 0x0CE0, 0x04E0, 0x08E0, 0x00E0, 0x0F60, 0x0760, 0x0B60, 0x0360, |
|---|
| 87 | 0x0D60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0E60, 0x0660, 0x0A60, |
|---|
| 88 | 0x000F, 0x0250, 0x0038, 0x0260, 0x0050, 0x0C60, 0x0390, 0x00D8, |
|---|
| 89 | 0x0042, 0x0002, 0x0058, 0x01B0, 0x007C, 0x0029, 0x003C, 0x0098, |
|---|
| 90 | 0x005C, 0x0009, 0x001C, 0x006C, 0x002C, 0x004C, 0x0018, 0x000C, |
|---|
| 91 | 0x0074, 0x00E8, 0x0068, 0x0460, 0x0090, 0x0034, 0x00B0, 0x0710, |
|---|
| 92 | 0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00A8, |
|---|
| 93 | 0x0028, 0x0001, 0x0310, 0x0130, 0x003E, 0x0064, 0x001E, 0x002E, |
|---|
| 94 | 0x0024, 0x0510, 0x000E, 0x0036, 0x0016, 0x0044, 0x0030, 0x00C8, |
|---|
| 95 | 0x01D0, 0x00D0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088, |
|---|
| 96 | 0x0FA0, 0x0007, 0x0026, 0x0006, 0x003A, 0x001B, 0x001A, 0x002A, |
|---|
| 97 | 0x000A, 0x000B, 0x0210, 0x0004, 0x0013, 0x0032, 0x0003, 0x001D, |
|---|
| 98 | 0x0012, 0x0190, 0x000D, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078, |
|---|
| 99 | 0x00F0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07A0, 0x0BA0, 0x03A0, |
|---|
| 100 | 0x0240, 0x1C40, 0x0C40, 0x1440, 0x0440, 0x1840, 0x0840, 0x1040, |
|---|
| 101 | 0x0040, 0x1F80, 0x0F80, 0x1780, 0x0780, 0x1B80, 0x0B80, 0x1380, |
|---|
| 102 | 0x0380, 0x1D80, 0x0D80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180, |
|---|
| 103 | 0x0180, 0x1E80, 0x0E80, 0x1680, 0x0680, 0x1A80, 0x0A80, 0x1280, |
|---|
| 104 | 0x0280, 0x1C80, 0x0C80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080, |
|---|
| 105 | 0x0080, 0x1F00, 0x0F00, 0x1700, 0x0700, 0x1B00, 0x0B00, 0x1300, |
|---|
| 106 | 0x0DA0, 0x05A0, 0x09A0, 0x01A0, 0x0EA0, 0x06A0, 0x0AA0, 0x02A0, |
|---|
| 107 | 0x0CA0, 0x04A0, 0x08A0, 0x00A0, 0x0F20, 0x0720, 0x0B20, 0x0320, |
|---|
| 108 | 0x0D20, 0x0520, 0x0920, 0x0120, 0x0E20, 0x0620, 0x0A20, 0x0220, |
|---|
| 109 | 0x0C20, 0x0420, 0x0820, 0x0020, 0x0FC0, 0x07C0, 0x0BC0, 0x03C0, |
|---|
| 110 | 0x0DC0, 0x05C0, 0x09C0, 0x01C0, 0x0EC0, 0x06C0, 0x0AC0, 0x02C0, |
|---|
| 111 | 0x0CC0, 0x04C0, 0x08C0, 0x00C0, 0x0F40, 0x0740, 0x0B40, 0x0340, |
|---|
| 112 | 0x0300, 0x0D40, 0x1D00, 0x0D00, 0x1500, 0x0540, 0x0500, 0x1900, |
|---|
| 113 | 0x0900, 0x0940, 0x1100, 0x0100, 0x1E00, 0x0E00, 0x0140, 0x1600, |
|---|
| 114 | 0x0600, 0x1A00, 0x0E40, 0x0640, 0x0A40, 0x0A00, 0x1200, 0x0200, |
|---|
| 115 | 0x1C00, 0x0C00, 0x1400, 0x0400, 0x1800, 0x0800, 0x1000, 0x0000 |
|---|
| 116 | }; |
|---|
| 117 | |
|---|
| 118 | /* Local variables */ |
|---|
| 119 | static char copyright[] = "PKWARE Data Compression Library for Win32\r\n" |
|---|
| 120 | "Copyright 1989-1995 PKWARE Inc. All Rights Reserved\r\n" |
|---|
| 121 | "Patent No. 5,051,745\r\n" |
|---|
| 122 | "PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n" |
|---|
| 123 | "Version 1.11\r\n"; |
|---|
| 124 | |
|---|
| 125 | /* Local functions */ |
|---|
| 126 | static void libmpq_pkzip_gen_decode_tabs(long count, unsigned char *bits, unsigned char *code, unsigned char *buf2) { |
|---|
| 127 | long i; |
|---|
| 128 | |
|---|
| 129 | for (i = count-1; i >= 0; i--) { /* EBX - count */ |
|---|
| 130 | unsigned long idx1 = code[i]; |
|---|
| 131 | unsigned long idx2 = 1 << bits[i]; |
|---|
| 132 | do { |
|---|
| 133 | buf2[idx1] = (unsigned char)i; |
|---|
| 134 | idx1 += idx2; |
|---|
| 135 | } while (idx1 < 0x100); |
|---|
| 136 | } |
|---|
| 137 | } |
|---|
| 138 | |
|---|
| 139 | static void libmpq_pkzip_gen_asc_tabs(pkzip_data_cmp *mpq_pkzip) { |
|---|
| 140 | unsigned short *code_asc = &pkzip_code_asc[0xFF]; |
|---|
| 141 | unsigned long acc, add; |
|---|
| 142 | unsigned short count; |
|---|
| 143 | |
|---|
| 144 | for (count = 0x00FF; code_asc >= pkzip_code_asc; code_asc--, count--) { |
|---|
| 145 | unsigned char *bits_asc = mpq_pkzip->bits_asc + count; |
|---|
| 146 | unsigned char bits_tmp = *bits_asc; |
|---|
| 147 | |
|---|
| 148 | if (bits_tmp <= 8) { |
|---|
| 149 | add = (1 << bits_tmp); |
|---|
| 150 | acc = *code_asc; |
|---|
| 151 | do { |
|---|
| 152 | mpq_pkzip->offs_2c34[acc] = (unsigned char)count; |
|---|
| 153 | acc += add; |
|---|
| 154 | } while (acc < 0x100); |
|---|
| 155 | } else { |
|---|
| 156 | if ((acc = (*code_asc & 0xFF)) != 0) { |
|---|
| 157 | mpq_pkzip->offs_2c34[acc] = 0xFF; |
|---|
| 158 | if (*code_asc & 0x3F) { |
|---|
| 159 | bits_tmp -= 4; |
|---|
| 160 | *bits_asc = bits_tmp; |
|---|
| 161 | add = (1 << bits_tmp); |
|---|
| 162 | acc = *code_asc >> 4; |
|---|
| 163 | do { |
|---|
| 164 | mpq_pkzip->offs_2d34[acc] = (unsigned char)count; |
|---|
| 165 | acc += add; |
|---|
| 166 | } while (acc < 0x100); |
|---|
| 167 | } else { |
|---|
| 168 | bits_tmp -= 6; |
|---|
| 169 | *bits_asc = bits_tmp; |
|---|
| 170 | add = (1 << bits_tmp); |
|---|
| 171 | acc = *code_asc >> 6; |
|---|
| 172 | do { |
|---|
| 173 | mpq_pkzip->offs_2e34[acc] = (unsigned char)count; |
|---|
| 174 | acc += add; |
|---|
| 175 | } while (acc < 0x80); |
|---|
| 176 | } |
|---|
| 177 | } else { |
|---|
| 178 | bits_tmp -= 8; |
|---|
| 179 | *bits_asc = bits_tmp; |
|---|
| 180 | add = (1 << bits_tmp); |
|---|
| 181 | acc = *code_asc >> 8; |
|---|
| 182 | do { |
|---|
| 183 | mpq_pkzip->offs_2eb4[acc] = (unsigned char)count; |
|---|
| 184 | acc += add; |
|---|
| 185 | } while (acc < 0x100); |
|---|
| 186 | } |
|---|
| 187 | } |
|---|
| 188 | } |
|---|
| 189 | } |
|---|
| 190 | |
|---|
| 191 | /* |
|---|
| 192 | * Skips given number of bits in bit buffer. Result is stored in mpq_pkzip->bit_buf |
|---|
| 193 | * If no data in input buffer, returns true |
|---|
| 194 | */ |
|---|
| 195 | static int libmpq_pkzip_skip_bits(pkzip_data_cmp *mpq_pkzip, unsigned long bits) { |
|---|
| 196 | /* If number of bits required is less than number of (bits in the buffer) ? */ |
|---|
| 197 | if (bits <= mpq_pkzip->extra_bits) { |
|---|
| 198 | mpq_pkzip->extra_bits -= bits; |
|---|
| 199 | mpq_pkzip->bit_buf >>= bits; |
|---|
| 200 | return 0; |
|---|
| 201 | } |
|---|
| 202 | |
|---|
| 203 | /* Load input buffer if necessary */ |
|---|
| 204 | mpq_pkzip->bit_buf >>= mpq_pkzip->extra_bits; |
|---|
| 205 | if (mpq_pkzip->in_pos == mpq_pkzip->in_bytes) { |
|---|
| 206 | mpq_pkzip->in_pos = sizeof(mpq_pkzip->in_buf); |
|---|
| 207 | if ((mpq_pkzip->in_bytes = mpq_pkzip->read_buf((char *)mpq_pkzip->in_buf, &mpq_pkzip->in_pos, mpq_pkzip->param)) == 0) { |
|---|
| 208 | return 1; |
|---|
| 209 | } |
|---|
| 210 | mpq_pkzip->in_pos = 0; |
|---|
| 211 | } |
|---|
| 212 | |
|---|
| 213 | /* Update bit buffer */ |
|---|
| 214 | mpq_pkzip->bit_buf |= (mpq_pkzip->in_buf[mpq_pkzip->in_pos++] << 8); |
|---|
| 215 | mpq_pkzip->bit_buf >>= (bits - mpq_pkzip->extra_bits); |
|---|
| 216 | mpq_pkzip->extra_bits = (mpq_pkzip->extra_bits - bits) + 8; |
|---|
| 217 | return 0; |
|---|
| 218 | } |
|---|
| 219 | |
|---|
| 220 | /* |
|---|
| 221 | * Decompress the imploded data using coded literals. |
|---|
| 222 | * Returns: 0x000 - 0x0FF : One byte from compressed file. |
|---|
| 223 | * 0x100 - 0x305 : Copy previous block (0x100 = 1 byte) |
|---|
| 224 | * 0x306 : Out of buffer (?) |
|---|
| 225 | */ |
|---|
| 226 | static unsigned long libmpq_pkzip_explode_lit(pkzip_data_cmp *mpq_pkzip) { |
|---|
| 227 | unsigned long bits; /* Number of bits to skip */ |
|---|
| 228 | unsigned long value; /* Position in buffers */ |
|---|
| 229 | |
|---|
| 230 | /* Test the current bit in byte buffer. If is not set, simply return the next byte. */ |
|---|
| 231 | if (mpq_pkzip->bit_buf & 1) { |
|---|
| 232 | |
|---|
| 233 | /* Skip current bit in the buffer. */ |
|---|
| 234 | if (libmpq_pkzip_skip_bits(mpq_pkzip, 1)) { |
|---|
| 235 | return 0x306; |
|---|
| 236 | } |
|---|
| 237 | |
|---|
| 238 | /* The next bits are position in buffers. */ |
|---|
| 239 | value = mpq_pkzip->pos2[(mpq_pkzip->bit_buf & 0xFF)]; |
|---|
| 240 | |
|---|
| 241 | /* Get number of bits to skip */ |
|---|
| 242 | if (libmpq_pkzip_skip_bits(mpq_pkzip, mpq_pkzip->slen_bits[value])) { |
|---|
| 243 | return 0x306; |
|---|
| 244 | } |
|---|
| 245 | if ((bits = mpq_pkzip->clen_bits[value]) != 0) { |
|---|
| 246 | unsigned long val2 = mpq_pkzip->bit_buf & ((1 << bits) - 1); |
|---|
| 247 | if (libmpq_pkzip_skip_bits(mpq_pkzip, bits)) { |
|---|
| 248 | if ((value + val2) != 0x10E) { |
|---|
| 249 | return 0x306; |
|---|
| 250 | } |
|---|
| 251 | } |
|---|
| 252 | value = mpq_pkzip->len_base[value] + val2; |
|---|
| 253 | } |
|---|
| 254 | return value + 0x100; /* Return number of bytes to repeat */ |
|---|
| 255 | } |
|---|
| 256 | |
|---|
| 257 | /* Skip one bit */ |
|---|
| 258 | if (libmpq_pkzip_skip_bits(mpq_pkzip, 1)) { |
|---|
| 259 | return 0x306; |
|---|
| 260 | } |
|---|
| 261 | |
|---|
| 262 | /* If the binary compression type, read 8 bits and return them as one byte. */ |
|---|
| 263 | if (mpq_pkzip->cmp_type == LIBMPQ_PKZIP_CMP_BINARY) { |
|---|
| 264 | value = mpq_pkzip->bit_buf & 0xFF; |
|---|
| 265 | if (libmpq_pkzip_skip_bits(mpq_pkzip, 8)) { |
|---|
| 266 | return 0x306; |
|---|
| 267 | } |
|---|
| 268 | return value; |
|---|
| 269 | } |
|---|
| 270 | |
|---|
| 271 | /* When ASCII compression ... */ |
|---|
| 272 | if (mpq_pkzip->bit_buf & 0xFF) { |
|---|
| 273 | value = mpq_pkzip->offs_2c34[mpq_pkzip->bit_buf & 0xFF]; |
|---|
| 274 | if (value == 0xFF) { |
|---|
| 275 | if (mpq_pkzip->bit_buf & 0x3F) { |
|---|
| 276 | if (libmpq_pkzip_skip_bits(mpq_pkzip, 4)) { |
|---|
| 277 | return 0x306; |
|---|
| 278 | } |
|---|
| 279 | value = mpq_pkzip->offs_2d34[mpq_pkzip->bit_buf & 0xFF]; |
|---|
| 280 | } else { |
|---|
| 281 | if (libmpq_pkzip_skip_bits(mpq_pkzip, 6)) { |
|---|
| 282 | return 0x306; |
|---|
| 283 | } |
|---|
| 284 | value = mpq_pkzip->offs_2e34[mpq_pkzip->bit_buf & 0x7F]; |
|---|
| 285 | } |
|---|
| 286 | } |
|---|
| 287 | } else { |
|---|
| 288 | if (libmpq_pkzip_skip_bits(mpq_pkzip, 8)) { |
|---|
| 289 | return 0x306; |
|---|
| 290 | } |
|---|
| 291 | value = mpq_pkzip->offs_2eb4[mpq_pkzip->bit_buf & 0xFF]; |
|---|
| 292 | } |
|---|
| 293 | return libmpq_pkzip_skip_bits(mpq_pkzip, mpq_pkzip->bits_asc[value]) ? 0x306 : value; |
|---|
| 294 | } |
|---|
| 295 | |
|---|
| 296 | /* |
|---|
| 297 | * Retrieves the number of bytes to move back. |
|---|
| 298 | */ |
|---|
| 299 | static unsigned long libmpq_pkzip_explode_dist(pkzip_data_cmp *mpq_pkzip, unsigned long length) { |
|---|
| 300 | unsigned long pos = mpq_pkzip->pos1[(mpq_pkzip->bit_buf & 0xFF)]; |
|---|
| 301 | unsigned long skip = mpq_pkzip->dist_bits[pos]; /* Number of bits to skip */ |
|---|
| 302 | |
|---|
| 303 | /* Skip the appropriate number of bits */ |
|---|
| 304 | if (libmpq_pkzip_skip_bits(mpq_pkzip, skip) == 1) { |
|---|
| 305 | return 0; |
|---|
| 306 | } |
|---|
| 307 | if (length == 2) { |
|---|
| 308 | pos = (pos << 2) | (mpq_pkzip->bit_buf & 0x03); |
|---|
| 309 | if (libmpq_pkzip_skip_bits(mpq_pkzip, 2) == 1) { |
|---|
| 310 | return 0; |
|---|
| 311 | } |
|---|
| 312 | } else { |
|---|
| 313 | pos = (pos << mpq_pkzip->dsize_bits) | (mpq_pkzip->bit_buf & mpq_pkzip->dsize_mask); |
|---|
| 314 | |
|---|
| 315 | /* Skip the bits */ |
|---|
| 316 | if (libmpq_pkzip_skip_bits(mpq_pkzip, mpq_pkzip->dsize_bits) == 1) { |
|---|
| 317 | return 0; |
|---|
| 318 | } |
|---|
| 319 | } |
|---|
| 320 | return pos + 1; |
|---|
| 321 | } |
|---|
| 322 | |
|---|
| 323 | static unsigned long libmpq_pkzip_expand(pkzip_data_cmp *mpq_pkzip) { |
|---|
| 324 | unsigned int copy_bytes; /* Number of bytes to copy */ |
|---|
| 325 | unsigned long one_byte; /* One byte from compressed file */ |
|---|
| 326 | unsigned long result; |
|---|
| 327 | |
|---|
| 328 | mpq_pkzip->out_pos = 0x1000; /* Initialize output buffer position */ |
|---|
| 329 | |
|---|
| 330 | /* If end of data or error, terminate decompress */ |
|---|
| 331 | while ((result = one_byte = libmpq_pkzip_explode_lit(mpq_pkzip)) < 0x305) { |
|---|
| 332 | |
|---|
| 333 | /* If one byte is greater than 0x100, means "Repeat n - 0xFE bytes" */ |
|---|
| 334 | if (one_byte >= 0x100) { |
|---|
| 335 | unsigned char *source; /* ECX */ |
|---|
| 336 | unsigned char *target; /* EDX */ |
|---|
| 337 | unsigned long copy_length = one_byte - 0xFE; |
|---|
| 338 | unsigned long move_back; |
|---|
| 339 | |
|---|
| 340 | /* Get length of data to copy */ |
|---|
| 341 | if ((move_back = libmpq_pkzip_explode_dist(mpq_pkzip, copy_length)) == 0) { |
|---|
| 342 | result = 0x306; |
|---|
| 343 | break; |
|---|
| 344 | } |
|---|
| 345 | |
|---|
| 346 | /* Target and source pointer */ |
|---|
| 347 | target = &mpq_pkzip->out_buf[mpq_pkzip->out_pos]; |
|---|
| 348 | source = target - move_back; |
|---|
| 349 | mpq_pkzip->out_pos += copy_length; |
|---|
| 350 | while (copy_length-- > 0) { |
|---|
| 351 | *target++ = *source++; |
|---|
| 352 | } |
|---|
| 353 | } else { |
|---|
| 354 | mpq_pkzip->out_buf[mpq_pkzip->out_pos++] = (unsigned char)one_byte; |
|---|
| 355 | } |
|---|
| 356 | |
|---|
| 357 | /* |
|---|
| 358 | * If number of extracted bytes has reached 1/2 of output buffer, |
|---|
| 359 | * flush output buffer. |
|---|
| 360 | */ |
|---|
| 361 | if (mpq_pkzip->out_pos >= 0x2000) { |
|---|
| 362 | |
|---|
| 363 | /* Copy decompressed data into user buffer. */ |
|---|
| 364 | copy_bytes = 0x1000; |
|---|
| 365 | mpq_pkzip->write_buf((char *)&mpq_pkzip->out_buf[0x1000], ©_bytes, mpq_pkzip->param); |
|---|
| 366 | |
|---|
| 367 | /* If there are some data left, keep them alive */ |
|---|
| 368 | memcpy(mpq_pkzip->out_buf, &mpq_pkzip->out_buf[0x1000], mpq_pkzip->out_pos - 0x1000); |
|---|
| 369 | mpq_pkzip->out_pos -= 0x1000; |
|---|
| 370 | } |
|---|
| 371 | } |
|---|
| 372 | copy_bytes = mpq_pkzip->out_pos - 0x1000; |
|---|
| 373 | mpq_pkzip->write_buf((char *)&mpq_pkzip->out_buf[0x1000], ©_bytes, mpq_pkzip->param); |
|---|
| 374 | return result; |
|---|
| 375 | } |
|---|
| 376 | |
|---|
| 377 | /* |
|---|
| 378 | * Main exploding function. |
|---|
| 379 | */ |
|---|
| 380 | unsigned int libmpq_pkzip_explode( |
|---|
| 381 | unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), |
|---|
| 382 | void (*write_buf)(char *buf, unsigned int *size, void *param), |
|---|
| 383 | char *work_buf, |
|---|
| 384 | void *param) { |
|---|
| 385 | |
|---|
| 386 | pkzip_data_cmp *mpq_pkzip = (pkzip_data_cmp *)work_buf; |
|---|
| 387 | |
|---|
| 388 | /* Set the whole work buffer to zeros */ |
|---|
| 389 | memset(mpq_pkzip, 0, sizeof(pkzip_data_cmp)); |
|---|
| 390 | |
|---|
| 391 | /* Initialize work struct and load compressed data */ |
|---|
| 392 | mpq_pkzip->read_buf = read_buf; |
|---|
| 393 | mpq_pkzip->write_buf = write_buf; |
|---|
| 394 | mpq_pkzip->param = param; |
|---|
| 395 | mpq_pkzip->in_pos = sizeof(mpq_pkzip->in_buf); |
|---|
| 396 | mpq_pkzip->in_bytes = mpq_pkzip->read_buf((char *)mpq_pkzip->in_buf, &mpq_pkzip->in_pos, mpq_pkzip->param); |
|---|
| 397 | if (mpq_pkzip->in_bytes <= 4) { |
|---|
| 398 | return LIBMPQ_PKZIP_CMP_BAD_DATA; |
|---|
| 399 | } |
|---|
| 400 | mpq_pkzip->cmp_type = mpq_pkzip->in_buf[0]; /* Get the compression type */ |
|---|
| 401 | mpq_pkzip->dsize_bits = mpq_pkzip->in_buf[1]; /* Get the dictionary size */ |
|---|
| 402 | mpq_pkzip->bit_buf = mpq_pkzip->in_buf[2]; /* Initialize 16-bit bit buffer */ |
|---|
| 403 | mpq_pkzip->extra_bits = 0; /* Extra (over 8) bits */ |
|---|
| 404 | mpq_pkzip->in_pos = 3; /* Position in input buffer */ |
|---|
| 405 | |
|---|
| 406 | /* Test for the valid dictionary size */ |
|---|
| 407 | if (4 > mpq_pkzip->dsize_bits || mpq_pkzip->dsize_bits > 6) { |
|---|
| 408 | return LIBMPQ_PKZIP_CMP_INV_DICTSIZE; |
|---|
| 409 | } |
|---|
| 410 | mpq_pkzip->dsize_mask = 0xFFFF >> (0x10 - mpq_pkzip->dsize_bits); /* Shifted by 'sar' instruction */ |
|---|
| 411 | if (mpq_pkzip->cmp_type != LIBMPQ_PKZIP_CMP_BINARY) { |
|---|
| 412 | if (mpq_pkzip->cmp_type != LIBMPQ_PKZIP_CMP_ASCII) { |
|---|
| 413 | return LIBMPQ_PKZIP_CMP_INV_MODE; |
|---|
| 414 | } |
|---|
| 415 | memcpy(mpq_pkzip->bits_asc, pkzip_bits_asc, sizeof(mpq_pkzip->bits_asc)); |
|---|
| 416 | libmpq_pkzip_gen_asc_tabs(mpq_pkzip); |
|---|
| 417 | } |
|---|
| 418 | memcpy(mpq_pkzip->slen_bits, pkzip_slen_bits, sizeof(mpq_pkzip->slen_bits)); |
|---|
| 419 | libmpq_pkzip_gen_decode_tabs(0x10, mpq_pkzip->slen_bits, pkzip_len_code, mpq_pkzip->pos2); |
|---|
| 420 | memcpy(mpq_pkzip->clen_bits, pkzip_clen_bits, sizeof(mpq_pkzip->clen_bits)); |
|---|
| 421 | memcpy(mpq_pkzip->len_base, pkzip_len_base, sizeof(mpq_pkzip->len_base)); |
|---|
| 422 | memcpy(mpq_pkzip->dist_bits, pkzip_dist_bits, sizeof(mpq_pkzip->dist_bits)); |
|---|
| 423 | libmpq_pkzip_gen_decode_tabs(0x40, mpq_pkzip->dist_bits, pkzip_dist_code, mpq_pkzip->pos1); |
|---|
| 424 | if (libmpq_pkzip_expand(mpq_pkzip) != 0x306) { |
|---|
| 425 | return LIBMPQ_PKZIP_CMP_NO_ERROR; |
|---|
| 426 | } |
|---|
| 427 | return LIBMPQ_PKZIP_CMP_ABORT; |
|---|
| 428 | } |
|---|