ID:               46479
 Updated by:       [EMAIL PROTECTED]
 Reported By:      rosenfield dot albert at gmail dot com
 Status:           Open
-Bug Type:         Scripting Engine problem
+Bug Type:         Apache2 related
-Operating System: Any
+Operating System: *
 PHP Version:      5.3.0alpha2
 New Comment:

Since you failed to give the actual Apache version (and I doubt 
you're using 5.3 either) I'm assuming you have apache 2 something. 
Please update that information. Also, give the exact PHP version.


Previous Comments:
------------------------------------------------------------------------

[2008-11-04 13:39:29] rosenfield dot albert at gmail dot com

Description:
------------
When execution is redirected with virtual(), before the Apache
sub-request is carried out, PHP prints headers and document contents.

The document contents are never a practical problem, because you never
have any - you're in the act of redirecting the request.

The headers however ARE a problem.  PHP generates some headers itself,
and these are then sent to the browser.

Whoops, there we go - now the new/real destination of the request is
unable to, for example, set it's own Content-Type header.  Or anything
else, because PHP has already printed something completely unrelated to
the contents the actual document is going to contain.

It could seem that the idea was to implement something akin to
<!--#include--> with a "virtual" keyword on it (often used in IIS for
ASP), but currently php's virtual() does not work like that.  Nobody
uses it for this purpose, rather developers use include() and require()
(often with __FILE__ or similar to hit a relative directory) because
these do not flush headers.

Where virtual() is really useful is in it's ability to perform Apache
sub-requests.  With this, and a simple Apache RewriteRule, any request
can be re-routed to a PHP script (effectively a filter), and then routed
back to the original destination after processing with virtual().

(This is an extremely convenient way to implement modular functionality
in web applications, for example a security filter written in PHP.)

As is currently, a significant number of hacks are required to work
around the fact that virtual() prints headers before redirection.  I
personally have about a hundred lines of code that does nothing but try
and predict which Content-Type the destination generates and try to
coerce PHP into printing that instead, when it would have been much more
practical if PHP just had discarded it's buffers in the first place.

Hereby a request to remove this automation.

With regards to backwards compatibility, I haven't been able to find
anyone via Google that used virtual() in a different fashion than above.
 Just in case someone really does, though, there should be a way for
them to continue to have headers flushed.

With the low-to-non-existent amount of scripts depending on this
flushing, I suggest that it is enough to modify the documentation.  For
example, it could read "if you want PHP's auto-generated headers to be
printed before the sub-request is carried out, execute flush()".


Reproduce code:
---------------
Doing virtual(whatever) reproduces the problem.

Here's a piece of code from a filter I'm using, which is perhaps more
explanatory.

if ($filter_mode) {
        // Pass request on via Apache to intended destination script or static
file.
        // Nesting via virtual() is broken, PHP flush()es and sends a bunch of
HTTP headers.
        // Crappy.
        if ($info->content_type == "application/x-httpd-php") {
                // Try to work around broken virtual() by using include() if 
target
happens to
                // be PHP script.
                chdir(dirname($info->filename));
                require($info->filename);
                die();
        } else if ($info->content_type == "text/x-perl") {
                // Dynamic content other than PHP must be fed through 
virtual(), so
we have
                // no way of working around the broken behaviour of header 
flushing. 
Sadly,
                // we'll both have to guess a content type and cross our 
fingers that
the
                // target script does not need to modify headers...
                header("Content-Type: text/html");
                // For some reason, contrary to documentation, virtual() 
requires an
URI
                // including query parameters, and not a filename, here.
                virtual($fulluri);
                die();
        } else if ($info->content_type == "httpd/unix-directory") {
                // See comments above and below.
                if ($block_dir_listing) {
                        fail_denied(
                                "Listing directory contents is not allowed on 
this server.\n" .
                                "Please browse the web pages to find what you 
need.\n"
                        );
                } else {
                        // Switch from httpd/unix-directory (see code below 
if/else branch)
to
                        // text/html content type. Apache generates the 
directory html 
                        // automatically.
                        header("Content-Type: text/html");
                        virtual($uri);
                        die();
                }
        }
        // Again, since PHP insists on flushing headers when virtual() is
invoked,
        // we have to apply the correct Content-Type.  For static files this
can
        // be deduced by looking at the filename, which is done here via
lookup_uri.
        // For other types of files, you will need to manually change the
script in
        // question and/or modify httpd.conf and modify the if/else block
above.
        header("Content-Type: ".$info->content_type);
        virtual($info->uri);
}


Expected result:
----------------
virtual() does not cause anything to print to the browser.


Actual result:
--------------
virtual() causes auto-generated headers to dump to the browser.


------------------------------------------------------------------------


-- 
Edit this bug report at http://bugs.php.net/?id=46479&edit=1

Reply via email to