Diff for /parser3/src/targets/cgi/parser3.C between versions 1.126 and 1.216.2.15

version 1.126, 2001/10/29 13:04:47 version 1.216.2.15, 2003/02/21 12:15:13
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: Alexander Petrosyan <paf@design.ru>(http://design.ru/paf)          Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
   
         $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 <crtdbg.h>
 #endif  #endif
   
 #include "pa_sapi.h"  #include "pa_sapi.h"
Line 19 Line 19
 #include "pa_request.h"  #include "pa_request.h"
 #include "pa_socks.h"  #include "pa_socks.h"
 #include "pa_version.h"  #include "pa_version.h"
 #include "pool_storage.h"  
   
 #ifdef XML  #ifdef WIN32
 #include <XalanTransformer/XalanCAPI.h>  #       include <windows.h>
   #       include "getopt.h"
   #else
   #       include <getopt.h>
 #endif  #endif
   
 #define DEBUG_POOL_MALLOC  //#define DEBUG_POOL_MALLOC
   //#define DEBUG_MAILRECEIVE "mailreceive.eml"
   
 // consts  // consts
   
 extern const char *main_RCSIds[];  #define REDIRECT_PREFIX "REDIRECT_"
 #ifdef USE_SMTP  #define PARSER_CONFIG_ENV_NAME "CGI_PARSER_CONFIG"
 extern const char *smtp_RCSIds[];  
 #endif  
 extern const char *gd_RCSIds[];  
 extern const char *classes_RCSIds[];  
 extern const char *types_RCSIds[];  
 extern const char *parser3_RCSIds[];  
 #ifdef XML  
 extern const char *xalan_patched_RCSIds[];  
 #endif  
 const char **RCSIds[]={  
         main_RCSIds,  
 #ifdef USE_SMTP  
         smtp_RCSIds,  
 #endif  
         gd_RCSIds,  
         classes_RCSIds,  
         types_RCSIds,  
         parser3_RCSIds,  
 #ifdef XML  
         xalan_patched_RCSIds,  
 #endif  
         0  
 };  
   
 /// 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_storage pool_storage;  static const char* config_filespec_cstr=0;
 Pool pool(&pool_storage); // global pool [dont describe to doxygen: it confuses it with param names]  static bool fail_on_config_read_problem=true;
 bool cgi; ///< we were started as CGI?  
   static bool force_header_output=false;
   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]
   
   // for signal handlers
   Request *request=0;
   
 // SAPI  // SAPI
   
 static void log(const char *fmt, va_list args) {  class SAPI_Info{} SAPI_info;
         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
   
         char buf[MAX_STRING];          char buf[MAX_STRING];
Line 102  static void log(const char *fmt, va_list Line 103  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, ...) {  void SAPI::die(const char* fmt, ...) {
           //_asm int 3;
   #ifdef DEBUG_POOL_MALLOC
           extern void log_pool_stats(Pool& pool);
           log_pool_stats(SAPI_info);
   #endif
   
     va_list args;      va_list args;
         va_start(args,fmt);          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);          ::log(fmt, args);
   
           // inform user
   
           char body[MAX_STRING];
           int content_length=vsnprintf(body, MAX_STRING, fmt, args);
   
         va_end(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
           //_asm int 3;
           // IIS with abort failes to show STDOUT, it just barks "abnormal program termination"
         exit(1);          exit(1);
   #else
           // exit & try to produce core dump
           abort();
   #endif
 }  }
   
 const char *SAPI::get_env(Pool& , const char *name) {  CharPtr SAPI::get_env(SAPI_Info& , const char* name) {
         return getenv(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(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 {
                 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 135  size_t SAPI::read_post(Pool& , char *buf Line 191  size_t SAPI::read_post(Pool& , char *buf
         return read_size;          return read_size;
 }  }
   
 void SAPI::add_header_attribute(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 || force_header_output)
                 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& ) {  void SAPI::send_header(SAPI_Info& ) {
         if(cgi) {          if(cgi || force_header_output) {
                 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& , 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(file_name && !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
Line 173  main workhorse Line 260  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 
 */  */
 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(pool);          pa_init_socks();
                   
 #ifdef XML  
         /**  
         * Initialize Xerces and Xalan.  
         *  
         * Should be called only once per process before making  
         * any other API calls.  
         */  
         //_asm int 3;  
         XalanInitialize();  
 #endif  
           
         // init global classes  
         init_methoded_array(pool);  
         // init global variables          // init global variables
         pa_globals_init(pool);          pa_globals_init();
                   
         if(!filespec_to_process)          // request pool, must be different ptr from global [used in VStateless_class.add_method]
                 throw Exception(0, 0,          Pool request_pool;
                 0,  
                 "Parser/%s", PARSER_VERSION);          if(!filespec_to_process || !*filespec_to_process)
                   SAPI::die("Parser/%s", PARSER_VERSION);
                   
         // Request info          // Request info
         Request::Info request_info;          Request_info request_info;
           char document_root_buf[MAX_STRING];
         if(cgi) {          if(cgi) {
                 if(const char *env_document_root=SAPI::get_env(pool, "DOCUMENT_ROOT"))                  if(CharPtr env_document_root=SAPI::get_env(SAPI_info, "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(pool, "PATH_INFO")) {                  else if(const char* path_info=SAPI::get_env(SAPI_info, "PATH_INFO")) {
                         // IIS                          // IIS
                         size_t len=strlen(filespec_to_process)-strlen(path_info);                          size_t len=min(sizeof(document_root_buf)-1, strlen(filespec_to_process)-strlen(path_info));
                         char *buf=(char *)pool.malloc(len+1);                          memcpy(document_root_buf, filespec_to_process, len); document_root_buf[len]=0;
                         memcpy(buf, filespec_to_process, len); buf[len]=0;                          request_info.document_root=document_root_buf;
                         request_info.document_root=buf;  
                 } else                  } else
                         throw Exception(0, 0,                          throw Exception("parser.runtime",
                         0,                                  Exception::undefined_source,
                         "CGI: no PATH_INFO defined(in reinventing DOCUMENT_ROOT)");                                  "CGI: no PATH_INFO defined(in reinventing DOCUMENT_ROOT)");
         } else {          } else {
                 static char buf[MAX_STRING];                  full_file_spec("", document_root_buf, sizeof(document_root_buf));
                 strncpy(buf, filespec_to_process, MAX_STRING-1); buf[MAX_STRING-1]=0;                  request_info.document_root=document_root_buf;
                 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.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(pool, "QUERY_STRING");          CharPtr query_string=SAPI::get_env(SAPI_info, "QUERY_STRING");
         request_info.query_string=query_string;          request_info.query_string=query_string;
         if(cgi) {          if(cgi) {
                 if(const char *env_request_uri=SAPI::get_env(pool, "REQUEST_URI"))                  // 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;                          request_info.uri=env_request_uri;
                 else if(const char *path_info=SAPI::get_env(pool, "PATH_INFO"))                  else 
                         if(query_string) {                          if(query_string) {
                                 char *reconstructed_uri=(char *)pool.malloc(                                  char *reconstructed_uri=new(request_pool) 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);
                                 request_info.uri=reconstructed_uri;                                  request_info.uri=reconstructed_uri;
                         } else                          } else
                                 request_info.uri=path_info;                                  request_info.uri=path_info;
                         else  
                                 throw Exception(0, 0,                  if(env_request_uri) { // apache & others stuck to standards
                                 0,                          /*
                                 "CGI: no PATH_INFO defined(in reinventing REQUEST_URI)");                                  http://parser3/env.html?123  =OK
                                                           $request:uri=/env.html?123
                         if(const char *script_name=SAPI::get_env(pool, "SCRIPT_NAME")) {                                  REQUEST_URI='/env.html?123'
                                 size_t script_name_len=strlen(script_name);                                  SCRIPT_NAME='/cgi-bin/parser3'
                                 size_t uri_len=strlen(request_info.uri);                                  PATH_INFO='/env.html'
                                 if(strncmp(request_info.uri,script_name, script_name_len)==0 &&  
                                         script_name_len != uri_len) // under IIS they are the same                                  http://parser3/cgi-bin/parser3/env.html?123 =ERROR
                                         throw Exception(0, 0,                                  $request:uri=/cgi-bin/parser3/env.html?123
                                         0,                                  REQUEST_URI='/cgi-bin/parser3/env.html?123'
                                         "CGI: illegal call");                                  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          } else
                 request_info.uri=0;                  request_info.uri="";
                   
         request_info.content_type=SAPI::get_env(pool, "CONTENT_TYPE");          request_info.content_type=SAPI::get_env(SAPI_info, "CONTENT_TYPE");
         const char *content_length=SAPI::get_env(pool, "CONTENT_LENGTH");          const char* content_length=SAPI::get_env(SAPI_info, "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(pool, "HTTP_COOKIE");          request_info.cookie=SAPI::get_env(SAPI_info, "HTTP_COOKIE");
         request_info.user_agent=SAPI::get_env(pool, "HTTP_USER_AGENT");          request_info.mail_received=mail_received;
           
   
         // prepare to process request          // prepare to process request
         Request request(pool,          Request request(request_pool, SAPI_info, 
                 request_info,                  request_info,
                 cgi ? String::UL_USER_HTML : String::UL_AS_IS  /*#ifdef _DEBUG
                 );                  String::UL_HTML|String::UL_OPTIMIZE_BIT
           #else*/
         // some root-controlled location                  cgi ? String::UL_HTML|String::UL_OPTIMIZE_BIT : String::UL_AS_IS
 #ifdef SYSCONFDIR  /*#endif*/
         const char *root_config_filespec=SYSCONFDIR "/" CONFIG_FILE_NAME;                  ,
 #else                  true /* status_allowed */);
 #       ifdef WIN32  
         // c:\windows          // get request ptr for signal handlers
         char root_config_path[MAX_STRING];          ::request=&request;
         GetWindowsDirectory(root_config_path, MAX_STRING);  
                   char config_filespec_buf[MAX_STRING];
         char root_config_filespec[MAX_STRING];          if(!config_filespec_cstr) {
         snprintf(root_config_filespec, MAX_STRING,                   const char* config_by_env=getenv(PARSER_CONFIG_ENV_NAME);
                 "%s/%s",                   if(!config_by_env)
                 root_config_path, CONFIG_FILE_NAME);                          config_by_env=getenv(REDIRECT_PREFIX PARSER_CONFIG_ENV_NAME);
 #       else                  if(config_by_env)
 #error must be compiled either configure/make or MSVC++                          config_filespec_cstr=config_by_env;
 #       endif                  else {
 #endif                          // beside by binary
                                   char beside_binary_path[MAX_STRING];
         // beside by binary                          strncpy(beside_binary_path, argv0, MAX_STRING-1);  beside_binary_path[MAX_STRING-1]=0; // filespec of my binary
         // @todo full path, not ./!                          if(!(
         static char site_config_path[MAX_STRING];                                  rsplit(beside_binary_path, '/') || 
         strncpy(site_config_path, argv0, MAX_STRING-1);  site_config_path[MAX_STRING-1]=0; // filespec of my binary                                  rsplit(beside_binary_path, '\\'))) { // strip filename
         if(!(                                  // no path, just filename
                 rsplit(site_config_path, '/') ||                                   // @todo full path, not ./!
                 rsplit(site_config_path, '\\'))) { // strip filename                                  beside_binary_path[0]='.'; beside_binary_path[1]=0;
                 // no path, just filename                          }
                 site_config_path[0]='.'; site_config_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);
                   }
         }          }
                   
         char site_config_filespec[MAX_STRING];  
         snprintf(site_config_filespec, MAX_STRING,   
                 "%s/%s",   
                 site_config_path, CONFIG_FILE_NAME);  
           
         // process the request          // process the request
         request.core(          request.core(
                 root_config_filespec, false,                  config_filespec_cstr, fail_on_config_read_problem,
                 site_config_filespec, false,  
                 header_only);                  header_only);
   
           // no request [prevent signal handlers from accessing invalid memory]
           ::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(Pool& pool);
         log_pool_stats(pool);          log_pool_stats(request_pool);
 #endif  #endif
 }  }
   
 void call_real_parser_handler__do_SEH(  #if _MSC_VER && !defined(_DEBUG)
                                                                  const char *filespec_to_process,  #       define PA_USE___TRY
                                                                  const char *request_method, bool header_only) {  struct Parser_executed {
 #if _MSC_VER & !defined(_DEBUG)          bool with_system_exception;
         LPEXCEPTION_POINTERS system_exception=0;          LPEXCEPTION_POINTERS system_exception;
   };
   #endif
   
   static 
   #ifdef PA_USE___TRY
   Parser_executed 
   #else
   void
   #endif
   call_real_parser_handler__do_SEH_return_it(
                                                                    const char* filespec_to_process,
                                                                    const char* request_method, bool header_only) {
   #ifdef PA_USE___TRY
           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,  
                                 0,  
                                 "Exception 0x%08X at 0x%08X", er->ExceptionCode,  er->ExceptionAddress);  
                         else  
                                 throw Exception(0, 0, 0, "Exception <no exception record>");  
                         else  
                                 throw Exception(0, 0, 0, "Exception <no exception information>");  
         }          }
           return result;
   #endif
   }
   
   static void call_real_parser_handler__do_SEH(
                                                                    const char* filespec_to_process,
                                                                    const char* request_method, bool header_only) {
   #ifdef PA_USE___TRY
           Parser_executed executed=
   #endif
                   call_real_parser_handler__do_SEH_return_it(filespec_to_process, 
                           request_method, header_only);
   
   #ifdef PA_USE___TRY
           if(executed.with_system_exception)
                   if(executed.system_exception)
                           if(_EXCEPTION_RECORD *er=executed.system_exception->ExceptionRecord)
                                   throw Exception(Exception::undefined_type,
                                           Exception::undefined_source,
                                           "Exception 0x%08X at 0x%08X", er->ExceptionCode,  er->ExceptionAddress);
                           else
                                   throw Exception(Exception::undefined_type, 
                                           Exception::undefined_source, 
                                           "Exception <no exception record>");
                   else
                           throw Exception(Exception::undefined_type, 
                                   Exception::undefined_source, 
                                   "Exception <no exception information>");
 #endif  #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              Output CGI header\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[]) {
         int result;  #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 362  int main(int argc, char *argv[]) { Line 540  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 'H':
                                   force_header_output=true;
                                   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 381  int main(int argc, char *argv[]) { Line 589  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  
         back_slashes_to_slashes(filespec_to_process);  #ifdef _DEBUG
           // Get current flag
           int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
   
           // Turn on leak-checking bit
   //      tmpFlag |= _CRTDBG_LEAK_CHECK_DF;
   
           // Set flag to the new value
           _CrtSetDbgFlag( tmpFlag );
   //      _CrtSetBreakAlloc(471);
   
   #endif
   
 #endif  #endif
         filespec_to_process=full_file_spec(filespec_to_process);  
   
         const char *request_method=getenv("REQUEST_METHOD");          char filespec_to_process[MAX_STRING];
           full_file_spec(raw_filespec_to_process, filespec_to_process, sizeof(filespec_to_process));
   
           const char* request_method=getenv("REQUEST_METHOD");
         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(                  call_real_parser_handler__do_SEH(
                         filespec_to_process,                          filespec_to_process,
                         request_method, header_only);                          request_method, header_only);
   
                 // successful finish  
                 result=0;  
         } 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
   
                 const char *body=e.comment();                  SAPI::die("exception in request exception handler: %s", e.comment());
                 // log it  
                 SAPI::log(pool, "exception in request exception handler: %s", body);  
   
                 //  
                 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);  
   
                 // unsuccessful finish  
                 result=1;  
         }          }
           
   
 #ifndef WIN32  //      _asm int 3;
         //           return 0;
         if(!cgi)  
                 SAPI::send_body(pool, "\n", 1);  
 #endif  
         return result;  
 }  }

Removed from v.1.126  
changed lines
  Added in v.1.216.2.15


E-mail: