--- trunk/reactos/lib/cabinet/cabextract.c 2004-12-31 13:38:22 UTC (rev 12424)
+++ trunk/reactos/lib/cabinet/cabextract.c 2004-12-31 13:45:51 UTC (rev 12425)
@@ -1,2654 +0,0 @@
-/*
- * cabextract.c
- *
- * Copyright 2000-2002 Stuart Caie
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Principal author: Stuart Caie <kyzer@4u.net>
- *
- * Based on specification documents from Microsoft Corporation
- * Quantum decompression researched and implemented by Matthew Russoto
- * Huffman code adapted from unlzx by Dave Tritscher.
- * InfoZip team's INFLATE implementation adapted to MSZIP by Dirk Stoecker.
- * Major LZX fixes by Jae Jung.
- */
-
-#include "config.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "windef.h"
-#include "winbase.h"
-#include "winerror.h"
-
-#include "cabinet.h"
-
-#include "wine/debug.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(cabinet);
-
-THOSE_ZIP_CONSTS;
-
-/* all the file IO is abstracted into these routines:
- * cabinet_(open|close|read|seek|skip|getoffset)
- * file_(open|close|write)
- */
-
-/* try to open a cabinet file, returns success */
-BOOL cabinet_open(struct cabinet *cab)
-{
- const char *name = cab->filename;
- HANDLE fh;
-
- TRACE("(cab == ^%p)\n", cab);
-
- if ((fh = CreateFileA( name, GENERIC_READ, FILE_SHARE_READ,
- NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL )) == INVALID_HANDLE_VALUE) {
- ERR("Couldn't open %s\n", debugstr_a(name));
- return FALSE;
- }
-
- /* seek to end of file and get the length */
- if ((cab->filelen = SetFilePointer(fh, 0, NULL, FILE_END)) == INVALID_SET_FILE_POINTER) {
- if (GetLastError() != NO_ERROR) {
- ERR("Seek END failed: %s\n", debugstr_a(name));
- CloseHandle(fh);
- return FALSE;
- }
- }
-
- /* return to the start of the file */
- if (SetFilePointer(fh, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
- ERR("Seek BEGIN failed: %s\n", debugstr_a(name));
- CloseHandle(fh);
- return FALSE;
- }
-
- cab->fh = fh;
- return TRUE;
-}
-
-/*******************************************************************
- * cabinet_close (internal)
- *
- * close the file handle in a struct cabinet.
- */
-void cabinet_close(struct cabinet *cab) {
- TRACE("(cab == ^%p)\n", cab);
- if (cab->fh) CloseHandle(cab->fh);
- cab->fh = 0;
-}
-
-/*******************************************************
- * ensure_filepath2 (internal)
- */
-BOOL ensure_filepath2(char *path) {
- BOOL ret = TRUE;
- int len;
- char *new_path;
-
- new_path = HeapAlloc(GetProcessHeap(), 0, (strlen(path) + 1));
- strcpy(new_path, path);
-
- while((len = strlen(new_path)) && new_path[len - 1] == '\\')
- new_path[len - 1] = 0;
-
- TRACE("About to try to create directory %s\n", debugstr_a(new_path));
- while(!CreateDirectoryA(new_path, NULL)) {
- char *slash;
- DWORD last_error = GetLastError();
-
- if(last_error == ERROR_ALREADY_EXISTS)
- break;
-
- if(last_error != ERROR_PATH_NOT_FOUND) {
- ret = FALSE;
- break;
- }
-
- if(!(slash = strrchr(new_path, '\\'))) {
- ret = FALSE;
- break;
- }
-
- len = slash - new_path;
- new_path[len] = 0;
- if(! ensure_filepath2(new_path)) {
- ret = FALSE;
- break;
- }
- new_path[len] = '\\';
- TRACE("New path in next iteration: %s\n", debugstr_a(new_path));
- }
-
- HeapFree(GetProcessHeap(), 0, new_path);
- return ret;
-}
-
-
-/**********************************************************************
- * ensure_filepath (internal)
- *
- * ensure_filepath("a\b\c\d.txt") ensures a, a\b and a\b\c exist as dirs
- */
-BOOL ensure_filepath(char *path) {
- char new_path[MAX_PATH];
- int len, i, lastslashpos = -1;
-
- TRACE("(path == %s)\n", debugstr_a(path));
-
- strcpy(new_path, path);
- /* remove trailing slashes (shouldn't need to but wth...) */
- while ((len = strlen(new_path)) && new_path[len - 1] == '\\')
- new_path[len - 1] = 0;
- /* find the position of the last '\\' */
- for (i=0; i<MAX_PATH; i++) {
- if (new_path[i] == 0) break;
- if (new_path[i] == '\\')
- lastslashpos = i;
- }
- if (lastslashpos > 0) {
- new_path[lastslashpos] = 0;
- /* may be trailing slashes but ensure_filepath2 will chop them */
- return ensure_filepath2(new_path);
- } else
- return TRUE; /* ? */
-}
-
-/*******************************************************************
- * file_open (internal)
- *
- * opens a file for output, returns success
- */
-BOOL file_open(struct cab_file *fi, BOOL lower, LPCSTR dir)
-{
- char c, *d, *name;
- BOOL ok = FALSE;
- const char *s;
-
- TRACE("(fi == ^%p, lower == %s, dir == %s)\n", fi, lower ? "TRUE" : "FALSE", debugstr_a(dir));
-
- if (!(name = malloc(strlen(fi->filename) + (dir ? strlen(dir) : 0) + 2))) {
- ERR("out of memory!\n");
- return FALSE;
- }
-
- /* start with blank name */
- *name = 0;
-
- /* add output directory if needed */
- if (dir) {
- strcpy(name, dir);
- strcat(name, "\\");
- }
-
- /* remove leading slashes */
- s = (char *) fi->filename;
- while (*s == '\\') s++;
-
- /* copy from fi->filename to new name.
- * lowercases characters if needed.
- */
- d = &name[strlen(name)];
- do {
- c = *s++;
- *d++ = (lower ? tolower((unsigned char) c) : c);
- } while (c);
-
- /* create directories if needed, attempt to write file */
- if (ensure_filepath(name)) {
- fi->fh = CreateFileA(name, GENERIC_WRITE, 0, NULL,
- CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
- if (fi->fh != INVALID_HANDLE_VALUE)
- ok = TRUE;
- else {
- ERR("CreateFileA returned INVALID_HANDLE_VALUE\n");
- fi->fh = 0;
- }
- } else
- ERR("Couldn't ensure filepath for %s\n", debugstr_a(name));
-
- if (!ok) {
- ERR("Couldn't open file %s for writing\n", debugstr_a(name));
- }
-
- /* as full filename is no longer needed, free it */
- free(name);
-
- return ok;
-}
-
-/********************************************************
- * close_file (internal)
- *
- * closes a completed file
- */
-void file_close(struct cab_file *fi)
-{
- TRACE("(fi == ^%p)\n", fi);
-
- if (fi->fh) {
- CloseHandle(fi->fh);
- }
- fi->fh = 0;
-}
-
-/******************************************************************
- * file_write (internal)
- *
- * writes from buf to a file specified as a cab_file struct.
- * returns success/failure
- */
-BOOL file_write(struct cab_file *fi, cab_UBYTE *buf, cab_off_t length)
-{
- DWORD bytes_written;
-
- TRACE("(fi == ^%p, buf == ^%p, length == %u)\n", fi, buf, length);
-
- if ((!WriteFile( fi->fh, (LPCVOID) buf, length, &bytes_written, FALSE) ||
- (bytes_written != length))) {
- ERR("Error writing file: %s\n", debugstr_a(fi->filename));
- return FALSE;
- }
- return TRUE;
-}
-
-
-/*******************************************************************
- * cabinet_skip (internal)
- *
- * advance the file pointer associated with the cab structure
- * by distance bytes
- */
-void cabinet_skip(struct cabinet *cab, cab_off_t distance)
-{
- TRACE("(cab == ^%p, distance == %u)\n", cab, distance);
- if (SetFilePointer(cab->fh, distance, NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER) {
- if (distance != INVALID_SET_FILE_POINTER)
- ERR("%s\n", debugstr_a(cab->filename));
- }
-}
-
-/*******************************************************************
- * cabinet_seek (internal)
- *
- * seek to the specified absolute offset in a cab
- */
-void cabinet_seek(struct cabinet *cab, cab_off_t offset) {
- TRACE("(cab == ^%p, offset == %u)\n", cab, offset);
- if (SetFilePointer(cab->fh, offset, NULL, FILE_BEGIN) != offset)
- ERR("%s seek failure\n", debugstr_a(cab->filename));
-}
-
-/*******************************************************************
- * cabinet_getoffset (internal)
- *
- * returns the file pointer position of a cab
- */
-cab_off_t cabinet_getoffset(struct cabinet *cab)
-{
- return SetFilePointer(cab->fh, 0, NULL, FILE_CURRENT);
-}
-
-/*******************************************************************
- * cabinet_read (internal)
- *
- * read data from a cabinet, returns success
- */
-BOOL cabinet_read(struct cabinet *cab, cab_UBYTE *buf, cab_off_t length)
-{
- DWORD bytes_read;
- cab_off_t avail = cab->filelen - cabinet_getoffset(cab);
-
- TRACE("(cab == ^%p, buf == ^%p, length == %u)\n", cab, buf, length);
-
- if (length > avail) {
- WARN("%s: WARNING; cabinet is truncated\n", debugstr_a(cab->filename));
- length = avail;
- }
-
- if (! ReadFile( cab->fh, (LPVOID) buf, length, &bytes_read, NULL )) {
- ERR("%s read error\n", debugstr_a(cab->filename));
- return FALSE;
- } else if (bytes_read != length) {
- ERR("%s read size mismatch\n", debugstr_a(cab->filename));
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**********************************************************************
- * cabinet_read_string (internal)
- *
- * allocate and read an aribitrarily long string from the cabinet
- */
-char *cabinet_read_string(struct cabinet *cab)
-{
- cab_off_t len=256, base = cabinet_getoffset(cab), maxlen = cab->filelen - base;
- BOOL ok = FALSE;
- unsigned int i;
- cab_UBYTE *buf = NULL;
-
- TRACE("(cab == ^%p)\n", cab);
-
- do {
- if (len > maxlen) len = maxlen;
- if (!(buf = realloc(buf, (size_t) len))) break;
- if (!cabinet_read(cab, buf, (size_t) len)) break;
-
- /* search for a null terminator in what we've just read */
- for (i=0; i < len; i++) {
- if (!buf[i]) {ok=TRUE; break;}
- }
-
- if (!ok) {
- if (len == maxlen) {
- ERR("%s: WARNING; cabinet is truncated\n", debugstr_a(cab->filename));
- break;
- }
- len += 256;
- cabinet_seek(cab, base);
- }
- } while (!ok);
-
- if (!ok) {
- if (buf)
- free(buf);
- else
- ERR("out of memory!\n");
- return NULL;
- }
-
- /* otherwise, set the stream to just after the string and return */
- cabinet_seek(cab, base + ((cab_off_t) strlen((char *) buf)) + 1);
-
- return (char *) buf;
-}
-
-/******************************************************************
- * cabinet_read_entries (internal)
- *
- * reads the header and all folder and file entries in this cabinet
- */
-BOOL cabinet_read_entries(struct cabinet *cab)
-{
- int num_folders, num_files, header_resv, folder_resv = 0, i;
- struct cab_folder *fol, *linkfol = NULL;
- struct cab_file *file, *linkfile = NULL;
- cab_off_t base_offset;
- cab_UBYTE buf[64];
-
- TRACE("(cab == ^%p)\n", cab);
-
- /* read in the CFHEADER */
- base_offset = cabinet_getoffset(cab);
- if (!cabinet_read(cab, buf, cfhead_SIZEOF)) {
- return FALSE;
- }
-
- /* check basic MSCF signature */
- if (EndGetI32(buf+cfhead_Signature) != 0x4643534d) {
- ERR("%s: not a Microsoft cabinet file\n", debugstr_a(cab->filename));
- return FALSE;
- }
-
- /* get the number of folders */
- num_folders = EndGetI16(buf+cfhead_NumFolders);
- if (num_folders == 0) {
- ERR("%s: no folders in cabinet\n", debugstr_a(cab->filename));
- return FALSE;
- }
-
- /* get the number of files */
- num_files = EndGetI16(buf+cfhead_NumFiles);
- if (num_files == 0) {
- ERR("%s: no files in cabinet\n", debugstr_a(cab->filename));
- return FALSE;
- }
-
- /* just check the header revision */
- if ((buf[cfhead_MajorVersion] > 1) ||
- (buf[cfhead_MajorVersion] == 1 && buf[cfhead_MinorVersion] > 3))
- {
- WARN("%s: WARNING; cabinet format version > 1.3\n", debugstr_a(cab->filename));
- }
-
- /* read the reserved-sizes part of header, if present */
- cab->flags = EndGetI16(buf+cfhead_Flags);
- if (cab->flags & cfheadRESERVE_PRESENT) {
- if (!cabinet_read(cab, buf, cfheadext_SIZEOF)) return FALSE;
- header_resv = EndGetI16(buf+cfheadext_HeaderReserved);
- folder_resv = buf[cfheadext_FolderReserved];
- cab->block_resv = buf[cfheadext_DataReserved];
-
- if (header_resv > 60000) {
- WARN("%s: WARNING; header reserved space > 60000\n", debugstr_a(cab->filename));
- }
-
- /* skip the reserved header */
- if (header_resv)
- if (SetFilePointer(cab->fh, (cab_off_t) header_resv, NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER)
- ERR("seek failure: %s\n", debugstr_a(cab->filename));
- }
-
- if (cab->flags & cfheadPREV_CABINET) {
- cab->prevname = cabinet_read_string(cab);
- if (!cab->prevname) return FALSE;
- cab->previnfo = cabinet_read_string(cab);
- }
-
- if (cab->flags & cfheadNEXT_CABINET) {
- cab->nextname = cabinet_read_string(cab);
- if (!cab->nextname) return FALSE;
- cab->nextinfo = cabinet_read_string(cab);
- }
-
- /* read folders */
- for (i = 0; i < num_folders; i++) {
- if (!cabinet_read(cab, buf, cffold_SIZEOF)) return FALSE;
- if (folder_resv) cabinet_skip(cab, folder_resv);
-
- fol = (struct cab_folder *) calloc(1, sizeof(struct cab_folder));
- if (!fol) {
- ERR("out of memory!\n");
- return FALSE;
- }
-
- fol->cab[0] = cab;
- fol->offset[0] = base_offset + (cab_off_t) EndGetI32(buf+cffold_DataOffset);
- fol->num_blocks = EndGetI16(buf+cffold_NumBlocks);
- fol->comp_type = EndGetI16(buf+cffold_CompType);
-
- if (!linkfol)
- cab->folders = fol;
- else
- linkfol->next = fol;
-
- linkfol = fol;
- }
-
- /* read files */
- for (i = 0; i < num_files; i++) {
- if (!cabinet_read(cab, buf, cffile_SIZEOF))
- return FALSE;
-
- file = (struct cab_file *) calloc(1, sizeof(struct cab_file));
- if (!file) {
- ERR("out of memory!\n");
- return FALSE;
- }
-
- file->length = EndGetI32(buf+cffile_UncompressedSize);
- file->offset = EndGetI32(buf+cffile_FolderOffset);
- file->index = EndGetI16(buf+cffile_FolderIndex);
- file->time = EndGetI16(buf+cffile_Time);
- file->date = EndGetI16(buf+cffile_Date);
- file->attribs = EndGetI16(buf+cffile_Attribs);
- file->filename = cabinet_read_string(cab);
-
- if (!file->filename) {
- free(file);
- return FALSE;
- }
-
- if (!linkfile)
- cab->files = file;
- else
- linkfile->next = file;
-
- linkfile = file;
- }
- return TRUE;
-}
-
-/***********************************************************
- * load_cab_offset (internal)
- *
- * validates and reads file entries from a cabinet at offset [offset] in
- * file [name]. Returns a cabinet structure if successful, or NULL
- * otherwise.
- */
-struct cabinet *load_cab_offset(LPCSTR name, cab_off_t offset)
-{
- struct cabinet *cab = (struct cabinet *) calloc(1, sizeof(struct cabinet));
- int ok;
-
- TRACE("(name == %s, offset == %u)\n", debugstr_a(name), offset);
-
- if (!cab) return NULL;
-
- cab->filename = name;
- if ((ok = cabinet_open(cab))) {
- cabinet_seek(cab, offset);
- ok = cabinet_read_entries(cab);
- cabinet_close(cab);
- }
-
- if (ok) return cab;
- free(cab);
- return NULL;
-}
-
-/* MSZIP decruncher */
-
-/* Dirk Stoecker wrote the ZIP decoder, based on the InfoZip deflate code */
-
-/********************************************************
- * Ziphuft_free (internal)
- */
-void Ziphuft_free(struct Ziphuft *t)
-{
- register struct Ziphuft *p, *q;
-
- /* Go through linked list, freeing from the allocated (t[-1]) address. */
- p = t;
- while (p != (struct Ziphuft *)NULL)
- {
- q = (--p)->v.t;
- free(p);
- p = q;
- }
-}
-
-/*********************************************************
- * Ziphuft_build (internal)
- */
-cab_LONG Ziphuft_build(cab_ULONG *b, cab_ULONG n, cab_ULONG s, cab_UWORD *d, cab_UWORD *e,
-struct Ziphuft **t, cab_LONG *m, cab_decomp_state *decomp_state)
-{
- cab_ULONG a; /* counter for codes of length k */
- cab_ULONG el; /* length of EOB code (value 256) */
- cab_ULONG f; /* i repeats in table every f entries */
- cab_LONG g; /* maximum code length */
- cab_LONG h; /* table level */
- register cab_ULONG i; /* counter, current code */
- register cab_ULONG j; /* counter */
- register cab_LONG k; /* number of bits in current code */
- cab_LONG *l; /* stack of bits per table */
- register cab_ULONG *p; /* pointer into ZIP(c)[],ZIP(b)[],ZIP(v)[] */
- register struct Ziphuft *q; /* points to current table */
- struct Ziphuft r; /* table entry for structure assignment */
- register cab_LONG w; /* bits before this table == (l * h) */
- cab_ULONG *xp; /* pointer into x */
- cab_LONG y; /* number of dummy codes added */
- cab_ULONG z; /* number of entries in current table */
-
- l = ZIP(lx)+1;
-
- /* Generate counts for each bit length */
- el = n > 256 ? b[256] : ZIPBMAX; /* set length of EOB code, if any */
-
- for(i = 0; i < ZIPBMAX+1; ++i)
- ZIP(c)[i] = 0;
- p = b; i = n;
- do
- {
- ZIP(c)[*p]++; p++; /* assume all entries <= ZIPBMAX */
- } while (--i);
- if (ZIP(c)[0] == n) /* null input--all zero length codes */
- {
- *t = (struct Ziphuft *)NULL;
- *m = 0;
- return 0;
- }
-
- /* Find minimum and maximum length, bound *m by those */
- for (j = 1; j <= ZIPBMAX; j++)
- if (ZIP(c)[j])
- break;
- k = j; /* minimum code length */
- if ((cab_ULONG)*m < j)
- *m = j;
- for (i = ZIPBMAX; i; i--)
- if (ZIP(c)[i])
- break;
- g = i; /* maximum code length */
- if ((cab_ULONG)*m > i)
- *m = i;
-
- /* Adjust last length count to fill out codes, if needed */
- for (y = 1 << j; j < i; j++, y <<= 1)
- if ((y -= ZIP(c)[j]) < 0)
- return 2; /* bad input: more codes than bits */
- if ((y -= ZIP(c)[i]) < 0)
- return 2;
- ZIP(c)[i] += y;
-
- /* Generate starting offsets LONGo the value table for each length */
- ZIP(x)[1] = j = 0;
- p = ZIP(c) + 1; xp = ZIP(x) + 2;
- while (--i)
- { /* note that i == g from above */
- *xp++ = (j += *p++);
- }
-
- /* Make a table of values in order of bit lengths */
- p = b; i = 0;
- do{
- if ((j = *p++) != 0)
- ZIP(v)[ZIP(x)[j]++] = i;
- } while (++i < n);
-
-
- /* Generate the Huffman codes and for each, make the table entries */
- ZIP(x)[0] = i = 0; /* first Huffman code is zero */
- p = ZIP(v); /* grab values in bit order */
- h = -1; /* no tables yet--level -1 */
- w = l[-1] = 0; /* no bits decoded yet */
- ZIP(u)[0] = (struct Ziphuft *)NULL; /* just to keep compilers happy */
- q = (struct Ziphuft *)NULL; /* ditto */
- z = 0; /* ditto */
-
- /* go through the bit lengths (k already is bits in shortest code) */
- for (; k <= g; k++)
- {
- a = ZIP(c)[k];
- while (a--)
- {
- /* here i is the Huffman code of length k bits for value *p */
- /* make tables up to required level */
- while (k > w + l[h])
- {
- w += l[h++]; /* add bits already decoded */
-
- /* compute minimum size table less than or equal to *m bits */
- z = (z = g - w) > (cab_ULONG)*m ? *m : z; /* upper limit */
- if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
- { /* too few codes for k-w bit table */
- f -= a + 1; /* deduct codes from patterns left */
- xp = ZIP(c) + k;
- while (++j < z) /* try smaller tables up to z bits */
- {
- if ((f <<= 1) <= *++xp)
- break; /* enough codes to use up j bits */
- f -= *xp; /* else deduct codes from patterns */
- }
- }
- if ((cab_ULONG)w + j > el && (cab_ULONG)w < el)
- j = el - w; /* make EOB code end at table */
- z = 1 << j; /* table entries for j-bit table */
- l[h] = j; /* set table size in stack */
-
- /* allocate and link in new table */
- if (!(q = (struct Ziphuft *) malloc((z + 1)*sizeof(struct Ziphuft))))
- {
- if(h)
- Ziphuft_free(ZIP(u)[0]);
- return 3; /* not enough memory */
- }
- *t = q + 1; /* link to list for Ziphuft_free() */
- *(t = &(q->v.t)) = (struct Ziphuft *)NULL;
- ZIP(u)[h] = ++q; /* table starts after link */
-
- /* connect to last table, if there is one */
- if (h)
- {
- ZIP(x)[h] = i; /* save pattern for backing up */
- r.b = (cab_UBYTE)l[h-1]; /* bits to dump before this table */
- r.e = (cab_UBYTE)(16 + j); /* bits in this table */
- r.v.t = q; /* pointer to this table */
- j = (i & ((1 << w) - 1)) >> (w - l[h-1]);
- ZIP(u)[h-1][j] = r; /* connect to last table */
- }
- }
-
- /* set up table entry in r */
- r.b = (cab_UBYTE)(k - w);
- if (p >= ZIP(v) + n)
- r.e = 99; /* out of values--invalid code */
- else if (*p < s)
- {
- r.e = (cab_UBYTE)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */
- r.v.n = *p++; /* simple code is just the value */
- }
- else
- {
- r.e = (cab_UBYTE)e[*p - s]; /* non-simple--look up in lists */
- r.v.n = d[*p++ - s];
- }
-
- /* fill code-like entries with r */
- f = 1 << (k - w);
- for (j = i >> w; j < z; j += f)
- q[j] = r;
-
- /* backwards increment the k-bit code i */
- for (j = 1 << (k - 1); i & j; j >>= 1)
- i ^= j;
- i ^= j;
-
- /* backup over finished tables */
- while ((i & ((1 << w) - 1)) != ZIP(x)[h])
- w -= l[--h]; /* don't need to update q */
- }
- }
-
- /* return actual size of base table */
- *m = l[0];
-
- /* Return true (1) if we were given an incomplete table */
- return y != 0 && g != 1;
-}
-
-/*********************************************************
- * Zipinflate_codes (internal)
- */
-cab_LONG Zipinflate_codes(struct Ziphuft *tl, struct Ziphuft *td,
- cab_LONG bl, cab_LONG bd, cab_decomp_state *decomp_state)
-{
- register cab_ULONG e; /* table entry flag/number of extra bits */
- cab_ULONG n, d; /* length and index for copy */
- cab_ULONG w; /* current window position */
- struct Ziphuft *t; /* pointer to table entry */
- cab_ULONG ml, md; /* masks for bl and bd bits */
- register cab_ULONG b; /* bit buffer */
- register cab_ULONG k; /* number of bits in bit buffer */
-
- /* make local copies of globals */
- b = ZIP(bb); /* initialize bit buffer */
- k = ZIP(bk);
- w = ZIP(window_posn); /* initialize window position */
-
- /* inflate the coded data */
- ml = Zipmask[bl]; /* precompute masks for speed */
- md = Zipmask[bd];
-
- for(;;)
- {
- ZIPNEEDBITS((cab_ULONG)bl)
- if((e = (t = tl + ((cab_ULONG)b & ml))->e) > 16)
- do
- {
- if (e == 99)
- return 1;
- ZIPDUMPBITS(t->b)
- e -= 16;
- ZIPNEEDBITS(e)
- } while ((e = (t = t->v.t + ((cab_ULONG)b & Zipmask[e]))->e) > 16);
- ZIPDUMPBITS(t->b)
- if (e == 16) /* then it's a literal */
- CAB(outbuf)[w++] = (cab_UBYTE)t->v.n;
- else /* it's an EOB or a length */
- {
- /* exit if end of block */
- if(e == 15)
- break;
-
- /* get length of block to copy */
- ZIPNEEDBITS(e)
- n = t->v.n + ((cab_ULONG)b & Zipmask[e]);
- ZIPDUMPBITS(e);
-
- /* decode distance of block to copy */
- ZIPNEEDBITS((cab_ULONG)bd)
- if ((e = (t = td + ((cab_ULONG)b & md))->e) > 16)
- do {
- if (e == 99)
- return 1;
- ZIPDUMPBITS(t->b)
- e -= 16;
- ZIPNEEDBITS(e)
- } while ((e = (t = t->v.t + ((cab_ULONG)b & Zipmask[e]))->e) > 16);
- ZIPDUMPBITS(t->b)
- ZIPNEEDBITS(e)
- d = w - t->v.n - ((cab_ULONG)b & Zipmask[e]);
- ZIPDUMPBITS(e)
- do
- {
- n -= (e = (e = ZIPWSIZE - ((d &= ZIPWSIZE-1) > w ? d : w)) > n ?n:e);
- do
- {
- CAB(outbuf)[w++] = CAB(outbuf)[d++];
- } while (--e);
- } while (n);
- }
- }
-
- /* restore the globals from the locals */
- ZIP(window_posn) = w; /* restore global window pointer */
- ZIP(bb) = b; /* restore global bit buffer */
- ZIP(bk) = k;
-
- /* done */
- return 0;
-}
-
-/***********************************************************
- * Zipinflate_stored (internal)
- */
-cab_LONG Zipinflate_stored(cab_decomp_state *decomp_state)
-/* "decompress" an inflated type 0 (stored) block. */
-{
- cab_ULONG n; /* number of bytes in block */
- cab_ULONG w; /* current window position */
- register cab_ULONG b; /* bit buffer */
- register cab_ULONG k; /* number of bits in bit buffer */
-
- /* make local copies of globals */
- b = ZIP(bb); /* initialize bit buffer */
- k = ZIP(bk);
- w = ZIP(window_posn); /* initialize window position */
-
- /* go to byte boundary */
- n = k & 7;
- ZIPDUMPBITS(n);
-
- /* get the length and its complement */
- ZIPNEEDBITS(16)
- n = ((cab_ULONG)b & 0xffff);
- ZIPDUMPBITS(16)
- ZIPNEEDBITS(16)
- if (n != (cab_ULONG)((~b) & 0xffff))
- return 1; /* error in compressed data */
- ZIPDUMPBITS(16)
-
- /* read and output the compressed data */
- while(n--)
- {
- ZIPNEEDBITS(8)
- CAB(outbuf)[w++] = (cab_UBYTE)b;
- ZIPDUMPBITS(8)
- }
-
- /* restore the globals from the locals */
- ZIP(window_posn) = w; /* restore global window pointer */
- ZIP(bb) = b; /* restore global bit buffer */
- ZIP(bk) = k;
- return 0;
-}
-
-/******************************************************
- * Zipinflate_fixed (internal)
- */
-cab_LONG Zipinflate_fixed(cab_decomp_state *decomp_state)
-{
- struct Ziphuft *fixed_tl;
- struct Ziphuft *fixed_td;
- cab_LONG fixed_bl, fixed_bd;
- cab_LONG i; /* temporary variable */
- cab_ULONG *l;
-
- l = ZIP(ll);
-
- /* literal table */
- for(i = 0; i < 144; i++)
- l[i] = 8;
- for(; i < 256; i++)
- l[i] = 9;
- for(; i < 280; i++)
- l[i] = 7;
- for(; i < 288; i++) /* make a complete, but wrong code set */
- l[i] = 8;
- fixed_bl = 7;
- if((i = Ziphuft_build(l, 288, 257, (cab_UWORD *) Zipcplens,
- (cab_UWORD *) Zipcplext, &fixed_tl, &fixed_bl, decomp_state)))
- return i;
-
- /* distance table */
- for(i = 0; i < 30; i++) /* make an incomplete code set */
- l[i] = 5;
- fixed_bd = 5;
- if((i = Ziphuft_build(l, 30, 0, (cab_UWORD *) Zipcpdist, (cab_UWORD *) Zipcpdext,
- &fixed_td, &fixed_bd, decomp_state)) > 1)
- {
- Ziphuft_free(fixed_tl);
- return i;
- }
-
- /* decompress until an end-of-block code */
- i = Zipinflate_codes(fixed_tl, fixed_td, fixed_bl, fixed_bd, decomp_state);
-
- Ziphuft_free(fixed_td);
- Ziphuft_free(fixed_tl);
- return i;
-}
-
-/**************************************************************
- * Zipinflate_dynamic (internal)
- */
-cab_LONG Zipinflate_dynamic(cab_decomp_state *decomp_state)
- /* decompress an inflated type 2 (dynamic Huffman codes) block. */
-{
- cab_LONG i; /* temporary variables */
- cab_ULONG j;
- cab_ULONG *ll;
- cab_ULONG l; /* last length */
- cab_ULONG m; /* mask for bit lengths table */
[truncated at 1000 lines; 5494 more skipped]