/* ==================================================================== * * MOD_GZIP.C - Version 1.3.26.1a * * This program was developed by * * Remote Communications, Inc. * Home page: http://www.RemoteCommunications.com * * and is currently maintained by * * Christian Kruse, and Michael Schroepl, * * Home page: http://sourceforge.net/projects/mod-gzip/ * * Original author: Kevin Kiley, CTO, Remote Communications, Inc. * Email: Kiley@RemoteCommunications.com * * As of this writing there is an online support forum which * anyone may join by following the instructions found at... * http://lists.over.net/mailman/listinfo/mod_gzip * * ==================================================================== */ /* APACHE LICENSE: START * * Portions of this software are covered under the following license * which, as it states, must remain included in this source code * module and may not be altered in any way. */ /* ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 2000 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . * * Portions of this software are based upon public domain software * originally written at the National Center for Supercomputing Applications, * University of Illinois, Urbana-Champaign. */ #include "httpd.h" #include "http_config.h" #include "http_log.h" #include "mod_gzip.h" /*--------------------------------------------------------------------------*/ /* COMPRESSION_SUPPORT: START */ /*--------------------------------------------------------------------------*/ #define BIG_MEM typedef unsigned uns; typedef unsigned int uni; typedef unsigned char uch; typedef unsigned short ush; typedef unsigned long ulg; typedef int gz1_file_t; #ifdef __STDC__ typedef void *voidp; #else typedef char *voidp; #endif #if defined(__MSDOS__) && !defined(MSDOS) # define MSDOS #endif #if defined(__OS2__) && !defined(OS2) # define OS2 #endif #if defined(OS2) && defined(MSDOS) # undef MSDOS #endif #ifdef MSDOS # ifdef __GNUC__ # define near # else # define MAXSEG_64K # ifdef __TURBOC__ # define NO_OFF_T # ifdef __BORLANDC__ # define DIRENT # else # define NO_UTIME # endif # else # define HAVE_SYS_UTIME_H # define NO_UTIME_H # endif # endif # define PATH_SEP2 '\\' # define PATH_SEP3 ':' # define MAX_PATH_LEN 128 # define NO_MULTIPLE_DOTS # define MAX_EXT_CHARS 3 # define Z_SUFFIX "z" # define NO_CHOWN # define PROTO # define STDC_HEADERS # define NO_SIZE_CHECK # define casemap(c) tolow(c) # include # undef OS_CODE # define OS_CODE 0x00 # define SET_BINARY_MODE(fd) setmode(fd, O_BINARY) # if !defined(NO_ASM) && !defined(ASMV) # define ASMV # endif #else # define near #endif #ifdef OS2 # define PATH_SEP2 '\\' # define PATH_SEP3 ':' # define MAX_PATH_LEN 260 # ifdef OS2FAT # define NO_MULTIPLE_DOTS # define MAX_EXT_CHARS 3 # define Z_SUFFIX "z" # define casemap(c) tolow(c) # endif # define NO_CHOWN # define PROTO # define STDC_HEADERS # include # undef OS_CODE # define OS_CODE 0x06 # define SET_BINARY_MODE(fd) setmode(fd, O_BINARY) # ifdef _MSC_VER # define HAVE_SYS_UTIME_H # define NO_UTIME_H # define MAXSEG_64K # undef near # define near _near # endif # ifdef __EMX__ # define HAVE_SYS_UTIME_H # define NO_UTIME_H # define DIRENT # define EXPAND(argc,argv) \ {_response(&argc, &argv); _wildcard(&argc, &argv);} # endif # ifdef __BORLANDC__ # define DIRENT # endif # ifdef __ZTC__ # define NO_DIR # define NO_UTIME_H # include # define EXPAND(argc,argv) \ {response_expand(&argc, &argv);} # endif #endif #ifdef WIN32 # define HAVE_SYS_UTIME_H # define NO_UTIME_H # define PATH_SEP2 '\\' # define PATH_SEP3 ':' # undef MAX_PATH_LEN # define MAX_PATH_LEN 260 # define NO_CHOWN # define PROTO # define STDC_HEADERS # define SET_BINARY_MODE(fd) setmode(fd, O_BINARY) # include # include # ifdef NTFAT # define NO_MULTIPLE_DOTS # define MAX_EXT_CHARS 3 # define Z_SUFFIX "z" # define casemap(c) tolow(c) # endif # undef OS_CODE # define OS_CODE 0x00 #endif #ifdef MSDOS # ifdef __TURBOC__ # include # define DYN_ALLOC void * fcalloc (unsigned items, unsigned size); void fcfree (void *ptr); # else # include # define fcalloc(nitems,itemsize) halloc((long)(nitems),(itemsize)) # define fcfree(ptr) hfree(ptr) # endif #else # ifdef MAXSEG_64K # define fcalloc(items,size) calloc((items),(size)) # else # define fcalloc(items,size) malloc((size_t)(items)*(size_t)(size)) # endif # define fcfree(ptr) free(ptr) #endif #if defined(VAXC) || defined(VMS) # define PATH_SEP ']' # define PATH_SEP2 ':' # define SUFFIX_SEP ';' # define NO_MULTIPLE_DOTS # define Z_SUFFIX "-gz" # define RECORD_IO 1 # define casemap(c) tolow(c) # undef OS_CODE # define OS_CODE 0x02 # define OPTIONS_VAR "GZIP_OPT" # define STDC_HEADERS # define NO_UTIME # define EXPAND(argc,argv) vms_expand_args(&argc,&argv); # include # define unlink delete # ifdef VAXC # define NO_FCNTL_H # include # endif #endif #ifdef AMIGA # define PATH_SEP2 ':' # define STDC_HEADERS # undef OS_CODE # define OS_CODE 0x01 # define ASMV # ifdef __GNUC__ # define DIRENT # define HAVE_UNISTD_H # else # define NO_STDIN_FSTAT # define SYSDIR # define NO_SYMLINK # define NO_CHOWN # define NO_FCNTL_H # include # define direct dirent extern void _expand_args(int *argc, char ***argv); # define EXPAND(argc,argv) _expand_args(&argc,&argv); # undef O_BINARY # endif #endif #if defined(ATARI) || defined(atarist) # ifndef STDC_HEADERS # define STDC_HEADERS # define HAVE_UNISTD_H # define DIRENT # endif # define ASMV # undef OS_CODE # define OS_CODE 0x05 # ifdef TOSFS # define PATH_SEP2 '\\' # define PATH_SEP3 ':' # define MAX_PATH_LEN 128 # define NO_MULTIPLE_DOTS # define MAX_EXT_CHARS 3 # define Z_SUFFIX "z" # define NO_CHOWN # define casemap(c) tolow(c) # define NO_SYMLINK # endif #endif #ifdef MACOS # define PATH_SEP ':' # define DYN_ALLOC # define PROTO # define NO_STDIN_FSTAT # define NO_CHOWN # define NO_UTIME # define chmod(file, mode) (0) # define OPEN(name, flags, mode) open(name, flags) # define SEEKFORWARD(handle, offset) lseek( handle, offset, 1 ) # undef OS_CODE # define OS_CODE 0x07 # ifdef MPW # define isatty(fd) ((fd) <= 2) # endif #endif #ifdef __50SERIES # define PATH_SEP '>' # define STDC_HEADERS # define NO_MEMORY_H # define NO_UTIME_H # define NO_UTIME # define NO_CHOWN # define NO_STDIN_FSTAT # define NO_SIZE_CHECK # define NO_SYMLINK # define RECORD_IO 1 # define casemap(c) tolow(c) # define put_char(c) put_byte((c) & 0x7F) # define get_char(c) ascii2pascii(get_byte()) # undef OS_CODE # define OS_CODE 0x0F # ifdef SIGTERM # undef SIGTERM # endif #endif #if defined(pyr) && !defined(NOMEMCPY) # define NOMEMCPY #endif #ifdef TOPS20 # undef OS_CODE # define OS_CODE 0x0a #endif #ifndef unix # define NO_ST_INO #endif #ifndef OS_CODE # undef OS_CODE # define OS_CODE 0x03 #endif #ifndef PATH_SEP # define PATH_SEP '/' #endif #ifndef casemap # define casemap(c) (c) #endif #ifndef OPTIONS_VAR # define OPTIONS_VAR "GZIP" #endif #ifndef Z_SUFFIX # define Z_SUFFIX ".gz" #endif #ifdef MAX_EXT_CHARS # define MAX_SUFFIX MAX_EXT_CHARS #else # define MAX_SUFFIX 30 #endif #ifndef MIN_PART # define MIN_PART 3 #endif #ifndef EXPAND # define EXPAND(argc,argv) #endif #ifndef RECORD_IO # define RECORD_IO 0 #endif #ifndef SET_BINARY_MODE # define SET_BINARY_MODE(fd) #endif #ifndef OPEN # define OPEN(name, flags, mode) open(name, flags, mode) #endif #ifndef SEEKFORWARD # define SEEKFORWARD(handle, offset) lseek( handle, offset, 1 ) #endif #ifndef get_char # define get_char() get_byte() #endif #ifndef put_char # define put_char(c) put_byte(c) #endif #ifndef O_BINARY #define O_BINARY 0 #endif #define OK 0 #define LZ1_ERROR 1 #define WARNING 2 #define STORED 0 #define COMPRESSED 1 #define PACKED 2 #define LZHED 3 #define DEFLATED 8 #define MAX_METHODS 9 #ifndef O_CREAT #include #ifndef O_CREAT #define O_CREAT FCREAT #endif #ifndef O_EXCL #define O_EXCL FEXCL #endif #endif #ifndef S_IRUSR #define S_IRUSR 0400 #endif #ifndef S_IWUSR #define S_IWUSR 0200 #endif #define RW_USER (S_IRUSR | S_IWUSR) #ifndef MAX_PATH_LEN #define MAX_PATH_LEN 256 #endif #ifndef SEEK_END #define SEEK_END 2 #endif #define PACK_MAGIC "\037\036" #define GZIP_MAGIC "\037\213" #define OLD_GZIP_MAGIC "\037\236" #define LZH_MAGIC "\037\240" #define PKZIP_MAGIC "\120\113\003\004" #define ASCII_FLAG 0x01 #define CONTINUATION 0x02 #define EXTRA_FIELD 0x04 #define ORIG_NAME 0x08 #define COMMENT 0x10 #define ENCRYPTED 0x20 #define RESERVED 0xC0 #define UNKNOWN 0xffff #define BINARY 0 #define ASCII 1 #ifndef WSIZE #define WSIZE 0x8000 #endif #ifndef INBUFSIZ #ifdef SMALL_MEM #define INBUFSIZ 0x2000 #else #define INBUFSIZ 0x8000 #endif #endif #define INBUF_EXTRA 64 #ifndef OUTBUFSIZ #ifdef SMALL_MEM #define OUTBUFSIZ 8192 #else #define OUTBUFSIZ 0x4000 #endif #endif #define OUTBUF_EXTRA 2048 #ifndef DIST_BUFSIZE #ifdef SMALL_MEM #define DIST_BUFSIZE 0x2000 #else #define DIST_BUFSIZE 0x8000 #endif #endif #ifndef BITS #define BITS 16 #endif #define LZW_MAGIC "\037\235" #define MIN_MATCH 3 #define MAX_MATCH 258 #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) #define MAX_DIST (WSIZE-MIN_LOOKAHEAD) #ifdef SMALL_MEM #define HASH_BITS 13 #endif #ifdef MEDIUM_MEM #define HASH_BITS 14 #endif #ifndef HASH_BITS #define HASH_BITS 15 #endif #define HASH_SIZE (unsigned)(1<block_start >= 0L ? (char*)&gz1->window[(unsigned)gz1->block_start] : \ (char*)NULL, (long)gz1->strstart - gz1->block_start, (eof)) #ifdef DYN_ALLOC # define ALLOC(type, array, size) { \ array = (type*)fcalloc((size_t)(((size)+1L)/2), 2*sizeof(type)); \ if (array == NULL) error("insufficient memory"); \ } # define FREE(array) {if (array != NULL) fcfree(array), array=NULL;} #else # define ALLOC(type, array, size) # define FREE(array) #endif #define GZ1_MAX(a,b) (a >= b ? a : b) #define tolow(c) (isupper(c) ? (c)-'A'+'a' : (c)) #define smaller(tree, n, m) \ (tree[n].fc.freq < tree[m].fc.freq || \ (tree[n].fc.freq == tree[m].fc.freq && gz1->depth[n] <= gz1->depth[m])) #define send_code(c, tree) send_bits(gz1,tree[c].fc.code, tree[c].dl.len) #define put_byte(c) {gz1->outbuf[gz1->outcnt++]=(uch)(c); if (gz1->outcnt==OUTBUFSIZ)\ flush_outbuf(gz1);} #define put_short(w) \ { if (gz1->outcnt < OUTBUFSIZ-2) { \ gz1->outbuf[gz1->outcnt++] = (uch) ((w) & 0xff); \ gz1->outbuf[gz1->outcnt++] = (uch) ((ush)(w) >> 8); \ } else { \ put_byte((uch)((w) & 0xff)); \ put_byte((uch)((ush)(w) >> 8)); \ } \ } #define put_long(n) { \ put_short((n) & 0xffff); \ put_short(((ulg)(n)) >> 16); \ } #ifdef CRYPT # define NEXTBYTE() \ (decrypt ? (cc = get_byte(), zdecode(cc), cc) : get_byte()) #else # define NEXTBYTE() (uch)get_byte() #endif #define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<>=(n);k-=(n);} #define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8)) #define LG(p) ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16)) #define put_ubyte(c) {gz1->window[gz1->outcnt++]=(uch)(c); if (gz1->outcnt==WSIZE)\ flush_window(gz1);} #define WARN(msg) { if (gz1->exit_code == OK) gz1->exit_code = WARNING; } #define get_byte() (gz1->inptr < gz1->insize ? gz1->inbuf[gz1->inptr++] : fill_inbuf(gz1,0)) #define try_byte() (gz1->inptr < gz1->insize ? gz1->inbuf[gz1->inptr++] : fill_inbuf(gz1,1)) #define d_code(dist) \ ((dist) < 256 ? gz1->dist_code[dist] : gz1->dist_code[256+((dist)>>7)]) typedef struct config { ush good_length; ush max_lazy; ush nice_length; ush max_chain; } config; config configuration_table[10] = { {0, 0, 0, 0}, {4, 4, 8, 4}, {4, 5, 16, 8}, {4, 6, 32, 32}, {4, 4, 16, 16}, {8, 16, 32, 32}, {8, 16, 128, 128}, {8, 32, 128, 256}, {32, 128, 258, 1024}, {32, 258, 258, 4096}}; typedef struct ct_data { union { ush freq; ush code; } fc; union { ush dad; ush len; } dl; } ct_data; typedef struct tree_desc { ct_data *dyn_tree; ct_data *static_tree; int *extra_bits; int extra_base; int elems; int max_length; int max_code; } tree_desc; struct huft { uch e; uch b; union { ush n; struct huft *t; } v; }; uch bl_order[BL_CODES] = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; int extra_lbits[LENGTH_CODES] = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; int extra_dbits[D_CODES] = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; int extra_blbits[BL_CODES] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; ulg crc_32_tab[] = { 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL }; typedef struct _GZ1 { long versionid1; int state; int done; int deflate1_initialized; unsigned deflate1_hash_head; unsigned deflate1_prev_match; int deflate1_flush; int deflate1_match_available; unsigned deflate1_match_length; char ifname[MAX_PATH_LEN]; char ofname[MAX_PATH_LEN]; struct stat istat; gz1_file_t zfile; int input_ismem; char *input_ptr; long input_bytesleft; int output_ismem; char *output_ptr; uns output_maxlen; int compr_level; long time_stamp; long ifile_size; int ifd; int ofd; int part_nb; int last_member; int save_orig_name; long header_bytes; long bytes_in; long bytes_out; uns insize; uns inptr; uns outcnt; uns ins_h; long block_start; uns good_match; uni max_lazy_match; uni prev_length; uns max_chain_length; uns strstart; uns match_start; int eofile; uns lookahead; ush *file_type; int *file_method; ulg opt_len; ulg static_len; ulg compressed_len; ulg input_len; uns last_flags; uch flags; uns last_lit; uns last_dist; uch flag_bit; int heap_len; int heap_max; ulg bb; uns bk; ush bi_buf; int bi_valid; uns hufts; int decrypt; int ascii; int msg_done; int abortflag; int decompress; int do_lzw; int to_stdout; int force; int verbose; int quiet; int list; int test; int ext_header; int pkzip; int method; int level; int no_time; int no_name; int exit_code; int lbits; int dbits; ulg window_size; ulg crc; uch dist_code[512]; uch length_code[MAX_MATCH-MIN_MATCH+1]; int heap[2*L_CODES+1]; uch depth[2*L_CODES+1]; int base_length[LENGTH_CODES]; int base_dist[D_CODES]; ush bl_count[MAX_BITS+1]; uch flag_buf[(LIT_BUFSIZE/8)]; #ifdef DYN_ALLOC uch *inbuf; uch *outbuf; ush *d_buf; uch *window; #else uch inbuf [INBUFSIZ +INBUF_EXTRA]; uch outbuf[OUTBUFSIZ+OUTBUF_EXTRA]; ush d_buf [DIST_BUFSIZE]; uch window[2L*WSIZE]; #endif #ifdef FULL_SEARCH #define nice_match MAX_MATCH #else int nice_match; #endif #ifdef CRYPT uch cc; #endif ct_data static_ltree[L_CODES+2]; ct_data static_dtree[D_CODES]; ct_data dyn_dtree[(2*D_CODES+1)]; ct_data dyn_ltree[HEAP_SIZE]; ct_data bl_tree[2*BL_CODES+1]; tree_desc l_desc; tree_desc d_desc; tree_desc bl_desc; #ifndef MAXSEG_64K ush prev2[1L<prev2 #define head (gz1->prev2+WSIZE) #else ush * prev2; ush * tab_prefix1; #define prev gz1->prev2 #define head gz1->tab_prefix1 #endif } GZ1; typedef GZ1 *PGZ1; int gz1_size = sizeof( GZ1 ); /* Declare some local function protypes... */ /* Any routine name that can/might conflict with */ /* other modules or object code should simply have */ /* the standard prefix 'gz1_' added to the front. */ /* This will only usually be any kind of problem at all */ /* if the code is being compiled directly into the parent */ /* instead of being built as a standalone DLL or DSO library. */ PGZ1 gz1_init ( void ); int gz1_cleanup ( PGZ1 gz1 ); ulg gz1_deflate ( PGZ1 gz1 ); ulg gz1_deflate_fast( PGZ1 gz1 ); /* The rest of the routines should not need the 'gz1_' prefix. */ /* No conflicts reported at this time. */ int inflate ( PGZ1 gz1 ); int inflate_dynamic( PGZ1 gz1 ); int inflate_stored ( PGZ1 gz1 ); int inflate_fixed ( PGZ1 gz1 ); void fill_window ( PGZ1 gz1 ); void flush_outbuf ( PGZ1 gz1 ); void flush_window ( PGZ1 gz1 ); void bi_windup ( PGZ1 gz1 ); void set_file_type ( PGZ1 gz1 ); void init_block ( PGZ1 gz1 ); int build_bl_tree ( PGZ1 gz1 ); void read_error ( PGZ1 gz1 ); void write_error ( PGZ1 gz1 ); int get_header ( PGZ1 gz1, int in ); int inflate_block ( PGZ1 gz1, int *e ); int fill_inbuf ( PGZ1 gz1, int eof_ok ); char *gz1_basename ( PGZ1 gz1, char *fname ); int longest_match ( PGZ1 gz1, unsigned cur_match ); void bi_init ( PGZ1 gz1, gz1_file_t zipfile ); int file_read ( PGZ1 gz1, char *buf, unsigned size ); void write_buf ( PGZ1 gz1, int fd, voidp buf, unsigned cnt ); void error( char *msg ); int zip( PGZ1 gz1, int in, int out ); ulg flush_block( PGZ1 gz1, char *buf, ulg stored_len, int eof ); void copy_block( PGZ1 gz1, char *buf, unsigned len, int header ); int ct_tally( PGZ1 gz1, int dist, int lc ); void send_bits( PGZ1 gz1, int value, int length ); void send_tree( PGZ1 gz1, ct_data *tree, int max_code ); void send_all_trees( PGZ1 gz1, int lcodes, int dcodes, int blcodes ); void mod_gzip_ct_init( PGZ1 gz1, ush *attr, int *methodp ); void lm_init( PGZ1 gz1, int pack_level, ush *flags ); void build_tree( PGZ1 gz1, tree_desc *desc ); void compress_block( PGZ1 gz1, ct_data *ltree, ct_data *dtree ); void gen_bitlen( PGZ1 gz1, tree_desc *desc ); void pqdownheap( PGZ1 gz1, ct_data *tree, int k ); int huft_build( PGZ1 gz1, unsigned *b, unsigned n, unsigned s, ush *d, ush *e, struct huft **t, int *m ); ulg updcrc( PGZ1 gz1, uch *s, unsigned n ); int inflate_codes( PGZ1 gz1, struct huft *tl, struct huft *td, int bl, int bd ); void gen_codes( PGZ1 gz1, ct_data *tree, int max_code ); void scan_tree( PGZ1 gz1, ct_data *tree, int max_code ); unsigned bi_reverse( PGZ1 gz1, unsigned code, int len ); int huft_free( PGZ1 gz1, struct huft *t ); PGZ1 gz1_init() { PGZ1 gz1=0; gz1 = (PGZ1) malloc( gz1_size ); if ( !gz1 ) { return 0; } memset( gz1, 0, gz1_size ); ALLOC(uch, gz1->inbuf, INBUFSIZ +INBUF_EXTRA); if ( !gz1->inbuf ) { free( gz1 ); return 0; } ALLOC(uch, gz1->outbuf, OUTBUFSIZ+OUTBUF_EXTRA); if ( !gz1->outbuf ) { FREE( gz1->inbuf ); free( gz1 ); return 0; } ALLOC(ush, gz1->d_buf, DIST_BUFSIZE); if ( !gz1->d_buf ) { FREE( gz1->outbuf ); FREE( gz1->inbuf ); free( gz1 ); return 0; } ALLOC(uch, gz1->window, 2L*WSIZE); if ( !gz1->window ) { FREE( gz1->d_buf ); FREE( gz1->outbuf ); FREE( gz1->inbuf ); free( gz1 ); return 0; } #ifndef MAXSEG_64K #else ALLOC(ush, gz1->prev2, 1L<<(BITS-1) ); if ( !gz1->prev2 ) { FREE( gz1->window ); FREE( gz1->d_buf ); FREE( gz1->outbuf ); FREE( gz1->inbuf ); free( gz1 ); return 0; } ALLOC(ush, gz1->tab_prefix1, 1L<<(BITS-1) ); if ( !gz1->tab_prefix1 ) { FREE( gz1->prev2 ); FREE( gz1->window ); FREE( gz1->d_buf ); FREE( gz1->outbuf ); FREE( gz1->inbuf ); free( gz1 ); return 0; } #endif gz1->method = DEFLATED; gz1->level = 6; gz1->no_time = -1; gz1->no_name = -1; gz1->exit_code = OK; gz1->lbits = 9; gz1->dbits = 6; gz1->window_size = (ulg)2*WSIZE; gz1->crc = (ulg)0xffffffffL; gz1->d_desc.dyn_tree = (ct_data *) gz1->dyn_dtree; gz1->d_desc.static_tree = (ct_data *) gz1->static_dtree; gz1->d_desc.extra_bits = (int *) extra_dbits; gz1->d_desc.extra_base = (int ) 0; gz1->d_desc.elems = (int ) D_CODES; gz1->d_desc.max_length = (int ) MAX_BITS; gz1->d_desc.max_code = (int ) 0; gz1->l_desc.dyn_tree = (ct_data *) gz1->dyn_ltree; gz1->l_desc.static_tree = (ct_data *) gz1->static_ltree; gz1->l_desc.extra_bits = (int *) extra_lbits; gz1->l_desc.extra_base = (int ) LITERALS+1; gz1->l_desc.elems = (int ) L_CODES; gz1->l_desc.max_length = (int ) MAX_BITS; gz1->l_desc.max_code = (int ) 0; gz1->bl_desc.dyn_tree = (ct_data *) gz1->bl_tree; gz1->bl_desc.static_tree = (ct_data *) 0; gz1->bl_desc.extra_bits = (int *) extra_blbits; gz1->bl_desc.extra_base = (int ) 0; gz1->bl_desc.elems = (int ) BL_CODES; gz1->bl_desc.max_length = (int ) MAX_BL_BITS; gz1->bl_desc.max_code = (int ) 0; return (PGZ1) gz1; } int gz1_cleanup( PGZ1 gz1 ) { #ifndef MAXSEG_64K #else FREE( gz1->tab_prefix1 ); FREE( gz1->prev2 ); #endif FREE( gz1->window ); FREE( gz1->d_buf ); FREE( gz1->outbuf ); FREE( gz1->inbuf ); free( gz1 ); gz1 = 0; return 0; } int (*read_buf)(PGZ1 gz1, char *buf, unsigned size); void error( char *msg ) { msg = msg; } int (*work)( PGZ1 gz1, int infile, int outfile ) = 0; #ifdef __BORLANDC__ #pragma argsused #endif int get_header( PGZ1 gz1, int in ) { uch flags; char magic[2]; ulg stamp; unsigned len; unsigned part; if ( gz1->force && gz1->to_stdout ) { magic[0] = (char)try_byte(); magic[1] = (char)try_byte(); } else { magic[0] = (char)get_byte(); magic[1] = (char)get_byte(); } gz1->method = -1; gz1->header_bytes = 0; gz1->last_member = RECORD_IO; gz1->part_nb++; if ( memcmp(magic, GZIP_MAGIC, 2 ) == 0 || memcmp(magic, OLD_GZIP_MAGIC, 2 ) == 0 ) { gz1->method = (int)get_byte(); if ( gz1->method != DEFLATED ) { gz1->exit_code = LZ1_ERROR; return -1; } return -1; if ((flags & ENCRYPTED) != 0) { gz1->exit_code = LZ1_ERROR; return -1; } if ((flags & CONTINUATION) != 0) { gz1->exit_code = LZ1_ERROR; if ( gz1->force <= 1) return -1; } if ((flags & RESERVED) != 0) { gz1->exit_code = LZ1_ERROR; if ( gz1->force <= 1) return -1; } stamp = (ulg)get_byte(); stamp |= ((ulg)get_byte()) << 8; stamp |= ((ulg)get_byte()) << 16; stamp |= ((ulg)get_byte()) << 24; if ( stamp != 0 && !gz1->no_time ) { gz1->time_stamp = stamp; } (void)get_byte(); (void)get_byte(); if ((flags & CONTINUATION) != 0) { part = (unsigned) get_byte(); part |= ((unsigned) get_byte())<<8; } if ((flags & EXTRA_FIELD) != 0) { len = (unsigned) get_byte(); len |= ((unsigned) get_byte())<<8; while (len--) (void)get_byte(); } if ((flags & COMMENT) != 0) { while (get_char() != 0) ; } if ( gz1->part_nb == 1 ) { gz1->header_bytes = gz1->inptr + 2*sizeof(long); } } return gz1->method; } int fill_inbuf( PGZ1 gz1, int eof_ok ) { int len; int bytes_to_copy; gz1->insize = 0; errno = 0; do { if ( gz1->input_ismem ) { if ( gz1->input_bytesleft > 0 ) { bytes_to_copy = INBUFSIZ - gz1->insize; if ( bytes_to_copy > gz1->input_bytesleft ) { bytes_to_copy = gz1->input_bytesleft; } memcpy( (char*)gz1->inbuf+gz1->insize, gz1->input_ptr, bytes_to_copy ); gz1->input_ptr += bytes_to_copy; gz1->input_bytesleft -= bytes_to_copy; len = bytes_to_copy; } else { len = 0; } } else { len = read( gz1->ifd, (char*)gz1->inbuf+gz1->insize, INBUFSIZ-gz1->insize ); } if (len == 0 || len == EOF) break; gz1->insize += len; } while( gz1->insize < INBUFSIZ ); if ( gz1->insize == 0 ) { if( eof_ok ) return EOF; read_error( gz1 ); } gz1->bytes_in += (ulg) gz1->insize; gz1->inptr = 1; return gz1->inbuf[0]; } ulg updcrc( PGZ1 gz1, uch *s, unsigned n ) { register ulg c; if ( s == NULL ) { c = 0xffffffffL; } else { c = gz1->crc; if ( n ) { do{ c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8); } while( --n ); } } gz1->crc = c; return( c ^ 0xffffffffL ); } void read_error( PGZ1 gz1 ) { gz1->abortflag = 1; } void mod_gzip_strlwr( char *s ) { char *p1=s; if ( s == 0 ) return; while ( *p1 != 0 ) { if ( *p1 > 96 ) *p1 = *p1 - 32; p1++; } } #ifdef __BORLANDC__ #pragma argsused #endif char *gz1_basename( PGZ1 gz1, char *fname ) { char *p; if ((p = strrchr(fname, PATH_SEP)) != NULL) fname = p+1; #ifdef PATH_SEP2 if ((p = strrchr(fname, PATH_SEP2)) != NULL) fname = p+1; #endif #ifdef PATH_SEP3 if ((p = strrchr(fname, PATH_SEP3)) != NULL) fname = p+1; #endif #ifdef SUFFIX_SEP if ((p = strrchr(fname, SUFFIX_SEP)) != NULL) *p = '\0'; #endif if (casemap('A') == 'a') mod_gzip_strlwr(fname); return fname; } void write_buf( PGZ1 gz1, int fd, voidp buf, unsigned cnt ) { unsigned n; if ( gz1->output_ismem ) { if ( ( gz1->bytes_out + cnt ) < gz1->output_maxlen ) { memcpy( gz1->output_ptr, buf, cnt ); gz1->output_ptr += cnt; } else { write_error( gz1 ); } } else { while ((n = write(fd, buf, cnt)) != cnt) { if (n == (unsigned)(-1)) { write_error( gz1 ); } cnt -= n; buf = (voidp)((char*)buf+n); } } } void write_error( PGZ1 gz1 ) { gz1->abortflag = 1; } #ifdef __TURBOC__ #ifndef BC55 static ush ptr_offset = 0; void * fcalloc( unsigned items, unsigned size ) { void * buf = farmalloc((ulg)items*size + 16L); if (buf == NULL) return NULL; if (ptr_offset == 0) { ptr_offset = (ush)((uch*)buf-0); } else if (ptr_offset != (ush)((uch*)buf-0)) { error("inconsistent ptr_offset"); } *((ush*)&buf+1) += (ptr_offset + 15) >> 4; *(ush*)&buf = 0; return buf; } void fcfree( void *ptr ) { *((ush*)&ptr+1) -= (ptr_offset + 15) >> 4; *(ush*)&ptr = ptr_offset; farfree(ptr); } #endif #endif int zip( PGZ1 gz1, int in, int out ) { uch flags = 0; ush attr = 0; ush deflate_flags = 0; gz1->ifd = in; gz1->ofd = out; gz1->outcnt = 0; gz1->method = DEFLATED; put_byte(GZIP_MAGIC[0]); put_byte(GZIP_MAGIC[1]); put_byte(DEFLATED); if ( gz1->save_orig_name ) { flags |= ORIG_NAME; } put_byte(flags); put_long(gz1->time_stamp); gz1->crc = -1; updcrc( gz1, NULL, 0 ); bi_init( gz1, out ); mod_gzip_ct_init( gz1, &attr, &gz1->method ); lm_init( gz1, gz1->level, &deflate_flags ); put_byte((uch)deflate_flags); put_byte(OS_CODE); if ( gz1->save_orig_name ) { char *p = gz1_basename( gz1, gz1->ifname ); do { put_char(*p); } while (*p++); } gz1->header_bytes = (long)gz1->outcnt; (void) gz1_deflate( gz1 ); put_long( gz1->crc ); put_long( gz1->bytes_in ); gz1->header_bytes += 2*sizeof(long); flush_outbuf( gz1 ); return OK; } ulg gz1_deflate( PGZ1 gz1 ) { unsigned hash_head; unsigned prev_match; int flush; int match_available = 0; register unsigned match_length = MIN_MATCH-1; #ifdef DEBUG long isize; #endif if (gz1->compr_level <= 3) { return gz1_deflate_fast(gz1); } while (gz1->lookahead != 0) { gz1->ins_h = (((gz1->ins_h)<window[gz1->strstart+MIN_MATCH-1])) & HASH_MASK; prev[ gz1->strstart & WMASK ] = hash_head = head[ gz1->ins_h ]; head[ gz1->ins_h ] = gz1->strstart; gz1->prev_length = match_length, prev_match = gz1->match_start; match_length = MIN_MATCH-1; if (hash_head != NIL && gz1->prev_length < gz1->max_lazy_match && gz1->strstart - hash_head <= MAX_DIST) { match_length = longest_match( gz1, hash_head ); if (match_length > gz1->lookahead) match_length = gz1->lookahead; if (match_length == MIN_MATCH && gz1->strstart-gz1->match_start > TOO_FAR){ match_length--; } } if (gz1->prev_length >= MIN_MATCH && match_length <= gz1->prev_length) { flush = ct_tally(gz1,gz1->strstart-1-prev_match, gz1->prev_length - MIN_MATCH); gz1->lookahead -= ( gz1->prev_length - 1 ); gz1->prev_length -= 2; do { gz1->strstart++; gz1->ins_h = (((gz1->ins_h)<window[ gz1->strstart + MIN_MATCH-1])) & HASH_MASK; prev[ gz1->strstart & WMASK ] = hash_head = head[gz1->ins_h]; head[ gz1->ins_h ] = gz1->strstart; } while (--gz1->prev_length != 0); match_available = 0; match_length = MIN_MATCH-1; gz1->strstart++; if (flush) FLUSH_BLOCK(0), gz1->block_start = gz1->strstart; } else if (match_available) { if (ct_tally( gz1, 0, gz1->window[gz1->strstart-1] )) { FLUSH_BLOCK(0), gz1->block_start = gz1->strstart; } gz1->strstart++; gz1->lookahead--; } else { match_available = 1; gz1->strstart++; gz1->lookahead--; } while (gz1->lookahead < MIN_LOOKAHEAD && !gz1->eofile) fill_window(gz1); } if (match_available) ct_tally( gz1, 0, gz1->window[gz1->strstart-1] ); return FLUSH_BLOCK(1); return 0; } void flush_outbuf( PGZ1 gz1 ) { if ( gz1->outcnt == 0 ) { return; } write_buf( gz1, gz1->ofd, (char *)gz1->outbuf, gz1->outcnt ); gz1->bytes_out += (ulg)gz1->outcnt; gz1->outcnt = 0; } void lm_init( PGZ1 gz1, int pack_level, ush *flags ) { register unsigned j; if ( pack_level < 1 || pack_level > 9 ) { error("bad pack level"); } gz1->compr_level = pack_level; #if defined(MAXSEG_64K) && HASH_BITS == 15 for (j = 0; j < HASH_SIZE; j++) head[j] = NIL; #else memset( (char*)head, 0, (HASH_SIZE*sizeof(*head)) ); #endif gz1->max_lazy_match = configuration_table[pack_level].max_lazy; gz1->good_match = configuration_table[pack_level].good_length; #ifndef FULL_SEARCH gz1->nice_match = configuration_table[pack_level].nice_length; #endif gz1->max_chain_length = configuration_table[pack_level].max_chain; if ( pack_level == 1 ) { *flags |= FAST; } else if ( pack_level == 9 ) { *flags |= SLOW; } gz1->strstart = 0; gz1->block_start = 0L; #ifdef ASMV match_init(); #endif gz1->lookahead = read_buf(gz1,(char*)gz1->window, sizeof(int) <= 2 ? (unsigned)WSIZE : 2*WSIZE); if (gz1->lookahead == 0 || gz1->lookahead == (unsigned)EOF) { gz1->eofile = 1, gz1->lookahead = 0; return; } gz1->eofile = 0; while (gz1->lookahead < MIN_LOOKAHEAD && !gz1->eofile) { fill_window(gz1); } gz1->ins_h = 0; for ( j=0; jins_h = (((gz1->ins_h)<window[j])) & HASH_MASK; } } void fill_window( PGZ1 gz1 ) { register unsigned n, m; unsigned more = (unsigned)( gz1->window_size - (ulg)gz1->lookahead - (ulg)gz1->strstart ); if ( more == (unsigned)EOF) { more--; } else if ( gz1->strstart >= WSIZE+MAX_DIST ) { memcpy((char*)gz1->window, (char*)gz1->window+WSIZE, (unsigned)WSIZE); gz1->match_start -= WSIZE; gz1->strstart -= WSIZE; gz1->block_start -= (long) WSIZE; for ( n = 0; n < HASH_SIZE; n++ ) { m = head[n]; head[n] = (ush)(m >= WSIZE ? m-WSIZE : NIL); } for ( n = 0; n < WSIZE; n++ ) { m = prev[n]; prev[n] = (ush)(m >= WSIZE ? m-WSIZE : NIL); } more += WSIZE; } if ( !gz1->eofile ) { n = read_buf(gz1,(char*)gz1->window+gz1->strstart+gz1->lookahead, more); if ( n == 0 || n == (unsigned)EOF ) { gz1->eofile = 1; } else { gz1->lookahead += n; } } } ulg gz1_deflate_fast( PGZ1 gz1 ) { unsigned hash_head; int flush; unsigned match_length = 0; gz1->prev_length = MIN_MATCH-1; while (gz1->lookahead != 0) { gz1->ins_h = (((gz1->ins_h)<window[ gz1->strstart + MIN_MATCH-1])) & HASH_MASK; prev[ gz1->strstart & WMASK ] = hash_head = head[ gz1->ins_h ]; head[ gz1->ins_h ] = gz1->strstart; if (hash_head != NIL && gz1->strstart - hash_head <= MAX_DIST) { match_length = longest_match( gz1, hash_head ); if (match_length > gz1->lookahead) match_length = gz1->lookahead; } if (match_length >= MIN_MATCH) { flush = ct_tally(gz1,gz1->strstart-gz1->match_start, match_length - MIN_MATCH); gz1->lookahead -= match_length; if (match_length <= gz1->max_lazy_match ) { match_length--; do { gz1->strstart++; gz1->ins_h = (((gz1->ins_h)<window[ gz1->strstart + MIN_MATCH-1])) & HASH_MASK; prev[ gz1->strstart & WMASK ] = hash_head = head[ gz1->ins_h ]; head[ gz1->ins_h ] = gz1->strstart; } while (--match_length != 0); gz1->strstart++; } else { gz1->strstart += match_length; match_length = 0; gz1->ins_h = gz1->window[gz1->strstart]; gz1->ins_h = (((gz1->ins_h)<window[gz1->strstart+1])) & HASH_MASK; #if MIN_MATCH != 3 Call UPDATE_HASH() MIN_MATCH-3 more times #endif } } else { flush = ct_tally(gz1, 0, gz1->window[gz1->strstart]); gz1->lookahead--; gz1->strstart++; } if (flush) FLUSH_BLOCK(0), gz1->block_start = gz1->strstart; while (gz1->lookahead < MIN_LOOKAHEAD && !gz1->eofile) fill_window(gz1); } return FLUSH_BLOCK(1); } void mod_gzip_ct_init( PGZ1 gz1, ush *attr, int *methodp ) { #ifdef DD1 int i,ii; #endif int n; int bits; int length; int code; int dist; gz1->file_type = attr; gz1->file_method = methodp; gz1->compressed_len = gz1->input_len = 0L; if ( gz1->static_dtree[0].dl.len != 0 ) { return; } length = 0; for ( code = 0; code < LENGTH_CODES-1; code++ ) { gz1->base_length[code] = length; for ( n = 0; n < (1<length_code[length++] = (uch)code; } } gz1->length_code[length-1] = (uch)code; dist = 0; for ( code = 0 ; code < 16; code++ ) { gz1->base_dist[code] = dist; for ( n = 0; n < (1<dist_code[dist++] = (uch)code; } } dist >>= 7; for ( ; code < D_CODES; code++ ) { gz1->base_dist[code] = dist << 7; for ( n = 0; n < (1<<(extra_dbits[code]-7)); n++ ) { gz1->dist_code[256 + dist++] = (uch)code; } } for ( bits = 0; bits <= MAX_BITS; bits++ ) { gz1->bl_count[bits] = 0; } n = 0; while (n <= 143) gz1->static_ltree[n++].dl.len = 8, gz1->bl_count[8]++; while (n <= 255) gz1->static_ltree[n++].dl.len = 9, gz1->bl_count[9]++; while (n <= 279) gz1->static_ltree[n++].dl.len = 7, gz1->bl_count[7]++; while (n <= 287) gz1->static_ltree[n++].dl.len = 8, gz1->bl_count[8]++; gen_codes(gz1,(ct_data *)gz1->static_ltree, L_CODES+1); for ( n = 0; n < D_CODES; n++ ) { gz1->static_dtree[n].dl.len = 5; gz1->static_dtree[n].fc.code = bi_reverse( gz1, n, 5 ); } init_block( gz1 ); } ulg flush_block( PGZ1 gz1, char *buf, ulg stored_len, int eof ) { ulg opt_lenb; ulg static_lenb; int max_blindex; gz1->flag_buf[gz1->last_flags] = gz1->flags; if (*gz1->file_type == (ush)UNKNOWN) set_file_type(gz1); build_tree( gz1, (tree_desc *)(&gz1->l_desc) ); build_tree( gz1, (tree_desc *)(&gz1->d_desc) ); max_blindex = build_bl_tree( gz1 ); opt_lenb = (gz1->opt_len+3+7)>>3; static_lenb = (gz1->static_len+3+7)>>3; gz1->input_len += stored_len; if (static_lenb <= opt_lenb) opt_lenb = static_lenb; #ifdef FORCE_METHOD if ( level == 1 && eof && gz1->compressed_len == 0L ) #else if (stored_len <= opt_lenb && eof && gz1->compressed_len == 0L && 0 ) #endif { if (buf == (char*)0) error ("block vanished"); copy_block( gz1, buf, (unsigned)stored_len, 0 ); gz1->compressed_len = stored_len << 3; *gz1->file_method = STORED; #ifdef FORCE_METHOD } else if (level == 2 && buf != (char*)0) { #else } else if (stored_len+4 <= opt_lenb && buf != (char*)0) { #endif send_bits(gz1,(STORED_BLOCK<<1)+eof, 3); gz1->compressed_len = (gz1->compressed_len + 3 + 7) & ~7L; gz1->compressed_len += (stored_len + 4) << 3; copy_block(gz1, buf, (unsigned)stored_len, 1); #ifdef FORCE_METHOD } else if (level == 3) { #else } else if (static_lenb == opt_lenb) { #endif send_bits(gz1,(STATIC_TREES<<1)+eof, 3); compress_block( gz1, (ct_data *)gz1->static_ltree, (ct_data *)gz1->static_dtree ); gz1->compressed_len += 3 + gz1->static_len; } else { send_bits(gz1,(DYN_TREES<<1)+eof, 3); send_all_trees( gz1, gz1->l_desc.max_code+1, gz1->d_desc.max_code+1, max_blindex+1 ); compress_block( gz1, (ct_data *)gz1->dyn_ltree, (ct_data *)gz1->dyn_dtree ); gz1->compressed_len += 3 + gz1->opt_len; } init_block( gz1 ); if ( eof ) { bi_windup( gz1 ); gz1->compressed_len += 7; } return gz1->compressed_len >> 3; } #ifdef __BORLANDC__ #pragma argsused #endif unsigned bi_reverse( PGZ1 gz1, unsigned code, int len ) { register unsigned res = 0; do { res |= code & 1; code >>= 1, res <<= 1; } while (--len > 0); return res >> 1; } void set_file_type( PGZ1 gz1 ) { int n = 0; unsigned ascii_freq = 0; unsigned bin_freq = 0; while (n < 7) bin_freq += gz1->dyn_ltree[n++].fc.freq; while (n < 128) ascii_freq += gz1->dyn_ltree[n++].fc.freq; while (n < LITERALS) bin_freq += gz1->dyn_ltree[n++].fc.freq; *gz1->file_type = bin_freq > (ascii_freq >> 2) ? BINARY : ASCII; } void init_block( PGZ1 gz1 ) { int n; for (n = 0; n < L_CODES; n++) gz1->dyn_ltree[n].fc.freq = 0; for (n = 0; n < D_CODES; n++) gz1->dyn_dtree[n].fc.freq = 0; for (n = 0; n < BL_CODES; n++) gz1->bl_tree[n].fc.freq = 0; gz1->dyn_ltree[END_BLOCK].fc.freq = 1; gz1->opt_len = 0L; gz1->static_len = 0L; gz1->last_lit = 0; gz1->last_dist = 0; gz1->last_flags = 0; gz1->flags = 0; gz1->flag_bit = 1; } void bi_init( PGZ1 gz1, gz1_file_t zipfile ) { gz1->zfile = zipfile; gz1->bi_buf = 0; gz1->bi_valid = 0; if ( gz1->zfile != NO_FILE ) { read_buf = file_read; } } int ct_tally( PGZ1 gz1, int dist, int lc ) { int dcode; gz1->inbuf[gz1->last_lit++] = (uch)lc; if ( dist == 0 ) { gz1->dyn_ltree[lc].fc.freq++; } else { dist--; gz1->dyn_ltree[gz1->length_code[lc]+LITERALS+1].fc.freq++; gz1->dyn_dtree[d_code(dist)].fc.freq++; gz1->d_buf[gz1->last_dist++] = (ush)dist; gz1->flags |= gz1->flag_bit; } gz1->flag_bit <<= 1; if ( (gz1->last_lit & 7) == 0 ) { gz1->flag_buf[gz1->last_flags++] = gz1->flags; gz1->flags = 0, gz1->flag_bit = 1; } if ( gz1->level > 2 && (gz1->last_lit & 0xfff) == 0) { ulg out_length = (ulg) ( gz1->last_lit * 8L ); ulg in_length = (ulg) ( gz1->strstart - gz1->block_start ); for ( dcode = 0; dcode < D_CODES; dcode++ ) { out_length += (ulg) ((gz1->dyn_dtree[dcode].fc.freq)*(5L+extra_dbits[dcode])); } out_length >>= 3; if ( gz1->last_dist < gz1->last_lit/2 && out_length < in_length/2 ) { return 1; } } return( gz1->last_lit == LIT_BUFSIZE-1 || gz1->last_dist == DIST_BUFSIZE ); } void compress_block( PGZ1 gz1, ct_data *ltree, ct_data *dtree ) { unsigned dist; int lc; unsigned lx = 0; unsigned dx = 0; unsigned fx = 0; uch flag = 0; unsigned code; int extra; if (gz1->last_lit != 0) do { if ((lx & 7) == 0) flag = gz1->flag_buf[fx++]; lc = gz1->inbuf[lx++]; if ((flag & 1) == 0) { send_code(lc, ltree); } else { code = gz1->length_code[lc]; send_code(code+LITERALS+1, ltree); extra = extra_lbits[code]; if (extra != 0) { lc -= gz1->base_length[code]; send_bits(gz1,lc, extra); } dist = gz1->d_buf[dx++]; code = d_code(dist); send_code(code, dtree); extra = extra_dbits[code]; if (extra != 0) { dist -= gz1->base_dist[code]; send_bits(gz1,dist, extra); } } flag >>= 1; } while (lx < gz1->last_lit); send_code(END_BLOCK, ltree); } #ifndef ASMV int longest_match( PGZ1 gz1, unsigned cur_match ) { unsigned chain_length = gz1->max_chain_length; register uch *scan = gz1->window + gz1->strstart; register uch *match; register int len; int best_len = gz1->prev_length; unsigned limit = gz1->strstart > (unsigned)MAX_DIST ? gz1->strstart - (unsigned)MAX_DIST : NIL; #if HASH_BITS < 8 || MAX_MATCH != 258 error: Code too clever #endif #ifdef UNALIGNED_OK register uch *strend = gz1->window + gz1->strstart + MAX_MATCH - 1; register ush scan_start = *(ush*)scan; register ush scan_end = *(ush*)(scan+best_len-1); #else register uch *strend = gz1->window + gz1->strstart + MAX_MATCH; register uch scan_end1 = scan[best_len-1]; register uch scan_end = scan[best_len]; #endif if (gz1->prev_length >= gz1->good_match) { chain_length >>= 2; } do { match = gz1->window + cur_match; #if (defined(UNALIGNED_OK) && MAX_MATCH == 258) if (*(ush*)(match+best_len-1) != scan_end || *(ush*)match != scan_start) continue; scan++, match++; do { } while (*(ush*)(scan+=2) == *(ush*)(match+=2) && *(ush*)(scan+=2) == *(ush*)(match+=2) && *(ush*)(scan+=2) == *(ush*)(match+=2) && *(ush*)(scan+=2) == *(ush*)(match+=2) && scan < strend); if (*scan == *match) scan++; len = (MAX_MATCH - 1) - (int)(strend-scan); scan = strend - (MAX_MATCH-1); #else if (match[best_len] != scan_end || match[best_len-1] != scan_end1 || *match != *scan || *++match != scan[1]) continue; scan += 2, match++; do { } while (*++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && scan < strend); len = MAX_MATCH - (int)(strend - scan); scan = strend - MAX_MATCH; #endif if (len > best_len) { gz1->match_start = cur_match; best_len = len; if (len >= gz1->nice_match) break; #ifdef UNALIGNED_OK scan_end = *(ush*)(scan+best_len-1); #else scan_end1 = scan[best_len-1]; scan_end = scan[best_len]; #endif } } while ((cur_match = prev[cur_match & WMASK]) > limit && --chain_length != 0); return best_len; } #endif void send_bits( PGZ1 gz1, int value, int length ) { if ( gz1->bi_valid > (int) BUFSIZE - length ) { gz1->bi_buf |= (value << gz1->bi_valid); put_short(gz1->bi_buf); gz1->bi_buf = (ush)value >> (BUFSIZE - gz1->bi_valid); gz1->bi_valid += length - BUFSIZE; } else { gz1->bi_buf |= value << gz1->bi_valid; gz1->bi_valid += length; } } void build_tree( PGZ1 gz1, tree_desc *desc ) { int elems = desc->elems; ct_data *tree = desc->dyn_tree; ct_data *stree = desc->static_tree; int n; int m; int max_code = -1; int node = elems; int new1; gz1->heap_len = 0, gz1->heap_max = HEAP_SIZE; for (n = 0; n < elems; n++) { if (tree[n].fc.freq != 0) { gz1->heap[++gz1->heap_len] = max_code = n; gz1->depth[n] = 0; } else { tree[n].dl.len = 0; } } while (gz1->heap_len < 2) { new1 = gz1->heap[++gz1->heap_len] = (max_code < 2 ? ++max_code : 0); tree[new1].fc.freq = 1; gz1->depth[new1] = 0; gz1->opt_len--; if (stree) gz1->static_len -= stree[new1].dl.len; } desc->max_code = max_code; for (n = gz1->heap_len/2; n >= 1; n--) pqdownheap(gz1, tree, n); do { n = gz1->heap[SMALLEST]; gz1->heap[SMALLEST] = gz1->heap[gz1->heap_len--]; pqdownheap(gz1, tree, SMALLEST); m = gz1->heap[SMALLEST]; gz1->heap[--gz1->heap_max] = n; gz1->heap[--gz1->heap_max] = m; tree[node].fc.freq = tree[n].fc.freq + tree[m].fc.freq; gz1->depth[node] = (uch) (GZ1_MAX(gz1->depth[n], gz1->depth[m]) + 1); tree[n].dl.dad = tree[m].dl.dad = (ush)node; gz1->heap[SMALLEST] = node++; pqdownheap(gz1, tree, SMALLEST); } while (gz1->heap_len >= 2); gz1->heap[--gz1->heap_max] = gz1->heap[SMALLEST]; gen_bitlen(gz1,(tree_desc *)desc); gen_codes(gz1,(ct_data *)tree, max_code); } int build_bl_tree( PGZ1 gz1 ) { int max_blindex; scan_tree( gz1, (ct_data *)gz1->dyn_ltree, gz1->l_desc.max_code ); scan_tree( gz1, (ct_data *)gz1->dyn_dtree, gz1->d_desc.max_code ); build_tree( gz1, (tree_desc *)(&gz1->bl_desc) ); for ( max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex-- ) { if (gz1->bl_tree[bl_order[max_blindex]].dl.len != 0) break; } gz1->opt_len += 3*(max_blindex+1) + 5+5+4; return max_blindex; } void gen_codes( PGZ1 gz1, ct_data *tree, int max_code ) { ush next_code[MAX_BITS+1]; ush code = 0; int bits; int n; for ( bits = 1; bits <= MAX_BITS; bits++ ) { next_code[bits] = code = (code + gz1->bl_count[bits-1]) << 1; } for ( n = 0; n <= max_code; n++ ) { int len = tree[n].dl.len; if (len == 0) continue; tree[n].fc.code = bi_reverse( gz1, next_code[len]++, len ); } return; } void gen_bitlen( PGZ1 gz1, tree_desc *desc ) { ct_data *tree = desc->dyn_tree; int *extra = desc->extra_bits; int base = desc->extra_base; int max_code = desc->max_code; int max_length = desc->max_length; ct_data *stree = desc->static_tree; int h; int n, m; int bits; int xbits; ush f; int overflow = 0; for (bits = 0; bits <= MAX_BITS; bits++) gz1->bl_count[bits] = 0; tree[gz1->heap[gz1->heap_max]].dl.len = 0; for (h = gz1->heap_max+1; h < HEAP_SIZE; h++) { n = gz1->heap[h]; bits = tree[tree[n].dl.dad].dl.len + 1; if (bits > max_length) bits = max_length, overflow++; tree[n].dl.len = (ush)bits; if (n > max_code) continue; gz1->bl_count[bits]++; xbits = 0; if (n >= base) xbits = extra[n-base]; f = tree[n].fc.freq; gz1->opt_len += (ulg)f * (bits + xbits); if (stree) gz1->static_len += (ulg)f * (stree[n].dl.len + xbits); } if (overflow == 0) return; do { bits = max_length-1; while (gz1->bl_count[bits] == 0) bits--; gz1->bl_count[bits]--; gz1->bl_count[bits+1] += 2; gz1->bl_count[max_length]--; overflow -= 2; } while (overflow > 0); for (bits = max_length; bits != 0; bits--) { n = gz1->bl_count[bits]; while (n != 0) { m = gz1->heap[--h]; if (m > max_code) continue; if (tree[m].dl.len != (unsigned) bits) { gz1->opt_len += ((long)bits-(long)tree[m].dl.len)*(long)tree[m].fc.freq; tree[m].dl.len = (ush)bits; } n--; } } } void copy_block( PGZ1 gz1, char *buf, unsigned len, int header ) { #ifdef CRYPT int t; #endif bi_windup( gz1 ); if ( header ) { put_short((ush)len); put_short((ush)~len); } while( len-- ) { #ifdef CRYPT if (key) zencode(*buf, t); #endif put_byte(*buf++); } } int file_read( PGZ1 gz1, char *buf, unsigned size ) { unsigned len = 0; unsigned bytes_to_copy = 0; if ( gz1->input_ismem ) { if ( gz1->input_bytesleft > 0 ) { bytes_to_copy = size; if ( bytes_to_copy > (unsigned) gz1->input_bytesleft ) { bytes_to_copy = (unsigned) gz1->input_bytesleft; } memcpy( buf, gz1->input_ptr, bytes_to_copy ); gz1->input_ptr += bytes_to_copy; gz1->input_bytesleft -= bytes_to_copy; len = bytes_to_copy; } else { len = 0; } } else { len = read( gz1->ifd, buf, size ); } if ( len == (unsigned)(-1) || len == 0 ) { gz1->crc = gz1->crc ^ 0xffffffffL; return (int)len; } updcrc( gz1, (uch*)buf, len ); gz1->bytes_in += (ulg)len; return (int)len; } void bi_windup( PGZ1 gz1 ) { if ( gz1->bi_valid > 8 ) { put_short(gz1->bi_buf); } else if ( gz1->bi_valid > 0 ) { put_byte(gz1->bi_buf); } gz1->bi_buf = 0; gz1->bi_valid = 0; } void send_all_trees( PGZ1 gz1, int lcodes, int dcodes, int blcodes ) { int rank; send_bits(gz1,lcodes-257, 5); send_bits(gz1,dcodes-1, 5); send_bits(gz1,blcodes-4, 4); for ( rank = 0; rank < blcodes; rank++ ) { send_bits(gz1,gz1->bl_tree[bl_order[rank]].dl.len, 3 ); } send_tree(gz1,(ct_data *)gz1->dyn_ltree, lcodes-1); send_tree(gz1,(ct_data *)gz1->dyn_dtree, dcodes-1); } void send_tree( PGZ1 gz1, ct_data *tree, int max_code ) { int n; int prevlen = -1; int curlen; int nextlen = tree[0].dl.len; int count = 0; int max_count = 7; int min_count = 4; if (nextlen == 0) max_count = 138, min_count = 3; for ( n = 0; n <= max_code; n++ ) { curlen = nextlen; nextlen = tree[n+1].dl.len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { do { send_code(curlen, gz1->bl_tree); } while (--count != 0); } else if (curlen != 0) { if ( curlen != prevlen ) { send_code(curlen, gz1->bl_tree); count--; } send_code( REP_3_6, gz1->bl_tree ); send_bits(gz1,count-3, 2); } else if (count <= 10) { send_code(REPZ_3_10, gz1->bl_tree); send_bits(gz1,count-3, 3); } else { send_code(REPZ_11_138, gz1->bl_tree); send_bits(gz1,count-11, 7); } count = 0; prevlen = curlen; if (nextlen == 0) { max_count = 138, min_count = 3; } else if (curlen == nextlen) { max_count = 6, min_count = 3; } else { max_count = 7, min_count = 4; } } } void scan_tree( PGZ1 gz1, ct_data *tree, int max_code ) { int n; int prevlen = -1; int curlen; int nextlen = tree[0].dl.len; int count = 0; int max_count = 7; int min_count = 4; if (nextlen == 0) max_count = 138, min_count = 3; tree[max_code+1].dl.len = (ush)0xffff; for ( n = 0; n <= max_code; n++ ) { curlen = nextlen; nextlen = tree[n+1].dl.len; if ( ++count < max_count && curlen == nextlen ) { continue; } else if ( count < min_count ) { gz1->bl_tree[curlen].fc.freq += count; } else if ( curlen != 0 ) { if ( curlen != prevlen ) gz1->bl_tree[curlen].fc.freq++; gz1->bl_tree[REP_3_6].fc.freq++; } else if ( count <= 10 ) { gz1->bl_tree[REPZ_3_10].fc.freq++; } else { gz1->bl_tree[REPZ_11_138].fc.freq++; } count = 0; prevlen = curlen; if ( nextlen == 0 ) { max_count = 138; min_count = 3; } else if (curlen == nextlen) { max_count = 6; min_count = 3; } else { max_count = 7; min_count = 4; } } } void pqdownheap( PGZ1 gz1, ct_data *tree, int k ) { int v = gz1->heap[k]; int j = k << 1; while( j <= gz1->heap_len ) { if (j < gz1->heap_len && smaller(tree, gz1->heap[j+1], gz1->heap[j])) j++; if (smaller(tree, v, gz1->heap[j])) break; gz1->heap[k] = gz1->heap[j]; k = j; j <<= 1; } gz1->heap[k] = v; } #define GZS_ZIP1 1 #define GZS_ZIP2 2 #define GZS_DEFLATE1 3 #define GZS_DEFLATE2 4 int gzs_fsp ( PGZ1 gz1 ); int gzs_zip1 ( PGZ1 gz1 ); int gzs_zip2 ( PGZ1 gz1 ); int gzs_deflate1( PGZ1 gz1 ); int gzs_deflate2( PGZ1 gz1 ); int gzp_main( request_rec *r, GZP_CONTROL *gzp ) { char cn[]="gzp_main()"; PGZ1 gz1 = 0; int rc = 0; int final_exit_code = 0; int ofile_flags = O_RDWR | O_CREAT | O_TRUNC | O_BINARY; gzp->result_code = 0; gzp->bytes_out = 0; gz1 = (PGZ1) gz1_init(); if ( gz1 == 0 ) { return 0; } gz1->decompress = gzp->decompress; mod_gzip_strcpy( gz1->ifname, gzp->input_filename ); mod_gzip_strcpy( gz1->ofname, gzp->output_filename ); gz1->input_ismem = gzp->input_ismem; gz1->input_ptr = gzp->input_ismem_ibuf + gzp->input_offset; gz1->input_bytesleft = gzp->input_ismem_ibuflen; gz1->output_ismem = gzp->output_ismem; gz1->output_ptr = gzp->output_ismem_obuf; gz1->output_maxlen = gzp->output_ismem_obuflen; if ( gz1->no_time < 0 ) gz1->no_time = gz1->decompress; if ( gz1->no_name < 0 ) gz1->no_name = gz1->decompress; work = zip; if ( !gz1->input_ismem ) { errno = 0; rc = stat( gz1->ifname, &gz1->istat ); if ( rc != 0 ) { ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server, "%s: stat(gz1->ifname=%s) FAILED", cn, gz1->ifname ); gz1_cleanup( gz1 ); return 0; } gz1->ifile_size = ( gz1->istat.st_size - gzp->input_offset ); if ( gz1->ifile_size < 0 ) gz1->ifile_size = 0; gz1->ifd = OPEN( gz1->ifname, gz1->ascii && !gz1->decompress ? O_RDONLY : O_RDONLY | O_BINARY, RW_USER ); if ( gz1->ifd == -1 ) { ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server, "%s: OPEN(gz1->ifname=%s) FAILED", cn, gz1->ifname ); gz1_cleanup( gz1 ); return 0; } if ( gzp->input_offset > 0 ) { SEEKFORWARD( gz1->ifd, gzp->input_offset ); } } if ( !gz1->output_ismem ) { if ( gz1->ascii && gz1->decompress ) { ofile_flags &= ~O_BINARY; } gz1->ofd = OPEN( gz1->ofname, ofile_flags, RW_USER ); if ( gz1->ofd == -1 ) { ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server, "%s: OPEN(gz1->ofname=%s) FAILED", cn, gz1->ofname ); if ( gz1->ifd ) { close( gz1->ifd ); gz1->ifd = 0; } gz1_cleanup( gz1 ); return 0; } } gz1->outcnt = 0; gz1->insize = 0; gz1->inptr = 0; gz1->bytes_in = 0L; gz1->bytes_out = 0L; gz1->part_nb = 0; if ( gz1->decompress ) { gz1->method = get_header( gz1, gz1->ifd ); if ( gz1->method < 0 ) { if ( gz1->ifd ) { close( gz1->ifd ); gz1->ifd = 0; } if ( gz1->ofd ) { close( gz1->ofd ); gz1->ofd = 0; } return 0; } } gz1->save_orig_name = 0; gz1->state = GZS_ZIP1; for (;;) { gzs_fsp( gz1 ); if ( gz1->done == 1 ) break; } if ( gz1->ifd ) { close( gz1->ifd ); gz1->ifd = 0; } if ( gz1->ofd ) { close( gz1->ofd ); gz1->ofd = 0; } gzp->result_code = gz1->exit_code; gzp->bytes_out = gz1->bytes_out; final_exit_code = (int) gz1->exit_code; gz1_cleanup( gz1 ); return final_exit_code; } int gzs_fsp( PGZ1 gz1 ) { int rc=0; switch( gz1->state ) { case GZS_ZIP1: rc = gzs_zip1( gz1 ); break; case GZS_ZIP2: rc = gzs_zip2( gz1 ); break; case GZS_DEFLATE1: rc = gzs_deflate1( gz1 ); break; case GZS_DEFLATE2: rc = gzs_deflate2( gz1 ); break; default: gz1->done = 1; break; } return( rc ); } int gzs_zip1( PGZ1 gz1 ) { uch flags = 0; #ifdef FUTURE_USE ush attr = 0; ush deflate_flags = 0; #endif gz1->outcnt = 0; gz1->method = DEFLATED; put_byte(GZIP_MAGIC[0]); put_byte(GZIP_MAGIC[1]); put_byte(DEFLATED); if ( gz1->save_orig_name ) { flags |= ORIG_NAME; } put_byte(flags); put_long(gz1->time_stamp); gz1->crc = -1; updcrc( gz1, NULL, 0 ); gz1->state = GZS_ZIP2; return 0; } int gzs_zip2( PGZ1 gz1 ) { #ifdef FUTURE_USE uch flags = 0; #endif ush attr = 0; ush deflate_flags = 0; bi_init( gz1, gz1->ofd ); mod_gzip_ct_init( gz1, &attr, &gz1->method ); lm_init( gz1, gz1->level, &deflate_flags ); put_byte((uch)deflate_flags); put_byte(OS_CODE); if ( gz1->save_orig_name ) { char *p = gz1_basename( gz1, gz1->ifname ); do { put_char(*p); } while (*p++); } gz1->header_bytes = (long)gz1->outcnt; gz1->state = GZS_DEFLATE1; return 0; } int gzs_deflate1( PGZ1 gz1 ) { if ( !gz1->deflate1_initialized ) { gz1->deflate1_match_available = 0; gz1->deflate1_match_length = MIN_MATCH-1; gz1->deflate1_initialized = 1; } if ( gz1->compr_level <= 3 ) { gz1->done = 1; return 0; } if ( gz1->lookahead == 0 ) { if ( gz1->deflate1_match_available ) { ct_tally( gz1, 0, gz1->window[gz1->strstart-1] ); } gz1->state = GZS_DEFLATE2; return (int) FLUSH_BLOCK(1); } #ifdef STAY_HERE_FOR_A_CERTAIN_AMOUNT_OF_ITERATIONS while( iterations < max_iterations_per_yield ) { #endif gz1->ins_h = (((gz1->ins_h)<window[gz1->strstart+MIN_MATCH-1])) & HASH_MASK; prev[ gz1->strstart & WMASK ] = gz1->deflate1_hash_head = head[ gz1->ins_h ]; head[ gz1->ins_h ] = gz1->strstart; gz1->prev_length = gz1->deflate1_match_length, gz1->deflate1_prev_match = gz1->match_start; gz1->deflate1_match_length = MIN_MATCH-1; if ( gz1->deflate1_hash_head != NIL && gz1->prev_length < gz1->max_lazy_match && gz1->strstart - gz1->deflate1_hash_head <= MAX_DIST) { gz1->deflate1_match_length = longest_match( gz1, gz1->deflate1_hash_head ); if ( gz1->deflate1_match_length > gz1->lookahead ) { gz1->deflate1_match_length = gz1->lookahead; } if (gz1->deflate1_match_length == MIN_MATCH && gz1->strstart-gz1->match_start > TOO_FAR) { gz1->deflate1_match_length--; } } if ( gz1->prev_length >= MIN_MATCH && gz1->deflate1_match_length <= gz1->prev_length ) { gz1->deflate1_flush = ct_tally(gz1,gz1->strstart-1-gz1->deflate1_prev_match, gz1->prev_length - MIN_MATCH); gz1->lookahead -= ( gz1->prev_length - 1 ); gz1->prev_length -= 2; do { gz1->strstart++; gz1->ins_h = (((gz1->ins_h)<window[ gz1->strstart + MIN_MATCH-1])) & HASH_MASK; prev[ gz1->strstart & WMASK ] = gz1->deflate1_hash_head = head[gz1->ins_h]; head[ gz1->ins_h ] = gz1->strstart; } while (--gz1->prev_length != 0); gz1->deflate1_match_available = 0; gz1->deflate1_match_length = MIN_MATCH-1; gz1->strstart++; if (gz1->deflate1_flush) FLUSH_BLOCK(0), gz1->block_start = gz1->strstart; } else { if ( gz1->deflate1_match_available ) { if ( ct_tally( gz1, 0, gz1->window[gz1->strstart-1] ) ) { FLUSH_BLOCK(0), gz1->block_start = gz1->strstart; } gz1->strstart++; gz1->lookahead--; } else { gz1->deflate1_match_available = 1; gz1->strstart++; gz1->lookahead--; } while (gz1->lookahead < MIN_LOOKAHEAD && !gz1->eofile ) { fill_window(gz1); } } return 0; } int gzs_deflate2( PGZ1 gz1 ) { #if !defined(NO_SIZE_CHECK) && !defined(RECORD_IO) if (gz1->ifile_size != -1L && gz1->isize != (ulg)gz1->ifile_size) { } #endif put_long( gz1->crc ); put_long( gz1->bytes_in ); gz1->header_bytes += 2*sizeof(long); flush_outbuf( gz1 ); gz1->done = 1; return OK; } /*--------------------------------------------------------------------------*/ /* COMPRESSION_SUPPORT: END */ /*--------------------------------------------------------------------------*/