The problem in this PR is that on Solaris, when Options FollowSymLinks
is specified for a CGI, the URI specifying the CGI can't have a
trailing slash.  If it has a trailing slash, the browser sees a 500
error with the "premature end of script headers" message.

The immediate cause of the CGI failure is trying to chdir() to
"prefix/mycgi/" instead of to "prefix".  We try to do that because
r->filename has "prefix/mycgi/" instead of "prefix/mycgi" and we don't
realize what is the containing directory of the cgi script.

The same testcase works on Linux.  The OS behavior which is different
is that on Solaris (and AIX and maybe others) returns 0 for
stat("prefix/mycgi/") whereas Linux (and FreeBSD and maybe others)
returns -1/ENOTDIR for the same stat.

The following patch assumes that our existing handling of the
Linux/FreeBSD-type platform is correct and that all we need to do is
force platforms with the alternate stat() semantics into the same
directory walk handling.

An alternate patch would change APR so that it returned APR_ENOTDIR if
a stat on a file name ending with '/' succeeds but the OS tells us it
is not actually a directory.

I don't know what the right fix is.  Directory walk already makes any
number of assumptions about the presence of a '/' in a filename so it
doesn't seem much of a stretch to add one more.  On the other hand,
consistent behavior in APR is always nice :)

Index: server/request.c
===================================================================
RCS file: /home/cvs/httpd-2.0/server/request.c,v
retrieving revision 1.104
diff -u -r1.104 request.c
--- server/request.c    12 Mar 2002 09:02:19 -0000      1.104
+++ server/request.c    13 Mar 2002 15:50:24 -0000
@@ -536,6 +536,17 @@
      */
     if (!r->finfo.filetype || r->finfo.filetype == APR_LNK) {
         apr_stat(&r->finfo, r->filename, APR_FINFO_MIN, r->pool);
+        /* some OSs will return APR_SUCCESS/APR_REG if we stat
+         * a regular file but we have '/' at the end of the name;
+         *
+         * other OSs will return APR_ENOTDIR for that situation;
+         *
+         * handle it the same everywhere
+         */
+        if (r->finfo.filetype == APR_REG && 
+            r->filename[strlen(r->filename) - 1] == '/') {
+            r->finfo.filetype = 0; /* forget what we learned */
+        }
     }
 
     if (r->finfo.filetype == APR_REG) {

-- 
Jeff Trawick | [EMAIL PROTECTED]
Born in Roswell... married an alien...

Reply via email to