fetch.bac
'
' Small utility to get some BaCon programs over HTTP from the BaCon website
'
' Dec 2010 - PvE.
' Mar 2011: added size check - PvE
' Jul 2013: various improvements, network handling more robust - PvE
' January 2017: option collapse to skip empty results - PvE
' Dec 2018: support for HTTP proxy, fix error in coloring, code optimizations - PvE
' July 2019: skip comments in files.txt
' Sept 2019: use plain HTTP only
'-----------------------------------------------------------------------------------
OPTION COLLAPSE TRUE
CONST Separator$ = CR$ & NL$ & CR$ & NL$
CONST website$ = "www.basic-converter.org"
CONST NetDelay = 500
'-----------------------------------------------------------------------------------------
FUNCTION Connect_To(name$)
LOCAL net TYPE int
' Get environment variable for proxy
proxy$ = GETENVIRON$("HTTP_PROXY")
IF LEN(proxy$) = 0 THEN proxy$ = GETENVIRON$("http_proxy")
' Parse proxy settings
IF LEN(proxy$) THEN
IF LEFT$(proxy$, 7) <> "http://" THEN
EPRINT "System error: proxy '", proxy$, "' not supported! Redefine to default HTTP proxy or undefine."
END 1
ENDIF
proxy$ = MID$(proxy$, 8)
IF TALLY(proxy$, "@") THEN
unpw$ = B64ENC$(TOKEN$(proxy$, 1, "@"))
proxy$ = TOKEN$(proxy$, 2, "@")
ENDIF
' Setup TCP connection on defined port
OPEN proxy$ FOR NETWORK AS net
SEND "CONNECT " & name$ & ":80 HTTP/1.1" & "\r\n" TO net
IF LEN(unpw$) THEN SEND "Proxy-Authorization: Basic " & B64ENC$(unpw$) & "\r\n" TO net
SEND "\r\n" TO net
' Return should be OK
RECEIVE dat$ FROM net
IF NOT(TALLY(dat$, " 200 ")) THEN
EPRINT "System error: proxy '", proxy$, "' returns error: " & dat$
END 1
ENDIF
ELSE
' Open TCP connection on port 80
OPEN name$ & ":80" FOR NETWORK AS net
ENDIF
RETURN net
ENDFUNCTION
'-----------------------------------------------------------------------------------------
SUB Close_Fd(int net)
CLOSE NETWORK net
END SUB
'-----------------------------------------------------------------------------------------
' Get the list with files
PRINT "Fetching the list of BaCon programs... ";
mynet = Connect_To(website$)
SEND "GET /files.txt HTTP/1.1\r\nHost: " & website$ & Separator$ TO mynet
REPEAT
RECEIVE dat$ FROM mynet
IF LEN(dat$) > 0 THEN allfile$ = allfile$ & dat$
UNTIL ISFALSE(WAIT(mynet, NetDelay))
Close_Fd(mynet)
COLOR FG TO GREEN
PRINT "done."
'-----------------------------------------------------------------------------------------
' Split the text into separate filenames and fetch one by one
FOR file$ IN TOKEN$(allfile$, 2, Separator$) STEP NL$
' Skip comments
IF LEFT$(file$, 1) = "#" THEN CONTINUE
' Give the remote server some time
SLEEP NetDelay
COLOR RESET
PRINT "Fetching ", file$, "... ";
attempt = 0
REPEAT
' We create a new connection for each individual file
mynet = Connect_To(website$)
' Get the current file
SEND "GET /" & file$ & " HTTP/1.1\r\nHost: " & website$ & Separator$ TO mynet
total$ = ""
' Prevent endless waiting for server
IF NOT(WAIT(mynet, NetDelay)) THEN
COLOR FG TO CYAN
PRINT "Timeout on server! Retrying... ";
SLEEP NetDelay
Close_Fd(mynet)
INCR attempt
IF attempt = 4 THEN
COLOR FG TO RED
PRINT "Could not download ", file$, " - skipping."
SLEEP NetDelay
BREAK
END IF
CONTINUE
ELSE
' So there is data
RECEIVE dat$ FROM mynet
' Get the filesize from the HTTP header
dat$ = MID$(dat$, INSTR(dat$, "Content-Length:")+15)
length = VAL(LEFT$(dat$, INSTR(dat$, NL$)))
' As long as there is data, get it
WHILE WAIT(mynet, NetDelay) AND LEN(dat$) > 0
total$ = total$ & dat$
RECEIVE dat$ FROM mynet
WEND
total$ = total$ & dat$
' Write to file
SAVE TOKEN$(total$, 2, Separator$) TO file$
' Closing the connection again
Close_Fd(mynet)
END IF
' If the size of the file is not correct
IF FILELEN(file$) <> length THEN
' Keep track of attempts
INCR attempt
SELECT attempt
CASE 2, 3
COLOR FG TO CYAN
PRINT "Failed! Retrying... ";
SLEEP NetDelay
CASE 4
COLOR FG TO RED
PRINT "Could not download ", file$, " - skipping."
SLEEP NetDelay
IF FILEEXISTS(file$) THEN DELETE FILE file$
BREAK
END SELECT
END IF
' Make sure filelength equals size mentioned in HTTP header
UNTIL LEN(total$) > 0 AND FILELEN(file$) = length
IF attempt < 4 THEN
COLOR FG TO GREEN
PRINT "done."
END IF
NEXT
COLOR RESET
PRINT "Finished list of BaCon demonstration programs. Enjoy!"
Generated by GNU Enscript 1.6.6.