-- 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