Last active
August 27, 2020 19:04
-
-
Save zr-tex8r/9752c31d76c31377efda58e9d2fb9844 to your computer and use it in GitHub Desktop.
Lua: “zrget” module
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
zrget = require 'zrget' | |
zrget.download( | |
'https://raw.githubusercontent.com/zr-tex8r/scllmk/master/doc/logo.png', | |
'logo.png', | |
function (d) return d:sub(1, 4) == '\137PNG' end) | |
-- EOF |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- zrget.lua | |
local info = 'zrget v0.3.0 2020/08/26' | |
local zrget | |
-- NOTE: This file can be used as a Lua module, but to copy & paste | |
-- the section below is also okay. | |
---------------------------------------- | |
zrget = (function(M) | |
-- parameters | |
M.max_trial = M.max_trial or 3 | |
M.interval = M.interval or 1 -- second | |
M.log = M.log or true | |
-- helpers | |
local lfs = require 'lfs' | |
local socket = require 'socket' | |
local tempb = '__zrget' | |
local win = (lfs.attributes('C:\\NUL', 'mode') ~= nil) | |
local function upath(pth) | |
return (win) and pth:gsub('\\', '/') or pth | |
end | |
local function npath(pth) | |
return (win) and pth:gsub('/', '\\') or pth | |
end | |
local function log_print(s) | |
io.stderr:write("zrget: ", s, "\n") | |
end | |
local function log(fmt, ...) | |
if not M.log then return end | |
local l = (type(M.log) == 'function') and M.log or log_print | |
l(tostring(fmt):format(...)) | |
end | |
local function file_ok(pth) | |
return ((lfs.attributes(pth, 'size') or 0) > 0) | |
end | |
local function execute(clfmt, ...) | |
local cl = clfmt:format(...) | |
if M.verbose then log("RUN: %s", cl) end | |
local ok = os.execute(cl) | |
return (ok == true) or (ok == 0) | |
end | |
local function exefile(pth) | |
pth = npath(pth..(win and '.exe' or '')) | |
return (file_ok(pth) or nil) and pth | |
end | |
local function validate(vprc, pth) | |
if not file_ok(pth) then return false end | |
local h = io.open(pth, 'rb') | |
local d = h and h:read('*a') | |
if h then h:close() end | |
local r = d and (not vprc or vprc(d)) | |
if not r then log("Validation failure") end | |
return r and d | |
end | |
-- TeXLive stuffs | |
local kpse | |
pcall(function() | |
kpse = require 'kpse' | |
kpse.set_program_name('luatex') | |
end) | |
local tlpkg = kpse and kpse.var_value('SELFAUTOPARENT') | |
tlpkg = tlpkg and tlpkg..'/tlpkg' | |
local tlwget = tlpkg and exefile(tlpkg..'/installer/wget/wget') | |
local tlperl = tlpkg and exefile(tlpkg..'/tlperl/bin/perl') | |
-- methods | |
local fcout, fcerr, ftdst = | |
tempb..'-1.out', tempb..'-2.out', tempb..'-0.bin' | |
local method_list = { | |
{ | |
name = 'wget'; | |
checker = 'wget --version'; check_tag = 'Wget'; | |
loader = function(src) | |
return execute('wget -q --no-check-certificate "%s" -O %s 2>%s', | |
src, ftdst, fcerr) | |
end | |
}, | |
{ | |
name = 'curl'; | |
checker = 'curl --version'; check_tag = 'curl'; | |
loader = function(src) | |
return execute('curl -k -s "%s" -o %s 2>%s', | |
src, ftdst, fcerr) | |
end | |
}, | |
{ | |
name = 'tl-wget'; | |
checker = tlwget and tlwget..' --version'; check_tag = 'Wget'; | |
loader = function(src) | |
return execute('%s -q --no-check-certificate "%s" -O %s 2>%s', | |
tlwget, src, ftdst, fcerr) | |
end | |
}, | |
{ | |
name = 'powershell'; | |
checker = 'powershell -Help'; check_tag = 'PowerShell'; | |
loader = function(src) | |
return execute('powershell -Command Invoke-WebRequest '.. | |
'"%s" -OutFile %s 2>%s', | |
src, ftdst, fcerr) | |
end | |
}, | |
{ | |
name = 'tl-perl'; | |
checker = tlperl and tlperl..' --version'; check_tag = '?Perl'; | |
loader = function(src) | |
return false -- TODO: make it | |
end | |
}, | |
} | |
-- main procedure | |
function M.download(url, dst, vprc) | |
url = tostring(url):gsub('[\1-\31 \"\'<>\\`{|}]', | |
function(s) return ('%%%02X'):format(string.byte(s)) end) | |
if dst then | |
if file_ok(dst) then | |
log("File '%s' already exists", dst) | |
return false | |
end | |
os.remove(dst) | |
end | |
-- | |
local data | |
for tc = 1, M.max_trial do | |
for _, mth in ipairs(method_list) do | |
repeat | |
if not mth.checker or mth.pass then break end | |
log("Try method '%s'...(%s)", mth.name, tc) | |
-- check | |
execute('%s 1>%s 2>%s', mth.checker, fcout, fcerr) | |
local hso = io.open(fcout, 'rb') | |
local p = (hso and hso:read('*a') or ''):find(mth.check_tag, 1, true) | |
hso:close() | |
if not p then | |
log("Method '%s' is not available", mth.name) | |
mth.pass = true | |
break | |
end | |
-- download | |
log("Try downloading...") | |
os.remove(ftdst) | |
if mth.loader(url) then | |
data = validate(vprc, ftdst) | |
if data then break end | |
end | |
socket.sleep(M.interval) | |
os.remove(ftdst) | |
until true | |
if data then break end | |
end | |
if data then break end | |
end | |
-- | |
local what = (dst) and ("File '%s'"):format(dst) or "Data" | |
if data then | |
if dst then os.rename(ftdst, dst) end | |
log("%s is successfully downloaded", what) | |
else | |
log("%s cannot be downloaded", what) | |
end | |
-- | |
for _, f in ipairs {ftdst, fcerr, fcout} do | |
os.remove(f) | |
end | |
return data | |
end | |
return M | |
end)({}) | |
---------------------------------------- | |
return zrget | |
-- EOF |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment