httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Francis Daly <d...@daoine.org>
Subject [patch] IndexResults
Date Sat, 25 Jan 2003 21:23:04 GMT
Hi there,

updating some old patches to the recent release...

This one is "IndexResults", the real intention of which is to allow
files requiring authentication appear in autoindex'ed directory
listings.

If the docs patch below doesn't properly describe what it does, then I
need to rewrite that too.

Built and tested against the 2.0.44 codebase.

Part 2, with some optional extras, follows.

All the best,

	f
-- 
Francis Daly        deva@daoine.org

--- modules/generators/mod_autoindex.c	2003-01-06 15:24:29.000000000 +0000
+++ modules/generators/mod_autoindex.c	2003-01-25 17:54:28.000000000 +0000
@@ -155,6 +155,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;
@@ -176,6 +182,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;
 
@@ -321,6 +328,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);
@@ -582,6 +628,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,
@@ -594,7 +642,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));
@@ -611,15 +659,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;
@@ -638,6 +718,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
@@ -710,6 +821,7 @@
                                             : base->default_keyid;
     new->default_direction = add->default_direction ? add->default_direction 
                                                     : base->default_direction;
+
     return new;
 }
 
@@ -799,6 +911,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 code[4];    /* HTTP codes are 3 digits long */
+    const char *res;
+
+    /* Check for exact match */
+    sprintf(code, "%d", status);
+    if ((res = apr_table_get(d->res_list, code)) != NULL) {
+        return res[0] == '1';
+    }
+    /* Check for within-range match */
+    code[1] = '\0'; 
+    if ((res = apr_table_get(d->res_list, code)) != 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
@@ -1320,7 +1450,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);
     }
--- docs/manual/mod/mod_autoindex.xml	2003-01-06 16:32:15.000000000 +0000
+++ docs/manual/mod/mod_autoindex.xml	2003-01-25 17:45:21.000000000 +0000
@@ -854,6 +854,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.45 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