(please note: the tek-tips parser has changed some of the simple ampersand characters in the following to being the encoded & ... so anywhere you see & imagine it just has & ;) Forms on the web can be submitted in two different ways: GET and POST. (HTTP describes the protocol 'suite' for the web, "HyperText Transfer Protocol" )
HTTP GET -- Simply includes the fields in the form as part of the request URL. Basically takes the URL from the "ACTION" parameter of the "FORM" tag, adds "?" to seperate the URL from the field values, then adds all the field values as "Name=value" pairs, pairs seperated by "&". ie: the Google search form using url http://www.google.com/search then adds "?" followed by the fields of the form: hl, ie, oe, q and btnG, like this: "hl=en&ie=UTF-8&oe=UTF-8&q=search+terms+here&btnG=Google+Search" Of course, the characters "?", "=" and "&" would be confusing if they appeared in the field values, so the field values should be URL-Encoded. The final google GET url is: http://www.google.com/search?hl=en&ie=UTF-8&oe=UTF-8&q=search+terms+here&btnG=Google+Search
HTTP POST -- POST, on the other hand, does not put the parameters in the request URL. Instead, after connecting to the server and issuing a "POST" command to the specified FORM ACTION URL, the browser sends the form values in the request header. Since there is a limitation on the length of a URL, POST is a way to send larger amounts of information (like entire files) to a form processor on a web server. Many web forms use POST even when only accepting a couple form fields: POST prevents the user from bookmarking the result of a form submission.
The code here is primarily concerned with POSTing form data, since GET is so easy.
There are many third party utilities to help with POSTing data, and some tools from Microsoft, too, that may or may not be installed in your users' Windows installs, so I'll start with a very basic, direct to TCP/IP WinSockets illustration of what goes on with a POST: ( The GET and SendMail support here is a bonus: I keep them together in this utility class )
DEFINE CLASS SocketWrapper As Custom * Author: William GC Steinford * Based on Anatoliy Mogylevets SMTP code at http://fox.wikis.com/wc.dll?Wiki~SendSmtpEmail #DEFINE SMTP_PORT 25 #DEFINE HTTP_PORT 80 #DEFINE AF_INET 2 #DEFINE SOCK_STREAM 1 #DEFINE IPPROTO_TCP 6 #DEFINE SOCKET_ERROR -1 #DEFINE FD_READ 1
FUNCTION httpGet( pcServer, pcUrl ) LOCAL lResult THIS.Host = pcServer IF THIS.Connect() THIS.snd('GET '+pcURL+' http/1.0'+crlf) THIS.snd('Accept: */*'+crlf) THIS.snd('Accept-Language: '+THIS.AcceptLanguage+crlf) THIS.snd('Accept-Encoding: gzip, deflate'+crlf) THIS.snd('User-Agent: '+THIS.UserAgent+crlf) THIS.snd('Host: '+pcServer+crlf) THIS.snd('Pragma: no-cache'+crlf) THIS.snd(crlf,.t.) && End of headers *info=url encoded string lResult = .T. ELSE lResult = .F. ENDIF THIS.Disconnect() ENDFUNC
FUNCTION httpPost( pcServer, pcUrl, pcData, poFdbk ) The parameters are:
httpPost( pcServer, pcUrl, pcData, poFdbk ) * Meaning of parameters: * pcServer: IP or hostname of the server to POST to * * pcURL: the URL of the page (CGI/Servlet/PHP, whatever) * on the server that the POST data will be sent to. * * pcData: the url-formatted string comprised of * name=value&name2=value2 data, * where all "value" data is UrlEncoded * * poFdBk: (optional) A reference to an object that has * a method called "Feedback" which accepts * a single decimal value, between 0 and 1, * which indicates the portion of the transfer * that is complete. * I usually add a "Feedback" method to a form, * and pass THISFORM as poFdbk, and in * THISFORM.Feedback, just update a progressbar * or something.
LOCAL lResult, lnLen, lnComplete, lcRemain, lcSnd THIS.Host = pcServer IF THIS.Connect() THIS.snd('POST '+pcURL+' http/1.0'+crlf) THIS.snd('Content-Type:application/x-www-form-urlencoded'+crlf) THIS.snd('Accept: */*'+crlf) THIS.snd('Accept-Language: '+THIS.AcceptLanguage+crlf) THIS.snd('Accept-Encoding: gzip, deflate'+crlf) THIS.snd('User-Agent: '+THIS.UserAgent+crlf) THIS.snd('Host: '+pcServer+crlf) lnLen = len(pcData) THIS.snd('Content-Length: '+tran(lnLen)+crlf) THIS.snd('Pragma: no-cache'+crlf) THIS.snd(crlf) && End of headers * If we have a valid feedback object, provide feedback if vartype(poFdbk)='O' and PEMStatus(poFdbk,'Feedback',5) ; and upper(PEMStatus(poFdbk,'Feedback',3))='METHOD' lcRemain = pcData lnComplete = 0 poFdbk.Feedback( 0 ) do while len(lcRemain)>0 lcSnd = LEFT( lcRemain, 100 ) lcRemain = SUBSTR( lcRemain, 101 ) THIS.snd(lcSnd) lnComplete = lnComplete+len(lcSnd) poFdbk.Feedback( lnComplete/lnLen*100 ) enddo THIS.snd("",.t.) && get a response, too. else && no feedback object, just send one big chunk. THIS.snd(pcData,.t.) && get a response, too. endif lResult = .T. ELSE lResult = .F. ENDIF THIS.Disconnect() ENDFUNC
FUNCTION num2word(lnValue) RETURN Chr(MOD(m.lnValue,256)) + CHR(INT(m.lnValue/256)) ENDFUNC ENDDEFINE
If you need to support authentication, or more features than the above code has, either write them yourself (and, I'd appreciate if you'd allow me to include your improvements here), or (particularly if you don't want to be responsible for complex features working) use an external tool. Here are some you may explore:
WinHttp control: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winhttp/http/about_winhttp.asp ( MS control included in: WinHTTP 5.1 is available only with Windows Server 2003, Windows XP SP1, and Windows 2000 SP3. A redistributable merge module (.msm) file is not available for WinHTTP 5.1. The WinHTTP 5.0 redistributable, winhttp5.dll, runs on Windows 2000 or later, or Microsoft Windows NT 4.0 with Microsoft Internet Explorer 5.01 or later. Important With the release of WinHTTP Version 5.1, the WinHTTP 5.0 download is no longer available.