]> granicus.if.org Git - apache/blobdiff - modules/mappers/mod_rewrite.c
Clean up some of the includes:
[apache] / modules / mappers / mod_rewrite.c
index 0117e84f7f557241688c4fa447fbba77e6a7363a..5b716c5075cbfd895f75a1589e10c4ff7533ae52 100644 (file)
@@ -1,5 +1,8 @@
 /* ====================================================================
- * Copyright (c) 1996-2000 The Apache Software Foundation.  All rights reserved.
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2000 The Apache Software Foundation.  All rights
+ * reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by the Apache Software Foundation
- *    for use in the Apache HTTP server project (http://www.apache.org/)."
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
  *
- * 4. The names "Apache Server" and "Apache Software Foundation" must not be used to
- *    endorse or promote products derived from this software without
- *    prior written permission. For written permission, please contact
- *    apache@apache.org.
+ * 4. The names "Apache" and "Apache Software Foundation" must
+ *    not be used to endorse or promote products derived from this
+ *    software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
  *
- * 5. Products derived from this software may not be called "Apache"
- *    nor may "Apache" appear in their names without prior written
+ * 5. Products derived from this software may not be called "Apache",
+ *    nor may "Apache" appear in their name, without prior written
  *    permission of the Apache Software Foundation.
  *
- * 6. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by the Apache Software Foundation
- *    for use in the Apache HTTP server project (http://www.apache.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY THE Apache Software Foundation ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE Apache Software Foundation OR
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  * ====================================================================
  *
  * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation and was originally based
- * on public domain software written at the National Center for
- * Supercomputing Applications, University of Illinois, Urbana-Champaign.
- * For more information on the Apache Software Foundation and the Apache HTTP server
- * project, please see <http://www.apache.org/>.
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
  *
+ * Portions of this software are based upon public domain software
+ * originally written at the National Center for Supercomputing Applications,
+ * University of Illinois, Urbana-Champaign.
  */
 
-
 /*                       _                            _ _
 **   _ __ ___   ___   __| |    _ __ _____      ___ __(_) |_ ___
 **  | '_ ` _ \ / _ \ / _` |   | '__/ _ \ \ /\ / / '__| | __/ _ \
 **      www.engelschall.com
 */
 
+#include "apr.h"
+#include "apr_strings.h"
+#include "apr_user.h"
+#include "apr_lib.h"
+
+#define APR_WANT_STRFUNC
+#define APR_WANT_IOVEC
+#include "apr_want.h"
+
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if APR_HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
 #include "ap_config.h"
 #include "httpd.h"
 #include "http_config.h"
 #include "http_protocol.h"
 #include "mod_rewrite.h"
 
-#if !defined(OS2) && !defined(WIN32)
+#if !defined(OS2) && !defined(WIN32) && !defined(BEOS)
 #include "unixd.h"
 #endif
 
-#ifndef NO_WRITEV
-#ifndef NETWARE
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#endif
-#ifdef HAVE_SYS_UIO_H
-#include <sys/uio.h>
-#endif
-#endif
-
 /*
 ** +-------------------------------------------------------+
 ** |                                                       |
 **         all hooks are run, independend of result
 **
 **  o  at the last stage, the core module always
-**       - says "BAD_REQUEST" if r->filename does not begin with "/"
+**       - says "HTTP_BAD_REQUEST" if r->filename does not begin with "/"
 **       - prefix URL with document_root or replaced server_root
 **         with document_root and sets r->filename
 **       - always return a "OK" independed if the file really exists
      * MODULE-DEFINITION-END
      */
 
-    /* the ap_table_t of commands we provide */
-static const command_rec command_table[] = {
-    { "RewriteEngine",   cmd_rewriteengine,   NULL, OR_FILEINFO, FLAG,
-      "On or Off to enable or disable (default) the whole rewriting engine" },
-    { "RewriteOptions",  cmd_rewriteoptions,  NULL, OR_FILEINFO, ITERATE,
-      "List of option strings to set" },
-    { "RewriteBase",     cmd_rewritebase,     NULL, OR_FILEINFO, TAKE1,
-      "the base URL of the per-directory context" },
-    { "RewriteCond",     cmd_rewritecond,     NULL, OR_FILEINFO, RAW_ARGS,
-      "an input string and a to be applied regexp-pattern" },
-    { "RewriteRule",     cmd_rewriterule,     NULL, OR_FILEINFO, RAW_ARGS,
-      "an URL-applied regexp-pattern and a substitution URL" },
-    { "RewriteMap",      cmd_rewritemap,      NULL, RSRC_CONF,   TAKE2,
-      "a mapname and a filename" },
-    { "RewriteLock",     cmd_rewritelock,     NULL, RSRC_CONF,   TAKE1,
-      "the filename of a lockfile used for inter-process synchronization"},
-    { "RewriteLog",      cmd_rewritelog,      NULL, RSRC_CONF,   TAKE1,
-      "the filename of the rewriting logfile" },
-    { "RewriteLogLevel", cmd_rewriteloglevel, NULL, RSRC_CONF,   TAKE1,
-      "the level of the rewriting logfile verbosity "
-      "(0=none, 1=std, .., 9=max)" },
-    { NULL }
-};
-
-    /* the ap_table_t of content handlers we provide */
-static const handler_rec handler_table[] = {
-    { "redirect-handler", handler_redirect },
-    { NULL }
-};
-
-static void register_hooks(void)
-{
-    ap_hook_post_config(init_module,NULL,NULL,HOOK_MIDDLE);
-    ap_hook_child_init(init_child,NULL,NULL,HOOK_MIDDLE);
-
-    ap_hook_fixups(hook_fixup,NULL,NULL,HOOK_FIRST);
-    ap_hook_translate_name(hook_uri2file,NULL,NULL,HOOK_FIRST);
-    ap_hook_type_checker(hook_mimetype,NULL,NULL,HOOK_MIDDLE);
-}
-
-    /* the main config structure */
-module MODULE_VAR_EXPORT rewrite_module = {
-   STANDARD20_MODULE_STUFF,
-   config_perdir_create,        /* create per-dir    config structures */
-   config_perdir_merge,         /* merge  per-dir    config structures */
-   config_server_create,        /* create per-server config structures */
-   config_server_merge,         /* merge  per-server config structures */
-   command_table,               /* ap_table_t of config file commands  */
-   handler_table,               /* [#8] MIME-typed-dispatched handlers */
-   register_hooks               /* register hooks                      */
-};
+    /* the module (predeclaration) */
+module AP_MODULE_DECLARE_DATA rewrite_module;
 
     /* the cache */
 static cache *cachep;
 
     /* whether proxy module is available or not */
 static int proxy_available;
-static int once_through = 0;
 
 static const char *lockname;
-static ap_lock_t *rewrite_map_lock = NULL;
-static ap_lock_t *rewrite_log_lock = NULL;
+static apr_lock_t *rewrite_mapr_lock_aquire = NULL;
+static apr_lock_t *rewrite_log_lock = NULL;
 
 /*
 ** +-------------------------------------------------------+
@@ -247,30 +202,30 @@ static ap_lock_t *rewrite_log_lock = NULL;
 **
 */
 
-static void *config_server_create(ap_context_t *p, server_rec *s)
+static void *config_server_create(apr_pool_t *p, server_rec *s)
 {
     rewrite_server_conf *a;
 
-    a = (rewrite_server_conf *)ap_pcalloc(p, sizeof(rewrite_server_conf));
+    a = (rewrite_server_conf *)apr_pcalloc(p, sizeof(rewrite_server_conf));
 
     a->state           = ENGINE_DISABLED;
     a->options         = OPTION_NONE;
     a->rewritelogfile  = NULL;
     a->rewritelogfp    = NULL;
     a->rewriteloglevel = 0;
-    a->rewritemaps     = ap_make_array(p, 2, sizeof(rewritemap_entry));
-    a->rewriteconds    = ap_make_array(p, 2, sizeof(rewritecond_entry));
-    a->rewriterules    = ap_make_array(p, 2, sizeof(rewriterule_entry));
+    a->rewritemaps     = apr_array_make(p, 2, sizeof(rewritemap_entry));
+    a->rewriteconds    = apr_array_make(p, 2, sizeof(rewritecond_entry));
+    a->rewriterules    = apr_array_make(p, 2, sizeof(rewriterule_entry));
     a->server          = s;
 
     return (void *)a;
 }
 
-static void *config_server_merge(ap_context_t *p, void *basev, void *overridesv)
+static void *config_server_merge(apr_pool_t *p, void *basev, void *overridesv)
 {
     rewrite_server_conf *a, *base, *overrides;
 
-    a         = (rewrite_server_conf *)ap_pcalloc(p, sizeof(rewrite_server_conf));
+    a         = (rewrite_server_conf *)apr_pcalloc(p, sizeof(rewrite_server_conf));
     base      = (rewrite_server_conf *)basev;
     overrides = (rewrite_server_conf *)overridesv;
 
@@ -292,11 +247,11 @@ static void *config_server_merge(ap_context_t *p, void *basev, void *overridesv)
         a->rewritelogfp    = overrides->rewritelogfp != NULL 
                              ? overrides->rewritelogfp 
                              : base->rewritelogfp;
-        a->rewritemaps     = ap_append_arrays(p, overrides->rewritemaps,
+        a->rewritemaps     = apr_array_append(p, overrides->rewritemaps,
                                               base->rewritemaps);
-        a->rewriteconds    = ap_append_arrays(p, overrides->rewriteconds,
+        a->rewriteconds    = apr_array_append(p, overrides->rewriteconds,
                                               base->rewriteconds);
-        a->rewriterules    = ap_append_arrays(p, overrides->rewriterules,
+        a->rewriterules    = apr_array_append(p, overrides->rewriterules,
                                               base->rewriterules);
     }
     else {
@@ -322,17 +277,17 @@ static void *config_server_merge(ap_context_t *p, void *basev, void *overridesv)
 **
 */
 
-static void *config_perdir_create(ap_context_t *p, char *path)
+static void *config_perdir_create(apr_pool_t *p, char *path)
 {
     rewrite_perdir_conf *a;
 
-    a = (rewrite_perdir_conf *)ap_pcalloc(p, sizeof(rewrite_perdir_conf));
+    a = (rewrite_perdir_conf *)apr_pcalloc(p, sizeof(rewrite_perdir_conf));
 
     a->state           = ENGINE_DISABLED;
     a->options         = OPTION_NONE;
     a->baseurl         = NULL;
-    a->rewriteconds    = ap_make_array(p, 2, sizeof(rewritecond_entry));
-    a->rewriterules    = ap_make_array(p, 2, sizeof(rewriterule_entry));
+    a->rewriteconds    = apr_array_make(p, 2, sizeof(rewritecond_entry));
+    a->rewriterules    = apr_array_make(p, 2, sizeof(rewriterule_entry));
 
     if (path == NULL) {
         a->directory = NULL;
@@ -340,21 +295,21 @@ static void *config_perdir_create(ap_context_t *p, char *path)
     else {
         /* make sure it has a trailing slash */
         if (path[strlen(path)-1] == '/') {
-            a->directory = ap_pstrdup(p, path);
+            a->directory = apr_pstrdup(p, path);
         }
         else {
-            a->directory = ap_pstrcat(p, path, "/", NULL);
+            a->directory = apr_pstrcat(p, path, "/", NULL);
         }
     }
 
     return (void *)a;
 }
 
-static void *config_perdir_merge(ap_context_t *p, void *basev, void *overridesv)
+static void *config_perdir_merge(apr_pool_t *p, void *basev, void *overridesv)
 {
     rewrite_perdir_conf *a, *base, *overrides;
 
-    a         = (rewrite_perdir_conf *)ap_pcalloc(p,
+    a         = (rewrite_perdir_conf *)apr_pcalloc(p,
                                                   sizeof(rewrite_perdir_conf));
     base      = (rewrite_perdir_conf *)basev;
     overrides = (rewrite_perdir_conf *)overridesv;
@@ -365,9 +320,9 @@ static void *config_perdir_merge(ap_context_t *p, void *basev, void *overridesv)
     a->baseurl   = overrides->baseurl;
 
     if (a->options & OPTION_INHERIT) {
-        a->rewriteconds = ap_append_arrays(p, overrides->rewriteconds,
+        a->rewriteconds = apr_array_append(p, overrides->rewriteconds,
                                            base->rewriteconds);
-        a->rewriterules = ap_append_arrays(p, overrides->rewriterules,
+        a->rewriterules = apr_array_append(p, overrides->rewriterules,
                                            base->rewriterules);
     }
     else {
@@ -386,8 +341,9 @@ static void *config_perdir_merge(ap_context_t *p, void *basev, void *overridesv)
 */
 
 static const char *cmd_rewriteengine(cmd_parms *cmd,
-                                     rewrite_perdir_conf *dconf, int flag)
+                                     void *in_dconf, int flag)
 {
+    rewrite_perdir_conf *dconf = in_dconf;
     rewrite_server_conf *sconf;
 
     sconf = 
@@ -405,8 +361,9 @@ static const char *cmd_rewriteengine(cmd_parms *cmd,
 }
 
 static const char *cmd_rewriteoptions(cmd_parms *cmd,
-                                      rewrite_perdir_conf *dconf, char *option)
+                                      void *in_dconf, const char *option)
 {
+    rewrite_perdir_conf *dconf = in_dconf;
     rewrite_server_conf *sconf;
     const char *err;
 
@@ -425,20 +382,20 @@ static const char *cmd_rewriteoptions(cmd_parms *cmd,
     return err;
 }
 
-static const char *cmd_rewriteoptions_setoption(ap_context_t *p, int *options,
-                                                char *name)
+static const char *cmd_rewriteoptions_setoption(apr_pool_t *p, int *options,
+                                                const char *name)
 {
     if (strcasecmp(name, "inherit") == 0) {
         *options |= OPTION_INHERIT;
     }
     else {
-        return ap_pstrcat(p, "RewriteOptions: unknown option '",
-                          name, "'\n", NULL);
+        return apr_pstrcat(p, "RewriteOptions: unknown option '",
+                          name, "'", NULL);
     }
     return NULL;
 }
 
-static const char *cmd_rewritelog(cmd_parms *cmd, void *dconf, char *a1)
+static const char *cmd_rewritelog(cmd_parms *cmd, void *dconf, const char *a1)
 {
     rewrite_server_conf *sconf;
 
@@ -450,7 +407,7 @@ static const char *cmd_rewritelog(cmd_parms *cmd, void *dconf, char *a1)
     return NULL;
 }
 
-static const char *cmd_rewriteloglevel(cmd_parms *cmd, void *dconf, char *a1)
+static const char *cmd_rewriteloglevel(cmd_parms *cmd, void *dconf, const char *a1)
 {
     rewrite_server_conf *sconf;
 
@@ -462,17 +419,17 @@ static const char *cmd_rewriteloglevel(cmd_parms *cmd, void *dconf, char *a1)
     return NULL;
 }
 
-static const char *cmd_rewritemap(cmd_parms *cmd, void *dconf, char *a1,
-                                  char *a2)
+static const char *cmd_rewritemap(cmd_parms *cmd, void *dconf, const char *a1,
+                                  const char *a2)
 {
     rewrite_server_conf *sconf;
     rewritemap_entry *newmap;
-    struct stat st;
+    apr_finfo_t st;
 
     sconf = (rewrite_server_conf *)
             ap_get_module_config(cmd->server->module_config, &rewrite_module);
 
-    newmap = ap_push_array(sconf->rewritemaps);
+    newmap = apr_array_push(sconf->rewritemaps);
 
     newmap->name = a1;
     newmap->func = NULL;
@@ -490,9 +447,9 @@ static const char *cmd_rewritemap(cmd_parms *cmd, void *dconf, char *a1,
 #ifndef NO_DBM_REWRITEMAP
         newmap->type      = MAPTYPE_DBM;
         newmap->datafile  = a2+4;
-        newmap->checkfile = ap_pstrcat(cmd->pool, a2+4, NDBM_FILE_SUFFIX, NULL);
+        newmap->checkfile = apr_pstrcat(cmd->pool, a2+4, NDBM_FILE_SUFFIX, NULL);
 #else
-        return ap_pstrdup(cmd->pool, "RewriteMap: cannot use NDBM mapfile, "
+        return apr_pstrdup(cmd->pool, "RewriteMap: cannot use NDBM mapfile, "
                           "because no NDBM support is compiled in");
 #endif
     }
@@ -518,7 +475,7 @@ static const char *cmd_rewritemap(cmd_parms *cmd, void *dconf, char *a1,
             newmap->func = rewrite_mapfunc_unescape;
         }
         else if (sconf->state == ENGINE_ENABLED) {
-            return ap_pstrcat(cmd->pool, "RewriteMap: internal map not found:",
+            return apr_pstrcat(cmd->pool, "RewriteMap: internal map not found:",
                               a2+4, NULL);
         }
     }
@@ -531,8 +488,9 @@ static const char *cmd_rewritemap(cmd_parms *cmd, void *dconf, char *a1,
     newmap->fpout = NULL;
 
     if (newmap->checkfile && (sconf->state == ENGINE_ENABLED)
-        && (stat(newmap->checkfile, &st) == -1)) {
-        return ap_pstrcat(cmd->pool,
+        && (apr_stat(&st, newmap->checkfile, APR_FINFO_MIN, 
+                     cmd->pool) != APR_SUCCESS)) {
+        return apr_pstrcat(cmd->pool,
                           "RewriteMap: map file or program not found:",
                           newmap->checkfile, NULL);
     }
@@ -540,7 +498,7 @@ static const char *cmd_rewritemap(cmd_parms *cmd, void *dconf, char *a1,
     return NULL;
 }
 
-static const char *cmd_rewritelock(cmd_parms *cmd, void *dconf, char *a1)
+static const char *cmd_rewritelock(cmd_parms *cmd, void *dconf, const char *a1)
 {
     const char *error;
 
@@ -552,9 +510,11 @@ static const char *cmd_rewritelock(cmd_parms *cmd, void *dconf, char *a1)
     return NULL;
 }
 
-static const char *cmd_rewritebase(cmd_parms *cmd, rewrite_perdir_conf *dconf,
-                                   char *a1)
+static const char *cmd_rewritebase(cmd_parms *cmd, void *in_dconf,
+                                   const char *a1)
 {
+    rewrite_perdir_conf *dconf = in_dconf;
+
     if (cmd->path == NULL || dconf == NULL) {
         return "RewriteBase: only valid in per-directory config files";
     }
@@ -570,9 +530,11 @@ static const char *cmd_rewritebase(cmd_parms *cmd, rewrite_perdir_conf *dconf,
     return NULL;
 }
 
-static const char *cmd_rewritecond(cmd_parms *cmd, rewrite_perdir_conf *dconf,
-                                   char *str)
+static const char *cmd_rewritecond(cmd_parms *cmd, void *in_dconf,
+                                   const char *in_str)
 {
+    rewrite_perdir_conf *dconf = in_dconf;
+    char *str = apr_pstrdup(cmd->pool, in_str);
     rewrite_server_conf *sconf;
     rewritecond_entry *newcond;
     regex_t *regexp;
@@ -588,20 +550,20 @@ static const char *cmd_rewritecond(cmd_parms *cmd, rewrite_perdir_conf *dconf,
 
     /*  make a new entry in the internal temporary rewrite rule list */
     if (cmd->path == NULL) {   /* is server command */
-        newcond = ap_push_array(sconf->rewriteconds);
+        newcond = apr_array_push(sconf->rewriteconds);
     }
     else {                     /* is per-directory command */
-        newcond = ap_push_array(dconf->rewriteconds);
+        newcond = apr_array_push(dconf->rewriteconds);
     }
 
     /*  parse the argument line ourself */
     if (parseargline(str, &a1, &a2, &a3)) {
-        return ap_pstrcat(cmd->pool, "RewriteCond: bad argument line '", str,
-                          "'\n", NULL);
+        return apr_pstrcat(cmd->pool, "RewriteCond: bad argument line '", str,
+                          "'", NULL);
     }
 
     /*  arg1: the input string */
-    newcond->input = ap_pstrdup(cmd->pool, a1);
+    newcond->input = apr_pstrdup(cmd->pool, a1);
 
     /* arg3: optional flags field
        (this have to be first parsed, because we need to
@@ -633,18 +595,18 @@ static const char *cmd_rewritecond(cmd_parms *cmd, rewrite_perdir_conf *dconf,
         rc = ((regexp = ap_pregcomp(cmd->pool, cp, REG_EXTENDED)) == NULL);
     }
     if (rc) {
-        return ap_pstrcat(cmd->pool,
+        return apr_pstrcat(cmd->pool,
                           "RewriteCond: cannot compile regular expression '",
-                          a2, "'\n", NULL);
+                          a2, "'", NULL);
     }
 
-    newcond->pattern = ap_pstrdup(cmd->pool, cp);
+    newcond->pattern = apr_pstrdup(cmd->pool, cp);
     newcond->regexp  = regexp;
 
     return NULL;
 }
 
-static const char *cmd_rewritecond_parseflagfield(ap_context_t *p,
+static const char *cmd_rewritecond_parseflagfield(apr_pool_t *p,
                                                   rewritecond_entry *cfg,
                                                   char *str)
 {
@@ -696,7 +658,7 @@ static const char *cmd_rewritecond_parseflagfield(ap_context_t *p,
     return NULL;
 }
 
-static const char *cmd_rewritecond_setflag(ap_context_t *p, rewritecond_entry *cfg,
+static const char *cmd_rewritecond_setflag(apr_pool_t *p, rewritecond_entry *cfg,
                                            char *key, char *val)
 {
     if (   strcasecmp(key, "nocase") == 0
@@ -708,14 +670,16 @@ static const char *cmd_rewritecond_setflag(ap_context_t *p, rewritecond_entry *c
         cfg->flags |= CONDFLAG_ORNEXT;
     }
     else {
-        return ap_pstrcat(p, "RewriteCond: unknown flag '", key, "'\n", NULL);
+        return apr_pstrcat(p, "RewriteCond: unknown flag '", key, "'", NULL);
     }
     return NULL;
 }
 
-static const char *cmd_rewriterule(cmd_parms *cmd, rewrite_perdir_conf *dconf,
-                                   char *str)
+static const char *cmd_rewriterule(cmd_parms *cmd, void *in_dconf,
+                                   const char *in_str)
 {
+    rewrite_perdir_conf *dconf = in_dconf;
+    char *str = apr_pstrdup(cmd->pool, in_str);
     rewrite_server_conf *sconf;
     rewriterule_entry *newrule;
     regex_t *regexp;
@@ -731,16 +695,16 @@ static const char *cmd_rewriterule(cmd_parms *cmd, rewrite_perdir_conf *dconf,
 
     /*  make a new entry in the internal rewrite rule list */
     if (cmd->path == NULL) {   /* is server command */
-        newrule = ap_push_array(sconf->rewriterules);
+        newrule = apr_array_push(sconf->rewriterules);
     }
     else {                     /* is per-directory command */
-        newrule = ap_push_array(dconf->rewriterules);
+        newrule = apr_array_push(dconf->rewriterules);
     }
 
     /*  parse the argument line ourself */
     if (parseargline(str, &a1, &a2, &a3)) {
-        return ap_pstrcat(cmd->pool, "RewriteRule: bad argument line '", str,
-                          "'\n", NULL);
+        return apr_pstrcat(cmd->pool, "RewriteRule: bad argument line '", str,
+                          "'", NULL);
     }
 
     /* arg3: optional flags field */
@@ -769,18 +733,20 @@ static const char *cmd_rewriterule(cmd_parms *cmd, rewrite_perdir_conf *dconf,
         mode |= REG_ICASE;
     }
     if ((regexp = ap_pregcomp(cmd->pool, cp, mode)) == NULL) {
-        return ap_pstrcat(cmd->pool,
+        return apr_pstrcat(cmd->pool,
                           "RewriteRule: cannot compile regular expression '",
-                          a1, "'\n", NULL);
+                          a1, "'", NULL);
     }
-    newrule->pattern = ap_pstrdup(cmd->pool, cp);
+    newrule->pattern = apr_pstrdup(cmd->pool, cp);
     newrule->regexp  = regexp;
 
     /*  arg2: the output string
      *  replace the $<N> by \<n> which is needed by the currently
      *  used Regular Expression library
+     *
+     * TODO: Is this still required for PCRE?  If not, does it *work* with PCRE?
      */
-    newrule->output = ap_pstrdup(cmd->pool, a2);
+    newrule->output = apr_pstrdup(cmd->pool, a2);
 
     /* now, if the server or per-dir config holds an
      * array of RewriteCond entries, we take it for us
@@ -788,19 +754,19 @@ static const char *cmd_rewriterule(cmd_parms *cmd, rewrite_perdir_conf *dconf,
      */
     if (cmd->path == NULL) {  /* is server command */
         newrule->rewriteconds   = sconf->rewriteconds;
-        sconf->rewriteconds = ap_make_array(cmd->pool, 2,
+        sconf->rewriteconds = apr_array_make(cmd->pool, 2,
                                             sizeof(rewritecond_entry));
     }
     else {                    /* is per-directory command */
         newrule->rewriteconds   = dconf->rewriteconds;
-        dconf->rewriteconds = ap_make_array(cmd->pool, 2,
+        dconf->rewriteconds = apr_array_make(cmd->pool, 2,
                                             sizeof(rewritecond_entry));
     }
 
     return NULL;
 }
 
-static const char *cmd_rewriterule_parseflagfield(ap_context_t *p,
+static const char *cmd_rewriterule_parseflagfield(apr_pool_t *p,
                                                   rewriterule_entry *cfg,
                                                   char *str)
 {
@@ -852,7 +818,7 @@ static const char *cmd_rewriterule_parseflagfield(ap_context_t *p,
     return NULL;
 }
 
-static const char *cmd_rewriterule_setflag(ap_context_t *p, rewriterule_entry *cfg,
+static const char *cmd_rewriterule_setflag(apr_pool_t *p, rewriterule_entry *cfg,
                                            char *key, char *val)
 {
     int status = 0;
@@ -871,7 +837,7 @@ static const char *cmd_rewriterule_setflag(ap_context_t *p, rewriterule_entry *c
             else if (strcasecmp(val, "seeother") == 0) {
                 status = HTTP_SEE_OTHER;
             }
-            else if (ap_isdigit(*val)) {
+            else if (apr_isdigit(*val)) {
                 status = atoi(val);
             }
             if (!ap_is_HTTP_REDIRECT(status)) {
@@ -895,7 +861,7 @@ static const char *cmd_rewriterule_setflag(ap_context_t *p, rewriterule_entry *c
     }
     else if (   strcasecmp(key, "type") == 0
              || strcasecmp(key, "T") == 0   ) {
-        cfg->forced_mimetype = ap_pstrdup(p, val);
+        cfg->forced_mimetype = apr_pstrdup(p, val);
         ap_str_tolower(cfg->forced_mimetype);
     }
     else if (   strcasecmp(key, "env") == 0
@@ -903,7 +869,7 @@ static const char *cmd_rewriterule_setflag(ap_context_t *p, rewriterule_entry *c
         for (i = 0; (cfg->env[i] != NULL) && (i < MAX_ENV_FLAGS); i++)
             ;
         if (i < MAX_ENV_FLAGS) {
-            cfg->env[i] = ap_pstrdup(p, val);
+            cfg->env[i] = apr_pstrdup(p, val);
             cfg->env[i+1] = NULL;
         }
         else {
@@ -943,7 +909,7 @@ static const char *cmd_rewriterule_setflag(ap_context_t *p, rewriterule_entry *c
         cfg->flags |= RULEFLAG_NOCASE;
     }
     else {
-        return ap_pstrcat(p, "RewriteRule: unknown flag '", key, "'\n", NULL);
+        return apr_pstrcat(p, "RewriteRule: unknown flag '", key, "'", NULL);
     }
     return NULL;
 }
@@ -957,22 +923,36 @@ static const char *cmd_rewriterule_setflag(ap_context_t *p, rewriterule_entry *c
 **
 */
 
-static void init_module(ap_context_t *p,
-                        ap_context_t *plog,
-                        ap_context_t *ptemp,
+static void init_module(apr_pool_t *p,
+                        apr_pool_t *plog,
+                        apr_pool_t *ptemp,
                         server_rec *s)
 {
+    apr_status_t rv;
+    void *data;
+    int first_time = 0;
+    const char *userdata_key = "rewrite_init_module";
+
+    apr_pool_userdata_get(&data, userdata_key, s->process->pool);
+    if (!data) {
+        first_time = 1;
+        apr_pool_userdata_set((const void *)1, userdata_key,
+                         apr_pool_cleanup_null, s->process->pool);
+    }
+
     /* check if proxy module is available */
     proxy_available = (ap_find_linked_module("mod_proxy.c") != NULL);
 
     /* create the rewriting lockfiles in the parent */
-    if (ap_create_lock (&rewrite_log_lock, APR_MUTEX, APR_INTRAPROCESS,
-                        NULL, NULL) != APR_SUCCESS)
-        exit(1);    /* ugly but I can't log anything yet. This is what */
-                    /*   the pre-existing rewritelock_create code did. */
+    if ((rv = apr_lock_create (&rewrite_log_lock, APR_MUTEX, APR_LOCKALL,
+                               NULL, p)) != APR_SUCCESS) {
+        ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
+                     "mod_rewrite: could not create rewrite_log_lock");
+        exit(1);
+    }
 
     rewritelock_create(s, p);
-    ap_register_cleanup(p, (void *)s, rewritelock_remove, ap_null_cleanup);
+    apr_pool_cleanup_register(p, (void *)s, rewritelock_remove, apr_pool_cleanup_null);
 
     /* step through the servers and
      * - open each rewriting logfile
@@ -980,11 +960,9 @@ static void init_module(ap_context_t *p,
      */
     for (; s; s = s->next) {
         open_rewritelog(s, p);
-        if (once_through > 0)
+        if (!first_time)
            run_rewritemap_programs(s, p);
     }
-
-    once_through++;
 }
 
 
@@ -995,11 +973,19 @@ static void init_module(ap_context_t *p,
 **
 */
 
-static void init_child(ap_context_t *p, server_rec *s)
+static void init_child(apr_pool_t *p, server_rec *s)
 {
+    apr_status_t rv;
 
     if (lockname != NULL && *(lockname) != '\0')
-        ap_child_init_lock (&rewrite_map_lock, lockname, p);
+    {
+        rv = apr_lock_child_init (&rewrite_mapr_lock_aquire, lockname, p);
+        if (rv != APR_SUCCESS) {
+            ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
+                         "mod_rewrite: could not init rewrite_mapr_lock_aquire "
+                         "in child");
+        }
+    }
 
     /* create the lookup cache */
     cachep = init_cache(p);
@@ -1035,7 +1021,7 @@ static int hook_uri2file(request_rec *r)
     char docroot[512];
     char *cp, *cp2;
     const char *ccp;
-    struct stat finfo;
+    apr_finfo_t finfo;
     unsigned int port;
     int n;
     int l;
@@ -1073,18 +1059,18 @@ static int hook_uri2file(request_rec *r)
      */
 
     if (r->main == NULL) {
-         var = ap_pstrcat(r->pool, "REDIRECT_", ENVVAR_SCRIPT_URL, NULL);
-         var = ap_table_get(r->subprocess_env, var);
+         var = apr_pstrcat(r->pool, "REDIRECT_", ENVVAR_SCRIPT_URL, NULL);
+         var = apr_table_get(r->subprocess_env, var);
          if (var == NULL) {
-             ap_table_setn(r->subprocess_env, ENVVAR_SCRIPT_URL, r->uri);
+             apr_table_setn(r->subprocess_env, ENVVAR_SCRIPT_URL, r->uri);
          }
          else {
-             ap_table_setn(r->subprocess_env, ENVVAR_SCRIPT_URL, var);
+             apr_table_setn(r->subprocess_env, ENVVAR_SCRIPT_URL, var);
          }
     }
     else {
-         var = ap_table_get(r->main->subprocess_env, ENVVAR_SCRIPT_URL);
-         ap_table_setn(r->subprocess_env, ENVVAR_SCRIPT_URL, var);
+         var = apr_table_get(r->main->subprocess_env, ENVVAR_SCRIPT_URL);
+         apr_table_setn(r->subprocess_env, ENVVAR_SCRIPT_URL, var);
     }
 
     /*
@@ -1098,21 +1084,21 @@ static int hook_uri2file(request_rec *r)
         thisport = "";
     }
     else {
-        ap_snprintf(buf, sizeof(buf), ":%u", port);
+        apr_snprintf(buf, sizeof(buf), ":%u", port);
         thisport = buf;
     }
-    thisurl = ap_table_get(r->subprocess_env, ENVVAR_SCRIPT_URL);
+    thisurl = apr_table_get(r->subprocess_env, ENVVAR_SCRIPT_URL);
 
     /* set the variable */
-    var = ap_pstrcat(r->pool, ap_http_method(r), "://", thisserver, thisport,
+    var = apr_pstrcat(r->pool, ap_http_method(r), "://", thisserver, thisport,
                      thisurl, NULL);
-    ap_table_setn(r->subprocess_env, ENVVAR_SCRIPT_URI, var);
+    apr_table_setn(r->subprocess_env, ENVVAR_SCRIPT_URI, var);
 
     /* if filename was not initially set,
      * we start with the requested URI
      */
     if (r->filename == NULL) {
-        r->filename = ap_pstrdup(r->pool, r->uri);
+        r->filename = apr_pstrdup(r->pool, r->uri);
         rewritelog(r, 2, "init rewrite engine with requested uri %s",
                    r->filename);
     }
@@ -1133,20 +1119,20 @@ static int hook_uri2file(request_rec *r)
                 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
                              "attempt to make remote request from mod_rewrite "
                              "without proxy enabled: %s", r->filename);
-                return FORBIDDEN;
+                return HTTP_FORBIDDEN;
             }
 
             /* make sure the QUERY_STRING and
              * PATH_INFO parts get incorporated
              */
             if (r->path_info != NULL) {
-                r->filename = ap_pstrcat(r->pool, r->filename,
+                r->filename = apr_pstrcat(r->pool, r->filename,
                                          r->path_info, NULL);
             }
             if (r->args != NULL &&
                 r->uri == r->unparsed_uri) {
                 /* see proxy_http:proxy_http_canon() */
-                r->filename = ap_pstrcat(r->pool, r->filename,
+                r->filename = apr_pstrcat(r->pool, r->filename,
                                          "?", r->args, NULL);
             }
 
@@ -1158,20 +1144,7 @@ static int hook_uri2file(request_rec *r)
                        r->filename);
             return OK;
         }
-        else if (  (strlen(r->filename) > 7 &&
-                    strncasecmp(r->filename, "http://",   7) == 0)
-                || (strlen(r->filename) > 8 &&
-                    strncasecmp(r->filename, "https://",  8) == 0)
-                || (strlen(r->filename) > 9 &&
-                    strncasecmp(r->filename, "gopher://", 9) == 0)
-                || (strlen(r->filename) > 6 &&
-                    strncasecmp(r->filename, "ftp://",    6) == 0)
-                || (strlen(r->filename) > 5 &&
-                    strncasecmp(r->filename, "ldap:",     5) == 0)
-                || (strlen(r->filename) > 5 &&
-                    strncasecmp(r->filename, "news:",     5) == 0)
-                || (strlen(r->filename) > 7 &&
-                    strncasecmp(r->filename, "mailto:",   7) == 0)) {
+        else if (is_absolute_uri(r->filename)) {
             /* it was finally rewritten to a remote URL */
 
             /* skip 'scheme:' */
@@ -1186,12 +1159,12 @@ static int hook_uri2file(request_rec *r)
                 rewritelog(r, 1, "escaping %s for redirect", r->filename);
                 cp2 = ap_escape_uri(r->pool, cp);
                 *cp = '\0';
-                r->filename = ap_pstrcat(r->pool, r->filename, cp2, NULL);
+                r->filename = apr_pstrcat(r->pool, r->filename, cp2, NULL);
             }
 
             /* append the QUERY_STRING part */
             if (r->args != NULL) {
-                r->filename = ap_pstrcat(r->pool, r->filename, "?", 
+                r->filename = apr_pstrcat(r->pool, r->filename, "?", 
                                          ap_escape_uri(r->pool, r->args), NULL);
             }
 
@@ -1201,18 +1174,18 @@ static int hook_uri2file(request_rec *r)
                 r->status = HTTP_OK; /* make Apache kernel happy */
             }
             else {
-                n = REDIRECT;
+                n = HTTP_MOVED_TEMPORARILY;
             }
 
             /* now do the redirection */
-            ap_table_setn(r->headers_out, "Location", r->filename);
+            apr_table_setn(r->headers_out, "Location", r->filename);
             rewritelog(r, 1, "redirect to %s [REDIRECT/%d]", r->filename, n);
             return n;
         }
         else if (strlen(r->filename) > 10 &&
                  strncmp(r->filename, "forbidden:", 10) == 0) {
             /* This URLs is forced to be forbidden for the requester */
-            return FORBIDDEN;
+            return HTTP_FORBIDDEN;
         }
         else if (strlen(r->filename) > 5 &&
                  strncmp(r->filename, "gone:", 5) == 0) {
@@ -1229,21 +1202,21 @@ static int hook_uri2file(request_rec *r)
              * r->uri! The difference here is: We do not try to
              * add the document root
              */
-            r->uri = ap_pstrdup(r->pool, r->filename+12);
+            r->uri = apr_pstrdup(r->pool, r->filename+12);
             return DECLINED;
         }
         else {
             /* it was finally rewritten to a local path */
 
             /* expand "/~user" prefix */
-#if !defined(WIN32) && !defined(NETWARE)
+#if APR_HAS_USER
             r->filename = expand_tildepaths(r, r->filename);
 #endif
             rewritelog(r, 2, "local path result: %s", r->filename);
 
             /* the filename has to start with a slash! */
             if (r->filename[0] != '/') {
-                return BAD_REQUEST;
+                return HTTP_BAD_REQUEST;
             }
 
             /* if there is no valid prefix, we have
@@ -1269,7 +1242,7 @@ static int hook_uri2file(request_rec *r)
             n = prefix_stat(r->filename, &finfo);
             if (n == 0) {
                 if ((ccp = ap_document_root(r)) != NULL) {
-                    l = ap_cpystrn(docroot, ccp, sizeof(docroot)) - docroot;
+                    l = apr_cpystrn(docroot, ccp, sizeof(docroot)) - docroot;
 
                     /* always NOT have a trailing slash */
                     if (docroot[l-1] == '/') {
@@ -1278,12 +1251,12 @@ static int hook_uri2file(request_rec *r)
                     if (r->server->path
                         && !strncmp(r->filename, r->server->path,
                                     r->server->pathlen)) {
-                        r->filename = ap_pstrcat(r->pool, docroot,
+                        r->filename = apr_pstrcat(r->pool, docroot,
                                                  (r->filename +
                                                   r->server->pathlen), NULL);
                     }
                     else {
-                        r->filename = ap_pstrcat(r->pool, docroot, 
+                        r->filename = apr_pstrcat(r->pool, docroot, 
                                                  r->filename, NULL);
                     }
                     rewritelog(r, 2, "prefixed with document_root to %s",
@@ -1315,7 +1288,7 @@ static int hook_mimetype(request_rec *r)
     const char *t;
 
     /* now check if we have to force a MIME-type */
-    t = ap_table_get(r->notes, REWRITE_FORCED_MIMETYPE_NOTEVAR);
+    t = apr_table_get(r->notes, REWRITE_FORCED_MIMETYPE_NOTEVAR);
     if (t == NULL) {
         return DECLINED;
     }
@@ -1377,7 +1350,7 @@ static int hook_fixup(request_rec *r)
                      "Options FollowSymLinks or SymLinksIfOwnerMatch is off "
                      "which implies that RewriteRule directive is forbidden: "
                      "%s", r->filename);
-        return FORBIDDEN;
+        return HTTP_FORBIDDEN;
     }
     else {
         /* FollowSymLinks is given, but the user can
@@ -1410,7 +1383,7 @@ static int hook_fixup(request_rec *r)
              * rewriting engine because of the per-dir context!)
              */
             if (r->args != NULL) {
-                r->filename = ap_pstrcat(r->pool, r->filename,
+                r->filename = apr_pstrcat(r->pool, r->filename,
                                          "?", r->args, NULL);
             }
 
@@ -1422,20 +1395,7 @@ static int hook_fixup(request_rec *r)
                        "%s [OK]", dconf->directory, r->filename);
             return OK;
         }
-        else if (  (strlen(r->filename) > 7 &&
-                    strncasecmp(r->filename, "http://",   7) == 0)
-                || (strlen(r->filename) > 8 &&          
-                    strncasecmp(r->filename, "https://",  8) == 0)
-                || (strlen(r->filename) > 9 &&
-                    strncasecmp(r->filename, "gopher://", 9) == 0)
-                || (strlen(r->filename) > 6 &&
-                    strncasecmp(r->filename, "ftp://",    6) == 0)
-                || (strlen(r->filename) > 5 &&
-                    strncasecmp(r->filename, "ldap:",     5) == 0)
-                || (strlen(r->filename) > 5 &&
-                    strncasecmp(r->filename, "news:",     5) == 0)
-                || (strlen(r->filename) > 7 &&
-                    strncasecmp(r->filename, "mailto:",   7) == 0)) {
+        else if (is_absolute_uri(r->filename)) {
             /* it was finally rewritten to a remote URL */
 
             /* because we are in a per-dir context
@@ -1458,7 +1418,7 @@ static int hook_fixup(request_rec *r)
                                             dconf->baseurl);
                     if (strcmp(cp2, cp) != 0) {
                         *cp = '\0';
-                        r->filename = ap_pstrcat(r->pool, r->filename,
+                        r->filename = apr_pstrcat(r->pool, r->filename,
                                                  cp2, NULL);
                     }
                 }
@@ -1479,12 +1439,12 @@ static int hook_fixup(request_rec *r)
                            dconf->directory, r->filename);
                 cp2 = ap_escape_uri(r->pool, cp);
                 *cp = '\0';
-                r->filename = ap_pstrcat(r->pool, r->filename, cp2, NULL);
+                r->filename = apr_pstrcat(r->pool, r->filename, cp2, NULL);
             }
 
             /* append the QUERY_STRING part */
             if (r->args != NULL) {
-                r->filename = ap_pstrcat(r->pool, r->filename, "?", 
+                r->filename = apr_pstrcat(r->pool, r->filename, "?", 
                                          ap_escape_uri(r->pool, r->args), NULL);
             }
 
@@ -1494,11 +1454,11 @@ static int hook_fixup(request_rec *r)
                 r->status = HTTP_OK; /* make Apache kernel happy */
             }
             else {
-                n = REDIRECT;
+                n = HTTP_MOVED_TEMPORARILY;
             }
 
             /* now do the redirection */
-            ap_table_setn(r->headers_out, "Location", r->filename);
+            apr_table_setn(r->headers_out, "Location", r->filename);
             rewritelog(r, 1, "[per-dir %s] redirect to %s [REDIRECT/%d]",
                        dconf->directory, r->filename, n);
             return n;
@@ -1506,7 +1466,7 @@ static int hook_fixup(request_rec *r)
         else if (strlen(r->filename) > 10 &&
                  strncmp(r->filename, "forbidden:", 10) == 0) {
             /* This URL is forced to be forbidden for the requester */
-            return FORBIDDEN;
+            return HTTP_FORBIDDEN;
         }
         else if (strlen(r->filename) > 5 &&
                  strncmp(r->filename, "gone:", 5) == 0) {
@@ -1522,12 +1482,12 @@ static int hook_fixup(request_rec *r)
              */
             if (strlen(r->filename) > 12 &&
                 strncmp(r->filename, "passthrough:", 12) == 0) {
-                r->filename = ap_pstrdup(r->pool, r->filename+12);
+                r->filename = apr_pstrdup(r->pool, r->filename+12);
             }
 
             /* the filename has to start with a slash! */
             if (r->filename[0] != '/') {
-                return BAD_REQUEST;
+                return HTTP_BAD_REQUEST;
             }
 
             /* Check for deadlooping:
@@ -1565,7 +1525,7 @@ static int hook_fixup(request_rec *r)
                  * document_root if it is prefix
                  */
                 if ((ccp = ap_document_root(r)) != NULL) {
-                    prefix = ap_pstrdup(r->pool, ccp);
+                    prefix = apr_pstrdup(r->pool, ccp);
                     /* always NOT have a trailing slash */
                     l = strlen(prefix);
                     if (prefix[l-1] == '/') {
@@ -1578,7 +1538,7 @@ static int hook_fixup(request_rec *r)
                                    "prefix: %s -> %s",
                                    dconf->directory, r->filename,
                                    r->filename+l);
-                        r->filename = ap_pstrdup(r->pool, r->filename+l);
+                        r->filename = apr_pstrdup(r->pool, r->filename+l);
                     }
                 }
             }
@@ -1586,7 +1546,7 @@ static int hook_fixup(request_rec *r)
             /* now initiate the internal redirect */
             rewritelog(r, 1, "[per-dir %s] internal redirect with %s "
                        "[INTERNAL REDIRECT]", dconf->directory, r->filename);
-            r->filename = ap_pstrcat(r->pool, "redirect:", r->filename, NULL);
+            r->filename = apr_pstrcat(r->pool, "redirect:", r->filename, NULL);
             r->handler = "redirect-handler";
             return OK;
         }
@@ -1609,13 +1569,17 @@ static int hook_fixup(request_rec *r)
 
 static int handler_redirect(request_rec *r)
 {
+    if (strcmp(r->handler, "redirect-handler")) {
+        return DECLINED;
+    }
+
     /* just make sure that we are really meant! */
     if (strncmp(r->filename, "redirect:", 9) != 0) {
         return DECLINED;
     }
 
     /* now do the internal redirect */
-    ap_internal_redirect(ap_pstrcat(r->pool, r->filename+9,
+    ap_internal_redirect(apr_pstrcat(r->pool, r->filename+9,
                                     r->args ? "?" : NULL, r->args, NULL), r);
 
     /* and return gracefully */
@@ -1635,7 +1599,7 @@ static int handler_redirect(request_rec *r)
  *  Apply a complete rule set,
  *  i.e. a list of rewrite rules
  */
-static int apply_rewrite_list(request_rec *r, ap_array_header_t *rewriterules,
+static int apply_rewrite_list(request_rec *r, apr_array_header_t *rewriterules,
                               char *perdir)
 {
     rewriterule_entry *entries;
@@ -1687,7 +1651,7 @@ static int apply_rewrite_list(request_rec *r, ap_array_header_t *rewriterules,
             if (p->flags & RULEFLAG_PASSTHROUGH) {
                 rewritelog(r, 2, "forcing '%s' to get passed through "
                            "to next API URI-to-filename handler", r->filename);
-                r->filename = ap_pstrcat(r->pool, "passthrough:",
+                r->filename = apr_pstrcat(r->pool, "passthrough:",
                                          r->filename, NULL);
                 changed = 1;
                 break;
@@ -1699,7 +1663,7 @@ static int apply_rewrite_list(request_rec *r, ap_array_header_t *rewriterules,
              */
             if (p->flags & RULEFLAG_FORBIDDEN) {
                 rewritelog(r, 2, "forcing '%s' to be forbidden", r->filename);
-                r->filename = ap_pstrcat(r->pool, "forbidden:",
+                r->filename = apr_pstrcat(r->pool, "forbidden:",
                                          r->filename, NULL);
                 changed = 1;
                 break;
@@ -1711,7 +1675,7 @@ static int apply_rewrite_list(request_rec *r, ap_array_header_t *rewriterules,
              */
             if (p->flags & RULEFLAG_GONE) {
                 rewritelog(r, 2, "forcing '%s' to be gone", r->filename);
-                r->filename = ap_pstrcat(r->pool, "gone:", r->filename, NULL);
+                r->filename = apr_pstrcat(r->pool, "gone:", r->filename, NULL);
                 changed = 1;
                 break;
             }
@@ -1773,14 +1737,13 @@ static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
     char *output;
     const char *vary;
     char newuri[MAX_STRING_LEN];
-    char env[MAX_STRING_LEN];
     regex_t *regexp;
     regmatch_t regmatch[MAX_NMATCH];
     backrefinfo *briRR = NULL;
     backrefinfo *briRC = NULL;
     int prefixstrip;
     int failed;
-    ap_array_header_t *rewriteconds;
+    apr_array_header_t *rewriteconds;
     rewritecond_entry *conds;
     rewritecond_entry *c;
     int i;
@@ -1800,7 +1763,7 @@ static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
     if (perdir != NULL && r->path_info != NULL && r->path_info[0] != '\0') {
         rewritelog(r, 3, "[per-dir %s] add path info postfix: %s -> %s%s",
                    perdir, uri, uri, r->path_info);
-        uri = ap_pstrcat(r->pool, uri, r->path_info, NULL);
+        uri = apr_pstrcat(r->pool, uri, r->path_info, NULL);
     }
 
     /*
@@ -1842,14 +1805,14 @@ static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
      *  Else create the RewriteRule `regsubinfo' structure which
      *  holds the substitution information.
      */
-    briRR = (backrefinfo *)ap_palloc(r->pool, sizeof(backrefinfo));
+    briRR = (backrefinfo *)apr_palloc(r->pool, sizeof(backrefinfo));
     if (!rc && (p->flags & RULEFLAG_NOTMATCH)) {
         /*  empty info on negative patterns  */
         briRR->source = "";
         briRR->nsub   = 0;
     }
     else {
-        briRR->source = ap_pstrdup(r->pool, uri);
+        briRR->source = apr_pstrdup(r->pool, uri);
         briRR->nsub   = regexp->re_nsub;
         memcpy((void *)(briRR->regmatch), (void *)(regmatch),
                sizeof(regmatch));
@@ -1860,7 +1823,7 @@ static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
      *  empty backrefinfo, i.e. not subst parts
      *  (this one is adjusted inside apply_rewrite_cond() later!!)
      */
-    briRC = (backrefinfo *)ap_pcalloc(r->pool, sizeof(backrefinfo));
+    briRC = (backrefinfo *)apr_pcalloc(r->pool, sizeof(backrefinfo));
     briRC->source = "";
     briRC->nsub   = 0;
 
@@ -1885,7 +1848,7 @@ static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
                 /*  One condition is false, but another can be
                  *  still true, so we have to continue...
                  */
-               ap_table_unset(r->notes, VARY_KEY_THIS);
+               apr_table_unset(r->notes, VARY_KEY_THIS);
                 continue;
             }
             else {
@@ -1911,16 +1874,16 @@ static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
                 break;
             }
         }
-       vary = ap_table_get(r->notes, VARY_KEY_THIS);
+       vary = apr_table_get(r->notes, VARY_KEY_THIS);
        if (vary != NULL) {
-           ap_table_merge(r->notes, VARY_KEY, vary);
-           ap_table_unset(r->notes, VARY_KEY_THIS);
+           apr_table_merge(r->notes, VARY_KEY, vary);
+           apr_table_unset(r->notes, VARY_KEY_THIS);
        }
     }
     /*  if any condition fails the complete rule fails  */
     if (failed) {
-        ap_table_unset(r->notes, VARY_KEY);
-        ap_table_unset(r->notes, VARY_KEY_THIS);
+        apr_table_unset(r->notes, VARY_KEY);
+        apr_table_unset(r->notes, VARY_KEY_THIS);
         return 0;
     }
 
@@ -1929,9 +1892,9 @@ static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
      * if any of the request header fields were involved, and add them
      * to the Vary field of the response.
      */
-    if ((vary = ap_table_get(r->notes, VARY_KEY)) != NULL) {
-        ap_table_merge(r->headers_out, "Vary", vary);
-       ap_table_unset(r->notes, VARY_KEY);
+    if ((vary = apr_table_get(r->notes, VARY_KEY)) != NULL) {
+        apr_table_merge(r->headers_out, "Vary", vary);
+       apr_table_unset(r->notes, VARY_KEY);
     }
 
     /*
@@ -1941,20 +1904,7 @@ static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
      *  (`RewriteRule <pat> - [E=...]')
      */
     if (strcmp(output, "-") == 0) {
-        for (i = 0; p->env[i] != NULL; i++) {
-            /*  1. take the string  */
-            ap_cpystrn(env, p->env[i], sizeof(env));
-            /*  2. expand $N (i.e. backrefs to RewriteRule pattern)  */
-            expand_backref_inbuffer(r->pool, env, sizeof(env), briRR, '$');
-            /*  3. expand %N (i.e. backrefs to latest RewriteCond pattern)  */
-            expand_backref_inbuffer(r->pool, env, sizeof(env), briRC, '%');
-            /*  4. expand %{...} (i.e. variables) */
-            expand_variables_inbuffer(r, env, sizeof(env));
-            /*  5. expand ${...} (RewriteMap lookups)  */
-            expand_map_lookups(r, env, sizeof(env));
-            /*  and add the variable to Apache's structures  */
-            add_env_variable(r, env);
-        }
+       do_expand_env(r, p->env, briRR, briRC);
         if (p->forced_mimetype != NULL) {
             if (perdir == NULL) {
                 /* In the per-server context we can force the MIME-type
@@ -1963,7 +1913,7 @@ static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
                  */
                 rewritelog(r, 2, "remember %s to have MIME-type '%s'",
                            r->filename, p->forced_mimetype);
-                ap_table_setn(r->notes, REWRITE_FORCED_MIMETYPE_NOTEVAR,
+                apr_table_setn(r->notes, REWRITE_FORCED_MIMETYPE_NOTEVAR,
                               p->forced_mimetype);
             }
             else {
@@ -1989,17 +1939,7 @@ static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
      *  that there is something to replace, so we create the
      *  substitution URL string in `newuri'.
      */
-    /*  1. take the output string  */
-    ap_cpystrn(newuri, output, sizeof(newuri));
-    /*  2. expand $N (i.e. backrefs to RewriteRule pattern)  */
-    expand_backref_inbuffer(r->pool, newuri, sizeof(newuri), briRR, '$');
-    /*  3. expand %N (i.e. backrefs to latest RewriteCond pattern)  */
-    expand_backref_inbuffer(r->pool, newuri, sizeof(newuri), briRC, '%');
-    /*  4. expand %{...} (i.e. variables) */
-    expand_variables_inbuffer(r, newuri, sizeof(newuri));
-    /*  5. expand ${...} (RewriteMap lookups)  */
-    expand_map_lookups(r, newuri, sizeof(newuri));
-    /*  and log the result... */
+    do_expand(r, output, newuri, sizeof(newuri), briRR, briRC);
     if (perdir == NULL) {
         rewritelog(r, 2, "rewrite %s -> %s", uri, newuri);
     }
@@ -2011,27 +1951,14 @@ static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
      *  Additionally do expansion for the environment variable
      *  strings (`RewriteRule .. .. [E=<string>]').
      */
-    for (i = 0; p->env[i] != NULL; i++) {
-        /*  1. take the string  */
-        ap_cpystrn(env, p->env[i], sizeof(env));
-        /*  2. expand $N (i.e. backrefs to RewriteRule pattern)  */
-        expand_backref_inbuffer(r->pool, env, sizeof(env), briRR, '$');
-        /*  3. expand %N (i.e. backrefs to latest RewriteCond pattern)  */
-        expand_backref_inbuffer(r->pool, env, sizeof(env), briRC, '%');
-        /*  4. expand %{...} (i.e. variables) */
-        expand_variables_inbuffer(r, env, sizeof(env));
-        /*  5. expand ${...} (RewriteMap lookups)  */
-        expand_map_lookups(r, env, sizeof(env));
-        /*  and add the variable to Apache's structures  */
-        add_env_variable(r, env);
-    }
+    do_expand_env(r, p->env, briRR, briRC);
 
     /*
      *  Now replace API's knowledge of the current URI:
      *  Replace r->filename with the new URI string and split out
      *  an on-the-fly generated QUERY_STRING part into r->args
      */
-    r->filename = ap_pstrdup(r->pool, newuri);
+    r->filename = apr_pstrdup(r->pool, newuri);
     splitout_queryargs(r, p->flags & RULEFLAG_QSAPPEND);
 
     /*
@@ -2040,19 +1967,11 @@ static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
      *   location, i.e. if it's not starting with either a slash
      *   or a fully qualified URL scheme.
      */
-    i = strlen(r->filename);
-    if (   prefixstrip
-        && !(   r->filename[0] == '/'
-             || (   (i > 7 && strncasecmp(r->filename, "http://",   7) == 0)
-                 || (i > 8 && strncasecmp(r->filename, "https://",  8) == 0)
-                 || (i > 9 && strncasecmp(r->filename, "gopher://", 9) == 0)
-                 || (i > 6 && strncasecmp(r->filename, "ftp://",    6) == 0)
-                 || (i > 5 && strncasecmp(r->filename, "ldap:",     5) == 0)
-                 || (i > 5 && strncasecmp(r->filename, "news:",     5) == 0)
-                 || (i > 7 && strncasecmp(r->filename, "mailto:",   7) == 0)))) {
+    if (prefixstrip && r->filename[0] != '/'
+       && !is_absolute_uri(r->filename)) {
         rewritelog(r, 3, "[per-dir %s] add per-dir prefix: %s -> %s%s",
                    perdir, r->filename, perdir, r->filename);
-        r->filename = ap_pstrcat(r->pool, perdir, r->filename, NULL);
+        r->filename = apr_pstrcat(r->pool, perdir, r->filename, NULL);
     }
 
     /*
@@ -2072,7 +1991,7 @@ static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
             rewritelog(r, 2, "[per-dir %s] forcing proxy-throughput with %s",
                        perdir, r->filename);
         }
-        r->filename = ap_pstrcat(r->pool, "proxy:", r->filename, NULL);
+        r->filename = apr_pstrcat(r->pool, "proxy:", r->filename, NULL);
         return 1;
     }
 
@@ -2113,14 +2032,7 @@ static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
      *  redirection (`RewriteRule .. <scheme>://...') then
      *  directly force an external HTTP redirect.
      */
-    i = strlen(r->filename);
-    if (   (i > 7 && strncasecmp(r->filename, "http://",   7) == 0)
-        || (i > 8 && strncasecmp(r->filename, "https://",  8) == 0)
-        || (i > 9 && strncasecmp(r->filename, "gopher://", 9) == 0)
-        || (i > 6 && strncasecmp(r->filename, "ftp://",    6) == 0)
-        || (i > 5 && strncasecmp(r->filename, "ldap:",     5) == 0)
-        || (i > 5 && strncasecmp(r->filename, "news:",     5) == 0)
-        || (i > 7 && strncasecmp(r->filename, "mailto:",   7) == 0) ) {
+    if (is_absolute_uri(r->filename)) {
         if (perdir == NULL) {
             rewritelog(r, 2,
                        "implicitly forcing redirect (rc=%d) with %s",
@@ -2145,7 +2057,7 @@ static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
     if (prefixstrip && r->filename[0] != '/') {
         rewritelog(r, 3, "[per-dir %s] add per-dir prefix: %s -> %s%s",
                    perdir, r->filename, perdir, r->filename);
-        r->filename = ap_pstrcat(r->pool, perdir, r->filename, NULL);
+        r->filename = apr_pstrcat(r->pool, perdir, r->filename, NULL);
     }
 
     /*
@@ -2157,7 +2069,7 @@ static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
      *  already processed) because a sub-request happens ;-)
      */
     if (p->forced_mimetype != NULL) {
-        ap_table_setn(r->notes, REWRITE_FORCED_MIMETYPE_NOTEVAR,
+        apr_table_setn(r->notes, REWRITE_FORCED_MIMETYPE_NOTEVAR,
                       p->forced_mimetype);
         if (perdir == NULL) {
             rewritelog(r, 2, "remember %s to have MIME-type '%s'",
@@ -2182,7 +2094,7 @@ static int apply_rewrite_cond(request_rec *r, rewritecond_entry *p,
                               backrefinfo *briRC)
 {
     char input[MAX_STRING_LEN];
-    struct stat sb;
+    apr_finfo_t sb;
     request_rec *rsub;
     regmatch_t regmatch[MAX_NMATCH];
     int rc;
@@ -2191,16 +2103,7 @@ static int apply_rewrite_cond(request_rec *r, rewritecond_entry *p,
      *   Construct the string we match against
      */
 
-    /*  1. take the string  */
-    ap_cpystrn(input, p->input, sizeof(input));
-    /*  2. expand $N (i.e. backrefs to RewriteRule pattern)  */
-    expand_backref_inbuffer(r->pool, input, sizeof(input), briRR, '$');
-    /*  3. expand %N (i.e. backrefs to latest RewriteCond pattern)  */
-    expand_backref_inbuffer(r->pool, input, sizeof(input), briRC, '%');
-    /*  4. expand %{...} (i.e. variables) */
-    expand_variables_inbuffer(r, input, sizeof(input));
-    /*  5. expand ${...} (RewriteMap lookups)  */
-    expand_map_lookups(r, input, sizeof(input));
+    do_expand(r, p->input, input, sizeof(input), briRR, briRC);
 
     /*
      *   Apply the patterns
@@ -2208,46 +2111,41 @@ static int apply_rewrite_cond(request_rec *r, rewritecond_entry *p,
 
     rc = 0;
     if (strcmp(p->pattern, "-f") == 0) {
-        if (stat(input, &sb) == 0) {
-            if (S_ISREG(sb.st_mode)) {
+        if (apr_stat(&sb, input, APR_FINFO_MIN, r->pool) == APR_SUCCESS) {
+            if (sb.filetype == APR_REG) {
                 rc = 1;
             }
         }
     }
     else if (strcmp(p->pattern, "-s") == 0) {
-        if (stat(input, &sb) == 0) {
-            if (S_ISREG(sb.st_mode) && sb.st_size > 0) {
+        if (apr_stat(&sb, input, APR_FINFO_MIN, r->pool) == APR_SUCCESS) {
+            if ((sb.filetype == APR_REG) && sb.size > 0) {
                 rc = 1;
             }
         }
     }
     else if (strcmp(p->pattern, "-l") == 0) {
-#if !defined(OS2) && !defined(WIN32)
-        if (lstat(input, &sb) == 0) {
-            if (S_ISLNK(sb.st_mode)) {
+#if !defined(OS2)
+        if (apr_lstat(&sb, input, APR_FINFO_MIN, r->pool) == APR_SUCCESS) {
+            if (sb.filetype == APR_LNK) {
                 rc = 1;
             }
         }
 #endif
     }
     else if (strcmp(p->pattern, "-d") == 0) {
-        if (stat(input, &sb) == 0) {
-            if (S_ISDIR(sb.st_mode)) {
+        if (apr_stat(&sb, input, APR_FINFO_MIN, r->pool) == APR_SUCCESS) {
+            if (sb.filetype == APR_DIR) {
                 rc = 1;
             }
         }
     }
     else if (strcmp(p->pattern, "-U") == 0) {
         /* avoid infinite subrequest recursion */
-        if (strlen(input) > 0               /* nonempty path, and            */
-            && (   r->main == NULL          /* - either not in a subrequest  */
-                || (   r->main->uri != NULL /* - or in a subrequest...       */
-                    && r->uri != NULL       /*   ...and URIs aren't NULL...  */
-                                            /*   ...and sub/main URIs differ */
-                    && strcmp(r->main->uri, r->uri) != 0) ) ) {
+        if (strlen(input) > 0 && subreq_ok(r)) {
 
             /* run a URI-based subrequest */
-            rsub = ap_sub_req_lookup_uri(input, r);
+            rsub = ap_sub_req_lookup_uri(input, r, NULL);
 
             /* URI exists for any result up to 3xx, redirects allowed */
             if (rsub->status < 400)
@@ -2263,22 +2161,18 @@ static int apply_rewrite_cond(request_rec *r, rewritecond_entry *p,
     }
     else if (strcmp(p->pattern, "-F") == 0) {
         /* avoid infinite subrequest recursion */
-        if (strlen(input) > 0               /* nonempty path, and            */
-            && (   r->main == NULL          /* - either not in a subrequest  */
-                || (   r->main->uri != NULL /* - or in a subrequest...       */
-                    && r->uri != NULL       /*   ...and URIs aren't NULL...  */
-                                            /*   ...and sub/main URIs differ */
-                    && strcmp(r->main->uri, r->uri) != 0) ) ) {
+        if (strlen(input) > 0 && subreq_ok(r)) {
 
             /* process a file-based subrequest:
              * this differs from -U in that no path translation is done.
              */
-            rsub = ap_sub_req_lookup_file(input, r);
+            rsub = ap_sub_req_lookup_file(input, r, NULL);
 
             /* file exists for any result up to 2xx, no redirects */
             if (rsub->status < 300 &&
                 /* double-check that file exists since default result is 200 */
-                stat(rsub->filename, &sb) == 0) {
+                apr_stat(&sb, rsub->filename, APR_FINFO_MIN, 
+                         r->pool) == APR_SUCCESS) {
                 rc = 1;
             }
 
@@ -2313,7 +2207,7 @@ static int apply_rewrite_cond(request_rec *r, rewritecond_entry *p,
         /* if it isn't a negated pattern and really matched
            we update the passed-through regex subst info structure */
         if (rc && !(p->flags & CONDFLAG_NOTMATCH)) {
-            briRC->source = ap_pstrdup(r->pool, input);
+            briRC->source = apr_pstrdup(r->pool, input);
             briRC->nsub   = p->regexp->re_nsub;
             memcpy((void *)(briRC->regmatch), (void *)(regmatch),
                    sizeof(regmatch));
@@ -2342,6 +2236,162 @@ static int apply_rewrite_cond(request_rec *r, rewritecond_entry *p,
 ** +-------------------------------------------------------+
 */
 
+
+/*
+**
+**  perform all the expansions on the input string
+**  leaving the result in the supplied buffer
+**
+*/
+
+static void do_expand(request_rec *r, char *input, char *buffer, int nbuf,
+                      backrefinfo *briRR, backrefinfo *briRC)
+{
+    char *inp, *outp;
+    size_t span, space;
+
+    /*
+     * for security reasons this expansion must be perfomed in a
+     * single pass, otherwise an attacker can arrange for the result
+     * of an earlier expansion to include expansion specifiers that
+     * are interpreted by a later expansion, producing results that
+     * were not intended by the administrator.
+     */
+
+    inp = input;
+    outp = buffer;
+    space = nbuf - 1; /* room for '\0' */
+
+    for (;;) {
+       span = strcspn(inp, "$%");
+       if (span > space) {
+           span = space;
+       }
+       memcpy(outp, inp, span);
+       inp += span;
+       outp += span;
+       space -= span;
+       if (space == 0 || *inp == '\0') {
+           break;
+       }
+       /* now we have a '$' or a '%' */
+       if (inp[1] == '{') {
+           char *endp;
+           endp = find_closing_bracket(inp+2, '{', '}');
+           if (endp == NULL) {
+               goto skip;
+           }
+           /*
+            * These lookups may be recursive in a very convoluted
+            * fashion -- see the LA-U and LA-F variable expansion
+            * prefixes -- so we copy lookup keys to a separate buffer
+            * rather than adding zero bytes in order to use them in
+            * place.
+            */
+           if (inp[0] == '$') {
+               /* ${...} map lookup expansion */
+               /*
+                * To make rewrite maps useful the lookup key and
+                * default values must be expanded, so we make
+                * recursive calls to do the work. For security
+                * reasons we must never expand a string that includes
+                * verbatim data from the network. The recursion here
+                * isn't a problem because the result of expansion is
+                * only passed to lookup_map() so it cannot be
+                * re-expanded, only re-looked-up. Another way of
+                * looking at it is that the recursion is entirely
+                * driven by the syntax of the nested curly brackets.
+                */
+               char *map, *key, *dflt, *result;
+               char xkey[MAX_STRING_LEN];
+               char xdflt[MAX_STRING_LEN];
+               key = find_char_in_brackets(inp+2, ':', '{', '}');
+               if (key == NULL)
+                   goto skip;
+               map  = apr_pstrndup(r->pool, inp+2, key-inp-2);
+               dflt = find_char_in_brackets(key+1, '|', '{', '}');
+               if (dflt == NULL) {
+                   key  = apr_pstrndup(r->pool, key+1, endp-key-1);
+                   dflt = "";
+               } else {
+                   key  = apr_pstrndup(r->pool, key+1, dflt-key-1);
+                   dflt = apr_pstrndup(r->pool, dflt+1, endp-dflt-1);
+               }
+               do_expand(r, key,  xkey,  sizeof(xkey),  briRR, briRC);
+               result = lookup_map(r, map, xkey);
+               if (result) {
+                   span = apr_cpystrn(outp, result, space) - outp;
+               } else {
+                   do_expand(r, dflt, xdflt, sizeof(xdflt), briRR, briRC);
+                   span = apr_cpystrn(outp, xdflt, space) - outp;
+               }
+           }
+           else if (inp[0] == '%') {
+               /* %{...} variable lookup expansion */
+               char *var;
+               var  = apr_pstrndup(r->pool, inp+2, endp-inp-2);
+               span = apr_cpystrn(outp, lookup_variable(r, var), space) - outp;
+           }
+           else {
+               span = 0;
+           }
+           inp = endp+1;
+           outp += span;
+           space -= span;
+           continue;
+       }
+       else if (apr_isdigit(inp[1])) {
+           int n = inp[1] - '0';
+           backrefinfo *bri = NULL;
+           if (inp[0] == '$') {
+               /* $N RewriteRule regexp backref expansion */
+               bri = briRR;
+           }
+           else if (inp[0] == '%') {
+               /* %N RewriteCond regexp backref expansion */
+               bri = briRC;
+           }
+           /* see ap_pregsub() in src/main/util.c */
+            if (bri && n <= bri->nsub &&
+               bri->regmatch[n].rm_eo > bri->regmatch[n].rm_so) {
+               span = bri->regmatch[n].rm_eo - bri->regmatch[n].rm_so;
+               if (span > space) {
+                   span = space;
+               }
+               memcpy(outp, bri->source + bri->regmatch[n].rm_so, span);
+               outp += span;
+               space -= span;
+           }
+           inp += 2;
+           continue;
+       }
+    skip:
+       *outp++ = *inp++;
+       space--;
+    }
+    *outp++ = '\0';
+}
+
+
+/*
+**
+**  perform all the expansions on the environment variables
+**
+*/
+
+static void do_expand_env(request_rec *r, char *env[],
+                         backrefinfo *briRR, backrefinfo *briRC)
+{
+    int i;
+    char buf[MAX_STRING_LEN];
+
+    for (i = 0; env[i] != NULL; i++) {
+       do_expand(r, env[i], buf, sizeof(buf), briRR, briRC);
+       add_env_variable(r, buf);
+    }
+}
+
+
 /*
 **
 **  split out a QUERY_STRING part from
@@ -2356,13 +2406,13 @@ static void splitout_queryargs(request_rec *r, int qsappend)
 
     q = strchr(r->filename, '?');
     if (q != NULL) {
-        olduri = ap_pstrdup(r->pool, r->filename);
+        olduri = apr_pstrdup(r->pool, r->filename);
         *q++ = '\0';
         if (qsappend) {
-            r->args = ap_pstrcat(r->pool, q, "&", r->args, NULL);
+            r->args = apr_pstrcat(r->pool, q, "&", r->args, NULL);
         }
         else {
-            r->args = ap_pstrdup(r->pool, q);
+            r->args = apr_pstrdup(r->pool, q);
         }
         if (strlen(r->args) == 0) {
             r->args = NULL;
@@ -2409,17 +2459,17 @@ static void reduce_uri(request_rec *r)
         && r->filename[l+2] == '/'             ) {
         /* there was really a rewrite to a remote path */
 
-        olduri = ap_pstrdup(r->pool, r->filename); /* save for logging */
+        olduri = apr_pstrdup(r->pool, r->filename); /* save for logging */
 
         /* cut the hostname and port out of the URI */
-        ap_cpystrn(buf, r->filename+(l+3), sizeof(buf));
+        apr_cpystrn(buf, r->filename+(l+3), sizeof(buf));
         hostp = buf;
         for (cp = hostp; *cp != '\0' && *cp != '/' && *cp != ':'; cp++)
             ;
         if (*cp == ':') {
             /* set host */
             *cp++ = '\0';
-            ap_cpystrn(host, hostp, sizeof(host));
+            apr_cpystrn(host, hostp, sizeof(host));
             /* set port */
             portp = cp;
             for (; *cp != '\0' && *cp != '/'; cp++)
@@ -2434,7 +2484,7 @@ static void reduce_uri(request_rec *r)
         else if (*cp == '/') {
             /* set host */
             *cp = '\0';
-            ap_cpystrn(host, hostp, sizeof(host));
+            apr_cpystrn(host, hostp, sizeof(host));
             *cp = '/';
             /* set port */
             port = ap_default_port(r);
@@ -2443,7 +2493,7 @@ static void reduce_uri(request_rec *r)
         }
         else {
             /* set host */
-            ap_cpystrn(host, hostp, sizeof(host));
+            apr_cpystrn(host, hostp, sizeof(host));
             /* set port */
             port = ap_default_port(r);
             /* set remaining url */
@@ -2453,7 +2503,7 @@ static void reduce_uri(request_rec *r)
         /* now check whether we could reduce it to a local path... */
         if (ap_matches_request_vhost(r, host, port)) {
             /* this is our host, so only the URL remains */
-            r->filename = ap_pstrdup(r->pool, url);
+            r->filename = apr_pstrdup(r->pool, url);
             rewritelog(r, 3, "reduce %s -> %s", olduri, r->filename);
         }
     }
@@ -2470,20 +2520,12 @@ static void reduce_uri(request_rec *r)
 
 static void fully_qualify_uri(request_rec *r)
 {
-    int i;
     char buf[32];
     const char *thisserver;
     char *thisport;
     int port;
 
-    i = strlen(r->filename);
-    if (!(   (i > 7 && strncasecmp(r->filename, "http://",   7) == 0)
-          || (i > 8 && strncasecmp(r->filename, "https://",  8) == 0)
-          || (i > 9 && strncasecmp(r->filename, "gopher://", 9) == 0)
-          || (i > 6 && strncasecmp(r->filename, "ftp://",    6) == 0)
-          || (i > 5 && strncasecmp(r->filename, "ldap:",     5) == 0)
-          || (i > 5 && strncasecmp(r->filename, "news:",     5) == 0)
-          || (i > 7 && strncasecmp(r->filename, "mailto:",   7) == 0))) {
+    if (!is_absolute_uri(r->filename)) {
 
         thisserver = ap_get_server_name(r);
         port = ap_get_server_port(r);
@@ -2491,17 +2533,17 @@ static void fully_qualify_uri(request_rec *r)
             thisport = "";
         }
         else {
-            ap_snprintf(buf, sizeof(buf), ":%u", port);
+            apr_snprintf(buf, sizeof(buf), ":%u", port);
             thisport = buf;
         }
 
         if (r->filename[0] == '/') {
-            r->filename = ap_psprintf(r->pool, "%s://%s%s%s",
+            r->filename = apr_psprintf(r->pool, "%s://%s%s%s",
                                       ap_http_method(r), thisserver,
                                       thisport, r->filename);
         }
         else {
-            r->filename = ap_psprintf(r->pool, "%s://%s%s/%s",
+            r->filename = apr_psprintf(r->pool, "%s://%s%s/%s",
                                       ap_http_method(r), thisserver,
                                       thisport, r->filename);
         }
@@ -2512,62 +2554,41 @@ static void fully_qualify_uri(request_rec *r)
 
 /*
 **
-**  Expand the %0-%9 or $0-$9 regex backreferences
+**  return non-zero if the URI is absolute (includes a scheme etc.)
 **
 */
 
-static void expand_backref_inbuffer(ap_context_t *p, char *buf, int nbuf,
-                                    backrefinfo *bri, char c)
+static int is_absolute_uri(char *uri)
 {
-    register int i;
-
-    /* protect existing $N and & backrefs and replace <c>N with $N backrefs */
-    for (i = 0; buf[i] != '\0' && i < nbuf; i++) {
-        if (buf[i] == '\\' && (buf[i+1] != '\0' && i < (nbuf-1))) {
-            i++; /* protect next */
-        }
-        else if (buf[i] == '&') {
-            buf[i] = '\001';
-        }
-        else if (c != '$' && buf[i] == '$' && (buf[i+1] >= '0' && buf[i+1] <= '9')) {
-            buf[i] = '\002';
-            i++; /* speedup */
-        }
-        else if (buf[i] == c && (buf[i+1] >= '0' && buf[i+1] <= '9')) {
-            buf[i] = '$';
-            i++; /* speedup */
-        }
+    int i = strlen(uri);
+    if (   (i > 7 && strncasecmp(uri, "http://",   7) == 0)
+        || (i > 8 && strncasecmp(uri, "https://",  8) == 0)
+        || (i > 9 && strncasecmp(uri, "gopher://", 9) == 0)
+        || (i > 6 && strncasecmp(uri, "ftp://",    6) == 0)
+        || (i > 5 && strncasecmp(uri, "ldap:",     5) == 0)
+        || (i > 5 && strncasecmp(uri, "news:",     5) == 0)
+        || (i > 7 && strncasecmp(uri, "mailto:",   7) == 0) ) {
+       return 1;
     }
-
-    /* now apply the standard regex substitution function */
-    ap_cpystrn(buf, ap_pregsub(p, buf, bri->source,
-                               bri->nsub+1, bri->regmatch), nbuf);
-
-    /* restore the original $N and & backrefs */
-    for (i = 0; buf[i] != '\0' && i < nbuf; i++) {
-        if (buf[i] == '\001') {
-            buf[i] = '&';
-        }
-        else if (buf[i] == '\002') {
-            buf[i] = '$';
-        }
+    else {
+       return 0;
     }
 }
 
 
 /*
 **
-**  Expand tilde-paths (/~user) through
-**  Unix /etc/passwd database information
+**  Expand tilde-paths (/~user) through Unix /etc/passwd 
+**  database information (or other OS-specific database)
 **
 */
-#if !defined(WIN32) && !defined(NETWARE)
+#if APR_HAS_USER
 static char *expand_tildepaths(request_rec *r, char *uri)
 {
     char user[LONG_STRING_LEN];
-    struct passwd *pw;
     char *newuri;
     int i, j;
+    char *homedir;
 
     newuri = uri;
     if (uri != NULL && strlen(uri) > 2 && uri[0] == '/' && uri[1] == '~') {
@@ -2580,137 +2601,24 @@ static char *expand_tildepaths(request_rec *r, char *uri)
         user[j] = '\0';
 
         /* lookup username in systems passwd file */
-        if ((pw = getpwnam(user)) != NULL) {
+        if (apr_get_home_directory(&homedir, user, r->pool) == APR_SUCCESS) {
             /* ok, user was found, so expand the ~user string */
             if (uri[i] != '\0') {
                 /* ~user/anything...  has to be expanded */
-                if (pw->pw_dir[strlen(pw->pw_dir)-1] == '/') {
-                    pw->pw_dir[strlen(pw->pw_dir)-1] = '\0';
+                if (homedir[strlen(homedir)-1] == '/') {
+                    homedir[strlen(homedir)-1] = '\0';
                 }
-                newuri = ap_pstrcat(r->pool, pw->pw_dir, uri+i, NULL);
+                newuri = apr_pstrcat(r->pool, homedir, uri+i, NULL);
             }
             else {
                 /* only ~user has to be expanded */
-                newuri = ap_pstrdup(r->pool, pw->pw_dir);
+                newuri = homedir;
             }
         }
     }
     return newuri;
 }
-#endif
-
-/*
-**
-**  mapfile expansion support
-**  i.e. expansion of MAP lookup directives
-**  ${<mapname>:<key>} in RewriteRule rhs
-**
-*/
-
-#define limit_length(n) (n > LONG_STRING_LEN-1 ? LONG_STRING_LEN-1 : n)
-
-static void expand_map_lookups(request_rec *r, char *uri, int uri_len)
-{
-    char newuri[MAX_STRING_LEN];
-    char *cpI;
-    char *cpIE;
-    char *cpO;
-    char *cpT;
-    char *cpT2;
-    char mapname[LONG_STRING_LEN];
-    char mapkey[LONG_STRING_LEN];
-    char defaultvalue[LONG_STRING_LEN];
-    int n;
-
-    cpI = uri;
-    cpIE = cpI+strlen(cpI);
-    cpO = newuri;
-    while (cpI < cpIE) {
-        if (cpI+6 < cpIE && strncmp(cpI, "${", 2) == 0) {
-            /* missing delimiter -> take it as plain text */
-            if (   strchr(cpI+2, ':') == NULL
-                || strchr(cpI+2, '}') == NULL) {
-                memcpy(cpO, cpI, 2);
-                cpO += 2;
-                cpI += 2;
-                continue;
-            }
-            cpI += 2;
-
-            cpT = strchr(cpI, ':');
-            n = cpT-cpI;
-            memcpy(mapname, cpI, limit_length(n));
-            mapname[limit_length(n)] = '\0';
-            cpI += n+1;
-
-            cpT2 = strchr(cpI, '|');
-            cpT = strchr(cpI, '}');
-            if (cpT2 != NULL && cpT2 < cpT) {
-                n = cpT2-cpI;
-                memcpy(mapkey, cpI, limit_length(n));
-                mapkey[limit_length(n)] = '\0';
-                cpI += n+1;
-
-                n = cpT-cpI;
-                memcpy(defaultvalue, cpI, limit_length(n));
-                defaultvalue[limit_length(n)] = '\0';
-                cpI += n+1;
-            }
-            else {
-                n = cpT-cpI;
-                memcpy(mapkey, cpI, limit_length(n));
-                mapkey[limit_length(n)] = '\0';
-                cpI += n+1;
-
-                defaultvalue[0] = '\0';
-            }
-
-            cpT = lookup_map(r, mapname, mapkey);
-            if (cpT != NULL) {
-                n = strlen(cpT);
-                if (cpO + n >= newuri + sizeof(newuri)) {
-                    ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR,
-                                 0, r, "insufficient space in "
-                                 "expand_map_lookups, aborting");
-                    return;
-                }
-                memcpy(cpO, cpT, n);
-                cpO += n;
-            }
-            else {
-                n = strlen(defaultvalue);
-                if (cpO + n >= newuri + sizeof(newuri)) {
-                    ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 
-                                 0, r, "insufficient space in "
-                                 "expand_map_lookups, aborting");
-                    return;
-                }
-                memcpy(cpO, defaultvalue, n);
-                cpO += n;
-            }
-        }
-        else {
-            cpT = strstr(cpI, "${");
-            if (cpT == NULL)
-                cpT = cpI+strlen(cpI);
-            n = cpT-cpI;
-            if (cpO + n >= newuri + sizeof(newuri)) {
-                ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 
-                             0, r, "insufficient space in "
-                             "expand_map_lookups, aborting");
-                return;
-            }
-            memcpy(cpO, cpI, n);
-            cpO += n;
-            cpI += n;
-        }
-    }
-    *cpO = '\0';
-    ap_cpystrn(uri, newuri, uri_len);
-    return;
-}
-
-#undef limit_length
+#endif  /* if APR_HAS_USER */
 
 
 
@@ -2727,11 +2635,12 @@ static char *lookup_map(request_rec *r, char *name, char *key)
 {
     void *sconf;
     rewrite_server_conf *conf;
-    ap_array_header_t *rewritemaps;
+    apr_array_header_t *rewritemaps;
     rewritemap_entry *entries;
     rewritemap_entry *s;
     char *value;
-    struct stat st;
+    apr_finfo_t st;
+    apr_status_t rv;
     int i;
 
     /* get map configuration */
@@ -2745,8 +2654,9 @@ static char *lookup_map(request_rec *r, char *name, char *key)
         s = &entries[i];
         if (strcmp(s->name, name) == 0) {
             if (s->type == MAPTYPE_TXT) {
-                if (stat(s->checkfile, &st) == -1) {
-                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                if ((rv = apr_stat(&st, s->checkfile, 
+                                   APR_FINFO_MIN, r->pool)) != APR_SUCCESS) {
+                    ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
                                  "mod_rewrite: can't access text RewriteMap "
                                  "file %s", s->checkfile);
                     rewritelog(r, 1, "can't open RewriteMap file, "
@@ -2754,7 +2664,7 @@ static char *lookup_map(request_rec *r, char *name, char *key)
                     return NULL;
                 }
                 value = get_cache_string(cachep, s->name, CACHEMODE_TS,
-                                         st.st_mtime, key);
+                                         st.mtime, key);
                 if (value == NULL) {
                     rewritelog(r, 6, "cache lookup FAILED, forcing new "
                                "map lookup");
@@ -2763,14 +2673,14 @@ static char *lookup_map(request_rec *r, char *name, char *key)
                         rewritelog(r, 5, "map lookup OK: map=%s key=%s[txt] "
                                    "-> val=%s", s->name, key, value);
                         set_cache_string(cachep, s->name, CACHEMODE_TS,
-                                         st.st_mtime, key, value);
+                                         st.mtime, key, value);
                         return value;
                     }
                     else {
                         rewritelog(r, 5, "map lookup FAILED: map=%s[txt] "
                                    "key=%s", s->name, key);
                         set_cache_string(cachep, s->name, CACHEMODE_TS,
-                                         st.st_mtime, key, "");
+                                         st.mtime, key, "");
                         return NULL;
                     }
                 }
@@ -2782,8 +2692,9 @@ static char *lookup_map(request_rec *r, char *name, char *key)
             }
             else if (s->type == MAPTYPE_DBM) {
 #ifndef NO_DBM_REWRITEMAP
-                if (stat(s->checkfile, &st) == -1) {
-                    ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r,
+                if ((rv = apr_stat(&st, s->checkfile,
+                                   APR_FINFO_MIN, r->pool)) != APR_SUCCESS) {
+                    ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
                                  "mod_rewrite: can't access DBM RewriteMap "
                                  "file %s", s->checkfile);
                     rewritelog(r, 1, "can't open DBM RewriteMap file, "
@@ -2791,7 +2702,7 @@ static char *lookup_map(request_rec *r, char *name, char *key)
                     return NULL;
                 }
                 value = get_cache_string(cachep, s->name, CACHEMODE_TS,
-                                         st.st_mtime, key);
+                                         st.mtime, key);
                 if (value == NULL) {
                     rewritelog(r, 6,
                                "cache lookup FAILED, forcing new map lookup");
@@ -2800,14 +2711,14 @@ static char *lookup_map(request_rec *r, char *name, char *key)
                         rewritelog(r, 5, "map lookup OK: map=%s[dbm] key=%s "
                                    "-> val=%s", s->name, key, value);
                         set_cache_string(cachep, s->name, CACHEMODE_TS,
-                                         st.st_mtime, key, value);
+                                         st.mtime, key, value);
                         return value;
                     }
                     else {
                         rewritelog(r, 5, "map lookup FAILED: map=%s[dbm] "
                                    "key=%s", s->name, key);
                         set_cache_string(cachep, s->name, CACHEMODE_TS,
-                                         st.st_mtime, key, "");
+                                         st.mtime, key, "");
                         return NULL;
                     }
                 }
@@ -2844,8 +2755,9 @@ static char *lookup_map(request_rec *r, char *name, char *key)
                 }
             }
             else if (s->type == MAPTYPE_RND) {
-                if (stat(s->checkfile, &st) == -1) {
-                    ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r,
+                if ((rv = apr_stat(&st, s->checkfile,
+                                   APR_FINFO_MIN, r->pool)) != APR_SUCCESS) {
+                    ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
                                  "mod_rewrite: can't access text RewriteMap "
                                  "file %s", s->checkfile);
                     rewritelog(r, 1, "can't open RewriteMap file, "
@@ -2853,7 +2765,7 @@ static char *lookup_map(request_rec *r, char *name, char *key)
                     return NULL;
                 }
                 value = get_cache_string(cachep, s->name, CACHEMODE_TS,
-                                         st.st_mtime, key);
+                                         st.mtime, key);
                 if (value == NULL) {
                     rewritelog(r, 6, "cache lookup FAILED, forcing new "
                                "map lookup");
@@ -2862,13 +2774,13 @@ static char *lookup_map(request_rec *r, char *name, char *key)
                         rewritelog(r, 5, "map lookup OK: map=%s key=%s[txt] "
                                    "-> val=%s", s->name, key, value);
                         set_cache_string(cachep, s->name, CACHEMODE_TS,
-                                         st.st_mtime, key, value);
+                                         st.mtime, key, value);
                     }
                     else {
                         rewritelog(r, 5, "map lookup FAILED: map=%s[txt] "
                                    "key=%s", s->name, key);
                         set_cache_string(cachep, s->name, CACHEMODE_TS,
-                                         st.st_mtime, key, "");
+                                         st.mtime, key, "");
                         return NULL;
                     }
                 }
@@ -2890,10 +2802,10 @@ static char *lookup_map(request_rec *r, char *name, char *key)
     return NULL;
 }
 
-static char *lookup_map_txtfile(request_rec *r, char *file, char *key)
+static char *lookup_map_txtfile(request_rec *r, const char *file, char *key)
 {
-    ap_file_t *fp = NULL;
-    ap_status_t rc;
+    apr_file_t *fp = NULL;
+    apr_status_t rc;
     char line[1024];
     char *value = NULL;
     char *cpT;
@@ -2901,12 +2813,12 @@ static char *lookup_map_txtfile(request_rec *r, char *file, char *key)
     char *curkey;
     char *curval;
 
-    rc = ap_open(&fp, file, APR_READ | APR_BUFFERED, APR_OS_DEFAULT, r->pool);
+    rc = apr_file_open(&fp, file, APR_READ, APR_OS_DEFAULT, r->pool);
     if (rc != APR_SUCCESS) {
        return NULL;
     }
 
-    while (ap_fgets(line, sizeof(line), fp) == APR_SUCCESS) {
+    while (apr_file_gets(line, sizeof(line), fp) == APR_SUCCESS) {
         if (line[0] == '#')
             continue; /* ignore comments */
         cpT = line;
@@ -2929,15 +2841,15 @@ static char *lookup_map_txtfile(request_rec *r, char *file, char *key)
             continue; /* no value... */
         cpT += skip;
         *cpT = '\0';
-        value = ap_pstrdup(r->pool, curval);
+        value = apr_pstrdup(r->pool, curval);
         break;
     }
-    ap_close(fp);
+    apr_file_close(fp);
     return value;
 }
 
 #ifndef NO_DBM_REWRITEMAP
-static char *lookup_map_dbmfile(request_rec *r, char *file, char *key)
+static char *lookup_map_dbmfile(request_rec *r, const char *file, char *key)
 {
     DBM *dbmfp = NULL;
     datum dbmkey;
@@ -2954,7 +2866,7 @@ static char *lookup_map_dbmfile(request_rec *r, char *file, char *key)
                    dbmval.dsize < sizeof(buf)-1 ? 
                    dbmval.dsize : sizeof(buf)-1  );
             buf[dbmval.dsize] = '\0';
-            value = ap_pstrdup(r->pool, buf);
+            value = apr_pstrdup(r->pool, buf);
         }
         dbm_close(dbmfp);
     }
@@ -2962,17 +2874,17 @@ static char *lookup_map_dbmfile(request_rec *r, char *file, char *key)
 }
 #endif
 
-static char *lookup_map_program(request_rec *r, ap_file_t *fpin,
-                                ap_file_t *fpout, char *key)
+static char *lookup_map_program(request_rec *r, apr_file_t *fpin,
+                                apr_file_t *fpout, char *key)
 {
     char buf[LONG_STRING_LEN];
     char c;
     int i;
-    ap_size_t nbytes;
+    apr_size_t nbytes;
 
 #ifndef NO_WRITEV
     struct iovec iova[2];
-    ap_size_t niov;
+    apr_size_t niov;
 #endif
 
     /* when `RewriteEngine off' was used in the per-server
@@ -2986,12 +2898,16 @@ static char *lookup_map_program(request_rec *r, ap_file_t *fpin,
 
     /* take the lock */
 
-    ap_lock(rewrite_map_lock);
+    if (rewrite_mapr_lock_aquire) {
+        apr_lock_aquire(rewrite_mapr_lock_aquire);
+    }
 
     /* write out the request key */
 #ifdef NO_WRITEV
-    ap_write(fpin, key, strlen(key));
-    ap_write(fpin, "\n", 1);
+    nbytes = strlen(key);
+    apr_file_write(fpin, key, &nbytes);
+    nbytes = 1;
+    apr_file_write(fpin, "\n", &nbytes);
 #else
     iova[0].iov_base = key;
     iova[0].iov_len = strlen(key);
@@ -2999,31 +2915,33 @@ static char *lookup_map_program(request_rec *r, ap_file_t *fpin,
     iova[1].iov_len = 1;
 
     niov = 2;
-    ap_writev(fpin, iova, niov, &nbytes);
+    apr_file_writev(fpin, iova, niov, &nbytes);
 #endif
 
     /* read in the response value */
     i = 0;
     nbytes = 1;
-    ap_read(fpout, &c, &nbytes);
+    apr_file_read(fpout, &c, &nbytes);
     while (nbytes == 1 && (i < LONG_STRING_LEN-1)) {
         if (c == '\n') {
             break;
         }
         buf[i++] = c;
 
-        ap_read(fpout, &c, &nbytes);
+        apr_file_read(fpout, &c, &nbytes);
     }
     buf[i] = '\0';
 
     /* give the lock back */
-    ap_unlock(rewrite_map_lock);
+    if (rewrite_mapr_lock_aquire) {
+        apr_lock_release(rewrite_mapr_lock_aquire);
+    }
 
     if (strcasecmp(buf, "NULL") == 0) {
         return NULL;
     }
     else {
-        return ap_pstrdup(r->pool, buf);
+        return apr_pstrdup(r->pool, buf);
     }
 }
 
@@ -3040,9 +2958,9 @@ static char *rewrite_mapfunc_toupper(request_rec *r, char *key)
 {
     char *value, *cp;
 
-    for (cp = value = ap_pstrdup(r->pool, key); cp != NULL && *cp != '\0';
+    for (cp = value = apr_pstrdup(r->pool, key); cp != NULL && *cp != '\0';
          cp++) {
-        *cp = ap_toupper(*cp);
+        *cp = apr_toupper(*cp);
     }
     return value;
 }
@@ -3051,9 +2969,9 @@ static char *rewrite_mapfunc_tolower(request_rec *r, char *key)
 {
     char *value, *cp;
 
-    for (cp = value = ap_pstrdup(r->pool, key); cp != NULL && *cp != '\0';
+    for (cp = value = apr_pstrdup(r->pool, key); cp != NULL && *cp != '\0';
          cp++) {
-        *cp = ap_tolower(*cp);
+        *cp = apr_tolower(*cp);
     }
     return value;
 }
@@ -3070,7 +2988,7 @@ static char *rewrite_mapfunc_unescape(request_rec *r, char *key)
 {
     char *value;
 
-    value = ap_pstrdup(r->pool, key);
+    value = apr_pstrdup(r->pool, key);
     ap_unescape_url(value);
     return value;
 }
@@ -3127,7 +3045,7 @@ static char *select_random_value_part(request_rec *r, char *value)
             n++;
         }
     }
-    buf = ap_pstrdup(r->pool, &value[i]);
+    buf = apr_pstrdup(r->pool, &value[i]);
     for (i = 0; buf[i] != '\0' && buf[i] != '|'; i++)
         ;
     buf[i] = '\0';
@@ -3144,11 +3062,11 @@ static char *select_random_value_part(request_rec *r, char *value)
 */
 
 
-static void open_rewritelog(server_rec *s, ap_context_t *p)
+static void open_rewritelog(server_rec *s, apr_pool_t *p)
 {
     rewrite_server_conf *conf;
     const char *fname;
-    ap_status_t rc;
+    apr_status_t rc;
     piped_log *pl;
     int    rewritelog_flags = ( APR_WRITE | APR_APPEND | APR_CREATE );
     mode_t rewritelog_mode  = ( APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD );
@@ -3169,7 +3087,7 @@ static void open_rewritelog(server_rec *s, ap_context_t *p)
 
     if (*conf->rewritelogfile == '|') {
         if ((pl = ap_open_piped_log(p, conf->rewritelogfile+1)) == NULL) {
-            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, 
+            ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, s, 
                          "mod_rewrite: could not open reliable pipe "
                          "to RewriteLog filter %s", conf->rewritelogfile+1);
             exit(1);
@@ -3177,9 +3095,9 @@ static void open_rewritelog(server_rec *s, ap_context_t *p)
         conf->rewritelogfp = ap_piped_log_write_fd(pl);
     }
     else if (*conf->rewritelogfile != '\0') {
-        rc = ap_open(&conf->rewritelogfp, fname, rewritelog_flags, rewritelog_mode, p);
+        rc = apr_file_open(&conf->rewritelogfp, fname, rewritelog_flags, rewritelog_mode, p);
         if (rc != APR_SUCCESS)  {
-            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, 
+            ap_log_error(APLOG_MARK, APLOG_ERR, rc, s, 
                          "mod_rewrite: could not open RewriteLog "
                          "file %s", fname);
             exit(1);
@@ -3199,7 +3117,7 @@ static void rewritelog(request_rec *r, int level, const char *text, ...)
     char redir[20];
     va_list ap;
     int i;
-    ap_size_t nbytes;
+    apr_size_t nbytes;
     request_rec *req;
     char *ruser;
     const char *rhost;
@@ -3238,11 +3156,11 @@ static void rewritelog(request_rec *r, int level, const char *text, ...)
         rhost = "UNKNOWN-HOST";
     }
 
-    str1 = ap_pstrcat(r->pool, rhost, " ",
+    str1 = apr_pstrcat(r->pool, rhost, " ",
                       (conn->remote_logname != NULL ?
                       conn->remote_logname : "-"), " ",
                       ruser, NULL);
-    ap_vsnprintf(str2, sizeof(str2), text, ap);
+    apr_vsnprintf(str2, sizeof(str2), text, ap);
 
     if (r->main == NULL) {
         strcpy(type, "initial");
@@ -3258,19 +3176,19 @@ static void rewritelog(request_rec *r, int level, const char *text, ...)
         redir[0] = '\0';
     }
     else {
-        ap_snprintf(redir, sizeof(redir), "/redir#%d", i);
+        apr_snprintf(redir, sizeof(redir), "/redir#%d", i);
     }
 
-    ap_snprintf(str3, sizeof(str3),
+    apr_snprintf(str3, sizeof(str3),
                 "%s %s [%s/sid#%lx][rid#%lx/%s%s] (%d) %s\n", str1,
                 current_logtime(r), ap_get_server_name(r),
                 (unsigned long)(r->server), (unsigned long)r,
                 type, redir, level, str2);
 
-    ap_lock(rewrite_log_lock);
+    apr_lock_aquire(rewrite_log_lock);
     nbytes = strlen(str3);
-    ap_write(conf->rewritelogfp, str3, &nbytes);
-    ap_unlock(rewrite_log_lock);
+    apr_file_write(conf->rewritelogfp, str3, &nbytes);
+    apr_lock_release(rewrite_log_lock);
 
     va_end(ap);
     return;
@@ -3278,17 +3196,17 @@ static void rewritelog(request_rec *r, int level, const char *text, ...)
 
 static char *current_logtime(request_rec *r)
 {
-    ap_exploded_time_t t;
+    apr_exploded_time_t t;
     char tstr[80];
-    ap_size_t len;
+    apr_size_t len;
 
-    ap_explode_localtime(&t, ap_now());
+    apr_explode_localtime(&t, apr_time_now());
 
-    ap_strftime(tstr, &len, 80, "[%d/%b/%Y:%H:%M:%S ", &t);
-    ap_snprintf(tstr + strlen(tstr), 80-strlen(tstr), "%c%.2d%.2d]",
+    apr_strftime(tstr, &len, 80, "[%d/%b/%Y:%H:%M:%S ", &t);
+    apr_snprintf(tstr + strlen(tstr), 80-strlen(tstr), "%c%.2d%.2d]",
                 t.tm_gmtoff < 0 ? '-' : '+',
                t.tm_gmtoff / (60*60), t.tm_gmtoff % (60*60));
-    return ap_pstrdup(r->pool, tstr);
+    return apr_pstrdup(r->pool, tstr);
 }
 
 
@@ -3304,9 +3222,9 @@ static char *current_logtime(request_rec *r)
 
 #define REWRITELOCK_MODE ( APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD )
 
-static void rewritelock_create(server_rec *s, ap_context_t *p)
+static void rewritelock_create(server_rec *s, apr_pool_t *p)
 {
-    ap_status_t rc;
+    apr_status_t rc;
 
     /* only operate if a lockfile is used */
     if (lockname == NULL || *(lockname) == '\0') {
@@ -3317,9 +3235,9 @@ static void rewritelock_create(server_rec *s, ap_context_t *p)
     lockname = ap_server_root_relative(p, lockname);
 
     /* create the lockfile */
-    rc = ap_create_lock (&rewrite_map_lock, APR_MUTEX, APR_LOCKALL, lockname, p);
+    rc = apr_lock_create (&rewrite_mapr_lock_aquire, APR_MUTEX, APR_LOCKALL, lockname, p);
     if (rc != APR_SUCCESS) {
-        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+        ap_log_error(APLOG_MARK, APLOG_ERR, rc, s,
                      "mod_rewrite: Parent could not create RewriteLock "
                      "file %s", lockname);
         exit(1);
@@ -3328,11 +3246,16 @@ static void rewritelock_create(server_rec *s, ap_context_t *p)
     return;
 }
 
-static ap_status_t rewritelock_remove(void *data)
+static apr_status_t rewritelock_remove(void *data)
 {
+    /* only operate if a lockfile is used */
+    if (lockname == NULL || *(lockname) == '\0') {
+        return APR_SUCCESS;
+    }
+
     /* destroy the rewritelock */
-    ap_destroy_lock (rewrite_map_lock);
-    rewrite_map_lock = NULL;
+    apr_lock_destroy (rewrite_mapr_lock_aquire);
+    rewrite_mapr_lock_aquire = NULL;
     lockname = NULL;
     return(0);
 }
@@ -3346,17 +3269,17 @@ static ap_status_t rewritelock_remove(void *data)
 ** +-------------------------------------------------------+
 */
 
-static void run_rewritemap_programs(server_rec *s, ap_context_t *p)
+static void run_rewritemap_programs(server_rec *s, apr_pool_t *p)
 {
     rewrite_server_conf *conf;
-    ap_file_t *fpin = NULL;
-    ap_file_t *fpout = NULL;
-    ap_file_t *fperr = NULL;
-    ap_array_header_t *rewritemaps;
+    apr_file_t *fpin = NULL;
+    apr_file_t *fpout = NULL;
+    apr_file_t *fperr = NULL;
+    apr_array_header_t *rewritemaps;
     rewritemap_entry *entries;
     rewritemap_entry *map;
     int i;
-    int rc;
+    apr_status_t rc;
 
     conf = ap_get_module_config(s->module_config, &rewrite_module);
 
@@ -3385,9 +3308,9 @@ static void run_rewritemap_programs(server_rec *s, ap_context_t *p)
         rc = rewritemap_program_child(p, map->datafile,
                                      &fpout, &fpin, &fperr);
         if (rc != APR_SUCCESS || fpin == NULL || fpout == NULL) {
-            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+            ap_log_error(APLOG_MARK, APLOG_ERR, rc, s,
                          "mod_rewrite: could not fork child for "
-                         "RewriteMap process. %d", rc);
+                         "RewriteMap process");
             exit(1);
         }
         map->fpin  = fpin;
@@ -3398,53 +3321,50 @@ static void run_rewritemap_programs(server_rec *s, ap_context_t *p)
 }
 
 /* child process code */
-static int rewritemap_program_child(ap_context_t *p, char *progname,
-                                    ap_file_t **fpout, ap_file_t **fpin,
-                                    ap_file_t **fperr)
+static apr_status_t rewritemap_program_child(apr_pool_t *p, const char *progname,
+                                             apr_file_t **fpout, apr_file_t **fpin,
+                                             apr_file_t **fperr)
 {
-    int rc = -1;
-    ap_procattr_t *procattr;
-    ap_proc_t *procnew;
-
-    ap_block_alarms();
+    apr_status_t rc;
+    apr_procattr_t *procattr;
+    apr_proc_t *procnew;
 
 #ifdef SIGHUP
-    signal(SIGHUP, SIG_IGN);
+    apr_signal(SIGHUP, SIG_IGN);
 #endif
 
     
-    if ((ap_createprocattr_init(&procattr, p)           != APR_SUCCESS) ||
-        (ap_setprocattr_io(procattr, APR_FULL_BLOCK,
-                                     APR_FULL_NONBLOCK,
-                                     APR_FULL_NONBLOCK) != APR_SUCCESS) ||
-        (ap_setprocattr_dir(procattr, ap_make_dirstr_parent(p, progname))
-                                                        != APR_SUCCESS) ||
-        (ap_setprocattr_cmdtype(procattr, APR_PROGRAM)  != APR_SUCCESS)) {
+    if (((rc = apr_procattr_create(&procattr, p)) != APR_SUCCESS) ||
+        ((rc = apr_procattr_io_set(procattr, APR_FULL_BLOCK,
+                                  APR_FULL_NONBLOCK,
+                                  APR_FULL_NONBLOCK)) != APR_SUCCESS) ||
+        ((rc = apr_procattr_dir_set(procattr, 
+                                   ap_make_dirstr_parent(p, progname)))
+         != APR_SUCCESS) ||
+        ((rc = apr_procattr_cmdtype_set(procattr, APR_PROGRAM)) != APR_SUCCESS)) {
         /* Something bad happened, give up and go away. */
-        rc = -1;
     }
     else {
-        rc = ap_create_process(&procnew, progname, NULL, NULL, procattr, p);
+        procnew = apr_pcalloc(p, sizeof(*procnew));
+        rc = apr_proc_create(procnew, progname, NULL, NULL, procattr, p);
     
         if (rc == APR_SUCCESS) {
-            ap_note_subprocess(p, procnew, kill_after_timeout);
+            apr_pool_note_subprocess(p, procnew, kill_after_timeout);
 
             if (fpin) {
-                ap_get_childin(fpin, procnew);
+                (*fpin) = procnew->in;
             }
 
             if (fpout) {
-                ap_get_childout(fpout, procnew);
+                (*fpout) = procnew->out;
             }
 
             if (fperr) {
-                ap_get_childerr(fperr, procnew);
+                (*fperr) = procnew->err;
             }
         }
     }
 
-    ap_unblock_alarms();
-
     return (rc);
 }
 
@@ -3460,64 +3380,12 @@ static int rewritemap_program_child(ap_context_t *p, char *progname,
 */
 
 
-static void expand_variables_inbuffer(request_rec *r, char *buf, int buf_len)
-{
-    char *newbuf;
-    newbuf = expand_variables(r, buf);
-    if (strcmp(newbuf, buf) != 0) {
-        ap_cpystrn(buf, newbuf, buf_len);
-    }
-    return;
-}
-
-static char *expand_variables(request_rec *r, char *str)
-{
-    char output[MAX_STRING_LEN];
-    char input[MAX_STRING_LEN];
-    char *cp;
-    char *cp2;
-    char *cp3;
-    int expanded;
-    char *outp;
-    char *endp;
-
-    ap_cpystrn(input, str, sizeof(input));
-    output[0] = '\0';
-    outp = output;
-    endp = output + sizeof(output);
-    expanded = 0;
-    for (cp = input; cp < input+MAX_STRING_LEN; ) {
-        if ((cp2 = strstr(cp, "%{")) != NULL) {
-            if ((cp3 = strstr(cp2, "}")) != NULL) {
-                *cp2 = '\0';
-                outp = ap_cpystrn(outp, cp, endp - outp);
-
-                cp2 += 2;
-                *cp3 = '\0';
-                outp = ap_cpystrn(outp, lookup_variable(r, cp2), endp - outp);
-
-                cp = cp3+1;
-                expanded = 1;
-                continue;
-            }
-        }
-        outp = ap_cpystrn(outp, cp, endp - outp);
-        break;
-    }
-    return expanded ? ap_pstrdup(r->pool, output) : str;
-}
-
 static char *lookup_variable(request_rec *r, char *var)
 {
     const char *result;
     char resultbuf[LONG_STRING_LEN];
-    ap_exploded_time_t tm;
+    apr_exploded_time_t tm;
     request_rec *rsub;
-#ifndef WIN32
-    struct passwd *pw;
-    struct group *gr;
-    struct stat finfo;
-#endif
 
     result = NULL;
 
@@ -3604,7 +3472,7 @@ static char *lookup_variable(request_rec *r, char *var)
         result = r->connection->local_ip;
     }
     else if (strcasecmp(var, "SERVER_PORT") == 0) {
-        ap_snprintf(resultbuf, sizeof(resultbuf), "%u", ap_get_server_port(r));
+        apr_snprintf(resultbuf, sizeof(resultbuf), "%u", ap_get_server_port(r));
         result = resultbuf;
     }
     else if (strcasecmp(var, "SERVER_PROTOCOL") == 0) {
@@ -3614,7 +3482,7 @@ static char *lookup_variable(request_rec *r, char *var)
         result = ap_get_server_version();
     }
     else if (strcasecmp(var, "API_VERSION") == 0) { /* non-standard */
-        ap_snprintf(resultbuf, sizeof(resultbuf), "%d:%d",
+        apr_snprintf(resultbuf, sizeof(resultbuf), "%d:%d",
                    MODULE_MAGIC_NUMBER_MAJOR, MODULE_MAGIC_NUMBER_MINOR);
         result = resultbuf;
     }
@@ -3622,13 +3490,13 @@ static char *lookup_variable(request_rec *r, char *var)
 /* XXX: wow this has gotta be slow if you actually use it for a lot, recalculates exploded time for each variable */
     /* underlaying Unix system stuff */
     else if (strcasecmp(var, "TIME_YEAR") == 0) {
-        ap_explode_localtime(&tm, ap_now());
-        ap_snprintf(resultbuf, sizeof(resultbuf), "%04d", tm.tm_year + 1900);
+        apr_explode_localtime(&tm, apr_time_now());
+        apr_snprintf(resultbuf, sizeof(resultbuf), "%04d", tm.tm_year + 1900);
         result = resultbuf;
     }
 #define MKTIMESTR(format, tmfield) \
-    ap_explode_localtime(&tm, ap_now()); \
-    ap_snprintf(resultbuf, sizeof(resultbuf), format, tm.tmfield); \
+    apr_explode_localtime(&tm, apr_time_now()); \
+    apr_snprintf(resultbuf, sizeof(resultbuf), format, tm.tmfield); \
     result = resultbuf;
     else if (strcasecmp(var, "TIME_MON") == 0) {
         MKTIMESTR("%02d", tm_mon+1)
@@ -3649,8 +3517,8 @@ static char *lookup_variable(request_rec *r, char *var)
         MKTIMESTR("%d", tm_wday)
     }
     else if (strcasecmp(var, "TIME") == 0) {
-        ap_explode_localtime(&tm, ap_now());
-        ap_snprintf(resultbuf, sizeof(resultbuf),
+        apr_explode_localtime(&tm, apr_time_now());
+        apr_snprintf(resultbuf, sizeof(resultbuf),
                    "%04d%02d%02d%02d%02d%02d", tm.tm_year + 1900,
                    tm.tm_mon+1, tm.tm_mday,
                    tm.tm_hour, tm.tm_min, tm.tm_sec);
@@ -3661,10 +3529,10 @@ static char *lookup_variable(request_rec *r, char *var)
     /* all other env-variables from the parent Apache process */
     else if (strlen(var) > 4 && strncasecmp(var, "ENV:", 4) == 0) {
         /* first try the internal Apache notes structure */
-        result = ap_table_get(r->notes, var+4);
+        result = apr_table_get(r->notes, var+4);
         /* second try the internal Apache env structure  */
         if (result == NULL) {
-            result = ap_table_get(r->subprocess_env, var+4);
+            result = apr_table_get(r->subprocess_env, var+4);
         }
         /* third try the external OS env */
         if (result == NULL) {
@@ -3683,11 +3551,11 @@ static char *lookup_variable(request_rec *r, char *var)
                         /*   ...and sub and main paths differ */ \
                         && strcmp(r->main->uri, r->uri) != 0))) { \
             /* process a file-based subrequest */ \
-            rsub = subrecfunc(r->filename, r); \
+            rsub = subrecfunc(r->filename, r, NULL); \
             /* now recursively lookup the variable in the sub_req */ \
             result = lookup_variable(rsub, var+5); \
-            /* copy it up to our scope before we destroy sub_req's ap_context_t */ \
-            result = ap_pstrdup(r->pool, result); \
+            /* copy it up to our scope before we destroy sub_req's apr_pool_t */ \
+            result = apr_pstrdup(r->pool, result); \
             /* cleanup by destroying the subrequest */ \
             ap_destroy_sub_req(rsub); \
             /* log it */ \
@@ -3706,65 +3574,42 @@ static char *lookup_variable(request_rec *r, char *var)
         LOOKAHEAD(ap_sub_req_lookup_file)
     }
 
-#if !defined(WIN32) && !defined(NETWARE)
-    /* Win32 has a rather different view of file ownerships.
-       For now, just forget it */
-
     /* file stuff */
     else if (strcasecmp(var, "SCRIPT_USER") == 0) {
         result = "<unknown>";
-        if (r->finfo.protection != 0) {
-            if ((pw = getpwuid(r->finfo.user)) != NULL) {
-                result = pw->pw_name;
-            }
-        }
-        else {
-            if (stat(r->filename, &finfo) == 0) {
-                if ((pw = getpwuid(finfo.st_uid)) != NULL) {
-                    result = pw->pw_name;
-                }
-            }
+        if (r->finfo.valid & APR_FINFO_USER) {
+            apr_get_username((char **)&result, r->finfo.user, r->pool);
         }
     }
     else if (strcasecmp(var, "SCRIPT_GROUP") == 0) {
         result = "<unknown>";
-        if (r->finfo.protection != 0) {
-            if ((gr = getgrgid(r->finfo.group)) != NULL) {
-                result = gr->gr_name;
-            }
-        }
-        else {
-            if (stat(r->filename, &finfo) == 0) {
-                if ((gr = getgrgid(finfo.st_gid)) != NULL) {
-                    result = gr->gr_name;
-                }
-            }
+        if (r->finfo.valid & APR_FINFO_GROUP) {
+            apr_get_groupname((char **)&result, r->finfo.group, r->pool);
         }
     }
-#endif /* ndef WIN32 && NETWARE*/
 
     if (result == NULL) {
-        return ap_pstrdup(r->pool, "");
+        return apr_pstrdup(r->pool, "");
     }
     else {
-        return ap_pstrdup(r->pool, result);
+        return apr_pstrdup(r->pool, result);
     }
 }
 
 static char *lookup_header(request_rec *r, const char *name)
 {
-    ap_array_header_t *hdrs_arr;
-    ap_table_entry_t *hdrs;
+    apr_array_header_t *hdrs_arr;
+    apr_table_entry_t *hdrs;
     int i;
 
-    hdrs_arr = ap_table_elts(r->headers_in);
-    hdrs = (ap_table_entry_t *)hdrs_arr->elts;
+    hdrs_arr = apr_table_elts(r->headers_in);
+    hdrs = (apr_table_entry_t *)hdrs_arr->elts;
     for (i = 0; i < hdrs_arr->nelts; ++i) {
         if (hdrs[i].key == NULL) {
             continue;
         }
         if (strcasecmp(hdrs[i].key, name) == 0) {
-           ap_table_merge(r->notes, VARY_KEY_THIS, name);
+           apr_table_merge(r->notes, VARY_KEY_THIS, name);
             return hdrs[i].val;
         }
     }
@@ -3783,18 +3628,18 @@ static char *lookup_header(request_rec *r, const char *name)
 */
 
 
-static cache *init_cache(ap_context_t *p)
+static cache *init_cache(apr_pool_t *p)
 {
     cache *c;
 
-    c = (cache *)ap_palloc(p, sizeof(cache));
-    if (ap_create_context(&c->pool, p) != APR_SUCCESS)
+    c = (cache *)apr_palloc(p, sizeof(cache));
+    if (apr_pool_create(&c->pool, p) != APR_SUCCESS)
                return NULL;
-    c->lists = ap_make_array(c->pool, 2, sizeof(cachelist));
+    c->lists = apr_array_make(c->pool, 2, sizeof(cachelist));
     return c;
 }
 
-static void set_cache_string(cache *c, char *res, int mode, time_t t,
+static void set_cache_string(cache *c, const char *res, int mode, time_t t,
                              char *key, char *value)
 {
     cacheentry ce;
@@ -3806,7 +3651,7 @@ static void set_cache_string(cache *c, char *res, int mode, time_t t,
     return;
 }
 
-static char *get_cache_string(cache *c, char *res, int mode,
+static char *get_cache_string(cache *c, const char *res, int mode,
                               time_t t, char *key)
 {
     cacheentry *ce;
@@ -3825,7 +3670,7 @@ static char *get_cache_string(cache *c, char *res, int mode,
             return NULL;
         }
     }
-    return ap_pstrdup(c->pool, ce->value);
+    return apr_pstrdup(c->pool, ce->value);
 }
 
 static int cache_tlb_hash(char *key)
@@ -3834,8 +3679,8 @@ static int cache_tlb_hash(char *key)
     char *p;
 
     n = 0;
-    for (p=key; *p != '\0'; ++p) {
-        n = n * 53711 + 134561 + (unsigned)(*p & 0xff);
+    for (p = key; *p != '\0'; p++) {
+        n = ((n << 5) + n) ^ (unsigned long)(*p++);
     }
 
     return n % CACHE_TLB_ROWS;
@@ -3872,7 +3717,7 @@ static void cache_tlb_replace(cachetlbentry *tlb, cacheentry *elt,
     tlb->t[0] = e - elt;
 }
 
-static void store_cache_string(cache *c, char *res, cacheentry *ce)
+static void store_cache_string(cache *c, const char *res, cacheentry *ce)
 {
     int i;
     int j;
@@ -3892,7 +3737,7 @@ static void store_cache_string(cache *c, char *res, cacheentry *ce)
                                  (cacheentry *)l->entries->elts, ce->key);
             if (e != NULL) {
                 e->time  = ce->time;
-                e->value = ap_pstrdup(c->pool, ce->value);
+                e->value = apr_pstrdup(c->pool, ce->value);
                 return;
             }
 
@@ -3900,7 +3745,7 @@ static void store_cache_string(cache *c, char *res, cacheentry *ce)
                 e = &(((cacheentry *)l->entries->elts)[j]);
                 if (strcmp(e->key, ce->key) == 0) {
                     e->time  = ce->time;
-                    e->value = ap_pstrdup(c->pool, ce->value);
+                    e->value = apr_pstrdup(c->pool, ce->value);
                   cache_tlb_replace((cachetlbentry *)l->tlb->elts,
                                     (cacheentry *)l->entries->elts, e);
                     return;
@@ -3911,10 +3756,10 @@ static void store_cache_string(cache *c, char *res, cacheentry *ce)
 
     /* create a needed new list */
     if (!found_list) {
-        l = ap_push_array(c->lists);
-        l->resource = ap_pstrdup(c->pool, res);
-        l->entries  = ap_make_array(c->pool, 2, sizeof(cacheentry));
-        l->tlb      = ap_make_array(c->pool, CACHE_TLB_ROWS,
+        l = apr_array_push(c->lists);
+        l->resource = apr_pstrdup(c->pool, res);
+        l->entries  = apr_array_make(c->pool, 2, sizeof(cacheentry));
+        l->tlb      = apr_array_make(c->pool, CACHE_TLB_ROWS,
                                     sizeof(cachetlbentry));
         for (i=0; i<CACHE_TLB_ROWS; ++i) {
             t = &((cachetlbentry *)l->tlb->elts)[i];
@@ -3927,10 +3772,10 @@ static void store_cache_string(cache *c, char *res, cacheentry *ce)
     for (i = 0; i < c->lists->nelts; i++) {
         l = &(((cachelist *)c->lists->elts)[i]);
         if (strcmp(l->resource, res) == 0) {
-            e = ap_push_array(l->entries);
+            e = apr_array_push(l->entries);
             e->time  = ce->time;
-            e->key   = ap_pstrdup(c->pool, ce->key);
-            e->value = ap_pstrdup(c->pool, ce->value);
+            e->key   = apr_pstrdup(c->pool, ce->key);
+            e->value = apr_pstrdup(c->pool, ce->value);
             cache_tlb_replace((cachetlbentry *)l->tlb->elts,
                               (cacheentry *)l->entries->elts, e);
             return;
@@ -3941,7 +3786,7 @@ static void store_cache_string(cache *c, char *res, cacheentry *ce)
     return;
 }
 
-static cacheentry *retrieve_cache_string(cache *c, char *res, char *key)
+static cacheentry *retrieve_cache_string(cache *c, const char *res, char *key)
 {
     int i;
     int j;
@@ -3980,7 +3825,7 @@ static cacheentry *retrieve_cache_string(cache *c, char *res, char *key)
 */
 
 static char *subst_prefix_path(request_rec *r, char *input, char *match,
-                               char *subst)
+                               const char *subst)
 {
     char matchbuf[LONG_STRING_LEN];
     char substbuf[LONG_STRING_LEN];
@@ -3990,7 +3835,7 @@ static char *subst_prefix_path(request_rec *r, char *input, char *match,
     output = input;
 
     /* first create a match string which always has a trailing slash */
-    l = ap_cpystrn(matchbuf, match, sizeof(matchbuf)) - matchbuf;
+    l = apr_cpystrn(matchbuf, match, sizeof(matchbuf)) - matchbuf;
     if (matchbuf[l-1] != '/') {
        matchbuf[l] = '/';
        matchbuf[l+1] = '\0';
@@ -3999,10 +3844,10 @@ static char *subst_prefix_path(request_rec *r, char *input, char *match,
     /* now compare the prefix */
     if (strncmp(input, matchbuf, l) == 0) {
         rewritelog(r, 5, "strip matching prefix: %s -> %s", output, output+l);
-        output = ap_pstrdup(r->pool, output+l);
+        output = apr_pstrdup(r->pool, output+l);
 
         /* and now add the base-URL as replacement prefix */
-        l = ap_cpystrn(substbuf, subst, sizeof(substbuf)) - substbuf;
+        l = apr_cpystrn(substbuf, subst, sizeof(substbuf)) - substbuf;
         if (substbuf[l-1] != '/') {
            substbuf[l] = '/';
            substbuf[l+1] = '\0';
@@ -4011,12 +3856,12 @@ static char *subst_prefix_path(request_rec *r, char *input, char *match,
         if (output[0] == '/') {
             rewritelog(r, 4, "add subst prefix: %s -> %s%s",
                        output, substbuf, output+1);
-            output = ap_pstrcat(r->pool, substbuf, output+1, NULL);
+            output = apr_pstrcat(r->pool, substbuf, output+1, NULL);
         }
         else {
             rewritelog(r, 4, "add subst prefix: %s -> %s%s",
                        output, substbuf, output);
-            output = ap_pstrcat(r->pool, substbuf, output, NULL);
+            output = apr_pstrcat(r->pool, substbuf, output, NULL);
         }
     }
     return output;
@@ -4114,13 +3959,30 @@ static void add_env_variable(request_rec *r, char *s)
         n = ((cp-s) > MAX_STRING_LEN-1 ? MAX_STRING_LEN-1 : (cp-s));
         memcpy(var, s, n);
         var[n] = '\0';
-        ap_cpystrn(val, cp+1, sizeof(val));
-        ap_table_set(r->subprocess_env, var, val);
+        apr_cpystrn(val, cp+1, sizeof(val));
+        apr_table_set(r->subprocess_env, var, val);
         rewritelog(r, 5, "setting env variable '%s' to '%s'", var, val);
     }
 }
 
 
+/*
+**
+**  check that a subrequest won't cause infinite recursion
+**
+*/
+
+static int subreq_ok(request_rec *r)
+{
+    /*
+     * either not in a subrequest, or in a subrequest
+     * and URIs aren't NULL and sub/main URIs differ
+     */
+    return (r->main == NULL ||
+           (r->main->uri != NULL && r->uri != NULL &&
+            strcmp(r->main->uri, r->uri) != 0));
+}
+
 
 /*
 **
@@ -4128,19 +3990,19 @@ static void add_env_variable(request_rec *r, char *s)
 **
 */
 
-static int prefix_stat(const char *path, struct stat *sb)
+static int prefix_stat(const char *path, apr_finfo_t *sb)
 {
     char curpath[LONG_STRING_LEN];
     char *cp;
 
-    ap_cpystrn(curpath, path, sizeof(curpath));
+    apr_cpystrn(curpath, path, sizeof(curpath));
     if (curpath[0] != '/') {
         return 0;
     }
     if ((cp = strchr(curpath+1, '/')) != NULL) {
         *cp = '\0';
     }
-    if (stat(curpath, sb) == 0) {
+    if (apr_stat(sb, curpath, APR_FINFO_MIN, NULL) == APR_SUCCESS) {
         return 1;
     }
     else {
@@ -4179,11 +4041,105 @@ static int compare_lexicography(char *cpNum1, char *cpNum2)
     return 0;
 }
 
+/*
+**
+**  Bracketed expression handling
+**  s points after the opening bracket
+**
+*/
+
+static char *find_closing_bracket(char *s, int left, int right)
+{
+    int depth;
+
+    for (depth = 1; *s; ++s) {
+       if (*s == right && --depth == 0) {
+           return s;
+       }
+       else if (*s == left) {
+           ++depth;
+       }
+    }
+    return NULL;
+}
+
+static char *find_char_in_brackets(char *s, int c, int left, int right)
+{
+    int depth;
+
+    for (depth = 1; *s; ++s) {
+       if (*s == c && depth == 1) {
+           return s;
+       }
+       else if (*s == right && --depth == 0) {
+           return NULL;
+       }
+       else if (*s == left) {
+           ++depth;
+       }
+    }
+    return NULL;
+}
+
+/*
+**
+** Module paraphernalia
+**
+*/
+
 #ifdef NETWARE
 int main(int argc, char *argv[]) 
 {
     ExitThread(TSR_THREAD, 0);
 }
 #endif
+
+    /* the apr_table_t of commands we provide */
+static const command_rec command_table[] = {
+    AP_INIT_FLAG(    "RewriteEngine",   cmd_rewriteengine,  NULL, OR_FILEINFO,
+                     "On or Off to enable or disable (default) the whole "
+                     "rewriting engine"),
+    AP_INIT_ITERATE( "RewriteOptions",  cmd_rewriteoptions,  NULL, OR_FILEINFO,
+                     "List of option strings to set"),
+    AP_INIT_TAKE1(   "RewriteBase",     cmd_rewritebase,     NULL, OR_FILEINFO, 
+                     "the base URL of the per-directory context"),
+    AP_INIT_RAW_ARGS("RewriteCond",     cmd_rewritecond,     NULL, OR_FILEINFO,
+                     "an input string and a to be applied regexp-pattern"),
+    AP_INIT_RAW_ARGS("RewriteRule",     cmd_rewriterule,     NULL, OR_FILEINFO,
+                     "an URL-applied regexp-pattern and a substitution URL"),
+    AP_INIT_TAKE2(   "RewriteMap",      cmd_rewritemap,      NULL, RSRC_CONF,
+                     "a mapname and a filename"),
+    AP_INIT_TAKE1(   "RewriteLock",     cmd_rewritelock,     NULL, RSRC_CONF,
+                     "the filename of a lockfile used for inter-process "
+                     "synchronization"),
+    AP_INIT_TAKE1(   "RewriteLog",      cmd_rewritelog,      NULL, RSRC_CONF,
+                     "the filename of the rewriting logfile"),
+    AP_INIT_TAKE1(   "RewriteLogLevel", cmd_rewriteloglevel, NULL, RSRC_CONF,
+                     "the level of the rewriting logfile verbosity "
+                     "(0=none, 1=std, .., 9=max)"),
+    { NULL }
+};
+
+static void register_hooks(apr_pool_t *p)
+{
+    ap_hook_handler(handler_redirect, NULL, NULL, APR_HOOK_MIDDLE);
+    ap_hook_post_config(init_module,NULL,NULL,APR_HOOK_MIDDLE);
+    ap_hook_child_init(init_child,NULL,NULL,APR_HOOK_MIDDLE);
+
+    ap_hook_fixups(hook_fixup,NULL,NULL,APR_HOOK_FIRST);
+    ap_hook_translate_name(hook_uri2file,NULL,NULL,APR_HOOK_FIRST);
+    ap_hook_type_checker(hook_mimetype,NULL,NULL,APR_HOOK_MIDDLE);
+}
+
+    /* the main config structure */
+module AP_MODULE_DECLARE_DATA rewrite_module = {
+   STANDARD20_MODULE_STUFF,
+   config_perdir_create,        /* create per-dir    config structures */
+   config_perdir_merge,         /* merge  per-dir    config structures */
+   config_server_create,        /* create per-server config structures */
+   config_server_merge,         /* merge  per-server config structures */
+   command_table,               /* apr_table_t of config file commands  */
+   register_hooks               /* register hooks                      */
+};
  
 /*EOF*/