@@ -1678,16 +1678,38 @@ static int php_cli_server_client_read_request_on_fragment(php_http_parser *parse
1678
1678
1679
1679
static void php_cli_server_client_save_header (php_cli_server_client * client )
1680
1680
{
1681
+ zval * entry ;
1681
1682
/* Wrap header value in a zval to add is to the HashTable which acts as an array */
1682
1683
zval tmp ;
1683
- ZVAL_STR (& tmp , client -> current_header_value );
1684
1684
/* strip off the colon */
1685
1685
zend_string * lc_header_name = zend_string_tolower_ex (client -> current_header_name , /* persistent */ true);
1686
1686
GC_MAKE_PERSISTENT_LOCAL (lc_header_name );
1687
1687
1688
- /* Add the wrapped zend_string to the HashTable */
1689
- zend_hash_add (& client -> request .headers , lc_header_name , & tmp );
1690
- zend_hash_add (& client -> request .headers_original_case , client -> current_header_name , & tmp );
1688
+ /**
1689
+ * **Forwarded** HTTP family headers can have 1 or more values separated by a comma while still
1690
+ * possibly be set separately by the client.
1691
+ **/
1692
+ if (!strstr (ZSTR_VAL (lc_header_name ), "forwarded" ) ||
1693
+ (entry = zend_hash_find (& client -> request .headers , lc_header_name )) == NULL ) {
1694
+ ZVAL_STR (& tmp , client -> current_header_value );
1695
+
1696
+ /* Add the wrapped zend_string to the HashTable */
1697
+ zend_hash_add (& client -> request .headers , lc_header_name , & tmp );
1698
+ zend_hash_add (& client -> request .headers_original_case , client -> current_header_name , & tmp );
1699
+ } else {
1700
+ zend_string * curval = Z_STR_P (entry );
1701
+ zend_string * newval = zend_string_alloc (ZSTR_LEN (curval ) + ZSTR_LEN (client -> current_header_value ) + 2 , /* persistent */ true);
1702
+
1703
+ memcpy (ZSTR_VAL (newval ), ZSTR_VAL (curval ), ZSTR_LEN (curval ));
1704
+ memcpy (ZSTR_VAL (newval ) + ZSTR_LEN (curval ), "," , 1 );
1705
+ memcpy (ZSTR_VAL (newval ) + ZSTR_LEN (curval ) + 1 , ZSTR_VAL (client -> current_header_value ), ZSTR_LEN (client -> current_header_value ) + 1 );
1706
+
1707
+ ZVAL_STR (& tmp , newval );
1708
+
1709
+ /* Update the wrapped zend_string to the HashTable */
1710
+ zend_hash_update (& client -> request .headers , lc_header_name , & tmp );
1711
+ zend_hash_update (& client -> request .headers_original_case , client -> current_header_name , & tmp );
1712
+ }
1691
1713
1692
1714
zend_string_release_ex (lc_header_name , /* persistent */ true);
1693
1715
zend_string_release_ex (client -> current_header_name , /* persistent */ true);
0 commit comments