|
|
| version 1.298, 2020/10/12 20:57:08 | version 1.308, 2020/11/12 15:06:12 |
|---|---|
| Line 38 volatile const char * IDENT_PARSER3_C="$ | Line 38 volatile const char * IDENT_PARSER3_C="$ |
| #define PARSER_CONFIG_ENV_NAME "CGI_PARSER_CONFIG" | #define PARSER_CONFIG_ENV_NAME "CGI_PARSER_CONFIG" |
| #define PARSER_LOG_ENV_NAME "CGI_PARSER_LOG" | #define PARSER_LOG_ENV_NAME "CGI_PARSER_LOG" |
| static const char* filespec_to_process=0; // [file] | |
| static const char* config_filespec_cstr=0; // -f option | static const char* config_filespec_cstr=0; // -f option |
| static const char* httpd_host_port=0; // -p option | static const char* httpd_host_port=0; // -p option |
| static bool mail_received=false; // -m option? [asked to parse incoming message to $mail:received] | static bool mail_received=false; // -m option? [asked to parse incoming message to $mail:received] |
| Line 105 static void log(const char* fmt, va_list | Line 106 static void log(const char* fmt, va_list |
| fwrite(buf, size, 1, f); | fwrite(buf, size, 1, f); |
| if(request_info.method) { | if(request_info.method) { |
| fprintf(f, " [uri=%s, method=%s, cl=%lu]\n", request_info.uri ? request_info.uri : "<unknown>", request_info.method, request_info.content_length); | fprintf(f, " [uri=%s, method=%s, cl=%lu]\n", request_info.uri ? request_info.uri : "<unknown>", request_info.method, (unsigned long)request_info.content_length); |
| } else | } else |
| fputs(" [no request info]\n", f); | fputs(" [no request info]\n", f); |
| Line 142 void SAPI::die(const char* fmt, ...) { | Line 143 void SAPI::die(const char* fmt, ...) { |
| // inform user, second vsnprintf | // inform user, second vsnprintf |
| va_start(args, fmt); | va_start(args, fmt); |
| char body[MAX_STRING]; | char message[MAX_STRING]; |
| int content_length=vsnprintf(body, MAX_STRING, fmt, args); | vsnprintf(message, MAX_STRING, fmt, args); |
| sapiInfo->die(body, content_length); | SAPI::send_error(*sapiInfo, message); |
| exit(1); | exit(1); |
| // va_end(args); | // va_end(args); |
| } | } |
| Line 154 char* SAPI::Env::get(SAPI_Info& info, co | Line 155 char* SAPI::Env::get(SAPI_Info& info, co |
| return info.get_env(name); | return info.get_env(name); |
| } | } |
| bool SAPI::Env::set(SAPI_Info& info, const char* name, const char* value) { | |
| return info.set_env(name, value); | |
| } | |
| const char* const *SAPI::Env::get(SAPI_Info& info) { | const char* const *SAPI::Env::get(SAPI_Info& info) { |
| return info.get_env(); | return info.get_env(); |
| } | } |
| Line 175 size_t SAPI::send_body(SAPI_Info& info, | Line 180 size_t SAPI::send_body(SAPI_Info& info, |
| } | } |
| static void full_file_spec(const char* file_name, char *buf, size_t buf_size) { | static void full_file_spec(const char* file_name, char *buf, size_t buf_size) { |
| if(file_name) | if(file_name[0]=='/' |
| if(file_name[0]=='/' | |
| #ifdef WIN32 | #ifdef WIN32 |
| || file_name[0] && file_name[1]==':' | || file_name[0] && file_name[1]==':' |
| #endif | #endif |
| ){ | ){ |
| strncpy(buf, file_name, buf_size-1); buf[buf_size-1]=0; | strncpy(buf, file_name, buf_size-1); buf[buf_size-1]=0; |
| } else { | } else { |
| char cwd[MAX_STRING]; | char cwd[MAX_STRING]; |
| snprintf(buf, buf_size, "%s/%s", getcwd(cwd, MAX_STRING) ? cwd : "", file_name); | snprintf(buf, buf_size, "%s/%s", getcwd(cwd, MAX_STRING) ? cwd : "", file_name); |
| } | } |
| else | |
| buf[0]=0; | |
| #ifdef WIN32 | #ifdef WIN32 |
| back_slashes_to_slashes(buf); | back_slashes_to_slashes(buf); |
| #endif | #endif |
| Line 291 static bool locate_config(){ | Line 293 static bool locate_config(){ |
| return true; | return true; |
| } | } |
| static void connection_handler(SAPI_Info_HTTPD &info, HTTPD_Connection &connection, const char* filespec_to_process){ | static void connection_handler(SAPI_Info_HTTPD &info, HTTPD_Connection &connection){ |
| connection.read_header(); | connection.read_header(); |
| info.populate_env(); | info.populate_env(); |
| // connection request info | // connection request info, still global for correct log() reporting |
| Request_info request_info; memset(&request_info, 0, sizeof(request_info)); | memset(&request_info, 0, sizeof(request_info)); |
| char document_root_buf[MAX_STRING]; | char document_root_buf[MAX_STRING]; |
| full_file_spec("", document_root_buf, sizeof(document_root_buf)); | full_file_spec("", document_root_buf, sizeof(document_root_buf)); |
| Line 316 static void connection_handler(SAPI_Info | Line 318 static void connection_handler(SAPI_Info |
| { | { |
| // initing ::request ptr for signal handlers | // initing ::request ptr for signal handlers |
| RequestController rc(&request); | RequestController rc(&request); |
| bool fail_on_config_read_problem=locate_config(); | // process the request, we need @httpd-main in auto.p if filespec_to_process not specified |
| // process the request | request.core(locate_config() || !filespec_to_process ? config_filespec_cstr : NULL, strcasecmp(request_info.method, "HEAD")==0, String("httpd-main")); |
| request.core(config_filespec_cstr, fail_on_config_read_problem, strcasecmp(request_info.method, "HEAD")==0); | |
| // clearing ::request in RequestController desctructor to prevent signal handlers from accessing invalid memory | // clearing ::request in RequestController desctructor to prevent signal handlers from accessing invalid memory |
| } | } |
| } | } |
| static void httpd_mode(const char* filespec_to_process){ | static void httpd_mode(){ |
| int sock = HTTPD_Server::bind(httpd_host_port); | int sock = HTTPD_Server::bind(httpd_host_port); |
| while(1){ | while(1){ |
| HTTPD_Connection *connection = HTTPD_Server::accept(sock, 5); | try { |
| if(!connection) | HTTPD_Connection connection; |
| continue; | if(!connection.accept(sock, 5)) |
| continue; | |
| SAPI_Info_HTTPD info(*connection); | |
| SAPI_Info_HTTPD info(connection); | |
| try { // connection try | |
| connection_handler(info, *connection, filespec_to_process); | try { // connection try |
| } catch(const Exception& e) { // exception in unhandled exception | connection_handler(info, connection); |
| // info.die(e); | } catch(const Exception& e) { // exception in connection handling or unhandled exception |
| SAPI::log(info, "%s", e.comment()); | |
| SAPI::send_error(info, e.comment(), info.exception_http_status(e.type())); | |
| } | |
| // closing connection socket in HTTPD_Connection destructor | |
| } catch(const Exception& e) { // exception in accept or send_error | |
| SAPI::log(*sapiInfo, "%s", e.comment()); | |
| } | } |
| close(connection->sock); | |
| } | } |
| } | } |
| /** main workhorse */ | /** main workhorse */ |
| static void real_parser_handler(const char* filespec_to_process) { | static void real_parser_handler() { |
| // init libraries | // init libraries |
| pa_globals_init(); | pa_globals_init(); |
| if(httpd_host_port){ | if(httpd_host_port){ |
| httpd_mode(filespec_to_process); | httpd_mode(); |
| } | } |
| const char* request_method=getenv("REQUEST_METHOD"); | const char* request_method=getenv("REQUEST_METHOD"); |
| if(!filespec_to_process || !*filespec_to_process) | if(!filespec_to_process) |
| SAPI::die("Parser/%s", PARSER_VERSION); | SAPI::die("Parser/%s", PARSER_VERSION); |
| char document_root_buf[MAX_STRING]; | char document_root_buf[MAX_STRING]; |
| Line 424 static void real_parser_handler(const ch | Line 429 static void real_parser_handler(const ch |
| } | } |
| request_info.content_type = getenv("CONTENT_TYPE"); | request_info.content_type = getenv("CONTENT_TYPE"); |
| request_info.content_length = pa_atoui(getenv("CONTENT_LENGTH"), 10); | request_info.content_length = pa_atoul(getenv("CONTENT_LENGTH")); |
| request_info.cookie = getenv("HTTP_COOKIE"); | request_info.cookie = getenv("HTTP_COOKIE"); |
| request_info.mail_received = mail_received; | request_info.mail_received = mail_received; |
| Line 449 static void real_parser_handler(const ch | Line 454 static void real_parser_handler(const ch |
| { | { |
| // initing ::request ptr for signal handlers | // initing ::request ptr for signal handlers |
| RequestController rc(&request); | RequestController rc(&request); |
| bool fail_on_config_read_problem=locate_config(); | |
| // process the request | // process the request |
| request.core(config_filespec_cstr, fail_on_config_read_problem, strcasecmp(request_info.method, "HEAD")==0); | request.core(locate_config() ? config_filespec_cstr : NULL, strcasecmp(request_info.method, "HEAD")==0); |
| // clearing ::request in RequestController desctructor to prevent signal handlers from accessing invalid memory | // clearing ::request in RequestController destructor to prevent signal handlers from accessing invalid memory |
| } | } |
| // finalize libraries | // finalize libraries |
| Line 460 static void real_parser_handler(const ch | Line 464 static void real_parser_handler(const ch |
| } | } |
| #ifdef PA_SUPPRESS_SYSTEM_EXCEPTION | #ifdef PA_SUPPRESS_SYSTEM_EXCEPTION |
| static const Exception call_real_parser_handler__do_PEH_return_it(const char* filespec_to_process) { | static const Exception call_real_parser_handler__do_PEH_return_it() { |
| try { | try { |
| real_parser_handler(filespec_to_process); | real_parser_handler(); |
| } catch(const Exception& e) { | } catch(const Exception& e) { |
| return e; | return e; |
| } | } |
| Line 470 static const Exception call_real_parser_ | Line 474 static const Exception call_real_parser_ |
| return Exception(); | return Exception(); |
| } | } |
| static void call_real_parser_handler__supress_system_exception(const char* filespec_to_process) { | static void call_real_parser_handler__supress_system_exception() { |
| Exception parser_exception; | Exception parser_exception; |
| LPEXCEPTION_POINTERS system_exception=0; | LPEXCEPTION_POINTERS system_exception=0; |
| __try { | __try { |
| parser_exception=call_real_parser_handler__do_PEH_return_it(filespec_to_process); | parser_exception=call_real_parser_handler__do_PEH_return_it(); |
| } __except ( (system_exception=GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER) { | } __except ( (system_exception=GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER) { |
| if(system_exception) | if(system_exception) |
| if(_EXCEPTION_RECORD *er=system_exception->ExceptionRecord) | if(_EXCEPTION_RECORD *er=system_exception->ExceptionRecord) |
| Line 501 static void usage(const char* program) { | Line 505 static void usage(const char* program) { |
| "Copyright (c) 2001-2017 Art. Lebedev Studio (http://www.artlebedev.com)\n" | "Copyright (c) 2001-2017 Art. Lebedev Studio (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 [options] file\n" | "Usage: %s [options] [file]\n" |
| "Options are:\n" | "Options are:\n" |
| #ifdef WITH_MAILRECEIVE | #ifdef WITH_MAILRECEIVE |
| " -m Parse mail, put received letter to $mail:received\n" | " -m Parse mail, put received letter to $mail:received\n" |
| Line 536 int main(int argc, char *argv[]) { | Line 540 int main(int argc, char *argv[]) { |
| SAPI::die("Can not set handler for SIGPIPE"); | SAPI::die("Can not set handler for SIGPIPE"); |
| #endif | #endif |
| char *raw_filespec_to_process; | char *raw_filespec_to_process = NULL; |
| if(cgi) { | if(cgi) { |
| raw_filespec_to_process=getenv("PATH_TRANSLATED"); | raw_filespec_to_process=getenv("PATH_TRANSLATED"); |
| if(raw_filespec_to_process && !*raw_filespec_to_process) | |
| raw_filespec_to_process=0; | |
| } else { | } else { |
| int optind=1; | int optind=1; |
| while(optind < argc){ | while(optind < argc){ |
| Line 616 int main(int argc, char *argv[]) { | Line 618 int main(int argc, char *argv[]) { |
| _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR ); | _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR ); |
| #endif | #endif |
| char filespec_to_process[MAX_STRING]; | char filespec_to_process_buf[MAX_STRING]; |
| full_file_spec(raw_filespec_to_process, filespec_to_process, sizeof(filespec_to_process)); | if(raw_filespec_to_process && *raw_filespec_to_process){ |
| full_file_spec(raw_filespec_to_process, filespec_to_process_buf, sizeof(filespec_to_process_buf)); | |
| filespec_to_process=filespec_to_process_buf; | |
| } | |
| try { // global try | try { // global try |
| REAL_PARSER_HANDLER(filespec_to_process); | REAL_PARSER_HANDLER(); |
| } catch(const Exception& e) { // exception in unhandled exception | } catch(const Exception& e) { // exception in unhandled exception |
| SAPI::die("%s", e.comment()); | SAPI::die("%s", e.comment()); |
| } | } |
| Line 628 int main(int argc, char *argv[]) { | Line 633 int main(int argc, char *argv[]) { |
| #ifdef PA_DEBUG_CGI_ENTRY_EXIT | #ifdef PA_DEBUG_CGI_ENTRY_EXIT |
| log("main: successful return"); | log("main: successful return"); |
| #endif | #endif |
| return sapiInfo && sapiInfo->http_response_code < 100 ? sapiInfo->http_response_code : 0; | return sapiInfo->http_response_code < 100 ? sapiInfo->http_response_code : 0; |
| } | } |