diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 7766762c6c..7cb892c5ee 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,9 @@ +19990601-09:50 CET Eddie Runia + * include/cgi.ch, tests/working/testcgi.prg + CGI test program added + * tests/working/run_exp.h + GetEnv() added + 19990531-23:05 CET Eddie Runia * source/compiler/harbour.y determination of symbol scope now correct. diff --git a/harbour/include/cgi.ch b/harbour/include/cgi.ch new file mode 100644 index 0000000000..577cea074f --- /dev/null +++ b/harbour/include/cgi.ch @@ -0,0 +1,32 @@ +// CGI.ch + +//+ +// Harbour project +// +// +// 99.05.31 initial posting. +// +// +//- + + +#define CGI_SERVER_SOFTWARE 01 +#define CGI_SERVER_NAME 02 +#define CGI_GATEWAY_INTERFACE 03 +#define CGI_SERVER_PROTOCOL 04 +#define CGI_SERVER_PORT 05 +#define CGI_REQUEST_METHOD 06 +#define CGI_HTTP_ACCEPT 07 +#define CGI_HTTP_USER_AGENT 08 +#define CGI_HTTP_REFERER 09 +#define CGI_PATH_INFO 10 +#define CGI_PATH_TRANSLATED 11 +#define CGI_SCRIPT_NAME 12 +#define CGI_QUERY_STRING 13 +#define CGI_REMOTE_HOST 14 +#define CGI_REMOTE_ADDR 15 +#define CGI_REMOTE_USER 16 +#define CGI_AUTH_TYPE 17 +#define CGI_CONTENT_TYPE 18 +#define CGI_CONTENT_LENGTH 19 +#define CGI_ANNOTATION_SERVER 20 diff --git a/harbour/tests/working/run_exp.h b/harbour/tests/working/run_exp.h index 255faa1463..3b3165fe5a 100644 --- a/harbour/tests/working/run_exp.h +++ b/harbour/tests/working/run_exp.h @@ -129,6 +129,7 @@ HARBOUR HB_FGOTO(); HARBOUR HB_FEOF(); HARBOUR HB_FREADLN(); HARBOUR HB_FSKIP(); +HARBOUR GETENV(); /* Same story. @@ -260,7 +261,8 @@ static SYMBOL symbols[] = { { "HB_FGOTO", FS_PUBLIC, HB_FGOTO , 0 }, { "HB_FEOF", FS_PUBLIC, HB_FEOF , 0 }, { "HB_FREADLN", FS_PUBLIC, HB_FREADLN , 0 }, -{ "HB_FSKIP", FS_PUBLIC, HB_FSKIP , 0 } +{ "HB_FSKIP", FS_PUBLIC, HB_FSKIP , 0 }, +{ "GETENV", FS_PUBLIC, GETENV , 0 } }; diff --git a/harbour/tests/working/testcgi.prg b/harbour/tests/working/testcgi.prg new file mode 100644 index 0000000000..3aea45653b --- /dev/null +++ b/harbour/tests/working/testcgi.prg @@ -0,0 +1,301 @@ +/* +* +* TestCGI.PRG +* Harbour Test of a CGI/HTML-Generator class. +* +* 1999/05/30 First implementation. +* +* Tips: - Use ShowResults to make dynamic html (to test dynamic +* results, put the exe file on CGI-BIN dir or equivalent); +* - Use SaveToFile to make static html page +* +* 1999/05/31 Initial CGI functionality. +* 1999/06/01 Translated %nn to correct chars. +* +**/ + +#include "CGI.ch" +#define NewLine chr(10)+chr(13) + +FUNCTION Main() + + LOCAL oHTML := THTML():New() + LOCAL cName := "" + + cName := oHTML:QueryFields( "NAME" ) + + oHTML:SetTitle( "Harbour CGI Scripting Demo" ) + oHTML:AddHead( "Harbour CGI Scripting DEMO" ) + oHTML:AddPara( "


Copyright © 1999 by Harbour Project" + ; + "
Generated at: " + dtoc( date() ) + " - " + time(), "LEFT" ) + oHTML:Generate() + + // Uncomment the following if you don't have a Web Server to test + // this sample + + // oHTML:SaveToFile( "test.htm" ) + + // If the above is uncommented, you may comment this line: + + oHTML:ShowResult() + + RETURN( NIL ) + +FUNCTION Hex2Dec( cHex ) + + LOCAL aHex := { { "0", 00 }, ; + { "1", 01 }, ; + { "2", 02 }, ; + { "3", 03 }, ; + { "4", 04 }, ; + { "5", 05 }, ; + { "6", 06 }, ; + { "7", 07 }, ; + { "8", 08 }, ; + { "9", 09 }, ; + { "A", 10 }, ; + { "B", 11 }, ; + { "C", 12 }, ; + { "D", 13 }, ; + { "E", 14 }, ; + { "F", 15 } } + LOCAL nRet + LOCAL nRes + + nRet := ascan( aHex, { |x| upper( x[1] ) = upper( left( cHex, 1 ) ) } ) + nRes := aHex[nRet, 2] * 16 + nRet := ascan( aHex, { |x| upper( x[1] ) = upper( right( cHex, 1 ) ) } ) + nRes += aHex[nRet, 2] + + RETURN( nRes ) + +/*-------------------------------------------------------------------------*/ + +FUNCTION THTML + + STATIC oClass + + IF oClass == NIL + oClass = TClass():New( "THTML" ) + + oClass:AddData( "cTitle" ) // Page Title + oClass:AddData( "cBody" ) // HTML Body Handler + oClass:AddData( "cBGColor" ) // Background Color + oClass:AddData( "cLinkColor" ) // Link Color + oClass:AddData( "cvLinkColor" ) // Visited Link Color + oClass:AddData( "cContent" ) // Page Content Handler + + oClass:AddData( "aCGIContents" ) + oClass:AddData( "aQueryFields" ) + + oClass:AddMethod( "New", @New() ) // New Method + oClass:AddMethod( "SetTitle", @SetTitle() ) // Set Page Title + oClass:AddMethod( "AddHead", @AddHead() ) // Add

Header + oClass:AddMethod( "AddLink", @AddLink() ) // Add Hyperlink + oClass:AddMethod( "AddPara", @AddPara() ) // Add Paragraph + oClass:AddMethod( "SaveToFile", @SaveToFile() ) // Saves Content to File + oClass:AddMethod( "ShowResult", @ShowResult() ) // Show Result - SEE Fcn + oClass:AddMethod( "Generate", @Generate() ) // Generate HTML + + oClass:AddMethod( "ProcessCGI", @ProcessCGI() ) + oClass:AddMethod( "GetCGIParam", @GetCGIParam() ) + oClass:AddMethod( "QueryFields", @QueryFields() ) + + oClass:Create() + + ENDIF + + RETURN( oClass:Instance() ) + +STATIC FUNCTION New() + + LOCAL Self := QSelf() + + ::cTitle := "Untitled" + ::cBGColor := "#FFFFFF" + ::cLinkColor := "#0000FF" + ::cvLinkColor := "#FF0000" + ::cContent := "" + ::cBody := "" + ::aCGIContents := {} + ::aQueryFields := {} + + RETURN( Self ) + +STATIC FUNCTION SetTitle( cTitle ) + + LOCAL Self := QSelf() + + ::cTitle := cTitle + + RETURN( Self ) + +STATIC FUNCTION AddLink( cLinkTo, cLinkName ) + + LOCAL Self := QSelf() + + ::cBody := ::cBody + ; + "" + cLinkName + "" + + RETURN( Self ) + +STATIC FUNCTION AddHead( cDescr ) + + LOCAL Self := QSelf() + + // Why this doesn't work? + // ::cBody += ... + // ??? + + ::cBody := ::cBody + ; + "

" + cDescr + "

" + + RETURN( NIL ) + +STATIC FUNCTION AddPara( cPara, cAlign ) + + LOCAL Self := QSelf() + + ::cBody := ::cBody + ; + "

" + NewLine + ; + cPara + NewLine + ; + "

" + + RETURN( Self ) + +STATIC FUNCTION Generate() + + LOCAL Self := QSelf() + + ::cContent := ; + "" + NewLine + ; + "" + ::cTitle + "" + NewLine + ; + "" + + NewLine + ; + ::cBody + NewLine + ; + "" + + RETURN( Self ) + +STATIC FUNCTION ShowResult() + + LOCAL Self := QSelf() + + qqOut( ; + "HTTP/1.0 200 OK" + NewLine + ; + "CONTENT-TYPE: TEXT/HTML" + NewLine + NewLine + ; + ::cContent ) + + RETURN( Self ) + +STATIC FUNCTION SaveToFile( cFile ) + + LOCAL Self := QSelf() + LOCAL hFile := fCreate( cFile ) + + fWrite( hFile, ::cContent ) + fClose( hFile ) + + RETURN( Self ) + +STATIC FUNCTION ProcessCGI() + + LOCAL Self := QSelf() + LOCAL cQuery := "" + LOCAL cBuff := "" + LOCAL nBuff := 0 + LOCAL i + + IF empty( ::aCGIContents ) + ::aCGIContents := { ; + GetEnv( "SERVER_SOFTWARE" ), ; + GetEnv( "SERVER_NAME" ), ; + GetEnv( "GATEWAY_INTERFACE" ), ; + GetEnv( "SERVER_PROTOCOL" ), ; + GetEnv( "SERVER_PORT" ), ; + GetEnv( "REQUEST_METHOD" ), ; + GetEnv( "HTTP_ACCEPT" ), ; + GetEnv( "HTTP_USER_AGENT" ), ; + GetEnv( "HTTP_REFERER" ), ; + GetEnv( "PATH_INFO" ), ; + GetEnv( "PATH_TRANSLATED" ), ; + GetEnv( "SCRIPT_NAME" ), ; + GetEnv( "QUERY_STRING" ), ; + GetEnv( "REMOTE_HOST" ), ; + GetEnv( "REMOTE_ADDR" ), ; + GetEnv( "REMOTE_USER" ), ; + GetEnv( "AUTH_TYPE" ), ; + GetEnv( "CONTENT_TYPE" ), ; + GetEnv( "CONTENT_LENGTH" ), ; + GetEnv( "ANNOTATION_SERVER" ) ; + } + + cQuery := ::GetCGIParam( CGI_QUERY_STRING ) + + IF !empty( cQuery ) + + ::aQueryFields := {} + + FOR i := 1 TO len( cQuery ) + 1 + + IF i > len( cQuery ) .OR. substr( cQuery, i, 1 ) == "&" + + aadd( ::aQueryFields, ; + { substr( cBuff, 1, at( "=", cBuff ) - 1 ), ; + strtran( substr( cBuff, at( "=", cBuff ) + 1, ; + len( cBuff ) - at( "=", cBuff ) + 1 ), "+", " " ) } ) + cBuff := "" + ELSE + IF substr( cQuery, i, 1 ) = "%" + cBuff += chr( Hex2Dec( substr( cQuery, i + 1, 2 ) ) ) + nBuff := 3 + ENDIF + + IF nBuff = 0 + cBuff += substr( cQuery, i, 1 ) + ELSE + nBuff-- + ENDIF + ENDIF + + NEXT + + ENDIF + + ENDIF + + RETURN( Self ) + +STATIC FUNCTION GetCGIParam( nParam ) + + LOCAL Self := QSelf() + + ::ProcessCGI() + + IF nParam > 20 .OR. nParam < 1 + outerr( "Invalid CGI parameter" ) + RETURN( NIL ) + ENDIF + + RETURN( ::aCGIContents[nParam] ) + +STATIC FUNCTION QueryFields( cQueryName ) + + LOCAL Self := QSelf() + LOCAL cRet := "" + LOCAL nRet + + ::ProcessCGI() + + nRet := aScan( ::aQueryFields, ; + { |x| upper( x[1] ) = upper( cQueryName ) } ) + + IF nRet > 0 + cRet := ::aQueryFields[nRet, 2] + ENDIF + + RETURN( cRet )