Diff for /parser3/src/targets/cgi/parser3.C between versions 1.216.2.2 and 1.216.2.30.2.12

version 1.216.2.2, 2003/01/31 16:05:59 version 1.216.2.30.2.12, 2003/03/27 15:44:00
Line 10  static const char* IDENT_PARSER3_C="$Dat Line 10  static const char* IDENT_PARSER3_C="$Dat
 #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 21  static const char* IDENT_PARSER3_C="$Dat Line 20  static const char* IDENT_PARSER3_C="$Dat
 #include "pa_socks.h"  #include "pa_socks.h"
 #include "pa_version.h"  #include "pa_version.h"
   
 #include "pool_storage.h"  
   
 #ifdef WIN32  #ifdef WIN32
 #       include <windows.h>  #       include <windows.h>
Line 31  static const char* IDENT_PARSER3_C="$Dat Line 30  static const char* IDENT_PARSER3_C="$Dat
 #endif  #endif
   
 //#define DEBUG_POOL_MALLOC  //#define DEBUG_POOL_MALLOC
 //#define DEBUG_STRING_APPENDS_VS_EXPANDS  
 //#define DEBUG_MAILRECEIVE "mailreceive.eml"  //#define DEBUG_MAILRECEIVE "mailreceive.eml"
   
 #ifdef DEBUG_STRING_APPENDS_VS_EXPANDS  
 extern ulong   
         string_piece_appends,   
         wcontext_result_size,  
         total_alloc_size,  
         string_string_shortcut_economy;  
 #endif  
   
 // consts  // consts
   
 #define REDIRECT_PREFIX "REDIRECT_"  #define REDIRECT_PREFIX "REDIRECT_"
Line 54  static const char* argv0; Line 44  static const char* argv0;
 static const char* config_filespec_cstr=0;  static const char* config_filespec_cstr=0;
 static bool fail_on_config_read_problem=true;  static bool fail_on_config_read_problem=true;
   
 static Pool_storage global_pool_storage; ///< global pool storage  
 static Pool global_pool(&global_pool_storage); ///< global pool  
 static bool cgi; ///< we were started as CGI?  static bool cgi; ///< we were started as CGI?
 static bool mail_received=false; ///< we were started with -m option? [asked to parse incoming message to $mail:received]  static bool mail_received=false; ///< we were started with -m option? [asked to parse incoming message to $mail:received]
   
 // for signal handlers  // for signal handlers
 Request *request=0;  Request *request=0;
   Request_info *request_info=0;
   bool execution_canceled=false;
   
 // SAPI  // SAPI
   
   class SAPI_Info{} SAPI_info;
   
 static void log(const char* fmt, va_list args) {  static void log(const char* fmt, va_list args) {
         bool opened=false;          bool opened=false;
         FILE *f=0;          FILE *f=0;
Line 114  static void log(const char* fmt, va_list Line 106  static void log(const char* fmt, va_list
 }  }
   
 // 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(Pool& , const char* fmt, ...) {  void SAPI::log(SAPI_Info&, const char* fmt, ...) {
     va_list args;      va_list args;
         va_start(args,fmt);          va_start(args,fmt);
         ::log(fmt, args);          ::log(fmt, args);
         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) {
           //_asm int 3;
 #ifdef DEBUG_POOL_MALLOC  #ifdef DEBUG_POOL_MALLOC
         extern void log_pool_stats(Pool& pool);          extern void log_pool_stats();
         log_pool_stats(global_pool);          log_pool_stats(SAPI_info);
 #endif  #endif
   
     va_list args;  
         va_start(args,fmt);  
         // log          // log
   
         // logging is more important than user           // logging is more important than user 
Line 141  void SAPI::die(const char* fmt, ...) { Line 132  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(global_pool, "status", "500");          SAPI::add_header_attribute(SAPI_info, "status", "500");
         SAPI::add_header_attribute(global_pool, "content-type", "text/plain");          SAPI::add_header_attribute(SAPI_info, "content-type", "text/plain");
         char content_length_cstr[MAX_NUMBER];          char content_length_cstr[MAX_NUMBER];
         snprintf(content_length_cstr, sizeof(content_length_cstr), "%u", content_length);          snprintf(content_length_cstr, sizeof(content_length_cstr), "%u", content_length);
         SAPI::add_header_attribute(global_pool, "content-length", content_length_cstr);          SAPI::add_header_attribute(SAPI_info, "content-length", content_length_cstr);
   
         // send header          // send header
         SAPI::send_header(global_pool);          SAPI::send_header(SAPI_info);
   
         // body          // body
         SAPI::send_body(global_pool, 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)
                   //_asm int 3;
                   // IIS with abort failes to show STDOUT, it just barks "abnormal program termination"
                   exit(1);
 #else  #else
         // exit & try to produce core dump                  abort();
         abort();  
 #endif  #endif
           } 
           else
                   exit(1);
   }
   
   void SAPI::die(const char* fmt, ...) {
       va_list args;
           va_start(args, fmt);
           die_or_abort(fmt, args, false/*write core?*/);
           va_end(args);
   }
   
   void SAPI::abort(const char* fmt, ...) {
       va_list args;
           va_start(args, fmt);
           die_or_abort(fmt, args, true/*write core?*/);
           va_end(args);
 }  }
   
 const char* SAPI::get_env(Pool& , const char* name) {  char* SAPI::get_env(SAPI_Info& , const char* name) {
         return getenv(name);          if(char *local=getenv(name))
                   return pa_strdup(local);
           else
                   return 0;
 }  }
   
 const char* const *SAPI::environment(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 180  const char* const *SAPI::environment(Poo Line 191  const char* const *SAPI::environment(Poo
 #endif  #endif
 }  }
   
 size_t SAPI::read_post(Pool& , char *buf, size_t max_bytes) {  size_t SAPI::read_post(SAPI_Info& , char *buf, size_t max_bytes) {
         size_t read_size=0;          size_t read_size=0;
         do {          do {
                 ssize_t chunk_size=read(fileno(stdin),                   ssize_t chunk_size=read(fileno(stdin), 
Line 193  size_t SAPI::read_post(Pool& , char *buf Line 204  size_t SAPI::read_post(Pool& , char *buf
         return read_size;          return read_size;
 }  }
   
 void SAPI::add_header_attribute(Pool& , const char* dont_store_key, const char* dont_store_value) {  void SAPI::add_header_attribute(SAPI_Info& , const char* dont_store_key, const char* dont_store_value) {
         if(cgi)          if(cgi)
                 printf("%s: %s\n", dont_store_key, dont_store_value);                  printf("%s: %s\n", dont_store_key, dont_store_value);
 }  }
   
 /// @todo intelligent cache-control  /// @todo intelligent cache-control
 void SAPI::send_header(Pool& ) {  void SAPI::send_header(SAPI_Info& ) {
         if(cgi) {          if(cgi) {
 //              puts("expires: Fri, 23 Mar 2001 09:32:23 GMT");  //              puts("expires: Fri, 23 Mar 2001 09:32:23 GMT");
   
Line 208  void SAPI::send_header(Pool& ) { Line 219  void SAPI::send_header(Pool& ) {
         }          }
 }  }
   
 void SAPI::send_body(Pool& , const void *buf, size_t size) {  void SAPI::send_body(SAPI_Info& , const void *buf, size_t size) {
         stdout_write(buf, size);          stdout_write(buf, size);
 }  }
   
Line 234  static void full_file_spec(const char* f Line 245  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(global_pool, 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, qs=%s, cl=%u",
                 signal_name,                          signal_name,
                 request && request->info.uri?request->info.uri:"-",                          request?"executing code":"reading data",
                 request && request->info.query_string?request->info.query_string:"-");                          request_info->uri,
                           request_info->method,
                           request_info->query_string,
                           request_info->content_length);
           else
                   SAPI::log(SAPI_info, "%s received before or after processing request",
                           signal_name);
 }  }
   
 #ifdef SIGUSR1  #ifdef SIGUSR1
Line 250  static void SIGUSR1_handler(int /*sig*/) Line 267  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  #endif
   
Line 262  main workhorse Line 280  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
         init_socks(global_pool);          pa_init_socks();
                   
         // init global classes  
         init_methoded_array(global_pool);  
         // init global variables          // init global variables
         pa_globals_init(global_pool);          pa_globals_init();
                   
         // request pool, must be different ptr from global [used in VStateless_class.add_method]  
         Pool request_pool(&global_pool_storage);  
   
         if(!filespec_to_process || !*filespec_to_process)          if(!filespec_to_process || !*filespec_to_process)
                 SAPI::die("Parser/%s", PARSER_VERSION);                  SAPI::die("Parser/%s", PARSER_VERSION);
                   
         // Request info          // Request info
         Request::Info request_info;          Request_info request_info;
         char document_root_buf[MAX_STRING];          char document_root_buf[MAX_STRING];
         if(cgi) {          if(cgi) {
                 if(const char* env_document_root=SAPI::get_env(request_pool, "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(request_pool, "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;
Line 302  static void real_parser_handler( Line 314  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(request_pool, "QUERY_STRING");          const char* query_string=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(request_pool, "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(request_pool, "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(request_pool, "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=(char *)request_pool.malloc(                                  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);
                                 strcat(reconstructed_uri, "?");                                  strcat(reconstructed_uri, "?");
                                 strcat(reconstructed_uri, query_string);                                  strcat(reconstructed_uri, query_string);
Line 367  static void real_parser_handler( Line 379  static void real_parser_handler(
         } else          } else
                 request_info.uri="";                  request_info.uri="";
                   
         request_info.content_type=SAPI::get_env(request_pool, "CONTENT_TYPE");          request_info.content_type=getenv("CONTENT_TYPE");
         const char* content_length=SAPI::get_env(request_pool, "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(request_pool, "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");
   
         // prepare to process request          // prepare to process request
         Request request(request_pool,          Request request(SAPI_info, 
                 request_info,                  request_info,
 /*#ifdef _DEBUG  /*#ifdef _DEBUG
                 String::UL_HTML|String::UL_OPTIMIZE_BIT                  String::L_HTML|String::L_OPTIMIZE_BIT
 #else*/  #else*/
                 cgi ? String::UL_HTML|String::UL_OPTIMIZE_BIT : String::UL_AS_IS                  cgi ? String::Language(String::L_HTML|String::L_OPTIMIZE_BIT) : String::L_AS_IS
 /*#endif*/  /*#endif*/
                 ,                  ,
                 true /* status_allowed */);                  true /* status_allowed */);
Line 423  static void real_parser_handler( Line 439  static void real_parser_handler(
         ::request=0;          ::request=0;
                   
         //          //
         done_socks();          pa_done_socks();
                   
 #ifdef DEBUG_POOL_MALLOC  #ifdef DEBUG_POOL_MALLOC
         extern void log_pool_stats(Pool& pool);          extern void log_pool_stats();
         log_pool_stats(request_pool);          log_pool_stats(request_pool);
 #endif  #endif
   }
   
 #ifdef DEBUG_STRING_APPENDS_VS_EXPANDS  #if _MSC_VER && !defined(_DEBUG)
         SAPI::log(global_pool,   #       define PA_USE___TRY
                 "string piece appends=%lu, wcontext_result_size=%lu, string_string_shortcut_economy_closer=%lu, total_alloc_size=%lu",   struct Parser_executed {
                 string_piece_appends,          bool with_system_exception;
                 wcontext_result_size,          LPEXCEPTION_POINTERS system_exception;
                 string_string_shortcut_economy,  };
                 total_alloc_size);  
 #endif  #endif
   
 }  static 
   #ifdef PA_USE___TRY
 static void call_real_parser_handler__do_SEH(  Parser_executed 
   #else
   void
   #endif
   call_real_parser_handler__do_SEH_return_it(
                                                                  const char* filespec_to_process,                                                                   const char* filespec_to_process,
                                                                  const char* request_method, bool header_only) {                                                                   const char* request_method, bool header_only) {
 #if _MSC_VER && !defined(_DEBUG)  #ifdef PA_USE___TRY
         LPEXCEPTION_POINTERS system_exception=0;          Parser_executed result={false};
         __try {          __try {
 #endif  #endif
                 real_parser_handler(                  real_parser_handler(
                         filespec_to_process,                          filespec_to_process,
                         request_method, header_only);                          request_method, header_only);
                                   
 #if _MSC_VER && !defined(_DEBUG)  #ifdef PA_USE___TRY
         } __except (          } __except (
                 (system_exception=GetExceptionInformation()),                   (result.system_exception=GetExceptionInformation()), 
                 EXCEPTION_EXECUTE_HANDLER) {                  EXCEPTION_EXECUTE_HANDLER) {
                                   //_asm int 3;
                 if(system_exception)                  result.with_system_exception=true;
                         if(_EXCEPTION_RECORD *er=system_exception->ExceptionRecord)  
                                 throw Exception(0,  
                                         0,  
                                         "Exception 0x%08X at 0x%08X", er->ExceptionCode,  er->ExceptionAddress);  
                         else  
                                 throw Exception(0, 0, "Exception <no exception record>");  
                         else  
                                 throw Exception(0, 0, "Exception <no exception information>");  
         }          }
           return result;
 #endif  #endif
 }  }
   
 #if _MSC_VER  static void call_real_parser_handler__do_SEH(
 int failed_new(size_t size) {                                                                   const char* filespec_to_process,
         SAPI::die("out of memory in 'new', failed to allocated %u bytes", size);                                                                   const char* request_method, bool header_only) {
         return 0; // not reached  #ifdef PA_USE___TRY
 }          Parser_executed executed=
 #endif  #endif
                   call_real_parser_handler__do_SEH_return_it(filespec_to_process, 
                           request_method, header_only);
   
 #ifdef HAVE_SET_NEW_HANDLER  #ifdef PA_USE___TRY
 static void failed_new() {          if(executed.with_system_exception)
     SAPI::die("out of memory in 'new'");                  if(executed.system_exception)
 }                          if(_EXCEPTION_RECORD *er=executed.system_exception->ExceptionRecord)
                                   throw Exception(0,
                                           0,
                                           "Exception 0x%08X at 0x%08X", er->ExceptionCode,  er->ExceptionAddress);
                           else
                                   throw Exception(0, 
                                           0, 
                                           "Exception <no exception record>");
                   else
                           throw Exception(0, 
                                   0, 
                                   "Exception <no exception information>");
 #endif  #endif
   }
   
 static void usage(const char* program) {  static void usage(const char* program) {
         printf(          printf(
Line 501  static void usage(const char* program) { Line 528  static void usage(const char* program) {
 }  }
   
 int main(int argc, char *argv[]) {  int main(int argc, char *argv[]) {
           GC_java_finalization=0;
   
           /*
   #ifndef PA_DEBUG_DISABLE_GC
           GC_dont_gc=1; // Dont collect unless explicitly requested
   #endif
           */
   
   /*      Array<int> test;
           test+=3;
           test+=4;
   //      int a=test.count();
           int b=test.get(0);
   //      int b=test.get(10);
           printf("%d", test.count(),b);*/
 #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 518  int main(int argc, char *argv[]) { Line 560  int main(int argc, char *argv[]) {
 #endif  #endif
   
 #ifdef _DEBUG  #ifdef _DEBUG
 //      _crtBreakAlloc=33112;          //_crtBreakAlloc=4042;
 #endif  #endif
 //      _asm int 3;          //_asm int 3;
         argv0=argv[0];          argv0=argv[0];
   
         umask(2);          umask(2);
Line 578  int main(int argc, char *argv[]) { Line 620  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 590  int main(int argc, char *argv[]) { Line 629  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(62143); //147302
   
 #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 616  int main(int argc, char *argv[]) { Line 651  int main(int argc, char *argv[]) {
                 //   and there could be out-of-memory exception                  //   and there could be out-of-memory exception
   
                 SAPI::die("exception in request exception handler: %s", e.comment());                  SAPI::die("exception in request exception handler: %s", e.comment());
 #ifndef _DEBUG  
         } catch(...) {   
                 SAPI::die("<unknown exception>");  
 #endif  
         }          }
   
         //_asm int 3;  //      _asm int 3;
         return 0;          return 0;
 }  }

Removed from v.1.216.2.2  
changed lines
  Added in v.1.216.2.30.2.12


E-mail: