summaryrefslogtreecommitdiffhomepage
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/luci-lib-httpclient/luasrc/httpclient.lua195
-rw-r--r--libs/luci-lib-httpprotoutils/luasrc/http/mime.luadoc2
-rw-r--r--libs/luci-lib-ip/src/ip.luadoc18
-rw-r--r--libs/luci-lib-ipkg/Makefile14
-rw-r--r--libs/luci-lib-ipkg/luasrc/model/ipkg.lua247
-rw-r--r--libs/luci-lib-ipkg/luasrc/model/ipkg.luadoc125
-rw-r--r--libs/luci-lib-iptparser/Makefile14
-rw-r--r--libs/luci-lib-iptparser/luasrc/sys/iptparser.lua374
-rw-r--r--libs/luci-lib-iptparser/luasrc/sys/iptparser.luadoc69
-rw-r--r--libs/luci-lib-jsonc/src/jsonc.c77
-rw-r--r--libs/luci-lib-nixio/Makefile38
-rw-r--r--libs/luci-lib-nixio/docsrc/CHANGELOG.lua2
-rw-r--r--libs/luci-lib-nixio/docsrc/README.lua2
-rw-r--r--libs/luci-lib-nixio/docsrc/nixio.lua2
-rw-r--r--libs/luci-lib-px5g/src/library/bignum.c8
-rw-r--r--libs/luci-lib-px5g/src/library/x509write.c8
-rw-r--r--libs/luci-lib-px5g/src/polarssl/bignum.h6
-rw-r--r--libs/luci-lib-px5g/src/polarssl/x509.h6
-rw-r--r--libs/rpcd-mod-rad2-enc/Makefile49
-rwxr-xr-xlibs/rpcd-mod-rad2-enc/files/rad2-enc50
20 files changed, 1204 insertions, 102 deletions
diff --git a/libs/luci-lib-httpclient/luasrc/httpclient.lua b/libs/luci-lib-httpclient/luasrc/httpclient.lua
index 3e8d7277d7..79ce41294c 100644
--- a/libs/luci-lib-httpclient/luasrc/httpclient.lua
+++ b/libs/luci-lib-httpclient/luasrc/httpclient.lua
@@ -9,9 +9,10 @@ local util = require "luci.util"
local table = require "table"
local http = require "luci.http"
local date = require "luci.http.date"
+local ip = require "luci.ip"
-local type, pairs, ipairs, tonumber = type, pairs, ipairs, tonumber
-local unpack = unpack
+local type, pairs, ipairs, tonumber, tostring = type, pairs, ipairs, tonumber, tostring
+local unpack, string = unpack, string
module "luci.httpclient"
@@ -25,7 +26,7 @@ function chunksource(sock, buffer)
if not newblock then
return nil, code
end
- buffer = buffer .. newblock
+ buffer = buffer .. newblock
_, endp, count = buffer:find("^([0-9a-fA-F]+);?.-\r\n")
end
count = tonumber(count, 16)
@@ -62,17 +63,17 @@ end
function request_to_buffer(uri, options)
local source, code, msg = request_to_source(uri, options)
local output = {}
-
+
if not source then
return nil, code, msg
end
-
+
source, code = ltn12.pump.all(source, (ltn12.sink.table(output)))
-
+
if not source then
return nil, code
end
-
+
return table.concat(output)
end
@@ -83,7 +84,7 @@ function request_to_source(uri, options)
elseif status ~= 200 and status ~= 206 then
return nil, status, buffer
end
-
+
if response.headers["Transfer-Encoding"] == "chunked" then
return chunksource(sock, buffer)
else
@@ -91,67 +92,115 @@ function request_to_source(uri, options)
end
end
+function parse_url(uri)
+ local url, rest, tmp = {}, nil, nil
+
+ url.scheme, rest = uri:match("^(%w+)://(.+)$")
+ if not (url.scheme and rest) then
+ return nil
+ end
+
+ url.auth, tmp = rest:match("^([^@]+)@(.+)$")
+ if url.auth and tmp then
+ rest = tmp
+ end
+
+ url.host, tmp = rest:match("^%[([0-9a-fA-F:]+)%](.*)$")
+ if url.host and tmp then
+ url.ip6addr = ip.IPv6(url.host)
+ if not url.ip6addr then
+ return nil
+ end
+ url.host = string.format("[%s]", url.ip6addr:string())
+ rest = tmp
+ else
+ url.host, tmp = rest:match("^(%d+%.%d+%.%d+%.%d+)(.*)$")
+ if url.host and tmp then
+ url.ipaddr = ip.IPv4(url.host)
+ if not url.ipaddr then
+ return nil
+ end
+ url.host = url.ipaddr:string()
+ rest = tmp
+ else
+ url.host, tmp = rest:match("^([0-9a-zA-Z%.%-]+)(.*)$")
+ if url.host and tmp then
+ rest = tmp
+ else
+ return nil
+ end
+ end
+ end
+
+ url.port, tmp = rest:match("^:(%d+)(.*)$")
+ if url.port and tmp then
+ url.port = tonumber(url.port)
+ rest = tmp
+ if url.port < 1 or url.port > 65535 then
+ return nil
+ end
+ end
+
+ if url.scheme == "http" then
+ url.port = url.port or 80
+ url.default_port = (url.port == 80)
+ elseif url.scheme == "https" then
+ url.port = url.port or 443
+ url.default_port = (url.port == 443)
+ end
+
+ if rest == "" then
+ url.path = "/"
+ else
+ url.path = rest
+ end
+
+ return url
+end
+
--
-- GET HTTP-resource
--
function request_raw(uri, options)
options = options or {}
- local pr, auth, host, port, path
if options.params then
uri = uri .. '?' .. http.urlencode_params(options.params)
end
- if uri:find("%[") then
- if uri:find("@") then
- pr, auth, host, port, path = uri:match("(%w+)://(.+)@(%b[]):?([0-9]*)(.*)")
- host = host:sub(2,-2)
- else
- pr, host, port, path = uri:match("(%w+)://(%b[]):?([0-9]*)(.*)")
- host = host:sub(2,-2)
- end
- else
- if uri:find("@") then
- pr, auth, host, port, path =
- uri:match("(%w+)://(.+)@([%w-.]+):?([0-9]*)(.*)")
- else
- pr, host, port, path = uri:match("(%w+)://([%w-.]+):?([0-9]*)(.*)")
- end
- end
+ local url = parse_url(uri)
- if not host then
+ if not url then
return nil, -1, "unable to parse URI"
end
-
- if pr ~= "http" and pr ~= "https" then
+
+ if url.scheme ~= "http" and url.scheme ~= "https" then
return nil, -2, "protocol not supported"
end
-
- port = #port > 0 and port or (pr == "https" and 443 or 80)
- path = #path > 0 and path or "/"
-
+
options.depth = options.depth or 10
local headers = options.headers or {}
local protocol = options.protocol or "HTTP/1.1"
headers["User-Agent"] = headers["User-Agent"] or "LuCI httpclient 0.1"
-
+
if headers.Connection == nil then
headers.Connection = "close"
end
-
- if auth and not headers.Authorization then
- headers.Authorization = "Basic " .. nixio.bin.b64encode(auth)
+
+ if url.auth and not headers.Authorization then
+ headers.Authorization = "Basic " .. nixio.bin.b64encode(url.auth)
end
- local sock, code, msg = nixio.connect(host, port)
+ local addr = tostring(url.ip6addr or url.ipaddr or url.host)
+ local sock, code, msg = nixio.connect(addr, url.port)
if not sock then
return nil, code, msg
end
-
+
sock:setsockopt("socket", "sndtimeo", options.sndtimeo or 15)
sock:setsockopt("socket", "rcvtimeo", options.rcvtimeo or 15)
-
- if pr == "https" then
+
+ if url.scheme == "https" then
local tls = options.tls_context or nixio.tls()
sock = tls:create(sock)
local stat, code, error = sock:connect()
@@ -160,11 +209,12 @@ function request_raw(uri, options)
end
end
- -- Pre assemble fixes
+ -- Pre assemble fixes
if protocol == "HTTP/1.1" then
- headers.Host = headers.Host or host
+ headers.Host = headers.Host or
+ (url.default_port and url.host or string.format("%s:%d", url.host, url.port))
end
-
+
if type(options.body) == "table" then
options.body = http.urlencode_params(options.body)
end
@@ -175,7 +225,7 @@ function request_raw(uri, options)
"application/x-www-form-urlencoded"
options.method = options.method or "POST"
end
-
+
if type(options.body) == "function" then
options.method = options.method or "POST"
end
@@ -185,12 +235,12 @@ function request_raw(uri, options)
for _, c in ipairs(options.cookies) do
local cdo = c.flags.domain
local cpa = c.flags.path
- if (cdo == host or cdo == "."..host or host:sub(-#cdo) == cdo)
- and (cpa == path or cpa == "/" or cpa .. "/" == path:sub(#cpa+1))
- and (not c.flags.secure or pr == "https")
+ if (cdo == url.host or cdo == "."..url.host or url.host:sub(-#cdo) == cdo)
+ and (cpa == url.path or cpa == "/" or cpa .. "/" == url.path:sub(#cpa+1))
+ and (not c.flags.secure or url.scheme == "https")
then
cookiedata[#cookiedata+1] = c.key .. "=" .. c.value
- end
+ end
end
if headers["Cookie"] then
headers["Cookie"] = headers["Cookie"] .. "; " .. table.concat(cookiedata, "; ")
@@ -200,8 +250,8 @@ function request_raw(uri, options)
end
-- Assemble message
- local message = {(options.method or "GET") .. " " .. path .. " " .. protocol}
-
+ local message = {(options.method or "GET") .. " " .. url.path .. " " .. protocol}
+
for k, v in pairs(headers) do
if type(v) == "string" or type(v) == "number" then
message[#message+1] = k .. ": " .. v
@@ -214,10 +264,10 @@ function request_raw(uri, options)
message[#message+1] = ""
message[#message+1] = ""
-
+
-- Send request
sock:sendall(table.concat(message, "\r\n"))
-
+
if type(options.body) == "string" then
sock:sendall(options.body)
elseif type(options.body) == "function" then
@@ -227,27 +277,27 @@ function request_raw(uri, options)
return unpack(res)
end
end
-
+
-- Create source and fetch response
local linesrc = sock:linesource()
local line, code, error = linesrc()
-
+
if not line then
sock:close()
return nil, code, error
end
-
+
local protocol, status, msg = line:match("^([%w./]+) ([0-9]+) (.*)")
-
+
if not protocol then
sock:close()
return nil, -3, "invalid response magic: " .. line
end
-
+
local response = {
status = line, headers = {}, code = 0, cookies = {}, uri = uri
}
-
+
line = linesrc()
while line and line ~= "" do
local key, val = line:match("^([%w-]+)%s?:%s?(.*)")
@@ -262,32 +312,32 @@ function request_raw(uri, options)
end
line = linesrc()
end
-
+
if not line then
sock:close()
return nil, -4, "protocol error"
end
-
+
-- Parse cookies
if response.headers["Set-Cookie"] then
local cookies = response.headers["Set-Cookie"]
for _, c in ipairs(type(cookies) == "table" and cookies or {cookies}) do
local cobj = cookie_parse(c)
- cobj.flags.path = cobj.flags.path or path:match("(/.*)/?[^/]*")
+ cobj.flags.path = cobj.flags.path or url.path:match("(/.*)/?[^/]*")
if not cobj.flags.domain or cobj.flags.domain == "" then
- cobj.flags.domain = host
+ cobj.flags.domain = url.host
response.cookies[#response.cookies+1] = cobj
else
local hprt, cprt = {}, {}
-
+
-- Split hostnames and save them in reverse order
- for part in host:gmatch("[^.]*") do
+ for part in url.host:gmatch("[^.]*") do
table.insert(hprt, 1, part)
end
for part in cobj.flags.domain:gmatch("[^.]*") do
table.insert(cprt, 1, part)
end
-
+
local valid = true
for i, part in ipairs(cprt) do
-- If parts are different and no wildcard
@@ -309,8 +359,8 @@ function request_raw(uri, options)
end
end
end
-
- -- Follow
+
+ -- Follow
response.code = tonumber(status)
if response.code and options.depth > 0 then
if (response.code == 301 or response.code == 302 or response.code == 307)
@@ -319,20 +369,21 @@ function request_raw(uri, options)
if not nuri then
return nil, -5, "invalid reference"
end
- if not nuri:find("https?://") then
- nuri = pr .. "://" .. host .. ":" .. port .. nuri
+ if not nuri:match("^%w+://") then
+ nuri = url.default_port and string.format("%s://%s%s", url.scheme, url.host, nuri)
+ or string.format("%s://%s:%d%s", url.scheme, url.host, url.port, nuri)
end
-
+
options.depth = options.depth - 1
if options.headers then
options.headers.Host = nil
end
sock:close()
-
+
return request_raw(nuri, options)
end
end
-
+
return response.code, response, linesrc(true)..sock:readall(), sock
end
diff --git a/libs/luci-lib-httpprotoutils/luasrc/http/mime.luadoc b/libs/luci-lib-httpprotoutils/luasrc/http/mime.luadoc
index 7751e2baf4..9c7f01aedf 100644
--- a/libs/luci-lib-httpprotoutils/luasrc/http/mime.luadoc
+++ b/libs/luci-lib-httpprotoutils/luasrc/http/mime.luadoc
@@ -7,7 +7,7 @@ vice versa.
module "luci.http.mime"
---[[
-MIME mapping table containg extension - mimetype relations.
+MIME mapping table containing extension - mimetype relations.
@class table
]]
diff --git a/libs/luci-lib-ip/src/ip.luadoc b/libs/luci-lib-ip/src/ip.luadoc
index b1ecae1453..a2df96cdb5 100644
--- a/libs/luci-lib-ip/src/ip.luadoc
+++ b/libs/luci-lib-ip/src/ip.luadoc
@@ -283,7 +283,7 @@ Fetch all routes, optionally matching the given criteria.
@sort 9
@name routes
@param filter <p>Table containing one or more of the possible filter
-critera described below (optional)</p><table>
+criteria described below (optional)</p><table>
<tr><th>Field</th><th>Description</th></tr>
<tr><td>`family`</td><td>
Number describing the address family to return - `4` selects
@@ -363,7 +363,7 @@ Fetches entries from the IPv4 ARP and IPv6 neighbour kernel table
@sort 10
@name neighbors
@param filter <p>Table containing one or more of the possible filter
-critera described below (optional)</p><table>
+criteria described below (optional)</p><table>
<tr><th>Field</th><th>Description</th></tr>
<tr><td>`family`</td><td>
Number describing the address family to return - `4` selects
@@ -652,7 +652,7 @@ are considered lower than MAC addresses</li>
@class function
@sort 10
@name cidr.lower
-@param addr A `luci.ip.cidr` instance or a string convertable by
+@param addr A `luci.ip.cidr` instance or a string convertible by
`luci.ip.new()` to compare against.
@return `true` if this CIDR is lower than the given address,
else `false`.
@@ -676,7 +676,7 @@ are considered lower than MAC addresses</li>
@class function
@sort 11
@name cidr.higher
-@param addr A `luci.ip.cidr` instance or a string convertable by
+@param addr A `luci.ip.cidr` instance or a string convertible by
`luci.ip.new()` to compare against.
@return `true` if this CIDR is higher than the given address,
else `false`.
@@ -696,7 +696,7 @@ Checks whether this CIDR instance is equal to the given argument.
@class function
@sort 12
@name cidr.equal
-@param addr A `luci.ip.cidr` instance or a string convertable by
+@param addr A `luci.ip.cidr` instance or a string convertible by
`luci.ip.new()` to compare against.
@return `true` if this CIDR is equal to the given address,
else `false`.
@@ -877,7 +877,7 @@ Test whether CIDR contains given range.
@class function
@sort 21
@name cidr.contains
-@param addr A `luci.ip.cidr` instance or a string convertable by
+@param addr A `luci.ip.cidr` instance or a string convertible by
`luci.ip.new()` to test.
@return `true` if this instance fully contains the given address else
`false`.
@@ -903,12 +903,12 @@ address space, the result is set to the highest possible address.
@sort 22
@name cidr.add
@param amount A numeric value between 0 and 0xFFFFFFFF, a
- `luci.ip.cidr` instance or a string convertable by
+ `luci.ip.cidr` instance or a string convertible by
`luci.ip.new()`.
@param inplace If `true`, modify this instance instead of returning
a new derived CIDR instance.
@return <ul>
- <li>When adding inplace: Return `true` if the addition succeded
+ <li>When adding inplace: Return `true` if the addition succeeded
or `false` when the addition overflowed.</li>
<li>When deriving new CIDR: Return new instance representing the value of
this instance plus the added amount or the highest possible address if
@@ -952,7 +952,7 @@ possible address is returned.
@sort 23
@name cidr.sub
@param amount A numeric value between 0 and 0xFFFFFFFF, a
- `luci.ip.cidr` instance or a string convertable by
+ `luci.ip.cidr` instance or a string convertible by
`luci.ip.new()`.
@param inplace If `true`, modify this instance instead of returning
a new derived CIDR instance.
diff --git a/libs/luci-lib-ipkg/Makefile b/libs/luci-lib-ipkg/Makefile
new file mode 100644
index 0000000000..52fcf6fe82
--- /dev/null
+++ b/libs/luci-lib-ipkg/Makefile
@@ -0,0 +1,14 @@
+#
+# Copyright (C) 2018 Jo-Philipp Wich <jo@mein.io>
+#
+# This is free software, licensed under the Apache License, Version 2.0 .
+#
+
+include $(TOPDIR)/rules.mk
+
+LUCI_TITLE:=Legacy opkg interface class
+LUCI_DEPENDS:=+luci-base
+
+include ../../luci.mk
+
+# call BuildPackage - OpenWrt buildroot signature
diff --git a/libs/luci-lib-ipkg/luasrc/model/ipkg.lua b/libs/luci-lib-ipkg/luasrc/model/ipkg.lua
new file mode 100644
index 0000000000..e27ea52895
--- /dev/null
+++ b/libs/luci-lib-ipkg/luasrc/model/ipkg.lua
@@ -0,0 +1,247 @@
+-- Copyright 2008-2011 Jo-Philipp Wich <jow@openwrt.org>
+-- Copyright 2008 Steven Barth <steven@midlink.org>
+-- Licensed to the public under the Apache License 2.0.
+
+local os = require "os"
+local io = require "io"
+local fs = require "nixio.fs"
+local util = require "luci.util"
+
+local type = type
+local pairs = pairs
+local error = error
+local table = table
+
+local ipkg = "opkg --force-removal-of-dependent-packages --force-overwrite --nocase"
+local icfg = "/etc/opkg.conf"
+
+module "luci.model.ipkg"
+
+
+-- Internal action function
+local function _action(cmd, ...)
+ local cmdline = { ipkg, cmd }
+
+ local k, v
+ for k, v in pairs({...}) do
+ cmdline[#cmdline+1] = util.shellquote(v)
+ end
+
+ local c = "%s >/tmp/opkg.stdout 2>/tmp/opkg.stderr" % table.concat(cmdline, " ")
+ local r = os.execute(c)
+ local e = fs.readfile("/tmp/opkg.stderr")
+ local o = fs.readfile("/tmp/opkg.stdout")
+
+ fs.unlink("/tmp/opkg.stderr")
+ fs.unlink("/tmp/opkg.stdout")
+
+ return r, o or "", e or ""
+end
+
+-- Internal parser function
+local function _parselist(rawdata)
+ if type(rawdata) ~= "function" then
+ error("OPKG: Invalid rawdata given")
+ end
+
+ local data = {}
+ local c = {}
+ local l = nil
+
+ for line in rawdata do
+ if line:sub(1, 1) ~= " " then
+ local key, val = line:match("(.-): ?(.*)%s*")
+
+ if key and val then
+ if key == "Package" then
+ c = {Package = val}
+ data[val] = c
+ elseif key == "Status" then
+ c.Status = {}
+ for j in val:gmatch("([^ ]+)") do
+ c.Status[j] = true
+ end
+ else
+ c[key] = val
+ end
+ l = key
+ end
+ else
+ -- Multi-line field
+ c[l] = c[l] .. "\n" .. line
+ end
+ end
+
+ return data
+end
+
+-- Internal lookup function
+local function _lookup(cmd, pkg)
+ local cmdline = { ipkg, cmd }
+ if pkg then
+ cmdline[#cmdline+1] = util.shellquote(pkg)
+ end
+
+ -- OPKG sometimes kills the whole machine because it sucks
+ -- Therefore we have to use a sucky approach too and use
+ -- tmpfiles instead of directly reading the output
+ local tmpfile = os.tmpname()
+ os.execute("%s >%s 2>/dev/null" %{ table.concat(cmdline, " "), tmpfile })
+
+ local data = _parselist(io.lines(tmpfile))
+ os.remove(tmpfile)
+ return data
+end
+
+
+function info(pkg)
+ return _lookup("info", pkg)
+end
+
+function status(pkg)
+ return _lookup("status", pkg)
+end
+
+function install(...)
+ return _action("install", ...)
+end
+
+function installed(pkg)
+ local p = status(pkg)[pkg]
+ return (p and p.Status and p.Status.installed)
+end
+
+function remove(...)
+ return _action("remove", ...)
+end
+
+function update()
+ return _action("update")
+end
+
+function upgrade()
+ return _action("upgrade")
+end
+
+-- List helper
+local function _list(action, pat, cb)
+ local cmdline = { ipkg, action }
+ if pat then
+ cmdline[#cmdline+1] = util.shellquote(pat)
+ end
+
+ local fd = io.popen(table.concat(cmdline, " "))
+ if fd then
+ local name, version, sz, desc
+ while true do
+ local line = fd:read("*l")
+ if not line then break end
+
+ name, version, sz, desc = line:match("^(.-) %- (.-) %- (.-) %- (.+)")
+
+ if not name then
+ name, version, sz = line:match("^(.-) %- (.-) %- (.+)")
+ desc = ""
+ end
+
+ if name and version then
+ if #version > 26 then
+ version = version:sub(1,21) .. ".." .. version:sub(-3,-1)
+ end
+
+ cb(name, version, sz, desc)
+ end
+
+ name = nil
+ version = nil
+ sz = nil
+ desc = nil
+ end
+
+ fd:close()
+ end
+end
+
+function list_all(pat, cb)
+ _list("list --size", pat, cb)
+end
+
+function list_installed(pat, cb)
+ _list("list_installed --size", pat, cb)
+end
+
+function find(pat, cb)
+ _list("find --size", pat, cb)
+end
+
+
+function overlay_root()
+ local od = "/"
+ local fd = io.open(icfg, "r")
+
+ if fd then
+ local ln
+
+ repeat
+ ln = fd:read("*l")
+ if ln and ln:match("^%s*option%s+overlay_root%s+") then
+ od = ln:match("^%s*option%s+overlay_root%s+(%S+)")
+
+ local s = fs.stat(od)
+ if not s or s.type ~= "dir" then
+ od = "/"
+ end
+
+ break
+ end
+ until not ln
+
+ fd:close()
+ end
+
+ return od
+end
+
+function compare_versions(ver1, comp, ver2)
+ if not ver1 or not ver2
+ or not comp or not (#comp > 0) then
+ error("Invalid parameters")
+ return nil
+ end
+ -- correct compare string
+ if comp == "<>" or comp == "><" or comp == "!=" or comp == "~=" then comp = "~="
+ elseif comp == "<=" or comp == "<" or comp == "=<" then comp = "<="
+ elseif comp == ">=" or comp == ">" or comp == "=>" then comp = ">="
+ elseif comp == "=" or comp == "==" then comp = "=="
+ elseif comp == "<<" then comp = "<"
+ elseif comp == ">>" then comp = ">"
+ else
+ error("Invalid compare string")
+ return nil
+ end
+
+ local av1 = util.split(ver1, "[%.%-]", nil, true)
+ local av2 = util.split(ver2, "[%.%-]", nil, true)
+
+ local max = table.getn(av1)
+ if (table.getn(av1) < table.getn(av2)) then
+ max = table.getn(av2)
+ end
+
+ for i = 1, max, 1 do
+ local s1 = av1[i] or ""
+ local s2 = av2[i] or ""
+
+ -- first "not equal" found return true
+ if comp == "~=" and (s1 ~= s2) then return true end
+ -- first "lower" found return true
+ if (comp == "<" or comp == "<=") and (s1 < s2) then return true end
+ -- first "greater" found return true
+ if (comp == ">" or comp == ">=") and (s1 > s2) then return true end
+ -- not equal then return false
+ if (s1 ~= s2) then return false end
+ end
+
+ -- all equal and not compare greater or lower then true
+ return not (comp == "<" or comp == ">")
+end
diff --git a/libs/luci-lib-ipkg/luasrc/model/ipkg.luadoc b/libs/luci-lib-ipkg/luasrc/model/ipkg.luadoc
new file mode 100644
index 0000000000..4e1548dda6
--- /dev/null
+++ b/libs/luci-lib-ipkg/luasrc/model/ipkg.luadoc
@@ -0,0 +1,125 @@
+---[[
+LuCI OPKG call abstraction library
+]]
+module "luci.model.ipkg"
+
+---[[
+Return information about installed and available packages.
+
+@class function
+@name info
+@param pkg Limit output to a (set of) packages
+@return Table containing package information
+]]
+
+---[[
+Return the package status of one or more packages.
+
+@class function
+@name status
+@param pkg Limit output to a (set of) packages
+@return Table containing package status information
+]]
+
+---[[
+Install one or more packages.
+
+@class function
+@name install
+@param ... List of packages to install
+@return Boolean indicating the status of the action
+@return OPKG return code, STDOUT and STDERR
+]]
+
+---[[
+Determine whether a given package is installed.
+
+@class function
+@name installed
+@param pkg Package
+@return Boolean
+]]
+
+---[[
+Remove one or more packages.
+
+@class function
+@name remove
+@param ... List of packages to install
+@return Boolean indicating the status of the action
+@return OPKG return code, STDOUT and STDERR
+]]
+
+---[[
+Update package lists.
+
+@class function
+@name update
+@return Boolean indicating the status of the action
+@return OPKG return code, STDOUT and STDERR
+]]
+
+---[[
+Upgrades all installed packages.
+
+@class function
+@name upgrade
+@return Boolean indicating the status of the action
+@return OPKG return code, STDOUT and STDERR
+]]
+
+---[[
+List all packages known to opkg.
+
+@class function
+@name list_all
+@param pat Only find packages matching this pattern, nil lists all packages
+@param cb Callback function invoked for each package, receives name, version and description as arguments
+@return nothing
+]]
+
+---[[
+List installed packages.
+
+@class function
+@name list_installed
+@param pat Only find packages matching this pattern, nil lists all packages
+@param cb Callback function invoked for each package, receives name, version and description as arguments
+@return nothing
+]]
+
+---[[
+Find packages that match the given pattern.
+
+@class function
+@name find
+@param pat Find packages whose names or descriptions match this pattern, nil results in zero results
+@param cb Callback function invoked for each patckage, receives name, version and description as arguments
+@return nothing
+]]
+
+---[[
+Determines the overlay root used by opkg.
+
+@class function
+@name overlay_root
+@return String containing the directory path of the overlay root.
+]]
+
+---[[
+lua version of opkg compare-versions
+
+@class function
+@name compare_versions
+@param ver1 string version 1
+@param ver2 string version 2
+@param comp string compare versions using
+ "<=" or "<" lower-equal
+ ">" or ">=" greater-equal
+ "=" equal
+ "<<" lower
+ ">>" greater
+ "~=" not equal
+@return Boolean indicating the status of the compare
+]]
+
diff --git a/libs/luci-lib-iptparser/Makefile b/libs/luci-lib-iptparser/Makefile
new file mode 100644
index 0000000000..06748adbfc
--- /dev/null
+++ b/libs/luci-lib-iptparser/Makefile
@@ -0,0 +1,14 @@
+#
+# Copyright (C) 2018 The LuCI Team <luci@lists.subsignal.org>
+#
+# This is free software, licensed under the Apache License, Version 2.0 .
+#
+
+include $(TOPDIR)/rules.mk
+
+LUCI_TITLE:=Iptables listing parser class
+LUCI_DEPENDS:=+luci-base
+
+include ../../luci.mk
+
+# call BuildPackage - OpenWrt buildroot signature
diff --git a/libs/luci-lib-iptparser/luasrc/sys/iptparser.lua b/libs/luci-lib-iptparser/luasrc/sys/iptparser.lua
new file mode 100644
index 0000000000..7ff665e7af
--- /dev/null
+++ b/libs/luci-lib-iptparser/luasrc/sys/iptparser.lua
@@ -0,0 +1,374 @@
+--[[
+
+Iptables parser and query library
+(c) 2008-2009 Jo-Philipp Wich <jow@openwrt.org>
+(c) 2008-2009 Steven Barth <steven@midlink.org>
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+$Id$
+
+]]--
+
+local luci = {}
+luci.util = require "luci.util"
+luci.sys = require "luci.sys"
+luci.ip = require "luci.ip"
+
+local pcall = pcall
+local io = require "io"
+local tonumber, ipairs, table = tonumber, ipairs, table
+
+module("luci.sys.iptparser")
+
+IptParser = luci.util.class()
+
+function IptParser.__init__( self, family )
+ self._family = (tonumber(family) == 6) and 6 or 4
+ self._rules = { }
+ self._chains = { }
+ self._tables = { }
+
+ local t = self._tables
+ local s = self:_supported_tables(self._family)
+
+ if s.filter then t[#t+1] = "filter" end
+ if s.nat then t[#t+1] = "nat" end
+ if s.mangle then t[#t+1] = "mangle" end
+ if s.raw then t[#t+1] = "raw" end
+
+ if self._family == 4 then
+ self._nulladdr = "0.0.0.0/0"
+ self._command = "iptables -t %s --line-numbers -nxvL"
+ else
+ self._nulladdr = "::/0"
+ self._command = "ip6tables -t %s --line-numbers -nxvL"
+ end
+
+ self:_parse_rules()
+end
+
+function IptParser._supported_tables( self, family )
+ local tables = { }
+ local ok, lines = pcall(io.lines,
+ (family == 6) and "/proc/net/ip6_tables_names"
+ or "/proc/net/ip_tables_names")
+
+ if ok and lines then
+ local line
+ for line in lines do
+ tables[line] = true
+ end
+ end
+
+ return tables
+end
+
+-- search criteria as only argument. If args is nil or an empty table then all
+-- rules will be returned.
+--
+-- The following keys in the args table are recognized:
+-- <ul>
+-- <li> table - Match rules that are located within the given table
+-- <li> chain - Match rules that are located within the given chain
+-- <li> target - Match rules with the given target
+-- <li> protocol - Match rules that match the given protocol, rules with
+-- protocol "all" are always matched
+-- <li> source - Match rules with the given source, rules with source
+-- "0.0.0.0/0" (::/0) are always matched
+-- <li> destination - Match rules with the given destination, rules with
+-- destination "0.0.0.0/0" (::/0) are always matched
+-- <li> inputif - Match rules with the given input interface, rules
+-- with input interface "*" (=all) are always matched
+-- <li> outputif - Match rules with the given output interface, rules
+-- with output interface "*" (=all) are always matched
+-- <li> flags - Match rules that match the given flags, current
+-- supported values are "-f" (--fragment)
+-- and "!f" (! --fragment)
+-- <li> options - Match rules containing all given options
+-- </ul>
+-- The return value is a list of tables representing the matched rules.
+-- Each rule table contains the following fields:
+-- <ul>
+-- <li> index - The index number of the rule
+-- <li> table - The table where the rule is located, can be one
+-- of "filter", "nat" or "mangle"
+-- <li> chain - The chain where the rule is located, e.g. "INPUT"
+-- or "postrouting_wan"
+-- <li> target - The rule target, e.g. "REJECT" or "DROP"
+-- <li> protocol The matching protocols, e.g. "all" or "tcp"
+-- <li> flags - Special rule options ("--", "-f" or "!f")
+-- <li> inputif - Input interface of the rule, e.g. "eth0.0"
+-- or "*" for all interfaces
+-- <li> outputif - Output interface of the rule,e.g. "eth0.0"
+-- or "*" for all interfaces
+-- <li> source - The source ip range, e.g. "0.0.0.0/0" (::/0)
+-- <li> destination - The destination ip range, e.g. "0.0.0.0/0" (::/0)
+-- <li> options - A list of specific options of the rule,
+-- e.g. { "reject-with", "tcp-reset" }
+-- <li> packets - The number of packets matched by the rule
+-- <li> bytes - The number of total bytes matched by the rule
+-- </ul>
+-- Example:
+-- <pre>
+-- ip = luci.sys.iptparser.IptParser()
+-- result = ip.find( {
+-- target="REJECT",
+-- protocol="tcp",
+-- options={ "reject-with", "tcp-reset" }
+-- } )
+-- </pre>
+-- This will match all rules with target "-j REJECT",
+-- protocol "-p tcp" (or "-p all")
+-- and the option "--reject-with tcp-reset".
+function IptParser.find( self, args )
+
+ local args = args or { }
+ local rv = { }
+
+ args.source = args.source and self:_parse_addr(args.source)
+ args.destination = args.destination and self:_parse_addr(args.destination)
+
+ for i, rule in ipairs(self._rules) do
+ local match = true
+
+ -- match table
+ if not ( not args.table or args.table:lower() == rule.table ) then
+ match = false
+ end
+
+ -- match chain
+ if not ( match == true and (
+ not args.chain or args.chain == rule.chain
+ ) ) then
+ match = false
+ end
+
+ -- match target
+ if not ( match == true and (
+ not args.target or args.target == rule.target
+ ) ) then
+ match = false
+ end
+
+ -- match protocol
+ if not ( match == true and (
+ not args.protocol or rule.protocol == "all" or
+ args.protocol:lower() == rule.protocol
+ ) ) then
+ match = false
+ end
+
+ -- match source
+ if not ( match == true and (
+ not args.source or rule.source == self._nulladdr or
+ self:_parse_addr(rule.source):contains(args.source)
+ ) ) then
+ match = false
+ end
+
+ -- match destination
+ if not ( match == true and (
+ not args.destination or rule.destination == self._nulladdr or
+ self:_parse_addr(rule.destination):contains(args.destination)
+ ) ) then
+ match = false
+ end
+
+ -- match input interface
+ if not ( match == true and (
+ not args.inputif or rule.inputif == "*" or
+ args.inputif == rule.inputif
+ ) ) then
+ match = false
+ end
+
+ -- match output interface
+ if not ( match == true and (
+ not args.outputif or rule.outputif == "*" or
+ args.outputif == rule.outputif
+ ) ) then
+ match = false
+ end
+
+ -- match flags (the "opt" column)
+ if not ( match == true and (
+ not args.flags or rule.flags == args.flags
+ ) ) then
+ match = false
+ end
+
+ -- match specific options
+ if not ( match == true and (
+ not args.options or
+ self:_match_options( rule.options, args.options )
+ ) ) then
+ match = false
+ end
+
+ -- insert match
+ if match == true then
+ rv[#rv+1] = rule
+ end
+ end
+
+ return rv
+end
+
+
+-- through external commands.
+function IptParser.resync( self )
+ self._rules = { }
+ self._chain = nil
+ self:_parse_rules()
+end
+
+
+function IptParser.tables( self )
+ return self._tables
+end
+
+
+function IptParser.chains( self, table )
+ local lookup = { }
+ local chains = { }
+ for _, r in ipairs(self:find({table=table})) do
+ if not lookup[r.chain] then
+ lookup[r.chain] = true
+ chains[#chains+1] = r.chain
+ end
+ end
+ return chains
+end
+
+
+-- and "rules". The "rules" field is a table of rule tables.
+function IptParser.chain( self, table, chain )
+ return self._chains[table:lower()] and self._chains[table:lower()][chain]
+end
+
+
+function IptParser.is_custom_target( self, target )
+ for _, r in ipairs(self._rules) do
+ if r.chain == target then
+ return true
+ end
+ end
+ return false
+end
+
+
+-- [internal] Parse address according to family.
+function IptParser._parse_addr( self, addr )
+ if self._family == 4 then
+ return luci.ip.IPv4(addr)
+ else
+ return luci.ip.IPv6(addr)
+ end
+end
+
+-- [internal] Parse iptables output from all tables.
+function IptParser._parse_rules( self )
+
+ for i, tbl in ipairs(self._tables) do
+
+ self._chains[tbl] = { }
+
+ for i, rule in ipairs(luci.util.execl(self._command % tbl)) do
+
+ if rule:find( "^Chain " ) == 1 then
+
+ local crefs
+ local cname, cpol, cpkt, cbytes = rule:match(
+ "^Chain ([^%s]*) %(policy (%w+) " ..
+ "(%d+) packets, (%d+) bytes%)"
+ )
+
+ if not cname then
+ cname, crefs = rule:match(
+ "^Chain ([^%s]*) %((%d+) references%)"
+ )
+ end
+
+ self._chain = cname
+ self._chains[tbl][cname] = {
+ policy = cpol,
+ packets = tonumber(cpkt or 0),
+ bytes = tonumber(cbytes or 0),
+ references = tonumber(crefs or 0),
+ rules = { }
+ }
+
+ else
+ if rule:find("%d") == 1 then
+
+ local rule_parts = luci.util.split( rule, "%s+", nil, true )
+ local rule_details = { }
+
+ -- cope with rules that have no target assigned
+ if rule:match("^%d+%s+%d+%s+%d+%s%s") then
+ table.insert(rule_parts, 4, nil)
+ end
+
+ -- ip6tables opt column is usually zero-width
+ if self._family == 6 then
+ table.insert(rule_parts, 6, "--")
+ end
+
+ rule_details["table"] = tbl
+ rule_details["chain"] = self._chain
+ rule_details["index"] = tonumber(rule_parts[1])
+ rule_details["packets"] = tonumber(rule_parts[2])
+ rule_details["bytes"] = tonumber(rule_parts[3])
+ rule_details["target"] = rule_parts[4]
+ rule_details["protocol"] = rule_parts[5]
+ rule_details["flags"] = rule_parts[6]
+ rule_details["inputif"] = rule_parts[7]
+ rule_details["outputif"] = rule_parts[8]
+ rule_details["source"] = rule_parts[9]
+ rule_details["destination"] = rule_parts[10]
+ rule_details["options"] = { }
+
+ for i = 11, #rule_parts do
+ if #rule_parts[i] > 0 then
+ rule_details["options"][i-10] = rule_parts[i]
+ end
+ end
+
+ self._rules[#self._rules+1] = rule_details
+
+ self._chains[tbl][self._chain].rules[
+ #self._chains[tbl][self._chain].rules + 1
+ ] = rule_details
+ end
+ end
+ end
+ end
+
+ self._chain = nil
+end
+
+
+-- [internal] Return true if optlist1 contains all elements of optlist 2.
+-- Return false in all other cases.
+function IptParser._match_options( self, o1, o2 )
+
+ -- construct a hashtable of first options list to speed up lookups
+ local oh = { }
+ for i, opt in ipairs( o1 ) do oh[opt] = true end
+
+ -- iterate over second options list
+ -- each string in o2 must be also present in o1
+ -- if o2 contains a string which is not found in o1 then return false
+ for i, opt in ipairs( o2 ) do
+ if not oh[opt] then
+ return false
+ end
+ end
+
+ return true
+end
diff --git a/libs/luci-lib-iptparser/luasrc/sys/iptparser.luadoc b/libs/luci-lib-iptparser/luasrc/sys/iptparser.luadoc
new file mode 100644
index 0000000000..071e7d52e4
--- /dev/null
+++ b/libs/luci-lib-iptparser/luasrc/sys/iptparser.luadoc
@@ -0,0 +1,69 @@
+---[[
+LuCI iptables parser and query library
+
+@cstyle instance
+]]
+module "luci.sys.iptparser"
+
+---[[
+Create a new iptables parser object.
+
+@class function
+@name IptParser
+@param family Number specifying the address family. 4 for IPv4, 6 for IPv6
+@return IptParser instance
+]]
+
+---[[
+Find all firewall rules that match the given criteria. Expects a table with
+
+search criteria as only argument. If args is nil or an empty table then all
+rules will be returned.
+]]
+
+---[[
+Rebuild the internal lookup table, for example when rules have changed
+
+through external commands.
+@class function
+@name IptParser.resync
+@return nothing
+]]
+
+---[[
+Find the names of all tables.
+
+@class function
+@name IptParser.tables
+@return Table of table names.
+]]
+
+---[[
+Find the names of all chains within the given table name.
+
+@class function
+@name IptParser.chains
+@param table String containing the table name
+@return Table of chain names in the order they occur.
+]]
+
+---[[
+Return the given firewall chain within the given table name.
+
+@class function
+@name IptParser.chain
+@param table String containing the table name
+@param chain String containing the chain name
+@return Table containing the fields "policy", "packets", "bytes"
+-- and "rules". The "rules" field is a table of rule tables.
+]]
+
+---[[
+Test whether the given target points to a custom chain.
+
+@class function
+@name IptParser.is_custom_target
+@param target String containing the target action
+@return Boolean indicating whether target is a custom chain.
+]]
+
diff --git a/libs/luci-lib-jsonc/src/jsonc.c b/libs/luci-lib-jsonc/src/jsonc.c
index ef11101660..9ff8520dbc 100644
--- a/libs/luci-lib-jsonc/src/jsonc.c
+++ b/libs/luci-lib-jsonc/src/jsonc.c
@@ -27,6 +27,12 @@ limitations under the License.
#define LUCI_JSONC "luci.jsonc"
#define LUCI_JSONC_PARSER "luci.jsonc.parser"
+struct seen {
+ size_t size;
+ size_t len;
+ const void *ptrs[];
+};
+
struct json_state {
struct json_object *obj;
struct json_tokener *tok;
@@ -35,6 +41,7 @@ struct json_state {
static void _json_to_lua(lua_State *L, struct json_object *obj);
static struct json_object * _lua_to_json(lua_State *L, int index);
+static struct json_object * _lua_to_json_rec(lua_State *L, int index, struct seen **seen);
static int json_new(lua_State *L)
{
@@ -199,6 +206,9 @@ static int _lua_test_array(lua_State *L, int index)
int max = 0;
lua_Number idx;
+ if (!lua_checkstack(L, 2))
+ return -1;
+
lua_pushnil(L);
/* check for non-integer keys */
@@ -243,16 +253,54 @@ out:
return max;
}
-static struct json_object * _lua_to_json(lua_State *L, int index)
+
+static bool visited(struct seen **sp, const void *ptr) {
+ struct seen *s = *sp;
+ size_t i;
+
+ if (s->len >= s->size)
+ {
+ i = s->size + 10;
+ s = realloc(*sp, sizeof(struct seen) + sizeof(void *) * i);
+
+ if (!s)
+ {
+ if (*sp)
+ free(*sp);
+
+ *sp = NULL;
+ return true;
+ }
+
+ s->size = i;
+ *sp = s;
+ }
+
+ for (i = 0; i < s->len; i++)
+ if (s->ptrs[i] == ptr)
+ return true;
+
+ s->ptrs[s->len++] = ptr;
+ return false;
+}
+
+static struct json_object * _lua_to_json_rec(lua_State *L, int index,
+ struct seen **seen)
{
lua_Number nd, ni;
struct json_object *obj;
const char *key;
int i, max;
+ if (index < 0)
+ index = lua_gettop(L) + index + 1;
+
switch (lua_type(L, index))
{
case LUA_TTABLE:
+ if (visited(seen, lua_topointer(L, index)))
+ return NULL;
+
max = _lua_test_array(L, index);
if (max >= 0)
@@ -262,12 +310,15 @@ static struct json_object * _lua_to_json(lua_State *L, int index)
if (!obj)
return NULL;
+ if (!lua_checkstack(L, 1))
+ return NULL;
+
for (i = 1; i <= max; i++)
{
lua_rawgeti(L, index, i);
json_object_array_put_idx(obj, i - 1,
- _lua_to_json(L, lua_gettop(L)));
+ _lua_to_json_rec(L, -1, seen));
lua_pop(L, 1);
}
@@ -280,6 +331,9 @@ static struct json_object * _lua_to_json(lua_State *L, int index)
if (!obj)
return NULL;
+ if (!lua_checkstack(L, 3))
+ return NULL;
+
lua_pushnil(L);
while (lua_next(L, index))
@@ -289,7 +343,7 @@ static struct json_object * _lua_to_json(lua_State *L, int index)
if (key)
json_object_object_add(obj, key,
- _lua_to_json(L, lua_gettop(L) - 1));
+ _lua_to_json_rec(L, -2, seen));
lua_pop(L, 2);
}
@@ -318,6 +372,23 @@ static struct json_object * _lua_to_json(lua_State *L, int index)
return NULL;
}
+static struct json_object * _lua_to_json(lua_State *L, int index)
+{
+ struct seen *s = calloc(sizeof(struct seen) + sizeof(void *) * 10, 1);
+ struct json_object *rv;
+
+ if (!s)
+ return NULL;
+
+ s->size = 10;
+
+ rv = _lua_to_json_rec(L, index, &s);
+
+ free(s);
+
+ return rv;
+}
+
static int json_parse_set(lua_State *L)
{
struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
diff --git a/libs/luci-lib-nixio/Makefile b/libs/luci-lib-nixio/Makefile
index bec5f83cda..4e501b89ce 100644
--- a/libs/luci-lib-nixio/Makefile
+++ b/libs/luci-lib-nixio/Makefile
@@ -11,6 +11,44 @@ LUCI_DEPENDS:=+PACKAGE_luci-lib-nixio_openssl:libopenssl +PACKAGE_luci-lib-nixio
PKG_LICENSE:=Apache-2.0
+define Package/luci-lib-nixio/config
+ choice
+ prompt "TLS Provider"
+ default PACKAGE_luci-lib-nixio_notls
+
+ config PACKAGE_luci-lib-nixio_notls
+ bool "Disabled"
+
+ config PACKAGE_luci-lib-nixio_axtls
+ bool "Builtin (axTLS)"
+
+ config PACKAGE_luci-lib-nixio_cyassl
+ bool "CyaSSL"
+ select PACKAGE_libcyassl
+
+ config PACKAGE_luci-lib-nixio_openssl
+ bool "OpenSSL"
+ select PACKAGE_libopenssl
+ endchoice
+endef
+
+NIXIO_TLS:=
+
+ifneq ($(CONFIG_PACKAGE_luci-lib-nixio_axtls),)
+ NIXIO_TLS:=axtls
+endif
+
+ifneq ($(CONFIG_PACKAGE_luci-lib-nixio_openssl),)
+ NIXIO_TLS:=openssl
+endif
+
+ifneq ($(CONFIG_PACKAGE_luci-lib-nixio_cyassl),)
+ NIXIO_TLS:=cyassl
+ LUCI_CFLAGS+=-I$(STAGING_DIR)/usr/include/cyassl
+endif
+
+MAKE_VARS += NIXIO_TLS="$(NIXIO_TLS)"
+
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature
diff --git a/libs/luci-lib-nixio/docsrc/CHANGELOG.lua b/libs/luci-lib-nixio/docsrc/CHANGELOG.lua
index aa31841402..8c9260317b 100644
--- a/libs/luci-lib-nixio/docsrc/CHANGELOG.lua
+++ b/libs/luci-lib-nixio/docsrc/CHANGELOG.lua
@@ -10,7 +10,7 @@ module "nixio.CHANGELOG"
-- <li>Added support for x509 certificates in DER format.</li>
-- <li>Added support for splice() in UnifiedIO.copyz().</li>
-- <li>Added interface to inject chunks into UnifiedIO.linesource() buffer.</li>
--- <li>Changed TLS behaviour to explicitely separate servers and clients.</li>
+-- <li>Changed TLS behaviour to explicitly separate servers and clients.</li>
-- <li>Fixed usage of signed datatype breaking Base64 decoding.</li>
-- <li>Fixed namespace clashes for nixio.fs.</li>
-- <li>Fixed splice() support for some exotic C libraries.</li>
diff --git a/libs/luci-lib-nixio/docsrc/README.lua b/libs/luci-lib-nixio/docsrc/README.lua
index 9860cf0919..d663b629ee 100644
--- a/libs/luci-lib-nixio/docsrc/README.lua
+++ b/libs/luci-lib-nixio/docsrc/README.lua
@@ -18,7 +18,7 @@ module "nixio.README"
-- table <strong>nixio.const_sock</strong> for socket error codes. This might
-- be important if you are dealing with Windows applications, on POSIX however
-- const_sock is just an alias for const.</li>
--- <li>With some exceptions - which are explicitely stated in the function
+-- <li>With some exceptions - which are explicitly stated in the function
-- documentation - all blocking functions are signal-protected and will not fail
-- with EINTR.</li>
-- <li>On POSIX the SIGPIPE signal will be set to ignore upon initialization.
diff --git a/libs/luci-lib-nixio/docsrc/nixio.lua b/libs/luci-lib-nixio/docsrc/nixio.lua
index 1a0d69a054..56a4afbb88 100644
--- a/libs/luci-lib-nixio/docsrc/nixio.lua
+++ b/libs/luci-lib-nixio/docsrc/nixio.lua
@@ -59,7 +59,7 @@ module "nixio"
-- <li>aliases = Table of alias names</li>
-- </ul>
---- Get all or a specifc proto entry.
+--- Get all or a specific proto entry.
-- @class function
-- @name nixio.getproto
-- @param proto protocol number or name to lookup (optional)
diff --git a/libs/luci-lib-px5g/src/library/bignum.c b/libs/luci-lib-px5g/src/library/bignum.c
index 8b7c12ff00..d2a8ff42e1 100644
--- a/libs/luci-lib-px5g/src/library/bignum.c
+++ b/libs/luci-lib-px5g/src/library/bignum.c
@@ -720,7 +720,7 @@ cleanup:
}
/*
- * Helper for mpi substraction
+ * Helper for mpi subtraction
*/
static void mpi_sub_hlp( int n, t_int *s, t_int *d )
{
@@ -741,7 +741,7 @@ static void mpi_sub_hlp( int n, t_int *s, t_int *d )
}
/*
- * Unsigned substraction: X = |A| - |B| (HAC 14.9)
+ * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
*/
int mpi_sub_abs( mpi *X, mpi *A, mpi *B )
{
@@ -809,7 +809,7 @@ cleanup:
}
/*
- * Signed substraction: X = A - B
+ * Signed subtraction: X = A - B
*/
int mpi_sub_mpi( mpi *X, mpi *A, mpi *B )
{
@@ -856,7 +856,7 @@ int mpi_add_int( mpi *X, mpi *A, int b )
}
/*
- * Signed substraction: X = A - b
+ * Signed subtraction: X = A - b
*/
int mpi_sub_int( mpi *X, mpi *A, int b )
{
diff --git a/libs/luci-lib-px5g/src/library/x509write.c b/libs/luci-lib-px5g/src/library/x509write.c
index 173610c1a0..b9ebf35bae 100644
--- a/libs/luci-lib-px5g/src/library/x509write.c
+++ b/libs/luci-lib-px5g/src/library/x509write.c
@@ -19,7 +19,7 @@
* MA 02110-1301 USA
*/
/*
- * The ITU-T X.509 standard defines a certificat format for PKI.
+ * The ITU-T X.509 standard defines a certificate format for PKI.
*
* http://www.ietf.org/rfc/rfc2459.txt
* http://www.ietf.org/rfc/rfc3279.txt
@@ -68,7 +68,7 @@ static int asn1_eval_octet(unsigned int digit)
}
/*
- * write the asn.1 lenght form into p
+ * write the asn.1 length form into p
*/
static int asn1_add_len(unsigned int size, x509_node *node)
{
@@ -788,7 +788,7 @@ static int x509write_parse_names(x509_node *node, unsigned char *names)
R_len = len;
}
- /* set tag poiner to begin */
+ /* set tag pointer to begin */
tag_sp = tag;
/* is at end? */
@@ -866,7 +866,7 @@ static int x509write_parse_names(x509_node *node, unsigned char *names)
}
/*
- * Copy raw data from orginal ca to node
+ * Copy raw data from original ca to node
*/
static int x509write_copy_from_raw(x509_node *node, x509_buf *raw)
{
diff --git a/libs/luci-lib-px5g/src/polarssl/bignum.h b/libs/luci-lib-px5g/src/polarssl/bignum.h
index c667303329..cf443ea922 100644
--- a/libs/luci-lib-px5g/src/polarssl/bignum.h
+++ b/libs/luci-lib-px5g/src/polarssl/bignum.h
@@ -272,7 +272,7 @@ int mpi_cmp_int( mpi *X, int z );
int mpi_add_abs( mpi *X, mpi *A, mpi *B );
/**
- * \brief Unsigned substraction: X = |A| - |B|
+ * \brief Unsigned subtraction: X = |A| - |B|
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_NEGATIVE_VALUE if B is greater than A
@@ -288,7 +288,7 @@ int mpi_sub_abs( mpi *X, mpi *A, mpi *B );
int mpi_add_mpi( mpi *X, mpi *A, mpi *B );
/**
- * \brief Signed substraction: X = A - B
+ * \brief Signed subtraction: X = A - B
*
* \return 0 if successful,
* 1 if memory allocation failed
@@ -304,7 +304,7 @@ int mpi_sub_mpi( mpi *X, mpi *A, mpi *B );
int mpi_add_int( mpi *X, mpi *A, int b );
/**
- * \brief Signed substraction: X = A - b
+ * \brief Signed subtraction: X = A - b
*
* \return 0 if successful,
* 1 if memory allocation failed
diff --git a/libs/luci-lib-px5g/src/polarssl/x509.h b/libs/luci-lib-px5g/src/polarssl/x509.h
index 908a1dbf51..6c9ef99a8a 100644
--- a/libs/luci-lib-px5g/src/polarssl/x509.h
+++ b/libs/luci-lib-px5g/src/polarssl/x509.h
@@ -375,7 +375,7 @@ int x509write_add_pubkey( x509_raw *chain, rsa_context *pubkey );
* the string parse.
*
* \param chain points to the raw certificate data
- * \param names a string that can hold (separete with ";"):
+ * \param names a string that can hold (separate with ";"):
* CN=CommonName
* -- O=Organization
* -- OU=OrgUnit
@@ -402,7 +402,7 @@ int x509write_add_customize ( x509_raw *crt,
* \brief Add x509 issuer field
*
* \param chain points to the raw certificate data
-* \param issuer a string holding (separete with ";"):
+* \param issuer a string holding (separate with ";"):
* CN=CommonName
* -- O=Organization
* -- OU=OrgUnit
@@ -419,7 +419,7 @@ int x509write_add_issuer( x509_raw *crt, unsigned char *issuer);
* \brief Add x509 subject field
*
* \param chain points to the raw certificate data
- * \param subject a string holding (separete with ";"):
+ * \param subject a string holding (separate with ";"):
* CN=CommonName
* -- O=Organization
* -- OU=OrgUnit
diff --git a/libs/rpcd-mod-rad2-enc/Makefile b/libs/rpcd-mod-rad2-enc/Makefile
new file mode 100644
index 0000000000..4cffc01cd3
--- /dev/null
+++ b/libs/rpcd-mod-rad2-enc/Makefile
@@ -0,0 +1,49 @@
+#
+# Copyright (C) 2016-2017 Jo-Philipp Wich <jo@mein.io>
+#
+# Licensed under the Apache License, Version 2.0.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=rpcd-mod-rad2-enc
+PKG_VERSION:=20190109
+PKG_MAINTAINER:=Daniel Dickinson <cshored@thecshore.com>
+
+PKG_LICENSE:=Apache-2.0
+
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Build/Prepare
+ true
+endef
+
+define Build/Compile
+ true
+endef
+
+define Package/rpcd-mod-rad2-enc
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=Radicale 2.x Hashing RPC module
+ DEPENDS:=+rpcd +python3 +python3-passlib
+endef
+
+define Package/rpcd-mod-rad2-enc/description
+ Python3 password hashing module for use Radicale 2.x LuCI app
+endef
+
+define Package/rpcd-mod-rad2-enc/install
+ $(INSTALL_DIR) $(1)/usr/libexec/rpcd
+ $(INSTALL_BIN) ./files/rad2-enc $(1)/usr/libexec/rpcd
+endef
+
+define Package/rpcd-mod-rad2-enc/postinst
+#!/bin/sh
+killall -HUP rpcd 2>/dev/null
+exit 0
+endef
+
+$(eval $(call BuildPackage,rpcd-mod-rad2-enc))
diff --git a/libs/rpcd-mod-rad2-enc/files/rad2-enc b/libs/rpcd-mod-rad2-enc/files/rad2-enc
new file mode 100755
index 0000000000..43bc49325c
--- /dev/null
+++ b/libs/rpcd-mod-rad2-enc/files/rad2-enc
@@ -0,0 +1,50 @@
+#!/usr/bin/python3
+
+import base64
+import sys
+import json
+from passlib import hash
+
+def main():
+
+ if len(sys.argv) < 2:
+ return -1
+
+ if sys.argv[1] == 'list':
+ print('{ "encrypt": { "type": "str", "plainpass": "str" } }\n')
+ return 0
+
+ if sys.argv[1] == 'call':
+ if len(sys.argv) < 3:
+ return -1
+
+ if sys.argv[2] != 'encrypt':
+ return -1
+
+ encpass = ""
+ try:
+ jsonin = json.loads(sys.stdin.readline())
+ enctype = jsonin['type'].strip()
+ plainpass = jsonin['plainpass']
+
+ if enctype == 'ssha':
+ encpass = hash.ldap_salted_sha1.hash(plainpass)
+ elif enctype == 'sha1':
+ encpass = hash.ldap_sha1.hash(plainpass)
+ elif enctype == 'plain':
+ encpass = plainpass
+ elif enctype == 'md5':
+ encpass = hash.apr_md5_crypt.hash(plainpass)
+ elif enctype == 'bcrypt':
+ encpass = hash.bcrypt.hash(plainpass)
+ elif enctype == 'crypt':
+ encpass = hash.des_crypt.hash(plainpass)
+
+ except:
+ encpass = ""
+
+ print(json.dumps({ "encrypted_password": encpass}))
+
+ return 0
+
+main()