You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by ig...@apache.org on 2012/03/08 11:01:46 UTC

git commit: TS-976: Removing this rather poor example plugin as we now have a proper deflate plugin (TS-1129)

Updated Branches:
  refs/heads/master 8a06dc143 -> e1d5d0fcc


TS-976: Removing this rather poor example plugin
as we now have a proper deflate plugin (TS-1129)


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/e1d5d0fc
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/e1d5d0fc
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/e1d5d0fc

Branch: refs/heads/master
Commit: e1d5d0fcca1efa31efd207c3d1e0324fe5f513e1
Parents: 8a06dc1
Author: Igor Galić <i....@brainsware.org>
Authored: Thu Mar 8 10:05:41 2012 +0000
Committer: Igor Galić <i....@brainsware.org>
Committed: Thu Mar 8 10:05:41 2012 +0000

----------------------------------------------------------------------
 example/Makefile.am                |    2 +-
 example/gzip-transform/Makefile.am |   29 --
 example/gzip-transform/README.txt  |   12 -
 example/gzip-transform/gunzip.c    |  545 --------------------------
 example/gzip-transform/gzip.c      |  632 -------------------------------
 5 files changed, 1 insertions(+), 1219 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e1d5d0fc/example/Makefile.am
----------------------------------------------------------------------
diff --git a/example/Makefile.am b/example/Makefile.am
index c28e2ad..cc20f10 100644
--- a/example/Makefile.am
+++ b/example/Makefile.am
@@ -17,5 +17,5 @@
 if STANDALONE_IOCORE
 SUBDIRS = app-template
 else
-SUBDIRS = . add-header append-transform basic-auth blacklist-0 blacklist-1 bnull-transform cache_scan file-1 gzip-transform hello null-transform output-header protocol query_remap redirect-1 remap replace-header response-header-1 server-transform session-1 thread-1 thread-pool
+SUBDIRS = . add-header append-transform basic-auth blacklist-0 blacklist-1 bnull-transform cache_scan file-1 hello null-transform output-header protocol query_remap redirect-1 remap replace-header response-header-1 server-transform session-1 thread-1 thread-pool
 endif

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e1d5d0fc/example/gzip-transform/Makefile.am
----------------------------------------------------------------------
diff --git a/example/gzip-transform/Makefile.am b/example/gzip-transform/Makefile.am
deleted file mode 100644
index 277bdcd..0000000
--- a/example/gzip-transform/Makefile.am
+++ /dev/null
@@ -1,29 +0,0 @@
-#  Licensed to the Apache Software Foundation (ASF) under one
-#  or more contributor license agreements.  See the NOTICE file
-#  distributed with this work for additional information
-#  regarding copyright ownership.  The ASF licenses this file
-#  to you under the Apache License, Version 2.0 (the
-#  "License"); you may not use this file except in compliance
-#  with the License.  You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-
-CFLAGS+=-I$(top_srcdir)/proxy/api
-
-pkglibdir = ${pkglibexecdir}
-pkglib_LTLIBRARIES = gzip.la gunzip.la
-gzip_la_SOURCES = gzip.c
-gzip_la_LDFLAGS = -module -avoid-version -shared
-
-gunzip_la_SOURCES = gunzip.c
-gunzip_la_LDFLAGS = -module -avoid-version -shared
-
-all:
-	ln -sf .libs/gzip.so
-	ln -sf .libs/gunzip.so

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e1d5d0fc/example/gzip-transform/README.txt
----------------------------------------------------------------------
diff --git a/example/gzip-transform/README.txt b/example/gzip-transform/README.txt
deleted file mode 100644
index dce6c4c..0000000
--- a/example/gzip-transform/README.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-Gzip / Gunzip plugins
----------------------
-
-These plugins work only in conjunction and should not be used
-separately to compress or uncompress data.
-For instance a TS child runs gunzip and parent runs gzip.
-Gzip compresses on one side and gunzip decompresses on the other.
-
-Note that gzip plugin produces a compressed file slightly different
-from what the gzip utility does (the header is different). 
-Thus, file compressed by gzip utility can not be uncompressed by gunzip. 
- 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e1d5d0fc/example/gzip-transform/gunzip.c
----------------------------------------------------------------------
diff --git a/example/gzip-transform/gunzip.c b/example/gzip-transform/gunzip.c
deleted file mode 100644
index 35b486e..0000000
--- a/example/gzip-transform/gunzip.c
+++ /dev/null
@@ -1,545 +0,0 @@
-/** @file
-
-  Transforms content using gzip
-
-  @section license License
-
-  Licensed to the Apache Software Foundation (ASF) under one
-  or more contributor license agreements.  See the NOTICE file
-  distributed with this work for additional information
-  regarding copyright ownership.  The ASF licenses this file
-  to you under the Apache License, Version 2.0 (the
-  "License"); you may not use this file except in compliance
-  with the License.  You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
- */
-
-#include <limits.h>
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/file.h>
-#include <sys/types.h>
-#include <stdlib.h>
-#include <string.h>
-#include <zlib.h>
-#include <assert.h>
-#include <ts/ts.h>
-
-#define DICT_PATH_MAX 512
-#define DICT_ENTRY_MAX 2048
-
-typedef struct
-{
-  TSHttpTxn txn;
-  TSVIO output_vio;
-  TSIOBuffer output_buffer;
-  TSIOBufferReader output_reader;
-  int output_length;
-  z_stream zstrm;
-  uLong crc;
-  int state;
-  int flag;
-} GzipData;
-
-char preload_file[1024];
-uLong dictId;
-int preload = 0;
-char dictionary[800000];
-
-
-void
-load_dictionary(char *dict, uLong * adler)
-{
-  FILE *fp;
-  int i = 0;
-
-  fp = fopen(preload_file, "r");
-  if (!fp) {
-    TSError("gunzip-transform: ERROR: Unable to open dict file %s\n", preload_file);
-    exit(0);
-  }
-
-  i = 0;
-  while (!feof(fp)) {
-    if (fscanf(fp, "%s\n", dict + i) == 1) {
-      i = strlen(dict);
-      TSstrlcat(dict + i, " ", sizeof(dict) - i);
-      i++;
-    }
-  }
-  dict[i - 1] = '\0';
-
-  /* TODO figure out the right way to do the adler -- this one is all messed up */
-  *adler = adler32(*adler, (Byte *) dict, strlen(dict));
-}
-
-static voidpf
-gzip_alloc(voidpf opaque, uInt items, uInt size)
-{
-  return (voidpf) TSmalloc(items * size);
-}
-
-
-static void
-gzip_free(voidpf opaque, voidpf address)
-{
-  TSfree(address);
-}
-
-
-static GzipData *
-gzip_data_alloc()
-{
-  GzipData *data;
-
-  data = (GzipData *) TSmalloc(sizeof(GzipData));
-  data->output_vio = NULL;
-  data->output_buffer = NULL;
-  data->output_reader = NULL;
-  data->output_length = 0;
-  data->state = 0;
-  data->flag = 1;
-  data->crc = crc32(0L, Z_NULL, 0);
-
-  data->zstrm.next_in = Z_NULL;
-  data->zstrm.avail_in = 0;
-  data->zstrm.total_in = 0;
-  data->zstrm.next_out = Z_NULL;
-  data->zstrm.avail_out = 0;
-  data->zstrm.total_out = 0;
-  data->zstrm.zalloc = gzip_alloc;
-  data->zstrm.zfree = gzip_free;
-  data->zstrm.opaque = (voidpf) 0;      /* Z_NULL */
-  data->zstrm.data_type = Z_ASCII;
-
-  dictId = adler32(0L, Z_NULL, 0);
-
-  return data;
-}
-
-
-static void
-gzip_data_destroy(GzipData * data)
-{
-  int err;
-
-  if (data) {
-    err = inflateEnd(&data->zstrm);
-    if (err != Z_OK) {
-      TSError("gunzip-transform: ERROR: inflateEnd (%d)!", err);
-    }
-
-    if (data->output_buffer)
-      TSIOBufferDestroy(data->output_buffer);
-    TSfree(data);
-  }
-}
-
-
-static void
-gzip_transform_init(TSCont contp, GzipData * data)
-{
-  TSVConn output_conn;
-
-  data->state = 1;
-
-  /* Get the output connection where we'll write data to. */
-  output_conn = TSTransformOutputVConnGet(contp);
-
-  data->output_buffer = TSIOBufferCreate();
-  data->output_reader = TSIOBufferReaderAlloc(data->output_buffer);
-  data->output_vio = TSVConnWrite(output_conn, contp, data->output_reader, INT64_MAX);
-}
-
-
-static void
-gzip_transform_one(GzipData * data, TSIOBufferReader input_reader, int amount)
-{
-  TSIOBufferBlock blkp;
-  const char *ibuf;
-  char *obuf;
-  int64_t ilength, olength;
-  int err = Z_OK;
-
-  while (amount > 0) {
-    blkp = TSIOBufferReaderStart(input_reader);
-    ibuf = TSIOBufferBlockReadStart(blkp, input_reader, &ilength);
-
-    if (ilength > amount) {
-      ilength = amount;
-    }
-
-    data->zstrm.next_in = (unsigned char *) ibuf;
-    data->zstrm.avail_in = ilength;
-
-    if (data->flag) {
-      err = inflateInit(&data->zstrm);
-      data->flag = 0;
-      if (err != Z_OK) {
-        TSError("gunzip-transform: ERROR: inflateInit (%d)!", err);
-        exit(1);
-      }
-    }
-
-    while (data->zstrm.avail_in > 0 && err != Z_STREAM_END) {
-      blkp = TSIOBufferStart(data->output_buffer);
-
-      obuf = TSIOBufferBlockWriteStart(blkp, &olength);
-
-      data->zstrm.next_out = (unsigned char *) obuf;
-      data->zstrm.avail_out = olength;
-
-      /* Uncompress */
-      err = inflate(&data->zstrm, Z_NO_FLUSH);
-/*
-	    assert( (err == Z_OK) || (err = Z_STREAM_END) || (err = Z_NEED_DICT));
-*/
-      if (err == Z_NEED_DICT) {
-        assert(preload);
-        TSDebug("gunzip-transform", "Transform needs dictionary");
-        /* TODO assert encoding dict is same as the decoding one, else send an error page */
-        /* Dont send the user binary junk! */
-
-        err = inflateSetDictionary(&data->zstrm, (Bytef *) dictionary, strlen(dictionary));
-        if (err != Z_OK) {
-          TSError("gunzip-transform: ERROR: inflateSetDictionary (%d)!", err);
-        }
-      }
-
-      if (olength > data->zstrm.avail_out) {
-        TSIOBufferProduce(data->output_buffer, olength - data->zstrm.avail_out);
-        data->output_length += (olength - data->zstrm.avail_out);
-      }
-
-    }
-
-    /* TODO compute crc */
-
-    TSIOBufferReaderConsume(input_reader, ilength);
-    amount -= ilength;
-  }
-}
-
-
-static void
-gzip_transform_finish(GzipData * data)
-{
-  if (data->state == 1) {
-    TSIOBufferBlock blkp;
-    char *obuf;
-    int64_t olength;
-    int err;
-
-    data->state = 2;
-
-    for (;;) {
-      blkp = TSIOBufferStart(data->output_buffer);
-
-      obuf = TSIOBufferBlockWriteStart(blkp, &olength);
-      data->zstrm.next_out = (unsigned char *) obuf;
-      data->zstrm.avail_out = olength;
-
-      /* Uncompress remaining data */
-      err = inflate(&data->zstrm, Z_FINISH);
-
-      if (olength > data->zstrm.avail_out) {
-        TSIOBufferProduce(data->output_buffer, olength - data->zstrm.avail_out);
-        data->output_length += (olength - data->zstrm.avail_out);
-      }
-
-      if (err == Z_OK) {        /* more to uncompress */
-        continue;
-      }
-      /* done! */
-      break;
-    }
-
-    if (data->output_length != (data->zstrm.total_out)) {
-      TSError("gunzip-transform: ERROR: output lengths don't match (%d, %ld)", data->output_length,
-               data->zstrm.total_out);
-    }
-
-    /* TODO crc checks */
-  }
-}
-
-
-static void
-gzip_transform_do(TSCont contp)
-{
-  TSVIO write_vio;
-  GzipData *data;
-  int towrite;
-  int avail;
-  int length;
-
-  /* Get our data structure for this operation. The private data
-     structure contains the output vio and output buffer. If the
-     private data structure pointer is NULL, then we'll create it
-     and initialize its internals. */
-  data = TSContDataGet(contp);
-  if (data->state == 0) {
-    gzip_transform_init(contp, data);
-  }
-
-  /* Get the write vio for the write operation that was performed on
-     ourself. This vio contains the buffer that we are to read from
-     as well as the continuation we are to call when the buffer is
-     empty. */
-  write_vio = TSVConnWriteVIOGet(contp);
-  length = data->output_length;
-
-  /* We also check to see if the write vio's buffer is non-NULL. A
-     NULL buffer indicates that the write operation has been
-     shutdown and that the continuation does not want us to send any
-     more WRITE_READY or WRITE_COMPLETE events. For this simplistic
-     transformation that means we're done. In a more complex
-     transformation we might have to finish writing the transformed
-     data to our output connection. */
-  if (!TSVIOBufferGet(write_vio)) {
-
-    gzip_transform_finish(data);
-
-    TSVIONBytesSet(data->output_vio, data->output_length);
-
-    TSVIOReenable(data->output_vio);
-    return;
-  }
-
-  /* Determine how much data we have left to read. For this gzip
-     transform plugin this is also the amount of data we have left
-     to write to the output connection. */
-  towrite = TSVIONTodoGet(write_vio);
-  if (towrite > 0) {
-    /* The amount of data left to read needs to be truncated by
-       the amount of data actually in the read buffer. */
-    avail = TSIOBufferReaderAvail(TSVIOReaderGet(write_vio));
-    if (towrite > avail) {
-      towrite = avail;
-    }
-
-    if (towrite > 0) {
-      gzip_transform_one(data, TSVIOReaderGet(write_vio), towrite);
-
-      /* Modify the write vio to reflect how much data we've
-         completed. */
-      TSVIONDoneSet(write_vio, TSVIONDoneGet(write_vio) + towrite);
-    }
-  }
-
-  /* Now we check the write vio to see if there is data left to
-     read. */
-  if (TSVIONTodoGet(write_vio) > 0) {
-    if (towrite > 0) {
-      /* If we output some data then we reenable the output
-         connection by reenabling the output vio. This will wakeup
-         the output connection and allow it to consume data from the
-         output buffer. */
-      if (data->output_length > length) {
-        TSVIOReenable(data->output_vio);
-      }
-
-      /* Call back the write vio continuation to let it know that we
-         are ready for more data. */
-      TSContCall(TSVIOContGet(write_vio), TS_EVENT_VCONN_WRITE_READY, write_vio);
-    }
-  } else {
-    /* If there is no data left to read, then we modify the output
-       vio to reflect how much data the output connection should
-       expect. This allows the output connection to know when it
-       is done reading. We then reenable the output connection so
-       that it can consume the data we just gave it. */
-    gzip_transform_finish(data);
-
-    TSVIONBytesSet(data->output_vio, data->output_length);
-
-    if (data->output_length > length) {
-      TSVIOReenable(data->output_vio);
-    }
-
-    /* Call back the write vio continuation to let it know that we
-       have completed the write operation. */
-    TSContCall(TSVIOContGet(write_vio), TS_EVENT_VCONN_WRITE_COMPLETE, write_vio);
-  }
-}
-
-
-static int
-gzip_transform(TSCont contp, TSEvent event, void *edata)
-{
-  /* Check to see if the transformation has been closed by a call to
-     TSVConnClose. */
-  if (TSVConnClosedGet(contp)) {
-    gzip_data_destroy(TSContDataGet(contp));
-    TSContDestroy(contp);
-    return 0;
-  } else {
-    switch (event) {
-    case TS_EVENT_ERROR:
-      {
-        TSVIO write_vio;
-
-        /* Get the write vio for the write operation that was
-           performed on ourself. This vio contains the continuation of
-           our parent transformation. */
-        write_vio = TSVConnWriteVIOGet(contp);
-
-        /* Call back the write vio continuation to let it know that we
-           have completed the write operation. */
-        TSContCall(TSVIOContGet(write_vio), TS_EVENT_ERROR, write_vio);
-      }
-      break;
-    case TS_EVENT_VCONN_WRITE_COMPLETE:
-    case TS_EVENT_VCONN_EOS:
-      /* When our output connection says that it has finished
-         reading all the data we've written to it then we should
-         shutdown the write portion of its connection to
-         indicate that we don't want to hear about it anymore. */
-      TSVConnShutdown(TSTransformOutputVConnGet(contp), 0, 1);
-      break;
-    case TS_EVENT_VCONN_WRITE_READY:
-    default:
-      /* If we get a WRITE_READY event or any other type of
-         event (sent, perhaps, because we were reenabled) then
-         we'll attempt to transform more data. */
-      gzip_transform_do(contp);
-      break;
-    }
-  }
-
-  return 0;
-}
-
-static int
-gzip_transformable(TSHttpTxn txnp, int server)
-{
-  TSMBuffer bufp;
-  TSMLoc hdr_loc;
-  TSMLoc field_loc;
-  const char *value;
-
-  if (server) {
-    TSHttpTxnServerRespGet(txnp, &bufp, &hdr_loc);
-  } else {
-    TSHttpTxnCachedRespGet(txnp, &bufp, &hdr_loc);
-  }
-
-  /* We only want to do gunzip(inflate) on documents that have a
-     content-encoding "deflate". */
-
-  field_loc = TSMimeHdrFieldFind(bufp, hdr_loc, "Content-Encoding", -1);
-  if (!field_loc) {
-    TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
-    return -4;
-  }
-
-  value = TSMimeHdrFieldValueStringGet(bufp, hdr_loc, field_loc, 0, NULL);
-  if (value && (strncasecmp(value, "deflate", sizeof("deflate") - 1) == 0)) {
-    TSHandleMLocRelease(bufp, hdr_loc, field_loc);
-    TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
-    return 0;
-  } else {
-    TSHandleMLocRelease(bufp, hdr_loc, field_loc);
-    TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
-    return -5;
-  }
-}
-
-
-static void
-gzip_transform_add(TSHttpTxn txnp, int flag)
-{
-  TSVConn connp;
-  GzipData *data;
-
-  data = gzip_data_alloc();
-  data->txn = txnp;
-
-  connp = TSTransformCreate(gzip_transform, txnp);
-  TSContDataSet(connp, data);
-  TSHttpTxnHookAdd(txnp, TS_HTTP_RESPONSE_TRANSFORM_HOOK, connp);
-}
-
-
-static int
-transform_plugin(TSCont contp, TSEvent event, void *edata)
-{
-  TSHttpTxn txnp = (TSHttpTxn) edata;
-  int reason;
-
-  switch (event) {
-  case TS_EVENT_HTTP_READ_REQUEST_HDR:
-    {
-      TSMBuffer bufp;
-      TSMLoc hdr_loc;
-      TSMLoc ae_loc;           /* for the accept encoding mime field */
-
-      TSHttpTxnClientReqGet(txnp, &bufp, &hdr_loc);
-      TSMimeHdrFieldCreate(bufp, hdr_loc, &ae_loc); /* Probably should check for errors */
-      TSMimeHdrFieldNameSet(bufp, hdr_loc, ae_loc, "Accept-Encoding", -1);
-      TSMimeHdrFieldValueAppend(bufp, hdr_loc, ae_loc, -1, "deflate", -1);
-      TSMimeHdrFieldAppend(bufp, hdr_loc, ae_loc);
-      TSHandleMLocRelease(bufp, hdr_loc, ae_loc);
-      TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
-
-      TSDebug("gunzip-transform", "Changed request header to accept deflate encoding");
-      TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
-      break;
-    }
-  case TS_EVENT_HTTP_READ_RESPONSE_HDR:
-    reason = gzip_transformable(txnp, 1);
-    if (reason >= 0) {
-      TSMBuffer bufp;
-      TSMLoc hdr_loc;
-      TSMLoc field_loc;
-
-      TSHttpTxnServerRespGet(txnp, &bufp, &hdr_loc);
-      field_loc = TSMimeHdrFieldFind(bufp, hdr_loc, "Content-Encoding", -1);
-      TSMimeHdrFieldDestroy(bufp, hdr_loc, field_loc);
-      TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
-
-      TSDebug("gunzip-transform", "server content transformable");
-      gzip_transform_add(txnp, 1);
-    } else {
-      TSDebug("gunzip-transform", "server content NOT transformable [%d]", reason);
-    }
-
-    TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
-    break;
-
-  case TS_EVENT_HTTP_READ_CACHE_HDR:
-
-    TSDebug("gunzip-transform", "Cached data");
-
-    TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
-    break;
-
-  default:
-    exit(1);
-  }
-
-  return 0;
-}
-
-
-void
-TSPluginInit(int argc, const char *argv[])
-{
-  if (argc == 2) {
-    TSstrlcpy(preload_file, argv[1], sizeof(preload_file));
-    preload = 1;
-    load_dictionary(dictionary, &dictId);
-  }
-
-  TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, TSContCreate(transform_plugin, NULL));
-  TSHttpHookAdd(TS_HTTP_READ_RESPONSE_HDR_HOOK, TSContCreate(transform_plugin, NULL));
-  TSHttpHookAdd(TS_HTTP_READ_CACHE_HDR_HOOK, TSContCreate(transform_plugin, NULL));
-}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e1d5d0fc/example/gzip-transform/gzip.c
----------------------------------------------------------------------
diff --git a/example/gzip-transform/gzip.c b/example/gzip-transform/gzip.c
deleted file mode 100644
index 7b5361e..0000000
--- a/example/gzip-transform/gzip.c
+++ /dev/null
@@ -1,632 +0,0 @@
-/** @file
-
-  Transforms content using gzip
-
-  @section license License
-
-  Licensed to the Apache Software Foundation (ASF) under one
-  or more contributor license agreements.  See the NOTICE file
-  distributed with this work for additional information
-  regarding copyright ownership.  The ASF licenses this file
-  to you under the Apache License, Version 2.0 (the
-  "License"); you may not use this file except in compliance
-  with the License.  You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
- */
-
-#include <limits.h>
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/file.h>
-#include <sys/types.h>
-#include <stdlib.h>
-#include <string.h>
-#include <zlib.h>
-#include <assert.h>
-#include <ts/ts.h>
-
-#define DICT_PATH_MAX 512
-#define DICT_ENTRY_MAX 2048
-
-typedef struct
-{
-  TSHttpTxn txn;
-  TSVIO output_vio;
-  TSIOBuffer output_buffer;
-  TSIOBufferReader output_reader;
-  int output_length;
-  z_stream zstrm;
-  uLong crc;
-  int state;
-} GzipData;
-
-
-char preload_file[1024];
-uLong dictId;
-int preload = 0;
-char dictionary[800000];
-
-void
-load_dictionary(char *dict, uLong * adler)
-{
-  FILE *fp;
-  int i = 0;
-
-  fp = fopen(preload_file, "r");
-  if (!fp) {
-    TSError("gzip-transform: ERROR: Unable to open dict file %s\n", preload_file);
-    exit(0);
-  }
-
-  /* dict = (char *) calloc(8000,sizeof(char)); */
-
-  i = 0;
-  while (!feof(fp)) {
-    if (fscanf(fp, "%s\n", dict + i) == 1) {
-      i = strlen(dict);
-      TSstrlcat(dict + i, " ", sizeof(dict) - i);
-      i++;
-    }
-  }
-  dict[i - 1] = '\0';
-
-  /* TODO get the adler compute right */
-  *adler = adler32(*adler, (const Byte *) dict, sizeof(dict));
-}
-
-static voidpf
-gzip_alloc(voidpf opaque, uInt items, uInt size)
-{
-  return (voidpf) TSmalloc(items * size);
-}
-
-
-static void
-gzip_free(voidpf opaque, voidpf address)
-{
-  TSfree(address);
-}
-
-
-static GzipData *
-gzip_data_alloc()
-{
-  GzipData *data;
-  int err;
-
-  data = (GzipData *) TSmalloc(sizeof(GzipData));
-  data->output_vio = NULL;
-  data->output_buffer = NULL;
-  data->output_reader = NULL;
-  data->output_length = 0;
-  data->state = 0;
-  data->crc = crc32(0L, Z_NULL, 0);
-
-  data->zstrm.next_in = Z_NULL;
-  data->zstrm.avail_in = 0;
-  data->zstrm.total_in = 0;
-  data->zstrm.next_out = Z_NULL;
-  data->zstrm.avail_out = 0;
-  data->zstrm.total_out = 0;
-  data->zstrm.zalloc = gzip_alloc;
-  data->zstrm.zfree = gzip_free;
-  data->zstrm.opaque = (voidpf) 0;
-  data->zstrm.data_type = Z_ASCII;
-
-  err = deflateInit(&data->zstrm, Z_BEST_COMPRESSION);
-
-  if (err != Z_OK) {
-    TSError("gzip-transform: ERROR: deflateInit (%d)!", err);
-    exit(1);
-  }
-
-  if (preload) {
-    assert(&data->zstrm);
-    err = deflateSetDictionary(&data->zstrm, (const Bytef *) dictionary, strlen(dictionary));
-    if (err != Z_OK) {
-      TSError("gzip-transform: ERROR: deflateSetDictionary (%d)!", err);
-    }
-  }
-
-  return data;
-}
-
-
-static void
-gzip_data_destroy(GzipData * data)
-{
-  int err;
-
-  if (data) {
-    err = deflateEnd(&data->zstrm);
-    if (err != Z_OK) {
-      TSError("gzip-transform: ERROR: deflateEnd (%d)!", err);
-    }
-
-    if (data->output_buffer)
-      TSIOBufferDestroy(data->output_buffer);
-    TSfree(data);
-  }
-}
-
-
-static void
-gzip_transform_init(TSCont contp, GzipData * data)
-{
-  TSVConn output_conn;
-  TSMBuffer bufp;
-  TSMLoc hdr_loc;
-  TSMLoc ce_loc;               /* for the content encoding mime field */
-
-  data->state = 1;
-
-  /*
-   * Mark the output data as having gzip content encoding
-   */
-  TSHttpTxnTransformRespGet(data->txn, &bufp, &hdr_loc);
-  TSMimeHdrFieldCreate(bufp, hdr_loc, &ce_loc); /* Probably should check for errors */
-  TSMimeHdrFieldNameSet(bufp, hdr_loc, ce_loc, "Content-Encoding", -1);
-  TSMimeHdrFieldValueStringInsert(bufp, hdr_loc, ce_loc, -1, "deflate", -1);
-  TSMimeHdrFieldAppend(bufp, hdr_loc, ce_loc);
-  TSHandleMLocRelease(bufp, hdr_loc, ce_loc);
-  TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
-
-
-  /* Get the output connection where we'll write data to. */
-  output_conn = TSTransformOutputVConnGet(contp);
-
-  data->output_buffer = TSIOBufferCreate();
-  data->output_reader = TSIOBufferReaderAlloc(data->output_buffer);
-  data->output_vio = TSVConnWrite(output_conn, contp, data->output_reader, INT64_MAX);
-}
-
-
-static void
-gzip_transform_one(GzipData * data, TSIOBufferReader input_reader, int amount)
-{
-  TSIOBufferBlock blkp;
-  const char *ibuf;
-  char *obuf;
-  int64_t ilength, olength;
-  int err;
-
-  while (amount > 0) {
-    blkp = TSIOBufferReaderStart(input_reader);
-    ibuf = TSIOBufferBlockReadStart(blkp, input_reader, &ilength);
-
-    if (ilength > amount) {
-      ilength = amount;
-    }
-
-    data->zstrm.next_in = (unsigned char *) ibuf;
-    data->zstrm.avail_in = ilength;
-
-    while (data->zstrm.avail_in > 0) {
-      blkp = TSIOBufferStart(data->output_buffer);
-
-      obuf = TSIOBufferBlockWriteStart(blkp, &olength);
-
-      data->zstrm.next_out = (unsigned char *) obuf;
-      data->zstrm.avail_out = olength;
-
-      /* Encode */
-      err = deflate(&data->zstrm, Z_NO_FLUSH);
-      TSDebug("gzip-transform", "deflate() returned %d", err);
-
-      if (olength > data->zstrm.avail_out) {
-        TSIOBufferProduce(data->output_buffer, olength - data->zstrm.avail_out);
-        data->output_length += (olength - data->zstrm.avail_out);
-      }
-
-      if (data->zstrm.avail_out > 0) {
-        if (data->zstrm.avail_in != 0) {
-          TSError("gzip-transform: ERROR: avail_in is (%d): should be 0", data->zstrm.avail_in);
-        }
-      }
-    }
-
-    /* compute CRC for error checking at client */
-    data->crc = crc32(data->crc, (unsigned char *) ibuf, ilength);
-
-    TSIOBufferReaderConsume(input_reader, ilength);
-    amount -= ilength;
-  }
-}
-
-
-static void
-gzip_transform_finish(GzipData * data)
-{
-  if (data->state == 1) {
-    TSIOBufferBlock blkp;
-    char *obuf;
-    int64_t olength;
-    int err;
-
-    data->state = 2;
-
-    for (;;) {
-      blkp = TSIOBufferStart(data->output_buffer);
-
-      obuf = TSIOBufferBlockWriteStart(blkp, &olength);
-      data->zstrm.next_out = (unsigned char *) obuf;
-      data->zstrm.avail_out = olength;
-
-      /* Encode remaining data */
-      err = deflate(&data->zstrm, Z_FINISH);
-
-      if (olength > data->zstrm.avail_out) {
-        TSIOBufferProduce(data->output_buffer, olength - data->zstrm.avail_out);
-        data->output_length += (olength - data->zstrm.avail_out);
-      }
-
-      if (err == Z_OK) {        /* some more data to encode */
-        continue;
-      }
-      /* done! */
-      if (err != Z_STREAM_END) {
-        TSDebug("gzip-transform", "deflate should report Z_STREAM_END\n");
-      }
-      break;
-    }
-
-    if (data->output_length != (data->zstrm.total_out)) {
-      TSError("gzip-transform: ERROR: output lengths don't match (%d, %ld)", data->output_length,
-               data->zstrm.total_out);
-    }
-
-    /* compute/append crc to end of stream */
-
-    /*
-       blkp = TSIOBufferStart (data->output_buffer);
-
-       tmp = data->crc;
-       buf[0] = tmp & 0xff; tmp >>= 8;
-       buf[1] = tmp & 0xff; tmp >>= 8;
-       buf[2] = tmp & 0xff; tmp >>= 8;
-       buf[3] = tmp & 0xff;
-
-       tmp = data->zstrm.total_in;
-       buf[4] = tmp & 0xff; tmp >>= 8;
-       buf[5] = tmp & 0xff; tmp >>= 8;
-       buf[6] = tmp & 0xff; tmp >>= 8;
-       buf[7] = tmp & 0xff;
-
-       p = buf;
-       length = 8;
-
-       while (length > 0) {
-       obuf = TSIOBufferBlockWriteStart (blkp, &olength);
-       if (olength > length) {
-       olength = length;
-       }
-
-       memcpy (obuf, p, olength);
-       p += olength;
-       length -= olength;
-
-       TSIOBufferProduce (data->output_buffer, olength);
-       }
-
-       data->output_length += 8;
-     */
-  }
-}
-
-
-static void
-gzip_transform_do(TSCont contp)
-{
-  TSVIO write_vio;
-  GzipData *data;
-  int towrite;
-  int avail;
-  int length;
-
-  /* Get our data structure for this operation. The private data
-     structure contains the output vio and output buffer. If the
-     private data structure pointer is NULL, then we'll create it
-     and initialize its internals. */
-  data = TSContDataGet(contp);
-  if (data->state == 0) {
-    gzip_transform_init(contp, data);
-  }
-
-  /* Get the write vio for the write operation that was performed on
-     ourself. This vio contains the buffer that we are to read from
-     as well as the continuation we are to call when the buffer is
-     empty. */
-  write_vio = TSVConnWriteVIOGet(contp);
-
-  length = data->output_length;
-
-  /* We also check to see if the write vio's buffer is non-NULL. A
-     NULL buffer indicates that the write operation has been
-     shutdown and that the continuation does not want us to send any
-     more WRITE_READY or WRITE_COMPLETE events. For this simplistic
-     transformation that means we're done. In a more complex
-     transformation we might have to finish writing the transformed
-     data to our output connection. */
-  if (!TSVIOBufferGet(write_vio)) {
-    gzip_transform_finish(data);
-
-    TSVIONBytesSet(data->output_vio, data->output_length);
-    TSDebug("gzip-transform", "Compressed size %d (bytes)", data->output_length);
-
-    if (data->output_length > length) {
-      TSVIOReenable(data->output_vio);
-    }
-    return;
-  }
-
-  /* Determine how much data we have left to read. For this gzip
-     transform plugin this is also the amount of data we have left
-     to write to the output connection. */
-  towrite = TSVIONTodoGet(write_vio);
-  if (towrite > 0) {
-    /* The amount of data left to read needs to be truncated by
-       the amount of data actually in the read buffer. */
-    avail = TSIOBufferReaderAvail(TSVIOReaderGet(write_vio));
-    if (towrite > avail) {
-      towrite = avail;
-    }
-
-    if (towrite > 0) {
-      gzip_transform_one(data, TSVIOReaderGet(write_vio), towrite);
-
-      /* Modify the write vio to reflect how much data we've
-         completed. */
-      TSVIONDoneSet(write_vio, TSVIONDoneGet(write_vio) + towrite);
-    }
-  }
-
-  /* Now we check the write vio to see if there is data left to
-     read. */
-  if (TSVIONTodoGet(write_vio) > 0) {
-    if (towrite > 0) {
-      /* If we output some data then we reenable the output
-         connection by reenabling the output vio. This will wakeup
-         the output connection and allow it to consume data from the
-         output buffer. */
-      if (data->output_length > length) {
-        TSVIOReenable(data->output_vio);
-      }
-
-      /* Call back the write vio continuation to let it know that we
-         are ready for more data. */
-      TSContCall(TSVIOContGet(write_vio), TS_EVENT_VCONN_WRITE_READY, write_vio);
-    }
-  } else {
-    /* If there is no data left to read, then we modify the output
-       vio to reflect how much data the output connection should
-       expect. This allows the output connection to know when it
-       is done reading. We then reenable the output connection so
-       that it can consume the data we just gave it. */
-    gzip_transform_finish(data);
-
-    TSVIONBytesSet(data->output_vio, data->output_length);
-    TSDebug("gzip-transform", "Compressed size %d (bytes)", data->output_length);
-
-    if (data->output_length > length) {
-      TSVIOReenable(data->output_vio);
-    }
-
-    /* Call back the write vio continuation to let it know that we
-       have completed the write operation. */
-    TSContCall(TSVIOContGet(write_vio), TS_EVENT_VCONN_WRITE_COMPLETE, write_vio);
-  }
-}
-
-
-static int
-gzip_transform(TSCont contp, TSEvent event, void *edata)
-{
-  /* Check to see if the transformation has been closed by a call to
-     TSVConnClose. */
-  if (TSVConnClosedGet(contp)) {
-    gzip_data_destroy(TSContDataGet(contp));
-    TSContDestroy(contp);
-    return 0;
-  } else {
-    switch (event) {
-    case TS_EVENT_ERROR:
-      {
-        TSVIO write_vio;
-
-        /* Get the write vio for the write operation that was
-           performed on ourself. This vio contains the continuation of
-           our parent transformation. */
-        write_vio = TSVConnWriteVIOGet(contp);
-
-        /* Call back the write vio continuation to let it know that we
-           have completed the write operation. */
-        TSContCall(TSVIOContGet(write_vio), TS_EVENT_ERROR, write_vio);
-      }
-      break;
-    case TS_EVENT_VCONN_WRITE_COMPLETE:
-      /* When our output connection says that it has finished
-         reading all the data we've written to it then we should
-         shutdown the write portion of its connection to
-         indicate that we don't want to hear about it anymore. */
-      TSVConnShutdown(TSTransformOutputVConnGet(contp), 0, 1);
-      break;
-    case TS_EVENT_VCONN_WRITE_READY:
-    default:
-      /* If we get a WRITE_READY event or any other type of
-         event (sent, perhaps, because we were reenabled) then
-         we'll attempt to transform more data. */
-      gzip_transform_do(contp);
-      break;
-    }
-  }
-
-  return 0;
-}
-
-
-static int
-gzip_transformable(TSHttpTxn txnp, int server)
-{
-  /* Server response header */
-  TSMBuffer bufp;
-  TSMLoc hdr_loc;
-  TSMLoc field_loc;
-
-  /* Client request header */
-  TSMBuffer cbuf;
-  TSMLoc chdr;
-  TSMLoc cfield;
-
-  const char *value;
-  int nvalues;
-  int i, deflate_flag;
-
-  TSHttpTxnClientReqGet(txnp, &cbuf, &chdr);
-
-  /* check if client accepts "deflate" */
-
-  cfield = TSMimeHdrFieldFind(cbuf, chdr, TS_MIME_FIELD_ACCEPT_ENCODING, -1);
-  if (TS_NULL_MLOC != cfield) {
-    nvalues = TSMimeHdrFieldValuesCount(cbuf, chdr, cfield);
-    value = TSMimeHdrFieldValueStringGet(cbuf, chdr, cfield, 0, NULL);
-    deflate_flag = 0;
-    i = 0;
-    while (nvalues > 0) {
-      if (value && (strncasecmp(value, "deflate", sizeof("deflate") - 1) == 0)) {
-        deflate_flag = 1;
-        break;
-      }
-      i++;
-      value = TSMimeHdrFieldValueStringGet(cbuf, chdr, cfield, i, NULL);
-      nvalues--;
-    }
-    if (!deflate_flag) {
-      return -7;
-    }
-    TSHandleMLocRelease(cbuf, chdr, cfield);
-    TSHandleMLocRelease(cbuf, TS_NULL_MLOC, chdr);
-  } else {
-    TSHandleMLocRelease(cbuf, chdr, cfield);
-    TSHandleMLocRelease(cbuf, TS_NULL_MLOC, chdr);
-    return -6;
-  }
-
-  if (server) {
-    TSHttpTxnServerRespGet(txnp, &bufp, &hdr_loc);
-  } else {
-    TSHttpTxnCachedRespGet(txnp, &bufp, &hdr_loc);
-  }
-
-  /* If there already exists a content encoding then we don't want
-     to do anything. */
-  field_loc = TSMimeHdrFieldFind(bufp, hdr_loc, TS_MIME_FIELD_CONTENT_ENCODING, -1);
-  if (field_loc) {
-    TSHandleMLocRelease(bufp, hdr_loc, field_loc);
-    TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
-    return -3;
-  }
-  TSHandleMLocRelease(bufp, hdr_loc, field_loc);
-
-  /* We only want to do gzip compression on documents that have a
-     content type of "text/" or "application/x-javascript". */
-
-  field_loc = TSMimeHdrFieldFind(bufp, hdr_loc, TS_MIME_FIELD_CONTENT_TYPE, -1);
-  if (!field_loc) {
-    TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
-    return -4;
-  }
-
-  value = TSMimeHdrFieldValueStringGet(bufp, hdr_loc, field_loc, 0, NULL);
-  if (value && (strncasecmp(value, "text/", sizeof("text/") - 1) == 0)) {
-    TSHandleMLocRelease(bufp, hdr_loc, field_loc);
-    TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
-    return 0;
-  } else if (value && (strncasecmp(value, "application/x-javascript", (sizeof("application/x-javascript") - 1)) == 0)) {
-    TSHandleMLocRelease(bufp, hdr_loc, field_loc);
-    TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
-    return 0;
-  } else {
-    TSHandleMLocRelease(bufp, hdr_loc, field_loc);
-    TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
-    return -5;
-  }
-}
-
-
-static void
-gzip_transform_add(TSHttpTxn txnp, int server)
-{
-  TSVConn connp;
-  GzipData *data;
-
-  connp = TSTransformCreate(gzip_transform, txnp);
-
-  data = gzip_data_alloc();
-  data->txn = txnp;
-  TSContDataSet(connp, data);
-
-  TSHttpTxnHookAdd(txnp, TS_HTTP_RESPONSE_TRANSFORM_HOOK, connp);
-}
-
-
-static int
-transform_plugin(TSCont contp, TSEvent event, void *edata)
-{
-  TSHttpTxn txnp = (TSHttpTxn) edata;
-  int reason;
-
-  switch (event) {
-  case TS_EVENT_HTTP_READ_RESPONSE_HDR:
-    reason = gzip_transformable(txnp, 1);
-    if (reason >= 0) {
-      TSDebug("gzip-transform", "server content transformable");
-      gzip_transform_add(txnp, 1);
-    } else {
-      TSDebug("gzip-transform", "server content NOT transformable [%d]", reason);
-    }
-
-    TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
-    break;
-
-  case TS_EVENT_HTTP_READ_CACHE_HDR:
-
-    reason = gzip_transformable(txnp, 0);
-    if (reason >= 0) {
-      TSDebug("gzip-transform", "cached content transformable");
-      gzip_transform_add(txnp, 1);
-    } else {
-      TSDebug("gzip-transform", "cached data:  forwarding unchanged (%d)", reason);
-    }
-    TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
-    break;
-
-  default:
-    exit(1);
-  }
-
-  return 0;
-}
-
-
-void
-TSPluginInit(int argc, const char *argv[])
-{
-  dictId = adler32(0L, Z_NULL, 0);
-  if (argc == 2) {
-    TSstrlcpy(preload_file, argv[1], sizeof(preload_file));
-    preload = 1;
-    load_dictionary(dictionary, &dictId);
-  }
-
-  TSHttpHookAdd(TS_HTTP_READ_RESPONSE_HDR_HOOK, TSContCreate(transform_plugin, NULL));
-  TSHttpHookAdd(TS_HTTP_READ_CACHE_HDR_HOOK, TSContCreate(transform_plugin, NULL));
-}
-