Return-Path: Delivered-To: apmail-apache-cvs-archive@apache.org Received: (qmail 16611 invoked by uid 500); 7 Aug 2001 12:56:13 -0000 Mailing-List: contact apache-cvs-help@apache.org; run by ezmlm Precedence: bulk Reply-To: new-httpd@apache.org list-help: list-unsubscribe: list-post: Delivered-To: mailing list apache-cvs@apache.org Received: (qmail 16591 invoked by uid 500); 7 Aug 2001 12:56:13 -0000 Delivered-To: apmail-httpd-2.0-cvs@apache.org Date: 7 Aug 2001 12:54:31 -0000 Message-ID: <20010807125431.33430.qmail@icarus.apache.org> From: wrowe@apache.org To: httpd-2.0-cvs@apache.org Subject: cvs commit: httpd-2.0/modules/generators mod_autoindex.c X-Spam-Rating: h31.sny.collab.net 1.6.2 0/1000/N Status: O X-Status: X-Keywords: X-UID: 84 wrowe 01/08/07 05:54:31 Modified: . CHANGES docs/manual/mod mod_autoindex.html modules/generators mod_autoindex.c Log: All mod_autoindex query parsing is now quietly quashed with the IndexOption IgnoreClient. The IndexOption SuppressColumnSorting still drops the column sort 's for the column headers, but IgnoreClient is required to ignore these Query options entirely. Introduced new mod_autoindex query argument parsing for F=[0|1|2] to allow the client to select plain, FancyIndexing or HTMLTable formatting, V=[0|1] to inhibit or enable version sorting, and P=pattern to return only specific files. The old Query Arguments were reorganized as C=f for sorting column 'f' (same N, D, S, or M as before), and O=A|D for ordering ascending or descending. Docs and an Example are provided in mod_autoindex.html Revision Changes Path 1.279 +14 -0 httpd-2.0/CHANGES Index: CHANGES =================================================================== RCS file: /home/cvs/httpd-2.0/CHANGES,v retrieving revision 1.278 retrieving revision 1.279 diff -u -r1.278 -r1.279 --- CHANGES 2001/08/07 08:02:41 1.278 +++ CHANGES 2001/08/07 12:54:31 1.279 @@ -1,5 +1,19 @@ Changes with Apache 2.0.23-dev + *) All mod_autoindex query parsing is now quietly quashed with the + IndexOption IgnoreClient. The IndexOption SuppressColumnSorting + still drops the column sort 's for the column headers, but + IgnoreClient is required to ignore these Query options entirely. + [William Rowe] + + *) Introduced new mod_autoindex query argument parsing for F=[0|1|2] + to allow the client to select plain, FancyIndexing or HTMLTable + formatting, V=[0|1] to inhibit or enable version sorting, and + P=pattern to return only specific files. The old Query Arguments + were reorganized as C=f for sorting column 'f' (same N, D, S, or M + as before), and O=A|D for ordering ascending or descending. + [William Rowe] + *) Fixed an error in mod_include's directive parsing routines which caused #if, #elif, and #else expressions containing backslashes to be improperly evaluated. [Cliff Woolley] 1.40 +74 -16 httpd-2.0/docs/manual/mod/mod_autoindex.html Index: mod_autoindex.html =================================================================== RCS file: /home/cvs/httpd-2.0/docs/manual/mod/mod_autoindex.html,v retrieving revision 1.39 retrieving revision 1.40 diff -u -r1.39 -r1.40 --- mod_autoindex.html 2001/08/07 04:33:58 1.39 +++ mod_autoindex.html 2001/08/07 12:54:31 1.40 @@ -86,20 +86,69 @@

Autoindex Request Query Arguments

-The column sorting headers are self-referencing hyperlinks that add the following -query options, they may be added to any request for the directory resource, where -They have no effect if the
IndexOptions directive's -SuppressColumnSorting option is in effect. In the list below, -S is the desired sort order, either A for ascending or -D for descending sequence. +

Apache 2.0.23 reorganized the Query Arguments for Column Sorting, and introduced +an entire group of new query options. To effectively eliminate all client control +over the output, the IndexOptions +IgnoreClient option was introduced.

+ +

The column sorting headers themselves are self-referencing hyperlinks that add the +sort query options shown below. Any option below may be added to any request for the +directory resource.

    -
  • N=S sorts the directory by file name -
  • M=S sorts the directory by last-modified date, then file name -
  • S=S sorts the directory by size, then file name -
  • D=S sorts the directory by description, then file name +
  • C=N sorts the directory by file name +
  • C=M sorts the directory by last-modified date, then file name +
  • C=S sorts the directory by size, then file name +
  • C=D sorts the directory by description, then file name
      + +
  • O=A sorts the listing in Ascending Order +
  • O=D sorts the listing in Descending Order
      + +
  • F=0 formats the listing as a simple list (not FancyIndexed) +
  • F=1 formats the listing as a FancyIndexed list +
  • F=2 formats the listing as an HTMLTable FancyIndexed list
      + +
  • V=0 disables version sorting +
  • V=0 enables version sorting
      + +
  • P=pattern lists only files matching the given pattern
+

Note that the 'P'attern query argument is tested after the usual IndexIgnore +directives are processed, and all file names are still subjected to the same critera +as any other autoindex listing. The Query Arguments parser in mod_autoindex will stop +abruptly when an unrecognized option is encountered. The Query Arguments must be well +formed, according to the table above.

+ +

The simple example below, which can be clipped and saved in a header.html file, +illustrates these query options. Note that the unknown "X" argument, for the +submit button, is listed last to assure the arguments are all parsed before +mod_autoindex encounters the X=Go input.

+ +
<FORM METHOD="GET">
  +    Show me a <SELECT NAME="F">
  +      <OPTION VALUE="0"> Plain list 
  +      <OPTION VALUE="1" SELECTED> Fancy list
  +      <OPTION VALUE="2"> Table list
  +    </SELECT>
  +    Sorted by <SELECT NAME="C">
  +      <OPTION VALUE="N" SELECTED> Name
  +      <OPTION VALUE="M"> Date Modified
  +      <OPTION VALUE="S"> Size
  +      <OPTION VALUE="D"> Description
  +    </SELECT>
  +    <SELECT NAME="O">
  +      <OPTION VALUE="A" SELECTED> Ascending
  +      <OPTION VALUE="D"> Descending
  +    </SELECT>
  +    <SELECT NAME="V">
  +      <OPTION VALUE="0" SELECTED> in Normal order
  +      <OPTION VALUE="1"> in Version order
  +    </SELECT>
  +    Matching <INPUT TYPE="text" NAME="P" VALUE="*">
  +    <INPUT TYPE="submit" NAME="X" VALUE="Go">
  +</FORM>
  +

Directives

@@ -603,6 +652,11 @@ necessary if file names or description text will alternate between left-to-right and right-to-left reading order, as can happen on WinNT or other utf-8 enabled platforms. +
IconsAreLinks +
+ +This makes the icons part of the anchor for the filename, for +fancy indexing.
IconHeight[=pixels] (Apache 1.3 and later)
@@ -613,11 +667,6 @@ images have been loaded. If no value is given for the option, it defaults to the standard height of the icons supplied with the Apache software. -
IconsAreLinks -
- -This makes the icons part of the anchor for the filename, for -fancy indexing.
IconWidth[=pixels] (Apache 1.3 and later)
@@ -628,6 +677,12 @@ images have been loaded. If no value is given for the option, it defaults to the standard width of the icons supplied with the Apache software. +
IgnoreClient +
+ +This option causes mod_autoindex to ignore all query variables from the +client, including sort order (implies SuppressColumnSorting.)
NameWidth=[n | *] (Apache 1.3.2 and later)
The NameWidth keyword allows you to specify the width of the @@ -649,7 +704,10 @@ If specified, Apache will not make the column headings in a FancyIndexed directory listing into links for sorting. The default behaviour is for them to be links; selecting the column heading will sort the directory -listing by the values in that column. +listing by the values in that column. Prior to Apache 2.0.23, this +also disabled parsing the Query Arguments for the sort string. +That behavior is now controled by IndexOptions IgnoreClient in Apache 2.0.23.
SuppressDescription
1.81 +163 -70 httpd-2.0/modules/generators/mod_autoindex.c Index: mod_autoindex.c =================================================================== RCS file: /home/cvs/httpd-2.0/modules/generators/mod_autoindex.c,v retrieving revision 1.80 retrieving revision 1.81 diff -u -r1.80 -r1.81 --- mod_autoindex.c 2001/08/07 04:33:58 1.80 +++ mod_autoindex.c 2001/08/07 12:54:31 1.81 @@ -109,6 +109,7 @@ #define TRACK_MODIFIED 0x1000 #define FANCY_INDEXING 0x2000 #define TABLE_INDEXING 0x4000 +#define IGNORE_CLIENT 0x8000 #define K_NOADJUST 0 #define K_ADJUST 1 @@ -121,9 +122,11 @@ #define K_LAST_MOD 'M' /* Last modification date */ #define K_SIZE 'S' /* Size (absolute, not as displayed) */ #define K_DESC 'D' /* Description */ +#define K_VALID "NMSD" /* String containing _all_ valid K_ opts */ #define D_ASCENDING 'A' #define D_DESCENDING 'D' +#define D_VALID "AD" /* String containing _all_ valid D_ opts */ /* * These are the dimensions of the default icons supplied with Apache. @@ -154,9 +157,9 @@ typedef struct autoindex_config_struct { char *default_icon; - int opts; - int incremented_opts; - int decremented_opts; + apr_int32_t opts; + apr_int32_t incremented_opts; + apr_int32_t decremented_opts; int name_width; int name_adjust; int desc_width; @@ -340,9 +343,9 @@ static const char *add_opts(cmd_parms *cmd, void *d, const char *optstr) { char *w; - int opts; - int opts_add; - int opts_remove; + apr_int32_t opts; + apr_int32_t opts_add; + apr_int32_t opts_remove; char action; autoindex_config_rec *d_cfg = (autoindex_config_rec *) d; @@ -371,9 +374,21 @@ else if (!strcasecmp(w, "IconsAreLinks")) { option = ICONS_ARE_LINKS; } + else if (!strcasecmp(w, "IgnoreClient")) { + option = IGNORE_CLIENT; + } else if (!strcasecmp(w, "ScanHTMLTitles")) { option = SCAN_HTML_TITLES; } + else if (!strcasecmp(w, "SuppressColumnSorting")) { + option = SUPPRESS_COLSORT; + } + else if (!strcasecmp(w, "SuppressDescription")) { + option = SUPPRESS_DESC; + } + else if (!strcasecmp(w, "SuppressHTMLPreamble")) { + option = SUPPRESS_PREAMBLE; + } else if (!strcasecmp(w, "SuppressIcon")) { option = SUPPRESS_ICON; } @@ -383,15 +398,6 @@ else if (!strcasecmp(w, "SuppressSize")) { option = SUPPRESS_SIZE; } - else if (!strcasecmp(w, "SuppressDescription")) { - option = SUPPRESS_DESC; - } - else if (!strcasecmp(w, "SuppressHTMLPreamble")) { - option = SUPPRESS_PREAMBLE; - } - else if (!strcasecmp(w, "SuppressColumnSorting")) { - option = SUPPRESS_COLSORT; - } else if (!strcasecmp(w, "SuppressRules")) { option = SUPPRESS_RULES; } @@ -565,7 +571,7 @@ 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"), + "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, @@ -683,6 +689,7 @@ new->name_width = add->name_width; new->name_adjust = add->name_adjust; } + /* * Likewise for DescriptionWidth. */ @@ -1171,7 +1178,7 @@ return NULL; } -static struct ent *make_parent_entry(int autoindex_opts, +static struct ent *make_parent_entry(apr_int32_t autoindex_opts, autoindex_config_rec *d, request_rec *r, char keyid, char direction) @@ -1219,7 +1226,8 @@ int autoindex_opts, autoindex_config_rec *d, request_rec *r, char keyid, - char direction) + char direction, + const char *pattern) { request_rec *rr; struct ent *p; @@ -1229,11 +1237,29 @@ || ((dirent->name[1] == '.') && !dirent->name[2]))) return (NULL); +#ifndef CASE_BLIND_FILESYSTEM + if (pattern && (apr_fnmatch(pattern, dirent->name, + FNM_NOESCAPE | FNM_PERIOD) + != APR_SUCCESS)) + return (NULL); +#else /* !CASE_BLIND_FILESYSTEM */ + /* + * On some platforms, the match must be case-blind. This is really + * a factor of the filesystem involved, but we can't detect that + * reliably - so we have to granularise at the OS level. + */ + if (pattern && (apr_fnmatch(pattern, dirent->name, + FNM_NOESCAPE | FNM_PERIOD | FNM_CASE_BLIND) + != APR_SUCCESS)) + return (NULL); +#endif /* !CASE_BLIND_FILESYSTEM */ + if (ignore_entry(d, ap_make_full_path(r->pool, r->filename, dirent->name))) return (NULL); - if (!(rr = ap_sub_req_lookup_dirent(dirent, r, NULL))) + if (!(rr = ap_sub_req_lookup_dirent(dirent, r, NULL))) { return (NULL); + } if ((rr->finfo.filetype != APR_DIR && rr->finfo.filetype != APR_REG) || !(rr->status == OK || ap_is_HTTP_SUCCESS(rr->status) @@ -1252,7 +1278,7 @@ p->isdir = 0; p->key = apr_toupper(keyid); p->ascending = (apr_toupper(direction) == D_ASCENDING); - p->version_sort = autoindex_opts & VERSION_SORT; + p->version_sort = !!(autoindex_opts & VERSION_SORT); if (autoindex_opts & (FANCY_INDEXING | TABLE_INDEXING)) { @@ -1295,7 +1321,7 @@ } static char *terminate_description(autoindex_config_rec *d, char *desc, - int autoindex_opts, int desc_width) + apr_int32_t autoindex_opts, int desc_width) { int maxsize = desc_width; register int x; @@ -1353,20 +1379,26 @@ * current request, the link changes its meaning to reverse the order when * selected again. Non-active fields always start in ascending order. */ -static void emit_link(request_rec *r, char *anchor, char fname, char curkey, - char curdirection, int nosort) +static void emit_link(request_rec *r, const char *anchor, char column, + char curkey, char curdirection, + const char *colargs, int nosort) { - char qvalue[5]; + char qvalue[9]; int reverse; if (!nosort) { + reverse = ((curkey == column) && (curdirection == D_ASCENDING)); qvalue[0] = '?'; - qvalue[1] = fname; + qvalue[1] = 'C'; qvalue[2] = '='; - qvalue[4] = '\0'; - reverse = ((curkey == fname) && (curdirection == D_ASCENDING)); - qvalue[3] = reverse ? D_DESCENDING : D_ASCENDING; - ap_rvputs(r, "", anchor, "", NULL); + qvalue[3] = column; + qvalue[4] = '&'; + qvalue[5] = 'O'; + qvalue[6] = '='; + qvalue[7] = reverse ? D_DESCENDING : D_ASCENDING; + qvalue[8] = '\0'; + ap_rvputs(r, "", anchor, "", NULL); } else { ap_rputs(anchor, r); @@ -1375,13 +1407,14 @@ static void output_directories(struct ent **ar, int n, autoindex_config_rec *d, request_rec *r, - int autoindex_opts, char keyid, char direction) + apr_int32_t autoindex_opts, char keyid, + char direction, const char *colargs) { int x; apr_size_t rv; char *name = r->uri; char *tp; - int static_columns = (autoindex_opts & SUPPRESS_COLSORT); + int static_columns = !!(autoindex_opts & SUPPRESS_COLSORT); apr_pool_t *scratch; int name_width; int desc_width; @@ -1443,20 +1476,24 @@ ++cols; } ap_rputs("", r); - emit_link(r, "Name", K_NAME, keyid, direction, static_columns); + emit_link(r, "Name", K_NAME, keyid, direction, + colargs, static_columns); if (!(autoindex_opts & SUPPRESS_LAST_MOD)) { ap_rputs("", r); - emit_link(r, "Last modified", K_LAST_MOD, keyid, direction, static_columns); + emit_link(r, "Last modified", K_LAST_MOD, keyid, direction, + colargs, static_columns); ++cols; } if (!(autoindex_opts & SUPPRESS_SIZE)) { ap_rputs("", r); - emit_link(r, "Size", K_SIZE, keyid, direction, static_columns); + emit_link(r, "Size", K_SIZE, keyid, direction, + colargs, static_columns); ++cols; } if (!(autoindex_opts & SUPPRESS_DESC)) { ap_rputs("", r); - emit_link(r, "Description", K_DESC, keyid, direction, static_columns); + emit_link(r, "Description", K_DESC, keyid, direction, + colargs, static_columns); ++cols; } if (!(autoindex_opts & SUPPRESS_RULES)) @@ -1481,7 +1518,8 @@ else ap_rputs(" ", r); } - emit_link(r, "Name", K_NAME, keyid, direction, static_columns); + emit_link(r, "Name", K_NAME, keyid, direction, + colargs, static_columns); ap_rputs(pad_scratch + 4, r); /* * Emit the guaranteed-at-least-one-space-between-columns byte. @@ -1489,16 +1527,17 @@ ap_rputs(" ", r); if (!(autoindex_opts & SUPPRESS_LAST_MOD)) { emit_link(r, "Last modified", K_LAST_MOD, keyid, direction, - static_columns); + colargs, static_columns); ap_rputs(" ", r); } if (!(autoindex_opts & SUPPRESS_SIZE)) { - emit_link(r, "Size", K_SIZE, keyid, direction, static_columns); + emit_link(r, "Size", K_SIZE, keyid, direction, + colargs, static_columns); ap_rputs(" ", r); } if (!(autoindex_opts & SUPPRESS_DESC)) { emit_link(r, "Description", K_DESC, keyid, direction, - static_columns); + colargs, static_columns); } if (!(autoindex_opts & SUPPRESS_RULES)) ap_rputs("
", r); @@ -1768,6 +1807,7 @@ char *title_name = ap_escape_html(r->pool, r->uri); char *title_endp; char *name = r->filename; + char *pstring = NULL; apr_finfo_t dirent; apr_dir_t *thedir; apr_status_t status; @@ -1775,9 +1815,10 @@ struct ent *head, *p; struct ent **ar = NULL; const char *qstring; - int autoindex_opts = autoindex_conf->opts; + apr_int32_t autoindex_opts = autoindex_conf->opts; char keyid; char direction; + char *colargs; if ((status = apr_dir_open(&thedir, name, r->pool)) != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, @@ -1809,8 +1850,85 @@ direction = autoindex_conf->default_direction ? autoindex_conf->default_direction : D_ASCENDING; - /* Spew HTML preamble */ + /* + * Figure out what sort of indexing (if any) we're supposed to use. + * + * If no QUERY_STRING was specified or client query strings have been + * explicitly disabled. + * If we are ignoring the client, suppress column sorting as well. + */ + if (autoindex_opts & IGNORE_CLIENT) { + qstring = NULL; + autoindex_opts |= SUPPRESS_COLSORT; + colargs = ""; + } + else { + char fval[5], vval[5], *ppre = ""; + fval[0] = '\0'; vval[0] = '\0'; + qstring = r->args; + while (qstring && *qstring) { + if (qstring[0] == 'C' && qstring[1] == '=' + && qstring[2] && strchr(K_VALID, qstring[2]) + && (qstring[3] == '&' || !qstring[3])) { + keyid = qstring[2]; + qstring += qstring[3] ? 4 : 3; + } + else if (qstring[0] == 'O' && qstring[1] == '=' + && ((qstring[2] == D_ASCENDING) + || (qstring[2] == D_DESCENDING)) + && (qstring[3] == '&' || !qstring[3])) { + direction = qstring[2]; + qstring += qstring[3] ? 4 : 3; + } + else if (qstring[0] == 'F' && qstring[1] == '=' + && qstring[2] && strchr("012", qstring[2]) + && (qstring[3] == '&' || !qstring[3])) { + if (qstring[2] == '0') + autoindex_opts &= ~(FANCY_INDEXING | TABLE_INDEXING); + else if (qstring[2] == '1') + autoindex_opts = (autoindex_opts | FANCY_INDEXING) + & ~TABLE_INDEXING; + else if (qstring[2] == '2') + autoindex_opts |= FANCY_INDEXING | TABLE_INDEXING; + strcpy(fval, "&F= "); + fval[3] = qstring[2]; + qstring += qstring[3] ? 4 : 3; + } + else if (qstring[0] == 'V' && qstring[1] == '=' + && (qstring[2] == '0' || qstring[2] == '1') + && (qstring[3] == '&' || !qstring[3])) { + if (qstring[2] == '0') + autoindex_opts &= ~VERSION_SORT; + else if (qstring[2] == '1') + autoindex_opts |= VERSION_SORT; + strcpy(fval, "&V= "); + vval[3] = qstring[2]; + qstring += qstring[3] ? 4 : 3; + } + else if (qstring[0] == 'P' && qstring[1] == '=') { + char *eos = strchr(qstring, '&'); + if (eos) { + pstring = apr_pstrndup(r->pool, qstring + 2, + eos - qstring - 2); + qstring = eos + 1; + } + else { + pstring = apr_pstrdup(r->pool, qstring + 2); + qstring = NULL; + } + if (*pstring) + ppre = "&P="; + else + pstring = NULL; + } + else /* Syntax error? Ignore the remainder! */ + qstring = NULL; + } + colargs = apr_pstrcat(r->pool, fval, vval, ppre, pstring, NULL); + } + + /* Spew HTML preamble */ title_endp = title_name + strlen(title_name) - 1; while (title_endp > title_name && *title_endp == '/') { @@ -1820,31 +1938,6 @@ emit_head(r, find_header(autoindex_conf, r), autoindex_opts & SUPPRESS_PREAMBLE, title_name); - /* - * Figure out what sort of indexing (if any) we're supposed to use. - * - * If no QUERY_STRING was specified or column sorting has been - * explicitly disabled, we use the default specified by the - * IndexOrderDefault directive (if there is one); otherwise, - * we fall back to ascending by name. - */ - if (!(autoindex_opts & SUPPRESS_COLSORT)) - qstring = r->args; - else - qstring = NULL; - - /* - * If there is no specific ordering defined for this directory, - * take the defaults above. - */ - if ((qstring != NULL) && (*qstring != '\0')) { - keyid = *qstring; - ap_getword(r->pool, &qstring, '='); - if (qstring != '\0') { - direction = *qstring; - } - } - /* * Since we don't know how many dir. entries there are, put them into a * linked list and then arrayificate them so qsort can use them. @@ -1857,8 +1950,8 @@ num_ent++; } while (apr_dir_read(&dirent, APR_FINFO_DIRENT, thedir) == APR_SUCCESS) { - p = make_autoindex_entry(&dirent, autoindex_opts, - autoindex_conf, r, keyid, direction); + p = make_autoindex_entry(&dirent, autoindex_opts, autoindex_conf, r, + keyid, direction, pstring); if (p != NULL) { p->next = head; head = p; @@ -1878,8 +1971,8 @@ qsort((void *) ar, num_ent, sizeof(struct ent *), (int (*)(const void *, const void *)) dsortf); } - output_directories(ar, num_ent, autoindex_conf, r, autoindex_opts, keyid, - direction); + output_directories(ar, num_ent, autoindex_conf, r, autoindex_opts, + keyid, direction, colargs); apr_dir_close(thedir); emit_tail(r, find_readme(autoindex_conf, r),