diff options
author | Shane Caraveo <shane@php.net> | 2002-12-01 21:37:14 +0000 |
---|---|---|
committer | Shane Caraveo <shane@php.net> | 2002-12-01 21:37:14 +0000 |
commit | a3bd39429ca53a1a6647c505bb82803490943ee5 (patch) | |
tree | dc16515cb37323386ce3baa1e5fc3e3c0edc8cc0 /sapi | |
parent | 529762a21aca6afe44f42550d2f4d134b61ece60 (diff) | |
download | php-git-a3bd39429ca53a1a6647c505bb82803490943ee5.tar.gz |
Fix CGI to match cgi spec.
This patch properly fixes support for CGI in PHP. For backwards compatible
broken behaviour, cgi.fix_pathinfo can be set to zero in php.ini.
CGI failed to work under apache at all, either using the cgi-script directive
or as a ScriptAlias setup. Typicaly it would try to parse itself. This will
still happen if you dissable fix_pathinfo, and set DISCARD_PATH.
This also fixes PATH_INFO, and finally we can run pres2 under cgi or fastcgi.
This patch has been tested under Apache 1.3, 2.0, IIS, as both cgi and fastcgi,
on Windows and OSX. A followup patch with build stuff for linux will follow.
Diffstat (limited to 'sapi')
-rw-r--r-- | sapi/cgi/cgi_main.c | 389 | ||||
-rw-r--r-- | sapi/cgi/libfcgi/fcgiapp.c | 58 | ||||
-rw-r--r-- | sapi/cgi/libfcgi/include/fcgiapp.h | 22 |
3 files changed, 338 insertions, 131 deletions
diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c index 76ef7bb31a..6127bd8cdf 100644 --- a/sapi/cgi/cgi_main.c +++ b/sapi/cgi/cgi_main.c @@ -119,6 +119,24 @@ static pid_t pgroup; extern char *ap_php_optarg; extern int ap_php_optind; +#if ENABLE_PATHINFO_CHECK +/* true global. this is retreived once only, even for fastcgi */ +int fix_pathinfo=1; +#endif + +#ifdef PHP_WIN32 +#define TRANSLATE_SLASHES(path) \ + { \ + char *tmp = path; \ + while (*tmp) { \ + if (*tmp == '\\') *tmp = '/'; \ + tmp++; \ + } \ + } +#else +#define TRANSLATE_SLASHES(path) +#endif + #define OPTSTRING "aCc:d:ef:g:hilmnqsw?vz:" static int print_module_info(zend_module_entry *module, void *arg TSRMLS_DC) @@ -330,14 +348,8 @@ static char *sapi_cgibin_getenv(char *name, size_t name_len TSRMLS_DC) of a request. So we have to do our own lookup to get env vars. This could probably be faster somehow. */ if (!FCGX_IsCGI()) { - int cgi_env_size = 0; FCGX_Request *request = (FCGX_Request *)SG(server_context); - while( request->envp[ cgi_env_size ] ) { - if (strncasecmp(name,request->envp[cgi_env_size],name_len) == 0) { - return (request->envp[cgi_env_size])+name_len+1; - } - cgi_env_size++; - } + return FCGX_GetParam(name,request->envp); } #endif /* if cgi, or fastcgi and not found in fcgi env @@ -345,9 +357,40 @@ static char *sapi_cgibin_getenv(char *name, size_t name_len TSRMLS_DC) return getenv(name); } +static int _sapi_cgibin_putenv(char *name, char *value TSRMLS_DC) +{ + int len=0; + char *buf = NULL; + if (!name) return -1; + len = strlen(name) + (value?strlen(value):0) + sizeof("=") + 2; + buf = (char *)emalloc(len); + if (value) { + snprintf(buf,len-1,"%s=%s", name, value); + } else { + snprintf(buf,len-1,"%s=", name); + } +#if PHP_FASTCGI + /* 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 (!FCGX_IsCGI()) { + FCGX_Request *request = (FCGX_Request *)SG(server_context); + FCGX_PutEnv(request,buf); + efree(buf); + return 0; + } +#endif + /* if cgi, or fastcgi and not found in fcgi env + check the regular environment */ + putenv(buf); + efree(buf); + return 0; +} + static char *sapi_cgi_read_cookies(TSRMLS_D) { - return sapi_cgibin_getenv((char *)"HTTP_COOKIE",strlen("HTTP_COOKIE") TSRMLS_CC); + return sapi_cgibin_getenv((char *)"HTTP_COOKIE",0 TSRMLS_CC); } #if PHP_FASTCGI @@ -491,62 +534,218 @@ static void php_cgi_usage(char *argv0) */ static void init_request_info(TSRMLS_D) { - char *content_length = sapi_cgibin_getenv("CONTENT_LENGTH",strlen("CONTENT_LENGTH") TSRMLS_CC); - char *content_type = sapi_cgibin_getenv("CONTENT_TYPE",strlen("CONTENT_TYPE") TSRMLS_CC); + char *content_length = sapi_cgibin_getenv("CONTENT_LENGTH",0 TSRMLS_CC); + char *content_type = sapi_cgibin_getenv("CONTENT_TYPE",0 TSRMLS_CC); const char *auth; - -#if 0 -/* SG(request_info).path_translated is always set to NULL at the end of this function - call so why the hell did this code exist in the first place? Am I missing something? */ - char *script_filename; - - - script_filename = sapi_cgibin_getenv("SCRIPT_FILENAME",strlen("SCRIPT_FILENAME") TSRMLS_CC); - /* Hack for annoying servers that do not set SCRIPT_FILENAME for us */ - if (!script_filename) { - script_filename = SG(request_info).argv0; - } -#ifdef PHP_WIN32 - /* FIXME WHEN APACHE NT IS FIXED */ - /* a hack for apache nt because it does not appear to set argv[1] and sets - script filename to php.exe thus makes us parse php.exe instead of file.php - requires we get the info from path translated. This can be removed at - such a time that apache nt is fixed */ - if (!script_filename) { - script_filename = sapi_cgibin_getenv("PATH_TRANSLATED",strlen("PATH_TRANSLATED") TSRMLS_CC); - } + char *env_path_translated; + + SG(request_info).path_translated = NULL; + /* + * If for some reason the CGI interface is not setting the + * PATH_TRANSLATED correctly, SG(request_info).path_translated is NULL. + * We still call php_fopen_primary_script, because if you set doc_root + * or user_dir configuration directives, SCRIPT_NAME is used to construct + * the filename as a side effect of php_fopen_primary_script. + * + * Fixup path stuff to conform to CGI spec + * + * http://localhost/info.php/test?a=b + * + * should produce, which btw is the same as if + * we were running under mod_cgi on apache (ie. not + * using ScriptAlias directives): + * + * PATH_INFO=/test + * PATH_TRANSLATED=/docroot/test + * SCRIPT_NAME=/info.php + * REQUEST_URI=/info.php/test?a=b + * SCRIPT_FILENAME=/docroot/info.php + * QUERY_STRING=a=b + * + * cgi/mod_fastcgi under apache produce: + * + * PATH_INFO=/info.php/test + * PATH_TRANSLATED=/docroot/info.php/test + * SCRIPT_NAME=/php/php-cgi (from the Action setting I suppose) + * REQUEST_URI=/info.php/test?a=b + * SCRIPT_FILENAME=/path/to/php/bin/php-cgi (Action setting translated) + * QUERY_STRING=a=b + * + * Comments in the code below refer to using the above URL in a request + * + */ + + env_path_translated = sapi_cgibin_getenv("PATH_TRANSLATED",0 TSRMLS_CC); + + if(env_path_translated) { +#ifdef __riscos__ + /* Convert path to unix format*/ + __riscosify_control|=__RISCOSIFY_DONT_CHECK_DIR; + env_path_translated=__unixify(env_path_translated,0,NULL,1,0); #endif + +#if ENABLE_PATHINFO_CHECK + /* + * if the file doesn't exist, try to extract PATH_INFO out + * of it by stat'ing back through the '/' + * this fixes url's like /info.php/test + * + * ini cgi.fix_pathinfo is on by default, but can be turned off + * if someone is running a server that does this correctly + */ + if (fix_pathinfo) { + struct stat st; + char *env_script_name = sapi_cgibin_getenv("SCRIPT_NAME",0 TSRMLS_CC); + char *env_path_info = sapi_cgibin_getenv("PATH_INFO",0 TSRMLS_CC); + if (env_path_info) env_path_info = estrdup(env_path_info); + if (sapi_cgibin_getenv("REDIRECT_URL",0 TSRMLS_CC) || + (env_script_name && env_path_info && + strcmp(env_path_info,env_script_name)==0)) { + /* + * if PHP is setup under a ScriptAlias in Apache, the + * redirect_url variable will be set. In this case, script_* + * points to the executable, not the script. We have to + * reset this stuff and clear PATH_INFO since it is also wrong. + * This unfortunately is Apache specific. IIS sets PATH_INFO + * and SCRIPT_NAME to the same thing if there is no *real* PATH_INFO. + */ + _sapi_cgibin_putenv("SCRIPT_FILENAME",env_path_translated TSRMLS_CC); + _sapi_cgibin_putenv("PATH_INFO",NULL TSRMLS_CC); + } - /* doc_root configuration variable is currently ignored, - as it is with every other access method currently also. */ - - /* We always need to emalloc() filename, since it gets placed into - the include file hash table, and gets freed with that table. - Notice that this means that we don't need to efree() it in - php_destroy_request_info()! */ + if (stat( env_path_translated, &st ) == -1 ) { + char *pt = estrdup(env_path_translated); + int len = strlen(pt); + char *ptr; + + while( (ptr = strrchr(pt,'/')) || (ptr = strrchr(pt,'\\')) ) { + *ptr = 0; + if ( lstat(pt, &st) == 0 && S_ISREG(st.st_mode) ) { + /* + * okay, we found the base script! + * work out how many chars we had to strip off; + * then we can modify PATH_INFO + * accordingly + * + * we now have the makings of + * PATH_INFO=/test + * SCRIPT_FILENAME=/docroot/info.php + * + * we now need to figure out what docroot is. + * if DOCUMENT_ROOT is set, this is easy, otherwise, + * we have to play the game of hide and seek to figure + * out what SCRIPT_NAME should be + */ + char *env_document_root = sapi_cgibin_getenv("DOCUMENT_ROOT",0 TSRMLS_CC); + int slen = len - strlen(pt); + int pilen = strlen( env_path_info ); + char *path_info = env_path_info + pilen - slen; + + _sapi_cgibin_putenv("PATH_INFO",path_info TSRMLS_CC); + _sapi_cgibin_putenv("SCRIPT_FILENAME",pt TSRMLS_CC); + TRANSLATE_SLASHES(pt); + + /* figure out docroot + SCRIPT_FILENAME minus SCRIPT_NAME + */ + if (!env_document_root) + env_document_root = PG(doc_root); + if (env_document_root) { + int l = strlen(env_document_root); + int path_translated_len = 0; + char *path_translated = NULL; + + /* we have docroot, so we should have: + * DOCUMENT_ROOT=/docroot + * SCRIPT_FILENAME=/docroot/info.php + * + * SCRIPT_NAME is the portion of the path beyond docroot + */ + _sapi_cgibin_putenv("SCRIPT_NAME",pt+l TSRMLS_CC); + + /* + * PATH_TRANSATED = DOCUMENT_ROOT + PATH_INFO + */ + path_translated_len = l + strlen(path_info) + 2; + path_translated = (char *)emalloc(path_translated_len); + *path_translated = 0; + strcat(path_translated,env_document_root); + strcat(path_translated,path_info); + _sapi_cgibin_putenv("PATH_TRANSLATED",path_translated TSRMLS_CC); + efree(path_translated); + } else if (env_script_name && + strstr(pt,env_script_name)) { + /* + * PATH_TRANSATED = PATH_TRANSATED - SCRIPT_NAME + PATH_INFO + */ + int ptlen = strlen(pt)-strlen(env_script_name); + int path_translated_len = ptlen + strlen(path_info) + 2; + char *path_translated = NULL; + path_translated = (char *)emalloc(path_translated_len); + *path_translated = 0; + strncat(path_translated,pt,ptlen); + strcat(path_translated,path_info); + _sapi_cgibin_putenv("PATH_TRANSLATED",path_translated TSRMLS_CC); + efree(path_translated); + } + break; + } + } + if (pt) efree(pt); + /* + * if we stripped out all the '/' and still didn't find + * a valid path... we will fail, badly. of course we would + * have failed anyway... is there a nice way to error? + */ + } + if (env_path_info) efree(env_path_info); + } else +#endif + { + /* old broken logic here, but at least reverts to + * previous behaviour if the fixup is ignored, or there + * is a working server. + * + * 1. DISCARD_PATH IS BAD + * 2. PATH_INFO will never be right + */ #if DISCARD_PATH - if (script_filename) { - SG(request_info).path_translated = estrdup(script_filename); - } else { - SG(request_info).path_translated = NULL; - } + env_path_translated = sapi_cgibin_getenv("SCRIPT_FILENAME",0 TSRMLS_CC); +#else + env_path_translated = sapi_cgibin_getenv("PATH_TRANSLATED",0 TSRMLS_CC); #endif + SG(request_info).path_translated = env_path_translated; + } + } -#endif /* 0 */ + SG(request_info).request_method = sapi_cgibin_getenv("REQUEST_METHOD",0 TSRMLS_CC); + SG(request_info).query_string = sapi_cgibin_getenv("QUERY_STRING",0 TSRMLS_CC); + SG(request_info).request_uri = sapi_cgibin_getenv("SCRIPT_NAME",0 TSRMLS_CC); - SG(request_info).request_method = sapi_cgibin_getenv("REQUEST_METHOD",strlen("REQUEST_METHOD") TSRMLS_CC); - SG(request_info).query_string = sapi_cgibin_getenv("QUERY_STRING",strlen("QUERY_STRING") TSRMLS_CC); - SG(request_info).request_uri = sapi_cgibin_getenv("PATH_INFO",strlen("PATH_INFO") TSRMLS_CC); if (!SG(request_info).request_uri) { - SG(request_info).request_uri = sapi_cgibin_getenv("SCRIPT_NAME",strlen("SCRIPT_NAME") TSRMLS_CC); + /* this is old logic, and completely incorrect by CGI spec + * this is used to generate PHP_SELF, which should actually + * match SCRIPT_NAME. This is being left so PHP will be as broken + * as it was before if a server does not set SCRIPT_NAME. + */ + SG(request_info).request_uri = sapi_cgibin_getenv("PATH_INFO",0 TSRMLS_CC); + } + if (!SG(request_info).path_translated) { + /* if this didn't get set above, do it now, default to script_filename */ + SG(request_info).path_translated = sapi_cgibin_getenv("SCRIPT_FILENAME",0 TSRMLS_CC); } - SG(request_info).path_translated = NULL; /* we have to update it later, when we have that information */ + if (!SG(request_info).path_translated) { + /* server didn't set script_filename, default to path_translated */ + SG(request_info).path_translated = sapi_cgibin_getenv("PATH_TRANSLATED",0 TSRMLS_CC); + } + if (SG(request_info).path_translated) + SG(request_info).path_translated = estrdup(SG(request_info).path_translated); SG(request_info).content_type = (content_type ? content_type : "" ); SG(request_info).content_length = (content_length?atoi(content_length):0); SG(sapi_headers).http_response_code = 200; /* The CGI RFC allows servers to pass on unvalidated Authorization data */ - auth = sapi_cgibin_getenv("HTTP_AUTHORIZATION",strlen("HTTP_AUTHORIZATION") TSRMLS_CC); + auth = sapi_cgibin_getenv("HTTP_AUTHORIZATION",0 TSRMLS_CC); php_handle_auth_data(auth TSRMLS_CC); } /* }}} */ @@ -623,7 +822,6 @@ int main(int argc, char *argv[]) char *script_file=NULL; zend_llist global_vars; int interactive=0; - #if FORCE_CGI_REDIRECT int force_redirect = 1; char *redirect_status_env = NULL; @@ -663,7 +861,6 @@ int main(int argc, char *argv[]) #endif #endif - #ifdef ZTS tsrm_startup(1, 1, 0, NULL); #endif @@ -794,6 +991,12 @@ consult the installation file that came with this distribution, or visit \n\ } #endif /* FORCE_CGI_REDIRECT */ +#if ENABLE_PATHINFO_CHECK + if (cfg_get_long("cgi.fix_pathinfo", &fix_pathinfo) == FAILURE) { + fix_pathinfo = 1; + } +#endif + #if PHP_FASTCGI if (bindpath) { /* Pass on the arg to the FastCGI library, with one exception. @@ -962,12 +1165,15 @@ consult the installation file that came with this distribution, or visit \n\ #else SG(server_context) = (void *) 1; /* avoid server_context==NULL checks */ #endif + init_request_info(TSRMLS_C); SG(request_info).argv0 = argv0; zend_llist_init(&global_vars, sizeof(char *), NULL, 0); + CG(interactive) = 0; + if (!cgi #if PHP_FASTCGI && !fastcgi @@ -1104,15 +1310,7 @@ consult the installation file that came with this distribution, or visit \n\ break; } } - } /* not cgi */ - - CG(interactive) = interactive; - if (!cgi -#if PHP_FASTCGI - && !fastcgi -#endif - ) { if (!SG(request_info).query_string) { len = 0; if (script_file) { @@ -1138,21 +1336,23 @@ consult the installation file that came with this distribution, or visit \n\ } SG(request_info).query_string = s; } - } - if (script_file) { - SG(request_info).path_translated = script_file; - } + if (script_file) { + /* override path_translated if -f on command line */ + SG(request_info).path_translated = script_file; + } - if (php_request_startup(TSRMLS_C)==FAILURE) { - php_module_shutdown(TSRMLS_C); - return FAILURE; - } + if (no_headers) { + SG(headers_sent) = 1; + SG(request_info).no_headers = 1; + } - if (no_headers) { - SG(headers_sent) = 1; - SG(request_info).no_headers = 1; + if (!SG(request_info).path_translated && argc > ap_php_optind) { + /* file is on command line, but not in -f opt */ + SG(request_info).path_translated = estrdup(argv[ap_php_optind]); + } } + #if PHP_FASTCGI if (fastcgi) { file_handle.type = ZEND_HANDLE_FILENAME; @@ -1168,41 +1368,17 @@ consult the installation file that came with this distribution, or visit \n\ file_handle.opened_path = NULL; file_handle.free_filename = 0; - /* This actually destructs the elements of the list - ugly hack */ - zend_llist_apply(&global_vars, (llist_apply_func_t) php_register_command_line_global_vars TSRMLS_CC); - zend_llist_destroy(&global_vars); - - if (!cgi -#if PHP_FASTCGI - && !fastcgi -#endif - ) { - if (!SG(request_info).path_translated && argc > ap_php_optind) { - SG(request_info).path_translated = estrdup(argv[ap_php_optind]); - } - } else { - /* If for some reason the CGI interface is not setting the - PATH_TRANSLATED correctly, SG(request_info).path_translated is NULL. - We still call php_fopen_primary_script, because if you set doc_root - or user_dir configuration directives, PATH_INFO is used to construct - the filename as a side effect of php_fopen_primary_script. - */ - char *env_path_translated=NULL; -#if DISCARD_PATH - env_path_translated = sapi_cgibin_getenv("SCRIPT_FILENAME",strlen("SCRIPT_FILENAME") TSRMLS_CC); -#else - env_path_translated = sapi_cgibin_getenv("PATH_TRANSLATED",strlen("PATH_TRANSLATED") TSRMLS_CC); -#endif + /* request startup only after we've done all we can to + get path_translated */ + if (php_request_startup(TSRMLS_C)==FAILURE) { + php_module_shutdown(TSRMLS_C); + return FAILURE; + } - if(env_path_translated) { -#ifdef __riscos__ - /* Convert path to unix format*/ - __riscosify_control|=__RISCOSIFY_DONT_CHECK_DIR; - env_path_translated=__unixify(env_path_translated,0,NULL,1,0); -#endif - SG(request_info).path_translated = estrdup(env_path_translated); - } - } + /* This actually destructs the elements of the list - ugly hack */ + zend_llist_apply(&global_vars, (llist_apply_func_t) php_register_command_line_global_vars TSRMLS_CC); + zend_llist_destroy(&global_vars); + if (cgi || SG(request_info).path_translated) { retval = php_fopen_primary_script(&file_handle TSRMLS_CC); } @@ -1216,7 +1392,7 @@ consult the installation file that came with this distribution, or visit \n\ } file_handle.filename = argv0; file_handle.opened_path = expand_filepath(argv0, NULL TSRMLS_CC); - } + } if (file_handle.handle.fp && (file_handle.handle.fp != stdin)) { /* #!php support */ @@ -1291,6 +1467,7 @@ consult the installation file that came with this distribution, or visit \n\ if (SG(request_info).path_translated) { free(SG(request_info).path_translated); + SG(request_info).path_translated = NULL; } } diff --git a/sapi/cgi/libfcgi/fcgiapp.c b/sapi/cgi/libfcgi/fcgiapp.c index 863b5e8d6e..75d91f5b93 100644 --- a/sapi/cgi/libfcgi/fcgiapp.c +++ b/sapi/cgi/libfcgi/fcgiapp.c @@ -980,24 +980,7 @@ void FCGX_ClearError(FCGX_Stream *stream) { */ } -/* - *====================================================================== - * Parameters - *====================================================================== - */ -/* - * A vector of pointers representing the parameters received - * by a FastCGI application server, with the vector's length - * and last valid element so adding new parameters is efficient. - */ - -typedef struct Params { - FCGX_ParamArray vec; /* vector of strings */ - int length; /* number of string vec can hold */ - char **cur; /* current item in vec; *cur == NULL */ -} Params; -typedef Params *ParamsPtr; /* *---------------------------------------------------------------------- @@ -1071,13 +1054,45 @@ static void PutParam(ParamsPtr paramsPtr, char *nameValue) *paramsPtr->cur++ = nameValue; size = paramsPtr->cur - paramsPtr->vec; if(size >= paramsPtr->length) { - paramsPtr->length *= 2; - paramsPtr->vec = (FCGX_ParamArray)realloc(paramsPtr->vec, paramsPtr->length * sizeof(char *)); - paramsPtr->cur = paramsPtr->vec + size; + paramsPtr->length *= 2; + paramsPtr->vec = (FCGX_ParamArray)realloc(paramsPtr->vec, paramsPtr->length * sizeof(char *)); + paramsPtr->cur = paramsPtr->vec + size; } *paramsPtr->cur = NULL; } + +void FCGX_PutEnv(FCGX_Request *request, char *var) +{ + char *nameValue; + char *e, **p; + int len; + + if (!strchr(var,'=')) { + return; + } + nameValue = StringCopy(var); + e = strchr(nameValue,'='); + *e = 0; + + /* find the name and replace it */ + len = strlen(nameValue); + + for (p = request->envp; p && *p; ++p) { + if((strncmp(nameValue, *p, len) == 0) && ((*p)[len] == '=')) { + free(*p); + *e = '='; + *p = nameValue; + return; + } + } + *e = '='; + /* this is a new var, add it to the environment */ + PutParam(request->paramsPtr,nameValue); + request->envp = request->paramsPtr->vec; +} + + /* *---------------------------------------------------------------------- * @@ -1100,7 +1115,7 @@ char *FCGX_GetParam(const char *name, FCGX_ParamArray envp) len = strlen(name); - for (p = envp; *p; ++p) { + for (p = envp; p && *p; ++p) { if((strncmp(name, *p, len) == 0) && ((*p)[len] == '=')) { return *p+len+1; } @@ -2027,6 +2042,7 @@ void FCGX_Free(FCGX_Request * request, int close) _FCGX_FreeStream(&request->out, FALSE); _FCGX_FreeStream(&request->err, FALSE); FreeParams(&request->paramsPtr); + request->envp = NULL; if (close) { OS_IpcClose(request->ipcFd); diff --git a/sapi/cgi/libfcgi/include/fcgiapp.h b/sapi/cgi/libfcgi/include/fcgiapp.h index 394e2078f9..8e35e0776c 100644 --- a/sapi/cgi/libfcgi/include/fcgiapp.h +++ b/sapi/cgi/libfcgi/include/fcgiapp.h @@ -80,6 +80,19 @@ typedef struct FCGX_Stream { typedef char **FCGX_ParamArray; /* + * A vector of pointers representing the parameters received + * by a FastCGI application server, with the vector's length + * and last valid element so adding new parameters is efficient. + */ + +typedef struct Params { + FCGX_ParamArray vec; /* vector of strings */ + int length; /* number of string vec can hold */ + char **cur; /* current item in vec; *cur == NULL */ +} Params; +typedef Params *ParamsPtr; + +/* * FCGX_Request Flags * * Setting FCGI_FAIL_ACCEPT_ON_INTR prevents FCGX_Accept() from @@ -98,11 +111,11 @@ typedef struct FCGX_Request { FCGX_Stream *in; FCGX_Stream *out; FCGX_Stream *err; - char **envp; + FCGX_ParamArray envp; /* Don't use anything below here */ - struct Params *paramsPtr; + ParamsPtr paramsPtr; int ipcFd; /* < 0 means no connection */ int isBeginProcessed; /* FCGI_BEGIN_REQUEST seen */ int keepConnection; /* don't close ipcFd at end of request */ @@ -351,7 +364,8 @@ DLLAPI void FCGX_SetExitStatus(int status, FCGX_Stream *stream); *---------------------------------------------------------------------- */ DLLAPI char *FCGX_GetParam(const char *name, FCGX_ParamArray envp); - +DLLAPI void FCGX_PutEnv(FCGX_Request *request, char *nameValue); + /* *====================================================================== * Readers @@ -533,7 +547,7 @@ DLLAPI int FCGX_VFPrintF(FCGX_Stream *stream, const char *format, va_list arg); *---------------------------------------------------------------------- */ DLLAPI int FCGX_FFlush(FCGX_Stream *stream); - + /* *====================================================================== * Both Readers and Writers |