diff options
Diffstat (limited to 'sapi/cgi/fastcgi.c')
| -rw-r--r-- | sapi/cgi/fastcgi.c | 202 |
1 files changed, 95 insertions, 107 deletions
diff --git a/sapi/cgi/fastcgi.c b/sapi/cgi/fastcgi.c index 807df718d..6f528109f 100644 --- a/sapi/cgi/fastcgi.c +++ b/sapi/cgi/fastcgi.c @@ -16,10 +16,10 @@ +----------------------------------------------------------------------+ */ -/* $Id: fastcgi.c,v 1.4.2.18 2006/08/20 17:49:05 sas Exp $ */ +/* $Id: fastcgi.c,v 1.4.2.13.2.11 2006/10/16 10:46:59 dmitry Exp $ */ -#include "fastcgi.h" #include "php.h" +#include "fastcgi.h" #include <string.h> #include <stdlib.h> @@ -125,14 +125,15 @@ typedef union _sa_t { } sa_t; typedef struct _fcgi_mgmt_rec { - char* name; - char val; + char* name; + size_t name_len; + char val; } fcgi_mgmt_rec; static const fcgi_mgmt_rec fcgi_mgmt_vars[] = { - {"FCGI_MAX_CONNS", 1}, - {"FCGI_MAX_REQS", 1}, - {"FCGI_MPXS_CONNS", 0} + {"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} }; @@ -140,13 +141,6 @@ static int is_initialized = 0; static int is_fastcgi = 0; static int in_shutdown = 0; -static inline char* fcgi_strndup(const char *str, int len) -{ - char *s = malloc(len+1); - memcpy(s, str, len+1); - return s; -} - #ifdef _WIN32 static DWORD WINAPI fcgi_shutdown_thread(LPVOID arg) @@ -396,12 +390,16 @@ static inline int fcgi_make_header(fcgi_header *hdr, fcgi_request_type type, int return pad; } -static int fcgi_get_params(fcgi_request *req, unsigned char *p, unsigned char *end, int n) +static int fcgi_get_params(fcgi_request *req, unsigned char *p, unsigned char *end) { + char buf[128]; + char *tmp = buf; + int buf_size = sizeof(buf); int name_len, val_len; char *s; + int ret = 1; - while (p < end && n < FCGI_MAX_ENV_VARS - 1) { + while (p < end) { name_len = *p++; if (name_len >= 128) { name_len = ((name_len & 0x7f) << 24); @@ -416,31 +414,43 @@ static int fcgi_get_params(fcgi_request *req, unsigned char *p, unsigned char *e val_len |= (*p++ << 8); val_len |= *p++; } - req->env[n] = s = malloc(name_len + val_len + 2); - memcpy(s, p, name_len); - p += name_len; - s[name_len] = '='; - memcpy(s+name_len+1, p, val_len); - p += val_len; - s[name_len+1+val_len] = '\0'; - n++; + if (p + name_len + val_len > end) { + /* 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)); + } + memcpy(tmp, p, name_len); + tmp[name_len] = 0; + s = zend_strndup((char*)p + name_len, val_len); + zend_hash_update(&req->env, tmp, name_len+1, &s, sizeof(char*), NULL); + p += name_len + val_len; } - return n; + if (tmp != buf && tmp != NULL) { + efree(tmp); + } + return ret; +} + +static void fcgi_free_var(char **s) +{ + free(*s); } static int fcgi_read_request(fcgi_request *req) { fcgi_header hdr; int len, padding; - int n = 1; - char *s; unsigned char buf[FCGI_MAX_LENGTH+8]; req->keep = 0; req->in_len = 0; req->out_hdr = NULL; req->out_pos = req->out_buf; - memset(req->env, 0, sizeof(req->env)); + zend_hash_init(&req->env, 0, NULL, (void (*)(void *)) fcgi_free_var, 1); if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || hdr.version < FCGI_VERSION_1) { @@ -463,6 +473,8 @@ 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; } @@ -470,13 +482,16 @@ static int fcgi_read_request(fcgi_request *req) req->keep = (((fcgi_begin_request*)buf)->flags & FCGI_KEEP_CONN); switch ((((fcgi_begin_request*)buf)->roleB1 << 8) + ((fcgi_begin_request*)buf)->roleB0) { case FCGI_RESPONDER: - req->env[0] = fcgi_strndup("FCGI_ROLE=RESPONDER", sizeof("FCGI_ROLE=RESPONDER")-1); + val = strdup("RESPONDER"); + zend_hash_update(&req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL); break; case FCGI_AUTHORIZER: - req->env[0] = fcgi_strndup("FCGI_ROLE=AUTHORIZER", sizeof("FCGI_ROLE=AUTHORIZER")-1); + val = strdup("AUTHORIZER"); + zend_hash_update(&req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL); break; case FCGI_FILTER: - req->env[0] = fcgi_strndup("FCGI_ROLE=FILTER", sizeof("FCGI_ROLE=FILTER")-1); + val = strdup("FILTER"); + zend_hash_update(&req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL); break; default: return 0; @@ -495,7 +510,11 @@ static int fcgi_read_request(fcgi_request *req) req->keep = 0; return 0; } - n = fcgi_get_params(req, buf, buf+len, n); + + if (!fcgi_get_params(req, buf, buf+len)) { + req->keep = 0; + return 0; + } if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || hdr.version < FCGI_VERSION_1) { @@ -506,31 +525,29 @@ static int fcgi_read_request(fcgi_request *req) padding = hdr.paddingLength; } } else if (hdr.type == FCGI_GET_VALUES) { - int i, j; - int name_len; + int j; unsigned char *p = buf + sizeof(fcgi_header); if (safe_read(req, buf, len+padding) != len+padding) { + req->keep = 0; return 0; } - n = fcgi_get_params(req, buf, buf+len, 0); - for (i = 0; i < n; i++) { - if ((s = strchr(req->env[i], '=')) != NULL) { - *s = '\0'; - name_len = s - req->env[i]; - } else { - name_len = strlen(req->env[i]); - } - for (j = 0; j < sizeof(fcgi_mgmt_vars)/sizeof(fcgi_mgmt_vars[0]); j++) { - if (strncmp(req->env[i], fcgi_mgmt_vars[j].name, name_len) == 0) { - sprintf((char*)p, "%c%c%s%c", name_len, 1, fcgi_mgmt_vars[j].name, fcgi_mgmt_vars[j].val); - p += name_len+3; - } + + if (!fcgi_get_params(req, buf, buf+len)) { + req->keep = 0; + 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; } } 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) { + req->keep = 0; return 0; } return 0; @@ -597,10 +614,7 @@ int fcgi_read(fcgi_request *req, char *str, int len) static inline void fcgi_close(fcgi_request *req, int force, int destroy) { if (destroy) { - char **env = req->env; - while (*env) { - free(*env++); - } + zend_hash_destroy(&req->env); } if ((force || !req->keep) && req->fd >= 0) { #ifdef _WIN32 @@ -614,10 +628,12 @@ static inline void fcgi_close(fcgi_request *req, int force, int destroy) RevertToSelf(); } #else - char buf[8]; + if (!force) { + char buf[8]; - shutdown(req->fd, 1); - while (recv(req->fd, buf, sizeof(buf), 0) > 0) {} + shutdown(req->fd, 1); + while (recv(req->fd, buf, sizeof(buf), 0) > 0) {} + } close(req->fd); #endif req->fd = -1; @@ -666,12 +682,12 @@ int fcgi_accept_request(fcgi_request *req) FCGI_UNLOCK(req->listen_socket); #else { - sa_t sa; - socklen_t len = sizeof(sa); + sa_t sa; + socklen_t len = sizeof(sa); - FCGI_LOCK(req->listen_socket); - req->fd = accept(req->listen_socket, (struct sockaddr *)&sa, &len); - FCGI_UNLOCK(req->listen_socket); + FCGI_LOCK(req->listen_socket); + req->fd = accept(req->listen_socket, (struct sockaddr *)&sa, &len); + FCGI_UNLOCK(req->listen_socket); } #endif @@ -683,7 +699,7 @@ int fcgi_accept_request(fcgi_request *req) break; #else if (req->fd >= 0) { - struct timeval tv = {1,0}; + struct timeval tv = {5,0}; fd_set set; FD_ZERO(&set); @@ -722,7 +738,7 @@ static inline void close_packet(fcgi_request *req) if (req->out_hdr) { int len = req->out_pos - ((unsigned char*)req->out_hdr + sizeof(fcgi_header)); - req->out_pos += fcgi_make_header(req->out_hdr, req->out_hdr->type, req->id, len); + req->out_pos += fcgi_make_header(req->out_hdr, (fcgi_request_type)req->out_hdr->type, req->id, len); req->out_hdr = NULL; } } @@ -777,7 +793,7 @@ int fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int l if (limit < sizeof(fcgi_header)) { if (!fcgi_flush(req, 0)) { return -1; - } + } } open_packet(req, type); } @@ -877,64 +893,36 @@ int fcgi_finish_request(fcgi_request *req) return 1; } -char* fcgi_getenv_helper(char** env, const char *name, int len) -{ - if (name && env) { - while (*env) { - if ((strncmp(name, *env, len) == 0) && ((*env)[len] == '=')) { - return *env+len+1; - } - env++; - } - } - return NULL; -} - char* fcgi_getenv(fcgi_request *req, const char* var, int var_len) { + char **val; + if (!req) return NULL; - return fcgi_getenv_helper(req->env, var, var_len); + + if (zend_hash_find(&req->env, (char*)var, var_len+1, (void**)&val) == SUCCESS) { + return *val; + } + return NULL; } -void fcgi_putenv(fcgi_request *req, char* var, int var_len) +char* fcgi_putenv(fcgi_request *req, char* var, int var_len, char* val) { if (var && req) { - char **env = req->env; - char *s = strchr(var, '='); - int len; - - if (!s) return ; - len = s - var + 1; - while (*env) { - if ((strncmp(var, *env, len) == 0)) { - free(*env); - *env = fcgi_strndup(var, var_len); - return; - } - env++; + char **ret; + + if (val == NULL) { + val = ""; } - if (env != &req->env[FCGI_MAX_ENV_VARS - 1]) { - *env = fcgi_strndup(var, var_len); + val = strdup(val); + if (zend_hash_update(&req->env, var, var_len+1, &val, sizeof(char*), (void**)&ret) == SUCCESS) { + return *ret; } } -} - -int FCGX_FPrintF(FCGX_Stream stream, const char *format, ...) -{ - int result; - va_list args; - char buf[4096]; - - va_start(args, format); - result = vsnprintf(buf, sizeof(buf), format, args); - va_end(args); - - fcgi_write(stream.req, stream.type, buf, result); - return result; + return NULL; } #ifdef _WIN32 -void OS_SetImpersonate(void) +void fcgi_impersonate(void) { char *os_name; |
