diff options
Diffstat (limited to 'sapi/cgi/fastcgi.c')
-rw-r--r-- | sapi/cgi/fastcgi.c | 181 |
1 files changed, 116 insertions, 65 deletions
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 |