Re: URL2PDF()

From: Gerben Kessen (gerben.kessen(_at_)wantit.nl)
Date: 05/26/04

  • Next message: Dorian C. Chalom: "Re: URL2PDF()"
    Date: Wed, 26 May 2004 20:40:42 +0200
    
    

    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: Dorian C. Chalom: "Re: URL2PDF()"
  • Quantcast