#define STDOUT_FILENO 1
#endif
-static inline size_t sapi_cgibin_single_write(const char *str, uint str_length TSRMLS_DC)
+static inline size_t sapi_cgi_single_write(const char *str, uint str_length TSRMLS_DC)
{
#ifdef PHP_WRITE_STDOUT
long ret;
-#else
- size_t ret;
-#endif
-
- if (fcgi_is_fastcgi()) {
- fcgi_request *request = (fcgi_request*) SG(server_context);
- long ret = fcgi_write(request, FCGI_STDOUT, str, str_length);
- if (ret <= 0) {
- return 0;
- }
- return ret;
- }
-#ifdef PHP_WRITE_STDOUT
ret = write(STDOUT_FILENO, str, str_length);
if (ret <= 0) return 0;
return ret;
#else
+ size_t ret;
+
ret = fwrite(str, 1, MIN(str_length, 16384), stdout);
return ret;
#endif
}
-static int sapi_cgibin_ub_write(const char *str, uint str_length TSRMLS_DC)
+static int sapi_cgi_ub_write(const char *str, uint str_length TSRMLS_DC)
{
const char *ptr = str;
uint remaining = str_length;
size_t ret;
while (remaining > 0) {
- ret = sapi_cgibin_single_write(ptr, remaining TSRMLS_CC);
+ ret = sapi_cgi_single_write(ptr, remaining TSRMLS_CC);
if (!ret) {
php_handle_aborted_connection();
return str_length - remaining;
return str_length;
}
+static int sapi_fcgi_ub_write(const char *str, uint str_length TSRMLS_DC)
+{
+ const char *ptr = str;
+ uint remaining = str_length;
+ fcgi_request *request = (fcgi_request*) SG(server_context);
+
+ while (remaining > 0) {
+ long ret = fcgi_write(request, FCGI_STDOUT, ptr, remaining);
+
+ if (ret <= 0) {
+ php_handle_aborted_connection();
+ return str_length - remaining;
+ }
+ ptr += ret;
+ remaining -= ret;
+ }
+
+ return str_length;
+}
+
+static void sapi_cgi_flush(void *server_context)
+{
+ if (fflush(stdout) == EOF) {
+ php_handle_aborted_connection();
+ }
+}
-static void sapi_cgibin_flush(void *server_context)
+static void sapi_fcgi_flush(void *server_context)
{
- if (fcgi_is_fastcgi()) {
- fcgi_request *request = (fcgi_request*) server_context;
- if (
+ fcgi_request *request = (fcgi_request*) server_context;
+
+ if (
#ifndef PHP_WIN32
!parent &&
#endif
request && !fcgi_flush(request, 0)) {
- php_handle_aborted_connection();
- }
- return;
- }
- if (fflush(stdout) == EOF) {
+
php_handle_aborted_connection();
}
}
count_bytes = MIN(count_bytes, (uint) SG(request_info).content_length - SG(read_post_bytes));
while (read_bytes < count_bytes) {
- if (fcgi_is_fastcgi()) {
- fcgi_request *request = (fcgi_request*) SG(server_context);
- tmp_read_bytes = fcgi_read(request, buffer + read_bytes, count_bytes - read_bytes);
- } else {
- tmp_read_bytes = read(STDIN_FILENO, buffer + read_bytes, count_bytes - read_bytes);
+ tmp_read_bytes = read(STDIN_FILENO, buffer + read_bytes, count_bytes - read_bytes);
+ if (tmp_read_bytes <= 0) {
+ break;
}
+ read_bytes += tmp_read_bytes;
+ }
+ return read_bytes;
+}
+
+static int sapi_fcgi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
+{
+ uint read_bytes = 0;
+ int tmp_read_bytes;
+ fcgi_request *request = (fcgi_request*) SG(server_context);
+
+ count_bytes = MIN(count_bytes, (uint) SG(request_info).content_length - SG(read_post_bytes));
+ while (read_bytes < count_bytes) {
+ tmp_read_bytes = fcgi_read(request, buffer + read_bytes, count_bytes - read_bytes);
if (tmp_read_bytes <= 0) {
break;
}
return read_bytes;
}
-static char *sapi_cgibin_getenv(char *name, size_t name_len TSRMLS_DC)
+static char *sapi_cgi_getenv(char *name, size_t name_len TSRMLS_DC)
+{
+ return getenv(name);
+}
+
+static char *sapi_fcgi_getenv(char *name, size_t name_len TSRMLS_DC)
{
/* when php is started by mod_fastcgi, no regular environment
* is provided to PHP. It is always sent to PHP at the start
* of a request. So we have to do our own lookup to get env
* vars. This could probably be faster somehow. */
- if (fcgi_is_fastcgi()) {
- fcgi_request *request = (fcgi_request*) SG(server_context);
- return fcgi_getenv(request, name, name_len);
- }
+ fcgi_request *request = (fcgi_request*) SG(server_context);
+ char *ret = fcgi_getenv(request, name, name_len);
+
+ if (ret) return ret;
/* if cgi, or fastcgi and not found in fcgi env
check the regular environment */
return getenv(name);
}
-static char *_sapi_cgibin_putenv(char *name, char *value TSRMLS_DC)
+static char *_sapi_cgi_putenv(char *name, int name_len, char *value)
{
- int name_len;
#if !HAVE_SETENV || !HAVE_UNSETENV
int len;
char *buf;
#endif
- if (!name) {
- return NULL;
- }
- name_len = strlen(name);
-
- /* when php is started by mod_fastcgi, no regular environment
- * is provided to PHP. It is always sent to PHP at the start
- * of a request. So we have to do our own lookup to get env
- * vars. This could probably be faster somehow. */
- if (fcgi_is_fastcgi()) {
- fcgi_request *request = (fcgi_request*) SG(server_context);
- return fcgi_putenv(request, name, name_len, value);
- }
-
#if HAVE_SETENV
if (value) {
setenv(name, value, 1);
static char *sapi_cgi_read_cookies(TSRMLS_D)
{
- return sapi_cgibin_getenv((char *) "HTTP_COOKIE", sizeof("HTTP_COOKIE")-1 TSRMLS_CC);
+ return getenv("HTTP_COOKIE");
+}
+
+static char *sapi_fcgi_read_cookies(TSRMLS_D)
+{
+ 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 TSRMLS_DC)
}
}
-void cgi_php_import_environment_variables(zval *array_ptr TSRMLS_DC)
+static void cgi_php_import_environment_variables(zval *array_ptr TSRMLS_DC)
{
if (PG(http_globals)[TRACK_VARS_ENV] &&
array_ptr != PG(http_globals)[TRACK_VARS_ENV] &&
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 TSRMLS_CC);
- unsigned int path_info_len = path_info ? strlen(path_info) : 0;
+ char *path_info;
+ unsigned int path_info_len;
+ int free_php_self;
+ ALLOCA_FLAG(use_heap)
- php_self_len = script_name_len + path_info_len;
- php_self = emalloc(php_self_len + 1);
+ if (fcgi_is_fastcgi()) {
+ fcgi_request *request = (fcgi_request*) SG(server_context);
- if (script_name) {
- memcpy(php_self, script_name, script_name_len + 1);
+ path_info = FCGI_GETENV(request, "PATH_INFO");
+ } else {
+ path_info = getenv("PATH_INFO");
}
+
if (path_info) {
- memcpy(php_self + script_name_len, path_info, path_info_len + 1);
+ unsigned int path_info_len = strlen(path_info);
+
+ if (script_name) {
+ unsigned int script_name_len = strlen(script_name);
+
+ php_self_len = script_name_len + path_info_len;
+ php_self = do_alloca(php_self_len + 1, use_heap);
+ memcpy(php_self, script_name, script_name_len + 1);
+ memcpy(php_self + script_name_len, path_info, path_info_len + 1);
+ free_php_self = 1;
+ } else {
+ php_self = path_info;
+ free_php_self = 0;
+ }
+ } else if (script_name) {
+ php_self = script_name;
+ php_self_len = strlen(script_name);
+ free_php_self = 0;
+ } else {
+ php_self = "";
+ php_self_len = 0;
+ free_php_self = 0;
}
/* Build the special-case PHP_SELF variable for the CGI version */
if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, php_self_len, &php_self_len TSRMLS_CC)) {
php_register_variable_safe("PHP_SELF", php_self, php_self_len, track_vars_array TSRMLS_CC);
}
- efree(php_self);
+ if (free_php_self) {
+ free_alloca(php_self, use_heap);
+ }
} else {
php_self = SG(request_info).request_uri ? SG(request_info).request_uri : "";
php_self_len = strlen(php_self);
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 TSRMLS_CC);
+ if (fcgi_is_fastcgi()) {
+ fcgi_request *request = (fcgi_request*) SG(server_context);
+
+ server_name = FCGI_GETENV(request, "SERVER_NAME");
+ } else {
+ server_name = getenv("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);
/* 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 TSRMLS_CC);
+ if (fcgi_is_fastcgi()) {
+ fcgi_request *request = (fcgi_request*) SG(server_context);
+
+ doc_root = FCGI_GETENV(request, "DOCUMENT_ROOT");
+ } else {
+ doc_root = getenv("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);
php_handle_aborted_connection();
}
} else {
- sapi_cgibin_flush(SG(server_context));
+ sapi_cgi_flush(SG(server_context));
}
}
return SUCCESS;
sapi_cgi_activate, /* activate */
sapi_cgi_deactivate, /* deactivate */
- sapi_cgibin_ub_write, /* unbuffered write */
- sapi_cgibin_flush, /* flush */
+ sapi_cgi_ub_write, /* unbuffered write */
+ sapi_cgi_flush, /* flush */
NULL, /* get uid */
- sapi_cgibin_getenv, /* getenv */
+ sapi_cgi_getenv, /* getenv */
php_error, /* error handler */
*/
static int is_valid_path(const char *path)
{
- const char *p;
+ const char *p = path;
- if (!path) {
+ if (UNEXPECTED(!p)) {
return 0;
}
- p = strstr(path, "..");
- if (p) {
- if ((p == path || IS_SLASH(*(p-1))) &&
- (*(p+2) == 0 || IS_SLASH(*(p+2)))
- ) {
- return 0;
- }
- while (1) {
- p = strstr(p+1, "..");
- if (!p) {
- break;
- }
- if (IS_SLASH(*(p-1)) &&
- (*(p+2) == 0 || IS_SLASH(*(p+2)))
- ) {
- return 0;
+ if (UNEXPECTED(*p == '.') && *(p+1) == '.' && (!*(p+2) || IS_SLASH(*(p+2)))) {
+ return 0;
+ }
+ while (*p) {
+ if (IS_SLASH(*p)) {
+ p++;
+ if (UNEXPECTED(*p == '.')) {
+ p++;
+ if (UNEXPECTED(*p == '.')) {
+ p++;
+ if (UNEXPECTED(!*p) || UNEXPECTED(IS_SLASH(*p))) {
+ return 0;
+ }
+ }
}
}
+ p++;
}
return 1;
}
/* }}} */
+#define CGI_GETENV(name) \
+ ((request) ? \
+ FCGI_GETENV(request, name) : \
+ getenv(name))
+
+#define CGI_PUTENV(name, value) \
+ ((request) ? \
+ FCGI_PUTENV(request, name, value) : \
+ _sapi_cgi_putenv(name, sizeof(name)-1, value))
+
/* {{{ init_request_info
initializes request_info structure
Comments in the code below refer to using the above URL in a request
*/
-static void init_request_info(TSRMLS_D)
+static void init_request_info(fcgi_request *request TSRMLS_DC)
{
- char *env_script_filename = sapi_cgibin_getenv("SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME")-1 TSRMLS_CC);
- char *env_path_translated = sapi_cgibin_getenv("PATH_TRANSLATED", sizeof("PATH_TRANSLATED")-1 TSRMLS_CC);
+ char *env_script_filename = CGI_GETENV("SCRIPT_FILENAME");
+ char *env_path_translated = CGI_GETENV("PATH_TRANSLATED");
char *script_path_translated = env_script_filename;
/* some broken servers do not have script_filename or argv0
* 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 TSRMLS_CC);
- char *content_type = sapi_cgibin_getenv("CONTENT_TYPE", sizeof("CONTENT_TYPE")-1 TSRMLS_CC);
- char *env_path_info = sapi_cgibin_getenv("PATH_INFO", sizeof("PATH_INFO")-1 TSRMLS_CC);
- char *env_script_name = sapi_cgibin_getenv("SCRIPT_NAME", sizeof("SCRIPT_NAME")-1 TSRMLS_CC);
+ char *content_length = CGI_GETENV("CONTENT_LENGTH");
+ char *content_type = CGI_GETENV("CONTENT_TYPE");
+ char *env_path_info = CGI_GETENV("PATH_INFO");
+ char *env_script_name = CGI_GETENV("SCRIPT_NAME");
#ifdef PHP_WIN32
/* Hack for buggy IIS that sets incorrect PATH_INFO */
- char *env_server_software = sapi_cgibin_getenv("SERVER_SOFTWARE", sizeof("SERVER_SOFTWARE")-1 TSRMLS_CC);
+ char *env_server_software = CGI_GETENV("SERVER_SOFTWARE");
if (env_server_software &&
env_script_name &&
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 TSRMLS_CC);
+ env_path_info = CGI_PUTENV("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 TSRMLS_CC);
+ env_path_info = CGI_PUTENV("PATH_INFO", env_path_info);
}
#endif
if (CGIG(fix_pathinfo)) {
struct stat st;
char *real_path = NULL;
- char *env_redirect_url = sapi_cgibin_getenv("REDIRECT_URL", sizeof("REDIRECT_URL")-1 TSRMLS_CC);
- char *env_document_root = sapi_cgibin_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT")-1 TSRMLS_CC);
+ char *env_redirect_url = CGI_GETENV("REDIRECT_URL");
+ char *env_document_root = CGI_GETENV("DOCUMENT_ROOT");
char *orig_path_translated = env_path_translated;
char *orig_path_info = env_path_info;
char *orig_script_name = env_script_name;
int script_path_translated_len;
if (!env_document_root && PG(doc_root)) {
- env_document_root = _sapi_cgibin_putenv("DOCUMENT_ROOT", PG(doc_root) TSRMLS_CC);
+ env_document_root = CGI_PUTENV("DOCUMENT_ROOT", PG(doc_root));
/* fix docroot */
TRANSLATE_SLASHES(env_document_root);
}
if (orig_path_info) {
char old;
- _sapi_cgibin_putenv("ORIG_PATH_INFO", orig_path_info TSRMLS_CC);
+ CGI_PUTENV("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 TSRMLS_CC);
+ CGI_PUTENV("ORIG_SCRIPT_NAME", orig_script_name);
}
- SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_path_info TSRMLS_CC);
+ SG(request_info).request_uri = CGI_PUTENV("SCRIPT_NAME", env_path_info);
} else {
SG(request_info).request_uri = orig_script_name;
}
path_info[0] = old;
}
- env_path_info = _sapi_cgibin_putenv("PATH_INFO", path_info TSRMLS_CC);
+ env_path_info = CGI_PUTENV("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 TSRMLS_CC);
+ CGI_PUTENV("ORIG_SCRIPT_FILENAME", orig_script_filename);
}
- script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", pt TSRMLS_CC);
+ script_path_translated = CGI_PUTENV("SCRIPT_FILENAME", pt);
}
TRANSLATE_SLASHES(pt);
}
path_translated[path_translated_len] = '\0';
if (orig_path_translated) {
- _sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated TSRMLS_CC);
+ CGI_PUTENV("ORIG_PATH_TRANSLATED", orig_path_translated);
}
- env_path_translated = _sapi_cgibin_putenv("PATH_TRANSLATED", path_translated TSRMLS_CC);
+ env_path_translated = CGI_PUTENV("PATH_TRANSLATED", path_translated);
efree(path_translated);
} else if ( env_script_name &&
strstr(pt, env_script_name)
}
path_translated[path_translated_len] = '\0';
if (orig_path_translated) {
- _sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated TSRMLS_CC);
+ CGI_PUTENV("ORIG_PATH_TRANSLATED", orig_path_translated);
}
- env_path_translated = _sapi_cgibin_putenv("PATH_TRANSLATED", path_translated TSRMLS_CC);
+ env_path_translated = CGI_PUTENV("PATH_TRANSLATED", path_translated);
efree(path_translated);
}
break;
* have failed anyway... we output 'no input file' now.
*/
if (orig_script_filename) {
- _sapi_cgibin_putenv("ORIG_SCRIPT_FILENAME", orig_script_filename TSRMLS_CC);
+ CGI_PUTENV("ORIG_SCRIPT_FILENAME", orig_script_filename);
}
- script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", NULL TSRMLS_CC);
+ script_path_translated = CGI_PUTENV("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 TSRMLS_CC);
+ CGI_PUTENV("ORIG_SCRIPT_NAME", orig_script_name);
}
- SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_script_name TSRMLS_CC);
+ SG(request_info).request_uri = CGI_PUTENV("SCRIPT_NAME", env_script_name);
} else {
SG(request_info).request_uri = orig_script_name;
}
(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 TSRMLS_CC);
+ CGI_PUTENV("ORIG_SCRIPT_FILENAME", orig_script_filename);
}
- script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", script_path_translated TSRMLS_CC);
+ script_path_translated = CGI_PUTENV("SCRIPT_FILENAME", script_path_translated);
}
if (env_redirect_url) {
if (orig_path_info) {
- _sapi_cgibin_putenv("ORIG_PATH_INFO", orig_path_info TSRMLS_CC);
- _sapi_cgibin_putenv("PATH_INFO", NULL TSRMLS_CC);
+ CGI_PUTENV("ORIG_PATH_INFO", orig_path_info);
+ CGI_PUTENV("PATH_INFO", NULL);
}
if (orig_path_translated) {
- _sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated TSRMLS_CC);
- _sapi_cgibin_putenv("PATH_TRANSLATED", NULL TSRMLS_CC);
+ CGI_PUTENV("ORIG_PATH_TRANSLATED", orig_path_translated);
+ CGI_PUTENV("PATH_TRANSLATED", NULL);
}
}
if (env_script_name != orig_script_name) {
if (orig_script_name) {
- _sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name TSRMLS_CC);
+ CGI_PUTENV("ORIG_SCRIPT_NAME", orig_script_name);
}
- SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_script_name TSRMLS_CC);
+ SG(request_info).request_uri = CGI_PUTENV("SCRIPT_NAME", env_script_name);
} else {
SG(request_info).request_uri = env_script_name;
}
SG(request_info).path_translated = estrdup(script_path_translated);
}
- SG(request_info).request_method = sapi_cgibin_getenv("REQUEST_METHOD", sizeof("REQUEST_METHOD")-1 TSRMLS_CC);
+ SG(request_info).request_method = CGI_GETENV("REQUEST_METHOD");
/* FIXME - Work out proto_num here */
- SG(request_info).query_string = sapi_cgibin_getenv("QUERY_STRING", sizeof("QUERY_STRING")-1 TSRMLS_CC);
+ SG(request_info).query_string = CGI_GETENV("QUERY_STRING");
SG(request_info).content_type = (content_type ? content_type : "" );
SG(request_info).content_length = (content_length ? atoi(content_length) : 0);
/* The CGI RFC allows servers to pass on unvalidated Authorization data */
- auth = sapi_cgibin_getenv("HTTP_AUTHORIZATION", sizeof("HTTP_AUTHORIZATION")-1 TSRMLS_CC);
+ auth = CGI_GETENV("HTTP_AUTHORIZATION");
php_handle_auth_data(auth TSRMLS_CC);
}
}
fastcgi = fcgi_is_fastcgi();
}
if (fastcgi) {
+ /* Override SAPI callbacks */
+ sapi_module.ub_write = sapi_fcgi_ub_write;
+ sapi_module.flush = sapi_fcgi_flush;
+ sapi_module.read_post = sapi_fcgi_read_post;
+ sapi_module.getenv = sapi_fcgi_getenv;
+ sapi_module.read_cookies = sapi_fcgi_read_cookies;
+
/* How many times to run PHP scripts before dying */
if (getenv("PHP_FCGI_MAX_REQUESTS")) {
max_requests = atoi(getenv("PHP_FCGI_MAX_REQUESTS"));
#endif
while (!fastcgi || fcgi_accept_request(request) >= 0) {
SG(server_context) = fastcgi ? (void *) request : (void *) 1;
- init_request_info(TSRMLS_C);
+ init_request_info(request TSRMLS_CC);
CG(interactive) = 0;
if (!cgi && !fastcgi) {
/* hash table */
-#define FCGI_HASH_TABLE_SIZE 64
+#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 long hash_value;
+ unsigned int hash_value;
unsigned int var_len;
char *var;
unsigned int val_len;
fcgi_data_seg *data;
} fcgi_hash;
-static void fcgi_hash_init(fcgi_hash *h, unsigned int seg_size)
+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 + seg_size);
+ 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 + seg_size;
+ h->data->end = h->data->pos + FCGI_HASH_SEG_SIZE;
h->data->next = NULL;
}
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)) {
- fcgi_data_seg *p = (fcgi_data_seg*)malloc(sizeof(fcgi_data_seg) + str_len);
+ 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 + str_len + 1;
+ p->end = p->pos + seg_size;
p->next = h->data;
h->data = p;
}
- memcpy(h->data->pos, str, str_len);
- str = h->data->pos;
- h->data->pos[str_len] = 0;
+ ret = h->data->pos;
+ memcpy(ret, str, str_len);
+ ret[str_len] = 0;
h->data->pos += str_len + 1;
- return str;
+ return ret;
}
-static char* fcgi_hash_set(fcgi_hash *h, char *var, unsigned int var_len, char *val, unsigned int val_len)
+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 long hash_value = zend_inline_hash_func(var, 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 &&
+ while (UNEXPECTED(p != NULL)) {
+ if (UNEXPECTED(p->hash_value == hash_value) &&
p->var_len == var_len &&
memcmp(p->var, var, var_len) == 0) {
}
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);
- p->next = h->hash_table[idx];
- h->hash_table[idx] = p;
- p->list_next = h->list;
- h->list = p;
return p->val;
}
-static void fcgi_hash_del(fcgi_hash *h, char *var, unsigned int var_len)
+static void fcgi_hash_del(fcgi_hash *h, unsigned int hash_value, char *var, unsigned int var_len)
{
- unsigned long hash_value = zend_inline_hash_func(var, var_len);
unsigned int idx = hash_value & FCGI_HASH_TABLE_MASK;
fcgi_hash_bucket **p = &h->hash_table[idx];
}
}
-static char *fcgi_hash_get(fcgi_hash *h, char *var, unsigned int var_len, unsigned int *val_len)
+static char *fcgi_hash_get(fcgi_hash *h, unsigned int hash_value, char *var, unsigned int var_len, unsigned int *val_len)
{
- unsigned long hash_value = zend_inline_hash_func(var, var_len);
unsigned int idx = hash_value & FCGI_HASH_TABLE_MASK;
fcgi_hash_bucket *p = h->hash_table[idx];
req->tcp = !GetNamedPipeInfo((HANDLE)_get_osfhandle(req->listen_socket), NULL, NULL, NULL, NULL);
#endif
- fcgi_hash_init(&req->env, 4096);
+ fcgi_hash_init(&req->env);
return req;
}
ret = 0;
break;
}
- fcgi_hash_set(&req->env, (char*)p, name_len, (char*)p + name_len, val_len);
+ 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;
}
return ret;
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:
- fcgi_hash_set(&req->env, "FCGI_ROLE", sizeof("FCGI_ROLE")-1, "RESPONDER", sizeof("RESPONDER")-1);
+ 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:
- fcgi_hash_set(&req->env, "FCGI_ROLE", sizeof("FCGI_ROLE")-1, "AUTHORIZER", sizeof("AUTHORIZER")-1);
+ 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:
- fcgi_hash_set(&req->env, "FCGI_ROLE", sizeof("FCGI_ROLE")-1, "FILTER", sizeof("FILTER")-1);
+ 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;
if (!req) return NULL;
- return fcgi_hash_get(&req->env, (char*)var, var_len, &val_len);
+ 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) {
- fcgi_hash_del(&req->env, var, var_len);
- } else {
- return fcgi_hash_set(&req->env, var, var_len, val, strlen(val));
- }
+ if (!req) return NULL;
+ if (val == NULL) {
+ fcgi_hash_del(&req->env, FCGI_HASH_FUNC(var, var_len), var, var_len);
+ } else {
+ return fcgi_hash_set(&req->env, FCGI_HASH_FUNC(var, var_len), var, var_len, val, strlen(val));
+ }
+}
+
+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);
+ } 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)