Diff for /parser3/src/targets/cgi/parser3.C between versions 1.159 and 1.208

version 1.159, 2002/02/18 12:45:46 version 1.208, 2002/12/05 10:08:59
Line 3 Line 3
   
         Copyright(c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com)          Copyright(c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com)
         Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)          Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
   
         $Id$  
 */  */
   
   static const char* IDENT_PARSER3_C="$Date$";
   
 #include "pa_config_includes.h"  #include "pa_config_includes.h"
   
 #if _MSC_VER  #if _MSC_VER
 #       include <new.h>  #       include <new.h>
 #       include <crtdbg.h>  #       include <crtdbg.h>
 #else  
 #       include "pa_config_paths.h"  
 #endif  #endif
   
 #include "pa_sapi.h"  #include "pa_sapi.h"
Line 22 Line 20
 #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"  #include "pool_storage.h"
   
 #ifdef WIN32  #ifdef WIN32
 #       include <windows.h>  #       include <windows.h>
   #       include "getopt.h"
   #else
   #       include <getopt.h>
 #endif  #endif
   
 //#define DEBUG_POOL_MALLOC  //#define DEBUG_POOL_MALLOC
   //#define DEBUG_STRING_APPENDS_VS_EXPANDS
   //#define DEBUG_MAILRECEIVE "mailreceive.eml"
   
 // consts  #ifdef DEBUG_STRING_APPENDS_VS_EXPANDS
   extern ulong 
           string_piece_appends, 
           wcontext_result_size,
           total_alloc_size,
           string_string_shortcut_economy;
   #endif
   
 extern const char *main_RCSIds[];  // consts
 #ifdef USE_SMTP  
 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[];  
 const char **RCSIds[]={  
         main_RCSIds,  
 #ifdef USE_SMTP  
         smtp_RCSIds,  
 #endif  
         gd_RCSIds,  
         classes_RCSIds,  
         types_RCSIds,  
         parser3_RCSIds,  
         0  
 };  
   
 const char *PARSER_ROOT_CONFIG_ENV_NAME="PARSER_ROOT_CONFIG";  #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_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 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 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) {  static void log(const char *fmt, va_list args) {
         bool opened;          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 111  void SAPI::log(Pool& , const char *fmt, Line 124  void SAPI::log(Pool& , const char *fmt,
 void SAPI::die(const char *fmt, ...) {  void SAPI::die(const char *fmt, ...) {
 #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(global_pool);
 #endif  #endif
   
     va_list args;      va_list args;
Line 119  void SAPI::die(const char *fmt, ...) { Line 132  void SAPI::die(const char *fmt, ...) {
         // log          // log
   
         // logging is more important than user           // logging is more important than user 
         // she can cancel download, we'd get SIG_PIPE,           // she can cancel download, we'd get SIGPIPE, 
         // nothing would be logged then          // nothing would be logged then
         ::log(fmt, args);          ::log(fmt, args);
   
Line 132  void SAPI::die(const char *fmt, ...) { Line 145  void SAPI::die(const char *fmt, ...) {
   
         // 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(pool, "status", "500");          SAPI::add_header_attribute(global_pool, "status", "500");
         SAPI::add_header_attribute(pool, "content-type", "text/plain");          SAPI::add_header_attribute(global_pool, "content-type", "text/plain");
         char content_length_cstr[MAX_NUMBER];          char content_length_cstr[MAX_NUMBER];
         snprintf(content_length_cstr, MAX_NUMBER, "%u", content_length);          snprintf(content_length_cstr, sizeof(content_length_cstr), "%u", content_length);
         SAPI::add_header_attribute(pool, "content-length", content_length_cstr);          SAPI::add_header_attribute(global_pool, "content-length", content_length_cstr);
   
         // send header          // send header
         SAPI::send_header(pool);          SAPI::send_header(global_pool);
   
         // body          // body
         SAPI::send_body(pool, body, content_length);          SAPI::send_body(global_pool, body, content_length);
   
         exit(1);          exit(1);
 }  }
Line 151  const char *SAPI::get_env(Pool& , const Line 164  const char *SAPI::get_env(Pool& , const
         return getenv(name);          return getenv(name);
 }  }
   
   const char *const *SAPI::environment(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(Pool& , 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;
Line 185  void SAPI::send_body(Pool& , const void Line 208  void SAPI::send_body(Pool& , const void
   
 //  //
   
 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(global_pool, request? "%s received. uri=%s, qs=%s"
                   :"%s received. no request being processed", 
                   signal_name,
                   request && request->info.uri?request->info.uri:"-",
                   request && request->info.query_string?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 204  main workhorse Line 258  main workhorse
                 wich is tested but seems slow.                  wich is tested but seems slow.
                 IIS5 todo find out proper 'illegal call' check                   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);          init_socks(global_pool);
                   
         // init global classes          // init global classes
         init_methoded_array(pool);          init_methoded_array(global_pool);
         // init global variables          // init global variables
         pa_globals_init(pool);          pa_globals_init(global_pool);
                   
         if(!filespec_to_process)          // 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)
                 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];
         if(cgi) {          if(cgi) {
                 if(const char *env_document_root=SAPI::get_env(pool, "DOCUMENT_ROOT"))                  if(const char *env_document_root=SAPI::get_env(request_pool, "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(request_pool, "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,                                  0,
                         "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");          const char *query_string=SAPI::get_env(request_pool, "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"))                  if(const char *env_request_uri=SAPI::get_env(request_pool, "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(const char *path_info=SAPI::get_env(request_pool, "PATH_INFO"))
                         if(query_string) {                          if(query_string) {
                                 char *reconstructed_uri=(char *)pool.malloc(                                  char *reconstructed_uri=(char *)request_pool.malloc(
                                         strlen(path_info)+1/*'?'*/+                                          strlen(path_info)+1/*'?'*/+
                                         strlen(query_string)+1/*0*/);                                          strlen(query_string)+1/*0*/);
                                 strcpy(reconstructed_uri, path_info);                                  strcpy(reconstructed_uri, path_info);
Line 259  void real_parser_handler( Line 312  void real_parser_handler(
                                 request_info.uri=reconstructed_uri;                                  request_info.uri=reconstructed_uri;
                         } else                          } else
                                 request_info.uri=path_info;                                  request_info.uri=path_info;
                         else                  else
                                 throw Exception(0, 0,                          throw Exception("parser.runtime",
                                 0,                                  0,
                                 "CGI: no PATH_INFO defined(in reinventing REQUEST_URI)");                                  "CGI: no PATH_INFO defined(in reinventing REQUEST_URI)");
                                                   
 #ifndef WIN32  
                         // they've changed this under IIS5.                          // they've changed this under IIS5.
                         if(const char *script_name=SAPI::get_env(pool, "SCRIPT_NAME")) {                          if(const char *script_name=SAPI::get_env(request_pool, "SCRIPT_NAME")) {
                                 size_t script_name_len=strlen(script_name);                                  size_t script_name_len=strlen(script_name);
                                 size_t uri_len=strlen(request_info.uri);                                  size_t uri_len=strlen(request_info.uri);
                                 if(strncmp(request_info.uri,script_name, script_name_len)==0 &&                                  if(strncmp(request_info.uri,script_name, script_name_len)==0 &&
                                         script_name_len != uri_len) // under IIS they are the same                                          script_name_len != uri_len) // under IIS they are the same
                                         SAPI::die("CGI: illegal call");                                          SAPI::die("CGI: illegal call");
                         }                          }
 #endif  
         } 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(request_pool, "CONTENT_TYPE");
         const char *content_length=SAPI::get_env(pool, "CONTENT_LENGTH");          const char *content_length=SAPI::get_env(request_pool, "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(request_pool, "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,
                 request_info,                  request_info,
 #ifdef _DEBUG  /*#ifdef _DEBUG
                 String::UL_HTML|String::UL_OPTIMIZE_BIT                  String::UL_HTML|String::UL_OPTIMIZE_BIT
 #else  #else*/
                 cgi ? String::UL_HTML|String::UL_OPTIMIZE_BIT : String::UL_AS_IS                  cgi ? String::UL_HTML|String::UL_OPTIMIZE_BIT : String::UL_AS_IS
 #endif  /*#endif*/
                 ,                  ,
                 true /* status_allowed */);                  true /* status_allowed */);
           
         // some root-controlled location          // get request ptr for signal handlers
         const char *root_config_filespec;          ::request=&request;
         if(const char *root_config_by_env=getenv(PARSER_ROOT_CONFIG_ENV_NAME))  
                 root_config_filespec=root_config_by_env;          char config_filespec_buf[MAX_STRING];
         else {          if(!config_filespec_cstr) {
 #ifdef ROOT_CONFIG_DIR                  const char *config_by_env=getenv(PARSER_CONFIG_ENV_NAME);
                 root_config_filespec=ROOT_CONFIG_DIR "/" CONFIG_FILE_NAME;                  if(!config_by_env)
 #else                          config_by_env=getenv(REDIRECT_PREFIX PARSER_CONFIG_ENV_NAME);
 #       ifdef WIN32                  if(config_by_env)
                 // c:\windows                          config_filespec_cstr=config_by_env;
                 char windows_dir[MAX_STRING];                  else {
                 GetWindowsDirectory(windows_dir, MAX_STRING);                          // beside by binary
                           char beside_binary_path[MAX_STRING];
                 char buf[MAX_STRING];                          strncpy(beside_binary_path, argv0, MAX_STRING-1);  beside_binary_path[MAX_STRING-1]=0; // filespec of my binary
                 snprintf(buf, MAX_STRING,                           if(!(
                         "%s/%s",                                   rsplit(beside_binary_path, '/') || 
                         windows_dir, CONFIG_FILE_NAME);                                  rsplit(beside_binary_path, '\\'))) { // strip filename
                                                   // no path, just filename
                 root_config_filespec=buf;                                  // @todo full path, not ./!
 #       else                                  beside_binary_path[0]='.'; beside_binary_path[1]=0;
 #error must be compiled either configure/make or MSVC++                          }
 #       endif                          snprintf(config_filespec_buf, MAX_STRING, 
 #endif                                  "%s/%s", 
         }                                  beside_binary_path, AUTO_FILE_NAME);
                                   config_filespec_cstr=config_filespec_buf;
         // beside by binary                          fail_on_config_read_problem=entry_exists(config_filespec_cstr);
         // @todo full path, not ./!                  }
         static char site_config_path[MAX_STRING];  
         strncpy(site_config_path, argv0, MAX_STRING-1);  site_config_path[MAX_STRING-1]=0; // filespec of my binary  
         if(!(  
                 rsplit(site_config_path, '/') ||   
                 rsplit(site_config_path, '\\'))) { // strip filename  
                 // no path, just filename  
                 site_config_path[0]='.'; site_config_path[1]=0;  
         }          }
                   
         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();          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
   
   #ifdef DEBUG_STRING_APPENDS_VS_EXPANDS
           SAPI::log(global_pool, 
                   "string piece appends=%lu, wcontext_result_size=%lu, string_string_shortcut_economy_closer=%lu, total_alloc_size=%lu", 
                   string_piece_appends,
                   wcontext_result_size,
                   string_string_shortcut_economy,
                   total_alloc_size);
 #endif  #endif
   
 }  }
   
 void call_real_parser_handler__do_SEH(  static void call_real_parser_handler__do_SEH(
                                                                  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)  #if _MSC_VER && !defined(_DEBUG)
Line 368  void call_real_parser_handler__do_SEH( Line 420  void call_real_parser_handler__do_SEH(
                                   
                 if(system_exception)                  if(system_exception)
                         if(_EXCEPTION_RECORD *er=system_exception->ExceptionRecord)                          if(_EXCEPTION_RECORD *er=system_exception->ExceptionRecord)
                                 throw Exception(0, 0,                                  throw Exception(0,
                                 0,                                          0,
                                 "Exception 0x%08X at 0x%08X", er->ExceptionCode,  er->ExceptionAddress);                                          "Exception 0x%08X at 0x%08X", er->ExceptionCode,  er->ExceptionAddress);
                         else                          else
                                 throw Exception(0, 0, 0, "Exception <no exception record>");                                  throw Exception(0, 0, "Exception <no exception record>");
                         else                          else
                                 throw Exception(0, 0, 0, "Exception <no exception information>");                                  throw Exception(0, 0, "Exception <no exception information>");
         }          }
 #endif  #endif
 }  }
Line 387  int failed_new(size_t size) { Line 439  int failed_new(size_t size) {
 #endif  #endif
   
 #ifdef HAVE_SET_NEW_HANDLER  #ifdef HAVE_SET_NEW_HANDLER
 void failed_new() {  static void failed_new() {
     SAPI::die("out of memory in 'new'");      SAPI::die("out of memory in 'new'");
 }  }
 #endif  #endif
   
   static void usage(const char *program) {
           printf(
                   "Parser/%s Copyright(c) 2001, 2002 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=33112;
   #endif
 //      _asm int 3;  //      _asm int 3;
         argv0=argv[0];          argv0=argv[0];
   
Line 405  int main(int argc, char *argv[]) { Line 493  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, 2002 ArtLebedev Group (http://www.artlebedev.com)\n"          else {
                                 "Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)\n"                  optind = 1;
                                 "\n"                  opterr = 0;
                                 "Usage: %s <file>\n",                  int c;
                                 PARSER_VERSION,                   while((c = getopt(argc, argv, "hf:"
                                 argv0?argv0:"parser3");  #ifdef WITH_MAILRECEIVE
                         return 1;                          "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 446  int main(int argc, char *argv[]) { Line 559  int main(int argc, char *argv[]) {
         std::set_new_handler(failed_new);          std::set_new_handler(failed_new);
 #endif  #endif
   
         char *filespec_to_process=cgi?getenv("PATH_TRANSLATED"):argv[1];          char filespec_to_process[MAX_STRING];
 #ifdef WIN32          full_file_spec(raw_filespec_to_process, filespec_to_process, sizeof(filespec_to_process));
         back_slashes_to_slashes(filespec_to_process);  
 #endif  
         filespec_to_process=full_file_spec(filespec_to_process);  
   
         const char *request_method=getenv("REQUEST_METHOD");          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;
Line 475  int main(int argc, char *argv[]) { Line 585  int main(int argc, char *argv[]) {
 #ifndef WIN32  #ifndef WIN32
         //           // 
         if(!cgi)          if(!cgi)
                 SAPI::send_body(pool, "\n", 1);                  SAPI::send_body(global_pool, "\n", 1);
 #endif  #endif
 //_asm int 3;  
           //_asm int 3;
         return 0;          return 0;
 }  }

Removed from v.1.159  
changed lines
  Added in v.1.208


E-mail: