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/13 22:18:14 UTC

[4/11] Moved these plugins from the separate git repo

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/bc13c5e0/plugins/experimental/esi/lib/HttpHeader.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/esi/lib/HttpHeader.h b/plugins/experimental/esi/lib/HttpHeader.h
new file mode 100644
index 0000000..bdef5ce
--- /dev/null
+++ b/plugins/experimental/esi/lib/HttpHeader.h
@@ -0,0 +1,45 @@
+/** @file
+
+  A brief file description
+
+  @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.
+ */
+
+#ifndef _ESI_HTTP_HEADER_H
+
+#define _ESI_HTTP_HEADER_H
+
+#include <list>
+
+namespace EsiLib {
+
+struct HttpHeader {
+  const char *name;
+  int name_len;
+  const char *value;
+  int value_len;
+  HttpHeader(const char *n = 0, int n_len = -1, const char *v = 0, int v_len = -1) 
+    : name(n), name_len(n_len), value(v), value_len(v_len) { };
+};
+
+typedef std::list<HttpHeader> HttpHeaderList;
+
+};
+
+#endif // _ESI_HTTP_HEADER_H

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/bc13c5e0/plugins/experimental/esi/lib/IncludeHandlerFactory.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/esi/lib/IncludeHandlerFactory.h b/plugins/experimental/esi/lib/IncludeHandlerFactory.h
new file mode 100644
index 0000000..2845d49
--- /dev/null
+++ b/plugins/experimental/esi/lib/IncludeHandlerFactory.h
@@ -0,0 +1,54 @@
+/** @file
+
+  A brief file description
+
+  @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.
+ */
+
+#ifndef _INCLUDE_HANDLER_FACTORY_H
+
+#define _INCLUDE_HANDLER_FACTORY_H
+
+#include <string>
+#include "SpecialIncludeHandler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EsiLib::SpecialIncludeHandler *createSpecialIncludeHandler(EsiLib::Variables &esi_vars,
+                                                           EsiLib::Expression &esi_expr,
+                                                           HttpDataFetcher &fetcher,
+                                                           const std::string &id);
+  
+#ifdef __cplusplus
+}
+#endif
+
+namespace EsiLib {
+
+typedef SpecialIncludeHandler *(*SpecialIncludeHandlerCreator)(Variables &esi_vars,
+                                                               Expression &esi_expr,
+                                                               HttpDataFetcher &fetcher,
+                                                               const std::string &id);
+
+};
+
+#endif
+

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/bc13c5e0/plugins/experimental/esi/lib/SpecialIncludeHandler.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/esi/lib/SpecialIncludeHandler.h b/plugins/experimental/esi/lib/SpecialIncludeHandler.h
new file mode 100644
index 0000000..d062d5f
--- /dev/null
+++ b/plugins/experimental/esi/lib/SpecialIncludeHandler.h
@@ -0,0 +1,72 @@
+/** @file
+
+  A brief file description
+
+  @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.
+ */
+
+#ifndef _ESI_SPECIAL_INCLUDE_HANDLER
+
+#define _ESI_SPECIAL_INCLUDE_HANDLER
+
+#include "HttpDataFetcher.h"
+#include "Variables.h"
+#include "Expression.h"
+
+namespace EsiLib {
+
+class SpecialIncludeHandler {
+
+public:
+
+  SpecialIncludeHandler(Variables &esi_vars,
+                        Expression &esi_expr, HttpDataFetcher &http_fetcher)
+    : _esi_vars(esi_vars), _esi_expr(esi_expr), _http_fetcher(http_fetcher) {
+  }
+
+  virtual int handleInclude(const char *data, int data_len) = 0;
+
+  virtual void handleParseComplete() = 0;
+
+  /** trivial implementation */
+  virtual DataStatus getIncludeStatus(int include_id) {
+    const char *data;
+    int data_len;
+    return getData(include_id, data, data_len) ? STATUS_DATA_AVAILABLE : STATUS_ERROR;
+  }
+
+  virtual bool getData(int include_id, const char *&data, int &data_len) = 0;
+
+  virtual void getFooter(const char *&footer, int &footer_len) {
+    footer_len = 0;
+  }
+
+  virtual ~SpecialIncludeHandler() { };
+
+protected:
+
+  Variables &_esi_vars;
+  Expression &_esi_expr;
+  HttpDataFetcher &_http_fetcher;
+
+};
+
+};
+
+#endif

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/bc13c5e0/plugins/experimental/esi/lib/Stats.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/esi/lib/Stats.cc b/plugins/experimental/esi/lib/Stats.cc
new file mode 100644
index 0000000..9f265f3
--- /dev/null
+++ b/plugins/experimental/esi/lib/Stats.cc
@@ -0,0 +1,69 @@
+/** @file
+
+  A brief file description
+
+  @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 "Stats.h"
+
+using namespace EsiLib;
+
+namespace EsiLib {
+namespace Stats {
+const char *STAT_NAMES[Stats::MAX_STAT_ENUM] = {
+  "esi.n_os_docs",
+  "esi.n_cache_docs",
+  "esi.n_parse_errs",
+  "esi.n_includes",
+  "esi.n_include_errs",
+  "esi.n_spcl_includes",
+  "esi.n_spcl_include_errs"
+};
+
+int g_stat_indices[Stats::MAX_STAT_ENUM];
+StatSystem *g_system = 0;
+
+void init(StatSystem *system) {
+  g_system = system;
+  if (g_system) {
+    for (int i = 0; i < Stats::MAX_STAT_ENUM; ++i) {
+//FIXME doesn't return avalue.
+g_system->create(i);
+/*      if (!g_system->create(i)) {
+        Utils::ERROR_LOG("[%s] Unable to create stat [%s]", __FUNCTION__, Stats::STAT_NAMES[i]);
+      }*/
+    }
+  }
+}
+
+//FIXME step should be TSMgmtInt but for some reason the linker is having some strange int vs long name mangling issue.
+void increment(Stats::STAT st, int step/* = 1 */) {
+  if (g_system) {
+//FIXME doesn't return avalue.
+g_system->increment(st, step);
+/*
+    if (!g_system->increment(st, step)) {
+      Utils::ERROR_LOG("[%s] Unable to increment stat [%s] by step [%d]", __FUNCTION__, step,
+                       Stats::STAT_NAMES[st]);
+    }
+*/
+  }
+}
+}}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/bc13c5e0/plugins/experimental/esi/lib/Stats.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/esi/lib/Stats.h b/plugins/experimental/esi/lib/Stats.h
new file mode 100644
index 0000000..d2036bc
--- /dev/null
+++ b/plugins/experimental/esi/lib/Stats.h
@@ -0,0 +1,66 @@
+/** @file
+
+  A brief file description
+
+  @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.
+ */
+
+#ifndef _ESI_STATS_H
+
+#define _ESI_STATS_H
+
+#include "Utils.h"
+#include <ts/ts.h>
+
+namespace EsiLib {
+
+/** interface that stat systems should implement */
+class StatSystem {
+public:
+  virtual void create(int handle) = 0;
+//FIXME step should be TSMgmtInt
+  virtual void increment(int handle, int step = 1) = 0;
+  virtual ~StatSystem() { };
+};
+
+namespace Stats {
+
+enum STAT { N_OS_DOCS = 0,
+            N_CACHE_DOCS = 1,
+            N_PARSE_ERRS = 2,
+            N_INCLUDES = 3,
+            N_INCLUDE_ERRS = 4,
+            N_SPCL_INCLUDES = 5,
+            N_SPCL_INCLUDE_ERRS = 6,
+            MAX_STAT_ENUM = 7 };
+
+extern const char *STAT_NAMES[MAX_STAT_ENUM];
+extern int g_stat_indices[Stats::MAX_STAT_ENUM];
+extern StatSystem *g_system;
+
+void init(StatSystem *system);
+
+void increment(STAT st, int step = 1);
+
+};
+
+};
+              
+
+#endif

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/bc13c5e0/plugins/experimental/esi/lib/StringHash.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/esi/lib/StringHash.h b/plugins/experimental/esi/lib/StringHash.h
new file mode 100644
index 0000000..6739cef
--- /dev/null
+++ b/plugins/experimental/esi/lib/StringHash.h
@@ -0,0 +1,47 @@
+/** @file
+
+  A brief file description
+
+  @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.
+ */
+
+#ifndef _STRING_HASH_H
+
+#define _STRING_HASH_H
+
+#include <string>
+#include <ext/hash_map>
+
+namespace EsiLib {
+
+struct StringHasher {
+  inline size_t operator ()(const std::string &str) const {
+    return __gnu_cxx::hash<const char *>()(str.c_str());
+  };
+};
+
+typedef __gnu_cxx::hash_map<std::string, std::string, StringHasher> StringHash;
+
+template<typename T>
+class StringKeyHash : public __gnu_cxx::hash_map<std::string, T, StringHasher> {
+};
+
+};
+
+#endif // _STRING_HASH_H

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/bc13c5e0/plugins/experimental/esi/lib/Utils.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/esi/lib/Utils.cc b/plugins/experimental/esi/lib/Utils.cc
new file mode 100644
index 0000000..047fbe6
--- /dev/null
+++ b/plugins/experimental/esi/lib/Utils.cc
@@ -0,0 +1,195 @@
+/** @file
+
+  A brief file description
+
+  @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 "Utils.h"
+
+#include <sstream>
+
+using namespace EsiLib;
+
+ComponentBase::Debug Utils::DEBUG_LOG(0);
+ComponentBase::Error Utils::ERROR_LOG(0);
+
+#define DEBUG_TAG "EsiUtils"
+
+using std::string;
+
+void
+Utils::init(ComponentBase::Debug debug_func, ComponentBase::Error error_func) {
+  DEBUG_LOG = debug_func;
+  ERROR_LOG = error_func;
+}
+
+bool
+Utils::getAttribute(const string &data, const string &attr, size_t curr_pos, size_t end_pos,
+                    Attribute &attr_info,
+                    size_t *term_pos /* = 0 */, char terminator /* = 0 */) {
+  size_t attr_start = data.find(attr, curr_pos);
+  if (attr_start >= end_pos) {
+    ERROR_LOG("[%s] Tag has no [%.*s] attribute", __FUNCTION__, attr.size(), attr.data());
+    return false;
+  }
+  curr_pos = attr_start + attr.size();
+  bool equals_found = false;
+  for (; curr_pos < end_pos; ++curr_pos) {
+    if (data[curr_pos] == ' ') {
+      continue;
+    } else {
+      if (data[curr_pos] == '=') {
+        equals_found = true;
+      }
+      break;
+    }
+  }
+  if (!equals_found) {
+    ERROR_LOG("[%s] Attribute [%.*s] has no value", __FUNCTION__, attr.size(), attr.data());
+    return false;
+  }
+  ++curr_pos;
+  if (curr_pos == end_pos) {
+    ERROR_LOG("[%s] No space for value after [%.*s] attribute", __FUNCTION__, attr.size(), attr.data());
+    return false;
+  }
+  bool in_quoted_part = false;
+  bool quoted = false;
+  size_t i;
+  for (i = curr_pos; i < end_pos; ++i) {
+    if (data[i] == '"') {
+      quoted = true;
+      in_quoted_part = !in_quoted_part;
+    }
+    else if (data[i] == ' ') {
+      if (!in_quoted_part) {
+        break;
+      }
+    } else if (terminator && !in_quoted_part && (data[i] == terminator)) {
+      break;
+    }
+  }
+  const char *data_start_ptr = data.data();
+  if (in_quoted_part) {
+    ERROR_LOG("[%s] Unterminated quote in value for attribute [%.*s] starting at [%.10s]",
+              __FUNCTION__, attr.size(), attr.data(), data_start_ptr + curr_pos);
+    return false;
+  }
+  if (terminator && term_pos) {
+    *term_pos = data.find(terminator, i);
+    if (*term_pos >= end_pos) {
+      ERROR_LOG("[%s] Unterminated attribute [%.*s]", __FUNCTION__, attr.size(), attr.data());
+      return false;
+    }
+  }
+  attr_info.name = data_start_ptr + attr_start;
+  attr_info.name_len = attr.size();
+  attr_info.value = data_start_ptr + curr_pos;
+  attr_info.value_len = i - curr_pos;
+  if (quoted) {
+    ++attr_info.value;
+    attr_info.value_len -= 2;
+  }
+  return true;
+}
+
+void
+Utils::parseKeyValueConfig(const std::list<string> &lines, KeyValueMap &kvMap) {
+  string key, value;
+  std::istringstream iss;
+  for (std::list<string>::const_iterator list_iter = lines.begin(); list_iter != lines.end(); ++list_iter) {
+    const string &conf_line = *list_iter; // handy reference
+    if (!conf_line.size() || (conf_line[0] == '#')) {
+      continue;
+    }
+    iss.clear();
+    iss.str(conf_line);
+    if (iss.good()) {
+      iss >> key;
+      iss >> value;
+      if (key.size() && value.size()) {
+        kvMap.insert(KeyValueMap::value_type(key, value));
+        DEBUG_LOG(DEBUG_TAG, "[%s] Read value [%s] for key [%s]", __FUNCTION__, value.c_str(), key.c_str());
+      }
+    }
+    key.clear();
+    value.clear();
+  }
+}
+
+void
+Utils::parseAttributes(const char *data, int data_len, AttributeList &attr_list,
+                       const char *pair_separators /* = " " */) {
+  attr_list.clear();
+  if (!data || (data_len <= 0)) {
+    return;
+  }
+  char separator_lookup[256] = { 0 };
+  int i;
+  for (i = 0; pair_separators[i]; ++i) {
+    separator_lookup[static_cast<unsigned int>(pair_separators[i])] = 1;
+  }
+  Attribute attr;
+  bool inside_quotes = false, end_of_attribute;
+  bool escape_on = false;
+  for (i = 0; (i < data_len) && ((isspace(data[i]) || separator_lookup[static_cast<unsigned int>(data[i])]));
+       ++i);
+  attr.name = data + i;
+  attr.value = 0;
+  for (; i <= data_len; ++i) {
+    end_of_attribute = false;
+    if (i == data_len) {
+      end_of_attribute = true;
+    } else if (separator_lookup[static_cast<unsigned int>(data[i])] && !inside_quotes) {
+      end_of_attribute = true;
+    } // else ignore separator when in quotes
+    if (end_of_attribute) {
+      if (!inside_quotes) {
+        if (attr.value > attr.name) {
+          attr.value_len = data + i - attr.value;
+          trimWhiteSpace(attr.name, attr.name_len);
+          trimWhiteSpace(attr.value, attr.value_len);
+          if (attr.value[0] == '"') {
+            ++attr.value;
+            attr.value_len -= 2;
+          }
+          if (attr.name_len && attr.value_len) {
+            DEBUG_LOG(DEBUG_TAG, "[%s] Added attribute with name [%.*s] and value [%.*s]",
+                      __FUNCTION__, attr.name_len, attr.name, attr.value_len, attr.value);
+            attr_list.push_back(attr);
+          } // else ignore empty name/value
+        } // else ignore attribute with no value
+      } // else ignore variable with unterminated quotes
+      for(; (i < data_len) && ((isspace(data[i]) || separator_lookup[static_cast<unsigned int>(data[i])]));
+          ++i);
+      attr.name = data + i;
+      attr.value = 0;
+      inside_quotes = false;
+    } else if (data[i] == '"') {
+      if (!escape_on) { 
+        inside_quotes = !inside_quotes;
+      }
+    } else if ((data[i] == '=') && !attr.value && !inside_quotes) {
+      attr.value = data + i + 1;
+      attr.name_len = data + i - attr.name;
+    }
+    escape_on = (data[i] == '\\') ? true : false;
+  }
+}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/bc13c5e0/plugins/experimental/esi/lib/Utils.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/esi/lib/Utils.h b/plugins/experimental/esi/lib/Utils.h
new file mode 100644
index 0000000..6308e7c
--- /dev/null
+++ b/plugins/experimental/esi/lib/Utils.h
@@ -0,0 +1,118 @@
+/** @file
+
+  A brief file description
+
+  @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.
+ */
+
+#ifndef _ESI_UTILS_H 
+
+#define _ESI_UTILS_H
+
+#include "DocNode.h"
+#include "ComponentBase.h"
+
+#include <cstring>
+#include <string>
+#include <map>
+#include <list>
+#include <ctype.h>
+
+namespace EsiLib {
+
+namespace Utils {
+
+  extern ComponentBase::Debug DEBUG_LOG;
+
+  extern ComponentBase::Error ERROR_LOG;
+
+  void init(ComponentBase::Debug debug_func, ComponentBase::Error error_func);
+
+  // looks for the given attribute in given data; a terminator can
+  // also be specified apart from the end_pos; attr_info will point
+  // to data inside data string
+  bool getAttribute(const std::string &data, const std::string &attr, size_t curr_pos, size_t end_pos,
+                    Attribute &attr_info, size_t *term_pos = 0, char terminator = 0);
+  
+  // less specialized version of method above
+  inline bool getAttribute(const std::string &data, const char *attr, Attribute &attr_info) {
+    return getAttribute(data, std::string(attr), 0, data.size(), attr_info);
+  }
+
+  // trims leading and trailing white space; input arguments
+  // will be modified to reflect trimmed data
+  inline void trimWhiteSpace(const char *&data, int &data_len) {
+    if (!data) {
+      data_len = 0;
+    } else {
+      if (data_len == -1) {
+        data_len = strlen(data);
+      }
+      int i, j;
+      for (i = 0; ((i < data_len) && isspace(data[i])); ++i);
+      for (j = (data_len - 1); ((j > i) && isspace(data[j])); --j);
+      data += i;
+      data_len = j - i + 1;
+    }
+  }
+
+  // does case insensitive comparison
+  inline bool areEqual(const char *str1, int str1_len, const char *str2, int str2_len) {
+    if (str1_len == str2_len) {
+      return (strncasecmp(str1, str2, str1_len) == 0);
+    }
+    return false;
+  }
+
+  inline bool areEqual(const char *str1, int str1_len, const std::string &str2) {
+    return areEqual(str1, str1_len, str2.data(), static_cast<int>(str2.size()));
+  }
+
+  // parses a string of name=value attributes separated by any character in pair_separators;
+  void parseAttributes(const char *data, int data_len, AttributeList &attr_list,
+                       const char *pair_separators = " ");
+
+  inline void parseAttributes(const std::string &data, AttributeList &attr_list,
+                              const char *pair_separators = " ") {
+    parseAttributes(data.data(), data.size(), attr_list, pair_separators);
+  }
+
+  typedef std::map<std::string, std::string> KeyValueMap;
+
+  // parses given lines (assumes <key><whitespace><value> format) and
+  // stores them in supplied map; Lines beginning with '#' are ignored
+  void parseKeyValueConfig(const std::list<std::string> &lines, KeyValueMap &kvMap);
+  
+  inline std::string unescape(const char *str, int len = -1) {
+    std::string retval("");
+    if (str) { 
+      for (int i = 0; (((len == -1) && (str[i] != '\0')) || (i < len)); ++i) {
+        if (str[i] != '\\') {
+          retval += str[i];
+        }
+      }
+    }
+    return retval;
+  }
+
+};
+
+};
+
+#endif

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/bc13c5e0/plugins/experimental/esi/lib/Variables.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/esi/lib/Variables.cc b/plugins/experimental/esi/lib/Variables.cc
new file mode 100644
index 0000000..d753172
--- /dev/null
+++ b/plugins/experimental/esi/lib/Variables.cc
@@ -0,0 +1,427 @@
+/** @file
+
+  A brief file description
+
+  @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 "Variables.h"
+#include "Attribute.h"
+#include "Utils.h"
+
+#include <errno.h>
+
+using std::list;
+using std::pair;
+using std::string;
+using namespace EsiLib;
+
+const string Variables::EMPTY_STRING("");
+const string Variables::TRUE_STRING("true");
+const string Variables::VENDOR_STRING("vendor");
+const string Variables::VERSION_STRING("version");
+const string Variables::PLATFORM_STRING("platform");
+const string Variables::SIMPLE_HEADERS[] = { string("HOST"),
+                                             string("REFERER"),
+                                             string("") };
+
+const string Variables::SPECIAL_HEADERS[] = { string("ACCEPT-LANGUAGE"),
+                                              string("COOKIE"),
+                                              string("USER-AGENT"),
+                                              string("QUERY_STRING"),
+                                              string("") };
+
+const string Variables::NORM_SIMPLE_HEADERS[] = { string("HTTP_HOST"),
+                                                  string("HTTP_REFERER"),
+                                                  string("") };
+
+const string Variables::NORM_SPECIAL_HEADERS[] = { string("HTTP_ACCEPT_LANGUAGE"),
+                                                   string("HTTP_COOKIE"),
+                                                   string("HTTP_USER_AGENT"),
+                                                   string("QUERY_STRING"),
+                                                   string("") };
+
+inline string &
+Variables::_toUpperCase(string &str) const {
+  for (size_t i = 0; i < str.size(); ++i) {
+    if ((str[i] >= 'a') && (str[i] <= 'z')) {
+      str[i] = 'A' + (str[i] - 'a');
+    }
+  }
+  return str;
+}
+
+inline int 
+Variables::_searchHeaders(const string headers[], const char *name, int name_len) const {
+  int curr_header_size;
+  for (int i = 0; (curr_header_size = static_cast<int>(headers[i].size())); ++i) {
+    if ((name_len == curr_header_size) && 
+        (strncasecmp(headers[i].data(), name, curr_header_size) == 0)) {
+      return i;
+    }
+  }
+  return -1;
+}
+
+inline void
+Variables::_insert(StringHash &hash, const std::string &key, const std::string &value) {
+  std::pair<StringHash::iterator, bool> result = hash.insert(StringHash::value_type(key, value));
+  if (!result.second) {
+    result.first->second = value;
+  }
+}
+
+void
+Variables::populate(const HttpHeader &header) {
+  if (header.name && header.name_len && header.value && header.value_len) {
+
+    // doing this because we can't change our const input arg
+    int name_len = (header.name_len == -1) ? strlen(header.name) : header.name_len;
+    int value_len = (header.value_len == -1) ? strlen(header.value) : header.value_len;
+
+    // we need to save the cookie string to build the jar from
+    if ((name_len == 6) && (strncasecmp(header.name, "Cookie", 6) == 0)) {
+      _releaseCookieJar();
+      if (_cookie_str.size()) {
+        _cookie_str.append(", ");
+      }
+      _cookie_str.append(header.value, value_len);
+    }
+
+    if (_headers_parsed) {
+      _parseHeader(header.name, name_len, header.value, value_len);
+    } else {
+      int match_index = _searchHeaders(SIMPLE_HEADERS, header.name, name_len);
+      if (match_index != -1) {
+        _cached_simple_headers[match_index].push_back(string(header.value, value_len));
+      } else {
+        match_index = _searchHeaders(SPECIAL_HEADERS, header.name, name_len);
+        if (match_index != -1) {
+          _cached_special_headers[match_index].push_back(string(header.value, value_len));
+        } else {
+          _debugLog(_debug_tag.c_str(), "[%s] Not retaining header [%.*s]", __FUNCTION__, name_len,
+                    header.name);
+        }
+      }
+    }
+  }
+}
+
+inline void
+Variables::_parseSimpleHeader(SimpleHeader hdr, const string &value) {
+  _debugLog(_debug_tag.c_str(), "[%s] Inserting value for simple header [%s]",
+            __FUNCTION__, SIMPLE_HEADERS[hdr].c_str());
+  _simple_data[NORM_SIMPLE_HEADERS[hdr]] = value;
+}
+
+inline void
+Variables::_parseSimpleHeader(SimpleHeader hdr, const char *value, int value_len) {
+  _parseSimpleHeader(hdr, string(value, value_len));
+}
+
+void
+Variables::_parseSpecialHeader(SpecialHeader hdr, const char *value, int value_len) {
+  switch (hdr) {
+  case HTTP_ACCEPT_LANGUAGE:
+    _parseAcceptLangString(value, value_len);
+    break;
+  case HTTP_COOKIE:
+    _parseCookieString(value, value_len);
+    break;
+  case HTTP_USER_AGENT:
+    _parseUserAgentString(value, value_len);
+    break;
+  default:
+    _debugLog(_debug_tag.c_str(), "[%s] Skipping unrecognized header", __FUNCTION__);
+    break;
+  }
+}
+
+void
+Variables::_parseHeader(const char *name, int name_len, const char *value, int value_len) {
+  int match_index = _searchHeaders(SIMPLE_HEADERS, name, name_len);
+  if (match_index != -1) {
+    _parseSimpleHeader(static_cast<SimpleHeader>(match_index), value, value_len);
+  } else {
+    match_index = _searchHeaders(SPECIAL_HEADERS, name, name_len);
+    if (match_index != -1) {
+      _parseSpecialHeader(static_cast<SpecialHeader>(match_index), value, value_len);
+    } else {
+      _debugLog(_debug_tag.c_str(), "[%s] Unrecognized header [%.*s]", __FUNCTION__, value_len, value);
+    }
+  }
+}
+
+void
+Variables::_parseQueryString(const char *query_string, int query_string_len) {
+  _insert(_simple_data, string("QUERY_STRING"), string(query_string, query_string_len));
+  AttributeList attr_list;
+  Utils::parseAttributes(query_string, query_string_len, attr_list, "&");
+  for (AttributeList::iterator iter = attr_list.begin(); iter != attr_list.end(); ++iter) {
+    _debugLog(_debug_tag.c_str(), "[%s] Inserting query string variable [%.*s] with value [%.*s]",
+              __FUNCTION__, iter->name_len, iter->name, iter->value_len, iter->value);
+    _insert(_dict_data[QUERY_STRING], string(iter->name, iter->name_len),
+            string(iter->value, iter->value_len));
+  }
+}
+
+void
+Variables::_parseCachedHeaders() {
+  _debugLog(_debug_tag.c_str(), "[%s] Parsing headers", __FUNCTION__);
+  for (int i = 0; i < N_SIMPLE_HEADERS; ++i) {
+    for (HeaderValueList::iterator value_iter = _cached_simple_headers[i].begin();
+         value_iter != _cached_simple_headers[i].end(); ++value_iter) {
+      _parseSimpleHeader(static_cast<SimpleHeader>(i), *value_iter);
+    }
+  }
+  for (int i = 0; i < N_SPECIAL_HEADERS; ++i) {
+    for (HeaderValueList::iterator value_iter = _cached_special_headers[i].begin();
+         value_iter != _cached_special_headers[i].end(); ++value_iter) {
+      _parseSpecialHeader(static_cast<SpecialHeader>(i), value_iter->data(), value_iter->size());
+    }
+  }
+}
+
+const std::string &
+Variables::getValue(const string &name) const {
+  if (!_headers_parsed || !_query_string_parsed) {
+    // we need to do this because we want to
+    // 1) present const getValue() to clients
+    // 2) parse lazily (only on demand)
+    Variables &non_const_self = const_cast<Variables &>(*this);
+    if (!_headers_parsed) {
+      non_const_self._parseCachedHeaders();
+      non_const_self._headers_parsed = true;
+    }
+    if (!_query_string_parsed) {
+      int query_string_size = static_cast<int>(_query_string.size());
+      if (query_string_size) {
+        non_const_self._parseQueryString(_query_string.data(), query_string_size);
+        non_const_self._query_string_parsed = true;
+      }
+    }
+  }
+  string search_key(name);
+  _toUpperCase(search_key);
+  StringHash::const_iterator iter = _simple_data.find(search_key);
+  if (iter != _simple_data.end()) {
+    _debugLog(_debug_tag.c_str(), "[%s] Found value [%.*s] for variable [%.*s] in simple data", 
+              __FUNCTION__, iter->second.size(), iter->second.data(), name.size(), name.data());
+    return iter->second;
+  }
+  const char *header;
+  int header_len;
+  const char *attr;
+  int attr_len;
+  if (!_parseDictVariable(name, header, header_len, attr, attr_len)) {
+    _debugLog(_debug_tag.c_str(), "[%s] Unmatched simple variable [%.*s] not in dict variable form",
+              __FUNCTION__, name.size(), name.data());
+    return EMPTY_STRING;
+  }
+  int dict_index = _searchHeaders(NORM_SPECIAL_HEADERS, header, header_len); // ignore the HTTP_ prefix
+  if (dict_index == -1) {
+    _debugLog(_debug_tag.c_str(), "[%s] Dict variable [%.*s] refers to unknown dictionary",
+              __FUNCTION__, name.size(), name.data());
+    return EMPTY_STRING;
+  }
+
+  // change variable name to use only the attribute field
+  search_key.assign(attr, attr_len);
+
+  iter = _dict_data[dict_index].find(search_key);
+
+  if (dict_index == HTTP_ACCEPT_LANGUAGE) {
+    _debugLog(_debug_tag.c_str(), "[%s] Returning boolean literal for lang variable [%.*s]",
+              __FUNCTION__, search_key.size(), search_key.data());
+    return (iter == _dict_data[dict_index].end()) ? EMPTY_STRING : TRUE_STRING;
+  }
+  
+  if (iter != _dict_data[dict_index].end()) {
+    _debugLog(_debug_tag.c_str(), "[%s] Found variable [%.*s] in %s dictionary with value [%.*s]",
+              __FUNCTION__, search_key.size(), search_key.data(), NORM_SPECIAL_HEADERS[dict_index].c_str(), 
+              iter->second.size(), iter->second.data());
+    return iter->second;
+  }
+
+  size_t cookie_part_divider = (dict_index == HTTP_COOKIE) ? search_key.find(';') : search_key.size();
+  if (cookie_part_divider && (cookie_part_divider < (search_key.size() - 1))) {
+    _debugLog(_debug_tag.c_str(), "[%s] Cookie variable [%s] refers to sub cookie", 
+              __FUNCTION__, search_key.c_str());
+    return _getSubCookieValue(search_key, cookie_part_divider);
+  }
+  
+  _debugLog(_debug_tag.c_str(), "[%s] Found no value for dict variable [%s]", __FUNCTION__, name.c_str());
+  return EMPTY_STRING;
+}
+
+const string &
+Variables::_getSubCookieValue(const string &cookie_str, size_t cookie_part_divider) const {
+  if (!_cookie_jar_created) {
+    if (_cookie_str.size()) {
+      Variables &non_const_self = const_cast<Variables &>(*this); // same reasoning as in getValue()
+      // TODO - code was here
+      non_const_self._cookie_jar_created = true;
+    } else {
+      _debugLog(_debug_tag.c_str(), "[%s] Cookie string empty; nothing to construct jar from", __FUNCTION__);
+    }
+  }
+  if (_cookie_jar_created) {
+    // we need to do this as we are going to manipulate the 'divider'
+    // character, and we don't need to create a copy of the string for
+    // that; hence this shortcut
+    string &non_const_cookie_str = const_cast<string &>(cookie_str);
+    
+    non_const_cookie_str[cookie_part_divider] = '\0'; // make sure cookie name is NULL terminated
+    const char *cookie_name = non_const_cookie_str.data(); /* above NULL will take effect */
+    const char *part_name = 
+      non_const_cookie_str.c_str() /* NULL terminate the part */ + cookie_part_divider + 1;
+    bool user_name = (part_name[0] == 'u') && (part_name[1] == '\0');
+    if (user_name) {
+      part_name = "l";
+    }
+    // TODO - code was here
+    const char *sub_cookie_value = NULL;
+    non_const_cookie_str[cookie_part_divider] = ';'; // restore before returning
+    if (!sub_cookie_value) {
+      _debugLog(_debug_tag.c_str(), "[%s] Could not find value for part [%s] of cookie [%.*s]", __FUNCTION__,
+                part_name, cookie_part_divider, cookie_name);
+      return EMPTY_STRING;
+    } else {
+      // we need to do this as have to return a string reference
+      string &retval = const_cast<Variables &>(*this)._cached_sub_cookie_value;
+
+      if (user_name) {
+        char unscrambled_login[256];
+        // TODO - code was here
+        _debugLog(_debug_tag.c_str(), "[%s] Unscrambled login name to [%s]", __FUNCTION__, unscrambled_login);
+        retval.assign(unscrambled_login);
+      } else {
+        _debugLog(_debug_tag.c_str(), "[%s] Got value [%s] for cookie name [%.*s] and part [%s]",
+                  __FUNCTION__, sub_cookie_value, cookie_part_divider, cookie_name, part_name);
+        retval.assign(sub_cookie_value);
+      }
+      return retval;
+    }
+  } else {
+    _errorLog("[%s] Cookie jar not available; Returning empty string", __FUNCTION__);
+    return EMPTY_STRING;
+  }
+}
+
+void
+Variables::clear() {
+  _simple_data.clear();
+  for (int i = 0; i < N_SPECIAL_HEADERS; ++i) {
+    _dict_data[i].clear();
+    _cached_special_headers[i].clear();
+  }
+  for (int i = 0; i < N_SIMPLE_HEADERS; ++i) {
+    _cached_simple_headers[i].clear();
+  }
+  _query_string.clear();
+  _headers_parsed = _query_string_parsed = false;
+  _cookie_str.clear();
+  _releaseCookieJar();
+}
+
+void
+Variables::_parseCookieString(const char *str, int str_len) {
+  AttributeList cookies;
+  Utils::parseAttributes(str, str_len, cookies, ";,");
+  for (AttributeList::iterator iter = cookies.begin(); iter != cookies.end(); ++iter) {
+    _insert(_dict_data[HTTP_COOKIE], string(iter->name, iter->name_len), string(iter->value, iter->value_len));
+    _debugLog(_debug_tag.c_str(), "[%s] Inserted cookie with name [%.*s] and value [%.*s]", __FUNCTION__,
+              iter->name_len, iter->name, iter->value_len, iter->value);
+  }
+}
+
+void
+Variables::_parseUserAgentString(const char *str, int str_len) {
+  string user_agent_str(str, str_len); // need NULL-terminated version
+  // TODO - code was here
+  char version_buf[64];
+  // TODO - code was here
+  _insert(_dict_data[HTTP_USER_AGENT], VERSION_STRING, version_buf);
+}
+
+void
+Variables::_parseAcceptLangString(const char *str, int str_len) {
+  int i;
+  for(i = 0; (i < str_len) && ((isspace(str[i]) || str[i] == ',')); ++i);
+  const char *lang = str + i;
+  int lang_len;
+  for (; i <= str_len; ++i) {
+    if ((i == str_len) || (str[i] == ',')) {
+      lang_len = str + i - lang;
+      for (; lang_len && isspace(lang[lang_len - 1]); --lang_len);
+      if (lang_len) {
+        _insert(_dict_data[HTTP_ACCEPT_LANGUAGE], string(lang, lang_len), EMPTY_STRING);
+        _debugLog(_debug_tag.c_str(), "[%s] Added language [%.*s]", __FUNCTION__, lang_len, lang);
+      }
+      for(; (i < str_len) && ((isspace(str[i]) || str[i] == ',')); ++i);
+      lang = str + i;
+    }
+  }
+}
+
+bool
+Variables::_parseDictVariable(const std::string &variable, const char *&header, int &header_len,
+                              const char *&attr, int &attr_len) const {
+  const char *var_ptr = variable.data();
+  int var_size = variable.size();
+  if ((var_size <= 4) || (variable[var_size - 1] != '}')) {
+    return false;
+  }
+  int paranth_index = -1;
+  for (int i = 0; i < (var_size - 1); ++i) {
+    if (variable[i] == '{') {
+      if (paranth_index != -1) {
+        _debugLog(_debug_tag.c_str(), "[%s] Cannot have multiple paranthesis in dict variable [%.*s]",
+                  __FUNCTION__, var_size, var_ptr);
+        return false;
+      }
+      paranth_index = i;
+    }
+    if (variable[i] == '}') {
+      _debugLog(_debug_tag.c_str(), "[%s] Cannot have multiple paranthesis in dict variable [%.*s]",
+                __FUNCTION__, var_size, var_ptr);
+      return false;
+    }
+  }
+  if (paranth_index == -1) {
+    _debugLog(_debug_tag.c_str(), "[%s] Could not find opening paranthesis in variable [%.*s]",
+              __FUNCTION__, var_size, var_ptr);
+    return false;
+  }
+  if (paranth_index == 0) {
+    _debugLog(_debug_tag.c_str(), "[%s] Dict variable has no dict name [%.*s]",
+              __FUNCTION__, var_size, var_ptr);
+    return false;
+  }
+  if (paranth_index == (var_size - 2)) {
+    _debugLog(_debug_tag.c_str(), "[%s] Dict variable has no attribute name [%.*s]",
+              __FUNCTION__, var_size, var_ptr);
+    return false;
+  }
+  header = var_ptr;
+  header_len = paranth_index;
+  attr = var_ptr + paranth_index + 1;
+  attr_len = var_size - header_len - 2;
+  return true;
+}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/bc13c5e0/plugins/experimental/esi/lib/Variables.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/esi/lib/Variables.h b/plugins/experimental/esi/lib/Variables.h
new file mode 100644
index 0000000..7bc985c
--- /dev/null
+++ b/plugins/experimental/esi/lib/Variables.h
@@ -0,0 +1,156 @@
+/** @file
+
+  A brief file description
+
+  @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.
+ */
+
+#ifndef _ESI_VARIABLES_H
+
+#define _ESI_VARIABLES_H
+
+#include <list>
+#include <boost/noncopyable.hpp>
+
+#include <cstring>
+#include "ComponentBase.h"
+#include "StringHash.h"
+#include "HttpHeader.h"
+
+namespace EsiLib {
+
+class Variables : private ComponentBase, boost::noncopyable {
+
+public:
+
+  Variables(const char *debug_tag, ComponentBase::Debug debug_func, ComponentBase::Error error_func)
+    : ComponentBase(debug_tag, debug_func, error_func), _headers_parsed(false), _query_string(""),
+      _query_string_parsed(false), _cookie_jar_created(false) { };
+  
+  /** currently 'host', 'referer', 'accept-language', 'cookie' and 'user-agent' headers are parsed */
+  void populate(const HttpHeader &header);
+
+  void populate(const HttpHeaderList &headers) {
+    for (HttpHeaderList::const_iterator iter = headers.begin(); iter != headers.end(); ++iter) {
+      populate(*iter);
+    }
+  };
+
+  void populate(const char *query_string, int query_string_len = -1) {
+    if (query_string && (query_string_len != 0)) {
+      if (query_string_len == -1) {
+        query_string_len = strlen(query_string);
+      }
+      if (_query_string_parsed) {
+        _parseQueryString(query_string, query_string_len);
+      } else {
+        _query_string.assign(query_string, query_string_len);
+      }
+    }
+  }
+
+  /** returns value of specified variable; empty string returned for unknown variable; key
+   * has to be prefixed with 'http_' string for all variable names except 'query_string' */
+  const std::string &getValue(const std::string &name) const;
+
+  /** convenient alternative for method above */
+  const std::string &getValue(const char *name, int name_len = -1) const {
+    if (!name) {
+      return EMPTY_STRING;
+    }
+    std::string var_name;
+    if (name_len == -1) {
+      var_name.assign(name);
+    } else {
+      var_name.assign(name, name_len);
+    }
+    return getValue(var_name);
+  }
+
+  void clear();
+
+  virtual ~Variables() { _releaseCookieJar(); };
+
+private:
+
+  static const std::string EMPTY_STRING;
+  static const std::string TRUE_STRING;
+  static const std::string VENDOR_STRING;
+  static const std::string VERSION_STRING;
+  static const std::string PLATFORM_STRING;
+
+  enum SimpleHeader { HTTP_HOST = 0, HTTP_REFERER = 1 };
+  static const std::string SIMPLE_HEADERS[];  // indices should map to enum values above
+
+  enum SpecialHeader { HTTP_ACCEPT_LANGUAGE = 0, HTTP_COOKIE = 1, HTTP_USER_AGENT = 2, QUERY_STRING = 3 };
+  static const std::string SPECIAL_HEADERS[];  // indices should map to enum values above
+
+  // normalized versions of the headers above; indices should correspond correctly
+  static const std::string NORM_SIMPLE_HEADERS[];
+  static const std::string NORM_SPECIAL_HEADERS[]; // indices should again map to enum values
+
+  static const int N_SIMPLE_HEADERS = HTTP_REFERER + 1;
+  static const int N_SPECIAL_HEADERS = QUERY_STRING + 1;
+
+  StringHash _simple_data;
+  StringHash _dict_data[N_SPECIAL_HEADERS];
+
+  inline std::string &_toUpperCase(std::string &str) const;
+  inline int _searchHeaders(const std::string headers[], const char *name, int name_len) const;
+  bool _parseDictVariable(const std::string &variable, const char *&header, int &header_len,
+                                 const char *&attr, int &attr_len) const;
+  void _parseCookieString(const char *str, int str_len);
+  void _parseUserAgentString(const char *str, int str_len);
+  void _parseAcceptLangString(const char *str, int str_len);
+  inline void _parseSimpleHeader(SimpleHeader hdr, const std::string &value);
+  inline void _parseSimpleHeader(SimpleHeader hdr, const char *value, int value_len);
+  void _parseSpecialHeader(SpecialHeader hdr, const char *value, int value_len);
+  void _parseCachedHeaders();
+
+  inline void _insert(StringHash &hash, const std::string &key, const std::string &value);
+
+  typedef std::list<std::string> HeaderValueList;
+  HeaderValueList _cached_simple_headers[N_SIMPLE_HEADERS];
+  HeaderValueList _cached_special_headers[N_SPECIAL_HEADERS];
+  
+  std::string _cookie_str;
+  bool _headers_parsed;
+  std::string _query_string;
+  bool _query_string_parsed;
+
+  void _parseHeader(const char *name, int name_len, const char *value, int value_len);
+  void _parseQueryString(const char *query_string, int query_string_len);
+  
+  // TODO - code was here
+  bool _cookie_jar_created;
+
+  inline void _releaseCookieJar() {
+    if (_cookie_jar_created) {
+      _cookie_jar_created = false;
+    }
+  }
+
+  std::string _cached_sub_cookie_value;
+  const std::string &_getSubCookieValue(const std::string &cookie_str, size_t cookie_part_divider) const;
+
+};
+
+};
+
+#endif // _ESI_VARIABLES_H

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/bc13c5e0/plugins/experimental/esi/lib/gzip.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/esi/lib/gzip.cc b/plugins/experimental/esi/lib/gzip.cc
new file mode 100644
index 0000000..0ec0ee4
--- /dev/null
+++ b/plugins/experimental/esi/lib/gzip.cc
@@ -0,0 +1,204 @@
+/** @file
+
+  A brief file description
+
+  @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 <stdint.h>
+
+#include "gzip.h"
+#include <zlib.h>
+
+#include "Utils.h"
+
+using namespace EsiLib;
+using std::string;
+
+static const int COMPRESSION_LEVEL = 6;
+static const int ZLIB_MEM_LEVEL = 8;
+
+static const int GZIP_HEADER_SIZE = 10;
+static const int GZIP_TRAILER_SIZE = 8;
+
+static const char MAGIC_BYTE_1 = 0x1f;
+static const char MAGIC_BYTE_2 = 0x8b;
+static const char OS_TYPE = 3; // Unix
+
+static const int BUF_SIZE = 1 << 15; // 32k buffer
+
+template<typename T>
+inline void append(string &out, T data) {
+  for (unsigned int i = 0; i < sizeof(data); ++i) {
+    out += static_cast<char>(data & 0xff);
+    data = data >> 8;
+  }
+}
+
+template<typename T>
+inline void extract(const char *in, T &data) {
+  data = 0;
+  for (int i = (sizeof(data) - 1); i >= 0; --i) {
+    data = data << 8;
+    data = data | static_cast<unsigned char>(*(in + i));
+  }
+}
+
+inline int runDeflateLoop(z_stream &zstrm, int flush, std::string &cdata) {
+  char buf[BUF_SIZE];
+  int deflate_result = Z_OK;
+  do {
+    zstrm.next_out = reinterpret_cast<Bytef *>(buf);
+    zstrm.avail_out = BUF_SIZE;
+    deflate_result = deflate(&zstrm, flush);
+    if ((deflate_result == Z_OK) || (deflate_result == Z_STREAM_END)) {
+      cdata.append(buf, BUF_SIZE - zstrm.avail_out);
+      if ((deflate_result == Z_STREAM_END) || zstrm.avail_out) {
+        break;
+      }
+    } else {
+      break;
+    }
+  } while (true);
+  return deflate_result;
+}
+
+bool
+EsiLib::gzip(const ByteBlockList& blocks, std::string &cdata) {
+  cdata.assign(GZIP_HEADER_SIZE, 0); // reserving space for the header
+  z_stream zstrm;
+  zstrm.zalloc = Z_NULL;
+  zstrm.zfree = Z_NULL;
+  zstrm.opaque = Z_NULL;
+  if (deflateInit2(&zstrm, COMPRESSION_LEVEL, Z_DEFLATED, -MAX_WBITS,
+                   ZLIB_MEM_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK) {
+    Utils::ERROR_LOG("[%s] deflateInit2 failed!", __FUNCTION__);
+    return false;
+  }
+
+  int total_data_len = 0;
+  uLong crc = crc32(0, Z_NULL, 0);
+  int deflate_result = Z_OK;
+  int in_data_size = 0;
+  for (ByteBlockList::const_iterator iter = blocks.begin(); iter != blocks.end(); ++iter) {
+    if (iter->data && (iter->data_len > 0)) {
+      zstrm.next_in = reinterpret_cast<Bytef *>(const_cast<char *>(iter->data));
+      zstrm.avail_in = iter->data_len;
+      in_data_size += iter->data_len;
+      deflate_result = runDeflateLoop(zstrm, 0, cdata);
+      if (deflate_result != Z_OK) {
+        break; // break out of the blocks iteration
+      }
+      crc = crc32(crc, reinterpret_cast<const Bytef *>(iter->data), iter->data_len);
+      total_data_len += iter->data_len;
+    }
+  }
+  if (!in_data_size) {
+      zstrm.avail_in = 0; // required for the "finish" loop as no data has been given so far
+  }
+  if (deflate_result == Z_OK) {
+    deflate_result = runDeflateLoop(zstrm, Z_FINISH, cdata);
+  }
+  deflateEnd(&zstrm);
+  if (deflate_result != Z_STREAM_END) {
+    Utils::ERROR_LOG("[%s] Failure while deflating; error code %d", __FUNCTION__, deflate_result);
+    return false;
+  }
+  cdata[0] = MAGIC_BYTE_1;
+  cdata[1] = MAGIC_BYTE_2;
+  cdata[2] = Z_DEFLATED;
+  cdata[9] = OS_TYPE;
+  append(cdata, static_cast<uint32_t>(crc));
+  append(cdata, static_cast<int32_t>(total_data_len));
+  return true;
+}
+
+bool
+EsiLib::gunzip(const char *data, int data_len, BufferList &buf_list) {
+  if (!data || (data_len <= (GZIP_HEADER_SIZE + GZIP_TRAILER_SIZE))) {
+    Utils::ERROR_LOG("[%s] Invalid arguments: 0x%p, %d", __FUNCTION__, data, data_len);
+    return false;
+  }
+  if ((data[0] != MAGIC_BYTE_1) || (data[1] != MAGIC_BYTE_2) || (data[2] != Z_DEFLATED) ||
+      (data[9] != OS_TYPE)) {
+    Utils::ERROR_LOG("[%s] Header check failed!", __FUNCTION__);
+    return false;
+  }
+  data += GZIP_HEADER_SIZE;
+  data_len -= (GZIP_HEADER_SIZE + GZIP_TRAILER_SIZE);
+  buf_list.clear();
+  z_stream zstrm;
+  zstrm.zalloc = Z_NULL;
+  zstrm.zfree = Z_NULL;
+  zstrm.opaque = Z_NULL;
+  zstrm.next_in = 0;
+  zstrm.avail_in = 0;
+  if (inflateInit2(&zstrm, -MAX_WBITS) != Z_OK) {
+    Utils::ERROR_LOG("[%s] inflateInit2 failed!", __FUNCTION__);
+    return false;
+  }
+  zstrm.next_in = reinterpret_cast<Bytef *>(const_cast<char *>(data));
+  zstrm.avail_in = data_len;
+  char raw_buf[BUF_SIZE];
+  int inflate_result;
+  int32_t unzipped_data_size = 0;
+  int32_t curr_buf_size;
+  uLong crc = crc32(0, Z_NULL, 0);
+  do {
+    zstrm.next_out = reinterpret_cast<Bytef *>(raw_buf);
+    zstrm.avail_out = BUF_SIZE;
+    inflate_result = inflate(&zstrm, Z_FINISH);
+    curr_buf_size = -1;
+    if ((inflate_result == Z_OK) || (inflate_result == Z_BUF_ERROR)) {
+      curr_buf_size = BUF_SIZE;
+    } else if (inflate_result == Z_STREAM_END) {
+      curr_buf_size = BUF_SIZE - zstrm.avail_out;
+    }
+    if (curr_buf_size == -1) {
+      break;
+    }
+    unzipped_data_size += curr_buf_size;
+    crc = crc32(crc, reinterpret_cast<const Bytef *>(raw_buf), curr_buf_size);
+
+    // push empty object onto list and add data to in-list object to
+    // avoid data copy for temporary
+    buf_list.push_back(string());
+    string &curr_buf = buf_list.back();
+    curr_buf.assign(raw_buf, curr_buf_size); 
+
+    if (inflate_result == Z_STREAM_END) {
+      break;
+    }
+  } while (true);
+  inflateEnd(&zstrm);
+  if (inflate_result != Z_STREAM_END) {
+    Utils::ERROR_LOG("[%s] Failure while inflating; error code %d", __FUNCTION__, inflate_result);
+    return false;
+  }
+  int32_t orig_size;
+  uLong orig_crc;
+  extract(data + data_len, orig_crc);
+  extract(data + data_len + 4, orig_size);
+  if ((crc != orig_crc) || (unzipped_data_size != orig_size)) {
+    Utils::ERROR_LOG("[%s] CRC/size error. Expecting (CRC, size) (0x%x, 0x%x); computed (0x%x, 0x%x)",
+                     __FUNCTION__, orig_crc, orig_size, crc, unzipped_data_size);
+    return false;
+  }
+  return true;
+}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/bc13c5e0/plugins/experimental/esi/lib/gzip.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/esi/lib/gzip.h b/plugins/experimental/esi/lib/gzip.h
new file mode 100644
index 0000000..92d81ec
--- /dev/null
+++ b/plugins/experimental/esi/lib/gzip.h
@@ -0,0 +1,55 @@
+/** @file
+
+  A brief file description
+
+  @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.
+ */
+
+#ifndef _GZIP_H
+
+#define _GZIP_H 
+
+#include <string>
+#include <list>
+
+namespace EsiLib {
+
+struct ByteBlock {
+  const char *data;
+  int data_len;
+  ByteBlock(const char *d = 0, int d_len = 0) : data(d), data_len(d_len) { };
+};
+
+typedef std::list<ByteBlock> ByteBlockList;
+
+bool gzip(const ByteBlockList& blocks, std::string &cdata);
+
+inline bool gzip(const char *data, int data_len, std::string &cdata) {
+  ByteBlockList blocks;
+  blocks.push_back(ByteBlock(data, data_len));
+  return gzip(blocks, cdata);
+}
+
+typedef std::list<std::string> BufferList;
+
+bool gunzip(const char *data, int data_len, BufferList &buf_list);
+
+}
+
+#endif // _GZIP_H