From 5fe6e5393b1afd3bfe75466c0265a7fc7ff79e24 Mon Sep 17 00:00:00 2001 From: Francesco Saverio Giudice Date: Tue, 3 Mar 2009 22:58:09 +0000 Subject: [PATCH] 2009-03-03 23:56 UTC+0100 Francesco Saverio Giudice (info/at/fsgiudice.com) * harbour/contrib/examples/uhttpd/uhttpd.prg * Updated uHTTPD (Work in progress) ! Fixing memory usage attempt. Set PRIVATE vars to NIL when not more used and force collect memory with hb_GCAll( .T. ) * Set Service Threads initial value to 0 + Added support for directory index files + Added support for filters (WIP) * Added creation of error.log file in case of error * Minor changes * harbour/contrib/examples/uhttpd/cgifunc.prg * Fixed comment * harbour/contrib/examples/uhttpd/uhttpd.ini + DirectoryIndex entry ; NOTE: Please check me for memory usage. I have added a comment // FSG - memory check to interested lines. But I'm not sure if this solves the problem. --- harbour/ChangeLog | 20 ++ harbour/contrib/examples/uhttpd/cgifunc.prg | 5 +- harbour/contrib/examples/uhttpd/uhttpd.ini | 5 +- harbour/contrib/examples/uhttpd/uhttpd.prg | 268 +++++++++++++------- 4 files changed, 196 insertions(+), 102 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 56fab6c15d..75c02f8ea5 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,26 @@ 2009-12-31 13:59 UTC+0100 Foo Bar (foo.bar foobar.org) */ +2009-03-03 23:56 UTC+0100 Francesco Saverio Giudice (info/at/fsgiudice.com) + * harbour/contrib/examples/uhttpd/uhttpd.prg + * Updated uHTTPD (Work in progress) + ! Fixing memory usage attempt. + Set PRIVATE vars to NIL when not more used and force + collect memory with hb_GCAll( .T. ) + * Set Service Threads initial value to 0 + + Added support for directory index files + + Added support for filters (WIP) + * Added creation of error.log file in case of error + * Minor changes + * harbour/contrib/examples/uhttpd/cgifunc.prg + * Fixed comment + * harbour/contrib/examples/uhttpd/uhttpd.ini + + DirectoryIndex entry + ; NOTE: Please check me for memory usage. I have added a comment + // FSG - memory check + to interested lines. But I'm not sure if this solves the + problem. + 2009-03-03 22:22 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/tests/speedtst.prg * updated to work with CA-Cl*pper diff --git a/harbour/contrib/examples/uhttpd/cgifunc.prg b/harbour/contrib/examples/uhttpd/cgifunc.prg index fc3717cf45..654b61ec57 100644 --- a/harbour/contrib/examples/uhttpd/cgifunc.prg +++ b/harbour/contrib/examples/uhttpd/cgifunc.prg @@ -53,7 +53,6 @@ #ifdef __XHARBOUR__ #include "hbcompat.ch" #else - //#include "xhb.ch" #include "common.ch" #include "error.ch" @@ -718,8 +717,7 @@ PROCEDURE uhttpd_WriteToLogFile( cString, cLog, lCreate ) nHandle := FOpen( cLog, FO_READWRITE + FO_SHARED) ELSE nHandle := FCreate( cLog ) - // Dopo che lo creato, lo richiudo immediatamente e lo riapro in modo condiviso - // nel caso arrivasse una nuova scrittura + // After creation, I close and reopen it shared IF Ferror() == 0 .AND. nHandle > 0 FClose( nHandle ) nHandle := FOpen( cLog, FO_READWRITE + FO_SHARED) @@ -862,3 +860,4 @@ FUNCTION uhttpd_HGetValue( hHash, cKey ) ENDIF //RETURN IIF( cKey IN hHash:Keys, hHash[ cKey ], NIL ) RETURN xVal + diff --git a/harbour/contrib/examples/uhttpd/uhttpd.ini b/harbour/contrib/examples/uhttpd/uhttpd.ini index b5701b8e22..f2eafabb5f 100644 --- a/harbour/contrib/examples/uhttpd/uhttpd.ini +++ b/harbour/contrib/examples/uhttpd/uhttpd.ini @@ -11,6 +11,9 @@ # --- display folder content #show_indexes = .f. +# --- default index files +#DirectoryIndex = index.html index.htm + [THREADS] # --- how much a thread has to wait a connection before quit #max_wait = 60 @@ -33,4 +36,4 @@ # --- here put aliases to real path # (under document_root path defined above) /info = /cgi-bin/info.hrb -/cookie = /cgi-bin/cookie.hrb +/cookie = /cgi-bin/cookie.hrb \ No newline at end of file diff --git a/harbour/contrib/examples/uhttpd/uhttpd.prg b/harbour/contrib/examples/uhttpd/uhttpd.prg index 0667ddb43a..a9fc804874 100644 --- a/harbour/contrib/examples/uhttpd/uhttpd.prg +++ b/harbour/contrib/examples/uhttpd/uhttpd.prg @@ -122,7 +122,7 @@ #define START_RUNNING_THREADS 4 // Start threads to serve connections #define MAX_RUNNING_THREADS 20 // Max running threads -#define START_SERVICE_THREADS 1 // Initial number for service connections +#define START_SERVICE_THREADS 0 // Initial number for service connections #define MAX_SERVICE_THREADS 3 // Max running threads #define LISTEN_PORT 8082 // differs from standard 80 port for tests in case @@ -130,6 +130,7 @@ #define FILE_STOP ".uhttpd.stop" #define FILE_ACCESS_LOG "logs\access.log" #define FILE_ERROR_LOG "logs\error.log" +#define DIRECTORYINDEX_ARRAY { "index.html", "index.htm" } #define PAGE_STATUS_REFRESH 5 #define THREAD_MAX_WAIT ( 60 ) // HOW MUCH TIME THREAD HAS TO WAIT BEFORE FINISH - IN SECONDS @@ -176,6 +177,7 @@ STATIC s_nServiceConnections, s_nMaxServiceConnections, s_nTotServiceConnections STATIC s_aRunningThreads := {} STATIC s_aServiceThreads := {} STATIC s_hHRBModules := {=>} +STATIC s_aDirectoryIndex #ifdef USE_HB_INET STATIC s_cLocalAddress, s_nLocalPort @@ -197,7 +199,7 @@ FUNCTION MAIN( ... ) LOCAL aThreads, nStartThreads, nMaxThreads, nStartServiceThreads LOCAL i, cPar, lStop LOCAL cGT, cDocumentRoot, lIndexes, cConfig - LOCAL lConsole, lScriptAliasMixedCase + LOCAL lConsole, lScriptAliasMixedCase, aDirectoryIndex LOCAL nProgress := 0 LOCAL hDefault, cLogAccess, cLogError, cSessionPath LOCAL cCmdPort, cCmdDocumentRoot, lCmdIndexes, nCmdStartThreads, nCmdMaxThreads @@ -294,6 +296,7 @@ FUNCTION MAIN( ... ) lIndexes := hDefault[ "MAIN" ][ "SHOW_INDEXES" ] lScriptAliasMixedCase := hDefault[ "MAIN" ][ "SCRIPTALIASMIXEDCASE" ] cSessionPath := hDefault[ "MAIN" ][ "SESSIONPATH" ] + aDirectoryIndex := hDefault[ "MAIN" ][ "DIRECTORYINDEX" ] cLogAccess := hDefault[ "LOGFILES" ][ "ACCESS" ] cLogError := hDefault[ "LOGFILES" ][ "ERROR" ] @@ -393,6 +396,7 @@ FUNCTION MAIN( ... ) s_nMaxServiceConnections := 0 s_nTotServiceConnections := 0 s_cSessionPath := cSessionPath + s_aDirectoryIndex := aDirectoryIndex // --------------------- Open log files ------------------------------------- @@ -456,6 +460,8 @@ FUNCTION MAIN( ... ) WriteToConsole( "Starting AcceptConnection Thread" ) aThreads := {} AADD( aThreads, hb_threadStart( @AcceptConnections() ) ) + //hb_ToOutDebug( "Len( aThreads ) = %i\n\r", Len( aThreads ) ) + // --------------------------------------------------------------------------------- // // main loop @@ -478,10 +484,10 @@ FUNCTION MAIN( ... ) // Show application infos IF hb_mutexLock( s_hmtxBusy ) - hb_DispOutAt( 5, 5, "Threads : " + Transform( s_nThreads, "9999999999" ) ) - hb_DispOutAt( 6, 5, "Connections : " + Transform( s_nConnections, "9999999999" ) ) - hb_DispOutAt( 7, 5, "Max Connections : " + Transform( s_nMaxConnections, "9999999999" ) ) - hb_DispOutAt( 8, 5, "Total Connections : " + Transform( s_nTotConnections, "9999999999" ) ) + hb_DispOutAt( 5, 5, "Threads : " + Transform( s_nThreads, "9999999999" ) ) + hb_DispOutAt( 6, 5, "Connections : " + Transform( s_nConnections, "9999999999" ) ) + hb_DispOutAt( 7, 5, "Max Connections : " + Transform( s_nMaxConnections, "9999999999" ) ) + hb_DispOutAt( 8, 5, "Total Connections : " + Transform( s_nTotConnections, "9999999999" ) ) hb_DispOutAt( 5, 37, "ServiceThreads : " + Transform( s_nServiceThreads, "9999999999" ) ) hb_DispOutAt( 6, 37, "Connections : " + Transform( s_nServiceConnections, "9999999999" ) ) @@ -506,7 +512,7 @@ FUNCTION MAIN( ... ) // Accept a remote connection #ifdef USE_HB_INET - hSocket := HB_INETACCEPT( hListen ) + hSocket := hb_InetAccept( hListen ) #else hSocket := socket_accept( hListen, @aRemote ) #endif @@ -535,10 +541,13 @@ FUNCTION MAIN( ... ) ENDIF + // Memory release + hb_GCAll( TRUE ) // FSG - memory check + ENDDO WriteToConsole( "Waiting threads" ) - // Send to thread that they have to stop + // Send to threads that they have to stop AEVAL( aThreads, {|| hb_mutexNotify( s_hmtxQueue, NIL ) } ) // Wait threads to end AEVAL( aThreads, {|h| hb_threadJoin( h ) } ) @@ -644,7 +653,7 @@ STATIC FUNCTION AcceptConnections() pThread := hb_threadStart( @ServiceConnection(), @nThreadID ) AADD( s_aServiceThreads, { pThread, nThreadID } ) ENDIF - // Otherwise I send connection to service thread + // Otherwise I send connection to current service thread queue hb_mutexNotify( s_hmtxServiceThreads, hSocket ) LOOP @@ -653,9 +662,11 @@ STATIC FUNCTION AcceptConnections() ELSEIF nConnections >= nThreads // Add one more pThread := hb_threadStart( @ProcessConnection(), @nThreadID ) + //hb_ToOutDebug( "Len( s_aRunningThreads ) = %i\n\r", Len( s_aRunningThreads ) ) AADD( s_aRunningThreads, { pThread, nThreadID } ) ENDIF - // Otherwise I send connection to running thread + // Otherwise I send connection to running thread queue + //hb_ToOutDebug( "Len( s_aRunningThreads ) = %i\n\r", Len( s_aRunningThreads ) ) hb_mutexNotify( s_hmtxRunningThreads, hSocket ) ENDDO @@ -673,6 +684,8 @@ STATIC FUNCTION ProcessConnection( /*@*/ nThreadId ) nThreadId := hb_threadID() + //hb_ToOutDebug( "nThreadId = %s\r\n", nThreadId ) + ErrorBlock( { | oError | uhttpd_DefError( oError ) } ) WriteToConsole( "Starting ProcessConnections() " + hb_CStr( nThreadId ) ) @@ -761,19 +774,24 @@ STATIC FUNCTION ProcessConnection( /*@*/ nThreadId ) WriteToLog( cRequest ) + // Destroy PRIVATE VARIABLES // FSG - memory check + _SERVER := _GET := _POST := _COOKIE := _SESSION := _REQUEST := _HTTP_REQUEST := m_cPost := NIL + ENDIF -#ifdef USE_HB_INET - hb_InetClose( hSocket ) -#else - socket_shutdown( hSocket ) - socket_close( hSocket ) -#endif END SEQUENCE nParseTime := hb_milliseconds() - nMsecs WriteToConsole( "Page served in : " + Str( nParseTime/1000, 7, 4 ) + " seconds" ) +#ifdef USE_HB_INET + hb_InetClose( hSocket ) + hSocket := NIL +#else + socket_shutdown( hSocket ) + socket_close( hSocket ) +#endif + IF hb_mutexLock( s_hmtxBusy ) s_nConnections-- hb_mutexUnlock( s_hmtxBusy ) @@ -785,6 +803,7 @@ STATIC FUNCTION ProcessConnection( /*@*/ nThreadId ) IF hb_mutexLock( s_hmtxBusy ) s_nThreads-- + //hb_ToOutDebug( "Len( s_aRunningThreads ) = %i\n\r", Len( s_aRunningThreads ) ) IF ( nPos := aScan( s_aRunningThreads, {|h| h[2] == nThreadId } ) > 0 ) hb_aDel( s_aRunningThreads, nPos, TRUE ) ENDIF @@ -884,18 +903,24 @@ STATIC FUNCTION ServiceConnection( /*@*/ nThreadId ) WriteToLog( cRequest ) + // Destroy PRIVATE VARIABLES // FSG - memory check + _SERVER := _GET := _POST := _COOKIE := _SESSION := _REQUEST := _HTTP_REQUEST := m_cPost := NIL + ENDIF -#ifdef USE_HB_INET - hb_InetClose( hSocket ) -#else - socket_shutdown( hSocket ) - socket_close( hSocket ) -#endif + END SEQUENCE nParseTime := hb_milliseconds() - nMsecs WriteToConsole( "Page served in : " + Str( nParseTime/1000, 7, 4 ) + " seconds" ) +#ifdef USE_HB_INET + hb_InetClose( hSocket ) + hSocket := NIL +#else + socket_shutdown( hSocket ) + socket_close( hSocket ) +#endif + IF hb_mutexLock( s_hmtxBusy ) s_nServiceConnections-- hb_mutexUnlock( s_hmtxBusy ) @@ -922,7 +947,7 @@ STATIC FUNCTION ParseRequest( cRequest ) // RFC2616 aRequest := uhttpd_split( CR_LF, cRequest ) - //hb_toOutDebug( "aRequest = %s\n\r", hb_ValToExp( aRequest ) ) + //hb_ToOutDebug( "aRequest = %s\n\r", hb_ValToExp( aRequest ) ) WriteToConsole( aRequest[1] ) aLine := uhttpd_split( " ", aRequest[1] ) @@ -1384,11 +1409,13 @@ STATIC FUNCTION readRequest( hSocket, /* @ */ cRequest ) DO WHILE /* AT( CR_LF + CR_LF, cRequest ) == 0 .AND. */ nRcvLen > 0 cBuf := hb_InetRecvLine( hSocket, @nRcvLen ) //hb_ToOutDebug( " nRcvLen = %i, cBuf = %s \n\r", nRcvLen, cBuf ) - cRequest += cBuf + CR_LF - nLen += nRcvLen - IF nRcvLen > 0 .AND. At( "CONTENT-LENGTH:", Upper( cBuf ) ) == 1 - cBuf := Substr( cBuf, At( ":", cBuf ) + 1 ) - nContLen := Val( cBuf ) + IF nRcvLen > 0 + cRequest += cBuf + CR_LF + nLen += nRcvLen + IF At( "CONTENT-LENGTH:", Upper( cBuf ) ) == 1 + cBuf := Substr( cBuf, At( ":", cBuf ) + 1 ) + nContLen := Val( cBuf ) + ENDIF ENDIF ENDDO @@ -1397,7 +1424,7 @@ STATIC FUNCTION readRequest( hSocket, /* @ */ cRequest ) IF nLen > 0 .AND. nContLen > 0 // cPostData is autoAllocated cBuf := Space( nContLen ) - IF InetRecvAll( hSocket, @cBuf, nContLen ) <= 0 + IF hb_InetRecvAll( hSocket, @cBuf, nContLen ) <= 0 nLen := -1 // force error check ELSE cRequest += cBuf @@ -1502,7 +1529,7 @@ FUNCTION uhttpd_join( cSeparator, aData ) STATIC FUNCTION uproc_default() LOCAL cFileName, nI, cI - LOCAL cExt, xResult, pHRB, oError, cHRBBody + LOCAL cExt //cFileName := STRTRAN(cRoot + _SERVER["SCRIPT_NAME"], "//", "/") cFileName := _SERVER[ "SCRIPT_FILENAME" ] @@ -1522,14 +1549,21 @@ STATIC FUNCTION uproc_default() //hb_toOutDebug( "cFileName = %s, uhttpd_OSFileName( cFileName ) = %s,\n\r s_hScriptAliases = %s\n\r", cFileName, uhttpd_OSFileName( cFileName ), hb_ValToExp( s_hScriptAliases ) ) + // Server status request IF Upper( _SERVER[ "SCRIPT_NAME" ] ) == "/SERVERSTATUS" + ShowServerStatus() + + // real file request ELSEIF HB_FileExists( uhttpd_OSFileName( cFileName ) ) + IF ( nI := RAT( ".", cFileName ) ) > 0 SWITCH ( cExt := LOWER( SUBSTR( cFileName, nI + 1 ) ) ) - CASE "hrb" ; cI := "text/html"; EXIT - CASE "exe" ; cI := "text/html"; EXIT + // First filters + CASE "hrb" ; EXIT + CASE "exe" ; EXIT + // Then other files CASE "css" ; cI := "text/css"; EXIT CASE "htm" ; CASE "html"; cI := "text/html"; EXIT CASE "txt" ; CASE "text"; CASE "asc" @@ -1566,95 +1600,44 @@ STATIC FUNCTION uproc_default() cI := "application/octet-stream" ENDSWITCH + // Starting Filters IF cExt == "hrb" // Starting HRB module - - TRY - // Lock HRB to avoid MT race conditions - IF !HRB_ACTIVATE_CACHE - cHRBBody := HRB_LoadFromFile( uhttpd_OSFileName( cFileName ) ) - ENDIF - IF hb_mutexLock( s_hmtxHRB ) - IF HRB_ACTIVATE_CACHE - // caching modules - IF !hb_HHasKey( s_hHRBModules, cFileName ) - hb_HSet( s_hHRBModules, cFileName, HRB_LoadFromFile( uhttpd_OSFileName( cFileName ) ) ) - ENDIF - cHRBBody := s_hHRBModules[ cFileName ] - ENDIF - IF !EMPTY( pHRB := HB_HRBLOAD( cHRBBody ) ) - - xResult := HRBMAIN() - - HB_HRBUNLOAD( pHRB ) - ELSE - uhttpd_SetStatusCode( 404 ) - t_cErrorMsg := "File does not exist: " + cFileName - ENDIF - hb_mutexUnlock( s_hmtxHRB ) - - ENDIF - - IF HB_ISSTRING( xResult ) - uhttpd_AddHeader( "Content-Type", cI ) - uhttpd_Write( xResult ) - ELSE - // Application in HRB module is responsible to send HTML content - ENDIF - - CATCH oError - - WriteToConsole( "Error!" ) - - uhttpd_AddHeader( "Content-Type", "text/html" ) - uhttpd_Write( "Error" ) - uhttpd_Write( "
Description: " + hb_cStr( oError:Description ) ) - uhttpd_Write( "
Filename: " + hb_cStr( oError:filename ) ) - uhttpd_Write( "
Operation: " + hb_cStr( oError:operation ) ) - uhttpd_Write( "
OsCode: " + hb_cStr( oError:osCode ) ) - uhttpd_Write( "
GenCode: " + hb_cStr( oError:genCode ) ) - uhttpd_Write( "
SubCode: " + hb_cStr( oError:subCode ) ) - uhttpd_Write( "
SubSystem: " + hb_cStr( oError:subSystem ) ) - uhttpd_Write( "
Args: " + hb_cStr( hb_ValToExp( oError:args ) ) ) - uhttpd_Write( "
ProcName: " + hb_cStr( procname( 0 ) ) ) - uhttpd_Write( "
ProcLine: " + hb_cStr( procline( 0 ) ) ) - END + RETURN Filter_HRB( cFileName ) ELSEIF cExt == "exe" // Starting CGI application - - IF ( CGIExec( uhttpd_OSFileName(cFileName), @xResult ) ) == 0 - - //uhttpd_AddHeader( "Content-Type", cI ) - //uhttpd_Write( xResult ) - RETURN "HTTP/1.1 200 OK " + CR_LF + xResult - - ELSE - - uhttpd_AddHeader( "Content-Type", cI ) - uhttpd_Write( "CGI Error" ) - - ENDIF + RETURN Filter_EXE( cFileName ) ELSE + + // Standard file + uhttpd_AddHeader( "Content-Type", cI ) uhttpd_Write( HB_MEMOREAD( uhttpd_OSFileName( cFileName ) ) ) ENDIF ELSE + // Unknown file type + cI := "application/octet-stream" uhttpd_AddHeader( "Content-Type", cI ) uhttpd_Write( HB_MEMOREAD( uhttpd_OSFileName( cFileName ) ) ) ENDIF + // Directory content request ELSEIF HB_DirExists( uhttpd_OSFileName( cFileName ) ) + + // if it exists as folder, add trailing slash and redirect to it IF RIGHT( cFileName, 1 ) != "/" uhttpd_AddHeader( "Location", "http://" + _SERVER[ "HTTP_HOST" ] + _SERVER[ "SCRIPT_NAME" ] + "/" ) RETURN MakeResponse() ENDIF - IF ASCAN( { "index.html", "index.htm" }, ; + + // Search for directory index file, i.e.: index.html + IF ASCAN( s_aDirectoryIndex, ; {|x| IIF( HB_FileExists( uhttpd_OSFileName( cFileName + X ) ), ( cFileName += X, .T. ), .F. ) } ) > 0 uhttpd_AddHeader( "Content-Type", "text/html" ) uhttpd_Write( HB_MEMOREAD( uhttpd_OSFileName( cFileName ) ) ) @@ -1672,9 +1655,13 @@ STATIC FUNCTION uproc_default() ShowFolder( cFileName ) ELSE + + // We cannot handle request + uhttpd_SetStatusCode( 404 ) t_cErrorMsg := "File does not exist: " + cFileName ENDIF + RETURN MakeResponse() // Define environment SET variables - TODO: Actually only for windows, make multiplatform @@ -1932,7 +1919,8 @@ STATIC FUNCTION ParseIni( cConfig ) "DOCUMENT_ROOT" => EXE_Path() + "\home" ,; "SHOW_INDEXES" => FALSE ,; "SCRIPTALIASMIXEDCASE" => TRUE ,; - "SESSIONPATH" => EXE_Path() + "\sessions" ; + "SESSIONPATH" => EXE_Path() + "\sessions" ,; + "DIRECTORYINDEX" => DIRECTORYINDEX_ARRAY ; },; "LOGFILES" => { ; "ACCESS" => FILE_ACCESS_LOG ,; @@ -1999,6 +1987,11 @@ STATIC FUNCTION ParseIni( cConfig ) // Change APP_DIR macro with current exe path xVal := StrTran( cVal, "$(APP_DIR)", Exe_Path() ) ENDIF + CASE cKey == "DIRECTORYINDEX" + IF !Empty( cVal ) + // Change APP_DIR macro with current exe path + xVal := uhttpd_split( " ", AllTrim( cVal ) ) + ENDIF ENDCASE CASE cSection == "LOGFILES" DO CASE @@ -2135,6 +2128,9 @@ STATIC FUNCTION uhttpd_DefError( oError ) OutErr( hb_OSNewLine() ) OutErr( cCallstack ) + // Write to errorlog + uhttpd_WriteToLogFile( cMessage + HB_OsPathSeparator() + cCallstack, Exe_Path() + "\error.log" ) + ErrorLevel( 1 ) QUIT @@ -2173,3 +2169,79 @@ STATIC FUNCTION ErrorMessage( oError ) ENDCASE RETURN cMessage + +// ------------------ FILTERS --------------------- +STATIC FUNCTION Filter_HRB( cFileName ) + LOCAL xResult + LOCAL cHRBBody, pHRB, oError + + TRY + // Lock HRB to avoid MT race conditions + IF !HRB_ACTIVATE_CACHE + cHRBBody := HRB_LoadFromFile( uhttpd_OSFileName( cFileName ) ) + ENDIF + IF hb_mutexLock( s_hmtxHRB ) + IF HRB_ACTIVATE_CACHE + // caching modules + IF !hb_HHasKey( s_hHRBModules, cFileName ) + hb_HSet( s_hHRBModules, cFileName, HRB_LoadFromFile( uhttpd_OSFileName( cFileName ) ) ) + ENDIF + cHRBBody := s_hHRBModules[ cFileName ] + ENDIF + IF !EMPTY( pHRB := HB_HRBLOAD( cHRBBody ) ) + + xResult := HRBMAIN() + + HB_HRBUNLOAD( pHRB ) + ELSE + uhttpd_SetStatusCode( 404 ) + t_cErrorMsg := "File does not exist: " + cFileName + ENDIF + hb_mutexUnlock( s_hmtxHRB ) + + ENDIF + + IF HB_ISSTRING( xResult ) + uhttpd_AddHeader( "Content-Type", "text/html" ) + uhttpd_Write( xResult ) + ELSE + // Application in HRB module is responsible to send HTML content + ENDIF + + CATCH oError + + WriteToConsole( "Error!" ) + + uhttpd_AddHeader( "Content-Type", "text/html" ) + uhttpd_Write( "Error" ) + uhttpd_Write( "
Description: " + hb_cStr( oError:Description ) ) + uhttpd_Write( "
Filename: " + hb_cStr( oError:filename ) ) + uhttpd_Write( "
Operation: " + hb_cStr( oError:operation ) ) + uhttpd_Write( "
OsCode: " + hb_cStr( oError:osCode ) ) + uhttpd_Write( "
GenCode: " + hb_cStr( oError:genCode ) ) + uhttpd_Write( "
SubCode: " + hb_cStr( oError:subCode ) ) + uhttpd_Write( "
SubSystem: " + hb_cStr( oError:subSystem ) ) + uhttpd_Write( "
Args: " + hb_cStr( hb_ValToExp( oError:args ) ) ) + uhttpd_Write( "
ProcName: " + hb_cStr( procname( 0 ) ) ) + uhttpd_Write( "
ProcLine: " + hb_cStr( procline( 0 ) ) ) + END + + RETURN MakeResponse() + +STATIC FUNCTION Filter_EXE( cFileName ) + LOCAL xResult + + IF ( CGIExec( uhttpd_OSFileName(cFileName), @xResult ) ) == 0 + + //uhttpd_AddHeader( "Content-Type", cI ) + //uhttpd_Write( xResult ) + RETURN "HTTP/1.1 200 OK " + CR_LF + xResult + + ELSE + + uhttpd_AddHeader( "Content-Type", "text/html" ) + uhttpd_Write( "CGI Error" ) + + ENDIF + + RETURN MakeResponse() \ No newline at end of file