|
|
| version 1.154, 2002/02/08 08:31:32 | version 1.166, 2002/04/04 07:57:50 |
|---|---|
| Line 1 | Line 1 |
| /** @file | /** @file |
| Parser: scripting and CGI main. | Parser: scripting and CGI main. |
| Copyright(c) 2001, 2002 ArtLebedev Group(http://www.artlebedev.com) | Copyright(c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com) |
| Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) | Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) |
| $Id$ | $Id$ |
| Line 29 | Line 29 |
| #endif | #endif |
| //#define DEBUG_POOL_MALLOC | //#define DEBUG_POOL_MALLOC |
| //#define DEBUG_STRING_APPENDS_VS_EXPANDS | |
| #ifdef DEBUG_STRING_APPENDS_VS_EXPANDS | |
| extern ulong | |
| string_piece_appends, | |
| wcontext_result_size, | |
| total_alloc_size, | |
| string_string_shortcut_economy; | |
| #endif | |
| // consts | // consts |
| Line 52 const char **RCSIds[]={ | Line 61 const char **RCSIds[]={ |
| 0 | 0 |
| }; | }; |
| const char *PARSER_ROOT_CONFIG_ENV_NAME="HTTP_PARSER_ROOT_CONFIG"; | |
| const char *PARSER_SITE_CONFIG_ENV_NAME="HTTP_PARSER_SITE_CONFIG"; | |
| /// IIS refuses to read bigger chunks | /// IIS refuses to read bigger chunks |
| const size_t READ_POST_CHUNK_SIZE=0x400*0x400; // 1M | const size_t READ_POST_CHUNK_SIZE=0x400*0x400; // 1M |
| Line 183 void SAPI::send_body(Pool& , const void | Line 195 void SAPI::send_body(Pool& , const void |
| // | // |
| char *full_file_spec(char *file_name) { | void full_file_spec(const char *file_name, char *buf, size_t buf_size) { |
| if(file_name && !strchr(file_name, '/')) { | if(file_name && !strchr(file_name, '/')) { |
| static char cwd[MAX_STRING]; getcwd(cwd, MAX_STRING); | char cwd[MAX_STRING]; getcwd(cwd, MAX_STRING); |
| static char buf[MAX_STRING]; | snprintf(buf, buf_size, "%s/%s", cwd, file_name); |
| snprintf(buf, MAX_STRING, "%s/%s", cwd, file_name); | } else { |
| return buf; | strncpy(buf, file_name, buf_size); |
| } | } |
| return file_name; | #ifdef WIN32 |
| back_slashes_to_slashes(buf); | |
| #endif | |
| } | } |
| /** | /** |
| Line 218 void real_parser_handler( | Line 232 void real_parser_handler( |
| // Request info | // Request info |
| Request::Info request_info; | Request::Info request_info; |
| char document_root_buf[MAX_STRING]; | |
| if(cgi) { | if(cgi) { |
| if(const char *env_document_root=SAPI::get_env(pool, "DOCUMENT_ROOT")) | if(const char *env_document_root=SAPI::get_env(pool, "DOCUMENT_ROOT")) |
| request_info.document_root=env_document_root; | request_info.document_root=env_document_root; |
| else if(const char *path_info=SAPI::get_env(pool, "PATH_INFO")) { | else if(const char *path_info=SAPI::get_env(pool, "PATH_INFO")) { |
| // IIS | // IIS |
| size_t len=strlen(filespec_to_process)-strlen(path_info); | size_t len=min(sizeof(document_root_buf)-1, strlen(filespec_to_process)-strlen(path_info)); |
| char *buf=(char *)pool.malloc(len+1); | memcpy(document_root_buf, filespec_to_process, len); document_root_buf[len]=0; |
| memcpy(buf, filespec_to_process, len); buf[len]=0; | request_info.document_root=document_root_buf; |
| request_info.document_root=buf; | |
| } else | } else |
| throw Exception(0, 0, | throw Exception("parser.runtime", |
| 0, | 0, |
| "CGI: no PATH_INFO defined(in reinventing DOCUMENT_ROOT)"); | "CGI: no PATH_INFO defined(in reinventing DOCUMENT_ROOT)"); |
| } else { | } else { |
| static char buf[MAX_STRING]; | full_file_spec("", document_root_buf, sizeof(document_root_buf)); |
| strncpy(buf, filespec_to_process, MAX_STRING-1); buf[MAX_STRING-1]=0; | request_info.document_root=document_root_buf; |
| if(rsplit(buf, '/') || rsplit(buf, '\\')) // strip filename | |
| request_info.document_root=buf; | |
| else | |
| request_info.document_root=""; | |
| } | } |
| request_info.path_translated=filespec_to_process; | request_info.path_translated=filespec_to_process; |
| request_info.method=request_method ? request_method : "GET"; | request_info.method=request_method ? request_method : "GET"; |
| Line 258 void real_parser_handler( | Line 268 void real_parser_handler( |
| } else | } else |
| request_info.uri=path_info; | request_info.uri=path_info; |
| else | else |
| throw Exception(0, 0, | throw Exception("parser.runtime", |
| 0, | 0, |
| "CGI: no PATH_INFO defined(in reinventing REQUEST_URI)"); | "CGI: no PATH_INFO defined(in reinventing REQUEST_URI)"); |
| #ifndef WIN32 | #ifndef WIN32 |
| // they've changed this under IIS5. | // they've changed this under IIS5. |
| Line 293 void real_parser_handler( | Line 303 void real_parser_handler( |
| true /* status_allowed */); | true /* status_allowed */); |
| // some root-controlled location | // some root-controlled location |
| const char *root_config_filespec; | |
| if(const char *root_config_by_env=getenv(PARSER_ROOT_CONFIG_ENV_NAME)) | |
| root_config_filespec=root_config_by_env; | |
| else { | |
| #ifdef ROOT_CONFIG_DIR | #ifdef ROOT_CONFIG_DIR |
| const char *root_config_filespec=ROOT_CONFIG_DIR "/" CONFIG_FILE_NAME; | root_config_filespec=ROOT_CONFIG_DIR "/" CONFIG_FILE_NAME; |
| #else | #else |
| # ifdef WIN32 | # ifdef WIN32 |
| // c:\windows | // c:\windows |
| char root_config_path[MAX_STRING]; | char windows_dir[MAX_STRING]; |
| GetWindowsDirectory(root_config_path, MAX_STRING); | GetWindowsDirectory(windows_dir, MAX_STRING); |
| char root_config_filespec[MAX_STRING]; | char buf[MAX_STRING]; |
| snprintf(root_config_filespec, MAX_STRING, | snprintf(buf, MAX_STRING, |
| "%s/%s", | "%s/%s", |
| root_config_path, CONFIG_FILE_NAME); | windows_dir, CONFIG_FILE_NAME); |
| root_config_filespec=buf; | |
| # else | # else |
| #error must be compiled either configure/make or MSVC++ | #error must be compiled either configure/make or MSVC++ |
| # endif | # endif |
| #endif | #endif |
| } | |
| const char *site_config_filespec; | |
| if(const char *site_config_by_env=getenv(PARSER_SITE_CONFIG_ENV_NAME)) | |
| site_config_filespec=site_config_by_env; | |
| else { | |
| // beside by binary | // beside by binary |
| // @todo full path, not ./! | // @todo full path, not ./! |
| static char site_config_path[MAX_STRING]; | char beside_binary_path[MAX_STRING]; |
| strncpy(site_config_path, argv0, MAX_STRING-1); site_config_path[MAX_STRING-1]=0; // filespec of my binary | strncpy(beside_binary_path, argv0, MAX_STRING-1); beside_binary_path[MAX_STRING-1]=0; // filespec of my binary |
| if(!( | if(!( |
| rsplit(site_config_path, '/') || | rsplit(beside_binary_path, '/') || |
| rsplit(site_config_path, '\\'))) { // strip filename | rsplit(beside_binary_path, '\\'))) { // strip filename |
| // no path, just filename | // no path, just filename |
| site_config_path[0]='.'; site_config_path[1]=0; | beside_binary_path[0]='.'; beside_binary_path[1]=0; |
| } | |
| char buf[MAX_STRING]; | |
| snprintf(buf, MAX_STRING, | |
| "%s/%s", | |
| beside_binary_path, CONFIG_FILE_NAME); | |
| site_config_filespec=buf; | |
| } | } |
| char site_config_filespec[MAX_STRING]; | |
| snprintf(site_config_filespec, MAX_STRING, | |
| "%s/%s", | |
| site_config_path, CONFIG_FILE_NAME); | |
| // process the request | // process the request |
| request.core( | request.core( |
| root_config_filespec, false, | root_config_filespec, false /*don't fail_on_read_problem*/, |
| site_config_filespec, false, | site_config_filespec, false /*don't fail_on_read_problem*/, |
| header_only); | header_only); |
| // | // |
| Line 339 void real_parser_handler( | Line 361 void real_parser_handler( |
| extern void log_pool_stats(Pool& pool); | extern void log_pool_stats(Pool& pool); |
| log_pool_stats(pool); | log_pool_stats(pool); |
| #endif | #endif |
| #ifdef DEBUG_STRING_APPENDS_VS_EXPANDS | |
| SAPI::log(pool, | |
| "string piece appends=%lu, wcontext_result_size=%lu, string_string_shortcut_economy_closer=%lu, total_alloc_size=%lu", | |
| string_piece_appends, | |
| wcontext_result_size, | |
| string_string_shortcut_economy, | |
| total_alloc_size); | |
| #endif | |
| } | } |
| void call_real_parser_handler__do_SEH( | void call_real_parser_handler__do_SEH( |
| Line 359 void call_real_parser_handler__do_SEH( | Line 391 void call_real_parser_handler__do_SEH( |
| if(system_exception) | if(system_exception) |
| if(_EXCEPTION_RECORD *er=system_exception->ExceptionRecord) | if(_EXCEPTION_RECORD *er=system_exception->ExceptionRecord) |
| throw Exception(0, 0, | throw Exception(0, |
| 0, | 0, |
| "Exception 0x%08X at 0x%08X", er->ExceptionCode, er->ExceptionAddress); | "Exception 0x%08X at 0x%08X", er->ExceptionCode, er->ExceptionAddress); |
| else | else |
| throw Exception(0, 0, 0, "Exception <no exception record>"); | throw Exception(0, 0, "Exception <no exception record>"); |
| else | else |
| throw Exception(0, 0, 0, "Exception <no exception information>"); | throw Exception(0, 0, "Exception <no exception information>"); |
| } | } |
| #endif | #endif |
| } | } |
| Line 399 int main(int argc, char *argv[]) { | Line 431 int main(int argc, char *argv[]) { |
| if(!cgi) { | if(!cgi) { |
| if(argc<2) { | if(argc<2) { |
| printf( | printf( |
| "Parser/%s Copyright(c) 2001, 2002 ArtLebedev Group(http://www.artlebedev.com)\n" | "Parser/%s Copyright(c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com)\n" |
| "Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)\n" | "Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)\n" |
| "\n" | "\n" |
| "Usage: %s <file>\n", | "Usage: %s <file>\n", |
| Line 437 int main(int argc, char *argv[]) { | Line 469 int main(int argc, char *argv[]) { |
| std::set_new_handler(failed_new); | std::set_new_handler(failed_new); |
| #endif | #endif |
| char *filespec_to_process=cgi?getenv("PATH_TRANSLATED"):argv[1]; | char *raw_filespec_to_process=cgi?getenv("PATH_TRANSLATED"):argv[1]; |
| #ifdef WIN32 | char filespec_to_process[MAX_STRING]; |
| back_slashes_to_slashes(filespec_to_process); | full_file_spec(raw_filespec_to_process, filespec_to_process, sizeof(filespec_to_process)); |
| #endif | |
| filespec_to_process=full_file_spec(filespec_to_process); | |
| const char *request_method=getenv("REQUEST_METHOD"); | const char *request_method=getenv("REQUEST_METHOD"); |
| bool header_only=request_method && strcasecmp(request_method, "HEAD")==0; | bool header_only=request_method && strcasecmp(request_method, "HEAD")==0; |
| Line 468 int main(int argc, char *argv[]) { | Line 498 int main(int argc, char *argv[]) { |
| if(!cgi) | if(!cgi) |
| SAPI::send_body(pool, "\n", 1); | SAPI::send_body(pool, "\n", 1); |
| #endif | #endif |
| //_asm int 3; | |
| return 0; | return 0; |
| } | } |