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 ) then .prb_Download->SyncTaskBar = TRUE$ end // The form's visibility is controlled from rti_HTTP_Download() // @atWindow->visible = TRUE$ if ( param1 ) then call set_Property( param1, "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 bModal = createParam asyncID = createParam // 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 ) 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 = tmp rspInfo = tmp rspInfo = tmp rspInfo = rti_Convert( .hcl_Download->responseHeaders, @fm, @vm ) responseFile = .hcl_Download->responseFile if bLen( responseFile ) then rspInfo = dir( responseFile )<1> rspContent = "" end else rspContent = .hcl_Download->GetResponseContent( "" ) rspInfo = 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 = asyncID call send_Event( parentID, "ENDDIALOG", atWindow, rspContent, rspInfo ) end end else // Send to the callback proc procID = createParam if bLen( procID ) then rspInfo = createParam call @procID( rspInfo, rspContent ) end end return /////////////////////////////////////////////////////////////////////////////// #endregion HCL_DOWNLOAD /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// $insert copyright /////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////