1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
-- 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
|