summaryrefslogtreecommitdiff
path: root/sapi/cgi
diff options
context:
space:
mode:
Diffstat (limited to 'sapi/cgi')
-rw-r--r--sapi/cgi/cgi_main.c153
-rw-r--r--sapi/cgi/fastcgi.c181
-rw-r--r--sapi/cgi/fastcgi.h8
-rw-r--r--sapi/cgi/getopt.c4
-rw-r--r--sapi/cgi/php_getopt.h4
-rw-r--r--sapi/cgi/tests/005.phpt3
-rw-r--r--sapi/cgi/tests/007.phpt2
-rw-r--r--sapi/cgi/tests/010.phpt53
-rw-r--r--sapi/cgi/tests/include.inc2
9 files changed, 295 insertions, 115 deletions
diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c
index f47ae96c8..6e1139966 100644
--- a/sapi/cgi/cgi_main.c
+++ b/sapi/cgi/cgi_main.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2008 The PHP Group |
+ | Copyright (c) 1997-2009 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 |
@@ -21,7 +21,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: cgi_main.c,v 1.267.2.15.2.56 2008/04/09 09:16:40 dmitry Exp $ */
+/* $Id: cgi_main.c,v 1.267.2.15.2.69 2009/01/19 18:17:59 dsp Exp $ */
#include "php.h"
#include "php_globals.h"
@@ -103,6 +103,12 @@ static int children = 0;
*/
static int parent = 1;
+/* Did parent received exit signals SIG_TERM/SIG_INT/SIG_QUIT */
+static int exit_signal = 0;
+
+/* Is Parent waiting for children to exit */
+static int parent_waiting = 0;
+
/**
* Process group
*/
@@ -232,6 +238,7 @@ static void print_extensions(TSRMLS_D)
zend_llist sorted_exts;
zend_llist_copy(&sorted_exts, &zend_extensions);
+ sorted_exts.dtor = NULL;
zend_llist_sort(&sorted_exts, extension_name_cmp TSRMLS_CC);
zend_llist_apply_with_argument(&sorted_exts, (llist_apply_with_arg_func_t) print_extension_info, NULL TSRMLS_CC);
zend_llist_destroy(&sorted_exts);
@@ -362,6 +369,8 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
char buf[SAPI_CGI_MAX_HEADER_LENGTH];
sapi_header_struct *h;
zend_llist_position pos;
+ zend_bool ignore_status = 0;
+ int response_status = SG(sapi_headers).http_response_code;
if (SG(request_info).no_headers == 1) {
return SAPI_HEADER_SENT_SUCCESSFULLY;
@@ -373,8 +382,11 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
zend_bool has_status = 0;
if (CGIG(rfc2616_headers) && SG(sapi_headers).http_status_line) {
- len = slprintf(buf, SAPI_CGI_MAX_HEADER_LENGTH,
- "%s\r\n", SG(sapi_headers).http_status_line);
+ char *s;
+ len = slprintf(buf, SAPI_CGI_MAX_HEADER_LENGTH, "%s\r\n", SG(sapi_headers).http_status_line);
+ if ((s = strchr(SG(sapi_headers).http_status_line, ' '))) {
+ response_status = atoi((s + 1));
+ }
if (len > SAPI_CGI_MAX_HEADER_LENGTH) {
len = SAPI_CGI_MAX_HEADER_LENGTH;
@@ -388,6 +400,7 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
(s - SG(sapi_headers).http_status_line) >= 5 &&
strncasecmp(SG(sapi_headers).http_status_line, "HTTP/", 5) == 0) {
len = slprintf(buf, sizeof(buf), "Status:%s\r\n", s);
+ response_status = atoi((s + 1));
} else {
h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos);
while (h) {
@@ -417,6 +430,7 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
}
if (!has_status) {
PHPWRITE_H(buf, len);
+ ignore_status = 1;
}
}
@@ -424,8 +438,21 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
while (h) {
/* prevent CRLFCRLF */
if (h->header_len) {
- PHPWRITE_H(h->header, h->header_len);
- PHPWRITE_H("\r\n", 2);
+ if (h->header_len > sizeof("Status:")-1 &&
+ strncasecmp(h->header, "Status:", sizeof("Status:")-1) == 0) {
+ if (!ignore_status) {
+ ignore_status = 1;
+ PHPWRITE_H(h->header, h->header_len);
+ PHPWRITE_H("\r\n", 2);
+ }
+ } else if (response_status == 304 && h->header_len > sizeof("Content-Type:")-1 &&
+ strncasecmp(h->header, "Content-Type:", sizeof("Content-Type:")-1) == 0) {
+ h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos);
+ continue;
+ } else {
+ PHPWRITE_H(h->header, h->header_len);
+ PHPWRITE_H("\r\n", 2);
+ }
}
h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos);
}
@@ -765,6 +792,39 @@ static void php_cgi_usage(char *argv0)
}
/* }}} */
+/* {{{ is_valid_path
+ *
+ * some server configurations allow '..' to slip through in the
+ * translated path. We'll just refuse to handle such a path.
+ */
+static int is_valid_path(const char *path)
+{
+ const char *p;
+
+ if (!path) {
+ return 0;
+ }
+ p = strstr(path, "..");
+ if (p) {
+ if ((p == path || IS_SLASH(*(p-1))) &&
+ (*(p+2) == 0 || IS_SLASH(*(p+2)))) {
+ return 0;
+ }
+ while (1) {
+ p = strstr(p+1, "..");
+ if (!p) {
+ break;
+ }
+ if (IS_SLASH(*(p-1)) &&
+ (*(p+2) == 0 || IS_SLASH(*(p+2)))) {
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+/* }}} */
+
/* {{{ init_request_info
initializes request_info structure
@@ -900,7 +960,8 @@ static void init_request_info(TSRMLS_D)
TRANSLATE_SLASHES(env_document_root);
}
- if (env_path_translated != NULL && env_redirect_url != NULL) {
+ if (env_path_translated != NULL && env_redirect_url != NULL &&
+ orig_script_filename != NULL && script_path_translated != NULL) {
/*
pretty much apache specific. If we have a redirect_url
then our script_filename and script_name point to the
@@ -925,6 +986,9 @@ static void init_request_info(TSRMLS_D)
if (script_path_translated &&
(script_path_translated_len = strlen(script_path_translated)) > 0 &&
(script_path_translated[script_path_translated_len-1] == '/' ||
+#ifdef PHP_WIN32
+ script_path_translated[script_path_translated_len-1] == '\\' ||
+#endif
(real_path = tsrm_realpath(script_path_translated, NULL TSRMLS_CC)) == NULL)) {
char *pt = estrndup(script_path_translated, script_path_translated_len);
int len = script_path_translated_len;
@@ -1061,9 +1125,7 @@ static void init_request_info(TSRMLS_D)
if (pt) {
efree(pt);
}
- /* some server configurations allow '..' to slip through in the
- translated path. We'll just refuse to handle such a path. */
- if (script_path_translated && !strstr(script_path_translated, "..")) {
+ if (is_valid_path(script_path_translated)) {
SG(request_info).path_translated = estrdup(script_path_translated);
}
} else {
@@ -1094,9 +1156,7 @@ static void init_request_info(TSRMLS_D)
} else {
SG(request_info).request_uri = env_script_name;
}
- /* some server configurations allow '..' to slip through in the
- translated path. We'll just refuse to handle such a path. */
- if (script_path_translated && !strstr(script_path_translated, "..")) {
+ if (is_valid_path(script_path_translated)) {
SG(request_info).path_translated = estrdup(script_path_translated);
}
free(real_path);
@@ -1114,9 +1174,7 @@ static void init_request_info(TSRMLS_D)
script_path_translated = env_path_translated;
}
#endif
- /* some server configurations allow '..' to slip through in the
- translated path. We'll just refuse to handle such a path. */
- if (script_path_translated && !strstr(script_path_translated, "..")) {
+ if (is_valid_path(script_path_translated)) {
SG(request_info).path_translated = estrdup(script_path_translated);
}
#if ENABLE_PATHINFO_CHECK
@@ -1135,7 +1193,7 @@ static void init_request_info(TSRMLS_D)
}
/* }}} */
-#if PHP_FASTCGI
+#if PHP_FASTCGI && !defined(PHP_WIN32)
/**
* Clean up child processes upon exit
*/
@@ -1145,15 +1203,16 @@ void fastcgi_cleanup(int signal)
fprintf(stderr, "FastCGI shutdown, pid %d\n", getpid());
#endif
-#ifndef PHP_WIN32
sigaction(SIGTERM, &old_term, 0);
/* Kill all the processes in our process group */
kill(-pgroup, SIGTERM);
-#endif
- /* We should exit at this point, but MacOSX doesn't seem to */
- exit(0);
+ if (parent && parent_waiting) {
+ exit_signal = 1;
+ } else {
+ exit(0);
+ }
}
#endif
@@ -1491,11 +1550,18 @@ consult the installation file that came with this distribution, or visit \n\
#ifndef PHP_WIN32
/* Pre-fork, if required */
if (getenv("PHP_FCGI_CHILDREN")) {
- children = atoi(getenv("PHP_FCGI_CHILDREN"));
+ char * children_str = getenv("PHP_FCGI_CHILDREN");
+ children = atoi(children_str);
if (children < 0) {
fprintf(stderr, "PHP_FCGI_CHILDREN is not valid\n");
return FAILURE;
}
+ fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, children_str, strlen(children_str));
+ /* This is the number of concurrent requests, equals FCGI_MAX_CONNS */
+ fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, children_str, strlen(children_str));
+ } else {
+ fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, "1", sizeof("1")-1);
+ fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, "1", sizeof("1")-1);
}
if (children) {
@@ -1520,7 +1586,7 @@ consult the installation file that came with this distribution, or visit \n\
}
if (fcgi_in_shutdown()) {
- exit(0);
+ goto parent_out;
}
while (parent) {
@@ -1557,9 +1623,25 @@ consult the installation file that came with this distribution, or visit \n\
#ifdef DEBUG_FASTCGI
fprintf(stderr, "Wait for kids, pid %d\n", getpid());
#endif
- while (wait(&status) < 0) {
+ parent_waiting = 1;
+ while (1) {
+ if (wait(&status) >= 0) {
+ running--;
+ break;
+ } else if (exit_signal) {
+ break;
+ }
+ }
+ if (exit_signal) {
+#if 0
+ while (running > 0) {
+ while (wait(&status) < 0) {
+ }
+ running--;
+ }
+#endif
+ goto parent_out;
}
- running--;
}
}
} else {
@@ -1628,17 +1710,6 @@ consult the installation file that came with this distribution, or visit \n\
&& !fastcgi
#endif
) {
- if (cgi_sapi_module.php_ini_path_override && cgi_sapi_module.php_ini_ignore) {
- no_headers = 1;
- php_output_startup();
- php_output_activate(TSRMLS_C);
- SG(headers_sent) = 1;
- php_printf("You cannot use both -n and -c switch. Use -h for help.\n");
- php_end_ob_buffers(1 TSRMLS_CC);
- exit_status = 1;
- goto out;
- }
-
while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0)) != -1) {
switch (c) {
@@ -1727,9 +1798,9 @@ consult the installation file that came with this distribution, or visit \n\
SG(request_info).no_headers = 1;
}
#if ZEND_DEBUG
- php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2008 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
+ php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2009 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
#else
- php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2008 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
+ php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2009 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
#endif
php_request_shutdown((void *) 0);
exit_status = 0;
@@ -1898,7 +1969,7 @@ consult the installation file that came with this distribution, or visit \n\
/* #!php support */
c = fgetc(file_handle.handle.fp);
if (c == '#') {
- while (c != '\n' && c != '\r') {
+ while (c != '\n' && c != '\r' && c != EOF) {
c = fgetc(file_handle.handle.fp); /* skip to end of line */
}
/* handle situations where line is terminated by \r\n */
@@ -2061,6 +2132,10 @@ out:
}
#endif
+#ifndef PHP_WIN32
+parent_out:
+#endif
+
SG(server_context) = NULL;
php_module_shutdown(TSRMLS_C);
sapi_shutdown();
diff --git a/sapi/cgi/fastcgi.c b/sapi/cgi/fastcgi.c
index 6503c3d00..f94d82d17 100644
--- a/sapi/cgi/fastcgi.c
+++ b/sapi/cgi/fastcgi.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2008 The PHP Group |
+ | Copyright (c) 1997-2009 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 |
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: fastcgi.c,v 1.4.2.13.2.30 2008/04/03 10:24:44 dmitry Exp $ */
+/* $Id: fastcgi.c,v 1.4.2.13.2.35 2008/12/31 11:17:48 sebastian Exp $ */
#include "php.h"
#include "fastcgi.h"
@@ -133,18 +133,7 @@ typedef union _sa_t {
struct sockaddr_in sa_inet;
} sa_t;
-typedef struct _fcgi_mgmt_rec {
- char* name;
- char name_len;
- char val;
-} fcgi_mgmt_rec;
-
-static const fcgi_mgmt_rec fcgi_mgmt_vars[] = {
- {"FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, 1},
- {"FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, 1},
- {"FCGI_MPXS_CONNS", sizeof("FCGI_MPXS_CONNS")-1, 0}
-};
-
+static HashTable fcgi_mgmt_vars;
static int is_initialized = 0;
static int is_fastcgi = 0;
@@ -170,6 +159,20 @@ static void fcgi_signal_handler(int signo)
}
}
+static void fcgi_setup_signals(void)
+{
+ struct sigaction new_sa, old_sa;
+
+ sigemptyset(&new_sa.sa_mask);
+ new_sa.sa_flags = 0;
+ new_sa.sa_handler = fcgi_signal_handler;
+ sigaction(SIGUSR1, &new_sa, NULL);
+ sigaction(SIGTERM, &new_sa, NULL);
+ sigaction(SIGPIPE, NULL, &old_sa);
+ if (old_sa.sa_handler == SIG_DFL) {
+ sigaction(SIGPIPE, &new_sa, NULL);
+ }
+}
#endif
int fcgi_in_shutdown(void)
@@ -180,6 +183,14 @@ int fcgi_in_shutdown(void)
int fcgi_init(void)
{
if (!is_initialized) {
+#ifndef _WIN32
+ sa_t sa;
+ socklen_t len = sizeof(sa);
+#endif
+ zend_hash_init(&fcgi_mgmt_vars, 0, NULL, fcgi_free_mgmt_var_cb, 1);
+ fcgi_set_mgmt_var("FCGI_MPXS_CONNS", sizeof("FCGI_MPXS_CONNS")-1, "0", sizeof("0")-1);
+
+ is_initialized = 1;
#ifdef _WIN32
# if 0
/* TODO: Support for TCP sockets */
@@ -190,8 +201,6 @@ int fcgi_init(void)
return 0;
}
# endif
- is_initialized = 1;
-
if ((GetStdHandle(STD_OUTPUT_HANDLE) == INVALID_HANDLE_VALUE) &&
(GetStdHandle(STD_ERROR_HANDLE) == INVALID_HANDLE_VALUE) &&
(GetStdHandle(STD_INPUT_HANDLE) != INVALID_HANDLE_VALUE)) {
@@ -218,24 +227,9 @@ int fcgi_init(void)
return is_fastcgi = 0;
}
#else
- sa_t sa;
- socklen_t len = sizeof(sa);
-
- is_initialized = 1;
errno = 0;
if (getpeername(0, (struct sockaddr *)&sa, &len) != 0 && errno == ENOTCONN) {
- struct sigaction new_sa, old_sa;
-
- sigemptyset(&new_sa.sa_mask);
- new_sa.sa_flags = 0;
- new_sa.sa_handler = fcgi_signal_handler;
- sigaction(SIGUSR1, &new_sa, NULL);
- sigaction(SIGTERM, &new_sa, NULL);
- sigaction(SIGPIPE, NULL, &old_sa);
- if (old_sa.sa_handler == SIG_DFL) {
- sigaction(SIGPIPE, &new_sa, NULL);
- }
-
+ fcgi_setup_signals();
return is_fastcgi = 1;
} else {
return is_fastcgi = 0;
@@ -257,6 +251,9 @@ int fcgi_is_fastcgi(void)
void fcgi_shutdown(void)
{
+ if (is_initialized) {
+ zend_hash_destroy(&fcgi_mgmt_vars);
+ }
is_fastcgi = 0;
}
@@ -459,35 +456,35 @@ int fcgi_listen(const char *path, int backlog)
if (!tcp) {
chmod(path, 0777);
} else {
- char *ip = getenv("FCGI_WEB_SERVER_ADDRS");
- char *cur, *end;
- int n;
-
- if (ip) {
- ip = strdup(ip);
- cur = ip;
- n = 0;
- while (*cur) {
- if (*cur == ',') n++;
- cur++;
- }
- allowed_clients = malloc(sizeof(in_addr_t) * (n+2));
- n = 0;
- cur = ip;
- while (cur) {
- end = strchr(cur, ',');
- if (end) {
- *end = 0;
- end++;
- }
- allowed_clients[n] = inet_addr(cur);
- if (allowed_clients[n] == INADDR_NONE) {
+ char *ip = getenv("FCGI_WEB_SERVER_ADDRS");
+ char *cur, *end;
+ int n;
+
+ if (ip) {
+ ip = strdup(ip);
+ cur = ip;
+ n = 0;
+ while (*cur) {
+ if (*cur == ',') n++;
+ cur++;
+ }
+ allowed_clients = malloc(sizeof(in_addr_t) * (n+2));
+ n = 0;
+ cur = ip;
+ while (cur) {
+ end = strchr(cur, ',');
+ if (end) {
+ *end = 0;
+ end++;
+ }
+ allowed_clients[n] = inet_addr(cur);
+ if (allowed_clients[n] == INADDR_NONE) {
fprintf(stderr, "Wrong IP address '%s' in FCGI_WEB_SERVER_ADDRS\n", cur);
- }
- n++;
- cur = end;
- }
- allowed_clients[n] = INADDR_NONE;
+ }
+ n++;
+ cur = end;
+ }
+ allowed_clients[n] = INADDR_NONE;
free(ip);
}
}
@@ -501,6 +498,8 @@ int fcgi_listen(const char *path, int backlog)
if (tcp) {
listen_socket = _open_osfhandle((long)listen_socket, 0);
}
+#else
+ fcgi_setup_signals();
#endif
return listen_socket;
}
@@ -743,8 +742,13 @@ static int fcgi_read_request(fcgi_request *req)
padding = hdr.paddingLength;
}
} else if (hdr.type == FCGI_GET_VALUES) {
- int j;
unsigned char *p = buf + sizeof(fcgi_header);
+ HashPosition pos;
+ char * str_index;
+ uint str_length;
+ ulong num_index;
+ int key_type;
+ zval ** value;
if (safe_read(req, buf, len+padding) != len+padding) {
req->keep = 0;
@@ -756,11 +760,41 @@ static int fcgi_read_request(fcgi_request *req)
return 0;
}
- for (j = 0; j < sizeof(fcgi_mgmt_vars)/sizeof(fcgi_mgmt_vars[0]); j++) {
- if (zend_hash_exists(&req->env, fcgi_mgmt_vars[j].name, fcgi_mgmt_vars[j].name_len+1) == 0) {
- sprintf((char*)p, "%c%c%s%c", fcgi_mgmt_vars[j].name_len, 1, fcgi_mgmt_vars[j].name, fcgi_mgmt_vars[j].val);
- p += fcgi_mgmt_vars[j].name_len + 3;
+ 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) {
+ int zlen;
+ zend_hash_move_forward_ex(&req->env, &pos);
+ if (key_type != HASH_KEY_IS_STRING) {
+ continue;
+ }
+ if (zend_hash_find(&fcgi_mgmt_vars, str_index, str_length, (void**) &value) != SUCCESS) {
+ continue;
+ }
+ --str_length;
+ zlen = Z_STRLEN_PP(value);
+ if ((p + 4 + 4 + str_length + zlen) >= (buf + sizeof(buf))) {
+ break;
+ }
+ if (str_length < 0x80) {
+ *p++ = str_length;
+ } else {
+ *p++ = ((str_length >> 24) & 0xff) | 0x80;
+ *p++ = (str_length >> 16) & 0xff;
+ *p++ = (str_length >> 8) & 0xff;
+ *p++ = str_length & 0xff;
+ }
+ if (zlen < 0x80) {
+ *p++ = zlen;
+ } else {
+ *p++ = ((zlen >> 24) & 0xff) | 0x80;
+ *p++ = (zlen >> 16) & 0xff;
+ *p++ = (zlen >> 8) & 0xff;
+ *p++ = zlen & 0xff;
}
+ memcpy(p, str_index, str_length);
+ p += str_length;
+ memcpy(p, Z_STRVAL_PP(value), zlen);
+ p += zlen;
}
len = p - buf - sizeof(fcgi_header);
len += fcgi_make_header((fcgi_header*)buf, FCGI_GET_VALUES_RESULT, 0, len);
@@ -1219,6 +1253,23 @@ void fcgi_impersonate(void)
}
#endif
+void fcgi_set_mgmt_var(char * name, size_t name_len, const char * value, size_t value_len)
+{
+ zval * zvalue;
+ zvalue = pemalloc(sizeof(*zvalue), 1);
+ Z_TYPE_P(zvalue) = IS_STRING;
+ Z_STRVAL_P(zvalue) = pestrndup(value, value_len, 1);
+ Z_STRLEN_P(zvalue) = value_len;
+ zend_hash_add(&fcgi_mgmt_vars, name, name_len + 1, &zvalue, sizeof(zvalue), NULL);
+}
+
+void fcgi_free_mgmt_var_cb(void * ptr)
+{
+ zval ** var = (zval **)ptr;
+ pefree(Z_STRVAL_PP(var), 1);
+ pefree(*var, 1);
+}
+
/*
* Local variables:
* tab-width: 4
diff --git a/sapi/cgi/fastcgi.h b/sapi/cgi/fastcgi.h
index 2b8606472..6df318052 100644
--- a/sapi/cgi/fastcgi.h
+++ b/sapi/cgi/fastcgi.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2008 The PHP Group |
+ | Copyright (c) 1997-2009 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 |
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: fastcgi.h,v 1.2.2.4.2.6 2007/12/31 07:20:16 sebastian Exp $ */
+/* $Id: fastcgi.h,v 1.2.2.4.2.8 2008/12/31 11:17:48 sebastian Exp $ */
/* FastCGI protocol */
@@ -131,6 +131,10 @@ int fcgi_flush(fcgi_request *req, int close);
#ifdef PHP_WIN32
void fcgi_impersonate(void);
#endif
+
+void fcgi_set_mgmt_var(char * name, size_t name_len, const char * value, size_t value_len);
+void fcgi_free_mgmt_var_cb(void * ptr);
+
/*
* Local variables:
* tab-width: 4
diff --git a/sapi/cgi/getopt.c b/sapi/cgi/getopt.c
index d5bb50618..1e2182f32 100644
--- a/sapi/cgi/getopt.c
+++ b/sapi/cgi/getopt.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2008 The PHP Group |
+ | Copyright (c) 1997-2009 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 |
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: getopt.c,v 1.9.2.1.2.5 2007/12/31 07:20:16 sebastian Exp $ */
+/* $Id: getopt.c,v 1.9.2.1.2.6 2008/12/31 11:17:48 sebastian Exp $ */
#include <stdio.h>
#include <string.h>
diff --git a/sapi/cgi/php_getopt.h b/sapi/cgi/php_getopt.h
index aa513dded..ac6cf5123 100644
--- a/sapi/cgi/php_getopt.h
+++ b/sapi/cgi/php_getopt.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2008 The PHP Group |
+ | Copyright (c) 1997-2009 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 |
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: php_getopt.h,v 1.7.2.1.2.3 2007/12/31 07:20:16 sebastian Exp $ */
+/* $Id: php_getopt.h,v 1.7.2.1.2.4 2008/12/31 11:17:48 sebastian Exp $ */
#include "php.h"
diff --git a/sapi/cgi/tests/005.phpt b/sapi/cgi/tests/005.phpt
index 6d82b0f31..34a28f9c5 100644
--- a/sapi/cgi/tests/005.phpt
+++ b/sapi/cgi/tests/005.phpt
@@ -10,15 +10,12 @@ include "include.inc";
$php = get_cgi_path();
reset_env_vars();
-var_dump(`$php -n -c -f 'wrong'`);
var_dump(`$php -n -a -f 'wrong'`);
var_dump(`$php -n -f 'wrong' -a`);
echo "Done\n";
?>
--EXPECTF--
-string(55) "You cannot use both -n and -c switch. Use -h for help.
-"
string(51) "No input file specified.
Interactive mode enabled
diff --git a/sapi/cgi/tests/007.phpt b/sapi/cgi/tests/007.phpt
index c0f8df1bf..92bf0f6aa 100644
--- a/sapi/cgi/tests/007.phpt
+++ b/sapi/cgi/tests/007.phpt
@@ -10,7 +10,7 @@ $php = get_cgi_path();
reset_env_vars();
var_dump(`"$php" -n -f some.php -f some.php`);
-var_dump(`"$php" -s -w -l`);
+var_dump(`"$php" -n -s -w -l`);
echo "Done\n";
?>
diff --git a/sapi/cgi/tests/010.phpt b/sapi/cgi/tests/010.phpt
new file mode 100644
index 000000000..e633ad28b
--- /dev/null
+++ b/sapi/cgi/tests/010.phpt
@@ -0,0 +1,53 @@
+--TEST--
+Bug #45860 (header() function fails to correctly replace all Status lines)
+--SKIPIF--
+<?php include "skipif.inc"; ?>
+--FILE--
+<?php
+
+include "include.inc";
+
+$php = get_cgi_path();
+reset_env_vars();
+
+$f = tempnam(sys_get_temp_dir(), 'cgitest');
+
+putenv("TRANSLATED_PATH=".$f."/x");
+putenv("SCRIPT_FILENAME=".$f."/x");
+file_put_contents($f, '<?php
+header("HTTP/1.1 403 Forbidden");
+header("Status: 403 Also Forbidden");
+?>');
+
+echo (`$php -n $f`);
+
+file_put_contents($f, '<?php
+header("HTTP/1.1 403 Forbidden");
+?>');
+
+echo (`$php -n $f`);
+
+file_put_contents($f, '<?php
+header("Status: 403 Also Forbidden");
+?>');
+
+echo (`$php -n $f`);
+
+echo "Done\n";
+
+@unlink($f);
+?>
+--EXPECTF--
+Status: 403 Forbidden
+X-Powered-By: PHP/%s
+Content-type: text/html
+
+Status: 403 Forbidden
+X-Powered-By: PHP/%s
+Content-type: text/html
+
+X-Powered-By: PHP/%s
+Status: 403 Also Forbidden
+Content-type: text/html
+
+Done
diff --git a/sapi/cgi/tests/include.inc b/sapi/cgi/tests/include.inc
index 11bf8f3b8..2d8ed8a2e 100644
--- a/sapi/cgi/tests/include.inc
+++ b/sapi/cgi/tests/include.inc
@@ -8,7 +8,7 @@ function get_cgi_path() /* {{{ */
$cgi = false;
if (file_exists($php) && is_executable($php)) {
- $version = `$php -v`;
+ $version = `$php -n -v`;
if (strstr($version, "(cli)")) {
/* that's cli */
$cli = true;