West Wind Web Connection For Visual FoxPro

advertisement
West Wind Web Connection
Class and Tool Reference
Class and Tool Reference
 Rick Strahl, West Wind Technologies, 1997
Support: http://www.west-wind.com/wwThreads
Overview of the main classes
The image above describes the main framework classes that are implemented in Visual FoxPro code by Web Connection. The
four important classes are:

wwServer
This class and the wwOLEServer subclass are responsible for communicating with the Web server handling request
routing and passing the input data and output HTTP results between the Web Connection DLL and the Visual FoxPro
framework. Also handles logging and all aspects of the visual server window.
- Page 1 -
West Wind Web Connection
Class and Tool Reference



wwProcess
This is the 'application' class that will be subclassed by you to handle all your application logic. Each Web request
translates into a matching method in this class. While you can write all of your code inside of this class, you can also
delegate logic from your entry method to other objects or user defined functions.
wwCGI/wwPostRequest
You use the wwCGI object as your program input. The wwCGI Object abstracts all the incoming data from the Web
server. This includes server variables, browser information, HTTP information, HTML form variables and Web
Connection status info.
wwHTML
You use the wwHTML object as your program output. The wwHTML class is used to return all output back to the
Web server. Output is string based and this class abstracts the interface with a large collection of both high and low
level methods for creating HTML and HTTP compliant output.
There are additional classes that are subclasses of these four basic classes as well:



wwOLEServer
This subclass is specific to Automation servers. It essentially overrides wwServer's ProcessHit, Init, Error methods to
allow to be able to respond to Automation commands sent by the Web Connection DLL.
wwHTMLString
This subclass of the HTML class keeps output in a result string, rather than sending output to file immediately as the
wwHTML class does. wwHTMLString optimizes string output by dumping large strings to disk – disk based output is
much faster for multiple concats on strings than memory operations. The interface is identical to wwHTML.
wwNetscapeCGI
This subclass of the CGI class is specific to Netscape servers and works around Netscape's non-standard
implementation of the Windows CGI standard.
A number of support classes that are called by these classes and are available for use in your code. Some of the support classes
available are:








wwAPI
A class that contains a number of API functions that are used in Web Connection. Includes INI, Registry access, path
related functions, Process priority function and more.
wwEval
This class allows safe execution of EVALUATEs as well as providing the ability to run entire programs and routines
without requiring the development version of Visual FoxPro. Courtesy of Randy Pearson's CodeBlck class.
wwIPStuff
Provides a number of Internet related functions in a compact DLL with a Visual FoxPro class wrapper. Included are
Async and blocking SMTP, FTP Get and Send, HTTP Get for getting Web pages into a string and DNS and reverse
DNS lookup.
wwHTTPHeader
This class allows building custom HTTP headers with ease. The class allows for adding individual header strings as
well as providing one line access to advanced features such as redirection and Authentication.
wwShowCursor
This powerful class can be used to display table based data in HTML table output with a single method call. It also
includes single record display in both ASCII and HTML table output formats.
wwSession
This class allows you to track users through a site by attaching dynamic variables stored in a table to a user. With this
mechanism you can implement a state table that can remember settings or filters set on previous requests. Works in
conjunction with HTTP Cookies.
wwDBFPopup
This class allows building complex HTML popup boxes that are data driven.
wwHTMLForm
This class allows on the fly display of most Visual FoxPro forms as HTML based forms under Internet Explorer 4.0
(Enterprise Edition only).
- Page 2 -
West Wind Web Connection
Table of Contents
Table of Contents
Class and Tool Reference ......................................................................................................................1
Overview of the main classes .................................................................................................................................................... 1
Table of Contents....................................................................................................................................3
Class wwServer & Class wwOLEServer ..............................................................................................9
Parent Class: wwServerForm Source: wwServer.prg ............................................................................................................ 9
How it works ............................................................................................................................................................................. 9
How to use it.............................................................................................................................................................................. 9
Server Setup ........................................................................................................................................................................ 10
Implementing your own wwServer class............................................................................................................................. 10
Pathing issues and dealing with multiple setups ................................................................................................................. 12
Exposed Properties: ................................................................................................................................................................. 12
Exposed Methods: ................................................................................................................................................................... 13
wwServer::Init .................................................................................................................................................................... 13
wwServer::SetServerEnvironment (virtual) ........................................................................................................................ 13
wwServer::SetServerProperties .......................................................................................................................................... 14
wwServer::ReadSettingsFromIni ........................................................................................................................................ 14
wwServer::SetCGIClass...................................................................................................................................................... 15
wwServer::Show ................................................................................................................................................................. 15
wwServer :: SetCGIFilePath ............................................................................................................................................... 16
wwServer :: SetForegroundTasking .................................................................................................................................... 16
wwServer :: SetTimerInterval ............................................................................................................................................. 17
wwServer :: SetLogToFile .................................................................................................................................................. 17
wwServer :: GetLogToFile ................................................................................................................................................. 18
wwServer :: LogEntry ......................................................................................................................................................... 18
wwServer :: SetStatusWindow ............................................................................................................................................ 19
wwServer :: SetCGITemplateFile ....................................................................................................................................... 19
wwServer :: CleanTempFiles .............................................................................................................................................. 20
wwServer::SendMail........................................................................................................................................................... 20
wwServer :: CreateSessionEntry ......................................................................................................................................... 21
wwServer :: KillSessionEntry ............................................................................................................................................. 22
wwServer :: GetSessionCount............................................................................................................................................. 22
wwServer :: GetAppBasePath() .......................................................................................................................................... 22
Class wwProcess..................................................................................................................................23
Parent Class: Relation Source: wwProcess.prg .................................................................................................................... 23
How it works ........................................................................................................................................................................... 23
Exposed Properties: ................................................................................................................................................................. 25
Exposed Methods .................................................................................................................................................................... 26
wwProcess::Init ................................................................................................................................................................... 26
wwProcess::Process (Virtual) ........................................................................................................................................... 26
wwProcess::InitSession....................................................................................................................................................... 27
wwProcess::GetAppIniVar ................................................................................................................................................. 27
wwProcess::DisplayFile ...................................................................................................................................................... 28
wwProcess::Error ................................................................................................................................................................ 28
wwProcess::StandardPage .................................................................................................................................................. 28
wwProcess::ErrorMsg ......................................................................................................................................................... 29
Class wwCGI .........................................................................................................................................30
Parent Class: Relation Source: wwCGI.PRG ....................................................................................................................... 30
How it works ........................................................................................................................................................................... 30
How to use it............................................................................................................................................................................ 30
wwCGI::Init ........................................................................................................................................................................ 31
wwCGI::LoadCGIFileNames ............................................................................................................................................. 31
- Page 3 -
West Wind Web Connection
Table of Contents
wwCGI::ServerVariables .................................................................................................................................................... 31
wwCGI::GetCGIVar ........................................................................................................................................................... 32
wwCGI::Form ..................................................................................................................................................................... 33
wwCGI::SetKey .................................................................................................................................................................. 33
wwCGI::GetFormCheckBox............................................................................................................................................... 33
wwCGI::GetFormMultiple.................................................................................................................................................. 34
wwCGI::aFormVars ............................................................................................................................................................ 34
wwCGI::GetOutFile ............................................................................................................................................................ 35
wwCGI::GetContentFile ..................................................................................................................................................... 35
wwCGI::QueryString .......................................................................................................................................................... 35
wwCGI::aCGIParms ........................................................................................................................................................... 36
wwCGI::GetCommandLine ................................................................................................................................................ 36
wwCGI::GetPreviousUrl..................................................................................................................................................... 36
wwCGI::GetCurrentUrl ...................................................................................................................................................... 37
wwCGI::GetServerAdmin................................................................................................................................................... 37
wwCGI::GetServerName .................................................................................................................................................... 37
wwCGI::GetRemoteAddress............................................................................................................................................... 37
wwCGI::GetBrowser .......................................................................................................................................................... 38
wwCGI::IsHTML30 ........................................................................................................................................................... 38
wwCGI::IsSecure ................................................................................................................................................................ 38
wwCGI::IsLinkSecure ........................................................................................................................................................ 38
wwCGI::GetClientCertificate ............................................................................................................................................. 39
wwCGI::GetCookie ............................................................................................................................................................ 39
wwCGI::GetRequestMethod ............................................................................................................................................... 39
wwCGI::GetRequestProtocol.............................................................................................................................................. 39
wwCGI::GetAuthenticatedUser .......................................................................................................................................... 40
wwCGI::GetPhysicalPath ................................................................................................................................................... 40
wwCGI::GetLogicalPath ..................................................................................................................................................... 40
wwCGI::ForcePath ............................................................................................................................................................. 40
Class wwPostRequest ..........................................................................................................................41
Parent Class: wwCGI Source: wwPostRequest.prg ............................................................................................................. 41
wCGI::GetMultiPartFile ..................................................................................................................................................... 41
wwCGI::GetMultiPartFormVar .......................................................................................................................................... 42
Class wwHTML .....................................................................................................................................43
Parent Class: Relation Source: wwHTML.prg..................................................................................................................... 43
How it works ........................................................................................................................................................................... 43
wwHTML Class: Exposed Methods ........................................................................................................................................ 43
wwHTML::Init.................................................................................................................................................................... 43
wwHTML::Destroy............................................................................................................................................................. 43
wwHTML::Write ................................................................................................................................................................ 44
wwHTML::Send ................................................................................................................................................................. 44
wwHTML::SendLn ............................................................................................................................................................. 44
wwHTML::FastSend........................................................................................................................................................... 45
wwHTML::SendPar ............................................................................................................................................................ 45
wwHTML::SendMemoLn................................................................................................................................................... 45
wwHTML::BreakMemo ..................................................................................................................................................... 46
wwHTML::ShowCursor ..................................................................................................................................................... 46
wwHTML::ExpandTemplate .............................................................................................................................................. 47
wwHTML::ExpandScript ................................................................................................................................................... 48
wwHTML::EnclosedText ................................................................................................................................................... 49
wwHTML::HeaderText ...................................................................................................................................................... 50
wwHTML::HRef................................................................................................................................................................. 50
wwHTML::HTMLColor ..................................................................................................................................................... 50
wwHTML::List ................................................................................................................................................................... 51
wwHTML::DBFPopup ....................................................................................................................................................... 51
wwHTML::ContentTypeHeader ......................................................................................................................................... 52
wwHTML::HTMLHeader .................................................................................................................................................. 53
- Page 4 -
West Wind Web Connection
Table of Contents
wwHTML::HTMLFooter ................................................................................................................................................... 55
wwHTML::HTMLAuthenticate .......................................................................................................................................... 55
wwHTML::HTMLRedirect ................................................................................................................................................ 56
wwHTML::HTMLError ..................................................................................................................................................... 56
wwHTML::FormTextBox................................................................................................................................................... 57
wwHTML::FormTextArea.................................................................................................................................................. 57
wwHTML::FormButton ...................................................................................................................................................... 58
wwHTML::FormRadio ....................................................................................................................................................... 58
wwHTML::FormCheckbox................................................................................................................................................. 58
wwHTML::NoOutput ......................................................................................................................................................... 59
wwHTML::SetHTTPHeaderClass ...................................................................................................................................... 59
wwHTML::AutoRefresh ..................................................................................................................................................... 59
wwHTML::IEChart............................................................................................................................................................. 60
Class wwHTMLString ...........................................................................................................................62
Parent Class: wwHTML .......................................................................................................................................................... 62
wwHTML::Init.................................................................................................................................................................... 62
wwHTMLString::Send........................................................................................................................................................ 62
wwHTML::GetOutput ........................................................................................................................................................ 63
wwHTML::SetBufferSize ................................................................................................................................................... 63
Class wwShowCursor ..........................................................................................................................64
Parent Class: Relation Source: ShowCursor.prg .................................................................................................................. 64
How it works ........................................................................................................................................................................... 64
Paged ShowCursor Display ..................................................................................................................................................... 65
Exposed Properties .................................................................................................................................................................. 67
Exposed Methods .................................................................................................................................................................... 67
wwShowCursor::Init ........................................................................................................................................................... 67
wwShowCursor::GetOutput ................................................................................................................................................ 68
wwShowCursor::ShowCursor ............................................................................................................................................. 68
wwShowCursor::ShowRecord ............................................................................................................................................ 68
wwShowCursor::ShowASCIIRecord .................................................................................................................................. 69
wwShowCursor::BuildFieldListHeader .............................................................................................................................. 69
wwShowCursor::SetCursor ................................................................................................................................................. 69
Class wwDBFPopup .............................................................................................................................71
Parent Class: Relation Source: DBFPopup .......................................................................................................................... 71
How it works ........................................................................................................................................................................... 71
Exposed Properties .................................................................................................................................................................. 71
Exposed Methods .................................................................................................................................................................... 72
wwDBFPopup::Init ............................................................................................................................................................. 72
wwDBFPopup::GetOutput .................................................................................................................................................. 72
wwDBFPopup::BuildList ................................................................................................................................................... 72
wwDBFPopup::Reset.......................................................................................................................................................... 73
Class wwHTTPHeader ..........................................................................................................................74
Parent Class: Relation Source: wwHTML.prg..................................................................................................................... 74
How it works ........................................................................................................................................................................... 74
wwHTTPHeader::GetOutput .............................................................................................................................................. 75
wwHTTPHeader::CompleteHeader .................................................................................................................................... 75
wwHTTPHeader::ClearHeader ........................................................................................................................................... 75
wwHTTPHeader::DefaultHeader ....................................................................................................................................... 76
wwHTTPHeader::SetProtocol ............................................................................................................................................ 76
wwHTTPHeader::SetContentType ..................................................................................................................................... 76
wwHTTPHeader::AddCookie............................................................................................................................................. 77
wwHTTPHeader::AddForceReload .................................................................................................................................... 77
wwHTTPHeader::More Methods ....................................................................................................................................... 78
Class wwHTMLForm .............................................................................................................................79
Parent Class: wwHTMLControl Source: wwForm.prg ........................................................................................................ 79
How to use it:........................................................................................................................................................................... 79
- Page 5 -
West Wind Web Connection
Table of Contents
Using the wwForm Wrapper ............................................................................................................................................... 79
Using the Class ................................................................................................................................................................... 79
How it works: .......................................................................................................................................................................... 80
Field and Value mapping .................................................................................................................................................... 80
HTML and Script hooks ..................................................................................................................................................... 80
Form Submission and Assigning values back to the form................................................................................................... 80
Rules of Operation .............................................................................................................................................................. 81
Overriding Object Types with your own Renderers............................................................................................................ 81
What doesn’t work .............................................................................................................................................................. 82
How to use it: ...................................................................................................................................................................... 82
Grids ................................................................................................................................................................................... 83
Exposed Properties: ................................................................................................................................................................. 85
Exposed Methods: ................................................................................................................................................................... 85
wwHTMLForm::Init ........................................................................................................................................................... 85
wwHTMLForm::GetOutput ................................................................................................................................................ 86
wwHTMLForm::ShowContainer ........................................................................................................................................ 86
wwHTMLForm::SetValues................................................................................................................................................. 87
wwHTMLForm::OverrideInsertObjectHTML.................................................................................................................... 87
wwHTMLForm::OverrideSetValue .................................................................................................................................... 88
Class wwVFPScript ..............................................................................................................................89
Parent Class: Relation Source: wwVFPScript.prg ............................................................................................................... 89
Related Classes: Request, Response, Session, Server.............................................................................................................. 89
How it works....................................................................................................................................................................... 89
A sample script page ........................................................................................................................................................... 91
Accessing Objects – ASP Objects and Web Connection Objects ....................................................................................... 92
The need to compile............................................................................................................................................................ 92
Class wwSession ..................................................................................................................................94
Parent Class: Relation Source: wwSession.prg .................................................................................................................... 94
How it works ........................................................................................................................................................................... 94
wwSession::Init ................................................................................................................................................................... 96
wwSession::Reindex ........................................................................................................................................................... 97
wwSession::NewSession ..................................................................................................................................................... 97
wwSession::IsValidSession................................................................................................................................................. 97
wwSession::SetSessionVar ................................................................................................................................................. 98
wwSession::GetSessionVar................................................................................................................................................. 98
wwSession::GetUserId ........................................................................................................................................................ 98
wwSession::GetField .......................................................................................................................................................... 99
Class wwIPStuff .................................................................................................................................. 100
Parent Class: Custom
Source: wwIPStuff.vcx .............................................................................................. 100
How it works ......................................................................................................................................................................... 100
How to use it.......................................................................................................................................................................... 101
Sending SMTP Mail ......................................................................................................................................................... 101
Sending and receiving files via FTP ................................................................................................................................. 101
Retrieving HTTP requests to strings (HTTP GET) .......................................................................................................... 102
Sending and Retrieving HTTP requests to strings (HTTP POST) .................................................................................... 102
Sending and Receiving files over HTTP: ......................................................................................................................... 102
Domain Name Lookup ...................................................................................................................................................... 103
Exposed Properties: ............................................................................................................................................................... 103
SMTP properties:.............................................................................................................................................................. 103
FTP Properties: ................................................................................................................................................................. 104
HTTP Properties: .............................................................................................................................................................. 104
Exposed Methods: ................................................................................................................................................................. 105
wwIPStuff::Init ................................................................................................................................................................. 105
wwIPStuff::GetDomainFromIp ......................................................................................................................................... 105
wwIPStuff::GetIPFromDomain ........................................................................................................................................ 106
wwIPStuff::SendMail wwIPStuff::SendMailAsync ......................................................................................................... 106
- Page 6 -
West Wind Web Connection
Table of Contents
wwIPStuff::FTPGetFile .................................................................................................................................................... 107
wwIPStuff::FTPSendFile .................................................................................................................................................. 108
wwIPStuff::FTPDeleteFile................................................................................................................................................ 108
wwIPStuff::aFTPDir ......................................................................................................................................................... 109
wwIPStuff::HTTPGet ....................................................................................................................................................... 109
wwIPStuff::HTTPConnect ................................................................................................................................................ 110
wwIPStuff::HTTPGetEx ................................................................................................................................................... 110
wwIPStuff::OnHTTPBufferUpdate .................................................................................................................................. 111
wwIPStuff::HTTPGetExAsync ......................................................................................................................................... 112
wwIPStuff::AddPostKey ................................................................................................................................................... 113
wwIPStuff::HTTPClose .................................................................................................................................................... 114
wwIPStuff::EncodeDBF ................................................................................................................................................... 114
wwIPStuff::DecodeDBF ................................................................................................................................................... 114
Low Level HTTP Methods ............................................................................................................................................... 115
wwIPStuff::RasDial .......................................................................................................................................................... 115
wwIPStuff::RasHangup..................................................................................................................................................... 116
wwIPStuff::GetSystemErrorMsg ...................................................................................................................................... 116
Class wwHTTPAsync .......................................................................................................................... 117
Parent Class: Timer
Source: wwIPStuff.vcx ............................................................................................................ 118
How it works ......................................................................................................................................................................... 118
Properties and Methods ......................................................................................................................................................... 119
Class wwHTTPData & wwHTTPFile ................................................................................................... 120
Parent Class: aHTTPData
Source: wwIPStuff.vcx ................................................................................................... 120
How it works ......................................................................................................................................................................... 120
The Client Side ................................................................................................................................................................. 120
The Server Side ................................................................................................................................................................ 121
Security.................................................................................................................................................................................. 122
Basic Authentication ......................................................................................................................................................... 122
Secure Sockets Layer (SSL) ............................................................................................................................................. 122
Uploading Files via HTTP with wwHTTPFile ................................................................................................................. 122
wwHTTPData::Execute .................................................................................................................................................... 123
wwHTTPData::S_Execute ................................................................................................................................................ 124
wwHTTPFile::SendFile .................................................................................................................................................... 124
wwHTTPFile::S_SendFile ................................................................................................................................................ 125
Class wwPDF – Adobe Acrobat File Creation ................................................................................... 126
Source: wwPDF.prg............................................................................................................................................................... 126
How to use it:......................................................................................................................................................................... 126
Adobe PDFWriter Configuration .......................................................................................................................................... 127
Support Classes ................................................................................................................................. 129
Class wwAPI ......................................................................................................................................................................... 129
Class wwEval ........................................................................................................................................................................ 131
Procedure Library wwUtils................................................................................................................. 135
Function File2Var .................................................................................................................................................................. 135
Function Extract .................................................................................................................................................................... 135
Function MergeText .............................................................................................................................................................. 135
Function AparseString ........................................................................................................................................................... 136
Function Path ......................................................................................................................................................................... 136
Function OpenExclusive ........................................................................................................................................................ 136
Functions URLEncode and URLDecode ............................................................................................................................... 137
IsComObject .......................................................................................................................................................................... 137
RegisterOleServer.................................................................................................................................................................. 137
DCOMCnfgServer ................................................................................................................................................................. 138
Function GetAppStartPath ..................................................................................................................................................... 138
Function DomainName .......................................................................................................................................................... 138
Function GoURL ................................................................................................................................................................... 138
Function ShowHTML............................................................................................................................................................ 139
- Page 7 -
West Wind Web Connection
Table of Contents
Function StripHTML ............................................................................................................................................................. 139
Function HTMLColor ........................................................................................................................................................... 139
Function DateToC ................................................................................................................................................................. 139
Functions JustFname, JustStem, JustExt, JustPath, ForcePath and AddBs ............................................................................ 140
Function IsDir ........................................................................................................................................................................ 141
Function FileSize ................................................................................................................................................................... 141
Function ProgLevel ............................................................................................................................................................... 141
Function PropertyDump ........................................................................................................................................................ 141
Function InputForm ............................................................................................................................................................... 141
Function PEMStatus .............................................................................................................................................................. 142
Other Tools.......................................................................................................................................... 143
West Wind Web Monitor ...................................................................................................................................................... 143
Web Server Configuration Component ................................................................................................................................. 143
Dependicies: ..................................................................................................................................................................... 143
Text Wrapper......................................................................................................................................................................... 144
ScriptMap .............................................................................................................................................................................. 144
LogCount ............................................................................................................................................................................... 144
- Page 8 -
West Wind Web Connection
Class wwServer & Class wwOLEServer
Class wwServer & Class wwOLEServer
Parent Class: wwServerForm
Source: wwServer.prg
The wwServer Class is responsible for retrieving incoming Web requests and passing them on to a user defined program or
procedure for processing, passing a wwCGI object as a parameter. The user procedure is responsible for creating an output
HTML document or command. When the Process() method returns wwServer returns the output to the Web Server for display
on the client's browser.
How it works
The Web Connection Server responsible for communicating with the Web server is implemented using the following class
hierarchy:

wwServerForm - Visual Form Aspects
 wwServer - Main Server Logic and File Based Messaging Implementation
 wwOleServer - Overrides the relevant wwServer methods for operation as an Automation Server
wwServerForm is a visual class contained in WebConnection.vcx and contains only the visual aspect of the Server component.
wwServer is the heart of the Server classes which contains the core logic of handling incoming Web requests. Web Connection
is set up to handle two communication methods with the Web server using file based messaging using a standalone VFP
application or OLE Automation based messaging using a compile Automation server. wwServer implements the file based
messaging mechanism with wwOLEServer overriding the relevant routines that are different for operation under OLE
Automation. The bottom line is that the external interface of the classes are identical and require no specific knowledge of
whether the code is running under Automation or File based messaging.
File based messaging is implemented using a timer on the main form. The timer polls for request files that are generated by the
Web Connection connector DLL (or EXE in the case of WinCGI). The request files go into a specified directory with a given
file name template that the Web Connection server is waiting for in the polling loop. When a message file is found an internal
method called ProcessHit() is invoked by wwServer. This method retrieves the file along with the path information that is
contained within it pointing at an INI file that contains all the server and HTML form data. The INI file is abstracted into a
wwCGI object by the wwServer object and then passed on to the Process() method which can now handle the Web request by
routing it to a custom program or class.
OLE Automation messaging works similiarily, but takes the polling out of the process. Instead of polling for a file, the
ProcessHit() method of the wwOLEServer class is called directly when a request is incoming. The Web Connection connector
ISAPI DLL loads the Automation server(s) and calls the OLEPUBLIC server ProcessHit() method in the Automation server.
A parameter is passed containing the path of the INI file with the Server and HTML Form data. From here on in the process is
identical to file based messaging: The INI is abstracted into an wwCGI object and the Process() method is invoked.
The wwServer object contains a large number of methods and properties that can be set to configure the server for optimal
performance in your environment.
How to use it
Using the wwServer or wwOleServer classes is a snap. There are two steps for setup: Create a custom class that customizes the
server for your application, then instantiate the server. With file based messaging a mainline program has to load the server,
with Automation the Web Connection DLL simply creates the server. What follows might look like a lot of code, but if you
look closely you'll see that most of it is comments and that you can simply cut and paste the code and change 4 lines of code or
so.
- Page 9 -
West Wind Web Connection
Class wwServer & Class wwOLEServer
Server Setup
With File based messaging the steps come down to initializing the server and then simply showing the server form, which
handles the entire server process. Here’s the code to get the server started and waiting for incoming Web requests using file
based messaging:
#INCLUDE WCONNECT.H
DO WCONNECT
&& Load all the framework classes
oServer=CREATE("wwMyServer")
oServer.show()
RETURN
This code loads the server and displays the server form. Check out the code in wcMain.prg for a more complete setup that sets
the basic environment and provides some basic loadtime error handling.
Implementing your own wwServer class
Before you can instantiate your own server though you have to subclass the Web Connection server. This requires creating a
class and overriding at minimum 2 methods: SetServerEnvironment() which is used to configure the server internally and
Process() which is the entry point routine when a Web hit arrives.
The following code shows a minimal implementation of the server class. Note that there are two class defines, one for the OLE
server and one for the standalone server. This is necessary since both server types share the same method interface, but a
different messing interface – hence the #DEFINE OLESERVER logic to create the appropriate type of server.
#IF OLESERVER
*************************************************************
DEFINE CLASS wcDemoServer AS wwOLEServer OLEPUBLIC
*************************************************************
#ELSE
*************************************************************
DEFINE CLASS wcDemoServer AS wwServer
*************************************************************
#ENDIF
*************************************************************
************************************************************************
* wwCGIServer :: SetServerEnvironment
*************************************
*** This method sets up the environment
*** These settings are required! For a more detailed example
*** on how to handle multiple setups see wcMain.prg
************************************************************************
FUNCTION SetServerEnvironment
*** Must establish root dir
SET DEFAULT TO C:\wwApps\wc2
*** Point at the startup INI file
THIS.cSetupIniFile="C:\WWAPPS\WC2\wcmain.ini"
*** Set up any paths required
DO PATH WITH "WWDEMO"
ENDFUNC
************************************************************************
* wcDemoServer :: SetServerProperties
*************************************
*** Function: This Method should be used to set any server properties
***
This occurs just prior to showing the server window.
***
Optional – if you do call it it's recommended you
- Page 10 -
West Wind Web Connection
Class wwServer & Class wwOLEServer
***
ReadSettingsFromIni().
************************************************************************
FUNCTION SetServerProperties
THIS.ReadSettingsFromIni()
&& Reads from THIS.cSetupIniFile
*** Any settings you want to make to the server
THIS.Caption = " Demo - Web Connection " + WWVERSION
*** You can override anything here, but I suggest you use
*** the INI file for most settings
* THIS.SetTimerInterval(150)
* THIS.SetCGITemplate("XX_")
ENDFUNC
* SetServerProperties
************************************************************************
* wcDemoServer :: Process
*************************
*** Function: This procedure's main purpose is to route incoming
***
requests to individual project PRGs/APPs.
************************************************************************
FUNCTION Process
THIS.oCGI.aCGIParms()
&& Create Array of parameters
lcParameter=UPPER(THIS.oCGI.GetCGIParameter(1)) && Get first Parameter (Project)
*** Set up project
*** Think of these
DO CASE
CASE lcParameter
DO wwDemo with
types and call external processing programs:
as 'projects' that contain many Web request handlers each
== "WWDEMO"
THIS.oCGI,THIS
CASE lcParameter == "WWTHREADS"
DO WWTHREADS WITH THIS.oCGI, THIS
*** SYSTEM TASKS
CASE lcParameter == "WWMAINT"
DO wwMaint with THIS.oCGI, THIS
OTHERWISE
*** No matching method
loHTML=CREATE("wwHTMLString")
loHTML.HTMLError("Unhandled CGI Request",;
"The server is not setup to handle this request: "+lcParameter)
#IF OLESERVER
*** Simply assign to output property
THIS.cOutput=loHTML.GetOutput()
#ELSE
*** File based: We need to create and output to file
loHTML2=CREATE("wwHTML",THIS.oCGI.GetOutFile())
IF TYPE("loHTML2")="O"
loHTML2.Send(loHTML.GetOutput())
ENDIF
#ENDIF
ENDCASE
RETURN
ENDDEFINE
- Page 11 -
West Wind Web Connection
Class wwServer & Class wwOLEServer
Once you've set up the server and you're running you can forget about this code – it's unlikely to require any changes, other than
perhaps an addition for a new 'project' routine or setup for a new site.
Pathing issues and dealing with multiple setups
This brings up the issue of pathing. You might wonder why there are hardcoded path inside of the class. Unfortunately, this is
necessary in order to allow the server to figure out where it's running from – servers might be started from within a system
context which is unlikely to put the default path into a known directory. Hence the server needs to have a baseline to find
supporting data files and the startup config file. In order to support multiple sites I've taken to using a global #DEFINE
LOCALSITE in WCONNECT.H – a numeric value that determines the site that I'm currently running under. In the
wwServer::SetServerEnvironment I can then do the following:
*** This value in WCONNECT.H
#DEFINE LOCALSITE 1
&& 1 – Office
2 – Online
3 – Notebook etc.
*** This code in wwYourServer::SetServerEnvironment()
#IF LOCALSITE=1
SET DEFAULT TO "C:\WWAPPS\WC2\"
THIS.cSetupIniFile="C:\WWAPPS\WC2\wcmain.ini"
#ENDIF
#IF LOCALSITE=2
SET DEFAULT TO C:\WCONNECT
THIS.cSetupIniFile="c:\WCONNECT\wcmain.ini"
#ENDIF
Exposed Properties:
Property
What it does
cTempCGIFile
The wwCGI object that is created whenever a Web request comes in. This object is created once and
then recycled for each hit.
An API object that is used internally by the server, but can also be used externally to minimize
object creation.
The temporary file path where Web Connection stores and retrieves the messaging files used for
communications with the server.
Full file path to the INI file that contains the server information.
cCGIFileTemplate
The three letter template that is used in File based messaging
cDLLIniFile
The name of the Web Connection DLL startup INI file. This file contains the system level
parameters. This value is set only after the first hit from the DLL occurs onto the server.
The startup path of the application. This value is read with GetAppBasePath() and set in the Init() of
this class. The Init does a SET DEFAULT TO (THIS.cAppBasePath). To override this value set it in
SetServerProperties directly or override GetAppBasePath()
The name of the Setup INI file that contains the server's startup parameters. Typically this is the
same name as the mainline program. For example: wcMain.ini. This property is handy for reading
application specific info such as paths from the INI. The file is located using the cAppBasePath
property path.
Contains an error message if the server's ProcessHit() method failed.
oCGI
oAPI
cTempFilePath
cAppBasePath
cSetupIniFile
cErrorString
nScriptMode
Property that determines how the default scriptmaps are for WCS pages are executed. The following
values are available:
2 - Precompiled FXP files
3 - Runtime Interpretation using CodeBlock (default)
For maximum flexibility at design and runtime use the Codeblock method. For maximum speed but
lack of dynamic changes to pages uses 2 precompiled FXP files. Because FXP files are compiled
- Page 12 -
West Wind Web Connection
Class wwServer & Class wwOLEServer
changes made to the script will not reflect until the FXP is recompiled.
Exposed Methods:
wwServer::Init
The class constructor for the wwServer class sets up the basic options for the server class by specifying the program to execute
when a CGI request is received.
Syntax
Return
Arguments
oServer=CREATE(“wwServer”, cTimerClass)
Nothing
CtimerClass
This parameter lets you specify the name of the timer class that is used to poll for
incoming requests. This option allows you to override the default timer and use your own
version, which should be subclassed from wwCGITimer.
Example
oServer=CREATE(“wwServer”,”ProcessCGI”,"MyCGITimer")
Remarks
See Also
wwCGI::SetForegroundTaskingPriority; wwServer::Show;
wwServer::SetCGIClass
wwServer::SetServerEnvironment (virtual)
This method is responsible for setting up the server's environment in terms of path information and finding the setup files to put
the server into a predictable state. Typically you'll set the the DEFAULT directory here and point the cSetupIniFile property at
the server settings INI file.
Syntax
oServer.SetServerEnvironment()
Return
Nothing
Arguments
None.
Example
*** Example implementation of SetServerEnvironment
FUNCTION SetServerEnvironment
*** Location of the startup INI file
THIS.cSetupIniFile= ADDBS(THIS.cAppBasePath) + "wcmain.ini"
*** This URL is executed when clicking on the Automation Server
*** form Exit button. It forces operation through a browser!
THIS.cOleReleaseUrl=;
"http://localhost/wconnect/wc.dll/maintain?release"
#IF !DEBUGMODE
ON ERROR DO ErrorHandler WITH ;
ERROR(),MESSAGE(),MESSAGE(1),SYS(16),LINENO()
IN WCMAIN.PRG
#ENDIF
ENDFUNC
* SetServerEnvironment
- Page 13 -
West Wind Web Connection
Class wwServer & Class wwOLEServer
Remarks
See Also
This method is virtual and must be overridden by your code.
wwServer::SetServerProperties
wwServer::SetServerProperties
This method is responsible for configuring the server object properties. This method is called just before the server is made
visible on the desktop with the Show() method, but after all objects have been created on the form.
Syntax
oServer.SetServerProperties()
Return
Nothing
Arguments
None
Example
*** Sample Implementation
FUNCTION SetServerProperties
THIS.ReadSettingsFromIni()
&& Reads from THIS.cSetupIniFile
*** Any settings you want to make to the server
THIS.Caption = " Demo – Web Connection " + WWVERSION
*** Any path settings should go here – SET DEFAULT already done
DO PATH WITH "WWDEMO"
DO PATH WITH "WWTHREADS"
ENDFUNC
Remarks
See Also
wwServer::SetServerEnvironment
wwServer::ReadSettingsFromIni
This method reads the standard INI file properties at startup. This method is automatically called in SetServerProperties. If you
override SetServerProperties you have to either call this method explicitly or load the following properties according to your set
up:
INI file keys read by ReadSettingFromIni
Path=c:\temp\
Template=WC_
Priority=0
TimerInterval=250
LogToFile=On
ShowStatus=On
SaveRequestFiles=Off
Properties set by ReadSettingsFromIni:
cTempFilePath=""
cCGIFileTemplate="WC_"
nTaskingPriority=0
tmrRequest.Interval=250
lLogStatus=.T.
lShowStatus=.T.
lSaveRequestFiles=.F.
- Page 14 -
West Wind Web Connection
Class wwServer & Class wwOLEServer
Syntax
oServer.ReadSettingsFromIni()
Return
nothing
Arguments
none
Example
PROTECTED FUNCTION SetServerProperties
*** Reads the settings from the WCMAIN.INI file
*** using the THIS.cSetupIniFile member
THIS.ReadSettingsFromINI()
… your additional code here
ENDFUNC
* SetServerProperties
Remarks
See Also
This method is called automatically in SetServerProperties. You should call this method
anytime you override SetServerProperties.
wwServer::SetServerProperties
wwServer::SetCGIClass
This method allows you to specify the CGI class that is instantiated and passed to your user defined function by the Web
Connection CGI Server. This allows you to subclass the CGI class for your own customizations or special Web Server specific
implementations.
Syntax
Return
Arguments
oServer.SetCGIClass( cClassName )
Nothing
cClassName
The name of the class that is instantiated by the CGI Server and passed to the user defined
function.
Example
Remarks
See Also
oServer=CREATE(“wwServer”,”Process”)
oServer.SetCGIClass("MyCGIClass")
oServer.Show
Required only if you are overriding the default wwCGI class provided with Web
Connection.
wwServer::Init
wwServer::Show
The Show method is the do all function that creates the process form, timer and initiates the event loop used to process
incoming CGI requests. By default the form created is modally, but you can pass a parameter of .T. to allow non-modal server
operation.
The Show method is automatically called for Automation servers at the end of the Form's Init.
Syntax
Return
Arguments
oServer.Show( nModal )
nothing
nNotModal
This parameter is not used internally, but required for baseclass compatibility
Example
oServer=CREATE(“wwServer”)
- Page 15 -
West Wind Web Connection
Class wwServer & Class wwOLEServer
oServer.Show()
In this example the server is started and will sit on the Show() method until the form’s
Exit button or close button is clicked.
PUBLIC oServer
oServer=CREATE(“wwServer”)
oServer.Show(0)
In this example the server will continue to run once you return to the FoxPro command
window. Note, that due to the way the VFP timer is used to periodically check for CGI
request files, the server will not check for requests whileVFP processes non-interactive
commands. This means it’ll only work non-modally from the command window, or while
sitting on a READ EVENTS while waiting for input.
Remarks
See Also
wwServer::Init
wwServer :: SetCGIFilePath
Allows you to set the path where the CGI server looks for CGI request files. By default this is the local machine’s TEMP
directory as received through Windows, but you can specify another path, most notable a network drive to move the VFP CGI
Server process onto a machine other than the one running the web server. To run remotely VFP and the entire VFP Web
Connection code resides on a separate network machine, while the web server and wwcgi.dll execute on a dedicated Web
Server machine. In this situation you usually assign the path to something like H:\TEMP where H: is the network drive that
contains the web server. This setting must match the path that is used by the web server and wwcgi.dll to place temporary files,
which with WebSite is in the local machine’s TEMP directory.
Syntax
Return
Arguments
oServer.SetCGIFilePath(cPath)
Nothing
cPath
The path where to look for CGI request files generated by the wwcgi.dll CGI program.
This method is optional and used internally by ReadSettingsFromIni()
Example
Remarks
See Also
oServer=CREATE(“wwServer”)
oServer.SetCGIFilePath(“F:\TEMP\”)
oServer.Show()
Use this method to effectively separate the web server and VFP CGI server process by
pointing at the Web Server’s TEMP over a network link.
wwServer::Init
wwServer :: SetForegroundTasking
Allows you to set the operating system tasking priority of the VFP server process. By default VFP operates as a background
task on the Windows desktop. By bumping up the priority level VFP can drastically speed up processing of requests. Keep in
mind that setting priority levels on VFP will affect other sessions. You need to experiment to find a balance that will allow you
to run multiple VFP sessions with equal response times.
Syntax
Return
Arguments
oServer.SetForegroundTasking(nPriority)
Nothing
nPriority
This is the priority level to set the CGIServer task to. VFP’s normal status is 0 and when
set to a background task results in abysmal performance. The default value set is 1, and is
- Page 16 -
West Wind Web Connection
Class wwServer & Class wwOLEServer
also set by the Init method (higher priority). Valid values are:
0 - Normal (background operation – recommended for multi-session under NT)
1 - Above Normal (recommended for Win95 or single server) Web Connection Default
2 – Highest
15 - Critical (not recommended)
31 - Real Time (not recommended)
Levels above 2 are not recommended as they will shut down even system tasks and mouse
operation.
Example
oServer=CREATE(“wwServer”)
oServer.SetForegroundTasking(2)
Remarks
This option can also be set with the Init method’s nTaskingPriority parameter.
Setting this option may require some tweaking depending on your configuration and on
how you use the VFP Web sessions. As a generic starting point priority 1 works very well.
In addition I find these priority settings adequate:
Single session:
NT: 1
95: 2
Multi-Session:
NT: 0 and set Control Panel Tasking to equal back and foreground
95: 1
See Also
wwServer::Init
wwServer :: SetTimerInterval
Allows you to specify the timer resolution of the polling loop used to check for incoming requests when using file based
messaging. Shorter intervals provide quicker response, but more CPU overhead. This method allows you to control the proper
balance on your own.
Syntax
Return
Arguments
oServer.SetTimerInterval(nInterval)
Nothing
NInterval
The timer interval value in milliseconds. The default (if not called or called without a
parameter) is 250 milliseconds, which works well on Pentium class machines. Slower
machines should use larger numbers to minimize CPU load while polling.
Example
Remarks
See Also
oServer=CREATE(“wwServer”)
oServer.SetTimerInterval(500)
Applies only to file based messaging.
Do not set this value too small or you might incur too high of a CPU load looking for
files. 100 is a good low value for busy servers that are running P166 or faster machines.
wwServer::SetForegroundTasking
wwServer :: SetLogToFile
Turns file logging of requests to a table on or off. By default no logging of requests takes place, but when passed .T. this
function sends all request statistics to the CGILOG.DBF table.
Syntax
Return
oServer.SetLogToFile (lLoggingOn)
Nothing
- Page 17 -
West Wind Web Connection
Class wwServer & Class wwOLEServer
Arguments
lLoggingOn
Turn logging on if .T. off if .F. .F. is the default at form creation time.
Example
Remarks
See Also
oServer=CREATE(“wwServer”)
oServer.SetLogToFile(.T.)
Use only if you need to keep a log of CGI requests since it affects performance slightly. If
you receive lots of requests the log file can big quickly and cause overhead.
CGILOG table logs: Date/Time, CGI parameter string, remote address (if available) and
the processing duration of the query/process.
wwServer::SetStatusWindow; wwServer::LogEntry
wwServer :: GetLogToFile
Tells whether file logging is turned on or off.
Syntax
Return
Example
oServer.GetLogToFile ()
.T. or .F.
llLoggingON=oServer.GetLogToFile()
Remarks
See Also
wwServer::SetLogToFile; wwServer::LogEntry
wwServer :: LogEntry
Places an entry into the log file, but only if request logging is turned on with SetLogToFile(.T.). When logging is enabled this
method is called automatically following each request. Entries are logged into CGILOG.DBF.
Syntax
Return
Arguments
oServer.LogEntry(cDescription, cRemoteAddress, nSeconds)
Nothing
cDescription
When automatic logging is enabled the CGI parameter is passed as the first description. If
you manually call this method use any string that describes the entry. This can be very
handy for writing error messages to the log file in case the program bombs.
There are two template values that you can pass:
START STOP -
Server Startup Entry
Server Shutdown Entry
cRemoteAddress
When automatic logging is enabled the remote address if available is placed into this
parameter. Note that some browser do not pass this information along for privacy reasons.
Use Local for system messages.
nSeconds
When automatic logging is enabled this parameter receives the time that it took to process
a CGI request by the user defined process. This is the same value that is displayed in the
server status window. Use 0 for system log entries or errors.
Example
PUBLIC oServer, glExitCGIServer
ON ERROR DO ERROR WITH ERROR(), MESSAGE(), MESSAGE(1)
- Page 18 -
West Wind Web Connection
Class wwServer & Class wwOLEServer
oServer.SetLogToFile(.T.)
oServer.LogEntry("START")
oServer.Show
oServer.LogEntry("STOP")
&& Turn Logging on
&& Send Start Message to log
PROCEDURE ERROR
LPARAMETER nErrorNo,cErrorMsg1,cErrorMsg2
lcError="Error #"+STR(nErrorNo)+CR+;
cErrorMsg1+CR+cErrorMsg2+CR+CR+;
"CGI Parameter String: "+
oServer.oCGI.GetCGIParameter()
oServer.LogEntry(lcError,"Local",0)
CLOSE DATA
RETURN TO MASTER
Remarks
See Also
wwServer::SetLogToFile
wwServer :: SetStatusWindow
Determines whether the status window shows the server status by displaying the processing light and showing the recent request
in the client area. Turning off the status window can speed operation slightly, since VFP's I/O operations are notoriously slow.
Use this only if you want to eek out every last bit of speed from a processing request or if you are already logging the info to
file.
Syntax
Return
Arguments
oServer.SetStatusWindow(lUpdateWindow)
Nothing
lUpdateWindow
Set to .F. if you don't want the status window to display the last request information.
Example
oServer=CREATE(“wwServer”)
oServer.SetStatusWindow(.F.)
Remarks
Only minor performance enhancements can be achieved by using this option.
See Also
wwServer::SetLogToFile
wwServer :: SetCGITemplateFile
Sets the template for the message file that the CGI server is looking for. The template consists of the first few letters plus a
unique hex string plus a TMP file extension. For example a template of “ww_” would yield: ww_xxxxxx.tmp where the xxxxx
would be a unique hex number. You have to use this method in conjunction with the Template entry in the wwcgi.ini (or
renamed) file setting to create files with this template.
Syntax
Return
Arguments
oServer.SetCGITemplate(cTemplateChars)
Nothing
cTemplateChars
First letters of the temporary message files that the CGI server is looking for. Default is
“wc_”, which is also the wwcgi.dll default.
Example
oServer=CREATE(“wwServer”)
oServer.SetCGITemplate (“wwWeb_”)
- Page 19 -
West Wind Web Connection
Class wwServer & Class wwOLEServer
Remarks
See Also
This method is useful only if you decide to rename the wwcgi.dll file to something else
and edit the corresponding .ini file to create message files with the new template. Using
this approach allows you to essentially separate VFP CGI Servers to process only requests
specific to a particular application for example.
wwcgi.ini Template setting
wwServer :: CleanTempFiles
This routine can be used to clean up any remaining temporary files generated by Web Connection and/or WinCGI Web servers.
Just call the method without parameters and it will clean up the temp files.
Syntax
Return
oServer.CleanTempFiles()
Nothing
Arguments
Example
Remarks
oServer.CleanTempFiles()
Use this method to cleanup leftover temp files. These files can be left over when requests
time out on the FoxPro end and cause the Web Connection connector to terminate the link
before output could be sent back from the FoxPro session.
Call this routine in an infrequently accessed method of your process class to execute
occasionally.
wwServer::SendMail
The SendMail method allows your Web Connection server to send SMTP email messages via an accessible SMTP email server.
SMTP mail is implemented in the wwIPStuff class using its SendMailAsync() method. The wwIPStuff.dll file must be installed
either in your Windows SYSTEM directory or within the FoxPro PATH in order to load the DLL properly. WinSock 2.0 is
required.
Syntax
Return
Arguments
oCGI.SendMail(cMailServer, cSenderDisplayName,;
cSenderEmailAddress, cRepientList, cCCList,;
cSubject, cMessage,;
cAttachment,cBCCList,cContentType)
.T. or .F. If .F. check wwIPStuff::cErrorMsg for an error message
CmailServer
The Domain name or IP Address of the mail server that will handle sending the message.
The mail server must be accessible via a TCP/IP connection at the designated IP address
and you must have a valid account on this mail server to successfully send email. IP
Addresses are in the format “205.111.111.2”.
CsenderDisplayName
The return address name that is displayed on the email message when received. This is the
display name only, not the email address. Note that most mail servers override this with
the name set up on the sending email account.
CsenderEmailAddress
The actual return address email address that is displayed on the email message. This
should be the address that you want replies to be sent to.
CrecipientList
The list of recipients represented as a comma delimited string. All recipients should be
- Page 20 -
West Wind Web Connection
Class wwServer & Class wwOLEServer
entered as fully qualified email addresses. You may also use the following syntax to enter
display names and email addresses:
["Rick Strahl" <rstrahl@west-wind.com>,Bill Dozer <bdozer@mail.com>]
CCCList
List of CCs represented as a comma delimited string. All recipients should be entered as
fully qualified email addresses.
Csubject
The subject for the email message.
Cmessage
The actual message text. This string can be of any length and can contain line breaks as
necessary.
Cattachment
You can attach one file attachment to the message. The file is UUEncoded and must exist
while the message is being sent. Since SendMail works asynchronously you can't delete
the file as part of your request
CcontentType
Allows you to set the Content Type of a message. The default is text/plain, but you can
also set it to text/html to send HTML formatted messages.
Example
Remarks
oServer.SendMail(;
"205.000.000.000",;
"Rick Strahl",;
"rstrahl@west-wind.com",;
"budney@bbatech.com, dan@gorge.net",;
"glenn@gorge.net, webmaster@surplus.com",;
"Test Message",;
"This is a test message."+CR+"End of Message")
All parameters to this method are optional! If not specified the class properties are used
instead and this is the recommended way to use this function. The parameter names
directly correspond to the property names that can be used instead.
Sendmail returns .T. or .F. If it returns .F. you can check the wwIPStuff::cErrorMsg
property for a potential error message
wwServer :: CreateSessionEntry
This and the following functions deal with managing multiple simultaneous Web Connection/Visual FoxPro sessions. These
methods are called by the SESSIONS procedure in the main program file (wcMain).
This method simply writes a session into the current session file. Sessions are created when Web Connection is started and
deleted when it's shut down. The Session table is called WWSESSIONS and is located in the Temp file directory. The file is
accessed only for maintainence tasks.
This method is likely only going to be called internally, but is provided here for completeness since the opposite method
KillSessionEntry is exposed in order to allow for early exits via QUIT.
Syntax
Remarks
See Also
oServer.CreateSessionEntry ()
Creates a session entry in wwSessions.dbf which is located in your CGITemp directory. If
no serious crashing errors occur wwSessions should contain an accurate count of sessions
running
wwServer::KillSessionEntry; wwServer::GetSessionCount
- Page 21 -
West Wind Web Connection
Class wwServer & Class wwOLEServer
wwServer :: KillSessionEntry
KillSessionEntry deletes the current server from the SessionLog file. This method is automatically called in the Destroy event
of this class. However, it's necessary to call this method manually when causing an early exit as required by the Session
functions to exit and recycle Visual FoxPro. When using these call KillSessionEntry to make sure the list of servers is updated
appropirately.
Syntax
Remarks
See Also
oServer.KillSessionEntry ()
Deletes the current server's entry in wwSessions.dbf which is located in your CGITemp
directory. If no serious crashing errors occur wwSessions should contain an accurate
count of sessions running
wwServer::CreateSessionEntry; wwServer::GetSessionCount
wwServer :: GetSessionCount
This method returns the number of sessions that are currently running. The count is based on the number of valid entries in
wwSessions in the CGITempFilePath. .
Syntax
Remarks
See Also
oServer.GetSessionCount ()
Returns the numeric value for the number of sessions. If no sessions are running or an
error occurs accessing the session file the method returns 0.
wwServer::KillSessionEntry; wwServer::GetSessionCount
wwServer :: GetAppBasePath()
This method returns the application startup path. The application startup path comes out of the registry by default – the value is
set from the Status window's Startup Path field (when you click Update Settings). This value is read at application startup. If the
value doesn't exist the startup directory of the EXE/APP/PRG is written to the registry as the new startup path.
This method sets the cAppBasePath property.
You can override this method for special handling of application startup paths and setting the cAppBasePath property.
Syntax
Remarks
See Also
oServer.GetAppBasePath()
Returns the application startup path from the registry.
wwServer::cAppBasePath
- Page 22 -
West Wind Web Connection
Class wwProcess
Class wwProcess
Parent Class: Relation
Source: wwProcess.prg
The wwProcess class is meant to be used as the Web application class or at least as the entry point rotuine for any Web request.
Each Web request has a corresponding method in this class that is called for each request.
The class provides automatic initialization of CGI and HTML objects which become members of the class and are thus
accessible for all process methods. In addition the class provides built in error handling with an Error Method that automatically
displays and logs an error page in case of any error (unless DEBUGMODE is set to .T. in WCONNECT.H in which case the
error bombs for debugging purposes).
The wwProcess class is not a required component in Web Connection. The way Web Connection you can use the main function
that is called of the wwServer::Process() method directly to handle requests without creating an instance of the wwProcess
object. However, use of this class will make life easier for you as it encapsulates access to various other objects in the
framework.
How it works
The wwProcess class is mostly a container class for other objects in order to simplify access to the other objects throughout the
framework. As such only a few custom methods and properties are defined in this class.
Typically a Web Connection request is started off by the wwServer::Process() method calling a UDF or PRG of your choice.
This PRG takes two parameters: a wwCGI and wwServer object. These parameters are used to create a new Process object
which builds references to them and uses them internally making them available for your own routines. The setup code for the
UDF and class creation looks like this:
* PROCEDURE wwDemo
LPARAMETER loCGI, loCGIServer
#INCLUDE WCONNECT.H
#IF OLESERVER
loProcess=CREATE("webConnectDemo",loCGI,loCGIServer,"~","+","wwhtmlstring")
#ELSE
loProcess=CREATE("webConnectDemo",loCGI,loCGIServer,"~","+","wwhtml")
#ENDIF
*** Call the Process Method that handles the request
loProcess.Process()
#IF OLESERVER
*** Must return output to the server in cOutput property
loCGIServer.cOutput=loProcess.oHTML.GetOutput()
#ENDIF
RETURN
The code above basically the two objects as parameters then creates a Process object and calls its Process() method which is its
entry point for Web request processing.
The actual wwProcess class implementation needs to be subclassed by you in order to attach custom processing methods to the
code. The minimal wwProcess subclass looks like this:
*************************************************************
- Page 23 -
West Wind Web Connection
Class wwProcess
DEFINE CLASS webConnectDemo AS wwProcess
*************************************************************
************************************************************************
* webConnectDemo :: HelloWorld
* URL to arrive here: wc.dll?MyPrg~HelloWorld
************************************************************************
FUNCTION HelloWorld
THIS.StandardPage ("Hello World","Hello from Visual FoxPro. "+;
"The current time is: <b>"+Time()+"</b>")
RETURN
*EOF TestPage
FUNCTION OtherRequest
…
ENDFUNC
ENDDEFINE
Each additional request you create with a link from an HTML page (link or Form button that calls wc.dll) needs to have a
corresponding method in this class. Your subclass of wwProcess can contain as many methods as you see fit, although it's best
to logically break up the size of classes into logical classes stored in separate program files or classes. In order to do so you'd
pass a different first 'parameter' on the URL (in the example above MyPrg – MySecondPrg for example) to route to another
PRG file that can handle another set of requests using another subclass of the wwProcess object.
The wwProcess class actually manages calling your code via its entry point method – the Process() method. If you need to do
some logic tasks that need to occur on each hit you should override the Process method with your own code. A typical custom
Process method looks like this:
************************************************************************
* webConnectDemo :: Process
***************************
*** Function: This is the callback program file that handles
***
processing a CGI request
***
Return: .T. to erase Temp File .F. to keep it
************************************************************************
FUNCTION Process
LOCAL lcParameter, lcOutFile, lcIniFile, lcOldError
*** And retrieve the HTMLPagePath and cDataPath vars
THIS.cHTMLPAGEPATH = THIS.GetAppIniVar("HTMLPAGEPATH",THIS.Class)
THIS.cDATAPATH = THIS.GetAppIniVar("DATAPATH",THIS.Class)
*** Retrieve the second parameter PrgFile~Method
lcParameter=UPPER(THIS.oCGI.GetCGIParameter(2))
DO CASE
CASE lcParameter = "DISPLAYFILE" OR lcParameter="SHOWPAGE"
=THIS.DisplayFile(THIS.oCGI.GetCGIParameter(3),THIS.cHTMLPagePath)
*** GENERIC ROUTING BY PARAMETER NAME
CASE !EMPTY(lcParameter) AND PEMSTATUS(THIS,lcParameter,5)
=EVALUATE("THIS."+lcParameter+"()")
OTHERWISE
*** Unhandled method - display error page
THIS.ErrorMsg("The server was unable to respond "+;
"to the CGI request",;
"Parameter Passed: <b>"+PROPER(lcParameter)+"</b><CR>"+;
"Error: <b>Unhandled Method</b>")
ENDCASE
RETURN
- Page 24 -
West Wind Web Connection
Class wwProcess
Some things you might want to do in your custom Process method is do password validation, checking for Authentication,
checking for cookies or other UserIds or anything that basically happens on every or most hits that you don't want to handle on
a specific request each time. For example, to check authorization you might use the following code snippet inside of the
Process() method:
*** Check if user was previously Authenticated
lcUserName=loCGI.GetAuthenticatedUser()
IF EMPTY(lcUserName)
*** User hasn't logged in yet
*** create HTTP header to force dialog
THIS.oHTML.HTMLAuthenticate(loCGI.GetServername())
RETURN .T.
ENDIF
DO CASE
…
ENDCASE
RETURN
The wwProcess object subclass you've created has a built-in error method. The Error method captures all errors that are
generated while processing CGIProcess code. Since all of your processing code will be implemented using new methods in this
subclass the Error method will catch the majority of coding errors. The error method simply returns an error message to the
Web Server thus completing the CGI request even though the actual CGI process failed. The ErrorMsg method is a quick way
to spit out an HTML error page, or any other quick message in response to unexpected events, either under program control or
as a response to an error event. To turn off built-in Error handling you can toggle the #DEFINE DEBUGMODE switch in
WCONNECT.H. When set .T. the Error method is not compiled into the code and errors stop in the VFP debugger for you to
trace or fix the error. When .F. the Error method gets compiled and saves handles the error.
Exposed Properties:
Property
oCGI
oHTML
oCGIServer
oSession
cHTMLPagePath
cDataPath
What it does
An instance of a wwCGI object that is pre-initialized when the Process object
is created. The object is passed in as part of the class Constructor (init()). See
wwProcess::Init for details.
An instance of an HTML that is pre-initialized for the appropriate output
method when the Process object is created. Note: The class that is used for
this object can be passed as the last parameter of the class Constructor
(Init()). See wwProcess::Init for details.
An instance of a wwServer object that is responsible for calling this request.
This back reference allows access to properties and methods of the server
object that might be used for maintenance and error operations.
An instance of a wwSession Object that must be explicitly created using the
InitSession() method. This object automatically manages an HTTP Cookie,
setting and retrieving the value as needed. Once created you can call Get and
SetSessionVar() methods to store user specific data.
Note: This object is not created automatically! The default is .NULL.!
A text variable that is empty by default, but should contain the base physical
HTML path where your code goes looking for template HTML pages. Use
wwProcess::GetAppFromIniFile() to potentially retrieve this value from the
startup INI file.
Note: This property is not filled by default.
A text variable that holds the path to your data. This should be a base path
that is specific for the machine that this request is running on. You can use
wwProcess::GetAppFromIniFile() to retrieve the value from the Setup INI for
- Page 25 -
West Wind Web Connection
Class wwProcess
example.
Note: This property is not filled by default.
Exposed Methods
wwProcess::Init
The wwProcess constructor is responsible for setting up CGI and HTML member objects.
Syntax
oProcess.Init(oCGI, oServer, cParmDelimiter, cParmSpaceChar,
cHTMLClass)
Return
Nothing
Arguments
oCGI
A wwCGI object passed from the Server process.
oServer
A wwServer object passed from the process.
cParmDelimiter
This optional parameter determines the character that is used to separate CGI parameters
passed as part of the CGI command line following the ? for the purpose of automatically
parsing the parameters into an array.
For example: wc.dll?Parameter~Optional+Arguments. The ~ here is a parameter
separator. The default is the ‘~’ character. The above example will create a parameter
array containing 2 elements: ‘Parameter’ and ‘Optional Parameters’. For more details see
the wwCGI::aCGIParms method.
CparmSpaceChar
Since spaces are not allowed as part of the CGI command line, a replacement character is
needed. This parameter specifies the character that is used. By default this character is a
‘+’. Optional.
CHTMLClass
The name of the HTML class that is automatically created. (wwHTML)
Example
See Also
oProcess=CREATE(“wwMyCGIProc”,loCGI,loServer,”&”,”+”,
"wwHTML")
wwCGI::aCGIParms
wwProcess::Process
(Virtual)
This method needs to always be overridden by the subclassed version. This method should be a routing routine that figures out
what task is to be performed based on the parameter(s) that were passed as part of the CGI commandline.
Syntax
Return
Arguments
Example
oProcess.Process(oCGI)
Nothing
OCGI
An wwCGI object as passed by the CGIServer process.
oProcess.Process(loCGI)
- Page 26 -
West Wind Web Connection
Class wwProcess
wwProcess::InitSession
This method is responsible for initializing the oSession object property. The object allows attaching a Session to a particular
user and attachment of any character variables to that user and session using the THIS.oSession.GetSessionVar() and
THIS.oSession.GetSessionVar() methods. This method automatically retrieves a Cookie specified by the single parameter. The
method also sets a cookie on the response request if a new cookie is created as long as an wwHTTPHeader Object, or
wwHTML::ContentTypeHeader, HTMLHeader, ShowHTMLPage, ShowMemoPage are used.
Syntax
Return
Arguments
Example
oProcess.InitSession(cSessionCookieName)
Session ID string (Char 9)
cSessionCookieName
Optional – Name of the Cookie that is automatically set and read.
Default: wwSessionId
loProcess=CREATE("webConnectDemo",loCGI,loServer,,,;
[WWC_wwHTMLstring])
*** Enable Automatic Session Object on every request
loProcess.InitSession()
loProcess.oSession.nSessionTimeout = 3600 && 1 hour
*** Call the Process Method that handles the request
loProcess.Process
*** Usage in wwProcess Request Method
PROCEDURE SomeMethod
lcWhere = THIS.oSession.GetSessionVar("SQLFilter")
IF EMPTY(lcWhere)
lcWhere = ""
ENDIF
SELECT * FROM SomeFile WHERE &lcFilter
*** To retrieve the SessionId for use as a Key use this
lcSessionId = THIS.oSession.cSessionId
INSERT INTO Shoppers (UserId,Visits) VALUES (lcSessionId,1)
ENDPROC
Remarks
See Also
This method must be explicitly called in order to create the oSession object. If not called
the object will be .NULL. You can choose between using the object as in the example
above on every request, or selectively in just the methods that require it. The latter is
usually more efficient unless every request requires the object.
WwSession Class
wwProcess::GetAppIniVar
This method retrieves values from the startup INI file. Typically the name of this file will have the same name as the mainline
program such as wcmain.ini for wcmain.exe/prg. Values are retrieved from a specific section of the file – by default this section
carries the same name as the name of your subclass of this wwProcess implementation.
You can use this method to store and retrieve app specific settings from the startup INI file. Good values to pull include an
HTML base path and the path to your data files.
Syntax
Return
Arguments
oProcess.GetAppIniVar (cValue, cSection)
String value of the key or "" if not found.
cValue
- Page 27 -
West Wind Web Connection
Class wwProcess
The value to retrieve
cSection
INI file section. If not passed the name of the current class is used.
Example
* wwMyProcess :: Process
PROCEDURE Process
THIS.cHTMLPagePath=THIS.GetAppIniVar("HTMLPagePath",;
"wwMyProcess")
THIS.cDataPath=THIS.GetAppIniVar("DataPath")
ENDPROC
See Also
wwProcess::DisplayFile
This is a highlevel method that allows generic display of Web Connection HTML files containing embedded FoxPro
expressions or code blocks. To call this method from a URL you would simply do:
<a HREF="http://www.west-wind.com/displayfile~Nocode.wc">No code required</a>
In order for this to work you need to set up a special handler in the Process method to allow routing any call using DisplayFile
to this routine:
CASE lcParameter="DISPLAYFILE"
=THIS.DisplayFile(loCGI.GetCGIParameter(2),HTMLPAGEPATH)
Once this is set up, though, no more code is required to diplay any page that contains embedded FoxPro code!
Syntax
Return
Arguments
oProcess.DisplayFile(cPageFile, cBaseHTMLPath)
nothing
cPageFile
Filename of the the HTML template file to display.
cBaseHTMLPath
Path where the page is to be displayed in. Note that this path should be the base path - any
subpaths that are server relative can be specified directly in the URL.
Example
oProcess.DisplayFile("Nocode.wc",HTMLPAGEPATH)
wwProcess::Error
This method captures all errors that occur while processing occurs in the wwProccess class. It calls the ErrorMsg method to
display an error page and log the error to the error log.
wwProcess::StandardPage
This method can be used to quickly display a simple HTML page by passing a title and a message. The page is generated with a
simple header and the message text. This page is fully self contained including a standard HTTP header.
Syntax
Return
Arguments
oProcess.StandardPage(cTitle, cMessage)
Nothing
cTitle
- Page 28 -
West Wind Web Connection
Class wwProcess
The page header. The header is displayed in <h2> text followed by an <HR> line. The
window title of the browser is also set.
cMessage
The main message text for the page. Note – this text can include HTML formatted text.
Example
oProcess.ErrorMsg("Query Results",;
lcResultHTML)
wwProcess::ErrorMsg
Same as StandardPage – included only for backwards compatibility as well as for readability to distinguish error messages from
simple status message pages.
Syntax
Return
Arguments
oProcess.ErrorMsg(cTitle, cMessage)
Nothing
cTitle
The page header. The header is displayed in <h2> text followed by an <HR> line. The
window title of the browser is also set.
cMessage
The main message text for the page. Note – this text can include HTML formatted text.
Example
oProcess.ErrorMsg("Invalid Input",;
"Make sure you enter a name..")
- Page 29 -
West Wind Web Connection
Class wwCGI
Class wwCGI
Parent Class: Relation
Source: wwCGI.PRG
The wwCGI class’ purpose is to allow your programs to receive information from the web server and the HTML page that
generated a CGI request. With it you can retrieve values from variables placed on HTML forms and information about the web
server, the client and its browser.
An instance of this class is passed to your VFP program that is responsible for creating an HTML form in response to a CGI
request generated by the server.
How it works
A CGIServer object waits for incoming CGI requests. When the Web Server generates a CGI request it is picked up by the VFP
CGI request server which in turn passes the wwCGI object to your user defined procedure or program.
The wwCGI class’ methods provide easy access to all of the CGI options provided by the server. Website uses an INI file that
contains all of the CGI parameters and envrionment variables which are easily accessed with the wwCGI classes methods. The
various Get Methods of this class provide specialized and formatted access to all of the CGI variables made available by the
web server with specialized methods available for the most commonly used variables.
How to use it
Your use of the wwCGI class consists mainly of retrieving variables and server stats from the CGI request. Here’s the startup
code for the Process procedure that is called when there is an incoming CGI request:
PROCEDURE Process
LPARAMETERS loCGI
LOCAL lcParameter, lcOutFile, lcIniFile
lcParameter=loCGI.GetCGIParameter()
lcOutFile=loCGI.GetOutfile()
lcLastName=loCGI.GetVar(“LastName”)
&& Optional CGI parameters following EXE name
&& The output HTML file
&& Retrieve the last name entered into form
The procedure receives a CGI object as a parameter and then immediately pulls some vital information from the CGI request:
The optional parameter passed on the CGI command line (ie. /cgi-win/wwcgi?Test_Page) which is used to determine the type
of request we’re dealing with, the output file name which is the name of the output HTML file we need to create. For
illustration purposes the example also pulls a form variable from the CGI request, but normally this is better left to the specific
request handler code that processes a given CGI request.
- Page 30 -
West Wind Web Connection
Class wwCGI
wwCGI::Init
This constructor of the wwCGI class takes a CGI commandline and assigns a basic set of CGI variables that allow retrieval of
all CGI variables from the CGI content file created by the Web Server. In addition, you can specify a path where wwCGI looks
for its temporary file. The latter parameter is used to map file names to network drives if the web server is running on a nonlocal machine.
Syntax
Return
Arguments
oCGI=CREATE(“wwCGI”,cCommandLine,cTempFilePath)
Nothing
cCommandLine
The constructor of the wwCGI class must be passed a CGI command line that was passed
by the web server. The webserver calls the wwcgi.dll file, which in turn captures the
commandline. This commandline contains the filenames of the content INI file, the output
file, as well as any of the optional CGI parameters that where passed as part of the CGI
command issued by the HTML form following a ‘?’ or other CGI path directive.
CtempFilePath
This optional parameter is important only when the web server is not running on the local
machine and is accessed over a network connection. By passing the path that contains the
temporary files the web server generates its temporary files to the GetOutFile() and
GetContentFile() are automatically translated and mapped to the remote drive.
By default this value is assigned by the wwServer class when it passes the CGI request to
you - the path is determined by the server’s SetCGIFilePath method.
Example
Remarks
See Also
oCGI=CREATE(“wwCGI”,”ProcessCGI”,lcCommandline)
You shouldn’t have to worry about this constructor, since the CGI object is created for
you in the wwServer class code and both parameters are passed to you pre-set.
wwCGI::LoadCGIFileNames; wwCGI::ForcePath
wwCGI::LoadCGIFileNames
This method assigns the filenames passed on the Webserver command line. Each time a request is incoming the filenames are
updated to reflect the latest input and output files specified by the CGI request.
Syntax
Return
Arguments
oCGI.LoadCGIFileNames(cCommandLine)
Nothing
cCommandLine
The Web Servers command line passed to the wwcgi.dll program file.
Example
Remarks
See Also
oCGI.LoadCGIFileNames(lcCommandLine)
You shouldn’t have to worry about this method, since this assignment is made
automatically for you when the wwServer class receives a request.
wwCGI::Init
wwCGI::ServerVariables
This is the low level method that allows accessing all CGI variables contained in the Website request information.This method
allows access to all variables. To see a complete list of avaiable keys use the Status form's Save Request Files option to capture
- Page 31 -
West Wind Web Connection
Class wwCGI
and view the request file. Most keys are abstracted with full methods listed below, but those few keys that don't have dedicated
methods can be accessed directly
Syntax
Return
Arguments
oCGI.ServerVariables (cVariable,cSection,lForceNull)
CGI Variable string or .NULL.
cEntry
The entry/key from the INI file to return.
cSection
Optional. This applies only when using the INI file Post Method where keys are separated
into sections. Default: CGI
Example
Remarks
See Also
oCGI.ServerVariables (“Server Name”)
This function allows you access to those values that aren’t as commonly accessed and thus
have no specific methods associated with them below. Use the specialized methods when
available.
Specific variable retrieval methods
wwCGI::GetCGIVar
This is the low level method that allows accessing all CGI variables contained in the Website content file. The content file
contains information about form variables, the web server and the calling web browser.
More specialized methods that retrieve and format specific values from the CGI file are provided below. For all available CGI
variables check your WebSite documentation.
Syntax
Return
Arguments
oCGI.GetCGIVar(cEntry,cSection,lForceNull)
CGI Variable string or .NULL.
cEntry
The entry/key from the INI file to return.
Csection
The INI file section from the INI file to return. This parameter is optional and defaults to
the ‘CGI’ section which contains standard CGI variables.
LForceNull
Pass as .T. if you want .NULL. to be returned for missing entries. Otherwise a null string
is returned, which also applies to empty entries.
This optional parameter allows you to specify how non-existant entries are returned. The
wwAPI::GetProfilestring method returns a .NULL. value by default, but for the CGI
purposes it is more useful to return a null string (“”) instead so no additional checking for
.NULL. has to take place.
Example
Remarks
See Also
oCGI.GetCGIVar(“Query String”,”CGI”)
This function allows you access to those values that aren’t as commonly accessed and thus
have no specific methods associated with them below. Use the specialized methods when
available.
Specific variable retrieval methods
- Page 32 -
West Wind Web Connection
Class wwCGI
wwCGI::Form
This method retrieves HTML form variables from the CGI content file. It works both with plain variables and for long text vars
or variables with embedded control characters.
Syntax
Return
Arguments
Example
Remarks
See Also
oCGI.Form(cVarname)
Value entered on the form or “”
cVarname
The name of the form variable to retrieve a value for as defined on the HTML form’s
NAME property.
oCGI.Form(“LastName”)
The format used follows CGI conventions for the various variable types like SELECT
MULTIPLE, radio buttons and lists. Variables are formatted (ie. Spaces and control
characters are properly translated).
wwCGI::GetFormMultiple; wwCGI::ScatterFormVars
wwCGI::SetKey
This method allows setting a value in the existing CGI object INI file. Useful when using Auto update functions such as the
wwHTMLForm :: SetValues() method when trying to not update certain fields on a form automatically.
Syntax
Return
Arguments
oCGI.SetKey(cKey,cValue,cSection)
Nothing
cKey
The entry/key from the INI file.
cValue
The value to set the key to.
cSection
Section where the key lives.
Default: Form Literal
Example
*** First let's make sure these values are *NOT* updated by
*** setting them to 'Null'
loCGI.SetKey("lstGuests",WWC_NULLSTRING)
loCGI.SetKey("txtCustId",WWC_NULLSTRING)
loCGI.SetKey("txtEntered",WWC_NULLSTRING)
*** Now update the rest of the form from the request
oHTMLForm.SetValues(loCGI)
Remarks
This method makes it possible to dynamically set values in the existing request. Use to
manipulate the key values prior to being used by 'generic' processing routines.
You can delete a key by passing CHR(0) as the value.
You can use WWC_NULLSTRING as a value to let WC methods know that the value is
invalid or should be left alone.
See Also
wwCGI::GetFormCheckBox
This method retrieves HTML form variables that is a checkbox and returns a logical value rather than ON or OFF.
- Page 33 -
West Wind Web Connection
Class wwCGI
Syntax
Return
Arguments
oCGI.GetFormCheckBox(cVarname)
.T. or .F.
cVarname
The name of the form checkbox variable to retrieve a value for as defined on the HTML
form’s NAME property.
Example
Remarks
See Also
oCGI.GetFormVar(“chkDownloadData”)
The format used follows CGI conventions for the various variable types like SELECT
MULTIPLE, radio buttons and lists. Variables are formatted (ie. Spaces and control
characters are properly translated).
wwCGI::GetFormVar; wwCGI::ScatterFormVars
wwCGI::GetFormMultiple
This method retrieves multiselect HTML form variables from the CGI content file into an array. Multiselect variables can be
returned when using scrolling HTML lists with the SELECT MULTIPE option.
Syntax
Return
Arguments
oCGI.GetFormMultiple(@aVars,cVarName)
Count of variables returned.
aVars
This is the array that will return the selected values. Must be passed by reference!
cVarname
The variable name used on the HTML form to define the SELECT MULTIPLE tag.
Example
Remarks
See Also
DIMENSION laVars[1]
lnVars=oCGI.GetFormMultiple(@laVars,“LastName”)
The format used follows CGI conventions for the various variable types. Variables are
returned formatted and decoded (ie. Spaces and control characters are properly
translated).
wwCGI::GetFormVar
wwCGI::aFormVars
Returns all the form vars captured by a request into an array. The array contains 2 dimensions – the name of the form variable
and its text value. Use this function to generically retrieve all the information of a form for library routines or repetitive input
captures that can be automated.
Syntax
Return
Arguments
nVarCount=oCGI.aFormVars (@laFormVars)
The number of variables that were created
@laFormVars
An array that will receive the 2 dimensional array result. Must be passed by reference
using the @ operator.
Example
DIMENSION laFormVars[1]
lnVars = THIS.oCGI.aFormVars(@laFormVars)
*** Output all form vars
FOR x = 1 to lnVars
loHTML.SendLn(laFormvars[x,1] + ": " + laFormVars[x,2])
- Page 34 -
West Wind Web Connection
Class wwCGI
ENDFOR
Remarks
See Also
MuliSelect values are not directly supported. These values are returned as they appear in
the ISAPI request: MultiVar, MultiVar_1, Multivar_2 etc. and are returned as individual
variables.
Also note that CheckBoxes that are not checked are not returned as a (empty) key as the
ISAPI/CGI request does not make them available.
wwCGI::GetFormVar; wwCGI::GetFormMultiple
wwCGI::GetOutFile
This method returns the name of the output file that the web server expects to receive as a result of the CGI request. The output
file must be a MIME/HTML compliant document (see your WebSite or general CGI documention for details).
Syntax
Return
oCGI.GetOutFile()
The output file name. Applies only to file based messaging.
wwCGI::GetContentFile
This method returns the name of the CGI content file. This method is probably most useful for debugging purposes so you can
capture the output file and save it for closer examination.
Under normal circumstances you shouldn’t need to know what the Content file name is as the class encapsulates it for you and
automatically accesses it for all CGI variable requests.
Syntax
Return
oCGI.GetContentFile()
The Content file name
wwCGI::QueryString
This method returns the Query String and individual pieces of it. The method supports both numeric,positional parameters and
named parameters. Positional parameters are great for grabbing request information:
wc.dll?ClientForm~West+Wind+Technologies~ID0001
URLEncoded parameters are better for optional parameters and look like this:
wc.dll?UserName=Rick+Strahl&UserId=0111&Address=400+Morton%0A%0Dhood+River,+OR
Essentially spaces are converted to + signs, keys are separated by & and any control characters are converted to hex
representations preceeded by a % sign.
You can mix positional and URLEncoded parameters by adding a separating ~ between the posititional parms and the named
ones:
wc.dll?wwdemo~URLTest~&Username=Rick+Strahl&Company=West+Wind
which allows you to use both GetCGIParameter(2), which returns URLTest or QueryString("Company") which returns West
Wind.
- Page 35 -
West Wind Web Connection
Class wwCGI
Syntax
Return
Arguments
oCGI.QueryString(vParameterName)
Returns the value of the parameter key specified as the parameter. If the parameter key
specified does not exist a null string ("") is returned.
cParameterName
The parameter key name to retrieve. The parameter can either be numeric for a positional
parameter or character to return a URLEncoded parameter. If no parameter is specified
the entire querystring is returned.
Remarks
The key name specified is case sensitive! In the example above, "UserName" works
"USERNAME" does not.
Parameter styles may be mixed. You can use Web Connection style parameters as long as
the URLEncoded parameters follow the WC parameters. To make things more efficient
when mixing styles preceed the first URLEncoded parameter with a &.
Example
See Also
lcName=loCGI.QueryString ("UserName")
lcRequest = loCGI.QueryString(2)
wwCGI::GetCGIParameter
wwCGI::aCGIParms
This method parses all numeric parameters separated by ~ into an internal array property, translating the decoding parameters.
This array of arguments is then accessible by using GetCGIParameter(nParameterIndex).
Syntax
Return
Arguments
oCGI.aCGIParms(cSeperator, cSpaceChar)
count of parameters
cSeparator
This optional character that is used to separate individual parameters on the CGI
commandline following the ?. By default this is a Tilde ('~')
cSpaceChar
Optional character used to replace spaces on the CGI parameter commandline. By default
this is a plus sign ('+').
Example
loCGI.aCGIParms("~","+")
lcName=loCGI.GetParameter(2)
Remarks
Only works with Positional parameters
See Also
wwCGI::GetCGIParameter
wwCGI::GetCommandLine
This method returns the full commandline that was used to call the wwCGI.dll/exe file. Again, this is more of a debugging or
information tool, more than a truly useful method.
Syntax
Return
oCGI.GetCommandLine()
The command line the Web Server used to call the CGI exe file.
wwCGI::GetPreviousUrl
This method returns the URL of the previous page that was used to call this CGI script.
- Page 36 -
West Wind Web Connection
Class wwCGI
Syntax
Return
Remarks
oCGI.GetPreviousURL()
The URL of the previously accessed page..
If you nest CGI requests this value returns invalid URL addresses - it’s not possible to
dynamically return to a previously generated CGI page other than using the browser’s
‘Back’ button. In these cases use a hardcoded URL instead
wwCGI::GetCurrentUrl
Returns the current link that's running.
Syntax
Arguments
oCGI.GetCurrentURL(lSecureLink)
lSecureLink
If specified returns HTTPS instead of HTTP for the protocol portion.
Return
The currently executing URL
wwCGI::GetServerAdmin
This method returns the name of the server Administrator as specified in the web server’s setup. Usually this is an e-mail
address.
Syntax
Return
oCGI.GetServerAdmin()
The server administrator’s email address.
wwCGI::GetServerName
This method returns the domain name of the server or the IP address if a domain name isn’t available.
Syntax
Return
oCGI.GetServerName()
The server name.
wwCGI::GetRemoteAddress
Returns the IP Address for the remote machine. This information is also logged in the CGILog file. You can use the
wwIPStuff::GetDomainFromIP method to resolve the IP address to a domain name.
Syntax
Return
See Also
oCGI.GetRemoteAddress()
The IP Address of the client connecting to the server. Only available if the browser makes
it available.
wwCGI::GetServerName
- Page 37 -
West Wind Web Connection
Class wwCGI
wwCGI::GetBrowser
This method returns the name of the Web Browser used to access the server.
Syntax
Return
See Also
oCGI.GetBrowser()
The name of the Web Browser (ie. Mozilla, Mosaic etc.)
wwCGI::IsHTML30
wwCGI::IsHTML30
This method returns .T. if the Browser in use supports HTML 3.0 tables. Use this method to check for table support. Note: This
method replaces the wwHTML::IsNetscape method which still works identically.
Syntax
Return
See Also
oCGI.IsHTML30()
.T. if the browser supports Netscape extensions and tables.
wwCGI::GetBrowser()
wwCGI::IsSecure
This method returns .T. if the Browser supports secure transactions. This method needs to be updated based on browser types
that support SSL or other secure format HTML forms.
Syntax
Remarks
Return
See Also
oCGI.IsSecure()
The functionality needs to be customized as new browser start supporting secure form
processing.
.T. if the browser supports secure transactions.
wwCGI::GetBrowser()
wwCGI::IsLinkSecure
This method returns .T. if the request was passed over an encrypted link port. By default this method checks the server port for
443, but you can specify an optional port as a parameter.
Syntax
Arguments
Remarks
Return
See Also
oCGI.IsLinkSecure(cPort)
cPort
Optional parameter that sets the port that is considered the secure port.
Default: 443
The functionality needs to be customized as new browser start supporting secure form
processing.
.T. if the browser supports secure transactions.
wwCGI::GetBrowser()
- Page 38 -
West Wind Web Connection
Class wwCGI
wwCGI::GetClientCertificate
Returns the contents of a client Certificate's Subject key. This information contains the info about the client. The following
information is provided:
ClientCert Flags=1
ClientCert Cookie=b0c24e793b9f11367c8ec916101b931e
ClientCert Subject=
L=Internet, O="VeriSign, Inc.", OU=VeriSign Class 1 CA - Individual Subscriber,
OU="www.verisign.com/repository/CPS Incorp. by Ref.,LIAB.LTD(c)96",
OU=Digital ID Class 1 - Microsoft Full Service,
CN=Rick Strahl, E=rstrahl@west-wind.com
You can retrieve the Flags and Cookie with the GetCGIVar() method. This method only retrieves information in the Subject
key.
Syntax
Arguments
Example
Remarks
oCGI.GetClientCertificate(cSubKey)
cSubKey
Retrieves the key from the subject line. A couple of special keys have been provided:
EMIAL, EMAIL retrieve those values. All other keys including the CN and E keys can be
retrieved by specifying the keyname.
oCGI.GetClientCertificate("CN")
&& Retrieve Common Name
This method only works when the PostMethod = URLEncoded in wc.ini and
POSTDATA=.T. in wconnect.h
wwCGI::GetCookie
Returns an HTTP Cookie that was previously set. HTTP cookies allow keeping state by keeping a persistent variable on the
user's browser. Cookies are sent along in each HTTP request and appear as a CGI variable in the Extra Headers section output.
Syntax
Arguments
Example
Remarks
oCGI.GetCookie(cCookieName)
cCookieNameCookies only work with Netscape, Internet Explorer and some of the newer
browser implementations. Older browsers in general do not support Cookies.
The value of the cookie or "" if not found
wwCGI::SetCookieString()
wwCGI::GetRequestMethod
This method returns the CGI method used to generate this request. “GET”, “POST” or “TRANSPARENT” are common
settings.
Syntax
Return
oCGI.GetRequestMethod()
The request method used to initiate CGI request.
wwCGI::GetRequestProtocol
This method returns the name of the protocol used by the Web Browser that initiated the CGI request.
- Page 39 -
West Wind Web Connection
Class wwCGI
Syntax
Return
oCGI.GetRequestProtocol()
Request Protocol (“HTTP/1.0” for example)
wwCGI::GetAuthenticatedUser
Returns the name of a user if he has been authenticated by the Web server. This variable gets set and stays set once a user has
entered a valid username into the browser dialog box when prompted. The username is valid for a given Web server path and
down and once set cannot be unset until the browser is shut down.
Syntax
Return
See Also
oCGI.GetAuthenticatedUser ()
The request method used to initiate CGI request.
wwHTTPHeader::Authenticate; wwHTML::HTMLAuthenticate
wwCGI::GetPhysicalPath
Returns the full path of the currently loaded page. Typically this will be the physical path to the wc.dll file. If you use IIS script
mapping to the physical path of the mapped page will be returned. For example: /wconnect/nocode.wc would return
C:\HTTP\WCONNECT\NOCODE.WC.
Note: the path is not translated for network purposes – a local drive is always returned. Your code needs to handle that if you're
running sessions across the network. You can use the ForcePath method to do this chore.
Syntax
Return
See Also
oCGI.GetPhysicalPath()
The physical path of the page requested. Typically the path will be to the wc.dll. The path
is not network corrected, but local to the Web server
wwCGI::GetLogicalPath
wwCGI::GetLogicalPath
Returns the Web server relative path of the currently loaded page. The path is returned relative to the Web server root with
forward slashes.
Syntax
Return
See Also
oCGI.GetLogicalPath()
The logical path of the current request, most likely the name of the wc.dll.
wwCGI::GetPhysicalPath
wwCGI::ForcePath
This utility method should be used on all CGI pathnames that are not retrieved with the specialized CGI methods. Forcepath
will strip a file’s current path and replace it with the path where the temporary CGI work files reside.
Syntax
Return
oCGI.ForcePath(cFilename)
Adjusted Filename that contains the translated path.
- Page 40 -
West Wind Web Connection
Class wwPostRequest
Class wwPostRequest
Parent Class: wwCGI
Source: wwPostRequest.prg
The wwPostRequest class is a specialized subclass of wwCGI to handle communication with URLEncoded string parameters
passed to the Web Connection server instead of the original INI file. This class is actually the default class in version 2.70 and
later. This class is invoked instead of wwCGI whenever the #DEFINE POSTDATA .T. is set in wconnect.h
The exposed interface of this class is identical to wwCGI.
wCGI::GetMultiPartFile
This methods allows retrieval of an uploaded file from an HTML page using multi-part forms. Multi-part forms and file uploads
are fairly efficient as they bypass the traditional URLEncoding that occurs with Form posts. The page link to start a file upload
looks like this:
<form ACTION="wc.dll?wwDemo~FileUpload" METHOD="POST" enctype="multipart/form-data">
<input TYPE="FILE" NAME="File"><br>
<input TYPE="submit" value="Upload File" name="btnSubmit"> </p>
</form>
To retrieve the file on the server you can use the following code:
lcFileName = ""
lcFileBuffer = Request.GetMultiPartFile("File",@lcFileName)
lcNotes = Request.GetMultipartFormVar("txtFileNotes")
lcFileName = SYS(2023)+"\"+lcFileName
*** Now dump the file to disk
File2Var(lcFileName,lcFileBuffer)
Note that lcFilename is passed by reference and filled by the call to GetMultiPartFile().
Note:
If you're uploading a file and also receive other form variables those form variables cannot be retrieved with
the Form() method as the format of the request is now a multipart form. In order to retrieve other form
variables you have to use GetMultipartFormVar().
Also note, that if you try to view the last request data from the server status window the data will look funky
as it is not URLEncoded as other text. To check out the request data with multi-part forms you can view the
raw request data.
Syntax
Return
Arguments
Request.GetMultiPartFile(cFormVar, @cFileName)
Value entered on the form or “”
cFormVar
Name of the Form variable for the File input field on the calling HTML form.
@cFileName
- Page 41 -
West Wind Web Connection
Class wwPostRequest
Passed by reference! This var receives the name of the file that was uploaded. The var
contains only the filename without a path.
Example
Remarks
See above
Multipart forms are fairly efficient as they bypass the traditional URLEncoding and
Decoding required by POST requests. Files are sent as is in binary form.
Please be aware that you may want to check for file sizes and disk space before accepting
files and saving them to disk. There's potential to do damage with this feature as people
can send you huge files that clog up memory or your disk. Use with caution!
See Also
wwCGI::GetMultiPartFormVar
wwCGI::GetMultiPartFormVar
When retrieving multi-part forms because a file upload is included with the form submission you have to use
GetMultiPartFormVar() in order to retrieve any additional form variables.
Syntax
Return
Arguments
Request.GetMultiPartFormVar (cFormVar)
Value entered on the form or “”
cFormVar
Name of the Form variable to retrieve
See Also
wwCGI::GetMultiPartFile
- Page 42 -
West Wind Web Connection
Class wwHTML
Class wwHTML
Parent Class: Relation
Source: wwHTML.prg
The wwHTML class provides the tools to easily create HTML pages in program code. While this class is purely optional, the
example code for Web Connection uses it exclusively to generate HTML output. Other methods of creating output are
available, like using the report generator or merging text from tables, but hand coded HTML pages usually provide the fastest
way to generate web output in real time. You can also combine use of these other methods with the text output options of this
class.
How it works
The HTML class encapsulates the file output routines required, so that you don’t have to worry about accessing low level file
functions for outputting your HTML text. All output can be sent either to a specified file or optionally be returned to you as a
result string without actually sending the output to file by setting the tlNoOutput parameter to .T. on each of the methods used.
The latter approach comes in handy to nest multiple HTML strings and formats into a single output command, or to use the
HTML class only as a partial solution when generating web documents.
wwHTML Class: Exposed Methods
wwHTML::Init
The wwHTML constructor is responsible for setting up the HTML class by setting up the filename that is used to send output
to.
Syntax
Return
Arguments
oHTML.Init(cOutFile)
Nothing
Coutfile
The filename that all output is sent to. The file is created and must be accessible.
You can also pass “NOFILE” which results in output not being sent to a file. This is
useful if you want to use the HTML class only partially to handle special HTML features,
but handle I/O with another method (say the report writer for example).
Example
oHTML=CREATE(“wwHTML”,loCGI.GetOutFile)
Remarks
See Also
wwHTML::Destroy, wwHTML::ContentTypeHeader
wwHTML::Destroy
The wwHTML destructor is responsible for closing the HTML output file of output is sent to a file.
- Page 43 -
West Wind Web Connection
Class wwHTML
Syntax
Return
oHTML.Destroy()
Nothing
Arguments
Example
Remarks
See Also
RELEASE oHTML
You will be unable to access the HTML file while the oHTML object is in scope, since
the output file will open.
wwHTML::Init
wwHTML::Write
Same as wwHTML::Send
wwHTML::Send
The Send method is used for all output that is sent to the HTML document in order to keep all file access localized to this one
method. Output is sent as is without a trailing carriage return.
The optional lNoOutput parameter is used to avoid sending output to the file, returning a string as a result of the method
instead. This tlNoOutput option is available for most other wwHTML class methods and passed through to the Send and
SendLn methods.
Syntax
Return
Arguments
oHTML.Send(cText,lNoOutput)
“” if sending to file and the output text if lNoOuput is .T.
cText
The text to be output. This text can be plain, or HTML formatted - this method doesn’t
care. It’s the low level output routine.
LNoOutput
When set to .T. output is not sent to file, instead returning the result as a string.
Example
Remarks
See Also
oHTML.Send(“<h1>Hello World Wide Web</h1>”)
Output is send as is, without trailing carriage return.
wwHTML::SendLn; wwHTML::SendMemoLn
wwHTML::SendLn
The SendLn method sends a carriage return terminated string to the HTML file. The syntax is identical to the Send method, but
operationally this method simply calls the Send method to carry out it’s output.
Syntax
Return
Arguments
oHTML.SendLn(cText,lNoOutput)
“” if sending to file and the output text if lNoOuput is .T.
cText
The text to be output. This text can be plain, or HTML formatted - this method doesn’t
care. It’s the low level output routine.
LNoOutput
When set to .T. output is not sent to file, instead returning the result as a string.
- Page 44 -
West Wind Web Connection
Class wwHTML
Example
Remarks
See Also
oHTML.SendLn(“<h1>Hello World Wide Web</h1>”)
Output gets an carriage return at the end.
wwHTML::Send; wwHTML::SendMemoLn
wwHTML::FastSend
The FastSend method is identical in operation to the Send method, but only outputs to the final datasource, missing the
lNoOutput option. This method provides the fastest possible output and should be used when dumping output in tight loops.
Syntax
Return
Arguments
Example
Remarks
See Also
oHTML.Send(cText)
""
cText
The text to be output. This text can be plain, or HTML formatted - this method doesn’t
care. It’s the low level output routine.
oHTML.FastSend(“<h1>Hello World Wide Web</h1>”)
Sends output directly to the output source. There is no error checking and the lNoOutput
option is not supported
wwHTML::SendLn; wwHTML::SendMemoLn
wwHTML::SendPar
This very simple method sends a hard paragraph break after the text specified if any. Same as SendLn(lcText+“<p>”) but easier
to type.
Syntax
Return
Arguments
oHTML.SendPar(cText, lNoOutput)
“” if sending to file and the output text if lNoOuput is .T.
cText
Optional text to output before sending <p>
lNoOutput
When set to .T. output is not sent to file, instead returning the result as a string.
See Also
wwHTML::SendLn
wwHTML::SendMemoLn
The SendMemoLn method formats mulit-line text output to look more like standard memo output you’d expect on a report.
HTML tends to crowd lines together and skip over carriage returns, which makes unformatted memo/multi-line text look
unprofessional. This method allows you to format the memo output by breaking up lines and indenting the text.
Syntax
oHTML.SendMemoLn(cText,lBreakLines,nColumns,;
nIndent,lNoOutput)
Return
“” if sending to file and the output text if lNoOuput is .T.
Arguments
cText
The text to be output. This text can be plain, or HTML formatted.
lBreakLines
When set to .T. lines are broken at carriage returns in the memo or when the width
specified with nColumns is exceeded.
- Page 45 -
West Wind Web Connection
Class wwHTML
nColumns
Column to break lines at.
nIndent
Number of columns to indent text with. Note this will only work if you are using a fixed
font (using the <PRE></PRE> tag).
lNoOutput
When set to .T. output is not sent to file, instead returning the result as a string.
Example
Remarks
See Also
oHTML.SendMemoLn(“<h1>Hello World Wide Web</h1>”)
Output gets an carriage return at the end. The indenting option only works appropriately
when using the <PRE> pre-formmatted text tag.
wwHTML::Send; wwHTML::SendLn
wwHTML::BreakMemo
A simpler and faster routine to break long text that needs to be displayed as standard font HTML output. All double breaks are
converted to <p> tags, all single breaks are converted to <BR> breaks. Lines are not broken as with the SendMemoLn method only natural breaks are converted.
Syntax
Return
Arguments
oHTML.BreakMemo(cText, lNoOutput)
“” if sending to file and the output text if lNoOuput is .T.
cText
The text to be output.
LNoOutput
When set to .T. output is not sent to file, instead returning the result as a string.
Example
Remarks
See Also
oHTML.BreakMemo(lcLongTextField)
This routine is much faster than SendMemoLn.
wwHTML::Send; wwHTML::SendLn; wwHTML.SendMemoLn
wwHTML::ShowCursor
This method allows easy display of an entire table, simply by having a table or cursor selected and calling this method. You can
optionally pass an array of headers as well as a title and the option to automatically sum all numeric fields.
Syntax
oHTML.ShowCursor(@aHeaders, cTitle, lSumNumbers, lNoOutput,;
cTableTags)
Return
“”
Arguments
aHeaders
An array that should contain as many text headers as they are columns in the table/cursor
to display. If this parameter is not passed the field names are used as column headers.
The header names may be followed by a colon followed by a number indicating the width
of the header to override the field width which is used by default.
Ctitle
Title text to display above the headers.
lSumNumbers
Flag that allows automatic summing of all numeric fields in the table to display. The total
is displayed at the bottom of the display below the appropriate numeric fields.
LNoOutput
When set to .T. output is not sent to file, instead returning the result as a string.
cTableTags
Allows adding additional table tags to the table display to control the appearance of the
HTML table. For example, you could pass "WIDTH=100% BORDER=5" to force the
- Page 46 -
West Wind Web Connection
Class wwHTML
table to be full size. The default value is "WIDTH=90%".
Example
SELECT company, lname ;
FROM TT_Cust ;
INTO CURSOR Tquery
DIMENSION laHeader[2]
laHeader[1]=”Company”
laHeader[2]=”Last Name”
oHTML.ShowCursor(@laHeaders,”Client List”)
Remarks
See Also
By default an HTML table is used for output unless output size exceeds
MAX_TABLE_CELLS (Wconnect.h) . To allow HTML tables you have to first call
SetAllowHTMLTables with .T.
wwHTML::SetAllowHTMLTables
wwHTML::ExpandTemplate
The ExpandTemplate method method is used to expand template pages that contain FoxPro expressions using Active Server
like syntax. The syntax allowed is simple and looks as follows:
<%=
<%=
<%=
<%=
<%=
Version() %>
Table.FieldName %>
MyUDF() %>
PrivateVar %>
Class.Property %>
or
<%
Code Block (any valid procedural FoxPro code)
%>
Expressions are expanded prior to sending the document back to the client, so expressions are valid anywhere inside of the
HTML document including in HTML field values and HREF links etc.
Note: Since embedded functions are dynamically evaluated through macro expansion you'll want to keep
the use of functions to a minimum for speed reasons. If you use excessive functions in your pages I would
highly recommend you build a custom Processing routine instead of building the code into an HTML page.
Custom code is much easier to debug and maintain and also runs a lot faster since no on the fly evaluation
takes place. As a compromise use UDF()s instead of inline functions.
Syntax
oHTML.ExpandTemplate(cPageName, vContentType, lTemplateString,;
lNoOutput)
Return
“” if sending to file and the output text if lNoOuput is .T.
Arguments
cPagename
The id of the page as entered into the pagename field of the wwHTML table.
vContentType
By default this parameter creates an HTML formatted document header. You can specify
any content type header, or “” to skip the content type header altogether. You may also
pass a previously set wwHTTPHeader object. See ContentTypeHeader() method for more
details for valid options.
lTemplateString
If this value is .T. the cPagename parameter contains the actual HTML template rather
than a filename.
lNoOutput
When set to .T. output is not sent to file, instead returning the result as a string.
- Page 47 -
West Wind Web Connection
Class wwHTML
Example
*** Output page in WWHTML.DBF
oHTML.ExpandTemplate(Request.GetPhysicalPath())
Remarks
All but the first parameter are optional.
Embedded expressions must evaluate to character using EVALUATE(). An internal error
handler catches invalid expressions and embeds and shows expressions un interpreted if
an error occurs.
See Also
wwHTML::ContentTypeHeader; wwHTML::CreateHTMLdbf
wwHTML::ExpandScript
The ExpandScript method method is used to expand script pages that contain FoxPro expressions using Active Server like
syntax. The syntax allowed is simple and looks as follows:
<%=
<%=
<%=
<%=
<%=
Version() %>
Table.FieldName %>
MyUDF() %>
PrivateVar %>
Class.Property %>
or
<%
Code Block (any valid procedural FoxPro code)
%>
Script pages differ from template in that they are complete Visual FoxPro programs that support structured statements inside the
HTML document. You can do things like the following:
<%
*** Demonstrate using WC objects
lcCompany = Request.QueryString("Company")
&& ASP Syntax
SELECT company,careof ;
FROM TT_CUST ;
WHERE UPPER(Company) = UPPER(lcCompany) ;
INTO Cursor TQuery
%>
<% SCAN %>
<HR>
Company: <%= Tquery.Company %>
Name: <%= Tquery.CareOf %>
<% ENDSCAN %>
Note the SCAN loop implemented at the script level. Web Connection implements scripts using TEXTMERGE and 'running'
the script as an actual program that contains TEXT/ENDTEXT and embedded textmerge expressions.
Expressions are expanded prior to sending the document back to the client, so expressions are valid anywhere inside of the
HTML document including in HTML field values and HREF links etc.
Note: Because scripts are essentially programs they can rather fast. Three scripting modes are
321-
Interpreted (using CodeBlock)
Compiled (running as a precompiled FXP file)
Inside of the VFP (recompiled on each hit in the IDE)
- Page 48 -
West Wind Web Connection
Class wwHTML
Option 2 and 1 are rather fast as they run as native code. Option 1 is much slower as each line of code is
interpreted by Randy Pearson's CodeBlock. However, because CodeBlock is fully interpreted it works
dynamically in either the development environment or runtime to allow making page changes without
recompilation.
Syntax
Return
Arguments
oHTML.ExpandScript(cPageName, nScriptMode,vContentType)
"" string always – output is sent directly to the Response stream
CPagename
The Page that is to be interpreted as script.
NScriptMode
The mode that the script runs in
3Interpreted (using CodeBlock)
2Compiled (running as a precompiled FXP file)
1Inside of the VFP (recompiled on each hit in the IDE)
Default: 1 (It's recommended you pass THIS.oCGIServer.nScriptMode which can be
configured in the startup INI file)
vContentType
By default this parameter creates an HTML formatted document header. You can specify
any content type header, or “” to skip the content type header altogether. You may also
pass a previously set wwHTTPHeader object. See ContentTypeHeader() method for more
details for valid options.
LTemplateString
If this value is .T. the cPagename parameter contains the actual HTML template rather
than a filename.
LNoOutput
When set to .T. output is not sent to file, instead returning the result as a string.
Example
*** Output page in WWHTML.DBF
oHTML.ExpandScript(Request.GetPhysicalPath())
Remarks
All but the first parameter are optional.
Embedded expressions must evaluate to character using EVALUATE(). Any error in the
script will cause an error message to be displayed attempting to show the context of the
error in several surrounding lines of code.
See Also
wwHTML::ContentTypeHeader
wwHTML::EnclosedText
This method encloses the specified text in a pair of HTML tags. For example, SendPar(“b”,”Hello World”) will generate
“<b>Hello World</b>”.
Syntax
Return
Arguments
oHTML.EnclosedText(cTag, cText, lNoOutput)
“” if sending to file and the output text if lNoOuput is .T.
CTag
HTML Tag name without the enclosing <>’s
CText
The text to enclose
LNoOutput
When set to .T. output is not sent to file, instead returning the result as a string.
Example
Remarks
oHTML.EnclosedText(“b”,”This is a bold Statement”)
No carriage return send at end of line. See wwHTML::HeaderText for sending headers
that are followed by CRs. You’ll commonly use this with the lNoOutput option to embed
- Page 49 -
West Wind Web Connection
Class wwHTML
enclosed text into another string.
See Also
wwHTML::HeaderText
wwHTML::HeaderText
This method encloses the specified text in a pair of HTML tags. For example, HeaderText(“H2”,”Hello World”) will generate
“<h2>Hello World</h2>”. The text is followed by a carriage return.
Syntax
Return
Arguments
oHTML.EnclosedText(cTag, cText, lNoOutput)
“” if sending to file and the output text if lNoOuput is .T.
CTag
HTML Tag name without the enclosing <>’s
CText
The text to enclose
LNoOutput
When set to .T. output is not sent to file, instead returning the result as a string.
Example
Remarks
See Also
oHTML.HeaderText(“h2”,”Hello World”)
A carriage return is send at end of line. See wwHTML::EnclosedText for sending in line
tags that aren’t followed by a carriage return.
wwHTML::EnclosedText
wwHTML::HRef
This method creates a hypertext link to another document, section or CGI command using the HTML HREF tag.
Syntax
Return
Arguments
oHTML.HRef(cLink, cText, lNoOutput)
“” if sending to file and the output text if lNoOuput is .T.
cLink
The hypertext link or address.
Ctext
The text to enclose
lNoOutput
When set to .T. output is not sent to file, instead returning the result as a string.
Example
oHTML.Href(“mailto:rstrahl@west-wind.com”,”Email Rick”)
or
oHTML.Href(“http://microsoft.com/index.htm”,”MS Home Page”)
or
oHTML.Href(“/cgi-win/wwcgi?ClientList”,”Show Clients”)
Remarks
See Also
No carriage return send at end of line. See wwHTML::HeaderText for sending headers
that are followed by CRs.
wwHTML::HeaderText
wwHTML::HTMLColor
This method outputs an HTML color string value from a Visual FoxPro RGB() color triplet.
Syntax
oHTML.HTMLColor(nColorValue, lNoOutput)
- Page 50 -
West Wind Web Connection
Class wwHTML
Return
Arguments
“” if sending to file and the color value output text if lNoOuput is .T. Color value is
preceeded by a #. For example, RGB(255,255,255) returns "#FFFFFF"
nColorValue
A Visual FoxPro color value. This value can come from a Visual Control color property
or an RGB() triplet.
LNoOutput
When set to .T. output is not sent to file, instead returning the result as a string.
Example
lcColor=oHTML.HTMLColor(RGB(192,192,192),.t.)
wwHTML::List
This method creates a HTML list of manually entered items. The list can be of any of the supported HTML list types. Currently
there is no support for not sending the output directly to a file.
Fix it/Wish List: Add support for arrays, allow lNoOutput option
Syntax
Return
Arguments
oHTML.List(cType, cItem1, cItem2…cItem9)
“”
cType
Any legal HTML list type:
UL - unordered list
OL - ordered list
DL - definition list.
cItem1..cItem9
Text to be displayed for each list item.
In the future the first item may be an array.
Example
oHTML.List(“UL”,”Option 1”,”Option 2”,;
oHTML.Href(“index.htm”,”Back to home page”,.T.))
Remarks
output cannot be returned as a string
See Also
wwHTML::DBFPopup
This method creates a HTML <SELECT></SELECT> form popup box populated by the currently open table. Form popups are
embedded inside of HTML forms and this routine generates only the popup list variable definition with the list populated from
an expression defined from the open table.
Not final: This implementation may change. (03/21/96)
Syntax
oHTML.DBFPopup(cFormVarName, cCharExpression, nSelected,;
nHeight, cFirstItem, lNoOutputList)
Return
Full <SELECT> </SELECT> string or nothing
Arguments
cFormVarName
The name of the popup field on the HTML form. The value chosen can be retrieved with
wwCGI::GetFormVar()
cCharExpression
The expression that is returned for each record in the open table/cursor. For example if
you have a customer list and you wanted to display the company field you would pass
"Tquery.Company" as the expression. The expression can be any valid FoxPro expression
that evaluates to a string.
- Page 51 -
West Wind Web Connection
Class wwHTML
cDefaultText
Text of an option that is highlighted when the form is first loaded .
nHeight
HTML lists can either be popups or lists. The height determines which is used. nHeight
determines the number of items that are visible in the list. Default is 1 or a Popup.
cFirstItem
Allows you to insert a list item at the top of the list. Useful for a blank entry or
instructions before a selection is made. To not force a first item pass a non-character value
or leave the parameter off.
lNoOutput
Determines whether output goes to file or is returned as a string.
Example
oHTML.DBFPopup("Company","Tquery.Company","",;
1,"Select Customer")
Remarks
Table referenced by cCharExpression must be open and selected. Performs a SCAN to
populate the list.
wwHTML::ContentTypeHeader
The ContentTypeHeader method sends an HTTP content type header which has to preceed any CGI processed request. A
typical Content Type header looks like this:
HTTP/1.0 200 OK
Content-type: text/html
<HTML>
...
</HTML>
In the above example the Content Type line plus a blank line is the actual text that makes up the Content type header.
Directly displayed text or HTML documents do not need a content type header, but any document that is sent via CGI to the
HTTP server must include a content type header.
This method is provided mainly for internal use by various full page methods. You programs should use HTMLHeader instead
which also calls this method to output the content type header.
Syntax
Return
Arguments
oHTML.ContentTypeHeader([oHTTPHeader | cContentType], lNoOutput)
“” if sending to file and the output text if lNoOuput is .T.
oHTTPHeader
or cContentType
You can pass either a text based header type or an HTTP header object that is
preconfigured.
oHTTPHeader
You can pass an HTTP header object that was previously created in your request routine.
The object is expected to hold a valid HTTP header as created by
oHTTP.DefaultHeader() or any of the additional methods.
loHeader=CREATE("wwHTTPHeader")
loHeader.DefaultHeader()
&& Create Default
loHeader.AddForceReload()
&& Force to not Cache page
*** Check if a Cookie exists for wwID
lcId=loCGI.GetCookie("wwId")
IF EMPTY(lcId)
lcId=Sys(3)
loHeader.AddCookie("wwId",lcId)
ENDIF
- Page 52 -
West Wind Web Connection
Class wwHTML
*** Now display the header on the page
loHTML.ContentTypeHeader(loHeader)
Note that if you simply create loHeader without calling any of the following methods no
HTTP header is created at all which works well for static HTML pages that aren't returned
to a Web Server.
cContentType
For backward compatibility you can also call this method with a text parameter
CGI requests require a Content Type header which usually looks like this in the generated
document:
Content Type: text/html
Common types are:
“text/html”
- Default
“Force Reload” - Force browser to always reload page
“text/plain”
- Displays plain text (non-HTML)
“none”
- No header is sent - your code has to set it up
This parameter basically creates a Content type line, so any Content Type that is legal can
be passed. The default is “text/html”. Another commonly used type is “text/plain” which
sends text without HTML formatting. Use “none” to skip creating the Content Type
header for example when creating static, non-CGI HTML pages for later display.
LNoOutput
When set to .T. output is not sent to file, instead returning the result as a string.
Example
Remarks
oHTML.ContentTypeHeader ()
Non-CGI pages should always set the cContentType parameter to “none”.
You can send a full HTTP1/0 header response using the Send/SendLn commands without
this method.
The Force Reload option should be used on any pages that need to be reloaded each time
the page is hit. For example an order form page should be always be recalculated even
when the user moves back to the page with the Browser’s Back button. Force Reload
immediately forces the cache to expire and causes any further access to reload the page
from the CGI script. By default pages do not expire, so that the user can get back to a CGI
page via the Back button or on some browsers (like MS IE) via a previously cached
HREF link. This works well for lookup lists and provides better speed on the browser’s
end…
Force Reload send a full HTTP header with a content type of text/html.
See Also
oHTML::HTMLHeader
wwHTML::HTMLHeader
The HTMLHeader method creates the beginning of a typical HTML document. By default this document includes a the content
type header required for CGI generated documents, a title (displayed in the browser’s title bar) and header text or a header tag
which can include images.
Syntax
oHTML.HTMLHeader(cHeaderText, cDocTitle,cBackground | cBGColor,;
oHTTPHeader | cContentType, lNoOutput)
Return
“” if sending to file and the output text if lNoOuput is .T.
Arguments
cHeaderText
- Page 53 -
West Wind Web Connection
Class wwHTML
This is typical header text displayed in the <h1> tag, followed by a <HR> line.
If you pass a preformatted string that contains tags (like an IMG SRC for example) the
header text is placed unformatted.
CDocTitle
This text is the document title that is displayed in the Browsers title bar. If not passed this
value is the same as the headertext.
CContentType
This optional parameter allows you to specify the MIME content type header for CGI
documents. By default this parameter is set to “text/html”, but it can also be set to
“text/plain” or “none”. “none” specifies that you don’t want a content type header, which
is appropriate for creating standalone, permanent HTML documents.
cBackground | cBGColor
Allows you to specify a background image to use as a backdrop on HTML pages. The
image is tiled across the page. Optionally you may specify a background color rather than
an image. To do so, specify the color using Hex RGB notation: #FFFF00 for example.
oHTTPHeader | cContentType
This optional parameter allows you to customize the HTTP header for a document. CGI
requests require an HTTP Content Type header which usually looks like this in the
generated document:
HTTP 1.0/200 Ok
Content Type: text/html
You can pass either a HTTPHeader object or use a text based command that will fill
a common default header.
oHTTPHeader
You can pass an HTTP header object that was previously created in your request routine.
The object is expected to hold a valid HTTP header as created by
oHTTP.DefaultHeader() or any of the additional methods.
loHeader=CREATE("wwHTTPHeader")
loHeader.DefaultHeader()
&& Create Default
loHeader.AddForceReload()
&& Force to not Cache page
*** Check if a Cookie exists for wwID
lcId=loCGI.GetCookie("wwId")
IF EMPTY(lcId)
lcId=Sys(3)
loHeader.AddCookie("wwId",lcId)
ENDIF
*** Now display the header on the page
loHTML.ContentTypeHeader(loHeader)
cContentType
For backwards compatibility or simplified requests you can pass a text parameter:
“text/html” - Default
“text/plain”
“Force Reload” - Force browser to always reload page from link.
“none”
This parameter basically creates a Content type line, so any Content Type that is legal can
be passed. The default is “text/html”. Another commonly used type is “text/plain” which
sends text without HTML formatting. Use “none” to skip creating the Content Type
header for example when creating static, non-CGI HTML pages for later display.
LNoOutput
When set to .T. output is not sent to file, instead returning the result as a string.
- Page 54 -
West Wind Web Connection
Class wwHTML
Example
Remarks
See Also
oHTML.HTMLHeader(“Welcome to West Wind Technologies”,;
“West Wind Technologies”,;
“/images/background.gif”)
Non-CGI pages should always set the cContentType parameter to “none”.
oHTML::HTMLFooter
wwHTML::HTMLFooter
The HTMLFooter method finishes up an HTML document by adding the </BODY></HTML> document tags to the document.
It also allows you to pass a text string that is inserted just prior to these tags. This function does nothing special other than
conveying balance for code when using HTMLHeader().
Syntax
Return
Arguments
oHTML.HTMLFooter(cFooterText,lNoOutput)
“” if sending to file and the output text if lNoOuput is .T.
cFooterText
Allows you to specify text to be used on the page footer
LNoOutput
When set to .T. output is not sent to file, instead returning the result as a string.
Example
oHTML.HTMLFooter()
Remarks
See Also
oHTML::Href
wwHTML::HTMLAuthenticate
This method sends an Authorization request to the Web server to figure out whether the user is allowed access. The
implementation of this mechanism depends on the Web server and operating system, but in most cases a request for
authentication will display a login box into which the user types a username and password. The username and password are
returned as "Authenticated User" and "Authenticated Password" in the CGI portion of the CGI profile. You can access this info
with loCGI.GetCGIVar("Authenticated User") and loCGI.GetCGIVar("Authenticated Password").
Note for MS Internet Information Server: Some Web servers, namely MS IIS, will not send the password! In order for IIS to
send even the user name you need to set the Basic Authentication flag on the Web server property sheet. IIS also verifies all
users through the NT security settings so each entry into the Auth box must first be validated through NT, before the value is
passed back to you in the CGI object. Once authenticated only the user name is sent.
Syntax
Return
Arguments
oHTML.HTMLAuthenticate (cDomain, lNoOutput)
“” if sending to file and an HTTP - 401 header.
cDomain
The 'realm' that this authentication is to be checked for. This can be an entire domain or a
domain subdirectory or other server resource.
LNoOutput
When set to .T. output is not sent to file, instead returning the result as a string.
Example
FUNCTION AuthTest
*** Easier reference
loCGI=THIS.oCGI
*** Try to retrieve the cookie...
lcUserName=loCGI.GetCGIVar("Authenticated Username")
lcUserId=loCGI.GetCGIVar("Authenticated Password")
- Page 55 -
West Wind Web Connection
Class wwHTML
IF EMPTY(lcUserName)
*** Send Password Dialog
THIS.oHTML.HTMLAuthenticate(loCGI.GetServername())
RETURN
ENDIF
THIS.ErrorMsg("You've been validated for this request...")
RETURN
Remarks
Implementation varies from Web server to Web server. IIS does not return the password
ever.
See Also
wwHTML::HTMLHeader; wwHTML.ContentTypeHeader;
wwHTTPHeader::Authenticate
wwHTML::HTMLRedirect
The HTMLRedirect method redirects output to another hyperlink rather than generating and displaying a page. This method
simply points at another URL or directive and executes that link.
Syntax
Return
Arguments
oHTML.HTMLRedirect(cLink, lNoOutput)
“” if sending to file and the output text if lNoOuput is .T.
cLink
The hotlink or URL to goto or execute.
LNoOutput
When set to .T. output is not sent to file, instead returning the result as a string.
Example
Remarks
See Also
oHTML.HTMLRedirect(“index.htm”)
This method is useful when you need a program to decide which page should be
displayed. This provides another option for quickly accessing a page under program
control.
oHTML::HTMLHeader
wwHTML::HTMLError
The HTMLError method allows you to quickly generate a customized HTML error document. This method should be called
anytime your VFP code fails (possibly as part of an error handler) or when unhandled conditions occur. When the HTMLError
method is called all existing HTML output is overwritten with a standard error message that includes a pair of messages that
can be supplied as parameter. In addition you can specify the name of the system administrator and the referring document.
Syntax
oHTML.HTMLError(cErrorHeader, cErrorMessage,
cAdministrator, cReferDoc)
Return
Nothing
Arguments
cErrorHeader
This is the main header message displayed of the error document. Should be a general
explanation in a few short words - uses <h1> tag, ie. big and bold.
CErrorMessage
This should be a more detailed description of the error that occurred. This text appears in
bold using the <h3> tag after a general error message. Optional.
Cadministrator
This should contain an email address that is used as a hotlink in the document to be sent
messages regarding the problem from users of the page. Usually this will be
loCGI.GetServerAdmin(). Optional.
Creferdoc
The referring document that called the current CGI request. Again this should be passed
from the CGI object with loCGI.GetPreviousUrl. Optional.
- Page 56 -
West Wind Web Connection
Class wwHTML
Example
oHTML.HTMLError(“Hold on to your hats!”,;
“The requested CGI request could not be ”+;
“completed, because the program is not “+;
“set up to handle this operation yet.”,;
loCGI.GetServerAdmin(),;
loCGI.GetPreviousUrl())
Remarks
See Also
wwHTML::FormTextBox
Creates a textbox on a form.
Syntax
oHTML.FormTextBox(cFieldName, cValue, nWidth, nMaxWidth, ;
cCustomTags, lNoOutput)
Return
“” if sending to file or the output text if lNoOuput is .T.
Arguments
cFieldName
The NAME= tag for the text field. For example, "txtEntry"
cValue
The default value to display in the text field.
nWidth
Width of the text field.
nMaxWidth
Maxium characters to allow.
cCustomTags
Any custom tags for the INPUT tag.
LnoOutput
When set to .T. output is not sent to file, instead returning the result as a string.
Example
oHTML.FormTextBox ("txtCompany",lcCompany,20)
wwHTML::FormTextArea
Syntax
oHTML.FormTextArea(cFieldName, cValue, nHeight, nWidth,;
cCustomTags, lNoOutput)
Return
“” if sending to file or the output text if lNoOuput is .T.
Arguments
cFieldName
The NAME= tag for the text field. For example, "txtEntry"
cValue
The default value to display in the text field.
nHeight
Number of rows for this text area.
nWidth
Display width of the text area.
cCustomTags
Any custom tags for the INPUT tag.
LnoOutput
When set to .T. output is not sent to file, instead returning the result as a string.
Example
oHTML.FormTextArea("txtNotes",lcNotes,10,80)
- Page 57 -
West Wind Web Connection
Class wwHTML
wwHTML::FormButton
Syntax
oHTML.FormButton(cFieldName, cCaption, ;
cCustomTags, lNoOutput)
Return
“” if sending to file or the output text if lNoOuput is .T.
Arguments
cFieldName
The NAME= tag for the button.
cCaption
The display text of the button.
cCustomTags
Any custom tags for the INPUT tag.
LnoOutput
When set to .T. output is not sent to file, instead returning the result as a string.
Example
oHTML.FormButton ("btnSubmit","Send us your Order")
wwHTML::FormRadio
Creates an individual radio button.
Syntax
oHTML.FormRadio(cFieldName, cValue, cText, lSelected,;
cCustomTags, lNoOutput)
Return
“” if sending to file or the output text if lNoOuput is .T.
Arguments
cFieldName
The NAME= tag for the text field. For example, "txtEntry"
cValue
The default value to display in the text field.
cText
The text to display on the right of the button.
lSelected
Determines whether the button is CHECKED. Note: Only one button can be checked.
cCustomTags
Any custom tags for the INPUT tag.
LnoOutput
When set to .T. output is not sent to file, instead returning the result as a string.
Example
oHTML.FormRadio("optColors","Red","Red Color",.T.)
wwHTML::FormCheckbox
Creates an individual radio button.
Syntax
oHTML.FormBox(cFieldName, lValue, cText,;
cCustomTags, lNoOutput)
Return
“” if sending to file or the output text if lNoOuput is .T.
Arguments
cFieldName
The NAME= tag for the text field. For example, "txtEntry"
lValue
.T. or false to determine whether the form is checked.
cText
The text to display on the right of the button.
cCustomTags
Any custom tags for the INPUT tag.
lNoOutput
When set to .T. output is not sent to file, instead returning the result as a string.
Example
oHTML.FormCheckBox ("optColors",.T.,"Download Orders",,.T.)
- Page 58 -
West Wind Web Connection
Class wwHTML
wwHTML::NoOutput
This method is used to keep output from going to file no matter how you call any of the above CGI routines. Useful after errors
to turn off file further file output that might be created by incomplete HTML processing code. Only affects output through
wwHTML of course.
Syntax
Return
Arguments
Example
Remarks
See Also
oHTML.NoOutput(lNoOutput)
"" if sending to file and the output text if lNoOuput is .T.
lNoOutput
If .T. output will not be sent to file.
oHTML.NoOutput(.T.)
Note that this is different than using the lNoOutput option on the various HTML
functions, since it does not affect how text is returned to you from the HTML functions. If
you want text returned as text instead of having it sent to file you still need to specify the
lNoOutput parameter on the individual HTML method calls.
lNoOutput parameter
wwHTML::SetHTTPHeaderClass
Sets the class that is used internally for setting up HTTP headers. Use this method only if you plan to subclass the
wwHTTPHeader class.
Syntax
Return
Arguments
oHTML.SetHTTPHeaderClass(cClassname)
Nothing
cClass
Name of the class to create for headers.
wwHTML::AutoRefresh
This method creates allows refreshing a page at certain intervals either with the same page or another page. However, this
method only works if you build the HTML header of the page manually as demonstrated in the example below.
Syntax
Return
Arguments
oHTML.AutoRefreshPage(cURL,nInterval,lNoOutput)
"" or the generated text string if lNoOutput is set to .T.
cURL
The URL to refresh the page with. If this value is a null string ("") the current page is
refreshed.
nInterval
The interval at which the page is refreshed in seconds.
LnoOutput
Remarks
If .T. output will not be sent to file.
This method only works if you manually build the header of a form. The <META> tag
resides in the top of the HTML document so you can't use HTMLHeader. You can
however embed a call to this method into template pages!
Example
*** Login Page
loHTML.ContentTypeHeader()
loHTML.Sendln("<HTML><HEAD><TITLE>Authenticated</TITLE>")
loHTML.AutoRefreshPage(loCGI.GetPreviousURL(),.01)
loHTML.SendLn("</HEAD>")
- Page 59 -
West Wind Web Connection
Class wwHTML
loHTML.SendLn([<BODY BGCOLOR="#FFFFFF">])
loHTML.SendLn("<h2>You're now logged in for " + lcAdmin_type + "
access</h2><HR>")
loHTML.SendLn([<CENTER><b>])
loHTML.HREF(loCGI.GetPreviousURL(),"Click here to return
continue")
loHTML.SendLn([</b></CENTER>])
loHTML.HTMLFOOTER(PAGEFOOT)
See Also
wwHTML::IEChart
This method allows embedding of the IE Chart ActiveX Control into your pages driven by data from the currently active cursor
when the method is called. The data in the cursor to graph must contain at least two fields in the following format:
Field
Type
Function
Field1
Character
Field 2-n
Numeric
The label that is to be displayed with the data item. In a bar chart this means the column labels
on a Pie chart it means the labels on the pie attached to each piece.
The data item to graph.
Syntax
Return
Arguments
oHTML.IEChart(cChartType,vWidth,cHeight,lNoOutput)
"" or the generated text string if lNoOutput is set to .T.
cChartType
Determines the type of chart that is displayed. Available chart types are:
BAR
LINE
AREA
PIE
The default graph type if not passed is BAR.
You may also pass a numeric string that corresponds to the IEChart object graph type
explicitly. You can get the available types from the IEChart object documentation from
MS’s ActiveX Gallery site.
nColumns
Determines the number of columns that are graphed. By default only one column is
graphed, but you make specify more than one for various graphs that support multiple
datasets such as the stacked bar chart.
VWidth
Determines the width of the chart. You may pass a numeric value that contains a fixed
pixel width or character string that specifies a percentage. The default is "100%".
Nheight
Determines the display height of the chart object in the HTML document in pixels.
Default is 250.
Clabels
You can specify space separated list of labels for the legend. If not specified no legend is
displayed on the graph. If specified the number of space separated labels should match the
number of colums specified in the nColums parameter.
LnoOutput
If .T. output will not be sent to file.
Example
SELECT hour(time) as HOUR, COUNT(time) AS Hits, DAY(TIME) AS DAY;
FROM cgilog ;
WHERE time > datetime() - 82800 ;
- Page 60 -
West Wind Web Connection
Class wwHTML
GROUP BY 1 ;
INTO Cursor Tquery
loHTML=CREATE("wwHTML","Chart.htm")
loHTML.HTMLHeader("IE Chart Test")
loHTML.IEGraph("AREA",1,"100%",250)
Remarks
Output generates an <OBJECT> tag which works only with ActiveX enabled browsers
like MS Internet Explorer 3.0.
See Also
- Page 61 -
West Wind Web Connection
Class wwHTMLString
Class wwHTMLString
Parent Class: wwHTML
This subclass of the HTML class builds an output string rather than outputting the result HTML document to a file. The string
is concatenated and internally stored in the class. All methods from the wwHTML class apply.
Web Connection provides automatic and transparent overflow buffering to disk. You can use the SetBufferSize method to
specify a buffer size above which Web Connection starts dumping to file. By default this value is set to a large number to
essentially disable disk buffering, but a good number is typically 10-15k at which point disk buffering becomes more efficient
than concatenating memory variables in physical memory.
Note: Crazy as it may sound, file based output is as much as 5-25 times faster than using strings to build your
HTML output. The larger the output string and the more string concats occur per request the more significant the
performance difference.
The reason for this is VFP's string handling mechanism which forces strings to be concatenated only by copying the
content of the previous string then appending the new value (ie lcString=lcString+lcNewText). Since the entire string
is copied each time this process can get very slow especially if strings get over 20k in size.
File processing on the other hand simply dumps output to disk. Since disk access is typically buffered in memory this
is vastly more efficient than string concats for anything over 20k strings. wwHTMLString automatically implements
dumping to disk via the #DEFINE MAX_STRINGSIZE which is defined as 5000 by default. Any string used with
HTMLString over this byte code goes to disk and is retrieved when GetOutput() is called.
wwHTML::Init
The wwHTML constructor is responsible for setting up the HTML class by setting up the filename that is used to send output
to.
Syntax
Return
oHTML.Init()
Nothing
Arguments
Example
Remarks
See Also
oHTML=CREATE(“wwHTML”)
Unlike the wwHTML file based class, the Init method does not accept a parameter.
wwHTML::Destroy, wwHTML::ContentTypeHeader
wwHTMLString::Send
The Send method is overridden for the HTML string concatenate all output to a string instead of sending output to file. If
SetBufferSize was called to specify a string buffer size, output goes to a temporary file once the buffer exceeds the specified
buffer size.
- Page 62 -
West Wind Web Connection
Class wwHTMLString
Syntax
Return
Arguments
oHTML.Send(cText,lNoOutput)
“” if sending to file and the output text if lNoOuput is .T.
cText
The text to be output. This text can be plain, or HTML formatted - this method doesn’t
care. It’s the low level output routine.
LNoOutput
When set to .T. output is not sent to the output string, instead returning the result as a
string return value.
Example
Remarks
oHTML.Send(“<h1>Hello World Wide Web</h1>”)
Output is send as is, without trailing carriage return.
Note that Send is used for all output operations by the HTMLString class.
See Also
wwHTML::GetOutput
Returns the current HTML output that has been built with the HTML class.
Syntax
oHTML.GetOutput()
Return
HTML output
Arguments
None
Example
oHTML=CREATE(“wwHTMLString”,loCGI.GetOutFile)
oHTML.ShowMemoPage(HTMLPAGEPATH+"NoCode.wc",.T.)
oHTML.HTMLFoot(PAGEFOOT)
lcText=oHTML.GetOutput
wwHTML::SetBufferSize
Setting this value determines when the HTML class decides to dump output to file instead of using a string. When output gets
larger than this value a new HTML file object is created and any existing output gets dumped to it. Any subsequent output also
goes to file.
wwHTMLString transparently handles output between string based and file based output.
Syntax
Return
Arguments
oHTML.SetBufferSize(nBufferSize)
nothing
nBufferSize
Specify the size of the string buffer in bytes. By default this value is set to 2 megs, so
typically disk buffering won't kick in. To enable you should experiment with values
between 10-20k bytes.
Example
loHTML.SetBufferSize(15000)
- Page 63 -
West Wind Web Connection
Class wwShowCursor
Class wwShowCursor
Parent Class: Relation
Source: ShowCursor.prg
The wwShowCursor class allows for easy display of table based data in HTML form. Its main functionality is to show a FoxPro
table as HTML table output for a list display using a single method call. There are also methods for displaying a single record
either as ASCII output (handy for email messages) or as an HTML table for display on an HTML page.
How it works
The wwShowCursor class builds output on the fly from the currently selected Visual FoxPro workarea. The class takes an
HTML object as an input parameter to the Constructor (init()) so you can send output to the selected HTML output source in an
optimized fashion. If no wwHTML object is passed an wwHTMLString object is created internally and the output is returned
via this self-created object.
wwShowCursor can display an entire table as row based list either using an HTML table or <PRE> tag list using the
ShowCursor() method.
loHTML=THIS.oHTML
loHTML.HTMLHeader("ShowCursor Test")
loShowCursor=CREATE("wwShowCursor",loHTML)
SELECT Company, CareOf as Full_Name ;
FROM TT_CUST ;
INTO CURSOR Tquery
loShowCursor.ShowCursor()
loHTML.HTMLFooter()
In addition there's support for building paged displays showing n of x pages per page by setting the appropriate nPage_
properties of the class. wwShowCursor can also display a single record either as an HTML table using the ShowRecord()
method or as plain ASCII using using ShowASCIIRecord.
To use the record functions you might do:
loShowCursor=CREATE("wwShowCursor")
SELE TT_CUST
LOCATE FOR CustNo = lcCustId
loShowCursor.ShowRecord()
lcOutput=loShowCursor.GetOutput()
Note that here no HTML object is passed. In this case an HTML object is created internally and the output can be returned with
the GetOutput() method. You can SET FIELDS TO to limit fields to display or use a SELECT statement to select a single
record with the appropriate fields.
Field headers are displayed from the plain field names, except for ShowRecord/ShowASCIIRecord which use the DBC captions
if available. In most cases tables used here are result sets from queries, so naming your fields with descriptive names using the
AS clause is a good idea. When fields are displayed any underscores ("_") are converted to spaces in the field display.
- Page 64 -
West Wind Web Connection
Class wwShowCursor
Paged ShowCursor Display
The ShowCursor() method supports paged display via the cPage_ properties. By default these properties are disabled and paged
display is off. Paged display allows viewing the results of a query in small pages rather than a whole result set. This is useful for
large result sets that would take a long time to generate all at once.
It's important to understand that this process is not fully automatic – some programming logic on the calling program code is
required to implement paging. The idea is that you tell wwShowCursor how many items to display and which page to show.
wwShowCursor will then take your result set and filter it accordingly and display only that data. In addition, it then tells you
what the next and previous page numbers are so you can use them on the same request. Optionally, you can set up a base URL
that will allow ShowCursor to display the Next and Previous buttons automatically the link of which point at the base URL plus
an added page parameter (~10 for example for page 10).
Paged display requires keeping track of the user who created the query and potentially the query conditions that created the
cursor. You can use your own mechanism or use the wwSession object to assign the user some state information (see
wwSession for more details on creating sessions).
The following example uses a wwSession object:
************************************************************************
* wwDemo :: PagedCustomerList
*********************************
*** Function: Demonstrates use of the wwSession object, Cookies the
***
wwShowCursor's Paging mode to display a query in paged
***
format. The code below stores the Filter of the query
***
in a Session variable which is retrieved on each page
***
hit to re-run the query and jump to the appropriate
***
page.
************************************************************************
FUNCTION PagedCustomerList
LOCAL lcCookie, loSession, loHeader, loHTML, loCGI
loCGI=THIS.oCGI
loHTML=THIS.oHTML
*** Ideally this object should be:
*** THIS.oCGIServer.AddObject("oSession","wwSession")
*** in wwServer :: SetServerProperties
loSession=CREATE("wwSession")
loSession.nSessionTimeout=1800
&& Seconds - 1/2 hour
*** Retrieve the Cookie
lcCookie=loCGI.GetCookie("WWDEMOID")
*** We'll need to create a custom HTTP header so we can potentially
*** add the Cookie to it
loHeader=CREATE("wwHTTPHeader")
loHeader.DefaultHeader()
*** Check if we have a valid Session
IF !loSession.IsValidSession(lcCookie)
*** Nope create it
lcCookie=loSession.NewSession()
*** And add a Cookie to the Request Header
loHeader.AddCookie("WWDEMOID",lcCookie)
ENDIF
*** Now try retrieving the Query Parameters
*** Values on relevant if we're running from the form on the 'first hit'
lcCompany=loCGI.GetFormVar("txtCompany")
lcName=loCGI.GetFormVar("txtName")
- Page 65 -
West Wind Web Connection
Class wwShowCursor
*** Retrieve the page number - wc.dll?wwDemo~PagedCustomerList~PageNo
lnCurrentPage=VAL(loCGI.GetCGIParameter(3))
IF lnCurrentPage=0
lnCurrentPage=1
ENDIF
*** Check if we clicked the button of the form
IF !EMPTY(loCGI.GetFormVar("btnSubmit"))
*** Build a filter
lcFilter=""
IF !EMPTY(lcCompany)
lcFilter="UPPER(Company) = '" + UPPER(lcCompany) + "' AND "
ENDIF
IF !EMPTY(lcName)
lcFilter=lcFilter + "UPPER(Careof) = '" + UPPER(lcName) + "'
ENDIF
AND "
IF !EMPTY(lcFilter)
lcFilter = lcFilter + "!DELETED()"
ENDIF
*** Store the filter in the Session Object
loSession.SetSessionVar("CustomerQueryFilter",lcFilter)
ELSE
*** No - paging through file
*** Retrieve the filter from the Session Variable
lcFilter=loSession.GetSessionVar("CustomerQueryFilter")
ENDIF
IF !EMPTY(lcFilter)
lcFilter= "WHERE " + lcFilter
ENDIF
SELECT Company, CareOf, Phone ;
FROM TT_CUST ;
&lcFilter ;
ORDER BY Company ;
INTO CURSOR TQuery
*** Create the HTML header for the page
*** Note the custom HTTP header object containing the Cookie (loHeader)
loHTML.HTMLHeader("Paged Customer List",,BACKIMG,loHeader)
*** Create a ShowCursor Object and pass our HTML object
loSC=CREATE("wwShowCursor",loHTML)
*** Set the Paging parameters - 5 per page
loSC.nPage_ItemsPerPage=5
loSC.nPage_ShowPage=lnCurrentPage && Which page?
*** The URL to use for the Next/Prev buttons - This page
loSC.cPage_PageURL="wc.dll?wwDemo~PagedCustomerList"
*** Now dump the HTML
loSC.ShowCursor()
loHTML.HTMLFooter(PAGEFOOT)
ENDFUNC
* PagedCustomerList
A single Web Connection request handler handles this display by running a query, then re-calling this request for each of the
Next/Previous links from the resulting HTML display. Note the use of the wwSession object to save the filter condition
(lcFilter) between requests. The Session is established at the top and saved with the use of an HTTP Cookie
(loHTTP.AddCookie()) that is passed to the client. On repeat hits, the cookie is found and the filter is retrieved based on that
- Page 66 -
West Wind Web Connection
Class wwShowCursor
cookie from the wwSession object. The query is re-run and passed to loSC.ShowCursor() which in turn filters the result based
on the pages set on wwShowCursor object.
Exposed Properties
Property
Function
Display Attributes:
cTableBGColor
cHeaderBGColor
cTableWidth
cExtraTableTags
cTableBorder
cCellPadding
cCellSpacing
lCenterTable
lSumNumerics
lShowAsTable
nForceToPREList
oHTML
Background Color for the table. "#EEEEEE"
Background Color for the table header and Summary Total
Footer. "#FFFFCC"
The width of the HTML table. Can be specified in percentages
or pixel values. If using percent add % to the end of the string.
"95%"
Extra tags that are added to the <TABLE> tag of the HTML
table. Note that the width and border attributes are always
preset.
Numeric value specified as a string to specify the width of the
border. "2"
The amount of padding applied to each cell. "3"
The spacing between cells in addition to the border. "2"
Whether the table is centered.
If .T. all numeric fields will be totalled and displayed in the
table footer.
Determines whether the result is displayed as an HTML table
or as <PRE> list. .T.
Number of cells after which to default to <PRE> tagged list
The HTML object that is used to send output to. You can
directly access this object if necessary.
Paging Attributes:
nPage_ItemsPerPage
nPage_ShowPage
nPage_NextPage
nPage_PrevPage
cPage_PageURL
cPage_LinkHTML
Determines the number of items per page to display. Only
applies if this value is non-zero. 0
The page that is actually displayed. 0
The next page or 0 if the current page is the last. 0
The previous page or 0 if the current page is 1. 0
The base URL used for the Next and Previous Links. For
example: wc.dll?wwDemo~PagedList.
The full HTML for the Previous/Next links as a string.
Exposed Methods
wwShowCursor::Init
The Constructor of this class handles basic setup for the display operation. It takes a single parameter of a wwHTML object
which can be passed to allow sending output directly to that object's output mechanism for optimized speed.
Syntax
Return
Arguments
oShowCursor=CREATE("wwShowCursor",oHTML)
nothing
oHTML
A reference to an existing wwHTML object. This parameter is optional – if no HTML
- Page 67 -
West Wind Web Connection
Class wwShowCursor
Example
oShowCursor=CREATE("wwShowCursor",oHTML)
Remarks
See Also
wwHTML::ShowCursor
wwShowCursor::GetOutput
If you want to return the output from the ShowCursor method use this method to return the text. Note: This method applies only
if you did not pass an HTML object in the Constructor.
Syntax
oShowCursor.GetOutput()
Return
HTML output
Arguments
None
Example
SELECT * FROM TT_CUST INTO CURSOR Tquery
oShowCursor=CREATE("wwShowCursor")
oShowCursor.ShowCursor()
lcText=oShowCursor.GetOutput()
Remarks
This method applies only if you did not pass in an existing HTML object. If you passed in
a wwHTML object GetOutput() will always return a "" string. If a wwHTMLString object
was passed in, its entire contents including any prior content will be returned.
Thus only use this method to return the output if no object was passed in.
wwShowCursor::ShowCursor
This method actually goes out and displays the currently selected workarea as an HTML table. It uses the property settings that
have been set previously or uses the defaults defined there.
Syntax
Return
Example
oShowCursor.ShowCursor()
nothing
oShowCursor=CREATE("wwShowCursor",oHTML)
oShowCursor.cTableBGColor="#FFFFFF"
oShowCursor.ShowCursor()
Remarks
See Also
wwHTML::ShowCursor
wwShowCursor::ShowRecord
This method displays a record as an as a simple two column text view displaying the field name or caption on the left and the
field value on the right.
Syntax
Return
Example
oShowCursor.ShowRecord
nothing
oShowCursor=CREATE("wwShowCursor",oHTML)
SELE Tquery
LOCATE FOR CustId=lcCustId
- Page 68 -
West Wind Web Connection
Class wwShowCursor
IF FOUND()
oShowCursor.ShowRecord ()
ENDIF
lcEmailText=oShowCursor.GetOutput()
wwShowCursor::ShowASCIIRecord
This method displays a record as an ASCII list as a simple two column text view. This can be handy for emailing results of
some data entry to a user with a single method call. This method uses the field names from the data dictionary if a DBC is open
for the current table.
Syntax
Return
Example
oShowCursor.ShowASCIIRecord
nothing
oShowCursor=CREATE("wwShowCursor",oHTML)
SELE Tquery
LOCATE FOR CustId=lcCustId
IF FOUND()
oShowCursor.ShowASCIIRecord ()
ENDIF
lcEmailText=oShowCursor.GetOutput()
wwShowCursor::BuildFieldListHeader
This method allows customizing the header for the ShowCursor() method. You can create custom field header strings in an
array and pass this array to this method.
Syntax
Return
Arguments
Example
oShowCursor.BuildFieldListHeader(aHeader)
nothing
aHeader
You can pass an array of headers to this method. The headers are then used instead of the
field names. The array must be passed by Reference!
If you don't call this method explicitly wwShowCursor calls it internally and uses the field
names for headers.
DIMENSION laHeaders[3]
laHeaders[1]="Field 1"
laHeaders[1]="Field 2"
laHeaders[1]="Field 3"
oShowCursor.BuildFieldListHeader(@laHeaders)
Remarks
See Also
This method is also called internally by ShowCursor. Once the header is filled it won't fill
again. To clear the header
wwHTML::ShowCursor
wwShowCursor::SetCursor
This method allows setting the table that is used with the action methods of this class.
Syntax
oShowCursor.SetCursor(cTable)
- Page 69 -
West Wind Web Connection
Class wwShowCursor
Return
Arguments
Example
Remarks
See Also
nothing
cTable
Table/View or Alias name that is to be operated on by ShowCursor() or the other action
methods.
field names for headers.
oShowCursor.SetCursor(DATAPATH + "TT_Cust")
oShowCursor.ShowCursor()
This method is only required if you want to use a cursor other than the one currently open
in the current work area. Typically, you'll run a SELECT and then use the result set in
which case this method is not required.
wwHTML::ShowCursor
- Page 70 -
West Wind Web Connection
Class wwDBFPopup
Class wwDBFPopup
Parent Class: Relation
Source: DBFPopup
The wwDBFPopup class allows for easy creation of data driven HTML popup form elements from a FoxPro table.
How it works
The wwDBFCursor class essentially takes an HTML object and then builds output on the fly from the currently selected Visual
FoxPro workarea. The class takes an HTML object as an input parameter to the Constructor (init()) so you can send output to
the selected output source in an optimized fashion. If no wwHTML object is passed an wwHTMLString object is created
internally and the output is returned via this self-created object.
Here's an example on how you can use this object to display a state popup from a table:
loHTML=THIS.oHTML
&& called
in standard wwProcess Method
*** Create a popup object and send output to the current HTML object
loPopup=CREATE("wwDBFPOPUP",loHTML)
SELECT cData AS StateName, cData1 AS StateCode ;
FROM sub_lookups ;
WHERE TYPE="STATE" ;
INTO CURSOR TList
loPopup.cKeyValueExpression="TList.StateCode"
loPopup.cDisplayExpression="TList.StateName"
loPopup.cFormVarName="co_state_ID"
loPopup.cAddFirstItem="&ltSelect for US or Canada&gt"
loPopup.cSelectedValue=Subscribers.Co_state_Id
*** Build the Popup – output goes to HTML object
loPopup.BuildList()
*** If you don't pass HTML object a wwHTMLString object is created
*** behind the scenes. To retrieve the value you'd use:
* lcStatePopup=loPopup.GetOutput()
Exposed Properties
The following properties can be set after an instance of the wwDBFPopup object has been created. STRING_NULL is defined
as "*#*" to differentiate between empty strings and unselected items.
oHTML=.NULL.
cFormVarName=""
cDisplayExpression=""
cKeyValueExpression=""
cAddFirstItem=""
cSelectedValue=STRING_NULL
cSelectedDisplayValue=STRING_NULL
lMultiSelect=.F.
- Page 71 -
West Wind Web Connection
Class wwDBFPopup
nHeight=1
Exposed Methods
wwDBFPopup::Init
The Constructor of this class handles basic setup for the display operation. It takes a single parameter of a wwHTML object
which can be passed to allow sending output directly to that object's output mechanism for optimized speed.
Syntax
Return
Arguments
Example
Remarks
See Also
oPopup=CREATE("wwDBFPopup",oHTML)
nothing
oHTML
A reference to an existing wwHTML object. This parameter is optional – if no HTML
object is provided a wwHTMLString object is created behind the scenes. Use the
wwDBFPopup::GetOutput() method to retrieve the generated text in that case.
oDBFPopup=CREATE("wwDBFPopup",oHTML)
The wwHTML::DBFPopup method uses this object
wwHTML::DBFPopup; wwDBFPopup::GetOutput()
wwDBFPopup::GetOutput
If you want to return the output from the DBFPopup method use this method to return the text. Note: This method applies only
if you did not pass an HTML object in the Constructor.
Syntax
oDBFPopup.GetOutput()
Return
HTML output
Arguments
None
Example
SELECT * FROM TT_CUST INTO CURSOR Tquery
oDBFPopup=CREATE("wwDBFPopup")
oDBFPopup.BuildList()
lcText=oDBFPopup.GetOutput()
Remarks
This method applies only if you did not pass in an existing HTML object. If you passed in
a wwHTML object GetOutput() will always return a "" string. If a wwHTMLString object
was passed in, its entire contents including any prior content will be returned.
Thus only use this method to return the output if no object was passed in.
wwDBFPopup::BuildList
This method actually goes out and displays the currently selected workarea as an HTML table. It uses the property settings that
have been set previously or uses the defaults defined there.
Syntax
Return
oDBFPopup.BuildList()
nothing
- Page 72 -
West Wind Web Connection
Class wwDBFPopup
Example
SELECT * FROM TT_CUST INTO CURSOR Tquery
oDBFPopup=CREATE("wwDBFPopup")
oDBFPopup.BuildList()
lcText=oDBFPopup.GetOutput()
wwDBFPopup::Reset
This method resets all of the properties of the object to its default values. Syntax oDBFPopup.Reset().
- Page 73 -
West Wind Web Connection
Class wwHTTPHeader
Class wwHTTPHeader
Parent Class: Relation
Source: wwHTML.prg
The wwHTTPHeader class provides an easy interface for building HTTP headers that can be output using both high and
lowlevel HTML class methods. HTTP headers are used to tell the Web Server certain characteristics about the Web page that is
being returned for display. HTTP Header options available include providing the content type, Cache and Page Expiration
options, HTTP Cookies for persistent state keeping between hits and sessions, Redirection and Authentication among other
things.
Note:
The wwHTTPHeader class is new in Verson 1.70. It provides enhanced functionality that supercedes the
functionality provided in wwHTML::ContentTypeHeader(). Functions that previously used text strings to specify
the Content Type header can now specify this HTTP Header object instead. For backwards compatibility the old
text based strings still work.
An oHTTPHeader object can be passed to the following wwHTML class methods:




ContentTypeHeader
HTMLHeader
ExpandTemplate
ExpandScript
These methods will incorporate the object and properly extract the header output and insert them into the output stream. You
can also force the HTTPHeader object to 'print' itself with the Getoutput method without using those methods:
loHTML.Send( loHeader.GetOutput() )
How it works
The HTTPHeader class essentially consists of a string property that's holds the entire HTTP header info. The string starts as a
blank and is filled with by any of the class method calls. You can return no header by simply creating the header and not calling
any of the methods provided. The GetOutput() method allows you to retrieve the HTTP header as a string. Here's a typical
example of how it works.
LoHTML=THIS.oHTML
&& CGI Process object HTML object
loHeader=CREATE("wwHTTPHeader")
loHeader.DefaultHeader()
&& Create Default Content Type="text/html"
loHeader.AddForceReload()
&& Force to not Cache page
*** Check if a Cookie exists for wwID
lcId=loCGI.GetCookie("wwId")
IF EMPTY(lcId)
lcId=Sys(3)
loHeader.AddCookie("wwId",lcId)
ENDIF
*** Display a page from disk and add the HTTP header
loHTML.ShowMemoPage(HTMLPAGEPATH+"NoCode.wc",.t.,loHeader)
RETURN
- Page 74 -
West Wind Web Connection
Class wwHTTPHeader
wwHTTPHeader::GetOutput
Returns any of the previously set HTTP header text. Simply returns a string that contains the current settings of the HTTP
Header.
Syntax
oHeader.GetOutput()
Arguments
None
Return
HTTP Header as a string
Example
oHeader=CREATE(“wwHTTPHeader")
oHeader.DefaultHeader()
loHTML.Send(oHeader.GetOutput())
See Also
wwHTTPHeader::CompleteHeader
wwHTTPHeader::CompleteHeader
This method should be used only if you're not calling GetOutput() on the wwHTTPHeader object to retrieve the header
generated. It should be used when output is sent directly to an HTML object passed in the Init() and stored in the oHTML
property of this object. The method simply appends the finally carriage return required at the end of the HTTPHeader block.
This method is called automatically from GetOuput().
Syntax
oHeader.CompleteHeader()
Arguments
None
Return
nothing
Example
See Also
loHTML = CREATE("wwHTML","c:\test\temp.htm")
oHeader=CREATE(“wwHTTPHeader",loHTML)
oHeader.DefaultHeader()
oHeader.CompleteHeader()
wwHTTPHeader::GetOutput
wwHTTPHeader::ClearHeader
Releases any previous header settings and sets the HTTP header to "". If an HTML object was passed to this object in the Init
the entire HTML output is cleared.
Syntax
oHeader.ClearHeader()
Arguments
None
Return
Nothing
Example
oHeader=CREATE(“wwHTTPHeader")
oHeader.DefaultHeader()
oHeader.ClearHeader()
*** Start over
- Page 75 -
West Wind Web Connection
Class wwHTTPHeader
See Also
oHeader.SetProtocol()
oHeader.SetContentType()
wwHTTPHeader::GetOutput
wwHTTPHeader::DefaultHeader
Creates a standard HTTP header that should be used for most Web HTML pages returned from a Web Connection request. This
Header creates:
HTTP/1.0 200 OK
Content-type: text/html
Syntax
oHeader.DefaultHeader()
Arguments
None
Return
Nothing
Example
See Also
oHeader=CREATE(“wwHTTPHeader")
oHeader.DefaultHeader()
wwHTTPHeader::SetProtocol, wwHTTPHeader::SetContentType
wwHTTPHeader::SetProtocol
This lower level function sets the protocol used when returning an HTML document. Use this method only if you are NOT
using DefaultHeader(). Creates:
HTTP/1.0 200 OK
Syntax
Arguments
oHeader.SetProtocol(cProtocol)
cProtocol
Specifies the protocol to be used by the Web server. In most cases this will be
HTTP/1.0 200 OK
Return
Example
See Also
which is the default if not specified.
Nothing
oHeader=CREATE(“wwHTTPHeader")
oHeader.SetProtocol("HTTP/1.1")
wwHTTPHeader::DefaultHeader
wwHTTPHeader::SetContentType
This lower level function sets the Content type used when returning an HTML document. Use this method only if you are NOT
using DefaultHeader(). Creates:
Content-type: text/html
Syntax
Arguments
Return
oHeader.SetContentType (cContentType)
cContentType
Content Type of the document. The default is "text/html".
Nothing
- Page 76 -
West Wind Web Connection
Class wwHTTPHeader
Example
See Also
oHeader=CREATE(“wwHTTPHeader")
oHeader.SetContentType()
wwHTTPHeader::DefaultHeader
wwHTTPHeader::AddCookie
This method adds an HTTP cookie to the header. HTTP cookies are stored on the client machine in special file that the Web
browser makes available. Cookies are stored and organized by site and path and when the site and path are accessed the Cookie
is sent to the Web server along with all other CGI information. You can retrieve cookies with wwCGI::GetCookie() method.
HTTP cookies are great for keeping track of users during a session by assigning the user a Cookie Id that can be retrieved on
each request. The Cookie can be mapped to an ID in a user table for example to always know which user has initiated the
current request.
This method creates a cookie by adding it to the HTTP header. Creates a string like the following:
Set-Cookie: CookieId=CookieValue; path=/; expires=Fri, 09-01-94 00:00:00 GMT
Syntax
Arguments
oHeader.AddCookie(cCookieName, cCookieValue, cPath, cExpire)
cCookieName
Specifies the cookie name or the identifier that is used to retrieve a cookie. See
wwCGI::GetCookie for more information on retrieving a cookie from a CGI request.
cCookieValue
The value to assign to the cookie.
cPath
Specifies the path that of the current server that the Cookie applies to. If omitted the path
is the root ("/") which means the Cookie is available on the entire site.
cExpire
Specifies when the Cookie is to expire. You can also specify "NEVER". Expiration times
should be specified in the following format:
"Fri, 31-Dec-99 01:01:01 GMT"
Return
Nothing
Example
oHeader=CREATE(“wwHTTPHeader")
oHeader.DefaultHeader()
*** Check if a Cookie exists for wwID
lcId=loCGI.GetCookie("wwId")
IF EMPTY(lcId)
*** Nope, create it
lcId=Sys(3)
loHeader.AddCookie("wwId",lcId)
ENDIF
*** Display page from disk and add HTTP Header
loHTML.ShowMemoPage(HTMLPAGEPATH+"NoCode.wc",.T.,loHeader)
See Also
wwHTTPHeader::DefaultHeader, wwCGI::GetCookie
wwHTTPHeader::AddForceReload
This method forces the page to not cache, so subsequent hits to the current CGI link will always reload the page from the scipt.
Adds:
Expires: Sunday 15-May-94 16:00:01 GMT
- Page 77 -
West Wind Web Connection
Class wwHTTPHeader
Syntax
oHeader.AddForceReload()
Arguments
None.
Return
Nothing
Example
See Also
oHeader=CREATE(“wwHTTPHeader")
oHeader.DefaultHeader()
oHeader.AddForceReload()
wwHTTPHeader::DefaultHeader
wwHTTPHeader::More Methods
************************************************************************
* wwHTTPHeader :: AddCustom
***************************
*** Function: Allows adding any custom header information to the
***
HTTP header. Note that a single CR is appended
***
automatically.
***
Pass: tcCustomString - Full HTTP Header line or lines
***
Return: nothing
************************************************************************
************************************************************************
* wwHTTPHeader :: Redirect
**************************
*** Function: Redirects Server output to the specified URL or Locator.
***
Note this operation creates a full document and erases
***
any existing text that was sent.
***
Pass: lcUrl
************************************************************************
**********************************************************************
* wwHTTPHeader :: Authenticate
******************************
*** Function: Sends the authorization content type header
***
Use to pop up Security Dialog and force authentication.
***
You can use Authentication Username (CGI)
***
to retrieve the entered user name if valid...
***
Pass: tcRealm
- Domain to log in to.
***
tlNoOutput - When .T. text is returned as string
***
Return: nothing or string if tlNoOutput=.T.
**********************************************************************
************************************************************************
* wwHTTPHeader :: GetOutput
***************************
*** Function: Returns the HTTP header as a string. Adds
***
terminating CR at the end.
***
Return: HTTP Header
************************************************************************
************************************************************************
* wwHTTPHeader :: ClearHeader
*****************************
*** Function: Clears the HTTP header string from any previous settings.
***
Return: nothing
************************************************************************
- Page 78 -
West Wind Web Connection
Class wwHTMLForm
Class wwHTMLForm
Parent Class: wwHTMLControl
Source: wwForm.prg
Support Classes: wwHTMLControl and its subclasses for each control supported.
wwHTMLControl, wwHTMLLabel, wwHTMLTextBox, wwHTMLEditBox, wwHTMLCheckbox, wwHTMLRadio,
wwHTMLListBox, wwHTMLButton, wwHTMLShape, wwHTMLImage, wwHTMLPageFrame, wwHTMLGrid.
The controls are contained in wwCtls.prg.
Disclaimer: This class will generate output only for use with Internet Explorer 4.0 and the Dynamic HTML specification!
How to use it:
Using the form rendering class is very easy. There are two modes of operation, one using a program file wrapper and one using
the class itself. Let's start with the program file.
Using the wwForm Wrapper
DO FORM Guest NAME oGuest LINKED
DO wwForm with oGuest
This will run the guest sample form and then render it as DHTML and automatically display in your browser (if IE4 is your
default browser – otherwise you may see some garbage <s>).
The full syntax to wwForm is as follows:
LPARAMETER loContainer, lnValueType, lcOutputFile, llNoShow
loContainer is the form or container object that you want to render. Remember any contained objects and containers inside of
the container are also rendered. For a form this means the form and any page frames or containers get rendered. lnValueType
allows you to determine how field values are displayed: 1 – Actual display value in the form (live), 2 – Blank values (great if
you need to modify the form) or 3 – using script tags that are compatible with Web Connection and Active Server Pages (<%=
Guest.Name %> where the expression is the control source). lcOutputFile lets you dump the result to a file and llNoShow will
supress the display in the Browser if set to .T.
Using the Class
Using the class is a little more complex, but gives you access to the full range of functionality of the class. The class properties
and method hooks are described in detail below, but here is a simple example that shows how to use the class against the sample
form:
DO FORM Guest2.scx NAME oGuest LINKED
&& NOSHOW
*** Set up the Form rendering class and point it at the oGuest form
oHTMLForm=CREATEOBJECT("wwHTMLForm",oGuest)
*** Some of the properties you can set
oHTMLForm.lShowAsFullHTML=.T.
&& Add HTML Startup <HTML><BODY> and title
*oHTMLForm.lShowFormCaption=.T.
*oHTMLForm.lAbsolutePosition=.F.
&& Show VFP Title Bar on Form
&& Float form
- Page 79 -
West Wind Web Connection
Class wwHTMLForm
*oHTMLForm.lFormBackgroundTransparent=.F.
*oHTMLForm.nValueType = 2
oHTMLForm.ShowContainer()
*** Return output to a string
lcHTML = oHTMLForm.GetOutput()
*** Show output in browser
ShowHTML(lcHTML)
How it works:
The wwForm class allows rendering of live isual FoxPro classes as DHTML. The basic idea is that you instantiate a Visual
FoxPro form, then pass a reference to the form instance or any container object to the wwForm class which runs through the
container and renders each object as HTML. The class recurses down the containers inside of the container and renders the
HTML to an internal wwHTML object or a text string (retrieved with the GetOutput() method).
Field and Value mapping
Fields on the form are rendered with the same name as the name of the control, so a field name of txtLastName turns into the
NAME="txtLastName" on the HTML form. Container naming is respected so THISFORM.Container1.txtLastName is placed
as NAME=”Container1.txtLastName”. There’s also an option that assigns the ControlSource as the name for any fields that
have a controlsource property. To do so use the lUseControlSourceAsName property. By default values display the actual
value of the current fields – you can also force field values to be blank or contain Active Server/Web Connection script tags
that wrap the ControlSource value (<%= Guest.Name %> for example). The property to control value assignment is
nValueType (1- value, 2 – blank, 3 – Script tags).
HTML and Script hooks
Once a form is rendered in the browser you are now running a standard DHTML form. None of your VFP code is ported. Any
of the form’s buttons submit the form to the server. The link used as the Form action is set with the ::cFormAction property,
which should always point to the same link as the original rendering link which contains a CASE statement for all the different
button clicks of the form. To see how this works look at the IEGuest sample in wwDemo.prg. In addition there's
cFormOnLoadCode which attaches code to the form's Form_OnLoad event. The class uses this internally to handle grid and
page frame initialization, but you can hook up additional code here.
Form Submission and Assigning values back to the form
This feature works only if you use this class with a Web Connection server
When a form is submitted you can automatically reassign all the values captured by the wwCGI object back to a running form.
To do so you have to reinstantiate the form and locate it appropriately (select the record you are editing or add a new record
when adding and display it) then use the ::SetValues() method of wwHTMLForm to repopulate the fields from the request data.
Note that you can use to wwCGI::SetKey() method to override or clear input field values to avoid updating fields that you not
want updated by using SetKey() with a value of WWC_NULLSTRING. The form is updated depending on your form data
mode: If buffering is on you need to call your Save mechanism to save the data on the form, if data buffering is not on values
are immediately stored to your tables. Make sure you have proper error controls in place and that your validation routines on
your form don’t pop up traditional UI responses such as MessageBoxes etc.
Hint: To quickly test a form to see how it will look in IE4 interactively without running it through the
Web server simply run your form and then do (where Test is the object reference to the form):
DO FORM Test
DO WWFORM WITH Test
- Page 80 -
West Wind Web Connection
Class wwHTMLForm
Rules of Operation
The form is rendered using IE 4.0 style sheet tags which preserve font and sizing information, enabled/disabled, visible and
color values. For most common controls operation is straight forward – field operation is mapped directly to the
HTML equivalents. However the following controls require special attention:
Listboxes are rendered from their Item[x] collection with the display value representing the VALUE= tag. This means you can’t
easily assign a Unique key to list items and will typically require a lookup on the display value to locate the appropriate item.
The highlighted item in a list is also highlighted in the HTML form although the current rev of IE 4 will not automatically scroll
to the selected item.
Optiongroups MUST return a numeric value of the option selected; the group is treated as a single object, but each radio is
rendered as a contained object with the name of the Optiongroup as the field name. IOW, the individual button objects are only
rendered but not directly accessible.
Images are rendered by their respective filenames, stripping off the path and converting the .BMP or .ICO extension to .GIF.
Images are pathed into the directory specified by WWFORM_IMAGEPATH in Wconnect.h (default is "FormImages" below
the current directory). This path is relative to the current request. It’s possible to use pathing like this: “/FormImages/” and then
store all form related images in this directory.
PageFrames are rendered as individual DIV tags with a separate additional tag for each tab in addition to the actual page. Each
Tab’s click event contains the logic to select and activate the proper page of the PageFrame using VBScript code. The more
pages you have the more code will be generated for each tab page – don’t over do pages or you’ll end up with a monster HTML
document.
Grids are implemented using a VB ActiveX control that wraps a ListView control. The VB wrapper was required to allow fast
operation and to create a simpler interface so less code needs to be generated. Grids are read only and the first column is the
‘key’ value that is returned when you click on a selection. Selection is not automatic – you need to create a
GridName_NodeClick event handler in VBScript to decide what to do when a user clicks on a grid item. You can use the
cExitFormHTML property to create the VBScript code which is embedded just prior to the </FORM> tag. Since the grid is an
ActiveX control users will have to download the control. The control is signed but it requires consent from the user to
download the control. If the VB5 runtime is not present on the client machine the compressed runtime is downloaded separately
(approx. 1meg) from the Internet (a connection is required for this to work).
Form Buttons are all mapped to a single name called btnSubmit which are SUBMIT buttons. When you click on a button a
request is sent back to the server based on the value specified in the ::cFormAction property. You can then use
wwHTML::GetFormVar(“btnSubmit”) to figure out which button was clicked and handle it appropriately.
Picture Buttons require special handling. Unlike regular buttons these buttons create a special Form Field name which is:
ImgFieldName.x, which returns the x coordinate of the button. This format is a limitation of picture buttons in HTML. To
check whether a picture button was clicked use logic like this:
CASE !EMPTY(lower(loCGI.GetFormVar(“imgCommand1.x”)))
… Image button was pressed
Messy, but it works.
Overriding Object Types with your own Renderers
By default wwHTMLForm looks at the BaseClass property of an object to determine how to render an object. The base class is
then mapped to a wwHTMLControl object that is responsible for rendering the object using its GetHTML() method that returns
the full HTML rendition for the object.
To override this behavior you can implement a method called OverrideInsertObjectHTML() and handle your own rendering
operations. For example, say you create a class called HyperLink and you want to override the default label class that WC
would use. To do this you’d create the method:
FUNCTION OverrideInsertObjectHTML
- Page 81 -
West Wind Web Connection
Class wwHTMLForm
LPARAMETER loObject
lcOutput=""
DO CASE
CASE UPPER(loObject.Class)="WWHYPERLINK"
LcOutput = “This is my Hyperlink output”
CASE UPPER(loObject.BASECLASS)="MyGRID"
LoGridHTML=CREATE("MyGridHTML",loObject)
lcOutput=loGridHTML.GetHTML()
ENDCASE
&& not what you’d really do here <s>
RETURN lcOutput
And this would override the call to the standard rendering. As long as this method call returns a string result that’s not “” (or
WWC_NULLSTRING if you really don’t want any output) that output is used instead of WC’s object generation code. With
this you can easily extend the functionality of the default behavior without modifying WC itself. For example, you could add
your own class to render TreeView controls here…
What doesn’t work
Most controls are rendered fine with wwHTMLForm, but there are several that do not work:




ActiveX Controls (not rendered at all)
Combo Boxes (rendered as drop downs)
Multicolumn List boxes (use grids instead)
Non square shapes
How to use it:
In most cases this code will look like this (simplified):
FUNCTION wwMyProcess :: CustForm
lcButton=loCGI.GetFormVar("btnSubmit")
lcCustId=loCGI.GetFormVar("txtCustId")
&& This field might be visible=.f. on the VFP form
DO CASE
CASE lcButton = "EDIT"
DO FORM CustForm NAME oForm LINKED
oForm.Navigate(lcCustId)
oForm.EditMode()
*** Create an wwHTMLForm object and set the behavior and pass an HTML object
oHTMLForm=CREATE("wwHTMLForm",oForm,THIS.oHTML)
oHTMLForm.lShowAsFullHTML=.T.
oHTMLForm.lShowFormCaption=.T.
oHTMLForm.lAbsolutePosition=.F.
oHTMLForm.lUseControlSourceAsName=.T.
oHTMLForm.cFormAction="wc.dll?wwDemo~CustForm"
oHTMLForm.ShowContainer()
&& Render the form!
CASE lcButton = "SAVE"
DO FORM CustForm NAME oForm LINKED
oForm.Navigate(lcCustId)
oForm.EditMode()
*** Create an wwHTMLForm object and set the behavior
oHTMLForm=CREATE("wwHTMLForm",oForm,THIS.oHTML)
oHTMLForm.lShowAsFullHTML=.T.
oHTMLForm.lShowFormCaption=.T.
oHTMLForm.lAbsolutePosition=.F.
oHTMLForm.lUseControlSourceAsName=.T.
oHTMLForm.cFormAction="wc.dll?wwDemo~CustForm"
- Page 82 -
West Wind Web Connection
Class wwHTMLForm
*** set the values of the form from the values in the wwCGI object
oForm.SetValues(loCGI)
*** You can now override any values or check for validity
oForm.txtState.value = oForm.ZipLookup(oForm.txtZip.Value)
*** If Buffering is enabled on the form write or revert the data
IF oForm.ValidateInput()
oForm.SaveRecord()
ELSE
oForm.RevertRecord()
ENDIF
oForm.ViewMode()
oHTMLForm.ShowContainer()
ENDCASE
&& Render the form!
RETURN
This code is essentially a handler for the form's actions. Note that your form needs no special subclasses or control. The method
names to navigate and control the form are arbitrary. The form is simply rendered based on the baseclass object type for each of
the controls.
To control the form you use a small stub Web Connection method. As you can also see this will not work with all forms – the
interface must be such that you can control the form externally via method calls or property settings such as the Navigate(),
ViewMode(), Editmode(), SaveRecord() and RevertRecord() methods used in the example above. If your existing form does
not have such an interface intertwining user interface and business logic and UI code you will have to create an 'external'
interface so you can control the form. However, with proper design this approach allows you to build the vast majority of your
form logic totally inside of Visual FoxPro without having to worry about any HTML or even Web Connection code! The Web
Connection code only is responsible for 'driving' the form with some minimal validation code.
Notice the wwHTMLForm::SetValues() method. This method takes a wwCGI object as a parameter that can repopulate a form
from the values retrieved by a previously rendered form. If your form does not use buffering the control source of each field is
immediately updated, which I wouldn't recommend <s>. Better to update the form, then double check the values, then call a
separate Save routine to actually dump the buffer to disk. You don't have to use this method – you can do your form validation
first then populate the form or simply update the data directly; the choice is yours.
A simple sample program is provided on the demo page in the wwDemo.prg program as wwDemo::IEGuest(). Additional
samples are wwDemo::IEFormDemo and IEFormDemo2.
Grids
Grids are read only with this mechanism, so all editing that you perform off of grids need to bring up another form that's
responsible for editing the code. Grids are actually implemented as a wrapper around a ListView control. You can click on the
leftmost item and capture that click with the object's wwItemClick method, but you need to do so with VBScript (or JavaScript)
code.
The trick is to insert some VBScript into the actual <FORM> submission to allow setting a variable that you can read in your
client request. You can then submit the form and test for this value. WwHTMLForm supports adding VBScript (or any HTML
markup for that matter) via the cExitFormHTML property, which inserts whatever is assigned here just prior to the </FORM>
tag. Note that by default wwHTMLForm creates a form called wwForm, which you can override with cFormName.
I modified the Control sample to demonstrate this. The form contains a row level display of a customer and a grid that displays
all of the customers. You can click on the grid to select a customer to display. Here the same form is displayed with the new
customer info on the first page. You can check out this demo in wwDemo::IEFormDemo2().
************************************************************************
* wwDemoProcess :: IEFormDemo2
- Page 83 -
West Wind Web Connection
Class wwHTMLForm
*********************************
*** Function: Demonstrates a simple implementation of HTML Form.
***
Shows off use of Page Frame and grid display.
************************************************************************
THIS.oHTML.HTMLHeader(,'HTML VFP Form Rendering Demo using PageFrame')
THIS.oHTML.SendLn('<CENTER>')
*** Retrieve Grid Selection if one was made
lcId = THIS.oCGI.GetFormVar('grdSubmit')
*** Pass ID to the form
DO FORM IEDemoForm NAME oCust WITH lcId LINKED
NOSHOW
oHTMLForm=CREATEOBJECT('wwHTMLForm',oCust,THIS.oHTML)
oHTMLForm.lShowAsFullHTML=.F.
oHTMLForm.lShowFormCaption=.T.
oHTMLForm.lAbsolutePosition=.F.
oHTMLForm.cFormAction='/wconnect/wc.dll?wwdemo~IEFormDemo2'
*** Now allow capturing the grid selection by creating a hidden
*** form variable and storing the result to it before submitting
*** the form
oHTMLForm.cExitFormHTML = ;
[<input type='HIDDEN' NAME='grdSubmit'>] + CR +;
[<script language='VBScript'>] + CR +;
[Sub masterpageframe_page3_grid1_wwItemClick(lcKey,lcText,lnIndex)] + CR +;
[ wwForm.grdSubmit.Value = lcText] + CR + ;
[ call wwForm.submit()] + CR + ;
[end sub] + CR +;
[</script>]
oCust.Refresh
oHTMLForm.ShowContainer()
THIS.oHTML.SendLn('</CENTER>')
THIS.oHTML.HTMLFooter(PAGEFOOT)
ENDFUNC
* IEFormDemo
Note that the addition of the cExitFormHTML and adding the following code to the form's Init:
LPARAMETER lcId
SET TALK OFF
SET NOTIFY OFF
IF !EMPTY(lcID)
LOCATE FOR Custno = PADL(lcId,8)
IF !FOUND()
LOCATE
ENDIF
ENDIF
was all I had to do to make the selection work...
If you're working with multiple forms (bringing up another form to display the actual detail info) you can handle it by simply
calling another request from your starting wwProcess Method.
- Page 84 -
West Wind Web Connection
Class wwHTMLForm
Exposed Properties:
Property/Default
oContainer
oHTML
lShowAsFullHTML=.F.
cHTMLBackGround="#FFFFFF"
lShowFormCaption=.F.
lAbsolutePosition=.F.
nValueType
lUseControlSourceAsName=.F.
lShowFormBackgroundTransparent=.F.
cFormName="wwForm"
cFormAction=""
cFormMethod="POST"
cFormTarget=""
cExitFormHTML=""
Function
Object reference to the object to render. Passed to Init().
An optional existing wwHTML object reference to output to. Passed to
Init()
Determines whether the Form as rendered as a complete HTML form or
only as an object embedded inside of an HTML page.
If rendering a full HTML document this is the background color for areas
not covered by the form. This can be an RGB color setting as the default
or a background image.
Determines whether the form's caption is displayed as a blue title bar. By
default the bar is not shown.
Determines whether the form is placed inside the browser at an absolute
position as determined by the form's Top and Left properties or relative at
the current location in the HTML document.
Determines how field values are displayed:
1 – The actual value of the live form (default)
2 – Blank. Use this for form you want to customize by hand.
3 – Script Tags. Creates a script tag for the control source using Web
Connection/Active Server script tags (<%= Guest.Name %>).
By default form fields are named the same as the form fields on the form.
The full name of a form is used minus the THISFORM/frmName object
reference. If this flag is set .T. wwForm uses the Control Source instead of
the field name. This allows easier mapping of tables/business objects in an
automated fashion.
By default the form is drawn based on the background of the form. When
this flag is true the form is shown transparent omitting the form BackColor
setting.
Name of the form as specified in the <FORM> tag. This matters only if
you plan to insert your own scripting code that needs access to form
objects, which requires Form.Object.Value= syntax.
You can optionally specify a FORM ACTION= that executes when the
form is submitted. If this value is set the FORM ACTION is embedded,
otherwise no <FORM> tag is created.
If a <FORM> tag is created this METHOD= is used.
The target frame for the <FORM> tag if used.
This is hook to allow you to insert additional HTML before the
</FORM>. You can add hidden vars to the form here in order to handle
special situations like New records.
Exposed Methods:
wwHTMLForm::Init
The class constructor for the wwHTMLForm class assigns object references to the container object to be rendered and the
HTML output source to be used.
Syntax
Return
oHTMLForm.Init(oContainer, oHTML)
Nothing
- Page 85 -
West Wind Web Connection
Class wwHTMLForm
Arguments
OContainer
An object reference to the container to be rendered. Typically this will be a form
reference but you can reference any container on a form.
OHTML
An object reference to an wwHTML or wwHTMLString object that is used for output of
the HTML. This parameter is optional – if not passed a wwHTMLString object is
automatically generated and you can then use the GetOutput() method to retrieve the
HTML text.
Example
loHTML=THIS.oHTML
DO FORM CustForm NAME oForm LINKED
oHTMLForm=CREATE("wwHTMLForm",oForm,loHTML)
Remarks
See Also
wwHTMLForm::GetOutput()
wwHTMLForm::GetOutput
This method retrieves the HTML text generated by the class. This method only applies if you're passing an wwHTMLString
object or no HTML object at all.
Syntax
Return
Arguments
Example
oHTMLForm.GetOutput()
HTML as a string
None
DO FORM CustForm NAME oForm LINKED
oHTMLForm=CREATE("wwHTMLForm",oForm)
oHTMLForm.ShowContainer()
lcOutput=oHTMLForm.GetOutput()
Remarks
See Also
wwHTMLForm::Init()
wwHTMLForm::ShowContainer
This is the main method of the wwHTMLForm class. It is responsible for converting the form to HTML and is the Go Do it
function. Output is sent to the current HTML object.
Syntax
Return
Arguments
Example
oHTMLForm.ShowContainer()
Nothing
None
loHTML=THIS.oHTML
DO FORM CustForm NAME oForm LINKED
oHTMLForm=CREATE("wwHTMLForm",oForm)
oHTMLForm.ShowContainer()
lcOutput=oHTMLForm.GetOutput()
Remarks
See Also
See notes above on how field names are converted on the HTML form.
wwHTMLForm::SetValues()
- Page 86 -
West Wind Web Connection
Class wwHTMLForm
wwHTMLForm::SetValues
This method allows you to update the values of the form from a wwCGI object. The form must have been created with
wwHTMLForm::ShowContainer() call for compatibility of names. The form fields are updated from the values in the wwCGI
object. Depending on your buffering mode on the form data is either updated directly or buffered for separate saving at a later
time.
Syntax
Return
Arguments
Example
oHTMLForm.SetValues(oCGI)
Nothing
oCGI
An object reference to an wwCGI that must come of a form created with the
ShowContainer() method.
loHTML=THIS.oHTML
loCGI=THIS.oCGI
DO FORM CustForm NAME oForm LINKED
oHTMLForm=CREATE("wwHTMLForm",oForm)
oHTMLForm.ShowContainer()
oHTMLForm.SetValues(loCGI)
lcOutput=oHTMLForm.GetOutput()
Remarks
See Also
See notes above on how field names are converted on the HTML form.
wwHTMLForm::ShowContainer()
wwHTMLForm::OverrideInsertObjectHTML
This method is a hook to override the wwHTMLForm class' HTML generation for each of the VFP form controls. By default
wwHTMLForm looks at the form's base class to determine how to render the form. You can override this behavior by
subclassing the wwHTMLForm object and implementing this method. The method is called when each object is rendered and
should return the HTML as string text that's to be embedded in the form. You can return a null string ("") to force
wwHTMLForm to continue with its form processing on the object or WWC_NullString to force no output at all for the object.
By default this method is empty and returns "" so the wwHTMLForm class renders the HTML.
Syntax
Return
Arguments
Example
oHTMLForm.OverrideInsertObjectHTML(oObject)
HTML string for the current control
"" to use the default control rendering
WWC_NullString to create no output at all
OObject
An object reference to the VFP form control to render.
FUNCTION OverrideInsertObjectHTML
LPARAMETER loObject
lcOutput=""
DO CASE
CASE loObject.Class="MyAutoRenderingHTMLClass"
LcOutput=loObject.RenderHTML()
CASE UPPER(loObject.BASECLASS)="GRID"
LoGridHTML=CREATE("wwGridHTML",loObject)
lcOutput=loGridHTML.GetHTML()
ENDCASE
RETURN lcOutput
This method will override wwHTMLForm's object rendering for the CASE statement
entries, but continue to use the default functionality on all other cases. This hook allows
- Page 87 -
West Wind Web Connection
Class wwHTMLForm
creating new object types or for you to use any HTML rendering you build into your own
base classes.
Remarks
See Also
wwHTMLForm::ShowContainer()
wwHTMLForm::OverrideSetValue
This method is a hook to override the wwHTMLForm class' SetValue mechanism when updating a running VFP form from a
wwCGI object. This method allows you to hook into the update mechanism that's responsible for updating the value so you can
provide custom update functionality for special class types or even specific form variables.
By default wwHTMLForm calls the protected SetValue() method which looks at the base class and accordingly sets the value
of the control. This method allows overriding of the value to set. If the method returns .T. default processing does not occur, if
the method returns .F. default processing occurs in addition to the method code executed.
.
Syntax
Return
oHTMLForm.OverrideSetValue(oObject)
.t. or .f. to indicate whether the default SetValue() processing should take place after the
method call.
Arguments
Example
FUNCTION OverrideSetValue
LPARAMETER loObject
llRetval=.F.
&& By default don't override
DO CASE
CASE UPPER(loObject.Class) = "MYCHECKBOX"
loObject.Value=.T.
loObject.Caption="Different Caption"
llRetVal=.T. && Override default processing
ENDCASE
RETURN llRetVal
Remarks
See Also
wwHTMLForm::SetValues()
- Page 88 -
West Wind Web Connection
Class wwVFPScript
Class wwVFPScript
Parent Class: Relation
Source: wwVFPScript.prg
Related Classes: Request, Response, Session, Server
PRE-RELEASE – implementation subject to change
The wwVFPScript class provides a scripting mechanism similar to the one found in Microsoft Active Server Pages providing
Visual FoxPro based scripting environment. Note that this is a pure Visual FoxPro implementation and thus the functionality is
approximated and not necessarily exact. The most common Active Server Objects are implemented along with the common
collections and methods that go with these objects. The Web Connection implementation allows use of either the Active Server
objects or the native Web Connection objects and of course any Visual FoxPro language constructs.
This scripting implementation is somewhat different from the scripting mechanism provided by the
MergeText/ExpandTemplate/ShowMemoPage methods available in the wwHTML Class. The main difference is that the
wwVFPScript class uses compiled code rather than the interpreted code used by MergeText. While this means much better
performance, especially for pages that contain looping constructs or lots of code, it also brings with it the requirement to
compile pages. This means that pages can be run, interactively be debugged and evaluated in the development version of Visual
FoxPro, but require pre-compilation into .FXP files for execution under the runtime environment. A tool and HTML link to
compile pages is provided, but remember that the Development version of VFP needs to be present even if your application
runs with the VFP runtime.
How it works
The scripting engine works as a separate object inside of the Web Connection framework that works in conjunction with the
Web Connection HTML object. A .WCS page is called using a Server based script map, which is captured by Web Connection
in the wwServer::Process method as follows:
DO CASE
CASE lcParameter == "WWDEMO"
DO wwDemo with THIS.oCGI, THIS
CASE lcParameter == "WWMAINT"
DO wwMaint with THIS.oCGI, THIS
OTHERWISE
*** Check for .WC or .WCS script mapped files
lcPhysicalPath=THIS.oCGI.GetPhysicalPath()
DO CASE
CASE ATC(".WC",lcPhysicalPath) > 0 OR ATC(".FXP",lcPhysicalPath) > 0
DO wwScriptMaps with THIS.oCGI,THIS
To load this page you’d simply do: /wconnect/wwScript.wcs or /wconnect/wwScript.fxp
A scriptmap is a server implemented mechanism that provides a mapping of a script file extension (.wcs or .wc for Web
Connection) to an ISAPI dll. In this case, .WC, .WCS and .FXP are mapped to the Web Connection DLL (wc.dll) in the
physical path of c:\http\wconnect\wc.dll (your base path may vary depending on where you installed the HTML files). Now
whenever you reference a file with a .WCS extension it will always execute the DLL. Furthermore, when you do this the Web
path will not be changed – you can access a .WCS page anywhere without having to explicitly tell it to look for the DLL in a
specific directory. So: /wwScript1.wcs or /wconnect/wwScript2.wcs both are valid with only a single copy of the WC.DLL in
/scripts/wc.dll.
- Page 89 -
West Wind Web Connection
Class wwVFPScript
Web Connection scripting sets up two separate scriptmaps: .WCS for the source file and .FXP for the compiled version. If
you’re running under the runtime of VFP they both do the same thing, which is to run the compiled .FXP file. Under the
development environment you can explicitly use the .FXP file as the script page and it will not try to evaluate the page first, but
rather always run the compiled file. As a result any changes made to the .WCS file are not respected until you recompile the
page. If you load the .WCS page under the development environment Web Connection first converts the page into code then
runs the newly created page. Notice that this compilation step can cause access problems if multiple simultaneous sessions
access the same .WCS page at the same time, since the simultaneous compilation can cause problems. Thus, for production
environments compiled pages are the only reliable way to use this feature.
When a scriptmap request is made on the Web server it fills in a server variable called Physical Path with the full DOS path for
the script that was called. So in the example above you might get: c:\http\wwScript1.wcs or c:\http\wconnect\wwScript2.wcs.
You can retrieve this path with loCGI.GetPhysicalPath() and voila you now know which page was requested by the server.
Once you can use the page on disk it’s now ready to be executed or interpreted.
Notice above that we’re calling wwScriptMaps.prg which is a subclassed wwProcess Implementation that looks like this:
************************************************************************
* wwScriptMaps :: Process
***************************
FUNCTION Process
LOCAL lcParameter, lcOutFile, lcIniFile, lcOldError
PRIVATE poProcess, poSession, poServer, poHTML, poCGI
lcPhysicalPath = THIS.oCGI.GetPhysicalPath()
*** PRIVATE refs to Web Connection Objects
poSession = THIS.oSession
poProcess = THIS
poServer = THIS.oCGIServer
poHTML = THIS.oHTML
poCGI = THIS.oCGI
DO CASE
CASE ATC(".WCS",lcPhysicalPath) > 0 OR ATC(".FXP",lcPhysicalPath) > 0
llRuntime = ATC("RUNTIME",Version()) > 0 or ATC(".FXP",lcPhysicalPath) > 0
lcFXP = ForceExt(lcPhysicalPath,"FXP")
IF llRunTime
lcPhysicalPath = lcFXP
ENDIF
*** WCS - Script Text
FXP - Compiled
WCT - Intermediate
oScript = CREATE("wwVFPScript",lcPhysicalPath,THIS.oHTML,THIS.oCGI)
oScript.lAlwaysUnloadScript = .T.
*** Convert Page to VFP Code
IF !llRunTime
oScript.ConvertPage() && Creates a .WCT file
ENDIF
oScript.RenderPage()
*** ##FOXCODE pages
CASE ATC(".WC",lcPhysicalPath) > 0
poCGI=THIS.oCGI
poHTML=loHTML
THIS.oHTML.ExpandTemplate(lcPhysicalPath)
OTHERWISE
*** Unhandled method - display error page
THIS.ErrorMsg("Invalid or unsupported scriptmap","")
THIS.oCGIServer.SendMail(MAILSERVER,;
- Page 90 -
West Wind Web Connection
Class wwVFPScript
WWC_ADMINISTRATOR_EMAIL,;
WWC_ADMINISTRATOR_EMAIL,;
WWC_ADMINISTRATOR_EMAIL,"", ;
"Web Connection Error Message - Invalid Script Map",;
THIS.oCGI.cQueryString)
ENDCASE
RETURN .T.
This code first checks to see whether we want to deal with a runtime file (VFP runtime is in use or a .FXP file was passed) or
with the development environment. If we’re running a .WCS file in the development environment the page is converted to VFP
code on every request with the wwVFPScript::ConvertPage() method. This method takes the scripted code in the WCS file and
creates something that Visual FoxPro can compile. Internally Web Connection uses VFP’s TEXTMERGE functions to do this
by delineating the script code with TEXT/ENDTEXT and embedded expressions. The code generated isn’t pretty, but if you’re
running the dev version you can look at the .WCT files generated in the same directory as the .WCS file.
Once the page has been converted to code Web Connection tries to run the page with wwVFPScript::RenderPage(). This does
the equivalent of DO (yourpage.wct). In the process the .WCT page is compiled into a .FXP file that is also stored in the same
directory as the .WCS script file.
A sample script page
Before we look at how the scripting works lets look at a simple script page – wwScript.wcs:
<HTML>
<h2>Hello World</h2>
The Time is: <%= Time() %>
<p>
<% For x= 1 to 12 %>
Loop Number: <%= x %><br>
<%
ENDFOR %>
<p>
<%
*** Demonstrate using WC objects
lcCompany = poCGI.GetUrlEncodedParameter("Company")
&& WC Syntax
lcCompany = Request.QueryString("Company")
&& ASP Syntax
SELECT company,careof FROM TT_CUST INTO Cursor TQuery ;
WHERE UPPER(Company) = UPPER(lcCompany)
Response.Write(poHTML.ShowCursor(,,,.T.))
&& Use of WC wwHTML method
%>
<PRE>
User Agent: <%= Request.ServerVariables("User-Agent") %>
Server Software: <%= Request.ServerVariables("Server Software") %>
User ID: <%= Request.QueryString("Company") %>
</PRE>
</HTML>
This page looks very much like an Active Server Page using the same syntax convention, but employing Visual FoxPro code
instead of VBScript or Jscript. This page runs through Web Connection rather than through ASP.DLL! As with ASP <% %>
delineates scripted code. Between these separators any Visual FoxPro code can be embedded. A slight variation of the syntax
with <%= %> means to evaluate a single expression, so you can put <%= TIME() %> for example. Expressions do not have to
be character based, but for proper formatting it’s recommended you do your own conversions to character as needed. Note
either type of script tags cannot be nested (nor does it really make sense) – if you do you’ll likely receive an error in your VFP
code.
Notice that you can break structured VFP statements with separate script tags like this:
<%
For x= 1 to 12 %>
Loop Number: <%= x %><br>
- Page 91 -
West Wind Web Connection
Class wwVFPScript
<%
ENDFOR %>
All output is sent to the current HTML output device via the Response object. Response.Write is responsible for this operation.
In fact the <%= %> syntax mentioned before is really a shortcut for a Response.Write construct and performs exactly the same
task. Thus:
<% lcOutput = “Hello World” %>
<% Response.Write(lcOutput)%>
<%= lcOutput %>
are identical.
Accessing Objects – ASP Objects and Web Connection Objects
Web Connection provides access to both ASP object simulations or all of the Web Connection native objects. The ASP objects
are implemented in VFP code by calling back on the appropriate Web Connection objects and are provided mainly for
familiarity for those that have already worked with Active Server. All Web Connection objects are also available (poProcess,
poServer, poSession, poHTML, poCGI) and you can of course create and destroy any Web Connection objects directly in your
code.
The need to compile
Up to now we’ve discussed converting and running a script page, but as you’ve probably noticed there is a compilation step that
takes place implicitly when you first DO yourpage.wct. For this reason the development version is required to dynamically run
pages that can be changed. When running a .WCS page in the development version you can make a change to the text file that
contains the script (.wcs page) and simply refresh the browser to immediately see your change. When running under the runtime
a compiled file is required so changing the text file requires recompilation with the development version. However, once a page
has been compiled into a .FXP the page can be run by the runtime version of Visual FoxPro – just when making changes do you
need to make sure the page is recompiled with the dev version.
To simplify recompilation there’s a utility in the .\tools directory called WCSCOMPILE.PRG that you can use to recompile
pages quickly. It takes advantage of the wwVFPScript Class’s CompilePage() method to quickly generate a compiled version of
a program. The syntax is:
DO WCSCOMPILE WITH [<cWCSPage>|<cScriptPath>]
You can either specify a single page or set of wildcarded pages, or an entire path. REMEMBER: This has to be run from the
development version of Visual FoxPro. There’s also a method in wwUtils that actually does the lowlevel work. Its syntax is:
WCSCompile(ScriptPath,lSilent)
Both of these require the VFP development environment in order to compile pages. However, if you are running a runtime
application or Automation server and you also have the Visual FoxPro development version (5.0 or later) installed, a new
method in the wwMaint module will invoke the VFP server application and run WCSCompile from there. Here’s what that code
looks like:
* wwMaint :: CompileWCS
FUNCTION CompileWCS
loCGI = THIS.oCGI
lcFileSpec = loCGI.GetCGIParameter(3)
IF EMPTY(lcFileSpec)
lcFileSpec = loCGI.GetFormVar("txtFileSpec")
ENDIF
IF EMPTY(lcFileSpec)
lcPhysicalPath = loCGI.GetPhysicalPath()
lcFileSpec = ADDBS(JustPath(lcPhysicalPath))+"*.wcs"
ENDIF
o=CREATEOBJECT("VisualFoxPro.Application")
o.DoCmd("SET DEFAULT TO "+SYS(5)+CURDIR())
o.DoCmd("SET PATH TO .\classes; .\eclasses; .\tools")
- Page 92 -
West Wind Web Connection
Class wwVFPScript
*** Load Web Connection Classes
o.DoCmd("DO WCONNECT")
*** Compile .WCS Active Server Script Pages
lcErrors = o.Eval("wcscompile('"+lcFileSpec+"',.t.)")
o = .F.
IF EMPTY(lcErrors)
lcErrors = "No Errors..."
ENDIF
THIS.ErrorMsg("Scripts Compiled",;
[ <font face="Verdana" size=3>ScriptPath: ]+lcFileSpec+CR+CR+;
"<HR><PRE>"+ lcErrors + "</PRE></FONT>")
ENDFUNC
* wwMaint :: CompileWCS
This code in wwMaint allows you to compile pages through an HTML link given that the dev version of VFP is installed. Using
OLE Automation of VFP this code then calls the WCSCompile() function to compile the specified script in the dev version.
You can specify the files to compile either as part of the URL (via the 3rd parameter) or a form link. By bookmarking a
parameter link you can have one step compilation of pages.
For example:
/wconnect/wc.wc?wwMaint~WCSCompile~\http\wconnect\*.wcs
- Page 93 -
West Wind Web Connection
Class wwSession
Class wwSession
Parent Class: Relation
Source: wwSession.prg
The wwSession class provides a state mechanism for tracking people through a 'visit' of a site. The most common example
would be to track a customer through a shopping site. Since HTTP is stateless you have no way to track the user from request to
request. With the use of HTTP Cookies or Ids passed as part of the URL you can track people through a site. This class
provides a mechanism for storing and retrieving session specific values for a particular user by creating an entry in a table that
has a timeout. Realize that you still need to manually set the cookie from your code using the wwHTTPHeader object (see
example below).
Methods for creating, reading and timing out the session are provided. You can genericly attach character variables to a session
object, the values of which are stored in a free form memo field using the SetSessionVariable() method. The variables can be
retrieved at any time with the GetSessionVariable() method.
How it works
The wwSession class is a wrapper around the wwSession table which stores all of the session information. The structure of this
table is:
CREATE TABLE ( THIS.cDataPath+THIS.cTableName );
(SESSIONID
C (9),;
USERID
C (8),;
FIRSTON
T ,;
LASTON
T ,;
VARS
M ,;
BROWSER
M,;
IP
M,;
CDATA1
M ,;
CDATA2
M )
The table is created the first time you try to use any of the methods of the session object – you can use the Reindex() method to
clean up and purge the session file.
The SessionId is the unique identifier for each session. Using the NewSession() method a new ID is generated and an entry is
created in the table. The resulting SessionId should be used as the Cookie you pass back to the browser. On the next hit you can
check for this Cookie and use it to check for a valid session using the IsValidSession() method.
wwSession doesn't explicitly use the UserId field, but you can assign this field as a parameter of NewSession() and use it to
cross reference a Session user with a user in an actual user table or security descriptor table. To optionally log the Browser and
IP address you can assign a reference to a wwCGI object to the oCGI property. CDATA1 and CDATA2 are not used but can be
used by you to store additional data without explicitly adding fields.
The following example uses a wwSession object:
************************************************************************
* wwDemo :: PagedCustomerList
*********************************
*** Function: Demonstrates use of the wwSession object, Cookies the
***
wwShowCursor's Paging mode to display a query in paged
***
format. The code below stores the Filter of the query
***
in a Session variable which is retrieved on each page
***
hit to re-run the query and jump to the appropriate
***
page.
- Page 94 -
West Wind Web Connection
Class wwSession
************************************************************************
FUNCTION PagedCustomerList
LOCAL lcCookie, loSession, loHeader, loHTML, loCGI
loCGI=THIS.oCGI
loHTML=THIS.oHTML
*** Ideally this object should be:
*** THIS.oCGIServer.AddObject("oSession","wwSession")
*** in wwServer :: SetServerProperties
loSession=CREATE("wwSession")
loSession.nSessionTimeout=1800
&& Seconds - 1/2 hour
*** Retrieve the Cookie
lcCookie=loCGI.GetCookie("WWDEMOID")
*** We'll need to create a custom HTTP header so we can potentially
*** add the Cookie to it
loHeader=CREATE("wwHTTPHeader")
loHeader.DefaultHeader()
*** Check if we have a valid Session
IF !loSession.IsValidSession(lcCookie)
*** Nope create it
lcCookie=loSession.NewSession()
*** And add a Cookie to the Request Header
loHeader.AddCookie("WWDEMOID",lcCookie)
ENDIF
*** Now try retrieving the Query Parameters
*** Values on relevant if we're running from the form on the 'first hit'
lcCompany=loCGI.GetFormVar("txtCompany")
lcName=loCGI.GetFormVar("txtName")
*** Retrieve the page number - wc.dll?wwDemo~PagedCustomerList~PageNo
lnCurrentPage=VAL(loCGI.GetCGIParameter(3))
IF lnCurrentPage=0
lnCurrentPage=1
ENDIF
*** Check if we clicked the button of the form
IF !EMPTY(loCGI.GetFormVar("btnSubmit"))
*** Build a filter
lcFilter=""
IF !EMPTY(lcCompany)
lcFilter="UPPER(Company) = '" + UPPER(lcCompany) + "' AND "
ENDIF
IF !EMPTY(lcName)
lcFilter=lcFilter + "UPPER(Careof) = '" + UPPER(lcName) + "'
ENDIF
IF !EMPTY(lcFilter)
lcFilter = lcFilter + "!DELETED()"
ENDIF
*** Store the filter in the Session Object
loSession.SetSessionVar("CustomerQueryFilter",lcFilter)
ELSE
*** No - paging through file
*** Retrieve the filter from the Session Variable
lcFilter=loSession.GetSessionVar("CustomerQueryFilter")
ENDIF
IF !EMPTY(lcFilter)
lcFilter= "WHERE " + lcFilter
- Page 95 -
AND "
West Wind Web Connection
Class wwSession
ENDIF
SELECT Company, CareOf, Phone ;
FROM TT_CUST ;
&lcFilter ;
ORDER BY Company ;
INTO CURSOR TQuery
*** Create the HTML header for the page
*** Note the custom HTTP header object containing the Cookie (loHeader)
loHTML.HTMLHeader("Paged Customer List",,BACKIMG,loHeader)
*** Create a ShowCursor Object and pass our HTML object
loSC=CREATE("wwShowCursor",loHTML)
*** Set the Paging parameters - 5 per page
loSC.nPage_ItemsPerPage=5
loSC.nPage_ShowPage=lnCurrentPage && Which page?
*** The URL to use for the Next/Prev buttons - This page
loSC.cPage_PageURL="wc.dll?wwDemo~PagedCustomerList"
*** Now dump the HTML
loSC.ShowCursor()
loHTML.HTMLFooter(PAGEFOOT)
ENDFUNC
* PagedCustomerList
Property
Function
nSessionTimeout
cTableName
cDataPath
cDelimiter
oCGI
The period for which a session is valid in seconds. 1800
The name of the session table. wwSession
The location of the session table. .\
The delimiter used by the Vars Session variable field. #!#
A reference to a wwCGI object used for retrieving the
Browser and IP Address. Must be set prior to a call to
NewSession().
The SessionID as retrieved by IsValidSession() or set by
NewSession().
cSessionID
wwSession::Init
The constructor allows setting the datapath and filename for the wwSession file. The file will always be aliased as wwSession
regardless of what the table name is here.
Syntax
Arguments
oSession.Init(cTableName, cDataPath)
cTableName
The name of the table to use.
cTableName
The location for the file.
Return
Example
loSession=CREATE("wwSession")
See Also
- Page 96 -
West Wind Web Connection
Class wwSession
wwSession::Reindex
Packs and reindexes the wwSession file. You can optionally pass a date/time value to tell this method to purge all entries before
that time.
Syntax
Arguments
Return
Example
See Also
oSession.Reindex (dtPurge)
tPurge
Purges entries prior to this date/time Optional
.T. or .F. if no exclusive lock
loSession=CREATE("wwSession")
loSession.Reindex()
wwMaint::ReindexSystemFiles
wwSession::NewSession
Creates a new session entry and returns a session ID
Syntax
Arguments
Return
Example
See Also
oSession.NewSession(cUserId)
cUserId
A user ID that crosslinks to a user table for your application. Optional.
nothing
lcCookie=THIS.oCGI.GetCookie("WWDEMOID")
loSession=CREATE("wwSession")
IF !IsValidSession(lcCookie)
lcCookie=loSession.NewSession()
ENDIF
wwSession::IsValidSession()
wwSession::IsValidSession
Checks to see if a session exists.
Syntax
Arguments
Return
Example
See Also
oSession.IsValidSession(cSessionId)
cSessionId
The SessionId to check for. Typically this will be an HTTP Cookie retrieved from the wwCGI object.
.T. or .F.
lcCookie=THIS.oCGI.GetCookie("WWDEMOID")
loSession=CREATE("wwSession")
IF !IsValidSession(lcCookie)
lcCookie=loSession.NewSession()
ENDIF
wwSession::NewSession()
- Page 97 -
West Wind Web Connection
Class wwSession
wwSession::SetSessionVar
Creates or sets a dynamic Session variable. The variables are stored in the Vars memo field and can only be retrieved using the
GetSessionVar method. All variables must be text strings.
Syntax
Arguments
oSession.SetSessionVar(cVarName, cValue)
cVarName
Name of the dynamic variable or key. This is the identifier.
cValue
Return
Example
The value to set the variable to.
nothing
lcCookie=THIS.oCGI.GetCookie("WWDEMOID")
loSession=CREATE("wwSession")
IF !IsValidSession(lcCookie)
lcCookie=loSession.NewSession()
ENDIF
See Also
lcFilter=loSession.GetSessionVar("QueryFilter")
IF EMPTY(lcFilter)
lcFilter="WHERE Company='S'"
loSession.SetSessionVar("QueryFilter",lcFilter)
ENDIF
wwSession::GetSessionVar()
wwSession::GetSessionVar
Retrieves a dynamic Session variable from the wwSession table's Var field.
Syntax
Arguments
Return
Example
oSession.GetSessionVar(cVarName)
cVarName
Name of the dynamic variable or key to retrieve the value for.
Value as a string or "" if not found or empty.
lcCookie=THIS.oCGI.GetCookie("WWDEMOID")
loSession=CREATE("wwSession")
IF !IsValidSession(lcCookie)
lcCookie=loSession.NewSession()
ENDIF
See Also
lcFilter=loSession.GetSessionVar("QueryFilter")
IF EMPTY(lcFilter)
lcFilter="WHERE Company='S'"
loSession.SetSessionVar("QueryFilter",lcFilter)
ENDIF
wwSession::SetSessionVar()
wwSession::GetUserId
Retrieves the user id from the session.
Syntax
oSession.GetUserId()
Arguments
- Page 98 -
West Wind Web Connection
Class wwSession
Return
Example
User ID or "" if not found or empty
lcCookie=THIS.oCGI.GetCookie("WWDEMOID")
loSession=CREATE("wwSession")
IF !IsValidSession(lcCookie)
lcCookie=loSession.NewSession(wwUsers.UserId)
ENDIF
See Also
lcID=loSession.GetUserId()
wwSession::NewSession()
wwSession::GetField
Retrieves a value from any field of the wwSession table. This is equivalent to doing lvValue=wwSession.Field, but this method
is provided here for consistency.
Syntax
Arguments
Return
Example
oSession.GetField (cFieldName)
cFieldName
Name of the field to retrieve. Field may be of any type. The value is EVALUATEd
Field value
lcCookie=THIS.oCGI.GetCookie("WWDEMOID")
loSession=CREATE("wwSession")
IF !IsValidSession(lcCookie)
lcCookie=loSession.NewSession(wwUsers.UserId)
ENDIF
lcAddress=loSession.GetField("SessionAddress")
See Also
- Page 99 -
West Wind Web Connection
Class wwIPStuff
Class wwIPStuff
Parent Class: Custom
wwIPStuff.vcx
Source:
The wwIPStuff class holds a number of Internet related utility routines that can be used with any Visual FoxPro application.
The class provides a wrapper around the wwIPStuff.dll file which is distributed with this package and provides the low level
interface to WinInet and Winsock for implementing the various protocols.
NOTE: You also need the WININET.DLL file, which is a Windows system file that gets installed with Internet
Explorer and various other Internet related applications (not with Netscape, though). This file is freely
distributable and can be downloaded from ftp://ftp.west-wind.com/wininet.zip. You need this file if you cannot get
wwIPStuff.dll to load when issueing the DECLARE in the Init() method of the wwIPStuff class. The failure will
be: 'Cannot find entry point to function…'.
The class provides the following features:
 SMTP SendMail capability both in blocking and asynchronous modes
 Support for Blind CCs and one Mime Base64 encoded file attachment
 Domain lookup by IP Address
 Reverse domain lookup of IP address from domain name
 Blocking FTPSend and FTPGet operations
 FTP Directory
 FTP File Delete
 HTTP GET – retrieve URLs to a text string
 HTTP POST via the extended HTTPConnect/AddPostKey/HTTPGetEx/HTTPClose methods. Allows sending data to a
Web server.
 HTTP functions support: HTTPS requests, Authentication and returning of HTTP Headers
 Low Level HTTP Get allows retrieving HTTP headers and multiple Get operations without reconnecting to the server.
 Events for HTTP download status
 HTTP Data class that allows running VFP database queries over HTTP (requires Web Connection server)
 File Encoding/Decoding routines that allow passing files over the Internet using HTTP
 Dialing and hanging up a RAS connection
 Low Level Interface to DynaZip DLLs so no OCX is required.
How it works
The wwIPStuff class is little more than a wrapper around the wwIPStuff.dll which abstracts many Internet Protocol operations
(with exception of the HTTP functions which are implemented as pure VFP code calling WinInet). The DLL expands on the
functionality provided there by providing support for SMTP and a front end that is capable of being called by Visual FoxPro's
simple API calling interface using the DECLARE DLL mechanism.
The VFP class provides a front for the DLL so you don't have to worry about the logistics of accessing the functionality. All
parameter passing and return value validation is performed by the class which also provides a property/method interface to the
static functions in the DLL.
When initially created a wwIPStuff object sets the path to the DLL which is used in all subsequent requests. The Init() of the
class also loads the DLL and the Winsock drivers into memory on instantiation. Once loaded Winsock stays resident for quicker
access of subsequent requests onto the DLL.
- Page 100 -
West Wind Web Connection
Class wwIPStuff
How to use it
Using the wwIPStuff class is accomplished by creating an instance of the class and setting the properties for the appropriate
method calls. The following example shows all of the functionality available:
SET PROCEDURE TO wwUtils ADDITIVE
SET CLASSLIB TO wwIPStuff ADDITIVE
CLEAR
o=CREATE("wwIPStuff")
Sending SMTP Mail
o.cMailServer="mail.yourserver.net"
o.cSenderEmail="rstrahl@west-wind.com"
o.cSenderName="Bill Bopp"
o.cRecipient="rstrahl@swest-wind.com,rstrahl@agorge.net"
o.cCCList="rstrahl@xwest-wind.com,looser@nobody.com"
o.cBCCList="rstrahl@west-wiund.com"
o.cSubject="wwIPStuff Test Message"
o.cMessage="Who said this had to be difficult?"
o.cAttachment="c:\config.sys"
*? o.SendMailAsync()
&& Send message and return immediately w/o result
llResult = o.SendMail()
&& Send again - wait for completion
IF !llResult
Wait window o.cErrorMsg
ENDIF
Sending and receiving files via FTP
The FTP class is implemented as a separate class and named wwFTP.
LoFTP = CREATE(“wwFTP”)
? o.FTPGetFile("ftp.west-wind.com","pkunzip.exe","c:\temp\pkzip.exe")
*** Or you can use syntax like this:
o.cFTPServer="ftp.west-wind.com"
o.cFTPSource="c:\wipeit.bat"
o.cFTPTarget="/uploads/wipeit.bat"
*** Use passwords if Anonymous is not allowed.
* o.cUsername="bozo"
* o.cPassword="looser"
? o.FTPSendFile()
The FTPGetFileEx and FTPSendFileEx methods also support downloads while providing event method calls to allow progress
reporting and aborting a download:
PUBLIC o
o=CREATE("myFTP")
wait window nowait "Alt-x to abort download..."
ON KEY LABEL ALT-X o.lCancelDownload = .T.
IF o.FTPConnect("ftp.west-wind.com") # 0
? o.nError
? o.cErrorMsg
RETURN
ENDIF
IF o.FtpGetFileEx("wconnect.zip","c:\temp\wconnect.zip")
- Page 101 -
# 0
West Wind Web Connection
Class wwIPStuff
? o.nError
? o.cErrorMsg
RETURN
ENDIF
ON KEY LABEL ALT-X
RETURN
*** Implementation of Message Display and abort code
Define class myFtp as wwFTP
Function OnFTPBufferUpdate
LPARAMETER lnBytesDownloaded,lnBufferReads,lcCurrentChunk
DO CASE
CASE lnBufferReads > 0
wait window "Downloaded: " + TRANSFORM(lnBytesDownloaded)+ " bytes (Alt-X to cancel)"
nowait
CASE lnBufferReads = -1
wait window "Download aborted..." timeout 2
ENDCASE
RETURN
ENDDEFINE
Retrieving HTTP requests to strings (HTTP GET)
You can simply retrieve a Web page or any HTTP data over the Web with:
? o.HTTPGet("http://www.west-wind.com/")
lcData=o.HTTPGet(http://www.west-wind.com/logstats.dat)
remember that the content return does not need to be HTML!!!
Sending and Retrieving HTTP requests to strings (HTTP POST)
o.HTTPConnect("www.west-wind.com ")
o.AddPostKey("Company","A")
o.AddPostKey("FromDate","01/01/96")
@lcBuffer = ""
*** Send the POST data and retrieve HTTP result
lnResult = o.HTTPGetEx("/wconnect/wc.dll?wwDemo~ShowHours",@lcBuffer)
IF lnResult = 0
wait window nowait o.cErrorMsg
ENDIF
*** Print out the HTTP header for the request
? o.cHTTPHeader
o.HTTPClose()
&& Close the connection
Sending and Receiving files over HTTP:
The following demonstrates how you can use a Visual FoxPro client (non-HTML) to connect to a VFP Web server and send
files between the two to essentially run queries over the Web:
Server Code using a standard Web Connection Request (can also be done with ASP, FoxISAPI etc.):
Function CustList && httpProcess::CustList
SELECT * FROM TT_CUST WHERE &lcFilter INTO TABLE Texport
- Page 102 -
West Wind Web Connection
Class wwIPStuff
*** Format the the file and memo field and store to a string
lcFileText = oIp.EncodeDBF("Texport.dbf",.T.)
*** Send Binary data to client as Web server response
loHTML.Send(lcFileText)
Client Code (plain VFP application):
*** Connect to server once
o.HTTPConnect("www.west-wind.com")
*** Presize the buffers!
lcText=SPACE(100000)
lnText=LEN(lcText)
*** Read the results send by the server – result is encoded file
o.HTTPGetEx("/wconnect/wc.dll?http~CustList",@lcText,@lnText)
*** decode the file and save to Timport.dbf
IF o.DecodeDBF(lcText,"Timport.dbf")
*** Show the result
USE Timport
BROWSE
ELSE
wait window "File could not be converted"
ENDIF
o.HTTPClose()
Domain Name Lookup
*** Domain Lookups from IP Address and Reverse Domain Lookups
? o.GetDomainFromIp("205.162.195.2")
? o.GetIpFromDomain("ftp.west-wind.com")
The FTP and SMTP methods can be used either with the property interface or by passing parameters directly to the methods.
Exposed Properties:
SMTP properties:
cMailServer
The IP Address or domain name of the SMTP server that is responsible for sending the message. The server must
support 'pure' SMTP mail services and must not require a login prior to sending messages.
cSendername
Display name of the person sending the message. This option is often overridden by the mail server with the actual
user account, but some servers leave the name as set here.
cSenderEmail
The sender's Email address.
cRecipient
Either a single recipient email address or a list of comma delimited addresses. Limited to 1024 characters.
cCCList
Either a single CC recipient email address of a list of comma delimited addresses. Limited to 1024 characters.
cBCCList
Blind CCs are sent messages but do not show on the recipient or CC listing of the receiver. Limited to 1024
characters.
- Page 103 -
West Wind Web Connection
Class wwIPStuff
cSubject
The message subject or title.
cMessage
The actual message body text.
cAttachment
The name of the file that is to be attached to the message. This property must be filled with a valid path pointing at the
file to attach.
cContentType
A content type that is used when sending the message. The default is text/plain, which is standard email format. You
can change the content type to text/html for example to force messages to be sent as HTML documents that can be
read in HTML capable email readers such as Outlook Express.
FTP Properties:
cFTPServer
IP Address or domain name of the FTP server to work with
cFTPSource
The source file to send from. When uploading the source is the local file, when downloading the source is the remote
file.
cFTPTarget
The target file to send to. When uploading the target is the remote file, when downloading the target is the local file.
nFTPBinary
Binary mode flag. 1 – binary file (default). 2 – ASCII Text.
cUsername
Username of the user to connect to the FTP site. If you want to connect anonymously leave out the username and
password
cPassword
The user's password. Note: both user name and password are required if loging onto a secured FTP directory.
HTTP Properties:
lSecureLink
Flag that determines whether the link attempts to use HTTPS. Same as flag on HTTPConnect method.
nHTTPConnectType
This flag determines how an Internet Connection is established by WinInet. 1 – Direct HTTP, 3 – Proxy, 0 –
Preconfig. The default is 1 which means a plain HTTP connection will be used. If you're running through a Proxy
Server you have to use a value of 3 – this value will also work with plain HTTP connections, but is available only for
systems running Internet Explorer 4.0 or later. 0 – Uses Preconfigured settings from Internet Explorer and requires that
IE is installed on the machine.
nHTTPPort
The port used to establish a connection. This value is 0 by default which means the default ports are used for normal
and secure HTTP connections. If this value is set with a value other than 0, that port is used. Note this setting only
works with synchronous HTTPConnect/HTTPGetEx operation.
nConnectionTimeout
- Page 104 -
West Wind Web Connection
Class wwIPStuff
Timeout on an HTTP Connection prior to receiving/sending data (5) . This value is not respected by the current
versions of WinInet, but maybe in future versions of Windows updates.
cHTTPHeaders
Property that will receive the HTTP Header when calling HTTPGetEx. The header is filled prior to any data being
retrieved and an OnHTTPBufferUpdate event fires with 0 size and 0 chunk values that you can capture.
lHTTPCancelDownload
Used with HTTPGetEx() this flag can be set in the OnHTTPBufferUpdate() event handler to cancel the current HTTP
request.
nHTTPWorkBufferSize
The size of the buffer used by HTTPGetEx to retrieve data. HTTPGetEx reads data from the wire into a temporary
buffer. The size of this buffer determines how often control returns to the class code. Whenever a block completes
wwIPStuff calls OnHTTPBufferUpdate to let you know that more data has arrived.
Exposed Methods:
wwIPStuff::Init
The class constructor for the wwServer class sets up the basic options for the server class by specifying the program to execute
when a CGI request is received.
Note: Parameters have changed in version 1.65!
Syntax
Return
Example
Arguments
oIP=CREATE(“wwIPStuff”,cDLLPath)
Nothing
oIP=CREATE("wwIPStuff","c:\SysDLLS\")
CDLLPath
The path where the wwIPStuff.dll file resides. If left out either the current path or
Windows SYSTEM path is used. The path must be terminated with a trailing backslash.
wwIPStuff::GetDomainFromIp
This method retrieves a domain name from an IP address that is passed as a parameter. If the domain cannot be resolved either
because the machine is not connected to a DNS server or because the domain cannot be resolved the value returned is an empty
string (“”).
Syntax
Arguments
Return
Example
See Also
oIP.GetDomainFromIp(cIPAddress)
CIPAddress
The IP Address for to resolve. Must be in ‘dot’ notation with four sets of digits between 1 and 255.
Example: “111.111.111.120”
Domain Name or “” if the address could not be resolved
lcDomain=oIP.GetDomainFromIP(“205.162.195.252”)
wwIPStuff::GetIpFromDomain
- Page 105 -
West Wind Web Connection
Class wwIPStuff
wwIPStuff::GetIPFromDomain
This method retrieves an IP Address from a domain name that is passed as a parameter. If the IP address cannot be resolved
either because the machine is not connected to a DNS server or because the domain cannot be resolved the value returned is an
empty string (“”).
Syntax
Arguments
Return
Example
See Also
oIP.GetDomainFromIp(cDomain)
cDomain
The Domain name to resolve. Example: “www.west-wind.com”
Domain Name or “” if the address could not be resolved
lcDomain=oIP.GetIpFromDomain(“ftp.west-wind.com”)
wwIPStuff::GetDomainFromIp
wwIPStuff::SendMail
wwIPStuff::SendMailAsync
This method allows sending of SMTP mail. The message parameters can be set either via direct parameters passed or by using
the class properties selectively to set the message properties one at a time. SendMail does a blocking mail send that waits for
completion while SendMailAsync does not.
Syntax
Return
Arguments
oIP.SendMail(cMailServer, cSenderDisplayName,;
cSenderEmailAddress, cRepientList,
cCCList,cBCCList;
cSubject, cMessage, ;
cAttachment, cContentType)
.T. or .F.
SendMailAsync always returns .T.
CmailServer
The domain name or IP address of the mail server that will handle sending the message.
The mail server must be accessible via a TCP/IP connection at the designated IP address
and you must have a valid account on this mail server to successfully send email. IP
Addresses are in the format “205.111.111.2”.
CsenderDisplayName
The return address name that is displayed on the email message when received. This is the
display name only, not the email address. Note that most mail servers override this with
the name set up on the sending email account.
CsenderEmailAddress
The actual return address email address that is displayed on the email message. This
should be the address that you want replies to be sent to.
CRecipientList
The list of recipients represented as a comma delimited string. All recipients should be
entered as fully qualified email addresses.
CCCList
List of CCs represented as a comma delimited string. All recipients should be entered as
fully qualified email addresses.
cBCCList
List of blind CCs represented as a comma delimited string. All recipients should be
entered as fully qualified email addresses. Blind CCs are sent messages, but do not show
up on either the Recipient or CC display of an email message.
cSubject
- Page 106 -
West Wind Web Connection
Class wwIPStuff
The subject for the email message.
cMessage
The actual message text. This string can be of any length and can contain line breaks as
necessary.
cAttachment
You can attach a single file to the message. The attachment must point to a file on disk
with a full path.
CContentType
Remarks
The message's content type.
You can attach a single file to the message. The attachment must point to a file on disk
All parameters are optional and you are encouraged to use the class properties by the
same name as the parameters to set SMTP options for sending.
The SendMail method sends messages by waiting for completion and returning .T. or .F.
based on the result. You can check wwIPStuff::cErrorMsg for the error code and
description returned from the mail server.
The SendMailAsync method creates a new thread and lets the Send operation occur in the
background. The routine immediately exits and no result code is returned.
Example
oIp.SendMailAsync("mail.bozo.com", "Rick Strahl", ;
"rstrahl@west-wind.com",;
lcEmail,"rstrahl@west-wind.com", ;
"Web Connection generated E-Mail Sample",;
"Message Body Text goes here…")
wwIPStuff::FTPGetFile
This method retrieves a file from an FTP server. This method operates in blocking mode waiting for completion of the file
transfer before returning a result code. File properties can either be set with the wwIPStuff properties or by passing the
parameters explicitly.
Syntax
oIP.FTPGetFile(cFTPServer, cSource, cTarget,;
nBinary, cUsername, cPassword)
Return
0 on success – Win32 API error code otherwise
Arguments
cFTPServer
The domain name or IP address of the FTP server. The server must be accessible via a
TCP/IP connection at the designated IP address.
cSource
The file to download from the FTP server.
cTarget
The filename and path where you want to save the file to.
nBinary
(optional)
Determines whether the file is sent in Binary (default) or ASCII format. Values are 1 for
binary or 0 for ASCII.
cUsername (Optional)
If the FTP server requires a login a username and password must be specified. If the
username and password are left out anonymous login is requested on the FTP server.
cPassword (Optional)
see cUsername.
Remarks
FTPGetFile sends file in blocking mode waiting for transfer completion and a result code.
Example
oIp.FTPGetFile ("ftp.west-wind.com",;
"ww_web.zip",;
- Page 107 -
West Wind Web Connection
Class wwIPStuff
"c:\download\ww_web.zip")
wwIPStuff::FTPSendFile
This method sends a file to an FTP server. This method operates in blocking mode waiting for completion of the file transfer
before returning a result code. File properties can either be set with the wwIPStuff properties or by passing the parameters
explicitly.
Syntax
oIP.FTPSendFile(cFTPServer, cSource, cTarget,;
cUsername, cPassword)
Return
0 on success – Win32 API error code otherwise
Arguments
cFTPServer
The domain name or IP address of the FTP server. The server must be accessible via a
TCP/IP connection at the designated IP address.
cSource
The file to send to the FTP server.
cTarget
The filename and path where you want to save the file to on the FTP server. Note the path
must be FTP server relative using forward slashes.
cUsername (Optional)
If the FTP server requires a login a username and password must be specified. If the
username and password are left out anonymous login is requested on the FTP server.
cPassword (Optional)
see cUsername.
Remarks
Example
FTPGetFile sends file in blocking mode waiting for transfer completion and a result code.
oIp.FTPSendFile ("ftp.west-wind.com",;
"c:\uploads\ww_web.zip",;
"/uploads/ww_web.zip",;
"bozo",;
"looser")
wwIPStuff::FTPDeleteFile
This method deletes a file from an FTP server. File paths can be relative and files require the proper rights in order to be
deleted.
This method operates in blocking mode waiting for completion of the file transfer before returning a result code. File properties
can either be set with the wwIPStuff properties or by passing the parameters explicitly.
Syntax
oIP.FTPDeleteFile(cFTPServer, cFileToDelete,
cUsername, cPassword)
Return
0 on success – Win32 API error code otherwise
Arguments
cFTPServer
The domain name or IP address of the FTP server. The server must be accessible via a
TCP/IP connection at the designated IP address.
cFileToDelete
The file to delete from the FTP server. The file name may have a server relative path
(using server specific / slashes).
cUsername (Optional)
If the FTP server requires a login a username and password must be specified. If the
username and password are left out anonymous login is requested on the FTP server.
- Page 108 -
West Wind Web Connection
Class wwIPStuff
cPassword (Optional)
see cUsername.
Remarks
Example
FTPDeleteFile blocks until completion.
oIp.FTPDeleteFile ("ftp.west-wind.com",;
"/uploads/tempfile.zip",;
"bozo","looser")
wwIPStuff::aFTPDir
This method retrieves a list of files for a given path spec. Unlike the VFP ADIR() function this method only returns a 1D array
of filenames and does not support attributes explicitly. In other words, all files matching a filespec are returned.
Syntax
noIP.aFTPDir(@aFTPFiles, cFTPServer, cFileSpec,
cUsername, cPassword)
Return
Numbe of files matching filespec or 0 if not found.
Arguments
aFTPFiles
An array that receives the resulting list of files. This parameter must be passed by
reference.
cFTPServer
The domain name or IP address of the FTP server. The server must be accessible via a
TCP/IP connection at the designated IP address.
cFileSpec
The path to retrieve files for. The path may include wildcard characters for file names.
cUsername (Optional)
If the FTP server requires a login a username and password must be specified. If the
username and password are left out anonymous login is requested on the FTP server.
cPassword (Optional)
see cUsername.
Remarks
Example
FTPDeleteFile blocks until completion.
lnFiles = oIp.FTPDir("ftp.west-wind.com",;
"/uploads/*.*",;
"bozo","looser")
wwIPStuff::HTTPGet
This method retrieves an HTTP request such as an HTML document or file from a Web server. This method can be useful to
retrieve information from another Web server and use that information inside of your application. You could infact read
streaming data information by occasionally polling data in remote file and updating your VFP form with a call to this method
off a timer.
This method returns ASCII text only – HTML is uninterpreted and presented as text.
Syntax
Return
Arguments
oIP.HTTPGet (cUrl, nMaxBuffer)
Result string of HTTP Get or ""
cUrl
The full URL that is to be retrieved. The URL cannot be relative, it must be a full
including protocol, server and relative path.
nMaxBuffer (Optional – Default: 16384)
The size of the buffer that is allocated to retrieve the data. If you know you're retrieving a
- Page 109 -
West Wind Web Connection
Class wwIPStuff
large buffer increase the size here.
Remarks
Example
If the data returned exceeds the buffer the data is truncated. HTTPGet blocks until
completion.
lcText=oIp.HTTPGet("http://www.west-wind.com/")
wwIPStuff::HTTPConnect
This HTTP method initiates a low level HTTP request for use with HTTPGetEx by establishing an IP Session and connecting
to a target server.
Syntax
oIP.HTTPConnect (cDomainOrIPAddress,cUsername, cPassword,
lSecure)
Return
0 on success or a Win32 error code. If the value is non-zero check oIP.cErrorMsg.
Arguments
cDomainOrIPAddress
Specify the site you want to access: www.west-wind.com for example.
cUsername, cPasswords
If the link you're trying to access requires Authentication (Basic Authentication or NT
Challenge Response) specify the account info here. Optional
lSecure
If you're accessing a secure link on the server (HTTPS) set this paramater to .t. Optional
Remarks
Example
lnResult=oIp.HTTPConnect("www.west-wind.com")
wwIPStuff::HTTPGetEx
This method retrieves an HTTP request such as an HTML document or file from a Web server. You must first use
HTTPConnect() to open a connection to a server before using this method. This method supports POSTing data to the server
using the AddPostKey() method. Each value to POST must be added with this method first before sending the request.
This method returns ASCII text only – HTML is uninterpreted and presented as text.
Syntax
Return
Arguments
oIP.HTTPGetEx(cRequestPage, @cBuffer, @nSize, cHeaders)
0 on success or a Win32 error code. If the value is non-zero check oIP.cErrorMsg.
cRequestPage
The name of the page or link to retrieve on the server connected to with HTTPConnect.
@cBuffer
This is the buffer that receives the result from the server. The buffer's size must be passed
in the nSize parameter. The buffer is filled by the function call and the size returned in
nSize.
@nSize
This value specifies the input buffer size and also receives the result buffer size when the
request returns. If this value is set to 0 the buffer will be sized automatically to the size of
the request retrieved. Optional
cHeaders
This allows you to add special headers to a request, such as special content types,
Cookies, page expiration etc. Use Key: Value pairs (Content-Type: text/html). Optional
- Page 110 -
West Wind Web Connection
Class wwIPStuff
Remarks
Example
See Also
If the data returned exceeds the buffer the data is truncated. HTTPGetEx blocks until
completion.
loIP = CREATE("WWIPStuff")
loIP.HTTPConnect("www.west-wind.com")
lcBuffer = ""
lnSize = 0
loIP.HTTPGetEx("/default.asp ",;
@lcBUffer,@lnSize)
loIP.HTTPClose()
RETURN
wwIPStuff::OnHTTPBufferUpdate; wwIPStuff::cHTTPHeaders
wwIPStuff::OnHTTPBufferUpdate
The HTTPGetEx method fires events whenever the buffer is updated. This event is a notification method that you can override
to provide a status display. Note, that this will work effectively only if you pass HTTPGetEx a BufferSize of 0 which creates a
dynamically sized buffer with small chunks. If you pass a dedicated buffer size all data is retrieved in one chunk and you only
get one event notification.
This event also fires when HTTPGetEx retrieves the HTTP header prior to retrieving data. In this case both the nBytes and
nBufferReads parameters are passed in as 0.
Syntax
Return
Arguments
OnHTTPBufferUpdate(nBytesRead,nBufferReads,cBuffer)
Nothing. This method is an Event Method.
nBytesRead
Returns the total number of bytes that have been read so far by this request.
nBufferReads
Returns the number of reads that have been made so far.
0 - The HTTP Header for the request
> 0 – The actual block count
cBuffer
Returns the currently read buffer. If your output contains text or other content that can be
built piecemeal you may be able to show some of the data as it comes in without waiting
for completion of the download.
Remarks
Example
The first call to this method may take a little bit. WinInet pulls an internal buffer off the
wire prior to passing control to the user code to retrieve the buffer.
The frequency of calls to this method is determined by the nHTTPWorkBuffer value. The
bigger the buffer the fewer times this method is called.
In order to capture the OnHTTPBufferUpdate you have to either create a subclass (as the
example show below) or drop the wwIPStuff class onto a form visually and event event
code into the event.
DEFINE CLASS MyWWIPStuff as wwIPStuff
FUNCTION OnHTTPBufferUpdate
LPARAMETER lnBytesRead, lnChunk, lcBuffer
DO CASE
*** If this chunkcount is 0 it's HTTP Header
CASE lnChunk = 0
ACTI SCREEN
CLEAR
- Page 111 -
West Wind Web Connection
Class wwIPStuff
? "The HTTP Header is:"
? lcBuffer
&& or use THIS.cHTTPHeaders
*** If your request set the Content-Length header
*** You can retrieve the size of the content!
lnRequestSize = EXTRACT(lcBuffer,CHR(13)+CHR(10) +;
"Content-length: ",CHR(13))
CASE lnChunk > 1
THISFORM.edtBox.value = THISFORM.edtBox.Value + lcBuffer
CASE lnChunk = -1
&& Done
MessageBox("Download Complete")
ENDCASE
wait wind TRANS (lnBytes,"999,999,999") + " bytes" nowait
*** If you want partial UI operation use DoEvents
DoEvents
RETURN
ENDDEFINE
loIP = CREATE("MyWWIPStuff")
loIP.HTTPConnect("www.west-wind.com")
loIP.nHTTPWorkBufferSize = 2048 && Updates by this chunk size
lcBuffer = ""
lnSize = 0
loIP.HTTPGetEx("/default.asp ",;
@lcBUffer,@lnSize)
See Also
loIP.HTTPClose()
RETURN
wwIPStuff::nHTTPWorkBufferSize; wwIPStuff::cHTTPHeaders
wwIPStuff::HTTPGetExAsync
Like the above HTTPGetEx method except it can run asynchronously. The method returns immediately from the HTTP call,
while the HTTP call continues to run in the background. You can force the HTTP call to create a message file that contains the
actual result from the HTTPGetEx. It'll return either the complete HTTP result or an error message.
This method supports POSTing data to the server using the AddPostKey() method. Each value to POST must be added with
this method first before sending the request.
This method returns ASCII text only – HTML is uninterpreted and presented as text.
Syntax
Return
Arguments
oIP.HTTPGetExAsync(cPage, cResultFile, nResultSize)
nothing
cPage
The server relative page (default.asp or /wconnect/wc.dll?wwDemo~TestPage)
cResultFile
Optional. If you want the output of the request to be written to a file you can specify a file
here. Note you should use unique filenames if you're firing more than one HTTP request
asyncronously. By default no file is created.
nResultSize
Optional. Allows you to specify the size of the result buffer that determines how much
data is pulled for the HTTP request. This value cannot be 0 – 0 will automatically resize
- Page 112 -
West Wind Web Connection
Class wwIPStuff
the buffer to 256 bytes. The buffer is sized to this value and written to disk if cResultFile
is specified. Otherwise the buffer is ignored.
Default: 256
Remarks
You can set the cUsername and cPassword properties and lSecureLink properties on
HTTPConnect to set security options on the request. You can use AddPostKey() to add
POST variables to the request.
It's possible to build an async event driven application using a timer and this method. See
the wwHTTPAsync object in wwipstuff.vcx.
Requires wwIPStuff.dll. Make sure you don't quit VFP while a request is still running in
the background or VFP will crash!
Example
*** Demonstrate Async operation with cancel dialog
o = CREATE("wwIPSTUFF")
o.HTTPConnect("www.west-wind.com")
o.AddPostKey("Test","Rick")
o.nTimeout = 20 && in seconds
plExit = .F.
DO CancelForm
&& Modeless cancel form – sets plExit
o.HTTPGetExAsync("/webconnection.asp",
"c:\temp\westwind.htm", 20000)
DO WHILE !FILE("c:\temp\westwind.htm") AND !plExit
DoEvents
ENDDO
See Also
IF FILE("c:\temp\westwind.htm")
lcFileText = File2Var("c:\temp\westwind.htm")
ACTI SCREEN
? lcFileText
ELSE
wait window "Operation cancelled…
ENDIF
wwHTTPAsync Control Class
wwIPStuff::AddPostKey
This method is used to add any information that needs to be POSTed to a Web server. You can post form variables or any data
you see fit including entire files. The data is URLEncoded by this method and automatically picked up by the HTTPGetEx
method when called.
Syntax
Return
Arguments
oIP.AddPostKey(cKey, cValue)
nothing
cKey
The key or identifier for the data to be posted. If filling HTML forms the key will be the
NAME of the form variable.
cValue
The actual value to send to the server. This value can be any size and can contain binary
data.
Remarks
Example
The data in cValue is URLEncoded once received. The encoding process can be slow on
large value fields.
Ip.AddPostKey("txtCompany","West Wind Technologies")
- Page 113 -
West Wind Web Connection
Class wwIPStuff
wwIPStuff::HTTPClose
Closes an HTTP request opened with HTTPConnect.
Syntax
oIP.HTTPClose()
Return
nothing
Arguments
none
Remarks
Example
oIP.HTTPClose()
wwIPStuff::EncodeDBF
Converts a file or DBF or DBF + Memo file into a single text string that you can easily send down the connection with
loHTML.Send(). wwIPStuff::DecodeDBF() can be used on the receiving end to retrieve the string back into a file.
Syntax
Return
Arguments
oIP.EncodeDBF (cFileName, lHasMemo)
binary string that contains a header plus the binary data of the file
cFilename
The filename to encode
lHasMemo
If this flag is set the memo file is automatically added to the encoded data to allow simple
packaging of the file.
Remarks
Example
Header contains ID, filename and length of the binary data
SELECT * FROM TT_CUST WHERE &lcFilter INTO TABLE Texport
lcFileText = oIp.EncodeDBF("Texport.dbf",.T.)
*** Send Binary data to client
loHTML.Send(lcFileText)
wwIPStuff::DecodeDBF
Converts a file or DBF or DBF + Memo file into a single text string that you can easily send down the connection with
loHTML.Send(). wwIPStuff::DecodeDBF() can be used on the receiving end to retrieve the string back into a file.
Syntax
Return
Arguments
oIP.DecodeDBF (cBuffer, cFileName)
.T. or .F.
cBuffer
The text string that contains the file plus header as created by EncodeDBF()
cFileName
The full filename to create. If the encoded file includes a memo simply specify the .DBF
file – the memo is automatically created.
Remarks
Example
The file to create must not be open or the file cannot be created.
lcFileText = oIP.HTTPGet("http://localhost/wc.wc?http~CustList")
IF oIp.DecodeDBF(lcFileText,"TcustList.dbf")
SELE TT_Cust
APPEND FROM TcustList
- Page 114 -
West Wind Web Connection
Class wwIPStuff
ENDIF
Low Level HTTP Methods
*** Connect to server once
o.HTTPConnect("www.microsoft.com")
*** Presize the buffers!
lcText=SPACE(16384)
lnText=LEN(lcText)
lcHeader=SPACE(2048)
lnHeader=LEN(lcHeader)
*** Read many times
SET MEMOWIDTH to 256
o.HTTPGetEx("/",@lcText,@lnText)
? lcText
&& Contains the actual HTML of the page
o.HTTPGetHeader("/",@lcHeader,@lnHeader)
? lcHeader
o.HTTPClose()
************************************************************************
* wwIPStuff :: HTTPGetHeader
*********************************
*** Function: Retrieves just the HTTP header of a page request.
***
Assume: Must call HTTPConnect/HTTPClose to manage connection
***
to Server
***
Pass: tcPage
The Server relative page to view
***
tcHeader Buffer to receive headers (by reference)
***
tnSize
Size of the Buffer (by Reference)
***
Return: Win32API Error Code
************************************************************************
wwIPStuff::RasDial
Dials an installed Remote Access Session entry.
Syntax
Return
Arguments
oIP.RasDial(cRasEntry)
.T. or. F.
cRasEntry
Name of a RAS connection as set up in Dial Up Networking under Window/NT. You can
find the names in your RAS phonebook.
Remarks
On failure a dialog box is displayed that describes the error.
A connection can only be closed by using the same handle that opened it. wwIPStuff
stores the handle as a class property, so in order to close the connection you need to keep
the instance that dialed open until you close the connection.
Example
oIP.RasDial("Gorge Net")
- Page 115 -
West Wind Web Connection
Class wwIPStuff
wwIPStuff::RasHangup
Hangs up a Ras Connection based on a handle created with RasDial.
Syntax
oIP.RasHangup()
Return
.T. or. F.
Arguments
none
Remarks
A connection can only be closed by using the same handle that opened it. wwIPStuff
stores the handle as a class property, so in order to close the connection you need to keep
the instance that dialed open until you close the connection.
Example
oIP.RasHangup()
wwIPStuff::GetSystemErrorMsg
This method converts the Win32API error number of the last operation to a string error message.
Syntax
Return
Arguments
oIP.GetSystemErrorMsg([nErrorNo,lAPIError])
Result error string or ""
nEerrorNo
The error to return a string for. If not specified the last error generated by a WinInet call is
retrieved. Optional
lAPIError
By default this method returns WinInet error codes. If this flag is set to .t. a Win32API
error code can be retrieved. Optional
Remarks
Example
Based on the value of the nError property which gets set on error conditions. You should
check this flag for a non-zero value before calling this method.
wait window oIp.GetSystemErrorMsg(6)
- Page 116 -
West Wind Web Connection
Class wwFTP
Class wwFTP
Parent Class: wwIPStuff
Source: wwIPStuff.vcx
For documentation please see the wconnect.chm HTML Help file for details.
- Page 117 -
West Wind Web Connection
Class wwHTTPAsync
Class wwHTTPAsync
Parent Class: Timer
Source: wwIPStuff.vcx
The wwHTTPAsync class implements asynchronous HTTP retrieval that allows you to run HTTP requests while continuing on
with your application. When the request is complete the NavigateComplete event is fired to let you know that the request has
finished processing. The request result is returned to you in form of a string.
How it works
This class is implemented using a timer and the wwIPStuff::wwHTTPGetExAsync method which creates an output file when
the request is complete. The timer class polls for the completion file and when found fires the NavigateComplete method which
you can attach code to. The class handles file cleanup when the request file is read. In addition the DLL also tries to delete the
result file if it sticks around for 20 seconds after completion. IOW, if you decide to cancel a download cleanup will still
commence. As with any Aysnc function, be careful not to quit Visual FoxPro while a background request is still running.
Each request is handled on a new thread. A new thread is fired in the DLL, which then runs the actual HTTP request link and
downloads the data to file. If an error occurs an error message is downloaded. Error messages start with the text Error: followed
by the actual error message.
To use the control simply drop the wwHTTPAsync control onto a form and set the appropriate properties either in the property
window or programmatically.
The following example demonstrates how you might use the control. Drop the control onto a form. You can add the following
code to a button event, which starts the Async request.
loIP = THISFORM.oAsyncDownload
loIP.nTimeout = 300
loIP.cServer = www.west-wind.com
loIP.cLink = "/default.asp "
loIP.nBuffersize = 500000
THISFORM.oAsyncDownload.StartRequest()
Once started the control will run the Async request while leaving your application active and operational. It will then fire the
OnDownloadComplete event, which you can override on the control:
* oAsyncObject::OnDownloadComplete
LPARAMETER lcRetrievedData
*** Take the retrieved data
File2Var("c:\temp\download.htm",lcRetrievedData)
*** Take the text and display it in a Web Browser control
THISFORM.oBrowser.Navigate("file://c:\temp\download.htm")
wait window "Download Complete!"
- Page 118 -
West Wind Web Connection
Class wwHTTPAsync
Properties and Methods
Property
What it does
cUsername
The name of the server to contact. Example: www.west-wind.com or
111.111.111.111.
The server relative link to access. Example: / or /default.asp or
/wconnect/wc.dll?wwDemo~TestPage~&UID=123
The buffer that receives the output from the request. This value can also be
retrieved directly from the NavigateComplete() method as a parameter.
The max size of the buffer to be returned. If the buffer is greater than the size
the buffer is truncated. 0 is not allowed as in wwIPStuff object. Default: 64k
Username for Authentication Optional
cPassword
Password for Authentication
lSecure
Whether to use SSL
lBusy
Check this to see whether a request is in process.
nTimeout
This value determines how long the request is waited for in seconds. If this
timeout value is exceeded the request is terminated with a timeout error
message.
An object reference to the actual wwIPStuff object that does all of the work.
You can set some of the non-exposed properties on this object directly.
cServer
cLink
cResultBuffer
nBufferSize
oIP
Optional
Method
StartRequest
NavigateComplete
CancelRequest
AddPostKey
Optional
What it does
Starts the request. This method returns immediately and sets the lBusy flag to
indicate busy status. No Parameters
This method is called when the request is complete. This method takes two
parameters:
lcResultBuffer
The full HTTP result of the request. If an error occurs this parameter will
contain an error message in the format Error: Error Message.
llError
Set to .T. if there was an error during a request.
Cancels the current request and resets the control. Cancel request is also
called internally if the request times out or an error occurs.
Allows you to add Post key value pairs to the request to allow sending data to
the Web server. See wwIPStuff::PostKey for more details.
- Page 119 -
West Wind Web Connection
Class wwHTTPData & wwHTTPFile
Class wwHTTPData & wwHTTPFile
Parent Class: aHTTPData
Source: wwIPStuff.vcx
This class uses the wwIPStuff class to provide a generic data transfer and query mechanism for Visual FoxPro clients accessing
a Web Connection back end server. This client server implementation supplies methods for the client code and the server side
code that need to run for communication over HTTP to occur. Web Connection also includes a generic wwProcess module
(wwHTTPData) that handles data transfers the basic data transfers generically. This wwProcess subclass will be described here
as well.
How it works
The primary function of this class is to allow a client to run a SQL query or command on the server and return the data back to
the client. When running a query from the client side you basically provide a SQL string that will be executed on the server. In
addition you can specify the result cursor name, a MaxBuffer size, secure connection over SSL and wether the file is zipped
(this feature requires you own a copy of DynaZip and have the DZ DLLs installed in your SYSTEM directory). In addition, you
can specify a user logon and password which can be matched to a user set up on the Web server. All of this is accomplished by
setting a few properties on the object, most of which are optional. When all is set up you simply call the Execute() method to
run your SQL Query.
The server responds to the request by instantiating the same class and using the S_Execute() method to unparse your request.
The SQL Statement is run and the result is returned back via HTTP to the client. The server sets various error messages if the
either the query or any part of the request fails along the way.
When the file reaches the client it decodes the downloaded file and creates a cursor from it, which is handed back to you to use.
All cleanup is performed for you, so this operation is not a lot different from running a native Visual FoxPro query.
The Client Side
The client side of this object is responsible for collecting the data necessary to allow the server to check security, decide
whether Zipping is used and what query to execute. The client side VFP code looks like this:
*** Demonstrate running query over the Web
o=CREATE("wwHTTPData")
o.cServername = "localhost"
* o.cHTTPLink= "/wconnect/wc.dll?wwHTTPData~Execute"
o.nMaxBufferSize = 100000
o.cUsername = "rstrahl"
o.cPassword = "mypassword"
o.lIsZipped = .T.
&& Requires DynaZip libraries
o.cSQL = "SELECT * FROM Tt_cust"
o.Execute()
&& Default value
IF o.lError
? o.cSQL
? o.cErrorMsg
RETUR
ENDIF
BROWSE
*** You can also do inserts and Updates like this
o.cSQL = [INSERT INTO Timebill (custno) VALUES ("123123")]
o.Execute()
- Page 120 -
West Wind Web Connection
Class wwHTTPData & wwHTTPFile
IF o.lError
? o.cSQL
? o.cErrorMsg
ENDIF
Note that most of these parameters are optional. The only required ones are the query and the server name. The HTTPLink is
actually the default, but if you build your own handler you will have to change this value to point at your request instead
(wwHTTPData is not enabled by default for security reasons – you can turn it on in wcDemoServer::Process() inside of the
CASE statement in wcMain.prg). The username and password must match what you have set up on your server – again this
depends on whether you check for this stuff or not, but the default link uses a username stored in wcmain.ini to check for a
validated account (either specific or generic ("Any") or no security ("")). When all is set, specify a SQL statement and call the
Execute() method to send the query.
If all goes well you'll receive a result cursor in the case when you ran a SELECT or CREATE TABLE command. Otherwise no
cursor is returned. You should check the lError flag after each request to make sure that request succeeded. If an error occurred
you can check the cErrorMsg property for a reason the request failed.
The Server Side
A Web Connection server can access the same object used on the client side to send the data. The server has to deal with the
security validation and then uses the S_Execute() method to actually run the query and send the data back to the client:
************************************************************************
* wwHTTPDataProcess :: Execute
*********************************
*** Function: Generic Execute request handler routine that can
***
be used to pull data from the wire.
***
Typically called from a wwHTTPData client in VFP
************************************************************************
FUNCTION Execute
*** Authentication is optional – here we pull the authorized user from
*** wcmain.ini in the [wwHTTPData] section
*** Supported values in the INI - Any
- Any Authorized user
***
Username
- A specific user
***
""
- None - no Authentication
lcAuthUser = THIS.GetAppIniVar("AuthUser","wwHTTPData")
*** Create Data Object and call Server Side Execute method (wrapper for Process Method)
loData = CREATE("wwHTTPData")
loData.S_Execute(THIS,lcAuthUser)
ENDFUNC
* wwHTTPDataProcess :: Execute
This is a standard Web Connection process class subclass. In fact you can find this generic handler in wwHTTPData.prg. If you
want a generic query engine you can simply enable this request processor (set the CASE "WWHTTPDATA" in wcMain's
CASE structure in the Process() method). Or, if you would like to customize operation you can implement this type of request
in any of your own request handlers. The S_Execute() method creates its own HTML output so all you really have to do is call
the method for actually running the query.
3 lines of code! How much simpler can you get?
You can add pre and post processing code, but you may not add any additional HTML output as the S_Execute() method
communicates with the matching Execute() call on the client side.
- Page 121 -
West Wind Web Connection
Class wwHTTPData & wwHTTPFile
Security
Security is a huge issue with this setup. You're basically opening up much of FoxPro for remote access. For this reason think
about security issues very, very carefully. Since the interface described here is generic (although you can simply change the
names of the generic metods on the server to get around this simple problem) anybody who knows the link can potentially
access your data - not a good idea!
Basic Authentication
To get around this Web Connection implements security for these methods via Basic Authentication and an option to specify
which user account is allowed access. The server determines the account and the client application (note the application, not the
user) must specify the account and password explicitly. Since this information will be hidden inside of your compiled
information it provides protection from somebody simply accessing the data link without authorization.
For example, you can set up the server so that it will allow only a certain user account to access this link. As part of the request
you create, you specify the AuthUser account as part of the call to S_Execute(). The method will the validate the user and allow
access to only that particular user. Alternately you can set cAuthuser to Any validated account or a blank string in which case
no checking is performed at all. The latter option is not recommended in any situation and the former only if you've cleared the
standard NT accounts like Guest that start out with generic passwords.
To make this work the client side call has specify a username and password. This is passed to the server via the HTTP Basic
Authentication scheme just like on a Web page asking for Authorization. For an application you'd probably want to set up a
special user account on the server that you use for all queries or file transfers performed. The username and password is then
compiled into your client application and invisible to prying eyes.
Secure Sockets Layer (SSL)
Data that travels over the wire can be encrypted with SSL if you have an SSL certificate by specifying the lSecure flag. This
will protect your data from sniffers and protocol analyzers.
Uploading Files via HTTP with wwHTTPFile
You can also use the wwHTTPFile class to upload files from a VFP application to a Web Connection Server. The process here
is similar to the query routines, but instead of retrieving information only a file is uploaded to the server. The file can be
automatically zipped (if DynaZip is installed) . Here's the code to upload a file to the server:
o=CREATE("wwHTTPFile")
o.cServername = "localhost"
* o.cHTTPLink = "/wconnect/wc.dll?wwHTTPData~SendFile" && Default Value
o.nMaxBufferSize = 100000
o.cUsername = "rstrahl"
o.cPassword = "mypassword"
o.lIsZipped = .T.
o.cSourceFile = "c:\wwapps\wc2\wcmain.prg"
o.cTargetFile = "c:\temp\wcmain.prg " && Only works if server allows full path
o.SendFile()
IF o.lError
? o.cErrorMsg
RETURN
ENDIF
RETURN
Note that the cTargetFile option is dependent on how the server is set up. If the server has the cForceSavePath property set files
are automatically forced into the directory specified there and the cTargetFile value specified here is ignored. It's recommended
that you do this and set the path to a work/temporary directory so that there's no chance of the client doing something like:
o.cTargetFile = c:\winnt\system32\explorer.exe
- Page 122 -
West Wind Web Connection
Class wwHTTPData & wwHTTPFile
Property/Method
What it does
wwHTTPData
cSQLCursor
SQL Statement to be sent to the server. This can be SELECT, INSERT,
UPDATE and CREATE TABLE.
The name of the result cursor. Default: THTTPQuery
cSourceFile
The Source File to send to the server. Required
cTargetFile
The file to copy to. If not specified the source file is used and sent to the
current server directory. If the server has defined a cForcedSavePath value
the path is stripped from the filename. Default: Blank
This server side method is used on the server side to determine whether the
client is allowed to specify a full or relative file path. If this property is not
empty any path specified by the client will be stripped and replaced with the
path specified in this property. Default: Blank
cSQL
wwHTTPFile
cForcedSavePath
Generic aHTTPData (applies to both above classes)
cServerName
Name of the Web Server to access.
cHTTPLink
cUsername/cPassword
Server relative link to the Web Connection request that fires. Defaults:
/wconnect/wc.dll?wwHTTPData~Execute for wwHTTPData
/wconnect/wc.dll?wwHTTPFile~SendFile for wwHTTPFile
Username and Password used for Authentication on the server.
lSecure
Determines whether the request uses SSL
lIsZipped
lError
Determines whether the request zips the query result or file to send. Requires
DynaZip libraries (third party).
Maximum size of the data to transfer over the wire. This is a safety setting
that makes sure huge data sets are not sent. Specify 0 to allow any size data.
Set to .t. if an error occurs.
cErrorMsg
Holds an error message if lError is .T.
nMaxBufferSize
wwHTTPData::Execute
This method is responsible for actually calling the remote server and causing it to run the query.
Syntax
Return
Arguments
oHTTPData.Execute(cSQLStatement)
.T. or .F.
cSQLStatement
Optionally provide a SQL statement here. The statement passed here overrides the cSQL
property setting. Optional
Remarks
Make sure all properties are set prior to calling this method.
Example
o.cSQL = "SELECT * FROM Tt_cust"
o.Execute()
IF o.lError
? o.cSQL
? o.cErrorMsg
RETURN
ENDIF
- Page 123 -
West Wind Web Connection
Class wwHTTPData & wwHTTPFile
BROWSE
wwHTTPData::S_Execute
Server Side Execute method that encapsulates a full Web Connection request to handle running the specified query and
returning the resulting result cursor back to the calling client.
Syntax
Return
Arguments
oHTTPData.S_Execute(oProcess,cAuthUser)
.T. or .F.
oProcess
Web Connection wwProcess object (pass as THIS).
cAuthUser
User account that must be sent and authenticated by the client. The client sends username
and password and the request validates these through the Web Server with Basic
Authentication. Maybe: "Any", "Username" or "", where username is a valid NT user
account. Note this value must match the exact Authenticated Username. Use the Web
Connection Demo's Authentication Demo to see what full Authentication names are for a
given account.
Remarks
Example
Method call is fully self contained Web Connection request. You cannot add any HTML
output in your request code!
Function MyWCRequestMethod
lcAuthUser = THIS.GetAppIniVar("AuthUser","wwHTTPData")
* lcAuthUser = "rstrahl"
loData = CREATE("wwHTTPData")
loData.S_Execute(THIS,lcAuthUser)
RETURN
wwHTTPFile::SendFile
Generic SendFile method takes the specified file and encodes it, zips it if specified and sends the file to the server via HTTP
request.
Syntax
Return
Arguments
oHTTPFile.SendFile()
.T. or .F.
oProcess
Web Connection wwProcess object (pass as THIS).
cAuthUser
User account that must be sent and authenticated by the client. The client sends username
and password and the request validates these through the Web Server with Basic
Authentication. Maybe: "Any", "Username" or "", where username is a valid NT user
account. Note this value must match the exact Authenticated Username. Use the Web
Connection Demo's Authentication Demo to see what full Authentication names are for a
given account.
Remarks
Example
Make sure all properties are set prior to calling this method.
o.cServername = "localhost"
o.cSourceFile = "c:\wwapps\wc2\wcmain.prg"
o.cTargetFile = "c:\temp\wcmain.prg"
- Page 124 -
West Wind Web Connection
Class wwHTTPData & wwHTTPFile
o.SendFile()
IF o.lError
? o.cErrorMsg
RETURN
ENDIF
wwHTTPFile::S_SendFile
Server Side SendFile method accepts the file sent by the client side SendFile. The file is decoded and stored depending on the
cForcedSavePath directory setting or the file path provided by the client
Syntax
oHTTPFile.S_SendFile(oProcess,cAuthUser)
Return
.T. or .F.
Arguments
o
Remarks
Method call is fully self contained Web Connection request. You cannot add any HTML
output in your request code!
Example
Function MyWCRequestMethod
lcAuthUser = THIS.GetAppIniVar("AuthUser","wwHTTPData")
loFile = CREATE("wwHTTPFile")
*** Always force file to an Uploads directory
loFile.cForcedSavePath = SYS(5) + CURDIR() + "Uploads\"
loFile.S_SendFile(THIS,lcAuthUser)
RETURN
- Page 125 -
Class wwPDF – Adobe Acrobat File Creation
West Wind Web Connection
Class wwPDF – Adobe Acrobat File Creation
Enterprise Edition only
Source: wwPDF.prg
One big issue when working with Web Applications is the inability to print efficiently from a Web browser. The problem is that
the Web Browser has no understanding of the data on the page and hence breaks text without concern for data groups and
general layout. It's also difficult to create complex reports that display well in HTML.
It's much easier to to do this with the VFP report writer. One way to create a report for viewing over the Web is to print it to an
Adobe Acrobat file, which can be viewed on the client side with the Acrobat Reader. The resulting document is rendered
exactly like the actual report preserving the rich text formatting (fonts, bold/italic, colors, alignment etc) and providing a
searchable, editable (with the proper Adobe software) document that can be printed from the viewer.
The viewer is freely downloadable from the Adobe Web site (www.adobe.com). Adobe also sells software that allows creation
of Acrobat documents and one of the features of this package is a printer driver that allows converting of standard printer output
to an Acrobat document. Unfortunately, this printer driver is not very well behaved and the implementation for providing
programmatic access is very badly implemented. It can be done, but beware of some of the issues. The following class
encapsulates the process into an easily accessible class.
How to use it:
The class is easy to use once the Adobe software is configured properly (see next section). The class provides easy methods for
calling reports and printing them to a PDF file or creating QuickReports on the fly.
SET PROCEDURE TO WWAPI ADDITIVE
SET PROCEDURE TO WWPDF ADDITIVE
oPDF=CREATE("wwPDF","WINNT")
* If the defaults don't work locate the INI file
* manually and then pass the path
* oPDF.SetAcrobateIniFile("c:\winnt\system32\WINNT\SYSTEM\spool\DRIVERS\W32X86\3\__pdf.ini")
*** Set Locking or Print Delay Timeout
oPDF.nTimeout = 20 && Seconds (default is 10)
SELECT * from TT_CUST INTO CURSOR TQuery
llResult = oPDF.PrintReport("Report.frx","c:\temp\MyPdf.pdf","FOR Customer = '"+lcCust+"'")
*** You can also print the PDFFile to a string
*** for sending back as HTTP result output
* lcFileText = oPDF.PrintReportToString("Report.frx")
SELECT Company, Careof, Phone
from TT_Cust into cursor Tquery
*** You can also create quick reports without an FRX
llResult = oPDF.QuickReport("c:\temp\MyPDF.pdf")
- Page 126 -
Class wwPDF – Adobe Acrobat File Creation
West Wind Web Connection
Adobe PDFWriter Configuration
This class works by dynamically switching the printer driver and updating the PDF configuration file. The class requires that
you have Adobe Acrobat and the PDFWriter software installed. This class has been tested with version 3.02 of the Adobe
PDFWriter driver. Make sure the PDFWriter printer driver is installed and that the printer driver has its port set to LPT1 and
not FILE. File will force a file name popup from the printer driver in addition to the PDF driver file requirements.
Find C:\WINNT\system32\spool\DRIVERS\W32X86\2\__pdf.ini. Note this file may exist in other places - just the W32X86
directory or any numbered subdir thereof. 2 seems to be the space where it's expected. There may be multiple copies of this file
- the right one should have a bunch of flags in it and should show the last document you printed with a date and whatever you
typed for the title.
This class will look for the file:


Win95: WINDOWS\Win.ini
WinNT: WINNT\SYSTEM\spool\DRIVERS\W32X86\2\__pdf.ini
Add the following two settings:
PDFFilename=c:\temp\__wwPdf.pdf
bDocInfo=0
(where \temp\ points at your temp directory) and reboot if you've printed to the driver during the current logon.
Using this class will make permanent changes to the way Acrobat prints. In particular it will always print to the file you specify
or the default (TEMP\__wwpdf.pdf). To change this you have delete these keys and then reboot.
These settings surpress all dialog boxes and always print to the file specified. Note that you can't change this on the fly - you
have to reboot after you make a change here. Actually, it looks like you can change the values once the keys exist, but it's not
very consistent.
Note:
The Acrobat driver can only print one report to the PDFWriter at a time on a given machine. The
class provides a semaphor locking scheme that queues reports, but be aware that this can cause
serious performance issues if you're printing lots of reports while running multiple Web Connection
instances
************************************************************************
* wwPDF :: SetAcrobatIniFile
*********************************
*** Function: Sets the path to the PDFWRiter configuration file.
***
This method is also called from the Init of the class.
***
***
Default Paths by Acrobat:
***
Win95: WINDOWS\Win.ini
***
WinNT: WINNT\SYSTEM\spool\DRIVERS\W32X86\2\__pdf.ini
***
***
Assume: THIS IS THE MOST IMPORTANT SETTING! MAKE SURE YOU MATCH
***
THIS TO YOUR INI FILE. START WITH THE DEFAULT SETTINGS
***
BY PLATFORM AND IF THAT FAILS TRY THE FULL INI FILE PATH.
***
NOTE: This setting will permanently change your Acrobat
***
configuration.
***
***
Pass: lcAcrobatIniFile "WINNT","WIN95" or
***
full path to Acrobat __PDF.INI (NT)
***
or Win.ini (Win95)
***
llForceInteractive to bring up dialogs
***
Return: .T. or .F.
- Page 127 -
Class wwPDF – Adobe Acrobat File Creation
West Wind Web Connection
************************************************************************
************************************************************************
* wwPDF :: PrintReport
*********************************
*** Function: The worker function. This method actually goes out
***
sets the printer and prints the report. Use this
***
instead of a REPORT form command.
***
Assume:
***
Pass: lcReport
Name of the FRX Report to run
***
lcOutputFile Filename to print the PDF output to
***
lcExtraReportClauses - Any extra tags like FOR, WHEN etc.
***
Return: .T. or .F.
************************************************************************
************************************************************************
* wwPDF :: SetLandscapeMode
*********************************
*** Function: Sets or unsets landscape mode
***
Pass: llPortrait - Optional Pass .F. only if you want to go
***
back to portrait
***
Return: nothing
************************************************************************
************************************************************************
* wwPDF :: PrintReportToString
*********************************
*** Function: Prints a report to string
***
Pass: lcReport
Name of the FRX Report to run
***
lcOutputFile Filename to print the PDF output to
***
lcExtraReportClauses - Any extra tags like FOR, WHEN etc.
***
Return: PDF file as a string or "" on failure
************************************************************************
************************************************************************
* wwPDF :: QuickReport
*********************************
*** Function: Prints a report from a cursor without an FRX
***
courtesy of Randy Pearson, Cycla Corp
***
Pass: lcOutputFile Filename to print the PDF output to
***
lcExtraReportClauses - Any extra tags like FOR, WHEN etc.
***
Return: .T. or .F.
************************************************************************
************************************************************************
* wwPDF :: QuickReportToString
*********************************
*** Function: Prints a PDF report to string without an FRX
***
courtesy of Randy Pearson, Cycla Corp
***
Pass: lcExtraReportClauses - Any extra tags like FOR, WHEN etc.
***
Return: PDF file as a string or '' on failure
************************************************************************
- Page 128 -
West Wind Web Connection
Support Classes
Support Classes
In addition to the main Web related classes described above Web Connection also includes a set of support classes and
functions in WWUTILS.PRG.
Class wwAPI
Contained in: wwapi.prg
The API Class provides various Windows API based interfaces used in Web Connection for accessing the registry, INI files,
getting system paths, setting thread priority, retrieving error messages and a few other functions.
************************************************************************
* wwAPI :: GetSystemErrorMsg
*********************************
*** Function: Returns the Message text for a Win32API error code.
***
Pass: lnErrorNo - WIN32 Error Code
***
Return: Error Message or "" if not found
************************************************************************
************************************************************************
* wwAPI :: MessageBeep
**********************
*** Function: MessageBeep API call runs system sounds
***
Pass: lnSound
Uses FoxPro.h MB_ICONxxxxx values
***
Return: nothing
************************************************************************
************************************************************************
* wwAPI :: ReadRegistryString
*********************************
*** Function: Reads a string value from the registry.
***
Pass: tnHKEY
- HKEY value (in CGIServ.h)
***
tcSubkey - The Registry subkey value
***
tcEntry
- The actual Key to retrieve
***
Return: Registry String or .NULL. on not found
************************************************************************
************************************************************************
* wwAPI :: EnumRegistryKey
**************************
*** Function: Returns a registry key name based on an index
***
Allows enumeration of keys in a FOR loop. If key
***
is empty end of list is reached.
***
Pass: tnHKey
HKEY_ root key
***
tcSubkey Subkey string
***
tnIndex
Index of key name to get (0 based)
***
Return: "" on error - Key name otherwise
************************************************************************
************************************************************************
* Registry :: WriteRegistryString
*********************************
*** Function: Writes a string value to the registry.
***
If the value doesn't exist it's created. If the key
***
doesn't exist it is also created, but this will only
***
succeed if it's the last key on the hive.
***
Pass: tnHKEY
- HKEY value (in WCONNECT.h)
- Page 129 -
West Wind Web Connection
Support Classes
***
tcSubkey - The Registry subkey value
***
tcEntry
- The actual Key to write to
***
tcValue
- Value to write or .NULL. to delete key
***
tlCreate - Create if it doesn't exist
***
Assume: Use with extreme caution!!! Blowing your registry can
***
hose your system!
***
Return: .T. or .NULL. on error
************************************************************************
************************************************************************
FUNCTION GetProfileString
*************************
*** Function: Read Profile String information from a given
***
text file using Windows INI formatting conventions
***
Pass: pcFileName
Name of INI file
***
pcSection
[Section] in the INI file ("Drivers")
***
pcEntry
Entry to retrieve ("Wave")
***
If this value is a null string
***
all values for the section are
***
retrieved seperated by CHR(13)s
***
Return: Value(s) or .NULL. if not found
************************************************************************
************************************************************************
* wwAPI :: WriteProfileString
*********************************
*** Function: Writes a value back to an INI file
***
Pass: pcFileName
Name of the file to write to
***
pcSection
Profile Section
***
pcKey
The key to write to
***
pcValue
The value to write
***
Return: .T. or .F.
************************************************************************
************************************************************************
* wwAPI :: GetProfileSections
*********************************
*** Function: Retrieves all sections of an INI File
***
Pass: @laSections
Empty array to receive sections
***
lcIniFile
Name of the INI file
***
lnBufSize
Size of result buffer (optional)
***
Return: Count of Sections
************************************************************************
************************************************************************
* wwAPI :: GetTempPath
***********************
*** Function: Returns the OS temporary files path
***
Return: Temp file path with trailing "\"
************************************************************************
************************************************************************
* wwAPI :: GetEXEFileName
*********************************
*** Function: Returns the Module name of the EXE file that started
***
the current application. Unlike Application.Filename
***
this function correctly returns the name of the EXE file
***
for Automation servers too!
***
Return: Filename or "" (VFP.EXE is returned in Dev Version)
************************************************************************
************************************************************************
* wwAPI :: GetComputerName
*********************************
*** Function: Returns the name of the current machine
***
Return: Name of the computer
- Page 130 -
West Wind Web Connection
Support Classes
************************************************************************
************************************************************************
* wwAPI :: GetSystemDir
*********************************
*** Function: Returns the Windows System directory path
***
Return: Windows System directory or "" if failed
************************************************************************
************************************************************************
* WinApi :: ShellExecute
*********************************
*** Function: Opens a file in the application that it's
***
associated with.
***
Pass: lcFileName - Name of the file to open
***
lcWorkDir
- Working directory
***
lcOperation ***
Return: 2 - Bad Association (invalid URL)
***
31 - No application association
***
29 - Failure to load application
***
30 - Application is busy
***
***
Values over 32 indicate success
***
and return an instance handle for
***
the application started (the browser)
************************************************************************
************************************************************************
* wwAPI :: GetCurrentThread
*********************************
*** Function: Returns handle to the current Process/Thread
***
Return: Process Handle or 0
************************************************************************
************************************************************************
* wwAPI :: GetThreadPriority
*********************************
*** Function: Gets the current Priority setting of the thread.
***
Use to save and reset priority when bumping it up.
***
Pass: tnThreadHandle
************************************************************************
************************************************************************
* wwAPI :: SetThreadPriority
*********************************
*** Function: Sets a thread process priority. Can dramatically
***
increase performance of a task.
***
Pass: tnThreadHandle
***
tnPriority
0 - Normal
***
2 - Highest Priority
***
15 - Time Critical
***
31 - Real Time (doesn't work Win95)
************************************************************************
************************************************************************
* wwAPI :: Sleep
*********************************
*** Function: Puts session into idle state
***
Pass: tnMilliseconds
***
Return: nothing
************************************************************************
Class wwEval
Program File: wwEval.prg
- Page 131 -
West Wind Web Connection
Support Classes
The wwEval class provides a safe interface for evaluating expressions and running entire code blocks inside of running
programs. Expressions are evaluated and checked for errors that occur. This class is used exclusively for executing all HTML
embedded FoxPro expressions. The Execute method wraps Rand Pearson's CodeBlck class (also included in the wwEval.prg
file).
************************************************************************
DEFINE CLASS wwEval as Custom
*****************************
*** Custom Properties
lError=.F.
nError=0
cResultType="C"
vErrorResult="Error"
Result=""
************************************************************************
* wwEval :: Evaluate
*********************************
*** Function: Actually evaluates expression.
***
Pass: lcExpression - Expression to evaluate
***
Return: Result
************************************************************************
************************************************************************
* wwEval :: ExecuteCommand
*********************************
*** Function: Macro Expands a single command. More efficient than
***
than Execute which uses CodeBlock.
***
Pass: lcCommand - Command to run
***
Return: nothing
************************************************************************
************************************************************************
* wwEval :: Execute
*********************************
*** Function: Executes a block of code using Randy Pearson's CodeBlock
***
class.
***
Pass: lcCode
Any block of Visual FoxPro code.
***
Return: Result of the code
************************************************************************
************************************************************************
* wwEval :: MergeText
*********************
*** Function: This function provides an evaluation engine for FoxPro
***
expressions and Codeblocks that is tuned for Active
***
Server syntax. It works with any delimiters however. This
***
parsing engine is faster than TEXTMERGE and provides
***
extensive error checking and the ability to run
***
dynamically in the VFP runtime (ie uncompiled). Embed any
***
valid FoxPro expressions using
***
***
<%= Expression%>
***
***
and any FoxPro code with
***
***
<% CodeBlock %>
***
***
Expressions ideally should be character for optimal
***
speed, but other values are converted to string
***
automatically. Although optimized for the delimiters
***
above you may specify your own. Make sure to set the
***
llNoAspSyntax parameter to .t. to disallow the = check
- Page 132 -
West Wind Web Connection
Support Classes
***
for expressions vs code. If you use your own parameters
***
you can only evaluate expressions OR you must use ASP
***
syntax and follow your deleimiters with an = for
***
expressions.
***
Assume: Delimiter is not used in regular text of the text.
***
Uses: wwEval class (wwEval.prg)
***
Codeblock Class (wwEval.prg)
***
Pass: tcString
String to Merge
***
tcDelimeter Delimiter used to embed expressions
***
Default is "<%"
***
tcDelimeter2Delimiter used to embed expressions
***
Default is "%>"
***
llNoAspSytnax
Don't interpret = following first
***
parm as expression. Everything is
***
evaluated as expressions.
***
*** Example: lcResult = loEval.MergeText(HTMLDocs.MemField)
*************************************************************************
************************************************************************
* wwEval :: SetResultType
*********************************
*** Function: Set the Result Type for the Evaluated expression.
***
Pass: lcType Valid FoxPro Type
***
Return: nothing
************************************************************************
************************************************************************
* wwEval :: SetErrorResult
*********************************
*** Function: Set the Default value that is returned if the Eval
***
fails.
***
Pass: lvErrorResult
Result value to assign
***
Return: nothing
************************************************************************
************************************************************************
* wwEval :: IsError
*********************************
*** Function: Returns error status of previous eval operation
***
Return: .T. or .F.
************************************************************************
************************************************************************
* wwEval :: GetErrorNumber
*********************************
*** Function: Returns the error number of the previous eval operation
***
if an error occurred.
***
Return: Error number or 0
************************************************************************
Example:
-------loEval=CREATE("wwEval")
loEval.cResultType="C"
loEval.vErrorResult="Error"
*** Generates an error
loEval.Evaluate("SYSx(0)")
IF !loEval.lError
wait window loEval.Result
ELSE
*** Handle the error here
wait window loEval.vErrorResult + STR(loEval.nError)
- Page 133 -
West Wind Web Connection
Support Classes
ENDIF
RETURN
- Page 134 -
West Wind Web Connection
Procedure Library wwUtils
Procedure Library wwUtils
Function File2Var
This handy function converts files to memory variables and back. Files can be read into memory for easy string manipulation
and easily be written back out using this function. Note: This function is safe for multi-user access of files – VFP 6.0's
STRTOFILE and FILETOSTR are not!
************************************************************************
FUNCTION File2Var
******************
*** Function: Takes a file and returns the contents as a string or
***
Takes a string and stores it in a file if a second
***
string parameter is specified.
***
Pass: tcFilename - Name of the file
***
tcString
- If specified the string is stored
***
in the file specified in tcFileName
***
Return: file contents as a string or nothing if storing to file
************************************************************************
Function Extract
This function extracts a text string from between a pair of delimiters or the end of a string.
************************************************************************
FUNCTION Extract
******************
*** Function: Extracts a text value between two delimiters
***
Pass: lcString
- Entire string
***
lcDelim1
- The starting delimiter
***
lcDelim2
- Ending delimiter
***
lcDelim3
- Alternate ending delimiter
***
llEndOk
- End of line is OK
***
Return: Text between delimiters or ""
********************************************************************************************
Function MergeText
This function parses Templates using Active Server type scripting expressions. Also see: wwEval::MergeText, which is faster
as it doesn't make external object calls.
************************************************************************
FUNCTION MergeText
******************
*** Function: This function provides an evaluation engine for FoxPro
***
expressions and Codeblocks that is tuned for Active
***
Server syntax. It works with any delimiters however. This
***
parsing engine is faster than TEXTMERGE and provides
***
extensive error checking and the ability to run
***
dynamically in the VFP runtime (ie uncompiled). Embed any
***
valid FoxPro expressions using
***
***
<%= Expression%>
***
***
and any FoxPro code with
***
***
<% CodeBlock %>
***
***
Expressions ideally should be character for optimal
- Page 135 -
West Wind Web Connection
Procedure Library wwUtils
***
speed, but other values are converted to string
***
automatically. Although optimized for the delimiters
***
above you may specify your own. Make sure to set the
***
llNoAspSyntax parameter to .t. to disallow the = check
***
for expressions vs code. If you use your own parameters
***
you can only evaluate expressions OR you must use ASP
***
syntax and follow your deleimiters with an = for
***
expressions.
***
Assume: Delimiter is not used in regular text of the text.
***
Uses: wwEval class (wwEval.prg)
***
Codeblock Class (wwEval.prg)
***
Pass: tcString
String to Merge
***
tcDelimeter Delimiter used to embed expressions
***
Default is "<%"
***
tcDelimeter2Delimiter used to embed expressions
***
Default is "%>"
***
llNoAspSytnax
Don't interpret = following first
***
parm as expression. Everything is
***
evaluated as expressions.
***
*** Example: lcresult MergeText(lcTemplateHTML)
*************************************************************************
Function AparseString
This function parses a delimited string into an array. The array must be passed by referenence and cannot be a VFP object
property.
************************************************************************
PROCEDURE AParseString
**********************
*** Function: Parses a delimited string into an array
***
Pass: laResult
Array containing the result strings (@)
***
lcString
The full string to parse
***
lcDelimiter The delimiter string or character
***
Return: Count of strings or 0 if null string is passed
*************************************************************************
Function Path
Adds or deletes a path from FoxPro's SET PATH.
************************************************************************
PROCEDURE PATH
***************
*** Function: Adds or deletes items from the path string
***
Pass: pcPathName
Path name to add or delete
***
pcMethod
*"ADD","DELETE"
*** Example: DO PATH WITH ".\Classes"
***
Return: New Path or ""
************************************************************************
Function OpenExclusive
Attempts to open a table for exclusive use. If successful returns .T. else returns .F. Uses wwEval class safely execute the file
open operation.
************************************************************************
FUNCTION OpenExclusive
**********************
*** Function: Tries to open a table exclusively. Selects the ALIAS
***
if successful.
- Page 136 -
West Wind Web Connection
Procedure Library wwUtils
***
Assume: No extension may be specified
***
Returns .F. for other reasons like file !found etc.
***
Pass: lcTable
- Name of table to open exclusively
***
Return: .T. or .F.
************************************************************************
Functions URLEncode and URLDecode
These function encode and decode text based on MIME encoding used by CGI/ISAPI request buffers.
************************************************************************
FUNCTION URLDecode
******************
*** Function: URLDecodes a text string to normal text.
***
Assume: Uses wwIPStuff.dll if the string is larger than 1024
***
Pass: lcText
Text string to decode
***
Return: Decoded string or ""
************************************************************************
********************************************************
PROCEDURE URLEncode
*******************
*** Function: Encodes a string in URL encoded format
***
for use on URL strings or when passing a
***
POST buffer to wwIPStuff::HTTPGetEx
***
Assume: Uses wwIPStuff.dll to encode
***
Pass: tcValue String to encode
***
Return: URLEncoded string or ""
********************************************************
IsComObject
Checks the registry to see if a COM object or ActiveX control is installed.
********************************************************
PROCEDURE IsCOMObject
*********************
*** Function: Checks to see if a COM object
***
or ActiveX control exists
***
Assume: Uses wwAPI
***
Pass: lcProgId
- Prog Id of the Class
***
lcClassId - (Optional) If passed in
***
by reference gets ClassId
***
lcClassDescript - (Optional)
***
Return: .T. or .F.
********************************************************
RegisterOleServer
This method allows you to register any DLL/OCX based com object that you would normally have to run RegSvr32 against
through code.
************************************************************************
FUNCTION RegisterOleServer
**************************
*** Function: Registers an OLE server or OCX control
***
Pass: lcServerPath - Full path and filename of OCX/OLE Server
***
llUnregister - .T. to unregister
***
lcClassId
- (optional) check for class Id - if
***
exist don't reregister
***
Return: .T. or .F.
- Page 137 -
West Wind Web Connection
Procedure Library wwUtils
*************************************************************************
DCOMCnfgServer
This function allows you to configure Automation Server access rights under Windows NT 4.0 without having to run the
DCOMCnfg.exe utility. This function registers an existing server and creates the security context under which the server runs.
NOTE: It's still necessary to configure DCOMCnfg at least once to give the server Launch and Access permissions either
individually or through the Default Security settings.
************************************************************************
PROCEDURE DCOMCnfgServer
***********************
*** Function: Sets the security attributes of an Automation server
***
to Interactive User
***
Assume: Only works for Interactive user for now
***
uses wwAPI
***
Pass: lcProgId - Program ID for the server (wcdemo.wcdemoserver)
***
lcRunAs
- User Account (Default: Interactive User)
***
Return: nothing
*************************************************************************
Function GetAppStartPath
Returns an applications startpath based on the EXE file that launched it. Works in all circumstances including Automation
servers compiled as EXE or DLL servers
************************************************************************
FUNCTION GetAppStartPath
*********************************
*** Function: Returns the FoxPro start path
***
of the *APPLICATION*
***
under all startmodes supported by VFP.
***
Returns the path of the starting EXE,
***
DLL, APP, PRG/FXP
***
Return: Path as a string with trailing "\"
************************************************************************
Function DomainName
Extracts a domain name from an URL.
************************************************************************
FUNCTION DomainName
*******************
*** Function: Retrieves a Domain name from an URL
***
Assume: URL contains // (as in http://west-wind.com/Test.htm)
***
Pass: lcUrl
- URL to retrieve name from
***
llNoStripWWW - Don't strip www.
***
Return: Domain Name or ""
*************************************************************************
Function GoURL
Goes to the specified URL by firing up the default browser and loading the specified location.
****************************************************
FUNCTION GoUrl
******************
*** Function: Starts associated Web Browser
***
and goes to the specified URL.
***
If Browser is already open it
***
reloads the page.
- Page 138 -
West Wind Web Connection
Procedure Library wwUtils
***
Assume: Works only on Win95 and NT 4.0
***
Pass: tcUrl - The URL of the site or
***
HTML page to bring up
***
in the Browser
***
Return: 2 - Bad Association (invalid URL)
****************************************************
Function ShowHTML
Takes text input and displays the HTML text in the default browser. Also works with _ScreenX if available or any other IE 4
WebBrowser control which you can pass as an object reference in the third parameter. Order is: Object reference passed,
_ScreenX if available or to the default browser.
************************************************************************
FUNCTION ShowHTML
*****************
*** Function: Takes an HTML string and displays it in the default
***
browser.
***
Assume: Uses a file to store HTML temporarily.
***
For this reason there may be concurrency issues
***
unless you change the file for each use
***
Pass: lcHTML
HTML to display
***
lcFile
Temporary File to use (Optional)
***
loWebBrowser Web Browser control ref (Optional)
************************************************************************
Function StripHTML
Removes HTML formatting from an HTML document.
************************************************************************
PROCEDURE StripHTML
*******************
*** Function: Removes HTML tags from the passed text and converts
***
it to plain text. Note formatting is totally removed!
***
Assume: only <br> and <p> are translated
***
any < or > in the HTML besides tags will break this
***
function.
***
Pass: lcText HTML Text to strip
***
Return: Stripped HTML text
*************************************************************************
Function HTMLColor
This function returns an HTML Color string from a Visual FoxPro RGB color value.
************************************************************************
FUNCTION HTMLColor
*********************************
*** Function: Converts a FoxPro Color to an HTML Hex color value
***
Pass: lnRGBColor
- FoxPro RGB color number - RGB(255,255,255)
***
llNoOutput
***
Return: Hex HTML Color String "#FFFFFF"
************************************************************************
Function DateToC
Like VFP's DOTC except blank dates are returned as blank strings rather than " / / ".
************************************************************************
PROCEDURE DateToC
******************
*** Function: Converts a date to string displaying empty dates as blanks
- Page 139 -
West Wind Web Connection
Procedure Library wwUtils
***
rather than displaying the empty date format
***
Pass: ldDate - Date to display
***
Return: Date String or "" if invalid date
*************************************************************************
Functions JustFname, JustStem, JustExt, JustPath, ForcePath
and AddBs
Fox implementations of the FOXTOOLS functions so that Foxtools does not have to be loaded.
************************************************************************
FUNCTION JustFname
******************
*** Function: Returns just the filename portion of a path spec
***
Pass: lcFullPath
***
Return: Filename
*************************************************************************
************************************************************************
FUNCTION JustStem
*****************
*** Function: Returns just the Filename without extension.
***
Pass: lcFile - File name or filename and path
***
Return: file stem
*************************************************************************
************************************************************************
FUNCTION JustExt
******************
*** Function: Returns just a file extension
***
Pass: lcFile - Name of the file or full path + file
***
Return: Extension or ""
*************************************************************************
************************************************************************
FUNCTION JustPath
******************
*** Function: Returns just the path portion of a path spec
***
Assume: Path is returned with a trailing slash
***
Pass: lcFullPath
***
Return: Filename
*************************************************************************
************************************************************************
FUNCTION AddBS
******************
*** Modified: 07/21/96
*** Function: Add BackSlash to path.
***
Pass: lcPath - Path to append Backslash to
***
Return:
*************************************************************************
************************************************************************
FUNCTION ForcePath
*********************************
*** Function: Forces a path expression to the path specified by
***
to allow mapping for network drives
***
to the INI and output files.
***
Pass: lcPath
- Path to work with
***
lcNewPath - Path to override with
***
Notes: Does not guarantee valid path name!!!
***
Return: changed path or same path if no drive was specified
***
in the path string.
************************************************************************
- Page 140 -
West Wind Web Connection
Procedure Library wwUtils
Function IsDir
This function returns .T. if a specified path exists.
************************************************************************
FUNCTION IsDir
******************
*** Modified: 10/09/97
*** Function: Checks to see whether a directory exists
***
Pass: lcPath
- Path to check
***
Return: .T. or .F.
*************************************************************************
Function FileSize
************************************************************************
FUNCTION FileSize
******************
*** Function: Returns the size of a file
***
Pass: lcFileName
***
Return: the size of the file or -1 on error
************************************************************************
Function ProgLevel
Return the current Visual FoxPro Call Stack level. This is a useful function to check on Automation Servers where call stack
corruption can occur when an Automation server crashes but doesn't unload. Also allows checking for recursive functions that
can blow the 128 call stack limit of VFP.
************************************************************************
PROCEDURE ProgLevel
******************
*** Function: Returns the current Calling Stack level. Used to check
***
recursive Error calls in Error methods.
*************************************************************************
Function PropertyDump
This method allows a quick view of an object's properties and values as a text string. I use this frequently to see object state
from a running program without having to fire up the debugger and dig through the objects.
************************************************************************
PROCEDURE PropertyDump
**********************
*** Function: Dumps all of an objects properties to a string separated
***
by Carriage Returns
***
Pass: loObject ***
Return: string of all property name and values
*************************************************************************
Function InputForm
Creates a simple input form dialog that can be used to enter single line values of any type. Used in the Setup program and in
various support utilities.
************************************************************************
FUNCTION InputForm
******************
*** Function: Creates a simple Input form that returns a value
***
Assume: Consists of this function and Form Class
***
Pass: lcValue
Initial value to retrieve
***
lcMessage The request message
***
lcCaption Form Caption (_Screen.Caption)
***
lnFormWidth
Width of the form
- Page 141 -
West Wind Web Connection
Procedure Library wwUtils
***
lnFieldWidth Widht of the input field
***
lcFormat
Format string for the input field
***
Return: Value or ("" or -1)
************************************************************************
Function PEMStatus
Provides PEMSTATUS() compatibility for version 3.0 of Visual FoxPro. Note only parameter 5 is implemented to return .t. or
.f. if a method/property exists.
************************************************************************
PROCEDURE PEMSTATUS
*******************
*** Modified: 06/11/96
*** Function: Simulates PEMSTATUS for VFP 3.0 *
***
Native PEMSTATUS() overrides in 3.0b and later
***
Note: Only PEMSTATUS(object, method, 5) is implemented
***
Pass: loObject - Object parameter to check PEMs for
***
lcMethod - Method or Property to check for
***
lnValue - Not used - like PEMSTATUS(o,m,5)
***
Return: .T. or .F. if object exists
************************************************************************
- Page 142 -
West Wind Web Connection
Other Tools
Other Tools
A set of tools is provided in the Tools directory. These tools are in rough form. I've been using these for a variety of
applications and have included them here only because they can save a lot of time for some purposes. Just be aware that they
are not polished nor documented very well. Some assembly may be required <g>...
West Wind Web Monitor
This utiltity is a separate standalone application that can be downloaded from the registered download directory or is available
as shareware for non-registered users at http://www.west-wind.com/webtools.htm. It provides the ability to monitor a Web site
by accessing a Web link and checking the resulting string for a match. If a match is not found the program will use a list of
email addresses to email you or your pager (if it has email paging capabilities).
Web Server Configuration Component
Enterprise Edition only
The Enterprise edition includes a tool to configure various Web servers programmatically from your VFP code. The utility
provides the ability to create Virtual Directories and scriptmaps by calling simple class methods. The wwWebServer class can
be found in \tools\Webserver.vcx. The class also contains a specific for IIS 4 configuration to access the IIS Admin objects and
Active Directory for configuring all aspects of IIS. The IISAdmin class provides access to all properties of IIS 4 while the
wwActiveDirectory base class allows lower level access to Active Directory properties in general.
Here's how it works:
oWS = CREATEOBJECT("wwWebServer","IIS4")
oWS.CreateVirtual("wconnect","c:\westwind\wconnect\")
oWS.CreateScriptMap(".wc","c:\westwind\wconnect\wc.dll")
Dependicies:
wconnect.h
wwAPI.prg
Methods
SetServerType
Function
This method should be called to determine which Web Server to configure for. Valid
values are:
IIS4, IIS3, PWS3, PWS4, WEBSITE, WSISAPI, COMMERCE, CB
WebSite and WSISAPI, COMMERCE and CB are each identical. PWS NT Workstation
should use the IIS values – the PWS keys only apply to the Win95 versions. This
property is also set by the Init if a parameter is passed:
oWS = CREATEOBJECT("wwWebServer","IIS4")
GetWebRootPath
GetTempPath
CreateVirtual
Returns the directory of the Root Web. This can be used to prompt users for new virtual
directories that should be created off the Web Root by default.
Retrieves the temporary directory for the user's machine. Since Web Connection uses
temp files for file based messaging this setting is important and must be set in the wc.ini
file and the application's startup Ini file.
Creates a Virtual Directory by passing the name of the virtual and a path to create it on.
The directory is created with Execute rights set. Note that this method always creates the
virtual on the default Web server if multiple servers exist.
Parameters:
- Page 143 -
West Wind Web Connection
Other Tools
lcVirtual
The name of the virtual directory to create.
lcPath
The path to make a virtual
lcIIS4Path
If you're using IIS4 you can specify an ADS path that specifies a non-default Web server.
For example: LOCALHOST/W3SVC/2/ROOT
CreateScriptMap
Returns: .T. or .F.
Allows creation of a script map that links a file extension to a specific ISAPI extension.
Parameters:
lcScriptMap
The extension to use as a scriptmap. Example: .WC
lcDLLPath
The full system path of the DLL to map.
lcIIS4Path
If you're using IIS4 you can specify an ADS path that specifies a non-default Web server.
For example: LOCALHOST/W3SVC/2/ROOT
Returns: .T. or .F.
Text Wrapper
To make it easier to create HTML code from existing pages Web Connection provides a tool called Text Wrapper. This little
utility is contained in WRAPPER.SCX in the TOOLS directory and allows you to capture text stored on the clipboard and wrap
the text with a set of strings before and after the string.
It’s very handy for quickly creating loHTML.SendLn( [ text line1 ] ) for an entire page of HTML text. This utility makes it
easy to go from HTML page to code, allowing you to easily add fields and calculations to the generated code.
Using Send/SendLn is the fastest output method available. A great way to produce the fastest possible HTML output is to use
highlevel methods like wwHTML::ShowCursor to quickly generate HTML output from a cursor or table then use the
WRAPPER form to capture the generated HTML code and build more optimized, hand code from it. ShowCursor is great for
quickly generating output, but unfortunately it's more than 2 times slower than the equivalent hand coded wwHTML.SendLn
statement code.
For more detailed information see WRAPPER.TXT in the TOOLS directory.
ScriptMap
The ScriptMap program file allows you to quickly create new script maps for IIS. You pass the full path of the DLL and the
name of the extension you want to be script mapped (.WC for example). When you run the Web Connection install a .wc script
map is automatically created for the wc.dll.
Script maps allow you to hide the .DLL extension from your site as well as providing a nice way to use a DLL in one directory
throughout your site without having to deal with the path issues involved with the plain DLL interface. Script mapped links act
as if the file DLL actually lived in the current directory so no path changes take place.
LogCount
The CGILog program summarizes hit counts on the CGILog file by query string 'parameter'. This function is extremely useful
for figuring out what operations happen most frequently on a server.
************************************************************************
PROCEDURE CGICount
- Page 144 -
West Wind Web Connection
Other Tools
******************
*** Function: Summarizes CGI hits on a site based on the first
***
parameter.
***
Assume: First Parameter is the Application name
***
Parameters are separated by ~ chars
***
Sample: wwcgi.dll?wwdemo~Test_Page
***
Pass: lcFile
Logfile created by Web Connection
***
lcParmChar Parameter separator ("~")
***
lnGroupParm Which parameter to group on (1)
***
Return: Cursor TCGISummary filled with summary
*************************************************************************
To use:
DO LogCount
WITH "CGILOG"
- Page 145 -
Download