1999-07-16 13:13:16 +00:00
/*
1999-05-06 21:58:49 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2009-03-10 23:40:06 +00:00
| PHP Version 6 |
1999-05-06 21:58:49 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2008-12-31 11:12:40 +00:00
| Copyright ( c ) 1997 - 2009 The PHP Group |
1999-05-06 21:58:49 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2006-01-01 13:10:10 +00:00
| This source file is subject to version 3.01 of the PHP license , |
1999-07-16 13:13:16 +00:00
| that is bundled with this package in the file LICENSE , and is |
2003-06-10 20:04:29 +00:00
| available through the world - wide - web at the following url : |
2006-01-01 13:10:10 +00:00
| http : //www.php.net/license/3_01.txt |
1999-07-16 13:13:16 +00:00
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world - wide - web , please send a note to |
| license @ php . net so we can mail you a copy immediately . |
1999-05-06 21:58:49 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2000-02-10 20:13:08 +00:00
| Original design : Shane Caraveo < shane @ caraveo . com > |
1999-05-06 21:58:49 +00:00
| Authors : Andi Gutmans < andi @ zend . com > |
| Zeev Suraski < zeev @ zend . com > |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
2001-11-24 23:38:08 +00:00
/* $Id$ */
1999-05-29 16:20:55 +00:00
# include <ctype.h>
2000-02-10 17:26:57 +00:00
# include <sys/stat.h>
1999-05-06 21:58:49 +00:00
1999-09-05 19:04:40 +00:00
# include "php.h"
1999-04-25 19:36:57 +00:00
# include "SAPI.h"
2006-05-10 21:25:01 +00:00
# include "php_variables.h"
2003-02-10 19:04:44 +00:00
# include "php_ini.h"
2001-10-20 22:01:56 +00:00
# include "ext/standard/php_string.h"
# include "ext/standard/pageinfo.h"
2003-02-10 19:04:44 +00:00
# if HAVE_ZLIB
2002-07-28 14:08:08 +00:00
# include "ext/zlib/php_zlib.h"
# endif
1999-04-26 14:00:49 +00:00
# ifdef ZTS
1999-04-25 19:36:57 +00:00
# include "TSRM.h"
1999-04-26 14:00:49 +00:00
# endif
2004-08-10 17:40:00 +00:00
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
# endif
1999-04-25 19:36:57 +00:00
1999-05-25 22:28:24 +00:00
# include "rfc1867.h"
2000-02-11 15:59:30 +00:00
# ifdef PHP_WIN32
1999-05-05 18:25:20 +00:00
# define STRCASECMP stricmp
# else
# define STRCASECMP strcasecmp
# endif
2000-07-05 08:57:37 +00:00
# include "php_content_types.h"
1999-04-25 19:36:57 +00:00
# ifdef ZTS
1999-04-26 14:00:49 +00:00
SAPI_API int sapi_globals_id ;
1999-04-26 17:26:37 +00:00
# else
sapi_globals_struct sapi_globals ;
1999-04-25 19:36:57 +00:00
# endif
2001-07-27 10:16:41 +00:00
static void sapi_globals_ctor ( sapi_globals_struct * sapi_globals TSRMLS_DC )
2000-03-05 21:37:47 +00:00
{
2001-07-28 11:36:37 +00:00
memset ( sapi_globals , 0 , sizeof ( * sapi_globals ) ) ;
2005-02-21 20:57:18 +00:00
zend_hash_init_ex ( & sapi_globals - > known_post_content_types , 5 , NULL , NULL , 1 , 0 ) ;
2005-03-05 16:41:13 +00:00
php_setup_sapi_content_types ( TSRMLS_C ) ;
2005-02-21 15:14:02 +00:00
}
static void sapi_globals_dtor ( sapi_globals_struct * sapi_globals TSRMLS_DC )
{
zend_hash_destroy ( & sapi_globals - > known_post_content_types ) ;
2000-03-05 21:37:47 +00:00
}
1999-05-06 21:58:49 +00:00
/* True globals (no need for thread safety) */
2001-01-02 22:49:31 +00:00
SAPI_API sapi_module_struct sapi_module ;
1999-04-25 19:36:57 +00:00
1999-05-02 18:07:41 +00:00
SAPI_API void sapi_startup ( sapi_module_struct * sf )
1999-04-25 19:36:57 +00:00
{
2006-02-13 10:23:59 +00:00
sf - > ini_entries = NULL ;
1999-05-02 18:07:41 +00:00
sapi_module = * sf ;
1999-09-16 23:18:15 +00:00
1999-04-25 19:36:57 +00:00
# ifdef ZTS
2005-02-21 15:14:02 +00:00
ts_allocate_id ( & sapi_globals_id , sizeof ( sapi_globals_struct ) , ( ts_allocate_ctor ) sapi_globals_ctor , ( ts_allocate_dtor ) sapi_globals_dtor ) ;
2000-03-16 21:23:24 +00:00
# else
2005-02-21 20:57:18 +00:00
sapi_globals_ctor ( & sapi_globals ) ;
1999-04-25 19:36:57 +00:00
# endif
2000-03-16 21:23:24 +00:00
2000-04-02 19:04:59 +00:00
virtual_cwd_startup ( ) ; /* Could use shutdown to free the main cwd but it would just slow it down for CGI */
2001-04-27 16:41:53 +00:00
# ifdef PHP_WIN32
tsrm_win32_startup ( ) ;
# endif
2000-01-05 19:25:19 +00:00
reentrancy_startup ( ) ;
1999-09-03 17:46:39 +00:00
}
1999-05-05 18:25:20 +00:00
1999-12-05 16:25:32 +00:00
SAPI_API void sapi_shutdown ( void )
1999-05-28 22:41:48 +00:00
{
2005-02-21 15:14:02 +00:00
# ifdef ZTS
2005-02-22 05:07:37 +00:00
ts_free_id ( sapi_globals_id ) ;
2005-02-21 15:14:02 +00:00
# else
2005-02-21 20:57:18 +00:00
sapi_globals_dtor ( & sapi_globals ) ;
2005-02-21 15:14:02 +00:00
# endif
2000-01-05 19:25:19 +00:00
reentrancy_shutdown ( ) ;
2004-10-05 00:42:25 +00:00
2000-04-02 20:26:06 +00:00
virtual_cwd_shutdown ( ) ;
2001-04-27 16:41:53 +00:00
# ifdef PHP_WIN32
tsrm_win32_shutdown ( ) ;
# endif
1999-05-28 22:41:48 +00:00
}
1999-12-10 12:38:20 +00:00
SAPI_API void sapi_free_header ( sapi_header_struct * sapi_header )
1999-05-05 18:25:20 +00:00
{
efree ( sapi_header - > header ) ;
}
2001-07-28 11:36:37 +00:00
SAPI_API void sapi_handle_post ( void * arg TSRMLS_DC )
2000-02-17 20:23:59 +00:00
{
2001-03-18 08:00:10 +00:00
if ( SG ( request_info ) . post_entry & & SG ( request_info ) . content_type_dup ) {
2009-05-23 18:03:27 +00:00
/*
* We need to re - populate post_data from the stored raw POST data in case we had
* any before , so that the handler can get to it .
*/
if ( SG ( request_info ) . post_data = = NULL & & SG ( request_info ) . raw_post_data ! = NULL ) {
SG ( request_info ) . post_data = estrndup ( SG ( request_info ) . raw_post_data , SG ( request_info ) . raw_post_data_length ) ;
}
2001-07-28 11:36:37 +00:00
SG ( request_info ) . post_entry - > post_handler ( SG ( request_info ) . content_type_dup , arg TSRMLS_CC ) ;
2000-09-09 15:02:15 +00:00
if ( SG ( request_info ) . post_data ) {
efree ( SG ( request_info ) . post_data ) ;
SG ( request_info ) . post_data = NULL ;
}
2009-05-23 18:03:27 +00:00
#if 0 /* UTODO see if this works */
2000-02-17 20:23:59 +00:00
efree ( SG ( request_info ) . content_type_dup ) ;
SG ( request_info ) . content_type_dup = NULL ;
2009-05-23 18:03:27 +00:00
# endif
2000-02-17 20:23:59 +00:00
}
}
2001-07-28 11:36:37 +00:00
static void sapi_read_post_data ( TSRMLS_D )
1999-05-25 21:14:54 +00:00
{
2000-02-17 20:23:59 +00:00
sapi_post_entry * post_entry ;
1999-05-25 21:14:54 +00:00
uint content_type_length = strlen ( SG ( request_info ) . content_type ) ;
char * content_type = estrndup ( SG ( request_info ) . content_type , content_type_length ) ;
1999-05-25 22:28:24 +00:00
char * p ;
char oldchar = 0 ;
2002-10-21 16:41:06 +00:00
void ( * post_reader_func ) ( TSRMLS_D ) = NULL ;
1999-09-16 23:18:15 +00:00
1999-05-25 22:28:24 +00:00
/* dedicated implementation for increased performance:
* - Make the content type lowercase
* - Trim descriptive data , stay with the content - type only
*/
for ( p = content_type ; p < content_type + content_type_length ; p + + ) {
switch ( * p ) {
case ' ; ' :
case ' , ' :
case ' ' :
content_type_length = p - content_type ;
oldchar = * p ;
* p = 0 ;
break ;
default :
* p = tolower ( * p ) ;
break ;
}
}
1999-05-25 21:14:54 +00:00
2002-11-08 08:41:52 +00:00
/* now try to find an appropriate POST content handler */
2009-05-23 18:19:11 +00:00
if ( zend_hash_find ( & SG ( known_post_content_types ) , content_type , content_type_length + 1 , ( void * * ) & post_entry ) = = SUCCESS ) {
2002-11-08 08:41:52 +00:00
/* found one, register it for use */
2000-02-17 20:23:59 +00:00
SG ( request_info ) . post_entry = post_entry ;
post_reader_func = post_entry - > post_reader ;
1999-09-16 23:18:15 +00:00
} else {
2002-11-08 08:41:52 +00:00
/* fallback */
SG ( request_info ) . post_entry = NULL ;
1999-09-16 23:18:15 +00:00
if ( ! sapi_module . default_post_reader ) {
2002-11-08 08:41:52 +00:00
/* no default reader ? */
2003-11-22 21:10:47 +00:00
SG ( request_info ) . content_type_dup = NULL ;
2000-09-09 15:02:15 +00:00
sapi_module . sapi_error ( E_WARNING , " Unsupported content type: '%s' " , content_type ) ;
1999-09-16 23:18:15 +00:00
return ;
}
1999-05-25 21:14:54 +00:00
}
1999-05-25 22:28:24 +00:00
if ( oldchar ) {
* ( p - 1 ) = oldchar ;
}
2001-09-03 02:31:56 +00:00
2000-02-17 20:23:59 +00:00
SG ( request_info ) . content_type_dup = content_type ;
2001-09-03 02:31:56 +00:00
2009-05-23 18:19:11 +00:00
if ( post_reader_func ) {
2001-09-03 02:31:56 +00:00
post_reader_func ( TSRMLS_C ) ;
2002-10-21 16:41:06 +00:00
}
2001-09-03 02:31:56 +00:00
2009-05-23 18:19:11 +00:00
if ( sapi_module . default_post_reader ) {
2002-10-21 16:41:06 +00:00
sapi_module . default_post_reader ( TSRMLS_C ) ;
2001-07-17 16:46:07 +00:00
}
1999-05-25 21:14:54 +00:00
}
2001-08-15 18:01:48 +00:00
SAPI_API SAPI_POST_READER_FUNC ( sapi_read_standard_form_data )
1999-05-09 18:40:59 +00:00
{
2000-04-01 01:11:39 +00:00
int read_bytes ;
1999-05-09 18:40:59 +00:00
int allocated_bytes = SAPI_POST_BLOCK_SIZE + 1 ;
2000-09-09 15:02:15 +00:00
if ( SG ( request_info ) . content_length > SG ( post_max_size ) ) {
2009-05-23 18:19:11 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " POST Content-Length of %ld bytes exceeds the limit of %ld bytes " , SG ( request_info ) . content_length , SG ( post_max_size ) ) ;
2000-09-09 15:02:15 +00:00
return ;
}
1999-05-09 18:40:59 +00:00
SG ( request_info ) . post_data = emalloc ( allocated_bytes ) ;
for ( ; ; ) {
2001-07-28 11:36:37 +00:00
read_bytes = sapi_module . read_post ( SG ( request_info ) . post_data + SG ( read_post_bytes ) , SAPI_POST_BLOCK_SIZE TSRMLS_CC ) ;
1999-05-09 18:40:59 +00:00
if ( read_bytes < = 0 ) {
break ;
}
2000-04-01 01:11:39 +00:00
SG ( read_post_bytes ) + = read_bytes ;
2000-09-09 15:02:15 +00:00
if ( SG ( read_post_bytes ) > SG ( post_max_size ) ) {
2003-08-28 17:07:40 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Actual POST length does not match Content-Length, and exceeds %ld bytes " , SG ( post_max_size ) ) ;
2004-05-25 22:12:40 +00:00
break ;
2000-09-09 15:02:15 +00:00
}
1999-05-09 18:40:59 +00:00
if ( read_bytes < SAPI_POST_BLOCK_SIZE ) {
break ;
}
2000-04-01 01:11:39 +00:00
if ( SG ( read_post_bytes ) + SAPI_POST_BLOCK_SIZE > = allocated_bytes ) {
allocated_bytes = SG ( read_post_bytes ) + SAPI_POST_BLOCK_SIZE + 1 ;
1999-05-09 18:40:59 +00:00
SG ( request_info ) . post_data = erealloc ( SG ( request_info ) . post_data , allocated_bytes ) ;
}
}
2009-05-23 18:19:11 +00:00
SG ( request_info ) . post_data [ SG ( read_post_bytes ) ] = 0 ; /* terminating NULL */
2000-04-01 01:11:39 +00:00
SG ( request_info ) . post_data_length = SG ( read_post_bytes ) ;
1999-05-09 18:40:59 +00:00
}
2005-08-11 23:36:07 +00:00
/* {{{ sapi_update_default_charset */
SAPI_API void sapi_update_default_charset ( TSRMLS_D )
{
2009-03-26 20:02:53 +00:00
const char * canonical_name = NULL ;
UErrorCode status = U_ZERO_ERROR ;
canonical_name = ucnv_getName ( ZEND_U_CONVERTER ( UG ( output_encoding_conv ) ) , & status ) ;
/*
* UTODO handle NULL return which signifies that MIME standard has no
* name for this converter
*/
SG ( default_charset ) = ( char * ) ucnv_getStandardName ( canonical_name , " MIME " , & status ) ;
2005-08-11 23:36:07 +00:00
}
/* }}} */
2001-07-28 11:36:37 +00:00
SAPI_API char * sapi_get_default_content_type ( TSRMLS_D )
2000-02-25 21:27:03 +00:00
{
char * mimetype , * charset , * content_type ;
mimetype = SG ( default_mimetype ) ? SG ( default_mimetype ) : SAPI_DEFAULT_MIMETYPE ;
2005-08-11 23:36:07 +00:00
/*
* Apache SAPI may invoke this function directly , before php_request_startup ( ) is
* called , so we need to update the default charset explicitly .
*/
sapi_update_default_charset ( TSRMLS_C ) ;
2000-02-25 21:27:03 +00:00
charset = SG ( default_charset ) ? SG ( default_charset ) : SAPI_DEFAULT_CHARSET ;
2000-02-26 14:29:27 +00:00
if ( strncasecmp ( mimetype , " text/ " , 5 ) = = 0 & & * charset ) {
2002-08-03 14:09:56 +00:00
int len = strlen ( mimetype ) + sizeof ( " ; charset= " ) + strlen ( charset ) ; /* sizeof() includes \0 */
2000-02-25 21:27:03 +00:00
content_type = emalloc ( len ) ;
2000-02-26 05:03:41 +00:00
snprintf ( content_type , len , " %s; charset=%s " , mimetype , charset ) ;
2000-02-25 21:27:03 +00:00
} else {
content_type = estrdup ( mimetype ) ;
}
return content_type ;
}
2001-07-28 11:36:37 +00:00
SAPI_API void sapi_get_default_content_type_header ( sapi_header_struct * default_header TSRMLS_DC )
2000-02-26 05:03:41 +00:00
{
2001-07-28 11:36:37 +00:00
char * default_content_type = sapi_get_default_content_type ( TSRMLS_C ) ;
2000-02-26 05:03:41 +00:00
int default_content_type_len = strlen ( default_content_type ) ;
default_header - > header_len = ( sizeof ( " Content-type: " ) - 1 ) + default_content_type_len ;
default_header - > header = emalloc ( default_header - > header_len + 1 ) ;
memcpy ( default_header - > header , " Content-type: " , sizeof ( " Content-type: " ) ) ;
memcpy ( default_header - > header + sizeof ( " Content-type: " ) - 1 , default_content_type , default_content_type_len ) ;
default_header - > header [ default_header - > header_len ] = 0 ;
2000-02-26 14:21:10 +00:00
efree ( default_content_type ) ;
2000-02-26 05:03:41 +00:00
}
2000-02-24 22:00:47 +00:00
/*
2000-02-25 21:27:03 +00:00
* Add charset on content - type header if the MIME type starts with
2000-02-26 14:29:27 +00:00
* " text/ " , the default_charset directive is not empty and
2000-02-25 21:27:03 +00:00
* there is not already a charset option in there .
*
* If " mimetype " is non - NULL , it should point to a pointer allocated
2009-05-23 18:19:11 +00:00
* with emalloc ( ) . If a charset is added , the string will be
* re - allocated and the new length is returned . If mimetype is
2000-02-25 21:27:03 +00:00
* unchanged , 0 is returned .
*
2000-02-24 22:00:47 +00:00
*/
2001-07-28 11:36:37 +00:00
SAPI_API size_t sapi_apply_default_charset ( char * * mimetype , size_t len TSRMLS_DC )
1999-05-05 18:25:20 +00:00
{
2000-02-25 21:27:03 +00:00
char * charset , * newtype ;
2000-10-20 19:10:27 +00:00
size_t newlen ;
2005-08-11 23:36:07 +00:00
2000-02-25 21:27:03 +00:00
charset = SG ( default_charset ) ? SG ( default_charset ) : SAPI_DEFAULT_CHARSET ;
2002-08-05 18:32:05 +00:00
if ( * mimetype ! = NULL ) {
if ( * charset & & strncmp ( * mimetype , " text/ " , 5 ) = = 0 & & strstr ( * mimetype , " charset= " ) = = NULL ) {
newlen = len + ( sizeof ( " ;charset= " ) - 1 ) + strlen ( charset ) ;
newtype = emalloc ( newlen + 1 ) ;
2009-05-23 18:19:11 +00:00
PHP_STRLCPY ( newtype , * mimetype , newlen + 1 , len ) ;
2002-08-05 18:32:05 +00:00
strlcat ( newtype , " ;charset= " , newlen + 1 ) ;
2002-09-08 01:06:29 +00:00
strlcat ( newtype , charset , newlen + 1 ) ;
2000-02-25 21:27:03 +00:00
efree ( * mimetype ) ;
2002-08-05 18:32:05 +00:00
* mimetype = newtype ;
return newlen ;
2000-02-25 21:27:03 +00:00
}
}
return 0 ;
}
2000-02-24 22:00:47 +00:00
2002-11-18 00:59:23 +00:00
SAPI_API void sapi_activate_headers_only ( TSRMLS_D )
{
2009-05-23 18:19:11 +00:00
if ( SG ( request_info ) . headers_read = = 1 ) {
2003-01-15 11:30:39 +00:00
return ;
2009-05-23 18:19:11 +00:00
}
2003-01-15 11:30:39 +00:00
SG ( request_info ) . headers_read = 1 ;
2009-05-23 18:19:11 +00:00
zend_llist_init ( & SG ( sapi_headers ) . headers , sizeof ( sapi_header_struct ) , ( void ( * ) ( void * ) ) sapi_free_header , 0 ) ;
2003-01-15 11:30:39 +00:00
SG ( sapi_headers ) . send_default_content_type = 1 ;
2009-05-23 18:19:11 +00:00
/* SG(sapi_headers).http_response_code = 200; */
2003-01-15 11:30:39 +00:00
SG ( sapi_headers ) . http_status_line = NULL ;
2007-12-03 16:04:47 +00:00
SG ( sapi_headers ) . mimetype = NULL ;
2004-11-28 13:32:29 +00:00
SG ( read_post_bytes ) = 0 ;
SG ( request_info ) . post_data = NULL ;
SG ( request_info ) . raw_post_data = NULL ;
2003-01-15 11:30:39 +00:00
SG ( request_info ) . current_user = NULL ;
SG ( request_info ) . current_user_length = 0 ;
SG ( request_info ) . no_headers = 0 ;
2004-08-19 20:26:39 +00:00
SG ( request_info ) . post_entry = NULL ;
2004-11-28 13:32:29 +00:00
SG ( global_request_time ) = 0 ;
2003-01-15 11:30:39 +00:00
/*
2009-05-23 18:19:11 +00:00
* It ' s possible to override this general case in the activate ( ) callback ,
2003-01-15 11:30:39 +00:00
* if necessary .
*/
if ( SG ( request_info ) . request_method & & ! strcmp ( SG ( request_info ) . request_method , " HEAD " ) ) {
SG ( request_info ) . headers_only = 1 ;
} else {
SG ( request_info ) . headers_only = 0 ;
}
if ( SG ( server_context ) ) {
SG ( request_info ) . cookie_data = sapi_module . read_cookies ( TSRMLS_C ) ;
if ( sapi_module . activate ) {
sapi_module . activate ( TSRMLS_C ) ;
}
}
2009-04-28 22:59:07 +00:00
if ( sapi_module . input_filter_init ) {
sapi_module . input_filter_init ( TSRMLS_C ) ;
}
2002-11-18 00:59:23 +00:00
}
2000-02-25 21:27:03 +00:00
/*
* Called from php_request_startup ( ) for every request .
*/
2002-11-18 00:59:23 +00:00
2001-07-28 11:36:37 +00:00
SAPI_API void sapi_activate ( TSRMLS_D )
2000-02-25 21:27:03 +00:00
{
1999-05-05 18:25:20 +00:00
zend_llist_init ( & SG ( sapi_headers ) . headers , sizeof ( sapi_header_struct ) , ( void ( * ) ( void * ) ) sapi_free_header , 0 ) ;
1999-05-09 08:48:05 +00:00
SG ( sapi_headers ) . send_default_content_type = 1 ;
2000-02-24 22:00:47 +00:00
2000-08-02 22:48:45 +00:00
/*
1999-05-05 18:25:20 +00:00
SG ( sapi_headers ) . http_response_code = 200 ;
2000-08-02 22:48:45 +00:00
*/
2000-08-02 22:53:55 +00:00
SG ( sapi_headers ) . http_status_line = NULL ;
2007-12-03 16:04:47 +00:00
SG ( sapi_headers ) . mimetype = NULL ;
1999-05-05 19:53:15 +00:00
SG ( headers_sent ) = 0 ;
1999-05-09 18:40:59 +00:00
SG ( read_post_bytes ) = 0 ;
1999-05-11 20:38:16 +00:00
SG ( request_info ) . post_data = NULL ;
2002-11-12 18:29:11 +00:00
SG ( request_info ) . raw_post_data = NULL ;
2000-02-10 20:13:08 +00:00
SG ( request_info ) . current_user = NULL ;
SG ( request_info ) . current_user_length = 0 ;
2000-11-13 18:54:37 +00:00
SG ( request_info ) . no_headers = 0 ;
2004-11-28 13:32:29 +00:00
SG ( request_info ) . post_entry = NULL ;
2005-03-14 19:25:39 +00:00
SG ( request_info ) . proto_num = 1000 ; /* Default to HTTP 1.0 */
2004-08-11 06:18:25 +00:00
SG ( global_request_time ) = 0 ;
1999-05-25 21:14:54 +00:00
2000-09-08 14:43:57 +00:00
/* It's possible to override this general case in the activate() callback, if
* necessary .
2000-08-02 22:48:45 +00:00
*/
1999-05-25 21:14:54 +00:00
if ( SG ( request_info ) . request_method & & ! strcmp ( SG ( request_info ) . request_method , " HEAD " ) ) {
SG ( request_info ) . headers_only = 1 ;
} else {
SG ( request_info ) . headers_only = 0 ;
}
2000-09-09 15:02:15 +00:00
SG ( rfc1867_uploaded_files ) = NULL ;
2009-05-23 18:03:27 +00:00
SG ( rfc1867_vars ) = NULL ;
2009-05-23 18:10:13 +00:00
SG ( rfc1867_files_vars ) = NULL ;
1999-05-25 21:14:54 +00:00
2002-10-21 16:41:06 +00:00
/* handle request mehtod */
1999-05-09 08:48:05 +00:00
if ( SG ( server_context ) ) {
2009-05-23 18:19:11 +00:00
if ( SG ( request_info ) . request_method ) {
if ( ! strcmp ( SG ( request_info ) . request_method , " POST " ) & &
( SG ( request_info ) . content_type )
) {
2002-10-21 16:41:06 +00:00
/* HTTP POST -> may contain form data to be read into variables
2009-05-23 18:19:11 +00:00
* depending on content type given */
2002-10-21 16:41:06 +00:00
sapi_read_post_data ( TSRMLS_C ) ;
} else {
2009-05-23 18:19:11 +00:00
/* Any other method with content payload will fill
* $ HTTP_RAW_POST_DATA if enabled by always_populate_raw_post_data
* it is up to the webserver to decide whether to allow a method or not */
2000-09-09 15:02:15 +00:00
SG ( request_info ) . content_type_dup = NULL ;
2009-05-23 18:19:11 +00:00
if ( sapi_module . default_post_reader ) {
2002-10-21 18:44:50 +00:00
sapi_module . default_post_reader ( TSRMLS_C ) ;
2001-10-23 20:48:30 +00:00
}
1999-05-28 22:41:48 +00:00
}
2000-02-18 01:52:11 +00:00
} else {
SG ( request_info ) . content_type_dup = NULL ;
1999-05-09 20:58:26 +00:00
}
2002-10-21 16:41:06 +00:00
/* Cookies */
2001-07-28 11:36:37 +00:00
SG ( request_info ) . cookie_data = sapi_module . read_cookies ( TSRMLS_C ) ;
2000-02-10 19:22:36 +00:00
if ( sapi_module . activate ) {
2001-07-28 11:36:37 +00:00
sapi_module . activate ( TSRMLS_C ) ;
2000-02-10 19:22:36 +00:00
}
2000-02-10 16:44:59 +00:00
}
2009-04-28 22:59:07 +00:00
if ( sapi_module . input_filter_init ) {
sapi_module . input_filter_init ( TSRMLS_C ) ;
}
1999-05-05 18:25:20 +00:00
}
2002-08-01 09:00:30 +00:00
static void sapi_send_headers_free ( TSRMLS_D )
{
if ( SG ( sapi_headers ) . http_status_line ) {
efree ( SG ( sapi_headers ) . http_status_line ) ;
SG ( sapi_headers ) . http_status_line = NULL ;
}
}
2009-05-23 18:19:11 +00:00
2001-07-28 11:36:37 +00:00
SAPI_API void sapi_deactivate ( TSRMLS_D )
1999-05-05 18:25:20 +00:00
{
zend_llist_destroy ( & SG ( sapi_headers ) . headers ) ;
1999-05-11 20:38:16 +00:00
if ( SG ( request_info ) . post_data ) {
1999-05-09 08:48:05 +00:00
efree ( SG ( request_info ) . post_data ) ;
2009-05-23 18:19:11 +00:00
} else if ( SG ( server_context ) ) {
if ( sapi_module . read_post ) {
2002-11-12 18:29:11 +00:00
/* make sure we've consumed all request input data */
2002-10-21 16:41:06 +00:00
char dummy [ SAPI_POST_BLOCK_SIZE ] ;
2002-11-21 10:29:11 +00:00
int read_bytes ;
while ( ( read_bytes = sapi_module . read_post ( dummy , sizeof ( dummy ) - 1 TSRMLS_CC ) ) > 0 ) {
SG ( read_post_bytes ) + = read_bytes ;
2002-10-21 16:41:06 +00:00
}
}
1999-05-05 21:29:26 +00:00
}
2002-11-12 18:29:11 +00:00
if ( SG ( request_info ) . raw_post_data ) {
efree ( SG ( request_info ) . raw_post_data ) ;
2009-05-23 18:19:11 +00:00
}
2000-02-15 23:31:10 +00:00
if ( SG ( request_info ) . auth_user ) {
efree ( SG ( request_info ) . auth_user ) ;
}
if ( SG ( request_info ) . auth_password ) {
efree ( SG ( request_info ) . auth_password ) ;
}
2005-04-04 15:06:36 +00:00
if ( SG ( request_info ) . auth_digest ) {
efree ( SG ( request_info ) . auth_digest ) ;
}
2000-02-17 20:23:59 +00:00
if ( SG ( request_info ) . content_type_dup ) {
efree ( SG ( request_info ) . content_type_dup ) ;
}
2000-02-10 20:13:08 +00:00
if ( SG ( request_info ) . current_user ) {
efree ( SG ( request_info ) . current_user ) ;
}
2000-02-10 16:44:59 +00:00
if ( sapi_module . deactivate ) {
2001-07-28 11:36:37 +00:00
sapi_module . deactivate ( TSRMLS_C ) ;
2000-02-10 16:44:59 +00:00
}
2000-09-08 21:56:47 +00:00
if ( SG ( rfc1867_uploaded_files ) ) {
2001-07-28 11:36:37 +00:00
destroy_uploaded_files_hash ( TSRMLS_C ) ;
2000-09-08 21:56:47 +00:00
}
2009-05-23 18:03:27 +00:00
if ( SG ( rfc1867_vars ) ) {
zend_hash_destroy ( SG ( rfc1867_vars ) ) ;
FREE_HASHTABLE ( SG ( rfc1867_vars ) ) ;
}
if ( SG ( rfc1867_files_vars ) ) {
zend_hash_destroy ( SG ( rfc1867_files_vars ) ) ;
FREE_HASHTABLE ( SG ( rfc1867_files_vars ) ) ;
}
2002-08-05 18:32:05 +00:00
if ( SG ( sapi_headers ) . mimetype ) {
efree ( SG ( sapi_headers ) . mimetype ) ;
SG ( sapi_headers ) . mimetype = NULL ;
}
2002-08-01 09:00:30 +00:00
sapi_send_headers_free ( TSRMLS_C ) ;
2003-01-15 11:30:39 +00:00
SG ( sapi_started ) = 0 ;
SG ( headers_sent ) = 0 ;
SG ( request_info ) . headers_read = 0 ;
2004-08-11 06:18:25 +00:00
SG ( global_request_time ) = 0 ;
1999-05-05 18:25:20 +00:00
}
2001-07-28 11:36:37 +00:00
SAPI_API void sapi_initialize_empty_request ( TSRMLS_D )
2000-02-17 20:23:59 +00:00
{
SG ( server_context ) = NULL ;
SG ( request_info ) . request_method = NULL ;
2005-07-12 16:53:30 +00:00
SG ( request_info ) . auth_digest = SG ( request_info ) . auth_user = SG ( request_info ) . auth_password = NULL ;
2000-02-17 20:23:59 +00:00
SG ( request_info ) . content_type_dup = NULL ;
}
1999-10-04 18:07:46 +00:00
static int sapi_extract_response_code ( const char * header_line )
{
int code = 200 ;
const char * ptr ;
for ( ptr = header_line ; * ptr ; ptr + + ) {
if ( * ptr = = ' ' & & * ( ptr + 1 ) ! = ' ' ) {
code = atoi ( ptr + 1 ) ;
break ;
}
}
2009-05-23 18:19:11 +00:00
1999-10-04 18:07:46 +00:00
return code ;
}
1999-05-05 18:25:20 +00:00
2002-07-03 10:47:16 +00:00
static void sapi_update_response_code ( int ncode TSRMLS_DC )
2002-07-03 10:42:31 +00:00
{
2003-06-03 10:06:45 +00:00
/* if the status code did not change, we do not want
2009-05-23 18:19:11 +00:00
* to change the status line , and no need to change the code */
2003-06-03 10:06:45 +00:00
if ( SG ( sapi_headers ) . http_response_code = = ncode ) {
return ;
}
2002-07-03 10:42:31 +00:00
if ( SG ( sapi_headers ) . http_status_line ) {
efree ( SG ( sapi_headers ) . http_status_line ) ;
SG ( sapi_headers ) . http_status_line = NULL ;
}
SG ( sapi_headers ) . http_response_code = ncode ;
}
2002-06-18 10:16:36 +00:00
static int sapi_find_matching_header ( void * element1 , void * element2 )
{
2008-11-13 10:33:08 +00:00
int len = strlen ( ( char * ) element2 ) ;
return strncasecmp ( ( ( sapi_header_struct * ) element1 ) - > header , ( char * ) element2 , len ) = = 0 & & ( ( sapi_header_struct * ) element1 ) - > header [ len ] = = ' : ' ;
2002-06-18 10:16:36 +00:00
}
2002-07-03 10:42:31 +00:00
SAPI_API int sapi_add_header_ex ( char * header_line , uint header_line_len , zend_bool duplicate , zend_bool replace TSRMLS_DC )
{
sapi_header_line ctr = { 0 } ;
int r ;
2009-05-23 18:19:11 +00:00
2002-07-03 10:42:31 +00:00
ctr . line = header_line ;
ctr . line_len = header_line_len ;
2009-05-23 18:19:11 +00:00
r = sapi_header_op ( replace ? SAPI_HEADER_REPLACE : SAPI_HEADER_ADD , & ctr TSRMLS_CC ) ;
2002-07-03 10:42:31 +00:00
2009-05-23 18:19:11 +00:00
if ( ! duplicate ) {
2002-07-03 10:42:31 +00:00
efree ( header_line ) ;
2009-05-23 18:19:11 +00:00
}
2002-07-03 10:42:31 +00:00
return r ;
}
SAPI_API int sapi_header_op ( sapi_header_op_enum op , void * arg TSRMLS_DC )
1999-05-05 18:25:20 +00:00
{
2002-06-18 15:04:58 +00:00
int retval ;
1999-05-05 18:25:20 +00:00
sapi_header_struct sapi_header ;
1999-05-11 18:36:35 +00:00
char * colon_offset ;
2001-10-20 22:01:56 +00:00
long myuid = 0L ;
2002-07-03 10:42:31 +00:00
char * header_line ;
uint header_line_len ;
int http_response_code ;
2009-05-23 18:19:11 +00:00
2000-11-13 18:54:37 +00:00
if ( SG ( headers_sent ) & & ! SG ( request_info ) . no_headers ) {
2006-06-03 11:19:44 +00:00
char * output_start_filename = php_output_get_start_filename ( TSRMLS_C ) ;
int output_start_lineno = php_output_get_start_lineno ( TSRMLS_C ) ;
2000-02-04 14:54:30 +00:00
if ( output_start_filename ) {
2009-05-23 18:19:11 +00:00
sapi_module . sapi_error ( E_WARNING , " Cannot modify header information - headers already sent by (output started at %s:%d) " , output_start_filename , output_start_lineno ) ;
2000-02-04 14:54:30 +00:00
} else {
2002-07-03 10:42:31 +00:00
sapi_module . sapi_error ( E_WARNING , " Cannot modify header information - headers already sent " ) ;
2000-04-28 13:03:13 +00:00
}
1999-05-06 21:58:49 +00:00
return FAILURE ;
}
2002-07-03 10:42:31 +00:00
switch ( op ) {
case SAPI_HEADER_SET_STATUS :
2007-04-16 09:43:53 +00:00
sapi_update_response_code ( ( int ) ( zend_intptr_t ) arg TSRMLS_CC ) ;
2002-07-03 10:42:31 +00:00
return SUCCESS ;
2008-11-13 10:33:08 +00:00
case SAPI_HEADER_ADD :
2002-07-03 10:42:31 +00:00
case SAPI_HEADER_REPLACE :
2008-11-13 10:33:08 +00:00
case SAPI_HEADER_DELETE : {
2002-07-03 10:42:31 +00:00
sapi_header_line * p = arg ;
2009-05-23 18:19:11 +00:00
2005-11-02 14:27:02 +00:00
if ( ! p - > line | | ! p - > line_len ) {
return FAILURE ;
}
2002-07-03 10:42:31 +00:00
header_line = p - > line ;
header_line_len = p - > line_len ;
http_response_code = p - > response_code ;
break ;
2009-05-23 18:19:11 +00:00
}
2008-11-13 10:33:08 +00:00
case SAPI_HEADER_DELETE_ALL :
if ( sapi_module . header_handler ) {
sapi_module . header_handler ( & sapi_header , op , & SG ( sapi_headers ) TSRMLS_CC ) ;
}
zend_llist_clean ( & SG ( sapi_headers ) . headers ) ;
return SUCCESS ;
2009-05-23 18:19:11 +00:00
2002-07-03 10:42:31 +00:00
default :
return FAILURE ;
2000-04-28 13:03:13 +00:00
}
2000-04-28 16:47:19 +00:00
2002-07-03 10:42:31 +00:00
header_line = estrndup ( header_line , header_line_len ) ;
2000-04-28 16:47:19 +00:00
/* cut of trailing spaces, linefeeds and carriage-returns */
2009-05-23 18:19:11 +00:00
while ( header_line_len & & isspace ( header_line [ header_line_len - 1 ] ) ) {
header_line [ - - header_line_len ] = ' \0 ' ;
}
2008-11-13 10:33:08 +00:00
if ( op = = SAPI_HEADER_DELETE ) {
if ( strchr ( header_line , ' : ' ) ) {
efree ( header_line ) ;
sapi_module . sapi_error ( E_WARNING , " Header to delete may not contain colon. " ) ;
return FAILURE ;
}
} else {
/* new line safety check */
2005-12-06 03:39:26 +00:00
char * s = header_line , * e = header_line + header_line_len , * p ;
while ( s < e & & ( p = memchr ( s , ' \n ' , ( e - s ) ) ) ) {
if ( * ( p + 1 ) = = ' ' | | * ( p + 1 ) = = ' \t ' ) {
s = p + 1 ;
continue ;
}
efree ( header_line ) ;
2005-12-30 05:39:38 +00:00
sapi_module . sapi_error ( E_WARNING , " Header may not contain more than a single header, new line detected. " ) ;
2005-12-06 03:39:26 +00:00
return FAILURE ;
}
}
2000-04-28 16:47:19 +00:00
1999-05-06 21:58:49 +00:00
sapi_header . header = header_line ;
1999-05-05 18:25:20 +00:00
sapi_header . header_len = header_line_len ;
2008-11-13 10:33:08 +00:00
if ( op = = SAPI_HEADER_DELETE ) {
if ( sapi_module . header_handler ) {
sapi_module . header_handler ( & sapi_header , op , & SG ( sapi_headers ) TSRMLS_CC ) ;
}
zend_llist_del_element ( & SG ( sapi_headers ) . headers , sapi_header . header , ( int ( * ) ( void * , void * ) ) sapi_find_matching_header ) ;
sapi_free_header ( & sapi_header ) ;
return SUCCESS ;
}
1999-05-05 18:25:20 +00:00
1999-05-11 20:38:16 +00:00
/* Check the header for a few cases that we have special support for in SAPI */
2009-05-23 18:19:11 +00:00
if ( header_line_len > = 5 & & ! strncasecmp ( header_line , " HTTP/ " , 5 ) ) {
1999-10-04 18:07:46 +00:00
/* filter out the response code */
2002-07-03 10:42:31 +00:00
sapi_update_response_code ( sapi_extract_response_code ( header_line ) TSRMLS_CC ) ;
2008-01-28 16:08:14 +00:00
/* sapi_update_response_code doesn't free the status line if the code didn't change */
if ( SG ( sapi_headers ) . http_status_line ) {
efree ( SG ( sapi_headers ) . http_status_line ) ;
}
1999-05-11 20:38:16 +00:00
SG ( sapi_headers ) . http_status_line = header_line ;
1999-08-09 17:40:28 +00:00
return SUCCESS ;
1999-05-11 20:38:16 +00:00
} else {
colon_offset = strchr ( header_line , ' : ' ) ;
if ( colon_offset ) {
* colon_offset = 0 ;
if ( ! STRCASECMP ( header_line , " Content-Type " ) ) {
2002-06-18 15:04:58 +00:00
char * ptr = colon_offset + 1 , * mimetype = NULL , * newheader ;
2000-02-25 21:27:03 +00:00
size_t len = header_line_len - ( ptr - header_line ) , newlen ;
2004-03-25 08:42:00 +00:00
while ( * ptr = = ' ' ) {
2002-08-01 21:12:09 +00:00
ptr + + ;
2004-03-25 08:42:00 +00:00
len - - ;
2002-08-01 21:12:09 +00:00
}
2003-02-10 19:04:44 +00:00
# if HAVE_ZLIB
2009-05-23 18:19:11 +00:00
if ( ! strncmp ( ptr , " image/ " , sizeof ( " image/ " ) - 1 ) ) {
2003-02-10 19:04:44 +00:00
zend_alter_ini_entry ( " zlib.output_compression " , sizeof ( " zlib.output_compression " ) , " 0 " , sizeof ( " 0 " ) - 1 , PHP_INI_USER , PHP_INI_STAGE_RUNTIME ) ;
2002-07-28 14:08:08 +00:00
}
# endif
2000-02-25 21:27:03 +00:00
mimetype = estrdup ( ptr ) ;
2001-07-28 11:36:37 +00:00
newlen = sapi_apply_default_charset ( & mimetype , len TSRMLS_CC ) ;
2002-07-27 13:58:16 +00:00
if ( ! SG ( sapi_headers ) . mimetype ) {
SG ( sapi_headers ) . mimetype = estrdup ( mimetype ) ;
}
2000-02-25 21:27:03 +00:00
if ( newlen ! = 0 ) {
newlen + = sizeof ( " Content-type: " ) ;
newheader = emalloc ( newlen ) ;
2000-08-27 09:48:03 +00:00
PHP_STRLCPY ( newheader , " Content-type: " , newlen , sizeof ( " Content-type: " ) - 1 ) ;
strlcat ( newheader , mimetype , newlen ) ;
2000-02-25 21:27:03 +00:00
sapi_header . header = newheader ;
sapi_header . header_len = newlen - 1 ;
2002-06-18 15:04:58 +00:00
efree ( header_line ) ;
2000-02-25 21:27:03 +00:00
}
efree ( mimetype ) ;
1999-05-11 20:38:16 +00:00
SG ( sapi_headers ) . send_default_content_type = 0 ;
} else if ( ! STRCASECMP ( header_line , " Location " ) ) {
2003-08-11 19:36:26 +00:00
if ( ( SG ( sapi_headers ) . http_response_code < 300 | |
SG ( sapi_headers ) . http_response_code > 307 ) & &
SG ( sapi_headers ) . http_response_code ! = 201 ) {
2002-06-21 09:31:21 +00:00
/* Return a Found Redirect if one is not already specified */
2006-12-31 19:22:17 +00:00
if ( http_response_code ) { /* user specified redirect code */
sapi_update_response_code ( http_response_code TSRMLS_CC ) ;
2009-05-23 18:19:11 +00:00
} else if ( SG ( request_info ) . proto_num > 1000 & &
SG ( request_info ) . request_method & &
strcmp ( SG ( request_info ) . request_method , " HEAD " ) & &
strcmp ( SG ( request_info ) . request_method , " GET " )
) {
2005-03-14 19:25:39 +00:00
sapi_update_response_code ( 303 TSRMLS_CC ) ;
} else {
sapi_update_response_code ( 302 TSRMLS_CC ) ;
}
2002-06-21 09:31:21 +00:00
}
1999-05-11 20:38:16 +00:00
} else if ( ! STRCASECMP ( header_line , " WWW-Authenticate " ) ) { /* HTTP Authentication */
2001-10-20 22:01:56 +00:00
2002-07-03 10:42:31 +00:00
sapi_update_response_code ( 401 TSRMLS_CC ) ; /* authentication-required */
2002-07-13 00:15:22 +00:00
2006-03-08 14:41:45 +00:00
myuid = php_getuid ( ) ;
efree ( header_line ) ;
sapi_header . header_len = spprintf ( & sapi_header . header , 0 , " WWW-Authenticate: Basic realm= \" %ld \" " , myuid ) ;
1999-05-11 20:38:16 +00:00
}
2001-12-16 23:21:52 +00:00
if ( sapi_header . header = = header_line ) {
* colon_offset = ' : ' ;
}
1999-05-11 18:36:35 +00:00
}
}
2002-06-21 09:31:21 +00:00
if ( http_response_code ) {
2002-07-03 10:42:31 +00:00
sapi_update_response_code ( http_response_code TSRMLS_CC ) ;
2002-06-21 09:31:21 +00:00
}
1999-05-05 19:53:15 +00:00
if ( sapi_module . header_handler ) {
2008-11-13 10:33:08 +00:00
retval = sapi_module . header_handler ( & sapi_header , op , & SG ( sapi_headers ) TSRMLS_CC ) ;
1999-05-05 19:53:15 +00:00
} else {
retval = SAPI_HEADER_ADD ;
}
1999-05-05 18:25:20 +00:00
if ( retval & SAPI_HEADER_ADD ) {
2002-06-18 10:16:36 +00:00
/* in replace mode first remove the header if it already exists in the headers llist */
2008-11-13 10:33:08 +00:00
if ( op = = SAPI_HEADER_REPLACE ) {
2002-06-18 12:57:09 +00:00
colon_offset = strchr ( sapi_header . header , ' : ' ) ;
2002-06-18 10:16:36 +00:00
if ( colon_offset ) {
char sav ;
sav = * colon_offset ;
* colon_offset = 0 ;
2002-06-18 12:57:09 +00:00
zend_llist_del_element ( & SG ( sapi_headers ) . headers , sapi_header . header , ( int ( * ) ( void * , void * ) ) sapi_find_matching_header ) ;
2002-06-18 10:16:36 +00:00
* colon_offset = sav ;
}
}
1999-05-05 18:25:20 +00:00
zend_llist_add_element ( & SG ( sapi_headers ) . headers , ( void * ) & sapi_header ) ;
2008-11-13 10:33:08 +00:00
} else {
sapi_free_header ( & sapi_header ) ;
1999-05-05 18:25:20 +00:00
}
return SUCCESS ;
}
2001-07-31 06:28:05 +00:00
SAPI_API int sapi_send_headers ( TSRMLS_D )
1999-05-05 18:25:20 +00:00
{
1999-05-05 19:53:15 +00:00
int retval ;
1999-10-04 18:07:46 +00:00
int ret = FAILURE ;
1999-05-05 18:25:20 +00:00
2000-11-13 18:54:37 +00:00
if ( SG ( headers_sent ) | | SG ( request_info ) . no_headers ) {
1999-05-05 19:53:15 +00:00
return SUCCESS ;
}
2009-05-23 18:19:11 +00:00
/* Success-oriented. We set headers_sent to 1 here to avoid an infinite loop
* in case of an error situation . */
2005-10-19 20:30:38 +00:00
if ( SG ( sapi_headers ) . send_default_content_type & & sapi_module . send_headers ) {
sapi_header_struct default_header ;
sapi_get_default_content_type_header ( & default_header TSRMLS_CC ) ;
sapi_add_header_ex ( default_header . header , default_header . header_len , 0 , 0 TSRMLS_CC ) ;
}
2000-08-19 16:38:19 +00:00
SG ( headers_sent ) = 1 ;
1999-05-05 19:53:15 +00:00
if ( sapi_module . send_headers ) {
2001-07-28 11:36:37 +00:00
retval = sapi_module . send_headers ( & SG ( sapi_headers ) TSRMLS_CC ) ;
1999-05-05 19:53:15 +00:00
} else {
retval = SAPI_HEADER_DO_SEND ;
}
switch ( retval ) {
1999-05-05 18:25:20 +00:00
case SAPI_HEADER_SENT_SUCCESSFULLY :
1999-10-05 12:06:35 +00:00
ret = SUCCESS ;
1999-05-05 18:25:20 +00:00
break ;
2002-07-03 10:42:31 +00:00
case SAPI_HEADER_DO_SEND : {
1999-05-11 20:38:16 +00:00
sapi_header_struct http_status_line ;
2002-07-03 10:42:31 +00:00
char buf [ 255 ] ;
1999-05-11 20:38:16 +00:00
2002-07-03 10:42:31 +00:00
if ( SG ( sapi_headers ) . http_status_line ) {
http_status_line . header = SG ( sapi_headers ) . http_status_line ;
http_status_line . header_len = strlen ( SG ( sapi_headers ) . http_status_line ) ;
} else {
http_status_line . header = buf ;
http_status_line . header_len = sprintf ( buf , " HTTP/1.0 %d X " , SG ( sapi_headers ) . http_response_code ) ;
}
2001-07-31 04:53:54 +00:00
sapi_module . send_header ( & http_status_line , SG ( server_context ) TSRMLS_CC ) ;
1999-05-11 20:38:16 +00:00
}
2001-07-31 04:53:54 +00:00
zend_llist_apply_with_argument ( & SG ( sapi_headers ) . headers , ( llist_apply_with_arg_func_t ) sapi_module . send_header , SG ( server_context ) TSRMLS_CC ) ;
2009-05-23 18:19:11 +00:00
if ( SG ( sapi_headers ) . send_default_content_type ) {
2000-02-26 05:03:41 +00:00
sapi_header_struct default_header ;
2001-07-28 11:36:37 +00:00
sapi_get_default_content_type_header ( & default_header TSRMLS_CC ) ;
2001-07-31 04:53:54 +00:00
sapi_module . send_header ( & default_header , SG ( server_context ) TSRMLS_CC ) ;
2000-02-26 05:03:41 +00:00
sapi_free_header ( & default_header ) ;
1999-12-19 02:04:20 +00:00
}
2001-07-31 04:53:54 +00:00
sapi_module . send_header ( NULL , SG ( server_context ) TSRMLS_CC ) ;
1999-10-04 18:07:46 +00:00
ret = SUCCESS ;
1999-05-05 18:25:20 +00:00
break ;
case SAPI_HEADER_SEND_FAILED :
2000-08-19 16:38:19 +00:00
SG ( headers_sent ) = 0 ;
1999-10-04 18:07:46 +00:00
ret = FAILURE ;
1999-05-05 18:25:20 +00:00
break ;
}
2002-07-31 17:55:15 +00:00
sapi_send_headers_free ( TSRMLS_C ) ;
1999-10-04 18:07:46 +00:00
return ret ;
1999-05-05 18:25:20 +00:00
}
1999-05-25 21:14:54 +00:00
2005-02-21 15:14:02 +00:00
SAPI_API int sapi_register_post_entries ( sapi_post_entry * post_entries TSRMLS_DC )
1999-09-16 23:18:15 +00:00
{
2000-02-17 20:23:59 +00:00
sapi_post_entry * p = post_entries ;
1999-09-16 23:18:15 +00:00
while ( p - > content_type ) {
2005-02-21 15:14:02 +00:00
if ( sapi_register_post_entry ( p TSRMLS_CC ) = = FAILURE ) {
1999-09-16 23:18:15 +00:00
return FAILURE ;
}
p + + ;
}
return SUCCESS ;
}
2005-02-21 15:14:02 +00:00
SAPI_API int sapi_register_post_entry ( sapi_post_entry * post_entry TSRMLS_DC )
1999-05-25 21:14:54 +00:00
{
2007-04-25 14:18:15 +00:00
if ( SG ( sapi_started ) & & EG ( in_execution ) ) {
2007-04-25 11:19:10 +00:00
return FAILURE ;
}
2009-05-23 18:19:11 +00:00
return zend_hash_add ( & SG ( known_post_content_types ) , post_entry - > content_type , post_entry - > content_type_len + 1 , ( void * ) post_entry , sizeof ( sapi_post_entry ) , NULL ) ;
1999-05-25 21:14:54 +00:00
}
1999-05-25 21:19:46 +00:00
2005-02-21 15:14:02 +00:00
SAPI_API void sapi_unregister_post_entry ( sapi_post_entry * post_entry TSRMLS_DC )
1999-05-25 21:19:46 +00:00
{
2007-04-25 14:18:15 +00:00
if ( SG ( sapi_started ) & & EG ( in_execution ) ) {
2007-04-25 11:19:10 +00:00
return ;
}
2009-05-23 18:19:11 +00:00
zend_hash_del ( & SG ( known_post_content_types ) , post_entry - > content_type , post_entry - > content_type_len + 1 ) ;
1999-05-28 22:41:48 +00:00
}
1999-09-16 23:18:15 +00:00
2001-07-28 11:36:37 +00:00
SAPI_API int sapi_register_default_post_reader ( void ( * default_post_reader ) ( TSRMLS_D ) )
1999-09-16 23:18:15 +00:00
{
2007-04-25 11:19:10 +00:00
TSRMLS_FETCH ( ) ;
2007-04-25 14:18:15 +00:00
if ( SG ( sapi_started ) & & EG ( in_execution ) ) {
2007-04-25 11:19:10 +00:00
return FAILURE ;
}
1999-09-16 23:18:15 +00:00
sapi_module . default_post_reader = default_post_reader ;
return SUCCESS ;
}
2002-08-02 06:53:48 +00:00
SAPI_API int sapi_register_treat_data ( void ( * treat_data ) ( int arg , char * str , zval * destArray TSRMLS_DC ) )
{
2007-04-25 11:19:10 +00:00
TSRMLS_FETCH ( ) ;
2007-04-25 14:18:15 +00:00
if ( SG ( sapi_started ) & & EG ( in_execution ) ) {
2007-04-25 11:19:10 +00:00
return FAILURE ;
}
2002-08-02 06:53:48 +00:00
sapi_module . treat_data = treat_data ;
return SUCCESS ;
}
2009-04-28 22:59:07 +00:00
SAPI_API int sapi_register_input_filter ( unsigned int ( * input_filter ) ( int arg , char * var , char * * val , unsigned int val_len , unsigned int * new_val_len TSRMLS_DC ) , unsigned int ( * input_filter_init ) ( TSRMLS_D ) )
2003-02-19 19:41:09 +00:00
{
2007-04-25 11:19:10 +00:00
TSRMLS_FETCH ( ) ;
2007-04-25 14:18:15 +00:00
if ( SG ( sapi_started ) & & EG ( in_execution ) ) {
2007-04-25 11:19:10 +00:00
return FAILURE ;
}
2003-02-19 19:41:09 +00:00
sapi_module . input_filter = input_filter ;
2009-04-28 22:59:07 +00:00
sapi_module . input_filter_init = input_filter_init ;
2003-02-19 19:41:09 +00:00
return SUCCESS ;
}
2002-08-02 06:53:48 +00:00
2001-07-31 06:28:05 +00:00
SAPI_API int sapi_flush ( TSRMLS_D )
2000-01-13 17:37:25 +00:00
{
if ( sapi_module . flush ) {
2000-02-10 19:29:21 +00:00
sapi_module . flush ( SG ( server_context ) ) ;
return SUCCESS ;
} else {
return FAILURE ;
2000-01-13 17:37:25 +00:00
}
}
2000-02-10 17:26:57 +00:00
2001-07-31 06:28:05 +00:00
SAPI_API struct stat * sapi_get_stat ( TSRMLS_D )
2000-02-10 17:26:57 +00:00
{
2000-02-10 18:19:04 +00:00
if ( sapi_module . get_stat ) {
2001-07-28 11:36:37 +00:00
return sapi_module . get_stat ( TSRMLS_C ) ;
2000-02-10 17:26:57 +00:00
} else {
2003-02-10 19:45:34 +00:00
if ( ! SG ( request_info ) . path_translated | | ( VCWD_STAT ( SG ( request_info ) . path_translated , & SG ( global_stat ) ) = = - 1 ) ) {
2000-02-10 18:19:04 +00:00
return NULL ;
2000-02-10 17:26:57 +00:00
}
2000-02-10 18:19:04 +00:00
return & SG ( global_stat ) ;
2000-02-10 17:26:57 +00:00
}
}
2000-02-10 17:55:01 +00:00
2001-07-31 06:28:05 +00:00
SAPI_API char * sapi_getenv ( char * name , size_t name_len TSRMLS_DC )
2000-02-10 17:55:01 +00:00
{
2009-05-23 18:19:11 +00:00
if ( sapi_module . getenv ) {
2006-05-10 21:25:01 +00:00
char * value , * tmp = sapi_module . getenv ( name , name_len TSRMLS_CC ) ;
2009-05-23 18:19:11 +00:00
2006-12-21 21:49:13 +00:00
if ( tmp ) {
value = estrdup ( tmp ) ;
} else {
return NULL ;
}
2006-05-10 21:25:01 +00:00
sapi_module . input_filter ( PARSE_ENV , name , & value , strlen ( value ) , NULL TSRMLS_CC ) ;
return value ;
2006-12-21 21:49:13 +00:00
}
2009-05-23 18:19:11 +00:00
return NULL ;
2000-02-24 22:00:47 +00:00
}
2000-02-25 21:27:03 +00:00
2002-11-26 05:15:55 +00:00
SAPI_API int sapi_get_fd ( int * fd TSRMLS_DC )
{
if ( sapi_module . get_fd ) {
return sapi_module . get_fd ( fd TSRMLS_CC ) ;
} else {
2003-02-09 21:15:55 +00:00
return FAILURE ;
2002-11-26 05:15:55 +00:00
}
}
2002-12-01 03:28:21 +00:00
SAPI_API int sapi_force_http_10 ( TSRMLS_D )
{
if ( sapi_module . force_http_10 ) {
return sapi_module . force_http_10 ( TSRMLS_C ) ;
} else {
2003-02-09 21:15:55 +00:00
return FAILURE ;
2002-12-01 03:28:21 +00:00
}
}
2003-01-21 11:03:58 +00:00
SAPI_API int sapi_get_target_uid ( uid_t * obj TSRMLS_DC )
{
if ( sapi_module . get_target_uid ) {
return sapi_module . get_target_uid ( obj TSRMLS_CC ) ;
} else {
2003-02-09 21:15:55 +00:00
return FAILURE ;
2003-01-21 11:03:58 +00:00
}
}
SAPI_API int sapi_get_target_gid ( gid_t * obj TSRMLS_DC )
{
if ( sapi_module . get_target_gid ) {
return sapi_module . get_target_gid ( obj TSRMLS_CC ) ;
} else {
2003-02-09 21:15:55 +00:00
return FAILURE ;
2003-01-21 11:03:58 +00:00
}
}
2004-08-10 17:40:00 +00:00
SAPI_API time_t sapi_get_request_time ( TSRMLS_D )
{
2009-05-23 18:19:11 +00:00
if ( SG ( global_request_time ) ) {
return SG ( global_request_time ) ;
}
2007-05-25 09:19:05 +00:00
if ( sapi_module . get_request_time & & SG ( server_context ) ) {
SG ( global_request_time ) = sapi_module . get_request_time ( TSRMLS_C ) ;
2004-08-10 17:40:00 +00:00
} else {
2007-05-25 09:19:05 +00:00
SG ( global_request_time ) = time ( 0 ) ;
2004-08-10 17:40:00 +00:00
}
2007-05-25 09:19:05 +00:00
return SG ( global_request_time ) ;
2004-08-10 17:40:00 +00:00
}
2003-01-21 11:03:58 +00:00
2009-05-23 18:19:11 +00:00
SAPI_API void sapi_terminate_process ( TSRMLS_D )
{
2008-03-19 16:37:49 +00:00
if ( sapi_module . terminate_process ) {
sapi_module . terminate_process ( TSRMLS_C ) ;
}
}
2000-02-25 21:27:03 +00:00
/*
* Local variables :
* tab - width : 4
* c - basic - offset : 4
* End :
2001-09-09 13:29:31 +00:00
* vim600 : sw = 4 ts = 4 fdm = marker
* vim < 600 : sw = 4 ts = 4
2000-02-25 21:27:03 +00:00
*/