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

version 1.126, 2001/10/29 13:04:47 version 1.162, 2002/02/20 12:40:24
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, 2002 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$          $Id$
 */  */
   
 #include "pa_config_includes.h"  #include "pa_config_includes.h"
   
 #ifdef WIN32  #if _MSC_VER
 #       include <windows.h>  #       include <new.h>
   #       include <crtdbg.h>
   #else
   #       include "pa_config_paths.h"
 #endif  #endif
   
 #include "pa_sapi.h"  #include "pa_sapi.h"
Line 21 Line 24
 #include "pa_version.h"  #include "pa_version.h"
 #include "pool_storage.h"  #include "pool_storage.h"
   
 #ifdef XML  #ifdef WIN32
 #include <XalanTransformer/XalanCAPI.h>  #       include <windows.h>
 #endif  #endif
   
 #define DEBUG_POOL_MALLOC  //#define DEBUG_POOL_MALLOC
   //#define DEBUG_STRING_APPENDS_VS_EXPANDS
   
   #ifdef DEBUG_STRING_APPENDS_VS_EXPANDS
   extern ulong 
           string_piece_appends, 
           wcontext_result_size,
           total_alloc_size,
           string_string_shortcut_economy;
   #endif
   
 // consts  // consts
   
Line 37  extern const char *gd_RCSIds[]; Line 49  extern const char *gd_RCSIds[];
 extern const char *classes_RCSIds[];  extern const char *classes_RCSIds[];
 extern const char *types_RCSIds[];  extern const char *types_RCSIds[];
 extern const char *parser3_RCSIds[];  extern const char *parser3_RCSIds[];
 #ifdef XML  
 extern const char *xalan_patched_RCSIds[];  
 #endif  
 const char **RCSIds[]={  const char **RCSIds[]={
         main_RCSIds,          main_RCSIds,
 #ifdef USE_SMTP  #ifdef USE_SMTP
Line 49  const char **RCSIds[]={ Line 58  const char **RCSIds[]={
         classes_RCSIds,          classes_RCSIds,
         types_RCSIds,          types_RCSIds,
         parser3_RCSIds,          parser3_RCSIds,
 #ifdef XML  
         xalan_patched_RCSIds,  
 #endif  
         0          0
 };  };
   
   const char *PARSER_ROOT_CONFIG_ENV_NAME="PARSER_ROOT_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 
   
Line 110  void SAPI::log(Pool& , const char *fmt, Line 118  void SAPI::log(Pool& , const char *fmt,
 }  }
   
 void SAPI::die(const char *fmt, ...) {  void SAPI::die(const char *fmt, ...) {
   #ifdef DEBUG_POOL_MALLOC
           extern void log_pool_stats(Pool& pool);
           log_pool_stats(pool);
   #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 SIG_PIPE, 
           // 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(pool, "status", "500");
           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
           SAPI::send_body(pool, body, content_length);
   
         exit(1);          exit(1);
 }  }
   
Line 127  size_t SAPI::read_post(Pool& , char *buf Line 165  size_t SAPI::read_post(Pool& , char *buf
         do {          do {
                 int chunk_size=read(fileno(stdin),                   int 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 143  void SAPI::add_header_attribute(Pool& , Line 181  void SAPI::add_header_attribute(Pool& ,
 /// @todo intelligent cache-control  /// @todo intelligent cache-control
 void SAPI::send_header(Pool& ) {  void SAPI::send_header(Pool& ) {
         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("");
Line 173  main workhorse Line 211  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(  void real_parser_handler(
                                         const char *filespec_to_process,                                          const char *filespec_to_process,
Line 180  void real_parser_handler( Line 219  void real_parser_handler(
         // init socks          // init socks
         init_socks(pool);          init_socks(pool);
                   
 #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 global classes
         init_methoded_array(pool);          init_methoded_array(pool);
         // init global variables          // init global variables
         pa_globals_init(pool);          pa_globals_init(pool);
                   
         if(!filespec_to_process)          if(!filespec_to_process)
                 throw Exception(0, 0,                  SAPI::die("Parser/%s", PARSER_VERSION);
                 0,  
                 "Parser/%s", PARSER_VERSION);  
                   
         // Request info          // Request info
         Request::Info request_info;          Request::Info request_info;
Line 247  void real_parser_handler( Line 273  void real_parser_handler(
                                 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.
                         if(const char *script_name=SAPI::get_env(pool, "SCRIPT_NAME")) {                          if(const char *script_name=SAPI::get_env(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
                                         throw Exception(0, 0,                                          SAPI::die("CGI: illegal call");
                                         0,  
                                         "CGI: illegal call");  
                         }                          }
   #endif
         } else          } else
                 request_info.uri=0;                  request_info.uri=0;
                   
Line 268  void real_parser_handler( Line 295  void real_parser_handler(
         // prepare to process request          // prepare to process request
         Request request(pool,          Request request(pool,
                 request_info,                  request_info,
                 cgi ? String::UL_USER_HTML : String::UL_AS_IS  #ifdef _DEBUG
                 );                  String::UL_HTML|String::UL_OPTIMIZE_BIT
   #else
                   cgi ? String::UL_HTML|String::UL_OPTIMIZE_BIT : String::UL_AS_IS
   #endif
                   ,
                   true /* status_allowed */);
                   
         // some root-controlled location          // some root-controlled location
 #ifdef SYSCONFDIR          const char *root_config_filespec;
         const char *root_config_filespec=SYSCONFDIR "/" CONFIG_FILE_NAME;          if(const char *root_config_by_env=getenv(PARSER_ROOT_CONFIG_ENV_NAME))
                   root_config_filespec=root_config_by_env;
           else {
   #ifdef ROOT_CONFIG_DIR
                   root_config_filespec=ROOT_CONFIG_DIR "/" CONFIG_FILE_NAME;
 #else  #else
 #       ifdef WIN32  #       ifdef WIN32
         // c:\windows                  // c:\windows
         char root_config_path[MAX_STRING];                  char windows_dir[MAX_STRING];
         GetWindowsDirectory(root_config_path, MAX_STRING);                  GetWindowsDirectory(windows_dir, MAX_STRING);
           
         char root_config_filespec[MAX_STRING];                  char buf[MAX_STRING];
         snprintf(root_config_filespec, MAX_STRING,                   snprintf(buf, MAX_STRING, 
                 "%s/%s",                           "%s/%s", 
                 root_config_path, CONFIG_FILE_NAME);                          windows_dir, CONFIG_FILE_NAME);
                   
                   root_config_filespec=buf;
 #       else  #       else
 #error must be compiled either configure/make or MSVC++  #error must be compiled either configure/make or MSVC++
 #       endif  #       endif
 #endif  #endif
           }
                   
         // beside by binary          // beside by binary
         // @todo full path, not ./!          // @todo full path, not ./!
Line 318  void real_parser_handler( Line 357  void real_parser_handler(
         extern void log_pool_stats(Pool& pool);          extern void log_pool_stats(Pool& pool);
         log_pool_stats(pool);          log_pool_stats(pool);
 #endif  #endif
   
   #ifdef DEBUG_STRING_APPENDS_VS_EXPANDS
           SAPI::log(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
   
 }  }
   
 void call_real_parser_handler__do_SEH(  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)
         LPEXCEPTION_POINTERS system_exception=0;          LPEXCEPTION_POINTERS system_exception=0;
         __try {          __try {
 #endif  #endif
Line 331  void call_real_parser_handler__do_SEH( Line 380  void call_real_parser_handler__do_SEH(
                         filespec_to_process,                          filespec_to_process,
                         request_method, header_only);                          request_method, header_only);
                                   
 #if _MSC_VER & !defined(_DEBUG)  #if _MSC_VER && !defined(_DEBUG)
         } __except (          } __except (
                 (system_exception=GetExceptionInformation()),                   (system_exception=GetExceptionInformation()), 
                 EXCEPTION_EXECUTE_HANDLER) {                  EXCEPTION_EXECUTE_HANDLER) {
Line 349  void call_real_parser_handler__do_SEH( Line 398  void call_real_parser_handler__do_SEH(
 #endif  #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
   void failed_new() {
       SAPI::die("out of memory in 'new'");
   }
   #endif
   
 int main(int argc, char *argv[]) {  int main(int argc, char *argv[]) {
         int result;  //      _asm int 3;
         argv0=argv[0];          argv0=argv[0];
   
         umask(2);          umask(2);
Line 365  int main(int argc, char *argv[]) { Line 427  int main(int argc, char *argv[]) {
         if(!cgi) {          if(!cgi) {
                 if(argc<2) {                  if(argc<2) {
                         printf(                          printf(
                                 "Parser/%s Copyright(c) 2001 ArtLebedev Group(http://www.artlebedev.com)\n"                                  "Parser/%s Copyright(c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com)\n"
                                 "Author: Alexander Petrosyan <paf@design.ru>(http://design.ru/paf)\n"                                  "Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)\n"
                                 "\n"                                  "\n"
                                 "Usage: %s <file>\n",                                  "Usage: %s <file>\n",
                                 PARSER_VERSION,                                   PARSER_VERSION, 
Line 381  int main(int argc, char *argv[]) { Line 443  int main(int argc, char *argv[]) {
         setmode(fileno(stderr), _O_BINARY);          setmode(fileno(stderr), _O_BINARY);
 #endif  #endif
   
   #if _MSC_VER
           _set_new_handler(failed_new);
   
   #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
   
   #ifdef HAVE_SET_NEW_HANDLER
           std::set_new_handler(failed_new);
   #endif
   
         char *filespec_to_process=cgi?getenv("PATH_TRANSLATED"):argv[1];          char *filespec_to_process=cgi?getenv("PATH_TRANSLATED"):argv[1];
 #ifdef WIN32  #ifdef WIN32
         back_slashes_to_slashes(filespec_to_process);          back_slashes_to_slashes(filespec_to_process);
Line 389  int main(int argc, char *argv[]) { Line 473  int main(int argc, char *argv[]) {
   
         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;
   
         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  #ifndef _DEBUG
                 SAPI::log(pool, "exception in request exception handler: %s", body);          } catch(...) { 
                   SAPI::die("<unknown exception>");
                 //  #endif
                 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;  
         }          }
                   
   
Line 431  int main(int argc, char *argv[]) { Line 496  int main(int argc, char *argv[]) {
         if(!cgi)          if(!cgi)
                 SAPI::send_body(pool, "\n", 1);                  SAPI::send_body(pool, "\n", 1);
 #endif  #endif
         return result;  //_asm int 3;
           return 0;
 }  }

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


E-mail: