httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "William A. Rowe, Jr." <wr...@apache.org>
Subject Re: [PATCH] IndexResults for mod_autoindex
Date Sat, 23 Nov 2002 05:52:10 GMT
Francis, very cool patch!  I'll look at it if noone beats me to it,
you aren't the only one who wants this feature :-)

Bill

At 03:09 AM 11/21/2002, Francis Daly wrote:
>Hi there,
>
>This is a late follow-on from some posts in May.
>
>mod_autoindex in Apache/2 does not show filenames for which the requester is
>not authenticated, which is a change from the 1.3 behaviour.
>
>The first patch below introduces a per-directory directive which
>allows the administrator list which http statuses (or status groups)
>should be shown or hidden.
>
>When left unset, I found no clear performance difference in listing a
>directory where no authentication was required (as expected); and also
>found no clear performance difference in listing a directory where each
>file individually required authentication (which was a bit of a
>surprise to me).
>
>Built and tested against vanilla 2.0.43, it applies cleanly to the
>current CVS version, 1.111.
>
>The second patch below is a docs patch against mod_autoindex.xml 1.12.
>
>There are two further optional code patches to follow, which are only
>useful if something similar to these are accepted.
>
>Any comments (and further performance testing) welcome.
>
>        f
>-- 
>Francis Daly        deva@daoine.org
>
>
>--- modules/generators/mod_autoindex.c  17 Oct 2002 18:09:52 -0000
>+++ modules/generators/mod_autoindex.c  21 Nov 2002 02:33:31 -0000
>@@ -154,6 +154,12 @@
>     int wildcards;
> } ai_desc_t;
> 
>+/* res_info is used when merging res_list */
>+typedef struct res_info {
>+    int *range;
>+    apr_table_t *tab;
>+} res_info;
>+
> typedef struct autoindex_config_struct {
> 
>     char *default_icon;
>@@ -175,6 +181,7 @@
>     apr_array_header_t *ign_list;
>     apr_array_header_t *hdr_list;
>     apr_array_header_t *rdme_list;
>+    apr_table_t *res_list;
> 
> } autoindex_config_rec;
> 
>@@ -320,6 +327,45 @@
>     return NULL;
> }
> 
>+static const char *set_results(cmd_parms *cmd, void *d, const char *name)
>+{
>+    char entry[4];
>+    int showp = 1;
>+
>+    if (name[0] == '-') {
>+        showp = 0;
>+        name++;
>+    }
>+
>+    /* verify that the form is valid */
>+    if (name[0] == '\0' || name[1] == '\0' || name[2] == '\0' ||
>+            name[3] != '\0') {
>+        return "Value (after leading minus) must be three characters long";
>+    }
>+
>+    /* verify that the value is valid */
>+    if ((name[0] < '1' || name[0] > '9')
>+        || !((isdigit(name[1]) && isdigit(name[2]))
>+            || (name[1] == 'x' && name[2] == 'x'))) {
>+        return "Value must be [-]### or [-]#xx, where # is a digit";
>+    }
>+
>+    strcpy(entry, name);
>+    if (name[1] == 'x') {
>+        entry[1] = '\0';
>+    }
>+
>+    /* The "value" here is "a string beginning with 1" (for show) or
>+     * "a string not beginning with 1" (for hide), as per show_result() */
>+    if (showp) {
>+        apr_table_set(((autoindex_config_rec *) d)->res_list, entry, "1");
>+    } else {
>+        apr_table_set(((autoindex_config_rec *) d)->res_list, entry, "0");
>+    }
>+
>+    return NULL;
>+}
>+
> 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);
>@@ -578,6 +624,8 @@
>                     "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_ITERATE("IndexResults", set_results, NULL, DIR_CMD_PERMS,
>+            "one or more http status codes"),
>     AP_INIT_TAKE1("HeaderName", add_header, NULL, DIR_CMD_PERMS,
>                   "a filename"),
>     AP_INIT_TAKE1("ReadmeName", add_readme, NULL, DIR_CMD_PERMS,
>@@ -590,7 +638,7 @@
>     {NULL}
> };
> 
>-static void *create_autoindex_config(apr_pool_t *p, char *dummy)
>+static void *create_autoindex_config(apr_pool_t *p, char *dir)
> {
>     autoindex_config_rec *new =
>     (autoindex_config_rec *) apr_pcalloc(p, sizeof(autoindex_config_rec));
>@@ -607,15 +655,47 @@
>     new->ign_list = apr_array_make(p, 4, sizeof(struct item));
>     new->hdr_list = apr_array_make(p, 4, sizeof(struct item));
>     new->rdme_list = apr_array_make(p, 4, sizeof(struct item));
>+    new->res_list = apr_table_make(p, 4);
>     new->opts = 0;
>     new->incremented_opts = 0;
>     new->decremented_opts = 0;
>     new->default_keyid = '\0';
>     new->default_direction = '\0';
> 
>+    /* include, effectively, a global "IndexResults 3xx" */
>+    if (dir == NULL) {
>+        apr_table_set(new->res_list, "3", "1");
>+    }
>+
>     return (void *) new;
> }
> 
>+static int res_list_ranges(int *range, const char *key, const char *dummy)
>+{
>+    int ikey;
>+
>+    ikey = atoi(key);
>+    if (ikey < 10) {
>+        range[ikey] = 1; 
>+        range[0] = 1;
>+    }
>+    return 1;
>+}
>+
>+static int res_list_del_entries(res_info *info, const char *key, 
>+                                const char *dummy)
>+{
>+    int ikey;
>+
>+    ikey = atoi(key);
>+    if (ikey >= 100) {
>+        if ((*info).range[ikey/100] == 1) {
>+            apr_table_unset((*info).tab, key);
>+        } 
>+    }
>+    return 1;
>+}
>+
> static void *merge_autoindex_configs(apr_pool_t *p, void *basev, void *addv)
> {
>     autoindex_config_rec *new;
>@@ -634,6 +714,37 @@
>     new->desc_list = apr_array_append(p, add->desc_list, base->desc_list);
>     new->icon_list = apr_array_append(p, add->icon_list, base->icon_list);
>     new->rdme_list = apr_array_append(p, add->rdme_list, base->rdme_list);
>+    if (apr_is_empty_table(add->res_list)) {
>+        /* Nothing new here */
>+        new->res_list = base->res_list;
>+    } else {
>+        /*
>+         * For each new range, unset any old keys within the range.
>+         * Then copy in all the new keys.
>+         */
>+        int range[10] = {0};
>+        res_info info;
>+
>+        new->res_list = apr_table_copy(p, base->res_list);
>+
>+        /* This sets range[R] to 1 if the range Rxx is to be merged 
>+         * and range[0] to 1 if any others are set
>+         */
>+        apr_table_do((int (*) (void *, const char *, const char *))
>+                     res_list_ranges, &range, add->res_list, NULL);
>+
>+        info.range = range;
>+        info.tab = new->res_list;
>+        /* This deletes each new{Rnn} if the range R is being merged */
>+        if (range[0] == 1) {
>+            apr_table_do((int (*) (void *, const char *, const char *))
>+                         res_list_del_entries, &info, new->res_list, NULL);
>+        }
>+
>+        /* This replaces-or-adds from add-> to new-> */
>+        apr_table_overlap(new->res_list, add->res_list, APR_OVERLAP_TABLES_SET);
>+    }
>+
>     if (add->opts & NO_OPTIONS) {
>         /*
>          * If the current directory says 'no options' then we also
>@@ -706,6 +817,7 @@
>                                             : base->default_keyid;
>     new->default_direction = add->default_direction ? add->default_direction

>                                                     : base->default_direction;
>+
>     return new;
> }
> 
>@@ -795,6 +907,24 @@
> #define find_default_icon(d,n) find_default_item(n, d->icon_list)
> #define find_default_alt(d,n) find_default_item(n, d->alt_list)
> 
>+static int show_result(autoindex_config_rec *d, int status)
>+{
>+    char stat[4];    /* HTTP codes are 3 digits long */
>+    const char *res;
>+
>+    /* Check for exact match */
>+    sprintf(stat, "%d", status);
>+    if ((res = apr_table_get(d->res_list, stat)) != NULL) {
>+        return res[0] == '1';
>+    }
>+    /* Check for within-range match */
>+    stat[1] = '\0'; 
>+    if ((res = apr_table_get(d->res_list, stat)) != NULL) {
>+        return res[0] == '1';
>+    }
>+    return 0;
>+}
>+
> /*
>  * Look through the list of pattern/description pairs and return the first one
>  * if any) that matches the filename in the request.  If multiple patterns
>@@ -1316,7 +1446,7 @@
> 
>     if ((rr->finfo.filetype != APR_DIR && rr->finfo.filetype != APR_REG)
>         || !(rr->status == OK || ap_is_HTTP_SUCCESS(rr->status)
>-                              || ap_is_HTTP_REDIRECT(rr->status))) {
>+                              || show_result(d, rr->status))) {
>         ap_destroy_sub_req(rr);
>         return (NULL);
>     }
>
>
>--- mod_autoindex.xml-1.12      Thu Nov 21 01:39:04 2002
>+++ mod_autoindex.xml   Thu Nov 21 01:50:14 2002
>@@ -846,6 +846,41 @@
> </directivesynopsis>
> 
> <directivesynopsis>
>+<name>IndexResults</name>
>+<description>Changes the list of files to show in a directory index,
>+based on the HTTP status</description>
>+<syntax>IndexResults <var>[-]code</var> [<var>[-]code</var>]
...</syntax>
>+<default>IndexResults 3xx<default>
>+<contextlist><context>server config</context><context>virtual
host</context>
>+<context>directory</context><context>.htaccess</context>
>+</contextlist>
>+<override>Indexes</override>
>+<compatibility>Available in version 2.0.44 and later</compatibility>
>+
>+<usage>
>+    <p>The <directive>IndexResults</directive> directive changes the
>+    list of files to show in a directory index. <var>code</var>
>+    is a HTTP status (from 100 to 999)(like <code>401</code>, for
>+    "unauthorized"), or a range (from 1xx to 9xx)(like <code>4xx</code>,
>+    meaning "all 400-series statuses") for additional files to show.
>+    Prefix <var>code</var> with a minus (-) to explicitly hide that
>+    status or range. Multiple IndexResults directives are processed
>+    by first modifying the ranges (in order), and then the individual
>+    statuses (in order). The <code>2xx</code> ("successful") range is
>+    always present. By default, the list contains the <code>3xx</code>
>+    range ("redirection"), but that can be explicitly overridden by a
>+    <code>-3xx</code> if that is really wanted.</p>
>+
>+    <example><title>Show unauthorized filenames</title>
>+      IndexResults 401
>+    </example>
>+    <example><title>Show unauthorized filenames, but no other 4xx ones</title>
>+      IndexResults 401 -4xx
>+    </example>
>+</usage>
>+</directivesynopsis>
>+
>+<directivesynopsis>
> <name>ReadmeName</name>
> <description>Name of the file that will be inserted at the end
> of the index listing</description>


Mime
View raw message