Re: URL2PDF()

Tech Tip: Click here to run a free scan for Windows Errors and optimize PC performance

From: Dorian C. Chalom (DChalom_at_Comcast.net)
Date: 05/27/04

  • Next message: Villi Bernaroli: "reversed "print when" in last page"
    Date: Wed, 26 May 2004 22:51:06 -0400
    
    

    Thanks Gerben;

    I admit I do not understand everything in it. But it worked!!!!!

    "Gerben Kessen" <gerben.kessen(@)wantit.nl> wrote in message
    news:OlXyJE1QEHA.3300@TK2MSFTNGP09.phx.gbl...
    > Ok, it can be done with low level http functions,....Of course there will
    be
    > a lot of other solutions for this but this is one....
    > For this code I used some public code of Rick Strahl from
    www.west-wind.com
    > (Thanks Rick) and write a little bit of code around it....
    > Hope this is what you want...
    >
    > Gerben Kessen
    > www.wantit.nl
    >
    >
    > *- start code
    > ox = CREATEOBJECT("_wDownloadPDF")
    > ox.DownloadPdf("http://www.sdgn.nl/gfx/magazine/sdgnnr81.pdf")
    >
    >
    > DEFINE CLASS _wDownloadPDF AS RELATION
    > oHTTP = NULL
    >
    > *-------------------------
    > PROCEDURE CreateHTTPClient
    > *-------------------------
    > *- Returns an handle to the http class.
    > THIS.oHTTP = CREATEOBJECT("wwHTTP")
    > THIS.oHTTP.nConnectTimeout = 10
    > RETURN THIS.oHTTP
    > ENDPROC
    >
    > *-----------------------
    > PROCEDURE DownloadPDF
    > *-----------------------
    > *- Downloads the update file from the website
    > *- Returns .T. or .F. succes or failure
    > LPARAMETERS tcPdfUrl
    >
    > LOCAL lcData, lnSize, loUrl, llReturn
    >
    > llReturn = .T.
    >
    > *- Check if the update is not already downloaded
    >
    > WITH This
    > IF ISNULL(.oHTTP)
    > .CreateHTTPClient()
    > ENDIF
    >
    > *- Break down the URL into its components
    > loUrl = .oHTTP.InternetCrackUrl(tcPdfUrl)
    >
    > IF !ISNULL(loUrl)
    > *- Continue
    > IF
    >
    .oHTTP.HTTPConnect(loUrl.cServer,"","",IIF(lower(loUrl.cProtocol)="https",.T
    > .,.F.)) = 0
    > *- Connection succesfull continue
    >
    >
    > lcTFile = "c:\" + JUSTFNAME(STRTRAN(tcPdfUrl,"/","\"))
    > lcData = ""
    > lnSize = 0
    >
    > IF .oHTTP.HTTPGetEx( TRIM(loUrl.cPath),@lcData,@lnSize,,lcTFile) = 0
    > *- Download successfull
    >
    > ELSE
    > .SetError(.oHttp.cErrorMsg)
    > llReturn = .F.
    > ENDIF
    > ELSE
    > .SetError(.oHTTP.cErrorMsg)
    > llReturn = .F.
    > ENDIF
    > *- Close the connection
    > .oHTTP.HTTPClose()
    > ELSE
    > llReturn = .F.
    > ENDIF
    > ENDWITH
    >
    > RETURN llReturn
    > ENDPROC
    >
    > ************************************************************************
    > * WCONNECT Header File
    > **********************
    > *** Author: Rick Strahl
    > *** (c) West Wind Technologies, 1995-2002
    > *** Contact: http://www.west-wind.com/
    > *** Function: Global DEFINEs used by West Wind Web Connection.
    > ***
    > *** IMPORTANT: Any changes made here or in WCONNECT_OVERRIDE.H
    > *** require a full recompile of all files that use
    > *** this header file!
    > ************************************************************************
    >
    > #DEFINE WWVERSION "Version 4.20"
    > #DEFINE WWVERSIONDATE "May 6, 2002"
    >
    > *** n.EBUGMODE effects how errors are handled.
    > *** If .T. errors are not handled and the server stops on errors.
    > *** If .F. the Web Connection error handlers kick in and
    > *** provide error pages and logging
    > #DEFINE DEBUGMODE .T.
    >
    > *** Use this flag to handle different configurations
    > *** You can set up conditional DEFINES for applications
    > *** to easily switch configurations. (Optional - not used by framework)
    > *** 1 - Development Server
    > *** 2 - Live Server
    > #DEFINE LOCALSITE 1
    >
    > *** When .T. server runs as a Top Level while running file based
    > #DEFINE SERVER_IN_DESKTOP .F.
    >
    > *** Carriage Return/Line Break
    > #DEFINE CR CHR(13)+CHR(10) && DO NOT USE ANY MORE
    > #DEFINE CRLF CHR(13)+CHR(10)
    >
    > *** Customizable default HTTP Header
    > #DEFINE DEFAULT_CONTENTTYPE_HEADER ;
    > "HTTP/1.1 200 OK" + CRLF + ;
    > "Content-type: text/html" + CRLF
    >
    > #DEFINE DEFAULT_HTTP_VERSION "1.1"
    >
    > *** Post boundary used for posting multipart vars
    > #DEFINE POST_BOUNDARY CHR(13)+CHR(10)+ "#@$ FORM VARIABLES $@#" +
    > CHR(13)+CHR(10)
    > #DEFINE MULTIPART_BOUNDARY "-----------------------------7cf2a327f01ae"
    >
    > *** SQL Connect String to database containing
    > *** wwSession and RequestLog files
    > #DEFINE WWC_USE_SQL_SYSTEMFILES .F.
    >
    > *** Determines whether the store runs with SQL Server Tables
    > #DEFINE WWSTORE_USE_SQL_TABLES .F.
    > #DEFINE WWMSGBOARD_USE_SQL_TABLES .F.
    >
    > *** Visual FoxPro Version Number Macro
    > #DEFINE wwVFPVERSION VAL(SUBSTR(Version(),ATC("FoxPro",VERSION())+7,2))
    >
    > *** Determines whether TEMPLATE pages are cached (ExpandTemplate calls)
    > *** Note: This value specifies how often the file is checked for
    > *** a newer version in seconds. 0 means - don't cache.
    > #DEFINE WWC_CACHE_TEMPLATES 0
    >
    > *** Maximum String size for the wwResponseString class
    > #DEFINE MAX_STRINGSIZE 8000
    >
    > *** Maximum number of cells that ShowCursor generates
    > *** before reverting to <pre> list
    > #DEFINE MAX_TABLE_CELLS 15000
    >
    > *** Special 'NULL' String to differentiate none from empty strings
    > #DEFINE WWC_NULLSTRING "*#*"
    >
    > *** Defines the location of the Web Connection framework
    > *** the default is the current directory
    > #DEFINE WWC_FRAMEWORK_PATH ".\"
    >
    > *** XML Size Id used for Memo Fields to differentiate memos from strings
    > *** This value is compatible with ADO's usage
    > #DEFINE XML_SCHEMA_MEMOSIZE 2147483647
    > #DEFINE XML_XMLDOM_PROGID "MSXML2.DOMDocument"
    > **"MSXML2.DOMDocument.4.0"
    >
    > *** Determines whether wwXML::XMLTOCURSOR tries to use
    > *** VFP 7's XMLTOCURSOR. NOTE: Requires SP1!!!!
    > *** This can drastically improve performance for large data sets
    > #DEFINE WWXML_USE_VFP_XMLTOCURSOR .F.
    >
    > *** Class Names - These classes are defined here and used in the code
    > *** so if you subclass an essential class you can change
    > *** the class used here and automatically have the framework
    > *** inherit from your subclass
    > #DEFINE WWC_SERVER wwServer
    > #DEFINE WWC_SERVERFORM wwServerForm
    > #DEFINE WWC_SERVERFORM_VFPFRAME wwServerFormVFPFrame
    >
    > #DEFINE WWC_PROCESS wwProcess
    > #DEFINE WWC_WEBSERVICE wwWebService
    >
    > #DEFINE WWC_SESSION wwSession
    > #DEFINE WWC_SQLSESSION wwSessionSQL
    >
    > #DEFINE WWC_REQUEST wwRequest
    > #DEFINE WWC_REQUESTASP wwASPRequest
    >
    > #DEFINE WWC_RESPONSE wwResponse
    > #DEFINE WWC_RESPONSEFILE wwResponseFile
    > #DEFINE WWC_RESPONSESTRING wwResponseStringNoBuffer
    > #DEFINE WWC_RESPONSEASP wwASPResponse
    >
    > #DEFINE WWC_WWDHTMLFORM wwDhtmlForm
    > #DEFINE WWC_WWDHTMLCONTROL wwDhtmlControl
    >
    > #DEFINE WWC_HTTPHEADER wwHTTPHeader
    >
    > #DEFINE WWC_WWEVAL wwEval
    > #DEFINE WWC_WWVFPSCRIPT wwVFPScript
    > #DEFINE WWC_WWPDF wwPDF50
    > #DEFINE WWC_WWSOAP wwSOAP
    >
    > #DEFINE WWC_WWBUSINESS wwBusiness
    >
    > *** Class Include flags - Use these to make the install lighter - New
    > 07/05/97
    > #DEFINE WWC_LOAD_WWSESSION .T.
    > #DEFINE WWC_LOAD_WWBANNER .T.
    > #DEFINE WWC_LOAD_WWSHOWCURSOR .T.
    > #DEFINE WWC_LOAD_WWDBFPOPUP .T.
    > #DEFINE WWC_LOAD_WWIPSTUFF .T.
    > #DEFINE WWC_LOAD_WWHTTP .T.
    > #DEFINE WWC_LOAD_WWBUSINESS .T.
    > #DEFINE WWC_LOAD_WWSQL .T.
    > #DEFINE WWC_LOAD_WWHTTPSQL .T.
    > #DEFINE WWC_LOAD_WWVFPSCRIPT .T.
    > #DEFINE WWC_LOAD_WWPDF .T.
    > #DEFINE WWC_LOAD_WWXML .T. && Don't change! Required!
    > #DEFINE WWC_LOAD_WWMSMQ .F.
    > #DEFINE WWC_LOAD_WWSOAP .T.
    > #DEFINE WWC_LOAD_DYNAMICHTML_FORMRENDERING .T.
    >
    > *** VERSION CONSTANTS
    > #DEFINE SHAREWARE .F.
    > #DEFINE WWC_DEMO .T.
    > #DEFINE SWTIMEOUT 1800
    > #DEFINE HTMLCLASSONLY .F.
    >
    > #DEFINE SHOWSQLERRORS .F.
    > #DEFINE FOXISAPI .F.
    > #DEFINE VISUALWEBBUILDER .F.
    >
    > *** COMPATIBILITY CONSTANTS
    > *** Turn on for backwards compatibility
    > *** As features are removed they are bracketed in this flag.
    > #DEFINE WWC_COMPATIBILITY .F.
    >
    > *** Use old Style button in Form Rendering
    > *** All buttons are rendered with the same name if .t.
    > *** END COMPATIBILITY CONSTANTS
    >
    > *** Images in forms are pathed relative to the Web request
    > *** and must be located in the directory specified here
    > #DEFINE WWFORM_IMAGEPATH "formimages/"
    > #DEFINE WWFORM_USEOLD_BUTTONSTYLE .F.
    >
    > *** wwList ActiveX Control settings - Changed 9/2/2000
    > #DEFINE WWLIST_USEOLDGRID .F.
    > #DEFINE WWLIST_CLASSID "36E500EB-8219-11D1-A398-00600889F23B"
    > #DEFINE WWLIST_CODEBASE "wwCTLS.cab"
    >
    > #DEFINE LISTVIEW_CLASSID "BDD1F04B-858B-11D1-B16A-00C0F0283628"
    > #DEFINE LISTVIEW_CODEBASE
    > "http://activex.microsoft.com/controls/vb6/MSComCtl.cab"
    >
    > *** General WinINET Constants
    > #DEFINE INTERNET_OPEN_TYPE_PRECONFIG 0
    > #DEFINE INTERNET_OPEN_TYPE_DIRECT 1
    > #DEFINE INTERNET_OPEN_TYPE_PROXY 3
    >
    > #DEFINE INTERNET_OPTION_CONNECT_TIMEOUT 2
    > #DEFINE INTERNET_OPTION_CONNECT_RETRIES 3
    > #DEFINE INTERNET_OPTION_SEND_TIMEOUT 5
    > #DEFINE INTERNET_OPTION_RECEIVE_TIMEOUT 6
    > #DEFINE INTERNET_OPTION_DATA_SEND_TIMEOUT 5
    > #DEFINE INTERNET_OPTION_DATA_RECEIVE_TIMEOUT 6
    > #DEFINE INTERNET_OPTION_LISTEN_TIMEOUT 11
    >
    > #DEFINE INTERNET_SERVICE_FTP 1
    > #DEFINE INTERNET_DEFAULT_FTP_PORT 21
    >
    > #DEFINE ERROR_INTERNET_EXTENDED_ERROR 12003
    >
    > *** WinInet Service Flags
    > #DEFINE INTERNET_SERVICE_HTTP 3
    > #DEFINE INTERNET_DEFAULT_HTTP_PORT 80
    > #DEFINE INTERNET_DEFAULT_HTTPS_PORT 443
    >
    > #DEFINE INTERNET_FLAG_RELOAD 2147483648
    > #DEFINE INTERNET_FLAG_SECURE 8388608
    > #define INTERNET_FLAG_KEEP_CONNECTION 0x00400000
    >
    > #DEFINE HTTP_STATUS_PROXY_AUTH_REQ 407
    > #define HTTP_QUERY_STATUS_CODE 19
    > #define HTTP_QUERY_FLAG_NUMBER 0x20000000
    > #DEFINE HTTP_QUERY_RAW_HEADERS_CRLF 22
    >
    > #define HTTP_QUERY_STATUS_CODE 19
    > #define HTTP_QUERY_STATUS_TEXT 20
    >
    > #DEFINE FTP_TRANSFER_TYPE_ASCII 1
    > #DEFINE FTP_TRANSFER_TYPE_BINARY 2
    >
    > #DEFINE INTERNET_FLAG_IGNORE_CERT_DATE_INVALID 0x00002000
    >
    > *** Win32 API Constants
    > #DEFINE ERROR_SUCCESS 0
    >
    > *** Access Flags
    > #DEFINE GENERIC_READ 0x80000000
    > #DEFINE GENERIC_WRITE 0x40000000
    > #DEFINE GENERIC_EXECUTE 0x20000000
    > #DEFINE GENERIC_ALL 0x10000000
    >
    > *** File Attribute Flags
    > #DEFINE FILE_ATTRIBUTE_NORMAL 0x00000080
    > #DEFINE FILE_ATTRIBUTE_READONLY 0x00000001
    > #DEFINE FILE_ATTRIBUTE_HIDDEN 0x00000002
    > #DEFINE FILE_ATTRIBUTE_SYSTEM 0x00000004
    >
    > *** Values for FormatMessage API
    > #DEFINE FORMAT_MESSAGE_FROM_SYSTEM 4096
    > #DEFINE FORMAT_MESSAGE_FROM_HMODULE 2048
    >
    > *** Registry roots
    > #DEFINE HKEY_CLASSES_ROOT -2147483648 && (( HKEY ) 0x80000000 )
    > #DEFINE HKEY_CURRENT_USER -2147483647 && (( HKEY ) 0x80000001 )
    > #DEFINE HKEY_LOCAL_MACHINE -2147483646 && (( HKEY ) 0x80000002 )
    > #DEFINE HKEY_USERS -2147483645 && (( HKEY ) 0x80000003 )
    >
    > *** Registry Value types
    > #DEFINE REG_NONE 0 && Undefined Type (default)
    > #DEFINE REG_SZ 1 && Regular Null Terminated String
    > #DEFINE REG_BINARY 3 && ??? (unimplemented)
    > #DEFINE REG_DWORD 4 && Long Integer value
    > #DEFINE MULTI_SZ 7 && Multiple Null Term Strings (not implemented)
    >
    > *** Generic File Access Rights for NT ACLs
    > #define FILERIGHTS_READ 1179785
    > #define FILERIGHTS_READEXECUTE 1179817
    > #define FILERIGHTS_CHANGE 1245631
    > #define FILERIGHTS_FULL 2032127
    >
    >
    > **** CUSTOMIZE AND OVERRIDE SETTINGS INDEPENDENTLY
    > **** OF THE WC INSTALLATION
    > #IF FILE("WCONNECT_OVERRIDE.H")
    > #INCLUDE WCONNECT_OVERRIDE.H
    > #ENDIF
    >
    > *!* WCONNECT_OVERRIDE.H would contain (for example):
    > *!* #UNDEFINE DEBUGMODE
    > *!* #DEFINE DEBUGMODE .T.
    >
    > *!* #UNDEFINE SERVER_IN_DESKTOP
    > *!* #DEFINE SERVER_IN_DESKTOP .T.
    >
    >
    >
    >
    >
    > *****************************
    > DEFINE CLASS w_HTTP as wwHTTP
    > *****************************
    >
    > *** Custom properties dealing with display
    > *** of download information
    > lShowDialog = .F.
    > oProgressForm = .NULL.
    > cCaption = "Downloading Update"
    > nContentSize = 0
    >
    > *--------------------------
    > FUNCTION OnHTTPBufferUpdate
    > *--------------------------
    > *- HTTP Progress Event Handler
    > LPARAMETERS lnbytes,lnbufferreads,lccurrentchunk
    >
    > DO CASE
    > *** If this is the 0 chunk it's HTTP Header
    > CASE lnBufferReads = 0
    > THIS.nContentSize = VAL( STREXTRACT(lcCurrentChunk,CHR(13)+CHR(10)
    +
    > "Content-Length: ",CHR(13)) )
    > DO CASE
    > CASE THIS.nContentSize > 90000
    > THIS.nHTTPWorkBufferSize = 16484
    > CASE THIS.nContentSize > 40000
    > THIS.nHTTPWorkBufferSize = 8182
    > ENDCASE
    > RETURN
    > CASE lnBufferReads = -1
    > *** Done
    > DOEVENTS
    > THIS.oProgressForm = .F.
    > THIS.oProgressForm = .NULL.
    > RETURN
    > OTHERWISE
    > DOEVENTS
    > ENDCASE
    >
    > IF THIS.lShowDialog
    > IF lnBufferReads=1
    > THIS.oProgressForm = CREATEOBJECT("wwProgressForm")
    > THIS.oProgressForm.SetCaption(THIS.cCaption)
    > THIS.oProgressForm.ShowCancelButton()
    > THIS.oProgressForm.Show()
    > ENDIF
    >
    > IF THIS.oProgressForm.lCancelled
    > THIS.lHTTPCancelDownload = .T.
    > ENDIF
    >
    > THIS.oProgressForm.SetDescription("Received from " + THIS.cserver + ":"
    > +CHR(13) +;
    > LTRIM( TRANSFORM(lnBytes,"999,999,999") ) + " of
    "
    > +;
    >
    LTRIM(TRANSFORM(THIS.nContentSize,"999,999,999"))+
    > " bytes")
    >
    > THIS.oProgressForm.SetProgress(lnBytes/ IIF(THIS.nContentSize > 0,
    > THIS.nContentSize, lnBytes) * 100)
    > ENDIF
    >
    > ENDFUNC
    >
    >
    > ENDDEFINE
    >
    > *****************************
    > DEFINE CLASS wwHTTP AS Custom
    > *****************************
    >
    > *-- Last Error Message Text for the last operation. Implemented only for
    > SMTP and HTTP operations.
    > cerrormsg = ""
    >
    > *-- Password to log on to server (applies to FTP and HTTP)
    > cpassword = ""
    >
    > *-- Username for log in operations (FTP and HTTP).
    > cusername = ""
    >
    > *-- Determines whether SSL is used
    > lsecurelink = .F.
    >
    > *-- Connection timeout for Connection, Send and Read operations
    > *-- if any take longer than the number of seconds here operation will
    abort
    > nconnecttimeout = 30
    >
    > PROTECTED hIPSession, hhttpsession
    > hhttpsession = 0
    > hipsession = 0
    >
    > *-- The last error code.
    > nerror = 0
    >
    > *-- Allows to specify how the connection is opened: 1 - Direct*, 3 - Proxy
    > (IE 4 and later) and 0 - PreConfig (using IE settings)
    > nhttpconnecttype = 1
    >
    > *-- HTTP Server Address. Format: www.west-wind.com, or 111.111.111.111
    > cserver = ""
    >
    > *-- HTTP Link to visit on a site. Site relative URL. Example:
    /default.asp,
    > /, /wconnect.dll?wwDemo~TestPage
    > clink = ""
    >
    > *-- The port to use for HTTP Connections. If the default value of 0 is
    used,
    > the HTTP and HTTPS default ports (80 and 443) are used.
    > nhttpport = 0
    >
    > *-- Size of the download HTTP buffer used while downloading dynamically
    > sized requests with HTTPGetEx. This is the size of chunks that will be
    > pulled at a time and also determines how often OnHTTPBufferUpdate is
    called.
    > nhttpworkbuffersize = 4096
    >
    > *-- This property is set when calling HTTPGetEx and contains the entire
    HTTP
    > header of a request
    > chttpheaders = ""
    >
    > cUserAgent = "West Wind Internet Protocols 4.20"
    >
    > *-- Flag that can be set in OnHTTPBufferUpdate to allow cancellation of
    the
    > current HTTP download
    > lhttpcanceldownload = .F.
    >
    > *-- HTTP Post mode determines how requests are posted to the server. 1 -
    > Form URLEncoded (default) 2 - Multipart forms. This property must be set
    > prior to calling AddPostKey and HTTPGetEx
    > nhttppostmode = 1
    >
    > *** The POST buffer used internally
    > cPostBuffer = ""
    >
    > *-- Version of the wwIPStuff library. This value should match the DLL
    > Version number.
    > cversion = "4.10"
    >
    > *-- String that specifies the name or IP address of the proxy server and
    its
    > port.
    > chttpproxyname = ""
    >
    > *-- Address of a string variable that contains an optional list of host
    > names or IP addresses, or both, that should not be routed through the
    proxy
    > chttpproxybypass = ""
    >
    > *-- Proxy Authentication info (make sure you use nHTTPConnectType=3)
    > chttpProxyUserName = ""
    > chttpProxyPassword = ""
    >
    > *-- Optional flags used for InternetOpen calls.
    > nserviceflags = 0
    > nHttpServiceFlags = 0
    >
    > ************************************************************************
    > * wwHTTP :: Init
    > *********************************
    > *** Function: Loads the DLL
    > *** Pass: lcPath - Path where to find the DLL. If "" is used
    > *** SYSTEM path or local is assumed. Path must
    > *** be terminated with a trailing backslash
    > ************************************************************************
    > FUNCTION INIT
    > LPARAMETER lcPath
    >
    > lcPath=IIF(VARTYPE(lcPath)="C",lcPath,"")
    >
    > DECLARE INTEGER GetLastError;
    > IN WIN32API
    >
    > RETURN
    >
    >
    >
    > ************************************************************************
    > * wwHTTP :: AddPostKey
    > *********************************
    > *** Function: Adds POST variables to the HTTP request
    > *** Assume: depends on nHTTPPostMode setting
    > *** Pass:
    > *** Return:
    > ************************************************************************
    >
    > ********************************************************
    > * wwHTTP :: HTTPConnect
    > *********************************
    > *** Function: Connect to an HTTP server.
    > *** Assume: Sets two handle values in this class Each
    > *** instance of this class can only manage
    > *** one HTTP session at a time. Use this low
    > *** level function for quick repeated access
    > *** to HTTP pages.
    > *** Pass: lcServer - Server name
    > *** lcUsername - Optional Username
    > *** lcPassword - Optional Password
    > *** llHTTPS - .T. for secure connections
    > *** Return: 0 on success or WinAPI Errorcode
    > ********************************************************
    > FUNCTION HTTPConnect
    > LPARAMETER lcServer, lcUserName, lcPassword, llHTTPS
    > LOCAL lhIP, lhHTTP, lnError, lnHTTPPort
    >
    > lcServer=TRIM(IIF(!EMPTY(lcServer),lcServer,THIS.cserver))
    > lcUserName=TRIM(IIF(!EMPTY(lcUserName),lcUserName,THIS.cusername))
    > lcPassword=TRIM(IIF(!EMPTY(lcPassword),lcPassword,THIS.cpassword))
    >
    > *** Assign Default Ports
    > IF THIS.nhttpport = 0
    > lnHTTPPort = IIF(llHTTPS or THIS.lSecureLink,;
    > INTERNET_DEFAULT_HTTPS_PORT,;
    > INTERNET_DEFAULT_HTTP_PORT)
    > ELSE
    > lnHTTPPort = THIS.nhttpport
    > ENDIF
    >
    > THIS.lsecurelink = llHTTPS OR THIS.lsecurelink
    >
    > THIS.cserver = lcServer
    >
    > THIS.nerror=0
    > THIS.cerrormsg=""
    >
    > DECLARE INTEGER InternetCloseHandle ;
    > IN WinInet.DLL ;
    > INTEGER
    >
    > DECLARE INTEGER GetLastError;
    > IN WIN32API
    >
    > DECLARE INTEGER InternetOpen ;
    > IN WININET.DLL ;
    > STRING,;
    > INTEGER,;
    > STRING, STRING, INTEGER
    >
    > *** Force to Proxy Operation
    > IF !EMPTY(THIS.cHttpProxyName)
    > THIS.nHTTPConnectType = 3 && Proxy
    > ENDIF
    >
    > hInetConnection=;
    > InternetOpen(THIS.cUserAgent,;
    > THIS.nhttpconnecttype,;
    > THIS.chttpproxyname,THIS.chttpproxybypass,0)
    >
    > IF hInetConnection = 0
    > THIS.nerror=GetLastError()
    > THIS.cerrormsg=THIS.getsystemerrormsg(THIS.nerror)
    > RETURN THIS.nerror
    > ENDIF
    >
    > THIS.hipsession=hInetConnection
    >
    > DECLARE INTEGER InternetConnect ;
    > IN WININET.DLL ;
    > INTEGER hIPHandle,;
    > STRING lpzServer,;
    > INTEGER dwPort, ;
    > STRING lpzUserName,;
    > STRING lpzPassword,;
    > INTEGER dwServiceFlags,;
    > INTEGER dwFlags,;
    > INTEGER dwReserved
    >
    >
    > lhHTTPSession=;
    > InternetConnect(hInetConnection,;
    > lcServer,;
    > lnHTTPPort,;
    > lcUserName,;
    > lcPassword,;
    > INTERNET_SERVICE_HTTP,;
    > THIS.nserviceflags,0)
    >
    >
    > IF (lhHTTPSession = 0)
    > =InternetCloseHandle(hInetConnection)
    > THIS.nerror = GetLastError()
    > THIS.cerrormsg = THIS.getsystemerrormsg()
    > RETURN THIS.nerror
    > ENDIF
    >
    > THIS.hhttpsession = lhHTTPSession
    >
    > RETURN 0
    >
    > ********************************************************
    > * wwHTTP :: HTTPClose
    > *********************************
    > *** Function: Closes an HTTP Session.
    > *** Return: nothing
    > ********************************************************
    > FUNCTION httpclose
    >
    > DECLARE INTEGER InternetCloseHandle ;
    > IN WININET.DLL ;
    > INTEGER hIPSession
    >
    > *** Always clear the POST buffer
    > THIS.cPostBuffer = ""
    >
    > IF THIS.hHTTPSession # 0
    > InternetCloseHandle(THIS.hhttpsession)
    > THIS.hhttpsession=0
    > ENDIF
    > IF THIS.hipSession # 0
    > InternetCloseHandle(THIS.hipsession)
    > THIS.hipsession=0
    > ENDIF
    >
    > ENDFUNC
    >
    > ************************************************************************
    > * wwHTTP :: HTTPGet
    > ****************************************
    > *** Function:
    > *** Assume:
    > *** Pass:
    > *** Return:
    > ************************************************************************
    > FUNCTION HTTPGet()
    > LPARAMETERS lcUrl, lcUserName, lcPassword
    > LOCAL lnError, lnSize, lcBuffer, szHead, loUrl, llHTTPS, lnResult,;
    > hInetConnection, hHTTPResult
    >
    > THIS.nerror = 0
    > THIS.cerrormsg = ""
    >
    > IF VARTYPE(lcUserName) = "N"
    > tnBufferSize=lcUserName
    > lcUserName = ""
    > lcPassword = ""
    > ELSE
    > tnBufferSize = 0
    > lcUserName=IIF(EMPTY(lcUserName),"",lcUserName)
    > lcPassword=IIF(EMPTY(lcPassword),"",lcPassword)
    > ENDIF
    >
    >
    > loUrl = THIS.InternetCrackUrl(lcUrl)
    > IF ISNULL(loUrl)
    > THIS.nError = -1
    > THIS.cerrormsg = "Invalid URL passed."
    > RETURN ""
    > ENDIF
    >
    > llHTTPS = IIF(LOWER(loUrl.cProtocol)="https",.T.,.F.)
    > THIS.nHttpPort=VAL(loUrl.cPort)
    >
    > lnResult = THIS.HTTPConnect(loUrl.cserver,lcUserName,lcPassword,llHTTPS)
    > IF lnResult # 0
    > RETURN ""
    > ENDIF
    >
    > IF tnBufferSize # 0
    > lcData=SPACE(tnBufferSize)
    > lnSize=tnBufferSize
    > ELSE
    > lcData = ""
    > lnSize = 0
    > ENDIF
    >
    > lnResult = THIS.HTTPGetEx(loUrl.cPath +
    loUrl.cQueryString,@lcData,@lnSize)
    >
    > THIS.HTTPClose()
    >
    > IF lnResult # 0
    > THIS.cerrormsg = THIS.cerrormsg
    > RETURN ""
    > ENDIF
    >
    > RETURN lcData
    > ENDFUNC
    >
    >
    > ********************************************************
    > * wwHTTP :: HTTPGetEx
    > *********************************
    > *** Function: Retrieves an HTTP request from the
    > *** network and returns a string. Read an
    > *** HTML or data file across the net.
    > *** Assume: Blocking call - waits for completion
    > *** before returning. Use AddPostKey
    > *** to post data to server
    > *** Must call HTTPConnect/HTTPClose to
    > *** manage connection to Server.
    > *** Pass: tcURL - URL to retrieve
    > *** tcBuffer - HTTP result (by Reference)
    > *** tnBufferSize - Size of the buffer (ref)
    > *** tcHeaders - HTTP Headers sent from
    > *** client request. Separate
    > *** key:value pairs with CR
    > *** tcFileName - Optional filename to save
    > *** content to to avoid keeping
    > *** the entire content in memory
    > *** Return: WinAPI Error Code (check THIS.cErrorMsg)
    > *******************************************************
    > FUNCTION HTTPGetEx
    > LPARAMETERS tcPage, tcBuffer, tnBufferSize, tcHeaders, tcFileName
    > LOCAL hHTTPResult, lcOldAlias, lhFile
    >
    > tcPage=IIF(EMPTY(tcPage),THIS.clink,tcPage)
    > tnBufferSize=IIF(VARTYPE(tnBufferSize)="N",;
    > tnBufferSize,LEN(tcPage))
    >
    > lcOldAlias=ALIAS()
    >
    > THIS.lhttpcanceldownload = .F.
    >
    > THIS.clink = tcPage
    >
    > IF !EMPTY(THIS.cPostBuffer)
    > IF THIS.nHTTPPostMode=1 AND RIGHT(THIS.cPostBuffer,1) = "&"
    > THIS.cPostbuffer = LEFT(THIS.cPostbuffer,LEN(THIS.cPostBuffer)-1)
    > ENDIF
    > tnPostSize=LEN(THIS.cPostBuffer)
    > lcPostBuffer= IIF(tnPostSize > 0,THIS.cPostBuffer,NULL)
    > ELSE
    > tnPostSize=0
    > lcPostBuffer=NULL
    > ENDIF
    >
    >
    > THIS.nerror =0
    > THIS.cerrormsg =""
    >
    > DECLARE INTEGER HttpOpenRequest ;
    > IN WININET.DLL ;
    > INTEGER hHTTPHandle,;
    > STRING lpzReqMethod,;
    > STRING lpzPage,;
    > STRING lpzVersion,;
    > STRING lpzReferer,;
    > STRING lpzAcceptTypes,;
    > INTEGER dwFlags,;
    > INTEGER dwContextw
    >
    > *** Keep alive must be used for Proxies
    > IF !EMPTY(THIS.cHTTPProxyName) OR this.nHTTPConnectType = 3
    > THIS.nHTTPServiceFlags = THIS.nHTTPServiceFlags +
    > INTERNET_FLAG_KEEP_CONNECTION
    > ENDIF
    >
    > hHTTPResult=HttpOpenRequest(THIS.hhttpsession,;
    > IIF( tnPostSize > 0, "POST","GET"),;
    > tcPage,;
    > NULL,NULL,NULL,;
    > INTERNET_FLAG_RELOAD + ;
    > IIF(THIS.lsecurelink,INTERNET_FLAG_SECURE,0) + ;
    > this.nHTTPServiceFlags,0)
    >
    >
    > IF (hHTTPResult = 0)
    > THIS.nerror=GetLastError()
    > THIS.cerrormsg=THIS.getsystemerrormsg()
    > RETURN THIS.nerror
    > ENDIF
    >
    > THIS.wininetsettimeout(THIS.nConnectTimeOut,hHTTPResult)
    >
    > THIS.hhttpsession=hHTTPResult
    >
    > THIS.OnHttpPostConnect(hHTTPResult)
    >
    >
    > DECLARE INTEGER HttpSendRequest ;
    > IN WININET.DLL ;
    > INTEGER hHTTPHandle,;
    > STRING lpzHeaders,;
    > INTEGER cbHeaders,;
    > STRING lpzPost,;
    > INTEGER cbPost
    >
    > IF tnPostSize > 0
    > DO CASE
    > CASE THIS.nhttppostmode = 1
    > tcHeaders = "Content-Type: application/x-www-form-urlencoded" +
    > CRLF +;
    > IIF(!EMPTY(tcHeaders),CRLF+tcHeaders,"")
    > CASE THIS.nhttppostmode = 2
    > tcHeaders = "Content-Type: multipart/form-data; boundary=" +
    > MULTIPART_BOUNDARY + CRLF + CRLF +;
    > IIF(EMPTY(tcHeaders),"",tcHeaders)
    >
    > *** NOTE: extra dashes required to simulate browser operation!
    > lcPostBuffer = lcPostBuffer + "--" + MULTIPART_BOUNDARY + CR
    > tnPostSize=LEN(lcPostBuffer)
    > CASE THIS.nhttppostmode = 4 && XML
    > tcHeaders="Content-Type: text/xml" + CRLF +;
    > IIF(EMPTY(tcHeaders),"",tcHeaders)
    > ENDCASE
    > * tcHeaders = tcHeaders + "Content-Length: " + TRANSFORM(tnPostSize) +
    > CRLF
    > ELSE
    > tcHeaders = IIF(!EMPTY(tcHeaders),tcHeaders,"")
    > ENDIF
    >
    > IF !EMPTY(THIS.cHTTPProxyUserName)
    > IF !THIS.SetProxyLogin()
    > RETURN THIS.nError
    > ENDIF
    > ENDIF
    >
    > lnRetval=0
    > lnRetval=HttpSendRequest(hHTTPResult,;
    > tcHeaders,LEN(tcHeaders),;
    > lcPostBuffer,tnPostSize)
    >
    > IF lnRetval = 0
    > THIS.nerror=GetLastError()
    > THIS.cerrormsg=THIS.getsystemerrormsg()
    > =InternetCloseHandle(hHTTPResult)
    > RETURN THIS.nerror
    > ENDIF
    >
    > DECLARE INTEGER HttpQueryInfo ;
    > IN WININET.DLL ;
    > INTEGER hHTTPHandle,;
    > INTEGER nType,;
    > STRING @cHeaders,;
    > INTEGER @cbHeaderSize,;
    > STRING cNULL
    >
    > *** Retrieve the HTTP Headers
    > lcHeaders = SPACE(1024)
    > lnHeaderSize = 1024
    > lnRetval = HttpQueryInfo(hHTTPResult,;
    > HTTP_QUERY_RAW_HEADERS_CRLF,;
    > @lcHeaders,@lnHeaderSize,NULL)
    > THIS.chttpheaders = TRIM(STRTRAN(lcHeaders,CHR(0),""))
    >
    > *** Check the HTTP Result Code
    > lcHeaders = SPACE(7)
    > lnHeaderSize = 6
    > lnRetval = HttpQueryInfo(hHTTPResult,;
    > HTTP_QUERY_STATUS_CODE,;
    > @lcHeaders,@lnHeaderSize,NULL)
    > lcResultCode = TRIM(STRTRAN(lcHeaders,CHR(0),""))
    >
    > IF lcResultCode # "200"
    > lcHeaders = SPACE(256)
    > lnHeaderSize = 255
    > lnRetval = HttpQueryInfo(hHTTPResult,;
    > HTTP_QUERY_STATUS_TEXT,;
    > @lcHeaders,@lnHeaderSize,NULL)
    > THIS.nerror=VAL(lcResultCode)
    > THIS.cErrorMsg = TRIM(STRTRAN(lcHeaders,CHR(0),""))
    > =InternetCloseHandle(hHTTPResult)
    > RETURN THIS.nerror
    > ENDIF
    >
    >
    > *** Call HTTP Event method
    > THIS.OnHTTPBufferUpdate(0,0,THIS.chttpheaders)
    >
    > DECLARE INTEGER InternetReadFile ;
    > IN WININET.DLL ;
    > INTEGER hHTTPHandle,;
    > STRING @lcBuffer,;
    > INTEGER cbBuffer,;
    > INTEGER @cbBuffer
    >
    > IF tnBufferSize > 0
    > *** Use Fixed Buffer Size
    > tcBuffer=SPACE(tnBufferSize)
    > lnBufferSize=tnBufferSize
    > lnRetval=InternetReadFile(hHTTPResult,;
    > @tcBuffer,;
    > tnBufferSize,;
    > @tnBufferSize)
    > ELSE
    > *** If a filename was specified output to the file instead of string
    > IF !EMPTY(tcFileName)
    > lhFile = FCREATE(tcFileName)
    > IF lhFile = -1
    > THIS.nerror=1
    > THIS.cerrormsg="Couldn't create output file"
    > =InternetCloseHandle(hHTTPResult)
    > RETURN THIS.nerror
    > ENDIF
    > ENDIF
    >
    > *** Build the buffer dynamically
    > tcBuffer = ""
    > tnSize = 0
    > lnRetval = 0
    > lnBytesRead = 1
    > lnBufferReads = 0
    > DO WHILE .T.
    > lcReadBuffer = SPACE(THIS.nhttpworkbuffersize)
    > lnBytesRead = 0
    > lnSize = LEN(lcReadBuffer)
    >
    > lnRetval=InternetReadFile(hHTTPResult,;
    > @lcReadBuffer,;
    > lnSize,;
    > @lnBytesRead)
    >
    > IF lnRetval = 1 AND lnBytesRead > 0
    > *** Update the input parameters - result buffer and size of
    buffer
    > IF EMPTY(tcFileName)
    > *** Build string
    > tcBuffer = tcBuffer + LEFT(lcReadBuffer,lnBytesRead)
    > ELSE
    > *** Write to file
    > FWRITE(lhFile,lcReadBuffer,lnBytesRead)
    > ENDIF
    > tnBufferSize = tnBufferSize + lnBytesRead
    > lnBufferReads = lnBufferReads + 1
    > THIS.OnHTTPBufferUpdate(tnBufferSize,lnBufferReads,@lcReadBuffer)
    > ENDIF
    > IF THIS.lhttpcanceldownload
    > tcBuffer = "Error: Download canceled"
    > tnBufferSize = LEN(tcBuffer)
    > THIS.nError = -2
    > THIS.cErrorMsg = "Download Cancelled"
    > EXIT
    > ENDIF
    > IF (lnRetval = 1 AND lnBytesRead = 0) OR (lnRetval = 0)
    > EXIT
    > ENDIF
    > ENDDO
    > lnBufferSize = tnBufferSize
    >
    > IF !EMPTY(tcFileName)
    > FCLOSE(lhFile)
    > ENDIF
    >
    > THIS.OnHTTPBufferUpdate(0,-1,"")
    > ENDIF
    >
    > IF lnRetval = 0
    > THIS.nerror=GetLastError()
    > THIS.cerrormsg=THIS.getsystemerrormsg()
    > ENDIF
    >
    > =InternetCloseHandle(hHTTPResult);
    >
    > tcBuffer = (IIF(tnBufferSize > 1 AND tnBufferSize <=
    > lnBufferSize,SUBSTR(tcBuffer,1,tnBufferSize),""))
    >
    > RETURN THIS.nerror
    >
    > ************************************************************************
    > * wwHTTP :: 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
    > ************************************************************************
    > LPARAMETERS tcPage, tcHeaders, tnHeaderSize
    > LOCAL lnError, lnSize, lcBuffer
    >
    > tcHeaders=IIF(TYPE("tcHeaders")="C",tcHeaders,"")
    > tnHeaderSize=IIF(TYPE("tnHeaderSize")="N",tnHeaderSize,2048)
    >
    > IF !EMPTY(THIS.cPostBuffer)
    > tnPostSize=LEN(THIS.cPostBuffer)
    > lcPostBuffer= IIF(tnPostSize > 0,THIS.cPostBuffer,NULL)
    > ELSE
    > tnPostSize=0
    > lcPostBuffer=NULL
    > ENDIF
    >
    > DECLARE INTEGER HttpOpenRequest ;
    > IN WININET.DLL ;
    > INTEGER hHTTPHandle,;
    > STRING lpzReqMethod,;
    > STRING lpzPage,;
    > STRING lpzVersion,;
    > STRING lpzReferer,;
    > STRING lpzAcceptTypes,;
    > INTEGER dwFlags,;
    > INTEGER dwContextw
    >
    > hHTTPResult=HttpOpenRequest(THIS.hhttpsession,;
    > IIF( tnPostSize > 0, "POST","GET"),;
    > tcPage,;
    > NULL,NULL,NULL,;
    > INTERNET_FLAG_RELOAD + IIF(THIS.lsecurelink,INTERNET_FLAG_SECURE,0),0)
    >
    >
    > IF (hHTTPResult = 0)
    > THIS.nerror=GetLastError()
    > THIS.cerrormsg=THIS.getsystemerrormsg()
    > RETURN THIS.nerror
    > ENDIF
    >
    >
    > DECLARE INTEGER HttpSendRequest ;
    > IN WININET.DLL ;
    > INTEGER hHTTPHandle,;
    > STRING lpzHeaders,;
    > INTEGER cbHeaders,;
    > STRING lpzPost,;
    > INTEGER cbPost
    >
    > lcHeaders=TRIM(tcHeaders)
    >
    > lnRetval=HttpSendRequest(hHTTPResult,;
    > lcHeaders,LEN(lcHeaders),;
    > lcPostBuffer,tnPostSize)
    >
    > IF lnRetval = 0
    > THIS.nerror=GetLastError()
    > THIS.cerrormsg=THIS.getsystemerrormsg()
    > RETURN THIS.nerror
    > ENDIF
    >
    > DECLARE INTEGER HttpQueryInfo ;
    > IN WININET.DLL ;
    > INTEGER hHTTPHandle,;
    > INTEGER nType,;
    > STRING @cHeaders,;
    > INTEGER @cbHeaderSize,;
    > STRING cNULL
    >
    > lnRetval = HttpQueryInfo(hHTTPResult,;
    > HTTP_QUERY_RAW_HEADERS_CRLF,;
    > @tcHeaders,@tnHeaderSize,NULL)
    > IF (lnRetval = 0)
    > THIS.nerror=GetLastError()
    > THIS.cerrormsg=THIS.getsystemerrormsg()
    > RETURN THIS.nerror
    > ENDIF
    >
    > InternetCloseHandle(hHTTPResult);
    >
    > tcHeaders = (IIF(tnHeaderSize > 1,SUBSTR(tcHeaders,1,tnHeaderSize-1),""))
    >
    > RETURN lnError
    >
    >
    > ********************************************************
    > * wwHTTP :: HTTPGetExAsync
    > *********************************
    > *** Function: Retrieves an HTTP request from the
    > *** network asynchronously. This means the
    > *** request fires and returns immediately
    > *** without an error code. Operation runs on
    > *** new thread in the background after returing
    > *** control to VFP.
    > ***
    > *** This method is fully self contained.
    > *** You don't need to call HTTPOpen or HTTPClose.
    > ***
    > *** This method allows full configuration
    > *** of the request with: POST data, SSL,
    > *** Passwords and creation of an output
    > *** file.
    > ***
    > *** Use AddPostKey to add POST vars. Use lSecureLink
    > *** to enable SSL operation. Use cUserName and cPassword
    > *** for passwords.
    > ***
    > *** Output file option allows for async
    > *** downloads and later checking for a result.
    > *** Using a timer it's possible to fire 'events'
    > *** when the download is complete.
    > ***
    > *** Pass: tcURL - Server relative link (/default.asp)
    > *** tcResultFile - File where result get stored to
    > *** Make sure this is file unique...
    > *** tnResultSize - If you're saving the result you
    > *** can use this to specify the size
    > *** Default is a small 256 (used for
    > *** not checking results).
    > *** Used: lSecureLink, cUserName, cPassword, AddPostKey()
    > *** Return: nothing
    > *** If tcResultFile is passed you can check
    > *** for this file. On success you'll get the
    > *** document. On failure you get:
    > *** Error: <nAPIErrorCode>
    > *******************************************************
    > FUNCTION httpgetexasync
    > LPARAMETERS tcPage, tcResultFile, tnResultSize, tcHeaders
    > LOCAL hHTTPResult
    >
    > *** Post Buffer and lSecureLink also apply via properties
    > tcServer=THIS.cserver
    > tcPage=IIF(EMPTY(tcPage),"/",tcPage)
    > tcUserName=THIS.cusername
    > tcPassword=THIS.cpassword
    > tcResultFile=IIF(EMPTY(tcResultFile),"",tcResultFile)
    > tnResultSize=IIF(EMPTY(tnResultSize),256,tnResultSize)
    >
    > IF !EMPTY(THIS.cPostBuffer)
    > tnPostSize=LEN(THIS.cPostBuffer)
    > lcPostBuffer= IIF(tnPostSize > 0,THIS.cPostBuffer,NULL)
    > ELSE
    > tnPostSize=0
    > lcPostBuffer=NULL
    > ENDIF
    >
    >
    > IF tnPostSize > 0
    > IF EMPTY(tcHeaders)
    > IF THIS.nhttppostmode = 1
    > tcHeaders = "Content-Type: application/x-www-form-urlencoded" +
    > CR+;
    > IIF(!EMPTY(tcHeaders),CR+tcHeaders,"")
    > ELSE
    > tcHeaders = "Content-Type: multipart/form-data; boundary=" +
    > MULTIPART_BOUNDARY + CR + CR +;
    > IIF(EMPTY(tcHeaders),"",tcHeaders)
    >
    > IF tnPostSize > 0
    > lcPostBuffer = lcPostBuffer + MULTIPART_BOUNDARY + CR
    > tnPostSize=LEN(lcPostBuffer)
    > ENDIF
    > ENDIF
    > ENDIF
    > ELSE
    > tcHeaders = IIF(!EMPTY(tcHeaders),tcHeaders,"")
    > ENDIF
    >
    > lcOldAlias=ALIAS()
    >
    >
    > DECLARE HTTPGetExAsync ;
    > IN WWIPSTUFF.DLL ;
    > INTEGER hInternet,;
    > INTEGER hHTTP,;
    > STRING SERVER,;
    > STRING PAGE,;
    > STRING BUFFER,;
    > INTEGER BufferSize,;
    > STRING HEADER,;
    > STRING POST,;
    > INTEGER POSTSIZE,;
    > INTEGER SECURE,;
    > INTEGER CONNECTTYPE,;
    > STRING Username, STRING PASSWORD,;
    > STRING ResultFile,;
    > INTEGER ResultSize
    >
    > tcBuffer = SPACE(256)
    > tnBufSize = LEN(tcBuffer)
    > lnRet = httpgetexasync(THIS.hipsession, THIS.hhttpsession,;
    > tcServer,;
    > tcPage,;
    > tcBuffer,tnBufSize,;
    > tcHeaders,;
    > lcPostBuffer, tnPostSize,;
    > IIF(THIS.lsecurelink,1,0),;
    > THIS.nhttpconnecttype,;
    > tcUserName, tcPassword,;
    > tcResultFile,tnResultSize)
    >
    > *** Cause HTTPClose() to have no effect on these
    > *** handles - the C thread code will clean these up
    > THIS.hIPSession = 0
    > THIS.hHTTPSession = 0
    >
    > RETURN
    >
    >
    > ************************************************************************
    > * 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
    > ************************************************************************
    > FUNCTION HTTPGetHeader
    > LPARAMETERS tcPage, tcHeaders, tnHeaderSize
    > LOCAL lnError, lnSize, lcBuffer
    >
    > tcHeaders=IIF(TYPE("tcHeaders")="C",tcHeaders,"")
    > tnHeaderSize=IIF(TYPE("tnHeaderSize")="N",tnHeaderSize,2048)
    >
    > IF USED("wwPostBuffer")
    > SELE wwPostBuffer
    > tnPostSize=LEN(wwPostBuffer.cPostBuffer)
    > lcPostBuffer= IIF(tnPostSize > 0,wwPostBuffer.cPostBuffer,NULL)
    > ELSE
    > tnPostSize=0
    > lcPostBuffer=NULL
    > ENDIF
    >
    > DECLARE INTEGER HttpOpenRequest ;
    > IN WININET.DLL ;
    > INTEGER hHTTPHandle,;
    > STRING lpzReqMethod,;
    > STRING lpzPage,;
    > STRING lpzVersion,;
    > STRING lpzReferer,;
    > STRING lpzAcceptTypes,;
    > INTEGER dwFlags,;
    > INTEGER dwContextw
    >
    > hHTTPResult=HttpOpenRequest(THIS.hHTTPSession,;
    > IIF( tnPostSize > 0, "POST","GET"),;
    > tcPage,;
    > NULL,NULL,NULL,;
    > INTERNET_FLAG_RELOAD + IIF(THIS.lSecureLink,INTERNET_FLAG_SECURE,0),0)
    >
    >
    > IF (hHTTPResult = 0)
    > THIS.nError=GetLastError()
    > THIS.cErrorMsg=THIS.GetSystemErrorMsg()
    > RETURN THIS.nError
    > ENDIF
    >
    >
    > DECLARE INTEGER HttpSendRequest ;
    > IN WININET.DLL ;
    > INTEGER hHTTPHandle,;
    > STRING lpzHeaders,;
    > INTEGER cbHeaders,;
    > STRING lpzPost,;
    > INTEGER cbPost
    >
    > lcHeaders=TRIM(tcHeaders)
    >
    > lnRetval=HttpSendRequest(hHTTPResult,;
    > lcHeaders,LEN(lcHeaders),;
    > lcPostBuffer,tnPostSize)
    >
    > IF lnRetval = 0
    > THIS.nError=GetLastError()
    > THIS.cErrorMsg=THIS.GetSystemErrorMsg()
    > RETURN THIS.nError
    > ENDIF
    >
    > DECLARE INTEGER HttpQueryInfo ;
    > IN WININET.DLL ;
    > INTEGER hHTTPHandle,;
    > INTEGER nType,;
    > STRING @cHeaders,;
    > INTEGER @cbHeaderSize,;
    > STRING cNULL
    >
    > lnRetval = HttpQueryInfo(hHTTPResult,;
    > HTTP_QUERY_RAW_HEADERS_CRLF,;
    > @tcHeaders,@tnHeaderSize,NULL)
    >
    > IF (lnRetval = 0)
    > THIS.nError=GetLastError()
    > THIS.cErrorMsg=THIS.GetSystemErrorMsg()
    > RETURN THIS.nError
    > ENDIF
    >
    > InternetCloseHandle(hHTTPResult);
    >
    > tcHeaders = (IIF(tnHeaderSize > 1,SUBSTR(tcHeaders,1,tnHeaderSize-1),""))
    >
    > RETURN lnRetVal
    >
    >
    >
    > *-- Gets called whenever the buffer is updated on an HTTPGetEx update.
    Only
    > applies if the buffer size is set to 0 (Automatic sizing)
    > FUNCTION OnHTTPBufferUpdate
    > LPARAMETER lnBytesDownloaded,lnBufferReads,lcCurrentChunk
    > ENDFUNC
    >
    > *-- Event that fires in HttpGetEx calls after the Connection is
    established
    > *-- Can be used to set WinInet options or otherwise insert code to fire
    > *-- before the request is sent to the server
    > FUNCTION OnHttpPostConnect
    > LPARAMETERS lnHttpHandle
    > ENDFUNC
    >
    > *-- Cancels an HTTPGetEx download if the buffer is sized dynamically
    > FUNCTION httpcanceldownload
    > THIS.lhttpcanceldownload = .T.
    > ENDFUNC
    >
    > ************************************************************************
    > * wwHTTP :: SetProxyLogin
    > ****************************************
    > *** Function: Sets the HTTP Proxy username and password
    > *** Assume: thanks to Erik Moore for providing this method
    > *** Pass: tcUserName
    > *** tcPassword
    > *** hIPHandle - HTTP Request handle (optional)
    > *** Return: .T. or .F.
    > ************************************************************************
    > PROTECTED FUNCTION SetProxyLogin(tcUserName, tcPassword, hIPHandle)
    >
    > LOCAL lcUsername, lcPassword, lpBuffer, lpdwBufferLength, nSuccess
    >
    > lcUserName = IIF(!EMPTY(tcUserName),tcUserName,THIS.cHTTPProxyUserName)
    > lcPassword = IIF(!EMPTY(tcPassword),tcPassword,THIS.cHTTPProxyPassword)
    > hIPHandle = IIF(EMPTY(hIPHandle),THIS.hHTTPSession,hIPHandle)
    >
    > IF EMPTY(lcUsername)
    > RETURN
    > ENDIF
    >
    > DECLARE INTEGER InternetSetOption IN WinInet.dll ;
    > INTEGER hInternet, ;
    > INTEGER dwOption, ;
    > STRING @lpBuffer, ;
    > LONG lpdwBufferLength
    >
    > INTERNET_OPTION_PROXY_USERNAME = 43
    > INTERNET_OPTION_PROXY_PASSWORD = 44
    >
    > IF !EMPTY(lcUserName)
    > lpBuffer = lcUserName
    > dwBufferLength = LEN(lpBuffer)
    > dwOption = INTERNET_OPTION_PROXY_USERNAME
    > nSuccess = InternetSetOption(hIPHandle, dwOption, @lpBuffer,
    > dwBufferLength)
    > IF nSuccess <> 1
    > THIS.nError = GetLastError()
    > THIS.cErrorMsg = THIS.GetSystemErrorMsg(THIS.nError)
    > RETURN .F.
    > ENDIF
    > ENDIF
    >
    > IF !EMPTY(lcPassword)
    > lpBuffer = lcpassword
    > dwBufferLength = LEN(lpBuffer)
    > dwOption = INTERNET_OPTION_PROXY_PASSWORD
    > nSuccess = InternetSetOption(hIPHandle, dwOption, @lpBuffer,
    > dwBufferLength)
    > IF nSuccess <> 1
    > THIS.nError = GetLastError()
    > THIS.cErrorMsg = THIS.GetSystemErrorMsg(THIS.nError)
    > RETURN .F.
    > ENDIF
    > ENDIF
    >
    > RETURN .T.
    > ENDFUNC
    >
    >
    >
    >
    > ************************************************************************
    > * wwHTTP :: HTTPPing
    > ****************************************
    > *** Function: Checks whether a site is up by a timeout value
    > *** Assume: IE 5.5 or later is installed
    > *** Pass: lnTimeout - in seconds
    > *** lcServer - (ie. www.west-wind.com)
    > *** lcLink - optional link to hit (/default.htm)
    > *** Return:
    > ************************************************************************
    > FUNCTION httpping
    > LPARAMETER lnTimeout, lcServer, lcLink
    > LOCAL lcFile, llSuccess, lnHandle
    >
    > IF EMPTY(lcLink)
    > lcLink = "/"
    > ENDIF
    >
    > lnSaveTimeout = THIS.nConnectTimeout
    > THIS.nConnectTimeout = lnTimeout
    >
    > lcResult = THIS.HTTPGet("http://" + lcServer + lcLink)
    >
    > THIS.nConnectTimeout = lnSaveTimeout
    >
    > IF THIS.nError = 0
    > RETURN .T.
    > ENDIF
    >
    > RETURN .F.
    >
    >
    > ************************************************************************
    > * wwHTTP :: InternetCrackUrl
    > *********************************
    > *** Function: Breaks out a URL into its component pieces
    > *** Pass: lcURL - URL to crack
    > *** Return: loUrl or NULL
    > ************************************************************************
    > FUNCTION InternetCrackUrl
    > LPARAMETERS lcUrl
    > LOCAL lnAT, lcProtocol, lcQuerystring, lcPort, lcServer
    >
    > *lcUrl = LOWER(lcUrl)
    >
    > *** Find the querystring first
    > lnAT = AT("?",lcUrl)
    > IF lnAT > 0
    > lcQuerystring = SUBSTR(lcUrl,lnAT)
    > lcUrl = LEFT(lcUrl,lnAT-1)
    > ELSE
    > lcQuerystring = ""
    > ENDIF
    >
    > lnAT = AT("://",lcUrl)
    > IF lnAT < 1
    > RETURN .NULL.
    > ENDIF
    >
    > lcProtocol = lower(LEFT(lcUrl,lnAT-1))
    > DO CASE
    > CASE lcProtocol == "http"
    > lcPort = "80"
    > CASE lcProtocol == "https"
    > lcPort = "443"
    > CASE lcProtocol == "ftp"
    > lcPort = "21"
    > OTHERWISE
    > *** Assume HTTP
    > lcPort = "80"
    > ENDCASE
    >
    > lcUrl = SUBSTR(lcUrl,lnAT + 3)
    > lnAT = AT(":",lcUrl)
    >
    > IF lnAT > 0
    > lcPort = STRExtract(lcUrl,":","/")
    > lcServer = LEFT(lcUrl,lnAT-1)
    > lcUrl = SUBSTR(lcUrl,lnAT + LEN(lcPort) + 1)
    > ELSE
    > lnAT = AT("/",lcUrl)
    > IF lnAT = 0
    > lcServer = lcUrl
    > lcUrl = ""
    > ELSE
    > lcServer = SUBSTR(lcUrl,1,lnAT-1)
    > lcURL = SUBSTR(lcUrl,lnAt)
    > ENDIF
    > ENDIF
    >
    > loUrl = CREATE("RELATION")
    > loUrl.ADDPROPERTY("cProtocol",lcProtocol)
    > loUrl.ADDPROPERTY("cServer",lcServer)
    > loUrl.ADDPROPERTY("cPath",lcUrl) && What's left of the url
    > loUrl.ADDPROPERTY("cquerystring",lcQuerystring)
    > loUrl.ADDPROPERTY("cPort",lcPort)
    >
    > *** Not implementented
    > loURL.AddProperty("cUserName","")
    > loUrl.AddProperty("cPassword","")
    >
    > RETURN loUrl
    > ENDFUNC
    > * wwHTTP :: InternetCrackUrl FUNCTION InternetCrackUrl
    >
    > ********************************************************
    > * wwHTTP :: WinInetSetTimeout
    > *********************************
    > *** Function: Sets various timeout for use with a
    > *** WinInet Connection
    > *** Pass: dwTimeoutSecs - Secs to wait for timeout
    > ********************************************************
    > FUNCTION wininetsettimeout
    > LPARAMETERS dwTimeoutSecs, lnHandle
    >
    > dwTimeoutSecs=IIF(VARTYPE(dwTimeoutSecs)="N",;
    > dwTimeoutSecs,THIS.nconnecttimeout)
    >
    > IF dwTimeoutSecs = 0
    > *** Just use the default
    > RETURN
    > ENDIF
    >
    > IF EMPTY(lnHandle)
    > lnHandle = THIS.hIPSession
    > ENDIF
    >
    > DECLARE INTEGER InternetSetOption ;
    > IN WININET.DLL ;
    > INTEGER HINTERNET,;
    > INTEGER dwFlags,;
    > INTEGER @dwValue,;
    > INTEGER
    >
    >
    > dwTimeoutSecs=dwTimeoutSecs * 1000 && to milliseconds
    > llRetVal=InternetSetOption(lnHandle,;
    > INTERNET_OPTION_CONNECT_TIMEOUT,;
    > @dwTimeoutSecs,4)
    >
    > llRetVal=InternetSetOption(lnHandle,;
    > INTERNET_OPTION_RECEIVE_TIMEOUT,;
    > @dwTimeoutSecs,4)
    >
    > llRetVal=InternetSetOption(lnHandle,;
    > INTERNET_OPTION_SEND_TIMEOUT,;
    > @dwTimeoutSecs,4)
    >
    > * dwTimeoutSecs=1 &&// Retry only 1 time
    > * llRetVal=InternetSetOption(lnHandle,;
    > * INTERNET_OPTION_CONNECT_RETRIES,;
    > * @dwTimeoutSecs,4)
    > RETURN
    >
    >
    >
    > ************************************************************************
    > * wwHTTP :: GetLastInternetError
    > *********************************
    > *** Function: Retrieves the last WinInet error using WinInet's error
    > *** responses.
    > *** Assume: Currently not used by class internally
    > *** Under Construction
    > *** Pass: lnError - Error Code to resolve(Optional)
    > *** Return: Error Message or ""
    > ************************************************************************
    > FUNCTION getlastinterneterror
    > LPARAMETERS lnError
    >
    > lnError=IIF(TYPE("lnError")="N",lnError,THIS.nerror)
    >
    > DECLARE INTEGER InternetGetLastResponseInfo ;
    > IN WININET.DLL ;
    > INTEGER @lpdwError,;
    > STRING @lpszBuffer,;
    > INTEGER @lpcbSize
    >
    > lcErrorMsg=SPACE(1024)
    > lnSize=LEN(lcErrorMsg)
    >
    > =InternetGetLastResponseInfo(@lnError,@lcErrorMsg,@lnSize)
    >
    > IF lnSize < 2
    > RETURN ""
    > ENDIF
    >
    > RETURN SUBSTR(lcErrorMsg,1,lnSize)
    > ENDFUNC
    >
    > ************************************************************************
    > * wwHTTP :: GetPostBuffer
    > *********************************
    > *** Function: Returns the entire Post Buffer as a string
    > ************************************************************************
    > FUNCTION getpostbuffer
    > RETURN THIS.cPostBuffer
    > ENDFUNC
    >
    >
    > ********************************************************
    > * wwHTTP :: GetSystemErrorMsg
    > *********************************
    > *** Function: Returns an Error Message for the last
    > *** error value set in nError property.
    > *** Assume: nError was set by last operation
    > *** Return: Error String or ""
    > ********************************************************
    > FUNCTION getsystemerrormsg
    > LPARAMETERS lnErrorNo, llAPI
    > LOCAL szMsgBuffer,lnSize
    >
    > lnErrorNo=IIF(TYPE("lnErrorNo")="N",lnErrorNo,THIS.nerror)
    >
    > IF lnErrorNo = ERROR_INTERNET_EXTENDED_ERROR
    > RETURN THIS.getlastinterneterror()
    > ENDIF
    >
    > szMsgBuffer=SPACE(500)
    > DECLARE INTEGER FormatMessage ;
    > IN WIN32API ;
    > INTEGER dwFlags ,;
    > INTEGER lpvSource,;
    > INTEGER dwMsgId,;
    > INTEGER dwLangId,;
    > STRING @lpBuffer,;
    > INTEGER nSize,;
    > INTEGER Arguments
    >
    > DECLARE INTEGER GetModuleHandle ;
    > IN WIN32API ;
    > STRING
    >
    > lnModule=GetModuleHandle("wininet.dll")
    > IF lnModule # 0 AND !llAPI
    > lnSize=FormatMessage(FORMAT_MESSAGE_FROM_HMODULE,lnModule,lnErrorNo,;
    > 0,@szMsgBuffer,LEN(szMsgBuffer),0)
    > ELSE
    > lnSize=0
    > ENDIF
    >
    > IF lnSize > 2
    > szMsgBuffer=SUBSTR(szMsgBuffer,1, lnSize -2 )
    > ELSE
    > *** REtry with 12000 less - WinInet return Windows API file error codes
    > lnSize=FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,0,lnErrorNo,;
    > 0,@szMsgBuffer,LEN(szMsgBuffer),0)
    >
    > IF lnSize > 2
    > szMsgBuffer="Win32 API: " + SUBSTR(szMsgBuffer,1, lnSize-2 )
    > ELSE
    > szMsgBuffer=""
    > ENDIF
    > ENDIF
    >
    > RETURN szMsgBuffer
    > ENDFUNC
    >
    >
    >
    > ************************************************************************
    > * wwHTTP :: Destroy
    > *********************************
    > *** Function: Clears HTTP Session Handles if open
    > ************************************************************************
    > FUNCTION DESTROY
    >
    > IF THIS.hipsession # 0 OR THIS.hhttpsession # 0
    > THIS.httpclose()
    > ENDIF
    >
    > ENDFUNC
    >
    >
    >
    > ENDDEFINE
    > *
    > *-- EndDefine: wwHTTP
    > **************************************************
    >
    >


  • Next message: Villi Bernaroli: "reversed "print when" in last page"
  • Quantcast