You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2012/06/20 23:23:01 UTC
[10/14] Delete all the old files,
they are moved to plugins/experimental in our normal repo
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/gzip/gzip.c
----------------------------------------------------------------------
diff --git a/gzip/gzip.c b/gzip/gzip.c
deleted file mode 100644
index 564fa23..0000000
--- a/gzip/gzip.c
+++ /dev/null
@@ -1,912 +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.
- */
-
-
-// WHAT THIS PLUGIN DOES:
-// in spite of its name, it compresses responses to the raw deflate format.
-// it also normalizes the accept-encoding header from user agent requests
-// to either deflate or nothing. it compresses responses from origins only,
-// though it can be modified easily to also compress contents from cache.
-//
-// MAJOR ISSUES:
-// - there is an issue with *some* origins that send connection:close.
-// the plugin will not execute in that situation as a temporary fix.
-// - the workings of this plugin support our use case, but probably is not
-// on size fits all. it shouldnt be too hard to adjust it to your own needs though.
-#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 <ts/ts.h>
-#include <inttypes.h>
-
-#define DICT_PATH_MAX 512
-#define DICT_ENTRY_MAX 2048
-
-const char* PLUGIN_NAME = "gzip";
-
-typedef struct
-{
- TSHttpTxn txn;
- TSVIO output_vio;
- TSIOBuffer output_buffer;
- TSIOBufferReader output_reader;
- int output_length;
- z_stream zstrm;
- uLong crc; //os: unused, we are using raw deflate
- 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);
- strcat(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)
-{
- TSDebug(PLUGIN_NAME, "gzip_alloc()");
- return (voidpf) TSmalloc(items * size);
-}
-
-
-static void
-gzip_free(voidpf opaque, voidpf address)
-{
- TSDebug(PLUGIN_NAME, "gzip_free() start");
- TSfree(address);
-}
-
-
-static GzipData *
-gzip_data_alloc()
-{
- GzipData *data;
- int err;
-
- TSDebug(PLUGIN_NAME, "gzip_data_alloc() start");
-
- 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;
-
-#define MOD_GZIP_ZLIB_WINDOWSIZE -15
-#define MOD_GZIP_ZLIB_CFACTOR 9
-#define MOD_GZIP_ZLIB_BSIZE 8096
-
-/* ZLIB's deflate() compression algorithm uses the same */
-/* 0-9 based scale that GZIP does where '1' is 'Best speed' */
-/* and '9' is 'Best compression'. Testing has proved level '6' */
-/* to be about the best level to use in an HTTP Server. */
-
-
-//os: FIXME: look into autoscaling the compression level based on connection speed
-//a gprs device might benefit from a higher compression ratio, whereas a desktop w. high bandwith
-//might be served better with little or no compression at all
-#define MOD_GZIP_DEFLATE_DEFAULT_COMPRESSION_LEVEL 6
- err = deflateInit2(
- &data->zstrm,
- MOD_GZIP_DEFLATE_DEFAULT_COMPRESSION_LEVEL,
- Z_DEFLATED,
- MOD_GZIP_ZLIB_WINDOWSIZE,
- MOD_GZIP_ZLIB_CFACTOR,
- Z_DEFAULT_STRATEGY);
-
- if (err != Z_OK) {
- TSError("gzip-transform: ERROR: deflateInit (%d)!", err);
- exit(1);
- }
-
- if (preload) {
- TSAssert(&data->zstrm);
- err = deflateSetDictionary(&data->zstrm, (const Bytef *) dictionary, strlen(dictionary));
- if (err != Z_OK) {
- TSError("gzip-transform: ERROR: deflateSetDictionary (%d)!", err);
- }
- }
- TSDebug(PLUGIN_NAME, "gzip_data_alloc() end");
-
- return data;
-}
-
-
-static void
-gzip_data_destroy(GzipData *data)
-{
- int err;
-
- TSDebug(PLUGIN_NAME,"gzip-transform: gzip_data_destroy() starts");
- if (data) {
- err = deflateEnd(&data->zstrm);
-
- //os: this can happen when clients abort.
- // that is not very uncommon, so don't log it.
- if (err != Z_OK) {
- //TSDebug(PLUGIN_NAME,"gzip-transform: ERROR: deflateEnd (%d)!", err);
- //TSError("gzip-transform: ERROR: deflateEnd (%d)!", err);
- }
-
- if (data->output_buffer)
- TSIOBufferDestroy(data->output_buffer);
- TSfree(data);
- }
-
- TSDebug(PLUGIN_NAME,"gzip-transform: gzip_data_destroy() ends");
-}
-
-
-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 */
-
- TSDebug(PLUGIN_NAME, "gzip_transform_init");
-
- data->state = 1;
-
- /* Mark the output data as having deflate content encoding */
-
- TSHttpTxnTransformRespGet(data->txn, &bufp, &hdr_loc);
-
-
- //FIXME: these todo's
- //os: this is a little rough around the edges.
- //this should insert/append field values as needed instead.
-
- //Probably should check for errors
- TSMimeHdrFieldCreate(bufp, hdr_loc, &ce_loc);
- 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);
-
-
- //os: error checking. formally -> this header should be send for any document,
- //that will potentially alternate on compression?
-
- TSMimeHdrFieldCreate(bufp, hdr_loc, &ce_loc);
- TSMimeHdrFieldNameSet(bufp, hdr_loc, ce_loc, "Vary", -1);
- TSMimeHdrFieldValueStringInsert(bufp, hdr_loc, ce_loc, -1, "Accept-Encoding", -1);
- TSMimeHdrFieldAppend(bufp, hdr_loc, ce_loc);
- TSHandleMLocRelease(bufp, hdr_loc, ce_loc);
-
-
- //os: since we alter the entity body, update the etag to something different as well
- ce_loc = TSMimeHdrFieldFind(bufp, hdr_loc, TS_MIME_FIELD_ETAG, TS_MIME_LEN_ETAG);
- if (ce_loc){
- TSMimeHdrFieldValueAppend(bufp, hdr_loc, ce_loc, 0, "-df", 3);
- 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;
-
- TSDebug(PLUGIN_NAME, "gzip_transform_one");
-
- while (amount > 0) {
- TSDebug(PLUGIN_NAME, "gzip_transform_one->loop, amount: %d", amount);
- blkp = TSIOBufferReaderStart(input_reader);
-
- /* TSIOBufferReaderStart may return an error pointer */
- if (!blkp) {
- TSDebug(PLUGIN_NAME, "couldn't get from IOBufferBlock");
- TSError("couldn't get from IOBufferBlock");
- return;
- }
-
- TSDebug(PLUGIN_NAME, "gzip_transform_one->TSIOBufferReaderStart finished");
- ibuf = TSIOBufferBlockReadStart(blkp, input_reader, &ilength);
-
- /* TSIOBufferReaderStart may return an error pointer */
- if (!ibuf) {
- TSDebug(PLUGIN_NAME, "couldn't get from TSIOBufferBlockReadStart");
- TSError("couldn't get from TSIOBufferBlockReadStart");
- return;
- }
-
- TSDebug(PLUGIN_NAME, "gzip_transform_one->TSIOBufferBlockReadStart ilength: %" PRId64, ilength);
-
- if (ilength > amount) {
- ilength = amount;
- }
-
- data->zstrm.next_in = (unsigned char *) ibuf;
- data->zstrm.avail_in = ilength;
-
- while (data->zstrm.avail_in > 0) {
- TSDebug(PLUGIN_NAME, "gzip_transform_one->Tdata->zstrm.avail_in: %d", data->zstrm.avail_in);
- 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);
-
- if (err != Z_OK)
- TSDebug(PLUGIN_NAME,"deflate() call failed: %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);
- }
-
- TSDebug(PLUGIN_NAME,"deflate() call values olength: %" PRId64 " , ilength: %" PRId64 ", data->output_length: %d",
- olength, ilength, data->output_length );
-
- 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);
- }
- }
- }
- TSDebug(PLUGIN_NAME, "gzip_transform_one pre compute crc");
- /* compute CRC for error checking at client */
- data->crc = crc32(data->crc, (unsigned char *) ibuf, ilength);
-
- TSDebug(PLUGIN_NAME, "gzip_transform_one pre consume %" PRId64 " from reader", ilength);
- TSIOBufferReaderConsume(input_reader, ilength);
- amount -= ilength;
- }
- TSDebug(PLUGIN_NAME, "gzip_transform_one survived");
-}
-
-
-static void
-gzip_transform_finish(GzipData *data)
-{
- TSDebug(PLUGIN_NAME, "gzip_transform_finish");
- 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(PLUGIN_NAME, "deflate should report Z_STREAM_END");
- }
- 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);
- char crcbuf[8];
- char* buf=crcbuf;
- uLong 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;
-
- char*p = buf;
- int length;
- 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;
-
- TSDebug(PLUGIN_NAME, "gzip_transform_do");
-
- /* 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) {
- TSDebug(PLUGIN_NAME, "gzip_transform_do: data->state == 0, get_transform_init");
- gzip_transform_init(contp, data);
- } else {
- TSDebug(PLUGIN_NAME, "gzip_transform_do: data->state == %d, NO get_transform_init", data->state);
- }
-
- /* 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;
- TSDebug(PLUGIN_NAME, "gzip_transform_do: first length: %d", 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)) {
- TSDebug(PLUGIN_NAME, "gzip_transform_do->!TSVIOBufferGet(write_vio)...");
- gzip_transform_finish(data);
-
- TSVIONBytesSet(data->output_vio, data->output_length);
- TSDebug(PLUGIN_NAME, "Compressed size %d (bytes)", data->output_length);
-
- if (data->output_length > length) {
- TSDebug(PLUGIN_NAME, "gzip_transform_do->!reeanble data->output_vio");
- 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);
- TSDebug(PLUGIN_NAME, "gzip_transform_do: towrite: %d", towrite);
- 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));
- TSDebug(PLUGIN_NAME, "gzip_transform_do: avail: %d", avail);
- if (towrite > avail) {
- towrite = avail;
- }
-
- if (towrite > 0) {
- TSDebug(PLUGIN_NAME, "gzip_transform_do: call gzip_transform_one");
- gzip_transform_one(data, TSVIOReaderGet(write_vio), towrite);
- TSDebug(PLUGIN_NAME, "gzip_transform_do-> gzip_transform_one finished");
- /* Modify the write vio to reflect how much data we've
- completed. */
- TSVIONDoneSet(write_vio, TSVIONDoneGet(write_vio) + towrite);
- TSDebug(PLUGIN_NAME, "gzip_transform_do-> TSVIONDoneSet finished");
- }
- }
-
- TSDebug(PLUGIN_NAME,"TSVIONTodoGet(write_vio) -> %" PRId64, TSVIONTodoGet(write_vio) );
-
- /* Now we check the write vio to see if there is data left to
- read. */
- if (TSVIONTodoGet(write_vio) > 0) {
- TSDebug(PLUGIN_NAME, "gzip_transform_do-> towrite: %d", towrite);
- 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. */
-
- TSDebug(PLUGIN_NAME, "gzip_transform_do: data->output_length > length? %d > %d",
- data->output_length, length);
- if (data->output_length > length) {
- TSDebug(PLUGIN_NAME, "gzip_transform_do-> vio renable");
- TSVIOReenable(data->output_vio);
- //return;
- }
-
- /* Call back the write vio continuation to let it know that we
- are ready for more data. */
- TSDebug(PLUGIN_NAME, "gzip_transform_do: TSContCall - TS_EVENT_VCONN_WRITE_READY");
- TSContCall(TSVIOContGet(write_vio), TS_EVENT_VCONN_WRITE_READY, write_vio);
- }
- } else {
- TSDebug(PLUGIN_NAME, "gzip_transform_do-> towrite <= 0");
- /* 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. */
-
- TSDebug(PLUGIN_NAME, "gzip_transform_do-> pre gzip_transform_finish");
- gzip_transform_finish(data);
- TSDebug(PLUGIN_NAME, "gzip_transform_do-> post gzip_transform_finish");
- TSVIONBytesSet(data->output_vio, data->output_length);
- TSDebug(PLUGIN_NAME, "gzip_transform_do-> post TSVIONBytesSet");
- TSDebug(PLUGIN_NAME, "gzip_transform_do-> Compressed size %d (bytes)", data->output_length);
-
- if (data->output_length > length) {
- TSDebug(PLUGIN_NAME, "gzip_transform_do-> call TSVIOReenable");
- TSVIOReenable(data->output_vio);
- }
-
- /* Call back the write vio continuation to let it know that we
- have completed the write operation. */
- TSDebug(PLUGIN_NAME, "gzip_transform_do: TSContCall - TS_EVENT_VCONN_WRITE_COMPLETE");
- TSContCall(TSVIOContGet(write_vio), TS_EVENT_VCONN_WRITE_COMPLETE, write_vio);
- }
- TSDebug(PLUGIN_NAME, "gzip_transform_do-> survived");
-}
-
-
-static int
-gzip_transform(TSCont contp, TSEvent event, void *edata)
-{
- TSDebug(PLUGIN_NAME, "gzip_transform event %d", event);
- /* Check to see if the transformation has been closed by a call to
- TSVConnClose. */
- if (TSVConnClosedGet(contp)) {
- TSDebug(PLUGIN_NAME,"gzip_transform -> transformation has been closed");
- //.TSHttpTxnRespCacheableSet((TSHttpTxn)edata,0);
- gzip_data_destroy(TSContDataGet(contp));
- TSContDestroy(contp);
- return 0;
- } else {
- TSDebug(PLUGIN_NAME, "gzip_transform: switch on event");
- switch (event) {
- case TS_EVENT_ERROR:
- {
- TSDebug(PLUGIN_NAME, "gzip_transform: TS_EVENT_ERROR starts");
- 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:
- TSDebug(PLUGIN_NAME, "gzip_transform: TS_EVENT_VCONN_WRITE_COMPLETE starts");
- /* 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:
- TSDebug(PLUGIN_NAME, "gzip_transform: TS_EVENT_VCONN_WRITE_READY starts");
- /* If we get a WRITE_READY we'll attempt to transform more data. */
- gzip_transform_do(contp);
- break;
-
- case TS_EVENT_IMMEDIATE:
- TSDebug(PLUGIN_NAME, "gzip_transform: TS_EVENT_IMMEDIATE received. how about spitting out an error?");
- gzip_transform_do(contp);
- break;
-
- default:
- TSDebug(PLUGIN_NAME, "gzip_transform: default starts %d", event);
- /* If we get 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)
-{
- // ToDo: This is pretty ugly, do we need a new scope here? XXX
- {
- TSMBuffer bufp;
- TSMLoc hdr_loc;
- TSHttpStatus resp_status;
- TSMLoc con_field;
- int con_len;
- const char *con_val;
-
- if (server) {
- TSHttpTxnServerRespGet(txnp, &bufp, &hdr_loc);
- } else {
- TSHttpTxnCachedRespGet(txnp, &bufp, &hdr_loc);
- }
- resp_status = TSHttpHdrStatusGet(bufp, hdr_loc);
-
- con_field = TSMimeHdrFieldFind(bufp, hdr_loc, TS_MIME_FIELD_CONNECTION, -1);
- if (con_field) {
- con_val = TSMimeHdrFieldValueStringGet(bufp, hdr_loc, con_field, 0, &con_len);
- TSHandleMLocRelease(bufp, hdr_loc, con_field);
-
- //OS: !!!!!! FIXME !!!!!!!
- //this is a hotfix for some weird behavior from an origin
- //needs to be patched properly. this disables support for transactions that send the connection:close header
- if (con_val && con_len == 5)
- {
- TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
- return -999;
- }
- }
-
- TSDebug(PLUGIN_NAME,"Got status %d", resp_status);
- if (TS_HTTP_STATUS_OK == resp_status) {
- if (TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc) != TS_SUCCESS) {
- TSError("Unable to release handle to server request");
- }
- //return 1;
- } else {
- if (TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc) != TS_SUCCESS) {
- TSError("Unable to release handle to server request");
- }
- return -100;
- }
- }
-
-// TSDebug(PLUGIN_NAME, "gzip_transformable");
- /* 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, len;
-
- 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, &len);
- 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, &len);
-
- --nvalues;
- }
-
- if (!deflate_flag) {
- TSHandleMLocRelease(cbuf, chdr, cfield);
- TSHandleMLocRelease(cbuf, TS_NULL_MLOC, chdr);
- 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, &len);
- /*os: FIXME -> vary:accept-encoding needs to be added if any of these contenttypes is encountered
- */
- if ( len >= 5 && value && (strncasecmp(value, "text/", sizeof("text/") - 1) == 0)) {
- TSHandleMLocRelease(bufp, hdr_loc, field_loc);
- TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
- TSDebug(PLUGIN_NAME, "@ transformable, it is text/*");
- return 0;
- } else if ( len >= (sizeof("application/x-javascript") -1) && 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);
- TSDebug(PLUGIN_NAME, "@ transformable, it is application/x-javascript");
- return 0;
- } else {
- TSHandleMLocRelease(bufp, hdr_loc, field_loc);
- TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
- TSDebug(PLUGIN_NAME, "@ not a transformable content type");
- return -5;
- }
-}
-
-
-static void
-gzip_transform_add(TSHttpTxn txnp, int server)
-{
- TSVConn connp;
- GzipData *data;
-
- TSDebug(PLUGIN_NAME,"zip_transform_add -> tstransformcreate()");
- connp = TSTransformCreate(gzip_transform, txnp);
-
- TSDebug(PLUGIN_NAME,"zip_transform_add -> gzip_data_alloc()");
- data = gzip_data_alloc();
- data->txn = txnp;
-
- TSDebug(PLUGIN_NAME,"zip_transform_add -> TSContDataSet()");
- TSContDataSet(connp, data);
-
- TSDebug(PLUGIN_NAME,"zip_transform_add -> TSHttpTxnHookAdd()");
- TSHttpTxnHookAdd(txnp, TS_HTTP_RESPONSE_TRANSFORM_HOOK, connp);
-}
-
-static void
-normalize_accept_encoding(TSHttpTxn txnp, TSMBuffer reqp, TSMLoc hdr_loc)
-{
-// const char *header = "Accept-Encoding";
-// int header_len = strlen(header);
- TSMLoc field = TSMimeHdrFieldFind(reqp, hdr_loc, TS_MIME_FIELD_ACCEPT_ENCODING, TS_MIME_LEN_ACCEPT_ENCODING);
- int deflate = 0;
-
- //remove the accept encoding field(s),
- //while finding out if deflate is supported.
- while (field) {
- TSMLoc tmp;
-
- if (!deflate) {
- int value_count = TSMimeHdrFieldValuesCount(reqp, hdr_loc, field);
-
- while (value_count > 0) {
- int val_len = 0;
- const char* val;
-
- --value_count;
- val = TSMimeHdrFieldValueStringGet(reqp, hdr_loc, field, value_count, &val_len);
-
- //FIXME
- //OS: these aren't always NULL terminated.
- if (val_len >= 7) //valgrind complains on the strstrs
- deflate = strstr(val, "deflate") != NULL;
-
- if (deflate)
- break;
- }
- }
-
- tmp = TSMimeHdrFieldNextDup(reqp, hdr_loc, field);
- TSMimeHdrFieldDestroy(reqp, hdr_loc, field); //catch retval?
- TSHandleMLocRelease(reqp, hdr_loc, field);
- field = tmp;
- }
-
- //if deflate is supported,
- //append a new accept-encoding field in the header
- if (deflate){
- TSMimeHdrFieldCreate(reqp, hdr_loc, &field);
- TSMimeHdrFieldNameSet(reqp, hdr_loc, field, TS_MIME_FIELD_ACCEPT_ENCODING, TS_MIME_LEN_ACCEPT_ENCODING);
- TSMimeHdrFieldValueStringInsert(reqp, hdr_loc, field, -1, "deflate", strlen("deflate"));
- TSMimeHdrFieldAppend(reqp, hdr_loc, field);
- TSHandleMLocRelease(reqp, hdr_loc, field);
- }
-}
-
-
-static int
-transform_plugin(TSCont contp, TSEvent event, void *edata)
-{
- TSHttpTxn txnp = (TSHttpTxn) edata;
- int reason;
-
- TSDebug(PLUGIN_NAME, "@ transform_plugin()");
-
- switch (event) {
- case TS_EVENT_HTTP_READ_REQUEST_HDR:
- {
- TSMBuffer req_buf;
- TSMLoc req_loc;
- if ( TSHttpTxnClientReqGet(txnp, &req_buf, &req_loc) == TS_SUCCESS ){
- normalize_accept_encoding(txnp, req_buf, req_loc);
- TSHandleMLocRelease(req_buf, TS_NULL_MLOC, req_loc);
- }
- TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
- }
- break;
-
- case TS_EVENT_HTTP_READ_RESPONSE_HDR:
- reason = gzip_transformable(txnp, 1);
- if (reason >= 0) {
- TSDebug(PLUGIN_NAME, "server content transformable");
- gzip_transform_add(txnp, 1);
- } else {
- TSDebug(PLUGIN_NAME, "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(PLUGIN_NAME, "cached content transformable");
- gzip_transform_add(txnp, 1);
- } else {
- TSDebug(PLUGIN_NAME, "cached data: forwarding unchanged (%d)", reason);
- }
- TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
- break;
-
- default:
- TSError("gzip transform unknown event, exit!");
- exit(1);
- }
-
- return 0;
-}
-
-
-void
-TSPluginInit(int argc, const char *argv[])
-{
- dictId = adler32(0L, Z_NULL, 0);
- if (argc == 2) {
- strcpy(preload_file, argv[1]);
- preload = 1;
- load_dictionary(dictionary, &dictId);
- }
-
- TSDebug(PLUGIN_NAME, "gzip plugin loads");
-
- 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-plugins/blob/ff849998/header_rewrite/Examples/Force-close
----------------------------------------------------------------------
diff --git a/header_rewrite/Examples/Force-close b/header_rewrite/Examples/Force-close
deleted file mode 100644
index f6e0ab6..0000000
--- a/header_rewrite/Examples/Force-close
+++ /dev/null
@@ -1,4 +0,0 @@
-cond %{READ_REQUEST_HDR_HOOK} [AND]
-cond %{ACCESS:/url/local/www/html/status.html} [NOT,OR]
-cond %{RANDOM:1000} =42
-add-header Connection "close"
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/header_rewrite/Examples/Regression
----------------------------------------------------------------------
diff --git a/header_rewrite/Examples/Regression b/header_rewrite/Examples/Regression
deleted file mode 100644
index 86c8d0f..0000000
--- a/header_rewrite/Examples/Regression
+++ /dev/null
@@ -1,15 +0,0 @@
-cond %{STATUS} =201
-set-status 999
-set-status-reason "YDoDed again ..."
-
-cond %{READ_REQUEST_HDR_HOOK}
-rm-header Set-Cookie
-rm-header WWW-Authenticate
-rm-header Connection
-add-header Connection "close"
-
-cond %{RANDOM:10} =4
-set-status 789
-
-cond %{ACCESS:/tmp/foobar} [NOT]
-set-status 666
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/header_rewrite/Examples/YCS-EC
----------------------------------------------------------------------
diff --git a/header_rewrite/Examples/YCS-EC b/header_rewrite/Examples/YCS-EC
deleted file mode 100644
index 90c3aaa..0000000
--- a/header_rewrite/Examples/YCS-EC
+++ /dev/null
@@ -1,19 +0,0 @@
-# The default hook is INK_HTTP_READ_RESPONSE_HDR_HOOK, so need to specify that
-# Remove any cookie/authentication headers from the origin server response
-rm-header Set-Cookie
-rm-header WWW-Authenticate
-
-# This technically violates RFC 2616, but allows us to calculate proper age / freshness
-# in YTS, even when the origin (*caugh* wikimedia) shows odd Date and Age responses.
-rm-header Date
-rm-header Age
-
-# If the origin responds with an HTTP status in the 400 range, normalize to a 404
-cond %{STATUS} >399 [AND]
-cond %{STATUS} <499
-set-status 404
-
-# Don't send these headers to the Origin server
-cond %{SEND_REQUEST_HDR_HOOK}
-rm-header Cache-Control
-rm-header Pragma
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/header_rewrite/LICENSE
----------------------------------------------------------------------
diff --git a/header_rewrite/LICENSE b/header_rewrite/LICENSE
deleted file mode 100644
index d64337f..0000000
--- a/header_rewrite/LICENSE
+++ /dev/null
@@ -1,212 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed 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.
-
-~~~
-
-Copyright (C) 2009 Yahoo! Inc.
-
-Licensed 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
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/header_rewrite/Makefile
----------------------------------------------------------------------
diff --git a/header_rewrite/Makefile b/header_rewrite/Makefile
deleted file mode 100644
index d0e2162..0000000
--- a/header_rewrite/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-TSXS?=tsxs
-
-all: condition.cc conditions.cc header_rewrite.cc matcher.cc operator.cc operators.cc parser.cc resources.cc ruleset.cc statement.cc factory.cc regex_helper.cc
- export CPPFLAGS=$(CPPFLAGS) && \
- export LDFLAGS=$(LDFLAGS) && \
- $(TSXS) -v -C $? -o header_rewrite.so
-
-install:
- $(TSXS) -i -o header_rewrite.so
-
-clean:
- rm -f *.lo *.so *.bz2 *.asc *.md5 *.sha1
-
-
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/header_rewrite/README
----------------------------------------------------------------------
diff --git a/header_rewrite/README b/header_rewrite/README
deleted file mode 100644
index df8165f..0000000
--- a/header_rewrite/README
+++ /dev/null
@@ -1,171 +0,0 @@
-Apache Traffic Server Rewrite Header Plugin
-This is a plugin for ATS (Apache Traffic Server), that allows you to
-perform various header "rewrite" rules (operations) on a request or
-response. Currently, only one operation is supported, since we had to get
-this rolling asap.
-
-Note that currently only static string "values" are supported. We'll add
-advanced features to allow for expansions in a future release.
-
-
-Operations
-----------
-
- rm-header header-name [flags]
- add-header header "string" [flags]
- set-status status-code [flags]
- set-status-reason reason-string [flags]
- no-op [flags]
-
-
-The following operator(s) currently only works when instantiating the
-plugin as a remap plugin:
-
- set-destination [qual] value
-
-Where qual is one of the support URL qualifiers
-
- HOST
- PORT
- PATH
- QUERY
-
-For example (as a remap rule):
-
- cond %{HEADER:X-Mobile} = "foo"
- set-destination HOST foo.mobile.bar.com [L]
-
-
-
-Operation flags
----------------
- [L] Last rule, do not continue
-
-
-Conditions
-----------
-
- cond %{STATUS} operand [flags]
- cond %{RANDOM:nn} operand [flags]
- cond %{ACCESS:file} [flags]
- cond %{TRUE} [flags]
- cond %{FALSE} [flags]
- cond %{HEADER:header-name} [flags]
-
-
-These conditions have to be first in a ruleset, and you can only have one:
-
- cond %{READ_RESPONSE_HDR_HOOK} (this is the default hook)
- cond %{READ_REQUEST_HDR_HOOK}
- cond %{SEND_REQUEST_HDR_HOOK}
- cond %{SEND_RESPONSE_HDR_HOOK}
-
-
-Condition flags
----------------
- [AND] AND with next condition (default)
- [OR] OR with next condition
- [NOT] Invert this condition
-
-
-Operands to conditions
-----------------------
- =val Lexically equal
- <val Lexically less then
- >val Lexically greater then
-
-
-
-RELEASES
---------
-Version 2.0.0 (6/8/12, bcall)
--- Ported to ATS
-
-Version 1.7.3 (12/01/11,sambani)
--- changed mdbm locks to mutex
-
-Version 1.7.2 (10/18/11,cdoshi)
--- check for url redirect length
-
-Version 1.7.1 (10/18/11,cdoshi)
--- use size_t instead of unsigned
-
-Version 1.7.0 (10/17/11,cdoshi)
- - Support for %{PATH}
-
-Version 1.6.9 (10,17,11,cdoshi)
- - Support for PATH condition
-
-Version 1.6.8 (10/17/11,cdoshi)
- - Replace the INKHttpHdrStatusSet with INKHttptxnSetHttpRetStatus
-
-Version 1.6.7 (07/21/11, bcall)
- - [bug 4699620] - Removed some extra printf()'s
-
-Version 1.6.6 (cdoshi)
- - when Host adder is added setHostChange will be called
-
-Version 1.6.5 (cdoshi)
- - fix QSA for set-destination
-
-Version 1.6.4 (cdoshi)
- - support QSA for set-destination
-
-Version 1.6.3 (cdoshi)
- - support the query,fix the remap stuff
-
-Version 1.6.2 (cdoshi)
- - Support for regex matcher
-
-Version 1.6.1 (09/15/10, leif)
- - [bug 3985913]
-
-Version 1.6.0 (07/14/10, leif)
- - Added support for the timeout-out operator.
- - Added support for the set-redirect operator.
- - Added support for INK_HTTP_READ_REQUEST_PRE_REMAP_HOOK (this means we
- now require YTS 1.18.1 or later).
-
-Version 1.5.0 (06/02/10, leif)
- - Add support for running as a remap plugin.
- - Add support for set-destination operator (this currently only works in
- a remap plugin).
-
-Version 1.4.1 (02/09/10, leif)
- - Cleanup of error messages.
- - Changed name from MDBM to DBM.
-
-Version 1.4 (01/20/10, leif)
- - Added support for CLIENT-HEADER condition.
- - Cleanup in flags handling and features.
- - Support MDBM as a condition.
-
-Version 1.3.1 (12/22/09, leif)
- - Fixed package to support MDBM v2.x and v3.x.
-
-Version 1.3 (12/22/09, leif)
- - Refactored to allow conditions to be used as values.
- - Added condition for HEADER.
- - Added condition for MDBM lookups.
- - Fixed consistency problems on HOOK names.
-
-Version 1.2 (10/28/09, leif)
- - Added support for SEND_RESPONSE_HDR_HOOK.
-
-Version 1.1 (10/08/09, leif)
- - Added support for SEND_REQUEST_HDR_HOOK.
-
-Version 1.0 (9/24/09, leif)
- - Added support for two hooks.
- - Added "add-header". Remember to "rm-header" the header first if you
- want to assure there's only one version.
- - Added support for %{RANDOM:NN} condition
- - Added support for %{ACCESS:file} condition
- - Lots of more code cleanup.
-
-Version 0.2 (7/24/09, leif)
- - Added support for some basic conditions.
- - Added support for setting the return status code and reason.
-
-Version 0.1 (7/13/09, leif)
- - Initial version.
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/header_rewrite/TODO
----------------------------------------------------------------------
diff --git a/header_rewrite/TODO b/header_rewrite/TODO
deleted file mode 100644
index d71e1d4..0000000
--- a/header_rewrite/TODO
+++ /dev/null
@@ -1,29 +0,0 @@
-* Add a new base class for extracting values (extractor)
-* Implement extractors for various values
-* Make the statement base class virtual inherited
-* In conditions / values, we can get the value by using the << or >> operator
-* Mark which conditions and operators work in what hooks
-* Better debugging on conditions.
-* Add descriptions to conditions and operators.
-* Support configurable timeouts
-* Support "super-conditions", or nested conditions (if (A) if (b) else if (c) )
-
-
-Conditions to add
-
-%{REQUEST-HEADER:<hdr>}
-%{RESPONSE-HEADER:<hdr>}
-
-%{CLIENT-URL}
-%{CLIENT-URL:HOST}
-%{CLIENT-URL:PORT}
-%{CLIENT-URL:PATH}
-%{CLIENT-URL:QUERY}
-%{CLIENT-URL:PARAMS}
-
-%{SERVER-URL}
-%{SERVER-URL:HOST}
-%{SERVER-URL:PORT}
-%{SERVER-URL:PATH}
-%{SERVER-URL:QUERY}
-%{SERVER-URL:PARAMS}
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/header_rewrite/condition.cc
----------------------------------------------------------------------
diff --git a/header_rewrite/condition.cc b/header_rewrite/condition.cc
deleted file mode 100644
index 518345a..0000000
--- a/header_rewrite/condition.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////////////////////
-// condition.cc: Implementation of the condition base class
-//
-//
-
-#define UNUSED __attribute__ ((unused))
-static char UNUSED rcsId__condition_cc[] = "@(#) $Id$ built on " __DATE__ " " __TIME__;
-
-#include <ts/ts.h>
-#include <string>
-
-#include "condition.h"
-
-
-static MatcherOps
-parse_matcher_op(std::string& arg)
-{
- switch (arg[0]) {
- case '=':
- arg.erase(0,1);
- return MATCH_EQUAL;
- break;
- case '<':
- arg.erase(0,1);
- return MATCH_LESS_THEN;
- break;
- case '>':
- arg.erase(0,1);
- return MATCH_GREATER_THEN;
- break;
- case '/':
- arg.erase(0,1);
- arg.erase(arg.length() -1 , arg.length());
- return MATCH_REGULAR_EXPRESSION;
- break;
- default:
- return MATCH_EQUAL;
- break;
- }
-}
-
-
-void
-Condition::initialize(Parser& p)
-{
- Statement::initialize(p);
-
- if (p.mod_exist("OR")) {
- if (p.mod_exist("AND")) {
- TSError("header_rewrite: Can't have both AND and OR in mods");
- } else {
- _mods = static_cast<CondModifiers>(_mods | COND_OR);
- }
- } else if (p.mod_exist("AND")) {
- _mods = static_cast<CondModifiers>(_mods | COND_AND);
- }
-
- if (p.mod_exist("NOT")) {
- _mods = static_cast<CondModifiers>(_mods | COND_NOT);
- }
-
- if (p.mod_exist("L")) {
- _mods = static_cast<CondModifiers>(_mods | COND_LAST);
- }
-
- _cond_op = parse_matcher_op(p.get_arg());
-}
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/header_rewrite/condition.h
----------------------------------------------------------------------
diff --git a/header_rewrite/condition.h b/header_rewrite/condition.h
deleted file mode 100644
index 149642c..0000000
--- a/header_rewrite/condition.h
+++ /dev/null
@@ -1,101 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////////////////////
-//
-// Implement the classes for the various types of hash keys we support.
-//
-#ifndef __CONDITION_H__
-#define __CONDITION_H__ 1
-
-#define UNUSED __attribute__ ((unused))
-static char UNUSED rcsId__condition_h[] = "@(#) $Id$ built on " __DATE__ " " __TIME__;
-
-#include <string>
-#include <ts/ts.h>
-
-#include "resources.h"
-#include "statement.h"
-#include "matcher.h"
-#include "parser.h"
-
-
-// Condition modifiers
-enum CondModifiers {
- COND_NONE = 0,
- COND_OR = 1,
- COND_AND = 2,
- COND_NOT = 4,
- COND_NOCASE = 8,
- COND_LAST = 16,
- COND_CHAIN = 32
-};
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Base class for all Conditions (this is also the interface)
-//
-class Condition : public Statement
-{
-public:
- Condition()
- : _qualifier(""), _cond_op(MATCH_EQUAL), _matcher(NULL), _mods(COND_NONE)
- {
- TSDebug(PLUGIN_NAME_DBG, "Calling CTOR for Condition");
- }
-
- // Inline this, it's critical for speed (and only used twice)
- bool do_eval(const Resources& res)
- {
- bool rt = eval(res);
-
- if (_mods & COND_NOT)
- rt = !rt;
-
- if (_next) {
- if (_mods & COND_OR) {
- return rt || (static_cast<Condition*>(_next)->do_eval(res));
- } else { // AND is the default
- // Short circuit if we're an AND and the first condition is FALSE.
- if (rt)
- return static_cast<Condition*>(_next)->do_eval(res);
- else
- return false;
- }
- } else {
- return rt;
- }
-
- return false; // Shouldn't happen.
- }
-
- bool last() const {
- return _mods & COND_LAST;
- }
-
- // Setters
- virtual void set_qualifier(const std::string& q) { _qualifier = q; }
-
- // Some getters
- const Matcher* get_matcher() const { return _matcher; }
- const MatcherOps get_cond_op() const { return _cond_op; }
- const std::string get_qualifier() const { return _qualifier; }
-
- // Virtual methods, has to be implemented by each conditional;
- virtual void initialize(Parser& p);
- virtual void append_value(std::string& s, const Resources& res) = 0;
-
-protected:
- // Evaluate the condition
- virtual bool eval(const Resources& res) = 0;
-
- std::string _qualifier;
- MatcherOps _cond_op;
- Matcher* _matcher;
-
-private:
- DISALLOW_COPY_AND_ASSIGN(Condition);
-
- CondModifiers _mods;
-};
-
-
-#endif // __CONDITION_H
-
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/header_rewrite/conditions.cc
----------------------------------------------------------------------
diff --git a/header_rewrite/conditions.cc b/header_rewrite/conditions.cc
deleted file mode 100644
index f05d8ec..0000000
--- a/header_rewrite/conditions.cc
+++ /dev/null
@@ -1,354 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////////////////////
-// conditions.cc: Implementation of the condition classes
-//
-//
-
-#define UNUSED __attribute__ ((unused))
-static char UNUSED rcsId__conditions_cc[] = "@(#) $Id$ built on " __DATE__ " " __TIME__;
-
-#include <unistd.h>
-#include <ts/ts.h>
-
-#include "conditions.h"
-#include "lulu.h"
-
-#include <sys/time.h>
-
-
-// ConditionStatus
-void
-ConditionStatus::initialize(Parser& p)
-{
- Condition::initialize(p);
-
- Matchers<TSHttpStatus>* match = new Matchers<TSHttpStatus>(_cond_op);
-
- match->set(static_cast<TSHttpStatus>(strtol(p.get_arg().c_str(), NULL, 10)));
- _matcher = match;
-
- require_resources(RSRC_SERVER_RESPONSE_HEADERS);
- require_resources(RSRC_CLIENT_RESPONSE_HEADERS);
- require_resources(RSRC_RESPONSE_STATUS);
-}
-
-
-void
-ConditionStatus::initialize_hooks() {
- add_allowed_hook(TS_HTTP_READ_RESPONSE_HDR_HOOK);
- add_allowed_hook(TS_HTTP_SEND_RESPONSE_HDR_HOOK);
-}
-
-
-bool
-ConditionStatus::eval(const Resources& res) {
- TSDebug(PLUGIN_NAME, "Evaluating STATUS()"); // TODO: It'd be nice to get the args here ...
- return static_cast<const Matchers<TSHttpStatus>*>(_matcher)->test(res.resp_status);
-}
-
-
-void
-ConditionStatus::append_value(std::string& s, const Resources& res) {
- s += boost::lexical_cast<std::string>(res.resp_status);
- TSDebug(PLUGIN_NAME, "Appending STATUS(%d) to evaluation value -> %s", res.resp_status, s.c_str());
-}
-
-
-// ConditionRandom: random 0 to (N-1)
-void
-ConditionRandom::initialize(Parser& p)
-{
- struct timeval tv;
-
- Condition::initialize(p);
-
- gettimeofday(&tv, NULL);
-
- Matchers<unsigned int>* match = new Matchers<unsigned int>(_cond_op);
- _seed = getpid()* tv.tv_usec;
- _max = strtol(_qualifier.c_str(), NULL, 10);
-
- match->set(static_cast<unsigned int>(strtol(p.get_arg().c_str(), NULL, 10)));
- _matcher = match;
-}
-
-
-bool
-ConditionRandom::eval(const Resources& res) {
- TSDebug(PLUGIN_NAME, "Evaluating RANDOM(%d)", _max);
- return static_cast<const Matchers<unsigned int>*>(_matcher)->test(rand_r(&_seed) % _max);
-}
-
-
-void
-ConditionRandom::append_value(std::string& s, const Resources& res)
-{
- s += boost::lexical_cast<std::string>(rand_r(&_seed) % _max);
- TSDebug(PLUGIN_NAME, "Appending RANDOM(%d) to evaluation value -> %s", _max, s.c_str());
-}
-
-
-// ConditionAccess: access(file)
-void
-ConditionAccess::initialize(Parser& p)
-{
- struct timeval tv;
-
- Condition::initialize(p);
-
- gettimeofday(&tv, NULL);
-
- _next = tv.tv_sec + 2;
- _last = !access(_qualifier.c_str(), R_OK);
-}
-
-
-void
-ConditionAccess::append_value(std::string& s, const Resources& res)
-{
- if (eval(res)) {
- s += "OK";
- } else {
- s += "NOT OK";
- }
-}
-
-
-bool
-ConditionAccess::eval(const Resources& res)
-{
- struct timeval tv;
-
- gettimeofday(&tv, NULL);
-
- TSDebug(PLUGIN_NAME, "Evaluating ACCESS(%s)", _qualifier.c_str());
- if (tv.tv_sec > _next) {
- // There is a small "race" here, where we could end up calling access() a few times extra. I think
- // that is OK, and not worth protecting with a lock.
- bool check = !access(_qualifier.c_str(), R_OK);
-
- tv.tv_sec += 2;
- mb();
- _next = tv.tv_sec; // I hope this is an atomic "set"...
- _last = check; // This sure ought to be
- }
-
- return _last;
-}
-
-
-// ConditionHeader: request or response header
-void
-ConditionHeader::initialize(Parser& p)
-{
- Condition::initialize(p);
-
- Matchers<std::string>* match = new Matchers<std::string>(_cond_op);
- match->set(p.get_arg());
-
- _matcher = match;
-
- require_resources(RSRC_CLIENT_REQUEST_HEADERS);
- require_resources(RSRC_CLIENT_RESPONSE_HEADERS);
- require_resources(RSRC_SERVER_REQUEST_HEADERS);
- require_resources(RSRC_SERVER_RESPONSE_HEADERS);
-}
-
-
-void
-ConditionHeader::append_value(std::string& s, const Resources& res)
-{
- TSMBuffer bufp;
- TSMLoc hdr_loc;
- TSMLoc field_loc;
- const char* value;
- int len;
-
- if (_client) {
- bufp = res.client_bufp;
- hdr_loc = res.client_hdr_loc;
- } else {
- bufp = res.bufp;
- hdr_loc = res.hdr_loc;
- }
-
- if (bufp && hdr_loc) {
- field_loc = TSMimeHdrFieldFind(bufp, hdr_loc, _qualifier.c_str(), _qualifier.size());
- if (field_loc) {
- value = TSMimeHdrFieldValueStringGet(res.bufp, res.hdr_loc, field_loc, 0, &len);
- TSDebug(PLUGIN_NAME, "Appending HEADER(%s) to evaluation value -> %.*s", _qualifier.c_str(), len, value);
- s.append(value, len);
- TSHandleMLocRelease(res.bufp, res.hdr_loc, field_loc);
- }
- }
-}
-
-
-bool
-ConditionHeader::eval(const Resources& res)
-{
- std::string s;
-
- append_value(s, res);
- bool rval = static_cast<const Matchers<std::string>*>(_matcher)->test(s);
- TSDebug(PLUGIN_NAME, "Evaluating HEADER(): %s - rval: %d", s.c_str(), rval);
- return rval;
-}
-
-// ConditionPath
-void
-ConditionPath::initialize(Parser& p)
-{
- Condition::initialize(p);
-
- Matchers<std::string>* match = new Matchers<std::string>(_cond_op);
- match->set(p.get_arg());
-
- _matcher = match;
-}
-
-void
-ConditionPath::append_value(std::string& s, const Resources& res)
-{
- int path_len = 0;
- const char *path = TSUrlPathGet(res._rri->requestBufp, res._rri->requestUrl, &path_len);
- TSDebug(PLUGIN_NAME, "Appending PATH to evaluation value: %.*s", path_len, path);
- s.append(path, path_len);
-}
-
-bool
-ConditionPath::eval(const Resources& res)
-{
- std::string s;
-
- append_value(s, res);
- TSDebug(PLUGIN_NAME, "Evaluating PATH");
-
- return static_cast<const Matchers<std::string>*>(_matcher)->test(s);
-}
-
-// ConditionQuery
-void
-ConditionQuery::initialize(Parser& p)
-{
- Condition::initialize(p);
-
- Matchers<std::string>* match = new Matchers<std::string>(_cond_op);
- match->set(p.get_arg());
- _matcher = match;
-
-}
-
-void
-ConditionQuery::append_value(std::string& s, const Resources& res)
-{
- int query_len = 0;
- const char *query = TSUrlHttpQueryGet(res._rri->requestBufp, res._rri->requestUrl, &query_len);
- TSDebug(PLUGIN_NAME, "Appending QUERY to evaluation value: %.*s", query_len, query);
- s.append(query, query_len);
-}
-
-bool
-ConditionQuery::eval(const Resources& res)
-{
- std::string s;
-
- append_value(s, res);
- TSDebug(PLUGIN_NAME, "Evaluating QUERY - %s", s.c_str());
- return static_cast<const Matchers<std::string>*>(_matcher)->test(s);
-}
-
-
-// ConditionUrl: request or response header. TODO: This is not finished, at all!!!
-void
-ConditionUrl::initialize(Parser& p)
-{
-}
-
-
-void
-ConditionUrl::set_qualifier(const std::string& q) {
- Condition::set_qualifier(q);
-
- _url_qual = parse_url_qualifier(q);
-}
-
-
-void
-ConditionUrl::append_value(std::string& s, const Resources& res)
-{
-}
-
-
-bool
-ConditionUrl::eval(const Resources& res)
-{
- bool ret = false;
-
- return ret;
-}
-
-
-// ConditionDBM: do a lookup against a DBM
-void
-ConditionDBM::initialize(Parser& p)
-{
- Condition::initialize(p);
-
- Matchers<std::string>* match = new Matchers<std::string>(_cond_op);
- match->set(p.get_arg());
- _matcher = match;
-
- std::string::size_type pos = _qualifier.find_first_of(',');
-
- if (pos != std::string::npos) {
- _file = _qualifier.substr(0, pos);
- //_dbm = mdbm_open(_file.c_str(), O_RDONLY, 0, 0, 0);
- // if (NULL != _dbm) {
- // TSDebug(PLUGIN_NAME, "Opened DBM file %s\n", _file.c_str());
- // _key.set_value(_qualifier.substr(pos + 1));
- // } else {
- // TSError("Failed to open DBM file: %s", _file.c_str());
- // }
- } else {
- TSError("Malformed DBM condition");
- }
-}
-
-
-void
-ConditionDBM::append_value(std::string& s, const Resources& res)
-{
- // std::string key;
-
- // if (!_dbm)
- // return;
-
- // _key.append_value(key, res);
- // if (key.size() > 0) {
- // datum k, v;
-
- // TSDebug(PLUGIN_NAME, "Looking up DBM(\"%s\")", key.c_str());
- // k.dptr = const_cast<char*>(key.c_str());
- // k.dsize = key.size();
-
- // TSMutexLock(_mutex);
- // //v = mdbm_fetch(_dbm, k);
- // TSMutexUnlock(_mutex);
- // if (v.dsize > 0) {
- // TSDebug(PLUGIN_NAME, "Appending DBM(%.*s) to evaluation value -> %.*s", k.dsize, k.dptr, v.dsize, v.dptr);
- // s.append(v.dptr, v.dsize);
- // }
- // }
-}
-
-
-bool
-ConditionDBM::eval(const Resources& res)
-{
- std::string s;
-
- append_value(s, res);
- TSDebug(PLUGIN_NAME, "Evaluating DBM(%s, \"%s\")", _file.c_str(), s.c_str());
-
- return static_cast<const Matchers<std::string>*>(_matcher)->test(s);
-}
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/header_rewrite/conditions.h
----------------------------------------------------------------------
diff --git a/header_rewrite/conditions.h b/header_rewrite/conditions.h
deleted file mode 100644
index 25975fb..0000000
--- a/header_rewrite/conditions.h
+++ /dev/null
@@ -1,270 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////////////////////
-//
-// Declarations for all conditionals / conditional values we support.
-//
-#ifndef __CONDITIONS_H__
-#define __CONDITIONS_H__ 1
-
-#define UNUSED __attribute__ ((unused))
-static char UNUSED rcsId__conditions_h[] = "@(#) $Id$ built on " __DATE__ " " __TIME__;
-
-#include <string>
-#include <ts/ts.h>
-#include <boost/lexical_cast.hpp>
-
-#include "condition.h"
-#include "matcher.h"
-#include "value.h"
-#include "lulu.h"
-//#include <mdbm.h>
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Condition declarations.
-//
-
-// Always true
-class ConditionTrue : public Condition
-{
-public:
- ConditionTrue()
- {
- TSDebug(PLUGIN_NAME_DBG, "Calling CTOR for ConditionTrue");
- }
-
- void append_value(std::string& s, const Resources& res) { s += "TRUE"; }
-
-protected:
- bool eval(const Resources& res) {
- TSDebug(PLUGIN_NAME, "Evaluating TRUE()");
- return true;
- }
-
-private:
- DISALLOW_COPY_AND_ASSIGN(ConditionTrue);
-};
-
-
-// Always false
-class ConditionFalse : public Condition
-{
-public:
- ConditionFalse()
- {
- TSDebug(PLUGIN_NAME_DBG, "Calling CTOR for ConditionFalse");
- }
- void append_value(std::string& s, const Resources& res) { s += "FALSE"; }
-
-protected:
- bool eval(const Resources& res) {
- TSDebug(PLUGIN_NAME, "Evaluating FALSE()");
- return false;
- }
-
-private:
- DISALLOW_COPY_AND_ASSIGN(ConditionFalse);
-};
-
-
-// Check the HTTP return status
-class ConditionStatus : public Condition
-{
-public:
- ConditionStatus()
- {
- TSDebug(PLUGIN_NAME_DBG, "Calling CTOR for ConditionStatus");
- }
- void initialize(Parser& p);
- void append_value(std::string& s, const Resources& res);
-
-protected:
- bool eval(const Resources& res);
- void initialize_hooks(); // Return status only valid in certain hooks
-
-private:
- DISALLOW_COPY_AND_ASSIGN(ConditionStatus);
-};
-
-
-// Random 0 to (N-1)
-class ConditionRandom : public Condition
-{
-public:
- ConditionRandom()
- : _seed(0), _max(0)
- {
- TSDebug(PLUGIN_NAME_DBG, "Calling CTOR for ConditionRandom");
- }
- void initialize(Parser& p);
- void append_value(std::string& s, const Resources& res);
-
-protected:
- bool eval(const Resources& res);
-
-private:
- DISALLOW_COPY_AND_ASSIGN(ConditionRandom);
-
- unsigned int _seed;
- unsigned int _max;
-};
-
-
-// access(file)
-class ConditionAccess : public Condition
-{
-public:
- ConditionAccess()
- : _next(0), _last(false)
- {
- TSDebug(PLUGIN_NAME_DBG, "Calling CTOR for ConditionAccess");
- }
- void initialize(Parser& p);
- void append_value(std::string& s, const Resources& res);
-
-protected:
- bool eval(const Resources& res);
-
-private:
- DISALLOW_COPY_AND_ASSIGN(ConditionAccess);
-
- time_t _next;
- bool _last;
-};
-
-
-// header
-class ConditionHeader : public Condition
-{
-public:
- explicit ConditionHeader(bool client = false)
- : _client(client)
- {
- TSDebug(PLUGIN_NAME_DBG, "Calling CTOR for ConditionHeader");
- };
-
- void initialize(Parser& p);
- void append_value(std::string& s, const Resources& res);
-
-protected:
- bool eval(const Resources& res);
-
-private:
- DISALLOW_COPY_AND_ASSIGN(ConditionHeader);
-
- bool _client;
-};
-
-// path
-class ConditionPath : public Condition
-{
-public:
- explicit ConditionPath()
- {
- TSDebug(PLUGIN_NAME_DBG, "Calling CTOR for ConditionPath");
- };
-
- void initialize(Parser& p);
- void append_value(std::string& s, const Resources& res);
-
-protected:
- bool eval(const Resources& res);
-
-private:
- DISALLOW_COPY_AND_ASSIGN(ConditionPath);
-};
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-class ConditionQuery : public Condition
-{
-public:
- explicit ConditionQuery()
- {
- TSDebug(PLUGIN_NAME_DBG, "Calling CTOR for ConditionQuery");
- };
-
- void initialize(Parser& p);
- void append_value(std::string& s, const Resources& res);
-
-protected:
- bool eval(const Resources& res);
-
-private:
- DISALLOW_COPY_AND_ASSIGN(ConditionQuery);
-
-};
-
-
-// url
-class ConditionUrl : public Condition
-{
-public:
- explicit ConditionUrl(bool client = false)
- : _url_qual(URL_QUAL_NONE), _client(client)
- {
- TSDebug(PLUGIN_NAME_DBG, "Calling CTOR for ConditionUrl");
- };
-
- void initialize(Parser& p);
- void set_qualifier(const std::string& q);
- void append_value(std::string& s, const Resources& res);
-
-protected:
- bool eval(const Resources& res);
-
-private:
- DISALLOW_COPY_AND_ASSIGN(ConditionUrl);
-
- UrlQualifiers _url_qual;
- bool _client;
-};
-
-
-// DBM lookups
-class ConditionDBM : public Condition
-{
-public:
- ConditionDBM()
- :
- //_dbm(NULL),
- _file("")
- {
- _mutex = TSMutexCreate();
- TSDebug(PLUGIN_NAME_DBG, "Calling CTOR for ConditionDBM");
- }
-
- ~ConditionDBM() {
- // if (_dbm) {
- // mdbm_close(_dbm);
- // _dbm = NULL;
- // }
- }
-
- void initialize(Parser& p);
- void append_value(std::string& s, const Resources& res);
-
-protected:
- bool eval(const Resources& res);
-
-private:
- DISALLOW_COPY_AND_ASSIGN(ConditionDBM);
-
- //MDBM* _dbm;
- std::string _file;
- Value _key;
- TSMutex _mutex;
-};
-
-#endif // __CONDITIONS_H
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/header_rewrite/factory.cc
----------------------------------------------------------------------
diff --git a/header_rewrite/factory.cc b/header_rewrite/factory.cc
deleted file mode 100644
index 0a89728..0000000
--- a/header_rewrite/factory.cc
+++ /dev/null
@@ -1,95 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////////////////////
-// factory.cc: Factory functions for operators, conditions and condition variables.
-//
-//
-#define UNUSED __attribute__ ((unused))
-static char UNUSED rcsId__factory_cc[] = "@(#) $Id$ built on " __DATE__ " " __TIME__;
-
-#include <string>
-
-#include "operators.h"
-#include "conditions.h"
-
-
-///////////////////////////////////////////////////////////////////////////////
-// "Factory" functions, processing the parsed lines
-//
-Operator*
-operator_factory(const std::string& op)
-{
- Operator* o = NULL;
-
- if (op == "rm-header") {
- o = new OperatorRMHeader();
- } else if (op == "add-header") {
- o = new OperatorAddHeader();
- } else if (op == "set-status") {
- o = new OperatorSetStatus();
- } else if (op == "set-status-reason") {
- o = new OperatorSetStatusReason();
- } else if (op == "set-destination") {
- o = new OperatorSetDestination();
- } else if (op == "set-redirect") {
- o = new OperatorSetRedirect();
- } else if (op == "timeout-out") {
- o = new OperatorSetTimeoutOut();
- } else if (op == "no-op") {
- o = new OperatorNoOp();
- } else {
- TSError("header_rewrite: unknown operator in header_rewrite: %s", op.c_str());
- return NULL;
- }
-
- return o;
-}
-
-
-Condition*
-condition_factory(const std::string& cond)
-{
- Condition* c = NULL;
- std::string c_name, c_qual;
- std::string::size_type pos = cond.find_first_of(':');
-
- if (pos != std::string::npos) {
- c_name = cond.substr(0, pos);
- c_qual = cond.substr(pos + 1);
- } else {
- c_name = cond;
- c_qual = "";
- }
-
- if (c_name == "TRUE") {
- c = new ConditionTrue();
- } else if (c_name == "FALSE") {
- c = new ConditionFalse();
- } else if (c_name == "STATUS") {
- c = new ConditionStatus();
- } else if (c_name == "RANDOM") {
- c = new ConditionRandom();
- } else if (c_name == "ACCESS") {
- c = new ConditionAccess();
- } else if (c_name == "HEADER") { // This condition adapts to the hook
- c = new ConditionHeader();
- }else if (c_name == "PATH"){
- c= new ConditionPath();
- } else if (c_name == "CLIENT-HEADER") {
- c = new ConditionHeader(true);
- } else if (c_name == "QUERY") {
- c = new ConditionQuery();
- } else if (c_name == "URL") { // This condition adapts to the hook
- c = new ConditionUrl();
- } else if (c_name == "CLIENT-URL") {
- c = new ConditionUrl(true);
- } else if (c_name == "DBM") {
- c = new ConditionDBM();
- } else {
- TSError("header_rewrite: unknown condition in header_rewrite: %s",c_name.c_str());
- return NULL;
- }
-
- if (c_qual != "")
- c->set_qualifier(c_qual);
-
- return c;
-}
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/header_rewrite/factory.h
----------------------------------------------------------------------
diff --git a/header_rewrite/factory.h b/header_rewrite/factory.h
deleted file mode 100644
index 3301ce3..0000000
--- a/header_rewrite/factory.h
+++ /dev/null
@@ -1,20 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////////////////////
-//
-// Implement the classes for the various types of hash keys we support.
-//
-#ifndef __FACTORY_H__
-#define __FACTORY_H__ 1
-
-#define UNUSED __attribute__ ((unused))
-static char UNUSED rcsId__factory_h[] = "@(#) $Id$ built on " __DATE__ " " __TIME__;
-
-#include <string>
-
-#include "operator.h"
-#include "condition.h"
-
-Operator* operator_factory(const std::string& op);
-Condition* condition_factory(const std::string& cond);
-
-
-#endif
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/header_rewrite/header_rewrite.cc
----------------------------------------------------------------------
diff --git a/header_rewrite/header_rewrite.cc b/header_rewrite/header_rewrite.cc
deleted file mode 100644
index aba03ef..0000000
--- a/header_rewrite/header_rewrite.cc
+++ /dev/null
@@ -1,331 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////////////////////
-// header_rewrite: YTS plugin to do header rewrites
-// --------------
-//
-//
-#define UNUSED __attribute__ ((unused))
-static char UNUSED rcsId__header_rewrite_cc[] = "@(#) $Id$ built on " __DATE__ " " __TIME__;
-
-#include <fstream>
-#include <string>
-#include <boost/algorithm/string.hpp>
-
-#include <ts/ts.h>
-#include <ts/remap.h>
-
-#include "parser.h"
-#include "ruleset.h"
-#include "resources.h"
-
-// "Defines"
-static const char* DEFAULT_CONF_PATH = "/usr/local/etc/header_rewrite/";
-
-
-// Global holding the rulesets and resource IDs
-static RuleSet* all_rules[TS_HTTP_LAST_HOOK+1];
-static ResourceIDs all_resids[TS_HTTP_LAST_HOOK+1];
-
-// Helper function to add a rule to the rulesets
-static bool
-add_rule(RuleSet* rule) {
- if (rule && rule->has_operator()) {
- TSDebug(PLUGIN_NAME, "Adding rule to hook=%d\n", rule->get_hook());
- if (NULL == all_rules[rule->get_hook()]) {
- all_rules[rule->get_hook()] = rule;
- } else {
- all_rules[rule->get_hook()]->append(rule);
- }
- return true;
- }
-
- return false;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Simple "config" parser, this modifies the global above. ToDo: What happens
-// on a "config" reload?
-//
-// Note that this isn't particularly efficient, but it's a startup time cost
-// anyways (or reload for remap.config), so not really in the critical path.
-//
-bool
-parse_config(const std::string fname, TSHttpHookID default_hook)
-{
- RuleSet* rule = NULL;
- std::string filename = fname;
- std::ifstream f;
- int lineno = 0;
-
- // Try appending the default conf path if the fname doesn't exist.
- if (0 != access(filename.c_str(), R_OK)) {
- filename = DEFAULT_CONF_PATH;
- filename += fname;
- }
-
- f.open(filename.c_str(), std::ios::in);
- if (!f.is_open()) {
- TSError("header_rewrite: unable to open %s", filename.c_str());
- return false;
- }
-
- TSDebug(PLUGIN_NAME, "Loading header_rewrite config from %s", filename.c_str());
-
- while (!f.eof()) {
- std::string line;
-
- getline(f, line);
- ++lineno; // ToDo: we should probably use this for error messages ...
-
- boost::trim(line);
- if (line.empty() || (line[0] == '#'))
- continue;
-
- Parser p(line); // Tokenize and parse this line
- if (p.empty())
- continue;
-
- // If we are at the beginning of a new condition, save away the previous rule (but only if it has operators).
- if (p.is_cond() && add_rule(rule))
- rule = NULL;
-
- if (NULL == rule) {
- rule = new RuleSet();
- rule->set_hook(default_hook);
-
- // Special case for specifying the HOOK this rule applies to.
- // These can only be at the beginning of a rule, and have an implicit [AND].
- if (p.cond_op_is("READ_RESPONSE_HDR_HOOK")) {
- rule->set_hook(TS_HTTP_READ_RESPONSE_HDR_HOOK);
- continue;
- } else if (p.cond_op_is("READ_REQUEST_HDR_HOOK")) {
- rule->set_hook(TS_HTTP_READ_REQUEST_HDR_HOOK);
- continue;
- } else if (p.cond_op_is("READ_REQUEST_PRE_REMAP_HOOK")) {
- rule->set_hook(TS_HTTP_READ_REQUEST_PRE_REMAP_HOOK);
- continue;
- } else if (p.cond_op_is("SEND_REQUEST_HDR_HOOK")) {
- rule->set_hook(TS_HTTP_SEND_REQUEST_HDR_HOOK);
- continue;
- } else if (p.cond_op_is("SEND_RESPONSE_HDR_HOOK")) {
- rule->set_hook(TS_HTTP_SEND_RESPONSE_HDR_HOOK);
- continue;
- }
- }
-
- if (p.is_cond()) {
- rule->add_condition(p);
- } else {
- rule->add_operator(p);
- }
- }
-
- // Add the last rule (possibly the only rule)
- add_rule(rule);
-
- // Collect all resource IDs that we need
- for (int i=TS_HTTP_READ_REQUEST_HDR_HOOK; i<TS_HTTP_LAST_HOOK; ++i)
- if (all_rules[i])
- all_resids[i] = all_rules[i]->get_all_resource_ids();
-
- return true;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Continuation
-//
-static int
-cont_rewrite_headers(TSCont contp, TSEvent event, void *edata)
-{
- TSDebug(PLUGIN_NAME, "plugin: %d", event);
-
- TSHttpTxn txnp = (TSHttpTxn) edata;
- Resources res(txnp, contp);
- const RuleSet* rule = NULL;
- TSHttpHookID hook = TS_HTTP_LAST_HOOK;
-
- // Get the resources necessary to process this event
- switch (event) {
- case TS_EVENT_HTTP_READ_RESPONSE_HDR:
- hook = TS_HTTP_READ_RESPONSE_HDR_HOOK;
- break;
- case TS_EVENT_HTTP_READ_REQUEST_HDR:
- hook = TS_HTTP_READ_REQUEST_HDR_HOOK;
- break;
- case TS_EVENT_HTTP_READ_REQUEST_PRE_REMAP:
- hook = TS_HTTP_READ_REQUEST_PRE_REMAP_HOOK;
- break;
- case TS_EVENT_HTTP_SEND_REQUEST_HDR:
- hook = TS_HTTP_SEND_REQUEST_HDR_HOOK;
- break;
- case TS_EVENT_HTTP_SEND_RESPONSE_HDR:
- hook = TS_HTTP_SEND_RESPONSE_HDR_HOOK;
- break;
- default:
- TSError("header_rewrite: unknown event for this plugin");
- TSDebug(PLUGIN_NAME, "unknown event for this plugin");
- break;
- }
-
- if (hook != TS_HTTP_LAST_HOOK) {
- res.gather(all_resids[hook], hook);
- rule = all_rules[hook];
-
- // Evaluation
- while (rule) {
- if (rule->eval(res)) {
- OperModifiers rt = rule->exec(res);
-
- if (rule->last() || (rt & OPER_LAST)) {
- break; // Conditional break, force a break with [L]
- }
- }
- rule = rule->next;
- }
- }
-
- TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
- return 0;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Initialize the InkAPI plugin for the global hooks we support.
-//
-void
-TSPluginInit(int argc, const char *argv[])
-{
- TSPluginRegistrationInfo info;
-
- info.plugin_name = (char*)PLUGIN_NAME;
- info.vendor_name = (char*)"";
- info.support_email = (char*)"";
-
- if (TS_SUCCESS != TSPluginRegister(TS_SDK_VERSION_3_0 , &info)) {
- TSError("header_rewrite: plugin registration failed.\n");
- }
-
- if (argc != 2) {
- TSError("usage: %s <config-file>\n", argv[0] );
- }
-
- // Initialize the globals
- for (int i=TS_HTTP_READ_REQUEST_HDR_HOOK; i<TS_HTTP_LAST_HOOK; ++i) {
- all_rules[i] = NULL;
- all_resids[i] = RSRC_NONE;
- }
-
- // Parse the config file
- if (parse_config(argv[1], TS_HTTP_READ_RESPONSE_HDR_HOOK)) {
- for (int i=TS_HTTP_READ_REQUEST_HDR_HOOK; i<TS_HTTP_LAST_HOOK; ++i) {
- if (all_rules[i]) {
- TSDebug(PLUGIN_NAME, "adding hook: %d", i);
- TSHttpHookAdd(static_cast<TSHttpHookID>(i), TSContCreate(cont_rewrite_headers, NULL));
- }
- }
- } else {
- TSError("header_rewrite: failed to parse configuration file");
- }
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Initialize the plugin as a remap plugin.
-//
-TSReturnCode
-TSRemapInit(TSRemapInterface *api_info, char *errbuf, int errbuf_size)
-{
- if (!api_info) {
- strncpy(errbuf, "[TSRemapInit] - Invalid TSRemapInterface argument", errbuf_size - 1);
- return TS_ERROR;
- }
-
- if (api_info->size < sizeof(TSRemapInterface)) {
- strncpy(errbuf, "[TSRemapInit] - Incorrect size of TSRemapInterface structure", errbuf_size - 1);
- return TS_ERROR;
- }
-
- if (api_info->tsremap_version < TSREMAP_VERSION) {
- snprintf(errbuf, errbuf_size - 1, "[TSRemapInit] - Incorrect API version %ld.%ld",
- api_info->tsremap_version >> 16, (api_info->tsremap_version & 0xffff));
- return TS_ERROR;
- }
-
- TSDebug(PLUGIN_NAME, "remap plugin is succesfully initialized");
- return TS_SUCCESS;
-}
-
-
-TSReturnCode
-TSRemapNewInstance(int argc, char *argv[], void **ih, char *errbuf, int errbuf_size)
-{
- TSDebug(PLUGIN_NAME, "initializing the remap plugin header_rewrite");
-
- if (argc < 3) {
- TSError("Unable to create remap instance, need config file");
- return TS_ERROR;
- }
-
- // TODO: this is a big ugly, we use a pseudo hook for parsing the config for a
- // remap instantiation.
- all_rules[TS_REMAP_PSEUDO_HOOK] = NULL;
- if (!parse_config(argv[2], TS_REMAP_PSEUDO_HOOK)) {
- TSError("Unable to create remap instance");
- return TS_ERROR;
- }
-
- *ih = all_rules[TS_REMAP_PSEUDO_HOOK];
- all_rules[TS_REMAP_PSEUDO_HOOK] = NULL;
-
- TSDebug(PLUGIN_NAME, "successfully initialize the header_rewrite plugin");
- return TS_SUCCESS;
-}
-
-void
-TSRemapDeleteInstance(void *ih)
-{
- RuleSet* rule = static_cast<RuleSet*>(ih);
-
- delete rule;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-// This is the main "entry" point for the plugin, called for every request.
-//
-TSRemapStatus
-TSRemapDoRemap(void *ih, TSHttpTxn rh, TSRemapRequestInfo *rri)
-{
- TSRemapStatus rval = TSREMAP_NO_REMAP;
-
- if (NULL == ih) {
- TSDebug(PLUGIN_NAME, "No Rules configured, falling back to default");
- return rval;
- } else {
- RuleSet* rule = (RuleSet*)ih;
- Resources res((TSHttpTxn)rh, rri);
-
- // TODO: This might be suboptimal, do we always need the client request
- // headers in a remap plugin?
- res.gather(RSRC_CLIENT_REQUEST_HEADERS, TS_REMAP_PSEUDO_HOOK);
-
- // Evaluation
- while (rule) {
- if (rule->eval(res)) {
- OperModifiers rt = rule->exec(res);
- if (res.changed_url == true)
- rval = TSREMAP_DID_REMAP;
-
- if (rule->last() || (rt & OPER_LAST)) {
- break; // Conditional break, force a break with [L]
- }
- }
- rule = rule->next;
- }
-
- }
-
- return rval;
-}
-
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/header_rewrite/header_rewrite.config
----------------------------------------------------------------------
diff --git a/header_rewrite/header_rewrite.config b/header_rewrite/header_rewrite.config
deleted file mode 100644
index 8be269a..0000000
--- a/header_rewrite/header_rewrite.config
+++ /dev/null
@@ -1,77 +0,0 @@
-Operators
----------
-rm-header Header matcher
-add-header Header value
-set-header Header value
-
-set-status value
-set-status-reason value
-
-
-Conditions
------------
-%{TRUE} # Default condition if none specified
-%{FALSE}
-%{HEADER:string}
-%{YCOOKIE:id}
-%{METHOD}
-%{PROTOCOL}
-%{PORT}
-%{HOST}
-%{TOHOST}
-%{FROMHOST}
-%{PATH}
-%{PARAMS}
-%{QUERY}
-%{STATUS}
-
-# These can only be used as the first condition of a new ruleset,
-# and have no run-time evaluation effects (only config parse time).
-%{READ_RESPONSE_HDR_HOOK} # Default
-%{READ_REQUEST_HDR_HOOK}
-
-
-Operator Flags
---------------
-L # Last rule (stop evaluations)
-
-
-Cond Flags
-----------
-NC # Not case sensitive condition (when applicable)
-NOT # Negate the cond
-OR # Local OR between conds
-AND # Logical AND betwen conds
-
-
-Matcher
---------
-
-/string/ # regular expression
-<string # lexically lower
->string # lexically greater
-=string # lexically equal
-
-(The absense of a "matcher" means value exists).
-
-
-Values
-------
-
-Any of the cond definitions, that extracts a value from the request
-$N 0 <= N <= 9, as grouped in a regular expression
-string (which can contain the above)
-null
-
-
-Examples
---------
-
-cond %{HEADER:X-Y-Foobar}
-cond %{METHOD} =GET [OR]
-cond %{METHOD} =POST
-set-header X-Y-Fiefum %{HEADER:X-Y-Foobar}
-rm-header X-Y-Foobar
-rm-header Set-Cookie
-
-cond %{HEADER:X-Y-Foobar} "Some string" [AND,NC]
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/header_rewrite/lulu.h
----------------------------------------------------------------------
diff --git a/header_rewrite/lulu.h b/header_rewrite/lulu.h
deleted file mode 100644
index 7452e49..0000000
--- a/header_rewrite/lulu.h
+++ /dev/null
@@ -1,42 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////////////////////
-//
-// Implement the classes for the various types of hash keys we support.
-//
-#ifndef __LULU_H__
-#define __LULU_H__ 1
-
-// Define UNUSED properly.
-#if ((__GNUC__ >= 3) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 7)))
-#define UNUSED __attribute__ ((unused))
-#else
-#define UNUSED
-#endif /* #if ((__GNUC__ >= 3) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 7))) */
-
-static char UNUSED rcsId__lulu_h[] = "@(#) $Id$ built on " __DATE__ " " __TIME__;
-
-#include <sys/types.h>
-
-// Memory barriers on i386 / linux / gcc
-#if defined(__i386__)
-#define mb() __asm__ __volatile__ ( "lock; addl $0,0(%%esp)" : : : "memory" )
-#define rmb() __asm__ __volatile__ ( "lock; addl $0,0(%%esp)" : : : "memory" )
-#define wmb() __asm__ __volatile__ ( "" : : : "memory")
-#elif defined(__x86_64__)
-#define mb() __asm__ __volatile__ ( "mfence" : : : "memory")
-#define rmb() __asm__ __volatile__ ( "lfence" : : : "memory")
-#define wmb() __asm__ __volatile__ ( "" : : : "memory")
-#else
-#error "Define barriers"
-#endif
-
-static const char* PLUGIN_NAME UNUSED = "header_rewrite";
-static const char* PLUGIN_NAME_DBG UNUSED = "header_rewrite_dbg";
-
-
-// From google styleguide: http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
-#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
- TypeName(const TypeName&); \
- void operator=(const TypeName&)
-
-
-#endif // __LULU_H__
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/header_rewrite/matcher.cc
----------------------------------------------------------------------
diff --git a/header_rewrite/matcher.cc b/header_rewrite/matcher.cc
deleted file mode 100644
index b520ab7..0000000
--- a/header_rewrite/matcher.cc
+++ /dev/null
@@ -1,12 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////////////////////
-// matcher.cc: Implementation of the condition classes
-//
-//
-
-#define UNUSED __attribute__ ((unused))
-static char UNUSED rcsId__matcher_cc[] = "@(#) $Id$ built on " __DATE__ " " __TIME__;
-
-#include <string>
-#include <ts/ts.h>
-
-#include "matcher.h"