Diff for /parser3/src/targets/cgi/parser3.C between versions 1.298 and 1.308

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;
 }  }

Removed from v.1.298  
changed lines
  Added in v.1.308


E-mail: