summaryrefslogtreecommitdiff
path: root/sapi/cgi/fastcgi.c
diff options
context:
space:
mode:
Diffstat (limited to 'sapi/cgi/fastcgi.c')
-rw-r--r--sapi/cgi/fastcgi.c519
1 files changed, 376 insertions, 143 deletions
diff --git a/sapi/cgi/fastcgi.c b/sapi/cgi/fastcgi.c
index 4d0791871b..c9c8da9ab8 100644
--- a/sapi/cgi/fastcgi.c
+++ b/sapi/cgi/fastcgi.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2013 The PHP Group |
+ | Copyright (c) 1997-2012 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 |
@@ -67,6 +67,7 @@
# include <sys/socket.h>
# include <sys/un.h>
# include <netinet/in.h>
+# include <netinet/tcp.h>
# include <arpa/inet.h>
# include <netdb.h>
# include <signal.h>
@@ -140,6 +141,224 @@ static int is_fastcgi = 0;
static int in_shutdown = 0;
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
static DWORD WINAPI fcgi_shutdown_thread(LPVOID arg)
@@ -180,6 +399,11 @@ int fcgi_in_shutdown(void)
return in_shutdown;
}
+void fcgi_terminate(void)
+{
+ in_shutdown = 1;
+}
+
int fcgi_init(void)
{
if (!is_initialized) {
@@ -417,7 +641,7 @@ int fcgi_listen(const char *path, int backlog)
8192, 8192, 0, &saw);
if (namedPipe == INVALID_HANDLE_VALUE) {
return -1;
- }
+ }
listen_socket = _open_osfhandle((long)namedPipe, 0);
if (!is_initialized) {
fcgi_init();
@@ -459,35 +683,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++;
+ 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 = 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) {
+ 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);
}
}
@@ -507,9 +731,9 @@ int fcgi_listen(const char *path, int backlog)
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->fd = -1;
req->id = -1;
@@ -523,6 +747,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)
@@ -603,64 +841,34 @@ static inline int fcgi_make_header(fcgi_header *hdr, fcgi_request_type type, int
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;
- char *s;
- int ret = 1;
while (p < end) {
name_len = *p++;
- if (name_len >= 128) {
- if (p + 3 >= end) {
- ret = 0;
- break;
- }
+ 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++;
}
- if (p >= end) {
- ret = 0;
- break;
- }
+ if (UNEXPECTED(p >= end)) return 0;
val_len = *p++;
- if (val_len >= 128) {
- if (p + 3 >= end) {
- ret = 0;
- break;
- }
+ 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++;
}
- if (name_len + val_len > end - p) {
+ if (UNEXPECTED(name_len + val_len > (unsigned int) (end - p))) {
/* Malformated request */
- ret = 0;
- break;
- }
- if (name_len+1 >= buf_size) {
- buf_size = name_len + 64;
- tmp = (tmp == buf ? emalloc(buf_size): erealloc(tmp, buf_size));
+ return 0;
}
- 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);
+ 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;
-}
-
-static void fcgi_free_var(char **s)
-{
- efree(*s);
+ return 1;
}
static int fcgi_read_request(fcgi_request *req)
@@ -674,8 +882,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, (void (*)(void *)) fcgi_free_var, 0);
+ req->has_env = 1;
if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) ||
hdr.version < FCGI_VERSION_1) {
@@ -702,25 +909,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_update(req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL);
+ 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_update(req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL);
+ 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_update(req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL);
+ 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;
@@ -759,12 +973,9 @@ static int fcgi_read_request(fcgi_request *req)
}
} else if (hdr.type == FCGI_GET_VALUES) {
unsigned char *p = buf + sizeof(fcgi_header);
- HashPosition pos;
- char * str_index;
- uint str_length;
- ulong num_index;
- int key_type;
zval ** value;
+ unsigned int zlen;
+ fcgi_hash_bucket *q;
if (safe_read(req, buf, len+padding) != len+padding) {
req->keep = 0;
@@ -776,28 +987,22 @@ static int fcgi_read_request(fcgi_request *req)
return 0;
}
- 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) {
+ q = req->env.list;
+ while (q != NULL) {
+ if (zend_hash_find(&fcgi_mgmt_vars, q->var, q->var_len, (void**) &value) != SUCCESS) {
continue;
}
- --str_length;
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;
}
- if (str_length < 0x80) {
- *p++ = str_length;
+ if (q->var_len < 0x80) {
+ *p++ = q->var_len;
} else {
- *p++ = ((str_length >> 24) & 0xff) | 0x80;
- *p++ = (str_length >> 16) & 0xff;
- *p++ = (str_length >> 8) & 0xff;
- *p++ = str_length & 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;
@@ -807,8 +1012,8 @@ static int fcgi_read_request(fcgi_request *req)
*p++ = (zlen >> 8) & 0xff;
*p++ = zlen & 0xff;
}
- memcpy(p, str_index, str_length);
- p += str_length;
+ memcpy(p, q->var, q->var_len);
+ p += q->var_len;
memcpy(p, Z_STRVAL_PP(value), zlen);
p += zlen;
}
@@ -881,10 +1086,9 @@ int fcgi_read(fcgi_request *req, char *str, int len)
static inline 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
@@ -904,22 +1108,27 @@ static inline void fcgi_close(fcgi_request *req, int force, int destroy)
DisconnectNamedPipe(pipe);
} else {
if (!force) {
- char buf[8];
+ fcgi_header buf;
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);
}
#else
if (!force) {
- char buf[8];
+ fcgi_header buf;
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);
#endif
+#ifdef TCP_NODELAY
+ req->nodelay = 0;
+#endif
req->fd = -1;
}
}
@@ -970,22 +1179,33 @@ int fcgi_accept_request(fcgi_request *req)
FCGI_LOCK(req->listen_socket);
req->fd = accept(listen_socket, (struct sockaddr *)&sa, &len);
FCGI_UNLOCK(req->listen_socket);
- if (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;
+ if (req->fd >= 0) {
+ if (((struct sockaddr *)&sa)->sa_family == AF_INET) {
+#ifndef _WIN32
+ req->tcp = 1;
+#endif
+ if (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) {
+ 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;
}
- 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;
+#ifndef _WIN32
+ } else {
+ req->tcp = 0;
+#endif
}
}
}
@@ -1195,8 +1415,8 @@ int fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int l
return -1;
}
pos += 0xfff8;
- }
-
+ }
+
pad = (((len - pos) + 7) & ~7) - (len - pos);
rest = pad ? 8 - pad : 0;
@@ -1236,31 +1456,44 @@ int fcgi_finish_request(fcgi_request *req, int force_close)
char* fcgi_getenv(fcgi_request *req, const char* var, int var_len)
{
- char **val;
+ unsigned int val_len;
if (!req) return NULL;
- if (zend_hash_find(req->env, (char*)var, var_len+1, (void**)&val) == SUCCESS) {
- return *val;
- }
- 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 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_del(req->env, var, var_len+1);
- } else {
- char **ret;
+ 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, strlen(val));
+ }
+}
- val = estrdup(val);
- if (zend_hash_update(req->env, var, var_len+1, &val, sizeof(char*), (void**)&ret) == SUCCESS) {
- return *ret;
- }
- }
+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, 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
@@ -1282,7 +1515,7 @@ void fcgi_set_mgmt_var(const char * name, size_t name_len, const char * value, s
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);
+ zend_hash_add(&fcgi_mgmt_vars, name, name_len, &zvalue, sizeof(zvalue), NULL);
}
void fcgi_free_mgmt_var_cb(void * ptr)