diff options
Diffstat (limited to 'sapi')
32 files changed, 1106 insertions, 130 deletions
diff --git a/sapi/apache/config.m4 b/sapi/apache/config.m4 index 1961289de0..7b0ee562eb 100644 --- a/sapi/apache/config.m4 +++ b/sapi/apache/config.m4 @@ -20,7 +20,7 @@ fi dnl Apache 1.x shared module PHP_ARG_WITH(apxs,, -[ --with-apxs[=FILE] Build shared Apache 1.x module. FILE is the optional +[ --with-apxs[=FILE] Build shared Apache 1.x module. FILE is the optional pathname to the Apache apxs tool [apxs]], no, no) AC_MSG_CHECKING([for Apache 1.x module support via DSO through APXS]) @@ -123,7 +123,7 @@ fi dnl Apache 1.x static module PHP_ARG_WITH(apache,, -[ --with-apache[=DIR] Build Apache 1.x module. DIR is the top-level Apache +[ --with-apache[=DIR] Build Apache 1.x module. DIR is the top-level Apache build directory [/usr/local/apache]], no, no) AC_MSG_CHECKING([for Apache 1.x module support]) @@ -237,7 +237,7 @@ if test -z "$enable_mod_charset" && test "$with_mod_charset"; then fi PHP_ARG_ENABLE(mod-charset, whether to enable Apache charset compatibility option, -[ --enable-mod-charset APACHE: Enable transfer tables for mod_charset (Rus Apache)], no, no) +[ --enable-mod-charset APACHE: Enable transfer tables for mod_charset (Rus Apache)], no, no) if test "$PHP_MOD_CHARSET" = "yes"; then AC_DEFINE(USE_TRANSFER_TABLES, 1, [ ]) diff --git a/sapi/apache2handler/config.m4 b/sapi/apache2handler/config.m4 index 753de10ba8..02f8a0b3ad 100644 --- a/sapi/apache2handler/config.m4 +++ b/sapi/apache2handler/config.m4 @@ -3,7 +3,7 @@ dnl $Id$ dnl PHP_ARG_WITH(apxs2,, -[ --with-apxs2[=FILE] Build shared Apache 2.0 Handler module. FILE is the optional +[ --with-apxs2[=FILE] Build shared Apache 2.0 Handler module. FILE is the optional pathname to the Apache apxs tool [apxs]], no, no) AC_MSG_CHECKING([for Apache 2.0 handler-module support via DSO through APXS]) diff --git a/sapi/apache_hooks/config.m4 b/sapi/apache_hooks/config.m4 index 672f298084..e2c71b4274 100644 --- a/sapi/apache_hooks/config.m4 +++ b/sapi/apache_hooks/config.m4 @@ -239,7 +239,7 @@ if test -z "$enable_mod_charset" && test "$with_mod_charset"; then fi PHP_ARG_ENABLE(mod-charset, whether to enable Apache charset compatibility option, -[ --enable-mod-charset APACHE (hooks): Enable transfer tables for mod_charset (Rus Apache)], no, no) +[ --enable-mod-charset APACHE (hooks): Enable transfer tables for mod_charset (Rus Apache)], no, no) if test "$PHP_MOD_CHARSET" = "yes"; then AC_DEFINE(USE_TRANSFER_TABLES, 1, [ ]) diff --git a/sapi/caudium/config.m4 b/sapi/caudium/config.m4 index 8aba33e23d..5ce55f3f01 100644 --- a/sapi/caudium/config.m4 +++ b/sapi/caudium/config.m4 @@ -4,7 +4,7 @@ dnl RESULT=no PHP_ARG_WITH(caudium,, -[ --with-caudium[=DIR] Build PHP as a Pike module for use with Caudium. +[ --with-caudium[=DIR] Build PHP as a Pike module for use with Caudium. DIR is the Caudium server dir [/usr/local/caudium/server]], no, no) AC_MSG_CHECKING([for Caudium support]) diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c index b8ff878fe4..b1e12f7324 100644 --- a/sapi/cgi/cgi_main.c +++ b/sapi/cgi/cgi_main.c @@ -884,7 +884,6 @@ static int sapi_cgi_activate(TSRMLS_D) } else { doc_root = getenv("DOCUMENT_ROOT"); } - /* DOCUMENT_ROOT should also be defined at this stage..but better check it anyway */ if (doc_root) { doc_root_len = strlen(doc_root); @@ -1689,8 +1688,8 @@ static void add_response_header(sapi_header_struct *h, zval *return_value TSRMLS PHP_FUNCTION(apache_response_headers) /* {{{ */ { - if (ZEND_NUM_ARGS() > 0) { - WRONG_PARAM_COUNT; + if (zend_parse_parameters_none() == FAILURE) { + return; } if (!&SG(sapi_headers).headers) { @@ -1956,7 +1955,11 @@ consult the installation file that came with this distribution, or visit \n\ } if (bindpath) { - fcgi_fd = fcgi_listen(bindpath, 128); + int backlog = 128; + if (getenv("PHP_FCGI_BACKLOG")) { + backlog = atoi(getenv("PHP_FCGI_BACKLOG")); + } + fcgi_fd = fcgi_listen(bindpath, backlog); if (fcgi_fd < 0) { fprintf(stderr, "Couldn't create FastCGI listen socket on port %s\n", bindpath); #ifdef ZTS diff --git a/sapi/cgi/tests/bug61605.phpt b/sapi/cgi/tests/bug61605.phpt index c6e4cf20ca..9c29e6dda2 100644 --- a/sapi/cgi/tests/bug61605.phpt +++ b/sapi/cgi/tests/bug61605.phpt @@ -4,6 +4,8 @@ Bug #61605 (header_remove() does not remove all headers) <?php include "skipif.inc"; ?> --GET-- foo=bar +--INI-- +expose_php=On --FILE-- <?php header("A: first"); diff --git a/sapi/cli/config.m4 b/sapi/cli/config.m4 index cdfa1f7daf..9a1b98da46 100644 --- a/sapi/cli/config.m4 +++ b/sapi/cli/config.m4 @@ -6,6 +6,23 @@ PHP_ARG_ENABLE(cli,, [ --disable-cli Disable building CLI version of PHP (this forces --without-pear)], yes, no) +AC_CHECK_FUNCS(setproctitle) + +AC_CHECK_HEADERS([sys/pstat.h]) + +AC_CACHE_CHECK([for PS_STRINGS], [cli_cv_var_PS_STRINGS], +[AC_TRY_LINK( +[#include <machine/vmparam.h> +#include <sys/exec.h> +], +[PS_STRINGS->ps_nargvstr = 1; +PS_STRINGS->ps_argvstr = "foo";], +[cli_cv_var_PS_STRINGS=yes], +[cli_cv_var_PS_STRINGS=no])]) +if test "$cli_cv_var_PS_STRINGS" = yes ; then + AC_DEFINE([HAVE_PS_STRINGS], [], [Define to 1 if the PS_STRINGS thing exists.]) +fi + AC_MSG_CHECKING(for CLI build) if test "$PHP_CLI" != "no"; then PHP_ADD_MAKEFILE_FRAGMENT($abs_srcdir/sapi/cli/Makefile.frag) @@ -14,7 +31,7 @@ if test "$PHP_CLI" != "no"; then SAPI_CLI_PATH=sapi/cli/php dnl Select SAPI - PHP_SELECT_SAPI(cli, program, php_cli.c php_http_parser.c php_cli_server.c,, '$(SAPI_CLI_PATH)') + PHP_SELECT_SAPI(cli, program, php_cli.c php_http_parser.c php_cli_server.c ps_title.c php_cli_process_title.c,, '$(SAPI_CLI_PATH)') case $host_alias in *aix*) diff --git a/sapi/cli/config.w32 b/sapi/cli/config.w32 index 4d0dad58e8..adcbb2b496 100644 --- a/sapi/cli/config.w32 +++ b/sapi/cli/config.w32 @@ -6,7 +6,7 @@ ARG_ENABLE('crt-debug', 'Enable CRT memory dumps for debugging sent to STDERR', ARG_ENABLE('cli-win32', 'Build console-less CLI version of PHP', 'no'); if (PHP_CLI == "yes") { - SAPI('cli', 'php_cli.c php_http_parser.c php_cli_server.c', 'php.exe'); + SAPI('cli', 'php_cli.c php_http_parser.c php_cli_server.c php_cli_process_title.c ps_title.c', 'php.exe'); ADD_FLAG("LIBS_CLI", "ws2_32.lib"); if (PHP_CRT_DEBUG == "yes") { ADD_FLAG("CFLAGS_CLI", "/D PHP_WIN32_DEBUG_HEAP"); @@ -15,7 +15,7 @@ if (PHP_CLI == "yes") { } if (PHP_CLI_WIN32 == "yes") { - SAPI('cli_win32', 'cli_win32.c', 'php-win.exe'); + SAPI('cli_win32', 'cli_win32.c php_cli_process_title.c ps_title.c', 'php-win.exe'); ADD_FLAG("LDFLAGS_CLI_WIN32", "/stack:8388608"); } diff --git a/sapi/cli/php.1.in b/sapi/cli/php.1.in index fff4363321..c062f3d20e 100644 --- a/sapi/cli/php.1.in +++ b/sapi/cli/php.1.in @@ -1,24 +1,24 @@ -.TH PHP 1 "2014" "The PHP Group" "Scripting Language" +.TH @program_prefix@php 1 "2014" "The PHP Group" "Scripting Language" .SH NAME -php \- PHP Command Line Interface 'CLI' +@program_prefix@php \- PHP Command Line Interface 'CLI' .P -php-cgi \- PHP Common Gateway Interface 'CGI' command +@program_prefix@php-cgi \- PHP Common Gateway Interface 'CGI' command .SH SYNOPSIS -.B php +.B @program_prefix@php [options] [ .B \-f\fP ] .IR file [[\-\-] .IR args.\|.\|. ] .LP -.B php +.B @program_prefix@php [options] .B \-r .IR code [[\-\-] .IR args.\|.\|. ] .LP -.B php +.B @program_prefix@php [options] [\-B .IR begin_code ] .B \-R @@ -28,7 +28,7 @@ php-cgi \- PHP Common Gateway Interface 'CGI' command [[\-\-] .IR args.\|.\|. ] .LP -.B php +.B @program_prefix@php [options] [\-B .IR begin_code ] .B \-F @@ -38,13 +38,13 @@ php-cgi \- PHP Common Gateway Interface 'CGI' command [[\-\-] .IR args.\|.\|. ] .LP -.B php +.B @program_prefix@php [options] \-\- [ .IR args.\|.\|. ] .LP -\fBphp \fP[options] \fB\-a\fP +\fB@program_prefix@php \fP[options] \fB\-a\fP .LP -.B php +.B @program_prefix@php [options] \-S .IR addr:port [\-t @@ -374,35 +374,35 @@ The standard configuration file will only be used when cannot be found. .SH EXAMPLES .TP 5 -\fIphp \-r 'echo "Hello World\\n";'\fP +\fI@program_prefix@php \-r 'echo "Hello World\\n";'\fP This command simply writes the text "Hello World" to standard out. .TP -\fIphp \-r 'print_r(gd_info());'\fP +\fI@program_prefix@php \-r 'print_r(gd_info());'\fP This shows the configuration of your gd extension. You can use this to easily check which image formats you can use. If you have any dynamic modules you may want to use the same ini file that php uses when executed from your webserver. There are more extensions which have such a function. For dba use: .RS -\fIphp \-r 'print_r(dba_handlers(1));'\fP +\fI@program_prefix@php \-r 'print_r(dba_handlers(1));'\fP .RE .TP -\fIphp \-R 'echo strip_tags($argn)."\\n";'\fP +\fI@program_prefix@php \-R 'echo strip_tags($argn)."\\n";'\fP This PHP command strips off the HTML tags line by line and outputs the result. To see how it works you can first look at the following PHP command \'\fIphp \-d html_errors=1 \-i\fP\' which uses PHP to output HTML formatted configuration information. If you then combine those two \'\fIphp \.\.\.|php \.\.\.\fP\' you'll see what happens. .TP -\fIphp \-E 'echo "Lines: $argi\\n";'\fP +\fI@program_prefix@php \-E 'echo "Lines: $argi\\n";'\fP Using this PHP command you can count the lines being input. .TP -\fIphp \-R '@$l+=count(file($argn));' \-E 'echo "Lines:$l\\n";'\fP +\fI@program_prefix@php \-R '@$l+=count(file($argn));' \-E 'echo "Lines:$l\\n";'\fP In this example PHP expects each input line being a file. It counts all lines of the files specified by each input line and shows the summarized result. You may combine this with tools like find and change the php scriptlet. .TP -\fIphp \-R 'echo "$argn\\n"; fgets(STDIN);'\fP +\fI@program_prefix@php \-R 'echo "$argn\\n"; fgets(STDIN);'\fP Since you have access to STDIN from within \-B \-R \-F and \-E you can skip certain input lines with your code. But note that in such cases $argi only counts the lines being processed by php itself. Having read this you will @@ -454,7 +454,7 @@ contributors all around the world. .SH VERSION INFORMATION This manpage describes \fBphp\fP, version @PHP_VERSION@. .SH COPYRIGHT -Copyright \(co 1997\-2013 The PHP Group +Copyright \(co 1997\-2014 The PHP Group .LP This source file is subject to version 3.01 of the PHP license, that is bundled with this package in the file LICENSE, and is diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c index 07371ee8e3..9daa382eec 100644 --- a/sapi/cli/php_cli.c +++ b/sapi/cli/php_cli.c @@ -86,6 +86,9 @@ #include "php_cli_server.h" #endif +#include "ps_title.h" +#include "php_cli_process_title.h" + #ifndef PHP_WIN32 # define php_select(m, r, w, e, t) select(m, r, w, e, t) #else @@ -478,6 +481,8 @@ ZEND_END_ARG_INFO() static const zend_function_entry additional_functions[] = { ZEND_FE(dl, arginfo_dl) + PHP_FE(cli_set_process_title, arginfo_cli_set_process_title) + PHP_FE(cli_get_process_title, arginfo_cli_get_process_title) {NULL, NULL, NULL} }; @@ -1201,6 +1206,7 @@ int main(int argc, char *argv[]) int argc = __argc; char **argv = __argv; #endif + int c; int exit_status = SUCCESS; int module_started = 0, sapi_started = 0; @@ -1212,6 +1218,12 @@ int main(int argc, char *argv[]) int ini_ignore = 0; sapi_module_struct *sapi_module = &cli_sapi_module; + /* + * Do not move this initialization. It needs to happen before argv is used + * in any way. + */ + argv = save_ps_args(argc, argv); + cli_sapi_module.additional_functions = additional_functions; #if defined(PHP_WIN32) && defined(_DEBUG) && defined(PHP_WIN32_DEBUG_HEAP) @@ -1300,6 +1312,7 @@ int main(int argc, char *argv[]) #ifndef PHP_CLI_WIN32_NO_CONSOLE case 'S': sapi_module = &cli_server_sapi_module; + cli_server_sapi_module.additional_functions = server_additional_functions; break; #endif case 'h': /* help & quit */ @@ -1386,6 +1399,11 @@ out: tsrm_shutdown(); #endif + /* + * Do not move this de-initialization. It needs to happen right before + * exiting. + */ + cleanup_ps_args(argv); exit(exit_status); } /* }}} */ diff --git a/sapi/cli/php_cli_process_title.c b/sapi/cli/php_cli_process_title.c new file mode 100644 index 0000000000..dec5613670 --- /dev/null +++ b/sapi/cli/php_cli_process_title.c @@ -0,0 +1,80 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2014 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | 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. | + +----------------------------------------------------------------------+ + | Author: Keyur Govande (kgovande@gmail.com) | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_cli_process_title.h" +#include "ps_title.h" + +/* {{{ proto boolean cli_set_process_title(string arg) + Return a boolean to confirm if the process title was successfully changed or not */ +PHP_FUNCTION(cli_set_process_title) +{ + char *title = NULL; + int title_len; + int rc; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &title, &title_len) == FAILURE) { + return; + } + + rc = set_ps_title(title); + if (rc == PS_TITLE_SUCCESS) { + RETURN_TRUE; + } + + php_error_docref(NULL TSRMLS_CC, E_WARNING, "cli_set_process_title had an error: %s", ps_title_errno(rc)); + RETURN_FALSE; +} +/* }}} */ + +/* {{{ proto string cli_get_process_title() + Return a string with the current process title. NULL if error. */ +PHP_FUNCTION(cli_get_process_title) +{ + int length = 0; + const char* title = NULL; + int rc; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + rc = get_ps_title(&length, &title); + if (rc != PS_TITLE_SUCCESS) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "cli_get_process_title had an error: %s", ps_title_errno(rc)); + RETURN_NULL(); + } + + RETURN_STRINGL(title, length, 1); +} +/* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/sapi/cli/php_cli_process_title.h b/sapi/cli/php_cli_process_title.h new file mode 100644 index 0000000000..bd44d99111 --- /dev/null +++ b/sapi/cli/php_cli_process_title.h @@ -0,0 +1,43 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2014 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | 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. | + +----------------------------------------------------------------------+ + | Author: Keyur Govande (kgovande@gmail.com) | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#ifndef PHP_PS_TITLE_HEADER +#define PHP_PS_TITLE_HEADER + +ZEND_BEGIN_ARG_INFO(arginfo_cli_set_process_title, 0) + ZEND_ARG_INFO(0, title) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO(arginfo_cli_get_process_title, 0) +ZEND_END_ARG_INFO() + +PHP_FUNCTION(cli_set_process_title); +PHP_FUNCTION(cli_get_process_title); + +#endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c index 375aa25c42..6cefa2de9f 100644 --- a/sapi/cli/php_cli_server.c +++ b/sapi/cli/php_cli_server.c @@ -105,6 +105,8 @@ #include "php_http_parser.h" #include "php_cli_server.h" +#include "php_cli_process_title.h" + #define OUTPUT_NOT_CHECKED -1 #define OUTPUT_IS_TTY 1 #define OUTPUT_NOT_TTY 0 @@ -131,6 +133,7 @@ typedef struct php_cli_server_request { char *query_string; size_t query_string_len; HashTable headers; + HashTable headers_original_case; char *content; size_t content_len; const char *ext; @@ -254,7 +257,7 @@ static php_cli_server_http_response_status_code_pair status_map[] = { static php_cli_server_http_response_status_code_pair template_map[] = { { 400, "<h1>%s</h1><p>Your browser sent a request that this server could not understand.</p>" }, - { 404, "<h1>%s</h1><p>The requested resource %s was not found on this server.</p>" }, + { 404, "<h1>%s</h1><p>The requested resource <code class=\"url\">%s</code> was not found on this server.</p>" }, { 500, "<h1>%s</h1><p>The server is temporarily unavailable.</p>" }, { 501, "<h1>%s</h1><p>Request method not supported.</p>" } }; @@ -268,12 +271,52 @@ static php_cli_server_ext_mime_type_pair mime_type_map[] = { { "jpg", "image/jpeg" }, { "jpeg", "image/jpeg" }, { "jpe", "image/jpeg" }, + { "pdf", "application/pdf" }, { "png", "image/png" }, { "svg", "image/svg+xml" }, { "txt", "text/plain" }, { "webm", "video/webm" }, { "ogv", "video/ogg" }, { "ogg", "audio/ogg" }, + { "3gp", "video/3gpp" }, /* This is standard video format used for MMS in phones */ + { "apk", "application/vnd.android.package-archive" }, + { "avi", "video/x-msvideo" }, + { "bmp", "image/x-ms-bmp" }, + { "csv", "text/comma-separated-values" }, + { "doc", "application/msword" }, + { "docx", "application/msword" }, + { "flac", "audio/flac" }, + { "gz", "application/x-gzip" }, + { "gzip", "application/x-gzip" }, + { "ics", "text/calendar" }, + { "kml", "application/vnd.google-earth.kml+xml" }, + { "kmz", "application/vnd.google-earth.kmz" }, + { "m4a", "audio/mp4" }, + { "mp3", "audio/mpeg" }, + { "mp4", "video/mp4" }, + { "mpg", "video/mpeg" }, + { "mpeg", "video/mpeg" }, + { "mov", "video/quicktime" }, + { "odp", "application/vnd.oasis.opendocument.presentation" }, + { "ods", "application/vnd.oasis.opendocument.spreadsheet" }, + { "odt", "application/vnd.oasis.opendocument.text" }, + { "oga", "audio/ogg" }, + { "pdf", "application/pdf" }, + { "pptx", "application/vnd.ms-powerpoint" }, + { "pps", "application/vnd.ms-powerpoint" }, + { "qt", "video/quicktime" }, + { "swf", "application/x-shockwave-flash" }, + { "tar", "application/x-tar" }, + { "text", "text/plain" }, + { "tif", "image/tiff" }, + { "wav", "audio/wav" }, + { "wmv", "video/x-ms-wmv" }, + { "xls", "application/vnd.ms-excel" }, + { "xlsx", "application/vnd.ms-excel" }, + { "zip", "application/x-zip-compressed" }, + { "xml", "application/xml" }, + { "xsl", "application/xml" }, + { "xsd", "application/xml" }, { NULL, NULL } }; @@ -291,8 +334,10 @@ ZEND_DECLARE_MODULE_GLOBALS(cli_server); * copied from ext/standard/info.c */ static const char php_cli_server_css[] = "<style>\n" \ - "body { background-color: #ffffff; color: #000000; }\n" \ - "h1 { font-family: sans-serif; font-size: 150%; background-color: #9999cc; font-weight: bold; color: #000000; margin-top: 0;}\n" \ + "body { background-color: #fcfcfc; color: #333333; margin: 0; padding:0; }\n" \ + "h1 { font-size: 1.5em; font-weight: normal; background-color: #9999cc; min-height:2em; line-height:2em; border-bottom: 1px inset black; margin: 0; }\n" \ + "h1, p { padding-left: 10px; }\n" \ + "code.url { background-color: #eeeeee; font-family:monospace; padding:0 2px;}\n" \ "</style>\n"; /* }}} */ @@ -432,6 +477,75 @@ static const char *get_mime_type(const char *ext, size_t ext_len) /* {{{ */ return NULL; } /* }}} */ +PHP_FUNCTION(apache_request_headers) /* {{{ */ +{ + php_cli_server_client *client; + HashTable *headers; + char *key; + uint key_len; + char **value_pointer; + HashPosition pos; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + client = SG(server_context); + headers = &client->request.headers_original_case; + + array_init_size(return_value, zend_hash_num_elements(headers)); + + zend_hash_internal_pointer_reset_ex(headers, &pos); + while (zend_hash_get_current_data_ex(headers, (void **)&value_pointer, &pos) == SUCCESS) { + zend_hash_get_current_key_ex(headers, &key, &key_len, NULL, 0, &pos); + add_assoc_string_ex(return_value, key, key_len, *value_pointer, 1); + zend_hash_move_forward_ex(headers, &pos); + } +} +/* }}} */ + +static void add_response_header(sapi_header_struct *h, zval *return_value TSRMLS_DC) /* {{{ */ +{ + char *s, *p; + int len; + ALLOCA_FLAG(use_heap) + + if (h->header_len > 0) { + p = strchr(h->header, ':'); + len = p - h->header; + if (p && (len > 0)) { + while (len > 0 && (h->header[len-1] == ' ' || h->header[len-1] == '\t')) { + len--; + } + if (len) { + s = do_alloca(len + 1, use_heap); + memcpy(s, h->header, len); + s[len] = 0; + do { + p++; + } while (*p == ' ' || *p == '\t'); + add_assoc_stringl_ex(return_value, s, len+1, p, h->header_len - (p - h->header), 1); + free_alloca(s, use_heap); + } + } + } +} +/* }}} */ + +PHP_FUNCTION(apache_response_headers) /* {{{ */ +{ + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + if (!&SG(sapi_headers).headers) { + RETURN_FALSE; + } + array_init(return_value); + zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t)add_response_header, return_value TSRMLS_CC); +} +/* }}} */ + /* {{{ cli_server module */ @@ -476,6 +590,18 @@ zend_module_entry cli_server_module_entry = { }; /* }}} */ +ZEND_BEGIN_ARG_INFO(arginfo_no_args, 0) +ZEND_END_ARG_INFO() + +const zend_function_entry server_additional_functions[] = { + PHP_FE(cli_set_process_title, arginfo_cli_set_process_title) + PHP_FE(cli_get_process_title, arginfo_cli_get_process_title) + PHP_FE(apache_request_headers, arginfo_no_args) + PHP_FE(apache_response_headers, arginfo_no_args) + PHP_FALIAS(getallheaders, apache_request_headers, arginfo_no_args) + {NULL, NULL, NULL} +}; + static int sapi_cli_server_startup(sapi_module_struct *sapi_module) /* {{{ */ { if (php_module_startup(sapi_module, &cli_server_module_entry, 1) == FAILURE) { @@ -1290,6 +1416,7 @@ static int php_cli_server_request_ctor(php_cli_server_request *req) /* {{{ */ req->query_string = NULL; req->query_string_len = 0; zend_hash_init(&req->headers, 0, NULL, (void(*)(void*))char_ptr_dtor_p, 1); + zend_hash_init(&req->headers_original_case, 0, NULL, NULL, 1); req->content = NULL; req->content_len = 0; req->ext = NULL; @@ -1315,6 +1442,7 @@ static void php_cli_server_request_dtor(php_cli_server_request *req) /* {{{ */ pefree(req->query_string, 1); } zend_hash_destroy(&req->headers); + zend_hash_destroy(&req->headers_original_case); if (req->content) { pefree(req->content, 1); } @@ -1557,9 +1685,14 @@ static int php_cli_server_client_read_request_on_header_value(php_http_parser *p return 1; } { - char *header_name = zend_str_tolower_dup(client->current_header_name, client->current_header_name_len); - zend_hash_add(&client->request.headers, header_name, client->current_header_name_len + 1, &value, sizeof(char *), NULL); - efree(header_name); + /* strip off the colon */ + char *orig_header_name = estrndup(client->current_header_name, client->current_header_name_len); + char *lc_header_name = zend_str_tolower_dup(client->current_header_name, client->current_header_name_len); + + zend_hash_add(&client->request.headers, lc_header_name, client->current_header_name_len + 1, &value, sizeof(char *), NULL); + zend_hash_add(&client->request.headers_original_case, orig_header_name, client->current_header_name_len + 1, &value, sizeof(char *), NULL); + efree(lc_header_name); + efree(orig_header_name); } if (client->current_header_name_allocated) { @@ -1984,40 +2117,38 @@ static int php_cli_server_request_shutdown(php_cli_server *server, php_cli_serve static int php_cli_server_dispatch_router(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) /* {{{ */ { int decline = 0; - if (!php_handle_special_queries(TSRMLS_C)) { - zend_file_handle zfd; - char *old_cwd; - - ALLOCA_FLAG(use_heap) - old_cwd = do_alloca(MAXPATHLEN, use_heap); - old_cwd[0] = '\0'; - php_ignore_value(VCWD_GETCWD(old_cwd, MAXPATHLEN - 1)); - - zfd.type = ZEND_HANDLE_FILENAME; - zfd.filename = server->router; - zfd.handle.fp = NULL; - zfd.free_filename = 0; - zfd.opened_path = NULL; - - zend_try { - zval *retval = NULL; - if (SUCCESS == zend_execute_scripts(ZEND_REQUIRE TSRMLS_CC, &retval, 1, &zfd)) { - if (retval) { - decline = Z_TYPE_P(retval) == IS_BOOL && !Z_LVAL_P(retval); - zval_ptr_dtor(&retval); - } - } else { - decline = 1; + zend_file_handle zfd; + char *old_cwd; + + ALLOCA_FLAG(use_heap) + old_cwd = do_alloca(MAXPATHLEN, use_heap); + old_cwd[0] = '\0'; + php_ignore_value(VCWD_GETCWD(old_cwd, MAXPATHLEN - 1)); + + zfd.type = ZEND_HANDLE_FILENAME; + zfd.filename = server->router; + zfd.handle.fp = NULL; + zfd.free_filename = 0; + zfd.opened_path = NULL; + + zend_try { + zval *retval = NULL; + if (SUCCESS == zend_execute_scripts(ZEND_REQUIRE TSRMLS_CC, &retval, 1, &zfd)) { + if (retval) { + decline = Z_TYPE_P(retval) == IS_BOOL && !Z_LVAL_P(retval); + zval_ptr_dtor(&retval); } - } zend_end_try(); - - if (old_cwd[0] != '\0') { - php_ignore_value(VCWD_CHDIR(old_cwd)); + } else { + decline = 1; } + } zend_end_try(); - free_alloca(old_cwd, use_heap); + if (old_cwd[0] != '\0') { + php_ignore_value(VCWD_CHDIR(old_cwd)); } + free_alloca(old_cwd, use_heap); + return decline; } /* }}} */ diff --git a/sapi/cli/php_cli_server.h b/sapi/cli/php_cli_server.h index f8dff05d02..a8d7f46e7c 100644 --- a/sapi/cli/php_cli_server.h +++ b/sapi/cli/php_cli_server.h @@ -23,6 +23,7 @@ #include "SAPI.h" +extern const zend_function_entry server_additional_functions[]; extern sapi_module_struct cli_server_sapi_module; extern int do_cli_server(int argc, char **argv TSRMLS_DC); diff --git a/sapi/cli/ps_title.c b/sapi/cli/ps_title.c new file mode 100644 index 0000000000..53cd5fc9a0 --- /dev/null +++ b/sapi/cli/ps_title.c @@ -0,0 +1,437 @@ +/* + * PostgreSQL is released under the PostgreSQL License, a liberal Open Source + * license, similar to the BSD or MIT licenses. + * PostgreSQL Database Management System (formerly known as Postgres, then as + * Postgres95) + * + * Portions Copyright (c) 1996-2014, The PostgreSQL Global Development Group + * + * Portions Copyright (c) 1994, The Regents of the University of California + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without a written + * agreement is hereby granted, provided that the above copyright notice + * and this paragraph and the following two paragraphs appear in all copies. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING + * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, + * EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN + * "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * The following code is adopted from the PostgreSQL's ps_status(.h/.c). + */ + +#include "ps_title.h" +#include <stdio.h> + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include <string.h> +#include <stdlib.h> + +#ifdef PHP_WIN32 +#include "config.w32.h" +#include <windows.h> +#include <process.h> +#else +#include "php_config.h" +extern char** environ; +#endif + +#ifdef HAVE_SYS_PSTAT_H +#include <sys/pstat.h> /* for HP-UX */ +#endif +#ifdef HAVE_PS_STRINGS +#include <machine/vmparam.h> /* for old BSD */ +#include <sys/exec.h> +#endif +#if defined(DARWIN) +#include <crt_externs.h> +#endif + +/* + * Ways of updating ps display: + * + * PS_USE_SETPROCTITLE + * use the function setproctitle(const char *, ...) + * (newer BSD systems) + * PS_USE_PSTAT + * use the pstat(PSTAT_SETCMD, ) + * (HPUX) + * PS_USE_PS_STRINGS + * assign PS_STRINGS->ps_argvstr = "string" + * (some BSD systems) + * PS_USE_CHANGE_ARGV + * assign argv[0] = "string" + * (some other BSD systems) + * PS_USE_CLOBBER_ARGV + * write over the argv and environment area + * (Linux and most SysV-like systems) + * PS_USE_WIN32 + * push the string out as the name of a Windows event + * PS_USE_NONE + * don't update ps display + * (This is the default, as it is safest.) + */ +#if defined(HAVE_SETPROCTITLE) +#define PS_USE_SETPROCTITLE +#elif defined(HAVE_SYS_PSTAT_H) && defined(PSTAT_SETCMD) +#define PS_USE_PSTAT +#elif defined(HAVE_PS_STRINGS) +#define PS_USE_PS_STRINGS +#elif defined(BSD) && !defined(DARWIN) +#define PS_USE_CHANGE_ARGV +#elif defined(__linux__) || defined(_AIX) || defined(__sgi) || (defined(sun) && !defined(BSD)) || defined(ultrix) || defined(__osf__) || defined(DARWIN) +#define PS_USE_CLOBBER_ARGV +#elif defined(PHP_WIN32) +#define PS_USE_WIN32 +#else +#define PS_USE_NONE +#endif + +/* Different systems want the buffer padded differently */ +#if defined(_AIX) || defined(__linux__) || defined(DARWIN) +#define PS_PADDING '\0' +#else +#define PS_PADDING ' ' +#endif + +#ifdef PS_USE_WIN32 +static char windows_error_details[64]; +static char ps_buffer[MAX_PATH]; +static const size_t ps_buffer_size = MAX_PATH; +#elif defined(PS_USE_CLOBBER_ARGV) +static char *ps_buffer; /* will point to argv area */ +static size_t ps_buffer_size; /* space determined at run time */ +static char *empty_environ[] = {0}; /* empty environment */ +#else +#define PS_BUFFER_SIZE 256 +static char ps_buffer[PS_BUFFER_SIZE]; +static const size_t ps_buffer_size = PS_BUFFER_SIZE; +#endif + +static size_t ps_buffer_cur_len; /* actual string length in ps_buffer */ + +/* save the original argv[] location here */ +static int save_argc; +static char** save_argv; + +/* + * This holds the 'locally' allocated environ from the save_ps_args method. + * This is subsequently free'd at exit. + */ +static char** frozen_environ, **new_environ; + +/* + * Call this method early, before any code has used the original argv passed in + * from main(). + * If needed, this code will make deep copies of argv and environ and return + * these to the caller for further use. The original argv is then 'clobbered' + * to store the process title. + */ +char** save_ps_args(int argc, char** argv) +{ + save_argc = argc; + save_argv = argv; + +#if defined(PS_USE_CLOBBER_ARGV) + /* + * If we're going to overwrite the argv area, count the available space. + * Also move the environment to make additional room. + */ + { + char* end_of_area = NULL; + int non_contiguous_area = 0; + int i; + + /* + * check for contiguous argv strings + */ + for (i = 0; (non_contiguous_area == 0) && (i < argc); i++) + { + if (i != 0 && end_of_area + 1 != argv[i]) + non_contiguous_area = 1; + end_of_area = argv[i] + strlen(argv[i]); + } + + /* + * check for contiguous environ strings following argv + */ + for (i = 0; (non_contiguous_area == 0) && (environ[i] != NULL); i++) + { + if (end_of_area + 1 != environ[i]) + non_contiguous_area = 1; + end_of_area = environ[i] + strlen(environ[i]); + } + + if (non_contiguous_area != 0) + goto clobber_error; + + ps_buffer = argv[0]; + ps_buffer_size = end_of_area - argv[0]; + + /* + * move the environment out of the way + */ + new_environ = (char **) malloc((i + 1) * sizeof(char *)); + frozen_environ = (char **) malloc((i + 1) * sizeof(char *)); + if (!new_environ || !frozen_environ) + goto clobber_error; + for (i = 0; environ[i] != NULL; i++) + { + new_environ[i] = strdup(environ[i]); + if (!new_environ[i]) + goto clobber_error; + } + new_environ[i] = NULL; + environ = new_environ; + memcpy((char *)frozen_environ, (char *)new_environ, sizeof(char *) * (i + 1)); + + } +#endif /* PS_USE_CLOBBER_ARGV */ + +#if defined(PS_USE_CHANGE_ARGV) || defined(PS_USE_CLOBBER_ARGV) + /* + * If we're going to change the original argv[] then make a copy for + * argument parsing purposes. + * + * (NB: do NOT think to remove the copying of argv[]! + * On some platforms, getopt() keeps pointers into the argv array, and + * will get horribly confused when it is re-called to analyze a subprocess' + * argument string if the argv storage has been clobbered meanwhile. + * Other platforms have other dependencies on argv[].) + */ + { + char** new_argv; + int i; + + new_argv = (char **) malloc((argc + 1) * sizeof(char *)); + if (!new_argv) + goto clobber_error; + for (i = 0; i < argc; i++) + { + new_argv[i] = strdup(argv[i]); + if (!new_argv[i]) + goto clobber_error; + } + new_argv[argc] = NULL; + +#if defined(DARWIN) + /* + * Darwin (and perhaps other NeXT-derived platforms?) has a static + * copy of the argv pointer, which we may fix like so: + */ + *_NSGetArgv() = new_argv; +#endif + + argv = new_argv; + + } +#endif /* PS_USE_CHANGE_ARGV or PS_USE_CLOBBER_ARGV */ + +#if defined(PS_USE_CLOBBER_ARGV) + { + /* make extra argv slots point at end_of_area (a NUL) */ + int i; + for (i = 1; i < save_argc; i++) + save_argv[i] = ps_buffer + ps_buffer_size; + } +#endif /* PS_USE_CLOBBER_ARGV */ + +#ifdef PS_USE_CHANGE_ARGV + save_argv[0] = ps_buffer; /* ps_buffer here is a static const array of size PS_BUFFER_SIZE */ + save_argv[1] = NULL; +#endif /* PS_USE_CHANGE_ARGV */ + + return argv; + +#if defined(PS_USE_CHANGE_ARGV) || defined(PS_USE_CLOBBER_ARGV) +clobber_error: + /* probably can't happen?! + * if we ever get here, argv still points to originally passed + * in argument + */ + save_argv = NULL; + save_argc = 0; + ps_buffer = NULL; + ps_buffer_size = 0; + return argv; +#endif /* PS_USE_CHANGE_ARGV or PS_USE_CLOBBER_ARGV */ +} + +/* + * Returns PS_TITLE_SUCCESS if the OS supports this functionality + * and the init function was called. + * Otherwise returns NOT_AVAILABLE or NOT_INITIALIZED + */ +int is_ps_title_available() +{ +#ifdef PS_USE_NONE + return PS_TITLE_NOT_AVAILABLE; /* disabled functionality */ +#endif + + if (!save_argv) + return PS_TITLE_NOT_INITIALIZED; + +#ifdef PS_USE_CLOBBER_ARGV + if (!ps_buffer) + return PS_TITLE_BUFFER_NOT_AVAILABLE; +#endif /* PS_USE_CLOBBER_ARGV */ + + return PS_TITLE_SUCCESS; +} + +/* + * Convert error codes into error strings + */ +const char* ps_title_errno(int rc) +{ + switch(rc) + { + case PS_TITLE_SUCCESS: + return "Success"; + + case PS_TITLE_NOT_AVAILABLE: + return "Not available on this OS"; + + case PS_TITLE_NOT_INITIALIZED: + return "Not initialized correctly"; + + case PS_TITLE_BUFFER_NOT_AVAILABLE: + return "Buffer not contiguous"; + +#ifdef PS_USE_WIN32 + case PS_TITLE_WINDOWS_ERROR: + sprintf(windows_error_details, "Windows error code: %d", GetLastError()); + return windows_error_details; +#endif + } + + return "Unknown error code"; +} + +/* + * Set a new process title. + * Returns the appropriate error code if if there's an error + * (like the functionality is compile time disabled, or the + * save_ps_args() was not called. + * Else returns 0 on success. + */ +int set_ps_title(const char* title) +{ + int rc = is_ps_title_available(); + if (rc != PS_TITLE_SUCCESS) + return rc; + + strncpy(ps_buffer, title, ps_buffer_size); + ps_buffer[ps_buffer_size - 1] = '\0'; + ps_buffer_cur_len = strlen(ps_buffer); + +#ifdef PS_USE_SETPROCTITLE + setproctitle("%s", ps_buffer); +#endif + +#ifdef PS_USE_PSTAT + { + union pstun pst; + + pst.pst_command = ps_buffer; + pstat(PSTAT_SETCMD, pst, ps_buffer_cur_len, 0, 0); + } +#endif /* PS_USE_PSTAT */ + +#ifdef PS_USE_PS_STRINGS + PS_STRINGS->ps_nargvstr = 1; + PS_STRINGS->ps_argvstr = ps_buffer; +#endif /* PS_USE_PS_STRINGS */ + +#ifdef PS_USE_CLOBBER_ARGV + /* pad unused memory */ + if (ps_buffer_cur_len < ps_buffer_size) + { + memset(ps_buffer + ps_buffer_cur_len, PS_PADDING, + ps_buffer_size - ps_buffer_cur_len); + } +#endif /* PS_USE_CLOBBER_ARGV */ + +#ifdef PS_USE_WIN32 + { + if (!SetConsoleTitle(ps_buffer)) + return PS_TITLE_WINDOWS_ERROR; + } +#endif /* PS_USE_WIN32 */ + + return PS_TITLE_SUCCESS; +} + +/* + * Returns the current ps_buffer value into string. On some platforms + * the string will not be null-terminated, so return the effective + * length into *displen. + * The return code indicates the error. + */ +int get_ps_title(int *displen, const char** string) +{ + int rc = is_ps_title_available(); + if (rc != PS_TITLE_SUCCESS) + return rc; + +#ifdef PS_USE_WIN32 + if (!(ps_buffer_cur_len = GetConsoleTitle(ps_buffer, ps_buffer_size))) + return PS_TITLE_WINDOWS_ERROR; +#endif + *displen = (int)ps_buffer_cur_len; + *string = ps_buffer; + return PS_TITLE_SUCCESS; +} + +/* + * Clean up the allocated argv and environ if applicable. Only call + * this right before exiting. + * This isn't needed per-se because the OS will clean-up anyway, but + * having and calling this will ensure Valgrind doesn't output 'false + * positives'. + */ +void cleanup_ps_args(char **argv) +{ +#ifndef PS_USE_NONE + if (save_argv) + { + save_argv = NULL; + save_argc = 0; + +#ifdef PS_USE_CLOBBER_ARGV + { + int i; + for (i = 0; frozen_environ[i] != NULL; i++) + free(frozen_environ[i]); + free(frozen_environ); + free(new_environ); + /* leave a sane environment behind since some atexit() handlers + call getenv(). */ + environ = empty_environ; + } +#endif /* PS_USE_CLOBBER_ARGV */ + +#if defined(PS_USE_CHANGE_ARGV) || defined(PS_USE_CLOBBER_ARGV) + { + int i; + for (i=0; argv[i] != NULL; i++) + free(argv[i]); + free(argv); + } +#endif /* PS_USE_CHANGE_ARGV or PS_USE_CLOBBER_ARGV */ + } +#endif /* PS_USE_NONE */ + + return; +} diff --git a/sapi/cli/ps_title.h b/sapi/cli/ps_title.h new file mode 100644 index 0000000000..09650fed08 --- /dev/null +++ b/sapi/cli/ps_title.h @@ -0,0 +1,42 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2014 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | 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. | + +----------------------------------------------------------------------+ + | Authors: Keyur Govande <kgovande@gmail.com> | + +----------------------------------------------------------------------+ + */ + +/* $Id$ */ + +#ifndef PS_TITLE_HEADER +#define PS_TITLE_HEADER + +#define PS_TITLE_SUCCESS 0 +#define PS_TITLE_NOT_AVAILABLE 1 +#define PS_TITLE_NOT_INITIALIZED 2 +#define PS_TITLE_BUFFER_NOT_AVAILABLE 3 +#define PS_TITLE_WINDOWS_ERROR 4 + +extern char** save_ps_args(int argc, char** argv); + +extern int set_ps_title(const char* new_str); + +extern int get_ps_title(int* displen, const char** string); + +extern const char* ps_title_errno(int rc); + +extern int is_ps_title_available(); + +extern void cleanup_ps_args(char **argv); + +#endif // PS_TITLE_HEADER diff --git a/sapi/cli/tests/bug64544.phpt b/sapi/cli/tests/bug64544.phpt new file mode 100644 index 0000000000..cc49545c16 --- /dev/null +++ b/sapi/cli/tests/bug64544.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug #64544 (Valgrind warnings after using putenv) +--SKIPIF-- +<?php +if (substr(PHP_OS, 0, 3) == "WIN") { + die("skip non windows test"); +} +?> +--FILE-- +<?php + +putenv("HOME=/tmp"); +var_dump(getenv("HOME")); + +putenv("FOO=BAR"); +var_dump(getenv("FOO")); +?> +--EXPECTF-- +string(4) "/tmp" +string(3) "BAR" diff --git a/sapi/cli/tests/cli_process_title_unix.phpt b/sapi/cli/tests/cli_process_title_unix.phpt new file mode 100644 index 0000000000..c2632704c5 --- /dev/null +++ b/sapi/cli/tests/cli_process_title_unix.phpt @@ -0,0 +1,49 @@ +--TEST-- +Check cli_process_title support on Unix +--SKIPIF-- +<?php +if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') + die("skip"); +?> +--FILE-- +<?php +echo "*** Testing setting the process title ***\n"; + +$set_title = $original_title = uniqid("title", true); +$pid = getmypid(); + +if (cli_set_process_title($original_title) === true) + echo "Successfully set title\n"; + +$ps_output = shell_exec("ps -p $pid -o command | tail -n 1"); + +if ($ps_output === null) +{ + echo "ps failed\n"; + die(); +} + +$loaded_title = trim($ps_output); +if (strpos(strtoupper(substr(PHP_OS, 0, 13)), "BSD") !== false) +{ + // Fix up title for BSD + $set_title = "php: $original_title (php)"; +} + +if ($loaded_title == $set_title) + echo "Successfully verified title using ps\n"; +else + echo "Actually loaded from ps: $loaded_title\n"; + +$read_title = cli_get_process_title(); +if ($read_title == $original_title) + echo "Successfully verified title using get\n"; +else + echo "Actually loaded from get: $read_title\n"; + +?> +--EXPECTF-- +*** Testing setting the process title *** +Successfully set title +Successfully verified title using ps +Successfully verified title using get diff --git a/sapi/cli/tests/cli_process_title_windows.phpt b/sapi/cli/tests/cli_process_title_windows.phpt new file mode 100644 index 0000000000..472f9c10fe --- /dev/null +++ b/sapi/cli/tests/cli_process_title_windows.phpt @@ -0,0 +1,83 @@ +--TEST-- +Check cli_process_title support in Windows +--SKIPIF-- +<?php +if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') + die("skip"); +?> +--FILE-- +<?php + +// On Windows 8 and Server 2012, this test does not work the same way. When the PowerShell +// command "get-process" is executed using shell_exec, it overwrites the ConsoleTitle with +// "Windows PowerShell" and this title ONLY clears away when the php.exe process exits +// i.e. the test finishes. +// On older versions like Windows 7 though, running the command appends +// "Windows PowerShell" to the ConsoleTitle temporarily and the title reverts +// back to the original once shell_exec is done. +// Hence on Windows 8, we don't verify that the title is actually set by +// cli_set_process_title(). We're only making the API calls to ensure there are +// no warnings/errors. + +$is_windows8 = false; +$ps_output = shell_exec("PowerShell -NoProfile \"(Get-Host).UI.RawUI.WindowTitle\""); +if ($ps_output === null) +{ + echo "Get-Host failed\n"; + die(); +} + +$ps_output = trim($ps_output); +$end_title_windows8 = ": Windows PowerShell"; +if (($ps_output == "Windows PowerShell") || (strlen($ps_output) > strlen($end_title_windows8) && substr($ps_output,-strlen($end_title_windows8)) === $end_title_windows8)) + $is_windows8 = true; + +echo "*** Testing setting the process title ***\n"; + +$original_title = uniqid("title", true); +$pid = getmypid(); + +if (cli_set_process_title($original_title) === true) + echo "Successfully set title\n"; + +if ($is_windows8) +{ + $loaded_title = $original_title; +} +else +{ + $loaded_title = shell_exec("PowerShell -NoProfile \"get-process cmd*,powershell* | Select-Object mainWindowTitle | ft -hide\""); + + if ($loaded_title === null) + { + echo "Reading title using get-process failed\n"; + die(); + } + + // Kind of convoluted. So when the test is run on Windows 7 or older, the console where + // the run-tests.php is executed forks a php.exe, which forks a cmd.exe, which then forks + // a final php.exe to run the actual test. But the console title is set for the original console. + // I couldn't figure out a good way to navigate this, so we're "grep'ing" all possible + // console windows for our very unique title. It should occur exactly once in the grep + // output. + if (substr_count($loaded_title, $original_title, 0) == 1) + $loaded_title = $original_title; +} + +if ($loaded_title == $original_title) + echo "Successfully verified title using get-process\n"; +else + echo "Actually loaded from get-process: $loaded_title\n"; + +$read_title = cli_get_process_title(); +if (substr_count($read_title, $original_title, 0) == 1) + echo "Successfully verified title using get\n"; +else + echo "Actually loaded from get: $read_title\n"; + +?> +--EXPECTF-- +*** Testing setting the process title *** +Successfully set title +Successfully verified title using get-process +Successfully verified title using get
\ No newline at end of file diff --git a/sapi/cli/tests/php_cli_server_011.phpt b/sapi/cli/tests/php_cli_server_011.phpt deleted file mode 100644 index a957a8ed4c..0000000000 --- a/sapi/cli/tests/php_cli_server_011.phpt +++ /dev/null @@ -1,41 +0,0 @@ ---TEST-- -Bug #60180 ($_SERVER["PHP_SELF"] incorrect) ---SKIPIF-- -<?php -include "skipif.inc"; -?> ---FILE-- -<?php -include "php_cli_server.inc"; -php_cli_server_start('sytanx error;', TRUE); - -list($host, $port) = explode(':', PHP_CLI_SERVER_ADDRESS); -$port = intval($port)?:80; - -$fp = fsockopen($host, $port, $errno, $errstr, 0.5); -if (!$fp) { - die("connect failed"); -} - -$logo_id = php_logo_guid(); - -if(fwrite($fp, <<<HEADER -GET /?={$logo_id} HTTP/1.1 -Host: {$host} - - -HEADER -)) { - while (!feof($fp)) { - if (("Content-Type: image/gif") == trim(fgets($fp))) { - echo "okey"; - break; - } - } -} - -fclose($fp); - -?> ---EXPECTF-- -okey diff --git a/sapi/cli/tests/php_cli_server_013.phpt b/sapi/cli/tests/php_cli_server_013.phpt index 570798a880..0e3f4ff74f 100644 --- a/sapi/cli/tests/php_cli_server_013.phpt +++ b/sapi/cli/tests/php_cli_server_013.phpt @@ -88,7 +88,7 @@ Content-Type: text/html; charset=UTF-8 Content-Length: %d <!doctype html><html><head><title>404 Not Found</title><style>AAA</style> -</head><body><h1>Not Found</h1><p>The requested resource / was not found on this server.</p></body></html> +</head><body><h1>Not Found</h1><p>The requested resource <code class="url">/</code> was not found on this server.</p></body></html> HTTP/1.1 404 Not Found Host: %s Connection: close @@ -96,7 +96,7 @@ Content-Type: text/html; charset=UTF-8 Content-Length: %d <!doctype html><html><head><title>404 Not Found</title><style>AAA</style> -</head><body><h1>Not Found</h1><p>The requested resource /main/style.css was not found on this server.</p></body></html> +</head><body><h1>Not Found</h1><p>The requested resource <code class="url">/main/style.css</code> was not found on this server.</p></body></html> HTTP/1.1 404 Not Found Host: %s Connection: close @@ -104,5 +104,5 @@ Content-Type: text/html; charset=UTF-8 Content-Length: %d <!doctype html><html><head><title>404 Not Found</title><style>AAA</style> -</head><body><h1>Not Found</h1><p>The requested resource /main/foo/bar was not found on this server.</p></body></html> +</head><body><h1>Not Found</h1><p>The requested resource <code class="url">/main/foo/bar</code> was not found on this server.</p></body></html> diff --git a/sapi/cli/tests/php_cli_server_014.phpt b/sapi/cli/tests/php_cli_server_014.phpt index f8a9905613..e8bb5fa8a2 100644 --- a/sapi/cli/tests/php_cli_server_014.phpt +++ b/sapi/cli/tests/php_cli_server_014.phpt @@ -77,4 +77,4 @@ Content-Type: %s Content-Length: %d <!doctype html><html><head><title>404 Not Found</title><style>AAA</style> -</head><body><h1>Not Found</h1><p>The requested resource /main/no-exists.php was not found on this server.</p></body></html> +</head><body><h1>Not Found</h1><p>The requested resource <code class="url">/main/no-exists.php</code> was not found on this server.</p></body></html> diff --git a/sapi/cli/tests/php_cli_server_019.phpt b/sapi/cli/tests/php_cli_server_019.phpt new file mode 100644 index 0000000000..2b983e5c0a --- /dev/null +++ b/sapi/cli/tests/php_cli_server_019.phpt @@ -0,0 +1,68 @@ +--TEST-- +Implement Req #65917 (getallheaders() is not supported by the built-in web server) +--SKIPIF-- +<?php +include "skipif.inc"; +?> +--FILE-- +<?php +include "php_cli_server.inc"; +php_cli_server_start(<<<'PHP' +header('Bar-Foo: Foo'); +var_dump(getallheaders()); +var_dump(apache_request_headers()); +var_dump(apache_response_headers()); +PHP +); + +list($host, $port) = explode(':', PHP_CLI_SERVER_ADDRESS); +$port = intval($port)?:80; + +$fp = fsockopen($host, $port, $errno, $errstr, 0.5); +if (!$fp) { + die("connect failed"); +} + +if(fwrite($fp, <<<HEADER +GET / HTTP/1.1 +Host: {$host} +Foo-Bar: Bar + + +HEADER +)) { + while (!feof($fp)) { + echo fgets($fp); + } +} + +fclose($fp); +?> +--EXPECTF-- +HTTP/1.1 200 OK +Host: %s +Connection: close +X-Powered-By: %s +Bar-Foo: Foo +Content-type: text/html + +array(2) { + ["Host"]=> + string(9) "localhost" + ["Foo-Bar"]=> + string(3) "Bar" +} +array(2) { + ["Host"]=> + string(9) "localhost" + ["Foo-Bar"]=> + string(3) "Bar" +} +array(3) { + ["X-Powered-By"]=> + string(%d) "P%s" + ["Bar-Foo"]=> + string(3) "Foo" + ["Content-type"]=> + string(9) "text/html" +} diff --git a/sapi/embed/config.m4 b/sapi/embed/config.m4 index 3a61b458f0..5ffb9b39bd 100644 --- a/sapi/embed/config.m4 +++ b/sapi/embed/config.m4 @@ -3,7 +3,7 @@ dnl $Id$ dnl PHP_ARG_ENABLE(embed,, -[ --enable-embed[=TYPE] EXPERIMENTAL: Enable building of embedded SAPI library +[ --enable-embed[=TYPE] EXPERIMENTAL: Enable building of embedded SAPI library TYPE is either 'shared' or 'static'. [TYPE=shared]], no, no) AC_MSG_CHECKING([for embedded SAPI library support]) diff --git a/sapi/fpm/config.m4 b/sapi/fpm/config.m4 index 579f7c2846..6db5e3b955 100644 --- a/sapi/fpm/config.m4 +++ b/sapi/fpm/config.m4 @@ -3,7 +3,7 @@ dnl $Id$ dnl PHP_ARG_ENABLE(fpm,, -[ --enable-fpm Enable building of the fpm SAPI executable], no, no) +[ --enable-fpm Enable building of the fpm SAPI executable], no, no) dnl configure checks {{{ AC_DEFUN([AC_FPM_STDLIBS], @@ -557,24 +557,51 @@ if test "$PHP_FPM" != "no"; then AC_FPM_SELECT PHP_ARG_WITH(fpm-user,, - [ --with-fpm-user[=USER] Set the user for php-fpm to run as. (default: nobody)], nobody, no) + [ --with-fpm-user[=USER] Set the user for php-fpm to run as. (default: nobody)], nobody, no) PHP_ARG_WITH(fpm-group,, - [ --with-fpm-group[=GRP] Set the group for php-fpm to run as. For a system user, this - should usually be set to match the fpm username (default: nobody)], nobody, no) + [ --with-fpm-group[=GRP] Set the group for php-fpm to run as. For a system user, this + should usually be set to match the fpm username (default: nobody)], nobody, no) PHP_ARG_WITH(fpm-systemd,, [ --with-fpm-systemd Activate systemd integration], no, no) if test "$PHP_FPM_SYSTEMD" != "no" ; then - AC_CHECK_LIB(systemd-daemon, sd_notify, SYSTEMD_LIBS="-lsystemd-daemon") + if test -z "$PKG_CONFIG"; then + AC_PATH_PROG(PKG_CONFIG, pkg-config, no) + fi + unset SYSTEMD_LIBS + unset SYSTEMD_INCS + + if test -x "$PKG_CONFIG" && $PKG_CONFIG --exists libsystemd; then + dnl systemd version >= 209 provides libsystemd + AC_MSG_CHECKING([for libsystemd]) + SYSTEMD_LIBS=`$PKG_CONFIG --libs libsystemd` + SYSTEMD_INCS=`$PKG_CONFIG --cflags-only-I libsystemd` + SYSTEMD_VERS=`$PKG_CONFIG --modversion libsystemd` + AC_MSG_RESULT([version $SYSTEMD_VERS]) + + elif test -x "$PKG_CONFIG" && $PKG_CONFIG --exists libsystemd-daemon; then + dnl systemd version < 209 provides libsystemd-daemon + AC_MSG_CHECKING([for libsystemd-daemon]) + SYSTEMD_LIBS=`$PKG_CONFIG --libs libsystemd-daemon` + SYSTEMD_INCS=`$PKG_CONFIG --cflags-only-I libsystemd-daemon` + SYSTEMD_VERS=`$PKG_CONFIG --modversion libsystemd-daemon` + AC_MSG_RESULT([version $SYSTEMD_VERS]) + + else + dnl failback when no pkg-config + AC_CHECK_LIB(systemd-daemon, sd_notify, SYSTEMD_LIBS="-lsystemd-daemon") + fi + AC_CHECK_HEADERS(systemd/sd-daemon.h, [HAVE_SD_DAEMON_H="yes"], [HAVE_SD_DAEMON_H="no"]) if test $HAVE_SD_DAEMON_H = "no" || test -z "${SYSTEMD_LIBS}"; then AC_MSG_ERROR([Your system does not support systemd.]) else AC_DEFINE(HAVE_SYSTEMD, 1, [FPM use systemd integration]) PHP_FPM_SD_FILES="fpm/fpm_systemd.c" - PHP_ADD_LIBRARY(systemd-daemon) + PHP_EVAL_LIBLINE($SYSTEMD_LIBS) + PHP_EVAL_INCLINE($SYSTEMD_INCS) php_fpm_systemd=notify fi else @@ -607,16 +634,12 @@ if test "$PHP_FPM" != "no"; then AC_DEFINE_UNQUOTED(PHP_FPM_USER, "$php_fpm_user", [fpm user name]) AC_DEFINE_UNQUOTED(PHP_FPM_GROUP, "$php_fpm_group", [fpm group name]) - AC_DEFINE_UNQUOTED(PHP_FPM_USER, "$php_fpm_user", [fpm user name]) - AC_DEFINE_UNQUOTED(PHP_FPM_GROUP, "$php_fpm_group", [fpm group name]) - PHP_ADD_BUILD_DIR(sapi/fpm/fpm) PHP_ADD_BUILD_DIR(sapi/fpm/fpm/events) PHP_OUTPUT(sapi/fpm/php-fpm.conf sapi/fpm/init.d.php-fpm sapi/fpm/php-fpm.service sapi/fpm/php-fpm.8 sapi/fpm/status.html) PHP_ADD_MAKEFILE_FRAGMENT([$abs_srcdir/sapi/fpm/Makefile.frag]) SAPI_FPM_PATH=sapi/fpm/php-fpm - if test "$fpm_trace_type" && test -f "$abs_srcdir/sapi/fpm/fpm/fpm_trace_$fpm_trace_type.c"; then PHP_FPM_TRACE_FILES="fpm/fpm_trace.c fpm/fpm_trace_$fpm_trace_type.c" diff --git a/sapi/fpm/fpm/fastcgi.c b/sapi/fpm/fpm/fastcgi.c index 80745a9c7e..d77b6f8ca7 100644 --- a/sapi/fpm/fpm/fastcgi.c +++ b/sapi/fpm/fpm/fastcgi.c @@ -611,7 +611,7 @@ static int fcgi_read_request(fcgi_request *req) } zend_hash_internal_pointer_reset_ex(req->env, &pos); - while ((key_type = zend_hash_get_current_key_ex(req->env, &str_index, &str_length, &num_index, 0, &pos)) != HASH_KEY_NON_EXISTANT) { + while ((key_type = zend_hash_get_current_key_ex(req->env, &str_index, &str_length, &num_index, 0, &pos)) != HASH_KEY_NON_EXISTENT) { int zlen; zend_hash_move_forward_ex(req->env, &pos); if (key_type != HASH_KEY_IS_STRING) { diff --git a/sapi/fpm/fpm/fpm_sockets.h b/sapi/fpm/fpm/fpm_sockets.h index cce5712b8c..121c016a7b 100644 --- a/sapi/fpm/fpm/fpm_sockets.h +++ b/sapi/fpm/fpm/fpm_sockets.h @@ -19,7 +19,7 @@ #if (__FreeBSD__) || (__OpenBSD__) #define FPM_BACKLOG_DEFAULT -1 #else -#define FPM_BACKLOG_DEFAULT 128 +#define FPM_BACKLOG_DEFAULT 65535 #endif enum fpm_address_domain fpm_sockets_domain_from_address(char *addr); diff --git a/sapi/fpm/php-fpm.conf.in b/sapi/fpm/php-fpm.conf.in index 9205d42239..c5f4abc59c 100644 --- a/sapi/fpm/php-fpm.conf.in +++ b/sapi/fpm/php-fpm.conf.in @@ -159,8 +159,8 @@ group = @php_fpm_group@ listen = 127.0.0.1:9000 ; Set listen(2) backlog. -; Default Value: 128 (-1 on FreeBSD and OpenBSD) -;listen.backlog = 128 +; Default Value: 65535 (-1 on FreeBSD and OpenBSD) +;listen.backlog = 65535 ; Set permissions for unix socket, if one is used. In Linux, read/write ; permissions must be set in order to allow connections from a web server. Many diff --git a/sapi/isapi/config.m4 b/sapi/isapi/config.m4 index 7c7dcf0c21..6014bab09f 100644 --- a/sapi/isapi/config.m4 +++ b/sapi/isapi/config.m4 @@ -3,7 +3,7 @@ dnl $Id$ dnl PHP_ARG_WITH(isapi, for Zeus ISAPI support, -[ --with-isapi[=DIR] Build PHP as an ISAPI module for use with Zeus], no, no) +[ --with-isapi[=DIR] Build PHP as an ISAPI module for use with Zeus], no, no) if test "$PHP_ISAPI" != "no"; then if test "$PHP_ISAPI" = "yes"; then diff --git a/sapi/milter/config.m4 b/sapi/milter/config.m4 index db9c4c5b4c..a69ab2e1e7 100644 --- a/sapi/milter/config.m4 +++ b/sapi/milter/config.m4 @@ -3,7 +3,7 @@ dnl $Id$ dnl PHP_ARG_WITH(milter, for Milter support, -[ --with-milter[=DIR] Build PHP as Milter application], no, no) +[ --with-milter[=DIR] Build PHP as Milter application], no, no) if test "$PHP_MILTER" != "no"; then if test "$PHP_MILTER" = "yes"; then diff --git a/sapi/pi3web/config.m4 b/sapi/pi3web/config.m4 index 7859481508..347a74ca06 100644 --- a/sapi/pi3web/config.m4 +++ b/sapi/pi3web/config.m4 @@ -3,7 +3,7 @@ dnl $Id$ dnl PHP_ARG_WITH(pi3web, for Pi3Web support, -[ --with-pi3web[=DIR] Build PHP as Pi3Web module], no, no) +[ --with-pi3web[=DIR] Build PHP as Pi3Web module], no, no) if test "$PHP_PI3WEB" != "no"; then if test "$PHP_PI3WEB" = "yes"; then diff --git a/sapi/roxen/config.m4 b/sapi/roxen/config.m4 index 9b0bb90c35..7601b0c1ed 100644 --- a/sapi/roxen/config.m4 +++ b/sapi/roxen/config.m4 @@ -7,7 +7,7 @@ PHP_ARG_WITH(roxen,, directory, normally /usr/local/roxen/server], no, no) PHP_ARG_ENABLE(roxen-zts, whether Roxen module is build using ZTS, -[ --enable-roxen-zts ROXEN: Build the Roxen module using Zend Thread Safety], no, no) +[ --enable-roxen-zts ROXEN: Build the Roxen module using Zend Thread Safety], no, no) RESULT= AC_MSG_CHECKING([for Roxen/Pike support]) |
