Browse Source

Merged fastcgi.* reated changes from sapi/cgi

pull/1276/merge
Dmitry Stogov 11 years ago
parent
commit
abb616ae20
  1. 490
      sapi/fpm/fpm/fastcgi.c
  2. 48
      sapi/fpm/fpm/fastcgi.h
  3. 135
      sapi/fpm/fpm/fpm_main.c
  4. 2
      sapi/fpm/fpm/fpm_php.c

490
sapi/fpm/fpm/fastcgi.c

@ -146,6 +146,226 @@ static sa_t *allowed_clients = NULL;
static sa_t client_sa;
/* hash table */
#define FCGI_HASH_TABLE_SIZE 128
#define FCGI_HASH_TABLE_MASK (FCGI_HASH_TABLE_SIZE - 1)
#define FCGI_HASH_SEG_SIZE 4096
typedef struct _fcgi_hash_bucket {
unsigned int hash_value;
unsigned int var_len;
char *var;
unsigned int val_len;
char *val;
struct _fcgi_hash_bucket *next;
struct _fcgi_hash_bucket *list_next;
} fcgi_hash_bucket;
typedef struct _fcgi_hash_buckets {
unsigned int idx;
struct _fcgi_hash_buckets *next;
struct _fcgi_hash_bucket data[FCGI_HASH_TABLE_SIZE];
} fcgi_hash_buckets;
typedef struct _fcgi_data_seg {
char *pos;
char *end;
struct _fcgi_data_seg *next;
char data[1];
} fcgi_data_seg;
typedef struct _fcgi_hash {
fcgi_hash_bucket *hash_table[FCGI_HASH_TABLE_SIZE];
fcgi_hash_bucket *list;
fcgi_hash_buckets *buckets;
fcgi_data_seg *data;
} fcgi_hash;
static void fcgi_hash_init(fcgi_hash *h)
{
memset(h->hash_table, 0, sizeof(h->hash_table));
h->list = NULL;
h->buckets = (fcgi_hash_buckets*)malloc(sizeof(fcgi_hash_buckets));
h->buckets->idx = 0;
h->buckets->next = NULL;
h->data = (fcgi_data_seg*)malloc(sizeof(fcgi_data_seg) - 1 + FCGI_HASH_SEG_SIZE);
h->data->pos = h->data->data;
h->data->end = h->data->pos + FCGI_HASH_SEG_SIZE;
h->data->next = NULL;
}
static void fcgi_hash_destroy(fcgi_hash *h)
{
fcgi_hash_buckets *b;
fcgi_data_seg *p;
b = h->buckets;
while (b) {
fcgi_hash_buckets *q = b;
b = b->next;
free(q);
}
p = h->data;
while (p) {
fcgi_data_seg *q = p;
p = p->next;
free(q);
}
}
static void fcgi_hash_clean(fcgi_hash *h)
{
memset(h->hash_table, 0, sizeof(h->hash_table));
h->list = NULL;
/* delete all bucket blocks except the first one */
while (h->buckets->next) {
fcgi_hash_buckets *q = h->buckets;
h->buckets = h->buckets->next;
free(q);
}
h->buckets->idx = 0;
/* delete all data segments except the first one */
while (h->data->next) {
fcgi_data_seg *q = h->data;
h->data = h->data->next;
free(q);
}
h->data->pos = h->data->data;
}
static inline char* fcgi_hash_strndup(fcgi_hash *h, char *str, unsigned int str_len)
{
char *ret;
if (UNEXPECTED(h->data->pos + str_len + 1 >= h->data->end)) {
unsigned int seg_size = (str_len + 1 > FCGI_HASH_SEG_SIZE) ? str_len + 1 : FCGI_HASH_SEG_SIZE;
fcgi_data_seg *p = (fcgi_data_seg*)malloc(sizeof(fcgi_data_seg) - 1 + seg_size);
p->pos = p->data;
p->end = p->pos + seg_size;
p->next = h->data;
h->data = p;
}
ret = h->data->pos;
memcpy(ret, str, str_len);
ret[str_len] = 0;
h->data->pos += str_len + 1;
return ret;
}
static char* fcgi_hash_set(fcgi_hash *h, unsigned int hash_value, char *var, unsigned int var_len, char *val, unsigned int val_len)
{
unsigned int idx = hash_value & FCGI_HASH_TABLE_MASK;
fcgi_hash_bucket *p = h->hash_table[idx];
while (UNEXPECTED(p != NULL)) {
if (UNEXPECTED(p->hash_value == hash_value) &&
p->var_len == var_len &&
memcmp(p->var, var, var_len) == 0) {
p->val_len = val_len;
p->val = fcgi_hash_strndup(h, val, val_len);
return p->val;
}
p = p->next;
}
if (UNEXPECTED(h->buckets->idx >= FCGI_HASH_TABLE_SIZE)) {
fcgi_hash_buckets *b = (fcgi_hash_buckets*)malloc(sizeof(fcgi_hash_buckets));
b->idx = 0;
b->next = h->buckets;
h->buckets = b;
}
p = h->buckets->data + h->buckets->idx;
h->buckets->idx++;
p->next = h->hash_table[idx];
h->hash_table[idx] = p;
p->list_next = h->list;
h->list = p;
p->hash_value = hash_value;
p->var_len = var_len;
p->var = fcgi_hash_strndup(h, var, var_len);
p->val_len = val_len;
p->val = fcgi_hash_strndup(h, val, val_len);
return p->val;
}
static void fcgi_hash_del(fcgi_hash *h, unsigned int hash_value, char *var, unsigned int var_len)
{
unsigned int idx = hash_value & FCGI_HASH_TABLE_MASK;
fcgi_hash_bucket **p = &h->hash_table[idx];
while (*p != NULL) {
if ((*p)->hash_value == hash_value &&
(*p)->var_len == var_len &&
memcmp((*p)->var, var, var_len) == 0) {
(*p)->val = NULL; /* NULL value means deleted */
(*p)->val_len = 0;
*p = (*p)->next;
return;
}
p = &(*p)->next;
}
}
static char *fcgi_hash_get(fcgi_hash *h, unsigned int hash_value, char *var, unsigned int var_len, unsigned int *val_len)
{
unsigned int idx = hash_value & FCGI_HASH_TABLE_MASK;
fcgi_hash_bucket *p = h->hash_table[idx];
while (p != NULL) {
if (p->hash_value == hash_value &&
p->var_len == var_len &&
memcmp(p->var, var, var_len) == 0) {
*val_len = p->val_len;
return p->val;
}
p = p->next;
}
return NULL;
}
static void fcgi_hash_apply(fcgi_hash *h, fcgi_apply_func func, void *arg)
{
fcgi_hash_bucket *p = h->list;
while (p) {
if (EXPECTED(p->val != NULL)) {
func(p->var, p->var_len, p->val, p->val_len, arg);
}
p = p->list_next;
}
}
struct _fcgi_request {
int listen_socket;
#ifdef _WIN32
int tcp;
#endif
int fd;
int id;
int keep;
#ifdef TCP_NODELAY
int nodelay;
#endif
int closed;
int in_len;
int in_pad;
fcgi_header *out_hdr;
unsigned char *out_pos;
unsigned char out_buf[1024*8];
unsigned char reserved[sizeof(fcgi_end_request_rec)];
int has_env;
fcgi_hash env;
};
#ifdef _WIN32
static DWORD WINAPI fcgi_shutdown_thread(LPVOID arg)
@ -181,10 +401,20 @@ static void fcgi_setup_signals(void)
}
#endif
int fcgi_in_shutdown(void)
{
return in_shutdown;
}
void fcgi_terminate(void)
{
in_shutdown = 1;
}
int fcgi_init(void)
{
if (!is_initialized) {
zend_hash_init(&fcgi_mgmt_vars, 0, NULL, fcgi_free_mgmt_var_cb, 1);
zend_hash_init(&fcgi_mgmt_vars, 8, 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;
@ -285,9 +515,9 @@ void fcgi_set_allowed_clients(char *ip)
}
}
void fcgi_init_request(fcgi_request *req, int listen_socket)
fcgi_request *fcgi_init_request(int listen_socket)
{
memset(req, 0, sizeof(fcgi_request));
fcgi_request *req = (fcgi_request*)calloc(1, sizeof(fcgi_request));
req->listen_socket = listen_socket;
req->fd = -1;
req->id = -1;
@ -301,6 +531,20 @@ void fcgi_init_request(fcgi_request *req, int listen_socket)
#ifdef _WIN32
req->tcp = !GetNamedPipeInfo((HANDLE)_get_osfhandle(req->listen_socket), NULL, NULL, NULL, NULL);
#endif
#ifdef TCP_NODELAY
req->nodelay = 0;
#endif
fcgi_hash_init(&req->env);
return req;
}
void fcgi_destroy_request(fcgi_request *req)
{
fcgi_hash_destroy(&req->env);
free(req);
}
static inline ssize_t safe_write(fcgi_request *req, const void *buf, size_t count)
@ -379,120 +623,47 @@ static inline int fcgi_make_header(fcgi_header *hdr, fcgi_request_type type, int
return pad;
}
static inline size_t fcgi_get_params_len( int *result, unsigned char *p, unsigned char *end)
{
size_t ret = 0;
if (p < end) {
*result = p[0];
if (*result < 128) {
ret = 1;
}
else if (p + 3 < end) {
*result = ((*result & 0x7f) << 24);
*result |= (p[1] << 16);
*result |= (p[2] << 8);
*result |= p[3];
ret = 4;
}
}
if (*result < 0) {
ret = 0;
}
return ret;
}
static inline int fcgi_param_get_eff_len( unsigned char *p, unsigned char *end, uint *eff_len)
{
int ret = 1;
int zero_found = 0;
*eff_len = 0;
for (; p != end; ++p) {
if (*p == '\0') {
zero_found = 1;
}
else {
if (zero_found) {
ret = 0;
break;
}
if (*eff_len < ((uint)-1)) {
++*eff_len;
}
else {
ret = 0;
break;
}
}
}
return ret;
}
static int fcgi_get_params(fcgi_request *req, unsigned char *p, unsigned char *end)
{
char buf[128];
char *tmp = buf;
size_t buf_size = sizeof(buf);
int name_len = 0;
int val_len = 0;
uint eff_name_len = 0;
char *s;
int ret = 1;
size_t bytes_consumed;
while (p < end) {
bytes_consumed = fcgi_get_params_len(&name_len, p, end);
if (!bytes_consumed) {
/* Malformated request */
ret = 0;
break;
name_len = *p++;
if (UNEXPECTED(name_len >= 128)) {
if (UNEXPECTED(p + 3 >= end)) return 0;
name_len = ((name_len & 0x7f) << 24);
name_len |= (*p++ << 16);
name_len |= (*p++ << 8);
name_len |= *p++;
}
p += bytes_consumed;
bytes_consumed = fcgi_get_params_len(&val_len, p, end);
if (!bytes_consumed) {
/* Malformated request */
ret = 0;
break;
if (UNEXPECTED(p >= end)) return 0;
val_len = *p++;
if (UNEXPECTED(val_len >= 128)) {
if (UNEXPECTED(p + 3 >= end)) return 0;
val_len = ((val_len & 0x7f) << 24);
val_len |= (*p++ << 16);
val_len |= (*p++ << 8);
val_len |= *p++;
}
p += bytes_consumed;
if (name_len > (INT_MAX - val_len) || /* would the addition overflow? */
name_len + val_len > end - p) { /* would we exceed the buffer? */
if (UNEXPECTED(name_len > (INT_MAX - val_len)) || /* would the addition overflow? */
UNEXPECTED(name_len + val_len > end - p)) { /* would we exceed the buffer? */
/* Malformated request */
ret = 0;
break;
return 0;
}
/*
* get the effective length of the name in case it's not a valid string
* don't do this on the value because it can be binary data
*/
if (!fcgi_param_get_eff_len(p, p+name_len, &eff_name_len)){
if (UNEXPECTED(memchr(p, 0, name_len) != NULL)) {
/* Malicious request */
ret = 0;
break;
}
if (eff_name_len >= buf_size-1) {
if (eff_name_len > ((uint)-1)-64) {
ret = 0;
break;
}
buf_size = eff_name_len + 64;
tmp = (tmp == buf ? emalloc(buf_size): erealloc(tmp, buf_size));
if (tmp == NULL) {
ret = 0;
break;
}
return 0;
}
memcpy(tmp, p, eff_name_len);
tmp[eff_name_len] = 0;
s = estrndup((char*)p + name_len, val_len);
zend_hash_str_update_ptr(req->env, tmp, eff_name_len, s);
fcgi_hash_set(&req->env, FCGI_HASH_FUNC(p, name_len), (char*)p, name_len, (char*)p + name_len, val_len);
p += name_len + val_len;
}
if (tmp != buf && tmp != NULL) {
efree(tmp);
}
return ret;
return 1;
}
static void fcgi_free_var(zval *zv)
@ -511,8 +682,7 @@ static int fcgi_read_request(fcgi_request *req)
req->in_len = 0;
req->out_hdr = NULL;
req->out_pos = req->out_buf;
ALLOC_HASHTABLE(req->env);
zend_hash_init(req->env, 0, NULL, fcgi_free_var, 0);
req->has_env = 1;
if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) ||
hdr.version < FCGI_VERSION_1) {
@ -539,25 +709,32 @@ static int fcgi_read_request(fcgi_request *req)
req->id = (hdr.requestIdB1 << 8) + hdr.requestIdB0;
if (hdr.type == FCGI_BEGIN_REQUEST && len == sizeof(fcgi_begin_request)) {
char *val;
if (safe_read(req, buf, len+padding) != len+padding) {
return 0;
}
req->keep = (((fcgi_begin_request*)buf)->flags & FCGI_KEEP_CONN);
#ifdef TCP_NODELAY
if (req->keep && req->tcp && !req->nodelay) {
# ifdef _WIN32
BOOL on = 1;
# else
int on = 1;
# endif
setsockopt(req->fd, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on));
req->nodelay = 1;
}
#endif
switch ((((fcgi_begin_request*)buf)->roleB1 << 8) + ((fcgi_begin_request*)buf)->roleB0) {
case FCGI_RESPONDER:
val = estrdup("RESPONDER");
zend_hash_str_update_ptr(req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), val);
fcgi_hash_set(&req->env, FCGI_HASH_FUNC("FCGI_ROLE", sizeof("FCGI_ROLE")-1), "FCGI_ROLE", sizeof("FCGI_ROLE")-1, "RESPONDER", sizeof("RESPONDER")-1);
break;
case FCGI_AUTHORIZER:
val = estrdup("AUTHORIZER");
zend_hash_str_update_ptr(req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), val);
fcgi_hash_set(&req->env, FCGI_HASH_FUNC("FCGI_ROLE", sizeof("FCGI_ROLE")-1), "FCGI_ROLE", sizeof("FCGI_ROLE")-1, "AUTHORIZER", sizeof("AUTHORIZER")-1);
break;
case FCGI_FILTER:
val = estrdup("FILTER");
zend_hash_str_update_ptr(req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), val);
fcgi_hash_set(&req->env, FCGI_HASH_FUNC("FCGI_ROLE", sizeof("FCGI_ROLE")-1), "FCGI_ROLE", sizeof("FCGI_ROLE")-1, "FILTER", sizeof("FILTER")-1);
break;
default:
return 0;
@ -596,8 +773,9 @@ static int fcgi_read_request(fcgi_request *req)
}
} else if (hdr.type == FCGI_GET_VALUES) {
unsigned char *p = buf + sizeof(fcgi_header);
zend_string *key;
zval *value;
unsigned int zlen;
fcgi_hash_bucket *q;
if (safe_read(req, buf, len+padding) != len+padding) {
req->keep = 0;
@ -609,26 +787,23 @@ static int fcgi_read_request(fcgi_request *req)
return 0;
}
ZEND_HASH_FOREACH_STR_KEY(req->env, key) {
int zlen;
if (!key) {
continue;
}
value = zend_hash_find(&fcgi_mgmt_vars, key);
if (!value) {
q = req->env.list;
while (q != NULL) {
if ((value = zend_hash_str_find(&fcgi_mgmt_vars, q->var, q->var_len)) == NULL) {
q = q->list_next;
continue;
}
zlen = Z_STRLEN_P(value);
if ((p + 4 + 4 + key->len + zlen) >= (buf + sizeof(buf))) {
zlen = (unsigned int)Z_STRLEN_P(value);
if ((p + 4 + 4 + q->var_len + zlen) >= (buf + sizeof(buf))) {
break;
}
if (key->len < 0x80) {
*p++ = key->len;
if (q->var_len < 0x80) {
*p++ = q->var_len;
} else {
*p++ = ((key->len >> 24) & 0xff) | 0x80;
*p++ = (key->len >> 16) & 0xff;
*p++ = (key->len >> 8) & 0xff;
*p++ = key->len & 0xff;
*p++ = ((q->var_len >> 24) & 0xff) | 0x80;
*p++ = (q->var_len >> 16) & 0xff;
*p++ = (q->var_len >> 8) & 0xff;
*p++ = q->var_len & 0xff;
}
if (zlen < 0x80) {
*p++ = zlen;
@ -638,11 +813,12 @@ static int fcgi_read_request(fcgi_request *req)
*p++ = (zlen >> 8) & 0xff;
*p++ = zlen & 0xff;
}
memcpy(p, key->val, key->len);
p += key->len;
memcpy(p, q->var, q->var_len);
p += q->var_len;
memcpy(p, Z_STRVAL_P(value), zlen);
p += zlen;
} ZEND_HASH_FOREACH_END();
q = q->list_next;
}
len = p - buf - sizeof(fcgi_header);
len += fcgi_make_header((fcgi_header*)buf, FCGI_GET_VALUES_RESULT, 0, len);
if (safe_write(req, buf, sizeof(fcgi_header)+len) != (int)sizeof(fcgi_header)+len) {
@ -712,10 +888,9 @@ int fcgi_read(fcgi_request *req, char *str, int len)
void fcgi_close(fcgi_request *req, int force, int destroy)
{
if (destroy && req->env) {
zend_hash_destroy(req->env);
FREE_HASHTABLE(req->env);
req->env = NULL;
if (destroy && req->has_env) {
fcgi_hash_clean(&req->env);
req->has_env = 0;
}
#ifdef _WIN32
@ -750,12 +925,20 @@ void fcgi_close(fcgi_request *req, int force, int destroy)
while (recv(req->fd, buf, sizeof(buf), 0) > 0) {}
}
close(req->fd);
#endif
#ifdef TCP_NODELAY
req->nodelay = 0;
#endif
req->fd = -1;
fpm_request_finished();
}
}
int fcgi_is_closed(fcgi_request *req)
{
return (req->fd < 0);
}
static int fcgi_is_allowed() {
int i;
@ -1072,25 +1255,44 @@ int fcgi_finish_request(fcgi_request *req, int force_close)
char* fcgi_getenv(fcgi_request *req, const char* var, int var_len)
{
if (!req) {
return NULL;
}
unsigned int val_len;
if (!req) return NULL;
return fcgi_hash_get(&req->env, FCGI_HASH_FUNC(var, var_len), (char*)var, var_len, &val_len);
}
char* fcgi_quick_getenv(fcgi_request *req, const char* var, int var_len, unsigned int hash_value)
{
unsigned int val_len;
return zend_hash_str_find_ptr(req->env, var, var_len);
return fcgi_hash_get(&req->env, hash_value, (char*)var, var_len, &val_len);
}
char* fcgi_putenv(fcgi_request *req, char* var, int var_len, char* val)
{
if (var && req) {
if (val == NULL) {
zend_hash_str_del(req->env, var, var_len);
} else {
val = estrdup(val);
zend_hash_str_update_ptr(req->env, var, var_len, val);
return val;
}
if (!req) return NULL;
if (val == NULL) {
fcgi_hash_del(&req->env, FCGI_HASH_FUNC(var, var_len), var, var_len);
return NULL;
} else {
return fcgi_hash_set(&req->env, FCGI_HASH_FUNC(var, var_len), var, var_len, val, (unsigned int)strlen(val));
}
return NULL;
}
char* fcgi_quick_putenv(fcgi_request *req, char* var, int var_len, unsigned int hash_value, char* val)
{
if (val == NULL) {
fcgi_hash_del(&req->env, hash_value, var, var_len);
return NULL;
} else {
return fcgi_hash_set(&req->env, hash_value, var, var_len, val, (unsigned int)strlen(val));
}
}
void fcgi_loadenv(fcgi_request *req, fcgi_apply_func func, zval *array)
{
fcgi_hash_apply(&req->env, func, array);
}
void fcgi_set_mgmt_var(const char * name, size_t name_len, const char * value, size_t value_len)

48
sapi/fpm/fpm/fastcgi.h

@ -26,6 +26,23 @@
#define FCGI_KEEP_CONN 1
/* this is near the perfect hash function for most useful FastCGI variables
* which combines efficiency and minimal hash collisions
*/
#define FCGI_HASH_FUNC(var, var_len) \
(UNEXPECTED(var_len < 3) ? var_len : \
(((unsigned int)var[3]) << 2) + \
(((unsigned int)var[var_len-2]) << 4) + \
(((unsigned int)var[var_len-1]) << 2) + \
var_len)
#define FCGI_GETENV(request, name) \
fcgi_quick_getenv(request, name, sizeof(name)-1, FCGI_HASH_FUNC(name, sizeof(name)-1))
#define FCGI_PUTENV(request, name, value) \
fcgi_quick_putenv(request, name, sizeof(name)-1, FCGI_HASH_FUNC(name, sizeof(name)-1), value)
typedef enum _fcgi_role {
FCGI_RESPONDER = 1,
FCGI_AUTHORIZER = 2,
@ -91,39 +108,28 @@ typedef struct _fcgi_end_request_rec {
/* FastCGI client API */
typedef struct _fcgi_request {
int listen_socket;
#ifdef _WIN32
int tcp;
#endif
int fd;
int id;
int keep;
int closed;
int in_len;
int in_pad;
fcgi_header *out_hdr;
unsigned char *out_pos;
unsigned char out_buf[1024*8];
unsigned char reserved[sizeof(fcgi_end_request_rec)];
typedef void (*fcgi_apply_func)(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg);
HashTable *env;
} fcgi_request;
typedef struct _fcgi_request fcgi_request;
int fcgi_init(void);
void fcgi_shutdown(void);
void fcgi_init_request(fcgi_request *req, int listen_socket);
int fcgi_in_shutdown(void);
void fcgi_terminate(void);
fcgi_request* fcgi_init_request(int listen_socket);
void fcgi_destroy_request(fcgi_request *req);
int fcgi_accept_request(fcgi_request *req);
int fcgi_finish_request(fcgi_request *req, int force_close);
void fcgi_set_in_shutdown(int);
void fcgi_set_allowed_clients(char *);
void fcgi_close(fcgi_request *req, int force, int destroy);
int fcgi_is_closed(fcgi_request *req);
char* fcgi_getenv(fcgi_request *req, const char* var, int var_len);
char* fcgi_putenv(fcgi_request *req, char* var, int var_len, char* val);
char* fcgi_quick_getenv(fcgi_request *req, const char* var, int var_len, unsigned int hash_value);
char* fcgi_quick_putenv(fcgi_request *req, char* var, int var_len, unsigned int hash_value, char* val);
void fcgi_loadenv(fcgi_request *req, fcgi_apply_func load_func, zval *array);
int fcgi_read(fcgi_request *req, char *str, int len);

135
sapi/fpm/fpm/fpm_main.c

@ -460,8 +460,7 @@ static size_t sapi_cgi_read_post(char *buffer, size_t count_bytes)
while (read_bytes < count_bytes) {
fcgi_request *request = (fcgi_request*) SG(server_context);
if (request_body_fd == -1) {
char *request_body_filename = sapi_cgibin_getenv((char *) "REQUEST_BODY_FILE",
sizeof("REQUEST_BODY_FILE") - 1);
char *request_body_filename = FCGI_GETENV(request, "REQUEST_BODY_FILE");
if (request_body_filename && *request_body_filename) {
request_body_fd = open(request_body_filename, O_RDONLY);
@ -515,7 +514,20 @@ static char *_sapi_cgibin_putenv(char *name, char *value)
static char *sapi_cgi_read_cookies(void)
{
return sapi_cgibin_getenv((char *) "HTTP_COOKIE", sizeof("HTTP_COOKIE") - 1);
fcgi_request *request = (fcgi_request*) SG(server_context);
return FCGI_GETENV(request, "HTTP_COOKIE");
}
static void cgi_php_load_env_var(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg)
{
zval *array_ptr = (zval*)arg;
int filter_arg = (Z_ARR_P(array_ptr) == Z_ARR(PG(http_globals)[TRACK_VARS_ENV]))?PARSE_ENV:PARSE_SERVER;
size_t new_val_len;
if (sapi_module.input_filter(filter_arg, var, &val, strlen(val), &new_val_len)) {
php_register_variable_safe(var, val, new_val_len, array_ptr);
}
}
void cgi_php_import_environment_variables(zval *array_ptr)
@ -545,20 +557,12 @@ void cgi_php_import_environment_variables(zval *array_ptr)
php_php_import_environment_variables(array_ptr);
request = (fcgi_request*) SG(server_context);
filter_arg = Z_ARR_P(array_ptr) == Z_ARR(PG(http_globals)[TRACK_VARS_ENV])
? PARSE_ENV : PARSE_SERVER;
ZEND_HASH_FOREACH_STR_KEY_PTR(request->env, var, val) {
size_t new_val_len;
if (var && sapi_module.input_filter(filter_arg, var->val, &val, strlen(val), &new_val_len)) {
php_register_variable_safe(var->val, val, new_val_len, array_ptr);
}
} ZEND_HASH_FOREACH_END();
fcgi_loadenv(request, cgi_php_load_env_var, array_ptr);
}
static void sapi_cgi_register_variables(zval *track_vars_array)
{
fcgi_request *request = (fcgi_request*) SG(server_context);
size_t php_self_len;
char *php_self;
@ -570,7 +574,7 @@ static void sapi_cgi_register_variables(zval *track_vars_array)
if (CGIG(fix_pathinfo)) {
char *script_name = SG(request_info).request_uri;
unsigned int script_name_len = script_name ? strlen(script_name) : 0;
char *path_info = sapi_cgibin_getenv("PATH_INFO", sizeof("PATH_INFO") - 1);
char *path_info = FCGI_GETENV(request, "PATH_INFO");
unsigned int path_info_len = path_info ? strlen(path_info) : 0;
php_self_len = script_name_len + path_info_len;
@ -711,6 +715,7 @@ static void php_cgi_ini_activate_user_config(char *path, int path_len, const cha
static int sapi_cgi_activate(void)
{
fcgi_request *request = (fcgi_request*) SG(server_context);
char *path, *doc_root, *server_name;
uint path_len, doc_root_len, server_name_len;
@ -721,7 +726,7 @@ static int sapi_cgi_activate(void)
if (php_ini_has_per_host_config()) {
/* Activate per-host-system-configuration defined in php.ini and stored into configuration_hash during startup */
server_name = sapi_cgibin_getenv("SERVER_NAME", sizeof("SERVER_NAME") - 1);
server_name = FCGI_GETENV(request, "SERVER_NAME");
/* SERVER_NAME should also be defined at this stage..but better check it anyway */
if (server_name) {
server_name_len = strlen(server_name);
@ -755,7 +760,7 @@ static int sapi_cgi_activate(void)
/* Load and activate user ini files in path starting from DOCUMENT_ROOT */
if (PG(user_ini_filename) && *PG(user_ini_filename)) {
doc_root = sapi_cgibin_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT") - 1);
doc_root = FCGI_GETENV(request, "DOCUMENT_ROOT");
/* DOCUMENT_ROOT should also be defined at this stage..but better check it anyway */
if (doc_root) {
doc_root_len = strlen(doc_root);
@ -984,8 +989,9 @@ static int is_valid_path(const char *path)
*/
static void init_request_info(void)
{
char *env_script_filename = sapi_cgibin_getenv("SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME") - 1);
char *env_path_translated = sapi_cgibin_getenv("PATH_TRANSLATED", sizeof("PATH_TRANSLATED") - 1);
fcgi_request *request = (fcgi_request*) SG(server_context);
char *env_script_filename = FCGI_GETENV(request, "SCRIPT_FILENAME");
char *env_path_translated = FCGI_GETENV(request, "PATH_TRANSLATED");
char *script_path_translated = env_script_filename;
char *ini;
int apache_was_here = 0;
@ -1013,25 +1019,25 @@ static void init_request_info(void)
* of the script will be retreived later via argc/argv */
if (script_path_translated) {
const char *auth;
char *content_length = sapi_cgibin_getenv("CONTENT_LENGTH", sizeof("CONTENT_LENGTH") - 1);
char *content_type = sapi_cgibin_getenv("CONTENT_TYPE", sizeof("CONTENT_TYPE") - 1);
char *env_path_info = sapi_cgibin_getenv("PATH_INFO", sizeof("PATH_INFO") - 1);
char *env_script_name = sapi_cgibin_getenv("SCRIPT_NAME", sizeof("SCRIPT_NAME") - 1);
char *content_length = FCGI_GETENV(request, "CONTENT_LENGTH");
char *content_type = FCGI_GETENV(request, "CONTENT_TYPE");
char *env_path_info = FCGI_GETENV(request, "PATH_INFO");
char *env_script_name = FCGI_GETENV(request, "SCRIPT_NAME");
/* Hack for buggy IIS that sets incorrect PATH_INFO */
char *env_server_software = sapi_cgibin_getenv("SERVER_SOFTWARE", sizeof("SERVER_SOFTWARE") - 1);
char *env_server_software = FCGI_GETENV(request, "SERVER_SOFTWARE");
if (env_server_software &&
env_script_name &&
env_path_info &&
strncmp(env_server_software, "Microsoft-IIS", sizeof("Microsoft-IIS") - 1) == 0 &&
strncmp(env_path_info, env_script_name, strlen(env_script_name)) == 0
) {
env_path_info = _sapi_cgibin_putenv("ORIG_PATH_INFO", env_path_info);
env_path_info = FCGI_PUTENV(request, "ORIG_PATH_INFO", env_path_info);
env_path_info += strlen(env_script_name);
if (*env_path_info == 0) {
env_path_info = NULL;
}
env_path_info = _sapi_cgibin_putenv("PATH_INFO", env_path_info);
env_path_info = FCGI_PUTENV(request, "PATH_INFO", env_path_info);
}
#define APACHE_PROXY_FCGI_PREFIX "proxy:fcgi://"
@ -1066,8 +1072,8 @@ static void init_request_info(void)
if (CGIG(fix_pathinfo)) {
struct stat st;
char *real_path = NULL;
char *env_redirect_url = sapi_cgibin_getenv("REDIRECT_URL", sizeof("REDIRECT_URL") - 1);
char *env_document_root = sapi_cgibin_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT") - 1);
char *env_redirect_url = FCGI_GETENV(request, "REDIRECT_URL");
char *env_document_root = FCGI_GETENV(request, "DOCUMENT_ROOT");
char *orig_path_translated = env_path_translated;
char *orig_path_info = env_path_info;
char *orig_script_name = env_script_name;
@ -1075,7 +1081,7 @@ static void init_request_info(void)
int script_path_translated_len;
if (!env_document_root && PG(doc_root)) {
env_document_root = _sapi_cgibin_putenv("DOCUMENT_ROOT", PG(doc_root));
env_document_root = FCGI_PUTENV(request, "DOCUMENT_ROOT", PG(doc_root));
/* fix docroot */
TRANSLATE_SLASHES(env_document_root);
}
@ -1156,15 +1162,15 @@ static void init_request_info(void)
if (orig_path_info) {
char old;
_sapi_cgibin_putenv("ORIG_PATH_INFO", orig_path_info);
FCGI_PUTENV(request, "ORIG_PATH_INFO", orig_path_info);
old = path_info[0];
path_info[0] = 0;
if (!orig_script_name ||
strcmp(orig_script_name, env_path_info) != 0) {
if (orig_script_name) {
_sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name);
FCGI_PUTENV(request, "ORIG_SCRIPT_NAME", orig_script_name);
}
SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_path_info);
SG(request_info).request_uri = FCGI_PUTENV(request, "SCRIPT_NAME", env_path_info);
} else {
SG(request_info).request_uri = orig_script_name;
}
@ -1176,19 +1182,19 @@ static void init_request_info(void)
*/
int snlen = strlen(env_script_name);
if (snlen>slen && !strcmp(env_script_name+snlen-slen, path_info)) {
_sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name);
FCGI_PUTENV(request, "ORIG_SCRIPT_NAME", orig_script_name);
env_script_name[snlen-slen] = 0;
SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_script_name);
SG(request_info).request_uri = FCGI_PUTENV(request, "SCRIPT_NAME", env_script_name);
}
}
env_path_info = _sapi_cgibin_putenv("PATH_INFO", path_info);
env_path_info = FCGI_PUTENV(request, "PATH_INFO", path_info);
}
if (!orig_script_filename ||
strcmp(orig_script_filename, pt) != 0) {
if (orig_script_filename) {
_sapi_cgibin_putenv("ORIG_SCRIPT_FILENAME", orig_script_filename);
FCGI_PUTENV(request, "ORIG_SCRIPT_FILENAME", orig_script_filename);
}
script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", pt);
script_path_translated = FCGI_PUTENV(request, "SCRIPT_FILENAME", pt);
}
TRANSLATE_SLASHES(pt);
@ -1218,9 +1224,9 @@ static void init_request_info(void)
}
path_translated[path_translated_len] = '\0';
if (orig_path_translated) {
_sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated);
FCGI_PUTENV(request, "ORIG_PATH_TRANSLATED", orig_path_translated);
}
env_path_translated = _sapi_cgibin_putenv("PATH_TRANSLATED", path_translated);
env_path_translated = FCGI_PUTENV(request, "PATH_TRANSLATED", path_translated);
efree(path_translated);
} else if ( env_script_name &&
strstr(pt, env_script_name)
@ -1237,9 +1243,9 @@ static void init_request_info(void)
}
path_translated[path_translated_len] = '\0';
if (orig_path_translated) {
_sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated);
FCGI_PUTENV(request, "ORIG_PATH_TRANSLATED", orig_path_translated);
}
env_path_translated = _sapi_cgibin_putenv("PATH_TRANSLATED", path_translated);
env_path_translated = FCGI_PUTENV(request, "PATH_TRANSLATED", path_translated);
efree(path_translated);
}
break;
@ -1255,18 +1261,18 @@ static void init_request_info(void)
* have failed anyway... we output 'no input file' now.
*/
if (orig_script_filename) {
_sapi_cgibin_putenv("ORIG_SCRIPT_FILENAME", orig_script_filename);
FCGI_PUTENV(request, "ORIG_SCRIPT_FILENAME", orig_script_filename);
}
script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", NULL);
script_path_translated = FCGI_PUTENV(request, "SCRIPT_FILENAME", NULL);
SG(sapi_headers).http_response_code = 404;
}
if (!SG(request_info).request_uri) {
if (!orig_script_name ||
strcmp(orig_script_name, env_script_name) != 0) {
if (orig_script_name) {
_sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name);
FCGI_PUTENV(request, "ORIG_SCRIPT_NAME", orig_script_name);
}
SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_script_name);
SG(request_info).request_uri = FCGI_PUTENV(request, "SCRIPT_NAME", env_script_name);
} else {
SG(request_info).request_uri = orig_script_name;
}
@ -1280,27 +1286,27 @@ static void init_request_info(void)
(script_path_translated != orig_script_filename &&
strcmp(script_path_translated, orig_script_filename) != 0)) {
if (orig_script_filename) {
_sapi_cgibin_putenv("ORIG_SCRIPT_FILENAME", orig_script_filename);
FCGI_PUTENV(request, "ORIG_SCRIPT_FILENAME", orig_script_filename);
}
script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", script_path_translated);
script_path_translated = FCGI_PUTENV(request, "SCRIPT_FILENAME", script_path_translated);
}
if (!apache_was_here && env_redirect_url) {
/* if we used PATH_TRANSLATED to work around Apache mod_fastcgi (but not mod_proxy_fcgi,
* hence !apache_was_here) weirdness, strip info accordingly */
if (orig_path_info) {
_sapi_cgibin_putenv("ORIG_PATH_INFO", orig_path_info);
_sapi_cgibin_putenv("PATH_INFO", NULL);
FCGI_PUTENV(request, "ORIG_PATH_INFO", orig_path_info);
FCGI_PUTENV(request, "PATH_INFO", NULL);
}
if (orig_path_translated) {
_sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated);
_sapi_cgibin_putenv("PATH_TRANSLATED", NULL);
FCGI_PUTENV(request, "ORIG_PATH_TRANSLATED", orig_path_translated);
FCGI_PUTENV(request, "PATH_TRANSLATED", NULL);
}
}
if (env_script_name != orig_script_name) {
if (orig_script_name) {
_sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name);
FCGI_PUTENV(request, "ORIG_SCRIPT_NAME", orig_script_name);
}
SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_script_name);
SG(request_info).request_uri = FCGI_PUTENV(request, "SCRIPT_NAME", env_script_name);
} else {
SG(request_info).request_uri = env_script_name;
}
@ -1322,19 +1328,19 @@ static void init_request_info(void)
SG(request_info).path_translated = estrdup(script_path_translated);
}
SG(request_info).request_method = sapi_cgibin_getenv("REQUEST_METHOD", sizeof("REQUEST_METHOD") - 1);
SG(request_info).request_method = FCGI_GETENV(request, "REQUEST_METHOD");
/* FIXME - Work out proto_num here */
SG(request_info).query_string = sapi_cgibin_getenv("QUERY_STRING", sizeof("QUERY_STRING") - 1);
SG(request_info).query_string = FCGI_GETENV(request, "QUERY_STRING");
SG(request_info).content_type = (content_type ? content_type : "" );
SG(request_info).content_length = (content_length ? atol(content_length) : 0);
/* The CGI RFC allows servers to pass on unvalidated Authorization data */
auth = sapi_cgibin_getenv("HTTP_AUTHORIZATION", sizeof("HTTP_AUTHORIZATION") - 1);
auth = FCGI_GETENV(request, "HTTP_AUTHORIZATION");
php_handle_auth_data(auth);
}
/* INI stuff */
ini = sapi_cgibin_getenv("PHP_VALUE", sizeof("PHP_VALUE") - 1);
ini = FCGI_GETENV(request, "PHP_VALUE");
if (ini) {
int mode = ZEND_INI_USER;
char *tmp;
@ -1343,7 +1349,7 @@ static void init_request_info(void)
efree(tmp);
}
ini = sapi_cgibin_getenv("PHP_ADMIN_VALUE", sizeof("PHP_ADMIN_VALUE") - 1);
ini = FCGI_GETENV(request, "PHP_ADMIN_VALUE");
if (ini) {
int mode = ZEND_INI_SYSTEM;
char *tmp;
@ -1463,7 +1469,7 @@ PHP_FUNCTION(fastcgi_finish_request) /* {{{ */
{
fcgi_request *request = (fcgi_request*) SG(server_context);
if (request->fd >= 0) {
if (!fcgi_is_closed(request)) {
php_output_end_all();
php_header();
@ -1517,7 +1523,7 @@ int main(int argc, char *argv[])
int max_requests = 500;
int requests = 0;
int fcgi_fd = 0;
fcgi_request request;
fcgi_request *request;
char *fpm_config = NULL;
char *fpm_prefix = NULL;
char *fpm_pid = NULL;
@ -1813,12 +1819,12 @@ consult the installation file that came with this distribution, or visit \n\
php_import_environment_variables = cgi_php_import_environment_variables;
/* library is already initialized, now init our request */
fcgi_init_request(&request, fcgi_fd);
request = fcgi_init_request(fcgi_fd);
zend_first_try {
while (fcgi_accept_request(&request) >= 0) {
while (fcgi_accept_request(request) >= 0) {
request_body_fd = -1;
SG(server_context) = (void *) &request;
SG(server_context) = (void *) request;
init_request_info();
char *primary_script = NULL;
@ -1827,7 +1833,7 @@ consult the installation file that came with this distribution, or visit \n\
/* request startup only after we've done all we can to
* get path_translated */
if (php_request_startup() == FAILURE) {
fcgi_finish_request(&request, 1);
fcgi_finish_request(request, 1);
SG(server_context) = NULL;
php_module_shutdown();
return FPM_EXIT_SOFTWARE;
@ -1920,11 +1926,12 @@ fastcgi_request_done:
requests++;
if (max_requests && (requests == max_requests)) {
fcgi_finish_request(&request, 1);
fcgi_finish_request(request, 1);
break;
}
/* end of fastcgi loop */
}
fcgi_destroy_request(request);
fcgi_shutdown();
if (cgi_sapi_module.php_ini_path_override) {

2
sapi/fpm/fpm/fpm_php.c

@ -201,7 +201,7 @@ static void fpm_php_cleanup(int which, void *arg) /* {{{ */
void fpm_php_soft_quit() /* {{{ */
{
fcgi_set_in_shutdown(1);
fcgi_terminate();
}
/* }}} */

Loading…
Cancel
Save