]> granicus.if.org Git - apache/blobdiff - modules/generators/mod_autoindex.c
adjust remaining modules to use the new handler hook method (Alan Edwards)
[apache] / modules / generators / mod_autoindex.c
index 0b4151bf28ec135525a399c498a842724839e20a..d4734ff93c1b2b275ef421624c089f433efbc5ad 100644 (file)
@@ -1,58 +1,59 @@
 /* ====================================================================
- * Copyright (c) 1995-1999 The Apache Group.  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
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    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 Group
- *    for use in the Apache HTTP server project (http://www.apache.org/)."
- *
- * 4. The names "Apache Server" and "Apache Group" 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.
+ * 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.
  *
- * 5. Products derived from this software may not be called "Apache"
- *    nor may "Apache" appear in their names without prior written
- *    permission of the Apache Group.
+ * 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.
  *
- * 6. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by the Apache Group
- *    for use in the Apache HTTP server project (http://www.apache.org/)."
+ * 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.
  *
- * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``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 GROUP 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 Group 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 Group 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.
  */
 
 /*
  * 3/23/93
  * 
  * Adapted to Apache by rst.
- */
+ *
+ * Version sort added by Martin Pool <mbp@humbug.org.au>. */
 
+#include "apr_strings.h"
+#include "ap_config.h"
 #include "httpd.h"
 #include "http_config.h"
 #include "http_core.h"
 #include "http_log.h"
 #include "http_main.h"
 #include "util_script.h"
-#include "fnmatch.h"
+#include "apr_fnmatch.h"
+#include "apr_strings.h"
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
 
-module MODULE_VAR_EXPORT autoindex_module;
+module AP_MODULE_DECLARE_DATA autoindex_module;
 
 /****************************************************************
  *
@@ -95,6 +106,7 @@ module MODULE_VAR_EXPORT autoindex_module;
 #define SUPPRESS_PREAMBLE 64
 #define SUPPRESS_COLSORT 128
 #define NO_OPTIONS 256
+#define VERSION_SORT   512
 
 #define K_PAD 1
 #define K_NOPAD 0
@@ -151,12 +163,12 @@ typedef struct autoindex_config_struct {
     int icon_height;
     char *default_order;
 
-    ap_array_header_t *icon_list;
-    ap_array_header_t *alt_list;
-    ap_array_header_t *desc_list;
-    ap_array_header_t *ign_list;
-    ap_array_header_t *hdr_list;
-    ap_array_header_t *rdme_list;
+    apr_array_header_t *icon_list;
+    apr_array_header_t *alt_list;
+    apr_array_header_t *desc_list;
+    apr_array_header_t *ign_list;
+    apr_array_header_t *hdr_list;
+    apr_array_header_t *rdme_list;
 
 } autoindex_config_rec;
 
@@ -171,7 +183,7 @@ static char c_by_encoding, c_by_type, c_by_path;
  * matches ".." or "../").  Hopefully this one call is significantly less
  * expensive than multiple strcmp() calls.
  */
-static ap_inline int is_parent(const char *name)
+static apr_inline int is_parent(const char *name)
 {
     /*
      * Now, IFF the first two bytes are dots, and the third byte is either
@@ -197,10 +209,10 @@ static void emit_preamble(request_rec *r, char *title)
              "</TITLE>\n </HEAD>\n <BODY>\n", NULL);
 }
 
-static void push_item(ap_array_header_t *arr, char *type, char *to, char *path,
-                     char *data)
+static void push_item(apr_array_header_t *arr, char *type, const char *to,
+                     const char *path, const char *data)
 {
-    struct item *p = (struct item *) ap_push_array(arr);
+    struct item *p = (struct item *) apr_push_array(arr);
 
     if (!to) {
        to = "";
@@ -210,21 +222,22 @@ static void push_item(ap_array_header_t *arr, char *type, char *to, char *path,
     }
 
     p->type = type;
-    p->data = data ? ap_pstrdup(arr->cont, data) : NULL;
-    p->apply_path = ap_pstrcat(arr->cont, path, "*", NULL);
+    p->data = data ? apr_pstrdup(arr->cont, data) : NULL;
+    p->apply_path = apr_pstrcat(arr->cont, path, "*", NULL);
 
     if ((type == BY_PATH) && (!ap_is_matchexp(to))) {
-       p->apply_to = ap_pstrcat(arr->cont, "*", to, NULL);
+       p->apply_to = apr_pstrcat(arr->cont, "*", to, NULL);
     }
     else if (to) {
-       p->apply_to = ap_pstrdup(arr->cont, to);
+       p->apply_to = apr_pstrdup(arr->cont, to);
     }
     else {
        p->apply_to = NULL;
     }
 }
 
-static const char *add_alt(cmd_parms *cmd, void *d, char *alt, char *to)
+static const char *add_alt(cmd_parms *cmd, void *d, const char *alt,
+                          const char *to)
 {
     if (cmd->info == BY_PATH) {
         if (!strcmp(to, "**DIRECTORY**")) {
@@ -232,7 +245,9 @@ static const char *add_alt(cmd_parms *cmd, void *d, char *alt, char *to)
        }
     }
     if (cmd->info == BY_ENCODING) {
-       ap_str_tolower(to);
+        char *tmp = apr_pstrdup(cmd->pool, to);
+       ap_str_tolower(tmp);
+       to = tmp;
     }
 
     push_item(((autoindex_config_rec *) d)->alt_list, cmd->info, to,
@@ -240,9 +255,10 @@ static const char *add_alt(cmd_parms *cmd, void *d, char *alt, char *to)
     return NULL;
 }
 
-static const char *add_icon(cmd_parms *cmd, void *d, char *icon, char *to)
+static const char *add_icon(cmd_parms *cmd, void *d, const char *icon,
+                           const char *to)
 {
-    char *iconbak = ap_pstrdup(cmd->pool, icon);
+    char *iconbak = apr_pstrdup(cmd->pool, icon);
 
     if (icon[0] == '(') {
        char *alt;
@@ -261,7 +277,9 @@ static const char *add_icon(cmd_parms *cmd, void *d, char *icon, char *to)
        }
     }
     if (cmd->info == BY_ENCODING) {
-       ap_str_tolower(to);
+        char *tmp = apr_pstrdup(cmd->pool, to);
+       ap_str_tolower(tmp);
+       to = tmp;
     }
 
     push_item(((autoindex_config_rec *) d)->icon_list, cmd->info, to,
@@ -291,43 +309,44 @@ static const char *add_icon(cmd_parms *cmd, void *d, char *icon, char *to)
 #define WILDCARDS_REQUIRED 0
 #endif
 
-static const char *add_desc(cmd_parms *cmd, void *d, char *desc, char *to)
+static const char *add_desc(cmd_parms *cmd, void *d, const char *desc,
+                           const char *to)
 {
     autoindex_config_rec *dcfg = (autoindex_config_rec *) d;
     ai_desc_t *desc_entry;
     char *prefix = "";
 
-    desc_entry = (ai_desc_t *) ap_push_array(dcfg->desc_list);
-    desc_entry->full_path = (strchr(to, '/') == NULL) ? 0 : 1;
+    desc_entry = (ai_desc_t *) apr_push_array(dcfg->desc_list);
+    desc_entry->full_path = (ap_strchr_c(to, '/') == NULL) ? 0 : 1;
     desc_entry->wildcards = (WILDCARDS_REQUIRED
                             || desc_entry->full_path
-                            || ap_is_fnmatch(to));
+                            || apr_is_fnmatch(to));
     if (desc_entry->wildcards) {
        prefix = desc_entry->full_path ? "*/" : "*";
-       desc_entry->pattern = ap_pstrcat(dcfg->desc_list->cont,
+       desc_entry->pattern = apr_pstrcat(dcfg->desc_list->cont,
                                         prefix, to, "*", NULL);
     }
     else {
-       desc_entry->pattern = ap_pstrdup(dcfg->desc_list->cont, to);
+       desc_entry->pattern = apr_pstrdup(dcfg->desc_list->cont, to);
     }
-    desc_entry->description = ap_pstrdup(dcfg->desc_list->cont, desc);
+    desc_entry->description = apr_pstrdup(dcfg->desc_list->cont, desc);
     return NULL;
 }
 
-static const char *add_ignore(cmd_parms *cmd, void *d, char *ext)
+static const char *add_ignore(cmd_parms *cmd, void *d, const char *ext)
 {
     push_item(((autoindex_config_rec *) d)->ign_list, 0, ext, cmd->path, NULL);
     return NULL;
 }
 
-static const char *add_header(cmd_parms *cmd, void *d, char *name)
+static const char *add_header(cmd_parms *cmd, void *d, const char *name)
 {
     push_item(((autoindex_config_rec *) d)->hdr_list, 0, NULL, cmd->path,
              name);
     return NULL;
 }
 
-static const char *add_readme(cmd_parms *cmd, void *d, char *name)
+static const char *add_readme(cmd_parms *cmd, void *d, const char *name)
 {
     push_item(((autoindex_config_rec *) d)->rdme_list, 0, NULL, cmd->path,
              name);
@@ -400,6 +419,9 @@ static const char *add_opts(cmd_parms *cmd, void *d, const char *optstr)
         else if (!strcasecmp(w, "SuppressColumnSorting")) {
             option = SUPPRESS_COLSORT;
        }
+        else if (!strcasecmp(w, "VersionSort")) {
+            option = VERSION_SORT;
+       }
        else if (!strcasecmp(w, "None")) {
            if (action != '\0') {
                return "Cannot combine '+' or '-' with 'None' keyword";
@@ -487,13 +509,13 @@ static const char *add_opts(cmd_parms *cmd, void *d, const char *optstr)
     return NULL;
 }
 
-static const char *set_default_order(cmd_parms *cmd, void *m, char *direction,
-                                    char *key)
+static const char *set_default_order(cmd_parms *cmd, void *m, const char *direction,
+                                    const char *key)
 {
     char temp[4];
     autoindex_config_rec *d_cfg = (autoindex_config_rec *) m;
 
-    ap_cpystrn(temp, "k=d", sizeof(temp));
+    apr_cpystrn(temp, "k=d", sizeof(temp));
     if (!strcasecmp(direction, "Ascending")) {
        temp[2] = D_ASCENDING;
     }
@@ -522,10 +544,10 @@ static const char *set_default_order(cmd_parms *cmd, void *m, char *direction,
     }
 
     if (d_cfg->default_order == NULL) {
-       d_cfg->default_order = ap_palloc(cmd->pool, 4);
+       d_cfg->default_order = apr_palloc(cmd->pool, 4);
        d_cfg->default_order[3] = '\0';
     }
-    ap_cpystrn(d_cfg->default_order, temp, sizeof(temp));
+    apr_cpystrn(d_cfg->default_order, temp, sizeof(temp));
     return NULL;
 }
 
@@ -533,51 +555,53 @@ static const char *set_default_order(cmd_parms *cmd, void *m, char *direction,
 
 static const command_rec autoindex_cmds[] =
 {
-    {"AddIcon", add_icon, BY_PATH, DIR_CMD_PERMS, ITERATE2,
-     "an icon URL followed by one or more filenames"},
-    {"AddIconByType", add_icon, BY_TYPE, DIR_CMD_PERMS, ITERATE2,
-     "an icon URL followed by one or more MIME types"},
-    {"AddIconByEncoding", add_icon, BY_ENCODING, DIR_CMD_PERMS, ITERATE2,
-     "an icon URL followed by one or more content encodings"},
-    {"AddAlt", add_alt, BY_PATH, DIR_CMD_PERMS, ITERATE2,
-     "alternate descriptive text followed by one or more filenames"},
-    {"AddAltByType", add_alt, BY_TYPE, DIR_CMD_PERMS, ITERATE2,
-     "alternate descriptive text followed by one or more MIME types"},
-    {"AddAltByEncoding", add_alt, BY_ENCODING, DIR_CMD_PERMS, ITERATE2,
-     "alternate descriptive text followed by one or more content encodings"},
-    {"IndexOptions", add_opts, NULL, DIR_CMD_PERMS, RAW_ARGS,
-     "one or more index options"},
-    {"IndexOrderDefault", set_default_order, NULL, DIR_CMD_PERMS, TAKE2,
-     "{Ascending,Descending} {Name,Size,Description,Date}"},
-    {"IndexIgnore", add_ignore, NULL, DIR_CMD_PERMS, ITERATE,
-     "one or more file extensions"},
-    {"AddDescription", add_desc, BY_PATH, DIR_CMD_PERMS, ITERATE2,
-     "Descriptive text followed by one or more filenames"},
-    {"HeaderName", add_header, NULL, DIR_CMD_PERMS, TAKE1, "a filename"},
-    {"ReadmeName", add_readme, NULL, DIR_CMD_PERMS, TAKE1, "a filename"},
-    {"FancyIndexing", fancy_indexing, NULL, DIR_CMD_PERMS, FLAG,
-     "Limited to 'on' or 'off' (superseded by IndexOptions FancyIndexing)"},
-    {"DefaultIcon", ap_set_string_slot,
-     (void *) XtOffsetOf(autoindex_config_rec, default_icon),
-     DIR_CMD_PERMS, TAKE1, "an icon URL"},
+    AP_INIT_ITERATE2("AddIcon", add_icon, BY_PATH, DIR_CMD_PERMS, 
+                     "an icon URL followed by one or more filenames"),
+    AP_INIT_ITERATE2("AddIconByType", add_icon, BY_TYPE, DIR_CMD_PERMS,
+                     "an icon URL followed by one or more MIME types"),
+    AP_INIT_ITERATE2("AddIconByEncoding", add_icon, BY_ENCODING, DIR_CMD_PERMS,
+                     "an icon URL followed by one or more content encodings"),
+    AP_INIT_ITERATE2("AddAlt", add_alt, BY_PATH, DIR_CMD_PERMS,
+                     "alternate descriptive text followed by one or more filenames"),
+    AP_INIT_ITERATE2("AddAltByType", add_alt, BY_TYPE, DIR_CMD_PERMS,
+                     "alternate descriptive text followed by one or more MIME types"),
+    AP_INIT_ITERATE2("AddAltByEncoding", add_alt, BY_ENCODING, DIR_CMD_PERMS,
+                     "alternate descriptive text followed by one or more content encodings"),
+    AP_INIT_RAW_ARGS("IndexOptions", add_opts, NULL, DIR_CMD_PERMS,
+                     "one or more index options"),
+    AP_INIT_TAKE2("IndexOrderDefault", set_default_order, NULL, DIR_CMD_PERMS,
+                  "{Ascending,Descending} {Name,Size,Description,Date}"),
+    AP_INIT_ITERATE("IndexIgnore", add_ignore, NULL, DIR_CMD_PERMS,
+                    "one or more file extensions"),
+    AP_INIT_ITERATE2("AddDescription", add_desc, BY_PATH, DIR_CMD_PERMS,
+                     "Descriptive text followed by one or more filenames"),
+    AP_INIT_TAKE1("HeaderName", add_header, NULL, DIR_CMD_PERMS,
+                  "a filename"),
+    AP_INIT_TAKE1("ReadmeName", add_readme, NULL, DIR_CMD_PERMS,
+                  "a filename"),
+    AP_INIT_FLAG("FancyIndexing", fancy_indexing, NULL, DIR_CMD_PERMS,
+                 "Limited to 'on' or 'off' (superseded by IndexOptions FancyIndexing)"),
+    AP_INIT_TAKE1("DefaultIcon", ap_set_string_slot,
+                  (void *) XtOffsetOf(autoindex_config_rec, default_icon),
+                  DIR_CMD_PERMS, "an icon URL"),
     {NULL}
 };
 
-static void *create_autoindex_config(ap_context_t *p, char *dummy)
+static void *create_autoindex_config(apr_pool_t *p, char *dummy)
 {
     autoindex_config_rec *new =
-    (autoindex_config_rec *) ap_pcalloc(p, sizeof(autoindex_config_rec));
+    (autoindex_config_rec *) apr_pcalloc(p, sizeof(autoindex_config_rec));
 
     new->icon_width = 0;
     new->icon_height = 0;
     new->name_width = DEFAULT_NAME_WIDTH;
     new->name_adjust = K_UNSET;
-    new->icon_list = ap_make_array(p, 4, sizeof(struct item));
-    new->alt_list = ap_make_array(p, 4, sizeof(struct item));
-    new->desc_list = ap_make_array(p, 4, sizeof(ai_desc_t));
-    new->ign_list = ap_make_array(p, 4, sizeof(struct item));
-    new->hdr_list = ap_make_array(p, 4, sizeof(struct item));
-    new->rdme_list = ap_make_array(p, 4, sizeof(struct item));
+    new->icon_list = apr_make_array(p, 4, sizeof(struct item));
+    new->alt_list = apr_make_array(p, 4, sizeof(struct item));
+    new->desc_list = apr_make_array(p, 4, sizeof(ai_desc_t));
+    new->ign_list = apr_make_array(p, 4, sizeof(struct item));
+    new->hdr_list = apr_make_array(p, 4, sizeof(struct item));
+    new->rdme_list = apr_make_array(p, 4, sizeof(struct item));
     new->opts = 0;
     new->incremented_opts = 0;
     new->decremented_opts = 0;
@@ -586,24 +610,24 @@ static void *create_autoindex_config(ap_context_t *p, char *dummy)
     return (void *) new;
 }
 
-static void *merge_autoindex_configs(ap_context_t *p, void *basev, void *addv)
+static void *merge_autoindex_configs(apr_pool_t *p, void *basev, void *addv)
 {
     autoindex_config_rec *new;
     autoindex_config_rec *base = (autoindex_config_rec *) basev;
     autoindex_config_rec *add = (autoindex_config_rec *) addv;
 
-    new = (autoindex_config_rec *) ap_pcalloc(p, sizeof(autoindex_config_rec));
+    new = (autoindex_config_rec *) apr_pcalloc(p, sizeof(autoindex_config_rec));
     new->default_icon = add->default_icon ? add->default_icon
                                           : base->default_icon;
     new->icon_height = add->icon_height ? add->icon_height : base->icon_height;
     new->icon_width = add->icon_width ? add->icon_width : base->icon_width;
 
-    new->alt_list = ap_append_arrays(p, add->alt_list, base->alt_list);
-    new->ign_list = ap_append_arrays(p, add->ign_list, base->ign_list);
-    new->hdr_list = ap_append_arrays(p, add->hdr_list, base->hdr_list);
-    new->desc_list = ap_append_arrays(p, add->desc_list, base->desc_list);
-    new->icon_list = ap_append_arrays(p, add->icon_list, base->icon_list);
-    new->rdme_list = ap_append_arrays(p, add->rdme_list, base->rdme_list);
+    new->alt_list = apr_append_arrays(p, add->alt_list, base->alt_list);
+    new->ign_list = apr_append_arrays(p, add->ign_list, base->ign_list);
+    new->hdr_list = apr_append_arrays(p, add->hdr_list, base->hdr_list);
+    new->desc_list = apr_append_arrays(p, add->desc_list, base->desc_list);
+    new->icon_list = apr_append_arrays(p, add->icon_list, base->icon_list);
+    new->rdme_list = apr_append_arrays(p, add->rdme_list, base->rdme_list);
     if (add->opts & NO_OPTIONS) {
        /*
         * If the current directory says 'no options' then we also
@@ -615,7 +639,7 @@ static void *merge_autoindex_configs(ap_context_t *p, void *basev, void *addv)
     }
     else {
        /*
-        * If there were any non ap_context_t ncremental options selected for
+        * If there were any nonincremental options selected for
         * this directory, they dominate and we don't inherit *anything.*
         * Contrariwise, we *do* inherit if the only settings here are
         * incremental ones.
@@ -634,7 +658,7 @@ static void *merge_autoindex_configs(ap_context_t *p, void *basev, void *addv)
        }
        else {
            /*
-            * There are local non ap_context_t ncremental settings, which clear
+            * There are local nonincremental settings, which clear
             * all inheritance from above.  They *are* the new base settings.
             */
            new->opts = add->opts;;
@@ -678,15 +702,15 @@ struct ent {
     char *alt;
     char *desc;
     off_t size;
-    time_t lm;
+    apr_time_t lm;
     struct ent *next;
-    int ascending;
+    int ascending, version_sort;
     char key;
 };
 
-static char *find_item(request_rec *r, ap_array_header_t *list, int path_only)
+static char *find_item(request_rec *r, apr_array_header_t *list, int path_only)
 {
-    const char *content_type = r->content_type;
+    const char *content_type = ap_field_noparam(r->pool, r->content_type);
     const char *content_encoding = r->content_encoding;
     char *path = r->filename;
 
@@ -776,7 +800,7 @@ static char *find_desc(autoindex_config_rec *dcfg, request_rec *r)
      * If the filename includes a path, extract just the name itself
      * for the simple matches.
      */
-    if ((filename_only = strrchr(filename_full, '/')) == NULL) {
+    if ((filename_only = ap_strrchr_c(filename_full, '/')) == NULL) {
        filename_only = filename_full;
     }
     else {
@@ -795,10 +819,10 @@ static char *find_desc(autoindex_config_rec *dcfg, request_rec *r)
         * wildcard checking if we must.
         */
        if (tuple->wildcards) {
-           found = (ap_fnmatch(tuple->pattern, filename, MATCH_FLAGS) == 0);
+           found = (apr_fnmatch(tuple->pattern, filename, MATCH_FLAGS) == 0);
        }
        else {
-           found = (strstr(filename, tuple->pattern) != NULL);
+           found = (ap_strstr_c(filename, tuple->pattern) != NULL);
        }
        if (found) {
            return tuple->description;
@@ -809,7 +833,7 @@ static char *find_desc(autoindex_config_rec *dcfg, request_rec *r)
 
 static int ignore_entry(autoindex_config_rec *d, char *path)
 {
-    ap_array_header_t *list = d->ign_list;
+    apr_array_header_t *list = d->ign_list;
     struct item *items = (struct item *) list->elts;
     char *tt;
     int i;
@@ -884,19 +908,20 @@ static int ignore_entry(autoindex_config_rec *d, char *path)
 /*
  * emit a plain text file
  */
-static void do_emit_plain(request_rec *r, ap_file_t *f)
+static void do_emit_plain(request_rec *r, apr_file_t *f)
 {
     char buf[IOBUFSIZE + 1];
-    int i, n, c, ch;
-    ap_status_t stat;
+    int i, c, ch;
+    apr_size_t n;
+    apr_status_t stat;
 
     ap_rputs("<PRE>\n", r);
-    while (!ap_eof(f)) {
+    while (!apr_eof(f)) {
        do {
             n = sizeof(char) * IOBUFSIZE;
-           stat = ap_read(f, buf, &n);
+           stat = apr_read(f, buf, &n);
        }
-       while (stat != APR_SUCCESS && stat == EINTR);
+       while (stat != APR_SUCCESS && APR_STATUS_IS_EINTR(stat));
        if (n == -1 || n == 0) {
            break;
        }
@@ -938,7 +963,7 @@ static void do_emit_plain(request_rec *r, ap_file_t *f)
 static void emit_head(request_rec *r, char *header_fname, int suppress_amble,
                      char *title)
 {
-    ap_file_t *f;
+    apr_file_t *f = NULL;
     request_rec *rr = NULL;
     int emit_amble = 1;
     int emit_H1 = 1;
@@ -949,10 +974,10 @@ static void emit_head(request_rec *r, char *header_fname, int suppress_amble,
      * pretend there's nothing there.
      */
     if ((header_fname != NULL)
-       && (rr = ap_sub_req_lookup_uri(header_fname, r))
+       && (rr = ap_sub_req_lookup_uri(header_fname, r, NULL))
        && (rr->status == HTTP_OK)
        && (rr->filename != NULL)
-       && S_ISREG(rr->finfo.st_mode)) {
+       && rr->finfo.filetype == APR_REG) {
        /*
         * Check for the two specific cases we allow: text/html and
         * text/anything-else.  The former is allowed to be processed for
@@ -986,12 +1011,12 @@ static void emit_head(request_rec *r, char *header_fname, int suppress_amble,
                 * the file's contents, any HTML header it had won't end up
                 * where it belongs.
                 */
-               if (ap_open(&f, r->pool, rr->filename, APR_READ | APR_BUFFERED,
-                            APR_OS_DEFAULT) == APR_SUCCESS) {
+               if (apr_open(&f, rr->filename, APR_READ,
+                            APR_OS_DEFAULT, r->pool) == APR_SUCCESS) {
                    emit_preamble(r, title);
                    emit_amble = 0;
                    do_emit_plain(r, f);
-                   ap_close(f);
+                   apr_close(f);
                    emit_H1 = 0;
                }
            }
@@ -1021,7 +1046,7 @@ static void emit_head(request_rec *r, char *header_fname, int suppress_amble,
  */
 static void emit_tail(request_rec *r, char *readme_fname, int suppress_amble)
 {
-    ap_file_t *f;
+    apr_file_t *f = NULL;
     request_rec *rr = NULL;
     int suppress_post = 0;
     int suppress_sig = 0;
@@ -1032,10 +1057,10 @@ static void emit_tail(request_rec *r, char *readme_fname, int suppress_amble)
      * pretend there's nothing there.
      */
     if ((readme_fname != NULL)
-       && (rr = ap_sub_req_lookup_uri(readme_fname, r))
+       && (rr = ap_sub_req_lookup_uri(readme_fname, r, NULL))
        && (rr->status == HTTP_OK)
        && (rr->filename != NULL)
-       && S_ISREG(rr->finfo.st_mode)) {
+       && rr->finfo.filetype == APR_REG) {
        /*
         * Check for the two specific cases we allow: text/html and
         * text/anything-else.  The former is allowed to be processed for
@@ -1054,10 +1079,10 @@ static void emit_tail(request_rec *r, char *readme_fname, int suppress_amble)
                /*
                 * If we can open the file, suppress the signature.
                 */
-               if (ap_open(&f, r->pool, rr->filename, APR_READ | APR_BUFFERED,
-                            APR_OS_DEFAULT) == APR_SUCCESS) {
+               if (apr_open(&f, rr->filename, APR_READ,
+                            APR_OS_DEFAULT, r->pool) == APR_SUCCESS) {
                    do_emit_plain(r, f);
-                   ap_close(f);
+                   apr_close(f);
                    suppress_sig = 1;
                }
            }
@@ -1079,8 +1104,9 @@ static void emit_tail(request_rec *r, char *readme_fname, int suppress_amble)
 static char *find_title(request_rec *r)
 {
     char titlebuf[MAX_STRING_LEN], *find = "<TITLE>";
-    ap_file_t *thefile = NULL;
-    int x, y, n, p;
+    apr_file_t *thefile = NULL;
+    int x, y, p;
+    apr_size_t n;
 
     if (r->status != HTTP_OK) {
        return NULL;
@@ -1090,19 +1116,19 @@ static char *find_title(request_rec *r)
                        "text/html")
            || !strcmp(r->content_type, INCLUDES_MAGIC_TYPE))
        && !r->content_encoding) {
-        if (ap_open(&thefile, r->pool, r->filename, APR_READ | APR_BUFFERED,
-                    APR_OS_DEFAULT) != APR_SUCCESS) {
+        if (apr_open(&thefile, r->filename, APR_READ,
+                    APR_OS_DEFAULT, r->pool) != APR_SUCCESS) {
            return NULL;
        }
         n = sizeof(char) * (MAX_STRING_LEN - 1);
-       ap_read(thefile, titlebuf, &n);
+       apr_read(thefile, titlebuf, &n);
        if (n <= 0) {
-           ap_close(thefile);
+           apr_close(thefile);
            return NULL;
        }
        titlebuf[n] = '\0';
        for (x = 0, p = 0; titlebuf[x]; x++) {
-           if (ap_toupper(titlebuf[x]) == find[p]) {
+           if (apr_toupper(titlebuf[x]) == find[p]) {
                if (!find[++p]) {
                    if ((p = ap_ind(&titlebuf[++x], '<')) != -1) {
                        titlebuf[x + p] = '\0';
@@ -1118,20 +1144,20 @@ static char *find_title(request_rec *r)
                            }
                        }
                    }
-                   ap_close(thefile);
-                   return ap_pstrdup(r->pool, &titlebuf[x]);
+                   apr_close(thefile);
+                   return apr_pstrdup(r->pool, &titlebuf[x]);
                }
            }
            else {
                p = 0;
            }
        }
-       ap_close(thefile);
+       apr_close(thefile);
     }
     return NULL;
 }
 
-static struct ent *make_autoindex_entry(char *name, int autoindex_opts,
+static struct ent *make_autoindex_entry(const char *name, int autoindex_opts,
                                        autoindex_config_rec *d,
                                        request_rec *r, char keyid,
                                        char direction)
@@ -1146,22 +1172,23 @@ static struct ent *make_autoindex_entry(char *name, int autoindex_opts,
         return (NULL);
     }
 
-    p = (struct ent *) ap_pcalloc(r->pool, sizeof(struct ent));
-    p->name = ap_pstrdup(r->pool, name);
+    p = (struct ent *) apr_pcalloc(r->pool, sizeof(struct ent));
+    p->name = apr_pstrdup(r->pool, name);
     p->size = -1;
     p->icon = NULL;
     p->alt = NULL;
     p->desc = NULL;
     p->lm = -1;
-    p->key = ap_toupper(keyid);
-    p->ascending = (ap_toupper(direction) == D_ASCENDING);
+    p->key = apr_toupper(keyid);
+    p->ascending = (apr_toupper(direction) == D_ASCENDING);
+    p->version_sort = autoindex_opts & VERSION_SORT;
 
     if (autoindex_opts & FANCY_INDEXING) {
-        request_rec *rr = ap_sub_req_lookup_file(name, r);
+        request_rec *rr = ap_sub_req_lookup_file(name, r, NULL);
 
-       if (rr->finfo.st_mode != 0) {
-           p->lm = rr->finfo.st_mtime;
-           if (S_ISDIR(rr->finfo.st_mode)) {
+       if (rr->finfo.protection != 0) {
+           p->lm = rr->finfo.mtime;
+           if (rr->finfo.filetype == APR_DIR) {
                if (!(p->icon = find_icon(d, rr, 1))) {
                    p->icon = find_default_icon(d, "^^DIRECTORY^^");
                }
@@ -1169,19 +1196,19 @@ static struct ent *make_autoindex_entry(char *name, int autoindex_opts,
                    p->alt = "DIR";
                }
                p->size = -1;
-               p->name = ap_pstrcat(r->pool, name, "/", NULL);
+               p->name = apr_pstrcat(r->pool, name, "/", NULL);
            }
            else {
                p->icon = find_icon(d, rr, 0);
                p->alt = find_alt(d, rr, 0);
-               p->size = rr->finfo.st_size;
+               p->size = rr->finfo.size;
            }
        }
 
        p->desc = find_desc(d, rr);
 
        if ((!p->desc) && (autoindex_opts & SCAN_HTML_TITLES)) {
-           p->desc = ap_pstrdup(r->pool, find_title(rr));
+           p->desc = apr_pstrdup(r->pool, find_title(rr));
        }
 
        ap_destroy_sub_req(rr);
@@ -1272,15 +1299,16 @@ static void output_directories(struct ent **ar, int n,
                               int autoindex_opts, char keyid, char direction)
 {
     int x;
+    apr_size_t rv;
     char *name = r->uri;
     char *tp;
     int static_columns = (autoindex_opts & SUPPRESS_COLSORT);
-    ap_context_t *scratch;
+    apr_pool_t *scratch;
     int name_width;
     char *name_scratch;
     char *pad_scratch;
 
-    ap_create_context(&scratch, r->pool);
+    apr_create_pool(&scratch, r->pool);
     if (name[0] == '\0') {
        name = "/";
     }
@@ -1294,8 +1322,8 @@ static void output_directories(struct ent **ar, int n,
            }
        }
     }
-    name_scratch = ap_palloc(r->pool, name_width + 1);
-    pad_scratch = ap_palloc(r->pool, name_width + 1);
+    name_scratch = apr_palloc(r->pool, name_width + 1);
+    pad_scratch = apr_palloc(r->pool, name_width + 1);
     memset(pad_scratch, ' ', name_width);
     pad_scratch[name_width] = '\0';
 
@@ -1344,7 +1372,7 @@ static void output_directories(struct ent **ar, int n,
        char *anchor, *t, *t2;
        int nwidth;
 
-       ap_clear_pool(scratch);
+       apr_clear_pool(scratch);
 
        if (is_parent(ar[x]->name)) {
            t = ap_make_full_path(scratch, name, "../");
@@ -1402,8 +1430,10 @@ static void output_directories(struct ent **ar, int n,
            if (!(autoindex_opts & SUPPRESS_LAST_MOD)) {
                if (ar[x]->lm != -1) {
                    char time_str[MAX_STRING_LEN];
-                   struct tm *ts = localtime(&ar[x]->lm);
-                   strftime(time_str, MAX_STRING_LEN, "%d-%b-%Y %H:%M  ", ts);
+                   apr_exploded_time_t ts;
+                    apr_explode_localtime(&ts, ar[x]->lm);
+                   apr_strftime(time_str, &rv, MAX_STRING_LEN, 
+                                "%d-%b-%Y %H:%M  ", &ts);
                    ap_rputs(time_str, r);
                }
                else {
@@ -1469,6 +1499,7 @@ static int dsortf(struct ent **e1, struct ent **e2)
         c1 = *e2;
         c2 = *e1;
     }
+
     switch (c1->key) {
     case K_LAST_MOD:
        if (c1->lm > c2->lm) {
@@ -1487,13 +1518,19 @@ static int dsortf(struct ent **e1, struct ent **e2)
         }
         break;
     case K_DESC:
-        result = strcmp(c1->desc ? c1->desc : "", c2->desc ? c2->desc : "");
+       if (c1->version_sort)
+           result = apr_strnatcmp(c1->desc ? c1->desc : "", c2->desc ? c2->desc : "");
+       else
+           result = strcmp(c1->desc ? c1->desc : "", c2->desc ? c2->desc : "");
         if (result) {
             return result;
         }
         break;
     }
-    return strcmp(c1->name, c2->name);
+    if (c1->version_sort)
+       return apr_strnatcmp(c1->name, c2->name);
+    else
+       return strcmp(c1->name, c2->name);
 }
 
 
@@ -1504,7 +1541,8 @@ static int index_directory(request_rec *r,
     char *title_endp;
     char *name = r->filename;
 
-    ap_dir_t *d;
+    apr_dir_t *d;
+    apr_status_t status;
     int num_ent = 0, x;
     struct ent *head, *p;
     struct ent **ar = NULL;
@@ -1513,18 +1551,25 @@ static int index_directory(request_rec *r,
     char keyid;
     char direction;
 
-    if (ap_opendir(&d, r->pool, name) != APR_SUCCESS) {
-       ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+    if ((status = apr_dir_open(&d, name, r->pool)) != APR_SUCCESS) {
+       ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
                    "Can't open directory for index: %s", r->filename);
        return HTTP_FORBIDDEN;
     }
 
+#if APR_HAS_UNICODE_FS 
+    r->content_type = "text/html;charset=utf-8";
+#else
     r->content_type = "text/html";
+#endif
+    ap_update_mtime(r, r->finfo.mtime);
+    ap_set_last_modified(r);
+    ap_set_etag(r);
 
     ap_send_http_header(r);
 
     if (r->header_only) {
-       ap_closedir(d);
+       apr_closedir(d);
        return 0;
     }
 
@@ -1576,9 +1621,9 @@ static int index_directory(request_rec *r,
      * linked list and then arrayificate them so qsort can use them. 
      */
     head = NULL;
-    while (ap_readdir(d)) {
-        char *d_name;
-        ap_get_dir_filename(&d_name, d);
+    while (apr_readdir(d) == APR_SUCCESS) {
+        const char *d_name;
+        apr_get_dir_filename(&d_name, d);
        p = make_autoindex_entry(d_name, autoindex_opts,
                                 autoindex_conf, r, keyid, direction);
        if (p != NULL) {
@@ -1588,7 +1633,7 @@ static int index_directory(request_rec *r,
        }
     }
     if (num_ent > 0) {
-       ar = (struct ent **) ap_palloc(r->pool,
+       ar = (struct ent **) apr_palloc(r->pool,
                                       num_ent * sizeof(struct ent *));
        p = head;
        x = 0;
@@ -1602,7 +1647,7 @@ static int index_directory(request_rec *r,
     }
     output_directories(ar, num_ent, autoindex_conf, r, autoindex_opts, keyid,
                       direction);
-    ap_closedir(d);
+    apr_closedir(d);
 
     if (autoindex_opts & FANCY_INDEXING) {
        ap_rputs("<HR>\n", r);
@@ -1618,7 +1663,12 @@ static int index_directory(request_rec *r,
 static int handle_autoindex(request_rec *r)
 {
     autoindex_config_rec *d;
-    int allow_opts = ap_allow_options(r);
+    int allow_opts;
+
+    if(strcmp(r->handler,DIR_MAGIC_TYPE))
+       return DECLINED;
+
+    allow_opts = ap_allow_options(r);
 
     d = (autoindex_config_rec *) ap_get_module_config(r->per_dir_config,
                                                      &autoindex_module);
@@ -1637,32 +1687,29 @@ static int handle_autoindex(request_rec *r)
         */
 
        if (r->filename[strlen(r->filename) - 1] != '/') {
-           r->filename = ap_pstrcat(r->pool, r->filename, "/", NULL);
+           r->filename = apr_pstrcat(r->pool, r->filename, "/", NULL);
        }
        return index_directory(r, d);
     }
     else {
-       ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+       ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
                     "Directory index forbidden by rule: %s", r->filename);
        return HTTP_FORBIDDEN;
     }
 }
 
-
-static const handler_rec autoindex_handlers[] =
+static void register_hooks(void)
 {
-    {DIR_MAGIC_TYPE, handle_autoindex},
-    {NULL}
-};
+    ap_hook_handler(handle_autoindex,NULL,NULL,AP_HOOK_MIDDLE);
+}
 
-module MODULE_VAR_EXPORT autoindex_module =
+module AP_MODULE_DECLARE_DATA autoindex_module =
 {
     STANDARD20_MODULE_STUFF,
     create_autoindex_config,   /* dir config creater */
     merge_autoindex_configs,   /* dir merger --- default is to override */
     NULL,                      /* server config */
     NULL,                      /* merge server config */
-    autoindex_cmds,            /* command ap_table_t */
-    autoindex_handlers,                /* handlers */
-    NULL                       /* register hooks */
+    autoindex_cmds,            /* command apr_table_t */
+    register_hooks             /* register hooks */
 };