httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Glenn <>
Subject [REPOST] server-side includes "virtual" and "exec" questions/patches
Date Tue, 17 Jun 2003 01:44:02 GMT
Repost.  Looking for feedback.  Thanks!  -Glenn

 Date: Fri, 9 May 2003 04:11:06 -0400
 Subject: server-side includes "virtual" and "exec" questions/patches
 Message-ID: <>

1) Why does includes "virtual" sometimes fail with
     "unable to include potential exec \"%s\" in parsed file %s"
   when Options IncludesNoEXEC is used?  Why is this check performed?
   What is the reasoning behind it?

--- httpd-2.0.45/modules/filters/mod_include.c  2003-02-03 12:31:38.000000000 -0500
+++ httpd-2.0.45/modules/filters/      2003-05-07 15:38:58.000000000 -0400
@@ -1274,12 +1274,6 @@
                     error_fmt = "unable to include \"%s\" in parsed file %s";
-                if (!error_fmt && (ctx->flags & FLAG_NO_EXEC) &&
-                    rr->content_type &&
-                    (strncmp(rr->content_type, "text/", 5))) {
-                    error_fmt = "unable to include potential exec \"%s\" "
-                        "in parsed file %s";
-                }
                 if (error_fmt == NULL) {
                     /* try to avoid recursive includes.  We do this by walking
                      * up the r->main list of subrequests, and at each level

The documentation for IncludeNoEXEC (with the Options directive) states:
    Server-side includes are permitted, but the #exec command and
    #exec CGI are disabled. It is still possible to #include virtual
    CGI scripts from ScriptAliase'd directories.

When Options IncludesNoEXEC is used, the code for include virtual="..."
currently checks the initial content-type of the target for for text/*
(before running the subrequest) and therefore disallows, for example,
  <!--#include virtual="/cgi-bin/foo.php"-->
since the initial content-type can be application/x-httpd-php.  This
fails even when /cgi-bin/ is marked Options +ExecCGI.  (A workaround
may be to use AddHandler to set it to "cgi-script" and to use AddType
to set the type to text/html.  Or the above patch could be modified
to check for ExecCGI: (ap_allow_options(r) & OPT_EXECCGI), or else
check for ScripAlias: ap_table_get(r->notes, "alias-forced-type") )

What is the reason that the #include virtual="..." (and "file") are
peeking into the subrequest?  Shouldn't they just run the subrequest
and include the results?  After all, requesting the URI directly would
produce identical results, wouldn't it?  Maybe only "#include file"
should check for content-type text/*, but not "#include virtual".

Can this be backported to 2.0 and 1.3?

2) Should <!--#exec cgi="..."--> be officially deprecated?
   The following two statements are almost semantically equivalent AFAICT:
     <!--#exec cgi="/path/to/cgi"-->
     <!--#include virtual="/path/to/cgi${PATH_INFO}?${QUERY_STRING}"-->
   and #include virtual is more flexible, and allowed with IncludesNoEXEC.
   Besides, I really do not like the idea of the silent inheritance of
   path info and query string by #exec cgi because it is an inheritance of
   the path info and query string of the base document, which gets really
   messy if you have nested includes and have an #include virtual in the
   mix which uses its own path info and query string.

   Is there any reason "#exec cgi" should remain in Apache 2.1?  If people
   support removing it, I'll whip up a quick patch to mod_cgi/mod_cgid.
   Backwards compatibility is one thing, but this is cruft.  Current
   documentation says:
     "The include virtual element should be used in preference to exec cgi"
   but does not go so far as to deprecate it, indicating that it might be
   removed in the future.

   In addition to path info and query string inheritance, the only
   difference between #exec cgi and #include virtual is that if the target
   CGI returns a redirect, #exec cgi will turn it into a hyperlink.  I'm
   not sure how often this "feature" is used, but the simple workaround is
   to have the CGI script return the hyperlink as the body of its output:
     print "Content-type: text/plain\n\n",
           "<a href="link">link</a>\n";

3) Apache2 mod_include performs lazy evaluation of a few environment
   These variables end up being empty strings ("") in a CGI environment
   unless they are used in the include document prior to the virtual or
   exec include, e.g. the no-op
     <!--#if expr="$DATE_LOCAL"--><!--#endif-->
   Can this be documented somewhere?  What pages should be updated?
   mod_include documentation, the SSI tutorial, others?

4) Minor nit.  Should USER_NAME be inherited from the base document, just
   as the LAST_MODIFIED time is done?  If USER_NAME was generated from the
   lazy value before a sub-include, then it is inherited.  If it was not
   generated before a sub-include, then it will be set with the value of
   the document when it is actually used, leading to inconsistencies.

--- httpd-2.0.45/modules/filters/mod_include.c  2003-02-03 12:31:38.000000000 -0500
+++ httpd-2.0.45/modules/filters/      2003-05-09 04:05:26.000000000 -0400
@@ -3386,10 +3386,12 @@
          * torquing our own last_modified date as well so that the
          * LAST_MODIFIED variable gets reset to the proper value if the
          * nested document resets <!--#config timefmt -->.
+         * Also torque info used to generate USER_NAME.
         r->subprocess_env = r->main->subprocess_env;
         apr_pool_join(r->main->pool, r->pool);
         r->finfo.mtime = r->main->finfo.mtime;
+        r->finfo.user  = r->main->finfo.user;
     else {
         /* we're not a nested include, so we create an initial

5) Can mod_include please export get_include_var() as an optional function?
   How about as ap_ssi_get_include_var()?

--- httpd-2.0.45/modules/filters/mod_include.c  2003-02-03 12:31:38.000000000 -0500
+++ httpd-2.0.45/modules/filters/      2003-05-07 15:46:05.000000000 -0400
@@ -206,8 +206,8 @@
     return val;
-static const char *get_include_var(request_rec *r, include_ctx_t *ctx,
-                                   const char *var)
+static const char *ap_ssi_get_include_var(request_rec *r, include_ctx_t *ctx,
+                                          const char *var)
     const char *val;
     if (apr_isdigit(*var) && !var[1]) {
@@ -1099,7 +1099,7 @@
                 if (l != 0) {
                     tmp_store        = *end_of_var_name;
                     *end_of_var_name = '\0';
-                    val = get_include_var(r, ctx, start_of_var_name);
+                    val = ap_ssi_get_include_var(r, ctx, start_of_var_name);
                     *end_of_var_name = tmp_store;
                     if (val) {
@@ -1387,9 +1387,9 @@
             if (!strcmp(tag, "var")) {
                 conn_rec *c = r->connection;
                 const char *val =
-                    get_include_var(r, ctx,
-                                    ap_ssi_parse_string(r, ctx, tag_val, NULL,
-                                                        MAX_STRING_LEN, 0));
+                    ap_ssi_get_include_var(
+                      r, ctx, ap_ssi_parse_string(r, ctx, tag_val, NULL
+                                                  MAX_STRING_LEN, 0));
                 if (val) {
                     switch(encode) {
                     case E_NONE:
@@ -3569,6 +3569,7 @@
 static void register_hooks(apr_pool_t *p)
+    APR_REGISTER_OPTIONAL_FN(ap_ssi_get_include_var);


View raw message