Diff for /parser3/src/targets/cgi/parser3.C between versions 1.216.2.9 and 1.236

version 1.216.2.9, 2003/02/19 16:22:56 version 1.236, 2005/01/19 15:48:25
Line 1 Line 1
 /** @file  /** @file
         Parser: scripting and CGI main.          Parser: scripting and CGI main.
   
         Copyright(c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com)          Copyright(c) 2001-2004 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)
 */  */
   
 static const char* IDENT_PARSER3_C="$Date$";  static const char * const IDENT_PARSER3_C="$Date$";
   
 #include "pa_config_includes.h"  #include "pa_config_includes.h"
   
 #if _MSC_VER  #if _MSC_VER
 #       include <new.h>  
 #       include <crtdbg.h>  #       include <crtdbg.h>
 #endif  #endif
   
Line 28  static const char* IDENT_PARSER3_C="$Dat Line 27  static const char* IDENT_PARSER3_C="$Dat
 #       include <getopt.h>  #       include <getopt.h>
 #endif  #endif
   
 //#define DEBUG_POOL_MALLOC  // defines
   
   // comment remove me after debugging
   //#define PA_DEBUG_CGI_ENTRY_EXIT       "c:\\parser\\debug-parser3.log"
   
   #if _MSC_VER && !defined(_DEBUG)
   #       define PA_SUPPRESS_SYSTEM_EXCEPTION
   #endif
   
 //#define DEBUG_MAILRECEIVE "mailreceive.eml"  //#define DEBUG_MAILRECEIVE "mailreceive.eml"
   
 // consts  // consts
   
 #define REDIRECT_PREFIX "REDIRECT_"  #define REDIRECT_PREFIX "REDIRECT_"
 #define PARSER_CONFIG_ENV_NAME "CGI_PARSER_CONFIG"  #define PARSER_CONFIG_ENV_NAME "CGI_PARSER_CONFIG"
   #define PARSER_LOG_ENV_NAME "CGI_PARSER_LOG"
   
 /// 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 48  static bool mail_received=false; ///< we Line 56  static bool mail_received=false; ///< we
   
 // for signal handlers  // for signal handlers
 Request *request=0;  Request *request=0;
   Request_info *request_info=0;
   bool execution_canceled=false;
   
 // SAPI  // SAPI
   
Line 57  static void log(const char* fmt, va_list Line 67  static void log(const char* fmt, va_list
         bool opened=false;          bool opened=false;
         FILE *f=0;          FILE *f=0;
   
         if(config_filespec_cstr) {          const char* log_by_env=getenv(PARSER_LOG_ENV_NAME);
           if(!log_by_env)
                   log_by_env=getenv(REDIRECT_PREFIX PARSER_LOG_ENV_NAME);
           if(log_by_env) {
                   f=fopen(log_by_env, "at");
                   opened=f!=0;
           }
   #ifdef PA_DEBUG_CGI_ENTRY_EXIT  
           f=fopen(PA_DEBUG_CGI_ENTRY_EXIT, "at");
           opened=f!=0;
   #endif
   
           if(!opened && config_filespec_cstr) {
                 char beside_config_path[MAX_STRING];                  char beside_config_path[MAX_STRING];
                 strncpy(beside_config_path, config_filespec_cstr, MAX_STRING-1);  beside_config_path[MAX_STRING-1]=0;                  strncpy(beside_config_path, config_filespec_cstr, MAX_STRING-1);  beside_config_path[MAX_STRING-1]=0;
                 if(!(                  if(!(
Line 84  static void log(const char* fmt, va_list Line 106  static void log(const char* fmt, va_list
         time_t t=time(0);          time_t t=time(0);
         if(const char* stamp=ctime(&t)) { // never saw that          if(const char* stamp=ctime(&t)) { // never saw that
                 if(size_t len=strlen(stamp)) // saw once stamp being =""                  if(size_t len=strlen(stamp)) // saw once stamp being =""
                         fprintf(f, "[%.*s] ", len-1, stamp);                          fprintf(f, "[%.*s] [%u] ", len-1, stamp,
                           (unsigned int)getpid()
                           );
         }          }
         // message          // message
   
Line 101  static void log(const char* fmt, va_list Line 125  static void log(const char* fmt, va_list
         else          else
                 fflush(f);                  fflush(f);
 }  }
   #ifdef PA_DEBUG_CGI_ENTRY_EXIT
   static void log(const char* fmt, ...) {
       va_list args;
           va_start(args,fmt);
           log(fmt, args);
           va_end(args);
   }
   #endif
   
 // appends to parser3.log located beside my binary if openable, to stderr otherwize  // appends to parser3.log located beside my binary if openable, to stderr otherwize
 void SAPI::log(SAPI_Info&, const char* fmt, ...) {  void SAPI::log(SAPI_Info&, const char* fmt, ...) {
Line 110  void SAPI::log(SAPI_Info&, const char* f Line 142  void SAPI::log(SAPI_Info&, const char* f
         va_end(args);          va_end(args);
 }  }
   
 void SAPI::die(const char* fmt, ...) {  static void die_or_abort(const char* fmt, va_list args, bool write_core) {
 #ifdef DEBUG_POOL_MALLOC  
         extern void log_pool_stats(Pool& pool);  
         log_pool_stats(SAPI_info);  
 #endif  
   
     va_list args;  
         va_start(args,fmt);  
         // log          // log
   
         // logging is more important than user           // logging is more important than user 
Line 130  void SAPI::die(const char* fmt, ...) { Line 155  void SAPI::die(const char* fmt, ...) {
         char body[MAX_STRING];          char body[MAX_STRING];
         int content_length=vsnprintf(body, MAX_STRING, fmt, args);          int content_length=vsnprintf(body, MAX_STRING, fmt, args);
   
         va_end(args);  
   
         // prepare header          // prepare header
         // let's be honest, that's bad we couldn't produce valid output          // let's be honest, that's bad we couldn't produce valid output
         SAPI::add_header_attribute(SAPI_info, "status", "500");          SAPI::add_header_attribute(SAPI_info, "status", "500");
Line 146  void SAPI::die(const char* fmt, ...) { Line 169  void SAPI::die(const char* fmt, ...) {
         // body          // body
         SAPI::send_body(SAPI_info, body, content_length);          SAPI::send_body(SAPI_info, body, content_length);
   
 #ifdef WIN32          // exit & try to produce core dump[unix] or invoke debugger[Win32 Debug version]
         // IIS with abort failes to show STDOUT, it just barks "abnormal program termination"          if(write_core) {
         exit(1);  #if defined(WIN32) && !defined(_DEBUG)
                   // IIS with abort failes to show STDOUT, it just barks "abnormal program termination"
                   exit(1);
 #else  #else
         // exit & try to produce core dump  #if _MSC_VER
         abort();                  _asm int 3;
   #endif
                   abort();
 #endif  #endif
           } 
           else
                   exit(1);
 }  }
   
 CharPtr SAPI::get_env(SAPI_Info& , const char* name) {  void SAPI::die(const char* fmt, ...) {
         if(char *local=getenv(name)) {      va_list args;
                 size_t size=strlen(local)+1;          va_start(args, fmt);
                 char *heap=new char[size];          die_or_abort(fmt, args, false/*write core?*/);
                 memcpy(heap, local, size);          va_end(args);
                 return CharPtr(heap);  }
         }  
   void SAPI::abort(const char* fmt, ...) {
       va_list args;
           va_start(args, fmt);
           die_or_abort(fmt, args, true/*write core?*/);
           va_end(args);
   }
   
   char* SAPI::get_env(SAPI_Info& , const char* name) {
           if(char *local=getenv(name))
                   return pa_strdup(local);
         else          else
                 return CharPtr(0);                  return 0;
 }  }
   
 const char* const *SAPI::environment(SAPI_Info&, Pool&) {  const char* const *SAPI::environment(SAPI_Info&) {
 #ifdef _MSC_VER  #ifdef _MSC_VER
         extern char **_environ;          extern char **_environ;
         return _environ;          return _environ;
Line 204  void SAPI::send_header(SAPI_Info& ) { Line 244  void SAPI::send_header(SAPI_Info& ) {
         }          }
 }  }
   
 void SAPI::send_body(SAPI_Info& , const void *buf, size_t size) {  size_t SAPI::send_body(SAPI_Info& , const void *buf, size_t size) {
         stdout_write(buf, size);          return stdout_write(buf, size);
 }  }
   
 //  //
Line 217  static void full_file_spec(const char* f Line 257  static void full_file_spec(const char* f
                         || file_name[0] && file_name[1]==':'                          || file_name[0] && file_name[1]==':'
 #endif  #endif
                         )                          )
                         strncpy(buf, file_name, buf_size);                                  strncpy(buf, file_name, buf_size);
                 else {                  else {
                         char cwd[MAX_STRING];  getcwd(cwd, MAX_STRING);                          char cwd[MAX_STRING];  getcwd(cwd, MAX_STRING);
                         snprintf(buf, buf_size, "%s/%s", cwd, file_name);                          snprintf(buf, buf_size, "%s/%s", cwd, file_name);
Line 230  static void full_file_spec(const char* f Line 270  static void full_file_spec(const char* f
 }  }
   
 static void log_signal(const char* signal_name) {  static void log_signal(const char* signal_name) {
         SAPI::log(SAPI_info, request? "%s received. uri=%s, qs=%s"          if(request_info)
                 :"%s received. no request being processed",                   SAPI::log(SAPI_info, "%s received while %s. uri=%s, method=%s, cl=%u",
                 signal_name,                          signal_name,
                 request && request->request_info.uri?request->request_info.uri:"-",                          request?"executing code":"reading data",
                 request && request->request_info.query_string?request->request_info.query_string:"-");                          request_info->uri,
                           request_info->method,
                           request_info->content_length);
           else
                   SAPI::log(SAPI_info, "%s received before or after processing request",
                           signal_name);
 }  }
   
 #ifdef SIGUSR1  #ifdef SIGUSR1
Line 246  static void SIGUSR1_handler(int /*sig*/) Line 291  static void SIGUSR1_handler(int /*sig*/)
 #ifdef SIGPIPE  #ifdef SIGPIPE
 static void SIGPIPE_handler(int /*sig*/){  static void SIGPIPE_handler(int /*sig*/){
         log_signal("SIGPIPE");          log_signal("SIGPIPE");
           execution_canceled=true;
         if(request)          if(request)
                 request->interrupt();                  request->set_interrupted(true);
   }
   #endif
   
   #ifdef WIN32
   const char* maybe_reconstruct_IIS_status_in_qs(const char* original) 
   {
           // 404;http://servername/page[?param=value...]
           // ';' should be urlencoded by HTTP standard, so we shouldn't get it from browser 
           // and can consider that as an indication that this is IIS way to report errors
   
           if(original 
                   && isdigit((unsigned char)original[0])
                   && isdigit((unsigned char)original[1])
                   && isdigit((unsigned char)original[2])
                   && original[3]==';') 
           {
                   size_t original_len=strlen(original);
           char* reconstructed=new(PointerFreeGC) char[original_len
                           +12/*IIS-STATUS=&*/
                           +14/*IIS-DOCUMENT=&*/
                           +1];
                   char* cur=reconstructed;
                   memcpy(cur, "IIS-STATUS=", 11);  cur+=11;
                   memcpy(cur, original, 3); cur+=3;
                   *cur++='&';
   
                   const char* qmark_at=strchr(original, '?');
                   memcpy(cur, "IIS-DOCUMENT=", 13);  cur+=13;
                   {
                           size_t value_len=(qmark_at? qmark_at-original: original_len)-4;
                           memcpy(cur, original+4, value_len);  cur+=value_len;
                   }
   
                   if(qmark_at) {
                           *cur++='&';
                           strcpy(cur, qmark_at+1/*skip ? itself*/);
                   } else
                           *cur=0;
   
                   return reconstructed;
           }
           
           return original;
 }  }
 #endif  #endif
   
Line 258  main workhorse Line 347  main workhorse
                 IIS: remove trailing default-document[index.html] from $request.uri.                  IIS: remove trailing default-document[index.html] from $request.uri.
                 to do that we need to consult metabase,                  to do that we need to consult metabase,
                 wich is tested but seems slow.                  wich is tested but seems slow.
                 IIS5 todo find out proper 'illegal call' check   
 */  */
 static void real_parser_handler(  static void real_parser_handler(const char* filespec_to_process,
                                         const char* filespec_to_process,                                  const char* request_method, bool header_only) 
                                         const char* request_method, bool header_only) {  {
         // init socks          // init socks
         pa_init_socks();          pa_socks_init();
           
         // init global variables          // init global variables
         pa_globals_init();          pa_globals_init();
                   
         // request pool, must be different ptr from global [used in VStateless_class.add_method]  
         Pool request_pool;  
   
         if(!filespec_to_process || !*filespec_to_process)          if(!filespec_to_process || !*filespec_to_process)
                 SAPI::die("Parser/%s", PARSER_VERSION);                  SAPI::die("Parser/%s"
   #ifdef PA_DEBUG_CGI_ENTRY_EXIT
                   " with entry/exit tracing"
   #endif
                   , PARSER_VERSION);
                   
         // Request info          // Request info
         Request_info request_info;          Request_info request_info;  memset(&request_info, 0, sizeof(request_info));
         char document_root_buf[MAX_STRING];          char document_root_buf[MAX_STRING];
         if(cgi) {          if(cgi) {
                 if(CharPtr env_document_root=SAPI::get_env(SAPI_info, "DOCUMENT_ROOT"))                  if(const char* env_document_root=getenv("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(SAPI_info, "PATH_INFO")) {                  else if(const char* path_info=getenv("PATH_INFO")) {
                         // IIS                          // IIS
                         size_t len=min(sizeof(document_root_buf)-1, strlen(filespec_to_process)-strlen(path_info));                          size_t len=min(sizeof(document_root_buf)-1, strlen(filespec_to_process)-strlen(path_info));
                         memcpy(document_root_buf, filespec_to_process, len); document_root_buf[len]=0;                          memcpy(document_root_buf, filespec_to_process, len); document_root_buf[len]=0;
                         request_info.document_root=document_root_buf;                          request_info.document_root=document_root_buf;
                 } else                  } else
                         throw Exception("parser.runtime",                          throw Exception("parser.runtime",
                                 Exception::undefined_source,                                  0,
                                 "CGI: no PATH_INFO defined(in reinventing DOCUMENT_ROOT)");                                  "CGI: no PATH_INFO defined(in reinventing DOCUMENT_ROOT)");
         } else {          } else {
                 full_file_spec("", document_root_buf, sizeof(document_root_buf));                  full_file_spec("", document_root_buf, sizeof(document_root_buf));
Line 296  static void real_parser_handler( Line 385  static void real_parser_handler(
         }          }
         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";
         const char* query_string=SAPI::get_env(SAPI_info, "QUERY_STRING");          const char* query_string=
   #ifdef WIN32
                   maybe_reconstruct_IIS_status_in_qs
   #endif
                   (getenv("QUERY_STRING"));
         request_info.query_string=query_string;          request_info.query_string=query_string;
         if(cgi) {          if(cgi) {
                 // few absolute obligatory                  // few absolute obligatory
                 const char* path_info=SAPI::get_env(SAPI_info, "PATH_INFO");                  const char* path_info=getenv("PATH_INFO");
                 if(!path_info)                  if(!path_info)
                         SAPI::die("CGI: illegal call (missing PATH_INFO)");                          SAPI::die("CGI: illegal call (missing PATH_INFO)");
                 const char* script_name=SAPI::get_env(SAPI_info, "SCRIPT_NAME");                  const char* script_name=getenv("SCRIPT_NAME");
                 if(!script_name)                  if(!script_name)
                                 SAPI::die("CGI: illegal call (missing SCRIPT_NAME)");                                  SAPI::die("CGI: illegal call (missing SCRIPT_NAME)");
   
                 const char* env_request_uri=SAPI::get_env(SAPI_info, "REQUEST_URI");                  const char* env_request_uri=getenv("REQUEST_URI");
                 if(env_request_uri)                  if(env_request_uri)
                         request_info.uri=env_request_uri;                          request_info.uri=env_request_uri;
                 else                   else 
                         if(query_string) {                          if(query_string) {
                                 char *reconstructed_uri=new(request_pool) char[                                  char* reconstructed_uri=new(PointerFreeGC) char[
                                         strlen(path_info)+1/*'?'*/+                                          strlen(path_info)+1/*'?'*/+
                                         strlen(query_string)+1/*0*/];                                          strlen(query_string)+1/*0*/];
                                 strcpy(reconstructed_uri, path_info);                                  strcpy(reconstructed_uri, path_info);
Line 361  static void real_parser_handler( Line 454  static void real_parser_handler(
         } else          } else
                 request_info.uri="";                  request_info.uri="";
                   
         request_info.content_type=SAPI::get_env(SAPI_info, "CONTENT_TYPE");          request_info.content_type=getenv("CONTENT_TYPE");
         const char* content_length=SAPI::get_env(SAPI_info, "CONTENT_LENGTH");          const char* content_length=getenv("CONTENT_LENGTH");
         request_info.content_length=(content_length?atoi(content_length):0);          request_info.content_length=(content_length?atoi(content_length):0);
         request_info.cookie=SAPI::get_env(SAPI_info, "HTTP_COOKIE");          request_info.cookie=getenv("HTTP_COOKIE");
         request_info.mail_received=mail_received;          request_info.mail_received=mail_received;
   
           // get request_info ptr for signal handlers
           ::request_info=&request_info;
           if(execution_canceled)
                   SAPI::die("Execution canceled");
   
   #ifdef PA_DEBUG_CGI_ENTRY_EXIT
           log("request_info: method=%s, uri=%s, q=%s, dr=%s, pt=%s, cookies=%s, cl=%u", 
                   request_info.method,
                   request_info.uri,
                   request_info.query_string,
                   request_info.document_root,
                   request_info.path_translated,
                   request_info.cookie,
                   request_info.content_length);
   #endif
   
         // prepare to process request          // prepare to process request
         Request request(request_pool, SAPI_info,           Request request(SAPI_info, request_info,
                 request_info,                  cgi ? String::Language(String::L_HTML|String::L_OPTIMIZE_BIT) : String::L_AS_IS,
 /*#ifdef _DEBUG  
                 String::UL_HTML|String::UL_OPTIMIZE_BIT  
 #else*/  
                 cgi ? String::UL_HTML|String::UL_OPTIMIZE_BIT : String::UL_AS_IS  
 /*#endif*/  
                 ,  
                 true /* status_allowed */);                  true /* status_allowed */);
   
         // get request ptr for signal handlers          // get request ptr for signal handlers
Line 415  static void real_parser_handler( Line 517  static void real_parser_handler(
   
         // no request [prevent signal handlers from accessing invalid memory]          // no request [prevent signal handlers from accessing invalid memory]
         ::request=0;          ::request=0;
           
           // finalize global variables
           pa_globals_done();
   
         //          //
         pa_done_socks();          pa_socks_done();
           
 #ifdef DEBUG_POOL_MALLOC  
         extern void log_pool_stats(Pool& pool);  
         log_pool_stats(request_pool);  
 #endif  
 }  }
   
 static void call_real_parser_handler__do_SEH(  #ifdef PA_SUPPRESS_SYSTEM_EXCEPTION
                                                                  const char* filespec_to_process,  static const Exception 
                                                                  const char* request_method, bool header_only) {  call_real_parser_handler__do_PEH_return_it(
 #if _MSC_VER && !defined(_DEBUG)          const char* filespec_to_process,
           const char* request_method, bool header_only) 
   {
           try {
                   real_parser_handler(
                           filespec_to_process,
                           request_method, header_only);
           } catch(const Exception& e) {
                   return e;
           }
   
           return Exception();
   }
   static void call_real_parser_handler__supress_system_exception(
           const char* filespec_to_process,
           const char* request_method, bool header_only) 
   {
           Exception parser_exception;
         LPEXCEPTION_POINTERS system_exception=0;          LPEXCEPTION_POINTERS system_exception=0;
   
         __try {          __try {
 #endif                  parser_exception=call_real_parser_handler__do_PEH_return_it(
                 real_parser_handler(  
                         filespec_to_process,                          filespec_to_process,
                         request_method, header_only);                          request_method, header_only);
                   
 #if _MSC_VER && !defined(_DEBUG)  
         } __except (          } __except (
                 (system_exception=GetExceptionInformation()),                   (system_exception=GetExceptionInformation()), 
                 EXCEPTION_EXECUTE_HANDLER) {                  EXCEPTION_EXECUTE_HANDLER) 
                           {
   
                 if(system_exception)                  if(system_exception)
                         if(_EXCEPTION_RECORD *er=system_exception->ExceptionRecord)                          if(_EXCEPTION_RECORD *er=system_exception->ExceptionRecord)
                                 throw Exception(0,                                  throw Exception("system",
                                         0,                                          0,
                                         "Exception 0x%08X at 0x%08X", er->ExceptionCode,  er->ExceptionAddress);                                          "0x%08X at 0x%08X", er->ExceptionCode,  er->ExceptionAddress);
                         else  
                                 throw Exception(0, 0, "Exception <no exception record>");  
                         else                          else
                                 throw Exception(0, 0, "Exception <no exception information>");                                  throw Exception("system", 
                                           0, 
                                           "<no exception record>");
                   else
                           throw Exception("system", 
                                   0, 
                                   "<no exception information>");
         }          }
 #endif  
 }  
   
 #if _MSC_VER  
 int failed_new(size_t size) {  
         SAPI::die("out of memory in 'new', failed to allocated %u bytes", size);  
         return 0; // not reached  
 }  
 #endif  
   
 #ifdef HAVE_SET_NEW_HANDLER          if(parser_exception)
 static void failed_new() {                  throw Exception(parser_exception);
     SAPI::die("out of memory in 'new'");  
 }  }
 #endif  #endif
   
 static void usage(const char* program) {  static void usage(const char* program) {
         printf(          printf(
                 "Parser/%s Copyright(c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com)\n"                  "Parser/%s\n"
                   "Copyright(c) 2001-2004 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 [options] file\n"                  "Usage: %s [options] file\n"
Line 485  static void usage(const char* program) { Line 596  static void usage(const char* program) {
 }  }
   
 int main(int argc, char *argv[]) {  int main(int argc, char *argv[]) {
   #ifdef PA_DEBUG_CGI_ENTRY_EXIT
           log("main: entry");
   #endif
           //_asm int 3;
           GC_java_finalization=0;
   
   #ifndef PA_DEBUG_DISABLE_GC
           // Dont collect unless explicitly requested 
           // this is quicker (~30% ), but less memory-efficient(~8%)
           // so deciding for speed
           GC_dont_gc=1; 
   #endif
   /*
           
           Array<int> test;
           test+=3;
           test+=4;
   //      int a=test.count();
           int i=0;
           scanf("%d", &i);
           int b=test.get(i);
   //      int b=test.get(10);
           printf("%d", b);//test.count());*/
   
 #ifdef SIGUSR1  #ifdef SIGUSR1
     if(signal(SIGUSR1, SIGUSR1_handler)==SIG_ERR)      if(signal(SIGUSR1, SIGUSR1_handler)==SIG_ERR)
                 SAPI::die("Can not set handler for SIGUSR1");                  SAPI::die("Can not set handler for SIGUSR1");
Line 502  int main(int argc, char *argv[]) { Line 637  int main(int argc, char *argv[]) {
 #endif  #endif
   
 #ifdef _DEBUG  #ifdef _DEBUG
         //_crtBreakAlloc=4042;          //_crtBreakAlloc=46;
 #endif  #endif
 //      _asm int 3;  
         argv0=argv[0];          argv0=argv[0];
   
         umask(2);          umask(2);
Line 562  int main(int argc, char *argv[]) { Line 696  int main(int argc, char *argv[]) {
         setmode(fileno(stderr), _O_BINARY);          setmode(fileno(stderr), _O_BINARY);
 #endif  #endif
   
 #if _MSC_VER  #if defined(_MSC_VER) && defined(_DEBUG)
         _set_new_handler(failed_new);  
   
 #ifdef _DEBUG  
         // Get current flag          // Get current flag
         int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );          int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
   
Line 574  int main(int argc, char *argv[]) { Line 705  int main(int argc, char *argv[]) {
   
         // Set flag to the new value          // Set flag to the new value
         _CrtSetDbgFlag( tmpFlag );          _CrtSetDbgFlag( tmpFlag );
 //      _CrtSetBreakAlloc(471);  //      _CrtSetBreakAlloc(61);
   
 #endif  
   
 #endif  
   
 #ifdef HAVE_SET_NEW_HANDLER          _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
         std::set_new_handler(failed_new);          _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR );
 #endif  #endif
   
         char filespec_to_process[MAX_STRING];          char filespec_to_process[MAX_STRING];
Line 591  int main(int argc, char *argv[]) { Line 718  int main(int argc, char *argv[]) {
         bool header_only=request_method && strcasecmp(request_method, "HEAD")==0;          bool header_only=request_method && strcasecmp(request_method, "HEAD")==0;
   
         try { // global try          try { // global try
                 call_real_parser_handler__do_SEH(  #ifdef PA_SUPPRESS_SYSTEM_EXCEPTION
                   call_real_parser_handler__supress_system_exception(
   #else
                   real_parser_handler(
   #endif
                         filespec_to_process,                          filespec_to_process,
                         request_method, header_only);                          request_method, header_only);
         } catch(const Exception& e) { // global problem           } catch(const Exception& e) { // global problem 
                 // don't allocate anything on pool here:                  // don't allocate anything on pool here:
                 //   possible pool' exception not catch-ed now                  //   possible pool' exception not catch-ed now
                 //   and there could be out-of-memory exception                  //   and there could be out-of-memory exception
                   char buf[MAX_STRING];
                   snprintf(buf, MAX_STRING, "Unhandled exception %s",
                           e.comment());
                   // log it
                   SAPI::log(SAPI_info, "%s", buf);
   
                   //
                   int content_length=strlen(buf);
   
                   // prepare header
                   SAPI::add_header_attribute(SAPI_info, "content-type", "text/plain");
                   char content_length_cstr[MAX_NUMBER];
                   snprintf(content_length_cstr, MAX_NUMBER, "%u", content_length);
                   SAPI::add_header_attribute(SAPI_info, "content-length", content_length_cstr);
   
                   // send header
                   SAPI::send_header(SAPI_info);
   
                   // send body
                   if(!header_only)
                           SAPI::send_body(SAPI_info, buf, content_length);
   
                 SAPI::die("exception in request exception handler: %s", e.comment());                  // unsuccessful finish
 #ifndef _DEBUG  
         } catch(...) {   
                 SAPI::die("<unknown exception>");  
 #endif  
         }          }
   
         //_asm int 3;  #ifdef PA_DEBUG_CGI_ENTRY_EXIT
           log("main: successful return");
   #endif
         return 0;          return 0;
 }  }

Removed from v.1.216.2.9  
changed lines
  Added in v.1.236


E-mail: