From 95ef44b2e286e2de0cb48757ca8c0bebf9e76380 Mon Sep 17 00:00:00 2001 From: richardtmiles Date: Thu, 25 Apr 2024 08:04:01 -0600 Subject: [PATCH 01/10] Adding PHP_FUNCTION apache_connection_stream to expose ap_get_conn_socket Apache CGI doesn't support WebSocket Upgrade requests out-of-the-box. php://input uses apache brigade/buckets but these are not fired with websocket Input; moreover, the php://input stream is cached and not seekable. php://stdio is the php code buffer so it is not useful here either. This allow a direct connection to the client. --- .DS_Store | Bin 0 -> 10244 bytes .gitignore | 6 + ext/.DS_Store | Bin 0 -> 6148 bytes ext/standard/php_fopen_wrapper.c | 18 ++- sapi/apache2handler/php_functions.c | 123 ++++++++++++++++++++ sapi/apache2handler/php_functions_arginfo.h | 4 + 6 files changed, 146 insertions(+), 5 deletions(-) create mode 100644 .DS_Store create mode 100644 ext/.DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..8060b2bde57951e48b081ddb9ebc6b9af91076fe GIT binary patch literal 10244 zcmeHMPiS0482@H>lWd5r)zCJ!nk?p^U|V*R_E3ZErfd!-i0E3-fRLmcvT1j-+ubDX zL1c^dU_pp@QBm;VzZL{@5fqUg>M56krBM%21SvGMl$N%a9{PPV^WOVr-|V)hMan#Q z@7wI}``+(2znM30X957?&{94PkOY7@o)ot{h8N30IGv#*qQ7|)qriHABT$4{yv`Tr zLfP&M=YVs-Ip7>{4mbz?4-Vivn~r#oitg$ha1J;JdSFAjxnQST}4$6LY0Hi%tEhFgk;CM zq)Z2qQPEwU1I~f41GIMUhCQ@qhbmvcr*lWjrHU%pdfT2=Drd7Z#qtcI@z*{(nC`ps z+i0`Q{6l6|3Y5>9OGJ6Uz)hL{hHL`*OtnG0vpbG2ZvL{ z+vV{>0hVBfvx8W<8qVMvwmvcH`O$D6uB3Su*8|ZhB!dprGY@&(VVO3xz?rvAl$epKlbi)j4Uy!;>*rqBRGt|T2h&_vIzH?#S>tD zb^4c|pHa`7uH#OGQO=jRv_gC_Z2LTp0mJ{u#t-xm`WWZ@?~~r~o!)$>YdNb8=e&`P z^NN?AhIv>p`h9f$l;qVI=Z!v_Sp9WV&$B)r_-w;DFN{}+w+rW!GWPwF+&wm04gI%< z!Wmq{2cKU*w{}%(Xt)n|pm~;|XMp6O#})Kp5ekM6o8SM$F|Oh8%3JBOn!o&7&Thjw zuXwWV@#5SLRf89{+|s-f4ioHIsj|aRqobz_(b-&kemZ{>1tDxIvzl&Y;%cKj846dQ~{SPm1c>Ugx6)0(* z#r1%oM+@g&dZ*PwT6))CHc_tQtJSAGFIYYAeS3z%f8a~v??mP*_QWzeV!8qGY$MJ! z9Ek4lG#K~bDw^dOI@Dq-25&$PUWZrscmTM&fEs*^^MBg6_V_!hFBl&5f(K z$N%=)?c)Kn4d=X(@8q~6Zg)5boCD5*b~+GMWJ%ipA8Y>q|8`1pT+RXKK${&9v1~4T z2ubzcdWfEu=Se)L@T7zC>MF_-yvP+iM!6l2f6#XP^LSEjiXt8OIiq7;Mf?Vjw*NDr X#XbT5eFkp*58&4Sa&ZEW*!urIn%a7w literal 0 HcmV?d00001 diff --git a/.gitignore b/.gitignore index cf11cd0ac20f9..9b4a492d71fc3 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,10 @@ # Various temporary generated files *.tmp +# editor includes +*.iml +.idea + # ------------------------------------------------------------------------------ # Generated by the PHP build system # ------------------------------------------------------------------------------ @@ -251,6 +255,7 @@ phpt.* # Temporary PHP INI configuration file(s) for tests, generated by `make test` tmp-php.ini +php.ini # ------------------------------------------------------------------------------ # Generated by GCC's gcov and LCOV via build/Makefile.gcov @@ -261,6 +266,7 @@ tmp-php.ini /gcovr_html/ /lcov_html/ /php_lcov.info +compile_commands.json # ------------------------------------------------------------------------------ # Archives generated during the PHP release process diff --git a/ext/.DS_Store b/ext/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..733a361d0cdb76ac394c51eac8c72ea07be3d93b GIT binary patch literal 6148 zcmeHKy-LGS6h1dC7=MP2LYHhVMeODnOLTIPzJP5bR%lF6yE)_md;lk3L1!lycNZ5y z+y%i$@H_V&+QhWo6p?e_+%Gvl_nv%#oE#!DopIbIY7mhRW%QP@%nTv_8qn|_ z?d~8=GPasm@hSXm2Ke38D5jK>(Q)zpJ?~FFNg74{QQC*azq-CTczb``DSG1t-fTGC z)!TeP8ZF_pj0V($4(X_Lu6enwMikG#-)N2H{BQdt>9mgdQN?=9_8r&b(>YzBnp5!5 zqce(26`izJX2le1y8PVQYkpWxDti^HS`=5T%WFPyT`J0eGN26n6a(nlEdHuPU6lc4 zKpB`Yz~6@e$`}gf4(+D{iyZ-gb(pQ-nr8{l2?RsI+#x&=<5Gbx)yRlpTsrK5#D#*n zLzhlQh7Thr8<|jyJstZ8Hk?f8P*-I@87MPQbGHrd|GV?&|8kPvDFe#Dzhc1Dqi)o} zBS~+qJRJAh0D1^z;kex4Bn20?6(g2g@jBEB>;Yc@L&4l3ED-$>ur%nR4E!nsU*&#r AUjP6A literal 0 HcmV?d00001 diff --git a/ext/standard/php_fopen_wrapper.c b/ext/standard/php_fopen_wrapper.c index 8926485025a3b..25e1a5d689031 100644 --- a/ext/standard/php_fopen_wrapper.c +++ b/ext/standard/php_fopen_wrapper.c @@ -215,7 +215,8 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const char *pa } if (!strcasecmp(path, "input")) { - php_stream_input_t *input; + + php_stream_input_t *input; if ((options & STREAM_OPEN_FOR_INCLUDE) && !PG(allow_url_include) ) { if (options & REPORT_ERRORS) { @@ -225,14 +226,21 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const char *pa } input = ecalloc(1, sizeof(*input)); + if ((input->body = SG(request_info).request_body)) { + php_stream_rewind(input->body); - } else { + + } else { + input->body = php_stream_temp_create_ex(TEMP_STREAM_DEFAULT, SAPI_POST_BLOCK_SIZE, PG(upload_tmp_dir)); + SG(request_info).request_body = input->body; - } + + } return php_stream_alloc(&php_stream_input_ops, input, 0, "rb"); + } if (!strcasecmp(path, "stdin")) { @@ -261,7 +269,7 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const char *pa if (!strcmp(sapi_module.name, "cli")) { static int cli_out = 0; fd = STDOUT_FILENO; - if (cli_out++) { + if (cli_out) { fd = dup(fd); } else { cli_out = 1; @@ -277,7 +285,7 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const char *pa if (!strcmp(sapi_module.name, "cli")) { static int cli_err = 0; fd = STDERR_FILENO; - if (cli_err++) { + if (cli_err) { fd = dup(fd); } else { cli_err = 1; diff --git a/sapi/apache2handler/php_functions.c b/sapi/apache2handler/php_functions.c index 27b8aab1dfb50..5fe205c47f253 100644 --- a/sapi/apache2handler/php_functions.c +++ b/sapi/apache2handler/php_functions.c @@ -50,6 +50,8 @@ #include "php_apache.h" #include "php_functions_arginfo.h" +#include "ext/standard/sha1.h" +#include "ext/standard/php_standard.h" #ifdef ZTS int php_apache2_info_id; @@ -216,6 +218,127 @@ PHP_FUNCTION(apache_response_headers) } /* }}} */ +/* {{{ Sends response headers required for a WebSocket connection */ +PHP_FUNCTION(apache_websocket_accept) { + php_struct *ctx = SG(server_context); + request_rec *r; + char *key; + char *concat; + unsigned char sha1str[20]; // SHA1 hash size + zend_string *encoded; + char *result; + sapi_header_line ctr = {0}; + apr_socket_t *apr_sock; + int fd; + + r = ctx->r; + + ZEND_PARSE_PARAMETERS_NONE(); + + // Retrieve the Sec-WebSocket-Key header + const apr_array_header_t *fields; + apr_table_entry_t *e = 0; + fields = apr_table_elts(r->headers_in); + e = (apr_table_entry_t *) fields->elts; + for (int i = 0; i < fields->nelts; i++) { + if (strcasecmp(e[i].key, "Sec-WebSocket-Key") == 0) { + key = e[i].val; + break; + } + } + + if (!key) { + php_error_docref(NULL, E_WARNING, "Sec-WebSocket-Key header not found."); + RETURN_FALSE; + } + + size_t key_len = strlen(key); + + // Prepare the source string with the GUID appended + concat = emalloc(key_len + 37); // Key length + GUID length + // @link https://www.rfc-editor.org/rfc/rfc6455 + snprintf(concat, key_len + 37, "%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11", key); + + // Compute the SHA1 hash + PHP_SHA1_CTX context; + PHP_SHA1Init(&context); + PHP_SHA1Update(&context, (unsigned char *)concat, strlen(concat)); + PHP_SHA1Final(sha1str, &context); + efree(concat); + + // Base64 encode the SHA1 hash + encoded = php_base64_encode(sha1str, sizeof(sha1str)); + result = estrndup(ZSTR_VAL(encoded), ZSTR_LEN(encoded)); + zend_string_release(encoded); + + // Send the Upgrade header + ctr.line = "Upgrade: websocket"; + ctr.line_len = sizeof("Upgrade: websocket") - 1; + sapi_header_op(SAPI_HEADER_REPLACE, &ctr); + + // Send the Connection header + ctr.line = "Connection: Upgrade"; + ctr.line_len = sizeof("Connection: Upgrade") - 1; + sapi_header_op(SAPI_HEADER_REPLACE, &ctr); + + // Send the Sec-WebSocket-Accept header + ctr.line_len = sizeof("Sec-WebSocket-Accept: ") - 1 + ZSTR_LEN(encoded) + 1; + char *sec_accept_header = emalloc(ctr.line_len); + snprintf(sec_accept_header, ctr.line_len, "Sec-WebSocket-Accept: %s", result); + ctr.line = sec_accept_header; + sapi_header_op(SAPI_HEADER_REPLACE, &ctr); + efree(sec_accept_header); + + // Flush all output buffers to ensure headers are sent immediately + php_output_flush_all(); + + efree(result); + + apr_sock = ap_get_conn_socket(r->connection); + + // Get the native descriptor + apr_os_sock_get(&fd, apr_sock); + + // Use php_stream_sock_open_from_socket() to create a PHP stream + php_stream *stream = php_stream_sock_open_from_socket(fd, NULL); + + if (!stream) { + RETURN_FALSE; + } + + php_stream_to_zval(stream, return_value); + +} +/* }}} */ + +/* {{{ Sends response headers required for a WebSocket connection */ +PHP_FUNCTION(apache_websocket_stream) { + php_struct *ctx = SG(server_context); + request_rec *r; + apr_socket_t *apr_sock; + int fd; + + r = ctx->r; + + ZEND_PARSE_PARAMETERS_NONE(); + + apr_sock = ap_get_conn_socket(r->connection); + + // Get the native descriptor + apr_os_sock_get(&fd, apr_sock); + + // Use php_stream_sock_open_from_socket() to create a PHP stream + php_stream *stream = php_stream_sock_open_from_socket(fd, NULL); + + if (!stream) { + 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 c5657e9429cab..23e5cf49a2b65 100644 --- a/sapi/apache2handler/php_functions_arginfo.h +++ b/sapi/apache2handler/php_functions_arginfo.h @@ -41,6 +41,8 @@ ZEND_FUNCTION(apache_lookup_uri); ZEND_FUNCTION(virtual); ZEND_FUNCTION(apache_request_headers); ZEND_FUNCTION(apache_response_headers); +ZEND_FUNCTION(apache_websocket_accept); +ZEND_FUNCTION(apache_websocket_stream); ZEND_FUNCTION(apache_note); ZEND_FUNCTION(apache_setenv); ZEND_FUNCTION(apache_getenv); @@ -53,6 +55,8 @@ 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_websocket_accept, NULL) + ZEND_FE(apache_websocket_stream, NULL) ZEND_FE(apache_note, arginfo_apache_note) ZEND_FE(apache_setenv, arginfo_apache_setenv) ZEND_FE(apache_getenv, arginfo_apache_getenv) From 84e35c14e2767a7e7482f4ec4c805c4ef9e3fe44 Mon Sep 17 00:00:00 2001 From: richardtmiles Date: Thu, 25 Apr 2024 08:05:21 -0600 Subject: [PATCH 02/10] Adding PHP_FUNCTION apache_connection_stream to expose ap_get_conn_socket for CGI WebSockets --- sapi/apache2handler/php_functions.c | 97 +-------------------- sapi/apache2handler/php_functions_arginfo.h | 6 +- 2 files changed, 4 insertions(+), 99 deletions(-) diff --git a/sapi/apache2handler/php_functions.c b/sapi/apache2handler/php_functions.c index 5fe205c47f253..20e296667bbd4 100644 --- a/sapi/apache2handler/php_functions.c +++ b/sapi/apache2handler/php_functions.c @@ -218,101 +218,8 @@ PHP_FUNCTION(apache_response_headers) } /* }}} */ -/* {{{ Sends response headers required for a WebSocket connection */ -PHP_FUNCTION(apache_websocket_accept) { - php_struct *ctx = SG(server_context); - request_rec *r; - char *key; - char *concat; - unsigned char sha1str[20]; // SHA1 hash size - zend_string *encoded; - char *result; - sapi_header_line ctr = {0}; - apr_socket_t *apr_sock; - int fd; - - r = ctx->r; - - ZEND_PARSE_PARAMETERS_NONE(); - - // Retrieve the Sec-WebSocket-Key header - const apr_array_header_t *fields; - apr_table_entry_t *e = 0; - fields = apr_table_elts(r->headers_in); - e = (apr_table_entry_t *) fields->elts; - for (int i = 0; i < fields->nelts; i++) { - if (strcasecmp(e[i].key, "Sec-WebSocket-Key") == 0) { - key = e[i].val; - break; - } - } - - if (!key) { - php_error_docref(NULL, E_WARNING, "Sec-WebSocket-Key header not found."); - RETURN_FALSE; - } - - size_t key_len = strlen(key); - - // Prepare the source string with the GUID appended - concat = emalloc(key_len + 37); // Key length + GUID length - // @link https://www.rfc-editor.org/rfc/rfc6455 - snprintf(concat, key_len + 37, "%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11", key); - - // Compute the SHA1 hash - PHP_SHA1_CTX context; - PHP_SHA1Init(&context); - PHP_SHA1Update(&context, (unsigned char *)concat, strlen(concat)); - PHP_SHA1Final(sha1str, &context); - efree(concat); - - // Base64 encode the SHA1 hash - encoded = php_base64_encode(sha1str, sizeof(sha1str)); - result = estrndup(ZSTR_VAL(encoded), ZSTR_LEN(encoded)); - zend_string_release(encoded); - - // Send the Upgrade header - ctr.line = "Upgrade: websocket"; - ctr.line_len = sizeof("Upgrade: websocket") - 1; - sapi_header_op(SAPI_HEADER_REPLACE, &ctr); - - // Send the Connection header - ctr.line = "Connection: Upgrade"; - ctr.line_len = sizeof("Connection: Upgrade") - 1; - sapi_header_op(SAPI_HEADER_REPLACE, &ctr); - - // Send the Sec-WebSocket-Accept header - ctr.line_len = sizeof("Sec-WebSocket-Accept: ") - 1 + ZSTR_LEN(encoded) + 1; - char *sec_accept_header = emalloc(ctr.line_len); - snprintf(sec_accept_header, ctr.line_len, "Sec-WebSocket-Accept: %s", result); - ctr.line = sec_accept_header; - sapi_header_op(SAPI_HEADER_REPLACE, &ctr); - efree(sec_accept_header); - - // Flush all output buffers to ensure headers are sent immediately - php_output_flush_all(); - - efree(result); - - apr_sock = ap_get_conn_socket(r->connection); - - // Get the native descriptor - apr_os_sock_get(&fd, apr_sock); - - // Use php_stream_sock_open_from_socket() to create a PHP stream - php_stream *stream = php_stream_sock_open_from_socket(fd, NULL); - - if (!stream) { - RETURN_FALSE; - } - - php_stream_to_zval(stream, return_value); - -} -/* }}} */ - -/* {{{ Sends response headers required for a WebSocket connection */ -PHP_FUNCTION(apache_websocket_stream) { +/* {{{ 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; diff --git a/sapi/apache2handler/php_functions_arginfo.h b/sapi/apache2handler/php_functions_arginfo.h index 23e5cf49a2b65..ce6d524336759 100644 --- a/sapi/apache2handler/php_functions_arginfo.h +++ b/sapi/apache2handler/php_functions_arginfo.h @@ -41,8 +41,7 @@ ZEND_FUNCTION(apache_lookup_uri); ZEND_FUNCTION(virtual); ZEND_FUNCTION(apache_request_headers); ZEND_FUNCTION(apache_response_headers); -ZEND_FUNCTION(apache_websocket_accept); -ZEND_FUNCTION(apache_websocket_stream); +ZEND_FUNCTION(apache_connection_stream); ZEND_FUNCTION(apache_note); ZEND_FUNCTION(apache_setenv); ZEND_FUNCTION(apache_getenv); @@ -55,8 +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_websocket_accept, NULL) - ZEND_FE(apache_websocket_stream, NULL) + 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) From 15cff3f0ea49b3298ef1341fe3314e02bae7e5bf Mon Sep 17 00:00:00 2001 From: richardtmiles Date: Thu, 25 Apr 2024 08:48:02 -0600 Subject: [PATCH 03/10] Added the apache_connection_stream() function for CGI WebSockets --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index f9099b98ac89a..58700ebae46e8 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.4.0alpha1 +- apache2handler: + . Added the apache_connection_stream() function for CGI WebSockets. (Richard Tyler Miles) + - Core: . Added zend_call_stack_get implementation for NetBSD, DragonFlyBSD, Solaris and Haiku. (David Carlier) From d4067d836dfa0c44ad59c20a5dd498e58cb9b729 Mon Sep 17 00:00:00 2001 From: richardtmiles Date: Thu, 25 Apr 2024 08:51:48 -0600 Subject: [PATCH 04/10] Cleaning commit, removing import --- ext/standard/php_fopen_wrapper.c | 11 ----------- sapi/apache2handler/php_functions.c | 1 - 2 files changed, 12 deletions(-) diff --git a/ext/standard/php_fopen_wrapper.c b/ext/standard/php_fopen_wrapper.c index 25e1a5d689031..4acd2f1104736 100644 --- a/ext/standard/php_fopen_wrapper.c +++ b/ext/standard/php_fopen_wrapper.c @@ -215,32 +215,21 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const char *pa } if (!strcasecmp(path, "input")) { - php_stream_input_t *input; - if ((options & STREAM_OPEN_FOR_INCLUDE) && !PG(allow_url_include) ) { if (options & REPORT_ERRORS) { php_error_docref(NULL, E_WARNING, "URL file-access is disabled in the server configuration"); } return NULL; } - input = ecalloc(1, sizeof(*input)); - if ((input->body = SG(request_info).request_body)) { - php_stream_rewind(input->body); - } else { - input->body = php_stream_temp_create_ex(TEMP_STREAM_DEFAULT, SAPI_POST_BLOCK_SIZE, PG(upload_tmp_dir)); - SG(request_info).request_body = input->body; - } - return php_stream_alloc(&php_stream_input_ops, input, 0, "rb"); - } if (!strcasecmp(path, "stdin")) { diff --git a/sapi/apache2handler/php_functions.c b/sapi/apache2handler/php_functions.c index 20e296667bbd4..69b24994c327b 100644 --- a/sapi/apache2handler/php_functions.c +++ b/sapi/apache2handler/php_functions.c @@ -50,7 +50,6 @@ #include "php_apache.h" #include "php_functions_arginfo.h" -#include "ext/standard/sha1.h" #include "ext/standard/php_standard.h" #ifdef ZTS From 7adc1e19846d98a0bce20a4069f9294fa0db67ad Mon Sep 17 00:00:00 2001 From: richardtmiles Date: Thu, 25 Apr 2024 10:04:13 -0600 Subject: [PATCH 05/10] updating branch name --- sapi/apache2handler/php_functions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sapi/apache2handler/php_functions.c b/sapi/apache2handler/php_functions.c index 69b24994c327b..96f2f0efd9b12 100644 --- a/sapi/apache2handler/php_functions.c +++ b/sapi/apache2handler/php_functions.c @@ -217,7 +217,7 @@ PHP_FUNCTION(apache_response_headers) } /* }}} */ -/* {{{ The allows for direct select calls on apache's connection socket */ +/* {{{ 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; From 60c1d6fdfa539520d44f9c41894fd342db3704db Mon Sep 17 00:00:00 2001 From: richardtmiles Date: Thu, 25 Apr 2024 16:29:48 -0600 Subject: [PATCH 06/10] untracking .DS_Store --- ext/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 ext/.DS_Store diff --git a/ext/.DS_Store b/ext/.DS_Store deleted file mode 100644 index 733a361d0cdb76ac394c51eac8c72ea07be3d93b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKy-LGS6h1dC7=MP2LYHhVMeODnOLTIPzJP5bR%lF6yE)_md;lk3L1!lycNZ5y z+y%i$@H_V&+QhWo6p?e_+%Gvl_nv%#oE#!DopIbIY7mhRW%QP@%nTv_8qn|_ z?d~8=GPasm@hSXm2Ke38D5jK>(Q)zpJ?~FFNg74{QQC*azq-CTczb``DSG1t-fTGC z)!TeP8ZF_pj0V($4(X_Lu6enwMikG#-)N2H{BQdt>9mgdQN?=9_8r&b(>YzBnp5!5 zqce(26`izJX2le1y8PVQYkpWxDti^HS`=5T%WFPyT`J0eGN26n6a(nlEdHuPU6lc4 zKpB`Yz~6@e$`}gf4(+D{iyZ-gb(pQ-nr8{l2?RsI+#x&=<5Gbx)yRlpTsrK5#D#*n zLzhlQh7Thr8<|jyJstZ8Hk?f8P*-I@87MPQbGHrd|GV?&|8kPvDFe#Dzhc1Dqi)o} zBS~+qJRJAh0D1^z;kex4Bn20?6(g2g@jBEB>;Yc@L&4l3ED-$>ur%nR4E!nsU*&#r AUjP6A From 73bb76430de827315ae5ed3ffc6de1fcc84cd317 Mon Sep 17 00:00:00 2001 From: richardtmiles Date: Thu, 25 Apr 2024 16:30:39 -0600 Subject: [PATCH 07/10] untracking .DS_Store --- .DS_Store | Bin 10244 -> 0 bytes .gitignore | 3 ++- 2 files changed, 2 insertions(+), 1 deletion(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 8060b2bde57951e48b081ddb9ebc6b9af91076fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10244 zcmeHMPiS0482@H>lWd5r)zCJ!nk?p^U|V*R_E3ZErfd!-i0E3-fRLmcvT1j-+ubDX zL1c^dU_pp@QBm;VzZL{@5fqUg>M56krBM%21SvGMl$N%a9{PPV^WOVr-|V)hMan#Q z@7wI}``+(2znM30X957?&{94PkOY7@o)ot{h8N30IGv#*qQ7|)qriHABT$4{yv`Tr zLfP&M=YVs-Ip7>{4mbz?4-Vivn~r#oitg$ha1J;JdSFAjxnQST}4$6LY0Hi%tEhFgk;CM zq)Z2qQPEwU1I~f41GIMUhCQ@qhbmvcr*lWjrHU%pdfT2=Drd7Z#qtcI@z*{(nC`ps z+i0`Q{6l6|3Y5>9OGJ6Uz)hL{hHL`*OtnG0vpbG2ZvL{ z+vV{>0hVBfvx8W<8qVMvwmvcH`O$D6uB3Su*8|ZhB!dprGY@&(VVO3xz?rvAl$epKlbi)j4Uy!;>*rqBRGt|T2h&_vIzH?#S>tD zb^4c|pHa`7uH#OGQO=jRv_gC_Z2LTp0mJ{u#t-xm`WWZ@?~~r~o!)$>YdNb8=e&`P z^NN?AhIv>p`h9f$l;qVI=Z!v_Sp9WV&$B)r_-w;DFN{}+w+rW!GWPwF+&wm04gI%< z!Wmq{2cKU*w{}%(Xt)n|pm~;|XMp6O#})Kp5ekM6o8SM$F|Oh8%3JBOn!o&7&Thjw zuXwWV@#5SLRf89{+|s-f4ioHIsj|aRqobz_(b-&kemZ{>1tDxIvzl&Y;%cKj846dQ~{SPm1c>Ugx6)0(* z#r1%oM+@g&dZ*PwT6))CHc_tQtJSAGFIYYAeS3z%f8a~v??mP*_QWzeV!8qGY$MJ! z9Ek4lG#K~bDw^dOI@Dq-25&$PUWZrscmTM&fEs*^^MBg6_V_!hFBl&5f(K z$N%=)?c)Kn4d=X(@8q~6Zg)5boCD5*b~+GMWJ%ipA8Y>q|8`1pT+RXKK${&9v1~4T z2ubzcdWfEu=Se)L@T7zC>MF_-yvP+iM!6l2f6#XP^LSEjiXt8OIiq7;Mf?Vjw*NDr X#XbT5eFkp*58&4Sa&ZEW*!urIn%a7w diff --git a/.gitignore b/.gitignore index 9b4a492d71fc3..d2f10ccdfa77b 100644 --- a/.gitignore +++ b/.gitignore @@ -256,6 +256,7 @@ phpt.* # Temporary PHP INI configuration file(s) for tests, generated by `make test` tmp-php.ini php.ini +.DS_Store # ------------------------------------------------------------------------------ # Generated by GCC's gcov and LCOV via build/Makefile.gcov @@ -266,7 +267,7 @@ php.ini /gcovr_html/ /lcov_html/ /php_lcov.info -compile_commands.json +/compile_commands.json # ------------------------------------------------------------------------------ # Archives generated during the PHP release process From 5c0084a1c2ed084e6b92007de06e1d91ea745d1c Mon Sep 17 00:00:00 2001 From: richardtmiles Date: Thu, 25 Apr 2024 17:00:30 -0600 Subject: [PATCH 08/10] error handling --- sapi/apache2handler/php_functions.c | 31 ++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/sapi/apache2handler/php_functions.c b/sapi/apache2handler/php_functions.c index 96f2f0efd9b12..584bfa5a9e521 100644 --- a/sapi/apache2handler/php_functions.c +++ b/sapi/apache2handler/php_functions.c @@ -223,25 +223,50 @@ PHP_FUNCTION(apache_connection_stream) { request_rec *r; apr_socket_t *apr_sock; int fd; + php_stream *stream; + + // Ensure the server context is available + if (!ctx) { + php_error_docref(NULL, E_WARNING, "Server context is not available"); + RETURN_FALSE; + } r = ctx->r; + // Ensure the request record is available + if (!r) { + php_error_docref(NULL, E_WARNING, "Request record is not available"); + RETURN_FALSE; + } + + // Check for proper parsing of parameters (none expected) ZEND_PARSE_PARAMETERS_NONE(); apr_sock = ap_get_conn_socket(r->connection); + // Ensure the connection socket is available + if (!apr_sock) { + php_error_docref(NULL, E_WARNING, "Failed to obtain connection socket"); + RETURN_FALSE; + } + // Get the native descriptor - apr_os_sock_get(&fd, apr_sock); + if (apr_os_sock_get(&fd, apr_sock) != APR_SUCCESS) { + php_error_docref(NULL, E_WARNING, "Failed to get native socket descriptor"); + RETURN_FALSE; + } // Use php_stream_sock_open_from_socket() to create a PHP stream - php_stream *stream = php_stream_sock_open_from_socket(fd, NULL); + stream = php_stream_sock_open_from_socket(fd, NULL); + // Check if the stream was successfully created if (!stream) { + php_error_docref(NULL, E_WARNING, "Failed to open stream from socket"); RETURN_FALSE; } + // Convert the php_stream to a zval and return it php_stream_to_zval(stream, return_value); - } /* }}} */ From bea8d2deac5885d4c5bef7a2487b5ecb4a5f1ffc Mon Sep 17 00:00:00 2001 From: richardtmiles Date: Thu, 25 Apr 2024 17:03:23 -0600 Subject: [PATCH 09/10] order of ZEND_PARSE_PARAMETERS_NONE --- sapi/apache2handler/php_functions.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sapi/apache2handler/php_functions.c b/sapi/apache2handler/php_functions.c index 584bfa5a9e521..4420fc2c3f681 100644 --- a/sapi/apache2handler/php_functions.c +++ b/sapi/apache2handler/php_functions.c @@ -225,6 +225,10 @@ PHP_FUNCTION(apache_connection_stream) { int fd; php_stream *stream; + + // Check for proper parsing of parameters (none expected) + ZEND_PARSE_PARAMETERS_NONE(); + // Ensure the server context is available if (!ctx) { php_error_docref(NULL, E_WARNING, "Server context is not available"); @@ -239,9 +243,6 @@ PHP_FUNCTION(apache_connection_stream) { RETURN_FALSE; } - // Check for proper parsing of parameters (none expected) - ZEND_PARSE_PARAMETERS_NONE(); - apr_sock = ap_get_conn_socket(r->connection); // Ensure the connection socket is available From 5641cf60ac1bf0d98b9c660fc34781a7d6d2a530 Mon Sep 17 00:00:00 2001 From: richardtmiles Date: Fri, 26 Apr 2024 11:49:16 -0600 Subject: [PATCH 10/10] PHP CLISERVER apache_connection_stream function When a connection is received you must hit enter in your server terminal to complete the connection. CLI server is single threaded, so only basic debugging can be done regarding websockets. --- sapi/cli/php_cli_server.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c index e84defb3da469..dfcfcb6801b8b 100644 --- a/sapi/cli/php_cli_server.c +++ b/sapi/cli/php_cli_server.c @@ -458,6 +458,27 @@ PHP_FUNCTION(apache_response_headers) /* {{{ */ } /* }}} */ +PHP_FUNCTION(apache_connection_stream) /* {{{ */ +{ + php_cli_server_client *client = SG(server_context); + + // Check for proper parsing of parameters (none expected) + ZEND_PARSE_PARAMETERS_NONE(); + + // Use php_stream_sock_open_from_socket() to create a PHP stream + php_stream *stream = php_stream_sock_open_from_socket(client->sock, NULL); + + // Check if the stream was successfully created + if (!stream) { + php_error_docref(NULL, E_WARNING, "Failed to open stream from socket in cli server"); + RETURN_FALSE; + } + + // Convert the php_stream to a zval and return it + php_stream_to_zval(stream, return_value); +} +/* }}} */ + /* {{{ cli_server module */ static void cli_server_init_globals(zend_cli_server_globals *cg) @@ -506,6 +527,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 };