--- parser3/src/targets/isapi/parser3isapi.C 2002/02/08 08:30:18 1.63 +++ parser3/src/targets/isapi/parser3isapi.C 2002/08/01 11:41:21 1.78 @@ -3,22 +3,16 @@ Copyright (c) 2000,2001, 2002 ArtLebedev Group (http://www.artlebedev.com) Author: Alexandr Petrosian (http://paf.design.ru) - - $Id: parser3isapi.C,v 1.63 2002/02/08 08:30:18 paf Exp $ */ +static const char* IDENT_PARSER3ISAPI_C="$Date: 2002/08/01 11:41:21 $"; + #ifndef _MSC_VER # error compile ISAPI module with MSVC [no urge for now to make it autoconf-ed (PAF)] #endif #include "pa_config_includes.h" -#include -#include -#include - -#include - #include "pa_sapi.h" #include "pa_globals.h" #include "pa_request.h" @@ -26,39 +20,37 @@ #include "pool_storage.h" #include "pa_socks.h" -#ifdef XML -#include -#endif +#include +#include +#include + +#include #define MAX_STATUS_LENGTH sizeof("xxxx LONGEST STATUS DESCRIPTION") // consts -extern const char *main_RCSIds[]; -#ifdef USE_SMTP -extern const char *smtp_RCSIds[]; -#endif -extern const char *gd_RCSIds[]; -extern const char *classes_RCSIds[]; -extern const char *types_RCSIds[]; -extern const char *parser3isapi_RCSIds[]; -#ifdef XML -extern const char *xalan_patched_RCSIds[]; -#endif -const char **RCSIds[]={ - main_RCSIds, -#ifdef USE_SMTP - smtp_RCSIds, -#endif - gd_RCSIds, - classes_RCSIds, - types_RCSIds, - parser3isapi_RCSIds, -#ifdef XML - xalan_patched_RCSIds, -#endif - 0 +const char *IIS51vars[]={ + "APPL_MD_PATH", "APPL_PHYSICAL_PATH", + "AUTH_PASSWORD", "AUTH_TYPE", "AUTH_USER", + "CERT_COOKIE", "CERT_FLAGS", "CERT_ISSUER", "CERT_KEYSIZE", "CERT_SECRETKEYSIZE", + "CERT_SERIALNUMBER", "CERT_SERVER_ISSUER", "CERT_SERVER_SUBJECT", "CERT_SUBJECT", + "CONTENT_LENGTH", "CONTENT_TYPE", + "LOGON_USER", + "HTTPS", "HTTPS_KEYSIZE", "HTTPS_SECRETKEYSIZE", "HTTPS_SERVER_ISSUER", "HTTPS_SERVER_SUBJECT", + "INSTANCE_ID", "INSTANCE_META_PATH", + "PATH_INFO", "PATH_TRANSLATED", + "QUERY_STRING", + "REMOTE_ADDR", "REMOTE_HOST", "REMOTE_USER", "REQUEST_METHOD", + "SCRIPT_NAME", + "SERVER_NAME", "SERVER_PORT", "SERVER_PORT_SECURE", "SERVER_PROTOCOL", "SERVER_SOFTWARE", + "URL", }; +const int IIS51var_count=sizeof(IIS51vars)/sizeof(*IIS51vars); + +// globals + +char argv0[MAX_STRING]=""; // SAPI @@ -74,24 +66,6 @@ struct SAPI_func_context { }; #endif -#ifdef XML -/** - * Terminate Xalan and Xerces. - * - * Should be called only once per process after deleting all - * instances of XalanTransformer. Once a process has called - * this function, it cannot use the API for the remaining - * lifetime of the process. - - - this requirement is fullfilled by using Pool::register_cleanup - */ -void callXalanTerminate(void *) { - //_asm int 3; - XalanTerminate(); -} -#endif - // goes to 'cs-uri-query' log file field. webmaster: switch it ON[default OFF]. void SAPI::log(Pool& pool, const char *fmt, ...) { SAPI_func_context& ctx=*static_cast(pool.get_context()); @@ -111,6 +85,12 @@ void SAPI::log(Pool& pool, const char *f /// @todo event log void SAPI::die(const char *fmt, ...) { + if(FILE *log=fopen("c:\\die.log", "at")) { + va_list args; + va_start(args,fmt); + vfprintf(log, fmt, args); + fclose(log); + } exit(1); } @@ -122,21 +102,69 @@ const char *SAPI::get_env(Pool& pool, co if(ctx.lpECB->GetServerVariable(ctx.lpECB->ConnID, const_cast(name), variable_buf, &variable_len)) { - variable_buf[variable_len]=0; - return variable_buf; + if(*variable_buf) { // saw returning len=1 && *buf=0 :( + variable_buf[variable_len]=0; + return variable_buf; + } } else if (GetLastError()==ERROR_INSUFFICIENT_BUFFER) { variable_buf=(char *)pool.malloc(variable_len+1); if(ctx.lpECB->GetServerVariable(ctx.lpECB->ConnID, const_cast(name), variable_buf, &variable_len)) { - variable_buf[variable_len]=0; - return variable_buf; + if(*variable_buf) { + variable_buf[variable_len]=0; + return variable_buf; + } } } return 0; } +static int grep_char(const char *s, char c) { + int result=0; + if(s) { + while(s=strchr(s, c)) { + s++; // skip found c + result++; + } + } + return result; +} +static const char *mk_env_pair(Pool& pool, const char *key, const char *value) { + char *result=(char *)pool.malloc(strlen(key)+1/*=*/+strlen(value)+1/*0*/); + strcpy(result, key); strcat(result, "="); strcat(result, value); + return result; +} +const char *const *SAPI::environment(Pool& pool) { + // we know this buf is writable + char *all_http_vars=const_cast(SAPI::get_env(pool, "ALL_HTTP")); + const int http_var_count=grep_char(all_http_vars, '\n')+1/*\n for theoretical(never saw) this \0*/; + + const char **result= + (const char **)pool.malloc(sizeof(char *)*(IIS51var_count+http_var_count+1/*0*/)); + const char **cur=result; + + // IIS5.1 vars + for(int i=0; i(pool.get_context()); @@ -187,10 +215,7 @@ void SAPI::add_header_attribute(Pool& po void SAPI::send_header(Pool& pool) { SAPI_func_context& ctx=*static_cast(pool.get_context()); -/* ctx.header->APPEND_CONST( - "expires: Fri, 23 Mar 2001 09:32:23 GMT\r\n" - "\r\n"); -*/ HSE_SEND_HEADER_EX_INFO header_info; + HSE_SEND_HEADER_EX_INFO header_info; char status_buf[MAX_STATUS_LENGTH]; switch(ctx.http_response_code) { @@ -210,6 +235,7 @@ void SAPI::send_header(Pool& pool) { break; } header_info.cchStatus=strlen(header_info.pszStatus); + *ctx.header << "\r\n"; // ISAPI v<5 did quite well without it header_info.pszHeader=ctx.header->cstr(); header_info.cchHeader=ctx.header->size(); header_info.fKeepConn=true; @@ -235,6 +261,9 @@ int failed_new(size_t size) { return 0; // not reached } +#ifdef _DEBUG +static Pool_storage *global_pool_storagep; +#endif static bool parser_init() { static bool globals_inited=false; if(globals_inited) @@ -243,28 +272,19 @@ static bool parser_init() { _set_new_handler(failed_new); - static Pool pool(0); // global pool + static Pool_storage pool_storage; +#ifdef _DEBUG + global_pool_storagep=&pool_storage; +#endif + static Pool pool(&pool_storage); // global pool try { // init socks init_socks(pool); - -#ifdef XML - /** - * Initialize Xerces and Xalan. - * - * Should be called only once per process before making - * any other API calls. - */ - //_asm int 3; - XalanInitialize(); - pool.register_cleanup(callXalanTerminate, 0); -#endif - // init global classes init_methoded_array(pool); // init global variables pa_globals_init(pool); - + // successful finish return true; } catch(const Exception& e) { // global problem @@ -315,7 +335,7 @@ void real_parser_handler(Pool& pool, LPE strncpy(buf, filespec_to_process, len); buf[len]=0; request_info.document_root=buf; } else - throw Exception(0, 0, + throw Exception("parser.runtime", 0, "ISAPI: no PATH_INFO defined (in reinventing DOCUMENT_ROOT)"); @@ -336,30 +356,36 @@ void real_parser_handler(Pool& pool, LPE request_info.content_type=lpECB->lpszContentType; request_info.content_length=lpECB->cbTotalBytes; request_info.cookie=SAPI::get_env(pool, "HTTP_COOKIE"); - request_info.user_agent=SAPI::get_env(pool, "HTTP_USER_AGENT"); - + request_info.mail_received=false; // prepare to process request Request request(pool, request_info, String::UL_HTML|String::UL_OPTIMIZE_BIT, - false /* status_allowed */); - - // some root-controlled location - // c:\windows - char root_config_path[MAX_STRING]; - GetWindowsDirectory(root_config_path, MAX_STRING); - // must be dynamic: rethrowing from request.core - // may return 'source' which can be inside of 'root auto.p@exeception' - char *root_config_filespec=(char *)pool.malloc(MAX_STRING); - snprintf(root_config_filespec, MAX_STRING, +#ifdef _DEBUG + true +#else + false +#endif + /* status_allowed */); + + // beside by binary + static char beside_binary_path[MAX_STRING]; + strncpy(beside_binary_path, argv0, MAX_STRING-1); beside_binary_path[MAX_STRING-1]=0; // filespec of my binary + if(!( + rsplit(beside_binary_path, '/') || + rsplit(beside_binary_path, '\\'))) { // strip filename + // no path, just filename + beside_binary_path[0]='.'; beside_binary_path[1]=0; + } + char config_filespec[MAX_STRING]; + snprintf(config_filespec, MAX_STRING, "%s/%s", - root_config_path, CONFIG_FILE_NAME); + beside_binary_path, AUTO_FILE_NAME); // process the request request.core( - root_config_filespec, false/*may be abcent*/, // /path/to/admin/auto.p - 0/*parser_site_auto_path*/, false, // /path/to/site/auto.p + config_filespec, false /*fail_on_read_problem*/, // /path/to/first/auto.p header_only); } @@ -379,19 +405,18 @@ void call_real_parser_handler__do_SEH(Po if(system_exception) if(_EXCEPTION_RECORD *er=system_exception->ExceptionRecord) - throw Exception(0, 0, + throw Exception(0, 0, "Exception 0x%08X at 0x%08X", er->ExceptionCode, er->ExceptionAddress); else - throw Exception(0, 0, 0, "Exception "); + throw Exception(0, 0, "Exception "); else - throw Exception(0, 0, 0, "Exception "); + throw Exception(0, 0, "Exception "); } #endif } - -DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB) { +inline DWORD RealHttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB) { Pool_storage pool_storage; Pool pool(&pool_storage); // no allocations until assigned context [for reporting] SAPI_func_context ctx={ @@ -400,19 +425,6 @@ DWORD WINAPI HttpExtensionProc(LPEXTENSI 200 // default http_response_code }; pool.set_context(&ctx);// no allocations before this line! - -#ifdef XML - /** - * Initialize Xerces and Xalan. - * - * Should be called only once per process before making - * any other API calls. - */ - //_asm int 3; - XalanInitialize(); - pool.register_cleanup(callXalanTerminate, 0); -#endif - bool header_only=strcasecmp(lpECB->lpszMethod, "HEAD")==0; try { // global try @@ -434,7 +446,7 @@ DWORD WINAPI HttpExtensionProc(LPEXTENSI int header_len=snprintf(header_buf, MAX_STRING, "content-type: text/plain\r\n" "content-length: %lu\r\n" - "expires: Fri, 23 Mar 2001 09:32:23 GMT\r\n" +// "expires: Fri, 23 Mar 2001 09:32:23 GMT\r\n" "\r\n", content_length); @@ -456,6 +468,80 @@ DWORD WINAPI HttpExtensionProc(LPEXTENSI // unsuccessful finish } - +/* + const char *body="test"; + + // + int content_length=strlen(body); + + // prepare header // not using SAPI func wich allocates on pool + char header_buf[MAX_STRING]; + int header_len=snprintf(header_buf, MAX_STRING, + "content-type: text/plain\r\n" + "content-length: %lu\r\n" + "expires: Fri, 23 Mar 2001 09:32:23 GMT\r\n" + "\r\n", + content_length); + HSE_SEND_HEADER_EX_INFO header_info; + header_info.pszStatus="200 OK"; + header_info.cchStatus=strlen(header_info.pszStatus); + header_info.pszHeader=header_buf; + header_info.cchHeader=header_len; + header_info.fKeepConn=true; + + // send header + lpECB->dwHttpStatusCode=200; + lpECB->ServerSupportFunction(lpECB->ConnID, + HSE_REQ_SEND_RESPONSE_HEADER_EX, &header_info, NULL, NULL); + + // send body + DWORD num_bytes=content_length; + lpECB->WriteClient(lpECB->ConnID, + (void *)body, &num_bytes, HSE_IO_SYNC); +*/ return HSE_STATUS_SUCCESS_AND_KEEP_CONN; } + +#ifdef _DEBUG +//for memory leaks detection only +#undef _WINDOWS_ +#include +#endif +DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB) { +// Declare the variables needed +#ifdef _DEBUG +// _crtBreakAlloc=97779;//97777; //997; + + CMemoryState oldMemState, newMemState, diffMemState; + oldMemState.Checkpoint(); + //global_pool_storagep->fbreak_on_alloc=true; +#endif + + DWORD result=RealHttpExtensionProc(lpECB); + +#ifdef _DEBUG + newMemState.Checkpoint(); + if( diffMemState.Difference( oldMemState, newMemState ) ) + { + TRACE( "Memory leaked!\n" ); + diffMemState.DumpStatistics( ); + diffMemState.DumpAllObjectsSince(); + } +#endif + return result; +} + +BOOL WINAPI DllMain( + HINSTANCE hinstDLL, // handle to the DLL module + DWORD fdwReason, // reason for calling function + LPVOID lpvReserved // reserved + ) { + + GetModuleFileName( + hinstDLL, // handle to module + argv0, // file name of module + sizeof(argv0) // size of buffer + ); + + return TRUE; +} \ No newline at end of file