The following reply was made to PR mod_autoindex/4256; it has been noted by GNATS.
From: Raymond S Brand <[EMAIL PROTECTED]> To: [EMAIL PROTECTED] Cc: [EMAIL PROTECTED], [EMAIL PROTECTED], [EMAIL PROTECTED] Subject: Re: mod_autoindex/4256: Patch to permit HeaderName and Readme files to be server parsed. Date: Thu, 22 Apr 1999 10:58:39 -0400 OK, yet another patch to mod_autoindex. I promiss I'll stop now. This one replaces insert_readme() because its logic and calling conventions were getting very convoluted and were still wrong. The server-parsed Header and Readme still have some of the environment variables reflecting the Header or Readme file instead of the indexed directory. I don't know how to solve that problem; how mod_include does it is not clear to me. I would really like to see this make it into 1.3.7, if possible. Raymond S Brand P.S. Please use [EMAIL PROTECTED] for correspondence. diff -ur apache_1.3.6-orig/htdocs/manual/mod/mod_autoindex.html apache_1.3.6-rsbx/htdocs/manual/mod/mod_autoindex.html --- apache_1.3.6-orig/htdocs/manual/mod/mod_autoindex.html Mon Mar 22 19:17:39 1999 +++ apache_1.3.6-rsbx/htdocs/manual/mod/mod_autoindex.html Thu Apr 22 10:19:29 1999 @@ -437,14 +437,20 @@ The HeaderName directive sets the name of the file that will be inserted at the top of the index listing. <EM>Filename</EM> is the name of the file to include, and is taken to be relative to the directory being indexed. -The server first attempts to include <EM>filename</EM><CODE>.html</CODE> +<BLOCKQUOTE><STRONG>Apache 1.3.7 and later</STRONG> +will "server-parse" <EM>filename</EM>, if enabled. +<A HREF="../content-negotiation.html">Content negotiation</A> +will be performed if MultiViews are allowed. +</BLOCKQUOTE> +<BLOCKQUOTE><STRONG>Apache prior to 1.3.7</STRONG> +first attempts to include <EM>filename</EM><CODE>.html</CODE> as an HTML document, otherwise it will include <EM>filename</EM> as plain text. Example: <BLOCKQUOTE><CODE>HeaderName HEADER</CODE></BLOCKQUOTE> when indexing the directory <CODE>/web</CODE>, the server will first look for the HTML file <CODE>/web/HEADER.html</CODE> and include it if found, otherwise it will include the plain text file <CODE>/web/HEADER</CODE>, if it exists. - +</BLOCKQUOTE> <P>See also <A HREF="#readmename">ReadmeName</A>.<P><HR> <H2><A NAME="indexignore">IndexIgnore</A></H2> @@ -764,14 +770,20 @@ The ReadmeName directive sets the name of the file that will be appended to the end of the index listing. <EM>Filename</EM> is the name of the file to include, and is taken to be relative to the directory being indexed. -The server first attempts to include <EM>filename</EM><CODE>.html</CODE> +<BLOCKQUOTE><STRONG>Apache 1.3.7 and later</STRONG> +will "server-parse" <EM>filename</EM>, if enabled. +<A HREF="../content-negotiation.html">Content negotiation</A> +will be performed if MultiViews are allowed. +</BLOCKQUOTE> +<BLOCKQUOTE><STRONG>Apache prior to 1.3.7</STRONG> +first attempts to include <EM>filename</EM><CODE>.html</CODE> as an HTML document, otherwise it will include <EM>filename</EM> as plain text. Example: <BLOCKQUOTE><CODE>ReadmeName README</CODE></BLOCKQUOTE> when indexing the directory <CODE>/web</CODE>, the server will first look for the HTML file <CODE>/web/README.html</CODE> and include it if found, otherwise it will include the plain text file <CODE>/web/README</CODE>, if it exists. - +</BLOCKQUOTE> <P>See also <A HREF="#headername">HeaderName</A>.<P> diff -ur apache_1.3.6-orig/src/modules/standard/mod_autoindex.c apache_1.3.6-rsbx/src/modules/standard/mod_autoindex.c --- apache_1.3.6-orig/src/modules/standard/mod_autoindex.c Mon Jan 4 14:49:41 1999 +++ apache_1.3.6-rsbx/src/modules/standard/mod_autoindex.c Wed Apr 21 23:20:10 1999 @@ -178,8 +178,11 @@ * We include the DOCTYPE because we may be using features therefrom (i.e., * HEIGHT and WIDTH attributes on the icons if we're FancyIndexing). */ -static void emit_preamble(request_rec *r, char *title) +static void emit_preamble(request_rec *r, char *title, int suppress) { + if (suppress) { + return; + } ap_rvputs(r, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n", "<HTML>\n <HEAD>\n <TITLE>Index of ", title, "</TITLE>\n </HEAD>\n <BODY>\n", NULL); @@ -757,101 +760,158 @@ * Actually generating output */ -/* - * Look for the specified file, and pump it into the response stream if we - * find it. - */ -static int insert_readme(char *name, char *readme_fname, char *title, - int hrule, int whichend, request_rec *r) -{ - char *fn; - FILE *f; - struct stat finfo; - int plaintext = 0; - request_rec *rr; - autoindex_config_rec *cfg; - int autoindex_opts; - - cfg = (autoindex_config_rec *) ap_get_module_config(r->per_dir_config, - &autoindex_module); - autoindex_opts = cfg->opts; - /* XXX: this is a load of crap, it needs to do a full sub_req_lookup_uri */ - fn = ap_make_full_path(r->pool, name, readme_fname); - fn = ap_pstrcat(r->pool, fn, ".html", NULL); - if (stat(fn, &finfo) == -1) { - /* A brief fake multiviews search for README.html */ - fn[strlen(fn) - 5] = '\0'; - if (stat(fn, &finfo) == -1) { - return 0; - } - plaintext = 1; - if (hrule) { - ap_rputs("<HR>\n", r); - } - } - else if (hrule) { - ap_rputs("<HR>\n", r); - } - /* XXX: when the above is rewritten properly, this necessary security - * check will be redundant. -djg */ - rr = ap_sub_req_lookup_file(fn, r); - if (rr->status != HTTP_OK) { - ap_destroy_sub_req(rr); - return 0; - } - ap_destroy_sub_req(rr); - if (!(f = ap_pfopen(r->pool, fn, "r"))) { - return 0; - } - if ((whichend == FRONT_MATTER) - && (!(autoindex_opts & SUPPRESS_PREAMBLE))) { - emit_preamble(r, title); - } - if (!plaintext) { - ap_send_fd(f, r); - } - else { - char buf[IOBUFSIZE + 1]; - int i, n, c, ch; - ap_rputs("<PRE>\n", r); - while (!feof(f)) { - do { - n = fread(buf, sizeof(char), IOBUFSIZE, f); - } - while (n == -1 && ferror(f) && errno == EINTR); - if (n == -1 || n == 0) { - break; - } - buf[n] = '\0'; - c = 0; - while (c < n) { - for (i = c; i < n; i++) { - if (buf[i] == '<' || buf[i] == '>' || buf[i] == '&') { - break; - } - } - ch = buf[i]; - buf[i] = '\0'; - ap_rputs(&buf[c], r); - if (ch == '<') { - ap_rputs("<", r); - } - else if (ch == '>') { - ap_rputs(">", r); - } - else if (ch == '&') { - ap_rputs("&", r); - } - c = i + 1; - } - } - } - ap_pfclose(r->pool, f); - if (plaintext) { - ap_rputs("</PRE>\n", r); - } - return 1; -} +/* + * Elements of the emitted document: + * Preamble + * Emitted unless SUPPRESS_PREAMBLE is set AND ap_run_sub_req + * succeeds for the (content_type == text/html) header file. + * Header file + * Emitted if found (and able). + * H1 tag line + * Emitted if a header file is NOT emitted. + * Directory stuff + * Always emitted. + * HR + * Emitted if FANCY_INDEXING is set AND a readme file is + * emitted. + * Readme file + * Emitted if found (and able). + * ServerSig + * Emitted if ServerSignature is not Off AND a readme file + * is NOT emitted. + * Postamble + * Emitted unless SUPPRESS_PREAMBLE is set AND ap_run_sub_req + * succeeds for the (content_type == text/html) readme file. + * + * Problem: The ap_run_sub_req could fail AFTER the HR is emitted. + * Solution: Make the HR only depend on FANCY_INDEXING. + */ + + +/* + * emit a plain text file + */ +static void do_emit_plain(request_rec *r, FILE *f) +{ + char buf[IOBUFSIZE + 1]; + int i, n, c, ch; + + ap_rputs("<PRE>\n", r); + while (!feof(f)) { + do { + n = fread(buf, sizeof(char), IOBUFSIZE, f); + } + while (n == -1 && ferror(f) && errno == EINTR); + if (n == -1 || n == 0) { + break; + } + buf[n] = '\0'; + c = 0; + while (c < n) { + for (i = c; i < n; i++) { + if (buf[i] == '<' || buf[i] == '>' || buf[i] == '&') { + break; + } + } + ch = buf[i]; + buf[i] = '\0'; + ap_rputs(&buf[c], r); + if (ch == '<') { + ap_rputs("<", r); + } + else if (ch == '>') { + ap_rputs(">", r); + } + else if (ch == '&') { + ap_rputs("&", r); + } + c = i + 1; + } + } + ap_rputs("</PRE>\n", r); +} + + +/* + * Handle the preamble through the H1 tag line, inclusive. + */ +static void emit_head(request_rec *r, char *header_fname, int suppress_amble, + char *title) + { + FILE *f; + request_rec *rr = NULL; + int emit_H1 = 0; + + if (header_fname + && (rr = ap_sub_req_lookup_uri(header_fname, r)) + && (rr->status == HTTP_OK) + && (rr->filename) + && S_ISREG(rr->finfo.st_mode)) { + if ((rr->content_type) + && !strcmp("text/html", rr->content_type)) { + emit_preamble(r, title, suppress_amble); + if (ap_run_sub_req(rr)) { + emit_preamble(r, title, !suppress_amble); + emit_H1 = 1; + } + } + else { + emit_preamble(r, title, 0); + if (f = ap_pfopen(r->pool, rr->filename, "r")) { + do_emit_plain(r, f); + ap_pfclose(r->pool, f); + } + else { + emit_H1 = 1; + } + } + } + else { + emit_preamble(r, title, 0); + emit_H1 = 1; + } + + if (emit_H1) { ap_rvputs(r, "<H1>Index of ", title, "</H1>\n", NULL); } + + if (rr) { ap_destroy_sub_req(rr); } + } + + +/* + * Handle the Readme file through the postamble, inclusive. + */ +static void emit_tail(request_rec *r, char *readme_fname, int suppress_amble) + { + FILE *f; + request_rec *rr = NULL; + int suppress_post = 0; + int suppress_sig = 0; + + if (readme_fname + && (rr = ap_sub_req_lookup_uri(readme_fname, r)) + && (rr->status == HTTP_OK) + && (rr->filename) + && S_ISREG(rr->finfo.st_mode)) { + if ((rr->content_type) + && !strcmp("text/html", rr->content_type)) { + if (!ap_run_sub_req(rr)) { + suppress_sig = 1; + suppress_post = suppress_amble; + } + } + else { + if (f = ap_pfopen(r->pool, rr->filename, "r")) { + do_emit_plain(r, f); + ap_pfclose(r->pool, f); + suppress_sig = 1; + } + } + } + + if (!suppress_sig) { ap_rputs(ap_psignature("", r), r); } + if (!suppress_post) { ap_rputs("</BODY></HTML>\n", r); } + if (rr) { ap_destroy_sub_req(rr); } + } static char *find_title(request_rec *r) @@ -1326,7 +1386,6 @@ int num_ent = 0, x; struct ent *head, *p; struct ent **ar = NULL; - char *tmp; const char *qstring; int autoindex_opts = autoindex_conf->opts; char keyid; @@ -1356,12 +1415,8 @@ *title_endp-- = '\0'; } - if ((!(tmp = find_header(autoindex_conf, r))) - || (!(insert_readme(name, tmp, title_name, NO_HRULE, FRONT_MATTER, r))) - ) { - emit_preamble(r, title_name); - ap_rvputs(r, "<H1>Index of ", title_name, "</H1>\n", NULL); - } + 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. @@ -1426,15 +1481,11 @@ direction); ap_pclosedir(r->pool, d); - if ((tmp = find_readme(autoindex_conf, r))) { - if (!insert_readme(name, tmp, "", - ((autoindex_opts & FANCY_INDEXING) ? HRULE - : NO_HRULE), - END_MATTER, r)) { - ap_rputs(ap_psignature("<HR>\n", r), r); - } - } - ap_rputs("</BODY></HTML>\n", r); + if (autoindex_opts & FANCY_INDEXING) { + ap_rputs("<HR>\n", r); + } + emit_tail(r, find_readme(autoindex_conf, r), + autoindex_opts & SUPPRESS_PREAMBLE); ap_kill_timeout(r); return 0; --