php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #16458 header() does not replace headers but always produces duplicates
Submitted: 2002-04-05 13:29 UTC Modified: 2002-06-18 06:17 UTC
Votes:4
Avg. Score:4.2 ± 0.8
Reproduced:4 of 4 (100.0%)
Same Version:1 (25.0%)
Same OS:3 (75.0%)
From: ernest at vogelsinger dot at Assigned:
Status: Closed Package: HTTP related
PHP Version: 4.1.1 OS: Win32 (XP)
Private report: No CVE-ID: None
 [2002-04-05 13:29 UTC] ernest at vogelsinger dot at
From the docs:
The optional "replace" parameter indicates whether the header should replace a previous similar header, or add a second header of the same type. By default it will replace, but if you pass in FALSE as the second argument you can force multiple headers of the same type.

At least with PHP 4.1.1/Win32(XP), this is NOT true - headers are always added up.

Using this little test:

<?php
header('X-Test-Header: Version 1');
header('X-Test-Header: Version 2');
?>

this output is created:

-------------------------------------
php headers.php
X-Powered-By: PHP/4.1.1
X-Test-Header: Version 1
X-Test-Header: Version 2
Content-type: text/html

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

According to the docs, only "Version 2" of the header should be sent. The results are identical if you do not provide the "replace" parameter, or if you set it to true or false.

This is a very annoying bug, and for my application I'd rate it "critical".

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2002-04-05 13:37 UTC] sander@php.net
Reproduced with 4.1.2, but it works fine for me with 4.3.0-dev.
You might want to try 4.2.0RC2 from www.php.net/~derick .

Anyway, it should be easy to code around this 'bug'.
 [2002-04-05 13:50 UTC] ernest at vogelsinger dot at
If this bug doesn't exist with the Linux/Apache module it is ok for me - if it is this doesn't "work for me" at all... Reason: my application framework uses output buffering so headers don't get sent until ob_end_flush() is called. Especially any caching headers are /modified/ depending on results of the application computations.

So it is not quite "easy" to "code around this 'bug'" - the caching headers are pre-set as soon as a session is established, and are not modifyable afterwards. In fact this 'bug' disables me to sent pages being cacheable, increasing server load and network traffic. And, with NetScape 4.x clients, pages resulting from posted forms cannot be resized (NS 4.x wants to resend the POST data to redraw the non-cacheable data).

Any idea when 4.2.0 will be out as production version?
On our production servers I cannot use an RC or -dev version, I need the stable build, so I have 4.1.2/RedHat Linux running there (cannot crosscheck the problem on the server just now).
 [2002-04-05 14:13 UTC] ernest at vogelsinger dot at
Just checked the 4.2.0-RC2 and found the identical behaviour from the command line (with PHP.EXE, no headers are displayed, so I used PHP-CGI.exe).
 [2002-04-05 15:06 UTC] sander@php.net
OK, to be more verbose:
I experienced the same problem with the CGI version of PHP 4.1.2 on Linux, but the problem didn't show up with the Apache-module of 4.3.0-dev.

I've just recompiled 4.2.0RC2 as CGI, and the bug reappeared.
So it's a CGI only bug. Reopened (and reclassifed).

Anyway, PHP 4.2.0 is scheduled for release at the 22th of April.
 [2002-04-05 15:08 UTC] sander@php.net
Note: the replace parameter seems to be completely ignored; it replaces the headers as an Apache module anyway, and it refuses to replace them as CGI.
 [2002-04-05 15:23 UTC] ernest at vogelsinger dot at
Thanks for the follow-up, and thanks for reopening... Sorry for the incorrect classification.
 [2002-05-14 16:33 UTC] msisolak at yahoo dot com
Suggested fix submitted to dev list:

Bug #16458 reports that the header() command does not correctly use the replace parameter (i.e., a header of the same name should be replaced if this parameter is true).  The problem is that the standard sapi_add_header_ex function assumes that the sapi being used with deal with any header replacements.  For Apache that works fine as the Apache sapi correctly used the replace parameter.  The IIS sapi, however, defaults to the standard funtionality in sapi_add_header_ex (as does the CGI).  The default handler just calls zend_llist_add_element to add the header to the header list thus appending even if replace was requested.

Attached is a suggested patch that first removes the header from the list if it already exists if we are in replace mode.  This works for the Win32 IIS and CGI builds, but I don't have a way to test any possible interaction this might have with the other sapi modules (or under GCC).

--- sapi.c	Tue May 14 16:11:31 2002
+++ sapi.c.new	Tue May 14 16:29:23 2002
@@ -385,6 +385,11 @@
 	return code;
 }
 
+static int sapi_find_matching_header(void *element1, void *element2)
+{
+	return strnicmp(((sapi_header_struct*)element1)->header, (char*)element2, strlen((char*)element2)) == 0;
+}
+
 /* This function expects a *duplicated* string, that was previously emalloc()'d.
  * Pointers sent to this functions will be automatically freed by the framework.
  */
@@ -551,6 +556,19 @@
 		zend_llist_clean(&SG(sapi_headers).headers);
 	}
 	if (retval & SAPI_HEADER_ADD) {
+		/* in replace mode first remove the header if it already exists in the headers llist */
+		if (replace) {
+			colon_offset = strchr(header_line, ':');
+			if (colon_offset) {
+				char sav;
+				colon_offset++;
+				sav = *colon_offset;
+				*colon_offset = 0;
+				zend_llist_del_element(&SG(sapi_headers).headers, header_line, (int(*)(void*, void*))sapi_find_matching_header);
+				*colon_offset = sav;
+			}
+		}
+
 		zend_llist_add_element(&SG(sapi_headers).headers, (void *) &sapi_header);
 	}
 	if (free_header) {
 [2002-06-18 06:17 UTC] sander@php.net
I've commited the patch to CVS, thanks for your help.
 [2002-10-19 15:58 UTC] systemshock87 at yahoo dot com
<?php
$user = crypt($usuario);
$password = md5($clave);

if (($usuario == "OSN") && ($clave == "misvr"))
{
header ("Location: http://24.232.112.10/<b>crypt(guestprivado3.php)</b>?Usuario=$userClave=$password");
}
else
{
header ("Location: http://24.232.112.10/guestprivado.php?Mensaje=osndiceqtevaairmal");
exit;
}
?>

When i load this in my page it appears an error:
Warning: Cannot add header information - headers already sent by (output started at c:/program files/apache group/apache/htdocs/guestprivado2.php:11) in c:/program files/apache group/apache/htdocs/guestprivado2.php on line 17

what's the problem?
 [2002-11-19 01:57 UTC] bahtiyar_s at yahoo dot com
yeah...
I have a same problem as systemshock87!!!!!!!!

What happening?
 [2002-11-20 21:37 UTC] walkibe at msn dot com
found the solution here :

http://www.faqts.com/knowledge_base/view.phtml/aid/19413/fid/59

the trick is NOT TO HAVE ANY SPACE in between the <?php ?> sets, before the header() command. cheers! =)
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Sun Sep 27 17:01:24 2020 UTC