Diff for /parser3/src/targets/cgi/parser3.C between versions 1.104 and 1.216.2.8

version 1.104, 2001/09/04 15:56:10 version 1.216.2.8, 2003/02/19 16:19:01
Line 1 Line 1
 /** @file  /** @file
         Parser: scripting and CGI main.          Parser: scripting and CGI main.
   
         Copyright(c) 2001 ArtLebedev Group(http://www.artlebedev.com)          Copyright(c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com)
           Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
         Author: Alexander Petrosyan <paf@design.ru>(http://design.ru/paf)  
 */  */
 static const char *RCSId="$Id$";   
   static const char* IDENT_PARSER3_C="$Date$";
   
 #include "pa_config_includes.h"  #include "pa_config_includes.h"
   
 #ifdef WIN32  #if _MSC_VER
 #       include <windows.h>  #       include <new.h>
   #       include <crtdbg.h>
 #endif  #endif
   
 #include "pa_sapi.h"  #include "pa_sapi.h"
Line 20  static const char *RCSId="$Id$"; Line 21  static const char *RCSId="$Id$";
 #include "pa_socks.h"  #include "pa_socks.h"
 #include "pa_version.h"  #include "pa_version.h"
   
   #ifdef WIN32
   #       include <windows.h>
   #       include "getopt.h"
   #else
   #       include <getopt.h>
   #endif
   
 //#define DEBUG_POOL_MALLOC  //#define DEBUG_POOL_MALLOC
   //#define DEBUG_MAILRECEIVE "mailreceive.eml"
   
   // consts
   
   #define REDIRECT_PREFIX "REDIRECT_"
   #define PARSER_CONFIG_ENV_NAME "CGI_PARSER_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 
   
 const char *argv0;  static const char* argv0;
 Pool pool(0); // global pool [dont describe to doxygen: it confuses it with param names]  static const char* config_filespec_cstr=0;
 bool cgi; ///< we were started as CGI?  static bool fail_on_config_read_problem=true;
   
 #ifdef WIN32  static bool cgi; ///< we were started as CGI?
 /// global system errors into parser exceptions converter  static bool mail_received=false; ///< we were started with -m option? [asked to parse incoming message to $mail:received]
 static LONG WINAPI TopLevelExceptionFilter(struct _EXCEPTION_POINTERS *ExceptionInfo) {  
         char buf[MAX_STRING];  
         if(ExceptionInfo && ExceptionInfo->ExceptionRecord) {  
                 struct _EXCEPTION_RECORD *er=ExceptionInfo->ExceptionRecord;  
                 snprintf(buf, MAX_STRING, "Exception 0x%X at %p",   
                         er->ExceptionCode,   
                         er->ExceptionAddress);  
         } else   
                 strcpy(buf, "Exception <unknown>");  
           
         PTHROW(0, 0,  
                 0,  
                 buf);  
   
         return EXCEPTION_EXECUTE_HANDLER; // never reached  // for signal handlers
 }  Request *request=0;
 #endif  
   
 // SAPI  // SAPI
   
 // appends to parser3.log located beside my binary if openable, to stderr otherwize  class SAPI_Info{} SAPI_info;
 void SAPI::log(Pool& pool, const char *fmt, ...) {  
         bool opened;  static void log(const char* fmt, va_list args) {
           bool opened=false;
         FILE *f=0;          FILE *f=0;
   
         if(argv0) {          if(config_filespec_cstr) {
                 // beside by binary                  char beside_config_path[MAX_STRING];
                   strncpy(beside_config_path, config_filespec_cstr, MAX_STRING-1);  beside_config_path[MAX_STRING-1]=0;
                   if(!(
                           rsplit(beside_config_path, '/') || 
                           rsplit(beside_config_path, '\\'))) { // strip filename
                           // no path, just filename
                           beside_config_path[0]='.'; beside_config_path[1]=0;
                   }
   
                 char file_spec[MAX_STRING];                  char file_spec[MAX_STRING];
                 strncpy(file_spec, argv0, MAX_STRING-1);  file_spec[MAX_STRING-1]=0; // filespec of my binary                  snprintf(file_spec, MAX_STRING, 
                 rsplit(file_spec, '/');  rsplit(file_spec, '\\');// strip filename                          "%s/parser3.log", beside_config_path);
                 strcat(file_spec, "/parser3.log");  
                 f=fopen(file_spec, "at");                  f=fopen(file_spec, "at");
                   opened=f!=0;
         }          }
         opened=f!=0;          // fallback to stderr
         if(!opened)          if(!opened)
                 f=stderr;                  f=stderr;
   
           // use no memory [so that we could log out-of-memory error]
           setbuf(f, 0); // stderr stream is unbuffered by default, but still...
   
         // prefix          // prefix
         time_t t=time(0);          time_t t=time(0);
         const char *stamp=ctime(&t);          if(const char* stamp=ctime(&t)) { // never saw that
         fprintf(f, "[%.*s] ", strlen(stamp)-1, stamp);                  if(size_t len=strlen(stamp)) // saw once stamp being =""
                           fprintf(f, "[%.*s] ", len-1, stamp);
           }
         // message          // message
     va_list args;  
         va_start(args,fmt);          char buf[MAX_STRING];
         vfprintf(f, fmt, args);          size_t size=vsnprintf(buf, MAX_STRING, fmt, args);
         va_end(args);          remove_crlf(buf, buf+size);
   
           fwrite(buf, size, 1, f);
         // newline          // newline
         fprintf(f, "\n");          fprintf(f, "\n");
   
Line 87  void SAPI::log(Pool& pool, const char *f Line 102  void SAPI::log(Pool& pool, const char *f
                 fflush(f);                  fflush(f);
 }  }
   
 const char *SAPI::get_env(Pool& pool, const char *name) {  // appends to parser3.log located beside my binary if openable, to stderr otherwize
         return getenv(name);  void SAPI::log(SAPI_Info&, const char* fmt, ...) {
       va_list args;
           va_start(args,fmt);
           ::log(fmt, args);
           va_end(args);
 }  }
   
 size_t SAPI::read_post(Pool& pool, char *buf, size_t max_bytes) {  void SAPI::die(const char* fmt, ...) {
   #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
   
           // logging is more important than user 
           // she can cancel download, we'd get SIGPIPE, 
           // nothing would be logged then
           ::log(fmt, args);
   
           // inform user
   
           char body[MAX_STRING];
           int content_length=vsnprintf(body, MAX_STRING, fmt, args);
   
           va_end(args);
   
           // prepare header
           // 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, "content-type", "text/plain");
           char content_length_cstr[MAX_NUMBER];
           snprintf(content_length_cstr, sizeof(content_length_cstr), "%u", content_length);
           SAPI::add_header_attribute(SAPI_info, "content-length", content_length_cstr);
   
           // send header
           SAPI::send_header(SAPI_info);
   
           // body
           SAPI::send_body(SAPI_info, body, content_length);
   
   #ifdef WIN32
           // IIS with abort failes to show STDOUT, it just barks "abnormal program termination"
           exit(1);
   #else
           // exit & try to produce core dump
           abort();
   #endif
   }
   
   CharPtr SAPI::get_env(SAPI_Info& , const char* name) {
           if(char *local=getenv(name)) {
                   size_t size=strlen(local)+1;
                   char *heap=new char[size];
                   memcpy(heap, local, size);
                   return CharPtr(heap);
           }
           else
                   return CharPtr(0);
   }
   
   const char* const *SAPI::environment(SAPI_Info&, Pool&) {
   #ifdef _MSC_VER
           extern char **_environ;
           return _environ;
   #else
           extern char **environ;
           return environ;
   #endif
   }
   
   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 {
                 int chunk_size=read(fileno(stdin),                   ssize_t chunk_size=read(fileno(stdin), 
                         buf+read_size, min(READ_POST_CHUNK_SIZE, max_bytes-read_size));                          buf+read_size, min(READ_POST_CHUNK_SIZE, max_bytes-read_size));
                 if(chunk_size<0)                  if(chunk_size<=0)
                         break;                          break;
                 read_size+=chunk_size;                  read_size+=chunk_size;
         } while(read_size<max_bytes);          } while(read_size<max_bytes);
Line 104  size_t SAPI::read_post(Pool& pool, char Line 189  size_t SAPI::read_post(Pool& pool, char
         return read_size;          return read_size;
 }  }
   
 void SAPI::add_header_attribute(Pool& pool, const char *key, const char *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", key, value);                  printf("%s: %s\n", dont_store_key, dont_store_value);
 }  }
   
 /// @todo intelligent cache-control  /// @todo intelligent cache-control
 void SAPI::send_header(Pool& 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");
   
                 // header | body  delimiter                  // header | body  delimiter
                 puts("");                  puts("");
         }          }
 }  }
   
 void SAPI::send_body(Pool& 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);
 }  }
   
 //  //
   
 char *full_file_spec(char *file_name) {  static void full_file_spec(const char* file_name, char *buf, size_t buf_size) {
         if(!strchr(file_name, '/')) {          if(file_name)
                 static char cwd[MAX_STRING];  getcwd(cwd, MAX_STRING);                  if(file_name[0]=='/' 
                 static char buf[MAX_STRING];  #ifdef WIN32
                 snprintf(buf, MAX_STRING, "%s/%s", cwd, file_name);                          || file_name[0] && file_name[1]==':'
                 return buf;  #endif
         }                          )
         return file_name;                          strncpy(buf, file_name, buf_size);
                   else {
                           char cwd[MAX_STRING];  getcwd(cwd, MAX_STRING);
                           snprintf(buf, buf_size, "%s/%s", cwd, file_name);
                   }
           else
                   buf[0]=0;
   #ifdef WIN32
           back_slashes_to_slashes(buf);
   #endif
 }  }
   
   static void log_signal(const char* signal_name) {
           SAPI::log(SAPI_info, request? "%s received. uri=%s, qs=%s"
                   :"%s received. no request being processed", 
                   signal_name,
                   request && request->request_info.uri?request->request_info.uri:"-",
                   request && request->request_info.query_string?request->request_info.query_string:"-");
   }
   
   #ifdef SIGUSR1
   static void SIGUSR1_handler(int /*sig*/){
           log_signal("SIGUSR1");
   }
   #endif
   
   #ifdef SIGPIPE
   static void SIGPIPE_handler(int /*sig*/){
           log_signal("SIGPIPE");
           if(request)
                   request->interrupt();
   }
   #endif
   
 /**  /**
         main workhorse  main workhorse
   
         @todo     @todo 
                 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(
                                           const char* filespec_to_process,
                                           const char* request_method, bool header_only) {
           // init socks
           pa_init_socks();
           
           // init global variables
           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)
                   SAPI::die("Parser/%s", PARSER_VERSION);
           
           // Request info
           Request_info request_info;
           char document_root_buf[MAX_STRING];
           if(cgi) {
                   if(CharPtr env_document_root=SAPI::get_env(SAPI_info, "DOCUMENT_ROOT"))
                           request_info.document_root=env_document_root;
                   else if(const char* path_info=SAPI::get_env(SAPI_info, "PATH_INFO")) {
                           // IIS
                           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;
                           request_info.document_root=document_root_buf;
                   } else
                           throw Exception("parser.runtime",
                                   Exception::undefined_source,
                                   "CGI: no PATH_INFO defined(in reinventing DOCUMENT_ROOT)");
           } else {
                   full_file_spec("", document_root_buf, sizeof(document_root_buf));
                   request_info.document_root=document_root_buf;
           }
           request_info.path_translated=filespec_to_process;
           request_info.method=request_method ? request_method : "GET";
           const char* query_string=SAPI::get_env(SAPI_info, "QUERY_STRING");
           request_info.query_string=query_string;
           if(cgi) {
                   // few absolute obligatory
                   const char* path_info=SAPI::get_env(SAPI_info, "PATH_INFO");
                   if(!path_info)
                           SAPI::die("CGI: illegal call (missing PATH_INFO)");
                   const char* script_name=SAPI::get_env(SAPI_info, "SCRIPT_NAME");
                   if(!script_name)
                                   SAPI::die("CGI: illegal call (missing SCRIPT_NAME)");
   
                   const char* env_request_uri=SAPI::get_env(SAPI_info, "REQUEST_URI");
                   if(env_request_uri)
                           request_info.uri=env_request_uri;
                   else 
                           if(query_string) {
                                   char *reconstructed_uri=new(request_pool) char[
                                           strlen(path_info)+1/*'?'*/+
                                           strlen(query_string)+1/*0*/];
                                   strcpy(reconstructed_uri, path_info);
                                   strcat(reconstructed_uri, "?");
                                   strcat(reconstructed_uri, query_string);
                                   request_info.uri=reconstructed_uri;
                           } else
                                   request_info.uri=path_info;
   
                   if(env_request_uri) { // apache & others stuck to standards
                           /*
                                   http://parser3/env.html?123  =OK
                                   $request:uri=/env.html?123
                                   REQUEST_URI='/env.html?123'
                                   SCRIPT_NAME='/cgi-bin/parser3'
                                   PATH_INFO='/env.html'
   
                                   http://parser3/cgi-bin/parser3/env.html?123 =ERROR
                                   $request:uri=/cgi-bin/parser3/env.html?123
                                   REQUEST_URI='/cgi-bin/parser3/env.html?123'
                                   SCRIPT_NAME='/cgi-bin/parser3'
                                   PATH_INFO='/env.html'
                           */
                           size_t script_name_len=strlen(script_name);
                           size_t uri_len=strlen(env_request_uri);
                           if(strncmp(env_request_uri, script_name, script_name_len)==0 &&
                                   script_name_len != uri_len) // under IIS they are the same
                                   SAPI::die("CGI: illegal call (1)");
                   } else { // seen on IIS5
                           /*
                                   http://nestle/env.html?123 =OK
                                   $request:uri=/env.html?123
                                   REQUEST_URI=''
                                   SCRIPT_NAME='/env.html'
                                   PATH_INFO='/env.html'
   
                                   http://nestle/cgi-bin/parser3.exe/env.html =ERROR
                                   $request:uri=/env.html
                                   REQUEST_URI=''
                                   SCRIPT_NAME='/cgi-bin/parser3.exe'
                                   PATH_INFO='/env.html'
                           */
                           if(strcmp(script_name, path_info)!=0)
                                   SAPI::die("CGI: illegal call (2)");
                   }
           } else
                   request_info.uri="";
           
           request_info.content_type=SAPI::get_env(SAPI_info, "CONTENT_TYPE");
           const char* content_length=SAPI::get_env(SAPI_info, "CONTENT_LENGTH");
           request_info.content_length=(content_length?atoi(content_length):0);
           request_info.cookie=SAPI::get_env(SAPI_info, "HTTP_COOKIE");
           request_info.mail_received=mail_received;
   
   
           // prepare to process request
           Request request(request_pool, SAPI_info, 
                   request_info,
   /*#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 */);
   
           // get request ptr for signal handlers
           ::request=&request;
   
           char config_filespec_buf[MAX_STRING];
           if(!config_filespec_cstr) {
                   const char* config_by_env=getenv(PARSER_CONFIG_ENV_NAME);
                   if(!config_by_env)
                           config_by_env=getenv(REDIRECT_PREFIX PARSER_CONFIG_ENV_NAME);
                   if(config_by_env)
                           config_filespec_cstr=config_by_env;
                   else {
                           // beside by binary
                           char beside_binary_path[MAX_STRING];
                           strncpy(beside_binary_path, argv0, MAX_STRING-1);  beside_binary_path[MAX_STRING-1]=0; // filespec of my binary
                           if(!(
                                   rsplit(beside_binary_path, '/') || 
                                   rsplit(beside_binary_path, '\\'))) { // strip filename
                                   // no path, just filename
                                   // @todo full path, not ./!
                                   beside_binary_path[0]='.'; beside_binary_path[1]=0;
                           }
                           snprintf(config_filespec_buf, MAX_STRING, 
                                   "%s/%s", 
                                   beside_binary_path, AUTO_FILE_NAME);
                           config_filespec_cstr=config_filespec_buf;
                           fail_on_config_read_problem=entry_exists(config_filespec_cstr);
                   }
           }
           
           // process the request
           request.core(
                   config_filespec_cstr, fail_on_config_read_problem,
                   header_only);
   
           // no request [prevent signal handlers from accessing invalid memory]
           ::request=0;
           
           //
           pa_done_socks();
           
   #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(
                                                                    const char* filespec_to_process,
                                                                    const char* request_method, bool header_only) {
   #if _MSC_VER && !defined(_DEBUG)
           LPEXCEPTION_POINTERS system_exception=0;
           __try {
   #endif
                   real_parser_handler(
                           filespec_to_process,
                           request_method, header_only);
                   
   #if _MSC_VER && !defined(_DEBUG)
           } __except (
                   (system_exception=GetExceptionInformation()), 
                   EXCEPTION_EXECUTE_HANDLER) {
                   
                   if(system_exception)
                           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>");
           }
   #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
   static void failed_new() {
       SAPI::die("out of memory in 'new'");
   }
   #endif
   
   static void usage(const char* program) {
           printf(
                   "Parser/%s Copyright(c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com)\n"
                   "Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)\n"
                   "\n"
                   "Usage: %s [options] file\n"
                   "Options are:\n"
   #ifdef WITH_MAILRECEIVE
                   "    -m              Parse mail, put received letter to $mail:received\n"
   #endif
                   "    -f config_file  Use this config file (/path/to/auto.p)\n"
                   "    -h              Display usage information (this message)\n"
                   , PARSER_VERSION, 
                   program);
           exit(EINVAL);
   }
   
 int main(int argc, char *argv[]) {  int main(int argc, char *argv[]) {
   #ifdef SIGUSR1
       if(signal(SIGUSR1, SIGUSR1_handler)==SIG_ERR)
                   SAPI::die("Can not set handler for SIGUSR1");
   #endif
   #ifdef SIGPIPE
       if(signal(SIGPIPE, SIGPIPE_handler)==SIG_ERR)
                   SAPI::die("Can not set handler for SIGPIPE");
   #endif
   
   
   #ifdef DEBUG_MAILRECEIVE
           if(FILE *fake_in=fopen(DEBUG_MAILRECEIVE, "rt")) {
                   dup2(fake_in->_file, 0/*STDIN_FILENO*/);
           }
   #endif
   
   #ifdef _DEBUG
           _crtBreakAlloc=4042;
   #endif
   //      _asm int 3;
         argv0=argv[0];          argv0=argv[0];
   
         umask(2);          umask(2);
Line 155  int main(int argc, char *argv[]) { Line 516  int main(int argc, char *argv[]) {
                 getenv("GATEWAY_INTERFACE") ||                   getenv("GATEWAY_INTERFACE") || 
                 getenv("REQUEST_METHOD");                  getenv("REQUEST_METHOD");
                   
         if(!cgi) {          char *raw_filespec_to_process;
                 if(argc<2) {          if(cgi) {
                         printf(                  raw_filespec_to_process=getenv("PATH_TRANSLATED");
                                 "Parser/%s Copyright(c) 2001 ArtLebedev Group(http://www.artlebedev.com)\n"                  if(raw_filespec_to_process && !*raw_filespec_to_process)
                                 "Author: Alexander Petrosyan <paf@design.ru>(http://design.ru/paf)\n"                          raw_filespec_to_process=0;
                                 "\n"          } else {
                                 "Usage: %s <file>\n",                  optind = 1;
                                 PARSER_VERSION,                   opterr = 0;
                                 argv0?argv0:"parser3");                  int c;
                         return 1;                  while((c = getopt(argc, argv, "hf:"
   #ifdef WITH_MAILRECEIVE
                           "m"
   #endif
                           )) > 0) {
                           switch (c) {
                           case 'h':
                                   usage(argv[0]);
                                   break;
                           case 'f':
                                   config_filespec_cstr=optarg;
                                   break;
   #ifdef WITH_MAILRECEIVE
                           case 'm':
                                   mail_received=true;
                                   break;
   #endif
                           default:
                                   fprintf(stderr, "%s: invalid option '%c'\n", argv[0], optopt);
                                   usage(argv[0]);
                                   break;
                           }
                   }
                   if (optind != argc - 1) {
                           fprintf(stderr, "%s: file not specified\n", argv[0]);
                           usage(argv[0]);
                 }                  }
                   
                   raw_filespec_to_process=argv[optind++];
         }          }
   
 #ifdef WIN32  #ifdef WIN32
Line 174  int main(int argc, char *argv[]) { Line 562  int main(int argc, char *argv[]) {
         setmode(fileno(stderr), _O_BINARY);          setmode(fileno(stderr), _O_BINARY);
 #endif  #endif
   
         char *filespec_to_process=cgi?getenv("PATH_TRANSLATED"):argv[1];  #if _MSC_VER
 #ifdef WIN32          _set_new_handler(failed_new);
         back_slashes_to_slashes(filespec_to_process);  
 #endif  
         filespec_to_process=full_file_spec(filespec_to_process);  
   
         const char *request_method=getenv("REQUEST_METHOD");  #ifdef _DEBUG
         bool header_only=request_method && strcasecmp(request_method, "HEAD")==0;          // Get current flag
         PTRY { // global try          int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
                 // must be first in PTRY{}PCATCH  
 #ifdef WIN32  
                 SetUnhandledExceptionFilter(&TopLevelExceptionFilter);  
 #endif  
   
                 // init socks          // Turn on leak-checking bit
                 init_socks(pool);          tmpFlag |= _CRTDBG_LEAK_CHECK_DF;
   
                 // init global classes          // Set flag to the new value
                 init_methoded_array(pool);          _CrtSetDbgFlag( tmpFlag );
                 // init global variables  //      _CrtSetBreakAlloc(471);
                 pa_globals_init(pool);  
   
                 if(!filespec_to_process)  
                         PTHROW(0, 0,  
                                 0,  
                                 "Parser/%s", PARSER_VERSION);  
   
                 // Request info  
                 Request::Info request_info;  
                 if(cgi) {  
                         if(const char *env_document_root=SAPI::get_env(pool, "DOCUMENT_ROOT"))  
                                 request_info.document_root=env_document_root;  
                         else if(const char *path_info=SAPI::get_env(pool, "PATH_INFO")) {  
                                 // IIS  
                                 size_t len=strlen(filespec_to_process)-strlen(path_info);  
                                 char *buf=(char *)pool.malloc(len+1);  
                                 memcpy(buf, filespec_to_process, len); buf[len]=0;  
                                 request_info.document_root=buf;  
                         } else  
                                 PTHROW(0, 0,  
                                         0,  
                                         "CGI: no PATH_INFO defined(in reinventing DOCUMENT_ROOT)");  
                 } else {  
                         static char buf[MAX_STRING];  
                         strncpy(buf, filespec_to_process, MAX_STRING-1); buf[MAX_STRING-1]=0;  
                         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.method=request_method;  
                 const char *query_string=SAPI::get_env(pool, "QUERY_STRING");  
                 request_info.query_string=query_string;  
                 if(cgi) {  
                         if(const char *env_request_uri=SAPI::get_env(pool, "REQUEST_URI"))  
                                 request_info.uri=env_request_uri;  
                         else if(const char *path_info=SAPI::get_env(pool, "PATH_INFO"))  
                                 if(query_string) {  
                                         char *reconstructed_uri=(char *)malloc(  
                                                 strlen(path_info)+1/*'?'*/+  
                                                 strlen(query_string)+1/*0*/);  
                                         strcpy(reconstructed_uri, path_info);  
                                         strcat(reconstructed_uri, "?");  
                                         strcat(reconstructed_uri, query_string);  
                                         request_info.uri=reconstructed_uri;  
                                 } else  
                                         request_info.uri=path_info;  
                         else  
                                 PTHROW(0, 0,  
                                         0,  
                                         "CGI: no PATH_INFO defined(in reinventing REQUEST_URI)");  
   
                         if(const char *script_name=SAPI::get_env(pool, "SCRIPT_NAME")) {  
                                 size_t script_name_len=strlen(script_name);  
                                 size_t uri_len=strlen(request_info.uri);  
                                 if(strncmp(request_info.uri,script_name, script_name_len)==0 &&  
                                         script_name_len != uri_len) // under IIS they are the same  
                                         PTHROW(0, 0,  
                                                 0,  
                                                 "CGI: illegal call");  
                         }  
                 } else  
                         request_info.uri=0;  
   
                 request_info.content_type=SAPI::get_env(pool, "CONTENT_TYPE");  
                 const char *content_length=SAPI::get_env(pool, "CONTENT_LENGTH");  
                 request_info.content_length=(content_length?atoi(content_length):0);  
                 request_info.cookie=SAPI::get_env(pool, "HTTP_COOKIE");  
                 request_info.user_agent=SAPI::get_env(pool, "HTTP_USER_AGENT");  
   
                 // prepare to process request  
                 Request request(pool,  
                         request_info,  
                         cgi ? String::UL_USER_HTML : String::UL_AS_IS  
                         );  
                   
                 // some root-controlled location  
 #ifdef SYSCONFDIR  
                 const char *root_auto_path=SYSCONFDIR;  
 #else  
 #       ifdef WIN32  
                 // c:\windows  
                 static char root_auto_path[MAX_STRING];  
                 GetWindowsDirectory(root_auto_path, MAX_STRING);  
 #       else  
                 #error must be compiled either configure/make or MSVC++  
 #       endif  
 #endif  #endif
                   
                 // beside by binary  
                 static char site_auto_path[MAX_STRING];  
                 strncpy(site_auto_path, argv0, MAX_STRING-1);  site_auto_path[MAX_STRING-1]=0; // filespec of my binary  
                 if(!(  
                         rsplit(site_auto_path, '/') ||   
                         rsplit(site_auto_path, '\\'))) { // strip filename  
                         // no path, just filename  
                         site_auto_path[0]='.'; site_auto_path[1]=0;  
                 }  
                   
                 // process the request  
                 request.core(  
                         root_auto_path, false,  
                         site_auto_path, false,  
                         header_only);  
   
                 //  
                 done_socks();  
   
 #ifdef DEBUG_POOL_MALLOC  
                 extern void log_pool_stats(Pool& pool);  
                 log_pool_stats(pool);  
 #endif  #endif
   
                 // must be last in PTRY{}PCATCH  #ifdef HAVE_SET_NEW_HANDLER
 #ifdef WIN32          std::set_new_handler(failed_new);
                 SetUnhandledExceptionFilter(0);  
 #endif  #endif
   
 #ifndef WIN32          char filespec_to_process[MAX_STRING];
                 //           full_file_spec(raw_filespec_to_process, filespec_to_process, sizeof(filespec_to_process));
                 if(!cgi)  
                         SAPI::send_body(pool, "\n", 1);  
 #endif  
   
                 // successful finish          const char* request_method=getenv("REQUEST_METHOD");
                 return 0;          bool header_only=request_method && strcasecmp(request_method, "HEAD")==0;
         } PCATCH(e) { // global problem   
                 // must be first in PCATCH{}          try { // global try
 #ifdef WIN32                  call_real_parser_handler__do_SEH(
                 SetUnhandledExceptionFilter(0);                          filespec_to_process,
 #endif                          request_method, header_only);
           } 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
   
                 const char *body=e.comment();                  SAPI::die("exception in request exception handler: %s", e.comment());
                 // log it  #ifndef _DEBUG
                 SAPI::log(pool, "exception in request exception handler: %s", body);          } catch(...) { 
                   SAPI::die("<unknown exception>");
                 //  
                 int content_length=strlen(body);  
   
                 // prepare header  
                 SAPI::add_header_attribute(pool, "content-type", "text/plain");  
                 char content_length_cstr[MAX_NUMBER];  
                 snprintf(content_length_cstr, MAX_NUMBER, "%u", content_length);  
                 SAPI::add_header_attribute(pool, "content-length", content_length_cstr);  
   
                 // send header  
                 SAPI::send_header(pool);  
   
                 // body  
                 if(!header_only)  
                         SAPI::send_body(pool, body, content_length);  
   
 #ifndef WIN32  
                 //   
                 if(!cgi)  
                         SAPI::send_body(pool, "\n", 1);  
 #endif  #endif
   
                 // unsuccessful finish  
                 return 1;  
         }          }
         PEND_CATCH  
           //_asm int 3;
           return 0;
 }  }

Removed from v.1.104  
changed lines
  Added in v.1.216.2.8


E-mail: