summaryrefslogtreecommitdiff
path: root/sapi
diff options
context:
space:
mode:
Diffstat (limited to 'sapi')
-rw-r--r--sapi/apache2handler/php_functions.c8
-rw-r--r--sapi/cgi/cgi_main.c2
-rw-r--r--sapi/cgi/fastcgi.c10
-rw-r--r--sapi/cli/php_cli_server.c11
-rw-r--r--sapi/cli/php_http_parser.c2
-rw-r--r--sapi/cli/ps_title.c4
-rw-r--r--sapi/cli/tests/bug64529.phpt10
-rw-r--r--sapi/embed/php_embed.c2
-rw-r--r--sapi/fpm/fpm/fastcgi.c100
-rw-r--r--sapi/fpm/fpm/fastcgi.h2
-rw-r--r--sapi/fpm/fpm/fpm_conf.c11
-rw-r--r--sapi/fpm/fpm/fpm_env.c2
-rw-r--r--sapi/fpm/fpm/fpm_log.c4
-rw-r--r--sapi/fpm/fpm/fpm_sockets.c44
-rw-r--r--sapi/fpm/fpm/fpm_stdio.c40
-rw-r--r--sapi/fpm/fpm/fpm_unix.c1
-rw-r--r--sapi/fpm/php-fpm.8.in21
-rw-r--r--sapi/fpm/php-fpm.conf.in9
-rw-r--r--sapi/fpm/tests/002.phpt14
-rw-r--r--sapi/fpm/tests/003.phpt14
-rw-r--r--sapi/fpm/tests/004.phpt59
-rw-r--r--sapi/fpm/tests/005.phpt57
-rw-r--r--sapi/fpm/tests/006.phpt57
-rw-r--r--sapi/fpm/tests/007.phpt68
-rw-r--r--sapi/fpm/tests/008.phpt84
-rw-r--r--sapi/fpm/tests/009.phpt53
-rw-r--r--sapi/fpm/tests/010.phpt84
-rw-r--r--sapi/fpm/tests/011.phpt53
-rw-r--r--sapi/fpm/tests/012.phpt79
-rw-r--r--sapi/fpm/tests/013.phpt54
-rw-r--r--sapi/fpm/tests/014.phpt54
-rw-r--r--sapi/fpm/tests/015.phpt87
-rw-r--r--sapi/fpm/tests/016.phpt87
-rw-r--r--sapi/fpm/tests/017.phpt67
-rw-r--r--sapi/fpm/tests/019.phpt80
-rw-r--r--sapi/fpm/tests/020.phpt76
-rw-r--r--sapi/fpm/tests/fcgi.inc592
-rw-r--r--sapi/fpm/tests/include.inc34
-rw-r--r--sapi/litespeed/lsapi_main.c116
-rw-r--r--sapi/litespeed/lsapilib.c2
-rw-r--r--sapi/nsapi/nsapi-readme.txt2
-rw-r--r--sapi/phpdbg/phpdbg.c2
-rw-r--r--sapi/phpdbg/phpdbg_frame.c4
-rw-r--r--sapi/phpdbg/xml.md6
-rw-r--r--sapi/thttpd/thttpd_patch2
45 files changed, 2032 insertions, 138 deletions
diff --git a/sapi/apache2handler/php_functions.c b/sapi/apache2handler/php_functions.c
index d9ae4d97ea..f32c881e05 100644
--- a/sapi/apache2handler/php_functions.c
+++ b/sapi/apache2handler/php_functions.c
@@ -388,8 +388,12 @@ PHP_MINFO_FUNCTION(apache)
}
smart_str_appendc(&tmp1, ' ');
}
- if (tmp1.s && (tmp1.s->len - 1) >= 0) {
- tmp1.s->val[tmp1.s->len - 1] = '\0';
+ if (tmp1.s) {
+ if (tmp1.s->len > 0) {
+ tmp1.s->val[tmp1.s->len - 1] = '\0';
+ } else {
+ tmp1.s->val[0] = '\0';
+ }
}
php_info_print_table_start();
diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c
index f06787543e..2d67321773 100644
--- a/sapi/cgi/cgi_main.c
+++ b/sapi/cgi/cgi_main.c
@@ -2280,7 +2280,7 @@ consult the installation file that came with this distribution, or visit \n\
/* all remaining arguments are part of the query string
* this section of code concatenates all remaining arguments
- * into a single string, seperating args with a &
+ * into a single string, separating args with a &
* this allows command lines like:
*
* test.php v1=test v2=hello+world!
diff --git a/sapi/cgi/fastcgi.c b/sapi/cgi/fastcgi.c
index 0cd3096e4d..7925f87562 100644
--- a/sapi/cgi/fastcgi.c
+++ b/sapi/cgi/fastcgi.c
@@ -435,7 +435,11 @@ int fcgi_init(void)
str = getenv("_FCGI_SHUTDOWN_EVENT_");
if (str != NULL) {
- HANDLE shutdown_event = (HANDLE) atoi(str);
+ zend_long ev;
+ HANDLE shutdown_event;
+
+ ZEND_ATOL(ev, str);
+ shutdown_event = (HANDLE) ev;
if (!CreateThread(NULL, 0, fcgi_shutdown_thread,
shutdown_event, 0, NULL)) {
return -1;
@@ -443,7 +447,9 @@ int fcgi_init(void)
}
str = getenv("_FCGI_MUTEX_");
if (str != NULL) {
- fcgi_accept_mutex = (HANDLE) atoi(str);
+ zend_long mt;
+ ZEND_ATOL(mt, str);
+ fcgi_accept_mutex = (HANDLE) mt;
}
return is_fastcgi = 1;
} else {
diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c
index 19a94218ff..49680cede4 100644
--- a/sapi/cli/php_cli_server.c
+++ b/sapi/cli/php_cli_server.c
@@ -259,7 +259,9 @@ static php_cli_server_http_response_status_code_pair template_map[] = {
{ 501, "<h1>%s</h1><p>Request method not supported.</p>" }
};
+#if HAVE_UNISTD_H
static int php_cli_output_is_tty = OUTPUT_NOT_CHECKED;
+#endif
static size_t php_cli_server_client_send_through(php_cli_server_client *client, const char *str, size_t str_len);
static php_cli_server_chunk *php_cli_server_chunk_heap_new_self_contained(size_t len);
@@ -556,7 +558,7 @@ static void sapi_cli_server_flush(void *server_context TSRMLS_DC) /* {{{ */
return;
}
- if (client->sock < 0) {
+ if (!ZEND_VALID_SOCKET(client->sock)) {
php_handle_aborted_connection();
return;
}
@@ -838,7 +840,6 @@ static int php_cli_server_poller_iter_on_active(php_cli_server_poller *poller, v
SOCKET fd;
int events;
} entries[FD_SETSIZE * 2];
- php_socket_t fd = 0;
size_t i;
struct socket_entry *n = entries, *m;
@@ -1338,7 +1339,7 @@ out:
php_network_freeaddresses(sal);
}
if (err) {
- if (retval >= 0) {
+ if (ZEND_VALID_SOCKET(retval)) {
closesocket(retval);
}
if (errstr) {
@@ -2186,7 +2187,7 @@ static void php_cli_server_dtor(php_cli_server *server TSRMLS_DC) /* {{{ */
{
zend_hash_destroy(&server->clients);
zend_hash_destroy(&server->extension_mime_types);
- if (server->server_sock >= 0) {
+ if (ZEND_VALID_SOCKET(server->server_sock)) {
closesocket(server->server_sock);
}
if (server->host) {
@@ -2407,7 +2408,7 @@ static int php_cli_server_do_event_for_each_fd_callback(void *_params, php_socke
return FAILURE;
}
client_sock = accept(server->server_sock, sa, &socklen);
- if (client_sock < 0) {
+ if (!ZEND_VALID_SOCKET(client_sock)) {
char *errstr;
errstr = php_socket_strerror(php_socket_errno(), NULL, 0);
php_cli_server_logf("Failed to accept a client (reason: %s)" TSRMLS_CC, errstr);
diff --git a/sapi/cli/php_http_parser.c b/sapi/cli/php_http_parser.c
index cc649af79a..31ae4167d1 100644
--- a/sapi/cli/php_http_parser.c
+++ b/sapi/cli/php_http_parser.c
@@ -1378,7 +1378,7 @@ size_t php_http_parser_execute (php_http_parser *parser,
/* Here we call the headers_complete callback. This is somewhat
* different than other callbacks because if the user returns 1, we
* will interpret that as saying that this message has no body. This
- * is needed for the annoying case of recieving a response to a HEAD
+ * is needed for the annoying case of receiving a response to a HEAD
* request.
*/
if (settings->on_headers_complete) {
diff --git a/sapi/cli/ps_title.c b/sapi/cli/ps_title.c
index 97eec86e5b..6cef483983 100644
--- a/sapi/cli/ps_title.c
+++ b/sapi/cli/ps_title.c
@@ -129,7 +129,9 @@ static char** save_argv;
* This holds the 'locally' allocated environ from the save_ps_args method.
* This is subsequently free'd at exit.
*/
+#if defined(PS_USE_CLOBBER_ARGV)
static char** frozen_environ, **new_environ;
+#endif
/*
* Call this method early, before any code has used the original argv passed in
@@ -311,7 +313,7 @@ const char* ps_title_errno(int rc)
#ifdef PS_USE_WIN32
case PS_TITLE_WINDOWS_ERROR:
- sprintf(windows_error_details, "Windows error code: %u", GetLastError());
+ sprintf(windows_error_details, "Windows error code: %lu", GetLastError());
return windows_error_details;
#endif
}
diff --git a/sapi/cli/tests/bug64529.phpt b/sapi/cli/tests/bug64529.phpt
index d3755724e8..8452953baf 100644
--- a/sapi/cli/tests/bug64529.phpt
+++ b/sapi/cli/tests/bug64529.phpt
@@ -21,7 +21,7 @@ if (extension_loaded("readline")) {
set php_executable [lindex \$argv 0]
-spawn \$php_executable -n -a
+spawn \$php_executable -n -d cli.prompt="" -a
expect "php >"
@@ -39,7 +39,7 @@ SCRIPT;
set php_executable [lindex \$argv 0]
-spawn \$php_executable -n -a
+spawn \$php_executable -n -d cli.prompt="" -a
expect "Interactive mode enabled"
@@ -60,8 +60,8 @@ system($expect_executable . " " . $script . " " . $php_executable);
@unlink($script);
?>
--EXPECTF--
-spawn %sphp -n -a
+spawn %sphp -n -d cli.prompt="" -a
Interactive %s
-%secho 'hello world';
-%sello worl%s
+%Secho 'hello world';
+%Shello world
diff --git a/sapi/embed/php_embed.c b/sapi/embed/php_embed.c
index e0df666108..8bfaf9f52d 100644
--- a/sapi/embed/php_embed.c
+++ b/sapi/embed/php_embed.c
@@ -108,7 +108,7 @@ static int php_embed_startup(sapi_module_struct *sapi_module)
return SUCCESS;
}
-extern EMBED_SAPI_API sapi_module_struct php_embed_module = {
+EMBED_SAPI_API sapi_module_struct php_embed_module = {
"embed", /* name */
"PHP Embedded Library", /* pretty name */
diff --git a/sapi/fpm/fpm/fastcgi.c b/sapi/fpm/fpm/fastcgi.c
index 4f7f5eab9c..3473f4b175 100644
--- a/sapi/fpm/fpm/fastcgi.c
+++ b/sapi/fpm/fpm/fastcgi.c
@@ -137,13 +137,14 @@ typedef union _sa_t {
struct sockaddr sa;
struct sockaddr_un sa_unix;
struct sockaddr_in sa_inet;
+ struct sockaddr_in6 sa_inet6;
} sa_t;
static HashTable fcgi_mgmt_vars;
static int is_initialized = 0;
static int in_shutdown = 0;
-static in_addr_t *allowed_clients = NULL;
+static sa_t *allowed_clients = NULL;
static sa_t client_sa;
@@ -266,15 +267,23 @@ void fcgi_set_allowed_clients(char *ip)
*end = 0;
end++;
}
- allowed_clients[n] = inet_addr(cur);
- if (allowed_clients[n] == INADDR_NONE) {
+ if (inet_pton(AF_INET, cur, &allowed_clients[n].sa_inet.sin_addr)>0) {
+ allowed_clients[n].sa.sa_family = AF_INET;
+ n++;
+ } else if (inet_pton(AF_INET6, cur, &allowed_clients[n].sa_inet6.sin6_addr)>0) {
+ allowed_clients[n].sa.sa_family = AF_INET6;
+ n++;
+ } else {
zlog(ZLOG_ERROR, "Wrong IP address '%s' in listen.allowed_clients", cur);
}
- n++;
cur = end;
}
- allowed_clients[n] = INADDR_NONE;
+ allowed_clients[n].sa.sa_family = 0;
free(ip);
+ if (!n) {
+ zlog(ZLOG_ERROR, "There are no allowed addresses for this pool");
+ /* don't clear allowed_clients as it will create an "open for all" security issue */
+ }
}
}
@@ -749,6 +758,43 @@ void fcgi_close(fcgi_request *req, int force, int destroy)
}
}
+static int fcgi_is_allowed() {
+ int i;
+
+ if (client_sa.sa.sa_family == AF_UNIX) {
+ return 1;
+ }
+ if (!allowed_clients) {
+ return 1;
+ }
+ if (client_sa.sa.sa_family == AF_INET) {
+ for (i=0 ; allowed_clients[i].sa.sa_family ; i++) {
+ if (allowed_clients[i].sa.sa_family == AF_INET
+ && !memcmp(&client_sa.sa_inet.sin_addr, &allowed_clients[i].sa_inet.sin_addr, 4)) {
+ return 1;
+ }
+ }
+ }
+ if (client_sa.sa.sa_family == AF_INET6) {
+ for (i=0 ; allowed_clients[i].sa.sa_family ; i++) {
+ if (allowed_clients[i].sa.sa_family == AF_INET6
+ && !memcmp(&client_sa.sa_inet6.sin6_addr, &allowed_clients[i].sa_inet6.sin6_addr, 12)) {
+ return 1;
+ }
+#ifdef IN6_IS_ADDR_V4MAPPED
+ if (allowed_clients[i].sa.sa_family == AF_INET
+ && IN6_IS_ADDR_V4MAPPED(&client_sa.sa_inet6.sin6_addr)
+ && !memcmp(((char *)&client_sa.sa_inet6.sin6_addr)+12, &allowed_clients[i].sa_inet.sin_addr, 4)) {
+ return 1;
+ }
+#endif
+ }
+ }
+
+ zlog(ZLOG_ERROR, "Connection disallowed: IP address '%s' has been dropped.", fcgi_get_last_client_ip());
+ return 0;
+}
+
int fcgi_accept_request(fcgi_request *req)
{
#ifdef _WIN32
@@ -799,23 +845,10 @@ int fcgi_accept_request(fcgi_request *req)
FCGI_UNLOCK(req->listen_socket);
client_sa = sa;
- if (sa.sa.sa_family == AF_INET && req->fd >= 0 && allowed_clients) {
- int n = 0;
- int allowed = 0;
-
- while (allowed_clients[n] != INADDR_NONE) {
- if (allowed_clients[n] == sa.sa_inet.sin_addr.s_addr) {
- allowed = 1;
- break;
- }
- n++;
- }
- if (!allowed) {
- zlog(ZLOG_ERROR, "Connection disallowed: IP address '%s' has been dropped.", inet_ntoa(sa.sa_inet.sin_addr));
- closesocket(req->fd);
- req->fd = -1;
- continue;
- }
+ if (req->fd >= 0 && !fcgi_is_allowed()) {
+ closesocket(req->fd);
+ req->fd = -1;
+ continue;
}
}
@@ -1073,12 +1106,27 @@ void fcgi_free_mgmt_var_cb(zval *zv)
zend_string_free(Z_STR_P(zv));
}
-char *fcgi_get_last_client_ip() /* {{{ */
+const char *fcgi_get_last_client_ip() /* {{{ */
{
- if (client_sa.sa.sa_family == AF_UNIX) {
- return NULL;
+ static char str[INET6_ADDRSTRLEN];
+
+ /* Ipv4 */
+ if (client_sa.sa.sa_family == AF_INET) {
+ return inet_ntop(client_sa.sa.sa_family, &client_sa.sa_inet.sin_addr, str, INET6_ADDRSTRLEN);
+ }
+#ifdef IN6_IS_ADDR_V4MAPPED
+ /* Ipv4-Mapped-Ipv6 */
+ if (client_sa.sa.sa_family == AF_INET6
+ && IN6_IS_ADDR_V4MAPPED(&client_sa.sa_inet6.sin6_addr)) {
+ return inet_ntop(AF_INET, ((char *)&client_sa.sa_inet6.sin6_addr)+12, str, INET6_ADDRSTRLEN);
}
- return inet_ntoa(client_sa.sa_inet.sin_addr);
+#endif
+ /* Ipv6 */
+ if (client_sa.sa.sa_family == AF_INET6) {
+ return inet_ntop(client_sa.sa.sa_family, &client_sa.sa_inet6.sin6_addr, str, INET6_ADDRSTRLEN);
+ }
+ /* Unix socket */
+ return NULL;
}
/* }}} */
/*
diff --git a/sapi/fpm/fpm/fastcgi.h b/sapi/fpm/fpm/fastcgi.h
index 6d1bb38dba..9c96f763a9 100644
--- a/sapi/fpm/fpm/fastcgi.h
+++ b/sapi/fpm/fpm/fastcgi.h
@@ -133,7 +133,7 @@ int fcgi_flush(fcgi_request *req, int close);
void fcgi_set_mgmt_var(const char * name, size_t name_len, const char * value, size_t value_len);
void fcgi_free_mgmt_var_cb(zval *ptr);
-char *fcgi_get_last_client_ip();
+const char *fcgi_get_last_client_ip();
/*
* Local variables:
diff --git a/sapi/fpm/fpm/fpm_conf.c b/sapi/fpm/fpm/fpm_conf.c
index 18ddccb300..d4e46853ff 100644
--- a/sapi/fpm/fpm/fpm_conf.c
+++ b/sapi/fpm/fpm/fpm_conf.c
@@ -819,7 +819,7 @@ static int fpm_conf_process_all_pools() /* {{{ */
if (config->pm_start_servers <= 0) {
config->pm_start_servers = config->pm_min_spare_servers + ((config->pm_max_spare_servers - config->pm_min_spare_servers) / 2);
- zlog(ZLOG_WARNING, "[pool %s] pm.start_servers is not set. It's been set to %d.", wp->config->name, config->pm_start_servers);
+ zlog(ZLOG_NOTICE, "[pool %s] pm.start_servers is not set. It's been set to %d.", wp->config->name, config->pm_start_servers);
} else if (config->pm_start_servers < config->pm_min_spare_servers || config->pm_start_servers > config->pm_max_spare_servers) {
zlog(ZLOG_ALERT, "[pool %s] pm.start_servers(%d) must not be less than pm.min_spare_servers(%d) and not greater than pm.max_spare_servers(%d)", wp->config->name, config->pm_start_servers, config->pm_min_spare_servers, config->pm_max_spare_servers);
@@ -1159,6 +1159,7 @@ static int fpm_conf_post_process(int force_daemon TSRMLS_DC) /* {{{ */
}
fpm_globals.log_level = fpm_global_config.log_level;
+ zlog_set_level(fpm_globals.log_level);
if (fpm_global_config.process_max < 0) {
zlog(ZLOG_ERROR, "process_max can't be negative");
@@ -1199,15 +1200,15 @@ static int fpm_conf_post_process(int force_daemon TSRMLS_DC) /* {{{ */
return -1;
}
- if (0 > fpm_log_open(0)) {
+ if (0 > fpm_event_pre_init(fpm_global_config.events_mechanism)) {
return -1;
}
- if (0 > fpm_event_pre_init(fpm_global_config.events_mechanism)) {
+ if (0 > fpm_conf_process_all_pools()) {
return -1;
}
- if (0 > fpm_conf_process_all_pools()) {
+ if (0 > fpm_log_open(0)) {
return -1;
}
@@ -1256,7 +1257,7 @@ static void fpm_conf_ini_parser_include(char *inc, void *arg TSRMLS_DC) /* {{{ *
#ifdef HAVE_GLOB
{
g.gl_offs = 0;
- if ((i = glob(inc, GLOB_ERR | GLOB_MARK | GLOB_NOSORT, NULL, &g)) != 0) {
+ if ((i = glob(inc, GLOB_ERR | GLOB_MARK, NULL, &g)) != 0) {
#ifdef GLOB_NOMATCH
if (i == GLOB_NOMATCH) {
zlog(ZLOG_WARNING, "Nothing matches the include pattern '%s' from %s at line %d.", inc, filename, ini_lineno);
diff --git a/sapi/fpm/fpm/fpm_env.c b/sapi/fpm/fpm/fpm_env.c
index 2ff0bdc0e4..3bdb346341 100644
--- a/sapi/fpm/fpm/fpm_env.c
+++ b/sapi/fpm/fpm/fpm_env.c
@@ -212,7 +212,7 @@ int fpm_env_init_main() /* {{{ */
#ifndef HAVE_SETPROCTITLE
#ifdef __linux__
/*
- * This piece of code has been inspirated from nginx and pureftpd code, whic
+ * This piece of code has been inspirated from nginx and pureftpd code, which
* are under BSD licence.
*
* To change the process title in Linux we have to set argv[1] to NULL
diff --git a/sapi/fpm/fpm/fpm_log.c b/sapi/fpm/fpm/fpm_log.c
index 4e1a057db1..b0bf32ac16 100644
--- a/sapi/fpm/fpm/fpm_log.c
+++ b/sapi/fpm/fpm/fpm_log.c
@@ -46,6 +46,8 @@ int fpm_log_open(int reopen) /* {{{ */
if (0 > fd) {
zlog(ZLOG_SYSERROR, "failed to open access log (%s)", wp->config->access_log);
return -1;
+ } else {
+ zlog(ZLOG_DEBUG, "open access log (%s)", wp->config->access_log);
}
if (reopen) {
@@ -367,7 +369,7 @@ int fpm_log_write(char *log_format TSRMLS_DC) /* {{{ */
case 'R': /* remote IP address */
if (!test) {
- char *tmp = fcgi_get_last_client_ip();
+ const char *tmp = fcgi_get_last_client_ip();
len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", tmp ? tmp : "-");
}
break;
diff --git a/sapi/fpm/fpm/fpm_sockets.c b/sapi/fpm/fpm/fpm_sockets.c
index da14d63d8c..e4e494876f 100644
--- a/sapi/fpm/fpm/fpm_sockets.c
+++ b/sapi/fpm/fpm/fpm_sockets.c
@@ -85,13 +85,24 @@ static void *fpm_get_in_addr(struct sockaddr *sa) /* {{{ */
}
/* }}} */
+static int fpm_get_in_port(struct sockaddr *sa) /* {{{ */
+{
+ if (sa->sa_family == AF_INET) {
+ return ntohs(((struct sockaddr_in*)sa)->sin_port);
+ }
+
+ return ntohs(((struct sockaddr_in6*)sa)->sin6_port);
+}
+/* }}} */
+
static int fpm_sockets_hash_op(int sock, struct sockaddr *sa, char *key, int type, int op) /* {{{ */
{
if (key == NULL) {
switch (type) {
case FPM_AF_INET : {
- key = alloca(INET6_ADDRSTRLEN);
- inet_ntop(sa->sa_family, fpm_get_in_addr(sa), key, sizeof key);
+ key = alloca(INET6_ADDRSTRLEN+10);
+ inet_ntop(sa->sa_family, fpm_get_in_addr(sa), key, INET6_ADDRSTRLEN);
+ sprintf(key+strlen(key), ":%d", fpm_get_in_port(sa));
break;
}
@@ -244,9 +255,10 @@ static int fpm_socket_af_inet_listening_socket(struct fpm_worker_pool_s *wp) /*
char *dup_address = strdup(wp->config->listen_address);
char *port_str = strrchr(dup_address, ':');
char *addr = NULL;
+ char tmpbuf[INET6_ADDRSTRLEN];
int addr_len;
int port = 0;
- int sock;
+ int sock = -1;
int status;
if (port_str) { /* this is host:port pair */
@@ -256,6 +268,8 @@ static int fpm_socket_af_inet_listening_socket(struct fpm_worker_pool_s *wp) /*
} else if (strlen(dup_address) == strspn(dup_address, "0123456789")) { /* this is port */
port = atoi(dup_address);
port_str = dup_address;
+ /* IPv6 catch-all + IPv4-mapped */
+ addr = "::";
}
if (port == 0) {
@@ -263,13 +277,11 @@ static int fpm_socket_af_inet_listening_socket(struct fpm_worker_pool_s *wp) /*
return -1;
}
- // strip brackets from address for getaddrinfo
- if (addr != NULL) {
- addr_len = strlen(addr);
- if (addr[0] == '[' && addr[addr_len - 1] == ']') {
- addr[addr_len - 1] = '\0';
- addr++;
- }
+ /* strip brackets from address for getaddrinfo */
+ addr_len = strlen(addr);
+ if (addr[0] == '[' && addr[addr_len - 1] == ']') {
+ addr[addr_len - 1] = '\0';
+ addr++;
}
memset(&hints, 0, sizeof hints);
@@ -281,14 +293,18 @@ static int fpm_socket_af_inet_listening_socket(struct fpm_worker_pool_s *wp) /*
return -1;
}
- free(dup_address);
-
for (p = servinfo; p != NULL; p = p->ai_next) {
- if ((sock = fpm_sockets_get_listening_socket(wp, p->ai_addr, p->ai_addrlen)) != -1) {
- break;
+ inet_ntop(p->ai_family, fpm_get_in_addr(p->ai_addr), tmpbuf, INET6_ADDRSTRLEN);
+ if (sock < 0) {
+ if ((sock = fpm_sockets_get_listening_socket(wp, p->ai_addr, p->ai_addrlen)) != -1) {
+ zlog(ZLOG_DEBUG, "Found address for %s, socket opened on %s", addr, tmpbuf);
+ }
+ } else {
+ zlog(ZLOG_WARNING, "Found multiple addresses for %s, %s ignored", addr, tmpbuf);
}
}
+ free(dup_address);
freeaddrinfo(servinfo);
return sock;
diff --git a/sapi/fpm/fpm/fpm_stdio.c b/sapi/fpm/fpm/fpm_stdio.c
index fcec78435b..e28c0cbe7f 100644
--- a/sapi/fpm/fpm/fpm_stdio.c
+++ b/sapi/fpm/fpm/fpm_stdio.c
@@ -42,9 +42,28 @@ int fpm_stdio_init_main() /* {{{ */
}
/* }}} */
+static inline int fpm_use_error_log() { /* {{{ */
+ /*
+ * the error_log is NOT used when running in foreground
+ * and from a tty (user looking at output).
+ * So, error_log is used by
+ * - SysV init launch php-fpm as a daemon
+ * - Systemd launch php-fpm in foreground
+ */
+#if HAVE_UNISTD_H
+ if (fpm_global_config.daemonize || (!isatty(STDERR_FILENO) && !fpm_globals.force_stderr)) {
+#else
+ if (fpm_global_config.daemonize) {
+#endif
+ return 1;
+ }
+ return 0;
+}
+
+/* }}} */
int fpm_stdio_init_final() /* {{{ */
{
- if (fpm_global_config.daemonize) {
+ if (fpm_use_error_log()) {
/* prevent duping if logging to syslog */
if (fpm_globals.error_log_fd > 0 && fpm_globals.error_log_fd != STDERR_FILENO) {
@@ -67,6 +86,11 @@ int fpm_stdio_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
closelog(); /* ensure to close syslog not to interrupt with PHP syslog code */
} else
#endif
+
+ /* Notice: child cannot use master error_log
+ * because not aware when being reopen
+ * else, should use if (!fpm_use_error_log())
+ */
if (fpm_globals.error_log_fd > 0) {
close(fpm_globals.error_log_fd);
}
@@ -268,11 +292,7 @@ int fpm_stdio_open_error_log(int reopen) /* {{{ */
if (!strcasecmp(fpm_global_config.error_log, "syslog")) {
openlog(fpm_global_config.syslog_ident, LOG_PID | LOG_CONS, fpm_global_config.syslog_facility);
fpm_globals.error_log_fd = ZLOG_SYSLOG;
-#if HAVE_UNISTD_H
- if (fpm_global_config.daemonize || (!isatty(STDERR_FILENO) && !fpm_globals.force_stderr)) {
-#else
- if (fpm_global_config.daemonize) {
-#endif
+ if (fpm_use_error_log()) {
zlog_set_fd(fpm_globals.error_log_fd);
}
return 0;
@@ -286,7 +306,7 @@ int fpm_stdio_open_error_log(int reopen) /* {{{ */
}
if (reopen) {
- if (fpm_global_config.daemonize) {
+ if (fpm_use_error_log()) {
dup2(fd, STDERR_FILENO);
}
@@ -295,11 +315,7 @@ int fpm_stdio_open_error_log(int reopen) /* {{{ */
fd = fpm_globals.error_log_fd; /* for FD_CLOSEXEC to work */
} else {
fpm_globals.error_log_fd = fd;
-#if HAVE_UNISTD_H
- if (fpm_global_config.daemonize || (!isatty(STDERR_FILENO) && !fpm_globals.force_stderr)) {
-#else
- if (fpm_global_config.daemonize) {
-#endif
+ if (fpm_use_error_log()) {
zlog_set_fd(fpm_globals.error_log_fd);
}
}
diff --git a/sapi/fpm/fpm/fpm_unix.c b/sapi/fpm/fpm/fpm_unix.c
index 68978ee75d..32448fc4d5 100644
--- a/sapi/fpm/fpm/fpm_unix.c
+++ b/sapi/fpm/fpm/fpm_unix.c
@@ -396,7 +396,6 @@ int fpm_unix_init_main() /* {{{ */
}
}
- zlog_set_level(fpm_globals.log_level);
return 0;
}
/* }}} */
diff --git a/sapi/fpm/php-fpm.8.in b/sapi/fpm/php-fpm.8.in
index b02aa25ba7..3a697c6a65 100644
--- a/sapi/fpm/php-fpm.8.in
+++ b/sapi/fpm/php-fpm.8.in
@@ -84,6 +84,13 @@ Version number
Specify alternative prefix path (the default is @php_fpm_prefix@)
.TP
.PD 0
+.B \-\-pid \fIfile\fP
+.TP
+.PD 1
+.B \-g
+Specify the PID file location.
+.TP
+.PD 0
.B \-\-fpm\-config \fIfile\fP
.TP
.PD 1
@@ -113,12 +120,18 @@ Force to run in background and ignore daemonize option from configuration file.
Force to stay in foreground and ignore daemonize option from configuration file.
.TP
.PD 0
-.B \-\-zend\-extension \fIfile\fP
+.B \-\-force-stderr
.TP
.PD 1
-.B \-z \fIfile\fP
-Load Zend extension
-.IR file
+.B \-O
+Force output to stderr in nodaemonize even if stderr is not a TTY.
+.TP
+.PD 0
+.B \-\-allow\-to\-run\-as\-root
+.TP
+.PD 1
+.B \-R
+Allow pool to run as root (disabled by default)
.SH FILES
.TP 15
.B php-fpm.conf
diff --git a/sapi/fpm/php-fpm.conf.in b/sapi/fpm/php-fpm.conf.in
index 106689f0a7..850a369002 100644
--- a/sapi/fpm/php-fpm.conf.in
+++ b/sapi/fpm/php-fpm.conf.in
@@ -131,6 +131,7 @@
; Per pool prefix
; It only applies on the following directives:
+; - 'access.log'
; - 'slowlog'
; - 'listen' (unixsocket)
; - 'chroot'
@@ -150,12 +151,12 @@ group = @php_fpm_group@
; The address on which to accept FastCGI requests.
; Valid syntaxes are:
-; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific address on
+; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific IPv4 address on
; a specific port;
; '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on
; a specific port;
-; 'port' - to listen on a TCP socket to all addresses on a
-; specific port;
+; 'port' - to listen on a TCP socket to all addresses
+; (IPv6 and IPv4-mapped) on a specific port;
; '/path/to/unix/socket' - to listen on a unix socket.
; Note: This value is mandatory.
listen = 127.0.0.1:9000
@@ -173,7 +174,7 @@ listen = 127.0.0.1:9000
;listen.group = @php_fpm_group@
;listen.mode = 0660
-; List of ipv4 addresses of FastCGI clients which are allowed to connect.
+; List of addresses (IPv4/IPv6) of FastCGI clients which are allowed to connect.
; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original
; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address
; must be separated by a comma. If this value is left blank, connections will be
diff --git a/sapi/fpm/tests/002.phpt b/sapi/fpm/tests/002.phpt
index 2ef6cedc38..89e431849a 100644
--- a/sapi/fpm/tests/002.phpt
+++ b/sapi/fpm/tests/002.phpt
@@ -8,12 +8,13 @@ FPM: Startup and connect
include "include.inc";
$logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+$port = 9000+PHP_INT_SIZE;
$cfg = <<<EOT
[global]
error_log = $logfile
[unconfined]
-listen = 127.0.0.1:9000
+listen = 127.0.0.1:$port
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
@@ -23,10 +24,9 @@ EOT;
$fpm = run_fpm($cfg, $tail);
if (is_resource($fpm)) {
- var_dump(fgets($tail));
- var_dump(fgets($tail));
+ fpm_display_log($tail, 2);
$i = 0;
- while (($i++ < 30) && !($fp = @fsockopen('127.0.0.1', 9000))) {
+ while (($i++ < 30) && !($fp = @fsockopen('127.0.0.1', $port))) {
usleep(10000);
}
if ($fp) {
@@ -41,10 +41,8 @@ if (is_resource($fpm)) {
?>
--EXPECTF--
-string(%d) "[%d-%s-%d %d:%d:%d] NOTICE: fpm is running, pid %d
-"
-string(%d) "[%d-%s-%d %d:%d:%d] NOTICE: ready to handle connections
-"
+[%d-%s-%d %d:%d:%d] NOTICE: fpm is running, pid %d
+[%d-%s-%d %d:%d:%d] NOTICE: ready to handle connections
Done
--CLEAN--
<?php
diff --git a/sapi/fpm/tests/003.phpt b/sapi/fpm/tests/003.phpt
index 389cb2401e..f928626ecc 100644
--- a/sapi/fpm/tests/003.phpt
+++ b/sapi/fpm/tests/003.phpt
@@ -8,12 +8,13 @@ FPM: Test IPv6 support
include "include.inc";
$logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+$port = 9000+PHP_INT_SIZE;
$cfg = <<<EOT
[global]
error_log = $logfile
[unconfined]
-listen = [::1]:9000
+listen = [::1]:$port
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
@@ -23,10 +24,9 @@ EOT;
$fpm = run_fpm($cfg, $tail);
if (is_resource($fpm)) {
- var_dump(fgets($tail));
- var_dump(fgets($tail));
+ fpm_display_log($tail, 2);
$i = 0;
- while (($i++ < 30) && !($fp = fsockopen('[::1]', 9000))) {
+ while (($i++ < 30) && !($fp = fsockopen('[::1]', $port))) {
usleep(10000);
}
if ($fp) {
@@ -41,10 +41,8 @@ if (is_resource($fpm)) {
?>
--EXPECTF--
-string(%d) "[%d-%s-%d %d:%d:%d] NOTICE: fpm is running, pid %d
-"
-string(%d) "[%d-%s-%d %d:%d:%d] NOTICE: ready to handle connections
-"
+[%d-%s-%d %d:%d:%d] NOTICE: fpm is running, pid %d
+[%d-%s-%d %d:%d:%d] NOTICE: ready to handle connections
Done
--CLEAN--
<?php
diff --git a/sapi/fpm/tests/004.phpt b/sapi/fpm/tests/004.phpt
new file mode 100644
index 0000000000..2a4d666c64
--- /dev/null
+++ b/sapi/fpm/tests/004.phpt
@@ -0,0 +1,59 @@
+--TEST--
+FPM: Test IPv4/IPv6 support
+--SKIPIF--
+<?php include "skipif.inc"; ?>
+--FILE--
+<?php
+
+include "include.inc";
+
+$logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+$port = 9000+PHP_INT_SIZE;
+
+$cfg = <<<EOT
+[global]
+error_log = $logfile
+[unconfined]
+listen = [::]:$port
+pm = dynamic
+pm.max_children = 5
+pm.start_servers = 2
+pm.min_spare_servers = 1
+pm.max_spare_servers = 3
+EOT;
+
+$fpm = run_fpm($cfg, $tail);
+if (is_resource($fpm)) {
+ fpm_display_log($tail, 2);
+ $i = 0;
+ while (($i++ < 30) && !($fp = @fsockopen('127.0.0.1', $port))) {
+ usleep(10000);
+ }
+ if ($fp) {
+ echo "Done IPv4\n";
+ fclose($fp);
+ }
+ while (($i++ < 30) && !($fp = @fsockopen('[::1]', $port))) {
+ usleep(10000);
+ }
+ if ($fp) {
+ echo "Done IPv6\n";
+ fclose($fp);
+ }
+ proc_terminate($fpm);
+ stream_get_contents($tail);
+ fclose($tail);
+ proc_close($fpm);
+}
+
+?>
+--EXPECTF--
+[%d-%s-%d %d:%d:%d] NOTICE: fpm is running, pid %d
+[%d-%s-%d %d:%d:%d] NOTICE: ready to handle connections
+Done IPv4
+Done IPv6
+--CLEAN--
+<?php
+ $logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+ @unlink($logfile);
+?>
diff --git a/sapi/fpm/tests/005.phpt b/sapi/fpm/tests/005.phpt
new file mode 100644
index 0000000000..c565c2a9eb
--- /dev/null
+++ b/sapi/fpm/tests/005.phpt
@@ -0,0 +1,57 @@
+--TEST--
+FPM: Test IPv4 allowed clients
+--SKIPIF--
+<?php include "skipif.inc"; ?>
+--FILE--
+<?php
+
+include "include.inc";
+
+$logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+$port = 9000+PHP_INT_SIZE;
+
+$cfg = <<<EOT
+[global]
+error_log = $logfile
+[unconfined]
+listen = [::]:$port
+listen.allowed_clients = 127.0.0.1
+pm = dynamic
+pm.max_children = 5
+pm.start_servers = 2
+pm.min_spare_servers = 1
+pm.max_spare_servers = 3
+EOT;
+
+$fpm = run_fpm($cfg, $tail);
+if (is_resource($fpm)) {
+ fpm_display_log($tail, 2);
+ try {
+ run_request('127.0.0.1', $port);
+ echo "IPv4 ok\n";
+ } catch (Exception $e) {
+ echo "IPv4 error\n";
+ }
+ try {
+ run_request('[::1]', $port);
+ echo "IPv6 ok\n";
+ } catch (Exception $e) {
+ echo "IPv6 error\n";
+ }
+ proc_terminate($fpm);
+ stream_get_contents($tail);
+ fclose($tail);
+ proc_close($fpm);
+}
+
+?>
+--EXPECTF--
+[%d-%s-%d %d:%d:%d] NOTICE: fpm is running, pid %d
+[%d-%s-%d %d:%d:%d] NOTICE: ready to handle connections
+IPv4 ok
+IPv6 error
+--CLEAN--
+<?php
+ $logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+ @unlink($logfile);
+?>
diff --git a/sapi/fpm/tests/006.phpt b/sapi/fpm/tests/006.phpt
new file mode 100644
index 0000000000..a12ca253d2
--- /dev/null
+++ b/sapi/fpm/tests/006.phpt
@@ -0,0 +1,57 @@
+--TEST--
+FPM: Test IPv6 allowed clients (bug #68428)
+--SKIPIF--
+<?php include "skipif.inc"; ?>
+--FILE--
+<?php
+
+include "include.inc";
+
+$logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+$port = 9000+PHP_INT_SIZE;
+
+$cfg = <<<EOT
+[global]
+error_log = $logfile
+[unconfined]
+listen = [::]:$port
+listen.allowed_clients = ::1
+pm = dynamic
+pm.max_children = 5
+pm.start_servers = 2
+pm.min_spare_servers = 1
+pm.max_spare_servers = 3
+EOT;
+
+$fpm = run_fpm($cfg, $tail);
+if (is_resource($fpm)) {
+ fpm_display_log($tail, 2);
+ try {
+ run_request('127.0.0.1', $port);
+ echo "IPv4 ok\n";
+ } catch (Exception $e) {
+ echo "IPv4 error\n";
+ }
+ try {
+ run_request('[::1]', $port);
+ echo "IPv6 ok\n";
+ } catch (Exception $e) {
+ echo "IPv6 error\n";
+ }
+ proc_terminate($fpm);
+ stream_get_contents($tail);
+ fclose($tail);
+ proc_close($fpm);
+}
+
+?>
+--EXPECTF--
+[%d-%s-%d %d:%d:%d] NOTICE: fpm is running, pid %d
+[%d-%s-%d %d:%d:%d] NOTICE: ready to handle connections
+IPv4 error
+IPv6 ok
+--CLEAN--
+<?php
+ $logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+ @unlink($logfile);
+?>
diff --git a/sapi/fpm/tests/007.phpt b/sapi/fpm/tests/007.phpt
new file mode 100644
index 0000000000..0d817907cf
--- /dev/null
+++ b/sapi/fpm/tests/007.phpt
@@ -0,0 +1,68 @@
+--TEST--
+FPM: Test IPv6 all addresses and access_log (bug #68421)
+--SKIPIF--
+<?php include "skipif.inc"; ?>
+--FILE--
+<?php
+
+include "include.inc";
+
+$logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+$accfile = dirname(__FILE__).'/php-fpm.acc.tmp';
+$port = 9000+PHP_INT_SIZE;
+
+$cfg = <<<EOT
+[global]
+error_log = $logfile
+[unconfined]
+listen = [::]:$port
+access.log = $accfile
+ping.path = /ping
+ping.response = pong
+pm = dynamic
+pm.max_children = 5
+pm.start_servers = 2
+pm.min_spare_servers = 1
+pm.max_spare_servers = 3
+EOT;
+
+$fpm = run_fpm($cfg, $tail);
+if (is_resource($fpm)) {
+ fpm_display_log($tail, 2);
+ try {
+ var_dump(strpos(run_request('127.0.0.1', $port), 'pong'));
+ echo "IPv4 ok\n";
+ } catch (Exception $e) {
+ echo "IPv4 error\n";
+ }
+ try {
+ var_dump(strpos(run_request('[::1]', $port), 'pong'));
+ echo "IPv6 ok\n";
+ } catch (Exception $e) {
+ echo "IPv6 error\n";
+ }
+ proc_terminate($fpm);
+ stream_get_contents($tail);
+ fclose($tail);
+ proc_close($fpm);
+
+ echo file_get_contents($accfile);
+}
+
+?>
+--EXPECTF--
+[%d-%s-%d %d:%d:%d] NOTICE: fpm is running, pid %d
+[%d-%s-%d %d:%d:%d] NOTICE: ready to handle connections
+int(%d)
+IPv4 ok
+int(%d)
+IPv6 ok
+127.0.0.1 %s "GET /ping" 200
+::1 %s "GET /ping" 200
+--CLEAN--
+<?php
+ $logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+ @unlink($logfile);
+ $accfile = dirname(__FILE__).'/php-fpm.acc.tmp';
+ @unlink($accfile);
+?>
diff --git a/sapi/fpm/tests/008.phpt b/sapi/fpm/tests/008.phpt
new file mode 100644
index 0000000000..60f1ea6ebd
--- /dev/null
+++ b/sapi/fpm/tests/008.phpt
@@ -0,0 +1,84 @@
+--TEST--
+FPM: Test multi pool (dynamic + ondemand + static) (bug #68423)
+--SKIPIF--
+<?php include "skipif.inc"; ?>
+--FILE--
+<?php
+
+include "include.inc";
+
+$logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+$port1 = 9000+PHP_INT_SIZE;
+$port2 = 9001+PHP_INT_SIZE;
+$port3 = 9002+PHP_INT_SIZE;
+
+$cfg = <<<EOT
+[global]
+error_log = $logfile
+[pool_dynamic]
+listen = 127.0.0.1:$port1
+ping.path = /ping
+ping.response = pong-dynamic
+pm = dynamic
+pm.max_children = 5
+pm.start_servers = 2
+pm.min_spare_servers = 1
+pm.max_spare_servers = 3
+[poold_ondemand]
+listen = 127.0.0.1:$port2
+ping.path = /ping
+ping.response = pong-on-demand
+pm = ondemand
+pm.max_children = 2
+pm.process_idle_timeout = 10
+[pool_static]
+listen = 127.0.0.1:$port3
+ping.path = /ping
+ping.response = pong-static
+pm = static
+pm.max_children = 2
+EOT;
+
+$fpm = run_fpm($cfg, $tail);
+if (is_resource($fpm)) {
+ fpm_display_log($tail, 2);
+ try {
+ var_dump(strpos(run_request('127.0.0.1', $port1), 'pong-dynamic'));
+ echo "Dynamic ok\n";
+ } catch (Exception $e) {
+ echo "Dynamic error\n";
+ }
+ try {
+ var_dump(strpos(run_request('127.0.0.1', $port2), 'pong-on-demand'));
+ echo "OnDemand ok\n";
+ } catch (Exception $e) {
+ echo "OnDemand error\n";
+ }
+ try {
+ var_dump(strpos(run_request('127.0.0.1', $port3), 'pong-static'));
+ echo "Static ok\n";
+ } catch (Exception $e) {
+ echo "Static error\n";
+ }
+
+ proc_terminate($fpm);
+ stream_get_contents($tail);
+ fclose($tail);
+ proc_close($fpm);
+}
+
+?>
+--EXPECTF--
+[%d-%s-%d %d:%d:%d] NOTICE: fpm is running, pid %d
+[%d-%s-%d %d:%d:%d] NOTICE: ready to handle connections
+int(%d)
+Dynamic ok
+int(%d)
+OnDemand ok
+int(%d)
+Static ok
+--CLEAN--
+<?php
+ $logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+ @unlink($logfile);
+?>
diff --git a/sapi/fpm/tests/009.phpt b/sapi/fpm/tests/009.phpt
new file mode 100644
index 0000000000..34cdffcf83
--- /dev/null
+++ b/sapi/fpm/tests/009.phpt
@@ -0,0 +1,53 @@
+--TEST--
+FPM: Test Unix Domain Socket
+--SKIPIF--
+<?php include "skipif.inc"; ?>
+--FILE--
+<?php
+
+include "include.inc";
+
+$logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+$socket = dirname(__FILE__).'/php-fpm.sock';
+
+$cfg = <<<EOT
+[global]
+error_log = $logfile
+[unconfined]
+listen = $socket
+ping.path = /ping
+ping.response = pong
+pm = dynamic
+pm.max_children = 5
+pm.start_servers = 2
+pm.min_spare_servers = 1
+pm.max_spare_servers = 3
+EOT;
+
+$fpm = run_fpm($cfg, $tail);
+if (is_resource($fpm)) {
+ fpm_display_log($tail, 2);
+ try {
+ var_dump(strpos(run_request('unix://'.$socket, -1), 'pong'));
+ echo "UDS ok\n";
+ } catch (Exception $e) {
+ echo "UDS error\n";
+ }
+
+ proc_terminate($fpm);
+ stream_get_contents($tail);
+ fclose($tail);
+ proc_close($fpm);
+}
+
+?>
+--EXPECTF--
+[%d-%s-%d %d:%d:%d] NOTICE: fpm is running, pid %d
+[%d-%s-%d %d:%d:%d] NOTICE: ready to handle connections
+int(%d)
+UDS ok
+--CLEAN--
+<?php
+ $logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+ @unlink($logfile);
+?>
diff --git a/sapi/fpm/tests/010.phpt b/sapi/fpm/tests/010.phpt
new file mode 100644
index 0000000000..37c778db5b
--- /dev/null
+++ b/sapi/fpm/tests/010.phpt
@@ -0,0 +1,84 @@
+--TEST--
+FPM: Test status page
+--SKIPIF--
+<?php include "skipif.inc"; ?>
+--FILE--
+<?php
+
+include "include.inc";
+
+$logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+$port = 9000+PHP_INT_SIZE;
+
+$cfg = <<<EOT
+[global]
+error_log = $logfile
+[unconfined]
+listen = 127.0.0.1:$port
+pm.status_path = /status
+pm = dynamic
+pm.max_children = 5
+pm.start_servers = 2
+pm.min_spare_servers = 1
+pm.max_spare_servers = 3
+EOT;
+
+$fpm = run_fpm($cfg, $tail);
+if (is_resource($fpm)) {
+ fpm_display_log($tail, 2);
+ try {
+ echo run_request('127.0.0.1', $port, '/status');
+
+ $html = run_request('127.0.0.1', $port, '/status', 'html');
+ var_dump(strpos($html, 'text/html') && strpos($html, 'DOCTYPE') && strpos($html, 'PHP-FPM Status Page'));
+
+ $json = run_request('127.0.0.1', $port, '/status', 'json');
+ var_dump(strpos($json, 'application/json') && strpos($json, '"pool":"unconfined"'));
+
+ $xml = run_request('127.0.0.1', $port, '/status', 'xml');
+ var_dump(strpos($xml, 'text/xml') && strpos($xml, '<?xml'));
+
+ echo "IPv4 ok\n";
+ } catch (Exception $e) {
+ echo "IPv4 error\n";
+ }
+
+ proc_terminate($fpm);
+ stream_get_contents($tail);
+ fclose($tail);
+ proc_close($fpm);
+}
+
+?>
+--EXPECTF--
+[%d-%s-%d %d:%d:%d] NOTICE: fpm is running, pid %d
+[%d-%s-%d %d:%d:%d] NOTICE: ready to handle connections
+X-Powered-By: PHP/%s
+Expires: %s
+Cache-Control: %s
+Content-type: text/plain%s
+
+pool: unconfined
+process manager: dynamic
+start time: %s
+start since: %d
+accepted conn: 1
+listen queue: 0
+max listen queue: 0
+listen queue len: %d
+idle processes: 1
+active processes: 1
+total processes: 2
+max active processes: 1
+max children reached: 0
+slow requests: 0
+
+bool(true)
+bool(true)
+bool(true)
+IPv4 ok
+--CLEAN--
+<?php
+ $logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+ @unlink($logfile);
+?>
diff --git a/sapi/fpm/tests/011.phpt b/sapi/fpm/tests/011.phpt
new file mode 100644
index 0000000000..0b849f873b
--- /dev/null
+++ b/sapi/fpm/tests/011.phpt
@@ -0,0 +1,53 @@
+--TEST--
+FPM: Test IPv4 all addresses (bug #68420)
+--SKIPIF--
+<?php include "skipif.inc"; ?>
+--FILE--
+<?php
+
+include "include.inc";
+
+$logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+$port = 9000+PHP_INT_SIZE;
+
+$cfg = <<<EOT
+[global]
+error_log = $logfile
+[unconfined]
+listen = $port
+ping.path = /ping
+ping.response = pong
+pm = dynamic
+pm.max_children = 5
+pm.start_servers = 2
+pm.min_spare_servers = 1
+pm.max_spare_servers = 3
+EOT;
+
+$fpm = run_fpm($cfg, $tail);
+if (is_resource($fpm)) {
+ fpm_display_log($tail, 2);
+ try {
+ var_dump(strpos(run_request('127.0.0.1', $port), 'pong'));
+ echo "IPv4 ok\n";
+ } catch (Exception $e) {
+ echo "IPv4 error\n";
+ }
+
+ proc_terminate($fpm);
+ stream_get_contents($tail);
+ fclose($tail);
+ proc_close($fpm);
+}
+
+?>
+--EXPECTF--
+[%d-%s-%d %d:%d:%d] NOTICE: fpm is running, pid %d
+[%d-%s-%d %d:%d:%d] NOTICE: ready to handle connections
+int(%d)
+IPv4 ok
+--CLEAN--
+<?php
+ $logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+ @unlink($logfile);
+?>
diff --git a/sapi/fpm/tests/012.phpt b/sapi/fpm/tests/012.phpt
new file mode 100644
index 0000000000..d96c53081c
--- /dev/null
+++ b/sapi/fpm/tests/012.phpt
@@ -0,0 +1,79 @@
+--TEST--
+FPM: Test reload configuration (bug #68442)
+--SKIPIF--
+<?php include "skipif.inc"; ?>
+--FILE--
+<?php
+
+include "include.inc";
+
+$logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+$pidfile = dirname(__FILE__).'/php-fpm.pid';
+$port = 9000+PHP_INT_SIZE;
+
+$cfg = <<<EOT
+[global]
+error_log = $logfile
+pid = $pidfile
+[unconfined]
+listen = 127.0.0.1:$port
+ping.path = /ping
+ping.response = pong
+pm = dynamic
+pm.max_children = 5
+pm.start_servers = 2
+pm.min_spare_servers = 1
+pm.max_spare_servers = 3
+EOT;
+
+$fpm = run_fpm($cfg, $tail);
+if (is_resource($fpm)) {
+ fpm_display_log($tail, 2);
+ try {
+ var_dump(strpos(run_request('127.0.0.1', $port), 'pong'));
+ echo "IPv4 ok\n";
+ } catch (Exception $e) {
+ echo "IPv4 error\n";
+ }
+
+ $pid=file_get_contents($pidfile);
+ if ($pid) {
+ exec("kill -USR2 $pid");
+ } else {
+ die("PID not found\n");
+ }
+ fpm_display_log($tail, 5);
+
+ try {
+ var_dump(strpos(run_request('127.0.0.1', $port), 'pong'));
+ echo "IPv4 ok\n";
+ } catch (Exception $e) {
+ echo "IPv4 error\n";
+ }
+
+ proc_terminate($fpm);
+ stream_get_contents($tail);
+ fclose($tail);
+ proc_close($fpm);
+}
+
+?>
+--EXPECTF--
+[%d-%s-%d %d:%d:%d] NOTICE: fpm is running, pid %d
+[%d-%s-%d %d:%d:%d] NOTICE: ready to handle connections
+int(%d)
+IPv4 ok
+[%d-%s-%d %d:%d:%d] NOTICE: Reloading in progress ...
+[%d-%s-%d %d:%d:%d] NOTICE: reloading: %s
+[%d-%s-%d %d:%d:%d] NOTICE: using inherited socket fd=%d, "127.0.0.1:%d"
+[%d-%s-%d %d:%d:%d] NOTICE: fpm is running, pid %d
+[%d-%s-%d %d:%d:%d] NOTICE: ready to handle connections
+int(%d)
+IPv4 ok
+--CLEAN--
+<?php
+ $logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+ @unlink($logfile);
+ $pidfile = dirname(__FILE__).'/php-fpm.pid';
+ @unlink($pidfile);
+?>
diff --git a/sapi/fpm/tests/013.phpt b/sapi/fpm/tests/013.phpt
new file mode 100644
index 0000000000..8d6a9d1d85
--- /dev/null
+++ b/sapi/fpm/tests/013.phpt
@@ -0,0 +1,54 @@
+--TEST--
+FPM: Test for log_level in fpm_unix_init_main #68381
+--SKIPIF--
+<?php include "skipif.inc"; ?>
+--FILE--
+<?php
+
+include "include.inc";
+
+$logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+$port = 9000+PHP_INT_SIZE;
+
+$cfg = <<<EOT
+[global]
+error_log = $logfile
+log_level = warning
+[unconfined]
+listen = 127.0.0.1:$port
+user = foo
+pm = dynamic
+pm.max_children = 5
+pm.start_servers = 2
+pm.min_spare_servers = 1
+pm.max_spare_servers = 3
+EOT;
+
+$fpm = run_fpm($cfg, $tail);
+if (is_resource($fpm)) {
+ $i = 0;
+ while (($i++ < 30) && !($fp = @fsockopen('127.0.0.1', $port))) {
+ usleep(10000);
+ }
+ if ($fp) {
+ echo "Started\n";
+ fclose($fp);
+ }
+ proc_terminate($fpm);
+ if (!feof($tail)) {
+ echo stream_get_contents($tail);
+ }
+ fclose($tail);
+ proc_close($fpm);
+}
+
+?>
+Done
+--EXPECTF--
+Started
+Done
+--CLEAN--
+<?php
+ $logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+ @unlink($logfile);
+?> \ No newline at end of file
diff --git a/sapi/fpm/tests/014.phpt b/sapi/fpm/tests/014.phpt
new file mode 100644
index 0000000000..ee0e549cc5
--- /dev/null
+++ b/sapi/fpm/tests/014.phpt
@@ -0,0 +1,54 @@
+--TEST--
+FPM: Test for pm.start_servers default calculation message being a notice and not a warning #68458
+--SKIPIF--
+<?php include "skipif.inc"; ?>
+--FILE--
+<?php
+
+include "include.inc";
+
+$logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+$port = 9000+PHP_INT_SIZE;
+
+$cfg = <<<EOT
+[global]
+error_log = $logfile
+log_level = warning
+[unconfined]
+listen = 127.0.0.1:$port
+user = foo
+pm = dynamic
+pm.max_children = 5
+;pm.start_servers = 2
+pm.min_spare_servers = 1
+pm.max_spare_servers = 3
+EOT;
+
+$fpm = run_fpm($cfg, $tail);
+if (is_resource($fpm)) {
+ $i = 0;
+ while (($i++ < 30) && !($fp = @fsockopen('127.0.0.1', $port))) {
+ usleep(10000);
+ }
+ if ($fp) {
+ echo "Started\n";
+ fclose($fp);
+ }
+ proc_terminate($fpm);
+ if (!feof($tail)) {
+ echo stream_get_contents($tail);
+ }
+ fclose($tail);
+ proc_close($fpm);
+}
+
+?>
+Done
+--EXPECTF--
+Started
+Done
+--CLEAN--
+<?php
+ $logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+ @unlink($logfile);
+?> \ No newline at end of file
diff --git a/sapi/fpm/tests/015.phpt b/sapi/fpm/tests/015.phpt
new file mode 100644
index 0000000000..fba333e256
--- /dev/null
+++ b/sapi/fpm/tests/015.phpt
@@ -0,0 +1,87 @@
+--TEST--
+FPM: Test various messages on start, from master and childs
+--SKIPIF--
+<?php include "skipif.inc"; ?>
+--FILE--
+<?php
+
+include "include.inc";
+
+$logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+$port1 = 9000+PHP_INT_SIZE;
+$port2 = 9001+PHP_INT_SIZE;
+
+$cfg = <<<EOT
+[global]
+error_log = $logfile
+log_level = notice
+[pool1]
+listen = 127.0.0.1:$port1
+listen.allowed_clients=127.0.0.1
+user = foo
+pm = dynamic
+pm.max_children = 5
+pm.min_spare_servers = 1
+pm.max_spare_servers = 3
+catch_workers_output = yes
+[pool2]
+listen = 127.0.0.1:$port2
+listen.allowed_clients=xxx
+pm = dynamic
+pm.max_children = 5
+pm.start_servers = 1
+pm.min_spare_servers = 1
+pm.max_spare_servers = 3
+catch_workers_output = yes
+EOT;
+
+$fpm = run_fpm($cfg, $tail);
+if (is_resource($fpm)) {
+ $i = 0;
+ while (($i++ < 30) && !($fp = @fsockopen('127.0.0.1', $port1))) {
+ usleep(10000);
+ }
+ if ($fp) {
+ echo "Started\n";
+ fclose($fp);
+ }
+ for ($i=0 ; $i<10 ; $i++) {
+ try {
+ run_request('127.0.0.1', $port1);
+ } catch (Exception $e) {
+ echo "Error 1\n";
+ }
+ }
+ try {
+ run_request('127.0.0.1', $port2);
+ } catch (Exception $e) {
+ echo "Error 2\n";
+ }
+ proc_terminate($fpm);
+ if (!feof($tail)) {
+ echo stream_get_contents($tail);
+ }
+ fclose($tail);
+ proc_close($fpm);
+}
+
+?>
+Done
+--EXPECTF--
+Started
+Error 2
+[%s] NOTICE: [pool pool1] pm.start_servers is not set. It's been set to 2.
+[%s] NOTICE: [pool pool1] 'user' directive is ignored when FPM is not running as root
+[%s] NOTICE: fpm is running, pid %d
+[%s] NOTICE: ready to handle connections
+[%s] WARNING: [pool pool2] child %d said into stderr: "ERROR: Wrong IP address 'xxx' in listen.allowed_clients"
+[%s] WARNING: [pool pool2] child %d said into stderr: "ERROR: There are no allowed addresses for this pool"
+[%s] WARNING: [pool pool2] child %d said into stderr: "ERROR: Connection disallowed: IP address '127.0.0.1' has been dropped."
+[%s] NOTICE: Terminating ...
+[%s] NOTICE: exiting, bye-bye!
+Done
+--CLEAN--
+<?php
+ $logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+ @unlink($logfile);
+?> \ No newline at end of file
diff --git a/sapi/fpm/tests/016.phpt b/sapi/fpm/tests/016.phpt
new file mode 100644
index 0000000000..1a9e8e7577
--- /dev/null
+++ b/sapi/fpm/tests/016.phpt
@@ -0,0 +1,87 @@
+--TEST--
+FPM: Test splited configuration and load order #68391
+--SKIPIF--
+<?php include "skipif.inc"; ?>
+--FILE--
+<?php
+
+include "include.inc";
+
+$logfile = __DIR__.'/php-fpm.log.tmp';
+$logdir = __DIR__.'/conf.d';
+$port = 9000+PHP_INT_SIZE;
+
+// Main configuration
+$cfg = <<<EOT
+[global]
+error_log = $logfile
+log_level = notice
+include = $logdir/*.conf
+EOT;
+
+// Splited configuration
+@mkdir($logdir);
+$i=$port;
+$names = ['cccc', 'aaaa', 'eeee', 'dddd', 'bbbb'];
+foreach($names as $name) {
+ $poolcfg = <<<EOT
+[$name]
+listen = 127.0.0.1:$i
+listen.allowed_clients=127.0.0.1
+user = foo
+pm = ondemand
+pm.max_children = 5
+EOT;
+ file_put_contents("$logdir/$name.conf", $poolcfg);
+ $i++;
+}
+
+// Test
+$fpm = run_fpm($cfg, $tail);
+if (is_resource($fpm)) {
+ fpm_display_log($tail, count($names)+2);
+ $i=$port;
+ foreach($names as $name) {
+ try {
+ run_request('127.0.0.1', $i++);
+ echo "OK $name\n";
+ } catch (Exception $e) {
+ echo "Error 1\n";
+ }
+ }
+ proc_terminate($fpm);
+ if (!feof($tail)) {
+ echo stream_get_contents($tail);
+ }
+ fclose($tail);
+ proc_close($fpm);
+}
+
+?>
+Done
+--EXPECTF--
+[%s] NOTICE: [pool aaaa] 'user' directive is ignored when FPM is not running as root
+[%s] NOTICE: [pool bbbb] 'user' directive is ignored when FPM is not running as root
+[%s] NOTICE: [pool cccc] 'user' directive is ignored when FPM is not running as root
+[%s] NOTICE: [pool dddd] 'user' directive is ignored when FPM is not running as root
+[%s] NOTICE: [pool eeee] 'user' directive is ignored when FPM is not running as root
+[%s] NOTICE: fpm is running, pid %d
+[%s] NOTICE: ready to handle connections
+OK cccc
+OK aaaa
+OK eeee
+OK dddd
+OK bbbb
+[%s] NOTICE: Terminating ...
+[%s] NOTICE: exiting, bye-bye!
+Done
+--CLEAN--
+<?php
+ $logfile = __DIR__.'/php-fpm.log.tmp';
+ $logdir = __DIR__.'/conf.d';
+ @unlink($logfile);
+ foreach(glob("$logdir/*.conf") as $name) {
+ unlink($name);
+ }
+ @rmdir($logdir);
+?> \ No newline at end of file
diff --git a/sapi/fpm/tests/017.phpt b/sapi/fpm/tests/017.phpt
new file mode 100644
index 0000000000..b3de089a70
--- /dev/null
+++ b/sapi/fpm/tests/017.phpt
@@ -0,0 +1,67 @@
+--TEST--
+FPM: Test fastcgi_finish_request function
+--SKIPIF--
+<?php include "skipif.inc"; ?>
+--FILE--
+<?php
+
+include "include.inc";
+
+$logfile = __DIR__.'/php-fpm.log.tmp';
+$srcfile = __DIR__.'/php-fpm.tmp.php';
+$port = 9000+PHP_INT_SIZE;
+
+$cfg = <<<EOT
+[global]
+error_log = $logfile
+[unconfined]
+listen = 127.0.0.1:$port
+pm = dynamic
+pm.max_children = 5
+pm.start_servers = 1
+pm.min_spare_servers = 1
+pm.max_spare_servers = 3
+EOT;
+
+$code = <<<EOT
+<?php
+echo "Test Start\n";
+fastcgi_finish_request();
+echo "Test End\n";
+EOT;
+file_put_contents($srcfile, $code);
+
+$fpm = run_fpm($cfg, $tail);
+if (is_resource($fpm)) {
+ fpm_display_log($tail, 2);
+ try {
+ $req = run_request('127.0.0.1', $port, $srcfile);
+ echo strstr($req, "Test Start");
+ echo "Request ok\n";
+ } catch (Exception $e) {
+ echo "Request error\n";
+ }
+ proc_terminate($fpm);
+ echo stream_get_contents($tail);
+ fclose($tail);
+ proc_close($fpm);
+}
+
+?>
+Done
+--EXPECTF--
+[%s] NOTICE: fpm is running, pid %d
+[%s] NOTICE: ready to handle connections
+Test Start
+
+Request ok
+[%s] NOTICE: Terminating ...
+[%s] NOTICE: exiting, bye-bye!
+Done
+--CLEAN--
+<?php
+ $logfile = __DIR__.'/php-fpm.log.tmp';
+ $srcfile = __DIR__.'/php-fpm.tmp.php';
+ @unlink($logfile);
+ @unlink($srcfile);
+?> \ No newline at end of file
diff --git a/sapi/fpm/tests/019.phpt b/sapi/fpm/tests/019.phpt
new file mode 100644
index 0000000000..cdf8126244
--- /dev/null
+++ b/sapi/fpm/tests/019.phpt
@@ -0,0 +1,80 @@
+--TEST--
+FPM: Test global prefix
+--SKIPIF--
+<?php include "skipif.inc"; ?>
+--FILE--
+<?php
+
+include "include.inc";
+
+$logfile = 'php-fpm.log.tmp';
+$accfile = 'php-fpm.acc.tmp';
+$slwfile = 'php-fpm.slw.tmp';
+$pidfile = 'php-fpm.pid.tmp';
+$port = 9000+PHP_INT_SIZE;
+
+$cfg = <<<EOT
+[global]
+error_log = $logfile
+pid = $pidfile
+[test]
+listen = 127.0.0.1:$port
+access.log = $accfile
+slowlog = $slwfile;
+request_slowlog_timeout = 1
+ping.path = /ping
+ping.response = pong
+pm = dynamic
+pm.max_children = 5
+pm.start_servers = 2
+pm.min_spare_servers = 1
+pm.max_spare_servers = 3
+catch_workers_output = yes
+EOT;
+
+$fpm = run_fpm($cfg, $tail, '--prefix '.__DIR__);
+if (is_resource($fpm)) {
+ fpm_display_log($tail, 2);
+ try {
+ run_request('127.0.0.1', $port);
+ echo "Ping ok\n";
+ } catch (Exception $e) {
+ echo "Ping error\n";
+ }
+ printf("File %s %s\n", $logfile, (file_exists(__DIR__.'/'.$logfile) ? "exists" : "missing"));
+ printf("File %s %s\n", $accfile, (file_exists(__DIR__.'/'.$accfile) ? "exists" : "missing"));
+ printf("File %s %s\n", $slwfile, (file_exists(__DIR__.'/'.$slwfile) ? "exists" : "missing"));
+ printf("File %s %s\n", $pidfile, (file_exists(__DIR__.'/'.$pidfile) ? "exists" : "missing"));
+
+ proc_terminate($fpm);
+ echo stream_get_contents($tail);
+ fclose($tail);
+ proc_close($fpm);
+ printf("File %s %s\n", $pidfile, (file_exists(__DIR__.'/'.$pidfile) ? "still exists" : "removed"));
+ readfile(__DIR__.'/'.$accfile);
+}
+
+?>
+--EXPECTF--
+[%s] NOTICE: fpm is running, pid %d
+[%s] NOTICE: ready to handle connections
+Ping ok
+File php-fpm.log.tmp exists
+File php-fpm.acc.tmp exists
+File php-fpm.slw.tmp exists
+File php-fpm.pid.tmp exists
+[%s] NOTICE: Terminating ...
+[%s] NOTICE: exiting, bye-bye!
+File php-fpm.pid.tmp removed
+127.0.0.1 - %s "GET /ping" 200
+--CLEAN--
+<?php
+ $logfile = __DIR__.'/php-fpm.log.tmp';
+ $accfile = __DIR__.'/php-fpm.acc.tmp';
+ $slwfile = __DIR__.'/php-fpm.slw.tmp';
+ $pidfile = __DIR__.'/php-fpm.pid.tmp';
+ @unlink($logfile);
+ @unlink($accfile);
+ @unlink($slwfile);
+ @unlink($pidfile);
+?>
diff --git a/sapi/fpm/tests/020.phpt b/sapi/fpm/tests/020.phpt
new file mode 100644
index 0000000000..d45eeccff8
--- /dev/null
+++ b/sapi/fpm/tests/020.phpt
@@ -0,0 +1,76 @@
+--TEST--
+FPM: Test pool prefix
+--SKIPIF--
+<?php include "skipif.inc"; ?>
+--FILE--
+<?php
+
+include "include.inc";
+
+$prefix = __DIR__;
+$logfile = __DIR__.'/php-fpm.log.tmp';
+$accfile = 'php-fpm.acc.tmp';
+$slwfile = 'php-fpm.slw.tmp';
+$pidfile = __DIR__.'/php-fpm.pid.tmp';
+$port = 9000+PHP_INT_SIZE;
+$cfg = <<<EOT
+
+[global]
+error_log = $logfile
+pid = $pidfile
+[test]
+prefix = $prefix;
+listen = 127.0.0.1:$port
+access.log = $accfile
+slowlog = $slwfile;
+request_slowlog_timeout = 1
+ping.path = /ping
+ping.response = pong
+pm = dynamic
+pm.max_children = 5
+pm.start_servers = 2
+pm.min_spare_servers = 1
+pm.max_spare_servers = 3
+catch_workers_output = yes
+EOT;
+
+$fpm = run_fpm($cfg, $tail);
+if (is_resource($fpm)) {
+ fpm_display_log($tail, 2);
+ try {
+ run_request('127.0.0.1', $port);
+ echo "Ping ok\n";
+ } catch (Exception $e) {
+ echo "Ping error\n";
+ }
+ printf("File %s %s\n", $accfile, (file_exists(__DIR__.'/'.$accfile) ? "exists" : "missing"));
+ printf("File %s %s\n", $slwfile, (file_exists(__DIR__.'/'.$slwfile) ? "exists" : "missing"));
+
+ proc_terminate($fpm);
+ echo stream_get_contents($tail);
+ fclose($tail);
+ proc_close($fpm);
+ readfile(__DIR__.'/'.$accfile);
+}
+
+?>
+--EXPECTF--
+[%s] NOTICE: fpm is running, pid %d
+[%s] NOTICE: ready to handle connections
+Ping ok
+File php-fpm.acc.tmp exists
+File php-fpm.slw.tmp exists
+[%s] NOTICE: Terminating ...
+[%s] NOTICE: exiting, bye-bye!
+127.0.0.1 - %s "GET /ping" 200
+--CLEAN--
+<?php
+ $logfile = __DIR__.'/php-fpm.log.tmp';
+ $accfile = __DIR__.'/php-fpm.acc.tmp';
+ $slwfile = __DIR__.'/php-fpm.slw.tmp';
+ $pidfile = __DIR__.'/php-fpm.pid.tmp';
+ @unlink($logfile);
+ @unlink($accfile);
+ @unlink($slwfile);
+ @unlink($pidfile);
+?>
diff --git a/sapi/fpm/tests/fcgi.inc b/sapi/fpm/tests/fcgi.inc
new file mode 100644
index 0000000000..b31676260d
--- /dev/null
+++ b/sapi/fpm/tests/fcgi.inc
@@ -0,0 +1,592 @@
+<?php
+/*
+ * This file is part of PHP-FastCGI-Client.
+ *
+ * (c) Pierrick Charron <pierrick@adoy.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace Adoy\FastCGI;
+
+class TimedOutException extends \Exception {}
+class ForbiddenException extends \Exception {}
+
+/**
+ * Handles communication with a FastCGI application
+ *
+ * @author Pierrick Charron <pierrick@adoy.net>
+ * @version 1.0
+ */
+class Client
+{
+ const VERSION_1 = 1;
+
+ const BEGIN_REQUEST = 1;
+ const ABORT_REQUEST = 2;
+ const END_REQUEST = 3;
+ const PARAMS = 4;
+ const STDIN = 5;
+ const STDOUT = 6;
+ const STDERR = 7;
+ const DATA = 8;
+ const GET_VALUES = 9;
+ const GET_VALUES_RESULT = 10;
+ const UNKNOWN_TYPE = 11;
+ const MAXTYPE = self::UNKNOWN_TYPE;
+
+ const RESPONDER = 1;
+ const AUTHORIZER = 2;
+ const FILTER = 3;
+
+ const REQUEST_COMPLETE = 0;
+ const CANT_MPX_CONN = 1;
+ const OVERLOADED = 2;
+ const UNKNOWN_ROLE = 3;
+
+ const MAX_CONNS = 'MAX_CONNS';
+ const MAX_REQS = 'MAX_REQS';
+ const MPXS_CONNS = 'MPXS_CONNS';
+
+ const HEADER_LEN = 8;
+
+ const REQ_STATE_WRITTEN = 1;
+ const REQ_STATE_OK = 2;
+ const REQ_STATE_ERR = 3;
+ const REQ_STATE_TIMED_OUT = 4;
+
+ /**
+ * Socket
+ * @var Resource
+ */
+ private $_sock = null;
+
+ /**
+ * Host
+ * @var String
+ */
+ private $_host = null;
+
+ /**
+ * Port
+ * @var Integer
+ */
+ private $_port = null;
+
+ /**
+ * Keep Alive
+ * @var Boolean
+ */
+ private $_keepAlive = false;
+
+ /**
+ * Outstanding request statuses keyed by request id
+ *
+ * Each request is an array with following form:
+ *
+ * array(
+ * 'state' => REQ_STATE_*
+ * 'response' => null | string
+ * )
+ *
+ * @var array
+ */
+ private $_requests = array();
+
+ /**
+ * Use persistent sockets to connect to backend
+ * @var Boolean
+ */
+ private $_persistentSocket = false;
+
+ /**
+ * Connect timeout in milliseconds
+ * @var Integer
+ */
+ private $_connectTimeout = 5000;
+
+ /**
+ * Read/Write timeout in milliseconds
+ * @var Integer
+ */
+ private $_readWriteTimeout = 5000;
+
+ /**
+ * Constructor
+ *
+ * @param String $host Host of the FastCGI application
+ * @param Integer $port Port of the FastCGI application
+ */
+ public function __construct($host, $port)
+ {
+ $this->_host = $host;
+ $this->_port = $port;
+ }
+
+ /**
+ * Define whether or not the FastCGI application should keep the connection
+ * alive at the end of a request
+ *
+ * @param Boolean $b true if the connection should stay alive, false otherwise
+ */
+ public function setKeepAlive($b)
+ {
+ $this->_keepAlive = (boolean)$b;
+ if (!$this->_keepAlive && $this->_sock) {
+ fclose($this->_sock);
+ }
+ }
+
+ /**
+ * Get the keep alive status
+ *
+ * @return Boolean true if the connection should stay alive, false otherwise
+ */
+ public function getKeepAlive()
+ {
+ return $this->_keepAlive;
+ }
+
+ /**
+ * Define whether or not PHP should attempt to re-use sockets opened by previous
+ * request for efficiency
+ *
+ * @param Boolean $b true if persistent socket should be used, false otherwise
+ */
+ public function setPersistentSocket($b)
+ {
+ $was_persistent = ($this->_sock && $this->_persistentSocket);
+ $this->_persistentSocket = (boolean)$b;
+ if (!$this->_persistentSocket && $was_persistent) {
+ fclose($this->_sock);
+ }
+ }
+
+ /**
+ * Get the pesistent socket status
+ *
+ * @return Boolean true if the socket should be persistent, false otherwise
+ */
+ public function getPersistentSocket()
+ {
+ return $this->_persistentSocket;
+ }
+
+
+ /**
+ * Set the connect timeout
+ *
+ * @param Integer number of milliseconds before connect will timeout
+ */
+ public function setConnectTimeout($timeoutMs)
+ {
+ $this->_connectTimeout = $timeoutMs;
+ }
+
+ /**
+ * Get the connect timeout
+ *
+ * @return Integer number of milliseconds before connect will timeout
+ */
+ public function getConnectTimeout()
+ {
+ return $this->_connectTimeout;
+ }
+
+ /**
+ * Set the read/write timeout
+ *
+ * @param Integer number of milliseconds before read or write call will timeout
+ */
+ public function setReadWriteTimeout($timeoutMs)
+ {
+ $this->_readWriteTimeout = $timeoutMs;
+ $this->set_ms_timeout($this->_readWriteTimeout);
+ }
+
+ /**
+ * Get the read timeout
+ *
+ * @return Integer number of milliseconds before read will timeout
+ */
+ public function getReadWriteTimeout()
+ {
+ return $this->_readWriteTimeout;
+ }
+
+ /**
+ * Helper to avoid duplicating milliseconds to secs/usecs in a few places
+ *
+ * @param Integer millisecond timeout
+ * @return Boolean
+ */
+ private function set_ms_timeout($timeoutMs) {
+ if (!$this->_sock) {
+ return false;
+ }
+ return stream_set_timeout($this->_sock, floor($timeoutMs / 1000), ($timeoutMs % 1000) * 1000);
+ }
+
+
+ /**
+ * Create a connection to the FastCGI application
+ */
+ private function connect()
+ {
+ if (!$this->_sock) {
+ if ($this->_persistentSocket) {
+ $this->_sock = pfsockopen($this->_host, $this->_port, $errno, $errstr, $this->_connectTimeout/1000);
+ } else {
+ $this->_sock = fsockopen($this->_host, $this->_port, $errno, $errstr, $this->_connectTimeout/1000);
+ }
+
+ if (!$this->_sock) {
+ throw new \Exception('Unable to connect to FastCGI application: ' . $errstr);
+ }
+
+ if (!$this->set_ms_timeout($this->_readWriteTimeout)) {
+ throw new \Exception('Unable to set timeout on socket');
+ }
+ }
+ }
+
+ /**
+ * Build a FastCGI packet
+ *
+ * @param Integer $type Type of the packet
+ * @param String $content Content of the packet
+ * @param Integer $requestId RequestId
+ */
+ private function buildPacket($type, $content, $requestId = 1)
+ {
+ $clen = strlen($content);
+ return chr(self::VERSION_1) /* version */
+ . chr($type) /* type */
+ . chr(($requestId >> 8) & 0xFF) /* requestIdB1 */
+ . chr($requestId & 0xFF) /* requestIdB0 */
+ . chr(($clen >> 8 ) & 0xFF) /* contentLengthB1 */
+ . chr($clen & 0xFF) /* contentLengthB0 */
+ . chr(0) /* paddingLength */
+ . chr(0) /* reserved */
+ . $content; /* content */
+ }
+
+ /**
+ * Build an FastCGI Name value pair
+ *
+ * @param String $name Name
+ * @param String $value Value
+ * @return String FastCGI Name value pair
+ */
+ private function buildNvpair($name, $value)
+ {
+ $nlen = strlen($name);
+ $vlen = strlen($value);
+ if ($nlen < 128) {
+ /* nameLengthB0 */
+ $nvpair = chr($nlen);
+ } else {
+ /* nameLengthB3 & nameLengthB2 & nameLengthB1 & nameLengthB0 */
+ $nvpair = chr(($nlen >> 24) | 0x80) . chr(($nlen >> 16) & 0xFF) . chr(($nlen >> 8) & 0xFF) . chr($nlen & 0xFF);
+ }
+ if ($vlen < 128) {
+ /* valueLengthB0 */
+ $nvpair .= chr($vlen);
+ } else {
+ /* valueLengthB3 & valueLengthB2 & valueLengthB1 & valueLengthB0 */
+ $nvpair .= chr(($vlen >> 24) | 0x80) . chr(($vlen >> 16) & 0xFF) . chr(($vlen >> 8) & 0xFF) . chr($vlen & 0xFF);
+ }
+ /* nameData & valueData */
+ return $nvpair . $name . $value;
+ }
+
+ /**
+ * Read a set of FastCGI Name value pairs
+ *
+ * @param String $data Data containing the set of FastCGI NVPair
+ * @return array of NVPair
+ */
+ private function readNvpair($data, $length = null)
+ {
+ $array = array();
+
+ if ($length === null) {
+ $length = strlen($data);
+ }
+
+ $p = 0;
+
+ while ($p != $length) {
+
+ $nlen = ord($data{$p++});
+ if ($nlen >= 128) {
+ $nlen = ($nlen & 0x7F << 24);
+ $nlen |= (ord($data{$p++}) << 16);
+ $nlen |= (ord($data{$p++}) << 8);
+ $nlen |= (ord($data{$p++}));
+ }
+ $vlen = ord($data{$p++});
+ if ($vlen >= 128) {
+ $vlen = ($nlen & 0x7F << 24);
+ $vlen |= (ord($data{$p++}) << 16);
+ $vlen |= (ord($data{$p++}) << 8);
+ $vlen |= (ord($data{$p++}));
+ }
+ $array[substr($data, $p, $nlen)] = substr($data, $p+$nlen, $vlen);
+ $p += ($nlen + $vlen);
+ }
+
+ return $array;
+ }
+
+ /**
+ * Decode a FastCGI Packet
+ *
+ * @param String $data String containing all the packet
+ * @return array
+ */
+ private function decodePacketHeader($data)
+ {
+ $ret = array();
+ $ret['version'] = ord($data{0});
+ $ret['type'] = ord($data{1});
+ $ret['requestId'] = (ord($data{2}) << 8) + ord($data{3});
+ $ret['contentLength'] = (ord($data{4}) << 8) + ord($data{5});
+ $ret['paddingLength'] = ord($data{6});
+ $ret['reserved'] = ord($data{7});
+ return $ret;
+ }
+
+ /**
+ * Read a FastCGI Packet
+ *
+ * @return array
+ */
+ private function readPacket()
+ {
+ if ($packet = fread($this->_sock, self::HEADER_LEN)) {
+ $resp = $this->decodePacketHeader($packet);
+ $resp['content'] = '';
+ if ($resp['contentLength']) {
+ $len = $resp['contentLength'];
+ while ($len && $buf=fread($this->_sock, $len)) {
+ $len -= strlen($buf);
+ $resp['content'] .= $buf;
+ }
+ }
+ if ($resp['paddingLength']) {
+ $buf = fread($this->_sock, $resp['paddingLength']);
+ }
+ return $resp;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Get Informations on the FastCGI application
+ *
+ * @param array $requestedInfo information to retrieve
+ * @return array
+ */
+ public function getValues(array $requestedInfo)
+ {
+ $this->connect();
+
+ $request = '';
+ foreach ($requestedInfo as $info) {
+ $request .= $this->buildNvpair($info, '');
+ }
+ fwrite($this->_sock, $this->buildPacket(self::GET_VALUES, $request, 0));
+
+ $resp = $this->readPacket();
+ if ($resp['type'] == self::GET_VALUES_RESULT) {
+ return $this->readNvpair($resp['content'], $resp['length']);
+ } else {
+ throw new \Exception('Unexpected response type, expecting GET_VALUES_RESULT');
+ }
+ }
+
+ /**
+ * Execute a request to the FastCGI application
+ *
+ * @param array $params Array of parameters
+ * @param String $stdin Content
+ * @return String
+ */
+ public function request(array $params, $stdin)
+ {
+ $id = $this->async_request($params, $stdin);
+ return $this->wait_for_response($id);
+ }
+
+ /**
+ * Execute a request to the FastCGI application asyncronously
+ *
+ * This sends request to application and returns the assigned ID for that request.
+ *
+ * You should keep this id for later use with wait_for_response(). Ids are chosen randomly
+ * rather than seqentially to guard against false-positives when using persistent sockets.
+ * In that case it is possible that a delayed response to a request made by a previous script
+ * invocation comes back on this socket and is mistaken for response to request made with same ID
+ * during this request.
+ *
+ * @param array $params Array of parameters
+ * @param String $stdin Content
+ * @return Integer
+ */
+ public function async_request(array $params, $stdin)
+ {
+ $this->connect();
+
+ // Pick random number between 1 and max 16 bit unsigned int 65535
+ $id = mt_rand(1, (1 << 16) - 1);
+
+ // Using persistent sockets implies you want them keept alive by server!
+ $keepAlive = intval($this->_keepAlive || $this->_persistentSocket);
+
+ $request = $this->buildPacket(self::BEGIN_REQUEST
+ ,chr(0) . chr(self::RESPONDER) . chr($keepAlive) . str_repeat(chr(0), 5)
+ ,$id
+ );
+
+ $paramsRequest = '';
+ foreach ($params as $key => $value) {
+ $paramsRequest .= $this->buildNvpair($key, $value, $id);
+ }
+ if ($paramsRequest) {
+ $request .= $this->buildPacket(self::PARAMS, $paramsRequest, $id);
+ }
+ $request .= $this->buildPacket(self::PARAMS, '', $id);
+
+ if ($stdin) {
+ $request .= $this->buildPacket(self::STDIN, $stdin, $id);
+ }
+ $request .= $this->buildPacket(self::STDIN, '', $id);
+
+ if (fwrite($this->_sock, $request) === false || fflush($this->_sock) === false) {
+
+ $info = stream_get_meta_data($this->_sock);
+
+ if ($info['timed_out']) {
+ throw new TimedOutException('Write timed out');
+ }
+
+ // Broken pipe, tear down so future requests might succeed
+ fclose($this->_sock);
+ throw new \Exception('Failed to write request to socket');
+ }
+
+ $this->_requests[$id] = array(
+ 'state' => self::REQ_STATE_WRITTEN,
+ 'response' => null
+ );
+
+ return $id;
+ }
+
+ /**
+ * Blocking call that waits for response to specific request
+ *
+ * @param Integer $requestId
+ * @param Integer $timeoutMs [optional] the number of milliseconds to wait. Defaults to the ReadWriteTimeout value set.
+ * @return string response body
+ */
+ public function wait_for_response($requestId, $timeoutMs = 0) {
+
+ if (!isset($this->_requests[$requestId])) {
+ throw new \Exception('Invalid request id given');
+ }
+
+ // If we already read the response during an earlier call for different id, just return it
+ if ($this->_requests[$requestId]['state'] == self::REQ_STATE_OK
+ || $this->_requests[$requestId]['state'] == self::REQ_STATE_ERR
+ ) {
+ return $this->_requests[$requestId]['response'];
+ }
+
+ if ($timeoutMs > 0) {
+ // Reset timeout on socket for now
+ $this->set_ms_timeout($timeoutMs);
+ } else {
+ $timeoutMs = $this->_readWriteTimeout;
+ }
+
+ // Need to manually check since we might do several reads none of which timeout themselves
+ // but still not get the response requested
+ $startTime = microtime(true);
+
+ do {
+ $resp = $this->readPacket();
+
+ if ($resp['type'] == self::STDOUT || $resp['type'] == self::STDERR) {
+ if ($resp['type'] == self::STDERR) {
+ $this->_requests[$resp['requestId']]['state'] = self::REQ_STATE_ERR;
+ }
+ $this->_requests[$resp['requestId']]['response'] .= $resp['content'];
+ }
+ if ($resp['type'] == self::END_REQUEST) {
+ $this->_requests[$resp['requestId']]['state'] = self::REQ_STATE_OK;
+ if ($resp['requestId'] == $requestId) {
+ break;
+ }
+ }
+ if (microtime(true) - $startTime >= ($timeoutMs * 1000)) {
+ // Reset
+ $this->set_ms_timeout($this->_readWriteTimeout);
+ throw new \Exception('Timed out');
+ }
+ } while ($resp);
+
+ if (!is_array($resp)) {
+ $info = stream_get_meta_data($this->_sock);
+
+ // We must reset timeout but it must be AFTER we get info
+ $this->set_ms_timeout($this->_readWriteTimeout);
+
+ if ($info['timed_out']) {
+ throw new TimedOutException('Read timed out');
+ }
+
+ if ($info['unread_bytes'] == 0
+ && $info['blocked']
+ && $info['eof']) {
+ throw new ForbiddenException('Not in white list. Check listen.allowed_clients.');
+ }
+
+ throw new \Exception('Read failed');
+ }
+
+ // Reset timeout
+ $this->set_ms_timeout($this->_readWriteTimeout);
+
+ switch (ord($resp['content']{4})) {
+ case self::CANT_MPX_CONN:
+ throw new \Exception('This app can\'t multiplex [CANT_MPX_CONN]');
+ break;
+ case self::OVERLOADED:
+ throw new \Exception('New request rejected; too busy [OVERLOADED]');
+ break;
+ case self::UNKNOWN_ROLE:
+ throw new \Exception('Role value not known [UNKNOWN_ROLE]');
+ break;
+ case self::REQUEST_COMPLETE:
+ return $this->_requests[$requestId]['response'];
+ }
+ }
+}
diff --git a/sapi/fpm/tests/include.inc b/sapi/fpm/tests/include.inc
index 983cbd3454..b195fad507 100644
--- a/sapi/fpm/tests/include.inc
+++ b/sapi/fpm/tests/include.inc
@@ -76,4 +76,36 @@ function run_fpm_till($needle, $config, $max = 10) /* {{{ */
}
/* }}} */
-?>
+function fpm_display_log($tail, $n=1, $ignore='systemd') {
+ while ($n) {
+ $a = fgets($tail);
+ if (empty($ignore) || !strpos($a, $ignore)) {
+ echo $a;
+ $n--;
+ }
+ }
+}
+
+function run_request($host, $port, $uri='/ping', $query='') {
+ require_once 'fcgi.inc';
+ $client = new Adoy\FastCGI\Client($host, $port);
+ $params = array(
+ 'GATEWAY_INTERFACE' => 'FastCGI/1.0',
+ 'REQUEST_METHOD' => 'GET',
+ 'SCRIPT_FILENAME' => $uri,
+ 'SCRIPT_NAME' => $uri,
+ 'QUERY_STRING' => $query,
+ 'REQUEST_URI' => $uri . ($query ? '?'.$query : ""),
+ 'DOCUMENT_URI' => $uri,
+ 'SERVER_SOFTWARE' => 'php/fcgiclient',
+ 'REMOTE_ADDR' => '127.0.0.1',
+ 'REMOTE_PORT' => '9985',
+ 'SERVER_ADDR' => '127.0.0.1',
+ 'SERVER_PORT' => '80',
+ 'SERVER_NAME' => php_uname('n'),
+ 'SERVER_PROTOCOL' => 'HTTP/1.1',
+ 'CONTENT_TYPE' => '',
+ 'CONTENT_LENGTH' => 0
+ );
+ return $client->request($params, false)."\n";
+}
diff --git a/sapi/litespeed/lsapi_main.c b/sapi/litespeed/lsapi_main.c
index a9f27fcea1..54b7ef9166 100644
--- a/sapi/litespeed/lsapi_main.c
+++ b/sapi/litespeed/lsapi_main.c
@@ -200,7 +200,12 @@ static char *sapi_lsapi_getenv( char * name, size_t name_len TSRMLS_DC )
static int add_variable( const char * pKey, int keyLen, const char * pValue, int valLen,
void * arg )
{
- int filter_arg = (arg == PG(http_globals)[TRACK_VARS_ENV])?PARSE_ENV:PARSE_SERVER;
+#if PHP_MAJOR_VERSION >= 7
+ int filter_arg = (Z_ARR_P((zval *)arg) == Z_ARR(PG(http_globals)[TRACK_VARS_ENV]))
+ ? PARSE_ENV : PARSE_SERVER;
+#else
+ int filter_arg = (arg == PG(http_globals)[TRACK_VARS_ENV])?PARSE_ENV:PARSE_SERVER;
+#endif
char * new_val = (char *) pValue;
unsigned int new_val_len;
@@ -238,27 +243,45 @@ static void litespeed_php_import_environment_variables(zval *array_ptr TSRMLS_DC
size_t alloc_size = sizeof(buf);
unsigned long nlen; /* ptrdiff_t is not portable */
- if (PG(http_globals)[TRACK_VARS_ENV] &&
- array_ptr != PG(http_globals)[TRACK_VARS_ENV] &&
- Z_TYPE_P(PG(http_globals)[TRACK_VARS_ENV]) == IS_ARRAY &&
- zend_hash_num_elements(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_ENV])) > 0
+#if PHP_MAJOR_VERSION >= 7
+ if (Z_TYPE(PG(http_globals)[TRACK_VARS_ENV]) == IS_ARRAY &&
+ Z_ARR_P(array_ptr) != Z_ARR(PG(http_globals)[TRACK_VARS_ENV]) &&
+ zend_hash_num_elements(Z_ARRVAL(PG(http_globals)[TRACK_VARS_ENV])) > 0
) {
- zval_dtor(array_ptr);
- *array_ptr = *PG(http_globals)[TRACK_VARS_ENV];
- INIT_PZVAL(array_ptr);
- zval_copy_ctor(array_ptr);
+ zval_dtor(array_ptr);
+ ZVAL_DUP(array_ptr, &PG(http_globals)[TRACK_VARS_ENV]);
return;
- } else if (PG(http_globals)[TRACK_VARS_SERVER] &&
- array_ptr != PG(http_globals)[TRACK_VARS_SERVER] &&
- Z_TYPE_P(PG(http_globals)[TRACK_VARS_SERVER]) == IS_ARRAY &&
- zend_hash_num_elements(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER])) > 0
+ } else if (Z_TYPE(PG(http_globals)[TRACK_VARS_SERVER]) == IS_ARRAY &&
+ Z_ARR_P(array_ptr) != Z_ARR(PG(http_globals)[TRACK_VARS_SERVER]) &&
+ zend_hash_num_elements(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER])) > 0
) {
- zval_dtor(array_ptr);
- *array_ptr = *PG(http_globals)[TRACK_VARS_SERVER];
- INIT_PZVAL(array_ptr);
- zval_copy_ctor(array_ptr);
+ zval_dtor(array_ptr);
+ ZVAL_DUP(array_ptr, &PG(http_globals)[TRACK_VARS_SERVER]);
return;
}
+#else
+ if (PG(http_globals)[TRACK_VARS_ENV] &&
+ array_ptr != PG(http_globals)[TRACK_VARS_ENV] &&
+ Z_TYPE_P(PG(http_globals)[TRACK_VARS_ENV]) == IS_ARRAY &&
+ zend_hash_num_elements(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_ENV])) > 0
+ ) {
+ zval_dtor(array_ptr);
+ *array_ptr = *PG(http_globals)[TRACK_VARS_ENV];
+ INIT_PZVAL(array_ptr);
+ zval_copy_ctor(array_ptr);
+ return;
+ } else if (PG(http_globals)[TRACK_VARS_SERVER] &&
+ array_ptr != PG(http_globals)[TRACK_VARS_SERVER] &&
+ Z_TYPE_P(PG(http_globals)[TRACK_VARS_SERVER]) == IS_ARRAY &&
+ zend_hash_num_elements(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER])) > 0
+ ) {
+ zval_dtor(array_ptr);
+ *array_ptr = *PG(http_globals)[TRACK_VARS_SERVER];
+ INIT_PZVAL(array_ptr);
+ zval_copy_ctor(array_ptr);
+ return;
+ }
+#endif
for (env = environ; env != NULL && *env != NULL; env++) {
p = strchr(*env, '=');
@@ -592,6 +615,9 @@ static int lsapi_module_main(int show_source TSRMLS_DC)
static int alter_ini( const char * pKey, int keyLen, const char * pValue, int valLen,
void * arg )
{
+#if PHP_MAJOR_VERSION >= 7
+ zend_string * psKey;
+#endif
int type = ZEND_INI_PERDIR;
if ( '\001' == *pKey ) {
++pKey;
@@ -606,9 +632,19 @@ static int alter_ini( const char * pKey, int keyLen, const char * pValue, int va
engine = 0;
}
else
- zend_alter_ini_entry((char *)pKey, keyLen,
+ {
+#if PHP_MAJOR_VERSION >= 7
+ psKey = STR_INIT( pKey, keyLen, 1 );
+ zend_alter_ini_entry(psKey,
(char *)pValue, valLen,
type, PHP_INI_STAGE_ACTIVATE);
+ STR_RELEASE( psKey );
+#else
+ zend_alter_ini_entry((char *)pKey, keyLen,
+ (char *)pValue, valLen,
+ type, PHP_INI_STAGE_ACTIVATE);
+#endif
+ }
}
return 1;
}
@@ -749,6 +785,9 @@ static int cli_main( int argc, char * argv[] )
char ** argend= &argv[argc];
int ret = -1;
int c;
+#if PHP_MAJOR_VERSION >= 7
+ zend_string * psKey;
+#endif
lsapi_mode = 0; /* enter CLI mode */
#ifdef PHP_WIN32
@@ -763,12 +802,21 @@ static int cli_main( int argc, char * argv[] )
zend_uv.html_errors = 0; /* tell the engine we're in non-html mode */
CG(in_compilation) = 0; /* not initialized but needed for several options */
+#if PHP_MAJOR_VERSION < 7
EG(uninitialized_zval_ptr) = NULL;
-
+#endif
for( ini = ini_defaults; *ini; ini+=2 ) {
+#if PHP_MAJOR_VERSION >= 7
+ psKey = STR_INIT( *ini, strlen( *ini ), 1 );
+ zend_alter_ini_entry( psKey,
+ (char *)*(ini+1), strlen( *(ini+1) ),
+ PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
+ STR_RELEASE( psKey );
+#else
zend_alter_ini_entry( (char *)*ini, strlen( *ini )+1,
(char *)*(ini+1), strlen( *(ini+1) ),
PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
+#endif
}
while (( p < argend )&&(**p == '-' )) {
@@ -1148,7 +1196,11 @@ zend_module_entry litespeed_module_entry = {
static int add_associate_array( const char * pKey, int keyLen, const char * pValue, int valLen,
void * arg )
{
- add_assoc_string_ex( (zval *)arg, (char *)pKey, keyLen+1, (char *)pValue);
+ add_assoc_string_ex( (zval *)arg, (char *)pKey, keyLen+1, (char *)pValue
+#if PHP_MAJOR_VERSION < 7
+ , 1
+#endif
+ );
return 1;
}
@@ -1202,7 +1254,11 @@ PHP_FUNCTION(litespeed_response_headers)
headerBuf[len] = 0;
if ( len ) {
while( isspace(*++p));
- add_assoc_string_ex(return_value, headerBuf, len+1, p);
+ add_assoc_string_ex(return_value, headerBuf, len+1, p
+#if PHP_MAJOR_VERSION < 7
+ , 1
+#endif
+ );
}
}
}
@@ -1217,15 +1273,25 @@ PHP_FUNCTION(litespeed_response_headers)
Fetch all loaded module names */
PHP_FUNCTION(apache_get_modules)
{
+ static const char * mod_names[] =
+ {
+ "mod_rewrite", "mod_mime", "mod_headers", "mod_expires", NULL
+ };
+ const char **name = mod_names;
/* TODO: */
if (ZEND_NUM_ARGS() > 0) {
WRONG_PARAM_COUNT;
}
array_init(return_value);
- add_next_index_string(return_value, "mod_rewrite");
- add_next_index_string(return_value, "mod_mime");
- add_next_index_string(return_value, "mod_headers");
- add_next_index_string(return_value, "mod_expires");
+ while( *name )
+ {
+ add_next_index_string(return_value, *name
+#if PHP_MAJOR_VERSION < 7
+ , 1
+#endif
+ );
+ ++name;
+ }
}
/* }}} */
diff --git a/sapi/litespeed/lsapilib.c b/sapi/litespeed/lsapilib.c
index cf63f6ab1c..daf0f37f14 100644
--- a/sapi/litespeed/lsapilib.c
+++ b/sapi/litespeed/lsapilib.c
@@ -2662,7 +2662,7 @@ static void lsapi_check_child_status( long tmCur )
}
if ( abs( g_prefork_server->m_iCurChildren - count ) > 1 )
{
- fprintf( stderr, "Children tracking is wrong: PID: %d, Cur Childen: %d, count: %d, idle: %d, dying: %d\n", getpid(),
+ fprintf( stderr, "Children tracking is wrong: PID: %d, Cur Children: %d, count: %d, idle: %d, dying: %d\n", getpid(),
g_prefork_server->m_iCurChildren, count, idle, dying );
}
diff --git a/sapi/nsapi/nsapi-readme.txt b/sapi/nsapi/nsapi-readme.txt
index 812507957e..6bf4afb83d 100644
--- a/sapi/nsapi/nsapi-readme.txt
+++ b/sapi/nsapi/nsapi-readme.txt
@@ -1,7 +1,7 @@
Configuration of your Netscape/iPlanet/Sun Webserver for PHP7
-----------------------------------------------------------------
-These instructions are targetted at Netscape Enterprise Web Server and
+These instructions are targeted at Netscape Enterprise Web Server and
SUN/Netscape Alliance iPlanet Web Server and the new Sun Java System Webserver.
On other web servers your milage may vary.
diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c
index ec65a22f12..c624669785 100644
--- a/sapi/phpdbg/phpdbg.c
+++ b/sapi/phpdbg/phpdbg.c
@@ -1571,7 +1571,7 @@ phpdbg_out:
#ifdef _WIN32
} __except(phpdbg_exception_handler_win32(xp = GetExceptionInformation())) {
- phpdbg_error("segfault", "", "Access violation (Segementation fault) encountered\ntrying to abort cleanly...");
+ phpdbg_error("segfault", "", "Access violation (Segmentation fault) encountered\ntrying to abort cleanly...");
}
phpdbg_out:
#endif
diff --git a/sapi/phpdbg/phpdbg_frame.c b/sapi/phpdbg/phpdbg_frame.c
index f42fc659f1..c9ba377d95 100644
--- a/sapi/phpdbg/phpdbg_frame.c
+++ b/sapi/phpdbg/phpdbg_frame.c
@@ -37,7 +37,7 @@ void phpdbg_restore_frame(TSRMLS_D) /* {{{ */
/* move things back */
EG(current_execute_data) = PHPDBG_FRAME(execute_data);
- EG(scope) = PHPDBG_EX(scope);
+ EG(scope) = PHPDBG_EX(func)->op_array.scope;
} /* }}} */
void phpdbg_switch_frame(int frame TSRMLS_DC) /* {{{ */
@@ -79,7 +79,7 @@ void phpdbg_switch_frame(int frame TSRMLS_DC) /* {{{ */
PHPDBG_FRAME(execute_data) = EG(current_execute_data);
EG(current_execute_data) = execute_data;
- EG(scope) = PHPDBG_EX(scope);
+ EG(scope) = PHPDBG_EX(func)->op_array.scope;
}
phpdbg_notice("frame", "id=\"%d\"", "Switched to frame #%d", frame);
diff --git a/sapi/phpdbg/xml.md b/sapi/phpdbg/xml.md
index 7871b31376..56dcaaa1f7 100644
--- a/sapi/phpdbg/xml.md
+++ b/sapi/phpdbg/xml.md
@@ -225,7 +225,7 @@ frame
- internal: has value "internal" when being an internal function call (one cannot inspect that frame)
- being an error: (by type)
- - maxnum: tried to access a frame with a number heigher than existing (or &lt; 0)
+ - maxnum: tried to access a frame with a number higher than existing (or &lt; 0)
### attributes on &lt;arg> ###
@@ -378,7 +378,7 @@ exec
- command executing and compiling a given file
- &lt;exec type="unset" context="" />: indicates unsetting of the old context
- &lt;exec type="unsetops" />: indicates unsetting of the old compiled opcodes
- - &lt;exec type="unchanged" />: same execution context choosen again
+ - &lt;exec type="unchanged" />: same execution context chosen again
- &lt;exec type="set" context="" />: indicates setting of the new context
- errors by tag
- &lt;compile>
@@ -527,7 +527,7 @@ set
### breaks ###
-- generally enables / disables breakpoint functionality silently with no futher xml answer
+- generally enables / disables breakpoint functionality silently with no further xml answer
- if the boolean switch is omitted, it emits current state in a &lt;setbreaks active="" /> where active is on or off
### color ###
diff --git a/sapi/thttpd/thttpd_patch b/sapi/thttpd/thttpd_patch
index 1a9ed29d60..1463d8fe0a 100644
--- a/sapi/thttpd/thttpd_patch
+++ b/sapi/thttpd/thttpd_patch
@@ -2059,7 +2059,7 @@ diff -ur thttpd-2.21b/thttpd.c thttpd-2.21b-cool/thttpd.c
@@ -1519,7 +1697,7 @@
if ( c->bytes_sent >= c->bytes_to_send )
{
- /* This conection is finished! */
+ /* This connection is finished! */
- clear_connection( c, tvP );
+ clear_connection( c, tvP, 1 );
return;