From: Andi Gutmans Date: Wed, 5 May 1999 18:25:20 +0000 (+0000) Subject: Added initial headers support in SAPI X-Git-Tag: BEFORE_PHP4_APACHE_MODULE_CHANGE~99 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=537cc54acd4844624e60ed9f128155b35374b4a6;p=php Added initial headers support in SAPI *untested* It definitely broke the thread-safe CGI, it may have broken other stuff as well. --- diff --git a/ext/standard/head.c b/ext/standard/head.c index ad21e99354..d2cd7eeb07 100644 --- a/ext/standard/head.c +++ b/ext/standard/head.c @@ -76,8 +76,9 @@ PHPAPI void php3_noheader(void) } +#ifndef ZTS /* Adds header information */ -void php4i_add_header_information(char *header_information) +void php4i_add_header_information(char *header_information, uint header_length) { char *r; #if APACHE @@ -202,6 +203,12 @@ void php4i_add_header_information(char *header_information) } #endif } +#else +void php4i_add_header_information(char *header_information, uint header_length) +{ + sapi_add_header(header_information, header_length); +} +#endif /* Implementation of the language Header() function */ @@ -213,12 +220,14 @@ void php3_Header(INTERNAL_FUNCTION_PARAMETERS) WRONG_PARAM_COUNT; } convert_to_string(arg1); - php4i_add_header_information(arg1->value.str.val); + php4i_add_header_information(arg1->value.str.val, arg1->value.str.len); } + +#ifndef ZTS /* * php3_header() flushes the header info built up using calls to * the Header() function. If type is 1, a redirect to str is done. @@ -384,6 +393,20 @@ PHPAPI int php3_header(void) PG(header_is_being_sent) = 0; return(1); } +#else +PHPAPI int php3_header() +{ + SLS_FETCH(); + + if (sapi_send_headers()==FAILURE || SG(request_info).headers_only) { + return 0; /* don't allow output */ + } else { + return 1; /* allow output */ + } +} +#endif + + void php3_PushCookieList(char *name, char *value, time_t expires, char *path, char *domain, int secure) { diff --git a/ext/standard/head.h b/ext/standard/head.h index f7b33d73fd..3ab12d0d84 100644 --- a/ext/standard/head.h +++ b/ext/standard/head.h @@ -56,7 +56,7 @@ extern int php3_init_head(INIT_FUNC_ARGS); extern void php3_Header(INTERNAL_FUNCTION_PARAMETERS); extern void php3_SetCookie(INTERNAL_FUNCTION_PARAMETERS); -void php4i_add_header_information(char *header_information); +void php4i_add_header_information(char *header_information, uint header_length); PHPAPI void php3_noheader(void); PHPAPI int php3_header(void); diff --git a/main/SAPI.c b/main/SAPI.c index bdb58baed4..c107365366 100644 --- a/main/SAPI.c +++ b/main/SAPI.c @@ -3,6 +3,12 @@ #include "TSRM.h" #endif +#if WIN32||WINNT +#define STRCASECMP stricmp +#else +#define STRCASECMP strcasecmp +#endif + #ifdef ZTS SAPI_API int sapi_globals_id; @@ -10,13 +16,94 @@ SAPI_API int sapi_globals_id; sapi_globals_struct sapi_globals; #endif + /* A true global (no need for thread safety) */ sapi_module_struct sapi_module; + SAPI_API void sapi_startup(sapi_module_struct *sf) { sapi_module = *sf; #ifdef ZTS sapi_globals_id = ts_allocate_id(sizeof(sapi_globals_struct), NULL, NULL); #endif -} \ No newline at end of file +} + + +static void sapi_free_header(sapi_header_struct *sapi_header) +{ + efree(sapi_header->header); +} + + +SAPI_API void sapi_activate(SLS_D) +{ + zend_llist_init(&SG(sapi_headers).headers, sizeof(sapi_header_struct), (void (*)(void *)) sapi_free_header, 0); + SG(sapi_headers).content_type.header = NULL; + SG(sapi_headers).http_response_code = 200; +} + + +SAPI_API void sapi_deactivate(SLS_D) +{ + zend_llist_destroy(&SG(sapi_headers).headers); +} + + +/* This function expects a *duplicated* string, that was previously emalloc()'d. + * Pointers sent to this functions will be automatically freed by the framework. + */ +SAPI_API int sapi_add_header(const char *header_line, uint header_line_len) +{ + int retval; + sapi_header_struct sapi_header; + SLS_FETCH(); + + sapi_header.header = (char *) header_line; + sapi_header.header_len = header_line_len; + + retval = sapi_module.header_handler(&sapi_header, &SG(sapi_headers)); + + if (retval & SAPI_HEADER_DELETE_ALL) { + zend_llist_clean(&SG(sapi_headers).headers); + } + if (retval & SAPI_HEADER_ADD) { + char *colon_offset = strchr(header_line, ':'); + + if (colon_offset) { + *colon_offset = 0; + if (!STRCASECMP(header_line, "Content-Type")) { + if (SG(sapi_headers).content_type.header) { + efree(SG(sapi_headers).content_type.header); + } + *colon_offset = ':'; + SG(sapi_headers).content_type.header = (char *) header_line; + SG(sapi_headers).content_type.header_len = header_line_len; + return SUCCESS; + } + *colon_offset = ':'; + } + zend_llist_add_element(&SG(sapi_headers).headers, (void *) &sapi_header); + } + return SUCCESS; +} + + +SAPI_API int sapi_send_headers() +{ + SLS_FETCH(); + + switch (sapi_module.send_headers(&SG(sapi_headers) SLS_CC)) { + case SAPI_HEADER_SENT_SUCCESSFULLY: + return SUCCESS; + break; + case SAPI_HEADER_DO_SEND: + zend_llist_apply_with_argument(&SG(sapi_headers).headers, (void (*)(void *, void *)) sapi_module.send_header, SG(server_context)); + return SUCCESS; + break; + case SAPI_HEADER_SEND_FAILED: + return FAILURE; + break; + } + return FAILURE; +} diff --git a/main/SAPI.h b/main/SAPI.h index 7796fc0634..2b76ceae4c 100644 --- a/main/SAPI.h +++ b/main/SAPI.h @@ -1,6 +1,9 @@ #ifndef _NEW_SAPI_H #define _NEW_SAPI_H +#include "zend.h" +#include "zend_llist.h" + #if WIN32||WINNT # ifdef SAPI_EXPORTS @@ -13,14 +16,20 @@ #endif -typedef struct _sapi_module_struct { - char *name; +typedef struct { + char *header; + uint header_len; +} sapi_header_struct; - int (*startup)(struct _sapi_module_struct *sapi_module); - int (*shutdown)(struct _sapi_module_struct *sapi_module); - int (*ub_write)(const char *str, unsigned int str_length); -} sapi_module_struct; +typedef struct { + zend_llist headers; + sapi_header_struct content_type; + int http_response_code; +} sapi_headers_struct; + + +typedef struct _sapi_module_struct sapi_module_struct; extern sapi_module_struct sapi_module; /* true global */ @@ -31,16 +40,24 @@ typedef struct { char *path_translated; char *request_uri; + + unsigned char headers_only; } sapi_request_info; typedef struct { void *server_context; sapi_request_info request_info; + sapi_headers_struct sapi_headers; } sapi_globals_struct; SAPI_API void sapi_startup(sapi_module_struct *sf); +SAPI_API void sapi_activate(SLS_D); +SAPI_API void sapi_deactivate(SLS_D); + +SAPI_API int sapi_add_header(const char *header_line, uint header_line_len); +SAPI_API int sapi_send_headers(); #ifdef ZTS # define SLS_D sapi_globals_struct *sapi_globals @@ -61,4 +78,32 @@ extern SAPI_API sapi_globals_struct sapi_globals; #endif + +struct _sapi_module_struct { + char *name; + + int (*startup)(struct _sapi_module_struct *sapi_module); + int (*shutdown)(struct _sapi_module_struct *sapi_module); + + int (*ub_write)(const char *str, unsigned int str_length); + + int (*header_handler)(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers); + int (*send_headers)(sapi_headers_struct *sapi_headers SLS_DC); + void (*send_header)(void *server_context, sapi_header_struct *sapi_header); +}; + + + +/* header_handler() constants */ +#define SAPI_HEADER_ADD (1<<0) +#define SAPI_HEADER_DELETE_ALL (1<<1) +#define SAPI_HEADER_SEND_NOW (1<<2) + + +#define SAPI_HEADER_SENT_SUCCESSFULLY 1 +#define SAPI_HEADER_DO_SEND 2 +#define SAPI_HEADER_SEND_FAILED 3 + +#define DEFAULT_CONTENT_TYPE "Content-Type: text/html" + #endif /* _NEW_SAPI_H */ \ No newline at end of file diff --git a/main/logos.h b/main/logos.h index 6c91b0ae56..2826a66a92 100644 --- a/main/logos.h +++ b/main/logos.h @@ -1,3 +1,5 @@ +#define CONTEXT_TYPE_IMAGE_GIF "Content-Type: image/gif" + unsigned char zendtech_logo[] = { 71, 73, 70, 56, 57, 97, 100, 0, 89, 0, 247, 255, 0, 255, 255, 255, 8, 8, 8, 16, diff --git a/main/main.c b/main/main.c index a745601c47..cfc39a5a0d 100644 --- a/main/main.c +++ b/main/main.c @@ -1124,16 +1124,16 @@ PHPAPI void php_execute_script(zend_file_handle *primary_file CLS_DC ELS_DC PLS_ if (SG(request_info).query_string && SG(request_info).query_string[0]=='=') { if (!strcmp(SG(request_info).query_string+1, "PHPE9568F34-D428-11d2-A769-00AA001ACF42")) { - char *header_line = estrndup("Content-type: image/gif", sizeof("Content-type: image/gif")-1); + char *header_line = estrndup(CONTEXT_TYPE_IMAGE_GIF, sizeof(CONTEXT_TYPE_IMAGE_GIF)); - php4i_add_header_information(header_line); + php4i_add_header_information(header_line, sizeof(CONTEXT_TYPE_IMAGE_GIF)); PHPWRITE(php4_logo, sizeof(php4_logo)); efree(header_line); return; } else if (!strcmp(SG(request_info).query_string+1, "PHPE9568F35-D428-11d2-A769-00AA001ACF42")) { - char *header_line = estrndup("Content-type: image/gif", sizeof("Content-type: image/gif")-1); + char *header_line = estrndup(CONTEXT_TYPE_IMAGE_GIF, sizeof(CONTEXT_TYPE_IMAGE_GIF)); - php4i_add_header_information(header_line); + php4i_add_header_information(header_line, sizeof(CONTEXT_TYPE_IMAGE_GIF)); PHPWRITE(zendtech_logo, sizeof(zendtech_logo)); efree(header_line); return; diff --git a/output.c b/output.c index fdf55945dc..c18650f2f4 100644 --- a/output.c +++ b/output.c @@ -35,9 +35,6 @@ void zend_ob_append(const char *text, uint text_length); void zend_ob_prepend(const char *text, uint text_length); static inline void zend_ob_send(); -/* HEAD support */ -static int header_request; - /* * Main @@ -47,7 +44,6 @@ PHPAPI void zend_output_startup() { ob_buffer = NULL; zend_body_write = zend_ub_body_write; - header_request=0; zend_header_write = sapi_module.ub_write; } @@ -172,7 +168,9 @@ static int zend_b_body_write(const char *str, uint str_length) static int zend_ub_body_write(const char *str, uint str_length) { - if (header_request) { + SLS_FETCH(); + + if (SG(request_info).headers_only) { zend_bailout(); } if (php3_header()) { @@ -189,5 +187,5 @@ static int zend_ub_body_write(const char *str, uint str_length) void set_header_request(int value) { - header_request = value; + /* deprecated */ }