Bug #8065 Updated: Form POST results in HTTP 500 - Internal server error
| From: | sniper@php.net | Date: | Fri, 15 Jun 2001 16:21:14 +0000 |
| Subject: | Bug #8065 Updated: Form POST results in HTTP 500 - Internal server error | ||
| Groups: | php.dev | ||
| Request: | Send a blank email to php-dev+get-56991@lists.php.net to get a copy of this message | ||
ID: 8065
Updated by: sniper
Reported By: daniel@pdq.net
Old-Status: Open
Status: Feedback
Bug Type: IIS related
Operating system:
PHP Version: 4.0.3pl1
Assigned To:
Comments:
Does this happen with PHP 4.0.5?
Previous Comments:
---------------------------------------------------------------------------
[2000-11-30 21:06:18] daniel@pdq.net
Any form post will fail. Two simple scripts that fail:
hello.php:
<form method="post" action="world.php">
<input type="submit">
</form>
<form method="get" action="world.php">
<input type="submit>
</form>
world.php:
hello world!
Possible solution from the Microsoft Knowledge Base:
PRB: CGI Applications Hang Under IIS 4.0 With POST
--------------------------------------------------------------------------------
The information in this article applies to:
Microsoft Internet Information Server version 4.0
--------------------------------------------------------------------------------
SYMPTOMS
Common gateway interface (CGI) applications that worked correctly under Microsoft Internet
Information Server (IIS) 3.0 with the HTTP POST method appear to hang under IIS 4.0. Using CGI with
the HTTP GET method still works correctly.
CAUSE
A typical scenario is that you upgrade your Microsoft Internet Information Server 3.0 to 4.0 and
suddenly all or some of your CGI applications appear to hang when called with a POST method.
The most likely reason for this is that the CGI in question was not written correctly. Under certain
conditions, an incorrectly written CGI can work properly with IIS 3.0 and earlier, but will appear
to break with IIS 4.0. The reason for this is that IIS 3.0 and earlier was more tolerant of
incorrectly written CGI applications. Browsers like Internet Explorer and Netscape Navigator will
append a Carriage Return + Line Feed (CRLF) pair to the end of any posted data. IIS 3.0 and earlier
will pass this extra CRLF pair to the CGI application, so that CGIs written depend on this
additional CRLF (which is against CGI and HTTP specifications) to work with IIS 3.0 and earlier.
However, any CGI application running under IIS 4.0 reading from standard input and waiting for a
CRLF character to indicate when the Posted data is complete will hang until a timeout occurs (or the
user aborts the session). This is because IIS 4.0 will no longer pass on the additional CRLF pair to
the CGI application.
The following CGI code sample is typical of this problem:
int main(int argc, char* argv[])
{
char szBuf[1024];
gets(szBuf);
// Do something with szBuf...
return 0;
}
The prior code hangs on the gets() call.
RESOLUTION
The correct solution is to rewrite the CGI application so it will adhere to the CGI and HTTP
specifications. Typically, there are two issues to deal with:
Reading from standard input only the amount of data specified by CONTENT_LENGTH variable.
Ensuring the standard input is read in binary mode and not text mode.
The CONTENT_LENGTH variable will be defined for all posted data. A correctly written CGI application
will check for this variable and determine how much data is being posted by the client and will only
read that many bytes from the standard input.
Also, the CGI application must be aware of the fact that by default the standard input will have
it's mode set to text stream. This means that if the posted data contains any instance of CRLF,
it is automatically converted to line feed (LF) only. This will alter the actual length of the
posted data. Two characters (CRLF) will be converted to a single character (LF). Therefore, the CGI
must set the mode on standard input to binary before attempting to read from it.
The following CGI code sample is a correct CGI application:
int main(int argc, char* argv[])
{
char* pCL = getenv("CONTENT_LENGTH");
if(pCL != NULL)
{
int nCL = atoi(pCL);
if(nCL > 0)
{
// WARNING: Error checking removed for clarity...
printf("Content-Type: text/htmlrnrn");
_setmode( _fileno( stdin ), _O_BINARY );
char* szBuf = new char[nCL + 1];
fread(szBuf + nRead, sizeof(char), nCL-nRead, stdin);
szBuf[nCL] = '