Diff for /parser3/src/targets/isapi/parser3isapi.C between versions 1.123 and 1.142

version 1.123, 2020/12/15 13:37:35 version 1.142, 2026/10/18 21:05:35
Line 1 Line 1
 /** @file  /** @file
         Parser: IIS extension.          Parser: IIS extension.
   
         Copyright (c) 2000-2017 Art. Lebedev Studio (http://www.artlebedev.com)          Copyright (c) 2000-2026 Art. Lebedev Studio (https://www.artlebedev.com)
         Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)          Authors: Konstantin Morshnev <moko@design.ru>, Alexandr Petrosian <paf@design.ru>
 */  */
   
 volatile const char * IDENT_PARSER3ISAPI_C="$Id$";  volatile const char * IDENT_PARSER3ISAPI_C="$Id$";
Line 56  const int IIS51var_count=sizeof(IIS51var Line 56  const int IIS51var_count=sizeof(IIS51var
 // globals  // globals
   
 char argv0[MAX_STRING]="";  char argv0[MAX_STRING]="";
   const char* parser3_mode="isapi"; // $status:mode
   const char *parser3_log_filespec(){ return ""; } // $status:log-filename
   
 // SAPI  // SAPI
   
Line 80  void SAPI::log(SAPI_Info& SAPI_info, con Line 82  void SAPI::log(SAPI_Info& SAPI_info, con
         const char* prefix="PARSER_ERROR:";          const char* prefix="PARSER_ERROR:";
         strcpy(buf, prefix);          strcpy(buf, prefix);
         char *start=buf+strlen(prefix);          char *start=buf+strlen(prefix);
         DWORD size=vsnprintf(start, MAX_LOG_STRING-strlen(prefix), fmt, args);          DWORD size=pa_vsnprintf(start, MAX_LOG_STRING-strlen(prefix), fmt, args);
         size=remove_crlf(start, start+size);          size=remove_crlf(start, start+size);
   
         SAPI_info.lpECB->ServerSupportFunction(SAPI_info.lpECB->ConnID, HSE_APPEND_LOG_PARAMETER, buf, &size, 0);          SAPI_info.lpECB->ServerSupportFunction(SAPI_info.lpECB->ConnID, HSE_APPEND_LOG_PARAMETER, buf, &size, 0);
Line 99  void SAPI::die(const char* fmt, ...) { Line 101  void SAPI::die(const char* fmt, ...) {
 //      va_end(args);  //      va_end(args);
 }  }
   
   void SAPI::send_error(SAPI_Info& SAPI_info, const char *exception_cstr, const char *status){
           // capitalized headers passed for preventing malloc during capitalization
           add_header_attribute(SAPI_info, HTTP_STATUS_CAPITALIZED, status);
           add_header_attribute(SAPI_info, HTTP_CONTENT_TYPE_CAPITALIZED, "text/plain");
           send_headers(SAPI_info);
           send_body(SAPI_info, exception_cstr, strlen(exception_cstr));
   }
   
 char* SAPI::Env::get(SAPI_Info& SAPI_info, const char* name) {  char* SAPI::Env::get(SAPI_Info& SAPI_info, const char* name) {
         char *variable_buf=new(PointerFreeGC) char[MAX_STRING];          char *variable_buf=new(PointerFreeGC) char[MAX_STRING];
         DWORD variable_len = MAX_STRING-1;          DWORD variable_len = MAX_STRING-1;
Line 206  void SAPI::add_header_attribute(SAPI_Inf Line 216  void SAPI::add_header_attribute(SAPI_Inf
 }  }
   
 /// @todo intelligent cache-control  /// @todo intelligent cache-control
 void SAPI::send_header(SAPI_Info& SAPI_info) {  void SAPI::send_headers(SAPI_Info& SAPI_info) {
         HSE_SEND_HEADER_EX_INFO header_info;          HSE_SEND_HEADER_EX_INFO header_info;
   
         char status_buf[MAX_STATUS_LENGTH];          char status_buf[MAX_STATUS_LENGTH];
Line 221  void SAPI::send_header(SAPI_Info& SAPI_i Line 231  void SAPI::send_header(SAPI_Info& SAPI_i
                         header_info.pszStatus="401 Authorization Required";                          header_info.pszStatus="401 Authorization Required";
                         break;                          break;
                 default:                  default:
                         snprintf(status_buf, MAX_STATUS_LENGTH,                           pa_snprintf(status_buf, MAX_STATUS_LENGTH, 
                                 "%d Undescribed", SAPI_info.http_response_code);                                  "%d Undescribed", SAPI_info.http_response_code);
                         header_info.pszStatus=status_buf;                          header_info.pszStatus=status_buf;
                         break;                          break;
Line 238  void SAPI::send_header(SAPI_Info& SAPI_i Line 248  void SAPI::send_header(SAPI_Info& SAPI_i
                 HSE_REQ_SEND_RESPONSE_HEADER_EX, &header_info, NULL, NULL);                  HSE_REQ_SEND_RESPONSE_HEADER_EX, &header_info, NULL, NULL);
 }  }
   
   void SAPI::clear_headers(SAPI_Info& SAPI_info) {
           SAPI_info.header=new String;
   }
   
 size_t SAPI::send_body(SAPI_Info& SAPI_info, const void *buf, size_t size) {  size_t SAPI::send_body(SAPI_Info& SAPI_info, const void *buf, size_t size) {
         DWORD num_bytes=size;          DWORD num_bytes=size;
         if(!SAPI_info.lpECB->WriteClient(SAPI_info.lpECB->ConnID,           if(!SAPI_info.lpECB->WriteClient(SAPI_info.lpECB->ConnID, 
Line 272  static void parser_done() { Line 286  static void parser_done() {
 /// ISAPI //  /// ISAPI //
 BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pVer) {  BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pVer) {
         pVer->dwExtensionVersion = HSE_VERSION;          pVer->dwExtensionVersion = HSE_VERSION;
         strncpy(pVer->lpszExtensionDesc, "Parser " PARSER_VERSION, HSE_MAX_EXT_DLL_NAME_LEN-1);          pa_strncpy(pVer->lpszExtensionDesc, "Parser " PARSER_VERSION_WITH_FEATURES, HSE_MAX_EXT_DLL_NAME_LEN);
         pVer->lpszExtensionDesc[HSE_MAX_EXT_DLL_NAME_LEN-1]=0;  
         return parser_init();          return parser_init();
 }  }
 // dwFlags & HSE_TERM_MUST_UNLOAD means we can't return false  // dwFlags & HSE_TERM_MUST_UNLOAD means we can't return false
Line 297  BOOL WINAPI TerminateExtension( Line 310  BOOL WINAPI TerminateExtension(
         @test          @test
                 PARSER_VERSION from outside                  PARSER_VERSION from outside
 */  */
 void real_parser_handler(SAPI_Info& SAPI_info, bool header_only) {  void real_parser_handler(SAPI_Info& SAPI_info) {
         // collect garbage from prev request          // collect garbage from prev request
         PA_GC_GCOLLECT;          pa_gc_collect();
                   
         SAPI_info.header=new String;          SAPI_info.header=new String;
         LPEXTENSION_CONTROL_BLOCK lpECB=SAPI_info.lpECB;          LPEXTENSION_CONTROL_BLOCK lpECB=SAPI_info.lpECB;
Line 307  void real_parser_handler(SAPI_Info& SAPI Line 320  void real_parser_handler(SAPI_Info& SAPI
         // Request info          // Request info
         Request_info request_info;  memset(&request_info, 0, sizeof(request_info));          Request_info request_info;  memset(&request_info, 0, sizeof(request_info));
   
         size_t path_translated_buf_size=strlen(lpECB->lpszPathTranslated)+1;          char *filespec_to_process=backslashes_to_slashes(lpECB->lpszPathTranslated);
         char *filespec_to_process=pa_strdup(lpECB->lpszPathTranslated, path_translated_buf_size);  
 #ifdef WIN32  
         back_slashes_to_slashes(filespec_to_process);  
 #endif  
   
         if(const char* path_info=SAPI::Env::get(SAPI_info, "PATH_INFO")) {          if(const char* path_info=SAPI::Env::get(SAPI_info, "PATH_INFO")) {
                 // IIS                  // IIS
                 size_t len=strlen(filespec_to_process)-strlen(path_info);                  size_t filespec_len=strlen(filespec_to_process);
                 char *buf=new(PointerFreeGC) char[len+1];                  size_t path_info_len=strlen(path_info);
                 strncpy(buf, filespec_to_process, len); buf[len]=0;                  request_info.set_document_root(filespec_len>path_info_len ? pa_strdup(filespec_to_process, filespec_len-path_info_len) : "");
                 request_info.document_root=buf;  
         } else          } else
                 throw Exception(PARSER_RUNTIME, 0, "ISAPI: no PATH_INFO defined (in reinventing DOCUMENT_ROOT)");                  throw Exception(PARSER_RUNTIME, 0, "ISAPI: no PATH_INFO defined (in reinventing DOCUMENT_ROOT)");
   
Line 336  void real_parser_handler(SAPI_Info& SAPI Line 344  void real_parser_handler(SAPI_Info& SAPI
   
         // beside by binary          // beside by binary
         static char beside_binary_path[MAX_STRING];          static 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          pa_strncpy(beside_binary_path, argv0, MAX_STRING); // filespec of my binary
         if(!(rsplit(beside_binary_path, '/') || rsplit(beside_binary_path, '\\'))) { // strip filename          if(!rsplit(beside_binary_path, "/\\")) { // strip filename
                 // no path, just filename                  // no path, just filename
                 beside_binary_path[0]='.'; beside_binary_path[1]=0;                  beside_binary_path[0]='.'; beside_binary_path[1]=0;
         }          }
         char config_filespec[MAX_STRING];          char config_filespec[MAX_STRING];
         snprintf(config_filespec, MAX_STRING, "%s/%s", beside_binary_path, AUTO_FILE_NAME);          pa_snprintf(config_filespec, MAX_STRING, "%s/%s", beside_binary_path, AUTO_FILE_NAME);
   
         // process the request          // process the request
         request.core(entry_exists(config_filespec) ? config_filespec : NULL, header_only);          request.core(entry_exists(config_filespec) ? config_filespec : NULL);
 }  }
   
 #ifdef PA_SUPPRESS_SYSTEM_EXCEPTION  #ifdef PA_SUPPRESS_SYSTEM_EXCEPTION
 static const Exception call_real_parser_handler__do_PEH_return_it(SAPI_Info& SAPI_info, bool header_only) {  static const Exception call_real_parser_handler__do_PEH_return_it(SAPI_Info& SAPI_info) {
         try {          try {
                 real_parser_handler(SAPI_info, header_only);                  real_parser_handler(SAPI_info);
         } catch(const Exception& e) {          } catch(const Exception& e) {
                 return e;                  return e;
         }          }
Line 359  static const Exception call_real_parser_ Line 367  static const Exception call_real_parser_
         return Exception();          return Exception();
 }  }
   
 static void call_real_parser_handler__supress_system_exception(SAPI_Info& SAPI_info, bool header_only) {  static void call_real_parser_handler__supress_system_exception(SAPI_Info& SAPI_info) {
         Exception parser_exception;          Exception parser_exception;
         LPEXCEPTION_POINTERS system_exception=0;          LPEXCEPTION_POINTERS system_exception=0;
   
         __try {          __try {
                 parser_exception=call_real_parser_handler__do_PEH_return_it(SAPI_info, header_only);                  parser_exception=call_real_parser_handler__do_PEH_return_it(SAPI_info);
         } __except ( (system_exception=GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER) {          } __except ( (system_exception=GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER) {
                 if(system_exception)                  if(system_exception)
                         if(_EXCEPTION_RECORD *er=system_exception->ExceptionRecord)                          if(_EXCEPTION_RECORD *er=system_exception->ExceptionRecord)
                                 throw Exception("system", 0, "0x%08X at 0x%08X", er->ExceptionCode,  er->ExceptionAddress);                                  throw Exception("system", 0, "0x%08X at %p", er->ExceptionCode, er->ExceptionAddress);
                         else                          else
                                 throw Exception("system", 0, "<no exception record>");                                  throw Exception("system", 0, "<no exception record>");
                 else                  else
Line 388  DWORD WINAPI HttpExtensionProc(LPEXTENSI Line 396  DWORD WINAPI HttpExtensionProc(LPEXTENSI
                 200 // default http_response_code [lpECB->dwHttpStatusCode seems to be always 0, even on 404 redirect to /404.html]                  200 // default http_response_code [lpECB->dwHttpStatusCode seems to be always 0, even on 404 redirect to /404.html]
         };          };
   
         bool header_only=strcasecmp(lpECB->lpszMethod, "HEAD")==0;  
         try { // global try          try { // global try
 #ifdef PA_SUPPRESS_SYSTEM_EXCEPTION  #ifdef PA_SUPPRESS_SYSTEM_EXCEPTION
                 call_real_parser_handler__supress_system_exception(                  call_real_parser_handler__supress_system_exception(
 #else  #else
                 real_parser_handler(                  real_parser_handler(
 #endif  #endif
                         SAPI_info, header_only);                          SAPI_info);
                 // successful finish                  // successful finish
         } catch(const Exception& e) { // exception in unhandled exception          } catch(const Exception& e) { // just in case
                 // log it                  // log it
                 SAPI::log(SAPI_info, "%s", e.comment());                  SAPI::log(SAPI_info, "%s", e.comment());
   
                 HSE_SEND_HEADER_EX_INFO header_info;                  HSE_SEND_HEADER_EX_INFO header_info;
                 header_info.pszStatus="200 OK";                  header_info.pszStatus="500 Internal Server Error";
                 header_info.cchStatus=strlen(header_info.pszStatus);                  header_info.cchStatus=strlen(header_info.pszStatus);
                 header_info.pszHeader=HTTP_CONTENT_TYPE_CAPITALIZED ": text/plain\r\n\r\n";                  header_info.pszHeader=HTTP_CONTENT_TYPE_CAPITALIZED ": text/plain\r\n\r\n";
                 header_info.cchHeader=strlen(header_info.pszHeader);                  header_info.cchHeader=strlen(header_info.pszHeader);
                 header_info.fKeepConn=true;                  header_info.fKeepConn=true;
                                   
                 // send header                  // send header
                 lpECB->dwHttpStatusCode=200;                  lpECB->dwHttpStatusCode=500;
                 lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER_EX, &header_info, NULL, NULL);                  lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER_EX, &header_info, NULL, NULL);
   
                 // send body                  // send body
                 if(!header_only)                  if(strcasecmp(lpECB->lpszMethod, "HEAD")!=0)
                         SAPI::send_body(SAPI_info, e.comment(), strlen(e.comment()));                          SAPI::send_body(SAPI_info, e.comment(), strlen(e.comment()));
   
                 // unsuccessful finish                  // unsuccessful finish
Line 434  BOOL WINAPI DllMain( Line 441  BOOL WINAPI DllMain(
         );          );
   
         return TRUE;          return TRUE;
 }  
   
   }

Removed from v.1.123  
changed lines
  Added in v.1.142


E-mail: