You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by jp...@apache.org on 2013/11/06 01:50:27 UTC

[08/12] git commit: TS-2323: separate remap.config parsing from UrlRewrite

TS-2323: separate remap.config parsing from UrlRewrite


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

Branch: refs/heads/master
Commit: 90f923ef36313f74241f9ebe55ceea17de5caac7
Parents: 3e8668d
Author: James Peach <jp...@apache.org>
Authored: Fri Nov 1 10:28:14 2013 -0700
Committer: James Peach <jp...@apache.org>
Committed: Tue Nov 5 16:46:35 2013 -0800

----------------------------------------------------------------------
 proxy/http/remap/RemapConfig.cc | 765 ++++++++++++++++++++++++++++++-
 proxy/http/remap/RemapConfig.h  |  11 +-
 proxy/http/remap/UrlRewrite.cc  | 860 ++++-------------------------------
 proxy/http/remap/UrlRewrite.h   |  11 +-
 4 files changed, 848 insertions(+), 799 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/90f923ef/proxy/http/remap/RemapConfig.cc
----------------------------------------------------------------------
diff --git a/proxy/http/remap/RemapConfig.cc b/proxy/http/remap/RemapConfig.cc
index 0c6442b..a4d41f2 100644
--- a/proxy/http/remap/RemapConfig.cc
+++ b/proxy/http/remap/RemapConfig.cc
@@ -22,8 +22,39 @@
  */
 
 #include "RemapConfig.h"
-#include "libts.h"
+#include "UrlRewrite.h"
+#include "ReverseProxy.h"
 #include "HTTP.h"
+#include "libts.h"
+#include "ink_cap.h"
+
+#define modulePrefix "[ReverseProxy]"
+
+/**
+  Returns the length of the URL.
+
+  Will replace the terminator with a '/' if this is a full URL and
+  there are no '/' in it after the the host.  This ensures that class
+  URL parses the URL correctly.
+
+*/
+static int
+UrlWhack(char *toWhack, int *origLength)
+{
+  int length = strlen(toWhack);
+  char *tmp;
+  *origLength = length;
+
+  // Check to see if this a full URL
+  tmp = strstr(toWhack, "://");
+  if (tmp != NULL) {
+    if (strchr(tmp + 3, '/') == NULL) {
+      toWhack[length] = '/';
+      length++;
+    }
+  }
+  return length;
+}
 
 /**
   Cleanup *char[] array - each item in array must be allocated via
@@ -58,6 +89,33 @@ BUILD_TABLE_INFO::reset()
   clear_xstr_array(this->argv, sizeof(this->argv) / sizeof(char *));
 }
 
+static const char *
+process_filter_opt(url_mapping * mp, const BUILD_TABLE_INFO * bti, char * errStrBuf, int errStrBufSize)
+{
+  acl_filter_rule *rp, **rpp;
+  const char *errStr = NULL;
+
+  if (unlikely(!mp || !bti || !errStrBuf || errStrBufSize <= 0)) {
+    Debug("url_rewrite", "[process_filter_opt] Invalid argument(s)");
+    return (const char *) "[process_filter_opt] Invalid argument(s)";
+  }
+  for (rp = bti->rules_list; rp; rp = rp->next) {
+    if (rp->active_queue_flag) {
+      Debug("url_rewrite", "[process_filter_opt] Add active main filter \"%s\" (argc=%d)",
+            rp->filter_name ? rp->filter_name : "<NULL>", rp->argc);
+      for (rpp = &mp->filter; *rpp; rpp = &((*rpp)->next));
+      if ((errStr = remap_validate_filter_args(rpp, (const char **)rp->argv, rp->argc, errStrBuf, errStrBufSize)) != NULL)
+        break;
+    }
+  }
+  if (!errStr && (bti->remap_optflg & REMAP_OPTFLG_ALL_FILTERS) != 0) {
+    Debug("url_rewrite", "[process_filter_opt] Add per remap filter");
+    for (rpp = &mp->filter; *rpp; rpp = &((*rpp)->next));
+    errStr = remap_validate_filter_args(rpp, (const char **)bti->argv, bti->argc, errStrBuf, errStrBufSize);
+  }
+  return errStr;
+}
+
 static bool
 is_inkeylist(const char * key, ...)
 {
@@ -104,7 +162,7 @@ parse_define_directive(const char * directive, BUILD_TABLE_INFO * bti, char * er
 
   flg = ((rp = acl_filter_rule::find_byname(bti->rules_list, (const char *) bti->paramv[1])) == NULL) ? true : false;
   // coverity[alloc_arg]
-  if ((cstr = remap_validate_filter_args(&rp, bti->argv, bti->argc, errbuf, errbufsize)) == NULL && rp) {
+  if ((cstr = remap_validate_filter_args(&rp, (const char **)bti->argv, bti->argc, errbuf, errbufsize)) == NULL && rp) {
     if (flg) {                  // new filter - add to list
       Debug("url_rewrite", "[parse_directive] new rule \"%s\" was created", bti->paramv[1]);
       for (rpp = &bti->rules_list; *rpp; rpp = &((*rpp)->next));
@@ -223,11 +281,12 @@ remap_parse_directive(BUILD_TABLE_INFO *bti, char * errbuf, size_t errbufsize)
 }
 
 const char *
-remap_validate_filter_args(acl_filter_rule ** rule_pp, char ** argv, int argc, char * errStrBuf, size_t errStrBufSize)
+remap_validate_filter_args(acl_filter_rule ** rule_pp, const char ** argv, int argc, char * errStrBuf, size_t errStrBufSize)
 {
   acl_filter_rule *rule;
   unsigned long ul;
-  char *argptr, tmpbuf[1024];
+  const char *argptr;
+  char tmpbuf[1024];
   src_ip_info_t *ipi;
   int i, j, m;
   bool new_rule_flg = false;
@@ -255,7 +314,7 @@ remap_validate_filter_args(acl_filter_rule ** rule_pp, char ** argv, int argc, c
   }
 
   for (i = 0; i < argc; i++) {
-    if ((ul = remap_check_option(&argv[i], 1, 0, NULL, &argptr)) == 0) {
+    if ((ul = remap_check_option((const char **)&argv[i], 1, 0, NULL, &argptr)) == 0) {
       Debug("url_rewrite", "[validate_filter_args] Unknow remap option - %s", argv[i]);
       snprintf(errStrBuf, errStrBufSize, "Unknown option - \"%s\"", argv[i]);
       errStrBuf[errStrBufSize - 1] = 0;
@@ -405,7 +464,7 @@ remap_validate_filter_args(acl_filter_rule ** rule_pp, char ** argv, int argc, c
 }
 
 unsigned long
-remap_check_option(char *argv[], int argc, unsigned long findmode, int *_ret_idx, char **argptr)
+remap_check_option(const char ** argv, int argc, unsigned long findmode, int *_ret_idx, const char **argptr)
 {
   unsigned long ret_flags = 0;
   int idx = 0;
@@ -474,3 +533,697 @@ remap_check_option(char *argv[], int argc, unsigned long findmode, int *_ret_idx
     *_ret_idx = idx;
   return ret_flags;
 }
+
+int
+remap_load_plugin(const char ** argv, int argc, url_mapping *mp, char *errbuf, int errbufsize,
+    int jump_to_argc, int *plugin_found_at)
+{
+  TSRemapInterface ri;
+  struct stat stat_buf;
+  remap_plugin_info *pi;
+  char *c, *err, tmpbuf[2048], default_path[PATH_NAME_MAX];
+  const char *new_argv[1024];
+  char * parv[1024];
+  int idx = 0, retcode = 0;
+  int parc = 0;
+
+  *plugin_found_at = 0;
+
+  memset(parv, 0, sizeof(parv));
+  memset(new_argv, 0, sizeof(new_argv));
+  tmpbuf[0] = 0;
+
+  ink_assert(argc < countof(new_argv));
+
+  if (jump_to_argc != 0) {
+    argc -= jump_to_argc;
+    int i = 0;
+    while (argv[i + jump_to_argc]) {
+      new_argv[i] = argv[i + jump_to_argc];
+      i++;
+    }
+    argv = &new_argv[0];
+    if (!remap_check_option(argv, argc, REMAP_OPTFLG_PLUGIN, &idx)) {
+      return -1;
+    }
+  } else {
+    if (unlikely(!mp || (remap_check_option(argv, argc, REMAP_OPTFLG_PLUGIN, &idx) & REMAP_OPTFLG_PLUGIN) == 0)) {
+      snprintf(errbuf, errbufsize, "Can't find remap plugin keyword or \"url_mapping\" is NULL");
+      return -1;                /* incorrect input data - almost impossible case */
+    }
+  }
+
+  if (unlikely((c = strchr(argv[idx], (int) '=')) == NULL || !(*(++c)))) {
+    snprintf(errbuf, errbufsize, "Can't find remap plugin file name in \"@%s\"", argv[idx]);
+    return -2;                  /* incorrect input data */
+  }
+
+  if (stat(c, &stat_buf) != 0) {
+    const char *plugin_default_path = TSPluginDirGet();
+
+    // Try with the plugin path instead
+    if (strlen(c) + strlen(plugin_default_path) > (PATH_NAME_MAX - 1)) {
+      Debug("remap_plugin", "way too large a path specified for remap plugin");
+      return -3;
+    }
+
+    snprintf(default_path, PATH_NAME_MAX, "%s/%s", plugin_default_path, c);
+    Debug("remap_plugin", "attempting to stat default plugin path: %s", default_path);
+
+    if (stat(default_path, &stat_buf) == 0) {
+      Debug("remap_plugin", "stat successful on %s using that", default_path);
+      c = &default_path[0];
+    } else {
+      snprintf(errbuf, errbufsize, "Can't find remap plugin file \"%s\"", c);
+      return -3;
+    }
+  }
+
+  Debug("remap_plugin", "using path %s for plugin", c);
+
+  if (!remap_pi_list || (pi = remap_pi_list->find_by_path(c)) == 0) {
+    pi = NEW(new remap_plugin_info(c));
+    if (!remap_pi_list) {
+      remap_pi_list = pi;
+    } else {
+      remap_pi_list->add_to_list(pi);
+    }
+    Debug("remap_plugin", "New remap plugin info created for \"%s\"", c);
+
+    if ((pi->dlh = dlopen(c, RTLD_NOW)) == NULL) {
+#if defined(freebsd) || defined(openbsd)
+      err = (char *)dlerror();
+#else
+      err = dlerror();
+#endif
+      snprintf(errbuf, errbufsize, "Can't load plugin \"%s\" - %s", c, err ? err : "Unknown dlopen() error");
+      return -4;
+    }
+    pi->fp_tsremap_init = (remap_plugin_info::_tsremap_init *) dlsym(pi->dlh, TSREMAP_FUNCNAME_INIT);
+    pi->fp_tsremap_done = (remap_plugin_info::_tsremap_done *) dlsym(pi->dlh, TSREMAP_FUNCNAME_DONE);
+    pi->fp_tsremap_new_instance = (remap_plugin_info::_tsremap_new_instance *) dlsym(pi->dlh, TSREMAP_FUNCNAME_NEW_INSTANCE);
+    pi->fp_tsremap_delete_instance = (remap_plugin_info::_tsremap_delete_instance *) dlsym(pi->dlh, TSREMAP_FUNCNAME_DELETE_INSTANCE);
+    pi->fp_tsremap_do_remap = (remap_plugin_info::_tsremap_do_remap *) dlsym(pi->dlh, TSREMAP_FUNCNAME_DO_REMAP);
+    pi->fp_tsremap_os_response = (remap_plugin_info::_tsremap_os_response *) dlsym(pi->dlh, TSREMAP_FUNCNAME_OS_RESPONSE);
+
+    if (!pi->fp_tsremap_init) {
+      snprintf(errbuf, errbufsize, "Can't find \"%s\" function in remap plugin \"%s\"", TSREMAP_FUNCNAME_INIT, c);
+      retcode = -10;
+    } else if (!pi->fp_tsremap_new_instance) {
+      snprintf(errbuf, errbufsize, "Can't find \"%s\" function in remap plugin \"%s\"",
+                   TSREMAP_FUNCNAME_NEW_INSTANCE, c);
+      retcode = -11;
+    } else if (!pi->fp_tsremap_do_remap) {
+      snprintf(errbuf, errbufsize, "Can't find \"%s\" function in remap plugin \"%s\"", TSREMAP_FUNCNAME_DO_REMAP, c);
+      retcode = -12;
+    }
+    if (retcode) {
+      if (errbuf && errbufsize > 0)
+        Debug("remap_plugin", "%s", errbuf);
+      dlclose(pi->dlh);
+      pi->dlh = NULL;
+      return retcode;
+    }
+    memset(&ri, 0, sizeof(ri));
+    ri.size = sizeof(ri);
+    ri.tsremap_version = TSREMAP_VERSION;
+
+    // elevate the access to read files as root if compiled with capabilities, if not
+    // change the effective user to root
+    {
+      uint32_t elevate_access = 0;
+      REC_ReadConfigInteger(elevate_access, "proxy.config.plugin.load_elevated");
+      ElevateAccess access(elevate_access != 0);
+
+      if (pi->fp_tsremap_init(&ri, tmpbuf, sizeof(tmpbuf) - 1) != TS_SUCCESS) {
+        Warning("Failed to initialize plugin %s (non-zero retval) ... bailing out", pi->path);
+        return -5;
+      }
+    } // done elevating access
+    Debug("remap_plugin", "Remap plugin \"%s\" - initialization completed", c);
+  }
+
+  if (!pi->dlh) {
+    snprintf(errbuf, errbufsize, "Can't load plugin \"%s\"", c);
+    return -6;
+  }
+
+  if ((err = mp->fromURL.string_get(NULL)) == NULL) {
+    snprintf(errbuf, errbufsize, "Can't load fromURL from URL class");
+    return -7;
+  }
+  parv[parc++] = ats_strdup(err);
+  ats_free(err);
+
+  if ((err = mp->toUrl.string_get(NULL)) == NULL) {
+    snprintf(errbuf, errbufsize, "Can't load toURL from URL class");
+    return -7;
+  }
+  parv[parc++] = ats_strdup(err);
+  ats_free(err);
+
+  bool plugin_encountered = false;
+  // how many plugin parameters we have for this remapping
+  for (idx = 0; idx < argc && parc < (int) (countof(parv) - 1); idx++) {
+
+    if (plugin_encountered && !strncasecmp("plugin=", argv[idx], 7) && argv[idx][7]) {
+      *plugin_found_at = idx;
+      break;                    //if there is another plugin, lets deal with that later
+    }
+
+    if (!strncasecmp("plugin=", argv[idx], 7)) {
+      plugin_encountered = true;
+    }
+
+    if (!strncasecmp("pparam=", argv[idx], 7) && argv[idx][7]) {
+      parv[parc++] = const_cast<char *>(&(argv[idx][7]));
+    }
+  }
+
+  Debug("url_rewrite", "Viewing all parameters for config line");
+  for (int k = 0; k < argc; k++) {
+    Debug("url_rewrite", "Argument %d: %s", k, argv[k]);
+  }
+
+  Debug("url_rewrite", "Viewing parsed plugin parameters for %s: [%d]", pi->path, *plugin_found_at);
+  for (int k = 0; k < parc; k++) {
+    Debug("url_rewrite", "Argument %d: %s", k, parv[k]);
+  }
+
+  void* ih;
+
+  Debug("remap_plugin", "creating new plugin instance");
+
+  TSReturnCode res = TS_ERROR;
+  // elevate the access to read files as root if compiled with capabilities, if not
+  // change the effective user to root
+  {
+    uint32_t elevate_access = 0;
+    REC_ReadConfigInteger(elevate_access, "proxy.config.plugin.load_elevated");
+    ElevateAccess access(elevate_access != 0);
+    res = pi->fp_tsremap_new_instance(parc, parv, &ih, tmpbuf, sizeof(tmpbuf) - 1);
+  } // done elevating access
+
+  Debug("remap_plugin", "done creating new plugin instance");
+
+  ats_free(parv[0]);               // fromURL
+  ats_free(parv[1]);               // toURL
+
+  if (res != TS_SUCCESS) {
+    snprintf(errbuf, errbufsize, "Can't create new remap instance for plugin \"%s\" - %s", c,
+                 tmpbuf[0] ? tmpbuf : "Unknown plugin error");
+    Warning("Failed to create new instance for plugin %s (not a TS_SUCCESS return)", pi->path);
+    return -8;
+  }
+
+  mp->add_plugin(pi, ih);
+
+  return 0;
+}
+/** will process the regex mapping configuration and create objects in
+    output argument reg_map. It assumes existing data in reg_map is
+    inconsequential and will be perfunctorily null-ed;
+*/
+static bool
+process_regex_mapping_config(const char *from_host_lower, url_mapping *new_mapping, UrlRewrite::RegexMapping *reg_map)
+{
+  const char *str;
+  int str_index;
+  const char *to_host;
+  int to_host_len;
+  int substitution_id;
+  int substitution_count = 0;
+
+  reg_map->re = NULL;
+  reg_map->re_extra = NULL;
+  reg_map->to_url_host_template = NULL;
+  reg_map->to_url_host_template_len = 0;
+  reg_map->n_substitutions = 0;
+
+  reg_map->url_map = new_mapping;
+
+  // using from_host_lower (and not new_mapping->fromURL.host_get())
+  // as this one will be NULL-terminated (required by pcre_compile)
+  reg_map->re = pcre_compile(from_host_lower, 0, &str, &str_index, NULL);
+  if (reg_map->re == NULL) {
+    Warning("pcre_compile failed! Regex has error starting at %s", from_host_lower + str_index);
+    goto lFail;
+  }
+
+  reg_map->re_extra = pcre_study(reg_map->re, 0, &str);
+  if ((reg_map->re_extra == NULL) && (str != NULL)) {
+    Warning("pcre_study failed with message [%s]", str);
+    goto lFail;
+  }
+
+  int n_captures;
+  if (pcre_fullinfo(reg_map->re, reg_map->re_extra, PCRE_INFO_CAPTURECOUNT, &n_captures) != 0) {
+    Warning("pcre_fullinfo failed!");
+    goto lFail;
+  }
+  if (n_captures >= UrlRewrite::MAX_REGEX_SUBS) { // off by one for $0 (implicit capture)
+    Warning("Regex has %d capturing subpatterns (including entire regex); Max allowed: %d",
+            n_captures + 1, UrlRewrite::MAX_REGEX_SUBS);
+    goto lFail;
+  }
+
+  to_host = new_mapping->toUrl.host_get(&to_host_len);
+  for (int i = 0; i < (to_host_len - 1); ++i) {
+    if (to_host[i] == '$') {
+      if (substitution_count > UrlRewrite::MAX_REGEX_SUBS) {
+        Warning("Cannot have more than %d substitutions in mapping with host [%s]",
+                UrlRewrite::MAX_REGEX_SUBS, from_host_lower);
+        goto lFail;
+      }
+      substitution_id = to_host[i + 1] - '0';
+      if ((substitution_id < 0) || (substitution_id > n_captures)) {
+        Warning("Substitution id [%c] has no corresponding capture pattern in regex [%s]",
+              to_host[i + 1], from_host_lower);
+        goto lFail;
+      }
+      reg_map->substitution_markers[reg_map->n_substitutions] = i;
+      reg_map->substitution_ids[reg_map->n_substitutions] = substitution_id;
+      ++reg_map->n_substitutions;
+    }
+  }
+
+  // so the regex itself is stored in fromURL.host; string to match
+  // will be in the request; string to use for substitutions will be
+  // in this buffer
+  str = new_mapping->toUrl.host_get(&str_index); // reusing str and str_index
+  reg_map->to_url_host_template_len = str_index;
+  reg_map->to_url_host_template = static_cast<char *>(ats_malloc(str_index));
+  memcpy(reg_map->to_url_host_template, str, str_index);
+
+  return true;
+
+ lFail:
+  if (reg_map->re) {
+    pcre_free(reg_map->re);
+    reg_map->re = NULL;
+  }
+  if (reg_map->re_extra) {
+    pcre_free(reg_map->re_extra);
+    reg_map->re_extra = NULL;
+  }
+  if (reg_map->to_url_host_template) {
+    ats_free(reg_map->to_url_host_template);
+    reg_map->to_url_host_template = NULL;
+    reg_map->to_url_host_template_len = 0;
+  }
+  return false;
+}
+
+bool
+remap_parse_config(const char * path, UrlRewrite * rewrite)
+{
+  BUILD_TABLE_INFO bti;
+
+  char errBuf[1024], errStrBuf[1024];
+  Tokenizer whiteTok(" \t");
+  bool alarm_already = false;
+  const char *errStr;
+
+  // Vars to parse line in file
+  char *tok_state, *cur_line, *cur_line_tmp;
+  int rparse, cur_line_size, cln = 0;        // Our current line number
+
+  // Vars to build the mapping
+  const char *fromScheme, *toScheme;
+  int fromSchemeLen, toSchemeLen;
+  const char *fromHost, *toHost;
+  int fromHostLen, toHostLen;
+  char *map_from, *map_from_start;
+  char *map_to, *map_to_start;
+  const char *tmp;              // Appease the DEC compiler
+  char *fromHost_lower = NULL;
+  char *fromHost_lower_ptr = NULL;
+  char fromHost_lower_buf[1024];
+  url_mapping *new_mapping = NULL;
+  mapping_type maptype;
+  referer_info *ri;
+  int origLength;
+  int length;
+  int tok_count;
+
+  UrlRewrite::RegexMapping* reg_map;
+  bool is_cur_mapping_regex;
+  const char *type_id_str;
+
+  xptr<char> file_buf(readIntoBuffer(path, modulePrefix, NULL));
+  if (!file_buf) {
+    Warning("can't load remapping configuration file %s", path);
+    return false;
+  }
+
+  Debug("url_rewrite", "[BuildTable] UrlRewrite::BuildTable()");
+
+  for (cur_line = tokLine(file_buf, &tok_state, '\\'); cur_line != NULL;) {
+    errStrBuf[0] = 0;
+    bti.reset();
+
+    // Strip leading whitespace
+    while (*cur_line && isascii(*cur_line) && isspace(*cur_line))
+      ++cur_line;
+
+    if ((cur_line_size = strlen((char *) cur_line)) <= 0) {
+      cur_line = tokLine(NULL, &tok_state, '\\');
+      ++cln;
+      continue;
+    }
+
+    // Strip trailing whitespace
+    cur_line_tmp = cur_line + cur_line_size - 1;
+    while (cur_line_tmp != cur_line && isascii(*cur_line_tmp) && isspace(*cur_line_tmp)) {
+      *cur_line_tmp = '\0';
+      --cur_line_tmp;
+    }
+
+    if ((cur_line_size = strlen((char *) cur_line)) <= 0 || *cur_line == '#' || *cur_line == '\0') {
+      cur_line = tokLine(NULL, &tok_state, '\\');
+      ++cln;
+      continue;
+    }
+
+    Debug("url_rewrite", "[BuildTable] Parsing: \"%s\"", cur_line);
+
+    tok_count = whiteTok.Initialize(cur_line, SHARE_TOKS);
+
+    for (int j = 0; j < tok_count; j++) {
+      if (((char *) whiteTok[j])[0] == '@') {
+        if (((char *) whiteTok[j])[1])
+          bti.argv[bti.argc++] = ats_strdup(&(((char *) whiteTok[j])[1]));
+      } else {
+        bti.paramv[bti.paramc++] = ats_strdup((char *) whiteTok[j]);
+      }
+    }
+
+    // Initial verification for number of arguments
+    if (bti.paramc<1 || (bti.paramc < 3 && bti.paramv[0][0] != '.') || bti.paramc> BUILD_TABLE_MAX_ARGS) {
+      snprintf(errBuf, sizeof(errBuf), "%s Malformed line %d in file %s", modulePrefix, cln + 1, path);
+      errStr = errStrBuf;
+      goto MAP_ERROR;
+    }
+    // just check all major flags/optional arguments
+    bti.remap_optflg = remap_check_option((const char **)bti.argv, bti.argc);
+
+    // Check directive keywords (starting from '.')
+    if (bti.paramv[0][0] == '.') {
+      if ((errStr = remap_parse_directive(&bti, errStrBuf, sizeof(errStrBuf))) != NULL) {
+        snprintf(errBuf, sizeof(errBuf) - 1, "%s Error on line %d - %s", modulePrefix, cln + 1, errStr);
+        errStr = errStrBuf;
+        goto MAP_ERROR;
+      }
+      // We skip the rest of the parsing here.
+      cur_line = tokLine(NULL, &tok_state, '\\');
+      ++cln;
+      continue;
+    }
+
+    is_cur_mapping_regex = (strncasecmp("regex_", bti.paramv[0], 6) == 0);
+    type_id_str = is_cur_mapping_regex ? (bti.paramv[0] + 6) : bti.paramv[0];
+
+    // Check to see whether is a reverse or forward mapping
+    if (!strcasecmp("reverse_map", type_id_str)) {
+      Debug("url_rewrite", "[BuildTable] - REVERSE_MAP");
+      maptype = REVERSE_MAP;
+    } else if (!strcasecmp("map", type_id_str)) {
+      Debug("url_rewrite", "[BuildTable] - %s",
+            ((bti.remap_optflg & REMAP_OPTFLG_MAP_WITH_REFERER) == 0) ? "FORWARD_MAP" : "FORWARD_MAP_REFERER");
+      maptype = ((bti.remap_optflg & REMAP_OPTFLG_MAP_WITH_REFERER) == 0) ? FORWARD_MAP : FORWARD_MAP_REFERER;
+    } else if (!strcasecmp("redirect", type_id_str)) {
+      Debug("url_rewrite", "[BuildTable] - PERMANENT_REDIRECT");
+      maptype = PERMANENT_REDIRECT;
+    } else if (!strcasecmp("redirect_temporary", type_id_str)) {
+      Debug("url_rewrite", "[BuildTable] - TEMPORARY_REDIRECT");
+      maptype = TEMPORARY_REDIRECT;
+    } else if (!strcasecmp("map_with_referer", type_id_str)) {
+      Debug("url_rewrite", "[BuildTable] - FORWARD_MAP_REFERER");
+      maptype = FORWARD_MAP_REFERER;
+    } else if (!strcasecmp("map_with_recv_port", type_id_str)) {
+      Debug("url_rewrite", "[BuildTable] - FORWARD_MAP_WITH_RECV_PORT");
+      maptype = FORWARD_MAP_WITH_RECV_PORT;
+    } else {
+      snprintf(errBuf, sizeof(errBuf) - 1, "%s Unknown mapping type at line %d", modulePrefix, cln + 1);
+      errStr = errStrBuf;
+      goto MAP_ERROR;
+    }
+
+    new_mapping = NEW(new url_mapping(cln));  // use line # for rank for now
+
+    // apply filter rules if we have to
+    if ((errStr = process_filter_opt(new_mapping, &bti, errStrBuf, sizeof(errStrBuf))) != NULL) {
+      goto MAP_ERROR;
+    }
+
+    new_mapping->map_id = 0;
+    if ((bti.remap_optflg & REMAP_OPTFLG_MAP_ID) != 0) {
+      int idx = 0;
+      char *c;
+      int ret = remap_check_option((const char **)bti.argv, bti.argc, REMAP_OPTFLG_MAP_ID, &idx);
+      if (ret & REMAP_OPTFLG_MAP_ID) {
+        c = strchr(bti.argv[idx], (int) '=');
+        new_mapping->map_id = (unsigned int) atoi(++c);
+      }
+    }
+
+    map_from = bti.paramv[1];
+    length = UrlWhack(map_from, &origLength);
+
+    // FIX --- what does this comment mean?
+    //
+    // URL::create modified map_from so keep a point to
+    //   the beginning of the string
+    if ((tmp = (map_from_start = map_from)) != NULL && length > 2 && tmp[length - 1] == '/' && tmp[length - 2] == '/') {
+      new_mapping->unique = true;
+      length -= 2;
+    }
+
+    new_mapping->fromURL.create(NULL);
+    rparse = new_mapping->fromURL.parse_no_path_component_breakdown(tmp, length);
+
+    map_from_start[origLength] = '\0';  // Unwhack
+
+    if (rparse != PARSE_DONE) {
+      errStr = "Malformed From URL";
+      goto MAP_ERROR;
+    }
+
+    map_to = bti.paramv[2];
+    length = UrlWhack(map_to, &origLength);
+    map_to_start = map_to;
+    tmp = map_to;
+
+    new_mapping->toUrl.create(NULL);
+    rparse = new_mapping->toUrl.parse_no_path_component_breakdown(tmp, length);
+    map_to_start[origLength] = '\0';    // Unwhack
+
+    if (rparse != PARSE_DONE) {
+      errStr = "Malformed To URL";
+      goto MAP_ERROR;
+    }
+
+    fromScheme = new_mapping->fromURL.scheme_get(&fromSchemeLen);
+    // If the rule is "/" or just some other relative path
+    //   we need to default the scheme to http
+    if (fromScheme == NULL || fromSchemeLen == 0) {
+      new_mapping->fromURL.scheme_set(URL_SCHEME_HTTP, URL_LEN_HTTP);
+      fromScheme = new_mapping->fromURL.scheme_get(&fromSchemeLen);
+      new_mapping->wildcard_from_scheme = true;
+    }
+    toScheme = new_mapping->toUrl.scheme_get(&toSchemeLen);
+
+    // Include support for HTTPS scheme
+    // includes support for FILE scheme
+    if ((fromScheme != URL_SCHEME_HTTP && fromScheme != URL_SCHEME_HTTPS &&
+         fromScheme != URL_SCHEME_FILE &&
+         fromScheme != URL_SCHEME_TUNNEL) ||
+        (toScheme != URL_SCHEME_HTTP && toScheme != URL_SCHEME_HTTPS &&
+         toScheme != URL_SCHEME_TUNNEL)) {
+      errStr = "Only http, https, and tunnel remappings are supported";
+      goto MAP_ERROR;
+    }
+    // Check if a tag is specified.
+    if (bti.paramv[3] != NULL) {
+      if (maptype == FORWARD_MAP_REFERER) {
+        new_mapping->filter_redirect_url = ats_strdup(bti.paramv[3]);
+        if (!strcasecmp(bti.paramv[3], "<default>") || !strcasecmp(bti.paramv[3], "default") ||
+            !strcasecmp(bti.paramv[3], "<default_redirect_url>") || !strcasecmp(bti.paramv[3], "default_redirect_url"))
+          new_mapping->default_redirect_url = true;
+        new_mapping->redir_chunk_list = redirect_tag_str::parse_format_redirect_url(bti.paramv[3]);
+        for (int j = bti.paramc; j > 4; j--) {
+          if (bti.paramv[j - 1] != NULL) {
+            char refinfo_error_buf[1024];
+            bool refinfo_error = false;
+
+            ri = NEW(new referer_info((char *) bti.paramv[j - 1], &refinfo_error, refinfo_error_buf,
+                                      sizeof(refinfo_error_buf)));
+            if (refinfo_error) {
+              snprintf(errBuf, sizeof(errBuf), "%s Incorrect Referer regular expression \"%s\" at line %d - %s",
+                           modulePrefix, bti.paramv[j - 1], cln + 1, refinfo_error_buf);
+              SignalError(errBuf, alarm_already);
+              delete ri;
+              ri = 0;
+            }
+
+            if (ri && ri->negative) {
+              if (ri->any) {
+                new_mapping->optional_referer = true;   /* referer header is optional */
+                delete ri;
+                ri = 0;
+              } else {
+                new_mapping->negative_referer = true;   /* we have negative referer in list */
+              }
+            }
+            if (ri) {
+              ri->next = new_mapping->referer_list;
+              new_mapping->referer_list = ri;
+            }
+          }
+        }
+      } else {
+        new_mapping->tag = ats_strdup(&(bti.paramv[3][0]));
+      }
+    }
+    // Check to see the fromHost remapping is a relative one
+    fromHost = new_mapping->fromURL.host_get(&fromHostLen);
+    if (fromHost == NULL || fromHostLen <= 0) {
+      if (maptype == FORWARD_MAP || maptype == FORWARD_MAP_REFERER || maptype == FORWARD_MAP_WITH_RECV_PORT) {
+        if (*map_from_start != '/') {
+          errStr = "Relative remappings must begin with a /";
+          goto MAP_ERROR;
+        } else {
+          fromHost = "";
+          fromHostLen = 0;
+        }
+      } else {
+        errStr = "Remap source in reverse mappings requires a hostname";
+        goto MAP_ERROR;
+      }
+    }
+
+    toHost = new_mapping->toUrl.host_get(&toHostLen);
+    if (toHost == NULL || toHostLen <= 0) {
+      errStr = "The remap destinations require a hostname";
+      goto MAP_ERROR;
+    }
+    // Get rid of trailing slashes since they interfere
+    //  with our ability to send redirects
+
+    // You might be tempted to remove these lines but the new
+    // optimized header system will introduce problems.  You
+    // might get two slashes occasionally instead of one because
+    // the rest of the system assumes that trailing slashes have
+    // been removed.
+
+    if (unlikely(fromHostLen >= (int) sizeof(fromHost_lower_buf))) {
+      fromHost_lower = (fromHost_lower_ptr = (char *)ats_malloc(fromHostLen + 1));
+    } else {
+      fromHost_lower = &fromHost_lower_buf[0];
+    }
+    // Canonicalize the hostname by making it lower case
+    memcpy(fromHost_lower, fromHost, fromHostLen);
+    fromHost_lower[fromHostLen] = 0;
+    LowerCaseStr(fromHost_lower);
+
+    // set the normalized string so nobody else has to normalize this
+    new_mapping->fromURL.host_set(fromHost_lower, fromHostLen);
+
+    reg_map = NULL;
+    if (is_cur_mapping_regex) {
+      reg_map = NEW(new UrlRewrite::RegexMapping());
+      if (!process_regex_mapping_config(fromHost_lower, new_mapping, reg_map)) {
+        errStr = "Could not process regex mapping config line";
+        goto MAP_ERROR;
+      }
+      Debug("url_rewrite_regex", "Configured regex rule for host [%s]", fromHost_lower);
+    }
+
+    // If a TS receives a request on a port which is set to tunnel mode
+    // (ie, blind forwarding) and a client connects directly to the TS,
+    // then the TS will use its IPv4 address and remap rules given
+    // to send the request to its proper destination.
+    // See HttpTransact::HandleBlindTunnel().
+    // Therefore, for a remap rule like "map tunnel://hostname..."
+    // in remap.config, we also needs to convert hostname to its IPv4 addr
+    // and gives a new remap rule with the IPv4 addr.
+    if ((maptype == FORWARD_MAP || maptype == FORWARD_MAP_REFERER || maptype == FORWARD_MAP_WITH_RECV_PORT) &&
+        fromScheme == URL_SCHEME_TUNNEL && (fromHost_lower[0]<'0' || fromHost_lower[0]> '9')) {
+      addrinfo* ai_records; // returned records.
+      ip_text_buffer ipb; // buffer for address string conversion.
+      if (0 == getaddrinfo(fromHost_lower, 0, 0, &ai_records)) {
+        for ( addrinfo* ai_spot = ai_records ; ai_spot ; ai_spot = ai_spot->ai_next) {
+          if (ats_is_ip(ai_spot->ai_addr) && !ats_is_ip_any(ai_spot->ai_addr)) {
+            url_mapping *u_mapping;
+
+            ats_ip_ntop(ai_spot->ai_addr, ipb, sizeof ipb);
+            u_mapping = NEW(new url_mapping);
+            u_mapping->fromURL.create(NULL);
+            u_mapping->fromURL.copy(&new_mapping->fromURL);
+            u_mapping->fromURL.host_set(ipb, strlen(ipb));
+            u_mapping->toUrl.create(NULL);
+            u_mapping->toUrl.copy(&new_mapping->toUrl);
+
+            if (bti.paramv[3] != NULL) {
+              u_mapping->tag = ats_strdup(&(bti.paramv[3][0]));
+            }
+
+            if (!rewrite->InsertForwardMapping(maptype, u_mapping, ipb)) {
+              errStr = "Unable to add mapping rule to lookup table";
+              freeaddrinfo(ai_records);
+              goto MAP_ERROR;
+            }
+          }
+        }
+
+        freeaddrinfo(ai_records);
+      }
+    }
+
+    // Check "remap" plugin options and load .so object
+    if ((bti.remap_optflg & REMAP_OPTFLG_PLUGIN) != 0 && (maptype == FORWARD_MAP || maptype == FORWARD_MAP_REFERER ||
+                                                          maptype == FORWARD_MAP_WITH_RECV_PORT)) {
+      if ((remap_check_option((const char **)bti.argv, bti.argc, REMAP_OPTFLG_PLUGIN, &tok_count) & REMAP_OPTFLG_PLUGIN) != 0) {
+        int plugin_found_at = 0;
+        int jump_to_argc = 0;
+
+        // this loads the first plugin
+        if (remap_load_plugin((const char **)bti.argv, bti.argc, new_mapping, errStrBuf, sizeof(errStrBuf), 0, &plugin_found_at)) {
+          Debug("remap_plugin", "Remap plugin load error - %s", errStrBuf[0] ? errStrBuf : "Unknown error");
+          errStr = errStrBuf;
+          goto MAP_ERROR;
+        }
+        //this loads any subsequent plugins (if present)
+        while (plugin_found_at) {
+          jump_to_argc += plugin_found_at;
+          if (remap_load_plugin((const char **)bti.argv, bti.argc, new_mapping, errStrBuf, sizeof(errStrBuf), jump_to_argc, &plugin_found_at)) {
+            Debug("remap_plugin", "Remap plugin load error - %s", errStrBuf[0] ? errStrBuf : "Unknown error");
+            errStr = errStrBuf;
+            goto MAP_ERROR;
+          }
+        }
+      }
+    }
+
+    // Now add the mapping to appropriate container
+    if (!rewrite->InsertMapping(maptype, new_mapping, reg_map, fromHost_lower, is_cur_mapping_regex)) {
+      errStr = "Unable to add mapping rule to lookup table";
+      goto MAP_ERROR;
+    }
+
+    fromHost_lower_ptr = (char *)ats_free_null(fromHost_lower_ptr);
+
+    cur_line = tokLine(NULL, &tok_state, '\\');
+    ++cln;
+    continue;
+
+    // Deal with error / warning scenarios
+  MAP_ERROR:
+    Warning("Could not add rule at line #%d; Aborting!", cln + 1);
+    snprintf(errBuf, sizeof(errBuf), "%s %s at line %d", modulePrefix, errStr, cln + 1);
+    SignalError(errBuf, alarm_already);
+    return 2;
+  }                             /* end of while(cur_line != NULL) */
+
+  return true;
+}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/90f923ef/proxy/http/remap/RemapConfig.h
----------------------------------------------------------------------
diff --git a/proxy/http/remap/RemapConfig.h b/proxy/http/remap/RemapConfig.h
index 8ba9afb..d5aecad 100644
--- a/proxy/http/remap/RemapConfig.h
+++ b/proxy/http/remap/RemapConfig.h
@@ -26,6 +26,8 @@
 
 #include "AclFiltering.h"
 
+class UrlRewrite;
+
 #define BUILD_TABLE_MAX_ARGS 2048
 
 // Remap inline options
@@ -62,11 +64,14 @@ private:
 
 const char *
 remap_parse_directive(BUILD_TABLE_INFO * bti, char * errbuf, size_t errbufsize);
-const char *
 
-remap_validate_filter_args(acl_filter_rule ** rule_pp, char ** argv, int argc, char * errStrBuf, size_t errStrBufSize);
+const char *
+remap_validate_filter_args(acl_filter_rule ** rule_pp, const char ** argv, int argc, char * errStrBuf, size_t errStrBufSize);
 
 unsigned long
-remap_check_option(char *argv[], int argc, unsigned long findmode = 0, int *_ret_idx = NULL, char **argptr = NULL);
+remap_check_option(const char ** argv, int argc, unsigned long findmode = 0, int *_ret_idx = NULL, const char ** argptr = NULL);
+
+bool
+remap_parse_config(const char * path, UrlRewrite * rewrite);
 
 #endif /* REMAPCONFIG_H_E862FB4C_EFFC_4F2A_8BF2_9AB6E1E5E9CF */

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/90f923ef/proxy/http/remap/UrlRewrite.cc
----------------------------------------------------------------------
diff --git a/proxy/http/remap/UrlRewrite.cc b/proxy/http/remap/UrlRewrite.cc
index 1046eac..32c6de6 100644
--- a/proxy/http/remap/UrlRewrite.cc
+++ b/proxy/http/remap/UrlRewrite.cc
@@ -35,37 +35,10 @@
 #include "RemapConfig.h"
 
 #include "ink_string.h"
-#include "ink_cap.h"
 
 #define modulePrefix "[ReverseProxy]"
 
 /**
-  Returns the length of the URL.
-
-  Will replace the terminator with a '/' if this is a full URL and
-  there are no '/' in it after the the host.  This ensures that class
-  URL parses the URL correctly.
-
-*/
-static int
-UrlWhack(char *toWhack, int *origLength)
-{
-  int length = strlen(toWhack);
-  char *tmp;
-  *origLength = length;
-
-  // Check to see if this a full URL
-  tmp = strstr(toWhack, "://");
-  if (tmp != NULL) {
-    if (strchr(tmp + 3, '/') == NULL) {
-      toWhack[length] = '/';
-      length++;
-    }
-  }
-  return length;
-}
-
-/**
   Determines where we are in a situation where a virtual path is
   being mapped to a server home page. If it is, we set a special flag
   instructing us to be on the lookout for the need to send a redirect
@@ -84,33 +57,6 @@ SetHomePageRedirectFlag(url_mapping *new_mapping, URL &new_to_url)
   new_mapping->homePageRedirect = (from_path && !to_path) ? true : false;
 }
 
-static const char *
-process_filter_opt(url_mapping *mp, BUILD_TABLE_INFO *bti, char *errStrBuf, int errStrBufSize)
-{
-  acl_filter_rule *rp, **rpp;
-  const char *errStr = NULL;
-
-  if (unlikely(!mp || !bti || !errStrBuf || errStrBufSize <= 0)) {
-    Debug("url_rewrite", "[process_filter_opt] Invalid argument(s)");
-    return (const char *) "[process_filter_opt] Invalid argument(s)";
-  }
-  for (rp = bti->rules_list; rp; rp = rp->next) {
-    if (rp->active_queue_flag) {
-      Debug("url_rewrite", "[process_filter_opt] Add active main filter \"%s\" (argc=%d)",
-            rp->filter_name ? rp->filter_name : "<NULL>", rp->argc);
-      for (rpp = &mp->filter; *rpp; rpp = &((*rpp)->next));
-      if ((errStr = remap_validate_filter_args(rpp, rp->argv, rp->argc, errStrBuf, errStrBufSize)) != NULL)
-        break;
-    }
-  }
-  if (!errStr && (bti->remap_optflg & REMAP_OPTFLG_ALL_FILTERS) != 0) {
-    Debug("url_rewrite", "[process_filter_opt] Add per remap filter");
-    for (rpp = &mp->filter; *rpp; rpp = &((*rpp)->next));
-    errStr = remap_validate_filter_args(rpp, bti->argv, bti->argc, errStrBuf, errStrBufSize);
-  }
-  return errStr;
-}
-
 //
 // CTOR / DTOR for the UrlRewrite class.
 //
@@ -634,9 +580,9 @@ UrlRewrite::Remap_redirect(HTTPHdr *request_header, URL *redirect_url)
   return NONE;
 }
 
-inline bool
+bool
 UrlRewrite::_addToStore(MappingsStore &store, url_mapping *new_mapping, RegexMapping *reg_map,
-                        char *src_host, bool is_cur_mapping_regex, int &count)
+                        const char * src_host, bool is_cur_mapping_regex, int &count)
 {
   bool retval;
   if (is_cur_mapping_regex) {
@@ -651,6 +597,78 @@ UrlRewrite::_addToStore(MappingsStore &store, url_mapping *new_mapping, RegexMap
   return retval;
 }
 
+bool
+UrlRewrite::InsertMapping(mapping_type maptype, url_mapping *new_mapping, RegexMapping *reg_map,
+                        const char * src_host, bool is_cur_mapping_regex)
+{
+  bool success = false;
+
+  // Now add the mapping to appropriate container
+  switch (maptype) {
+  case FORWARD_MAP:
+  case FORWARD_MAP_REFERER:
+    success = _addToStore(forward_mappings, new_mapping, reg_map, src_host,
+                                  is_cur_mapping_regex, num_rules_forward);
+    if (success) {
+      // @todo: is this applicable to regex mapping too?
+      SetHomePageRedirectFlag(new_mapping, new_mapping->toUrl);
+    }
+    break;
+  case REVERSE_MAP:
+    success = _addToStore(reverse_mappings, new_mapping, reg_map, src_host,
+                             is_cur_mapping_regex, num_rules_reverse);
+    new_mapping->homePageRedirect = false;
+    break;
+  case PERMANENT_REDIRECT:
+    success = _addToStore(permanent_redirects, new_mapping, reg_map, src_host,
+                             is_cur_mapping_regex, num_rules_redirect_permanent);
+    break;
+  case TEMPORARY_REDIRECT:
+    success = _addToStore(temporary_redirects, new_mapping, reg_map, src_host,
+                             is_cur_mapping_regex, num_rules_redirect_temporary);
+    break;
+  case FORWARD_MAP_WITH_RECV_PORT:
+    success = _addToStore(forward_mappings_with_recv_port, new_mapping, reg_map, src_host,
+                             is_cur_mapping_regex, num_rules_forward_with_recv_port);
+    break;
+  default:
+    // 'default' required to avoid compiler warning; unsupported map
+    // type would have been dealt with much before this
+    return false;
+  }
+
+  return success;
+}
+
+bool
+UrlRewrite::InsertForwardMapping(mapping_type maptype, url_mapping * mapping, const char * src_host)
+{
+  bool success;
+
+  if (maptype == FORWARD_MAP_WITH_RECV_PORT) {
+    success = TableInsert(forward_mappings_with_recv_port.hash_lookup, mapping, src_host);
+  } else {
+    success = TableInsert(forward_mappings.hash_lookup, mapping, src_host);
+  }
+
+  if (success) {
+    switch (maptype) {
+      case FORWARD_MAP:
+      case FORWARD_MAP_REFERER:
+      case FORWARD_MAP_WITH_RECV_PORT:
+        SetHomePageRedirectFlag(mapping, mapping->toUrl);
+        break;
+      default:
+        break;
+    }
+
+    (maptype != FORWARD_MAP_WITH_RECV_PORT) ? ++num_rules_forward
+                                            : ++num_rules_forward_with_recv_port;
+  }
+
+  return success;
+}
+
 /**
   Reads the configuration file and creates a new hash table.
 
@@ -681,8 +699,9 @@ UrlRewrite::BuildTable()
   temporary_redirects.hash_lookup = ink_hash_table_create(InkHashTableKeyType_String);
   forward_mappings_with_recv_port.hash_lookup = ink_hash_table_create(InkHashTableKeyType_String);
 
-  if (!this->_parseRemapConfigFile(config_file_path, &bti)) {
+  if (!remap_parse_config(config_file_path, this)) {
     // XXX handle file reload error
+    return 3;
   }
 
   // Add the mapping for backdoor urls if enabled.
@@ -739,434 +758,6 @@ UrlRewrite::BuildTable()
   return 0;
 }
 
-bool
-UrlRewrite::_parseRemapConfigFile(const char * config_file_path, BUILD_TABLE_INFO * bti)
-{
-  char errBuf[1024], errStrBuf[1024];
-  Tokenizer whiteTok(" \t");
-  bool alarm_already = false;
-  const char *errStr;
-
-  // Vars to parse line in file
-  char *tok_state, *cur_line, *cur_line_tmp;
-  int rparse, cur_line_size, cln = 0;        // Our current line number
-
-  // Vars to build the mapping
-  const char *fromScheme, *toScheme;
-  int fromSchemeLen, toSchemeLen;
-  const char *fromHost, *toHost;
-  int fromHostLen, toHostLen;
-  char *map_from, *map_from_start;
-  char *map_to, *map_to_start;
-  const char *tmp;              // Appease the DEC compiler
-  char *fromHost_lower = NULL;
-  char *fromHost_lower_ptr = NULL;
-  char fromHost_lower_buf[1024];
-  url_mapping *new_mapping = NULL;
-  mapping_type maptype;
-  referer_info *ri;
-  int origLength;
-  int length;
-  int tok_count;
-
-  RegexMapping* reg_map;
-  bool is_cur_mapping_regex;
-  const char *type_id_str;
-  bool add_result;
-
-  xptr<char> file_buf(readIntoBuffer(config_file_path, modulePrefix, NULL));
-  if (!file_buf) {
-    Warning("Can't load remapping configuration file - %s", config_file_path);
-    return false;
-  }
-
-  Debug("url_rewrite", "[BuildTable] UrlRewrite::BuildTable()");
-
-  for (cur_line = tokLine(file_buf, &tok_state, '\\'); cur_line != NULL;) {
-    errStrBuf[0] = 0;
-    bti->reset();
-
-    // Strip leading whitespace
-    while (*cur_line && isascii(*cur_line) && isspace(*cur_line))
-      ++cur_line;
-
-    if ((cur_line_size = strlen((char *) cur_line)) <= 0) {
-      cur_line = tokLine(NULL, &tok_state, '\\');
-      ++cln;
-      continue;
-    }
-
-    // Strip trailing whitespace
-    cur_line_tmp = cur_line + cur_line_size - 1;
-    while (cur_line_tmp != cur_line && isascii(*cur_line_tmp) && isspace(*cur_line_tmp)) {
-      *cur_line_tmp = '\0';
-      --cur_line_tmp;
-    }
-
-    if ((cur_line_size = strlen((char *) cur_line)) <= 0 || *cur_line == '#' || *cur_line == '\0') {
-      cur_line = tokLine(NULL, &tok_state, '\\');
-      ++cln;
-      continue;
-    }
-
-    Debug("url_rewrite", "[BuildTable] Parsing: \"%s\"", cur_line);
-
-    tok_count = whiteTok.Initialize(cur_line, SHARE_TOKS);
-
-    for (int j = 0; j < tok_count; j++) {
-      if (((char *) whiteTok[j])[0] == '@') {
-        if (((char *) whiteTok[j])[1])
-          bti->argv[bti->argc++] = ats_strdup(&(((char *) whiteTok[j])[1]));
-      } else {
-        bti->paramv[bti->paramc++] = ats_strdup((char *) whiteTok[j]);
-      }
-    }
-
-    // Initial verification for number of arguments
-    if (bti->paramc<1 || (bti->paramc < 3 && bti->paramv[0][0] != '.') || bti->paramc> BUILD_TABLE_MAX_ARGS) {
-      snprintf(errBuf, sizeof(errBuf), "%s Malformed line %d in file %s", modulePrefix, cln + 1, config_file_path);
-      errStr = errStrBuf;
-      goto MAP_ERROR;
-    }
-    // just check all major flags/optional arguments
-    bti->remap_optflg = remap_check_option(bti->argv, bti->argc);
-
-    // Check directive keywords (starting from '.')
-    if (bti->paramv[0][0] == '.') {
-      if ((errStr = remap_parse_directive(bti, errStrBuf, sizeof(errStrBuf))) != NULL) {
-        snprintf(errBuf, sizeof(errBuf) - 1, "%s Error on line %d - %s", modulePrefix, cln + 1, errStr);
-        errStr = errStrBuf;
-        goto MAP_ERROR;
-      }
-      // We skip the rest of the parsing here.
-      cur_line = tokLine(NULL, &tok_state, '\\');
-      ++cln;
-      continue;
-    }
-
-    is_cur_mapping_regex = (strncasecmp("regex_", bti->paramv[0], 6) == 0);
-    type_id_str = is_cur_mapping_regex ? (bti->paramv[0] + 6) : bti->paramv[0];
-
-    // Check to see whether is a reverse or forward mapping
-    if (!strcasecmp("reverse_map", type_id_str)) {
-      Debug("url_rewrite", "[BuildTable] - REVERSE_MAP");
-      maptype = REVERSE_MAP;
-    } else if (!strcasecmp("map", type_id_str)) {
-      Debug("url_rewrite", "[BuildTable] - %s",
-            ((bti->remap_optflg & REMAP_OPTFLG_MAP_WITH_REFERER) == 0) ? "FORWARD_MAP" : "FORWARD_MAP_REFERER");
-      maptype = ((bti->remap_optflg & REMAP_OPTFLG_MAP_WITH_REFERER) == 0) ? FORWARD_MAP : FORWARD_MAP_REFERER;
-    } else if (!strcasecmp("redirect", type_id_str)) {
-      Debug("url_rewrite", "[BuildTable] - PERMANENT_REDIRECT");
-      maptype = PERMANENT_REDIRECT;
-    } else if (!strcasecmp("redirect_temporary", type_id_str)) {
-      Debug("url_rewrite", "[BuildTable] - TEMPORARY_REDIRECT");
-      maptype = TEMPORARY_REDIRECT;
-    } else if (!strcasecmp("map_with_referer", type_id_str)) {
-      Debug("url_rewrite", "[BuildTable] - FORWARD_MAP_REFERER");
-      maptype = FORWARD_MAP_REFERER;
-    } else if (!strcasecmp("map_with_recv_port", type_id_str)) {
-      Debug("url_rewrite", "[BuildTable] - FORWARD_MAP_WITH_RECV_PORT");
-      maptype = FORWARD_MAP_WITH_RECV_PORT;
-    } else {
-      snprintf(errBuf, sizeof(errBuf) - 1, "%s Unknown mapping type at line %d", modulePrefix, cln + 1);
-      errStr = errStrBuf;
-      goto MAP_ERROR;
-    }
-
-    new_mapping = NEW(new url_mapping(cln));  // use line # for rank for now
-
-    // apply filter rules if we have to
-    if ((errStr = process_filter_opt(new_mapping, bti, errStrBuf, sizeof(errStrBuf))) != NULL) {
-      goto MAP_ERROR;
-    }
-
-    new_mapping->map_id = 0;
-    if ((bti->remap_optflg & REMAP_OPTFLG_MAP_ID) != 0) {
-      int idx = 0;
-      char *c;
-      int ret = remap_check_option(bti->argv, bti->argc, REMAP_OPTFLG_MAP_ID, &idx);
-      if (ret & REMAP_OPTFLG_MAP_ID) {
-        c = strchr(bti->argv[idx], (int) '=');
-        new_mapping->map_id = (unsigned int) atoi(++c);
-      }
-    }
-
-    map_from = bti->paramv[1];
-    length = UrlWhack(map_from, &origLength);
-
-    // FIX --- what does this comment mean?
-    //
-    // URL::create modified map_from so keep a point to
-    //   the beginning of the string
-    if ((tmp = (map_from_start = map_from)) != NULL && length > 2 && tmp[length - 1] == '/' && tmp[length - 2] == '/') {
-      new_mapping->unique = true;
-      length -= 2;
-    }
-
-    new_mapping->fromURL.create(NULL);
-    rparse = new_mapping->fromURL.parse_no_path_component_breakdown(tmp, length);
-
-    map_from_start[origLength] = '\0';  // Unwhack
-
-    if (rparse != PARSE_DONE) {
-      errStr = "Malformed From URL";
-      goto MAP_ERROR;
-    }
-
-    map_to = bti->paramv[2];
-    length = UrlWhack(map_to, &origLength);
-    map_to_start = map_to;
-    tmp = map_to;
-
-    new_mapping->toUrl.create(NULL);
-    rparse = new_mapping->toUrl.parse_no_path_component_breakdown(tmp, length);
-    map_to_start[origLength] = '\0';    // Unwhack
-
-    if (rparse != PARSE_DONE) {
-      errStr = "Malformed To URL";
-      goto MAP_ERROR;
-    }
-
-    fromScheme = new_mapping->fromURL.scheme_get(&fromSchemeLen);
-    // If the rule is "/" or just some other relative path
-    //   we need to default the scheme to http
-    if (fromScheme == NULL || fromSchemeLen == 0) {
-      new_mapping->fromURL.scheme_set(URL_SCHEME_HTTP, URL_LEN_HTTP);
-      fromScheme = new_mapping->fromURL.scheme_get(&fromSchemeLen);
-      new_mapping->wildcard_from_scheme = true;
-    }
-    toScheme = new_mapping->toUrl.scheme_get(&toSchemeLen);
-
-    // Include support for HTTPS scheme
-    // includes support for FILE scheme
-    if ((fromScheme != URL_SCHEME_HTTP && fromScheme != URL_SCHEME_HTTPS &&
-         fromScheme != URL_SCHEME_FILE &&
-         fromScheme != URL_SCHEME_TUNNEL) ||
-        (toScheme != URL_SCHEME_HTTP && toScheme != URL_SCHEME_HTTPS &&
-         toScheme != URL_SCHEME_TUNNEL)) {
-      errStr = "Only http, https, and tunnel remappings are supported";
-      goto MAP_ERROR;
-    }
-    // Check if a tag is specified.
-    if (bti->paramv[3] != NULL) {
-      if (maptype == FORWARD_MAP_REFERER) {
-        new_mapping->filter_redirect_url = ats_strdup(bti->paramv[3]);
-        if (!strcasecmp(bti->paramv[3], "<default>") || !strcasecmp(bti->paramv[3], "default") ||
-            !strcasecmp(bti->paramv[3], "<default_redirect_url>") || !strcasecmp(bti->paramv[3], "default_redirect_url"))
-          new_mapping->default_redirect_url = true;
-        new_mapping->redir_chunk_list = redirect_tag_str::parse_format_redirect_url(bti->paramv[3]);
-        for (int j = bti->paramc; j > 4; j--) {
-          if (bti->paramv[j - 1] != NULL) {
-            char refinfo_error_buf[1024];
-            bool refinfo_error = false;
-
-            ri = NEW(new referer_info((char *) bti->paramv[j - 1], &refinfo_error, refinfo_error_buf,
-                                      sizeof(refinfo_error_buf)));
-            if (refinfo_error) {
-              snprintf(errBuf, sizeof(errBuf), "%s Incorrect Referer regular expression \"%s\" at line %d - %s",
-                           modulePrefix, bti->paramv[j - 1], cln + 1, refinfo_error_buf);
-              SignalError(errBuf, alarm_already);
-              delete ri;
-              ri = 0;
-            }
-
-            if (ri && ri->negative) {
-              if (ri->any) {
-                new_mapping->optional_referer = true;   /* referer header is optional */
-                delete ri;
-                ri = 0;
-              } else {
-                new_mapping->negative_referer = true;   /* we have negative referer in list */
-              }
-            }
-            if (ri) {
-              ri->next = new_mapping->referer_list;
-              new_mapping->referer_list = ri;
-            }
-          }
-        }
-      } else {
-        new_mapping->tag = ats_strdup(&(bti->paramv[3][0]));
-      }
-    }
-    // Check to see the fromHost remapping is a relative one
-    fromHost = new_mapping->fromURL.host_get(&fromHostLen);
-    if (fromHost == NULL || fromHostLen <= 0) {
-      if (maptype == FORWARD_MAP || maptype == FORWARD_MAP_REFERER || maptype == FORWARD_MAP_WITH_RECV_PORT) {
-        if (*map_from_start != '/') {
-          errStr = "Relative remappings must begin with a /";
-          goto MAP_ERROR;
-        } else {
-          fromHost = "";
-          fromHostLen = 0;
-        }
-      } else {
-        errStr = "Remap source in reverse mappings requires a hostname";
-        goto MAP_ERROR;
-      }
-    }
-
-    toHost = new_mapping->toUrl.host_get(&toHostLen);
-    if (toHost == NULL || toHostLen <= 0) {
-      errStr = "The remap destinations require a hostname";
-      goto MAP_ERROR;
-    }
-    // Get rid of trailing slashes since they interfere
-    //  with our ability to send redirects
-
-    // You might be tempted to remove these lines but the new
-    // optimized header system will introduce problems.  You
-    // might get two slashes occasionally instead of one because
-    // the rest of the system assumes that trailing slashes have
-    // been removed.
-
-    if (unlikely(fromHostLen >= (int) sizeof(fromHost_lower_buf))) {
-      fromHost_lower = (fromHost_lower_ptr = (char *)ats_malloc(fromHostLen + 1));
-    } else {
-      fromHost_lower = &fromHost_lower_buf[0];
-    }
-    // Canonicalize the hostname by making it lower case
-    memcpy(fromHost_lower, fromHost, fromHostLen);
-    fromHost_lower[fromHostLen] = 0;
-    LowerCaseStr(fromHost_lower);
-
-    // set the normalized string so nobody else has to normalize this
-    new_mapping->fromURL.host_set(fromHost_lower, fromHostLen);
-
-    reg_map = NULL;
-    if (is_cur_mapping_regex) {
-      reg_map = NEW(new RegexMapping);
-      if (!_processRegexMappingConfig(fromHost_lower, new_mapping, reg_map)) {
-        errStr = "Could not process regex mapping config line";
-        goto MAP_ERROR;
-      }
-      Debug("url_rewrite_regex", "Configured regex rule for host [%s]", fromHost_lower);
-    }
-
-    // If a TS receives a request on a port which is set to tunnel mode
-    // (ie, blind forwarding) and a client connects directly to the TS,
-    // then the TS will use its IPv4 address and remap rules given
-    // to send the request to its proper destination.
-    // See HttpTransact::HandleBlindTunnel().
-    // Therefore, for a remap rule like "map tunnel://hostname..."
-    // in remap.config, we also needs to convert hostname to its IPv4 addr
-    // and gives a new remap rule with the IPv4 addr.
-    if ((maptype == FORWARD_MAP || maptype == FORWARD_MAP_REFERER || maptype == FORWARD_MAP_WITH_RECV_PORT) &&
-        fromScheme == URL_SCHEME_TUNNEL && (fromHost_lower[0]<'0' || fromHost_lower[0]> '9')) {
-      addrinfo* ai_records; // returned records.
-      ip_text_buffer ipb; // buffer for address string conversion.
-      if (0 == getaddrinfo(fromHost_lower, 0, 0, &ai_records)) {
-        for ( addrinfo* ai_spot = ai_records ; ai_spot ; ai_spot = ai_spot->ai_next) {
-          if (ats_is_ip(ai_spot->ai_addr) && !ats_is_ip_any(ai_spot->ai_addr)) {
-            url_mapping *u_mapping;
-
-            ats_ip_ntop(ai_spot->ai_addr, ipb, sizeof ipb);
-            u_mapping = NEW(new url_mapping);
-            u_mapping->fromURL.create(NULL);
-            u_mapping->fromURL.copy(&new_mapping->fromURL);
-            u_mapping->fromURL.host_set(ipb, strlen(ipb));
-            u_mapping->toUrl.create(NULL);
-            u_mapping->toUrl.copy(&new_mapping->toUrl);
-
-            if (bti->paramv[3] != NULL) {
-              u_mapping->tag = ats_strdup(&(bti->paramv[3][0]));
-            }
-
-            bool insert_result = (maptype != FORWARD_MAP_WITH_RECV_PORT) ? TableInsert(forward_mappings.hash_lookup, u_mapping, ipb)
-                                                                        : TableInsert(forward_mappings_with_recv_port.hash_lookup, u_mapping, ipb);
-            if (!insert_result) {
-              errStr = "Unable to add mapping rule to lookup table";
-              goto MAP_ERROR;
-            }
-
-            (maptype != FORWARD_MAP_WITH_RECV_PORT) ? ++num_rules_forward : ++num_rules_forward_with_recv_port;
-            SetHomePageRedirectFlag(u_mapping, u_mapping->toUrl);
-          }
-        }
-        freeaddrinfo(ai_records);
-      }
-    }
-
-    // Check "remap" plugin options and load .so object
-    if ((bti->remap_optflg & REMAP_OPTFLG_PLUGIN) != 0 && (maptype == FORWARD_MAP || maptype == FORWARD_MAP_REFERER ||
-                                                          maptype == FORWARD_MAP_WITH_RECV_PORT)) {
-      if ((remap_check_option(bti->argv, bti->argc, REMAP_OPTFLG_PLUGIN, &tok_count) & REMAP_OPTFLG_PLUGIN) != 0) {
-        int plugin_found_at = 0;
-        int jump_to_argc = 0;
-
-        // this loads the first plugin
-        if (load_remap_plugin(bti->argv, bti->argc, new_mapping, errStrBuf, sizeof(errStrBuf), 0, &plugin_found_at)) {
-          Debug("remap_plugin", "Remap plugin load error - %s", errStrBuf[0] ? errStrBuf : "Unknown error");
-          errStr = errStrBuf;
-          goto MAP_ERROR;
-        }
-        //this loads any subsequent plugins (if present)
-        while (plugin_found_at) {
-          jump_to_argc += plugin_found_at;
-          if (load_remap_plugin(bti->argv, bti->argc, new_mapping, errStrBuf, sizeof(errStrBuf), jump_to_argc, &plugin_found_at)) {
-            Debug("remap_plugin", "Remap plugin load error - %s", errStrBuf[0] ? errStrBuf : "Unknown error");
-            errStr = errStrBuf;
-            goto MAP_ERROR;
-          }
-        }
-      }
-    }
-
-    // Now add the mapping to appropriate container
-    add_result = false;
-    switch (maptype) {
-    case FORWARD_MAP:
-    case FORWARD_MAP_REFERER:
-      if ((add_result = _addToStore(forward_mappings, new_mapping, reg_map, fromHost_lower,
-                                    is_cur_mapping_regex, num_rules_forward)) == true) {
-        // @todo: is this applicable to regex mapping too?
-        SetHomePageRedirectFlag(new_mapping, new_mapping->toUrl);
-      }
-      break;
-    case REVERSE_MAP:
-      add_result = _addToStore(reverse_mappings, new_mapping, reg_map, fromHost_lower,
-                               is_cur_mapping_regex, num_rules_reverse);
-      new_mapping->homePageRedirect = false;
-      break;
-    case PERMANENT_REDIRECT:
-      add_result = _addToStore(permanent_redirects, new_mapping, reg_map, fromHost_lower,
-                               is_cur_mapping_regex, num_rules_redirect_permanent);
-      break;
-    case TEMPORARY_REDIRECT:
-      add_result = _addToStore(temporary_redirects, new_mapping, reg_map, fromHost_lower,
-                               is_cur_mapping_regex, num_rules_redirect_temporary);
-      break;
-    case FORWARD_MAP_WITH_RECV_PORT:
-      add_result = _addToStore(forward_mappings_with_recv_port, new_mapping, reg_map, fromHost_lower,
-                               is_cur_mapping_regex, num_rules_forward_with_recv_port);
-      break;
-    default:
-      // 'default' required to avoid compiler warning; unsupported map
-      // type would have been dealt with much before this
-      break;
-    }
-    if (!add_result) {
-      errStr = "Unable to add mapping rule to lookup table";
-      goto MAP_ERROR;
-    }
-
-    fromHost_lower_ptr = (char *)ats_free_null(fromHost_lower_ptr);
-
-    cur_line = tokLine(NULL, &tok_state, '\\');
-    ++cln;
-    continue;
-
-    // Deal with error / warning scenarios
-  MAP_ERROR:
-    Warning("Could not add rule at line #%d; Aborting!", cln + 1);
-    snprintf(errBuf, sizeof(errBuf), "%s %s at line %d", modulePrefix, errStr, cln + 1);
-    SignalError(errBuf, alarm_already);
-    return 2;
-  }                             /* end of while(cur_line != NULL) */
-
-  return true;
-}
-
 /**
   Inserts arg mapping in h_table with key src_host chaining the mapping
   of existing entries bound to src_host if necessary.
@@ -1201,210 +792,6 @@ UrlRewrite::TableInsert(InkHashTable *h_table, url_mapping *mapping, const char
   return true;
 }
 
-int
-UrlRewrite::load_remap_plugin(char *argv[], int argc, url_mapping *mp, char *errbuf, int errbufsize, int jump_to_argc,
-                              int *plugin_found_at)
-{
-  TSRemapInterface ri;
-  struct stat stat_buf;
-  remap_plugin_info *pi;
-  char *c, *err, tmpbuf[2048], *parv[1024], default_path[PATH_NAME_MAX];
-  char *new_argv[1024];
-  int idx = 0, retcode = 0;
-  int parc = 0;
-
-  *plugin_found_at = 0;
-
-  memset(parv, 0, sizeof(parv));
-  memset(new_argv, 0, sizeof(new_argv));
-  tmpbuf[0] = 0;
-
-  if (jump_to_argc != 0) {
-    argc -= jump_to_argc;
-    int i = 0;
-    while (argv[i + jump_to_argc]) {
-      new_argv[i] = argv[i + jump_to_argc];
-      i++;
-    }
-    argv = new_argv;
-    if (!remap_check_option(argv, argc, REMAP_OPTFLG_PLUGIN, &idx)) {
-      return -1;
-    }
-  } else {
-    if (unlikely(!mp || (remap_check_option(argv, argc, REMAP_OPTFLG_PLUGIN, &idx) & REMAP_OPTFLG_PLUGIN) == 0)) {
-      snprintf(errbuf, errbufsize, "Can't find remap plugin keyword or \"url_mapping\" is NULL");
-      return -1;                /* incorrect input data - almost impossible case */
-    }
-  }
-
-  if (unlikely((c = strchr(argv[idx], (int) '=')) == NULL || !(*(++c)))) {
-    snprintf(errbuf, errbufsize, "Can't find remap plugin file name in \"@%s\"", argv[idx]);
-    return -2;                  /* incorrect input data */
-  }
-
-  if (stat(c, &stat_buf) != 0) {
-    const char *plugin_default_path = TSPluginDirGet();
-
-    // Try with the plugin path instead
-    if (strlen(c) + strlen(plugin_default_path) > (PATH_NAME_MAX - 1)) {
-      Debug("remap_plugin", "way too large a path specified for remap plugin");
-      return -3;
-    }
-
-    snprintf(default_path, PATH_NAME_MAX, "%s/%s", plugin_default_path, c);
-    Debug("remap_plugin", "attempting to stat default plugin path: %s", default_path);
-
-    if (stat(default_path, &stat_buf) == 0) {
-      Debug("remap_plugin", "stat successful on %s using that", default_path);
-      c = &default_path[0];
-    } else {
-      snprintf(errbuf, errbufsize, "Can't find remap plugin file \"%s\"", c);
-      return -3;
-    }
-  }
-
-  Debug("remap_plugin", "using path %s for plugin", c);
-
-  if (!remap_pi_list || (pi = remap_pi_list->find_by_path(c)) == 0) {
-    pi = NEW(new remap_plugin_info(c));
-    if (!remap_pi_list) {
-      remap_pi_list = pi;
-    } else {
-      remap_pi_list->add_to_list(pi);
-    }
-    Debug("remap_plugin", "New remap plugin info created for \"%s\"", c);
-
-    if ((pi->dlh = dlopen(c, RTLD_NOW)) == NULL) {
-#if defined(freebsd) || defined(openbsd)
-      err = (char *)dlerror();
-#else
-      err = dlerror();
-#endif
-      snprintf(errbuf, errbufsize, "Can't load plugin \"%s\" - %s", c, err ? err : "Unknown dlopen() error");
-      return -4;
-    }
-    pi->fp_tsremap_init = (remap_plugin_info::_tsremap_init *) dlsym(pi->dlh, TSREMAP_FUNCNAME_INIT);
-    pi->fp_tsremap_done = (remap_plugin_info::_tsremap_done *) dlsym(pi->dlh, TSREMAP_FUNCNAME_DONE);
-    pi->fp_tsremap_new_instance = (remap_plugin_info::_tsremap_new_instance *) dlsym(pi->dlh, TSREMAP_FUNCNAME_NEW_INSTANCE);
-    pi->fp_tsremap_delete_instance = (remap_plugin_info::_tsremap_delete_instance *) dlsym(pi->dlh, TSREMAP_FUNCNAME_DELETE_INSTANCE);
-    pi->fp_tsremap_do_remap = (remap_plugin_info::_tsremap_do_remap *) dlsym(pi->dlh, TSREMAP_FUNCNAME_DO_REMAP);
-    pi->fp_tsremap_os_response = (remap_plugin_info::_tsremap_os_response *) dlsym(pi->dlh, TSREMAP_FUNCNAME_OS_RESPONSE);
-
-    if (!pi->fp_tsremap_init) {
-      snprintf(errbuf, errbufsize, "Can't find \"%s\" function in remap plugin \"%s\"", TSREMAP_FUNCNAME_INIT, c);
-      retcode = -10;
-    } else if (!pi->fp_tsremap_new_instance) {
-      snprintf(errbuf, errbufsize, "Can't find \"%s\" function in remap plugin \"%s\"",
-                   TSREMAP_FUNCNAME_NEW_INSTANCE, c);
-      retcode = -11;
-    } else if (!pi->fp_tsremap_do_remap) {
-      snprintf(errbuf, errbufsize, "Can't find \"%s\" function in remap plugin \"%s\"", TSREMAP_FUNCNAME_DO_REMAP, c);
-      retcode = -12;
-    }
-    if (retcode) {
-      if (errbuf && errbufsize > 0)
-        Debug("remap_plugin", "%s", errbuf);
-      dlclose(pi->dlh);
-      pi->dlh = NULL;
-      return retcode;
-    }
-    memset(&ri, 0, sizeof(ri));
-    ri.size = sizeof(ri);
-    ri.tsremap_version = TSREMAP_VERSION;
-
-    // elevate the access to read files as root if compiled with capabilities, if not
-    // change the effective user to root
-    {
-      uint32_t elevate_access = 0;
-      REC_ReadConfigInteger(elevate_access, "proxy.config.plugin.load_elevated");
-      ElevateAccess access(elevate_access != 0);
-
-      if (pi->fp_tsremap_init(&ri, tmpbuf, sizeof(tmpbuf) - 1) != TS_SUCCESS) {
-        Warning("Failed to initialize plugin %s (non-zero retval) ... bailing out", pi->path);
-        return -5;
-      }
-    } // done elevating access
-    Debug("remap_plugin", "Remap plugin \"%s\" - initialization completed", c);
-  }
-
-  if (!pi->dlh) {
-    snprintf(errbuf, errbufsize, "Can't load plugin \"%s\"", c);
-    return -6;
-  }
-
-  if ((err = mp->fromURL.string_get(NULL)) == NULL) {
-    snprintf(errbuf, errbufsize, "Can't load fromURL from URL class");
-    return -7;
-  }
-  parv[parc++] = ats_strdup(err);
-  ats_free(err);
-
-  if ((err = mp->toUrl.string_get(NULL)) == NULL) {
-    snprintf(errbuf, errbufsize, "Can't load toURL from URL class");
-    return -7;
-  }
-  parv[parc++] = ats_strdup(err);
-  ats_free(err);
-
-  bool plugin_encountered = false;
-  // how many plugin parameters we have for this remapping
-  for (idx = 0; idx < argc && parc < (int) ((sizeof(parv) / sizeof(char *)) - 1); idx++) {
-
-    if (plugin_encountered && !strncasecmp("plugin=", argv[idx], 7) && argv[idx][7]) {
-      *plugin_found_at = idx;
-      break;                    //if there is another plugin, lets deal with that later
-    }
-
-    if (!strncasecmp("plugin=", argv[idx], 7)) {
-      plugin_encountered = true;
-    }
-
-    if (!strncasecmp("pparam=", argv[idx], 7) && argv[idx][7]) {
-      parv[parc++] = &(argv[idx][7]);
-    }
-  }
-
-  Debug("url_rewrite", "Viewing all parameters for config line");
-  for (int k = 0; k < argc; k++) {
-    Debug("url_rewrite", "Argument %d: %s", k, argv[k]);
-  }
-
-  Debug("url_rewrite", "Viewing parsed plugin parameters for %s: [%d]", pi->path, *plugin_found_at);
-  for (int k = 0; k < parc; k++) {
-    Debug("url_rewrite", "Argument %d: %s", k, parv[k]);
-  }
-
-  void* ih;
-
-  Debug("remap_plugin", "creating new plugin instance");
-
-  TSReturnCode res = TS_ERROR;
-  // elevate the access to read files as root if compiled with capabilities, if not
-  // change the effective user to root
-  {
-    uint32_t elevate_access = 0;
-    REC_ReadConfigInteger(elevate_access, "proxy.config.plugin.load_elevated");
-    ElevateAccess access(elevate_access != 0);
-    res = pi->fp_tsremap_new_instance(parc, parv, &ih, tmpbuf, sizeof(tmpbuf) - 1);
-  } // done elevating access
-
-  Debug("remap_plugin", "done creating new plugin instance");
-
-  ats_free(parv[0]);               // fromURL
-  ats_free(parv[1]);               // toURL
-
-  if (res != TS_SUCCESS) {
-    snprintf(errbuf, errbufsize, "Can't create new remap instance for plugin \"%s\" - %s", c,
-                 tmpbuf[0] ? tmpbuf : "Unknown plugin error");
-    Warning("Failed to create new instance for plugin %s (not a TS_SUCCESS return)", pi->path);
-    return -8;
-  }
-
-  mp->add_plugin(pi, ih);
-
-  return 0;
-}
-
 /**  First looks up the hash table for "simple" mappings and then the
      regex mappings.  Only higher-ranked regex mappings are examined if
      a hash mapping is found; or else all regex mappings are examined
@@ -1601,98 +988,3 @@ UrlRewrite::_destroyList(RegexMappingList &mappings)
   }
   mappings.clear();
 }
-
-/** will process the regex mapping configuration and create objects in
-    output argument reg_map. It assumes existing data in reg_map is
-    inconsequential and will be perfunctorily null-ed;
-*/
-bool
-UrlRewrite::_processRegexMappingConfig(const char *from_host_lower, url_mapping *new_mapping,
-                                       RegexMapping *reg_map)
-{
-  const char *str;
-  int str_index;
-  const char *to_host;
-  int to_host_len;
-  int substitution_id;
-  int substitution_count = 0;
-
-  reg_map->re = NULL;
-  reg_map->re_extra = NULL;
-  reg_map->to_url_host_template = NULL;
-  reg_map->to_url_host_template_len = 0;
-  reg_map->n_substitutions = 0;
-
-  reg_map->url_map = new_mapping;
-
-  // using from_host_lower (and not new_mapping->fromURL.host_get())
-  // as this one will be NULL-terminated (required by pcre_compile)
-  reg_map->re = pcre_compile(from_host_lower, 0, &str, &str_index, NULL);
-  if (reg_map->re == NULL) {
-    Warning("pcre_compile failed! Regex has error starting at %s", from_host_lower + str_index);
-    goto lFail;
-  }
-
-  reg_map->re_extra = pcre_study(reg_map->re, 0, &str);
-  if ((reg_map->re_extra == NULL) && (str != NULL)) {
-    Warning("pcre_study failed with message [%s]", str);
-    goto lFail;
-  }
-
-  int n_captures;
-  if (pcre_fullinfo(reg_map->re, reg_map->re_extra, PCRE_INFO_CAPTURECOUNT, &n_captures) != 0) {
-    Warning("pcre_fullinfo failed!");
-    goto lFail;
-  }
-  if (n_captures >= MAX_REGEX_SUBS) { // off by one for $0 (implicit capture)
-    Warning("Regex has %d capturing subpatterns (including entire regex); Max allowed: %d",
-            n_captures + 1, MAX_REGEX_SUBS);
-    goto lFail;
-  }
-
-  to_host = new_mapping->toUrl.host_get(&to_host_len);
-  for (int i = 0; i < (to_host_len - 1); ++i) {
-    if (to_host[i] == '$') {
-      if (substitution_count > MAX_REGEX_SUBS) {
-        Warning("Cannot have more than %d substitutions in mapping with host [%s]",
-                MAX_REGEX_SUBS, from_host_lower);
-        goto lFail;
-      }
-      substitution_id = to_host[i + 1] - '0';
-      if ((substitution_id < 0) || (substitution_id > n_captures)) {
-        Warning("Substitution id [%c] has no corresponding capture pattern in regex [%s]",
-              to_host[i + 1], from_host_lower);
-        goto lFail;
-      }
-      reg_map->substitution_markers[reg_map->n_substitutions] = i;
-      reg_map->substitution_ids[reg_map->n_substitutions] = substitution_id;
-      ++reg_map->n_substitutions;
-    }
-  }
-
-  // so the regex itself is stored in fromURL.host; string to match
-  // will be in the request; string to use for substitutions will be
-  // in this buffer
-  str = new_mapping->toUrl.host_get(&str_index); // reusing str and str_index
-  reg_map->to_url_host_template_len = str_index;
-  reg_map->to_url_host_template = static_cast<char *>(ats_malloc(str_index));
-  memcpy(reg_map->to_url_host_template, str, str_index);
-
-  return true;
-
- lFail:
-  if (reg_map->re) {
-    pcre_free(reg_map->re);
-    reg_map->re = NULL;
-  }
-  if (reg_map->re_extra) {
-    pcre_free(reg_map->re_extra);
-    reg_map->re_extra = NULL;
-  }
-  if (reg_map->to_url_host_template) {
-    ats_free(reg_map->to_url_host_template);
-    reg_map->to_url_host_template = NULL;
-    reg_map->to_url_host_template_len = 0;
-  }
-  return false;
-}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/90f923ef/proxy/http/remap/UrlRewrite.h
----------------------------------------------------------------------
diff --git a/proxy/http/remap/UrlRewrite.h b/proxy/http/remap/UrlRewrite.h
index 66f0799..35788f9 100644
--- a/proxy/http/remap/UrlRewrite.h
+++ b/proxy/http/remap/UrlRewrite.h
@@ -108,6 +108,10 @@ public:
     _destroyList(store.regex_list);
   }
 
+  bool InsertForwardMapping(mapping_type maptype, url_mapping * mapping, const char * src_host);
+  bool InsertMapping(mapping_type maptype, url_mapping *new_mapping, RegexMapping *reg_map,
+                        const char * src_host, bool is_cur_mapping_regex);
+
   bool TableInsert(InkHashTable *h_table, url_mapping *mapping, const char *src_host);
 
   MappingsStore forward_mappings;
@@ -147,9 +151,6 @@ public:
                           request_host_len, mapping_container);
   }
 
-  int load_remap_plugin(char *argv[], int argc, url_mapping * mp, char *errbuf, int errbufsize, int jump_to_argc,
-                        int *plugin_found_at);
-
   int nohost_rules;
   int reverse_proxy;
   int backdoor_enabled;
@@ -173,7 +174,6 @@ public:
 private:
   bool _valid;
 
-  bool _parseRemapConfigFile(const char * path, BUILD_TABLE_INFO * bti);
   bool _mappingLookup(MappingsStore &mappings, URL *request_url, int request_port, const char *request_host,
                       int request_host_len, UrlMappingContainer &mapping_container);
   url_mapping *_tableLookup(InkHashTable * h_table, URL * request_url, int request_port, char *request_host,
@@ -183,10 +183,9 @@ private:
                            UrlMappingContainer &mapping_container);
   int _expandSubstitutions(int *matches_info, const RegexMapping *reg_map, const char *matched_string, char *dest_buf,
                            int dest_buf_size);
-  bool _processRegexMappingConfig(const char *from_host_lower, url_mapping *new_mapping, RegexMapping *reg_map);
   void _destroyTable(InkHashTable *h_table);
   void _destroyList(RegexMappingList &regexes);
-  inline bool _addToStore(MappingsStore &store, url_mapping *new_mapping, RegexMapping *reg_map, char *src_host,
+  inline bool _addToStore(MappingsStore &store, url_mapping *new_mapping, RegexMapping *reg_map, const char *src_host,
                           bool is_cur_mapping_regex, int &count);
 };
 


Re: [08/12] git commit: TS-2323: separate remap.config parsing from UrlRewrite

Posted by Igor Galić <i....@brainsware.org>.

----- Original Message -----
> TS-2323: separate remap.config parsing from UrlRewrite
> 
> 
> Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
> Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/90f923ef
> Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/90f923ef
> Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/90f923ef
> 
> Branch: refs/heads/master
> Commit: 90f923ef36313f74241f9ebe55ceea17de5caac7
> Parents: 3e8668d
> Author: James Peach <jp...@apache.org>
> Authored: Fri Nov 1 10:28:14 2013 -0700
> Committer: James Peach <jp...@apache.org>
> Committed: Tue Nov 5 16:46:35 2013 -0800
> 
> ----------------------------------------------------------------------
>  proxy/http/remap/RemapConfig.cc | 765 ++++++++++++++++++++++++++++++-
>  proxy/http/remap/RemapConfig.h  |  11 +-
>  proxy/http/remap/UrlRewrite.cc  | 860 ++++-------------------------------
>  proxy/http/remap/UrlRewrite.h   |  11 +-
>  4 files changed, 848 insertions(+), 799 deletions(-)
> ----------------------------------------------------------------------
> 
> 
> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/90f923ef/proxy/http/remap/RemapConfig.cc
> ----------------------------------------------------------------------
> diff --git a/proxy/http/remap/RemapConfig.cc
> b/proxy/http/remap/RemapConfig.cc
> index 0c6442b..a4d41f2 100644
> --- a/proxy/http/remap/RemapConfig.cc
> +++ b/proxy/http/remap/RemapConfig.cc
> @@ -22,8 +22,39 @@
>   */
>  
>  #include "RemapConfig.h"
> -#include "libts.h"
> +#include "UrlRewrite.h"
> +#include "ReverseProxy.h"
>  #include "HTTP.h"
> +#include "libts.h"
> +#include "ink_cap.h"
> +
> +#define modulePrefix "[ReverseProxy]"
> +
> +/**
> +  Returns the length of the URL.
> +
> +  Will replace the terminator with a '/' if this is a full URL and
> +  there are no '/' in it after the the host.  This ensures that class
> +  URL parses the URL correctly.
> +
> +*/
> +static int
> +UrlWhack(char *toWhack, int *origLength)
> +{
> +  int length = strlen(toWhack);
> +  char *tmp;
> +  *origLength = length;
> +
> +  // Check to see if this a full URL
> +  tmp = strstr(toWhack, "://");
> +  if (tmp != NULL) {
> +    if (strchr(tmp + 3, '/') == NULL) {
> +      toWhack[length] = '/';
> +      length++;
> +    }
> +  }
> +  return length;
> +}
>  
>  /**
>    Cleanup *char[] array - each item in array must be allocated via
> @@ -58,6 +89,33 @@ BUILD_TABLE_INFO::reset()
>    clear_xstr_array(this->argv, sizeof(this->argv) / sizeof(char *));
>  }
>  
> +static const char *
> +process_filter_opt(url_mapping * mp, const BUILD_TABLE_INFO * bti, char *
> errStrBuf, int errStrBufSize)
> +{
> +  acl_filter_rule *rp, **rpp;
> +  const char *errStr = NULL;
> +
> +  if (unlikely(!mp || !bti || !errStrBuf || errStrBufSize <= 0)) {
> +    Debug("url_rewrite", "[process_filter_opt] Invalid argument(s)");
> +    return (const char *) "[process_filter_opt] Invalid argument(s)";
> +  }
> +  for (rp = bti->rules_list; rp; rp = rp->next) {
> +    if (rp->active_queue_flag) {
> +      Debug("url_rewrite", "[process_filter_opt] Add active main filter
> \"%s\" (argc=%d)",
> +            rp->filter_name ? rp->filter_name : "<NULL>", rp->argc);
> +      for (rpp = &mp->filter; *rpp; rpp = &((*rpp)->next));
> +      if ((errStr = remap_validate_filter_args(rpp, (const char **)rp->argv,
> rp->argc, errStrBuf, errStrBufSize)) != NULL)
> +        break;
> +    }
> +  }
> +  if (!errStr && (bti->remap_optflg & REMAP_OPTFLG_ALL_FILTERS) != 0) {
> +    Debug("url_rewrite", "[process_filter_opt] Add per remap filter");
> +    for (rpp = &mp->filter; *rpp; rpp = &((*rpp)->next));
> +    errStr = remap_validate_filter_args(rpp, (const char **)bti->argv,
> bti->argc, errStrBuf, errStrBufSize);
> +  }
> +  return errStr;
> +}
> +
>  static bool
>  is_inkeylist(const char * key, ...)
>  {
> @@ -104,7 +162,7 @@ parse_define_directive(const char * directive,
> BUILD_TABLE_INFO * bti, char * er
>  
>    flg = ((rp = acl_filter_rule::find_byname(bti->rules_list, (const char *)
>    bti->paramv[1])) == NULL) ? true : false;
>    // coverity[alloc_arg]
> -  if ((cstr = remap_validate_filter_args(&rp, bti->argv, bti->argc, errbuf,
> errbufsize)) == NULL && rp) {
> +  if ((cstr = remap_validate_filter_args(&rp, (const char **)bti->argv,
> bti->argc, errbuf, errbufsize)) == NULL && rp) {
>      if (flg) {                  // new filter - add to list
>        Debug("url_rewrite", "[parse_directive] new rule \"%s\" was created",
>        bti->paramv[1]);
>        for (rpp = &bti->rules_list; *rpp; rpp = &((*rpp)->next));
> @@ -223,11 +281,12 @@ remap_parse_directive(BUILD_TABLE_INFO *bti, char *
> errbuf, size_t errbufsize)
>  }
>  
>  const char *
> -remap_validate_filter_args(acl_filter_rule ** rule_pp, char ** argv, int
> argc, char * errStrBuf, size_t errStrBufSize)
> +remap_validate_filter_args(acl_filter_rule ** rule_pp, const char ** argv,
> int argc, char * errStrBuf, size_t errStrBufSize)
>  {
>    acl_filter_rule *rule;
>    unsigned long ul;
> -  char *argptr, tmpbuf[1024];
> +  const char *argptr;
> +  char tmpbuf[1024];
>    src_ip_info_t *ipi;
>    int i, j, m;
>    bool new_rule_flg = false;
> @@ -255,7 +314,7 @@ remap_validate_filter_args(acl_filter_rule ** rule_pp,
> char ** argv, int argc, c
>    }
>  
>    for (i = 0; i < argc; i++) {
> -    if ((ul = remap_check_option(&argv[i], 1, 0, NULL, &argptr)) == 0) {
> +    if ((ul = remap_check_option((const char **)&argv[i], 1, 0, NULL,
> &argptr)) == 0) {
>        Debug("url_rewrite", "[validate_filter_args] Unknow remap option -
>        %s", argv[i]);
>        snprintf(errStrBuf, errStrBufSize, "Unknown option - \"%s\"",
>        argv[i]);
>        errStrBuf[errStrBufSize - 1] = 0;
> @@ -405,7 +464,7 @@ remap_validate_filter_args(acl_filter_rule ** rule_pp,
> char ** argv, int argc, c
>  }
>  
>  unsigned long
> -remap_check_option(char *argv[], int argc, unsigned long findmode, int
> *_ret_idx, char **argptr)
> +remap_check_option(const char ** argv, int argc, unsigned long findmode, int
> *_ret_idx, const char **argptr)
>  {
>    unsigned long ret_flags = 0;
>    int idx = 0;
> @@ -474,3 +533,697 @@ remap_check_option(char *argv[], int argc, unsigned
> long findmode, int *_ret_idx
>      *_ret_idx = idx;
>    return ret_flags;
>  }
> +
> +int
> +remap_load_plugin(const char ** argv, int argc, url_mapping *mp, char
> *errbuf, int errbufsize,
> +    int jump_to_argc, int *plugin_found_at)
> +{
> +  TSRemapInterface ri;
> +  struct stat stat_buf;
> +  remap_plugin_info *pi;
> +  char *c, *err, tmpbuf[2048], default_path[PATH_NAME_MAX];
> +  const char *new_argv[1024];
> +  char * parv[1024];
> +  int idx = 0, retcode = 0;
> +  int parc = 0;
> +
> +  *plugin_found_at = 0;
> +
> +  memset(parv, 0, sizeof(parv));
> +  memset(new_argv, 0, sizeof(new_argv));
> +  tmpbuf[0] = 0;
> +
> +  ink_assert(argc < countof(new_argv));
> +
> +  if (jump_to_argc != 0) {
> +    argc -= jump_to_argc;
> +    int i = 0;
> +    while (argv[i + jump_to_argc]) {
> +      new_argv[i] = argv[i + jump_to_argc];
> +      i++;
> +    }
> +    argv = &new_argv[0];
> +    if (!remap_check_option(argv, argc, REMAP_OPTFLG_PLUGIN, &idx)) {
> +      return -1;
> +    }
> +  } else {
> +    if (unlikely(!mp || (remap_check_option(argv, argc, REMAP_OPTFLG_PLUGIN,
> &idx) & REMAP_OPTFLG_PLUGIN) == 0)) {
> +      snprintf(errbuf, errbufsize, "Can't find remap plugin keyword or
> \"url_mapping\" is NULL");
> +      return -1;                /* incorrect input data - almost impossible
> case */
> +    }
> +  }
> +
> +  if (unlikely((c = strchr(argv[idx], (int) '=')) == NULL || !(*(++c)))) {
> +    snprintf(errbuf, errbufsize, "Can't find remap plugin file name in
> \"@%s\"", argv[idx]);
> +    return -2;                  /* incorrect input data */
> +  }
> +
> +  if (stat(c, &stat_buf) != 0) {
> +    const char *plugin_default_path = TSPluginDirGet();
> +
> +    // Try with the plugin path instead
> +    if (strlen(c) + strlen(plugin_default_path) > (PATH_NAME_MAX - 1)) {
> +      Debug("remap_plugin", "way too large a path specified for remap
> plugin");
> +      return -3;

not a huge fan of these return values (would be nice if they had names)
How do we know what they mean? What's the difference between -1 and -2 in
this instance? etc...

Also, this debug message seems strange.

[snip]

++ i
Igor Galić

Tel: +43 (0) 664 886 22 883
Mail: i.galic@brainsware.org
URL: http://brainsware.org/
GPG: 8716 7A9F 989B ABD5 100F  4008 F266 55D6 2998 1641