version 1.1, 2012/02/21 23:48:06
|
version 1.1.1.4, 2014/06/15 20:04:02
|
Line 2
|
Line 2
|
+----------------------------------------------------------------------+ |
+----------------------------------------------------------------------+ |
| PHP Version 5 | |
| PHP Version 5 | |
+----------------------------------------------------------------------+ |
+----------------------------------------------------------------------+ |
| Copyright (c) 1997-2012 The PHP Group | | | Copyright (c) 1997-2014 The PHP Group | |
+----------------------------------------------------------------------+ |
+----------------------------------------------------------------------+ |
| This source file is subject to version 3.01 of the PHP license, | |
| 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 | |
| that is bundled with this package in the file LICENSE, and is | |
Line 67
|
Line 67
|
# include <sys/socket.h> |
# include <sys/socket.h> |
# include <sys/un.h> |
# include <sys/un.h> |
# include <netinet/in.h> |
# include <netinet/in.h> |
|
# include <netinet/tcp.h> |
# include <arpa/inet.h> |
# include <arpa/inet.h> |
# include <netdb.h> |
# include <netdb.h> |
# include <signal.h> |
# include <signal.h> |
Line 140 static int is_fastcgi = 0;
|
Line 141 static int is_fastcgi = 0;
|
static int in_shutdown = 0; |
static int in_shutdown = 0; |
static in_addr_t *allowed_clients = NULL; |
static in_addr_t *allowed_clients = NULL; |
|
|
|
/* 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 TSRMLS_DC) |
|
{ |
|
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 TSRMLS_CC); |
|
} |
|
p = p->list_next; |
|
} |
|
} |
|
|
|
struct _fcgi_request { |
|
int listen_socket; |
|
int tcp; |
|
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 |
#ifdef _WIN32 |
|
|
static DWORD WINAPI fcgi_shutdown_thread(LPVOID arg) |
static DWORD WINAPI fcgi_shutdown_thread(LPVOID arg) |
Line 180 int fcgi_in_shutdown(void)
|
Line 399 int fcgi_in_shutdown(void)
|
return in_shutdown; |
return in_shutdown; |
} |
} |
|
|
|
void fcgi_terminate(void) |
|
{ |
|
in_shutdown = 1; |
|
} |
|
|
int fcgi_init(void) |
int fcgi_init(void) |
{ |
{ |
if (!is_initialized) { |
if (!is_initialized) { |
Line 417 int fcgi_listen(const char *path, int backlog)
|
Line 641 int fcgi_listen(const char *path, int backlog)
|
8192, 8192, 0, &saw); |
8192, 8192, 0, &saw); |
if (namedPipe == INVALID_HANDLE_VALUE) { |
if (namedPipe == INVALID_HANDLE_VALUE) { |
return -1; |
return -1; |
} | } |
listen_socket = _open_osfhandle((long)namedPipe, 0); |
listen_socket = _open_osfhandle((long)namedPipe, 0); |
if (!is_initialized) { |
if (!is_initialized) { |
fcgi_init(); |
fcgi_init(); |
Line 459 int fcgi_listen(const char *path, int backlog)
|
Line 683 int fcgi_listen(const char *path, int backlog)
|
if (!tcp) { |
if (!tcp) { |
chmod(path, 0777); |
chmod(path, 0777); |
} else { |
} else { |
char *ip = getenv("FCGI_WEB_SERVER_ADDRS"); | char *ip = getenv("FCGI_WEB_SERVER_ADDRS"); |
char *cur, *end; | char *cur, *end; |
int n; | int n; |
| |
if (ip) { | if (ip) { |
ip = strdup(ip); | ip = strdup(ip); |
cur = ip; | cur = ip; |
n = 0; | n = 0; |
while (*cur) { | while (*cur) { |
if (*cur == ',') n++; | if (*cur == ',') n++; |
cur++; | 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 = malloc(sizeof(in_addr_t) * (n+2)); | allowed_clients[n] = inet_addr(cur); |
n = 0; | if (allowed_clients[n] == INADDR_NONE) { |
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); |
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); |
free(ip); |
} |
} |
} |
} |
Line 507 int fcgi_listen(const char *path, int backlog)
|
Line 731 int fcgi_listen(const char *path, int backlog)
|
return listen_socket; |
return listen_socket; |
} |
} |
|
|
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->listen_socket = listen_socket; |
req->fd = -1; |
req->fd = -1; |
req->id = -1; |
req->id = -1; |
Line 523 void fcgi_init_request(fcgi_request *req, int listen_s
|
Line 747 void fcgi_init_request(fcgi_request *req, int listen_s
|
#ifdef _WIN32 |
#ifdef _WIN32 |
req->tcp = !GetNamedPipeInfo((HANDLE)_get_osfhandle(req->listen_socket), NULL, NULL, NULL, NULL); |
req->tcp = !GetNamedPipeInfo((HANDLE)_get_osfhandle(req->listen_socket), NULL, NULL, NULL, NULL); |
#endif |
#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) |
static inline ssize_t safe_write(fcgi_request *req, const void *buf, size_t count) |
{ |
{ |
int ret; |
int ret; |
Line 603 static inline int fcgi_make_header(fcgi_header *hdr, f
|
Line 841 static inline int fcgi_make_header(fcgi_header *hdr, f
|
|
|
static int fcgi_get_params(fcgi_request *req, unsigned char *p, unsigned char *end) |
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); |
|
unsigned int name_len, val_len; |
unsigned int name_len, val_len; |
char *s; |
|
int ret = 1; |
|
|
|
while (p < end) { |
while (p < end) { |
name_len = *p++; |
name_len = *p++; |
if (name_len >= 128) { | if (UNEXPECTED(name_len >= 128)) { |
if (p + 3 >= end) { | if (UNEXPECTED(p + 3 >= end)) return 0; |
ret = 0; | |
break; | |
} | |
name_len = ((name_len & 0x7f) << 24); |
name_len = ((name_len & 0x7f) << 24); |
name_len |= (*p++ << 16); |
name_len |= (*p++ << 16); |
name_len |= (*p++ << 8); |
name_len |= (*p++ << 8); |
name_len |= *p++; |
name_len |= *p++; |
} |
} |
if (p >= end) { | if (UNEXPECTED(p >= end)) return 0; |
ret = 0; | |
break; | |
} | |
val_len = *p++; |
val_len = *p++; |
if (val_len >= 128) { | if (UNEXPECTED(val_len >= 128)) { |
if (p + 3 >= end) { | if (UNEXPECTED(p + 3 >= end)) return 0; |
ret = 0; | |
break; | |
} | |
val_len = ((val_len & 0x7f) << 24); |
val_len = ((val_len & 0x7f) << 24); |
val_len |= (*p++ << 16); |
val_len |= (*p++ << 16); |
val_len |= (*p++ << 8); |
val_len |= (*p++ << 8); |
val_len |= *p++; |
val_len |= *p++; |
} |
} |
if (name_len + val_len > end - p) { | if (UNEXPECTED(name_len + val_len > (unsigned int) (end - p))) { |
/* Malformated request */ |
/* Malformated request */ |
ret = 0; | return 0; |
break; | |
} |
} |
if (name_len+1 >= buf_size) { | fcgi_hash_set(&req->env, FCGI_HASH_FUNC(p, name_len), (char*)p, name_len, (char*)p + name_len, val_len); |
buf_size = name_len + 64; | |
tmp = (tmp == buf ? emalloc(buf_size): erealloc(tmp, buf_size)); | |
} | |
memcpy(tmp, p, name_len); | |
tmp[name_len] = 0; | |
s = estrndup((char*)p + name_len, val_len); | |
zend_hash_update(req->env, tmp, name_len+1, &s, sizeof(char*), NULL); | |
p += name_len + val_len; |
p += name_len + val_len; |
} |
} |
if (tmp != buf && tmp != NULL) { | return 1; |
efree(tmp); | |
} | |
return ret; | |
} |
} |
|
|
static void fcgi_free_var(char **s) |
|
{ |
|
efree(*s); |
|
} |
|
|
|
static int fcgi_read_request(fcgi_request *req) |
static int fcgi_read_request(fcgi_request *req) |
{ |
{ |
fcgi_header hdr; |
fcgi_header hdr; |
Line 674 static int fcgi_read_request(fcgi_request *req)
|
Line 882 static int fcgi_read_request(fcgi_request *req)
|
req->in_len = 0; |
req->in_len = 0; |
req->out_hdr = NULL; |
req->out_hdr = NULL; |
req->out_pos = req->out_buf; |
req->out_pos = req->out_buf; |
ALLOC_HASHTABLE(req->env); | req->has_env = 1; |
zend_hash_init(req->env, 0, NULL, (void (*)(void *)) fcgi_free_var, 0); | |
|
|
if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || |
if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || |
hdr.version < FCGI_VERSION_1) { |
hdr.version < FCGI_VERSION_1) { |
Line 702 static int fcgi_read_request(fcgi_request *req)
|
Line 909 static int fcgi_read_request(fcgi_request *req)
|
req->id = (hdr.requestIdB1 << 8) + hdr.requestIdB0; |
req->id = (hdr.requestIdB1 << 8) + hdr.requestIdB0; |
|
|
if (hdr.type == FCGI_BEGIN_REQUEST && len == sizeof(fcgi_begin_request)) { |
if (hdr.type == FCGI_BEGIN_REQUEST && len == sizeof(fcgi_begin_request)) { |
char *val; |
|
|
|
if (safe_read(req, buf, len+padding) != len+padding) { |
if (safe_read(req, buf, len+padding) != len+padding) { |
return 0; |
return 0; |
} |
} |
|
|
req->keep = (((fcgi_begin_request*)buf)->flags & FCGI_KEEP_CONN); |
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) { |
switch ((((fcgi_begin_request*)buf)->roleB1 << 8) + ((fcgi_begin_request*)buf)->roleB0) { |
case FCGI_RESPONDER: |
case FCGI_RESPONDER: |
val = estrdup("RESPONDER"); | fcgi_hash_set(&req->env, FCGI_HASH_FUNC("FCGI_ROLE", sizeof("FCGI_ROLE")-1), "FCGI_ROLE", sizeof("FCGI_ROLE")-1, "RESPONDER", sizeof("RESPONDER")-1); |
zend_hash_update(req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL); | |
break; |
break; |
case FCGI_AUTHORIZER: |
case FCGI_AUTHORIZER: |
val = estrdup("AUTHORIZER"); | fcgi_hash_set(&req->env, FCGI_HASH_FUNC("FCGI_ROLE", sizeof("FCGI_ROLE")-1), "FCGI_ROLE", sizeof("FCGI_ROLE")-1, "AUTHORIZER", sizeof("AUTHORIZER")-1); |
zend_hash_update(req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL); | |
break; |
break; |
case FCGI_FILTER: |
case FCGI_FILTER: |
val = estrdup("FILTER"); | fcgi_hash_set(&req->env, FCGI_HASH_FUNC("FCGI_ROLE", sizeof("FCGI_ROLE")-1), "FCGI_ROLE", sizeof("FCGI_ROLE")-1, "FILTER", sizeof("FILTER")-1); |
zend_hash_update(req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL); | |
break; |
break; |
default: |
default: |
return 0; |
return 0; |
Line 759 static int fcgi_read_request(fcgi_request *req)
|
Line 973 static int fcgi_read_request(fcgi_request *req)
|
} |
} |
} else if (hdr.type == FCGI_GET_VALUES) { |
} else if (hdr.type == FCGI_GET_VALUES) { |
unsigned char *p = buf + sizeof(fcgi_header); |
unsigned char *p = buf + sizeof(fcgi_header); |
HashPosition pos; |
|
char * str_index; |
|
uint str_length; |
|
ulong num_index; |
|
int key_type; |
|
zval ** value; |
zval ** value; |
|
unsigned int zlen; |
|
fcgi_hash_bucket *q; |
|
|
if (safe_read(req, buf, len+padding) != len+padding) { |
if (safe_read(req, buf, len+padding) != len+padding) { |
req->keep = 0; |
req->keep = 0; |
Line 776 static int fcgi_read_request(fcgi_request *req)
|
Line 987 static int fcgi_read_request(fcgi_request *req)
|
return 0; |
return 0; |
} |
} |
|
|
zend_hash_internal_pointer_reset_ex(req->env, &pos); | q = req->env.list; |
while ((key_type = zend_hash_get_current_key_ex(req->env, &str_index, &str_length, &num_index, 0, &pos)) != HASH_KEY_NON_EXISTANT) { | while (q != NULL) { |
int zlen; | if (zend_hash_find(&fcgi_mgmt_vars, q->var, q->var_len, (void**) &value) != SUCCESS) { |
zend_hash_move_forward_ex(req->env, &pos); | |
if (key_type != HASH_KEY_IS_STRING) { | |
continue; |
continue; |
} |
} |
if (zend_hash_find(&fcgi_mgmt_vars, str_index, str_length, (void**) &value) != SUCCESS) { |
|
continue; |
|
} |
|
--str_length; |
|
zlen = Z_STRLEN_PP(value); |
zlen = Z_STRLEN_PP(value); |
if ((p + 4 + 4 + str_length + zlen) >= (buf + sizeof(buf))) { | if ((p + 4 + 4 + q->var_len + zlen) >= (buf + sizeof(buf))) { |
break; |
break; |
} |
} |
if (str_length < 0x80) { | if (q->var_len < 0x80) { |
*p++ = str_length; | *p++ = q->var_len; |
} else { |
} else { |
*p++ = ((str_length >> 24) & 0xff) | 0x80; | *p++ = ((q->var_len >> 24) & 0xff) | 0x80; |
*p++ = (str_length >> 16) & 0xff; | *p++ = (q->var_len >> 16) & 0xff; |
*p++ = (str_length >> 8) & 0xff; | *p++ = (q->var_len >> 8) & 0xff; |
*p++ = str_length & 0xff; | *p++ = q->var_len & 0xff; |
} |
} |
if (zlen < 0x80) { |
if (zlen < 0x80) { |
*p++ = zlen; |
*p++ = zlen; |
Line 807 static int fcgi_read_request(fcgi_request *req)
|
Line 1012 static int fcgi_read_request(fcgi_request *req)
|
*p++ = (zlen >> 8) & 0xff; |
*p++ = (zlen >> 8) & 0xff; |
*p++ = zlen & 0xff; |
*p++ = zlen & 0xff; |
} |
} |
memcpy(p, str_index, str_length); | memcpy(p, q->var, q->var_len); |
p += str_length; | p += q->var_len; |
memcpy(p, Z_STRVAL_PP(value), zlen); |
memcpy(p, Z_STRVAL_PP(value), zlen); |
p += zlen; |
p += zlen; |
} |
} |
Line 881 int fcgi_read(fcgi_request *req, char *str, int len)
|
Line 1086 int fcgi_read(fcgi_request *req, char *str, int len)
|
|
|
static inline void fcgi_close(fcgi_request *req, int force, int destroy) |
static inline void fcgi_close(fcgi_request *req, int force, int destroy) |
{ |
{ |
if (destroy && req->env) { | if (destroy && req->has_env) { |
zend_hash_destroy(req->env); | fcgi_hash_clean(&req->env); |
FREE_HASHTABLE(req->env); | req->has_env = 0; |
req->env = NULL; | |
} |
} |
|
|
#ifdef _WIN32 |
#ifdef _WIN32 |
Line 904 static inline void fcgi_close(fcgi_request *req, int f
|
Line 1108 static inline void fcgi_close(fcgi_request *req, int f
|
DisconnectNamedPipe(pipe); |
DisconnectNamedPipe(pipe); |
} else { |
} else { |
if (!force) { |
if (!force) { |
char buf[8]; | fcgi_header buf; |
|
|
shutdown(req->fd, 1); |
shutdown(req->fd, 1); |
while (recv(req->fd, buf, sizeof(buf), 0) > 0) {} | /* read the last FCGI_STDIN header (it may be omitted) */ |
| recv(req->fd, &buf, sizeof(buf), 0); |
} |
} |
closesocket(req->fd); |
closesocket(req->fd); |
} |
} |
#else |
#else |
if (!force) { |
if (!force) { |
char buf[8]; | fcgi_header buf; |
|
|
shutdown(req->fd, 1); |
shutdown(req->fd, 1); |
while (recv(req->fd, buf, sizeof(buf), 0) > 0) {} | /* read the last FCGI_STDIN header (it may be omitted) */ |
| recv(req->fd, &buf, sizeof(buf), 0); |
} |
} |
close(req->fd); |
close(req->fd); |
#endif |
#endif |
|
#ifdef TCP_NODELAY |
|
req->nodelay = 0; |
|
#endif |
req->fd = -1; |
req->fd = -1; |
} |
} |
} |
} |
Line 970 int fcgi_accept_request(fcgi_request *req)
|
Line 1179 int fcgi_accept_request(fcgi_request *req)
|
FCGI_LOCK(req->listen_socket); |
FCGI_LOCK(req->listen_socket); |
req->fd = accept(listen_socket, (struct sockaddr *)&sa, &len); |
req->fd = accept(listen_socket, (struct sockaddr *)&sa, &len); |
FCGI_UNLOCK(req->listen_socket); |
FCGI_UNLOCK(req->listen_socket); |
if (req->fd >= 0 && allowed_clients) { | if (req->fd >= 0) { |
int n = 0; | if (((struct sockaddr *)&sa)->sa_family == AF_INET) { |
int allowed = 0; | #ifndef _WIN32 |
| req->tcp = 1; |
| #endif |
| if (allowed_clients) { |
| int n = 0; |
| int allowed = 0; |
|
|
while (allowed_clients[n] != INADDR_NONE) { | while (allowed_clients[n] != INADDR_NONE) { |
if (allowed_clients[n] == sa.sa_inet.sin_addr.s_addr) { | if (allowed_clients[n] == sa.sa_inet.sin_addr.s_addr) { |
allowed = 1; | allowed = 1; |
break; | break; |
| } |
| n++; |
} |
} |
n++; | if (!allowed) { |
| fprintf(stderr, "Connection from disallowed IP address '%s' is dropped.\n", inet_ntoa(sa.sa_inet.sin_addr)); |
| closesocket(req->fd); |
| req->fd = -1; |
| continue; |
| } |
} |
} |
if (!allowed) { | #ifndef _WIN32 |
fprintf(stderr, "Connection from disallowed IP address '%s' is dropped.\n", inet_ntoa(sa.sa_inet.sin_addr)); | } else { |
closesocket(req->fd); | req->tcp = 0; |
req->fd = -1; | #endif |
continue; | |
} |
} |
} |
} |
} |
} |
Line 1195 int fcgi_write(fcgi_request *req, fcgi_request_type ty
|
Line 1415 int fcgi_write(fcgi_request *req, fcgi_request_type ty
|
return -1; |
return -1; |
} |
} |
pos += 0xfff8; |
pos += 0xfff8; |
} | } |
| |
pad = (((len - pos) + 7) & ~7) - (len - pos); |
pad = (((len - pos) + 7) & ~7) - (len - pos); |
rest = pad ? 8 - pad : 0; |
rest = pad ? 8 - pad : 0; |
|
|
Line 1236 int fcgi_finish_request(fcgi_request *req, int force_c
|
Line 1456 int fcgi_finish_request(fcgi_request *req, int force_c
|
|
|
char* fcgi_getenv(fcgi_request *req, const char* var, int var_len) |
char* fcgi_getenv(fcgi_request *req, const char* var, int var_len) |
{ |
{ |
char **val; | unsigned int val_len; |
|
|
if (!req) return NULL; |
if (!req) return NULL; |
|
|
if (zend_hash_find(req->env, (char*)var, var_len+1, (void**)&val) == SUCCESS) { | return fcgi_hash_get(&req->env, FCGI_HASH_FUNC(var, var_len), (char*)var, var_len, &val_len); |
return *val; | |
} | |
return NULL; | |
} |
} |
|
|
|
char* fcgi_quick_getenv(fcgi_request *req, const char* var, int var_len, unsigned int hash_value) |
|
{ |
|
unsigned int val_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) |
char* fcgi_putenv(fcgi_request *req, char* var, int var_len, char* val) |
{ |
{ |
if (var && req) { | if (!req) return NULL; |
if (val == NULL) { | if (val == NULL) { |
zend_hash_del(req->env, var, var_len+1); | fcgi_hash_del(&req->env, FCGI_HASH_FUNC(var, var_len), var, var_len); |
} else { | return NULL; |
char **ret; | } else { |
| return fcgi_hash_set(&req->env, FCGI_HASH_FUNC(var, var_len), var, var_len, val, strlen(val)); |
| } |
| } |
|
|
val = estrdup(val); | char* fcgi_quick_putenv(fcgi_request *req, char* var, int var_len, unsigned int hash_value, char* val) |
if (zend_hash_update(req->env, var, var_len+1, &val, sizeof(char*), (void**)&ret) == SUCCESS) { | { |
return *ret; | 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, strlen(val)); |
} |
} |
return NULL; |
|
} |
} |
|
|
|
void fcgi_loadenv(fcgi_request *req, fcgi_apply_func func, zval *array TSRMLS_DC) |
|
{ |
|
fcgi_hash_apply(&req->env, func, array TSRMLS_CC); |
|
} |
|
|
#ifdef _WIN32 |
#ifdef _WIN32 |
void fcgi_impersonate(void) |
void fcgi_impersonate(void) |
{ |
{ |
Line 1282 void fcgi_set_mgmt_var(const char * name, size_t name_
|
Line 1515 void fcgi_set_mgmt_var(const char * name, size_t name_
|
Z_TYPE_P(zvalue) = IS_STRING; |
Z_TYPE_P(zvalue) = IS_STRING; |
Z_STRVAL_P(zvalue) = pestrndup(value, value_len, 1); |
Z_STRVAL_P(zvalue) = pestrndup(value, value_len, 1); |
Z_STRLEN_P(zvalue) = value_len; |
Z_STRLEN_P(zvalue) = value_len; |
zend_hash_add(&fcgi_mgmt_vars, name, name_len + 1, &zvalue, sizeof(zvalue), NULL); | zend_hash_add(&fcgi_mgmt_vars, name, name_len, &zvalue, sizeof(zvalue), NULL); |
} |
} |
|
|
void fcgi_free_mgmt_var_cb(void * ptr) |
void fcgi_free_mgmt_var_cb(void * ptr) |