478 lines
15 KiB
Plaintext
478 lines
15 KiB
Plaintext
compile function rti_HTTP_Download_UI( object, method, param1, param2, param3, param4, param5, param6, param7, param8 )
|
|
/*
|
|
** Copyright (C) 2012-2019 Revelation Software Inc. All Rights Reserved **
|
|
|
|
Author : Captain C
|
|
Date : June 2019
|
|
Purpose : Commuter module for the RTI_HTTP_DOWNLOAD_UI form
|
|
|
|
|
|
Comments
|
|
========
|
|
|
|
|
|
Amended Date Reason
|
|
======= ==== ======
|
|
Mr C 09 Mar 22 The form's visibility is controlled from it's caller
|
|
(i.e. rti_HTTP_Download)
|
|
*/
|
|
#pragma precomp event_precomp
|
|
|
|
declare function get_Property, retStack, rti_Res2Str, rti_ErrorText
|
|
declare function rti_Convert, msWin_GetTickCount64, exec_Method
|
|
$insert rti_HTTP_Download_Equates
|
|
$insert ps_HTTPClient_Equates
|
|
$insert rti_Resources_Equates
|
|
$insert rti_SSP_Equates
|
|
$insert logical
|
|
|
|
equ UDP_TIMEDATA$ to "@_TIMEDATA"
|
|
|
|
if assigned( object ) else object = ""
|
|
if assigned( method ) else method = ""
|
|
if assigned( param1 ) else param1 = ""
|
|
if assigned( param2 ) else param2 = ""
|
|
if assigned( param3 ) else param3 = ""
|
|
if assigned( param4 ) else param4 = ""
|
|
if assigned( param5 ) else param5 = ""
|
|
if assigned( param6 ) else param6 = ""
|
|
if assigned( param7 ) else param7 = ""
|
|
if assigned( param8 ) else param8 = ""
|
|
|
|
errorText = ""
|
|
abort = FALSE$
|
|
retVal = ""
|
|
|
|
atWindow = object[1,"."]
|
|
atCtrl = object[col2()+1,\00\]
|
|
if bLen( atWindow ) else
|
|
atWindow = @window
|
|
end
|
|
|
|
if bLen( method ) then
|
|
locate method in "CREATE,CLOSE,PROGRESS,READYSTATECHANGED,TIMEOUT" using "," setting pos then
|
|
on pos goSub onCreate,onClose,onProgress,onReadyStateChanged,onTimeout
|
|
end else
|
|
// ERR002: Invalid method "%1% passed to the %2% procedure
|
|
errorText = rti_Res2Str( RESID$, "ERR002", method : @fm : retStack()<1> )
|
|
abort = TRUE$
|
|
end
|
|
end else
|
|
// ERR001: No method passed to the %1% procedure
|
|
errorText = rti_Res2Str( RESID$, "ERR001", retStack()<1> )
|
|
abort = TRUE$
|
|
end
|
|
|
|
return retVal
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// onClose subroutine
|
|
//
|
|
// CLOSE event handler for the
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
onClose:
|
|
|
|
rs = .hcl_Download->readyState
|
|
begin case
|
|
case ( rs == PS_HCL_RS_UNSENT$ )
|
|
null
|
|
case ( rs == PS_HCL_RS_DONE$ )
|
|
null
|
|
case OTHERWISE$
|
|
@@window->$@_ABORT = TRUE$
|
|
.hcl_Download->abort( "" )
|
|
goSub hclDownload_ReturnResponse
|
|
end case
|
|
|
|
return
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// onCreate subroutine
|
|
//
|
|
// CREATE event handler
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
// [i] param1 : CreateParam. Contains an @fm delimited list UI information
|
|
// : as passed to the RTI_HTTP_DOWNLOAD proc
|
|
// ----------------------------------------------------------------------------
|
|
onCreate:
|
|
|
|
@@window->$@_CREATEPARAM = param1
|
|
|
|
startTime = msWin_GetTickCount64()
|
|
prevTime = startTime
|
|
timeData = startTime : @fm : prevTime
|
|
|
|
@@window->$@_TIMEDATA = timeData
|
|
|
|
if ( param1<HDL_UIPARAM_POS_SYNCPROGRESS$> ) then
|
|
.prb_Download->SyncTaskBar = TRUE$
|
|
end
|
|
|
|
// The form's visibility is controlled from rti_HTTP_Download()
|
|
// @atWindow->visible = TRUE$
|
|
|
|
if ( param1<HDL_UIPARAM_POS_MODAL$> ) then
|
|
call set_Property( param1<HDL_UIPARAM_POS_PARENTWIN$>, "ENABLED", FALSE$ )
|
|
end
|
|
|
|
// We're all set - return to the caller to set the HCL_DOWNLOAD properties
|
|
// execute the OPEN/SEND methods ...
|
|
|
|
return
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// onProgress subroutine
|
|
//
|
|
// PROGRESS event dispatch handler
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
// [i] param1 : bytesReceived. Number of bytes received between this PROGRESS
|
|
// : event and the previous one
|
|
// [i] param2 : bytesDownloaded. Total Number of bytes downloaded so far
|
|
// [i] param3 : bytesExpected. Total number of bytes expected from the server
|
|
// ----------------------------------------------------------------------------
|
|
onProgress:
|
|
|
|
bytesReceived = param1
|
|
bytesDownloaded = param2
|
|
bytesExpected = param3
|
|
|
|
begin case
|
|
case ( atCtrl == "HCL_DOWNLOAD" )
|
|
goSub hclDownload_OnProgress
|
|
end case
|
|
|
|
return
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// onReadyStateChanged subroutine
|
|
//
|
|
// READYSTATECHANGED event dispatch handler
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
// [i] param1 : newState
|
|
// ----------------------------------------------------------------------------
|
|
onReadyStateChanged:
|
|
|
|
newState = param1
|
|
|
|
begin case
|
|
case ( atCtrl == "HCL_DOWNLOAD" )
|
|
goSub hclDownload_OnReadyStateChanged
|
|
end case
|
|
|
|
return
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// onTimeout subroutine
|
|
//
|
|
// TIMEOUT event dispatch handler
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
// [i] param1 : StatusID, identifies the handle that timed out (connect, open,
|
|
// : request)
|
|
// ----------------------------------------------------------------------------
|
|
onTimeout:
|
|
|
|
statusID = param1
|
|
|
|
begin case
|
|
case ( atCtrl == "HCL_DOWNLOAD" )
|
|
goSub hclDownload_OnTimeout
|
|
end case
|
|
|
|
return
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#region HCL_DOWNLOAD
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// hclDownload_OnProgress subroutine
|
|
//
|
|
// PROGRESS event handler for the HCL_DOWNLOAD control
|
|
//
|
|
// * Update the progress bar
|
|
// * Update the Estimated Time Left (ETL)
|
|
// * Update the Transfer Rate
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
// [i] : bytesReceived. Number of bytes received between this PROGRESS event
|
|
// : and the previous one
|
|
// [i] : bytesDownloaded. Total Number of bytes downloaded so far
|
|
// [i] : bytesExpected. Total number of bytes expected from the server
|
|
// ----------------------------------------------------------------------------
|
|
hclDownload_OnProgress:
|
|
|
|
timeData = @@window->$@_TIMEDATA
|
|
|
|
startTime = timeData<1>
|
|
prevTime = timeData<2>
|
|
prevRate = timeData<3>
|
|
|
|
now = msWin_GetTickCount64()
|
|
|
|
if ( now > prevTime ) else
|
|
now = prevTime + 1
|
|
end
|
|
|
|
elapsedTime = now - startTime
|
|
transferRate = int( ( bytesDownloaded / elapsedTime ) * 1000 ) ; // in secs
|
|
|
|
etlText = ""
|
|
trText = ""
|
|
|
|
if ( bytesExpected ) then
|
|
|
|
// If we know how much we're expected to deal with we can
|
|
// calculate how much time is left and ho far we are
|
|
// through
|
|
|
|
if ( .prb_download->marquee ) then
|
|
.prb_download->marquee = 0 ; // ms
|
|
.prb_download->showText = TRUE$
|
|
end
|
|
|
|
.prb_download->value = int( ( bytesDownloaded / bytesExpected ) * 100 )
|
|
|
|
etlSecs = ( bytesExpected - bytesDownloaded ) / transferRate ; // seconds to complete
|
|
|
|
etlHours = 0
|
|
etlMins = 0
|
|
|
|
if ( etlSecs > 3600 ) then
|
|
etlHours = int( etlSecs / 3600 )
|
|
etlSecs = mod( etlSecs , 3600 )
|
|
end
|
|
|
|
if ( etlSecs > 60 ) then
|
|
etlMins = int( etlSecs / 60 )
|
|
etlSecs = mod( etlSecs , 60 )
|
|
end
|
|
|
|
etlSecs = int( etlSecs )
|
|
|
|
if ( etlHours ) then
|
|
etlText := etlHours : " hours "
|
|
end
|
|
|
|
if ( etlMins ) then
|
|
etlText := etlMins : " minutes "
|
|
end
|
|
|
|
if ( etlSecs ) then
|
|
etlText := etlSecs : " seconds "
|
|
end
|
|
|
|
cb = bytesDownloaded
|
|
goSub hclDownload_OnProgress_bytesToText
|
|
|
|
etlText := " (" : cb : " " : sf : " of "
|
|
|
|
cb = bytesExpected
|
|
goSub hclDownload_OnProgress_bytesToText
|
|
|
|
etlText := cb : " " : sf : " downloaded)"
|
|
|
|
end else
|
|
// We can't calculate the ETL or the progress done because we don't
|
|
// how much we've got left to down load
|
|
|
|
// Ensure we set the progress bar to a marquee
|
|
if ( .prb_download->marquee ) else
|
|
.prb_download->showText = FALSE$
|
|
.prb_download->marquee = 20 ; // ms
|
|
end
|
|
|
|
// We can however show the amount copied....
|
|
|
|
cb = bytesDownloaded
|
|
goSub hclDownload_OnProgress_bytesToText
|
|
|
|
etlText = cb : " " : sf : " downloaded"
|
|
|
|
end
|
|
|
|
cb = transferRate
|
|
goSub hclDownload_OnProgress_bytesToText
|
|
|
|
begin case
|
|
case ( transferRate > 0x100000 )
|
|
// We're working in MB
|
|
sf = "Mb/s"
|
|
|
|
case ( transferRate > 0x400 )
|
|
// We're working in KB
|
|
sf = "Kb/s"
|
|
|
|
case OTHERWISE$
|
|
sf = "b/s"
|
|
|
|
end case
|
|
|
|
trText = cb : " " : sf
|
|
|
|
.txt_ETL->text = etlText
|
|
.txt_TR->text = trText
|
|
|
|
timeData<2> = now
|
|
timeData<3> = transferRate
|
|
|
|
@@window->$@_TIMEDATA = timeData
|
|
|
|
return
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// hclDownload_OnProgress_bytesToText subroutine
|
|
//
|
|
// Simple routine to translate the number of bytes into MB, KB etc ...
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
// [i,o] cb : Number of bytes in, translated amount out
|
|
// [o] sf : Suffic to append to the translated amount - MB, KB or "Bytes"
|
|
// ----------------------------------------------------------------------------
|
|
hclDownload_OnProgress_bytesToText:
|
|
|
|
// We can however show the amount copied....
|
|
begin case
|
|
case ( cb > 0x100000 )
|
|
cb = oconv( ( cb / 0x100000 ) * 100, "MD2" )
|
|
sf = "MB"
|
|
|
|
case ( cb > 0x400 )
|
|
cb = oconv( ( cb / 0x400 ) * 100, "MD2" )
|
|
sf = "KB"
|
|
|
|
case OTHERWISE$
|
|
sf = "Bytes"
|
|
|
|
end case
|
|
|
|
return
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
hclDownload_OnReadyStateChanged:
|
|
|
|
begin case
|
|
case ( newState == PS_HCL_RS_DONE$ )
|
|
// When we get this notification the client has finished downloading
|
|
// from theserver so we need to grab the content and then pass it to
|
|
// the parent's ENDDIALOG event or the specified callback proc.
|
|
goSub hclDownload_ReturnResponse
|
|
|
|
case OTHERWISE$
|
|
null
|
|
|
|
end case
|
|
|
|
return
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// hclDownload_OnTimeout subroutine
|
|
//
|
|
// TIMEOUT event handler for the HCL_DOWNLOAD control
|
|
//
|
|
// Return what we have to the caller - the status code returned should be 408
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
hclDownload_OnTimeout:
|
|
goSub hclDownload_ReturnResponse
|
|
return
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// hclDownload_ReturnResponse subroutine
|
|
//
|
|
// Call back with the reponse content and close the dialog.
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
hclDownload_ReturnResponse:
|
|
|
|
// Details we need were passed to the create event which we saved in a UDP:
|
|
createParam = @@window->$@_CREATEPARAM
|
|
|
|
parentID = createParam<HDL_UIPARAM_POS_PARENTWIN$>
|
|
bModal = createParam<HDL_UIPARAM_POS_MODAL$>
|
|
asyncID = createParam<HDL_UIPARAM_POS_ENDDIALOGASYNCID$>
|
|
|
|
// Renable the parent window if we have one...
|
|
if bLen( parentID ) then
|
|
if bModal then
|
|
@parentID->enabled = TRUE$
|
|
end
|
|
end
|
|
|
|
// Remove this dialog from screen
|
|
@@window->hide( "" )
|
|
|
|
if ( createParam<HDL_UIPARAM_POS_SYNCPROGRESS$> ) then
|
|
.prb_Download->value = 0
|
|
.prb_Download->syncTaskbar = FALSE$
|
|
end
|
|
|
|
// We send back two parameters to the callback event/proc
|
|
//
|
|
// 1) An array of response data
|
|
//
|
|
// <1> AsyncID or CallBackID
|
|
// <2> Response Status Code
|
|
// <3> Response Status Text
|
|
// <4> Content Length
|
|
// <5> Response Header Names
|
|
// <6> Bytes received for the response content
|
|
//
|
|
// 2) The response content (unless this was a file download)
|
|
|
|
rspInfo = ""
|
|
|
|
tmp = .hcl_Download->responseStatus
|
|
|
|
rspInfo<HDL_RSPINFO_POS_STATUSCODE$> = tmp<PS_HCL_RSPSTAT_POS_CODE$>
|
|
rspInfo<HDL_RSPINFO_POS_STATUSTEXT$> = tmp<PS_HCL_RSPSTAT_POS_TEXT$>
|
|
rspInfo<HDL_RSPINFO_POS_CONTENTLEN$> = tmp<PS_HCL_RSPSTAT_POS_CNTLEN$>
|
|
rspInfo<HDL_RSPINFO_POS_HEADERS$> = rti_Convert( .hcl_Download->responseHeaders, @fm, @vm )
|
|
|
|
responseFile = .hcl_Download->responseFile
|
|
if bLen( responseFile ) then
|
|
rspInfo<HDL_RSPINFO_POS_BYTESRECEIVED$> = dir( responseFile )<1>
|
|
rspContent = ""
|
|
end else
|
|
rspContent = .hcl_Download->GetResponseContent( "" )
|
|
rspInfo<HDL_RSPINFO_POS_BYTESRECEIVED$> = bLen( rspContent )
|
|
end
|
|
|
|
// If ww're here because of an Abort() call then we don't bother closing...
|
|
if ( @@window->$@_ABORT ) else
|
|
call post_Event( @window, "CLOSE" )
|
|
end
|
|
|
|
// Now decide where to send the data
|
|
if bLen( asyncID ) then
|
|
// Send to the parent's ENDDIALOG
|
|
if ( @parentID->handle ) then
|
|
|
|
rspInfo<HDL_RSPINFO_POS_ID$> = asyncID
|
|
call send_Event( parentID, "ENDDIALOG", atWindow, rspContent, rspInfo )
|
|
|
|
end
|
|
end else
|
|
// Send to the callback proc
|
|
procID = createParam<HDL_UIPARAM_POS_CALLBACKPROC$>
|
|
if bLen( procID ) then
|
|
rspInfo<HDL_RSPINFO_POS_ID$> = createParam<HDL_UIPARAM_POS_CALLBACKID$>
|
|
call @procID( rspInfo, rspContent )
|
|
end
|
|
end
|
|
|
|
return
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#endregion HCL_DOWNLOAD
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
$insert copyright
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|