PDA

View Full Version : Programatically download the latest 64 bit version of Firefox for Windows.



John Spikowski
30-10-2018, 00:24
Hi Eros,

You are invited to test your thinBasic web tools with AIR's Firefox download challenge on the All BASIC forum.

Show us your stuff! :cool:

ErosOlmi
30-10-2018, 07:53
I've moved your post into a specific thread.

Reference for all: https://www.allbasic.info/forum/index.php?topic=515.0

ErosOlmi
30-10-2018, 07:57
This is my 5 minutes code.
Download is missing but should be easy to add but no time now, hurry to my 2 hours drive to work :(



uses "Console"
uses "iNet"
uses "OS"


printl "Connect to Firefox web site, determine latest Firefox version and download it"


'---Check if computer is connected to internet
if INET_GetState Then
'---Get Firefox web site page
string Firefox_Info_Page = INET_UrlGetString("https://www.mozilla.org/en-US/firefox/new/")


'---Get Firefox available version
string Firefox_Available_Version = grab$(Firefox_Info_Page, "data-latest-firefox=""", """")


'---Get Win64 direct download url
string Firefox_DownLoad_Url_Win64 = grab$(Firefox_Info_Page, "<div id=""other-platforms"">", "</div>")
Firefox_DownLoad_Url_Win64 = grab$(Firefox_DownLoad_Url_Win64, "<li class=""os_win64"">", "</li>")
Firefox_DownLoad_Url_Win64 = grab$(Firefox_DownLoad_Url_Win64, "<a href=""", """")


printl "Firefox available version...:", Firefox_Available_Version
printl "Firefox Download url........:", Firefox_DownLoad_Url_Win64


'---Download
string sLocalFile = APP_SourcePath + "Firefox Setup " + Firefox_Available_Version + ".exe"
printl "Downlaoding to", sLocalFile, "..."
INET_UrlDownload(Firefox_DownLoad_Url_Win64, sLocalFile)
printl "File downlaoded."
printl
printl "Press ESC to end or any other key within 10 secs to execute setup"


'---Ask if execute setup
string sUserReply = WaitKey(10)
if sUserReply <> "[ESC]" and sUserReply <> "[TIMEOUT]" Then
printl "Executing " + sLocalFile
OS_Shell(sLocalFile, %OS_WNDSTYLE_NORMAL, %OS_SHELL_SYNC)
Else
printl "No execution. Execute manually if needed."
end If


Else
printl "! it seems you are not connected to internet." in %CCOLOR_FLIGHTRED
end If


printl "---All done, press a key to end or wait 5 secs---"
WaitKey(5)


'[todo] To add async download with any progress info ...
' Install thinBasic and see example at \thinBasic\SampleScripts\INet\Internet_FileDownload.tbasic

John Spikowski
30-10-2018, 20:01
Outstanding Eros!

Can you post this to the All BASIC forum code challenge when you have time. Maybe your support for the challenge will get others to submit code.

Update:

Thanks for posting the thinBasic submission on All BASIC!

ErosOlmi
01-11-2018, 14:10
Here a thinBasic ASYNC version with callback function used to determine download progression.
Progress data is shown on a pop up box that will be removed when download is finished.

Maybe a little bit complex but worth to post.



uses "Console"
uses "iNet"
uses "OS"


printl "Connect to Firefox web site, determine latest Firefox version and download it"


'---Check if computer is connected to internet
if INET_GetState Then
'---Get Firefox web site page
string Firefox_Info_Page = INET_UrlGetString("https://www.mozilla.org/en-US/firefox/new/")


'---Get Firefox available version
string Firefox_Available_Version = grab$(Firefox_Info_Page, "data-latest-firefox=""", """")


'---Get Win64 direct download url
string Firefox_DownLoad_Url_Win64 = grab$(Firefox_Info_Page, "<div id=""other-platforms"">", "</div>")
Firefox_DownLoad_Url_Win64 = grab$(Firefox_DownLoad_Url_Win64, "<li class=""os_win64"">", "</li>")
Firefox_DownLoad_Url_Win64 = grab$(Firefox_DownLoad_Url_Win64, "<a href=""", """")


printl "Firefox available version...:", Firefox_Available_Version
printl "Firefox Download url........:", Firefox_DownLoad_Url_Win64


'---Download
string sLocalFile = APP_SourcePath + "Firefox Setup " + Firefox_Available_Version + ".exe"


'---Initializes an application's use of the WinINet Internet functions.
dword hInternet = INET_Internet_Open("Download Fireforx", %INTERNET_OPEN_TYPE_DIRECT)
IF hInternet = %NULL THEN
printl "INET_Internet_Open error"
waitkey
stop
END IF


long MyContext = 1
long hFile = INET_Internet_OpenUrl(hInternet, Firefox_DownLoad_Url_Win64, "", %INTERNET_FLAG_NO_CACHE_WRITE, MyContext)
IF hFile = %NULL THEN
printl "INET_Internet_OpenUrl error. Check url: " & Firefox_DownLoad_Url_Win64
INET_Internet_CloseHandle hInternet
waitkey
stop
END IF


'---Set a callback for hInternet events. Driver will automatically call MyStatusFunction on status change
long bResult = INET_Internet_SetStatusCallBack(hFile, MyStatusFunction)


'---Query remote server about the size of the file we are going to download
long FileSize = INET_Http_QueryInfo(hFile, %HTTP_QUERY_CONTENT_LENGTH)
printl "Real file size in bytes: " & FileSize
IF FileSize = %NULL THEN
printl "INET_Http_QueryInfo(hInternet, %HTTP_QUERY_CONTENT_LENGTH) error. Check url: " & Firefox_DownLoad_Url_Win64
INET_Internet_CloseHandle hInternet
INET_Internet_CloseHandle hFile
waitkey
stop
END IF



'---Ok we can start a loop for file download. This can be automated in a loop or in a timer function
'---Reads the data in %BufferLen bytes chunks
double T0 = timer
double T1

'---Setup a %BufferLen bytes buffer
long lBufferLen = 500000 '500k
string strBuffer = STRING$(lBufferLen, $SPC)
dword pstrBuffer = STRPTR(strBuffer)
String strData
dword cbBytesRead
DWord TotalBytesRead
long lScreenLine = 8
long lScreenPos = 20


string sSave = Console_SaveScreen(1, 1, 80, 24)
Console_Box(lScreenPos - 1, lScreenLine - 1, 40, 8, 24, 24, "Downloading ...", 26, %Console_BOX_FLAG_3DOFF)
DO
bResult = INET_Internet_ReadFile(hFile, pstrBuffer, len(strBuffer), cbBytesRead)
IF bResult = 0 OR cbBytesRead = 0 THEN EXIT DO
IF cbBytesRead = LEN(strBuffer) THEN
strData &= strBuffer
ELSE
strData &= LEFT$(strBuffer, cbBytesRead)
END IF
TotalBytesRead += cbBytesRead
T1 = Timer

PrintAt "Elapsed seconds : " & LSet$(Format$(T1-T0, "0"), 19) , lScreenPos + 1, lScreenLine + 1, 24
PrintAt "Bytes read so far: " & LSet$(TotalBytesRead, 19) , lScreenPos + 1, lScreenLine + 2, 24
PrintAt "KBytes per second: " & LSet$(Format$((TotalBytesRead / Max(T1-T0, 1))/1024, "0.00"), 19) , lScreenPos + 1, lScreenLine + 3, 24
PrintAt "Estimated seconds: " & LSet$(Format$((FileSize * (T1-T0))/TotalBytesRead, "0"), 19) , lScreenPos + 1, lScreenLine + 4, 24
PrintAt "Seconds to go : " & LSet$(Format$(((FileSize * (T1-T0))/TotalBytesRead)-(T1-T0), "0"), 19) , lScreenPos + 1, lScreenLine + 5, 24

Console_ProgressBar(1, lScreenPos + 1, lScreenLine + 7, 40-1, 27, 1, FileSize, TotalBytesRead)
LOOP


Console_RestoreScreen(1, 1, 80, 24, sSave)


'---Closes all used handles
INET_Internet_CloseHandle hInternet
INET_Internet_CloseHandle hFile




printl "Saving file: " & sLocalFile
Save_File(sLocalFile, strData)


printl "File saved."
printl
printl "Press ESC to end or any other key within 10 secs to execute setup"




'---Ask if execute setup
string sUserReply = WaitKey(10)
if sUserReply <> "[ESC]" and sUserReply <> "[TIMEOUT]" Then
printl "Executing " + sLocalFile
OS_Shell(sLocalFile, %OS_WNDSTYLE_NORMAL, %OS_SHELL_SYNC)
Else
printl "No execution. Execute manually if needed."
end If


Else
printl "! it seems you are not connected to internet." in %CCOLOR_FLIGHTRED
end If


printl "---All done, press a key to end or wait 5 secs---"
WaitKey(5)




'------------------------------------------------------------------
' CallBack function automatically called by Internet driver when
' status change for a specific Internet handle to which a callback
' function has been installed.
' Parameters are mandatory and are defined my Microsoft
' callback template. More info at: http://msdn.microsoft.com/en-us/library/aa385121(VS.85).aspx
'------------------------------------------------------------------
callback function MyStatusFunction( _
byval hInternet as long , _ '---Mandatory in thinBasic and in API
byval dwContext as long , _ '---Mandatory in thinBasic and in API
byval dwInternetStatus as long , _ '---Mandatory in thinBasic and in API
byval lpvStatusInformation as long , _ '---Optional in thinBasic, mandatory in API
byval dwStatusInformationLength as long _ '---Optional in thinBasic, mandatory in API
) as long
'------------------------------------------------------------------
dim BytesReceived as dword at 0
static TotBytes as dword


static MoreStatusLine as long = 20

'printat "Data from " & function_name & " callback" , 1, 17
'printat " Internet handle: " & hInternet & " Internet dwContext: " & dwContext, 1, 18


select case dwInternetStatus
case %INTERNET_STATUS_RECEIVING_RESPONSE


case %INTERNET_STATUS_RESPONSE_RECEIVED
'--- Successfully received a response from the server.
'--- The lpvStatusInformation parameter points to a DWORD value that contains the number, in bytes, received.
setat(BytesReceived, lpvStatusInformation)
TotBytes += BytesReceived


'---ATTENTION: TotalBytes received can differ from total bytes of the file to be downloaded


'printat " Receiving data (" & dwInternetStatus & " " & INET_Internet_StatusGetDescription(dwInternetStatus) & ") TotBytes: " & TotBytes, 1, 19


case else
'---In case of other status, just decode it at the bottom.
'printat " (" & dwInternetStatus & " " & INET_Internet_StatusGetDescription(dwInternetStatus) & ")", 1, MoreStatusLine
incr MoreStatusLine


end select




end function