00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <string.h>
00004 #include <windows.h>
00005 #include <time.h>
00006 #include <httpext.h>
00007 #include <process.h>
00008
00009 #include "../../report.h"
00010 #include "../../lexer.h"
00011 #include "../../sym.h"
00012 #include "../../expression.h"
00013 #include "../../syntax.h"
00014 #include "../../reader.h"
00015 #include "../../myalloc.h"
00016 #include "../../builder.h"
00017 #include "../../memory.h"
00018 #include "../../execute.h"
00019 #include "../../buildnum.h"
00020 #include "../../conftree.h"
00021 #include "../../filesys.h"
00022 #include "../../errcodes.h"
00023 #include "../../epreproc.h"
00024 #include "../../uniqfnam.h"
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 static void IsapiStdOutFunction(char Character, LPEXTENSION_CONTROL_BLOCK lpECB){
00040 static DWORD dwBytes = 1;
00041 lpECB->WriteClient(lpECB->ConnID,&Character,&dwBytes,HSE_IO_SYNC);
00042 }
00043
00044
00045
00046
00047
00048
00049 static tConfigTree MyCONF;
00050 static char *szCache;
00051 static char *szReportFile;
00052 static FILE *ReportFile;
00053 CRITICAL_SECTION csReport;
00054 static char *szErrorMessage;
00055
00056 static int DoMemoryCache;
00057 CRITICAL_SECTION csCacheWrite;
00058 static SymbolTable ProgramCache;
00059 static void *pCacheMemorySegment;
00060 typedef struct _CacheItem {
00061 BuildObject *pMyBUILD;
00062 CRITICAL_SECTION csCompile;
00063 }CacheItem,*pCacheItem;
00064
00065 static void IsapiErrorScreen(LPEXTENSION_CONTROL_BLOCK lpECB){
00066 DWORD dwBytes;
00067 static char *szDefaultErrorMessage =
00068 "</PRE></FONT>\n</BODY>\n</HTML>\n";
00069
00070 if( szErrorMessage == NULL )szErrorMessage = szDefaultErrorMessage;
00071
00072 dwBytes = strlen(szErrorMessage);
00073 lpECB->WriteClient(lpECB->ConnID,szErrorMessage,&dwBytes,HSE_IO_SYNC);
00074
00075 }
00076
00077 int GetC(void *f){ return getc((FILE *)f); }
00078
00079 void isapi_report(void *vlpECB,
00080 char *FileName,
00081 long LineNumber,
00082 unsigned int iErrorCode,
00083 int iErrorSeverity,
00084 int *piErrorCounter,
00085 char *szErrorString,
00086 unsigned long *fFlags
00087 ){
00088 char timebuf[9],datebuf[9];
00089 LPEXTENSION_CONTROL_BLOCK lpECB=vlpECB;
00090 char ErrMes[256];
00091 DWORD dwBytes;
00092 static char *szErrorHeader =
00093 "HTTP/1.0 200 OK\nContent-Type: text/html\n\n"
00094 "<HTML>\n<HEAD>\n<TITLE>ScriptBasic Program Error</TITLE>\n</HEAD>\n<BODY BGCOLOR=\"WHITE\">\n"
00095 "<FONT FACE=\"VERDANA\" SIZE=\"2\">\n"
00096 "<H1>ScriptBasic Program Error</H1>\n"
00097 "An error happened while executing the program.<P>\n<FONT SIZE=\"3\"><TT>";
00098
00099 #define EMIT dwBytes = strlen(ErrMes);lpECB->WriteClient(lpECB->ConnID,ErrMes,&dwBytes,HSE_IO_SYNC)
00100
00101 if( !((*fFlags) & REPORT_F_FRST) ){
00102 dwBytes = strlen(szErrorHeader);
00103 lpECB->WriteClient(lpECB->ConnID,szErrorHeader,&dwBytes,HSE_IO_SYNC);
00104 }
00105
00106 if( szReportFile == NULL )return;
00107 EnterCriticalSection(&csReport);
00108 ReportFile = fopen(szReportFile,"a");
00109 if( ReportFile == NULL )
00110 LeaveCriticalSection(&csReport);
00111
00112 _strtime( timebuf );
00113 _strdate( datebuf );
00114 if( szErrorString && strlen(szErrorString) > 80 )szErrorString[79] = (char)0;
00115
00116 if( iErrorSeverity >= REPORT_ERROR && piErrorCounter )(*piErrorCounter)++;
00117
00118 if( ReportFile )fprintf(ReportFile,"%s %s:",datebuf,timebuf);
00119 sprintf(ErrMes,"%s %s:",datebuf,timebuf);
00120 EMIT;
00121 if( FileName && ReportFile )fprintf(ReportFile,"%s(%ld):",FileName,LineNumber);
00122 if( FileName ){
00123 sprintf(ErrMes,"%s(%ld):",FileName,LineNumber);
00124 EMIT;
00125 }
00126 if( ReportFile )
00127 fprintf(ReportFile,(iErrorCode < MAX_ERROR_CODE ? " error &H%x:" : " error 0x%08x:"),iErrorCode);
00128 sprintf(ErrMes,(iErrorCode < MAX_ERROR_CODE ? " error &H%x:" : " error 0x%08x:"),iErrorCode);
00129 EMIT;
00130 if( iErrorCode >= MAX_ERROR_CODE )iErrorCode = COMMAND_ERROR_EXTENSION_SPECIFIC;
00131 if( szErrorString ){
00132 fprintf(ReportFile,en_error_messages[iErrorCode],szErrorString);
00133 fprintf(ReportFile,"\n");
00134 }else
00135 fprintf(ReportFile,"%s\n",en_error_messages[iErrorCode]);
00136
00137 if( szErrorString ){
00138 sprintf(ErrMes,en_error_messages[iErrorCode],szErrorString);
00139 EMIT;
00140 sprintf(ErrMes,"<P>\n");
00141 EMIT;
00142 }else{
00143 sprintf(ErrMes,"%s<P>\n",en_error_messages[iErrorCode]);
00144 EMIT;
00145 }
00146 *fFlags |= REPORT_F_FRST;
00147 if( ReportFile ){
00148 fclose(ReportFile);
00149 LeaveCriticalSection(&csReport);
00150 }
00151 }
00152
00153
00154 DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB){
00155 LexObject MyLEX;
00156 ReadObject MyREAD;
00157 BuildObject *pMyBUILD;
00158 #define MyBUILD (*pMyBUILD)
00159 eXobject MyEX;
00160 ExecuteObject MyEXE;
00161 peNODE_l CommandList;
00162 unsigned long fErrorFlags;
00163 int iError,iErrorCounter;
00164 char *szInputFile;
00165 char *pszPreprocessedFileName=NULL;
00166 int binarycode;
00167 #define FULL_PATH_BUFFER_LENGTH 256
00168 char *s;
00169 char Argv0[FULL_PATH_BUFFER_LENGTH];
00170 char CachedFileName[FULL_PATH_BUFFER_LENGTH];
00171 unsigned long FileTime,CacheTime;
00172 pCacheItem *ppCache;
00173
00174
00175
00176 lpECB->dwHttpStatusCode = 200;
00177
00178
00179 szInputFile = lpECB->lpszPathTranslated;
00180 binarycode = 0;
00181 DoMemoryCache = 0;
00182 if( DoMemoryCache )
00183 ppCache = (pCacheItem *)sym_LookupSymbol(szInputFile,
00184 ProgramCache,
00185 0,
00186 alloc_Alloc,
00187 alloc_Free,
00188 pCacheMemorySegment);
00189
00190 if( DoMemoryCache && ppCache && *ppCache && (*ppCache)->pMyBUILD ){
00191 CodeIsCached:;
00192
00193
00194 EnterCriticalSection( &((*ppCache)->csCompile) );
00195 LeaveCriticalSection( &((*ppCache)->csCompile) );
00196 pMyBUILD = (*ppCache)->pMyBUILD;
00197 }else{
00198
00199 if( DoMemoryCache ){
00200 EnterCriticalSection(&csCacheWrite);
00201 ppCache = (pCacheItem *)sym_LookupSymbol(szInputFile,
00202 ProgramCache,
00203 1,
00204 alloc_Alloc,
00205 alloc_Free,
00206 pCacheMemorySegment);
00207
00208 if( *ppCache && (*ppCache)->pMyBUILD ){
00209
00210
00211
00212
00213
00214 LeaveCriticalSection(&csCacheWrite);
00215 goto CodeIsCached;
00216 }
00217
00218 *ppCache = alloc_Alloc(sizeof(CacheItem),pCacheMemorySegment);
00219 if( *ppCache == NULL ){
00220 sprintf(lpECB->lpszLogData,"Not enough memory.");
00221 IsapiErrorScreen(lpECB);
00222 return HSE_STATUS_SUCCESS;
00223 }
00224 InitializeCriticalSection( &((*ppCache)->csCompile) );
00225 EnterCriticalSection( &((*ppCache)->csCompile) );
00226 LeaveCriticalSection( &csCacheWrite );
00227 }
00228
00229 if( DoMemoryCache )
00230 pMyBUILD = alloc_Alloc(sizeof(BuildObject),pCacheMemorySegment);
00231 else
00232 pMyBUILD = malloc(sizeof(BuildObject));
00233
00234 if( pMyBUILD == NULL ){
00235 if( DoMemoryCache ){
00236 (*ppCache)->pMyBUILD = NULL;
00237 LeaveCriticalSection( &((*ppCache)->csCompile) );
00238 }
00239 sprintf(lpECB->lpszLogData,"Not enough memory.");
00240 IsapiErrorScreen(lpECB);
00241 return HSE_STATUS_SUCCESS;
00242 }
00243
00244 if( DoMemoryCache )
00245 (*ppCache)->pMyBUILD = pMyBUILD;
00246
00247 if( szCache ){
00248 strcpy(CachedFileName,szCache);
00249 s = CachedFileName + strlen(CachedFileName);
00250
00251 strcpy(s,szInputFile);
00252
00253 strcpy(Argv0,s);
00254 uniqfnam(s,s);
00255 FileTime = file_time_modified(szInputFile);
00256 CacheTime = file_time_modified(CachedFileName);
00257 if( FileTime && CacheTime && CacheTime > FileTime ){
00258 szInputFile = CachedFileName;
00259
00260
00261
00262
00263
00264
00265 binarycode = build_IsFileBinaryFormat(szInputFile);
00266 }
00267 }else{
00268 strcpy(Argv0,szInputFile);
00269 }
00270
00271 if( binarycode || build_IsFileBinaryFormat(szInputFile) ){
00272
00273 MyBUILD.memory_allocating_function = malloc;
00274 MyBUILD.memory_releasing_function = free;
00275 MyBUILD.iErrorCounter = 0;
00276 MyBUILD.reportptr = lpECB;
00277 MyBUILD.report = isapi_report;
00278 MyBUILD.fErrorFlags = 0;
00279 build_LoadCode(&MyBUILD,szInputFile);
00280 if( MyBUILD.iErrorCounter ){
00281 if( DoMemoryCache ){
00282 (*ppCache)->pMyBUILD = NULL;
00283 LeaveCriticalSection( &((*ppCache)->csCompile) );
00284 }
00285 alloc_FinishSegment(MyBUILD.pMemorySegment);
00286 sprintf(lpECB->lpszLogData,"There were %d error(s) reading the code %s while executing %s.",MyBUILD.iErrorCounter,szInputFile,Argv0);
00287 IsapiErrorScreen(lpECB);
00288 return HSE_STATUS_SUCCESS;
00289 }
00290 }else{
00291
00292 fErrorFlags = 0;
00293 iErrorCounter = 0;
00294 iError = epreproc(&MyCONF,szInputFile,&pszPreprocessedFileName,NULL,malloc,free);
00295 if( iError ){
00296 isapi_report(stderr,"",0,iError,REPORT_ERROR,&iErrorCounter,NULL,&fErrorFlags);
00297
00298 sprintf(lpECB->lpszLogData,"There was an error executing the externalpreprocessor.");
00299 IsapiErrorScreen(lpECB);
00300 return HSE_STATUS_SUCCESS;
00301 }
00302
00303 reader_InitStructure(&MyREAD);
00304 MyREAD.memory_allocating_function = alloc_Alloc;
00305 MyREAD.memory_releasing_function = alloc_Free;
00306 MyREAD.pMemorySegment = alloc_InitSegment(malloc,free);
00307 MyREAD.report = isapi_report;
00308 MyREAD.reportptr = lpECB;
00309 MyREAD.iErrorCounter = 0;
00310 MyREAD.fErrorFlags = 0;
00311 MyREAD.pConfig = &MyCONF;
00312 if( pszPreprocessedFileName )
00313 reader_ReadLines(&MyREAD,pszPreprocessedFileName);
00314 else
00315 reader_ReadLines(&MyREAD,szInputFile);
00316
00317 if( MyREAD.iErrorCounter ){
00318
00319 if( DoMemoryCache ){
00320 (*ppCache)->pMyBUILD = NULL;
00321 LeaveCriticalSection( &((*ppCache)->csCompile) );
00322 }
00323 sprintf(lpECB->lpszLogData,"There were %d error(s) during read executing %s.",MyREAD.iErrorCounter,szInputFile);
00324 IsapiErrorScreen(lpECB);
00325 return HSE_STATUS_SUCCESS;
00326 }
00327
00328 reader_StartIteration(&MyREAD);
00329
00330 MyLEX.memory_allocating_function = alloc_Alloc;
00331 MyLEX.memory_releasing_function = alloc_Free;
00332 MyLEX.pMemorySegment = alloc_InitSegment(malloc,free);
00333 lex_InitStructure(&MyLEX);
00334
00335 MyLEX.pfGetCharacter = reader_NextCharacter;
00336 MyLEX.pfFileName = reader_FileName;
00337 MyLEX.pfLineNumber = reader_LineNumber;
00338
00339 MyLEX.pNASymbols = NASYMBOLS;
00340 MyLEX.pASymbols = ASYMBOLS;
00341 MyLEX.pCSymbols = CSYMBOLS;
00342 MyLEX.report = isapi_report;
00343 MyLEX.reportptr = lpECB;
00344 MyLEX.fErrorFlags = MyREAD.fErrorFlags;
00345 MyLEX.iErrorCounter = 0;
00346 MyLEX.pLexResult = NULL;
00347
00348
00349 MyLEX.pvInput = (void *)&MyREAD;
00350 lex_ReadInput(&MyLEX);
00351
00352 if( MyLEX.iErrorCounter ){
00353
00354 if( DoMemoryCache ){
00355 (*ppCache)->pMyBUILD = NULL;
00356 LeaveCriticalSection( &((*ppCache)->csCompile) );
00357 }
00358 sprintf(lpECB->lpszLogData,"There were %d error(s) during lex executing %s.",MyLEX.iErrorCounter,szInputFile);
00359 IsapiErrorScreen(lpECB);
00360 return HSE_STATUS_SUCCESS;
00361 }
00362
00363 lex_RemoveComments(&MyLEX);
00364 lex_HandleContinuationLines(&MyLEX);
00365
00366 MyEX.memory_allocating_function = malloc;
00367 MyEX.memory_releasing_function = free;
00368 MyEX.cbBuffer = 1024;
00369 MyEX.cbCurrentNameSpace = 1024;
00370 MyEX.pLex = &MyLEX;
00371
00372 MyEX.Unaries = UNARIES;
00373 MyEX.Binaries = BINARIES;
00374 MyEX.BuiltInFunctions = INTERNALFUNCTIONS;
00375 MyEX.MAXPREC = MAX_BINARY_OPERATOR_PRECEDENCE;
00376 MyEX.PredeclaredLongConstants = PREDLCONSTS;
00377 MyEX.reportptr = lpECB;
00378 MyEX.report = isapi_report;
00379 MyEX.fErrorFlags = MyLEX.fErrorFlags;
00380 MyEX.iErrorCounter = 0;
00381
00382 MyEX.Command = COMMANDS;
00383
00384 ex_init(&MyEX);
00385
00386 ex_Command_l(&MyEX,&CommandList);
00387
00388 if( MyEX.iErrorCounter ){
00389 if( DoMemoryCache ){
00390 (*ppCache)->pMyBUILD = NULL;
00391 LeaveCriticalSection( &((*ppCache)->csCompile) );
00392 }
00393 sprintf(lpECB->lpszLogData,"There were %d error(s) during syntax analisys executing %s.",MyEX.iErrorCounter,szInputFile);
00394 IsapiErrorScreen(lpECB);
00395 return HSE_STATUS_SUCCESS;
00396 }
00397
00398 MyEX.pCommandList = CommandList;
00399
00400 MyBUILD.memory_allocating_function = malloc;
00401 MyBUILD.memory_releasing_function = free;
00402 MyBUILD.pEx = &MyEX;
00403 MyBUILD.iErrorCounter = 0;
00404 MyBUILD.fErrorFlags = MyEX.fErrorFlags;
00405 MyBUILD.FirstUNIXline = NULL;
00406
00407 build_Build(&MyBUILD);
00408
00409 if( MyBUILD.iErrorCounter ){
00410 if( DoMemoryCache ){
00411 (*ppCache)->pMyBUILD = NULL;
00412 LeaveCriticalSection( &((*ppCache)->csCompile) );
00413 }
00414 alloc_FinishSegment(MyBUILD.pMemorySegment);
00415 sprintf(lpECB->lpszLogData,"There were %d error(s) during building executing %s.",MyBUILD.iErrorCounter,szInputFile);
00416 IsapiErrorScreen(lpECB);
00417 return HSE_STATUS_SUCCESS;
00418 }
00419
00420 if( DoMemoryCache )
00421 alloc_Merge(pCacheMemorySegment,MyBUILD.pMemorySegment);
00422
00423
00424
00425
00426 alloc_FinishSegment(MyLEX.pMemorySegment);
00427
00428 ex_free(&MyEX);
00429
00430 if( szCache ){
00431 build_SaveCode(&MyBUILD,CachedFileName);
00432 }
00433 alloc_FinishSegment(MyREAD.pMemorySegment);
00434 }
00435
00436 if( DoMemoryCache )
00437 LeaveCriticalSection( &((*ppCache)->csCompile) );
00438 }
00439
00440 MyEXE.memory_allocating_function = malloc;
00441 MyEXE.memory_releasing_function = free;
00442 MyEXE.reportptr = lpECB;
00443 MyEXE.report = isapi_report;
00444 MyEXE.fErrorFlags = MyEX.fErrorFlags;
00445
00446 MyEXE.pConfig = &MyCONF;
00447
00448 build_MagicCode(&(MyEXE.Ver));
00449 if( execute_InitStructure(&MyEXE,pMyBUILD) ){
00450 sprintf(lpECB->lpszLogData,"Memory low executing %s.",szInputFile);
00451 IsapiErrorScreen(lpECB);
00452 return HSE_STATUS_SUCCESS;
00453 }
00454
00455
00456
00457
00458 MyEXE.CmdLineArgument = "";
00459 MyEXE.pEmbedder = lpECB;
00460 MyEXE.fpStdouFunction = IsapiStdOutFunction;
00461 strcpy(MyEXE.Ver.Variation,"WINISAPI");
00462
00463 execute_Execute(&MyEXE,&iError);
00464 alloc_FinishSegment(MyEXE.pMo->pMemorySegment);
00465 alloc_FinishSegment(MyEXE.pMemorySegment);
00466
00467 if( pszPreprocessedFileName )free(pszPreprocessedFileName);
00468
00469 if( ! DoMemoryCache ){
00470 alloc_FinishSegment(MyBUILD.pMemorySegment);
00471 free(pMyBUILD);
00472 }
00473 sprintf(lpECB->lpszLogData,"Executed %s.",szInputFile);
00474 return HSE_STATUS_SUCCESS;
00475 }
00476
00477 BOOL WINAPI TerminateExtension(DWORD dwFlags){
00478 char timebuf[9],datebuf[9];
00479
00480 switch( dwFlags ){
00481 case HSE_TERM_ADVISORY_UNLOAD:
00482 if( szReportFile != NULL ){
00483 EnterCriticalSection(&csReport);
00484 ReportFile = fopen(szReportFile,"a");
00485 if( ReportFile != NULL ){
00486 _strtime( timebuf );
00487 _strdate( datebuf );
00488 fprintf(ReportFile,"%s %s: ScriptBasic ISAPI variation was unloaded upon request.\n",datebuf,timebuf);
00489 fclose(ReportFile);
00490 }
00491 LeaveCriticalSection(&csReport);
00492 }
00493 alloc_FinishSegment(MyCONF.pMemorySegment);
00494 MyCONF.pMemorySegment = NULL;
00495 return TRUE;
00496 case HSE_TERM_MUST_UNLOAD:
00497 if( szReportFile != NULL ){
00498 EnterCriticalSection(&csReport);
00499 ReportFile = fopen(szReportFile,"a");
00500 if( ReportFile != NULL ){
00501 _strtime( timebuf );
00502 _strdate( datebuf );
00503 fprintf(ReportFile,"%s %s: ScriptBasic ISAPI variation was forcefully unloaded.\n",datebuf,timebuf);
00504 fclose(ReportFile);
00505 }
00506 LeaveCriticalSection(&csReport);
00507 }
00508 alloc_FinishSegment(MyCONF.pMemorySegment);
00509 MyCONF.pMemorySegment = NULL;
00510 return TRUE;
00511 default:;
00512 }
00513 return 0;
00514 }
00515
00516 BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pVer){
00517 char *szErrorMessageFile,*s;
00518 FILE *fp;
00519 int cbErrorMessage;
00520 char timebuf[9],datebuf[9];
00521 void *pMEM;
00522
00523 pMEM = alloc_InitSegment(malloc,free);
00524 if( pMEM == NULL )return FALSE;
00525
00526 cft_start(&MyCONF,alloc_Alloc,alloc_Free,pMEM,
00527 #ifdef WIN32
00528 "Software\\ScriptBasic\\config",
00529 "WINNT\\SCRIBA.INI",
00530 #else
00531 "SCRIBACONF",
00532 "/etc/scriba/basic.conf",
00533 #endif
00534 NULL);
00535 DebugBreak();
00536 szCache = cft_GetString(&MyCONF,"cache");
00537 szCache = NULL;
00538 szReportFile = cft_GetString(&MyCONF,"isapi.report");
00539 InitializeCriticalSection(&csReport);
00540
00541
00542
00543
00544 szErrorMessageFile = cft_GetString(&MyCONF,"isapi.errmesfile");
00545 szErrorMessage = NULL;
00546 if( szErrorMessageFile ){
00547 fp = fopen(szErrorMessageFile,"rb");
00548 if( fp ){
00549 szErrorMessage = (char *)malloc((cbErrorMessage = file_size(szErrorMessageFile))+1);
00550 if( (s=szErrorMessage) && cbErrorMessage ){
00551 while( cbErrorMessage-- )*s++ = getc(fp);
00552 *s = (char)0;
00553 fclose(fp);
00554 }else szErrorMessage = NULL;
00555 }
00556 }
00557
00558 if( szReportFile != NULL ){
00559 EnterCriticalSection(&csReport);
00560 ReportFile = fopen(szReportFile,"a");
00561 if( ReportFile != NULL ){
00562 _strtime( timebuf );
00563 _strdate( datebuf );
00564 fprintf(ReportFile,"%s %s: ScriptBasic ISAPI variation was loaded.\n",datebuf,timebuf);
00565 fclose(fp);
00566 }
00567 LeaveCriticalSection(&csReport);
00568 }
00569
00570
00571
00572
00573
00574 s = cft_GetString(&MyCONF,"isapi.memcache");
00575 if( s ){
00576 pCacheMemorySegment = alloc_InitSegment(malloc,free);
00577 if( pCacheMemorySegment == NULL )return FALSE;
00578 ProgramCache = sym_NewSymbolTable(alloc_Alloc,pCacheMemorySegment);
00579 if( ProgramCache == NULL )return FALSE;
00580 InitializeCriticalSection(&csCacheWrite);
00581 DoMemoryCache = 1;
00582 }else{
00583 DoMemoryCache = 0;
00584 pCacheMemorySegment = NULL;
00585 ProgramCache = NULL;
00586 }
00587
00588 pVer->dwExtensionVersion = HSE_VERSION;
00589 return TRUE;
00590 }