41a6c3
diff --git a/include/ap_mmn.h b/include/ap_mmn.h
41a6c3
index 89c4140..82a0acb 100644
41a6c3
--- a/include/ap_mmn.h
41a6c3
+++ b/include/ap_mmn.h
41a6c3
@@ -418,6 +418,7 @@
41a6c3
  *                         ap_proxy_pass_brigade()
41a6c3
  * 20120211.22 (2.4.5-dev) No longer prevent usage of strtoul()
41a6c3
  * 20120211.23 (2.4.5-dev) Add ap_proxy_clear_connection()
41a6c3
+ * 20120211.24 (2.4.7-dev) add open_htaccess hook.
41a6c3
  */
41a6c3
 
41a6c3
 #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
41a6c3
@@ -425,7 +426,7 @@
41a6c3
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
41a6c3
 #define MODULE_MAGIC_NUMBER_MAJOR 20120211
41a6c3
 #endif
41a6c3
-#define MODULE_MAGIC_NUMBER_MINOR 23                   /* 0...n */
41a6c3
+#define MODULE_MAGIC_NUMBER_MINOR 24                   /* 0...n */
41a6c3
 
41a6c3
 /**
41a6c3
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
41a6c3
diff --git a/include/http_config.h b/include/http_config.h
41a6c3
index 7ee3760..c93c3b2 100644
41a6c3
--- a/include/http_config.h
41a6c3
+++ b/include/http_config.h
41a6c3
@@ -1322,6 +1322,31 @@ AP_DECLARE_HOOK(int,quick_handler,(request_rec *r, int lookup_uri))
41a6c3
 AP_DECLARE_HOOK(void,optional_fn_retrieve,(void))
41a6c3
 
41a6c3
 /**
41a6c3
+ * Allow modules to open htaccess files or perform operations before doing so
41a6c3
+ * @param r The current request
41a6c3
+ * @param dir_name The directory for which the htaccess file should be opened
41a6c3
+ * @param access_name The filename  for which the htaccess file should be opened
41a6c3
+ * @param conffile Where the pointer to the opened ap_configfile_t must be
41a6c3
+ *        stored
41a6c3
+ * @param full_name Where the full file name of the htaccess file must be
41a6c3
+ *        stored.
41a6c3
+ * @return APR_SUCCESS on success,
41a6c3
+ *         APR_ENOENT or APR_ENOTDIR if no htaccess file exists,
41a6c3
+ *         AP_DECLINED to let later modules do the opening,
41a6c3
+ *         any other error code on error.
41a6c3
+ */
41a6c3
+AP_DECLARE_HOOK(apr_status_t,open_htaccess,
41a6c3
+                (request_rec *r, const char *dir_name, const char *access_name,
41a6c3
+                 ap_configfile_t **conffile, const char **full_name))
41a6c3
+
41a6c3
+/**
41a6c3
+ * Core internal function, use ap_run_open_htaccess() instead.
41a6c3
+ */
41a6c3
+apr_status_t ap_open_htaccess(request_rec *r, const char *dir_name,
41a6c3
+        const char *access_name, ap_configfile_t **conffile,
41a6c3
+        const char **full_name);
41a6c3
+
41a6c3
+/**
41a6c3
  * A generic pool cleanup that will reset a pointer to NULL. For use with
41a6c3
  * apr_pool_cleanup_register.
41a6c3
  * @param data The address of the pointer
41a6c3
diff --git a/server/config.c b/server/config.c
41a6c3
index c1aae17..265744e 100644
41a6c3
--- a/server/config.c
41a6c3
+++ b/server/config.c
41a6c3
@@ -80,6 +80,7 @@ APR_HOOK_STRUCT(
41a6c3
            APR_HOOK_LINK(quick_handler)
41a6c3
            APR_HOOK_LINK(optional_fn_retrieve)
41a6c3
            APR_HOOK_LINK(test_config)
41a6c3
+           APR_HOOK_LINK(open_htaccess)
41a6c3
 )
41a6c3
 
41a6c3
 AP_IMPLEMENT_HOOK_RUN_ALL(int, header_parser,
41a6c3
@@ -171,6 +172,12 @@ AP_IMPLEMENT_HOOK_RUN_FIRST(int, handler, (request_rec *r),
41a6c3
 AP_IMPLEMENT_HOOK_RUN_FIRST(int, quick_handler, (request_rec *r, int lookup),
41a6c3
                             (r, lookup), DECLINED)
41a6c3
 
41a6c3
+AP_IMPLEMENT_HOOK_RUN_FIRST(apr_status_t, open_htaccess,
41a6c3
+                            (request_rec *r, const char *dir_name, const char *access_name,
41a6c3
+                             ap_configfile_t **conffile, const char **full_name),
41a6c3
+                            (r, dir_name, access_name, conffile, full_name),
41a6c3
+                            AP_DECLINED)
41a6c3
+
41a6c3
 /* hooks with no args are implemented last, after disabling APR hook probes */
41a6c3
 #if defined(APR_HOOK_PROBES_ENABLED)
41a6c3
 #undef APR_HOOK_PROBES_ENABLED
41a6c3
@@ -2073,14 +2080,23 @@ AP_DECLARE(int) ap_process_config_tree(server_rec *s,
41a6c3
     return OK;
41a6c3
 }
41a6c3
 
41a6c3
+apr_status_t ap_open_htaccess(request_rec *r, const char *dir_name,
41a6c3
+                              const char *access_name,
41a6c3
+                              ap_configfile_t **conffile,
41a6c3
+                              const char **full_name)
41a6c3
+{
41a6c3
+    *full_name = ap_make_full_path(r->pool, dir_name, access_name);
41a6c3
+    return ap_pcfg_openfile(conffile, r->pool, *full_name);
41a6c3
+}
41a6c3
+
41a6c3
 AP_CORE_DECLARE(int) ap_parse_htaccess(ap_conf_vector_t **result,
41a6c3
                                        request_rec *r, int override,
41a6c3
                                        int override_opts, apr_table_t *override_list,
41a6c3
-                                       const char *d, const char *access_name)
41a6c3
+                                       const char *d, const char *access_names)
41a6c3
 {
41a6c3
     ap_configfile_t *f = NULL;
41a6c3
     cmd_parms parms;
41a6c3
-    char *filename = NULL;
41a6c3
+    const char *filename;
41a6c3
     const struct htaccess_result *cache;
41a6c3
     struct htaccess_result *new;
41a6c3
     ap_conf_vector_t *dc = NULL;
41a6c3
@@ -2104,15 +2120,11 @@ AP_CORE_DECLARE(int) ap_parse_htaccess(ap_conf_vector_t **result,
41a6c3
     parms.path = apr_pstrdup(r->pool, d);
41a6c3
 
41a6c3
     /* loop through the access names and find the first one */
41a6c3
-    while (access_name[0]) {
41a6c3
-        /* AFAICT; there is no use of the actual 'filename' against
41a6c3
-         * any canonicalization, so we will simply take the given
41a6c3
-         * name, ignoring case sensitivity and aliases
41a6c3
-         */
41a6c3
-        filename = ap_make_full_path(r->pool, d,
41a6c3
-                                     ap_getword_conf(r->pool, &access_name));
41a6c3
-        status = ap_pcfg_openfile(&f, r->pool, filename);
41a6c3
+    while (access_names[0]) {
41a6c3
+        const char *access_name = ap_getword_conf(r->pool, &access_names);
41a6c3
 
41a6c3
+        filename = NULL;
41a6c3
+        status = ap_run_open_htaccess(r, d, access_name, &f, &filename);
41a6c3
         if (status == APR_SUCCESS) {
41a6c3
             const char *errmsg;
41a6c3
             ap_directive_t *temptree = NULL;
41a6c3
diff --git a/server/core.c b/server/core.c
41a6c3
index f3965ca..85f876b 100644
41a6c3
--- a/server/core.c
41a6c3
+++ b/server/core.c
41a6c3
@@ -4930,6 +4930,7 @@ static void register_hooks(apr_pool_t *p)
41a6c3
     ap_hook_insert_network_bucket(core_insert_network_bucket, NULL, NULL,
41a6c3
                                   APR_HOOK_REALLY_LAST);
41a6c3
     ap_hook_dirwalk_stat(core_dirwalk_stat, NULL, NULL, APR_HOOK_REALLY_LAST);
41a6c3
+    ap_hook_open_htaccess(ap_open_htaccess, NULL, NULL, APR_HOOK_REALLY_LAST);
41a6c3
     
41a6c3
     /* register the core's insert_filter hook and register core-provided
41a6c3
      * filters