94 lines
2.3 KiB
Lua
94 lines
2.3 KiB
Lua
-- SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
local ffi = require('ffi')
|
|
local kluautil = {}
|
|
|
|
-- Get length of table
|
|
function kluautil.kr_table_len(t)
|
|
if type(t) ~= 'table' then
|
|
return nil
|
|
end
|
|
|
|
local len = 0
|
|
for _ in pairs(t) do
|
|
len = len + 1
|
|
end
|
|
return len
|
|
end
|
|
|
|
-- pack varargs including nil arguments into a table
|
|
function kluautil.kr_table_pack(...)
|
|
local tab = {...}
|
|
tab.n = select('#', ...)
|
|
return tab
|
|
end
|
|
|
|
-- unpack table produced by kr_table_pack and including nil values
|
|
function kluautil.kr_table_unpack(tab)
|
|
return unpack(tab, 1, tab.n)
|
|
end
|
|
|
|
-- Fetch over HTTPS
|
|
function kluautil.kr_https_fetch(url, out_file, ca_file)
|
|
local http_ok, http_request = pcall(require, 'http.request')
|
|
local httptls_ok, http_tls = pcall(require, 'http.tls')
|
|
local openssl_ok, openssl_ctx = pcall(require, 'openssl.ssl.context')
|
|
|
|
if not http_ok or not httptls_ok or not openssl_ok then
|
|
return nil, 'error: lua-http and luaossl libraries are missing (but required)'
|
|
end
|
|
local cqerrno = require('cqueues.errno')
|
|
|
|
assert(string.match(url, '^https://'))
|
|
|
|
local req = http_request.new_from_uri(url)
|
|
req.tls = true
|
|
if ca_file then
|
|
req.ctx = openssl_ctx.new()
|
|
local store = req.ctx:getStore()
|
|
local load_ok, errmsg = pcall(store.add, store, ca_file)
|
|
if not load_ok then
|
|
return nil, errmsg
|
|
end
|
|
else -- use defaults
|
|
req.ctx = http_tls.new_client_context()
|
|
end
|
|
|
|
req.ctx:setVerify(openssl_ctx.VERIFY_PEER)
|
|
|
|
local headers, stream, errmsg = req:go()
|
|
if not headers then
|
|
errmsg = errmsg or 'unknown error'
|
|
if type(errmsg) == 'number' then
|
|
errmsg = cqerrno.strerror(errmsg) ..
|
|
' (' .. tostring(errmsg) .. ')'
|
|
end
|
|
return nil, 'HTTP client library error: ' .. errmsg
|
|
end
|
|
if headers:get(':status') ~= "200" then
|
|
return nil, 'HTTP status != 200, got ' .. headers:get(':status')
|
|
end
|
|
|
|
local err
|
|
err, errmsg = stream:save_body_to_file(out_file)
|
|
if err == nil then
|
|
return nil, errmsg
|
|
end
|
|
|
|
out_file:seek('set', 0)
|
|
|
|
return true
|
|
end
|
|
|
|
-- Copy a lua string to C (to knot_mm_t or nil=malloc, zero-terminated).
|
|
function kluautil.kr_string2c(str, mempool)
|
|
if str == nil then return nil end
|
|
local result = ffi.C.mm_realloc(mempool, nil, #str + 1, 0)
|
|
if result == nil then panic("not enough memory") end
|
|
ffi.copy(result, str)
|
|
return ffi.cast('const char *', result)
|
|
end
|
|
|
|
kluautil.list_dir = kluautil_list_dir
|
|
|
|
return kluautil
|