Return-Path: Delivered-To: apmail-new-httpd-archive@apache.org Received: (qmail 93504 invoked by uid 500); 13 Oct 2000 15:14:13 -0000 Mailing-List: contact new-httpd-help@apache.org; run by ezmlm Precedence: bulk Reply-To: new-httpd@apache.org list-help: list-unsubscribe: list-post: Delivered-To: mailing list new-httpd@apache.org Received: (qmail 93466 invoked from network); 13 Oct 2000 15:14:02 -0000 From: TOKILEY@aol.com Message-ID: <37.b663b5a.2718807d@aol.com> Date: Fri, 13 Oct 2000 11:13:01 EDT Subject: Complete mod_gzip.c source attached to this message To: new-httpd@apache.org MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="part1_37.b663b5a.2718807d_boundary" X-Mailer: Windows AOL sub 86 X-Spam-Rating: locus.apache.org 1.6.2 0/1000/N --part1_37.b663b5a.2718807d_boundary Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit FYI: mod_gzip for Apache is now available with complete source code mod_gzip.c is attached to this message. Headline article today 10.13.00 at Internet.com webreference site... Article title: "mod_gzip released for Apache" Link: http://www.webreference.com Featured news story about mod_gzip and HTTP compression at Internet.com webreference site... http://webreference.com/internet/software/servers/http/compression/ mod_gzip home page ( Contains links for downloading all pre-compiled versions of ApacheModuleGzip.dll for Windows and mod_gzip.so for Linux, UNIX, etc. Also contains links for downloading SOURCE CODE.)... http://www.RemoteCommunications.com/apache/mod_gzip/ mod_gzip online FAQ... http://www.RemoteCommunications.com/apache/mod_gzip/mod_gzip_faq.htm Pre-compiled binary sizes... Windows - ApacheModuleGzip.dll - Only 38k Linux - mod_gzip.so - Only 57k Solaris7 64-bit version - mod_gzip.so - Only 58k Source code: mod_gzip.c ( Only 161k complete ) There are no header files or any other source code files. mod_gzip.c is the only source code file there is. There is also no requirement for any 3rd party compression libraries whatsoever. All the code that mod_gzip needs is in mod_gzip.c itself. mod_gzip.c contains a highly optimized and Web-Server thread safe version of the LZ77 + Huffman compression technique that has come to be known as GZIP. Runs perfectly as either an external DSO load module or built right into the core. Yours... Kevin Kiley CTO, Remote Communications, Inc. http://www.RemoteCommunications.com/ http://www.RemoteCommunications.com/rctpd/ - Free IETF Encoding Server http://www.RemoteCommunications.com/apache/ab/ - Free Enhanced ApacheBench http://www.RemoteCommunications.com/apache/mod_gzip/ - Free Apache module --part1_37.b663b5a.2718807d_boundary Content-Type: text/plain; name="MOD_GZIP.C" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline; filename="MOD_GZIP.C" /* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D * Copyright (c) 1995-2000 The Apache Group. 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.=20 * * 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. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the Apache Group * for use in the Apache HTTP server project (http://www.apache.org/)." * * 4. The names "Apache Server" and "Apache Group" 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 names without prior written * permission of the Apache Group. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the Apache Group * for use in the Apache HTTP server project (http://www.apache.org/)." * * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``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 GROUP 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. * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Group and was originally based * on public domain software written at the National Center for * Supercomputing Applications, University of Illinois, Urbana-Champaign. * For more information on the Apache Group and the Apache HTTP server * project, please see . * */ /*=20 * mod_gzip.c * * Apache gzip compression module. * * This module adds 'on the fly' compression of HTTP content to * any Apache Web Server. It uses the IETF Content-encoding standard(s). * * There is NO client-side software required for using this module * other than any fully HTTP 1.1 compliant user agent. * * Any fully HTTP 1.1 compliant user agent will be able to receive and * automatically decode the compressed content. * * All fully HTTP 1.1 compliant user agents that are capable of receiving * gzip encoded data will indicate their ability to do so by adding the * standard "Accept-Encoding: gzip" field to the inbound request header. *=20 * This module may be compiled as a stand-alone external 'plug-in' * or be compiled into the Apache core server as a 'built-in' module. * * Sponsor: Remote Communications, Inc. http://www.RemoteCommunications.com/ * Authors: Konstantin Balashov, Alex Kosobrukhov and Kevin Kiley. * Contact: info@RemoteCommunications.com * * Initial public release date: 13-Oct-2000 * * Miscellaneous release notes: * * This is a standard Apache type-registered module and, as such, will only * compress static files and will not provide compression for dynamically * generated content. * * The module never really returns an ERROR. It will either simply return * compressed data and the OK return code if all goes well or it will * DECLINE the processing in the hopes that the default logic can resolve * any conflicts and send the requested entity. * * If any requesting user agent is unable to receive gzip compressed * content then this module will DECLINE the processing. * * Even if this module cannot find the requested object it will still * simply DECLINE the processing and allow the default logic to kick * in and send the HTTP 404 Not Found error, if the object is truly * unavailable. * * This module is capable of adding detailed compression information * to any existing Apache log file such as 'access.log'. See the * information in the code itself about how to add compression * statistics and information to any standard Apache log file. * * THIS IS A COMPLETELY SELF-CONTAINED MODULE. MOD_GZIP.C IS THE * ONY SOURCE CODE FILE THERE IS AND THERE ARE NO MODULE SPECIFIC * HEADER FILES OR THE NEED FOR ANY 3RD PARTY COMPRESSION LIBRARIES. * ALL OF THE COMPRESSION CODE NEEDED BY THIS MODULE IS CONTAINED * WITHIN THIS SINGLE SOURCE FILE. * * Many standard compression libraries are not designed or optimized * for use as real-time compression codecs nor are they guaranteed * to be 'thread-safe'. The internal compression code used by mod_gzip * is all of those things. It is a highly-optimized and thread-safe * implementation of the standard LZ77 + Huffman compression * technique that has come to be known as GZIP. */ char mod_gzip_version_string[] =3D "1.3.14"; /* Global version string */ #include "httpd.h" #include "http_config.h" #include "http_core.h" #include "http_log.h" #include "http_main.h" #include "http_protocol.h" #include "util_script.h" #include /*--------------------------------------------------------------------------= */ /* =20= */ /* Data declarations. =20= */ /* =20= */ /* Here are the static cells and structure declarations private to our =20= */ /* module. =20= */ /* =20= */ /*--------------------------------------------------------------------------= */ /* * Sample configuration record. Used for both per-directory and per-server * configuration data. * * It's perfectly reasonable to have two different structures for the two * different environments. The same command handlers will be called for * both, though, so the handlers need to be able to tell them apart. One * possibility is for both structures to start with an int which is zero for * one and 1 for the other. * * Note that while the per-directory and per-server configuration records ar= e * available to most of the module handlers, they should be treated as * READ-ONLY by all except the command and merge handlers. Sometimes handle= rs * are handed a record that applies to the current location by implication o= r * inheritance, and modifying it will change the rules for other locations. * * To avoid leaking memory from pools other than the per-request one, we * allocate a module-private pool, and then use a sub-pool of that which get= s * freed each time we modify the trace. That way previous layers of trace * data don't get lost. */ /*--------------------------------------------------------------------------= */ static pool *gzip_pool =3D NULL; static pool *gzip_subpool =3D NULL; /* Turn this compile flag ON to include some console diagnostics... #define USE_MOD_GZIP_CONSOLE_DEBUG1 */ /* Turn this compile flag ON to include complete private DEBUG log... #define USE_MOD_GZIP_DEBUG1 */ #ifndef MAX_PATH_LEN #define MAX_PATH_LEN 512 #endif /* GZP_CONTROL_STRUCTURE */ typedef struct _GZP_CONTROL { =09int decompress; /* 0=3DCompress 1=3DDecompress */ =09/* Input control... */ int input_ismem; /* Input source is memory buffer, not file */ char *input_ismem_ibuf; /* Pointer to input memory buffer */ long input_ismem_ibuflen; /* Total length of input data */ char input_filename[ MAX_PATH_LEN + 2 ]; /* Input file name */ /* Output control... */ int output_ismem; /* Output source is memory buffer, not file=20= */ char *output_ismem_obuf; /* Pointer to output memory buffer */ long output_ismem_obuflen; /* Maximum length of output data buffer */ char output_filename[ MAX_PATH_LEN + 2 ]; /* Output file name */ /* Results... */ int result_code; /* Result code */ long bytes_out; /* Total number of compressed output bytes */ } GZP_CONTROL; int gzp_main( GZP_CONTROL *gzp ); /* API entry point */ /* Some globals for statistics... */ long mod_gzip_total_commands_received =3D 0; long mod_gzip_total_requests_received =3D 0; long mod_gzip_total_requests_declined =3D 0; long mod_gzip_total_requests_processed =3D 0; long mod_gzip_total_bytes_processed_raw =3D 0; long mod_gzip_total_bytes_processed_compressed =3D 0; /* Some global behaviorial switches... */ int mod_gzip_keep_work_files =3D 0; /* 1=3DKeep work files 0=3DNo (Default)=20= */ #define GZIP_MINIMUM_SIZE 300L #define GZIP_INMEM_MAXSIZE 60000L long mod_gzip_inmem_maxsize =3D (long) GZIP_INMEM_MAXSIZE; long mod_gzip_minimum_size =3D (long) GZIP_MINIMUM_SIZE; /* * Declare ourselves so the configuration routines can find and know us. * We'll fill it in at the end of the module. */ module MODULE_VAR_EXPORT gzip_module; /* * This routine sets up some module-wide cells if they haven't been already. */ static void setup_module_cells() { /* * If we haven't already allocated our module-private pool, do so now. */ if ( gzip_pool =3D=3D NULL ) { gzip_pool =3D ap_make_sub_pool(NULL); } }/* End of setup_module_cells() */ /*--------------------------------------------------------------------------= */ /* Now we declare our content handlers, which are invoked when the server =20= */ /* encounters a document which our module is supposed to have a chance to =20= */ /* see. (See mod_mime's SetHandler and AddHandler directives, and the =20= */ /* mod_info and mod_status gzips, for more details.) =20= */ /* =20= */ /* Since content handlers are dumping data directly into the connexion =20= */ /* (using the r*() routines, such as rputs() and rprintf()) without =20= */ /* intervention by other parts of the server, they need to make =20= */ /* sure any accumulated HTTP headers are sent first. This is done by =20= */ /* calling send_http_header(). Otherwise, no header will be sent at all, =20= */ /* and the output sent to the client will actually be HTTP-uncompliant. =20= */ /*--------------------------------------------------------------------------= */ /*=20 * Sample content handler. All this does is display the call list that has * been built up so far. * * The return value instructs the caller concerning what happened and what t= o * do next: * OK ("we did our thing") * DECLINED ("this isn't something with which we want to get involved") * HTTP_mumble ("an error status should be reported") */ /*--------------------------------------------------------------------------= */ /* * Adjustable Apache API call selection... */ /* Turn this ON to use ap_send_mmap(). */ /* If this define is OFF then we default to ap_rwrite() calls. */ #define MOD_GZIP_USES_AP_SEND_MMAP /* * Forward prototypes for some local utility calls... */ #define USE_MOD_GZIP_INTERNAL_COMMANDS #ifdef USE_MOD_GZIP_INTERNAL_COMMANDS int mod_gzip_send_html_command_response( request_rec *r, /* Request record */ char *tmp, /* Response to send */ FILE *gzdb_fh1 /* Always NULL if no DEBUG is used */ ); #endif /* USE_MOD_GZIP_INTERNAL_COMMANDS */ #ifdef USE_MOD_GZIP_DEBUG1 int mod_gzip_show_memory_status( char *msg1, /* Test point indication string */ FILE *gzdb_fh1 /* Always NULL if no DEBUG is used */ ); =20 #endif /* USE_MOD_GZIP_DEBUG1 */ /* * Standard Apache Log updates * * This module can add compression information to any standard * Apache log file. See the notes farther down in the code about * how this is accomplished and how to enable the logging. * * The following compile-time switch can be used to either include * or exclude all the standard Apache log interface code. */ #define MOD_GZIP_USES_APACHE_LOGS /* * The primary transaction handler entry point... */ static int gzip_handler( request_rec *r ) { GZP_CONTROL* gzp =3D 0; char* gz1_ismem_obuf =3D 0; long input_size =3D 0; long output_size =3D 0; long compression_ratio =3D 0; const char* accept_encoding =3D 0; const char* has_encoding =3D 0; int process =3D 0; int do_command =3D 0; int bytesread =3D 0; FILE* file =3D 0; FILE* ifh =3D 0; int rc =3D 0; long process_id; /* Current Process ID */ long thread_id; /* Current thread ID */ char content_length[20]; /* For Content-length updates */ char tmp[8192]; /* Scratch buffer - 2 * 4096 */ FILE *gzdb_fh1=3D0; /* Remains NULL if no DEBUG is used */ char *fname=3D0; /* Scratch filename pointer */ char *server_root=3D0; /* The Server's home directory */ #ifdef MOD_GZIP_USES_APACHE_LOGS char log_info[90]; /* Adds compression results to Apache log(s) */ #endif /* MOD_GZIP_USES_APACHE_LOGS */ #ifdef USE_MOD_GZIP_DEBUG1 char cn[]=3D"mod_gzip.c: gzip_handler()"; const char* the_type =3D 0; char logname[256]; #endif /* Start... */ #ifdef MOD_GZIP_USES_APACHE_LOGS /* * If the MOD_GZIP_USES_APACHE_LOGS compile-time switch is ON * then the Apache log module interface code is being included. * * Reset the module 'notes' that are used by mod_gzip to * add entries to Apache standard log files... * * See the note farther below about how to add mod_gzip * compression information to any standard Apache log file. */ /* Default for 'mod_result' message is 'DECLINED'... */ ap_table_setn( r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED")= ); /* Default for in/out size is 'n/a'... 'Not available'...*/ sprintf( log_info, "n/a" ); ap_table_setn( r->notes,"mod_gzip_input_size",ap_pstrdup(r->pool,log_inf= o)); ap_table_setn( r->notes,"mod_gzip_output_size",ap_pstrdup(r->pool,log_in= fo)); /* Default for compression ratio is '0' percent... */ ap_table_setn( r->notes,"mod_gzip_compression_ratio",ap_pstrdup(r->pool,= "0")); #endif /* MOD_GZIP_USES_APACHE_LOGS */ #ifdef USE_MOD_GZIP_DEBUG1 /*--------------------------------------------------------------*/ /* If we are writing GZIP DEBUG log to disk then the log name */ /* is 'mod_gzip.log' and it will appear in the same DIR as */ /* APACHE.EXE (Win32) or the HTTPD daemon binary (UNIX). */ /* There is no multi-thread protection for this simple debug */ /* output log so it should be used to test single requests only */ /*--------------------------------------------------------------*/ /* NOTE: fopen("wa") will reset the log file each time it opens */ /* since the 'w' flag is included. Use fopen("a") for true */ /* 'append' mode so all transactions are logged... */ /*--------------------------------------------------------------*/ server_root =3D ap_server_root_relative( r->pool, "" ); /* There should already be a 'slash' on the end of the dir name... */ sprintf( logname, "%smod_gzip.log", server_root ); gzdb_fh1 =3D fopen( logname, "a" ); /* Open in append mode... */ if ( !gzdb_fh1 ) /* Cannot open file... */ { /* See if the file can be created... */ gzdb_fh1 =3D fopen( logname, "wb" ); /* Create it */ if ( !gzdb_fh1 ) /* Cannot create file... */ { /* This is really an error... */ /* Log the 'last' error along with the message... */ ap_log_error( APLOG_MARK,APLOG_ERR, r->server, "mod_gzip: gzip_handler(): Cannot open or create log file [%s]",lo= gname); #ifdef MOD_GZIP_USES_APACHE_LOGS /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */ ap_table_setn( r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:LOGFAIL1")= ); #endif /* MOD_GZIP_USES_APACHE_LOGS */ return DECLINED; } } fprintf( gzdb_fh1, "\n%s: Entry\n",cn); /* Turn this on for internal memory leak checking... #define USE_MOD_GZIP_MEMORY_CHECK */ #ifdef USE_MOD_GZIP_MEMORY_CHECK mod_gzip_show_memory_status( "Before request processing", gzdb_fh1 ); #endif /* USE_MOD_GZIP_MEMORY_CHECK */ fprintf( gzdb_fh1, "%s: mod_gzip version =3D %s\n", cn,mod_gzip_version_string); fprintf( gzdb_fh1, "%s: logname=3D[%s]\n",cn,logname); /* Request info... */ fprintf( gzdb_fh1, "%s: r->filename=3D[%s]\n",cn,r->filename); fprintf( gzdb_fh1, "%s: r->finfo.st_size =3D %ld\n", cn, (long) r->finfo.st_size ); the_type =3D ap_table_get( r->headers_in, "Content-type" ); fprintf( gzdb_fh1, "%s: r->headers_in, Content-type =3D [%s]\n",cn,the= _type); the_type =3D ap_table_get( r->headers_out,"Content-type" ); fprintf( gzdb_fh1, "%s: r->headers_out, Content-type =3D [%s]\n",cn,the= _type); fprintf( gzdb_fh1, "%s: r->content_type =3D [%s]\n",cn,r->content_type=20= ); /* Server info */ fprintf( gzdb_fh1, "%s: r->server->path =3D [%s]\n",cn,r->server->pa= th ); fprintf( gzdb_fh1, "%s: r->server->pathlen =3D %d\n",cn,(int)r->server-= >pathlen); fprintf( gzdb_fh1, "%s: r->server->server_admin =3D [%s]\n",cn,r->se= rver->server_admin); fprintf( gzdb_fh1, "%s: r->server->server_hostname =3D [%s]\n",cn,r->se= rver->server_hostname); fprintf( gzdb_fh1, "%s: r->server->error_fname =3D [%s]\n",cn,r->se= rver->error_fname); /* Environment info... */ fprintf( gzdb_fh1, "%s: DOCUMENT_ROOT =3D [%s]\n",cn,ap_document_root(r= )); /* Request info... */ /*--------------------------------------------------------------*/ #endif /* USE_MOD_GZIP_DEBUG1 */ #ifdef USE_MOD_GZIP_INTERNAL_COMMANDS /* * Internal command pickups... * * If this module was compiled with the * USE_MOD_GZIP_INTERNAL_COMMANDS switch ON * then the first thing we do is check for valid * URL-based internal commands. * * This commnd interface was designed to be most effective * in Windows or UNIX multi-thread environments. Statistics for * UNIX multi-process implementations that keep reloading DSO * files and clearing the globals will only report statistics * for the most recent transaction(s). * * TODO: Add persistent storage for multi-process DSO reloading. */ /* * Rather than check for all possible commands each time * just do 1 quick check for the command prefix and set * a flag to indicate if there is any need to enter the * actual command handler... */ if ( strstr( r->filename, "mod_gzip_command_" ) ) { do_command =3D 1; /* Process the command */ } #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: do_command =3D %d\n",cn,do_command); #endif /* USE_MOD_GZIP_DEBUG1 */ if ( do_command ) { /* Determine the exact command and respond... */ if ( strstr( r->filename, "mod_gzip_command_version" ) ) { /*------------------------------------------------------*/ /* Command: 'mod_gzip_command_version' */ /* Purpose: Return the current mod_gzip version number. */ /* Comment: Allows anyone to query any Apache Server at */ /* any URL with a browser and discover if */ /* mod_gzip is in use at that site. */ /*------------------------------------------------------*/ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: 'mod_gzip_command_version' seen...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ /* NOTE: mod_gzip command results are not sent compressed */ mod_gzip_total_commands_received++; /* Increase total */ /* Build the response buffer... */ sprintf( tmp, "
"
          "mod_gzip is available on this Server\r\n"
          "mod_gzip version =3D %s\r\n"
          "
", mod_gzip_version_string ); /* For all mod_gzip commands that are intercepted we */ /* simply return OK. */ return( mod_gzip_send_html_command_response( r, tmp, gzdb_fh1 )); } else if ( strstr( r->filename, "mod_gzip_command_showstats" ) ) { /*------------------------------------------------------*/ /* Command: 'mod_gzip_command_showstats' */ /* Purpose: Return the internal statistics. */ /* Comment: Provides information about request activity */ /*------------------------------------------------------*/ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: 'mod_gzip_command_showstats' seen...\n",cn= ); #endif /* USE_MOD_GZIP_DEBUG1 */ /* NOTE: mod_gzip command results are not sent compressed */ mod_gzip_total_commands_received++; /* Increase total */ compression_ratio =3D 0; /* Reset */ /* Prevent 'Divide by zero' error... */ if ( ( mod_gzip_total_bytes_processed_raw > 0 ) && ( mod_gzip_total_bytes_processed_compressed > 0 ) ) { compression_ratio =3D 100 - (int) ( mod_gzip_total_bytes_processed_compressed * 100L / mod_gzip_total_bytes_processed_raw ); } /* Build the response buffer... */ sprintf( tmp, "
"
          "mod_gzip_command_showstats seen...\r\n"
          "mod_gzip version =3D %s\r\n"
          "mod_gzip_total_commands_received =3D %ld\r\n"
          "mod_gzip_total_requests_received =3D %ld\r\n"
          "mod_gzip_total_requests_declined =3D %ld\r\n"
          "mod_gzip_total_requests_processed =3D %ld\r\n"
          "mod_gzip_total_bytes_processed_raw =3D %ld\r\n"
          "mod_gzip_total_bytes_processed_compressed =3D %ld\r\n"
          "mod_gzip_total_bytes_saved_using_compression =3D %ld\r\n"
          "compression_ratio =3D %ld (percent)\r\n"
          "
", mod_gzip_version_string, mod_gzip_total_commands_received, mod_gzip_total_requests_received, mod_gzip_total_requests_received - mod_gzip_total_requests_processed, mod_gzip_total_requests_processed, mod_gzip_total_bytes_processed_raw, mod_gzip_total_bytes_processed_compressed, mod_gzip_total_bytes_processed_raw - mod_gzip_total_bytes_processed_compressed, compression_ratio ); /* For all mod_gzip commands that are intercepted we */ /* simply return OK. */ return( mod_gzip_send_html_command_response( r, tmp, gzdb_fh1 )); } else if ( strstr( r->filename, "mod_gzip_command_resetstats" ) ) { /*------------------------------------------------------*/ /* Command: 'mod_gzip_command_resetstats' */ /* Purpose: Reset the internal statistics. */ /* Comment: Allows user to reset values from a browser. */ /*------------------------------------------------------*/ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: 'mod_gzip_command_resetstats' seen...\n",c= n); #endif /* USE_MOD_GZIP_DEBUG1 */ /* NOTE: mod_gzip command results are not sent compressed */ mod_gzip_total_commands_received++; /* Increase total */ /* Reset internal statistics... */ compression_ratio =3D 0; mod_gzip_total_commands_received =3D 0; mod_gzip_total_requests_received =3D 0; mod_gzip_total_requests_processed =3D 0; mod_gzip_total_bytes_processed_raw =3D 0; mod_gzip_total_bytes_processed_compressed =3D 0; /* Build the response buffer... */ sprintf( tmp, "
"
          "mod_gzip_command_resetstats seen...\r\n"
          "mod_gzip version =3D %s\r\n"
          "mod_gzip_total_commands_received =3D %ld\r\n"
          "mod_gzip_total_requests_received =3D %ld\r\n"
          "mod_gzip_total_requests_declined =3D %ld\r\n"
          "mod_gzip_total_requests_processed =3D %ld\r\n"
          "mod_gzip_total_bytes_processed_raw =3D %ld\r\n"
          "mod_gzip_total_bytes_processed_compressed =3D %ld\r\n"
          "mod_gzip_total_bytes_saved_using_compression =3D %ld\r\n"
          "compression_ratio =3D %ld (percent)\r\n"
          "
", mod_gzip_version_string, mod_gzip_total_commands_received, mod_gzip_total_requests_received, mod_gzip_total_requests_received - mod_gzip_total_requests_processed, mod_gzip_total_requests_processed, mod_gzip_total_bytes_processed_raw, mod_gzip_total_bytes_processed_compressed, mod_gzip_total_bytes_processed_raw - mod_gzip_total_bytes_processed_compressed, compression_ratio ); /* For all mod_gzip commands that are intercepted we */ /* simply return OK. */ return( mod_gzip_send_html_command_response( r, tmp, gzdb_fh1 )); } else /* Unrecognized command... */ { /* The command prefix was 'seen' and the 'do_command' flag */ /* was TRUE but either the command was mis-typed or there */ /* is no such command available. This is not an ERROR and */ /* we should simply fall-through and assume that the URL */ /* is valid for the local Server. A 404 will be returned */ /* if there is no object that actually matches the name. */ } }/* End 'if( do_command )' */ #endif /* USE_MOD_GZIP_INTERNAL_COMMANDS */ /* * Increase the total number of requests that entered this * module regardless of the final processing status. * mod_gzip internal commands are not included in the totals. * Don't let the total overflow. */ mod_gzip_total_requests_received++; /* Increase total */ if ( mod_gzip_total_requests_received > 999999999L ) { mod_gzip_total_requests_received =3D 1; /* Wrap */ } /* * Sanity checks... */ /* * If the requested file already contains the .gz designation * then we must assume it is pre-compressed and let the * default logic take care of sending the file... */ if ( strstr( r->filename, ".gz" ) ) { #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: r->filename already contains '.gz'.\n",cn); fprintf( gzdb_fh1, "%s: Pre-compression is assumed.\n",cn); fprintf( gzdb_fh1, "%s: Exit > return( DECLINED ) >\n",cn); fclose( gzdb_fh1 ); #endif /* USE_MOD_GZIP_DEBUG1 */ #ifdef MOD_GZIP_USES_APACHE_LOGS /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */ ap_table_setn( r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:HAS.GZ")); #endif /* MOD_GZIP_USES_APACHE_LOGS */ return DECLINED; } else /* r->filename doesn not contain '.gz' designator... */ { #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: r->filename does NOT contain '.gz'.\n",cn); fprintf( gzdb_fh1, "%s: Assuming OK to proceed...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ } /* * Safeguard against situations where some other module or * filter has gotten to this request BEFORE us and has already * added the 'Content-encoding: gzip' field to the output header. * It must be assumed that whoever added the header prior to this * point also took care of the compression itself. * * If the output header already contains "Content-encoding: gzip" * then simply DECLINE the processing and let the default chain * take care of it... */ has_encoding =3D ap_table_get( r->headers_out, "Content-encoding" ); #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: has_encoding =3D [%s]\n",cn,has_encoding); #endif /* USE_MOD_GZIP_DEBUG1 */ if ( has_encoding ) /* 'Content-encoding' field is present... */ { #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Output header already contains 'Content-encod= ing:' field\n",cn); fprintf( gzdb_fh1, "%s: Checking for 'gzip' designator...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ if ( strstr( has_encoding, "gzip" ) ) { #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: 'Content-encoding:' field contains 'gzip'=20= designator...\n",cn); fprintf( gzdb_fh1, "%s: Pre-compression is assumed.\n",cn); fprintf( gzdb_fh1, "%s: Exit > return( DECLINED ) >\n",cn); fclose( gzdb_fh1 ); #endif /* USE_MOD_GZIP_DEBUG1 */ #ifdef MOD_GZIP_USES_APACHE_LOGS /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */ ap_table_setn( r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:HAS_CE:GZI= P")); #endif /* MOD_GZIP_USES_APACHE_LOGS */ return DECLINED; } else /* 'gzip' designator not found... */ { #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: 'Content-encoding:' field does NOT contain= 'gzip' designator...\n",cn); fprintf( gzdb_fh1, "%s: Assuming OK to proceed...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ } }/* End 'if( has_encoding )' */ else /* Output header does NOT contain 'Content-encoding:' field... */ { #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Output header does NOT contain 'Content-encod= ing:' field.\n",cn); fprintf( gzdb_fh1, "%s: Assuming OK to proceed...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ } /* * Basic sanity checks completed and we are still here. * * Now we must determine if the User-Agent is capable of receiving * compressed data... * * There are, currently, many reasons why it is actually never * enough to simply trust the 'Accept-encoding: foo, bar' * request header field when it comes to actually determining * if a User-agent is capable of receiving content or transfer * encodings. * * Some of them are... * * 1. There have been several major releases of popular browsers * that actually send the 'Accept-encoding:' request field but * are, in reality, unable to perform the specified decoding(s). * In some cases the result will be that the browser screen * simply fills with garbage ( the binary compressed data * itself ) but in some cases the browser will actually crash. * * 2. There have been other major releases of browsers that are * specifying multiple 'Accept-encoding' techniques but are * actually only able to handle one of the multiple types * specified and there is no way to know which one that is * other than by using other empiricial data extracted from * the 'User-agent' field or other inbound request headers. * * 3. Same as 1 and 2 but relates to SIZE. Some major browser * releases can handle the encoded content but only up to * a certain 'SIZE' limit and then they will fail. There * is no way for a User-agent to specify this limitation * via HTTP so empirical header analysis is the only option. * * 4. The HTTP specification has no way for a Server to distinguish * from the 'Accept encoding: foo, bar' input request field * whether the user agent can only support the specified encodings * as either a Content-encoding OR a Transfer-encoding, but * not both. There is also no way of knowing if the user * agent is able to handle any of the specified types being * used as both a Content-encoding AND a Transfer-encoding * for the same message body. All the Server can do is assume * that the encodings are valid in any/all combinations * and that the user agent can 'Accept' them as either * 'Content' encodings and/or 'Transfer' encodings under * any and all circumstances. This blanket assumption will * cause problems with some release versions of some browsers * because the assumed 'do all' capability is simply not a * reality. * * This version of this module takes the 'What, me worry' approach * and simply uses the accepted method of relying solely on the * 'Accept-encoding: foo, bar' field and also assumes this means * that the User-agent can accept the specified encodings as * either Content-encodings (CE) and/or Transfer-encodings (TE) * under all circumstances and in any combinations that the * Server decides to send. * * It also assumes that the caller has no preference and should * be able to decode any of the specified encodings equally well. */ accept_encoding =3D ap_table_get( r->headers_in, "Accept-Encoding" ); #ifdef USE_MOD_GZIP_DEBUG1 if ( accept_encoding ) fprintf( gzdb_fh1, "%s: 'Accept Encoding:' field seen.\n",cn); else fprintf( gzdb_fh1, "%s: 'Accept Encoding' field NOT seen.\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ /* If Accept-Encoding is applicable to this request...*/ if ( accept_encoding ) { /* ...and if it has the right 'gzip' indicator... */ if ( strstr( accept_encoding, "gzip" ) ) { process =3D 1; /* ...set the 'process' flag TRUE */ } }/* End 'if( accept_encoding )' */ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: 'process' flag =3D %d\n",cn,process); #endif /* USE_MOD_GZIP_DEBUG1 */ if ( !process ) /* Request does not meet criteria for processing... */ { #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: No 'gzip' capability specified by user-agent.= \n",cn); fprintf( gzdb_fh1, "%s: 'process' flag is FALSE.\n",cn); fprintf( gzdb_fh1, "%s: This request will not be processed.\n",cn); fprintf( gzdb_fh1, "%s: Exit > return( DECLINED ) >\n",cn); fclose( gzdb_fh1 ); #endif /* USE_MOD_GZIP_DEBUG1 */ #ifdef MOD_GZIP_USES_APACHE_LOGS /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */ ap_table_setn( r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:NO_GZIP")); #endif /* MOD_GZIP_USES_APACHE_LOGS */ return DECLINED; } else /* 'gzip' designator was seen in 'Accept-Encoding:' field */ { #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: 'gzip' capability specified by user-agent.\n"= ,cn); fprintf( gzdb_fh1, "%s: Assuming OK to proceed...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ } #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Processing file [%s]\n",cn,r->filename); fprintf( gzdb_fh1, "%s: r->finfo.st_size =3D %ld\n", cn, (long) r->finfo.st_size); #endif /* USE_MOD_GZIP_DEBUG1 */ /* * If there is a valid file size already associated with * the request then we can assume the core stat() call succeeded * and that r->filename actually exists. * * If the inbound file size was '0' then we need to do some * verifications of our own. */ if ( r->finfo.st_size > 0 ) { #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Source file length already known...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ input_size =3D (long) r->finfo.st_size; } else /* Do our own checking... */ { /* * See if the requested source file exists... * Be SURE to open the file in BINARY mode... */ file =3D fopen( r->filename, "rb" ); if ( !file ) /* The file cannot be found or opened... */ { #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: The requested source file was NOT FOUND.\n= ",cn); fprintf( gzdb_fh1, "%s: Exit > return( HTTP_NOT_FOUND ) >\n",cn); fclose( gzdb_fh1 ); #endif /* USE_MOD_GZIP_DEBUG1 */ return HTTP_NOT_FOUND; } else /* The file was found and opened OK... */ { #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: The requested source file is now OPEN...\n= ",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ } /* * Move the current file pointer to the end of the file... */ if ( fseek( file, 0, SEEK_END ) ) { #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: ERROR: fseek() call failed...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ fclose( file ); /* FILE is still open so CLOSE it... */ /* fseek() failure could be a platform issue so log the event... *= / ap_log_error( APLOG_MARK,APLOG_NOERRNO|APLOG_ERR, r->server, "mod_gzip: gzip_handler(): fseek() failed for r->filename=3D[%s]", r->filename ); /* Return DECLINED and let default logic finish the request... */ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Exit > return( DECLINED ) >\n",cn); fclose( gzdb_fh1 ); #endif /* USE_MOD_GZIP_DEBUG1 */ #ifdef MOD_GZIP_USES_APACHE_LOGS /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */ ap_table_setn( r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:FSEEK_FAIL= ")); #endif /* MOD_GZIP_USES_APACHE_LOGS */ return DECLINED; } /* * Get the current SIZE of the requested file... */ input_size =3D (long) ftell( file ); if ( input_size =3D=3D -1l ) { #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: ERROR: ftell() call failed...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ fclose( file ); /* FILE is still open so CLOSE it... */ /* ftell() failure could be a platform issue so log the event... *= / ap_log_error( APLOG_MARK,APLOG_NOERRNO|APLOG_ERR, r->server, "mod_gzip: gzip_handler(): ftell() failed for r->filename=3D[%s]", r->filename ); /* Return DECLINED and let default logic finish the request... */ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Exit > return( DECLINED ) >\n",cn); fclose( gzdb_fh1 ); #endif /* USE_MOD_GZIP_DEBUG1 */ #ifdef MOD_GZIP_USES_APACHE_LOGS /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */ ap_table_setn( r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:FTELL_FAIL= ")); #endif /* MOD_GZIP_USES_APACHE_LOGS */ return DECLINED; } /* * Once we have the length just close the file... */ if ( fclose( file ) =3D=3D EOF ) { #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: ERROR: fclose() following ftell() call fai= led...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ /* fclose() failure could be a platform issue so log the event...=20= */ ap_log_error( APLOG_MARK,APLOG_NOERRNO|APLOG_ERR, r->server, "mod_gzip: gzip_handler(): fclose() failed for r->filename=3D[%s]"= , r->filename ); /* Return DECLINED and let default logic finish the request... */ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Exit > return( DECLINED ) >\n",cn); fclose( gzdb_fh1 ); #endif /* USE_MOD_GZIP_DEBUG1 */ #ifdef MOD_GZIP_USES_APACHE_LOGS /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */ ap_table_setn( r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:FCLOSE_FAI= L")); #endif /* MOD_GZIP_USES_APACHE_LOGS */ return DECLINED; } }/* End 'else' */ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: input_size =3D %ld\n", cn,(long)input_size); #endif /* USE_MOD_GZIP_DEBUG1 */ /* * If the file has no length then DECLINE the processing... */ if ( input_size < 1 ) { #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: ERROR: Input file has no valid length.\n",cn)= ; fprintf( gzdb_fh1, "%s: This request will not be processed...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ /* An existing request object with no length is worth a warning... */ ap_log_error( APLOG_MARK,APLOG_NOERRNO|APLOG_WARNING, r->server, "mod_gzip: gzip_handler(): r->filename=3D[%s] has no length", r->filename ); #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Exit > return( DECLINED ) >\n",cn); fclose( gzdb_fh1 ); #endif /* USE_MOD_GZIP_DEBUG1 */ #ifdef MOD_GZIP_USES_APACHE_LOGS /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */ ap_table_setn( r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:NO_I_LEN")); #endif /* MOD_GZIP_USES_APACHE_LOGS */ return DECLINED; } /* * See if the file meets the MINUMUM SIZE requirement... * * Default to 300 bytes as a minimum size requirement for it * to even be worth a compression attempt. This works well as a * minimum for both GZIP and ZLIB which are both LZ77 based and, * as such, always have the potential to actually increase the * size of the file. * * The value is a module global that can be adjusted 'on the fly' * as load conditions change or as required for other reasons. */ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: mod_gzip_minimum_size =3D %ld\n", cn, (long) mod_gzip_minimum_size ); #endif /* USE_MOD_GZIP_DEBUG1 */ if ( input_size < (long) mod_gzip_minimum_size ) { #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: File does not meet the minimum size requireme= nt...\n",cn); fprintf( gzdb_fh1, "%s: Exit > return( DECLINED ) >\n",cn); fclose( gzdb_fh1 ); #endif /* USE_MOD_GZIP_DEBUG1 */ #ifdef MOD_GZIP_USES_APACHE_LOGS /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */ ap_table_setn( r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:TOO_SMALL")); #endif /* MOD_GZIP_USES_APACHE_LOGS */ return DECLINED; } else /* The file is larger than the minimum size requirement... */ { #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: File meets the minimum size requirement.\n",c= n); fprintf( gzdb_fh1, "%s: Assuming OK to proceed...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ } =09/* * If we're only supposed to send header information (HEAD request) * then all we need to do is call ap_send_http_header() at this point * and then return 'OK'... */ if ( r->header_only ) { #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: HEAD request only... ignore body data...\n",c= n); #endif /* USE_MOD_GZIP_DEBUG1 */ /* Set outbound response header fields... */ #ifdef FUTURE_USE ap_set_etag(r); ap_table_setn(r->headers_out, "Accept-Ranges", "bytes"); #endif /* FUTURE_USE */ ap_set_last_modified(r); ap_set_etag(r); ap_table_setn(r->headers_out, "Accept-Ranges", "bytes"); /* Start a timer for this transaction... */ ap_soft_timeout( "mod_gzip: HEAD request handler", r ); #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Call ap_send_http_header()...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ ap_send_http_header(r); #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Back ap_send_http_header()...\n",cn); fprintf( gzdb_fh1, "%s: Call ap_kill_timeout()...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ ap_kill_timeout(r); #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Back ap_kill_timeout()...\n",cn); fprintf( gzdb_fh1, "%s: Exit > return( OK ) >\n",cn); fclose ( gzdb_fh1 ); #endif /* USE_MOD_GZIP_DEBUG1 */ return OK; }/* End 'if( r->header_only )' */ =09/* * We must now encode the requested object... * * Statistically speaking, most 'text/*' pages are * less than 60k. XML documents are an exception. * * If the size of the requested object is less than 60k * then go ahead and compress the file directly to a * small memory buffer. If the requested object is greater * than 60k then go ahead and swap the results to an output * disk file and then send the contents of the result file. * * We can't ever allocate all the memory we want inside of * a Server task thread so there must always be this kind * of 'decision' making about when we can compress to * a memory buffer ( Less than 60k ) and when we must * compress to DISK. ( Greater than 60k ). * * There is a trade-off here between running the risk of * too many tasks stealing away all the heap space and * still maintaining performance. Given all the variables * involved such as the true efficiency of the compression * algorithm(s) and the speed of the CPU and the amount of * memory/disk space available there is no 'real' answer to * this dilemma other than relying on statistical data * and empirical observations. The 60k limit on in-memory * compression seems to strike a good balance and performs * incredibly well under the heaviest of loads. * * At all times, the greatest benefit being gained is the * appreciable reduction of data that must actually be * sent by the TCP/IP sub-system and the reduced usage * of those resources to perform the transmission task(s), * * The key, then, is to always strive for a balance where * the time and resource usage it takes to compress a * deliverable object will always be less than the processor * burden that would otherwise be realized by handing the * full, uncompressed object to the TCP/IP sub-system which * always extend the time that the thread and all its * locked resources must be maintained as well as the * overhead for keeping a connection active any longer * than is absolutely necessary. * * As long as the resource usage it takes to accomplish * a significant reduction in the amount of data that * must actually be processed by the remainder of the * HTTP task thread and the TCP/IP sub-system itself * is always less than the processor burden seen by * NOT doing so then we are always 'ahead of the game'. */ /* Prepare the GZIP memory context control structure... */ gzp =3D (GZP_CONTROL*) malloc( sizeof( GZP_CONTROL )); if ( !gzp ) { #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: ERROR: Cannot allocate GZP memory...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ /* malloc() failure could be a platform issue so log the event... */ ap_log_error( APLOG_MARK,APLOG_NOERRNO|APLOG_ERR, r->server, "mod_gzip: gzip_handler(): gzp malloc(%ld) failed for r->filename=3D[= %s]", (long) sizeof( GZP_CONTROL ), r->filename ); /* Return DECLINED and let default logic finish the request... */ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Exit > return( DECLINED ) >\n",cn); fclose( gzdb_fh1 ); #endif /* USE_MOD_GZIP_DEBUG1 */ #ifdef MOD_GZIP_USES_APACHE_LOGS /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */ ap_table_setn( r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:GZP_ALLOC_FAI= L")); #endif /* MOD_GZIP_USES_APACHE_LOGS */ return DECLINED; } /* * Increase the total number of requests that have entered * the encoding processing state. * * Since this number is used to help build unique workfile * names make sure it wraps and never overflows no matter * how long the server has been running. */ mod_gzip_total_requests_processed++; /* Increase total */ if ( mod_gzip_total_requests_processed > 999999999L ) { mod_gzip_total_requests_processed =3D 1; /* Wrap */ } /* * See if the object size exceeds the current MAXIMUM size * to use for in-memory compression... * * See notes above about a range of 60k or so being the best * value for heavy load conditions. * * This number is currently a global so it can be changed * 'on the fly' and can 'breathe' as the load changes. * It should probably become a thread specific variable * so each task can have its 'own' max value depending * on current load conditions. */ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: mod_gzip_inmem_maxsize =3D %ld\n", cn, (long) mod_gzip_inmem_maxsize ); #endif /* USE_MOD_GZIP_DEBUG1 */ if ( input_size <=3D (long) mod_gzip_inmem_maxsize ) { /* The input file is small enough to compress directly */ /* to an in-memory output buffer... */ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Input file is small enough for in-memory comp= ression.\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ strcpy( gzp->input_filename, r->filename); strcpy( gzp->output_filename, "" ); /* Not used */ gzp->decompress =3D 0; /* Perform encoding */ gzp->input_ismem =3D 0; /* Input is a disk file */ gzp->output_ismem =3D 1; /* Output is a memory buffer */ /* * Allocate a memory buffer to hold compressed output. * * For now this is borrowed from the heap for only * the lifetime of this function call. If the stack * can handle the current in-memory MAXSIZE then * that will work just as well. * * Add at least 1000 bytes in case the compression * algorithm(s) actually expands the file ( which is * not likely but is always a possibility when using * any LZ77 based compression such as GZIP or ZLIB ) */ gz1_ismem_obuf =3D (char *) malloc( input_size + 1000 ); if ( !gz1_ismem_obuf ) { /* * There wasn't enough memory left for another * in-memory compression buffer so default to using * an output disk file instead... */ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: ERROR: Cannot allocate GZP memory...\n",cn= ); fprintf( gzdb_fh1, "%s: Defaulting to output file method... \n",cn= ); #endif /* USE_MOD_GZIP_DEBUG1 */ gzp->output_ismem =3D 0; /* Switch to using a disk file */ } else /* We got the memory we need for in-memory compression... */ { memset( gz1_ismem_obuf, 0, ( input_size + 1000 ) ); /* Set OUTPUT buffer control variables... */ gzp->output_ismem_obuf =3D gz1_ismem_obuf; gzp->output_ismem_obuflen =3D input_size + 1000; } }/* End 'if ( input_size <=3D mod_gzip_inmem_maxsize )' */ /* * If we are unable ( or it is unadvisable ) to use * an in-memory output buffer at this time then the * 'gzp->output_ismem' flag will still be ZERO at this point. */ if ( gzp->output_ismem !=3D 1 ) { /* * The input file is NOT small enough to compress to an * in-memory output buffer or it is unadvisable to do * so at this time so just use an output file... */ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Input file too big for in-memory compression.= \n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ strcpy( gzp->input_filename, r->filename ); /* * NOTE: workfiles must be created in a directory that is * known to be readable/writable by current user id. * For now we just default to Server directory. * * TODO: Add config parms and/or environment variable * and/or special uid/gid to next version. * * Get the current process and thread IDs... */ #ifdef WIN32 process_id =3D (long) GetCurrentProcessId(); thread_id =3D (long) GetCurrentThreadId(); #else /* !WIN32 */ process_id =3D (long) getpid(); thread_id =3D (long) process_id; /* TODO: Add pthreads call */ #endif /* WIN32 */ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: process_id =3D %ld\n",cn, process_id ); fprintf( gzdb_fh1, "%s: thread_id =3D %ld\n",cn, thread_id ); #endif /* USE_MOD_GZIP_DEBUG1 */ /* * Use the PROCESS + THREAD ID's and the current USN * ( Unique Sequence Number ) transaction ID to create * a one-time only unique output workfile name... */ /* * COMPRESSION OBJECT CACHE * * TODO: Obviously one place to add the compression cache * logic is right here. If there is already a pre-compressed * version of the requested entity sitting in the special * compression cache and it is 'fresh' then go ahead and * send it as the actual response. Add a CRC/MD5 checksum * to the stored compression object(s) so we can quickly * determine if the compressed object is 'fresh'. Relying * on Content-length and/or modification time/date won't handle * all possible expiration scenarios for compressed objects. */ /* Use Server home dir... */ server_root =3D ap_server_root_relative( r->pool, "" ); /* There should already be a 'slash' on the end of 'server_root' */ sprintf( gzp->output_filename, "%s_%ld_%ld_%ld.wrk", server_root, (long) process_id, (long) thread_id, (long) mod_gzip_total_requests_processed /* Unique Sequence Number */ ); gzp->decompress =3D 0; /* Perform encoding */ gzp->input_ismem =3D 0; /* Input is a disk file */ gzp->output_ismem =3D 0; /* Output is a disk file */ gz1_ismem_obuf =3D 0; /* Make sure this is NULL */ /* Set INPUT buffer control variables... */ gzp->input_ismem_ibuf =3D 0; gzp->input_ismem_ibuflen =3D 0; /* Set OUTPUT buffer control variables... */ gzp->output_ismem_obuf =3D 0; /* Not used for this method */ gzp->output_ismem_obuflen =3D 0; /* Not used for this method */ }/* End 'else' */ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: gzp->decompress =3D %d\n" ,cn,gzp->decompr= ess); fprintf( gzdb_fh1, "%s: gzp->input_ismem =3D %d\n", cn,gzp->input_i= smem); fprintf( gzdb_fh1, "%s: gzp->output_ismem =3D %d\n", cn,gzp->output_= ismem); fprintf( gzdb_fh1, "%s: gzp->input_filename =3D [%s]\n",cn,gzp->input_f= ilename); fprintf( gzdb_fh1, "%s: gzp->output_filename =3D [%s]\n",cn,gzp->output_= filename); fprintf( gzdb_fh1, "%s: Call gzp_main()...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ rc =3D gzp_main( gzp ); /* Perform the compression... */ output_size =3D (long) gzp->bytes_out; #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Back gzp_main()...\n",cn); fprintf( gzdb_fh1, "%s: input_size =3D %ld\n",cn,(long)input_size); fprintf( gzdb_fh1, "%s: output_size =3D %ld\n",cn,(long)output_size); fprintf( gzdb_fh1, "%s: gzp->bytes_out =3D %ld\n",cn,(long)gzp->bytes= _out); fprintf( gzdb_fh1, "%s: Bytes saved =3D %ld\n",cn, (long)input_size-gzp->bytes_out ); #endif /* USE_MOD_GZIP_DEBUG1 */ /* Compute the compresion ratio for access.log and */ /* internal statistics update... */ compression_ratio =3D 0; /* Reset */ /* Prevent 'Divide by zero' error... */ if ( ( input_size > 0 ) && ( output_size > 0 ) ) { compression_ratio =3D 100 - (int) ( output_size * 100L / input_size ); } #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Compression ratio =3D %ld percent\n",cn, (long) compression_ratio ); #endif /* USE_MOD_GZIP_DEBUG1 */ /* * Evaluate the compression result(s)... * * If the compression pass failed then the output length * will be ZERO bytes... */ if ( output_size < 1 ) { #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Compressed version has no length.\n",cn); fprintf( gzdb_fh1, "%s: Sending the original version uncompressed...\= n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ /* Subtract this transaction from the count of requests */ /* actually encoded... */ mod_gzip_total_requests_processed--; /* Decrease total */ /* Prevent underflow... */ if ( mod_gzip_total_requests_processed < 0 ) { mod_gzip_total_requests_processed =3D 0; /* Wrap */ } #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Exit > return( DECLINED ) >\n",cn); fclose( gzdb_fh1 ); #endif /* USE_MOD_GZIP_DEBUG1 */ #ifdef MOD_GZIP_USES_APACHE_LOGS /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */ ap_table_setn( r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:NO_O_LEN")); #endif /* MOD_GZIP_USES_APACHE_LOGS */ return DECLINED; } /* * If we reach this point then the compressed version has * a valid length. Time to see if it it's worth sending. * * If the original file is SMALLER than the COMPRESSED * version ( not likely but possible with LZ77 ) then * just punt and send the original file... */ if ( output_size > input_size ) { #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Compressed version is larger than original.\n= ",cn); fprintf( gzdb_fh1, "%s: Sending the original version uncompressed...\= n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ /* Subtract this transaction from the count of requests */ /* actually encoded... */ mod_gzip_total_requests_processed--; /* Decrease total */ /* Prevent underflow... */ if ( mod_gzip_total_requests_processed < 0 ) { mod_gzip_total_requests_processed =3D 0; /* Wrap */ } #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Exit > return( DECLINED ) >\n",cn); fclose( gzdb_fh1 ); #endif /* USE_MOD_GZIP_DEBUG1 */ #ifdef MOD_GZIP_USES_APACHE_LOGS /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */ ap_table_setn( r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:ORIGINAL_SMAL= LER")); #endif /* MOD_GZIP_USES_APACHE_LOGS */ return DECLINED; } else /* Compressed version is smaller than original... */ { #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Compressed version is smaller than original.\= n",cn); fprintf( gzdb_fh1, "%s: Sending the compressed version...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ } /* * If an output workfile was used then make SURE it is going * to reopen before beginning the transmit phase. * * If we begin the transmit phase before discovering a problem * re-opening the workfile then we have lost the chance to * DECLINE the processing and allow the default logic to * deliver the requested object. */ if ( !gzp->output_ismem ) /* Workfile was used... */ { #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Opening compressed output file [%s]...\n", cn, gzp->output_filename ); #endif /* USE_MOD_GZIP_DEBUG1 */ ifh =3D fopen( gzp->output_filename, "rb" ); /* Open in BINARY mode *= / if ( !ifh ) /* The file failed to open... */ { #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: ERROR: Cannot re-open file [%s]\n", cn,gzp->output_filename); #endif /* USE_MOD_GZIP_DEBUG1 */ /* * The workfile was created OK but now will not re-open. * This is worth a strike in the ERROR log. Do it before * releasing the local GZP control structure so the file * name can be printed in the log... */ ap_log_error( APLOG_MARK,APLOG_NOERRNO|APLOG_ERR, r->server, "mod_gzip: gzip_handler(): Cannot re-open gzp->output_filename=3D[= %s]", gzp->output_filename ); /* Free the GZP control structure... */ free( gzp ); /* Subtract this transaction from the count of requests */ /* actually encoded... */ mod_gzip_total_requests_processed--; /* Prevent underflow... */ if ( mod_gzip_total_requests_processed < 0 ) { mod_gzip_total_requests_processed =3D 0; /* Wrap */ } /* Return DECLINED and let default logic finish the request... */ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Exit > return( DECLINED ) >\n",cn); fclose( gzdb_fh1 ); #endif /* USE_MOD_GZIP_DEBUG1 */ #ifdef MOD_GZIP_USES_APACHE_LOGS /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */ ap_table_setn( r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:WORK_OPENF= AIL")); #endif /* MOD_GZIP_USES_APACHE_LOGS */ return DECLINED; }/* End 'if ( !ifh )' */ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Workile re-opened OK...\n",cn); fprintf( gzdb_fh1, "%s: Starting transmit phase...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ }/* End 'if ( !gzp->output_ismem )' */ /* * We are ready to send content so update the "Content-length:" * response field and send the HTTP header. We don't need to * worry about setting the "Content-type:" field since we are * simply accepting the value that was passed to us as indicated * by the inbound r->content_type string. The "Content-type:" * field never changes even when multiple encodings have been * applied to the content itself. * * This version does not make any attempt to use 'Chunked' * transfer encoding since there are so many user agents that * do not support it and when Content-length is known prior * to header transmission ( as is always the case with this * code ) then there is simply no reason to even think about * using the slower and more problematic 'Chunked' encoding * transfer method. */ /* * Set relevant outbound response header fields... */ ap_set_last_modified(r); #ifdef FUTURE_USE ap_set_etag(r); ap_table_setn(r->headers_out, "Accept-Ranges", "bytes"); #endif r->content_encoding =3D "gzip"; /* * Start a timer for this transaction... */ ap_soft_timeout( "mod_gzip: Encoded data transmit", r ); /* * Return the length of the compressed output in * the response header. * * See notes above about there never being a requirement * to use 'Chunked' transfer encoding since the content * length is always 'known' prior to transmission. */ sprintf( content_length, "%ld", output_size ); ap_table_set (r->headers_out, "Content-Length", content_length ); #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Call ap_send_http_header()...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ ap_send_http_header(r); #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Back ap_send_http_header()...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ =09/* * Send the actual compressed response... * * If the requested object was small enough to fit into * our special in-memory output space then send the result * directly from memory. If the requested object exceeded * the minimum size for in-memory compression then an output * file was used so re-open and send the results file... */ if ( gzp->output_ismem ) { /* Send the in-memory output buffer... */ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Sending the in-memory output buffer...\n",cn)= ; #endif /* This module can use either ap_send_mmap() or ap_rwrite()... */ #ifdef MOD_GZIP_USES_AP_SEND_MMAP /* Use ap_send_mmap() call to send the data... */ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Call ap_send_mmap( gz1_ismem_obuf, bytes=3D%l= d )...\n", cn, (long)output_size ); #endif ap_send_mmap( gz1_ismem_obuf, r, 0, output_size ); #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Back ap_send_mmap( gz1_ismem_obuf, bytes=3D%l= d )...\n", cn, (long)output_size ); #endif #else /* !MOD_GZIP_USES_AP_SEND_MMAP */ /* Use ap_rwrite() call to send the data... */ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Call ap_rwrite( gz1_ismem_obuf, bytes=3D%ld )= ...\n", cn, (long)output_size ); #endif ap_rwrite( gz1_ismem_obuf, output_size, r ); #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Back ap_rwrite( gz1_ismem_obuf, bytes=3D%ld )= ...\n", cn, (long)output_size ); #endif #endif /* MOD_GZIP_USES_AP_SEND_MMAP */ /* Stop the timer... */ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Call ap_kill_timeout()...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ ap_kill_timeout(r); #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Back ap_kill_timeout()...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ /* Free the local memory buffer allocation... */ if ( gz1_ismem_obuf ) { free( gz1_ismem_obuf ); gz1_ismem_obuf =3D 0; } } else /* Output workfile was used so send the contents... */ { /* * NOTE: The workfile was already 're-opened' up above * before the transmit phase began so that we still had * the chance to return DECLINED if, for some reason, the * workfile could not be re-opened. */ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: sizeof( tmp ) =3D %d\n",cn,sizeof(tmp)= ); fprintf( gzdb_fh1, "%s: Transmit buffer size =3D %d\n",cn,sizeof(tmp)= ); fprintf( gzdb_fh1, "%s: Sending compressed output file...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ for (;;) { bytesread =3D fread( tmp, 1, sizeof( tmp ), ifh ); #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Back fread(): bytesread=3D%d\n",cn,bytesr= ead); #endif /* USE_MOD_GZIP_DEBUG1 */ if ( bytesread < 1 ) break; /* File is exhausted... We are done..= .*/ /* This module can use either ap_send_mmap() or ap_rwrite()... */ #ifdef MOD_GZIP_USES_AP_SEND_MMAP /* Use ap_send_mmap() call to send the data... */ ap_send_mmap( tmp, r, 0, bytesread ); #else /* !MOD_GZIP_USES_AP_SEND_MMAP */ /* Use ap_rwrite() call to send the data... */ ap_rwrite( tmp, bytesread, r ); #endif /* MOD_GZIP_USES_AP_SEND_MMAP */ } #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Done Sending compressed output file...\n",cn)= ; fprintf( gzdb_fh1, "%s: Closing workfile [%s]...\n", cn, gzp->output_filename ); #endif /* USE_MOD_GZIP_DEBUG1 */ fclose( ifh ); /* Close the input file */ /* Stop the timer before attempting to delete the workfile... */ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Call ap_kill_timeout()...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ ap_kill_timeout(r); #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Back ap_kill_timeout()...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ /* Delete the workfile if 'keep' flag is OFF... */ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: mod_gzip_keep_work_files =3D %d\n", cn, mod_gzip_keep_work_files ); #endif /* USE_MOD_GZIP_DEBUG1 */ if ( !mod_gzip_keep_work_files ) /* Default */ { #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Deleting workfile [%s]...\n", cn, gzp->output_filename ); #endif /* USE_MOD_GZIP_DEBUG1 */ #ifdef WIN32 DeleteFile( gzp->output_filename ); #else /* !WIN32 */ unlink( gzp->output_filename ); #endif /* WIN32 */ } else /* Keep all work files... */ { #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Keeping workfile [%s]...\n", cn, gzp->output_filename ); #endif /* USE_MOD_GZIP_DEBUG1 */ } }/* End 'else' that sends compressed workfile */ /* * The compressed object has been sent... * * Update the internal statistics... */ mod_gzip_total_bytes_processed_raw +=3D input_size; mod_gzip_total_bytes_processed_compressed +=3D output_size; /* * Reset both values if either one overflows... */ if ( ( mod_gzip_total_bytes_processed_raw > 999999999L ) || ( mod_gzip_total_bytes_processed_compressed > 999999999L ) ) { mod_gzip_total_bytes_processed_raw =3D 0L; mod_gzip_total_bytes_processed_compressed =3D 0L; } /* * Free the local GZP control structure... */ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Call free( gzp )...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ free( gzp ); #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Back free( gzp )...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ #ifdef MOD_GZIP_USES_APACHE_LOGS /*--------------------------------------------------------------------- * Make compression information available to standard Apache logs... *--------------------------------------------------------------------- * * If the compression was successful and the reduced content * was delivered OK then update some internal module 'notes' * which allow anyone to display the compression results in * standard Apache logs using any format they desire. * * Additional notes about logging compression information... * * The Apache LogFormat directive is unable to actually display * the 'percent' symbol since it is used exclusively as a 'pickup' * character in the formatting string and cannot be 'escaped' so * all logging of compression ratios cannot use the PERCENT symbol. * *--------------------------------------------------------------------- */ /*--------------------------------------------------------------------- * Additional NOTES on enabling the mod_gzip log output... *--------------------------------------------------------------------- * * The following comments have been 'cut and pasted' from * a working httpd.conf file on an Apache Server that is * mod_gzip and adding compression detail to Apache's access.log * * It is also the same information available on the mod_gzip * FAQ page which is located at the following address... * * http://www.RemoteCommunications.com/apache/mod_gzip/mod_gzip_faq.htm * * If desired, you should be able to simply 'cut and paste' * the following relevant entries directly into your httpd.conf * file to enable compression logging in the manner described. * * Only the few lines without the pound sign comment characters * need to be added to http.conf itself. * *--------------------------------------------------------------------- # mod_gzip log formats... # mod_gzip makes a number of statistical items for each transaction # available through the use of Apache's 'LogFormat' directives which # can be specified in the httpd.conf Apache config file # mod_gzip uses the standard NOTES interface to allow compression # information t be added to the standard Apache log files. # Standard NOTES may be added to Apache logs using the following syntax # in any LogFormat directive... # * %...{Foobar}n: The contents of note "Foobar" from another module. # Additional notes about logging compression information... # The Apache LogFormat directive is unable to actually display # the 'percent' symbol since it is used exclusively as a 'pickup' # character in the formatting string and cannot be 'escaped' so # all logging of compression ratios cannot use the PERCENT symbol. # Use ASCII 'pct.' designation instead for all PERCENTAGE values. # Example: This will display the compression ratio percentage along # with the standard CLF ( Common Log Format ) information... # Available 'mod_gzip' compression information 'notes'... # # %{mod_gzip_result}n - A short 'result' message. Could be OK or DECLIN= ED, etc. # %{mod_gzip_input_size}n - The size ( in bytes ) of the requested obje= ct. # %{mod_gzip_output_size}n - The size ( in bytes ) of the compressed ve= rsion. # %{mod_gzip_compression_ration}n - The compression rate achieved. LogFormat "%h %l %u %t \"%r\" %>s %b mod_gzip: %{mod_gzip_compression_r= atio}npct." common_with_mod_gzip_info1 LogFormat "%h %l %u %t \"%r\" %>s %b mod_gzip: %{mod_gzip_result}n In:%= {mod_gzip_input_size}n Out:%{mod_gzip_output_size}n:%{mod_gzip_compression_r= atio}npct." common_with_mod_gzip_info2 # If you create your own custom 'LogFormat' lines don't forget that # the entire LogFormat line must be encased in quote marks or you # won't get the right results. The visible effect of there not being # and end-quote on a LogFormat line is that the NAME you are choosing # for the LogFormat line is the only thing that will appear in the # log file that tries to use the unbalanced line. # Also... when using the %{mod_gzip_xxxxx}n note references in your # LogFormat line don't forget to add the lowercase letter 'n' after # the closing bracket to indicate that this is a module 'note' value. # Once a LogFormat directive has been added to your httpd.conf file # which displays whatever level of compression information desired # simply use the 'name' associated with that LogFormat line in # the 'CustomLog' directive for 'access.log'. # Example: The line below simply changes the default access.log format # for Apache to the special mog_gzip information record defined above..= . # CustomLog logs/access.log common CustomLog logs/access.log common_with_mod_gzip_info2 # Using the 'common_with_mod_gzip_info1' LogFormat line for Apache's # normal access.log file produces the following results in the access.l= og # file when a gigantic 679,188 byte online CD music collection HTML # document called 'music.htm' is requested and the Server delivers the # file via mod_gzip compressed 93 percent down to only 48,951 bytes... # 216.20.10.1 [12/Oct...] "GET /music.htm HTTP/1.1" 200 48951 mod_gzip:= 93pct. # The line below shows what will appear in the Apache access.log file # if the more detailed 'common_with_mod_gzip_info2' LogFormat line is u= sed. # The line has been intentionally 'wrapped' for better display below # but would normally appear as a single line entry in access.log. # 216.20.10.1 [12/Oct...] "GET /music.htm HTTP/1.1" 200 48951 # mod_gzip: OK In:679188 Out:48951:93pct. # The 'OK' result string shows that the compression was successful. # The 'In:' value is the size (in bytes) of the requested file and # the 'Out:' value is the size (in bytes) after compression followed # by a colon and a number showing that the document was compressed # 93 percent before being returned to the user. *--------------------------------------------------------------------- * End of mod_gzip logfile format notes. */ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Updating module 'notes'...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ ap_table_setn( r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"OK")); sprintf( log_info,"%d", (int) input_size ); ap_table_setn( r->notes,"mod_gzip_input_size",ap_pstrdup(r->pool,log_inf= o)); sprintf( log_info,"%d", (int) output_size ); ap_table_setn( r->notes,"mod_gzip_output_size",ap_pstrdup(r->pool,log_in= fo)); sprintf( log_info,"%d", (int) compression_ratio ); ap_table_setn( r->notes,"mod_gzip_compression_ratio",ap_pstrdup(r->pool,= log_info)); /*---------------------------------------------------------------------*= / #endif /* MOD_GZIP_USES_APACHE_LOGS */ /* * Return OK to the Server to indicate SUCCESS... */ #ifdef USE_MOD_GZIP_DEBUG1 fprintf( gzdb_fh1, "%s: Exit > return( OK ) >\n",cn); #ifdef USE_MOD_GZIP_MEMORY_CHECK mod_gzip_show_memory_status( "After request processing", gzdb_fh1 ); #endif /* USE_MOD_GZIP_MEMORY_CHECK */ fclose( gzdb_fh1 ); #endif /* USE_MOD_GZIP_DEBUG1 */ return OK; }/* End of gzip_handler() */ /*--------------------------------------------------------------------------= */ /*=20 * This function is called during server initialisation. Any information * that needs to be recorded must be in static cells, since there's no * configuration record. * * There is no return value. */ /*--------------------------------------------------------------------------= */ static void gzip_init(server_rec *s, pool *p) { /* * Set up any module cells that ought to be initialised. */ #ifdef USE_MOD_GZIP_CONSOLE_DEBUG1 printf ("mod_gzip.c: gzip_init(): Entry point\n"); printf ("mod_gzip.c: gzip_init(): Call setup_module_cells()...\n"); #endif /* USE_MOD_GZIP_CONSOLE_DEBUG1 */ setup_module_cells(); #ifdef USE_MOD_GZIP_CONSOLE_DEBUG1 printf ("mod_gzip.c: gzip_init(): Back setup_module_cells()...\n"); printf ("mod_gzip.c: gzip_init(): Exit > return( void ) >\n"); #endif }/* End of gzip_init() */ /*--------------------------------------------------------------------------= */ /* =20= */ /* Now the list of content handlers available from this module. =20= */ /* =20= */ /*--------------------------------------------------------------------------= */ /*=20 * List of content handlers our module supplies. Each handler is defined by * two parts: a name by which it can be referenced (such as by * {Add,Set}Handler), and the actual routine name. The list is terminated b= y * a NULL block, since it can be of variable length. * * Note that content-handlers are invoked on a most-specific to least-specif= ic * basis; that is, a handler that is declared for "text/plain" will be * invoked before one that was declared for "text / *". Note also that * if a content-handler returns anything except DECLINED, no other * content-handlers will be called. */ /*--------------------------------------------------------------------------= */ static const command_rec gzip_cmds[] =3D { /* No directives are required at this time */ {NULL} }; static const handler_rec gzip_handlers[] =3D { /* * Add the compressible mime types we should deal with * to this lookup table. This version of this module * just does the 'basics' and will compress all 'text/*' * based mime types. The FILE type has little to do with * whether the requested object will be compressed. If * the server determines that the MIME type matches any * of the types specified here then the content will * compressed on its way back to the caller. */ {"text/*", gzip_handler}, {NULL} }; /*--------------------------------------------------------------------------= */ /* =20= */ /* Finally, the list of callback routines and data structures that =20= */ /* provide the hooks into our module from the other parts of the server. =20= */ /* =20= */ /*--------------------------------------------------------------------------= */ /*=20 * Module definition for configuration. If a particular callback is not * needed, replace its routine name below with the word NULL. * * The number in brackets indicates the order in which the routine is called * during request processing. Note that not all routines are necessarily * called (such as if a resource doesn't have access restrictions). */ /*--------------------------------------------------------------------------= */ module MODULE_VAR_EXPORT gzip_module =3D { STANDARD_MODULE_STUFF, gzip_init, /* module initializer */ NULL,=09=09=09=09=09 /* per-directory config creator */ NULL,=09=09=09=09=09 /* dir config merger */ NULL,=09=09=09=09=09 /* server config creator */ NULL,=09=09=09=09=09 /* server config merger */ gzip_cmds, /* command table */ gzip_handlers, /* [7] list of handlers */ NULL,=09=09=09=09=09 /* [2] filename-to-URI translation */ NULL,=09=09=09=09=09 /* [5] check/validate user_id */ NULL,=09=09=09=09=09 /* [6] check user_id is valid *here* */ NULL,=09=09=09=09=09 /* [4] check access by host address */ NULL,=09=09=09=09=09 /* [7] MIME type checker/setter */ NULL,=09=09=09=09=09 /* [8] fixups */ NULL,=09=09=09=09=09 /* [10] logger */ #if MODULE_MAGIC_NUMBER >=3D 19970103 NULL,=09=09=09=09=09 /* [3] header parser */ #endif #if MODULE_MAGIC_NUMBER >=3D 19970719 NULL,=09=09=09=09=09 /* process initializer */ #endif #if MODULE_MAGIC_NUMBER >=3D 19970728 NULL,=09=09=09=09=09 /* process exit/cleanup */ #endif #if MODULE_MAGIC_NUMBER >=3D 19970902 NULL=09=09=09=09=09 /* [1] post read_request handling */ #endif }; /* Utility sub-routines... */ int mod_gzip_send_html_command_response( request_rec *r, /* Request record */ char *tmp, /* Response to send */ FILE *gzdb_fh1 /* Always NULL if no DEBUG is used */ ) { /* Generic command response transmitter... */ int tmplen=3D0; char content_type[90]; char content_length[20]; #ifdef USE_MOD_GZIP_DEBUG1 char cn[]=3D"mod_gzip.c: mod_gzip_send_html_command_response()"; #endif /* Start... */ #ifdef USE_MOD_GZIP_DEBUG1 if ( gzdb_fh1 ) fprintf( gzdb_fh1, "%s: Entry...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ /* Add the length of the response to the output header... */ /* The third parameter to ap_table_set() MUST be a string. */ tmplen =3D strlen( tmp ); sprintf( content_length, "%d", tmplen ); #ifdef USE_MOD_GZIP_DEBUG1 if ( gzdb_fh1 ) fprintf( gzdb_fh1, "%s: content_length =3D [%s]\n",cn,conte= nt_length); #endif /* USE_MOD_GZIP_DEBUG1 */ ap_table_set( r->headers_out, "Content-Length", content_length ); /* Make sure the content type matches this response... */ strcpy( content_type, "text/html" ); r->content_type =3D content_type; #ifdef USE_MOD_GZIP_DEBUG1 if ( gzdb_fh1 ) fprintf( gzdb_fh1, "%s: content_type =3D [%s]\n",cn,content= _type); #endif /* USE_MOD_GZIP_DEBUG1 */ /* Start a timer... */ #ifdef USE_MOD_GZIP_DEBUG1 if ( gzdb_fh1 ) fprintf( gzdb_fh1, "%s: Call ap_soft_timeout()...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ ap_soft_timeout( "mod_gzip: mod_gzip_send_html_command", r ); #ifdef USE_MOD_GZIP_DEBUG1 if ( gzdb_fh1 ) fprintf( gzdb_fh1, "%s: Back ap_soft_timeout()...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ =20 #ifdef MOD_GZIP_COMMANDS_USE_LAST_MODIFIED /* Set the 'Last modified' stamp to current time/date... */ #ifdef USE_MOD_GZIP_DEBUG1 if ( gzdb_fh1 ) fprintf( gzdb_fh1, "%s: Call ap_set_last_modified()...\n",c= n); #endif /* USE_MOD_GZIP_DEBUG1 */ ap_set_last_modified(r); /* TODO: Add 'no-cache' option(s) to mod_gzip command responses */ /* so user doesn't have hit reload to get fresh data. */ #ifdef USE_MOD_GZIP_DEBUG1 if ( gzdb_fh1 ) fprintf( gzdb_fh1, "%s: Back ap_set_last_modified()...\n",c= n); #endif /* USE_MOD_GZIP_DEBUG1 */ #endif /* MOD_GZIP_COMMANDS_USE_LAST_MODIFIED */ /* Send the HTTP response header... */ #ifdef USE_MOD_GZIP_DEBUG1 if ( gzdb_fh1 ) fprintf( gzdb_fh1, "%s: Call ap_send_http_header()...\n",cn= ); #endif /* USE_MOD_GZIP_DEBUG1 */ ap_send_http_header(r); #ifdef USE_MOD_GZIP_DEBUG1 if ( gzdb_fh1 ) fprintf( gzdb_fh1, "%s: Back ap_send_http_header()...\n",cn= ); #endif /* USE_MOD_GZIP_DEBUG1 */ /* Send the response BODY... */ #ifdef USE_MOD_GZIP_DEBUG1 if ( gzdb_fh1 ) fprintf( gzdb_fh1, "%s: Sending response...\n%s\n",cn,tmp); #endif /* USE_MOD_GZIP_DEBUG1 */ #ifdef MOD_GZIP_USES_AP_SEND_MMAP /* Use ap_send_mmap() call to send the data... */ ap_send_mmap( tmp, r, 0, tmplen ); #else /* !MOD_GZIP_USES_AP_SEND_MMAP */ /* Use ap_rwrite() call to send the data... */ ap_rwrite( tmp, tmplen, r ); #endif /* MOD_GZIP_USES_AP_SEND_MMAP */ /* Clean up and exit... */ #ifdef USE_MOD_GZIP_DEBUG1 if ( gzdb_fh1 ) fprintf( gzdb_fh1, "%s: Call ap_kill_timeout()...\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ ap_kill_timeout(r); #ifdef USE_MOD_GZIP_DEBUG1 if ( gzdb_fh1 ) fprintf( gzdb_fh1, "%s: Back ap_kill_timeout()...\n",cn); if ( gzdb_fh1 ) fprintf( gzdb_fh1, "%s: Exit > return( OK ) >\n",cn); #endif /* USE_MOD_GZIP_DEBUG1 */ return OK; }/* End of mod_gzip_send_html_command_response() */ #ifdef USE_MOD_GZIP_DEBUG1 long aphymem_last =3D 0; long apagmem_last =3D 0; long avirmem_last =3D 0; long aphymem_diff =3D 0; long apagmem_diff =3D 0; long avirmem_diff =3D 0; int mod_gzip_show_memory_status( char *msg1, /* Test point indication string */ FILE *gzdb_fh1 /* Always NULL if no DEBUG is used */ ) { #ifdef WIN32 MEMORYSTATUS ms; #endif /* Start... */ #ifdef WIN32 ms.dwLength =3D sizeof( MEMORYSTATUS ); GlobalMemoryStatus( &ms ); fprintf(gzdb_fh1,"--------------------------------------------------------\= n"); fprintf(gzdb_fh1,"MEMORY STATUS CHECKPOINT: %s\n", msg1 ); fprintf(gzdb_fh1,"--------------------------------------------------------\= n"); fprintf(gzdb_fh1,"Percent of memory in use : %ld%%\n", ms.dwMemoryLoad=20= ); fprintf(gzdb_fh1,"--------------------------------------------------------\= n"); fprintf(gzdb_fh1,"Total Physical Memory: %ld bytes\n", ms.dwTotalPhys =20= ); fprintf(gzdb_fh1,"Total Paging Memory: %ld bytes\n", ms.dwTotalPageFi= le); fprintf(gzdb_fh1,"Total Virtual Memory: %ld bytes\n", ms.dwTotalVirtua= l ); fprintf(gzdb_fh1,"--------------------------------------------------------\= n"); fprintf(gzdb_fh1,"Available Physical Memory: %ld bytes\n", ms.dwAvailPhys =20= ); fprintf(gzdb_fh1,"Available Paging Memory: %ld bytes\n", ms.dwAvailPageFi= le); fprintf(gzdb_fh1,"Available Virtual Memory: %ld bytes\n", ms.dwAvailVirtua= l ); fprintf(gzdb_fh1,"---------------------------------------------------------= \n"); /* Show the difference in the 'Available' category since last call.. */ if ( aphymem_last !=3D 0 ) /* We have been called at least once... */ { aphymem_diff =3D (long) ms.dwAvailPhys - aphymem_last; apagmem_diff =3D (long) ms.dwAvailPageFile - apagmem_last; avirmem_diff =3D (long) ms.dwAvailVirtual - avirmem_last; } fprintf(gzdb_fh1,"Available Physical (diff): %ld bytes\n", aphymem_diff ); fprintf(gzdb_fh1,"Available Paging (diff): %ld bytes\n", apagmem_diff ); fprintf(gzdb_fh1,"Available Virtual (diff): %ld bytes\n", avirmem_diff ); fprintf(gzdb_fh1,"---------------------------------------------------------= \n"); /* Record the current numbers as the 'last' values for next call... */ aphymem_last =3D (long) ms.dwAvailPhys; apagmem_last =3D (long) ms.dwAvailPageFile; avirmem_last =3D (long) ms.dwAvailVirtual; #else /* !WIN32 */ /* TODO: Add UNIX equivalent of Win32 'GlobalMemoryStatus()' call */ #endif /* WIN32 */ return 0; }/* End of 'mod_gzip_show_memory_status()' */ #endif /* USE_MOD_GZIP_DEBUG1 */ /*--------------------------------------------------------------------------= */ /* ALL SOURCE CODE BELOW THIS POINT IS COMPRESSION SPECIFIC... =20= */ /*--------------------------------------------------------------------------= */ #define BIG_MEM typedef unsigned uns; typedef unsigned int uni; typedef unsigned char uch; typedef unsigned short ush; typedef unsigned long ulg; typedef int 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) # undef OS_CODE # define OS_CODE 0x07 # ifdef MPW # define isatty(fd) ((fd) <=3D 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=20 # define NO_STDIN_FSTAT=20 # define NO_SIZE_CHECK=20 # 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 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=20 #define CONTINUATION 0x02=20 #define EXTRA_FIELD 0x04=20 #define ORIG_NAME 0x08=20 #define COMMENT 0x10=20 #define ENCRYPTED 0x20=20 #define RESERVED 0xC0=20 #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=09OUTBUFSIZ #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 >=3D 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 =3D (type*)fcalloc((size_t)(((size)+1L)/2), 2*sizeof(type)); \ if (array =3D=3D NULL) error("insufficient memory"); \ } # define FREE(array) {if (array !=3D NULL) fcfree(array), array=3DNULL;} #else # define ALLOC(type, array, size) # define FREE(array) #endif #define MAX(a,b) (a >=3D b ? a : b) #define tolow(c) (isupper(c) ? (c)-'A'+'a' : (c)) =20 #define smaller(tree, n, m) \ (tree[n].fc.freq < tree[m].fc.freq || \ (tree[n].fc.freq =3D=3D tree[m].fc.freq && gz1->depth[n] <=3D 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++]=3D(uch)(c); if (gz1->outcnt= =3D=3DOUTBUFSIZ)\ flush_outbuf(gz1);} #define put_short(w) \ { if (gz1->outcnt < OUTBUFSIZ-2) { \ gz1->outbuf[gz1->outcnt++] =3D (uch) ((w) & 0xff); \ gz1->outbuf[gz1->outcnt++] =3D (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 =3D get_byte(), zdecode(cc), cc) : get_byte()) #else # define NEXTBYTE() (uch)get_byte() #endif #define NEEDBITS(n) {while(k<(n)){b|=3D((ulg)NEXTBYTE())<>=3D(n);k-=3D(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++]=3D(uch)(c); if (gz1->outcnt= =3D=3DWSIZE)\ flush_window(gz1);} #define WARN(msg) { if (gz1->exit_code =3D=3D OK) gz1->exit_code =3D WARNING= ; } #define get_byte() (gz1->inptr < gz1->insize ? gz1->inbuf[gz1->inptr++] : f= ill_inbuf(gz1,0)) #define try_byte() (gz1->inptr < gz1->insize ? gz1->inbuf[gz1->inptr++] : f= ill_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;=20 ush max_lazy; =20 ush nice_length;=20 ush max_chain; } config; config configuration_table[10] =3D { {0, 0, 0, 0}, =20 {4, 4, 8, 4}, =20 {4, 5, 16, 8}, {4, 6, 32, 32}, {4, 4, 16, 16}, =20 {8, 16, 32, 32}, {8, 16, 128, 128}, {8, 32, 128, 256}, {32, 128, 258, 1024}, {32, 258, 258, 4096}};=20 typedef struct ct_data { union { ush freq;=20 ush code;=20 } fc; union { ush dad; =20 ush len; =20 } dl; } ct_data; typedef struct tree_desc { ct_data *dyn_tree; =20 ct_data *static_tree;=20 int *extra_bits; =20 int extra_base; =20 int elems; =20 int max_length; =20 int max_code; =20 } tree_desc; struct huft { uch e; =20 uch b; =20 union { ush n; =20 struct huft *t; =20 } v; }; uch bl_order[BL_CODES] =3D {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; int extra_lbits[LENGTH_CODES] =3D {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] =3D {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] =3D {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; ulg crc_32_tab[] =3D { 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; =20 unsigned deflate1_hash_head; =20 unsigned deflate1_prev_match; =20 int deflate1_flush; =20 int deflate1_match_available;=20 unsigned deflate1_match_length; =20 char ifname[MAX_PATH_LEN];=20 char ofname[MAX_PATH_LEN];=20 struct stat istat; =20 file_t zfile; =20 =20 int input_ismem; =20 char *input_ptr; =20 long input_bytesleft;=20 =20 int output_ismem; =20 char *output_ptr; =20 uns output_maxlen; =20 int compr_level; =20 long time_stamp; =20 long ifile_size; =20 int ifd; =20 int ofd; =20 int part_nb; =20 int last_member; =20 int save_orig_name; =20 long header_bytes; =20 long bytes_in; =20 long bytes_out; =20 uns insize; =20 uns inptr; =20 uns outcnt; =20 uns ins_h; =20 long block_start; =20 uns good_match; =20 uni max_lazy_match; =20 uni prev_length; =20 uns max_chain_length;=20 uns strstart; =20 uns match_start; =20 int eofile; =20 uns lookahead; =20 ush *file_type; =20 int *file_method; =20 ulg opt_len; =20 ulg static_len; =20 ulg compressed_len; =20 ulg input_len; =20 uns last_flags; =20 uch flags; =20 uns last_lit; =20 uns last_dist; =20 uch flag_bit; =20 int heap_len; =20 int heap_max; =20 ulg bb; =20 uns bk; =20 ush bi_buf; =20 int bi_valid; =20 uns hufts; =20 int decrypt; =20 int ascii; =20 int msg_done; =20 int abortflag; =20 int decompress; =20 int do_lzw; =20 int to_stdout; =20 int force; =20 int verbose; int quiet; int list; =20 int test; =20 int ext_header; =20 int pkzip; =20 int method; =20 int level; =20 int no_time; =20 int no_name; =20 int exit_code; =20 int lbits; =20 int dbits; =20 ulg window_size; =20 ulg crc; =20 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 =3D sizeof( GZ1 ); PGZ1 gz1_init ( void ); int gz1_cleanup ( PGZ1 gz1 ); ulg deflate ( PGZ1 gz1 ); int inflate ( PGZ1 gz1 ); int inflate_dynamic( PGZ1 gz1 ); int inflate_stored ( PGZ1 gz1 ); int inflate_fixed ( PGZ1 gz1 ); void fill_window ( PGZ1 gz1 ); ulg deflate_fast ( 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 *basename ( PGZ1 gz1, char *fname ); int longest_match ( PGZ1 gz1, unsigned cur_match ); void bi_init ( PGZ1 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,=20 int in, =20 int out =20 ); ulg flush_block( PGZ1 gz1, =20 char *buf, =20 ulg stored_len,=20 int eof =20 ); void copy_block( PGZ1 gz1, =20 char *buf, =20 unsigned len, =20 int header =20 ); int ct_tally( PGZ1 gz1, =20 int dist,=20 int lc =20 ); void send_bits( PGZ1 gz1, =20 int value,=20 int length=20 ); void send_tree( PGZ1 gz1, =20 ct_data *tree, =20 int max_code=20 ); void send_all_trees( PGZ1 gz1, =20 int lcodes,=20 int dcodes,=20 int blcodes=20 ); void ct_init( PGZ1 gz1, =20 ush *attr, =20 int *methodp=20 ); void lm_init( PGZ1 gz1, =20 int pack_level,=20 ush *flags =20 ); void build_tree( PGZ1 gz1,=20 tree_desc *desc=20 ); void compress_block( PGZ1 gz1, =20 ct_data *ltree,=20 ct_data *dtree =20 ); void gen_bitlen( PGZ1 gz1,=20 tree_desc *desc=20 ); void pqdownheap( PGZ1 gz1, =20 ct_data *tree,=20 int k =20 ); int huft_build( PGZ1 gz1,=20 unsigned *b, =20 unsigned n, =20 unsigned s, =20 ush *d, =20 ush *e, =20 struct huft **t, =20 int *m =20 ); ulg updcrc( PGZ1 gz1,=20 uch *s, =20 unsigned n =20 ); int inflate_codes( PGZ1 gz1, =20 struct huft *tl, =20 struct huft *td, =20 int bl, =20 int bd =20 ); void gen_codes( PGZ1 gz1, =20 ct_data *tree, =20 int max_code=20 ); void scan_tree( PGZ1 gz1, =20 ct_data *tree, =20 int max_code=20 ); unsigned bi_reverse( PGZ1 gz1, =20 unsigned code,=20 int len =20 ); int huft_free( PGZ1 gz1,=20 struct huft *t =20 ); PGZ1 gz1_init() { PGZ1 gz1=3D0;=20 gz1 =3D (PGZ1) malloc( gz1_size ); if ( !gz1 )=20 { return 0;=20 } memset( gz1, 0, gz1_size ); ALLOC(uch, gz1->inbuf, INBUFSIZ +INBUF_EXTRA); if ( !gz1->inbuf )=20 { free( gz1 );=20 return 0; =20 } ALLOC(uch, gz1->outbuf, OUTBUFSIZ+OUTBUF_EXTRA); =20 if ( !gz1->outbuf )=20 { FREE( gz1->inbuf );=20 free( gz1 );=20 return 0; =20 } ALLOC(ush, gz1->d_buf, DIST_BUFSIZE); if ( !gz1->d_buf )=20 { FREE( gz1->outbuf );=20 FREE( gz1->inbuf );=20 free( gz1 );=20 return 0; =20 } ALLOC(uch, gz1->window, 2L*WSIZE); if ( !gz1->window )=20 { FREE( gz1->d_buf );=20 FREE( gz1->outbuf );=20 FREE( gz1->inbuf );=20 free( gz1 );=20 return 0; =20 } #ifndef MAXSEG_64K =20 #else=20 =20 ALLOC(ush, gz1->prev2, 1L<<(BITS-1) ); if ( !gz1->prev2 )=20 { FREE( gz1->window );=20 FREE( gz1->d_buf );=20 FREE( gz1->outbuf );=20 FREE( gz1->inbuf );=20 free( gz1 );=20 return 0; =20 } ALLOC(ush, gz1->tab_prefix1, 1L<<(BITS-1) ); if ( !gz1->tab_prefix1 )=20 { FREE( gz1->prev2 );=20 FREE( gz1->window );=20 FREE( gz1->d_buf );=20 FREE( gz1->outbuf );=20 FREE( gz1->inbuf );=20 free( gz1 );=20 return 0; =20 } #endif=20 gz1->method =3D DEFLATED; =20 gz1->level =3D 6; =20 gz1->no_time =3D -1; =20 gz1->no_name =3D -1; =20 gz1->exit_code =3D OK; =20 gz1->lbits =3D 9; =20 gz1->dbits =3D 6; =20 gz1->window_size =3D (ulg)2*WSIZE; =20 gz1->crc =3D (ulg)0xffffffffL;=20 gz1->d_desc.dyn_tree =3D (ct_data *) gz1->dyn_dtree; gz1->d_desc.static_tree =3D (ct_data *) gz1->static_dtree; gz1->d_desc.extra_bits =3D (int *) extra_dbits;=20 gz1->d_desc.extra_base =3D (int ) 0; gz1->d_desc.elems =3D (int ) D_CODES; gz1->d_desc.max_length =3D (int ) MAX_BITS; gz1->d_desc.max_code =3D (int ) 0; gz1->l_desc.dyn_tree =3D (ct_data *) gz1->dyn_ltree; gz1->l_desc.static_tree =3D (ct_data *) gz1->static_ltree; gz1->l_desc.extra_bits =3D (int *) extra_lbits;=20 gz1->l_desc.extra_base =3D (int ) LITERALS+1; gz1->l_desc.elems =3D (int ) L_CODES; gz1->l_desc.max_length =3D (int ) MAX_BITS; gz1->l_desc.max_code =3D (int ) 0; gz1->bl_desc.dyn_tree =3D (ct_data *) gz1->bl_tree; gz1->bl_desc.static_tree =3D (ct_data *) 0; gz1->bl_desc.extra_bits =3D (int *) extra_blbits;=20 gz1->bl_desc.extra_base =3D (int ) 0; gz1->bl_desc.elems =3D (int ) BL_CODES; gz1->bl_desc.max_length =3D (int ) MAX_BL_BITS; gz1->bl_desc.max_code =3D (int ) 0; return (PGZ1) gz1; } int gz1_cleanup( PGZ1 gz1 ) { =20 #ifndef MAXSEG_64K =20 #else =20 FREE( gz1->tab_prefix1 ); FREE( gz1->prev2 ); #endif=20 FREE( gz1->window );=20 FREE( gz1->d_buf );=20 FREE( gz1->outbuf );=20 FREE( gz1->inbuf );=20 free( gz1 );=20 gz1 =3D 0; =20 return 0; } int (*read_buf)(PGZ1 gz1, char *buf, unsigned size); void error( char *msg ) { msg =3D msg; } int (*work)( PGZ1 gz1, int infile, int outfile ) =3D 0;=20 #ifdef __BORLANDC__ #pragma argsused #endif int get_header( PGZ1 gz1, int in ) { =20 uch flags; =20 char magic[2];=20 ulg stamp; =20 unsigned len; =20 unsigned part; =20 if ( gz1->force && gz1->to_stdout ) { =20 magic[0] =3D (char)try_byte(); magic[1] =3D (char)try_byte(); } else { magic[0] =3D (char)get_byte(); magic[1] =3D (char)get_byte(); } gz1->method =3D -1; =20 gz1->header_bytes =3D 0; =20 gz1->last_member =3D RECORD_IO;=20 gz1->part_nb++; =20 if ( memcmp(magic, GZIP_MAGIC, 2 ) =3D=3D 0 || memcmp(magic, OLD_GZIP_MAGIC, 2 ) =3D=3D 0 ) { gz1->method =3D (int)get_byte(); if ( gz1->method !=3D DEFLATED ) { gz1->exit_code =3D LZ1_ERROR; return -1; } return -1; if ((flags & ENCRYPTED) !=3D 0) { gz1->exit_code =3D LZ1_ERROR; return -1; } if ((flags & CONTINUATION) !=3D 0) { gz1->exit_code =3D LZ1_ERROR; if ( gz1->force <=3D 1) return -1; } if ((flags & RESERVED) !=3D 0) { gz1->exit_code =3D LZ1_ERROR; if ( gz1->force <=3D 1) return -1; } stamp =3D (ulg)get_byte(); =09stamp |=3D ((ulg)get_byte()) << 8; =09stamp |=3D ((ulg)get_byte()) << 16; =09stamp |=3D ((ulg)get_byte()) << 24; if ( stamp !=3D 0 && !gz1->no_time ) { gz1->time_stamp =3D stamp; } (void)get_byte();=20 (void)get_byte();=20 if ((flags & CONTINUATION) !=3D 0) { part =3D (unsigned) get_byte(); part |=3D ((unsigned) get_byte())<<8; } if ((flags & EXTRA_FIELD) !=3D 0) { len =3D (unsigned) get_byte(); len |=3D ((unsigned) get_byte())<<8; while (len--) (void)get_byte(); } if ((flags & COMMENT) !=3D 0) { while (get_char() !=3D 0) ; } if ( gz1->part_nb =3D=3D 1 ) { =20 gz1->header_bytes =3D gz1->inptr + 2*sizeof(long); } } return gz1->method; } int fill_inbuf( PGZ1 gz1, int eof_ok ) { =20 int len; int bytes_to_copy; gz1->insize =3D 0; errno =3D 0; do { =20 if ( gz1->input_ismem ) { =20 if ( gz1->input_bytesleft > 0 ) { bytes_to_copy =3D INBUFSIZ - gz1->insize; if ( bytes_to_copy > gz1->input_bytesleft ) { bytes_to_copy =3D gz1->input_bytesleft; } memcpy( (char*)gz1->inbuf+gz1->insize, gz1->input_ptr, bytes_to_copy ); gz1->input_ptr +=3D bytes_to_copy; gz1->input_bytesleft -=3D bytes_to_copy; len =3D bytes_to_copy; } else=20 { len =3D 0;=20 } } else=20 { len =3D read( gz1->ifd, (char*)gz1->inbuf+gz1->insize, INBUFSIZ-gz1->insize ); } if (len =3D=3D 0 || len =3D=3D EOF) break; gz1->insize +=3D len; } while( gz1->insize < INBUFSIZ ); if ( gz1->insize =3D=3D 0 ) { if( eof_ok ) return EOF; read_error( gz1 ); } gz1->bytes_in +=3D (ulg) gz1->insize; gz1->inptr =3D 1; return gz1->inbuf[0]; } ulg updcrc( PGZ1 gz1,=20 uch *s, =20 unsigned n =20 ) { =20 register ulg c;=20 if ( s =3D=3D NULL ) { c =3D 0xffffffffL; } else { c =3D gz1->crc; if ( n ) { do{ c =3D crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8); } while( --n ); } } gz1->crc =3D c; return( c ^ 0xffffffffL );=20 } void read_error( PGZ1 gz1 ) { gz1->abortflag =3D 1; } void mod_gzip_strlwr( char *s ) { =20 char *p1=3Ds; if ( s =3D=3D 0 ) return; while ( *p1 !=3D 0 ) { if ( *p1 > 96 ) *p1 =3D *p1 - 32; p1++; } } #ifdef __BORLANDC__ #pragma argsused #endif char *basename( PGZ1 gz1, char *fname ) { =20 char *p; if ((p =3D strrchr(fname, PATH_SEP)) !=3D NULL) fname =3D p+1; #ifdef PATH_SEP2 if ((p =3D strrchr(fname, PATH_SEP2)) !=3D NULL) fname =3D p+1; #endif #ifdef PATH_SEP3 if ((p =3D strrchr(fname, PATH_SEP3)) !=3D NULL) fname =3D p+1; #endif #ifdef SUFFIX_SEP if ((p =3D strrchr(fname, SUFFIX_SEP)) !=3D NULL) *p =3D '\0'; #endif if (casemap('A') =3D=3D 'a') mod_gzip_strlwr(fname); return fname; } void write_buf( PGZ1 gz1, int fd, voidp buf, unsigned cnt ) { =20 unsigned n; if ( gz1->output_ismem ) { if ( ( gz1->bytes_out + cnt ) < gz1->output_maxlen ) { memcpy( gz1->output_ptr, buf, cnt ); gz1->output_ptr +=3D cnt; } else { write_error( gz1 ); } } else { while ((n =3D write(fd, buf, cnt)) !=3D cnt) { if (n =3D=3D (unsigned)(-1)) { write_error( gz1 ); } cnt -=3D n; buf =3D (voidp)((char*)buf+n); } } } void write_error( PGZ1 gz1 ) { gz1->abortflag =3D 1; } #ifdef __TURBOC__ #ifndef BC55 static ush ptr_offset =3D 0; void * fcalloc( unsigned items,=20 unsigned size =20 ) { =20 void * buf =3D farmalloc((ulg)items*size + 16L); if (buf =3D=3D NULL) return NULL; if (ptr_offset =3D=3D 0) { ptr_offset =3D (ush)((uch*)buf-0); } else if (ptr_offset !=3D (ush)((uch*)buf-0)) { error("inconsistent ptr_offset"); } *((ush*)&buf+1) +=3D (ptr_offset + 15) >> 4; *(ush*)&buf =3D 0; return buf; } void fcfree( void *ptr ) { =20 *((ush*)&ptr+1) -=3D (ptr_offset + 15) >> 4; *(ush*)&ptr =3D ptr_offset; farfree(ptr); } #endif=20 #endif=20 int zip( PGZ1 gz1,=20 int in, =20 int out =20 ) { uch flags =3D 0; =20 ush attr =3D 0; =20 ush deflate_flags =3D 0;=20 gz1->ifd =3D in; gz1->ofd =3D out; gz1->outcnt =3D 0; gz1->method =3D DEFLATED; put_byte(GZIP_MAGIC[0]);=20 put_byte(GZIP_MAGIC[1]); put_byte(DEFLATED); =20 if ( gz1->save_orig_name ) { =09flags |=3D ORIG_NAME; } put_byte(flags); =20 put_long(gz1->time_stamp);=20 gz1->crc =3D -1;=20 updcrc( gz1, NULL, 0 );=20 bi_init( gz1, out ); ct_init( gz1, &attr, &gz1->method ); lm_init( gz1, gz1->level, &deflate_flags ); put_byte((uch)deflate_flags);=20 put_byte(OS_CODE);=20 if ( gz1->save_orig_name ) { char *p =3D basename( gz1, gz1->ifname ); do { =09 put_char(*p); } while (*p++); } gz1->header_bytes =3D (long)gz1->outcnt; (void)deflate( gz1 ); #if !defined(NO_SIZE_CHECK) && !defined(RECORD_IO) =20 if (gz1->ifile_size !=3D -1L && gz1->isize !=3D (ulg)gz1->ifile_size) { } #endif put_long( gz1->crc ); put_long( gz1->bytes_in ); gz1->header_bytes +=3D 2*sizeof(long); flush_outbuf( gz1 ); return OK; } ulg deflate( PGZ1 gz1 ) { unsigned hash_head; =20 unsigned prev_match; =20 int flush; =20 int match_available =3D 0;=20 register unsigned match_length =3D MIN_MATCH-1;=20 #ifdef DEBUG long isize; =20 #endif if (gz1->compr_level <=3D 3) { return deflate_fast(gz1);=20 } while (gz1->lookahead !=3D 0) { =20 gz1->ins_h =3D (((gz1->ins_h)<window[gz1->strstart+MIN_MATCH-1]))=20= & HASH_MASK; prev[ gz1->strstart & WMASK ] =3D hash_head =3D head[ gz1->ins_h ]; head[ gz1->ins_h ] =3D gz1->strstart; gz1->prev_length =3D match_length, prev_match =3D gz1->match_start; match_length =3D MIN_MATCH-1; if (hash_head !=3D NIL && gz1->prev_length < gz1->max_lazy_match && gz1->strstart - hash_head <=3D MAX_DIST) { =20 match_length =3D longest_match( gz1, hash_head ); =20 if (match_length > gz1->lookahead) match_length =3D gz1->lookahe= ad; if (match_length =3D=3D MIN_MATCH && gz1->strstart-gz1->match_st= art > TOO_FAR){ =20 match_length--; } } =20 if (gz1->prev_length >=3D MIN_MATCH && match_length <=3D gz1->prev_l= ength) { flush =3D ct_tally(gz1,gz1->strstart-1-prev_match, gz1->prev_len= gth - MIN_MATCH); gz1->lookahead -=3D ( gz1->prev_length - 1 ); gz1->prev_length -=3D 2; do { gz1->strstart++; gz1->ins_h =3D (((gz1->ins_h)<window[ gz1->strstart + MIN= _MATCH-1])) & HASH_MASK; prev[ gz1->strstart & WMASK ] =3D hash_head =3D head[gz1->in= s_h]; head[ gz1->ins_h ] =3D gz1->strstart; } while (--gz1->prev_length !=3D 0); match_available =3D 0; match_length =3D MIN_MATCH-1; gz1->strstart++; if (flush) FLUSH_BLOCK(0), gz1->block_start =3D gz1->strstart; } else if (match_available) { =20 if (ct_tally( gz1, 0, gz1->window[gz1->strstart-1] )) { FLUSH_BLOCK(0), gz1->block_start =3D gz1->strstart; } gz1->strstart++; gz1->lookahead--; } else { =20 match_available =3D 1; gz1->strstart++; gz1->lookahead--; } =20 while (gz1->lookahead < MIN_LOOKAHEAD && !gz1->eofile) fill_window(g= z1); } if (match_available) ct_tally( gz1, 0, gz1->window[gz1->strstart-1] ); return FLUSH_BLOCK(1);=20 return 0; } void flush_outbuf( PGZ1 gz1 ) { if ( gz1->outcnt =3D=3D 0 ) { return; } write_buf( gz1, gz1->ofd, (char *)gz1->outbuf, gz1->outcnt ); gz1->bytes_out +=3D (ulg)gz1->outcnt; gz1->outcnt =3D 0; } void lm_init( PGZ1 gz1, =20 int pack_level,=20 ush *flags =20 ) { register unsigned j; if ( pack_level < 1 || pack_level > 9 ) { error("bad pack level"); } gz1->compr_level =3D pack_level; #if defined(MAXSEG_64K) && HASH_BITS =3D=3D 15 for (j =3D 0; j < HASH_SIZE; j++) head[j] =3D NIL; #else memset( (char*)head, 0, (HASH_SIZE*sizeof(*head)) ); #endif gz1->max_lazy_match =3D configuration_table[pack_level].max_lazy; gz1->good_match =3D configuration_table[pack_level].good_length; #ifndef FULL_SEARCH gz1->nice_match =3D configuration_table[pack_level].nice_length; #endif gz1->max_chain_length =3D configuration_table[pack_level].max_chain; if ( pack_level =3D=3D 1 ) { =20 *flags |=3D FAST; } else if ( pack_level =3D=3D 9 ) { =20 *flags |=3D SLOW; } gz1->strstart =3D 0; gz1->block_start =3D 0L; #ifdef ASMV match_init();=20 #endif gz1->lookahead =3D read_buf(gz1,(char*)gz1->window, sizeof(int) <=3D 2 ? (unsigned)WSIZE : 2*WSIZE); if (gz1->lookahead =3D=3D 0 || gz1->lookahead =3D=3D (unsigned)EOF) { gz1->eofile =3D 1, gz1->lookahead =3D 0; return; } gz1->eofile =3D 0; while (gz1->lookahead < MIN_LOOKAHEAD && !gz1->eofile) { fill_window(gz1); } gz1->ins_h =3D 0; for ( j=3D0; jins_h =3D (((gz1->ins_h)<window[j])) & HASH_MASK; } } void fill_window( PGZ1 gz1 ) { register unsigned n, m; unsigned more =3D (unsigned)( gz1->window_size - (ulg)gz1->lookahead - (ulg)gz1->strstart ); if ( more =3D=3D (unsigned)EOF) { =20 more--; } else if ( gz1->strstart >=3D WSIZE+MAX_DIST ) { =20 memcpy((char*)gz1->window, (char*)gz1->window+WSIZE, (unsigned)WSIZE); gz1->match_start -=3D WSIZE; gz1->strstart -=3D WSIZE;=20 gz1->block_start -=3D (long) WSIZE; for ( n =3D 0; n < HASH_SIZE; n++ ) { m =3D head[n]; head[n] =3D (ush)(m >=3D WSIZE ? m-WSIZE : NIL); } for ( n =3D 0; n < WSIZE; n++ ) { m =3D prev[n]; prev[n] =3D (ush)(m >=3D WSIZE ? m-WSIZE : NIL); } more +=3D WSIZE; } if ( !gz1->eofile ) { n =3D read_buf(gz1,(char*)gz1->window+gz1->strstart+gz1->lookahead, more= ); if ( n =3D=3D 0 || n =3D=3D (unsigned)EOF ) { gz1->eofile =3D 1; } else { gz1->lookahead +=3D n; } } } ulg deflate_fast( PGZ1 gz1 ) { unsigned hash_head;=20 int flush; =20 unsigned match_length =3D 0; =20 gz1->prev_length =3D MIN_MATCH-1; while (gz1->lookahead !=3D 0) { =20 gz1->ins_h =3D (((gz1->ins_h)<window[ gz1->strstart + MIN_MATCH-1]= )) & HASH_MASK; =20 prev[ gz1->strstart & WMASK ] =3D hash_head =3D head[ gz1->ins_h ]; head[ gz1->ins_h ] =3D gz1->strstart; if (hash_head !=3D NIL && gz1->strstart - hash_head <=3D MAX_DIST) { =20 match_length =3D longest_match( gz1, hash_head ); =20 if (match_length > gz1->lookahead) match_length =3D gz1->lookahe= ad; } if (match_length >=3D MIN_MATCH) { flush =3D ct_tally(gz1,gz1->strstart-gz1->match_start, match_len= gth - MIN_MATCH); gz1->lookahead -=3D match_length; if (match_length <=3D gz1->max_lazy_match ) { match_length--;=20 do { gz1->strstart++; gz1->ins_h =3D (((gz1->ins_h)<window[ gz1->strstart += MIN_MATCH-1])) & HASH_MASK; =20 prev[ gz1->strstart & WMASK ] =3D hash_head =3D head[ gz= 1->ins_h ]; head[ gz1->ins_h ] =3D gz1->strstart; } while (--match_length !=3D 0); gz1->strstart++; } else { gz1->strstart +=3D match_length; =09 match_length =3D 0; gz1->ins_h =3D gz1->window[gz1->strstart]; gz1->ins_h =3D (((gz1->ins_h)<window[gz1->strstart+1])) & HAS= H_MASK; =20 #if MIN_MATCH !=3D 3 Call UPDATE_HASH() MIN_MATCH-3 more times #endif } } else { =20 flush =3D ct_tally(gz1, 0, gz1->window[gz1->strstart]); gz1->lookahead--; gz1->strstart++; } if (flush) FLUSH_BLOCK(0), gz1->block_start =3D gz1->strstart; while (gz1->lookahead < MIN_LOOKAHEAD && !gz1->eofile) fill_window(g= z1); } return FLUSH_BLOCK(1);=20 } void ct_init( PGZ1 gz1, =20 ush *attr, =20 int *methodp=20 ) { #ifdef DD1 int i,ii; #endif int n; =20 int bits; =20 int length;=20 int code; =20 int dist; =20 gz1->file_type =3D attr; gz1->file_method =3D methodp; gz1->compressed_len =3D gz1->input_len =3D 0L; =20 if ( gz1->static_dtree[0].dl.len !=3D 0 ) { =20 return; } length =3D 0; for ( code =3D 0; code < LENGTH_CODES-1; code++ ) { gz1->base_length[code] =3D length; for ( n =3D 0; n < (1<length_code[length++] =3D (uch)code; } } gz1->length_code[length-1] =3D (uch)code; dist =3D 0; for ( code =3D 0 ; code < 16; code++ ) { gz1->base_dist[code] =3D dist; for ( n =3D 0; n < (1<dist_code[dist++] =3D (uch)code; } } dist >>=3D 7;=20 for ( ; code < D_CODES; code++ ) { gz1->base_dist[code] =3D dist << 7; for ( n =3D 0; n < (1<<(extra_dbits[code]-7)); n++ ) { gz1->dist_code[256 + dist++] =3D (uch)code; } } for ( bits =3D 0; bits <=3D MAX_BITS; bits++ ) { gz1->bl_count[bits] =3D 0; } n =3D 0; while (n <=3D 143) gz1->static_ltree[n++].dl.len =3D 8, gz1->bl_count[8]++; while (n <=3D 255) gz1->static_ltree[n++].dl.len =3D 9, gz1->bl_count[9]++; while (n <=3D 279) gz1->static_ltree[n++].dl.len =3D 7, gz1->bl_count[7]++; while (n <=3D 287) gz1->static_ltree[n++].dl.len =3D 8, gz1->bl_count[8]++; gen_codes(gz1,(ct_data *)gz1->static_ltree, L_CODES+1); for ( n =3D 0; n < D_CODES; n++ ) { gz1->static_dtree[n].dl.len =3D 5; gz1->static_dtree[n].fc.code =3D bi_reverse( gz1, n, 5 ); } init_block( gz1 ); } ulg flush_block( PGZ1 gz1, =20 char *buf, =20 ulg stored_len,=20 int eof =20 ) { ulg opt_lenb; =20 ulg static_lenb; =20 int max_blindex; =20 gz1->flag_buf[gz1->last_flags] =3D gz1->flags; if (*gz1->file_type =3D=3D (ush)UNKNOWN) set_file_type(gz1); build_tree( gz1, (tree_desc *)(&gz1->l_desc) ); build_tree( gz1, (tree_desc *)(&gz1->d_desc) ); max_blindex =3D build_bl_tree( gz1 ); opt_lenb =3D (gz1->opt_len+3+7)>>3; static_lenb =3D (gz1->static_len+3+7)>>3; gz1->input_len +=3D stored_len;=20 if (static_lenb <=3D opt_lenb) opt_lenb =3D static_lenb; #ifdef FORCE_METHOD =20 if ( level =3D=3D 1 && eof && gz1->compressed_len =3D=3D 0L ) #else if (stored_len <=3D opt_lenb && eof && gz1->compressed_len =3D=3D 0L && 0 ) #endif { =20 if (buf =3D=3D (char*)0) error ("block vanished"); copy_block( gz1, buf, (unsigned)stored_len, 0 );=20 gz1->compressed_len =3D stored_len << 3; *gz1->file_method =3D STORED; #ifdef FORCE_METHOD } else if (level =3D=3D 2 && buf !=3D (char*)0) {=20 #else } else if (stored_len+4 <=3D opt_lenb && buf !=3D (char*)0) { =20 #endif =20 send_bits(gz1,(STORED_BLOCK<<1)+eof, 3); =20 gz1->compressed_len =3D (gz1->compressed_len + 3 + 7) & ~7L; gz1->compressed_len +=3D (stored_len + 4) << 3; copy_block(gz1, buf, (unsigned)stored_len, 1);=20 #ifdef FORCE_METHOD } else if (level =3D=3D 3) {=20 #else } else if (static_lenb =3D=3D 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 +=3D 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 +=3D 3 + gz1->opt_len; } init_block( gz1 ); if ( eof ) { bi_windup( gz1 ); gz1->compressed_len +=3D 7; =20 } return gz1->compressed_len >> 3; } #ifdef __BORLANDC__ #pragma argsused #endif unsigned bi_reverse( PGZ1 gz1, =20 unsigned code,=20 int len =20 ) { register unsigned res =3D 0; do { res |=3D code & 1; code >>=3D 1, res <<=3D 1; } while (--len > 0); return res >> 1; } void set_file_type( PGZ1 gz1 ) { int n =3D 0; unsigned ascii_freq =3D 0; unsigned bin_freq =3D 0; while (n < 7) bin_freq +=3D gz1->dyn_ltree[n++].fc.freq; while (n < 128) ascii_freq +=3D gz1->dyn_ltree[n++].fc.freq; while (n < LITERALS) bin_freq +=3D gz1->dyn_ltree[n++].fc.freq; *gz1->file_type =3D bin_freq > (ascii_freq >> 2) ? BINARY : ASCII; } void init_block( PGZ1 gz1 ) { int n;=20 for (n =3D 0; n < L_CODES; n++) gz1->dyn_ltree[n].fc.freq =3D 0; for (n =3D 0; n < D_CODES; n++) gz1->dyn_dtree[n].fc.freq =3D 0; for (n =3D 0; n < BL_CODES; n++) gz1->bl_tree[n].fc.freq =3D 0; gz1->dyn_ltree[END_BLOCK].fc.freq =3D 1; gz1->opt_len =3D 0L; gz1->static_len =3D 0L; gz1->last_lit =3D 0; gz1->last_dist =3D 0; gz1->last_flags =3D 0; gz1->flags =3D 0; gz1->flag_bit =3D 1; } void bi_init( PGZ1 gz1, file_t zipfile ) { gz1->zfile =3D zipfile; gz1->bi_buf =3D 0; gz1->bi_valid =3D 0; if ( gz1->zfile !=3D NO_FILE ) { read_buf =3D file_read; } } int ct_tally( PGZ1 gz1, =20 int dist,=20 int lc =20 ) { int dcode; gz1->inbuf[gz1->last_lit++] =3D (uch)lc; if ( dist =3D=3D 0 ) { gz1->dyn_ltree[lc].fc.freq++;=20 } else { =20 dist--;=20 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++] =3D (ush)dist; gz1->flags |=3D gz1->flag_bit; } gz1->flag_bit <<=3D 1; if ( (gz1->last_lit & 7) =3D=3D 0 ) { gz1->flag_buf[gz1->last_flags++] =3D gz1->flags; gz1->flags =3D 0, gz1->flag_bit =3D 1; } if ( gz1->level > 2 && (gz1->last_lit & 0xfff) =3D=3D 0) { =20 ulg out_length =3D (ulg) ( gz1->last_lit * 8L ); ulg in_length =3D (ulg) ( gz1->strstart - gz1->block_start ); for ( dcode =3D 0; dcode < D_CODES; dcode++ ) { out_length +=3D (ulg) ((gz1->dyn_dtree[dcode].fc.freq)*(5L+extra_dbi= ts[dcode])); } out_length >>=3D 3; if ( gz1->last_dist < gz1->last_lit/2 && out_length < in_length/2 ) { return 1; } } return( gz1->last_lit =3D=3D LIT_BUFSIZE-1 || gz1->last_dist =3D=3D DIST_BU= FSIZE ); } void compress_block( PGZ1 gz1, =20 ct_data *ltree,=20 ct_data *dtree =20 ) { unsigned dist; =20 int lc; =20 unsigned lx =3D 0;=20 unsigned dx =3D 0;=20 unsigned fx =3D 0;=20 uch flag =3D 0; =20 unsigned code; =20 int extra; =20 if (gz1->last_lit !=3D 0) do { if ((lx & 7) =3D=3D 0) flag =3D gz1->flag_buf[fx++]; lc =3D gz1->inbuf[lx++]; if ((flag & 1) =3D=3D 0) { send_code(lc, ltree);=20 } else { =20 code =3D gz1->length_code[lc]; send_code(code+LITERALS+1, ltree);=20 extra =3D extra_lbits[code]; if (extra !=3D 0) { lc -=3D gz1->base_length[code]; send_bits(gz1,lc, extra);=20 } dist =3D gz1->d_buf[dx++]; =20 code =3D d_code(dist); send_code(code, dtree); =20 extra =3D extra_dbits[code]; if (extra !=3D 0) { dist -=3D gz1->base_dist[code]; send_bits(gz1,dist, extra);=20 } }=20 flag >>=3D 1; } while (lx < gz1->last_lit); send_code(END_BLOCK, ltree); } #ifndef ASMV int longest_match( PGZ1 gz1, unsigned cur_match ) { unsigned chain_length =3D gz1->max_chain_length; =20 register uch *scan =3D gz1->window + gz1->strstart; =20 register uch *match; =20 register int len; =20 int best_len =3D gz1->prev_length; =20 unsigned limit =3D gz1->strstart > (unsigned)MAX_DIST ? gz1->strstart - (un= signed)MAX_DIST : NIL; =20 #if HASH_BITS < 8 || MAX_MATCH !=3D 258 error: Code too clever #endif #ifdef UNALIGNED_OK =20 register uch *strend =3D gz1->window + gz1->strstart + MAX_MATCH - 1; register ush scan_start =3D *(ush*)scan; register ush scan_end =3D *(ush*)(scan+best_len-1); #else register uch *strend =3D gz1->window + gz1->strstart + MAX_MATCH; register uch scan_end1 =3D scan[best_len-1]; register uch scan_end =3D scan[best_len]; #endif if (gz1->prev_length >=3D gz1->good_match) { chain_length >>=3D 2; } do { match =3D gz1->window + cur_match; #if (defined(UNALIGNED_OK) && MAX_MATCH =3D=3D 258) =20 if (*(ush*)(match+best_len-1) !=3D scan_end || *(ush*)match !=3D scan_start) continue; scan++, match++; do { } while (*(ush*)(scan+=3D2) =3D=3D *(ush*)(match+=3D2) && *(ush*)(scan+=3D2) =3D=3D *(ush*)(match+=3D2) && *(ush*)(scan+=3D2) =3D=3D *(ush*)(match+=3D2) && *(ush*)(scan+=3D2) =3D=3D *(ush*)(match+=3D2) && scan < strend); =20 if (*scan =3D=3D *match) scan++; len =3D (MAX_MATCH - 1) - (int)(strend-scan); scan =3D strend - (MAX_MATCH-1); #else=20 if (match[best_len] !=3D scan_end || match[best_len-1] !=3D scan_end1 || *match !=3D *scan || *++match !=3D scan[1]) continue; scan +=3D 2, match++; do { } while (*++scan =3D=3D *++match && *++scan =3D=3D *++match && *++scan =3D=3D *++match && *++scan =3D=3D *++match && *++scan =3D=3D *++match && *++scan =3D=3D *++match && *++scan =3D=3D *++match && *++scan =3D=3D *++match && scan < strend); len =3D MAX_MATCH - (int)(strend - scan); scan =3D strend - MAX_MATCH; #endif=20 if (len > best_len) { gz1->match_start =3D cur_match; best_len =3D len; if (len >=3D gz1->nice_match) break; #ifdef UNALIGNED_OK scan_end =3D *(ush*)(scan+best_len-1); #else scan_end1 =3D scan[best_len-1]; scan_end =3D scan[best_len]; #endif } } while ((cur_match =3D prev[cur_match & WMASK]) > limit =09 && --chain_length !=3D 0); return best_len; } #endif=20 void send_bits( PGZ1 gz1, =20 int value,=20 int length=20 ) { if ( gz1->bi_valid > (int) BUFSIZE - length ) { gz1->bi_buf |=3D (value << gz1->bi_valid); put_short(gz1->bi_buf); gz1->bi_buf =3D (ush)value >> (BUFSIZE - gz1->bi_valid); gz1->bi_valid +=3D length - BUFSIZE; } else { gz1->bi_buf |=3D value << gz1->bi_valid; gz1->bi_valid +=3D length; } } void build_tree( PGZ1 gz1,=20 tree_desc *desc=20 ) { int elems =3D desc->elems; ct_data *tree =3D desc->dyn_tree; ct_data *stree =3D desc->static_tree; int n; =20 int m; =20 int max_code =3D -1;=20 int node =3D elems; =20 int new1; =20 gz1->heap_len =3D 0, gz1->heap_max =3D HEAP_SIZE; for (n =3D 0; n < elems; n++) { if (tree[n].fc.freq !=3D 0) { gz1->heap[++gz1->heap_len] =3D max_code =3D n; gz1->depth[n] =3D 0; } else { tree[n].dl.len =3D 0; } } while (gz1->heap_len < 2) { new1 =3D gz1->heap[++gz1->heap_len] =3D (max_code < 2 ? ++max_code := 0); tree[new1].fc.freq =3D 1; gz1->depth[new1] =3D 0; gz1->opt_len--; if (stree) gz1->static_len -=3D stree[new1].dl.len; } desc->max_code =3D max_code; for (n =3D gz1->heap_len/2; n >=3D 1; n--) pqdownheap(gz1, tree, n); do { n =3D gz1->heap[SMALLEST]; gz1->heap[SMALLEST] =3D gz1->heap[gz1->heap_len--]; pqdownheap(gz1, tree, SMALLEST); m =3D gz1->heap[SMALLEST]; gz1->heap[--gz1->heap_max] =3D n; gz1->heap[--gz1->heap_max] =3D m; tree[node].fc.freq =3D tree[n].fc.freq + tree[m].fc.freq; gz1->depth[node] =3D (uch) (MAX(gz1->depth[n], gz1->depth[m]) + 1); tree[n].dl.dad =3D tree[m].dl.dad =3D (ush)node; gz1->heap[SMALLEST] =3D node++; pqdownheap(gz1, tree, SMALLEST); } while (gz1->heap_len >=3D 2); gz1->heap[--gz1->heap_max] =3D 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;=20 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 =3D BL_CODES-1; max_blindex >=3D 3; max_blindex-- ) { if (gz1->bl_tree[bl_order[max_blindex]].dl.len !=3D 0) break; } gz1->opt_len +=3D 3*(max_blindex+1) + 5+5+4; return max_blindex; } void gen_codes( PGZ1 gz1, =20 ct_data *tree, =20 int max_code=20 ) { ush next_code[MAX_BITS+1];=20 ush code =3D 0; =20 int bits; =20 int n; =20 for ( bits =3D 1; bits <=3D MAX_BITS; bits++ ) { next_code[bits] =3D code =3D (code + gz1->bl_count[bits-1]) << 1; } for ( n =3D 0; n <=3D max_code; n++ ) { int len =3D tree[n].dl.len; if (len =3D=3D 0) continue; tree[n].fc.code =3D bi_reverse( gz1, next_code[len]++, len ); } return; } void gen_bitlen( PGZ1 gz1,=20 tree_desc *desc=20 ) { ct_data *tree =3D desc->dyn_tree; int *extra =3D desc->extra_bits; int base =3D desc->extra_base; int max_code =3D desc->max_code; int max_length =3D desc->max_length; ct_data *stree =3D desc->static_tree; int h; =20 int n, m; =20 int bits; =20 int xbits; =20 ush f; =20 int overflow =3D 0; =20 for (bits =3D 0; bits <=3D MAX_BITS; bits++) gz1->bl_count[bits] =3D 0; tree[gz1->heap[gz1->heap_max]].dl.len =3D 0; for (h =3D gz1->heap_max+1; h < HEAP_SIZE; h++) { n =3D gz1->heap[h]; bits =3D tree[tree[n].dl.dad].dl.len + 1; if (bits > max_length) bits =3D max_length, overflow++; tree[n].dl.len =3D (ush)bits; =20 if (n > max_code) continue;=20 gz1->bl_count[bits]++; xbits =3D 0; if (n >=3D base) xbits =3D extra[n-base]; f =3D tree[n].fc.freq; gz1->opt_len +=3D (ulg)f * (bits + xbits); if (stree) gz1->static_len +=3D (ulg)f * (stree[n].dl.len + xbits); } if (overflow =3D=3D 0) return; do { bits =3D max_length-1; while (gz1->bl_count[bits] =3D=3D 0) bits--; gz1->bl_count[bits]--; =20 gz1->bl_count[bits+1] +=3D 2;=20 gz1->bl_count[max_length]--; =20 overflow -=3D 2; } while (overflow > 0); for (bits =3D max_length; bits !=3D 0; bits--) { n =3D gz1->bl_count[bits]; while (n !=3D 0) { m =3D gz1->heap[--h]; if (m > max_code) continue; if (tree[m].dl.len !=3D (unsigned) bits) { gz1->opt_len +=3D ((long)bits-(long)tree[m].dl.len)*(long)tree[= m].fc.freq; tree[m].dl.len =3D (ush)bits; } n--; } } } void copy_block( PGZ1 gz1, =20 char *buf, =20 unsigned len, =20 int header =20 ) { #ifdef CRYPT int t; #endif bi_windup( gz1 );=20 if ( header ) { put_short((ush)len); put_short((ush)~len); } while( len-- ) { #ifdef CRYPT =09if (key) zencode(*buf, t); #endif put_byte(*buf++); } } int file_read( PGZ1 gz1, char *buf, unsigned size ) { unsigned len =3D 0; unsigned bytes_to_copy =3D 0; if ( gz1->input_ismem ) { if ( gz1->input_bytesleft > 0 ) { bytes_to_copy =3D size; if ( bytes_to_copy > (unsigned) gz1->input_bytesleft ) { bytes_to_copy =3D (unsigned) gz1->input_bytesleft; } memcpy( buf, gz1->input_ptr, bytes_to_copy ); gz1->input_ptr +=3D bytes_to_copy; gz1->input_bytesleft -=3D bytes_to_copy; len =3D bytes_to_copy; } else { len =3D 0; } } else { len =3D read( gz1->ifd, buf, size ); } if ( len =3D=3D (unsigned)(-1) || len =3D=3D 0 ) { =09gz1->crc =3D gz1->crc ^ 0xffffffffL; return (int)len; } updcrc( gz1, (uch*)buf, len ); gz1->bytes_in +=3D (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 =3D 0; gz1->bi_valid =3D 0; } void send_all_trees( PGZ1 gz1, =20 int lcodes,=20 int dcodes,=20 int blcodes=20 ) { int rank;=20 send_bits(gz1,lcodes-257, 5);=20 send_bits(gz1,dcodes-1, 5); send_bits(gz1,blcodes-4, 4);=20 for ( rank =3D 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);=20 send_tree(gz1,(ct_data *)gz1->dyn_dtree, dcodes-1);=20 } void send_tree( PGZ1 gz1, =20 ct_data *tree, =20 int max_code=20 ) { int n; =20 int prevlen =3D -1; =20 int curlen; =20 int nextlen =3D tree[0].dl.len;=20 int count =3D 0; =20 int max_count =3D 7; =20 int min_count =3D 4; =20 if (nextlen =3D=3D 0) max_count =3D 138, min_count =3D 3; for ( n =3D 0; n <=3D max_code; n++ ) { curlen =3D nextlen; nextlen =3D tree[n+1].dl.len; if (++count < max_count && curlen =3D=3D nextlen) { continue; } else if (count < min_count) { do { send_code(curlen, gz1->bl_tree); } while (--count !=3D 0); } else if (curlen !=3D 0) { if ( curlen !=3D 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 <=3D 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 =3D 0; prevlen =3D curlen; if (nextlen =3D=3D 0) { max_count =3D 138, min_count =3D 3; } else if (curlen =3D=3D nextlen) { max_count =3D 6, min_count =3D 3; } else { max_count =3D 7, min_count =3D 4; } } } void scan_tree( PGZ1 gz1, =20 ct_data *tree, =20 int max_code=20 ) { int n; =20 int prevlen =3D -1; =20 int curlen; =20 int nextlen =3D tree[0].dl.len;=20 int count =3D 0; =20 int max_count =3D 7; =20 int min_count =3D 4; =20 if (nextlen =3D=3D 0) max_count =3D 138, min_count =3D 3; tree[max_code+1].dl.len =3D (ush)0xffff;=20 for ( n =3D 0; n <=3D max_code; n++ ) { curlen =3D nextlen; nextlen =3D tree[n+1].dl.len; if ( ++count < max_count && curlen =3D=3D nextlen ) { continue; } else if ( count < min_count ) { gz1->bl_tree[curlen].fc.freq +=3D count; } else if ( curlen !=3D 0 ) { if ( curlen !=3D prevlen ) gz1->bl_tree[curlen].fc.freq++; gz1->bl_tree[REP_3_6].fc.freq++; } else if ( count <=3D 10 ) { gz1->bl_tree[REPZ_3_10].fc.freq++; } else { gz1->bl_tree[REPZ_11_138].fc.freq++; } count =3D 0; prevlen =3D curlen; if ( nextlen =3D=3D 0 ) { max_count =3D 138; min_count =3D 3; } else if (curlen =3D=3D nextlen) { max_count =3D 6; min_count =3D 3; } else { max_count =3D 7; min_count =3D 4; } } } void pqdownheap( PGZ1 gz1, =20 ct_data *tree,=20 int k =20 ) { int v =3D gz1->heap[k]; int j =3D k << 1; =20 while( j <=3D gz1->heap_len ) { =20 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] =3D gz1->heap[j]; k =3D j; j <<=3D 1; } gz1->heap[k] =3D v; } #define GZS_ZIP1 1 #define GZS_ZIP2 2 #define GZS_DEFLATE1 3 #define GZS_DEFLATE2 4 int gzs_fsp ( PGZ1 gz1 );=20 int gzs_zip1 ( PGZ1 gz1 );=20 int gzs_zip2 ( PGZ1 gz1 );=20 int gzs_deflate1( PGZ1 gz1 );=20 int gzs_deflate2( PGZ1 gz1 );=20 int gzp_main( GZP_CONTROL *gzp ) { PGZ1 gz1 =3D 0;=20 int rc =3D 0; int final_exit_code =3D 0; int ofile_flags =3D O_RDWR | O_CREAT | O_TRUNC | O_BINARY; gzp->result_code =3D 0;=20 gzp->bytes_out =3D 0;=20 gz1 =3D (PGZ1) gz1_init(); if ( gz1 =3D=3D 0 ) { return 0; } gz1->decompress =3D gzp->decompress; strcpy( gz1->ifname, gzp->input_filename ); strcpy( gz1->ofname, gzp->output_filename ); gz1->input_ismem =3D gzp->input_ismem; gz1->input_ptr =3D gzp->input_ismem_ibuf; gz1->input_bytesleft =3D gzp->input_ismem_ibuflen; gz1->output_ismem =3D gzp->output_ismem; gz1->output_ptr =3D gzp->output_ismem_obuf; gz1->output_maxlen =3D gzp->output_ismem_obuflen; if ( gz1->no_time < 0 ) gz1->no_time =3D gz1->decompress; if ( gz1->no_name < 0 ) gz1->no_name =3D gz1->decompress; work =3D zip;=20 if ( !gz1->input_ismem )=20 { =20 errno =3D 0; rc =3D stat( gz1->ifname, &gz1->istat ); if ( rc !=3D 0 )=20 { gz1_cleanup( gz1 );=20 return 0;=20 } gz1->ifile_size =3D gz1->istat.st_size; gz1->ifd =3D OPEN( gz1->ifname, gz1->ascii && !gz1->decompress ? O_RDONLY : O_RDONLY | O_BINARY, RW_USER ); if ( gz1->ifd =3D=3D -1 ) { gz1_cleanup( gz1 );=20 return 0;=20 } } if ( !gz1->output_ismem )=20 { =20 if ( gz1->ascii && gz1->decompress ) { ofile_flags &=3D ~O_BINARY;=20 } gz1->ofd =3D OPEN( gz1->ofname, ofile_flags, RW_USER ); if ( gz1->ofd =3D=3D -1 ) { if ( gz1->ifd )=20 { close( gz1->ifd );=20 gz1->ifd =3D 0; =20 } gz1_cleanup( gz1 );=20 return 0;=20 } } gz1->outcnt =3D 0; gz1->insize =3D 0; gz1->inptr =3D 0; gz1->bytes_in =3D 0L; gz1->bytes_out =3D 0L;=20 gz1->part_nb =3D 0; if ( gz1->decompress ) { =20 gz1->method =3D get_header( gz1, gz1->ifd ); if ( gz1->method < 0 ) { if ( gz1->ifd )=20 { close( gz1->ifd );=20 gz1->ifd =3D 0; =20 } if ( gz1->ofd )=20 { close( gz1->ofd );=20 gz1->ofd =3D 0; =20 } return 0;=20 } } gz1->save_orig_name =3D 0; gz1->state =3D GZS_ZIP1; for (;;)=20 { gzs_fsp( gz1 );=20 if ( gz1->done =3D=3D 1 ) break;=20 } if ( gz1->ifd )=20 { close( gz1->ifd );=20 gz1->ifd =3D 0; =20 } if ( gz1->ofd )=20 { close( gz1->ofd );=20 gz1->ofd =3D 0; =20 } gzp->result_code =3D gz1->exit_code; gzp->bytes_out =3D gz1->bytes_out; final_exit_code =3D (int) gz1->exit_code; gz1_cleanup( gz1 ); =20 return final_exit_code;=20 } int gzs_fsp( PGZ1 gz1 ) { int rc=3D0;=20 switch( gz1->state ) { case GZS_ZIP1: rc =3D gzs_zip1( gz1 ); break; case GZS_ZIP2: rc =3D gzs_zip2( gz1 ); break; case GZS_DEFLATE1: rc =3D gzs_deflate1( gz1 ); break; case GZS_DEFLATE2: rc =3D gzs_deflate2( gz1 ); break; default:=20 gz1->done =3D 1; break; } return( rc ); } int gzs_zip1( PGZ1 gz1 ) { uch flags =3D 0; =20 ush attr =3D 0; =20 ush deflate_flags =3D 0;=20 gz1->outcnt =3D 0; gz1->method =3D DEFLATED; put_byte(GZIP_MAGIC[0]);=20 put_byte(GZIP_MAGIC[1]); put_byte(DEFLATED); =20 if ( gz1->save_orig_name ) { =09flags |=3D ORIG_NAME; } put_byte(flags); =20 put_long(gz1->time_stamp);=20 gz1->crc =3D -1;=20 updcrc( gz1, NULL, 0 );=20 gz1->state =3D GZS_ZIP2; return 0; } int gzs_zip2( PGZ1 gz1 ) { uch flags =3D 0; =20 ush attr =3D 0; =20 ush deflate_flags =3D 0;=20 bi_init( gz1, gz1->ofd ); ct_init( gz1, &attr, &gz1->method ); lm_init( gz1, gz1->level, &deflate_flags ); put_byte((uch)deflate_flags);=20 put_byte(OS_CODE);=20 if ( gz1->save_orig_name ) { =20 char *p =3D basename( gz1, gz1->ifname ); do { =09 put_char(*p); } while (*p++); } gz1->header_bytes =3D (long)gz1->outcnt; gz1->state =3D GZS_DEFLATE1; return 0; } int gzs_deflate1( PGZ1 gz1 ) { if ( !gz1->deflate1_initialized ) { =20 gz1->deflate1_match_available =3D 0; =20 gz1->deflate1_match_length =3D MIN_MATCH-1;=20 gz1->deflate1_initialized =3D 1;=20 } if ( gz1->compr_level <=3D 3 ) { gz1->done =3D 1;=20 return 0; } if ( gz1->lookahead =3D=3D 0 ) { =20 if ( gz1->deflate1_match_available ) { ct_tally( gz1, 0, gz1->window[gz1->strstart-1] ); } gz1->state =3D GZS_DEFLATE2; return (int) FLUSH_BLOCK(1);=20 } #ifdef STAY_HERE_FOR_A_CERTAIN_AMOUNT_OF_ITERATIONS =20 while( iterations < max_iterations_per_yield ) { =20 #endif gz1->ins_h =3D (((gz1->ins_h)<window[gz1->strstart+MIN_MATCH-1])) & H= ASH_MASK; prev[ gz1->strstart & WMASK ] =3D gz1->deflate1_hash_head =3D head[ gz1-= >ins_h ]; head[ gz1->ins_h ] =3D gz1->strstart; gz1->prev_length =3D gz1->deflate1_match_length, gz1->deflate1_prev_matc= h =3D gz1->match_start; gz1->deflate1_match_length =3D MIN_MATCH-1; if ( gz1->deflate1_hash_head !=3D NIL && gz1->prev_length < gz1->max_laz= y_match && gz1->strstart - gz1->deflate1_hash_head <=3D MAX_DIST) { gz1->deflate1_match_length =3D longest_match( gz1, gz1->deflate1_hash= _head ); if ( gz1->deflate1_match_length > gz1->lookahead ) { gz1->deflate1_match_length =3D gz1->lookahead; } if (gz1->deflate1_match_length =3D=3D MIN_MATCH && gz1->strstart-gz1-= >match_start > TOO_FAR) { =20 gz1->deflate1_match_length--; } } if ( gz1->prev_length >=3D MIN_MATCH && gz1->deflate1_match_length <=3D=20= gz1->prev_length ) { gz1->deflate1_flush =3D ct_tally(gz1,gz1->strstart-1-gz1->deflate1_prev_match, gz1->prev_leng= th - MIN_MATCH); gz1->lookahead -=3D ( gz1->prev_length - 1 ); gz1->prev_length -=3D 2; do { gz1->strstart++; gz1->ins_h =3D (((gz1->ins_h)<window[ gz1->strstart + MIN_MATC= H-1])) & HASH_MASK; prev[ gz1->strstart & WMASK ] =3D gz1->deflate1_hash_head =3D hea= d[gz1->ins_h]; head[ gz1->ins_h ] =3D gz1->strstart; } while (--gz1->prev_length !=3D 0); gz1->deflate1_match_available =3D 0; gz1->deflate1_match_length =3D MIN_MATCH-1; gz1->strstart++; if (gz1->deflate1_flush) FLUSH_BLOCK(0), gz1->block_start =3D gz1->st= rstart; } else { if ( gz1->deflate1_match_available ) { if ( ct_tally( gz1, 0, gz1->window[gz1->strstart-1] ) ) { FLUSH_BLOCK(0), gz1->block_start =3D gz1->strstart; } gz1->strstart++; gz1->lookahead--; } else=20 { =20 gz1->deflate1_match_available =3D 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) =20 if (gz1->ifile_size !=3D -1L && gz1->isize !=3D (ulg)gz1->ifile_size) { } #endif put_long( gz1->crc ); put_long( gz1->bytes_in ); gz1->header_bytes +=3D 2*sizeof(long); flush_outbuf( gz1 ); gz1->done =3D 1;=20 return OK; } /* END OF FILE */ --part1_37.b663b5a.2718807d_boundary--