This patch is generated from the te_modules branch of te in squid Wed Sep 29 01:33:46 2004 GMT See http://devel.squid-cache.org/ Index: squid/acconfig.h diff -u squid/acconfig.h:1.1.1.3.8.6 squid/acconfig.h:1.1.1.3.8.6.2.1 --- squid/acconfig.h:1.1.1.3.8.6 Wed Jan 10 05:09:13 2001 +++ squid/acconfig.h Mon Jan 15 15:53:03 2001 @@ -275,6 +275,11 @@ #undef ATHY_COMPRESSION /* + * Use the freely available zlib compression/decompression library + */ +#undef ZLIB_COMPRESSION + +/* * message type for message queues */ #undef mtyp_t Index: squid/configure.in diff -u squid/configure.in:1.1.1.3.8.11 squid/configure.in:1.1.1.3.8.10.2.2 --- squid/configure.in:1.1.1.3.8.11 Thu Jan 11 04:09:57 2001 +++ squid/configure.in Mon Jan 15 15:53:03 2001 @@ -688,6 +688,41 @@ fi ]) +AC_ARG_WITH(pthreads, +[ --with-pthreads Use POSIX Threads], +[ if test "$enableval" = "yes"; then + with_pthreads=yes + fi +]) +if test "$with_pthreads"; then + echo "With pthreads" + SQUID_PTHREAD_LIB='$(PTHREADLIB)' + CFLAGS="$CFLAGS -D_REENTRANT" + case "$host" in + i386-unknown-freebsd*) + if test "$GCC" = "yes" ; then + if test -z "$PRESET_LDFLAGS"; then + LDFLAGS="$LDFLAGS -pthread" + fi + fi + ;; + esac +fi + +dnl Enable zlib_compression +AC_ARG_WITH(zlib, +[ --with-zlib This option makes use of libz (zlib) to handle + compressed transfer encodings.], +[ if test "$enableval" = "yes" ; then + with_zlib=yes + fi +]) +if test "$with_zlib"; then + echo "Enabling ZLIB_COMPRESSION" + AC_DEFINE(ZLIB_COMPRESSION, 1) + LIBS="-lz $LIBS" +fi + dnl Select auth schemes modules to build AC_ARG_ENABLE(auth, [ --enable-auth=\"list of auth scheme modules\" Index: squid/src/client_side.c diff -u squid/src/client_side.c:1.1.1.3.4.1.4.15 squid/src/client_side.c:1.1.1.3.4.1.4.13.2.4 --- squid/src/client_side.c:1.1.1.3.4.1.4.15 Sat Jan 13 00:31:13 2001 +++ squid/src/client_side.c Fri Feb 2 06:23:23 2001 @@ -1242,7 +1242,6 @@ last call: b==0.. good time to clean up *e if you've stored stuff there.. you may produce output if necessary, but last call will be repeated. */ - #ifndef _TE_RVALUES_ #define _TE_RVALUES_ #define TE_BUFFER_ALLOCATED 0x01 @@ -1341,7 +1340,6 @@ stringClean(&strConnection); } - te_build_encode_xlate_list(ohdr, hdr, &http->te_translations, request->http_ver, &request->flags); #if wrong_order @@ -2105,6 +2103,7 @@ (size == 0 && !(http->oldte_rv & TE_BUFFERING_OUTPUT))) { debug(33, 5) ("clientWriteComplete: FD %d transfer is DONE\n", fd); /* We're finished case */ + if (!http->flags.done_copying) { http->oldte_rv = free_te = perform_te (http->te_translations,NULL,0, &stuck_data, &stuckdatasize); if (stuckdatasize > 0) @@ -2124,6 +2123,11 @@ if (free_te & TE_BUFFER_ALLOCATED) xfree (stuck_data); + if (free_te & TE_CHUNK_A) /* signal from dochunk() that + data has been chunked */ + { + http->flags.done_copying = 1; + } return; } if (free_te & TE_CHUNK_A) /* signal from dochunk() that @@ -2131,6 +2135,7 @@ { http->flags.done_copying = 1; } + } if (httpReplyBodySize(http->request->method, entry->mem_obj->reply) < 0) { debug(33, 5) ("clientWriteComplete: closing, content_length < 0\n"); comm_close(fd); Index: squid/src/http.c diff -u squid/src/http.c:1.1.1.3.4.1.4.12 squid/src/http.c:1.1.1.3.4.1.4.10.2.3 --- squid/src/http.c:1.1.1.3.4.1.4.12 Sat Jan 13 00:31:13 2001 +++ squid/src/http.c Mon Jan 15 15:53:04 2001 @@ -565,9 +565,9 @@ } /* perform response data modifications here */ -{ -size_t k=0; -int terv=0; + { + size_t k=0; + int terv=0; /* for now, client_side filters bad headers, we just know where they stop for te to start */ /* recreate headers without te stuff */ @@ -578,8 +578,8 @@ httpState->written+=k; } - if (k != len) - { + if (k != len) { + if (entry->mem_obj->reply->decode_translations) { char *te_body_buf; size_t te_body_len; /* perform transfer encoding on the recieved buffer */ @@ -624,8 +624,14 @@ */ } + else { + /* no te took place */ + storeAppend(entry, buf+k, len-k); + /* don't alter content length on non te responses. */ + } } -debug(1,1)("written - %d\n",httpState->written); + } + debug(1,1)("written - %d\n",httpState->written); if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { /* * the above storeAppend() call could ABORT this entry, @@ -831,20 +837,8 @@ if (Config.fake_ua && !httpHeaderHas(hdr_out, HDR_USER_AGENT)) httpHeaderPutStr(hdr_out, HDR_USER_AGENT, Config.fake_ua); #endif - /* append TE */ - { - char strTE[128]; - - httpHeaderDelById(hdr_out, HDR_TE); /* hop by hop.. that's what last - hop could do*/ - /* TODO: this should be built from a list of known types & a acl allowing type - * to be used in requests vs responses */ - strcpy (strTE,"chunked;q=1.0"); - httpHeaderPutStr (hdr_out,HDR_TE,strTE); - httpHeaderPutStr(hdr_out,HDR_CONNECTION, "TE"); /* its hop by hop */ - - } + te_generate_request(hdr_out); /* append Via */ strVia = httpHeaderGetList(hdr_in, HDR_VIA); Index: squid/src/protos.h diff -u squid/src/protos.h:1.1.1.3.8.11 squid/src/protos.h:1.1.1.3.8.10.2.3 --- squid/src/protos.h:1.1.1.3.8.11 Sat Jan 13 00:31:13 2001 +++ squid/src/protos.h Mon Jan 15 15:53:04 2001 @@ -1292,12 +1292,9 @@ /* * transfer_encoding.c */ -extern void new_xlat (TE_list **translations, int beg_or_end, - int (*func)(char *, int , char **, int *, void **), - void *data); extern int perform_te (TE_list *xlat, char *ibuf, int ibufl, char **obuf, int *obufl); /* alters hdr as it build the list */ extern void te_build_decode_xlate_list(HttpHeader * hdr, TE_list **translations); extern void te_build_encode_xlate_list(const HttpHeader *ohdr, HttpHeader *hdr, TE_list **translations, http_version_t http_ver, request_flags *flags); - +extern void te_generate_request(HttpHeader * hdrout); Index: squid/src/structs.h diff -u squid/src/structs.h:1.1.1.3.4.1.4.12 squid/src/structs.h:1.1.1.3.4.1.4.11.2.2 --- squid/src/structs.h:1.1.1.3.4.1.4.12 Sat Jan 13 00:31:13 2001 +++ squid/src/structs.h Mon Jan 15 01:38:17 2001 @@ -865,9 +865,16 @@ }; +struct _te_coding_t { + te_coding_t *next; + char *token; + TEFILTER *encode; + TEFILTER *decode; +}; + typedef struct _TE_list { - int (*func)(char *ibuf, int ibufl, char **obuf, int *obufl, void **data); + TEFILTER *func; void *data; struct _TE_list *next; } Index: squid/src/transfer-encoding.c diff -u squid/src/transfer-encoding.c:1.1.2.1 squid/src/transfer-encoding.c:1.1.4.6 --- squid/src/transfer-encoding.c:1.1.2.1 Sat Jan 13 00:31:13 2001 +++ squid/src/transfer-encoding.c Fri Feb 2 06:23:23 2001 @@ -37,6 +37,26 @@ #include "squid.h" +#ifdef ATHY_COMPRESSION +#include +#else +#ifdef ZLIB_COMPRESSION +#ifdef _SQUID_CYGWIN_ +#define ZLIB_STATIC +#endif +#include +#endif +#endif + +#define HAVE_H_HSYNC +#ifdef HAVE_H_HSYNC +#include +#endif + +/* NOTES: TEFILTERS MUST set obuf and obufl */ +/* TEFILTERS use obuf for output IFF the outpub <= the input size */ +/* ibuf always == obuf */ + int perform_te (TE_list *xlat, char *ibuf, int ibufl, char **obuf, int *obufl) @@ -52,6 +72,7 @@ while (xlat) { /* xlat func is likely to be unbiff or dogzip() or something */ + debug(82,1)("perform te %p\n",xlat->func); rv &= 0xFE; /* turn off low bit, for reuse, while preserving chunk indicators */ @@ -82,7 +103,7 @@ } /* this is a TE filter */ -static int dochunk (char *ibuf, int ibufl, char **obuf, int *obufl, void **d) +static int dochunk (char *ibuf, size_t ibufl, char **obuf, size_t *obufl, void **d) { char *tb, *w; int tbl, created, rv; @@ -104,14 +125,18 @@ *d = (void *) 0x01; } else /* end signal */ +#if 0 if (*d) +#endif { strcpy (tb,"0\r\n\r\n"); created = 5; debug(82,8) ("created chunk of %d\n",ibufl); *d = NULL; - rv = TE_BUFFERING_OUTPUT; - } + rv = TE_CHUNK_A | TE_BUFFER_ALLOCATED; //TE_BUFFERING_OUTPUT; + +} +#if 0 else { /* allocate a buffer of length 128, and return it with length 0 */ @@ -119,7 +144,7 @@ *obufl = 0; return TE_CHUNK_A | TE_BUFFER_ALLOCATED; /* signal that dochunk() is complete */ } - +#endif *obuf = tb; *obufl = created; @@ -127,7 +152,7 @@ } static int undochunked - (char *ibuf, int ibufl, char **obuf, int *obufl, void **d) + (char *ibuf, size_t ibufl, char **obuf, size_t *obufl, void **d) { chunked_t *h; char *tb, *w, *l; @@ -298,15 +323,1195 @@ return rv; } + + +/* this is a TE filter */ +static int unbiff (char *ibuf, size_t ibufl, char **obuf, size_t *obufl, void **d) +{ + + *obuf = ibuf; + *obufl = ibufl; + + if (!ibufl) return 0; + + for (;ibufl>0;ibufl--) + if (ibuf[ibufl-1] == 'a') + ibuf[ibufl-1] ='b'; + else + if (ibuf[ibufl-1] == 'b') + ibuf[ibufl-1] ='a'; + return 0; +} + +/* this is a TE filter */ +int biff (char *ibuf, size_t ibufl, char **obuf, size_t *obufl, void **d) +{ + /* like ROT13.. symmetrical mappings */ + return unbiff (ibuf,ibufl,obuf,obufl,d); +} + +/* this is a TE filter */ +static int unjones (char *ibuf, size_t ibufl, char **obuf, size_t *obufl, void **d) +{ + + *obufl = ibufl; + *obuf = ibuf; + + if (!ibufl) return 0; + + for (;ibufl>0;ibufl--) + if (ibuf[ibufl-1] == 'c') + ibuf[ibufl-1] ='b'; + else + if (ibuf[ibufl-1] == 'b') + ibuf[ibufl-1] ='c'; + return 0; +} + +/* this is a TE filter */ +int jones (char *ibuf, size_t ibufl, char **obuf, size_t *obufl, void **d) +{ + /* like ROT13.. symmetrical mappings */ + return unjones (ibuf,ibufl,obuf,obufl,d); +} + + +#ifdef ATHY_COMPRESSION + +/* this is a TE filter */ +static int dogzip (char *ibuf, int ibufl, char **obuf, int *obufl, void **d) +{ + compression_t *m13; + char *tb; + int tbl, of,created; + + m13 = *((compression_t **) d); + + if (!m13) + { + if (!ibufl) /* no input, nothing to finish.. */ + { + *obufl = 0; + return 0; + } + + m13 = compression_init (COMPRESSION_GZIP,COMPRESSION_STD); + *d = (void *) m13; + } + + tbl = ibufl+512; + tb = xmalloc (tbl); + + if (ibufl > 0) + { + created = 0; + do + { + created += compression_shrink (m13,ibuf,ibufl,tb+created,tbl,&of); + if (of>0) + { + tbl = of+16; + tb = xrealloc (tb,created+tbl); + ibufl = 0; + } + } + while (of>0); + + } + else /* end signal */ + { + created = compression_free (m13,tb); + *d = NULL; + } + + + *obuf = tb; + *obufl = created; + + return 1; +} + +/* this is a TE filter */ +static int undogzip (char *ibuf, int ibufl, char **obuf, int *obufl, void **d) +{ + compression_t *m13; + char *tb; + int tbl, of,created; + + m13 = *((compression_t **) d); + if (!m13) + { + m13 = compression_init (COMPRESSION_GZIP,COMPRESSION_STD); + *d = (void *) m13; + } + + tbl = ibufl*2+512; + tb = xmalloc (tbl); + + created = 0; + if (ibuf) + { + do + { + created += compression_expand (m13,ibuf,ibufl,tb+created,tbl,&of); + if (of>0) + { + tbl = of+16; + tb = xrealloc (tb,created+tbl); + ibufl = 0; + } + } + while (of>0); + } + + else + { + do + { + created += compression_finish_expand (m13,tb+created,tbl,&of); + if (of>0) + { + tbl = of+16; + tb = xrealloc (tb,created+tbl); + } + } + while (of > 0); + + compression_free (m13,tb); + *d = NULL; + } + + + *obuf = tb; + *obufl = created; + + return 1; +} + + +/* this is a TE filter */ +static int dodeflate (char *ibuf, int ibufl, char **obuf, int *obufl, void **d) +{ + compression_t *m13; + char *tb; + int tbl, of,created; + + m13 = *((compression_t **) d); + + if (!m13) + { + if (!ibufl) /* no input, nothing to finish.. */ + { + *obufl = 0; + return 0; + } + + m13 = compression_init (COMPRESSION_ZLIB,COMPRESSION_STD); + *d = (void *) m13; + } + + tbl = ibufl+512; + tb = xmalloc (tbl); + + if (ibufl > 0) + { + created = 0; + do + { + created += compression_shrink (m13,ibuf,ibufl,tb+created,tbl,&of); + if (of>0) + { + tbl = of+16; + tb = xrealloc (tb,created+tbl); + ibufl = 0; + } + } + while (of>0); + + } + else /* end signal */ + { + created = compression_free (m13,tb); + *d = NULL; + } + + + *obuf = tb; + *obufl = created; + + return 1; +} + +/* this is a TE filter */ +static int undodeflate(char *ibuf, int ibufl, char **obuf, int *obufl, void **d) +{ + compression_t *m13; + char *tb; + int tbl, of,created; + + m13 = *((compression_t **) d); + + if (!m13) + { + m13 = compression_init (COMPRESSION_ZLIB,COMPRESSION_STD); /* rfc 1950 */ + *d = (void *) m13; + } + + tbl = ibufl*2+512; + tb = xmalloc (tbl); + + created = 0; + if (ibuf) + { + do + { + created += compression_expand (m13,ibuf,ibufl,tb+created,tbl,&of); + if (of>0) + { + tbl = of+16; + tb = xrealloc (tb,created+tbl); + ibufl = 0; + } + } + while (of>0); + } + + else + { + do + { + created += compression_finish_expand (m13,tb+created,tbl,&of); + if (of>0) + { + tbl = of+16; + tb = xrealloc (tb,created+tbl); + } + } + while (of > 0); + + compression_free (m13,tb); + *d = NULL; + } + + + *obuf = tb; + *obufl = created; + + return 1; +} +#else /*ATH_COMPRESSION*/ +#if ZLIB_COMPRESSION + +static void * compcalloc (void *opaque, uInt items, uInt size) { + return xcalloc(items, size); +} + +static void compfree (void *opaque, void * address) { + xfree (address); +} + +/* this is a TE filter */ +static int dodeflate (char *ibuf, size_t ibufl, char **obuf, size_t *obufl, void **d) +{ +/* 4K. TODO: lookup membuf 4k thingy code */ +#define DEFLATEBLOCKSIZE 4096 + z_streamp zdata; + size_t output=0; + int rv; + /* if we run out of output space, we have to store the already output data */ + char *tempbuf=NULL; + + if (!ibufl && !*d) { + /* we haven't been inited and there's nothing to do */ + *obufl=0; + *obuf=NULL; + return 1; + } + if (!*d) { + int rv; + /* first call - no data in progress */ + zdata=xmalloc(sizeof(z_stream)); + *d=zdata; + assert(zdata!= NULL); + zdata->zalloc=compcalloc; + zdata->zfree=compfree; + zdata->opaque=NULL; + + rv=deflateInit(zdata, Z_DEFAULT_COMPRESSION); + debug (82,1)("dodeflate: initialising compression library: rv is %d\n",rv); + if (rv != Z_OK) { + /* error initing compressiong */ + debug(82,1)("dodeflate: compression library returned: %s\n",zdata->msg); + return 0; + } + + } + zdata=*d; + assert (!((ibufl==0) && ibuf != NULL)); + zdata->next_in=ibuf; + zdata->avail_in=ibufl; + debug(82,1)("available buffer = %d ibufl = %d\n", DEFLATEBLOCKSIZE,ibufl); + *obuf = xmalloc( DEFLATEBLOCKSIZE); + if (ibufl >0) { + debug(82,1)("dodeflate compressing %d bytes\n",ibufl); + do { + zdata->next_out=*obuf+output; + zdata->avail_out=DEFLATEBLOCKSIZE; + rv=deflate(zdata,Z_NO_FLUSH); + output+= DEFLATEBLOCKSIZE-zdata->avail_out; + if (zdata->avail_in) { + /* ran out of space */ + debug(82,1)("dodeflate allocating another %d bytes\n",DEFLATEBLOCKSIZE); + tempbuf=*obuf; + *obuf=xmalloc(output+DEFLATEBLOCKSIZE); + memcpy(*obuf,tempbuf,output); + xfree(tempbuf); + } else if (rv != Z_OK) { + xfree(*obuf); + *obuf=0; + *obufl=0; + deflateEnd(zdata); + xfree(zdata); + *d=NULL; + return 0; + } + } while (zdata->avail_in); + } + else { + debug(82,1)("dodeflate flushing buffer at EOF\n"); + /* flush the remaining data */ + do { + zdata->avail_out= DEFLATEBLOCKSIZE; + zdata->next_out=*obuf+output; + rv=deflate (zdata, Z_FINISH); + output+= DEFLATEBLOCKSIZE-zdata->avail_out; + if (rv==Z_OK && (zdata->avail_out == 0)) { + /* ran out of space */ + debug(82,1)("dodeflate allocating another %d bytes\n",DEFLATEBLOCKSIZE); + tempbuf=*obuf; + *obuf=xmalloc(output+DEFLATEBLOCKSIZE); + memcpy(*obuf,tempbuf,output); + xfree(tempbuf); + } else if (rv != Z_STREAM_END) { + /* wasn't out of space, and not all finished */ + debug(82,1)("dodeflate: error flushing data\n"); + xfree(*obuf); + *obuf=0; + *obufl=0; + deflateEnd(zdata); + xfree(zdata); + *d=NULL; + return 0; + } + } while (rv != Z_STREAM_END); + deflateEnd(zdata); + xfree(zdata); + *d=NULL; + /* return TE_BUFFER_ALLOCATED; */ /* & TE_BUFFERED_OUTPUT */ + + } + debug(82,1)("avail in %d, out %d\n",zdata->avail_in, zdata->avail_out); + debug(82,1)("created block of %d bytes\n",output); + *obufl=output; + return TE_BUFFER_ALLOCATED; /* & TE_BUFFERED_OUTPUT */ +} + + +/* this is a TE filter */ +static int undodeflate(char *ibuf, size_t ibufl, char **obuf, size_t *obufl, void **d) +{ +/* 4K. TODO: lookup membuf 4k thingy code */ +#define DEFLATEBLOCKSIZE 4096 + z_streamp zdata; + size_t output=0; + int rv; + /* if we run out of output space, we have to store the already output data */ + char *tempbuf=NULL; + + if (!ibufl && !*d) { + /* we haven't been inited and there's nothing to do */ + *obufl=0; + *obuf=NULL; + return 0; + } + if (!*d) { + int rv; + /* first call - no data in progress */ + zdata=xmalloc(sizeof(z_stream)); + *d=zdata; + assert(zdata!= NULL); + zdata->zalloc=compcalloc; + zdata->zfree=compfree; + zdata->opaque=NULL; + zdata->next_in=ibuf; + /* defer header reading */ + zdata->avail_in=0; + + rv=inflateInit(zdata); + debug (82,1)("undodeflate: initialising compression library: rv is %d\n",rv); + if (rv != Z_OK) { + /* error initing compressiong */ + debug(82,1)("undodeflate: compression library returned: %s\n",zdata->msg); + return 0; + } + + } + zdata=*d; + assert (!((ibufl==0) && ibuf != NULL)); + zdata->next_in=ibuf; + zdata->avail_in=ibufl; + debug(82,1)("available buffer = %d ibufl = %d\n", DEFLATEBLOCKSIZE,ibufl); + *obuf = xmalloc( DEFLATEBLOCKSIZE); + if (ibufl >0) { + debug(82,1)("undodeflate uncompressing %d bytes\n",ibufl); + do { + zdata->next_out=*obuf+output; + zdata->avail_out=DEFLATEBLOCKSIZE; + rv=inflate(zdata,Z_NO_FLUSH); + output+= DEFLATEBLOCKSIZE-zdata->avail_out; + if (zdata->avail_in) { + /* ran out of space */ + debug(82,1)("undodeflate allocating another %d bytes - buffer now %d - remaining bytes to be process %d\n",DEFLATEBLOCKSIZE,output+DEFLATEBLOCKSIZE,zdata->avail_in); + tempbuf=*obuf; + *obuf=xmalloc(output+DEFLATEBLOCKSIZE); + memcpy(*obuf,tempbuf,output); + xfree(tempbuf); + } else if (!((rv == Z_OK) || (rv == Z_STREAM_END))) { + xfree(*obuf); + *obuf=0; + *obufl=0; + inflateEnd(zdata); + xfree(zdata); + *d=NULL; + return 0; + } + } while (zdata->avail_in); + if (rv== Z_STREAM_END) { + inflateEnd(zdata); + xfree(zdata); + *d=NULL; + } + } + else { + /* errors in decoding are trapped above. Successful decoding frees t*d, + * so the !*d && !ibufl test runs above. */ + fatal("undodeflate: inconsistent decompression state reached\n"); +#if 0 + debug(82,1)("undodeflate flushing buffer at EOF\n"); + /* flush the remaining data */ + do { + zdata->stream.avail_out= DEFLATEBLOCKSIZE; + zdata->next_out=*obuf+output; + rv=deflate (zdata, Z_FINISH); + output+= DEFLATEBLOCKSIZE-zdata->stream.avail_out; + if (rv==Z_OK && (zdata->stream.avail_out == 0)) { + /* ran out of space */ + debug(82,1)("undodeflate allocating another %d bytes\n",DEFLATEBLOCKSIZE); + tempbuf=*obuf; + *obuf=xmalloc(output+DEFLATEBLOCKSIZE); + memcpy(*obuf,tempbuf,output); + xfree(tempbuf); + } else if (rv != Z_STREAM_END) { + /* wasn't out of space, and not all finished */ + debug(82,1)("undodeflate: error flushing data\n"); + xfree(*obuf); + *obuf=0; + *obufl=0; + deflateEnd(zdata); + xfree(zdata); + *d=NULL; + return 0; + } + } while (rv != Z_STREAM_END); + deflateEnd(zdata); + xfree(zdata); + *d=NULL; + /* return TE_BUFFER_ALLOCATED; */ /* & TE_BUFFERED_OUTPUT */ +#endif + } + if (zdata) + debug(82,1)("avail in %d, out %d\n",zdata->avail_in, zdata->avail_out); + debug(82,1)("created block of %d bytes\n",output); + *obufl=output; + return TE_BUFFER_ALLOCATED; /* & TE_BUFFERED_OUTPUT */ +} + + +static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ + +typedef struct _gzipstate { + z_stream stream; + uLong crc; + int headerread; + char transparent; + } gzipstate; + +/* this is a TE filter */ +/* look at gzio.c in zlib's source for the inspiration code */ +static int dogzip (char *ibuf, size_t ibufl, char **obuf, size_t *obufl, void **d) +{ +/* 4K. TODO: lookup membuf 4k thingy code */ +/* this hsould be large enough to handle the gzip header */ +#define DEFLATEBLOCKSIZE 4096 + gzipstate * zdata; + size_t output=0; + int rv; + /* if we run out of output space, we have to store the already output data */ + char *tempbuf=NULL; + + if (!ibufl && !*d) { + /* we haven't been inited and there's nothing to do */ + *obufl=0; + *obuf=NULL; + return 1; + } + zdata=*d; + assert (!((ibufl==0) && ibuf != NULL)); + if (!*d) { + int rv; + /* first call - no data in progress */ + zdata=xmalloc(sizeof(gzipstate)); + *d=zdata; + assert(zdata!= NULL); + zdata->stream.zalloc=compcalloc; + zdata->stream.zfree=compfree; + zdata->stream.opaque=NULL; + zdata->crc=crc32(0L, Z_NULL, 0); + zdata->stream.next_in=zdata->stream.next_out=NULL; + zdata->stream.avail_in=zdata->stream.avail_out=0; + + rv=deflateInit2(&(zdata->stream), Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS, + 8, Z_DEFAULT_STRATEGY); + debug (82,1)("dogzip: initialising compression library: rv is %d\n",rv); + if (rv != Z_OK) { + /* error initing compressiong */ + debug(82,1)("dogzip: compression library returned: %s\n",zdata->stream.msg); + return 0; + } + *obuf= xmalloc (11); + snprintf(*obuf,11, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], + Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, 0x03); + output=10; + tempbuf=*obuf; + *obuf=xmalloc(output+DEFLATEBLOCKSIZE); + memcpy(*obuf,tempbuf,output); + xfree(tempbuf); + } else { + *obuf = xmalloc( DEFLATEBLOCKSIZE); + } + zdata->stream.next_in=ibuf; + zdata->stream.avail_in=ibufl; + debug(82,1)("available buffer = %d ibufl = %d\n", DEFLATEBLOCKSIZE,ibufl); + if (ibufl >0) { + debug(82,1)("dogzip compressing %d bytes\n",ibufl); + do { + zdata->stream.next_out=*obuf+output; + zdata->stream.avail_out=DEFLATEBLOCKSIZE; + rv=deflate(&(zdata->stream),Z_NO_FLUSH); + output+= DEFLATEBLOCKSIZE-zdata->stream.avail_out; + if (zdata->stream.avail_in) { + /* ran out of space */ + debug(82,1)("dogzip allocating another %d bytes\n",DEFLATEBLOCKSIZE); + tempbuf=*obuf; + *obuf=xmalloc(output+DEFLATEBLOCKSIZE); + memcpy(*obuf,tempbuf,output); + xfree(tempbuf); + } else if (rv != Z_OK) { + xfree(*obuf); + *obuf=0; + *obufl=0; + deflateEnd(&(zdata->stream)); + xfree(zdata); + *d=NULL; + return 0; + } + } while (zdata->stream.avail_in); + zdata->crc = crc32(zdata->crc, ibuf, ibufl); + } + else { + debug(82,1)("dogzip flushing buffer at EOF\n"); + /* flush the remaining data */ + do { + zdata->stream.avail_out= DEFLATEBLOCKSIZE; + zdata->stream.next_out=*obuf+output; + rv=deflate (&(zdata->stream), Z_FINISH); + output+= DEFLATEBLOCKSIZE-zdata->stream.avail_out; + if (rv==Z_OK && (zdata->stream.avail_out == 0)) { + /* ran out of space */ + debug(82,1)("dogzip allocating another %d bytes\n",DEFLATEBLOCKSIZE); + tempbuf=*obuf; + *obuf=xmalloc(output+DEFLATEBLOCKSIZE); + memcpy(*obuf,tempbuf,output); + xfree(tempbuf); + } else if (rv != Z_STREAM_END) { + /* wasn't out of space, and not all finished */ + debug(82,1)("dogzip: error flushing data\n"); + xfree(*obuf); + *obuf=0; + *obufl=0; + deflateEnd(&(zdata->stream)); + xfree(zdata); + *d=NULL; + return 0; + } + } while (rv != Z_STREAM_END); + if (zdata->stream.avail_out<9) { + /* ran out of space */ + debug(82,1)("dogzip allocating another %d bytes\n",DEFLATEBLOCKSIZE); + tempbuf=*obuf; + *obuf=xmalloc(output+DEFLATEBLOCKSIZE); + memcpy(*obuf,tempbuf,output); + xfree(tempbuf); + } + /* write checksum and content length */ + { + int n; + for (n = 0; n < 4; n++) { + *(*obuf+output++)=(unsigned char)(zdata->crc & 0xff); + zdata->crc >>= 8; + } + } + { + int n; + for (n = 0; n < 4; n++) { + *(*obuf+output++)=(unsigned char)(zdata->stream.total_in & 0xff); + zdata->stream.total_in >>= 8; + } + } + deflateEnd(&(zdata->stream)); + xfree(zdata); + *d=NULL; + + } + debug(82,1)("avail in %d, out %d\n",zdata->stream.avail_in, zdata->stream.avail_out); + debug(82,1)("created block of %d bytes\n",output); + *obufl=output; + return TE_BUFFER_ALLOCATED; /* & TE_BUFFERED_OUTPUT */ +} + +/* this is a TE filter */ +static int undogzip(char *ibuf, size_t ibufl, char **obuf, size_t *obufl, void **d) +{ +/* 4K. TODO: lookup membuf 4k thingy code */ +#define DEFLATEBLOCKSIZE 4096 + gzipstate *zdata; + size_t output=0; + int rv; + /* if we run out of output space, we have to store the already output data */ + char *tempbuf=NULL; + + if (!ibufl && !*d) { + /* we haven't been inited and there's nothing to do */ + *obufl=0; + *obuf=NULL; + return 0; + } + zdata=*d; + if (ibuf == NULL && ibufl != 0) { + /* tail end of data after compression stream ended */ + /* throw it away */ + *obufl=0; + *obuf=NULL; + return 0; + } + debug(82,1)("%p\n",*d); + assert (!((ibufl==0) && ibuf != NULL)); + if (!*d) { + int rv; + /* first call - no data in progress */ + zdata=xmalloc(sizeof(gzipstate)); + *d=zdata; + assert(zdata!= NULL); + zdata->stream.zalloc=compcalloc; + zdata->stream.zfree=compfree; + zdata->stream.opaque=NULL; + zdata->stream.next_in=ibuf; + /* defer header reading */ + zdata->stream.avail_in=0; + zdata->crc=crc32(0L, Z_NULL, 0); + zdata->headerread=0; + zdata->stream.next_out=NULL; + zdata->stream.avail_in=zdata->stream.avail_out=0; + + rv=inflateInit2(&(zdata->stream), -MAX_WBITS); + debug (82,1)("undogzip: initialising compression library: rv is %d\n",rv); + if (rv != Z_OK) { + /* error initing compressiong */ + debug(82,1)("undogzip: compression library returned: %s\n",zdata->stream.msg); + return 0; + } + rv = *ibuf; + } + + debug(82,1)("available buffer = %d ibufl = %d\n", DEFLATEBLOCKSIZE,ibufl); + zdata->stream.next_in=ibuf; + zdata->stream.avail_in=ibufl; + +/* this code is slightly broken: it requires the whole header before it does anything, + AND it wants it in the first call. What is should do is store how far through + the header decode it is as part of it's state, and return to there on subsequent + calls + */ + + if (zdata->headerread==0) { + /* processing the header still: ie called with inital buffer */ + int c; + int method,flags; + uInt len; + if (ibufl<10) { + /* bad magic */ + *obuf=NULL; + *obufl=0; + return 0; + } + for (len = 0 ;len < 2 ; len ++) { + c = *(zdata->stream.next_in); + if ( c!= gz_magic[len] ) { + /* bad magic */ + *obuf=NULL; + *obufl=0; + return 0; + } + zdata->stream.next_in++; + zdata->stream.avail_in--; + } + method=*(zdata->stream.next_in++);zdata->stream.avail_in--; + flags= *(zdata->stream.next_in++);zdata->stream.avail_in--; + if (method != Z_DEFLATED || (flags & RESERVED) != 0) { + /* bad magic */ + *obuf=NULL; + *obufl=0; + return 0; + } + /* discard time, xflags and OS code */ + zdata->stream.next_in+=6; + zdata->stream.avail_in-=6; + if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ + len = *(zdata->stream.next_in++);zdata->stream.avail_in--; + len += (*(zdata->stream.next_in++))<<8;zdata->stream.avail_in--; + /* len is garbage if EOF but the loop below will quit anyway */ + while (len-- != 0 && zdata->stream.avail_in>0){ zdata->stream.next_in++;zdata->stream.avail_in--;} + } + if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ + while ((c = *(zdata->stream.next_in++) != 0) && (zdata->stream.avail_in-- > 0)) ; + } + if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ + while ((c = *(zdata->stream.next_in++) != 0) && (zdata->stream.avail_in-- > 0)) ; + } + if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ + zdata->stream.next_in+=2; + zdata->stream.avail_in-=2; + } + if (zdata->stream.avail_in<0) { + /* bad magic */ + *obuf=NULL; + *obufl=0; + return 0; + } + debug(82,1)("gzip header decoded\n"); + zdata->headerread=1; + if (zdata->stream.avail_in==0) { + /* got exactly the header */ + *obuf=NULL; + *obufl=0; + return TE_BUFFERING_OUTPUT; + } + } + + + *obuf = xmalloc( DEFLATEBLOCKSIZE); + if (ibufl >0) { + size_t crcstart; + debug(82,1)("undogzip uncompressing %d bytes\n",ibufl); + do { + zdata->stream.next_out=*obuf+output; + zdata->stream.avail_out=DEFLATEBLOCKSIZE; + crcstart=zdata->stream.total_out; + rv=inflate(&(zdata->stream),Z_NO_FLUSH); + output+= DEFLATEBLOCKSIZE-zdata->stream.avail_out; + /* update the crc */ + zdata->crc=crc32(zdata->crc, *obuf, zdata->stream.total_out-crcstart); + if (rv == Z_STREAM_END) { + /* read checksum and content length */ + { + int n; + uLong tempcrc=0; + for (n = 0; n < 4; n++) { + tempcrc |= (unsigned char) (*(*obuf+n) & 0xff); + tempcrc <<= 8; + } + + if (tempcrc != zdata->crc) { + debug(82,1)("crc data mismatch in undogzip \n"); +/* + xfree(*obuf); + *obuf=NULL; + *obufl=0; + return 0; +*/ } + } + /* for now, ignore the uncompressed length field = we've check the check + * sum, and this is a file transfer coding: we cannot handle multiple + * entities no matter what */ +#if ignorefield + { + int n; + for (n = 0; n < 4; n++) { + *(*obuf+output++)=(unsigned char)(zdata->stream.total_in & 0xff); + zdata->stream.total_in >>= 8; + } + } +#endif + } + if (zdata->stream.avail_in) { + /* ran out of space */ + debug(82,1)("undogzip allocating another %d bytes - buffer now %d - rem +aining bytes to be process %d\n",DEFLATEBLOCKSIZE,output+DEFLATEBLOCKSIZE,zdata->stream.avail_in) +; + tempbuf=*obuf; + *obuf=xmalloc(output+DEFLATEBLOCKSIZE); + memcpy(*obuf,tempbuf,output); + xfree(tempbuf); + } else if (!((rv == Z_OK) || (rv == Z_STREAM_END))) { + xfree(*obuf); + *obuf=0; + *obufl=0; + inflateEnd(&(zdata->stream)); + xfree(zdata); + *d=NULL; + return 0; + } + } while (zdata->stream.avail_in>0 &! (rv == Z_STREAM_END)); + if (rv== Z_STREAM_END) { + inflateEnd(&(zdata->stream)); + xfree(zdata); + *d=NULL; + } + } + else { + /* errors in decoding are trapped above. Successful decoding frees t*d, + * so the !*d && !ibufl test runs above. */ + fatal("undogzip: inconsistent decompression state reached\n"); +#if 0 + debug(82,1)("undodeflate flushing buffer at EOF\n"); + /* flush the remaining data */ + do { + zdata->stream.avail_out= DEFLATEBLOCKSIZE; + zdata->next_out=*obuf+output; + rv=deflate (zdata, Z_FINISH); + output+= DEFLATEBLOCKSIZE-zdata->stream.avail_out; + if (rv==Z_OK && (zdata->stream.avail_out == 0)) { + /* ran out of space */ + debug(82,1)("undodeflate allocating another %d bytes\n",DEFLATEBLOCKSIZE); + tempbuf=*obuf; + *obuf=xmalloc(output+DEFLATEBLOCKSIZE); + memcpy(*obuf,tempbuf,output); + xfree(tempbuf); + } else if (rv != Z_STREAM_END) { + /* wasn't out of space, and not all finished */ + debug(82,1)("undodeflate: error flushing data\n"); + xfree(*obuf); + *obuf=0; + *obufl=0; + deflateEnd(zdata); + xfree(zdata); + *d=NULL; + return 0; + } + } while (rv != Z_STREAM_END); + deflateEnd(zdata); + xfree(zdata); + *d=NULL; + /* return TE_BUFFER_ALLOCATED; */ /* & TE_BUFFERED_OUTPUT */ +#endif + } + if (zdata) + debug(82,1)("avail in %d, out %d\n",zdata->stream.avail_in, zdata->stream.avail_out); + debug(82,1)("created block of %d bytes\n",output); + *obufl=output; + return TE_BUFFER_ALLOCATED; /* & TE_BUFFERED_OUTPUT */ +} + +#endif /*ZLIB_COMPRESSION */ +#endif /*!ATHY_COMPRESSION*/ + + +#ifdef HAVE_H_HSYNC +/* this is a TE filter */ +static int dorsyncdelta (char *ibuf, size_t ibufl, char **obuf, size_t *obufl, void **d) +{ +/* 4K. TODO: lookup membuf 4k thingy code */ +#define DEFLATEBLOCKSIZE 4096 + z_streamp zdata; + size_t output=0; + int rv; + /* if we run out of output space, we have to store the already output data */ + char *tempbuf=NULL; + + if (!ibufl && !*d) { + /* we haven't been inited and there's nothing to do */ + *obufl=0; + *obuf=NULL; + return 1; + } + if (!*d) { + int rv; + /* first call - no data in progress */ + zdata=xmalloc(sizeof(z_stream)); + *d=zdata; + assert(zdata!= NULL); + zdata->zalloc=compcalloc; + zdata->zfree=compfree; + zdata->opaque=NULL; + + rv=deflateInit(zdata, Z_DEFAULT_COMPRESSION); + debug (82,1)("dodeflate: initialising compression library: rv is %d\n",rv); + if (rv != Z_OK) { + /* error initing compressiong */ + debug(82,1)("dodeflate: compression library returned: %s\n",zdata->msg); + return 0; + } + + } + zdata=*d; + assert (!((ibufl==0) && ibuf != NULL)); + zdata->next_in=ibuf; + zdata->avail_in=ibufl; + debug(82,1)("available buffer = %d ibufl = %d\n", DEFLATEBLOCKSIZE,ibufl); + *obuf = xmalloc( DEFLATEBLOCKSIZE); + if (ibufl >0) { + debug(82,1)("dodeflate compressing %d bytes\n",ibufl); + do { + zdata->next_out=*obuf+output; + zdata->avail_out=DEFLATEBLOCKSIZE; + rv=deflate(zdata,Z_NO_FLUSH); + output+= DEFLATEBLOCKSIZE-zdata->avail_out; + if (zdata->avail_in) { + /* ran out of space */ + debug(82,1)("dodeflate allocating another %d bytes\n",DEFLATEBLOCKSIZE); + tempbuf=*obuf; + *obuf=xmalloc(output+DEFLATEBLOCKSIZE); + memcpy(*obuf,tempbuf,output); + xfree(tempbuf); + } else if (rv != Z_OK) { + xfree(*obuf); + *obuf=0; + *obufl=0; + deflateEnd(zdata); + xfree(zdata); + *d=NULL; + return 0; + } + } while (zdata->avail_in); + } + else { + debug(82,1)("dodeflate flushing buffer at EOF\n"); + /* flush the remaining data */ + do { + zdata->avail_out= DEFLATEBLOCKSIZE; + zdata->next_out=*obuf+output; + rv=deflate (zdata, Z_FINISH); + output+= DEFLATEBLOCKSIZE-zdata->avail_out; + if (rv==Z_OK && (zdata->avail_out == 0)) { + /* ran out of space */ + debug(82,1)("dodeflate allocating another %d bytes\n",DEFLATEBLOCKSIZE); + tempbuf=*obuf; + *obuf=xmalloc(output+DEFLATEBLOCKSIZE); + memcpy(*obuf,tempbuf,output); + xfree(tempbuf); + } else if (rv != Z_STREAM_END) { + /* wasn't out of space, and not all finished */ + debug(82,1)("dodeflate: error flushing data\n"); + xfree(*obuf); + *obuf=0; + *obufl=0; + deflateEnd(zdata); + xfree(zdata); + *d=NULL; + return 0; + } + } while (rv != Z_STREAM_END); + deflateEnd(zdata); + xfree(zdata); + *d=NULL; + /* return TE_BUFFER_ALLOCATED; */ /* & TE_BUFFERED_OUTPUT */ + + } + debug(82,1)("avail in %d, out %d\n",zdata->avail_in, zdata->avail_out); + debug(82,1)("created block of %d bytes\n",output); + *obufl=output; + return TE_BUFFER_ALLOCATED; /* & TE_BUFFERED_OUTPUT */ +} + +/* this is a TE filter */ +static int applyrsyncdelta(char *ibuf, size_t ibufl, char **obuf, size_t *obufl, void **d) +{ +/* 4K. TODO: lookup membuf 4k thingy code */ +#define DEFLATEBLOCKSIZE 4096 + z_streamp zdata; + size_t output=0; + int rv; + /* if we run out of output space, we have to store the already output data */ + char *tempbuf=NULL; + + if (!ibufl && !*d) { + /* we haven't been inited and there's nothing to do */ + *obufl=0; + *obuf=NULL; + return 0; + } + if (!*d) { + int rv; + /* first call - no data in progress */ + zdata=xmalloc(sizeof(z_stream)); + *d=zdata; + assert(zdata!= NULL); + zdata->zalloc=compcalloc; + zdata->zfree=compfree; + zdata->opaque=NULL; + zdata->next_in=ibuf; + /* defer header reading */ + zdata->avail_in=0; + + rv=inflateInit(zdata); + debug (82,1)("undodeflate: initialising compression library: rv is %d\n",rv); + if (rv != Z_OK) { + /* error initing compressiong */ + debug(82,1)("undodeflate: compression library returned: %s\n",zdata->msg); + return 0; + } + + } + zdata=*d; + assert (!((ibufl==0) && ibuf != NULL)); + zdata->next_in=ibuf; + zdata->avail_in=ibufl; + debug(82,1)("available buffer = %d ibufl = %d\n", DEFLATEBLOCKSIZE,ibufl); + *obuf = xmalloc( DEFLATEBLOCKSIZE); + if (ibufl >0) { + debug(82,1)("undodeflate uncompressing %d bytes\n",ibufl); + do { + zdata->next_out=*obuf+output; + zdata->avail_out=DEFLATEBLOCKSIZE; + rv=inflate(zdata,Z_NO_FLUSH); + output+= DEFLATEBLOCKSIZE-zdata->avail_out; + if (zdata->avail_in) { + /* ran out of space */ + debug(82,1)("undodeflate allocating another %d bytes - buffer now %d\n",DEFLATEBLOCKSIZE,output+DEFLATEBLOCKSIZE); + tempbuf=*obuf; + *obuf=xmalloc(output+DEFLATEBLOCKSIZE); + memcpy(*obuf,tempbuf,output); + xfree(tempbuf); + } else if (!((rv == Z_OK) || (rv == Z_STREAM_END))) { + xfree(*obuf); + *obuf=0; + *obufl=0; + inflateEnd(zdata); + xfree(zdata); + *d=NULL; + return 0; + } + } while (zdata->avail_in); + if (rv== Z_STREAM_END) { + inflateEnd(zdata); + xfree(zdata); + *d=NULL; + } + } + else { + /* errors in decoding are trapped above. Successful decoding frees t*d, + * so the !*d && !ibufl test runs above. */ + fatal("undodeflate: inconsistent decompression state reached\n"); +#if 0 + debug(82,1)("undodeflate flushing buffer at EOF\n"); + /* flush the remaining data */ + do { + zdata->stream.avail_out= DEFLATEBLOCKSIZE; + zdata->next_out=*obuf+output; + rv=deflate (zdata, Z_FINISH); + output+= DEFLATEBLOCKSIZE-zdata->stream.avail_out; + if (rv==Z_OK && (zdata->stream.avail_out == 0)) { + /* ran out of space */ + debug(82,1)("undodeflate allocating another %d bytes\n",DEFLATEBLOCKSIZE); + tempbuf=*obuf; + *obuf=xmalloc(output+DEFLATEBLOCKSIZE); + memcpy(*obuf,tempbuf,output); + xfree(tempbuf); + } else if (rv != Z_STREAM_END) { + /* wasn't out of space, and not all finished */ + debug(82,1)("undodeflate: error flushing data\n"); + xfree(*obuf); + *obuf=0; + *obufl=0; + deflateEnd(zdata); + xfree(zdata); + *d=NULL; + return 0; + } + } while (rv != Z_STREAM_END); + deflateEnd(zdata); + xfree(zdata); + *d=NULL; + /* return TE_BUFFER_ALLOCATED; */ /* & TE_BUFFERED_OUTPUT */ +#endif + } + if (zdata) + debug(82,1)("avail in %d, out %d\n",zdata->avail_in, zdata->avail_out); + debug(82,1)("created block of %d bytes\n",output); + *obufl=output; + return TE_BUFFER_ALLOCATED; /* & TE_BUFFERED_OUTPUT */ +} + +static int dorsyncsignature() +{ +} + +#endif + +static te_coding_t *codecs=NULL; + +void teAddCoding(char *token, void *makerequest, TEFILTER *coder, TEFILTER *decoder) { + te_coding_t * codec; + codec=codecs; + while (codec){ + if (!strcmp(codec->token,token)) { + debug(82,1)("teAddCoding: cannot add already registered codec %s\n",token); + return; + } + codec=codec->next; + } + /* yes yes mempools come after it works */ + codec=xmalloc(sizeof(te_coding_t)); + codec->next=codecs; + codecs=codec; + codec->token=token; + codec->encode=coder; + codec->decode=decoder; +} + void -new_xlat (TE_list **translations, int beg_or_end, - int (*func)(char *, int , char **, int *, void **), - void *data) +new_xlat (TE_list **translations, int beg_or_end, const char * token, int decode, void *data) { TE_list *tp,*tx; + te_coding_t *codec; tp = xmalloc (sizeof (TE_list)); - tp->func = func; + codec=codecs; + while (codec){ + if (!strcmp(codec->token,token)) + break; + codec=codec->next; + } + assert (codec); + debug(1,1)("***************** codec is %s\n",codec->token); + tp->func = decode ? codec->decode : codec->encode; tp->data = data; if (beg_or_end == 0) @@ -335,21 +1540,84 @@ const char *pos = NULL; const char *item; int y; + + if (!codecs) { + teAddCoding("chunked", NULL, dochunk, undochunked); + teAddCoding("biff", NULL, biff, unbiff); + teAddCoding("jones", NULL, jones, unjones); +#if ZLIB_COMPRESSION || ATHY_COMPRESSION + teAddCoding("deflate", NULL, dodeflate, undodeflate); + teAddCoding("gzip", NULL, dogzip, undogzip); +#endif +#ifdef HAVE_H_HSYNC + teAddCoding("rsync", dorsyncsignature, dorsyncdelta, applyrsyncdelta); +#endif + } + +#ifdef originalcode + if (httpHeaderHas(hdr, HDR_TRANSFER_ENCODING)) { + s_transfer_encoding = httpHeaderGetList(hdr, HDR_TRANSFER_ENCODING); + + /* REMOVE ALL TRANSFER ENCODINGS */ + /* order is impt here.. want those entries at end of transfer-encoding + * list to be undone first and they are listed in the order they are + * applied .. TE's are HOP BY HOP */ + + pos = NULL; + while (strListGetItem(&s_transfer_encoding, ',', &item, &y, &pos)) +#ifdef ATHY_COMPRESSION + else if (!strncasecmp(item, "gzip", y)) { + /* need to remove the TE.. and rewrite the header */ + + debug(33, 7) ("removing gzip\n"); + new_xlat(http, 0, undogzip, NULL); + } else if (!strncasecmp(item, "deflate", y)) { + /* need to remove the TE.. and rewrite the header */ + debug(33, 7) ("removing deflate\n"); + new_xlat(http, 0, undodeflate, NULL); + } +#endif +#endif + + if (httpHeaderHas(hdr, HDR_TRANSFER_ENCODING)) { s_transfer_encoding = httpHeaderGetList(hdr, HDR_TRANSFER_ENCODING); /* REMOVE ALL TRANSFER ENCODINGS */ - /* order is impt here.. want those entries at end of transfer-encoding - * list to be undone first and they are listed in the order they are - * applied .. TE's are HOP BY HOP */ + /* order for new_xlat is impt here.. want those entries at end of + * transfer-encoding list to be undone first and they are listed in the + * order they are applied .. TE's are HOP BY HOP + */ pos = NULL; while (strListGetItem(&s_transfer_encoding, ',', &item, &y, &pos)) - if (!strncasecmp(item, "chunked", y)) { + if (!strncasecmp(item, "biff", y)) { + /* need to remove the TE.. and rewrite the header */ + + debug(33, 7) ("removing biff\n"); + new_xlat(translations, 0, "biff", 1, NULL); + + } else if (!strncasecmp(item, "jones", y)) { + /* need to remove the TE.. and rewrite the header */ + debug(33, 7) ("removing jones\n"); + new_xlat(translations, 0, "jones", 1, NULL); + } else if (!strncasecmp(item, "chunked", y)) { /* need to remove the TE.. and rewrite the header */ debug(82, 7) ("removing chunked\n"); - new_xlat(translations, 0, undochunked, NULL); + new_xlat(translations, 0, "chunked", 1, NULL); +#if ATHY_COMPRESSION || ZLIB_COMPRESSION + } else if (!strncasecmp(item, "deflate", y)) { + /* need to remove the TE.. and rewrite the header */ + debug(33, 7) ("removing deflate\n"); + new_xlat(translations, 0, "deflate", 1, NULL); + } else if (!strncasecmp(item, "gzip", y)) { + /* need to remove the TE.. and rewrite the header */ + debug(33, 7) ("removing gzip\n"); + new_xlat(translations, 0, "gzip", 1, NULL); +#endif + } else { + debug(1,1)("unknown transfer encoding in response\n"); } @@ -394,31 +1662,169 @@ * by allowing pipelining */ +/* + + The Internet Assigned Numbers Authority (IANA) acts as a registry for + transfer-coding value tokens. Initially, the registry contains the + following tokens: "chunked" (section 3.6.1), "identity" (section + 3.6.2), "gzip" (section 3.5), "compress" (section 3.5), and "deflate" + (section 3.5). +*/ + + if (!codecs) { + teAddCoding("chunked", NULL, dochunk, undochunked); + teAddCoding("biff", NULL, biff, unbiff); + teAddCoding("jones", NULL, jones, unjones); +#if ZLIB_COMPRESSION || ATHY_COMPRESSION + teAddCoding("deflate", NULL, dodeflate, undodeflate); + teAddCoding("gzip", NULL, dogzip, undogzip); +#endif +#ifdef HAVE_H_HSYNC + teAddCoding("rsync", dorsyncsignature, dorsyncdelta, applyrsyncdelta); +#endif + } + + +#if original_code + /* ADD NEW TRANSFER ENCODINGS.. check announcements */ + if (may_apply_tes && httpHeaderHas(ohdr, HDR_TE)) { + char vlb[128]; + vlb[0] = '\0'; + s_te = httpHeaderGetList(ohdr, HDR_TE); + if ((strListWithParamsIsMember(&s_te, "chunked", ',')) || + ((request->http_ver.major == 1) && (request->http_ver.minor >=1))) { + /* chunked is known.. we can add te's. */ + + if (strListWithParamsIsMember_q(&s_te, "biff", ',')) { + debug(33, 7) ("will add biff\n"); + new_xlat(http, 1, biff, NULL); + + if (added_te) + strcat(vlb, ", "); + else + added_te = 1; + strcat(vlb, "biff"); + } + + if (strListIsMember_q(&s_te, "jones", ',')) { + debug(33, 7) ("will add jones\n"); + new_xlat(http, 1, jones, NULL); + + if (added_te) + strcat(vlb, ", "); + else + added_te = 1; + strcat(vlb, "jones"); + } + +#ifdef ATHY_COMPRESSION + if ((strListIsMember_q(&s_te, "deflate", ',')) + && (!(may_apply_tes & 0x02))) { /* the ce: compressed */ + debug(33, 7) ("will add deflate\n"); + new_xlat(http, 1, dodeflate, NULL); + + if (added_te) + strcat(vlb, ", "); + else + added_te = 1; + strcat(vlb, "deflate"); + } + else /* ONLY IF NOT DEFLATE */ if ((strListIsMember_q(&s_te, + "gzip", ',')) + && (!(may_apply_tes & 0x02))) { /* the ce: compressed */ + debug(33, 7) ("will add gzip\n"); + new_xlat(http, 1, dogzip, NULL); + + if (added_te) + strcat(vlb, ", "); + else + added_te = 1; + strcat(vlb, "gzip"); + } +#endif +#endif + + + if ((httpHeaderHas(ohdr, HDR_TE) || ((http_ver.major == 1) && (http_ver.minor >=1)))) { char vlb[128]; + int added_te=0; vlb[0] = '\0'; s_te = httpHeaderGetList(ohdr, HDR_TE); + + /* at least some TE's are supported. Chunked is always supported */ + + /* else if constructs are used for mutually exclusive or redundant + * codings*/ /* loop /choose compression te's */ -/* finish with chunked */ + + /* strListIsMember_q returns the value of param q.. but it's broken */ + /* what is used elsewhere in squid to parse headers like type;param=value;param=value.. */ + if (strListIsMember_q(&s_te, "biff", ',')) { + new_xlat(translations, 1, "biff", 0, NULL); + + if (added_te) + strcat(vlb, ", "); + else + added_te = 1; + strcat(vlb, "biff"); + } else + if (strListIsMember_q(&s_te, "jones", ',')) { + new_xlat(translations, 1, "jones", 0, NULL); + + if (added_te) + strcat(vlb, ", "); + else + added_te = 1; + strcat(vlb, "jones"); + } + +#ifdef HAVE_H_HSYNC + if ((strListIsMember_q(&s_te, "rsync", ','))){ + new_xlat(translations, 1, "rsync", 0, NULL); + if (added_te) + strcat(vlb, ", "); + else + added_te = 1; + strcat(vlb, "rsync"); + } +#endif -#if TEMPORARY_HACK - if ((strListIsMember_q(&s_te, "chunked", ',')) || - ((http_ver.major == 1) && (http_ver.minor >=1))) +#if ATHY_COMPRESSION || ZLIB_COMPRESSION + if ((strListIsMember_q(&s_te, "deflate", ','))){ +#if 0 + /* this needs to be an acl test against content-encoding */ + && (!(may_apply_tes & 0x02))) { /* the ce: compressed */ #endif - { + new_xlat(translations, 1, "deflate", 0, NULL); - /* chunked is known.. we can add te's. */ + if (added_te) + strcat(vlb, ", "); + else + added_te = 1; + strcat(vlb, "deflate"); + } else if ((strListIsMember_q(&s_te, "gzip", ','))){ + new_xlat(translations, 1, "gzip", 0, NULL); + if (added_te) + strcat(vlb, ", "); + else + added_te = 1; + strcat(vlb, "gzip"); + } +#endif /* always add chunked to cover nonterminating encodings */ - debug(82, 7) ("will add chunked\n"); - new_xlat(translations, 1, dochunk, NULL); - strcat(vlb, "chunked"); - httpHeaderPutStr(hdr, HDR_TRANSFER_ENCODING, vlb); - httpHeaderDelById(hdr, HDR_CONTENT_LENGTH); + new_xlat(translations, 1, "chunked", 0, NULL); - } + if (added_te) + strcat(vlb, ", "); + strcat(vlb, "chunked"); + httpHeaderPutStr(hdr, HDR_TRANSFER_ENCODING, vlb); + httpHeaderDelById(hdr, HDR_CONTENT_LENGTH); + + stringClean(&s_te); flags->te_encoding=1; s_te = httpHeaderGetList(hdr, HDR_CONNECTION); @@ -429,3 +1835,26 @@ } /* add transfer-encoding to the connection header */ } + +void +te_generate_request(HttpHeader *hdr_out) +{ + /* append TE */ + char strTE[128]; + + httpHeaderDelById(hdr_out, HDR_TE); /* hop by hop.. that's what last + hop could do*/ + +#if 0 && defined(HAVE_H_HSYNC) + strcpy (strTE,"chunked;q=1.0, rsync;q=1.0"); +#endif +#if ATHY_COMPRESSION || ZLIB_COMPRESSION + strcpy (strTE,"biff;q=0.0, gzip;q=1.0, deflate;q=0.0, jones;q=0.0, chunked;q=1.0"); +#else + strcpy (strTE,"biff;q=1.0, gzip;q=0.0, deflate;q=0.0, jones;q=1.0, chunked;q=1.0"); +#endif + + httpHeaderPutStr (hdr_out,HDR_TE,strTE); + httpHeaderPutStr(hdr_out,HDR_CONNECTION, "TE"); /* its hop by hop */ + +} Index: squid/src/typedefs.h diff -u squid/src/typedefs.h:1.1.1.3.8.7 squid/src/typedefs.h:1.1.1.3.8.7.2.1 --- squid/src/typedefs.h:1.1.1.3.8.7 Wed Jan 10 05:09:41 2001 +++ squid/src/typedefs.h Mon Jan 15 01:38:18 2001 @@ -352,4 +352,9 @@ typedef int STDIRSELECT(const StoreEntry *); +/* transfer-encoding.c */ +typedef int TEFILTER (char *ibuf, size_t ibufl, char **obuf, size_t *obufl, void **data); +typedef struct _te_coding_t te_coding_t; + + #endif /* _TYPEDEFS_H_ */