diff --git a/sapi/apache2handler/php_functions.c b/sapi/apache2handler/php_functions.c index 1baa1f5225e0..f749bac4a735 100644 --- a/sapi/apache2handler/php_functions.c +++ b/sapi/apache2handler/php_functions.c @@ -205,6 +205,49 @@ PHP_FUNCTION(apache_response_headers) } /* }}} */ +/* {{{ The allows for direct select calls on Apache's connection socket */ +PHP_FUNCTION(apache_connection_stream) +{ + php_struct *ctx = SG(server_context); + request_rec *r; + apr_socket_t *apr_sock; + int fd; + php_stream *stream; + + ZEND_PARSE_PARAMETERS_NONE(); + + if (!ctx) { + php_error_docref(NULL, E_WARNING, "Server context is not available"); + RETURN_FALSE; + } + + r = ctx->r; + if (!r) { + php_error_docref(NULL, E_WARNING, "Request record is not available"); + RETURN_FALSE; + } + + apr_sock = ap_get_conn_socket(r->connection); + if (!apr_sock) { + php_error_docref(NULL, E_WARNING, "Failed to obtain connection socket"); + RETURN_FALSE; + } + + if (apr_os_sock_get(&fd, apr_sock) != APR_SUCCESS) { + php_error_docref(NULL, E_WARNING, "Failed to get native socket descriptor"); + RETURN_FALSE; + } + + stream = php_stream_sock_open_from_socket(fd, NULL); + if (!stream) { + php_error_docref(NULL, E_WARNING, "Failed to open stream from socket"); + RETURN_FALSE; + } + + php_stream_to_zval(stream, return_value); +} +/* }}} */ + /* {{{ Get and set Apache request notes */ PHP_FUNCTION(apache_note) { diff --git a/sapi/apache2handler/php_functions_arginfo.h b/sapi/apache2handler/php_functions_arginfo.h index f816c29f8621..d1d981bf49a8 100644 --- a/sapi/apache2handler/php_functions_arginfo.h +++ b/sapi/apache2handler/php_functions_arginfo.h @@ -41,6 +41,7 @@ ZEND_FUNCTION(apache_lookup_uri); ZEND_FUNCTION(virtual); ZEND_FUNCTION(apache_request_headers); ZEND_FUNCTION(apache_response_headers); +ZEND_FUNCTION(apache_connection_stream); ZEND_FUNCTION(apache_note); ZEND_FUNCTION(apache_setenv); ZEND_FUNCTION(apache_getenv); @@ -53,6 +54,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(apache_request_headers, arginfo_apache_request_headers) ZEND_RAW_FENTRY("getallheaders", zif_apache_request_headers, arginfo_getallheaders, 0, NULL, NULL) ZEND_FE(apache_response_headers, arginfo_apache_response_headers) + ZEND_FE(apache_connection_stream, NULL) ZEND_FE(apache_note, arginfo_apache_note) ZEND_FE(apache_setenv, arginfo_apache_setenv) ZEND_FE(apache_getenv, arginfo_apache_getenv) diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c index 007718e37b9c..d2e59bc16522 100644 --- a/sapi/cli/php_cli_server.c +++ b/sapi/cli/php_cli_server.c @@ -447,6 +447,28 @@ PHP_FUNCTION(apache_response_headers) /* {{{ */ } /* }}} */ +PHP_FUNCTION(apache_connection_stream) /* {{{ */ +{ + php_cli_server_client *client = SG(server_context); + php_stream *stream; + + ZEND_PARSE_PARAMETERS_NONE(); + + if (!client) { + php_error_docref(NULL, E_WARNING, "Server context is not available"); + RETURN_FALSE; + } + + stream = php_stream_sock_open_from_socket(client->sock, NULL); + if (!stream) { + php_error_docref(NULL, E_WARNING, "Failed to open stream from socket in cli server"); + RETURN_FALSE; + } + + php_stream_to_zval(stream, return_value); +} +/* }}} */ + /* {{{ cli_server module */ static void cli_server_init_globals(zend_cli_server_globals *cg) @@ -495,6 +517,7 @@ const zend_function_entry server_additional_functions[] = { PHP_FE(cli_get_process_title, arginfo_cli_get_process_title) PHP_FE(apache_request_headers, arginfo_apache_request_headers) PHP_FE(apache_response_headers, arginfo_apache_response_headers) + PHP_FE(apache_connection_stream, NULL) PHP_FALIAS(getallheaders, apache_request_headers, arginfo_getallheaders) PHP_FE_END };