httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From c...@hyperreal.org
Subject cvs commit: apache-1.3/src/modules/standard mod_autoindex.c mod_include.c
Date Thu, 13 May 1999 18:26:00 GMT
coar        99/05/13 11:25:59

  Modified:    htdocs/manual/mod mod_autoindex.html
               src      CHANGES
               src/modules/standard mod_autoindex.c mod_include.c
  Log:
  	Someone finally stood up and made the ReadmeName and HeaderName
  	features use subrequests.  Not only that, but they can be
  	parsed for SSIs too!
  
  PR:		1574, 3026, 3529, 3569, 4256
  Submitted by:	Raymond S Brand <rsbx@rsbx.net>
  Reviewed by:	Ken Coar
  
  Revision  Changes    Path
  1.31      +57 -17    apache-1.3/htdocs/manual/mod/mod_autoindex.html
  
  Index: mod_autoindex.html
  ===================================================================
  RCS file: /home/cvs/apache-1.3/htdocs/manual/mod/mod_autoindex.html,v
  retrieving revision 1.30
  retrieving revision 1.31
  diff -u -r1.30 -r1.31
  --- mod_autoindex.html	1999/01/04 14:35:53	1.30
  +++ mod_autoindex.html	1999/05/13 18:25:45	1.31
  @@ -426,20 +426,53 @@
   <A
    HREF="directive-dict.html#Module"
    REL="Help"
  -><STRONG>Module:</STRONG></A> mod_autoindex<P>
  +><STRONG>Module:</STRONG></A> mod_autoindex
  +  <BR>
  +  <A
  +   HREF="directive-dict.html#Compatibility"
  +   REL="Help"
  +  ><STRONG>Compatibility:</STRONG></A> some features only available
after
  + 1.3.6; see text
   
  +<P>
   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>
  -as an HTML document, otherwise it will include <EM>filename</EM> as plain
  -text. Example:
  +to include.
  +</P>
  +<BLOCKQUOTE><STRONG>Apache 1.3.6 and earlier:</STRONG>
  +The module first attempts to include <EM>filename</EM><CODE>.html</CODE>
  +as an HTML document, otherwise it will try to include <EM>filename</EM> as
  +plain text.  <EM>Filename</EM> is treated as a filesystem path relative
  +to the directory being indexed.  In no case is SSI processing done.
  +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.
  -
  -<P>See also <A HREF="#readmename">ReadmeName</A>.<P><HR>
  +</BLOCKQUOTE>
  +<BLOCKQUOTE><STRONG>Apache versions after 1.3.6:</STRONG>
  +<EM>Filename</EM> is treated as a URI path relative to the one used
  +to access the directory being indexed, and must resolve to a document
  +with a major content type of "<SAMP>text</SAMP>" (<EM>e.g.</EM>,
  +<SAMP>text/html</SAMP>, <SAMP>text/plain</SAMP>, <EM>etc.</EM>).
  +This means that <EM>filename</EM> may refer to a CGI script if the
  +script's actual file type (as opposed to its output) is marked as
  +<SAMP>text/html</SAMP> such as with a directive like:
  +<PRE>
  +    AddType text/html .cgi
  +</PRE>
  +<A HREF="../content-negotiation.html">Content negotiation</A>
  +will be performed if the <SAMP>MultiViews</SAMP>
  +<A HREF="core.html#options">option</A> is enabled.
  +If <EM>filename</EM> resolves to a static <SAMP>text/html</SAMP>
document
  +(not a CGI script) and the
  +<SAMP>Includes</SAMP> <A HREF="core.html#options">option</A> is
enabled,
  +the file will be processed for server-side includes (see the
  +<A HREF="mod_include.html"><SAMP>mod_include</SAMP></A> documentation).
  +</BLOCKQUOTE>
  +<P>
  +See also <A HREF="#readmename">ReadmeName</A>.
  +<P><HR>
   
   <H2><A NAME="indexignore">IndexIgnore</A></H2>
   <!--%plaintext &lt;?INDEX {\tt IndexIgnore} directive&gt; -->
  @@ -753,19 +786,26 @@
   <A
    HREF="directive-dict.html#Module"
    REL="Help"
  -><STRONG>Module:</STRONG></A> mod_autoindex<P>
  +><STRONG>Module:</STRONG></A> mod_autoindex
  +  <BR>
  +  <A
  +   HREF="directive-dict.html#Compatibility"
  +   REL="Help"
  +  ><STRONG>Compatibility:</STRONG></A> some features only available
after
  + 1.3.6; see text
   
  +<P>
   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>
  -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.
  -
  +to include, and is taken to be relative to the location being indexed.
  +</P>
  +<BLOCKQUOTE>
  +<STRONG>The <EM>filename</EM> argument is treated as a stub filename
  +in Apache 1.3.6 and earlier, and as a relative URI in later versions.
  +Details of how it is handled may be found under the description of
  +the <A HREF="#headername">HeaderName</A> directive, which uses the
  +same mechanism and changed at the same time as ReadmeName.</STRONG>
  +</BLOCKQUOTE>
   <P>See also <A HREF="#headername">HeaderName</A>.<P>
   
   
  
  
  
  1.1354    +8 -0      apache-1.3/src/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/CHANGES,v
  retrieving revision 1.1353
  retrieving revision 1.1354
  diff -u -r1.1353 -r1.1354
  --- CHANGES	1999/05/12 16:50:40	1.1353
  +++ CHANGES	1999/05/13 18:25:50	1.1354
  @@ -1,5 +1,13 @@
   Changes with Apache 1.3.7
   
  +  *) Support for server-parsed and multiview-determined ReadmeName and
  +     HeaderName files in mod_autoindex. Removed the restriction on
  +     "/"s in ReadmeName and HeaderName directives since the *sub_req*
  +     routines will deal with the access issues. (It's now possible to
  +     have {site|group|project|customer|...} wide readmes and headers.)
  +     [Raymond S Brand <rsbx@rsbx.net>, Ken Coar] PR#1574, 3026, 3529,
  +     3569, 4256
  +
     *) When stat() fails, don't assume anything about the contents of
        the struct stat.  [Ed Korthof <ed@bitmechanic.com>]
   
  
  
  
  1.107     +208 -99   apache-1.3/src/modules/standard/mod_autoindex.c
  
  Index: mod_autoindex.c
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/modules/standard/mod_autoindex.c,v
  retrieving revision 1.106
  retrieving revision 1.107
  diff -u -r1.106 -r1.107
  --- mod_autoindex.c	1999/05/03 20:48:43	1.106
  +++ mod_autoindex.c	1999/05/13 18:25:56	1.107
  @@ -322,9 +322,6 @@
   
   static const char *add_header(cmd_parms *cmd, void *d, char *name)
   {
  -    if (strchr(name, '/')) {
  -	return "HeaderName cannot contain a /";
  -    }
       push_item(((autoindex_config_rec *) d)->hdr_list, 0, NULL, cmd->path,
   	      name);
       return NULL;
  @@ -332,9 +329,6 @@
   
   static const char *add_readme(cmd_parms *cmd, void *d, char *name)
   {
  -    if (strchr(name, '/')) {
  -	return "ReadmeName cannot contain a /";
  -    }
       push_item(((autoindex_config_rec *) d)->rdme_list, 0, NULL, cmd->path,
   	      name);
       return NULL;
  @@ -864,99 +858,223 @@
    */
   
   /*
  - * Look for the specified file, and pump it into the response stream if we
  - * find it.
  + * 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.
  + *	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.
    */
  -static int insert_readme(char *name, char *readme_fname, char *title,
  -			 int hrule, int whichend, request_rec *r)
  +
  +
  +/*
  + * emit a plain text file
  + */
  +static void do_emit_plain(request_rec *r, FILE *f)
   {
  -    char *fn;
  -    FILE *f;
  -    struct stat finfo;
  -    int plaintext = 0;
  -    request_rec *rr;
  -    autoindex_config_rec *cfg;
  -    int autoindex_opts;
  +    char buf[IOBUFSIZE + 1];
  +    int i, n, c, ch;
   
  -    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);
  +    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("&lt;", r);
  +	    }
  +	    else if (ch == '>') {
  +		ap_rputs("&gt;", r);
  +	    }
  +	    else if (ch == '&') {
  +		ap_rputs("&amp;", r);
  +	    }
  +	    c = i + 1;
   	}
  -    }
  -    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;
  +    ap_rputs("</PRE>\n", r);
  +}
  +
  +/* See mod_include */
  +#define SUB_REQ_STRING	"Sub request to mod_include"
  +#define PARENT_STRING	"Parent request to mod_include"
  +
  +/*
  + * Handle the preamble through the H1 tag line, inclusive.  Locate
  + * the file with a subrequests.  Process text/html documents by actually
  + * running the subrequest; text/xxx documents get copied verbatim,
  + * and any other content type is ignored.  This means that a non-text
  + * document (such as HEADER.gif) might get multiviewed as the result
  + * instead of a text document, meaning nothing will be displayed, but
  + * oh well.
  + */
  +static void emit_head(request_rec *r, char *header_fname, int suppress_amble,
  +		      char *title)
  +{
  +    FILE *f;
  +    request_rec *rr = NULL;
  +    int emit_amble = 1;
  +    int emit_H1 = 1;
  +
  +    /*
  +     * If there's a header file, send a subrequest to look for it.  If it's
  +     * found and a text file, handle it -- otherwise fall through and
  +     * pretend there's nothing there.
  +     */
  +    if ((header_fname != NULL)
  +	&& (rr = ap_sub_req_lookup_uri(header_fname, r))
  +	&& (rr->status == HTTP_OK)
  +	&& (rr->filename != NULL)
  +	&& S_ISREG(rr->finfo.st_mode)) {
  +	/*
  +	 * Check for the two specific cases we allow: text/html and
  +	 * text/anything-else.  The former is allowed to be processed for
  +	 * SSIs.
  +	 */
  +	if (rr->content_type != NULL) {
  +	    if (!strcasecmp("text/html", rr->content_type)) {
  +		/* Hope everything will work... */
  +		emit_amble = 0;
  +		emit_H1 = 0;
  +
  +		if (! suppress_amble) {
  +		    emit_preamble(r, title);
  +		}
  +		ap_table_add(r->notes, PARENT_STRING, "");
  +		ap_table_add(rr->notes, SUB_REQ_STRING, "");
  +		/*
  +		 * If there's a problem running the subrequest, display the
  +		 * preamble if we didn't do it before -- the header file
  +		 * didn't get displayed.
  +		 */
  +		if (ap_run_sub_req(rr) != OK) {
  +		    /* It didn't work */
  +		    emit_amble = suppress_amble;
  +		    emit_H1 = 1;
  +		}
  +	    }
  +	    else if (!strncasecmp("text/", rr->content_type, 5)) {
  +		/*
  +		 * If we can open the file, prefix it with the preamble
  +		 * regardless; since we'll be sending a <PRE> block around
  +		 * the file's contents, any HTML header it had won't end up
  +		 * where it belongs.
  +		 */
  +		if ((f = ap_pfopen(r->pool, rr->filename, "r")) != 0) {
  +		    emit_preamble(r, title);
  +		    emit_amble = 0;
  +		    do_emit_plain(r, f);
  +		    ap_pfclose(r->pool, f);
  +		    emit_H1 = 0;
  +		}
  +	    }
  +	}
       }
  -    if ((whichend == FRONT_MATTER)
  -	&& (!(autoindex_opts & SUPPRESS_PREAMBLE))) {
  +
  +    if (emit_amble) {
   	emit_preamble(r, title);
       }
  -    if (!plaintext) {
  -	ap_send_fd(f, r);
  +    if (emit_H1) {
  +	ap_rvputs(r, "<H1>Index of ", title, "</H1>\n", NULL);
       }
  -    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("&lt;", r);
  -		}
  -		else if (ch == '>') {
  -		    ap_rputs("&gt;", r);
  +    if (rr != NULL) {
  +	ap_destroy_sub_req(rr);
  +    }
  +}
  +
  +
  +/*
  + * Handle the Readme file through the postamble, inclusive.  Locate
  + * the file with a subrequests.  Process text/html documents by actually
  + * running the subrequest; text/xxx documents get copied verbatim,
  + * and any other content type is ignored.  This means that a non-text
  + * document (such as FOOTER.gif) might get multiviewed as the result
  + * instead of a text document, meaning nothing will be displayed, but
  + * oh well.
  + */
  +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 there's a readme file, send a subrequest to look for it.  If it's
  +     * found and a text file, handle it -- otherwise fall through and
  +     * pretend there's nothing there.
  +     */
  +    if ((readme_fname != NULL)
  +	&& (rr = ap_sub_req_lookup_uri(readme_fname, r))
  +	&& (rr->status == HTTP_OK)
  +	&& (rr->filename != NULL)
  +	&& S_ISREG(rr->finfo.st_mode)) {
  +	/*
  +	 * Check for the two specific cases we allow: text/html and
  +	 * text/anything-else.  The former is allowed to be processed for
  +	 * SSIs.
  +	 */
  +	if (rr->content_type != NULL) {
  +	    if (!strcasecmp("text/html", rr->content_type)) {
  +		ap_table_add(r->notes, PARENT_STRING, "");
  +		ap_table_add(rr->notes, SUB_REQ_STRING, "");
  +		if (ap_run_sub_req(rr) == OK) {
  +		    /* worked... */
  +		    suppress_sig = 1;
  +		    suppress_post = suppress_amble;
   		}
  -		else if (ch == '&') {
  -		    ap_rputs("&amp;", r);
  +	    }
  +	    else if (!strncasecmp("text/", rr->content_type, 5)) {
  +		/*
  +		 * If we can open the file, suppress the signature.
  +		 */
  +		if ((f = ap_pfopen(r->pool, rr->filename, "r")) != 0) {
  +		    do_emit_plain(r, f);
  +		    ap_pfclose(r->pool, f);
  +		    suppress_sig = 1;
   		}
  -		c = i + 1;
   	    }
   	}
  +    }
  +    
  +    if (!suppress_sig) {
  +	ap_rputs(ap_psignature("", r), r);
       }
  -    ap_pfclose(r->pool, f);
  -    if (plaintext) {
  -	ap_rputs("</PRE>\n", r);
  +    if (!suppress_post) {
  +	ap_rputs("</BODY></HTML>\n", r);
  +    }
  +    if (rr != NULL) {
  +	ap_destroy_sub_req(rr);
       }
  -    return 1;
   }
   
   
  @@ -1389,7 +1507,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;
  @@ -1419,12 +1536,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.
  @@ -1489,15 +1602,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);
  -	}
  +    if (autoindex_opts & FANCY_INDEXING) {
  +	ap_rputs("<HR>\n", r);
       }
  -    ap_rputs("</BODY></HTML>\n", r);
  +    emit_tail(r, find_readme(autoindex_conf, r),
  +	      autoindex_opts & SUPPRESS_PREAMBLE);
   
       ap_kill_timeout(r);
       return 0;
  
  
  
  1.115     +40 -9     apache-1.3/src/modules/standard/mod_include.c
  
  Index: mod_include.c
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/modules/standard/mod_include.c,v
  retrieving revision 1.114
  retrieving revision 1.115
  diff -u -r1.114 -r1.115
  --- mod_include.c	1999/05/05 17:46:07	1.114
  +++ mod_include.c	1999/05/13 18:25:57	1.115
  @@ -108,9 +108,6 @@
   
   module MODULE_VAR_EXPORT includes_module;
   
  -/* just need some arbitrary non-NULL pointer which can't also be a request_rec */
  -#define NESTED_INCLUDE_MAGIC	(&includes_module)
  -
   /* ------------------------ Environment function -------------------------- */
   
   /* XXX: could use ap_table_overlap here */
  @@ -746,9 +743,7 @@
               }
   
   	    /* destroy the sub request if it's not a nested include */
  -            if (rr != NULL
  -		&& ap_get_module_config(rr->request_config, &includes_module)
  -		    != NESTED_INCLUDE_MAGIC) {
  +	    if (rr != NULL) {
   		ap_destroy_sub_req(rr);
               }
           }
  @@ -2376,6 +2371,41 @@
           return OK;
       }
   
  +#define SUB_REQ_STRING	"Sub request to mod_include"
  +#define PARENT_STRING	"Parent request to mod_include"
  +
  +    if (ap_table_get(r->notes, SUB_REQ_STRING) != NULL) {
  +	request_rec *p = r->main;
  +
  +	/*
  +	 * The note is a flag to mod_include that this request is actually
  +	 * a subrequest from another module and that mod_include needs to
  +	 * treat it as if it's a subrequest from mod_include.
  +	 *
  +	 * HACK ALERT!
  +	 * There is no good way to pass the parent request_rec to mod_include.
  +	 * Tables only take string values and there is nowhere appropriate in
  +	 * in the request_rec that can safely be used.
  +	 *
  +	 * So we search up the chain of requests and redirects looking for
  +	 * the parent request.
  +	 */
  +
  +	while (p) {
  +	    if (ap_table_get(p->notes, PARENT_STRING) != NULL) {
  +		/* Kludge --- See below */
  +		ap_set_module_config(r->request_config, &includes_module, p);
  +
  +		ap_add_common_vars(p);
  +		ap_add_cgi_vars(p);
  +		add_include_vars(p, DEFAULT_TIME_FORMAT);
  +		ap_table_unset(r->notes, SUB_REQ_STRING);
  +		break;
  +	    }
  +	    p = (p->prev) ? p->prev : p->main;
  +	}
  +    }
  +
       if ((parent = ap_get_module_config(r->request_config, &includes_module))) {
   	/* Kludge --- for nested includes, we want to keep the subprocess
   	 * environment of the base document (for compatibility); that means
  @@ -2411,9 +2441,10 @@
       send_parsed_content(f, r);
   
       if (parent) {
  -	/* signify that the sub request should not be killed */
  -	ap_set_module_config(r->request_config, &includes_module,
  -	    NESTED_INCLUDE_MAGIC);
  +	/* Kludge --- Doing this allows the caller to safely destroy the
  +	 * sub_req
  +	 */
  +	r->pool = ap_make_sub_pool(r->pool);
       }
   
       ap_kill_timeout(r);
  
  
  

Mime
View raw message