PHP kernel-SAPI of Apache2. We know before defining SAPI, first we need to define sapi_module_struct this structure, look at the source code: softphp-5.2.9sapiapache2handlersapi_apache2.c, you can see the definition of this structure, I am straight we know before defining SAPI, first we need to define sapi_module_struct this structure, look at the source code:/soft/php-5.2.9/sapi/apache2handler/sapi_apache2.c, you can see the definition of this structure, I directly copy it over:
[Cpp]
Static sapi_module_struct apache2_sapi_module = {
"Apache2handler ",
"Apache 2.0 Handler ",
Php_apache2_startup,/* startup */
Php_module_shutdown_wrapper,/* shutdown */
NULL,/* activate */
NULL,/* deactivate */
Php_apache_sapi_ub_write,/* unbuffered write */
Php_apache_sapi_flush,/* flush */
Php_apache_sapi_get_stat,/* get uid */
Php_apache_sapi_getenv,/* getenv */
Php_error,/* error handler */
Php_apache_sapi_header_handler,/* header handler */
Php_apache_sapi_send_headers,/* send headers handler */
NULL,/* send header handler */
Php_apache_sapi_read_post,/* read POST data */
Php_apache_sapi_read_cookies,/* read Cookies */
Php_apache_sapi_register_variables,
Php_apache_sapi_log_message,/* Log message */
Php_apache_sapi_get_request_time,/* Request Time */
STANDARD_SAPI_MODULE_PROPERTIES
};
1. php_apache2_startup: This function is called When PHP is called through apache. This function is defined as follows, mainly to initialize PHP.
[Cpp]
Static int php_apache2_startup (sapi_module_struct * sapi_module)
{
If (php_module_startup (sapi_module, & php_apache_module, 1) = FAILURE ){
Return FAILURE;
}
Return SUCCESS;
}
2. php_module_shutdown_wrapper: disable the function of PHP.
3. PHP processes initialization and resource allocation transactions for each request. This part is to be defined by the activate field.
4. the Function with activate is deactiveate, which provides a handler to deal with the final work.
5. php_apache_sapi_ub_write: provides an interface for writing data to Response.
[Cpp]
Static int
Php_apache_sapi_ub_write (const char * str, uint str_length TSRMLS_DC)
{
Request_rec * r;
Php_struct * ctx;
Ctx = SG (server_context );
R = ctx-> r;
If (ap_rwrite (str, str_length, r) <0 ){
Php_handle_aborted_connection ();
}
Return str_length;/* we always consume all the data passed to us .*/
}
6. php_apache_sapi_flush: the handle that is provided to zend to refresh the cache.
[Cpp]
Static void
Php_apache_sapi_flush (void * server_context)
{
Php_struct * ctx;
Request_rec * r;
TSRMLS_FETCH ();
Ctx = server_context;
/* If we haven't registered a server_context yet,
* Then don't bother flushing .*/
If (! Server_context ){
Return;
}
R = ctx-> r;
Sapi_send_headers (TSRMLS_C );
R-> status = SG (sapi_headers). http_response_code;
SG (headers_sent) = 1;
If (ap_rflush (r) <0 | r-> connection-> aborted ){
Php_handle_aborted_connection ();
}
}
7. php_apache_sapi_get_stat: This part allows Zend to verify the state of the script file to be executed and determine whether the file has execution permissions.
[Cpp]
Static struct stat *
Php_apache_sapi_get_stat (TSRMLS_D)
{
Php_struct * ctx = SG (server_context );
Ctx-> finfo. st_uid = ctx-> r-> finfo. user;
Ctx-> finfo. st_gid = ctx-> r-> finfo. group;
Ctx-> finfo. st_dev = ctx-> r-> finfo. device;
Ctx-> finfo. st_ino = ctx-> r-> finfo. inode;
# If defined (NETWARE) & defined (CLIB_STAT_PATCH)
Ctx-> finfo. st_atime. TV _sec = apr_time_sec (ctx-> r-> finfo. atime );
Ctx-> finfo. st_mtime. TV _sec = apr_time_sec (ctx-> r-> finfo. mtime );
Ctx-> finfo. st_ctime. TV _sec = apr_time_sec (ctx-> r-> finfo. ctime );
# Else
Ctx-> finfo. st_atime = apr_time_sec (ctx-> r-> finfo. atime );
Ctx-> finfo. st_mtime = apr_time_sec (ctx-> r-> finfo. mtime );
Ctx-> finfo. st_ctime = apr_time_sec (ctx-> r-> finfo. ctime );
# Endif
Ctx-> finfo. st_size = ctx-> r-> finfo. size;
Ctx-> finfo. st_nlink = ctx-> r-> finfo. nlink;
Return & ctx-> finfo;
}
8. php_apache_sapi_getenv: provides an interface for Zend to find environment variables based on name. when we call getenv in a script, this handle is indirectly called.
[Cpp]
Static char *
Php_apache_sapi_getenv (char * name, size_t name_len TSRMLS_DC)
{
Php_struct * ctx = SG (server_context );
Const char * env_var;
Env_var = apr_table_get (ctx-> r-> subprocess_env, name );
Return (char *) env_var;
}
9. php_error: Error handling function, which calls the PHP error handling function directly.
10. php_apache_sapi_header_handler: This function is called when the PHP header () function is called.
[Cpp]
Static int
Php_apache_sapi_header_handler (sapi_header_struct * sapi_header, sapi_headers_struct * sapi_headers TSRMLS_DC)
{
Php_struct * ctx;
Char * val, * ptr;
Ctx = SG (server_context );
Val = strchr (sapi_header-> header ,':');
If (! Val ){
Sapi_free_header (sapi_header );
Return 0;
}
Ptr = val;
* Val = '\ 0 ';
Do {
Val ++;
} While (* val = '');
If (! Strcasecmp (sapi_header-> header, "content-type ")){
If (ctx-> content_type ){
Efree (ctx-> content_type );
}
Ctx-> content_type = estrdup (val );
} Else if (sapi_header-> replace ){
Apr_table_set (ctx-> r-> headers_out, sapi_header-> header, val );
} Else {
Apr_table_add (ctx-> r-> headers_out, sapi_header-> header, val );
}
* Ptr = ':';
Return SAPI_HEADER_ADD;
}
11. php_apache_sapi_send_headers: This function will be called to actually send the header.
[Cpp]
Static int
Php_apache_sapi_send_headers (sapi_headers_struct * sapi_headers TSRMLS_DC)
{
Php_struct * ctx = SG (server_context );
Const char * sline = SG (sapi_headers). http_status_line;
Ctx-> r-> status = SG (sapi_headers). http_response_code;
/* Httpd requires that r-> status_line is set to the first digit
* The status-code :*/
If (sline & strlen (sline)> 12 & strncmp (sline, "HTTP/1. ", 7) = 0 & sline [8] = ''){
Ctx-> r-> status_line = apr_pstrdup (ctx-> r-> pool, sline + 9 );
Ctx-> r-> proto_num = 1000 + (sline [7]-'0 ');
If (sline [7]-'0') = 0 ){
Apr_table_set (ctx-> r-> subprocess_env, "force-response-1.0", "true ");
}
}
/* Call ap_set_content_type only once, else each time we call it,
Configured output filters for that content type will be added */
If (! Ctx-> content_type ){
Ctx-> content_type = sapi_get_default_content_type (TSRMLS_C );
}
Ap_set_content_type (ctx-> r, apr_pstrdup (ctx-> r-> pool, ctx-> content_type ));
Efree (ctx-> content_type );
Ctx-> content_type = NULL;
Return SAPI_HEADER_SENT_SUCCESSFULLY;
}
12. there is a field under the php_apache_sapi_send_headers pointer to indicate that it is called when each separate header is sent.
13. php_apache_sapi_read_post: indicates how to read POST data.
[Cpp]
Static int
Php_apache_sapi_read_post (char * buf, uint count_bytes TSRMLS_DC)
{
Apr_size_t len, tlen = 0;
Php_struct * ctx = SG (server_context );
Request_rec * r;
Apr_bucket_brigade * brigade;
R = ctx-> r;
Brigade = ctx-> brigade;
Len = count_bytes;
/*
* This loop is needed because ap_get_brigade () can return us partial data
* Which wocould cause premature termination of request read. Therefor we
* Need to make sure that if data is available we fill the buffer completely.
*/
While (ap_get_brigade (r-> input_filters, brigade, AP_MODE_READBYTES, APR_BLOCK_READ, len) = APR_SUCCESS ){
Apr_brigade_flatten (brigade, buf, & len );
Apr_brigade_cleanup (brigade );
Tlen + = len;
If (tlen = count_bytes |! Len ){
Break;
}
Buf + = len;
Len = count_bytes-tlen;
}
Return tlen;
}
14. php_apache_sapi_read_cookie: how to read the cookie.
[Cpp]
Static char *
Php_apache_sapi_read_cookies (TSRMLS_D)
{
Php_struct * ctx = SG (server_context );
Const char * http_cookie;
Http_cookie = apr_table_get (ctx-> r-> headers_in, "cookie ");
/* The SAPI interface shoshould use 'const char *'*/
Return (char *) http_cookie;
}
15. php_apache_sapi_register_variables: provides an interface to provide variables to the $ _ SERVER [] array.
[Cpp]
Static void
Php_apache_sapi_register_variables (zval * track_vars_array TSRMLS_DC)
{
Php_struct * ctx = SG (server_context );
Const apr_array_header_t * arr = apr_table_elts (ctx-> r-> subprocess_env );
Char * key, * val;
Int new_val_len;
APR_ARRAY_FOREACH_OPEN (arr, key, val)
If (! Val ){
Val = "";
}
If (sapi_module.input_filter (PARSE_SERVER, key, & val, strlen (val), & new_val_len TSRMLS_CC )){
Php_register_variable_safe (key, val, new_val_len, track_vars_array TSRMLS_CC );
}
APR_ARRAY_FOREACH_CLOSE ()
If (sapi_module.input_filter (PARSE_SERVER, "PHP_SELF", & ctx-> r-> uri, strlen (ctx-> r-> uri), & new_val_len TSRMLS_CC )){
Php_register_variable_safe ("PHP_SELF", ctx-> r-> uri, new_val_len, track_vars_array TSRMLS_CC );
}
}
16, php_apache_sapi_log_message: output error message.
[Cpp]
Static void php_apache_sapi_log_message (char * msg)
{
Php_struct * ctx;
TSRMLS_FETCH ();
Ctx = SG (server_context );
If (ctx = NULL) {/* we haven' t initialized our ctx yet, oh well */
Ap_log_error (APLOG_MARK, APLOG_ERR | APLOG_STARTUP, 0, NULL, "% s", msg );
} Else {
Ap_log_rerror (APLOG_MARK, APLOG_ERR, 0, ctx-> r, "% s", msg );
}
}
17, php_apache_sapi_get_request_time: Gets the request time.
[Cpp]
Static time_t php_apache_sapi_get_request_time (TSRMLS_D ){
Php_struct * ctx = SG (server_context );
Return apr_time_sec (ctx-> r-> request_time );
}
This completes the SAPI definition of apache. Then, when the user uses a URL to request the apache service, these function pointers will play a role (called) when appropriate ).
...