-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I'd just like to say thanks that someone finally got round to this,
it's been my only significant issue with Apache 2 since I started
using it :)

Thanks again,

Chris Taylor - The guy with the PS2 WebServer
Email: [EMAIL PROTECTED] - PGP: http://www.x-bb.org/chris.asc

- ----- Original Message ----- 
From: "Francis Daly" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Thursday, November 21, 2002 9:09 AM
Subject: [PATCH] IndexResults for mod_autoindex


> 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        [EMAIL PROTECTED]
> 
> 
> --- 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>

-----BEGIN PGP SIGNATURE-----
Version: PGPfreeware 7.0.3 for non-commercial use <http://www.pgp.com>

iQA/AwUBPdy0iSqf8lmE2RZkEQJ8AgCgk8D/e8qCwuPZKBkB6vJQjbZO0SMAoLiF
GlTL+EAvXJyJiYMF82ErlX+h
=nhXL
-----END PGP SIGNATURE-----


Reply via email to