mirror of
https://github.com/JamesonHuang/OpenWrt_Luci_Lua.git
synced 2024-11-23 22:00:11 +00:00
create luci frame
This commit is contained in:
parent
42317d1f67
commit
daa1b5684b
14
Me_Lua/r13/MZLog.lua
Normal file
14
Me_Lua/r13/MZLog.lua
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
module ("MZLog", package.seeall)
|
||||||
|
|
||||||
|
function log(...)
|
||||||
|
local posix = require("posix")
|
||||||
|
local util = require("luci.util")
|
||||||
|
local priority = arg[1]
|
||||||
|
if priority and tonumber(priority) then
|
||||||
|
posix.openlog("luci", "nep", LOG_USER)
|
||||||
|
for i = 2, arg.n do
|
||||||
|
posix.syslog(priority, util.serialize_data(arg[i]))
|
||||||
|
end
|
||||||
|
posix.closelog()
|
||||||
|
end
|
||||||
|
end
|
113
Me_Lua/r13/Posix.lua
Normal file
113
Me_Lua/r13/Posix.lua
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
local base = _G
|
||||||
|
local string = require("string")
|
||||||
|
local M = require "posix"
|
||||||
|
|
||||||
|
function M.timeradd (x,y)
|
||||||
|
local sec, usec = 0, 0
|
||||||
|
if x.sec then sec = sec + x.sec end
|
||||||
|
if y.sec then sec = sec + y.sec end
|
||||||
|
if x.usec then usec = usec + x.usec end
|
||||||
|
if y.usec then usec = usec + y.usec end
|
||||||
|
if usec > 1000000 then
|
||||||
|
sec = sec + 1
|
||||||
|
usec = usec - 1000000
|
||||||
|
end
|
||||||
|
|
||||||
|
return { sec = sec, usec = usec }
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function M.timercmp (x, y)
|
||||||
|
local x = { sec = x.sec or 0, usec = x.usec or 0 }
|
||||||
|
local y = { sec = y.sec or 0, usec = y.usec or 0 }
|
||||||
|
if x.sec ~= y.sec then
|
||||||
|
return x.sec - y.sec
|
||||||
|
else
|
||||||
|
return x.usec - y.usec
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function M.timersub (x,y)
|
||||||
|
local sec, usec = 0, 0
|
||||||
|
if x.sec then sec = x.sec end
|
||||||
|
if y.sec then sec = sec - y.sec end
|
||||||
|
if x.usec then usec = x.usec end
|
||||||
|
if y.usec then usec = usec - y.usec end
|
||||||
|
if usec < 0 then
|
||||||
|
sec = sec - 1
|
||||||
|
usec = usec + 1000000
|
||||||
|
end
|
||||||
|
|
||||||
|
return { sec = sec, usec = usec }
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.timesleep (x)
|
||||||
|
local sec, nsec = 0, 0
|
||||||
|
y = M.gettimeofday();
|
||||||
|
if( M.timercmp(x, y) > 0 ) then
|
||||||
|
sec = x.sec - y.sec
|
||||||
|
nsec = (x.usec - y.usec) * 1000
|
||||||
|
if nsec < 0 then
|
||||||
|
sec = sec - 1
|
||||||
|
nsec = nsec + 1000000000
|
||||||
|
end
|
||||||
|
M.nanosleep(sec, nsec)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.strsplit(str, delim, maxNb)
|
||||||
|
-- Eliminate bad cases...
|
||||||
|
if string.find(str, delim) == nil then
|
||||||
|
return { str }
|
||||||
|
end
|
||||||
|
if maxNb == nil or maxNb < 1 then
|
||||||
|
maxNb = 0 -- No limit
|
||||||
|
end
|
||||||
|
local result = {}
|
||||||
|
local pat = "(.-)" .. delim .. "()"
|
||||||
|
local nb = 0
|
||||||
|
local lastPos
|
||||||
|
for part, pos in string.gfind(str, pat) do
|
||||||
|
nb = nb + 1
|
||||||
|
result[nb] = part
|
||||||
|
lastPos = pos
|
||||||
|
if nb == maxNb then break end
|
||||||
|
end
|
||||||
|
-- Handle the last field
|
||||||
|
if nb ~= maxNb then
|
||||||
|
result[nb + 1] = string.sub(str, lastPos)
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.var_dump(data, max_level, prefix)
|
||||||
|
if type(prefix) ~= "string" then
|
||||||
|
prefix = ""
|
||||||
|
end
|
||||||
|
if type(data) ~= "table" then
|
||||||
|
print(prefix .. tostring(data))
|
||||||
|
else
|
||||||
|
print(data)
|
||||||
|
if max_level ~= 0 then
|
||||||
|
local prefix_next = prefix .. " "
|
||||||
|
print(prefix .. "{")
|
||||||
|
for k,v in pairs(data) do
|
||||||
|
io.stdout:write(prefix_next .. k .. " = ")
|
||||||
|
if type(v) ~= "table" or (type(max_level) == "number" and max_level <= 1) then
|
||||||
|
print(v)
|
||||||
|
else
|
||||||
|
if max_level == nil then
|
||||||
|
M.var_dump(v, nil, prefix_next)
|
||||||
|
else
|
||||||
|
M.var_dump(v, max_level - 1, prefix_next)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
print(prefix .. "}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return M
|
BIN
Me_Lua/r13/cjson.so
Normal file
BIN
Me_Lua/r13/cjson.so
Normal file
Binary file not shown.
BIN
Me_Lua/r13/lfs.so
Normal file
BIN
Me_Lua/r13/lfs.so
Normal file
Binary file not shown.
BIN
Me_Lua/r13/lsqlite3.so
Normal file
BIN
Me_Lua/r13/lsqlite3.so
Normal file
Binary file not shown.
305
Me_Lua/r13/ltn12.lua
Normal file
305
Me_Lua/r13/ltn12.lua
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- LTN12 - Filters, sources, sinks and pumps.
|
||||||
|
-- LuaSocket toolkit.
|
||||||
|
-- Author: Diego Nehab
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Declare module
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
local string = require("string")
|
||||||
|
local table = require("table")
|
||||||
|
local base = _G
|
||||||
|
local _M = {}
|
||||||
|
if module then -- heuristic for exporting a global package table
|
||||||
|
ltn12 = _M
|
||||||
|
end
|
||||||
|
local filter,source,sink,pump = {},{},{},{}
|
||||||
|
|
||||||
|
_M.filter = filter
|
||||||
|
_M.source = source
|
||||||
|
_M.sink = sink
|
||||||
|
_M.pump = pump
|
||||||
|
|
||||||
|
-- 2048 seems to be better in windows...
|
||||||
|
_M.BLOCKSIZE = 2048
|
||||||
|
_M._VERSION = "LTN12 1.0.3"
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Filter stuff
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- returns a high level filter that cycles a low-level filter
|
||||||
|
function filter.cycle(low, ctx, extra)
|
||||||
|
base.assert(low)
|
||||||
|
return function(chunk)
|
||||||
|
local ret
|
||||||
|
ret, ctx = low(ctx, chunk, extra)
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- chains a bunch of filters together
|
||||||
|
-- (thanks to Wim Couwenberg)
|
||||||
|
function filter.chain(...)
|
||||||
|
local arg = {...}
|
||||||
|
local n = select('#',...)
|
||||||
|
local top, index = 1, 1
|
||||||
|
local retry = ""
|
||||||
|
return function(chunk)
|
||||||
|
retry = chunk and retry
|
||||||
|
while true do
|
||||||
|
if index == top then
|
||||||
|
chunk = arg[index](chunk)
|
||||||
|
if chunk == "" or top == n then return chunk
|
||||||
|
elseif chunk then index = index + 1
|
||||||
|
else
|
||||||
|
top = top+1
|
||||||
|
index = top
|
||||||
|
end
|
||||||
|
else
|
||||||
|
chunk = arg[index](chunk or "")
|
||||||
|
if chunk == "" then
|
||||||
|
index = index - 1
|
||||||
|
chunk = retry
|
||||||
|
elseif chunk then
|
||||||
|
if index == n then return chunk
|
||||||
|
else index = index + 1 end
|
||||||
|
else base.error("filter returned inappropriate nil") end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Source stuff
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- create an empty source
|
||||||
|
local function empty()
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function source.empty()
|
||||||
|
return empty
|
||||||
|
end
|
||||||
|
|
||||||
|
-- returns a source that just outputs an error
|
||||||
|
function source.error(err)
|
||||||
|
return function()
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- creates a file source
|
||||||
|
function source.file(handle, io_err)
|
||||||
|
if handle then
|
||||||
|
return function()
|
||||||
|
local chunk = handle:read(_M.BLOCKSIZE)
|
||||||
|
if not chunk then handle:close() end
|
||||||
|
return chunk
|
||||||
|
end
|
||||||
|
else return source.error(io_err or "unable to open file") end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- turns a fancy source into a simple source
|
||||||
|
function source.simplify(src)
|
||||||
|
base.assert(src)
|
||||||
|
return function()
|
||||||
|
local chunk, err_or_new = src()
|
||||||
|
src = err_or_new or src
|
||||||
|
if not chunk then return nil, err_or_new
|
||||||
|
else return chunk end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- creates string source
|
||||||
|
function source.string(s)
|
||||||
|
if s then
|
||||||
|
local i = 1
|
||||||
|
return function()
|
||||||
|
local chunk = string.sub(s, i, i+_M.BLOCKSIZE-1)
|
||||||
|
i = i + _M.BLOCKSIZE
|
||||||
|
if chunk ~= "" then return chunk
|
||||||
|
else return nil end
|
||||||
|
end
|
||||||
|
else return source.empty() end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- creates rewindable source
|
||||||
|
function source.rewind(src)
|
||||||
|
base.assert(src)
|
||||||
|
local t = {}
|
||||||
|
return function(chunk)
|
||||||
|
if not chunk then
|
||||||
|
chunk = table.remove(t)
|
||||||
|
if not chunk then return src()
|
||||||
|
else return chunk end
|
||||||
|
else
|
||||||
|
table.insert(t, chunk)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- chains a source with one or several filter(s)
|
||||||
|
function source.chain(src, f, ...)
|
||||||
|
if ... then f=filter.chain(f, ...) end
|
||||||
|
base.assert(src and f)
|
||||||
|
local last_in, last_out = "", ""
|
||||||
|
local state = "feeding"
|
||||||
|
local err
|
||||||
|
return function()
|
||||||
|
if not last_out then
|
||||||
|
base.error('source is empty!', 2)
|
||||||
|
end
|
||||||
|
while true do
|
||||||
|
if state == "feeding" then
|
||||||
|
last_in, err = src()
|
||||||
|
if err then return nil, err end
|
||||||
|
last_out = f(last_in)
|
||||||
|
if not last_out then
|
||||||
|
if last_in then
|
||||||
|
base.error('filter returned inappropriate nil')
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
elseif last_out ~= "" then
|
||||||
|
state = "eating"
|
||||||
|
if last_in then last_in = "" end
|
||||||
|
return last_out
|
||||||
|
end
|
||||||
|
else
|
||||||
|
last_out = f(last_in)
|
||||||
|
if last_out == "" then
|
||||||
|
if last_in == "" then
|
||||||
|
state = "feeding"
|
||||||
|
else
|
||||||
|
base.error('filter returned ""')
|
||||||
|
end
|
||||||
|
elseif not last_out then
|
||||||
|
if last_in then
|
||||||
|
base.error('filter returned inappropriate nil')
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return last_out
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- creates a source that produces contents of several sources, one after the
|
||||||
|
-- other, as if they were concatenated
|
||||||
|
-- (thanks to Wim Couwenberg)
|
||||||
|
function source.cat(...)
|
||||||
|
local arg = {...}
|
||||||
|
local src = table.remove(arg, 1)
|
||||||
|
return function()
|
||||||
|
while src do
|
||||||
|
local chunk, err = src()
|
||||||
|
if chunk then return chunk end
|
||||||
|
if err then return nil, err end
|
||||||
|
src = table.remove(arg, 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Sink stuff
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- creates a sink that stores into a table
|
||||||
|
function sink.table(t)
|
||||||
|
t = t or {}
|
||||||
|
local f = function(chunk, err)
|
||||||
|
if chunk then table.insert(t, chunk) end
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
return f, t
|
||||||
|
end
|
||||||
|
|
||||||
|
-- turns a fancy sink into a simple sink
|
||||||
|
function sink.simplify(snk)
|
||||||
|
base.assert(snk)
|
||||||
|
return function(chunk, err)
|
||||||
|
local ret, err_or_new = snk(chunk, err)
|
||||||
|
if not ret then return nil, err_or_new end
|
||||||
|
snk = err_or_new or snk
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- creates a file sink
|
||||||
|
function sink.file(handle, io_err)
|
||||||
|
if handle then
|
||||||
|
return function(chunk, err)
|
||||||
|
if not chunk then
|
||||||
|
handle:close()
|
||||||
|
return 1
|
||||||
|
else return handle:write(chunk) end
|
||||||
|
end
|
||||||
|
else return sink.error(io_err or "unable to open file") end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- creates a sink that discards data
|
||||||
|
local function null()
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
function sink.null()
|
||||||
|
return null
|
||||||
|
end
|
||||||
|
|
||||||
|
-- creates a sink that just returns an error
|
||||||
|
function sink.error(err)
|
||||||
|
return function()
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- chains a sink with one or several filter(s)
|
||||||
|
function sink.chain(f, snk, ...)
|
||||||
|
if ... then
|
||||||
|
local args = { f, snk, ... }
|
||||||
|
snk = table.remove(args, #args)
|
||||||
|
f = filter.chain(unpack(args))
|
||||||
|
end
|
||||||
|
base.assert(f and snk)
|
||||||
|
return function(chunk, err)
|
||||||
|
if chunk ~= "" then
|
||||||
|
local filtered = f(chunk)
|
||||||
|
local done = chunk and ""
|
||||||
|
while true do
|
||||||
|
local ret, snkerr = snk(filtered, err)
|
||||||
|
if not ret then return nil, snkerr end
|
||||||
|
if filtered == done then return 1 end
|
||||||
|
filtered = f(done)
|
||||||
|
end
|
||||||
|
else return 1 end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Pump stuff
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- pumps one chunk from the source to the sink
|
||||||
|
function pump.step(src, snk)
|
||||||
|
local chunk, src_err = src()
|
||||||
|
local ret, snk_err = snk(chunk, src_err)
|
||||||
|
if chunk and ret then return 1
|
||||||
|
else return nil, src_err or snk_err end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- pumps all data from a source to a sink, using a step function
|
||||||
|
function pump.all(src, snk, step)
|
||||||
|
base.assert(src and snk)
|
||||||
|
step = step or pump.step
|
||||||
|
while true do
|
||||||
|
local ret, err = step(src, snk)
|
||||||
|
if not ret then
|
||||||
|
if err then return nil, err
|
||||||
|
else return 1 end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return _M
|
611
Me_Lua/r13/luci/controller/admin/network.lua
Normal file
611
Me_Lua/r13/luci/controller/admin/network.lua
Normal file
@ -0,0 +1,611 @@
|
|||||||
|
--[[
|
||||||
|
LuCI - Lua Configuration Interface
|
||||||
|
|
||||||
|
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||||
|
Copyright 2011 Jo-Philipp Wich <xm@subsignal.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
|
||||||
|
|
||||||
|
]]--
|
||||||
|
|
||||||
|
module("luci.controller.admin.network", package.seeall)
|
||||||
|
|
||||||
|
function index()
|
||||||
|
local uci = require("luci.model.uci").cursor()
|
||||||
|
local page
|
||||||
|
|
||||||
|
page = node("admin", "network")
|
||||||
|
page.target = firstchild()
|
||||||
|
page.title = _("Network")
|
||||||
|
page.order = 50
|
||||||
|
page.index = true
|
||||||
|
|
||||||
|
-- if page.inreq then
|
||||||
|
local has_switch = false
|
||||||
|
|
||||||
|
uci:foreach("network", "switch",
|
||||||
|
function(s)
|
||||||
|
has_switch = true
|
||||||
|
return false
|
||||||
|
end)
|
||||||
|
|
||||||
|
if has_switch then
|
||||||
|
page = node("admin", "network", "vlan")
|
||||||
|
page.target = cbi("admin_network/vlan")
|
||||||
|
page.title = _("Switch")
|
||||||
|
page.order = 20
|
||||||
|
|
||||||
|
page = entry({"admin", "network", "switch_status"}, call("switch_status"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local has_wifi = false
|
||||||
|
|
||||||
|
uci:foreach("wireless", "wifi-device",
|
||||||
|
function(s)
|
||||||
|
has_wifi = true
|
||||||
|
return false
|
||||||
|
end)
|
||||||
|
|
||||||
|
if has_wifi then
|
||||||
|
page = entry({"admin", "network", "wireless_join"}, call("wifi_join"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"admin", "network", "wireless_add"}, call("wifi_add"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"admin", "network", "wireless_delete"}, call("wifi_delete"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"admin", "network", "wireless_status"}, call("wifi_status"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"admin", "network", "getWifiSettings"}, call("getWifiSettings"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"admin", "network", "getConnectInfo"}, call("lease_status"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"admin", "network", "getUpLoadSpeed"}, call("getUpLoadSpeed"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"admin", "network", "getWanInfo"}, call("getWanInfo"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"admin", "network", "getLanDhcp"}, call("getLanDhcp"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"admin", "network", "wireless_reconnect"}, call("wifi_reconnect"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"admin", "network", "wireless_shutdown"}, call("wifi_shutdown"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"admin", "network", "wireless"}, arcombine(template("admin_network/wifi_overview"), cbi("admin_network/wifi")), _("Wifi"), 15)
|
||||||
|
page.leaf = true
|
||||||
|
page.subindex = true
|
||||||
|
|
||||||
|
if page.inreq then
|
||||||
|
local wdev
|
||||||
|
local net = require "luci.model.network".init(uci)
|
||||||
|
for _, wdev in ipairs(net:get_wifidevs()) do
|
||||||
|
local wnet
|
||||||
|
for _, wnet in ipairs(wdev:get_wifinets()) do
|
||||||
|
entry(
|
||||||
|
{"admin", "network", "wireless", wnet:id()},
|
||||||
|
alias("admin", "network", "wireless"),
|
||||||
|
wdev:name() .. ": " .. wnet:shortname()
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
page = entry({"admin", "network", "iface_add"}, cbi("admin_network/iface_add"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"admin", "network", "iface_delete"}, call("iface_delete"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"admin", "network", "iface_status"}, call("iface_status"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"admin", "network", "iface_reconnect"}, call("iface_reconnect"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"admin", "network", "iface_shutdown"}, call("iface_shutdown"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"admin", "network", "network"}, arcombine(cbi("admin_network/network"), cbi("admin_network/ifaces")), _("Interfaces"), 10)
|
||||||
|
page.leaf = true
|
||||||
|
page.subindex = true
|
||||||
|
|
||||||
|
if page.inreq then
|
||||||
|
uci:foreach("network", "interface",
|
||||||
|
function (section)
|
||||||
|
local ifc = section[".name"]
|
||||||
|
if ifc ~= "loopback" then
|
||||||
|
entry({"admin", "network", "network", ifc},
|
||||||
|
true, ifc:upper())
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
if nixio.fs.access("/etc/config/dhcp") then
|
||||||
|
page = node("admin", "network", "dhcp")
|
||||||
|
page.target = cbi("admin_network/dhcp")
|
||||||
|
page.title = _("DHCP and DNS")
|
||||||
|
page.order = 30
|
||||||
|
|
||||||
|
page = entry({"admin", "network", "dhcplease_status"}, call("lease_status"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = node("admin", "network", "hosts")
|
||||||
|
page.target = cbi("admin_network/hosts")
|
||||||
|
page.title = _("Hostnames")
|
||||||
|
page.order = 40
|
||||||
|
end
|
||||||
|
|
||||||
|
page = node("admin", "network", "routes")
|
||||||
|
page.target = cbi("admin_network/routes")
|
||||||
|
page.title = _("Static Routes")
|
||||||
|
page.order = 50
|
||||||
|
|
||||||
|
page = node("admin", "network", "diagnostics")
|
||||||
|
page.target = template("admin_network/diagnostics")
|
||||||
|
page.title = _("Diagnostics")
|
||||||
|
page.order = 60
|
||||||
|
|
||||||
|
page = entry({"admin", "network", "diag_ping"}, call("diag_ping"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"admin", "network", "diag_nslookup"}, call("diag_nslookup"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"admin", "network", "diag_traceroute"}, call("diag_traceroute"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"admin", "network", "diag_ping6"}, call("diag_ping6"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"admin", "network", "diag_traceroute6"}, call("diag_traceroute6"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
end
|
||||||
|
|
||||||
|
function wifi_join()
|
||||||
|
local function param(x)
|
||||||
|
return luci.http.formvalue(x)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function ptable(x)
|
||||||
|
x = param(x)
|
||||||
|
return x and (type(x) ~= "table" and { x } or x) or {}
|
||||||
|
end
|
||||||
|
|
||||||
|
local dev = param("device")
|
||||||
|
local ssid = param("join")
|
||||||
|
|
||||||
|
if dev and ssid then
|
||||||
|
local cancel = (param("cancel") or param("cbi.cancel")) and true or false
|
||||||
|
|
||||||
|
if cancel then
|
||||||
|
luci.http.redirect(luci.dispatcher.build_url("admin/network/wireless_join?device=" .. dev))
|
||||||
|
else
|
||||||
|
local cbi = require "luci.cbi"
|
||||||
|
local tpl = require "luci.template"
|
||||||
|
local map = luci.cbi.load("admin_network/wifi_add")[1]
|
||||||
|
|
||||||
|
if map:parse() ~= cbi.FORM_DONE then
|
||||||
|
tpl.render("header")
|
||||||
|
map:render()
|
||||||
|
tpl.render("footer")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
luci.template.render("admin_network/wifi_join")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function wifi_add()
|
||||||
|
local dev = luci.http.formvalue("device")
|
||||||
|
local ntm = require "luci.model.network".init()
|
||||||
|
|
||||||
|
dev = dev and ntm:get_wifidev(dev)
|
||||||
|
|
||||||
|
if dev then
|
||||||
|
local net = dev:add_wifinet({
|
||||||
|
mode = "ap",
|
||||||
|
ssid = "OpenWrt",
|
||||||
|
encryption = "none"
|
||||||
|
})
|
||||||
|
|
||||||
|
ntm:save("wireless")
|
||||||
|
luci.http.redirect(net:adminlink())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function wifi_delete(network)
|
||||||
|
local ntm = require "luci.model.network".init()
|
||||||
|
local wnet = ntm:get_wifinet(network)
|
||||||
|
if wnet then
|
||||||
|
local dev = wnet:get_device()
|
||||||
|
local nets = wnet:get_networks()
|
||||||
|
if dev then
|
||||||
|
ntm:del_wifinet(network)
|
||||||
|
ntm:commit("wireless")
|
||||||
|
local _, net
|
||||||
|
for _, net in ipairs(nets) do
|
||||||
|
if net:is_empty() then
|
||||||
|
ntm:del_network(net:name())
|
||||||
|
ntm:commit("network")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
luci.sys.call("env -i /bin/ubus call network reload >/dev/null 2>/dev/null")
|
||||||
|
luci.sys.call("env -i /sbin/wifi reload >/dev/null 2>/dev/null")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
luci.http.redirect(luci.dispatcher.build_url("admin/network/wireless"))
|
||||||
|
end
|
||||||
|
|
||||||
|
function iface_status(ifaces)
|
||||||
|
local netm = require "luci.model.network".init()
|
||||||
|
local rv = { }
|
||||||
|
|
||||||
|
local iface
|
||||||
|
for iface in ifaces:gmatch("[%w%.%-_]+") do
|
||||||
|
local net = netm:get_network(iface)
|
||||||
|
local device = net and net:get_interface()
|
||||||
|
if device then
|
||||||
|
local data = {
|
||||||
|
id = iface,
|
||||||
|
proto = net:proto(),
|
||||||
|
uptime = net:uptime(),
|
||||||
|
gwaddr = net:gwaddr(),
|
||||||
|
dnsaddrs = net:dnsaddrs(),
|
||||||
|
name = device:shortname(),
|
||||||
|
type = device:type(),
|
||||||
|
ifname = device:name(),
|
||||||
|
macaddr = device:mac(),
|
||||||
|
is_up = device:is_up(),
|
||||||
|
rx_bytes = device:rx_bytes(),
|
||||||
|
tx_bytes = device:tx_bytes(),
|
||||||
|
rx_packets = device:rx_packets(),
|
||||||
|
tx_packets = device:tx_packets(),
|
||||||
|
|
||||||
|
ipaddrs = { },
|
||||||
|
ip6addrs = { },
|
||||||
|
subdevices = { }
|
||||||
|
}
|
||||||
|
|
||||||
|
local _, a
|
||||||
|
for _, a in ipairs(device:ipaddrs()) do
|
||||||
|
data.ipaddrs[#data.ipaddrs+1] = {
|
||||||
|
addr = a:host():string(),
|
||||||
|
netmask = a:mask():string(),
|
||||||
|
prefix = a:prefix()
|
||||||
|
}
|
||||||
|
end
|
||||||
|
for _, a in ipairs(device:ip6addrs()) do
|
||||||
|
if not a:is6linklocal() then
|
||||||
|
data.ip6addrs[#data.ip6addrs+1] = {
|
||||||
|
addr = a:host():string(),
|
||||||
|
netmask = a:mask():string(),
|
||||||
|
prefix = a:prefix()
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, device in ipairs(net:get_interfaces() or {}) do
|
||||||
|
data.subdevices[#data.subdevices+1] = {
|
||||||
|
name = device:shortname(),
|
||||||
|
type = device:type(),
|
||||||
|
ifname = device:name(),
|
||||||
|
macaddr = device:mac(),
|
||||||
|
macaddr = device:mac(),
|
||||||
|
is_up = device:is_up(),
|
||||||
|
rx_bytes = device:rx_bytes(),
|
||||||
|
tx_bytes = device:tx_bytes(),
|
||||||
|
rx_packets = device:rx_packets(),
|
||||||
|
tx_packets = device:tx_packets(),
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
rv[#rv+1] = data
|
||||||
|
else
|
||||||
|
rv[#rv+1] = {
|
||||||
|
id = iface,
|
||||||
|
name = iface,
|
||||||
|
type = "ethernet"
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if #rv > 0 then
|
||||||
|
luci.http.prepare_content("application/json")
|
||||||
|
luci.http.write_json(rv)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
luci.http.status(404, "No such device")
|
||||||
|
end
|
||||||
|
|
||||||
|
function iface_reconnect(iface)
|
||||||
|
local netmd = require "luci.model.network".init()
|
||||||
|
local net = netmd:get_network(iface)
|
||||||
|
if net then
|
||||||
|
luci.sys.call("env -i /sbin/ifup %q >/dev/null 2>/dev/null" % iface)
|
||||||
|
luci.http.status(200, "Reconnected")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
luci.http.status(404, "No such interface")
|
||||||
|
end
|
||||||
|
|
||||||
|
function iface_shutdown(iface)
|
||||||
|
local netmd = require "luci.model.network".init()
|
||||||
|
local net = netmd:get_network(iface)
|
||||||
|
if net then
|
||||||
|
luci.sys.call("env -i /sbin/ifdown %q >/dev/null 2>/dev/null" % iface)
|
||||||
|
luci.http.status(200, "Shutdown")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
luci.http.status(404, "No such interface")
|
||||||
|
end
|
||||||
|
|
||||||
|
function iface_delete(iface)
|
||||||
|
local netmd = require "luci.model.network".init()
|
||||||
|
local net = netmd:del_network(iface)
|
||||||
|
if net then
|
||||||
|
luci.sys.call("env -i /sbin/ifdown %q >/dev/null 2>/dev/null" % iface)
|
||||||
|
luci.http.redirect(luci.dispatcher.build_url("admin/network/network"))
|
||||||
|
netmd:commit("network")
|
||||||
|
netmd:commit("wireless")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
luci.http.status(404, "No such interface")
|
||||||
|
end
|
||||||
|
|
||||||
|
function wifi_status(devs)
|
||||||
|
local s = require "luci.tools.status"
|
||||||
|
local rv = { }
|
||||||
|
|
||||||
|
local dev
|
||||||
|
for dev in devs:gmatch("[%w%.%-]+") do
|
||||||
|
rv[#rv+1] = s.wifi_network(dev)
|
||||||
|
end
|
||||||
|
|
||||||
|
if #rv > 0 then
|
||||||
|
luci.http.prepare_content("application/json")
|
||||||
|
luci.http.write_json(rv)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
luci.http.status(404, "No such device")
|
||||||
|
end
|
||||||
|
|
||||||
|
--wifi重连 &开关基础函数
|
||||||
|
local function wifi_reconnect_shutdown(shutdown, wnet)
|
||||||
|
local netmd = require "luci.model.network".init()
|
||||||
|
local net = netmd:get_wifinet(wnet)
|
||||||
|
local dev = net:get_device()
|
||||||
|
if dev and net then
|
||||||
|
dev:set("disabled", nil)
|
||||||
|
net:set("disabled", shutdown and 1 or nil)
|
||||||
|
netmd:commit("wireless")
|
||||||
|
|
||||||
|
luci.sys.call("env -i /bin/ubus call network reload >/dev/null 2>/dev/null")
|
||||||
|
|
||||||
|
luci.sys.call("env -i /sbin/wifi reload >/dev/null 2>/dev/null")
|
||||||
|
|
||||||
|
luci.http.status(200, shutdown and "Shutdown" or "Reconnected")
|
||||||
|
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
luci.http.status(404, "No such radio")
|
||||||
|
end
|
||||||
|
--wifi重连
|
||||||
|
function wifi_reconnect(wnet)
|
||||||
|
wifi_reconnect_shutdown(false, wnet)
|
||||||
|
end
|
||||||
|
--wifi开关
|
||||||
|
function wifi_shutdown(wnet)
|
||||||
|
wifi_reconnect_shutdown(true, wnet)
|
||||||
|
end
|
||||||
|
|
||||||
|
function wifiNetworks()
|
||||||
|
local result = {}
|
||||||
|
local network = require "luci.model.network".init()
|
||||||
|
local dev
|
||||||
|
for _, dev in ipairs(network:get_wifidevs()) do
|
||||||
|
local rd = {
|
||||||
|
up = dev:is_up(),
|
||||||
|
device = dev:name(),
|
||||||
|
name = dev:get_i18n(),
|
||||||
|
networks = {}
|
||||||
|
}
|
||||||
|
local wifiNet
|
||||||
|
for _, wifiNet in ipairs(dev:get_wifinets()) do
|
||||||
|
rd.networks[#rd.networks+1] = {
|
||||||
|
name = wifiNet:shortname(),
|
||||||
|
up = wifiNet:is_up(),
|
||||||
|
mode = wifiNet:active_mode(),
|
||||||
|
ssid = wifiNet:active_ssid(),
|
||||||
|
bssid = wifiNet:active_bssid(),
|
||||||
|
encryption = wifiNet:active_encryption(),
|
||||||
|
frequency = wifiNet:frequency(),
|
||||||
|
channel = wifiNet:channel(),
|
||||||
|
signal = wifiNet:signal(),
|
||||||
|
quality = wifiNet:signal_percent(),
|
||||||
|
noise = wifiNet:noise(),
|
||||||
|
bitrate = wifiNet:bitrate(),
|
||||||
|
ifname = wifiNet:ifname(),
|
||||||
|
assoclist = wifiNet:assoclist(),
|
||||||
|
country = wifiNet:country(),
|
||||||
|
txpower = wifiNet:txpower(),
|
||||||
|
txpoweroff = wifiNet:txpower_offset(),
|
||||||
|
key = wifiNet:get("key"),
|
||||||
|
key1 = wifiNet:get("key1"),
|
||||||
|
encryption_src = wifiNet:get("encryption"),
|
||||||
|
hidden = wifiNet:get("hidden"),
|
||||||
|
}
|
||||||
|
end
|
||||||
|
result[#result+1] = rd
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
function wifiNetwork(wifiDeviceName)
|
||||||
|
local network = require "luci.model.network".init()
|
||||||
|
local wifiNet = network:get_wifinet(wifiDeviceName)
|
||||||
|
if wifiNet then
|
||||||
|
local dev = wifiNet:get_device()
|
||||||
|
if dev then
|
||||||
|
return {
|
||||||
|
id = wifiDeviceName,
|
||||||
|
name = wifiNet:shortname(),
|
||||||
|
up = wifiNet:is_up(),
|
||||||
|
mode = wifiNet:active_mode(),
|
||||||
|
ssid = wifiNet:active_ssid(),
|
||||||
|
bssid = wifiNet:active_bssid(),
|
||||||
|
encryption = wifiNet:active_encryption(),
|
||||||
|
encryption_src = wifiNet:get("encryption"),
|
||||||
|
frequency = wifiNet:frequency(),
|
||||||
|
channel = wifiNet:channel(),
|
||||||
|
signal = wifiNet:signal(),
|
||||||
|
quality = wifiNet:signal_percent(),
|
||||||
|
noise = wifiNet:noise(),
|
||||||
|
bitrate = wifiNet:bitrate(),
|
||||||
|
ifname = wifiNet:ifname(),
|
||||||
|
assoclist = wifiNet:assoclist(),
|
||||||
|
country = wifiNet:country(),
|
||||||
|
txpower = wifiNet:txpower(),
|
||||||
|
txpoweroff = wifiNet:txpower_offset(),
|
||||||
|
key = wifiNet:get("key"),
|
||||||
|
key1 = wifiNet:get("key1"),
|
||||||
|
hidden = wifiNet:get("hidden"),
|
||||||
|
device = {
|
||||||
|
up = dev:is_up(),
|
||||||
|
device = dev:name(),
|
||||||
|
name = dev:get_i18n()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return {}
|
||||||
|
end
|
||||||
|
|
||||||
|
function getWifiSettings()
|
||||||
|
local infoList = {}
|
||||||
|
local wifis = wifiNetworks()
|
||||||
|
for i,wifiNet in ipairs(wifis) do
|
||||||
|
local item = {}
|
||||||
|
local index = 1
|
||||||
|
if wifiNet["up"] then
|
||||||
|
item["status"] = "1"
|
||||||
|
else
|
||||||
|
item["status"] = "0"
|
||||||
|
end
|
||||||
|
local encryption = wifiNet.networks[index].encryption_src
|
||||||
|
local key = wifiNet.networks[index].key
|
||||||
|
if encryption == "wep-open" then
|
||||||
|
key = wifiNet.networks[index].key1
|
||||||
|
if key:len()>4 and key:sub(0,2)=="s:" then
|
||||||
|
key = key:sub(3)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local channel = wifiNet.networks[index].cchannel
|
||||||
|
-- local channelparseinfo = channelHelper(channel)
|
||||||
|
item["ifname"] = wifiNet.networks[index].ifname
|
||||||
|
item["device"] = wifiNet.device..".network"..index
|
||||||
|
item["ssid"] = wifiNet.networks[index].ssid
|
||||||
|
-- item["channel"] = channelparseinfo.channel
|
||||||
|
-- item["channelInfo"] = getBandList(channel)
|
||||||
|
-- item["channelInfo"]["channel"] = wifiNet.networks[index].channel
|
||||||
|
item["mode"] = wifiNet.networks[index].mode
|
||||||
|
item["hidden"] = wifiNet.networks[index].hidden or 0
|
||||||
|
item["signal"] = wifiNet.networks[index].signal
|
||||||
|
item["password"] = key
|
||||||
|
item["encryption"] = encryption
|
||||||
|
infoList[#wifis+1-i] = item
|
||||||
|
end
|
||||||
|
--local guestwifi = getGuestWifi(1)
|
||||||
|
-- if guestwifi then
|
||||||
|
-- table.insert(infoList, guestwifi)
|
||||||
|
-- end
|
||||||
|
--return infoList
|
||||||
|
local result = {}
|
||||||
|
-- local code = 0
|
||||||
|
-- result["info"] = infoList
|
||||||
|
-- result["code"] = code
|
||||||
|
luci.http.write_json(infoList)
|
||||||
|
end
|
||||||
|
|
||||||
|
function lease_status()
|
||||||
|
local s = require "luci.tools.status"
|
||||||
|
|
||||||
|
luci.http.prepare_content("application/json")
|
||||||
|
luci.http.write('[')
|
||||||
|
luci.http.write_json(s.dhcp_leases())
|
||||||
|
luci.http.write(',')
|
||||||
|
luci.http.write_json(s.dhcp6_leases())
|
||||||
|
luci.http.write(']')
|
||||||
|
end
|
||||||
|
|
||||||
|
function switch_status(switches)
|
||||||
|
local s = require "luci.tools.status"
|
||||||
|
|
||||||
|
luci.http.prepare_content("application/json")
|
||||||
|
luci.http.write_json(s.switch_status(switches))
|
||||||
|
end
|
||||||
|
|
||||||
|
function diag_command(cmd, addr)
|
||||||
|
if addr and addr:match("^[a-zA-Z0-9%-%.:_]+$") then
|
||||||
|
luci.http.prepare_content("text/plain")
|
||||||
|
|
||||||
|
local util = io.popen(cmd % addr)
|
||||||
|
if util then
|
||||||
|
while true do
|
||||||
|
local ln = util:read("*l")
|
||||||
|
if not ln then break end
|
||||||
|
luci.http.write(ln)
|
||||||
|
luci.http.write("\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
util:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
luci.http.status(500, "Bad address")
|
||||||
|
end
|
||||||
|
|
||||||
|
function diag_ping(addr)
|
||||||
|
diag_command("ping -c 5 -W 1 %q 2>&1", addr)
|
||||||
|
end
|
||||||
|
|
||||||
|
function diag_traceroute(addr)
|
||||||
|
diag_command("traceroute -q 1 -w 1 -n %q 2>&1", addr)
|
||||||
|
end
|
||||||
|
|
||||||
|
function diag_nslookup(addr)
|
||||||
|
diag_command("nslookup %q 2>&1", addr)
|
||||||
|
end
|
||||||
|
|
||||||
|
function diag_ping6(addr)
|
||||||
|
diag_command("ping6 -c 5 %q 2>&1", addr)
|
||||||
|
end
|
||||||
|
|
||||||
|
function diag_traceroute6(addr)
|
||||||
|
diag_command("traceroute6 -q 1 -w 2 -n %q 2>&1", addr)
|
||||||
|
end
|
||||||
|
|
238
Me_Lua/r13/luci/controller/api/index.lua
Normal file
238
Me_Lua/r13/luci/controller/api/index.lua
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
module("luci.controller.api.index", package.seeall)
|
||||||
|
--import lua_file,路径问题?
|
||||||
|
local bfs = require "meizu.bfs"
|
||||||
|
local cjson = require "cjson"
|
||||||
|
local lfs = require "lfs"
|
||||||
|
local lue = require("luci.util").exec
|
||||||
|
local nwfs = require "meizu.nwfs"
|
||||||
|
local RC = require "meizu.r10config"
|
||||||
|
local sipfs = require "meizu.sipfs"
|
||||||
|
local upgdfs = require "meizu.upgdfs"
|
||||||
|
|
||||||
|
--replace
|
||||||
|
--bind_router流程如何?
|
||||||
|
bind_router = bfs.bind_router
|
||||||
|
data_to_json = bfs.data_to_json
|
||||||
|
exec_cmd_in_sh = bfs.exec_cmd_in_sh
|
||||||
|
exec_reboot = bfs.exec_reboot
|
||||||
|
factory_reset = bfs.factory_reset
|
||||||
|
set_passwd = bfs.set_passwd
|
||||||
|
silent_upgrade = bfs.silent_upgrade
|
||||||
|
|
||||||
|
sip = sipfs.sip
|
||||||
|
pysip = sipfs.pysip
|
||||||
|
upload_router_log = sipfs.upload_router_log
|
||||||
|
--network
|
||||||
|
nw_check_sys_password = nwfs.nw_check_sys_password
|
||||||
|
nw_get_connect_device_list = nwfs.nw_get_connect_device_list
|
||||||
|
nw_get_device_details = nwfs.nw_get_device_details
|
||||||
|
nw_get_wan_type = nwfs.nw_get_wan_type
|
||||||
|
nw_get_wifi_settings = nwfs.nw_get_wifi_settings
|
||||||
|
nw_set_device_name = nwfs.nw_set_device_name
|
||||||
|
nw_set_wan_switch = nwfs.nw_set_wan_switch
|
||||||
|
nw_set_wan_type = nwfs.nw_set_wan_type
|
||||||
|
nw_wifi_settings = nwfs.nw_wifi_settings
|
||||||
|
nw_get_wireless_channel = nwfs.nw_get_wireless_channel
|
||||||
|
nw_set_wireless_channel = nwfs.nw_set_wireless_channel
|
||||||
|
|
||||||
|
nw_scan_ble_switch = nwfs.nw_scan_ble_switch
|
||||||
|
nw_get_ble_device_list = nwfs.nw_get_ble_device_list
|
||||||
|
nw_add_ble_mesh_device = nwfs.nw_add_ble_mesh_device
|
||||||
|
nw_get_ble_device_status = nwfs.nw_get_ble_device_status
|
||||||
|
nw_get_mesh_device_list = nwfs.nw_get_mesh_device_list
|
||||||
|
nw_remove_ble_from_mesh = nwfs.nw_remove_ble_from_mesh
|
||||||
|
nw_dismiss_mesh = nwfs.nw_dismiss_mesh
|
||||||
|
nw_set_mesh_device_attr = nwfs.nw_set_mesh_device_attr
|
||||||
|
nw_reboot_mesh_device = nwfs.nw_reboot_mesh_device
|
||||||
|
nw_unmesh_all_device = nwfs.nw_unmesh_all_device
|
||||||
|
nw_set_mesh_device_timer = nwfs.nw_set_mesh_device_timer
|
||||||
|
nw_del_mesh_device_timer = nwfs.nw_del_mesh_device_timer
|
||||||
|
nw_set_mesh_network_pwd = nwfs.nw_set_mesh_network_pwd
|
||||||
|
nw_set_lamp_brightness = nwfs.nw_set_lamp_brightness
|
||||||
|
|
||||||
|
get_net_device = nwfs.get_net_device
|
||||||
|
real_time_net_speed = nwfs.real_time_net_speed
|
||||||
|
|
||||||
|
check_upgrade = upgdfs.check_upgrade
|
||||||
|
do_upgrade = upgdfs.do_upgrade
|
||||||
|
local_upgrade = upgdfs.local_upgrade
|
||||||
|
|
||||||
|
function index()
|
||||||
|
--nw: abridged for "Nei Wang"; ww abridged for "Wai Wang"
|
||||||
|
--??
|
||||||
|
local root = node()
|
||||||
|
if not root.target then
|
||||||
|
root.target = alias("api")
|
||||||
|
root.index = true
|
||||||
|
end
|
||||||
|
local page = node("api")
|
||||||
|
|
||||||
|
--?
|
||||||
|
page.target = firstchild()
|
||||||
|
page.title = _("api")
|
||||||
|
page.order = 10
|
||||||
|
page.index = true
|
||||||
|
page.sysauth = "root"
|
||||||
|
page.sysauth_authenticator = "htmlauth"
|
||||||
|
|
||||||
|
page = entry({"api", "searchrouter"}, call("nw_search_router"), nil)
|
||||||
|
--leaf属性具体?
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"api", "bindRouter"}, call("bind_router"), nil, nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"api", "sip"}, call("sip"), nil, nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "pysip"}, call("pysip"), nil, nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"api", "getWifiSettings"}, call("nw_get_wifi_settings"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "getConnectDeviceList"}, call("nw_get_connect_device_list"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "getdevicedetails"}, call("nw_get_device_details"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "getNetDevice"}, call("get_net_device"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "getWanType"}, call("nw_get_wan_type"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "realtimenetspeed"}, call("nw_real_time_net_speed"), nil, nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "setWanType"}, call("nw_set_wan_type"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "setDeviceName"}, call("nw_set_device_name"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "setWanSwitch"}, call("nw_set_wan_switch"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "wifiSettings"}, call("nw_wifi_settings"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "getWirelessChannel"}, call("nw_get_wireless_channel"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "setWirelessChannel"}, call("nw_set_wireless_channel"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"api", "factoryreset"}, call("factory_reset"), nil, nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "reboot"}, call("nw_exec_reboot"), nil, nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "localupgrade"}, call("local_upgrade"), nil, nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "silentupgrade"}, call("silent_upgrade"), nil, nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"api", "checkSysPassword"}, call("nw_check_sys_password"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "setpasswd"}, call("set_passwd"), nil, nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"api", "doupgrade"}, call("nw_do_upgrade"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "checkupgrade"}, call("nw_check_upgrade"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"api", "scanBleSwitch"}, call("nw_scan_ble_switch"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "getBleDeviceList"}, call("nw_get_ble_device_list"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "addMeshDevice"}, call("nw_add_ble_mesh_device"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "removeBleFromMesh"}, call("nw_remove_ble_from_mesh"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "getMeshDeviceDetail"}, call("nw_get_ble_device_status"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "getMeshDeviceList"}, call("nw_get_mesh_device_list"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "dismissMesh"}, call("nw_dismiss_mesh"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "setMeshDeviceAttr"}, call("nw_set_mesh_device_attr"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "rebootMeshDevice"}, call("nw_reboot_mesh_device"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "unmeshAllDevice"}, call("nw_unmesh_all_device"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "setMeshDeviceTimer"}, call("nw_set_mesh_device_timer"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "delMeshDeviceTimer"}, call("nw_del_mesh_device_timer"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "setMeshNetWorkPassword"}, call("nw_set_mesh_network_pwd"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"api", "setLampBrightness"}, call("nw_set_lamp_brightness"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
end
|
||||||
|
--验证升级
|
||||||
|
function nw_check_upgrade()
|
||||||
|
local ret = check_upgrade()
|
||||||
|
luci.http.write(ret) --输出到html页面,结果?
|
||||||
|
end
|
||||||
|
|
||||||
|
--升级,nw全称是?
|
||||||
|
function nw_do_upgrade()
|
||||||
|
local ret = {} --这是一个数组还是哈希?
|
||||||
|
luci.http.status(200, "upgrading....")
|
||||||
|
ret["code"] = 2004
|
||||||
|
ret["result"] = "upgrading...."
|
||||||
|
luci.http.write(data_to_json(ret)) --把ret转成json并输出到页面?
|
||||||
|
do_upgrade()
|
||||||
|
end
|
||||||
|
--实时网速
|
||||||
|
function nw_real_time_net_speed()
|
||||||
|
--这句是做啥?
|
||||||
|
luci.http.prepare_content("application/json")
|
||||||
|
|
||||||
|
local result = real_time_net_speed()
|
||||||
|
luci.http.write_json(result)
|
||||||
|
end
|
||||||
|
--执行重刷固件?
|
||||||
|
function nw_exec_reboot()
|
||||||
|
local ret = {}
|
||||||
|
ret["result"] = true
|
||||||
|
luci.http.write_json(ret)
|
||||||
|
exec_reboot()
|
||||||
|
end
|
||||||
|
--搜索路由器具体功能实现?
|
||||||
|
function nw_search_router()
|
||||||
|
local wl_type_val = luci.http.formvalue("type")
|
||||||
|
local wireless_dev = "ra0"
|
||||||
|
local wireless_type = "2.4G"
|
||||||
|
if wl_type_val == "2" then
|
||||||
|
wireless_type = "5G"
|
||||||
|
wireless_dev = "rai0"
|
||||||
|
end
|
||||||
|
--MZLog.log??
|
||||||
|
require "MZLog".log(3, wl_type_val)
|
||||||
|
require "MZLog".log(3, wireless_type)
|
||||||
|
local sub = require "string".sub
|
||||||
|
local trim = require "string".trim
|
||||||
|
local ssid_table = {}
|
||||||
|
local cmd = [[ap_scan.sh ]]..wireless_dev..[[| grep "^[0-9]"]]
|
||||||
|
local ssids = io.popen(cmd)
|
||||||
|
local ln = 1
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
for line in ssids:lines() do
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, line)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
local assid = {}
|
||||||
|
|
||||||
|
local channel = trim(sub(line, 1, 4))
|
||||||
|
local ssid = trim(sub(line, 5, 37))
|
||||||
|
local mac = trim(sub(line, 38, 54))
|
||||||
|
local sec = trim(sub(line, 58, 79))
|
||||||
|
local rss = trim(sub(line, 81, 82))
|
||||||
|
local extch = trim(sub(line, 98, 103))
|
||||||
|
assid["mac"] = mac
|
||||||
|
assid["rss"] = rss
|
||||||
|
assid["sec"] = sec
|
||||||
|
assid["ssid"] = ssid
|
||||||
|
assid["type"] = wireless_type
|
||||||
|
assid["channel"] = channel
|
||||||
|
assid["extch"] = extch
|
||||||
|
|
||||||
|
ssid_table[ln] = assid
|
||||||
|
ln = ln + 1
|
||||||
|
end
|
||||||
|
ssids:close()
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
luci.http.write_json(ssid_table)
|
||||||
|
end
|
105
Me_Lua/r13/luci/controller/bs/index.lua
Normal file
105
Me_Lua/r13/luci/controller/bs/index.lua
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
module("luci.controller.bs.index", package.seeall)
|
||||||
|
|
||||||
|
|
||||||
|
local arpmon = require "meizu.arpmon"
|
||||||
|
local bfs = require "meizu.bfs"
|
||||||
|
|
||||||
|
new_device_notify = arpmon.new_device_notify
|
||||||
|
|
||||||
|
function index()
|
||||||
|
local root = node()
|
||||||
|
if not root.target then
|
||||||
|
root.target = alias("bs")
|
||||||
|
root.index = true
|
||||||
|
end
|
||||||
|
local page = node("bs")
|
||||||
|
--page.target = firstchild()
|
||||||
|
page.title = _("bs")
|
||||||
|
page.order = 10
|
||||||
|
page.index = true
|
||||||
|
page = entry({"bs", "info"}, call("info"), nil, nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"bs", "token"}, call("token"), nil, nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"bs", "newdevicenotify"}, call("new_device_notify"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"bs", "devip"}, call("devip"), nil, nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"bs", "testip"}, call("testip"), nil, nil)
|
||||||
|
page.leaf = true
|
||||||
|
page = entry({"bs", "normip"}, call("normip"), nil, nil)
|
||||||
|
page.leaf = true
|
||||||
|
|
||||||
|
page = entry({"bs", "apk"}, call("apk"), nil)
|
||||||
|
page.leaf = true
|
||||||
|
end
|
||||||
|
|
||||||
|
function info()
|
||||||
|
luci.http.prepare_content("application/json")
|
||||||
|
local result = bfs.sysinfo()
|
||||||
|
luci.http.write_json(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
function token()
|
||||||
|
luci.http.prepare_content("application/json")
|
||||||
|
local sauth = require "luci.sauth"
|
||||||
|
local token = sauth.noAuthGetToken()
|
||||||
|
if token then
|
||||||
|
luci.http.write_json(token)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function show_hosts()
|
||||||
|
local lue = require"luci.util".exec
|
||||||
|
local cmd = "cat /etc/hosts"
|
||||||
|
local ret = lue(cmd)
|
||||||
|
luci.http.write(ret)
|
||||||
|
end
|
||||||
|
|
||||||
|
function devip()
|
||||||
|
local lue = require"luci.util".exec
|
||||||
|
local cmd = "/usr/sbin/mzrts_ips.sh devip"
|
||||||
|
local ret = lue(cmd)
|
||||||
|
show_hosts()
|
||||||
|
end
|
||||||
|
|
||||||
|
function normip()
|
||||||
|
local lue = require"luci.util".exec
|
||||||
|
local cmd = "/usr/sbin/mzrts_ips.sh"
|
||||||
|
local ret = lue(cmd)
|
||||||
|
show_hosts()
|
||||||
|
end
|
||||||
|
|
||||||
|
function testip()
|
||||||
|
local lue = require"luci.util".exec
|
||||||
|
local cmd = "/usr/sbin/mzrts_ips.sh testip"
|
||||||
|
local ret = lue(cmd)
|
||||||
|
show_hosts()
|
||||||
|
end
|
||||||
|
|
||||||
|
function apk()
|
||||||
|
local fn, fd, block
|
||||||
|
local cmd = "ls /www/apk_download/apk/*.apk | awk '{printf $1}'"
|
||||||
|
fd = io.popen(cmd)
|
||||||
|
fn = fd:read("*l")
|
||||||
|
fd:close()
|
||||||
|
if fn ~= nil then
|
||||||
|
fd = nixio.open(fn, "r")
|
||||||
|
luci.http.header('Content-Disposition', 'attachment; filename="%s"' % {nixio.fs.basename(fn)})
|
||||||
|
luci.http.prepare_content("application/octet-stream")
|
||||||
|
while true do
|
||||||
|
block = fd:read(nixio.const.buffersize)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
if (not block) or (#block == 0) then
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
break
|
||||||
|
else
|
||||||
|
luci.http.write(block)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
fd:close()
|
||||||
|
end
|
||||||
|
luci.http.close()
|
||||||
|
end
|
965
Me_Lua/r13/luci/dispatcher.lua
Normal file
965
Me_Lua/r13/luci/dispatcher.lua
Normal file
@ -0,0 +1,965 @@
|
|||||||
|
--[[
|
||||||
|
LuCI - Dispatcher
|
||||||
|
|
||||||
|
Description:
|
||||||
|
The request dispatcher and module dispatcher generators
|
||||||
|
|
||||||
|
FileId:
|
||||||
|
$Id$
|
||||||
|
|
||||||
|
License:
|
||||||
|
Copyright 2008 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
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
]]--
|
||||||
|
|
||||||
|
--- LuCI web dispatcher.
|
||||||
|
local fs = require "nixio.fs"
|
||||||
|
local sys = require "luci.sys"
|
||||||
|
local init = require "luci.init"
|
||||||
|
local util = require "luci.util"
|
||||||
|
local http = require "luci.http"
|
||||||
|
local nixio = require "nixio", require "nixio.util"
|
||||||
|
|
||||||
|
module("luci.dispatcher", package.seeall)
|
||||||
|
context = util.threadlocal()
|
||||||
|
uci = require "luci.model.uci"
|
||||||
|
i18n = require "luci.i18n"
|
||||||
|
_M.fs = fs
|
||||||
|
|
||||||
|
authenticator = {}
|
||||||
|
|
||||||
|
-- Index table
|
||||||
|
local index = nil
|
||||||
|
|
||||||
|
-- Fastindex
|
||||||
|
local fi
|
||||||
|
|
||||||
|
|
||||||
|
--- Build the URL relative to the server webroot from given virtual path.
|
||||||
|
-- @param ... Virtual path
|
||||||
|
-- @return Relative URL
|
||||||
|
function build_url(...)
|
||||||
|
local path = {...}
|
||||||
|
local url = { http.getenv("SCRIPT_NAME") or "" }
|
||||||
|
|
||||||
|
local k, v
|
||||||
|
for k, v in pairs(context.urltoken) do
|
||||||
|
url[#url+1] = "/;"
|
||||||
|
url[#url+1] = http.urlencode(k)
|
||||||
|
url[#url+1] = "="
|
||||||
|
url[#url+1] = http.urlencode(v)
|
||||||
|
end
|
||||||
|
|
||||||
|
local p
|
||||||
|
for _, p in ipairs(path) do
|
||||||
|
if p:match("^[a-zA-Z0-9_%-%.%%/,;]+$") then
|
||||||
|
url[#url+1] = "/"
|
||||||
|
url[#url+1] = p
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return table.concat(url, "")
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check whether a dispatch node shall be visible
|
||||||
|
-- @param node Dispatch node
|
||||||
|
-- @return Boolean indicating whether the node should be visible
|
||||||
|
function node_visible(node)
|
||||||
|
if node then
|
||||||
|
return not (
|
||||||
|
(not node.title or #node.title == 0) or
|
||||||
|
(not node.target or node.hidden == true) or
|
||||||
|
(type(node.target) == "table" and node.target.type == "firstchild" and
|
||||||
|
(type(node.nodes) ~= "table" or not next(node.nodes)))
|
||||||
|
)
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Return a sorted table of visible childs within a given node
|
||||||
|
-- @param node Dispatch node
|
||||||
|
-- @return Ordered table of child node names
|
||||||
|
function node_childs(node)
|
||||||
|
local rv = { }
|
||||||
|
if node then
|
||||||
|
local k, v
|
||||||
|
for k, v in util.spairs(node.nodes,
|
||||||
|
function(a, b)
|
||||||
|
return (node.nodes[a].order or 100)
|
||||||
|
< (node.nodes[b].order or 100)
|
||||||
|
end)
|
||||||
|
do
|
||||||
|
if node_visible(v) then
|
||||||
|
rv[#rv+1] = k
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return rv
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Send a 404 error code and render the "error404" template if available.
|
||||||
|
-- @param message Custom error message (optional)
|
||||||
|
-- @return false
|
||||||
|
function error404(message)
|
||||||
|
luci.http.status(404, "Not Found")
|
||||||
|
message = message or "Not Found"
|
||||||
|
|
||||||
|
require("luci.template")
|
||||||
|
if not luci.util.copcall(luci.template.render, "error404") then
|
||||||
|
luci.http.prepare_content("text/plain")
|
||||||
|
luci.http.write(message)
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Send a 500 error code and render the "error500" template if available.
|
||||||
|
-- @param message Custom error message (optional)#
|
||||||
|
-- @return false
|
||||||
|
function error500(message)
|
||||||
|
luci.util.perror(message)
|
||||||
|
if not context.template_header_sent then
|
||||||
|
luci.http.status(500, "Internal Server Error")
|
||||||
|
luci.http.prepare_content("text/plain")
|
||||||
|
luci.http.write(message)
|
||||||
|
else
|
||||||
|
require("luci.template")
|
||||||
|
if not luci.util.copcall(luci.template.render, "error500", {message=message}) then
|
||||||
|
luci.http.prepare_content("text/plain")
|
||||||
|
luci.http.write(message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function authenticator.htmlauth(validator, accs, default)
|
||||||
|
local user = luci.http.formvalue("username")
|
||||||
|
local pass = luci.http.formvalue("password")
|
||||||
|
|
||||||
|
if user and validator(user, pass) then
|
||||||
|
return user
|
||||||
|
end
|
||||||
|
|
||||||
|
require("luci.i18n")
|
||||||
|
require("luci.template")
|
||||||
|
context.path = {}
|
||||||
|
luci.template.render("sysauth", {duser=default, fuser=user})
|
||||||
|
return false
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Dispatch an HTTP request.
|
||||||
|
-- @param request LuCI HTTP Request object
|
||||||
|
function httpdispatch(request, prefix)
|
||||||
|
luci.http.context.request = request
|
||||||
|
|
||||||
|
local r = {}
|
||||||
|
context.request = r
|
||||||
|
context.urltoken = {}
|
||||||
|
|
||||||
|
local pathinfo = http.urldecode(request:getenv("PATH_INFO") or "", true)
|
||||||
|
|
||||||
|
if prefix then
|
||||||
|
for _, node in ipairs(prefix) do
|
||||||
|
r[#r+1] = node
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local tokensok = true
|
||||||
|
for node in pathinfo:gmatch("[^/]+") do
|
||||||
|
local tkey, tval
|
||||||
|
if tokensok then
|
||||||
|
tkey, tval = node:match(";(%w+)=([a-fA-F0-9]*)")
|
||||||
|
end
|
||||||
|
if tkey then
|
||||||
|
context.urltoken[tkey] = tval
|
||||||
|
else
|
||||||
|
tokensok = false
|
||||||
|
r[#r+1] = node
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local stat, err = util.coxpcall(function()
|
||||||
|
dispatch(context.request)
|
||||||
|
end, error500)
|
||||||
|
|
||||||
|
luci.http.close()
|
||||||
|
|
||||||
|
--context._disable_memtrace()
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Dispatches a LuCI virtual path.
|
||||||
|
-- @param request Virtual path
|
||||||
|
function dispatch(request)
|
||||||
|
--context._disable_memtrace = require "luci.debug".trap_memtrace("l")
|
||||||
|
require "MZLog".log(3, request)
|
||||||
|
local ctx = context
|
||||||
|
ctx.path = request
|
||||||
|
|
||||||
|
local conf = require "luci.config"
|
||||||
|
assert(conf.main,
|
||||||
|
"/etc/config/luci seems to be corrupt, unable to find section 'main'")
|
||||||
|
|
||||||
|
local lang = conf.main.lang or "auto"
|
||||||
|
if lang == "auto" then
|
||||||
|
lang = "zh_cn"
|
||||||
|
--[[
|
||||||
|
[local aclang = http.getenv("HTTP_ACCEPT_LANGUAGE") or ""
|
||||||
|
[for lpat in aclang:gmatch("[%w-]+") do
|
||||||
|
[ lpat = lpat and lpat:gsub("-", "_")
|
||||||
|
[ if conf.languages[lpat] then
|
||||||
|
[ lang = lpat
|
||||||
|
[ break
|
||||||
|
[ end
|
||||||
|
[end
|
||||||
|
]]
|
||||||
|
end
|
||||||
|
require "luci.i18n".setlanguage(lang)
|
||||||
|
|
||||||
|
local c = ctx.tree
|
||||||
|
local stat
|
||||||
|
if not c then
|
||||||
|
c = createtree()
|
||||||
|
end
|
||||||
|
|
||||||
|
local track = {}
|
||||||
|
local args = {}
|
||||||
|
ctx.args = args
|
||||||
|
ctx.requestargs = ctx.requestargs or args
|
||||||
|
local n
|
||||||
|
local token = ctx.urltoken
|
||||||
|
local preq = {}
|
||||||
|
local freq = {}
|
||||||
|
|
||||||
|
for i, s in ipairs(request) do
|
||||||
|
preq[#preq+1] = s
|
||||||
|
freq[#freq+1] = s
|
||||||
|
c = c.nodes[s]
|
||||||
|
n = i
|
||||||
|
if not c then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
util.update(track, c)
|
||||||
|
|
||||||
|
if c.leaf then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if c and c.leaf then
|
||||||
|
for j=n+1, #request do
|
||||||
|
args[#args+1] = request[j]
|
||||||
|
freq[#freq+1] = request[j]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ctx.requestpath = ctx.requestpath or freq
|
||||||
|
ctx.path = preq
|
||||||
|
|
||||||
|
if track.i18n then
|
||||||
|
i18n.loadc(track.i18n)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Init template engine
|
||||||
|
if (c and c.index) or not track.notemplate then
|
||||||
|
local tpl = require("luci.template")
|
||||||
|
local media = track.mediaurlbase or luci.config.main.mediaurlbase
|
||||||
|
if not pcall(tpl.Template, "themes/%s/header" % fs.basename(media)) then
|
||||||
|
media = nil
|
||||||
|
for name, theme in pairs(luci.config.themes) do
|
||||||
|
if name:sub(1,1) ~= "." and pcall(tpl.Template,
|
||||||
|
"themes/%s/header" % fs.basename(theme)) then
|
||||||
|
media = theme
|
||||||
|
end
|
||||||
|
end
|
||||||
|
assert(media, "No valid theme found")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function _ifattr(cond, key, val)
|
||||||
|
if cond then
|
||||||
|
local env = getfenv(3)
|
||||||
|
local scope = (type(env.self) == "table") and env.self
|
||||||
|
return string.format(
|
||||||
|
' %s="%s"', tostring(key),
|
||||||
|
luci.util.pcdata(tostring( val
|
||||||
|
or (type(env[key]) ~= "function" and env[key])
|
||||||
|
or (scope and type(scope[key]) ~= "function" and scope[key])
|
||||||
|
or "" ))
|
||||||
|
)
|
||||||
|
else
|
||||||
|
return ''
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
tpl.context.viewns = setmetatable({
|
||||||
|
write = luci.http.write;
|
||||||
|
include = function(name) tpl.Template(name):render(getfenv(2)) end;
|
||||||
|
translate = i18n.translate;
|
||||||
|
translatef = i18n.translatef;
|
||||||
|
export = function(k, v) if tpl.context.viewns[k] == nil then tpl.context.viewns[k] = v end end;
|
||||||
|
striptags = util.striptags;
|
||||||
|
pcdata = util.pcdata;
|
||||||
|
media = media;
|
||||||
|
theme = fs.basename(media);
|
||||||
|
resource = luci.config.main.resourcebase;
|
||||||
|
ifattr = function(...) return _ifattr(...) end;
|
||||||
|
attr = function(...) return _ifattr(true, ...) end;
|
||||||
|
}, {__index=function(table, key)
|
||||||
|
if key == "controller" then
|
||||||
|
return build_url()
|
||||||
|
elseif key == "REQUEST_URI" then
|
||||||
|
return build_url(unpack(ctx.requestpath))
|
||||||
|
else
|
||||||
|
return rawget(table, key) or _G[key]
|
||||||
|
end
|
||||||
|
end})
|
||||||
|
end
|
||||||
|
|
||||||
|
track.dependent = (track.dependent ~= false)
|
||||||
|
assert(not track.dependent or not track.auto,
|
||||||
|
"Access Violation\nThe page at '" .. table.concat(request, "/") .. "/' " ..
|
||||||
|
"has no parent node so the access to this location has been denied.\n" ..
|
||||||
|
"This is a software bug, please report this message at " ..
|
||||||
|
"http://luci.subsignal.org/trac/newticket"
|
||||||
|
)
|
||||||
|
|
||||||
|
local isremote = http.getenv("REMOTE_ADDR") == "127.0.0.1"
|
||||||
|
|
||||||
|
if not isremote and track.sysauth then
|
||||||
|
local sauth = require "luci.sauth"
|
||||||
|
|
||||||
|
local authen = type(track.sysauth_authenticator) == "function"
|
||||||
|
and track.sysauth_authenticator
|
||||||
|
or authenticator[track.sysauth_authenticator]
|
||||||
|
|
||||||
|
local def = (type(track.sysauth) == "string") and track.sysauth
|
||||||
|
local accs = def and {track.sysauth} or track.sysauth
|
||||||
|
local sess = ctx.authsession
|
||||||
|
local verifytoken = false
|
||||||
|
if not sess then
|
||||||
|
sess = luci.http.getcookie("sysauth")
|
||||||
|
sess = sess and sess:match("^[a-f0-9]*$")
|
||||||
|
verifytoken = true
|
||||||
|
end
|
||||||
|
|
||||||
|
local sdat = sauth.read(sess)
|
||||||
|
local user
|
||||||
|
|
||||||
|
if sdat then
|
||||||
|
if not verifytoken or ctx.urltoken.stok == sdat.token then
|
||||||
|
user = sdat.user
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local eu = http.getenv("HTTP_AUTH_USER")
|
||||||
|
local ep = http.getenv("HTTP_AUTH_PASS")
|
||||||
|
if eu and ep and luci.sys.user.checkpasswd(eu, ep) then
|
||||||
|
authen = function() return eu end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not util.contains(accs, user) then
|
||||||
|
if authen then
|
||||||
|
ctx.urltoken.stok = nil
|
||||||
|
local user, sess = authen(luci.sys.user.checkpasswd, accs, def)
|
||||||
|
if not user or not util.contains(accs, user) then
|
||||||
|
return
|
||||||
|
else
|
||||||
|
local sid = sess or luci.sys.uniqueid(16)
|
||||||
|
if not sess then
|
||||||
|
local token = luci.sys.uniqueid(16)
|
||||||
|
sauth.reap()
|
||||||
|
sauth.write(sid, {
|
||||||
|
user=user,
|
||||||
|
token=token,
|
||||||
|
secret=luci.sys.uniqueid(16)
|
||||||
|
})
|
||||||
|
ctx.urltoken.stok = token
|
||||||
|
end
|
||||||
|
luci.http.header("Set-Cookie", "sysauth=" .. sid.."; path="..build_url())
|
||||||
|
ctx.authsession = sid
|
||||||
|
ctx.authuser = user
|
||||||
|
end
|
||||||
|
else
|
||||||
|
luci.http.status(403, "Forbidden")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
else
|
||||||
|
ctx.authsession = sess
|
||||||
|
ctx.authuser = user
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if track.setgroup then
|
||||||
|
luci.sys.process.setgroup(track.setgroup)
|
||||||
|
end
|
||||||
|
|
||||||
|
if track.setuser then
|
||||||
|
luci.sys.process.setuser(track.setuser)
|
||||||
|
end
|
||||||
|
|
||||||
|
local target = nil
|
||||||
|
if c then
|
||||||
|
if type(c.target) == "function" then
|
||||||
|
target = c.target
|
||||||
|
elseif type(c.target) == "table" then
|
||||||
|
target = c.target.target
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if c and (c.index or type(target) == "function") then
|
||||||
|
ctx.dispatched = c
|
||||||
|
ctx.requested = ctx.requested or ctx.dispatched
|
||||||
|
end
|
||||||
|
|
||||||
|
if c and c.index then
|
||||||
|
local tpl = require "luci.template"
|
||||||
|
|
||||||
|
if util.copcall(tpl.render, "indexer", {}) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(target) == "function" then
|
||||||
|
util.copcall(function()
|
||||||
|
local oldenv = getfenv(target)
|
||||||
|
local module = require(c.module)
|
||||||
|
local env = setmetatable({}, {__index=
|
||||||
|
|
||||||
|
function(tbl, key)
|
||||||
|
return rawget(tbl, key) or module[key] or oldenv[key]
|
||||||
|
end})
|
||||||
|
|
||||||
|
setfenv(target, env)
|
||||||
|
end)
|
||||||
|
|
||||||
|
local ok, err
|
||||||
|
if type(c.target) == "table" then
|
||||||
|
ok, err = util.copcall(target, c.target, unpack(args))
|
||||||
|
else
|
||||||
|
ok, err = util.copcall(target, unpack(args))
|
||||||
|
end
|
||||||
|
assert(ok,
|
||||||
|
"Failed to execute " .. (type(c.target) == "function" and "function" or c.target.type or "unknown") ..
|
||||||
|
" dispatcher target for entry '/" .. table.concat(request, "/") .. "'.\n" ..
|
||||||
|
"The called action terminated with an exception:\n" .. tostring(err or "(unknown)"))
|
||||||
|
else
|
||||||
|
local root = node()
|
||||||
|
if not root or not root.target then
|
||||||
|
error404("No root node was registered, this usually happens if no module was installed.\n" ..
|
||||||
|
"Install luci-mod-admin-full and retry. " ..
|
||||||
|
"If the module is already installed, try removing the /tmp/luci-indexcache file.")
|
||||||
|
else
|
||||||
|
error404("No page is registered at '/" .. table.concat(request, "/") .. "'.\n" ..
|
||||||
|
"If this url belongs to an extension, make sure it is properly installed.\n" ..
|
||||||
|
"If the extension was recently installed, try removing the /tmp/luci-indexcache file.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Generate the dispatching index using the best possible strategy.
|
||||||
|
function createindex()
|
||||||
|
local path = luci.util.libpath() .. "/controller/"
|
||||||
|
local suff = { ".lua", ".lua.gz" }
|
||||||
|
|
||||||
|
if luci.util.copcall(require, "luci.fastindex") then
|
||||||
|
createindex_fastindex(path, suff)
|
||||||
|
else
|
||||||
|
createindex_plain(path, suff)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Generate the dispatching index using the fastindex C-indexer.
|
||||||
|
-- @param path Controller base directory
|
||||||
|
-- @param suffixes Controller file suffixes
|
||||||
|
function createindex_fastindex(path, suffixes)
|
||||||
|
index = {}
|
||||||
|
|
||||||
|
if not fi then
|
||||||
|
fi = luci.fastindex.new("index")
|
||||||
|
for _, suffix in ipairs(suffixes) do
|
||||||
|
fi.add(path .. "*" .. suffix)
|
||||||
|
fi.add(path .. "*/*" .. suffix)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
fi.scan()
|
||||||
|
|
||||||
|
for k, v in pairs(fi.indexes) do
|
||||||
|
index[v[2]] = v[1]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Generate the dispatching index using the native file-cache based strategy.
|
||||||
|
-- @param path Controller base directory
|
||||||
|
-- @param suffixes Controller file suffixes
|
||||||
|
function createindex_plain(path, suffixes)
|
||||||
|
local controllers = { }
|
||||||
|
for _, suffix in ipairs(suffixes) do
|
||||||
|
nixio.util.consume((fs.glob(path .. "*" .. suffix)), controllers)
|
||||||
|
nixio.util.consume((fs.glob(path .. "*/*" .. suffix)), controllers)
|
||||||
|
end
|
||||||
|
|
||||||
|
if indexcache then
|
||||||
|
local cachedate = fs.stat(indexcache, "mtime")
|
||||||
|
if cachedate then
|
||||||
|
local realdate = 0
|
||||||
|
for _, obj in ipairs(controllers) do
|
||||||
|
local omtime = fs.stat(obj, "mtime")
|
||||||
|
realdate = (omtime and omtime > realdate) and omtime or realdate
|
||||||
|
end
|
||||||
|
|
||||||
|
if cachedate > realdate then
|
||||||
|
assert(
|
||||||
|
sys.process.info("uid") == fs.stat(indexcache, "uid")
|
||||||
|
and fs.stat(indexcache, "modestr") == "rw-------",
|
||||||
|
"Fatal: Indexcache is not sane!"
|
||||||
|
)
|
||||||
|
|
||||||
|
index = loadfile(indexcache)()
|
||||||
|
return index
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
index = {}
|
||||||
|
|
||||||
|
for i,c in ipairs(controllers) do
|
||||||
|
local modname = "luci.controller." .. c:sub(#path+1, #c):gsub("/", ".")
|
||||||
|
for _, suffix in ipairs(suffixes) do
|
||||||
|
modname = modname:gsub(suffix.."$", "")
|
||||||
|
end
|
||||||
|
|
||||||
|
local mod = require(modname)
|
||||||
|
assert(mod ~= true,
|
||||||
|
"Invalid controller file found\n" ..
|
||||||
|
"The file '" .. c .. "' contains an invalid module line.\n" ..
|
||||||
|
"Please verify whether the module name is set to '" .. modname ..
|
||||||
|
"' - It must correspond to the file path!")
|
||||||
|
|
||||||
|
local idx = mod.index
|
||||||
|
assert(type(idx) == "function",
|
||||||
|
"Invalid controller file found\n" ..
|
||||||
|
"The file '" .. c .. "' contains no index() function.\n" ..
|
||||||
|
"Please make sure that the controller contains a valid " ..
|
||||||
|
"index function and verify the spelling!")
|
||||||
|
|
||||||
|
index[modname] = idx
|
||||||
|
end
|
||||||
|
|
||||||
|
if indexcache then
|
||||||
|
local f = nixio.open(indexcache, "w", 600)
|
||||||
|
f:writeall(util.get_bytecode(index))
|
||||||
|
f:close()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Create the dispatching tree from the index.
|
||||||
|
-- Build the index before if it does not exist yet.
|
||||||
|
function createtree()
|
||||||
|
if not index then
|
||||||
|
createindex()
|
||||||
|
end
|
||||||
|
|
||||||
|
local ctx = context
|
||||||
|
local tree = {nodes={}, inreq=true}
|
||||||
|
local modi = {}
|
||||||
|
|
||||||
|
ctx.treecache = setmetatable({}, {__mode="v"})
|
||||||
|
ctx.tree = tree
|
||||||
|
ctx.modifiers = modi
|
||||||
|
|
||||||
|
-- Load default translation
|
||||||
|
require "luci.i18n".loadc("base")
|
||||||
|
|
||||||
|
local scope = setmetatable({}, {__index = luci.dispatcher})
|
||||||
|
|
||||||
|
for k, v in pairs(index) do
|
||||||
|
scope._NAME = k
|
||||||
|
setfenv(v, scope)
|
||||||
|
v()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function modisort(a,b)
|
||||||
|
return modi[a].order < modi[b].order
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, v in util.spairs(modi, modisort) do
|
||||||
|
scope._NAME = v.module
|
||||||
|
setfenv(v.func, scope)
|
||||||
|
v.func()
|
||||||
|
end
|
||||||
|
|
||||||
|
return tree
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Register a tree modifier.
|
||||||
|
-- @param func Modifier function
|
||||||
|
-- @param order Modifier order value (optional)
|
||||||
|
function modifier(func, order)
|
||||||
|
context.modifiers[#context.modifiers+1] = {
|
||||||
|
func = func,
|
||||||
|
order = order or 0,
|
||||||
|
module
|
||||||
|
= getfenv(2)._NAME
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Clone a node of the dispatching tree to another position.
|
||||||
|
-- @param path Virtual path destination
|
||||||
|
-- @param clone Virtual path source
|
||||||
|
-- @param title Destination node title (optional)
|
||||||
|
-- @param order Destination node order value (optional)
|
||||||
|
-- @return Dispatching tree node
|
||||||
|
function assign(path, clone, title, order)
|
||||||
|
local obj = node(unpack(path))
|
||||||
|
obj.nodes = nil
|
||||||
|
obj.module = nil
|
||||||
|
|
||||||
|
obj.title = title
|
||||||
|
obj.order = order
|
||||||
|
|
||||||
|
setmetatable(obj, {__index = _create_node(clone)})
|
||||||
|
|
||||||
|
return obj
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Create a new dispatching node and define common parameters.
|
||||||
|
-- @param path Virtual path
|
||||||
|
-- @param target Target function to call when dispatched.
|
||||||
|
-- @param title Destination node title
|
||||||
|
-- @param order Destination node order value (optional)
|
||||||
|
-- @return Dispatching tree node
|
||||||
|
function entry(path, target, title, order)
|
||||||
|
local c = node(unpack(path))
|
||||||
|
|
||||||
|
c.target = target
|
||||||
|
c.title = title
|
||||||
|
c.order = order
|
||||||
|
c.module = getfenv(2)._NAME
|
||||||
|
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Fetch or create a dispatching node without setting the target module or
|
||||||
|
-- enabling the node.
|
||||||
|
-- @param ... Virtual path
|
||||||
|
-- @return Dispatching tree node
|
||||||
|
function get(...)
|
||||||
|
return _create_node({...})
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Fetch or create a new dispatching node.
|
||||||
|
-- @param ... Virtual path
|
||||||
|
-- @return Dispatching tree node
|
||||||
|
function node(...)
|
||||||
|
local c = _create_node({...})
|
||||||
|
|
||||||
|
c.module = getfenv(2)._NAME
|
||||||
|
c.auto = nil
|
||||||
|
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
|
||||||
|
function _create_node(path)
|
||||||
|
if #path == 0 then
|
||||||
|
return context.tree
|
||||||
|
end
|
||||||
|
|
||||||
|
local name = table.concat(path, ".")
|
||||||
|
local c = context.treecache[name]
|
||||||
|
|
||||||
|
if not c then
|
||||||
|
local last = table.remove(path)
|
||||||
|
local parent = _create_node(path)
|
||||||
|
|
||||||
|
c = {nodes={}, auto=true}
|
||||||
|
-- the node is "in request" if the request path matches
|
||||||
|
-- at least up to the length of the node path
|
||||||
|
if parent.inreq and context.path[#path+1] == last then
|
||||||
|
c.inreq = true
|
||||||
|
end
|
||||||
|
parent.nodes[last] = c
|
||||||
|
context.treecache[name] = c
|
||||||
|
end
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Subdispatchers --
|
||||||
|
|
||||||
|
function _firstchild()
|
||||||
|
local path = { unpack(context.path) }
|
||||||
|
local name = table.concat(path, ".")
|
||||||
|
local node = context.treecache[name]
|
||||||
|
|
||||||
|
local lowest
|
||||||
|
if node and node.nodes and next(node.nodes) then
|
||||||
|
local k, v
|
||||||
|
for k, v in pairs(node.nodes) do
|
||||||
|
if not lowest or
|
||||||
|
(v.order or 100) < (node.nodes[lowest].order or 100)
|
||||||
|
then
|
||||||
|
lowest = k
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assert(lowest ~= nil,
|
||||||
|
"The requested node contains no childs, unable to redispatch")
|
||||||
|
|
||||||
|
path[#path+1] = lowest
|
||||||
|
dispatch(path)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Alias the first (lowest order) page automatically
|
||||||
|
function firstchild()
|
||||||
|
return { type = "firstchild", target = _firstchild }
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Create a redirect to another dispatching node.
|
||||||
|
-- @param ... Virtual path destination
|
||||||
|
function alias(...)
|
||||||
|
local req = {...}
|
||||||
|
return function(...)
|
||||||
|
for _, r in ipairs({...}) do
|
||||||
|
req[#req+1] = r
|
||||||
|
end
|
||||||
|
|
||||||
|
dispatch(req)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Rewrite the first x path values of the request.
|
||||||
|
-- @param n Number of path values to replace
|
||||||
|
-- @param ... Virtual path to replace removed path values with
|
||||||
|
function rewrite(n, ...)
|
||||||
|
local req = {...}
|
||||||
|
return function(...)
|
||||||
|
local dispatched = util.clone(context.dispatched)
|
||||||
|
|
||||||
|
for i=1,n do
|
||||||
|
table.remove(dispatched, 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
for i, r in ipairs(req) do
|
||||||
|
table.insert(dispatched, i, r)
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, r in ipairs({...}) do
|
||||||
|
dispatched[#dispatched+1] = r
|
||||||
|
end
|
||||||
|
|
||||||
|
dispatch(dispatched)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function _call(self, ...)
|
||||||
|
local func = getfenv()[self.name]
|
||||||
|
assert(func ~= nil,
|
||||||
|
'Cannot resolve function "' .. self.name .. '". Is it misspelled or local?')
|
||||||
|
|
||||||
|
assert(type(func) == "function",
|
||||||
|
'The symbol "' .. self.name .. '" does not refer to a function but data ' ..
|
||||||
|
'of type "' .. type(func) .. '".')
|
||||||
|
|
||||||
|
if #self.argv > 0 then
|
||||||
|
return func(unpack(self.argv), ...)
|
||||||
|
else
|
||||||
|
return func(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Create a function-call dispatching target.
|
||||||
|
-- @param name Target function of local controller
|
||||||
|
-- @param ... Additional parameters passed to the function
|
||||||
|
function call(name, ...)
|
||||||
|
return {type = "call", argv = {...}, name = name, target = _call}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local _template = function(self, ...)
|
||||||
|
require "luci.template".render(self.view)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Create a template render dispatching target.
|
||||||
|
-- @param name Template to be rendered
|
||||||
|
function template(name)
|
||||||
|
return {type = "template", view = name, target = _template}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function _cbi(self, ...)
|
||||||
|
local cbi = require "luci.cbi"
|
||||||
|
local tpl = require "luci.template"
|
||||||
|
local http = require "luci.http"
|
||||||
|
|
||||||
|
local config = self.config or {}
|
||||||
|
local maps = cbi.load(self.model, ...)
|
||||||
|
|
||||||
|
local state = nil
|
||||||
|
|
||||||
|
for i, res in ipairs(maps) do
|
||||||
|
res.flow = config
|
||||||
|
local cstate = res:parse()
|
||||||
|
if cstate and (not state or cstate < state) then
|
||||||
|
state = cstate
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function _resolve_path(path)
|
||||||
|
return type(path) == "table" and build_url(unpack(path)) or path
|
||||||
|
end
|
||||||
|
|
||||||
|
if config.on_valid_to and state and state > 0 and state < 2 then
|
||||||
|
http.redirect(_resolve_path(config.on_valid_to))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if config.on_changed_to and state and state > 1 then
|
||||||
|
http.redirect(_resolve_path(config.on_changed_to))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if config.on_success_to and state and state > 0 then
|
||||||
|
http.redirect(_resolve_path(config.on_success_to))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if config.state_handler then
|
||||||
|
if not config.state_handler(state, maps) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
http.header("X-CBI-State", state or 0)
|
||||||
|
|
||||||
|
if not config.noheader then
|
||||||
|
tpl.render("cbi/header", {state = state})
|
||||||
|
end
|
||||||
|
|
||||||
|
local redirect
|
||||||
|
local messages
|
||||||
|
local applymap = false
|
||||||
|
local pageaction = true
|
||||||
|
local parsechain = { }
|
||||||
|
|
||||||
|
for i, res in ipairs(maps) do
|
||||||
|
if res.apply_needed and res.parsechain then
|
||||||
|
local c
|
||||||
|
for _, c in ipairs(res.parsechain) do
|
||||||
|
parsechain[#parsechain+1] = c
|
||||||
|
end
|
||||||
|
applymap = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if res.redirect then
|
||||||
|
redirect = redirect or res.redirect
|
||||||
|
end
|
||||||
|
|
||||||
|
if res.pageaction == false then
|
||||||
|
pageaction = false
|
||||||
|
end
|
||||||
|
|
||||||
|
if res.message then
|
||||||
|
messages = messages or { }
|
||||||
|
messages[#messages+1] = res.message
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for i, res in ipairs(maps) do
|
||||||
|
res:render({
|
||||||
|
firstmap = (i == 1),
|
||||||
|
applymap = applymap,
|
||||||
|
redirect = redirect,
|
||||||
|
messages = messages,
|
||||||
|
pageaction = pageaction,
|
||||||
|
parsechain = parsechain
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
if not config.nofooter then
|
||||||
|
tpl.render("cbi/footer", {
|
||||||
|
flow = config,
|
||||||
|
pageaction = pageaction,
|
||||||
|
redirect = redirect,
|
||||||
|
state = state,
|
||||||
|
autoapply = config.autoapply
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Create a CBI model dispatching target.
|
||||||
|
-- @param model CBI model to be rendered
|
||||||
|
function cbi(model, config)
|
||||||
|
return {type = "cbi", config = config, model = model, target = _cbi}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function _arcombine(self, ...)
|
||||||
|
local argv = {...}
|
||||||
|
local target = #argv > 0 and self.targets[2] or self.targets[1]
|
||||||
|
setfenv(target.target, self.env)
|
||||||
|
target:target(unpack(argv))
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Create a combined dispatching target for non argv and argv requests.
|
||||||
|
-- @param trg1 Overview Target
|
||||||
|
-- @param trg2 Detail Target
|
||||||
|
function arcombine(trg1, trg2)
|
||||||
|
return {type = "arcombine", env = getfenv(), target = _arcombine, targets = {trg1, trg2}}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function _form(self, ...)
|
||||||
|
local cbi = require "luci.cbi"
|
||||||
|
local tpl = require "luci.template"
|
||||||
|
local http = require "luci.http"
|
||||||
|
|
||||||
|
local maps = luci.cbi.load(self.model, ...)
|
||||||
|
local state = nil
|
||||||
|
|
||||||
|
for i, res in ipairs(maps) do
|
||||||
|
local cstate = res:parse()
|
||||||
|
if cstate and (not state or cstate < state) then
|
||||||
|
state = cstate
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
http.header("X-CBI-State", state or 0)
|
||||||
|
tpl.render("header")
|
||||||
|
for i, res in ipairs(maps) do
|
||||||
|
res:render()
|
||||||
|
end
|
||||||
|
tpl.render("footer")
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Create a CBI form model dispatching target.
|
||||||
|
-- @param model CBI form model tpo be rendered
|
||||||
|
function form(model)
|
||||||
|
return {type = "cbi", model = model, target = _form}
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Access the luci.i18n translate() api.
|
||||||
|
-- @class function
|
||||||
|
-- @name translate
|
||||||
|
-- @param text Text to translate
|
||||||
|
translate = i18n.translate
|
||||||
|
|
||||||
|
--- No-op function used to mark translation entries for menu labels.
|
||||||
|
-- This function does not actually translate the given argument but
|
||||||
|
-- is used by build/i18n-scan.pl to find translatable entries.
|
||||||
|
function _(text)
|
||||||
|
return text
|
||||||
|
end
|
1632
Me_Lua/r13/luci/model/network.lua
Normal file
1632
Me_Lua/r13/luci/model/network.lua
Normal file
File diff suppressed because it is too large
Load Diff
200
Me_Lua/r13/luci/sauth.lua
Normal file
200
Me_Lua/r13/luci/sauth.lua
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
--[[
|
||||||
|
|
||||||
|
Session authentication
|
||||||
|
(c) 2008 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$
|
||||||
|
|
||||||
|
]]--
|
||||||
|
|
||||||
|
--- LuCI session library.
|
||||||
|
module("luci.sauth", package.seeall)
|
||||||
|
require("luci.util")
|
||||||
|
require("luci.sys")
|
||||||
|
require("luci.config")
|
||||||
|
local nixio = require "nixio", require "nixio.util"
|
||||||
|
local fs = require "nixio.fs"
|
||||||
|
|
||||||
|
|
||||||
|
luci.config.sauth = luci.config.sauth or {}
|
||||||
|
sessionpath = luci.config.sauth.sessionpath
|
||||||
|
sessiontime = tonumber(luci.config.sauth.sessiontime) or 15 * 60
|
||||||
|
|
||||||
|
--- Prepare session storage by creating the session directory.
|
||||||
|
function prepare()
|
||||||
|
fs.mkdir(sessionpath, 700)
|
||||||
|
if not sane() then
|
||||||
|
error("Security Exception: Session path is not sane!")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function _read(id)
|
||||||
|
local blob = fs.readfile(sessionpath .. "/" .. id)
|
||||||
|
return blob
|
||||||
|
end
|
||||||
|
|
||||||
|
local function _write(id, data)
|
||||||
|
local tempid = luci.sys.uniqueid(16)
|
||||||
|
local tempfile = sessionpath .. "/" .. tempid
|
||||||
|
local sessfile = sessionpath .. "/" .. id
|
||||||
|
local f = nixio.open(tempfile, "w", 600)
|
||||||
|
f:writeall(data)
|
||||||
|
f:close()
|
||||||
|
fs.rename(tempfile, sessfile)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function _checkid(id)
|
||||||
|
return not not (id and #id == 32 and id:match("^[a-fA-F0-9]+$"))
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Write session data to a session file.
|
||||||
|
-- @param id Session identifier
|
||||||
|
-- @param data Session data table
|
||||||
|
function write(id, data)
|
||||||
|
if not sane() then
|
||||||
|
prepare()
|
||||||
|
end
|
||||||
|
|
||||||
|
if not _checkid(id) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(data) ~= "table" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
data.atime = luci.sys.uptime()
|
||||||
|
|
||||||
|
_write(id, luci.util.get_bytecode(data))
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Read a session and return its content.
|
||||||
|
-- @param id Session identifier
|
||||||
|
-- @return Session data table or nil if the given id is not found
|
||||||
|
function read(id)
|
||||||
|
if not id or #id == 0 then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if not _checkid(id) then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if not sane(sessionpath .. "/" .. id) then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local blob = _read(id)
|
||||||
|
local func = loadstring(blob)
|
||||||
|
setfenv(func, {})
|
||||||
|
|
||||||
|
local sess = func()
|
||||||
|
if type(sess) ~= "table" then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if sess.atime and sess.atime + sessiontime < luci.sys.uptime() then
|
||||||
|
kill(id)
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- refresh atime in session
|
||||||
|
write(id, sess)
|
||||||
|
|
||||||
|
return sess
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check whether Session environment is sane.
|
||||||
|
-- @return Boolean status
|
||||||
|
function sane(file)
|
||||||
|
return luci.sys.process.info("uid")
|
||||||
|
== fs.stat(file or sessionpath, "uid")
|
||||||
|
and fs.stat(file or sessionpath, "modestr")
|
||||||
|
== (file and "rw-------" or "rwx------")
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Kills a session
|
||||||
|
-- @param id Session identifier
|
||||||
|
function kill(id)
|
||||||
|
if not _checkid(id) then
|
||||||
|
else
|
||||||
|
fs.unlink(sessionpath .. "/" .. id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Remove all expired session data files
|
||||||
|
function reap()
|
||||||
|
if sane() then
|
||||||
|
local id
|
||||||
|
for id in nixio.fs.dir(sessionpath) do
|
||||||
|
if _checkid(id) then
|
||||||
|
-- reading the session will kill it if it is expired
|
||||||
|
read(id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get available session data
|
||||||
|
function available()
|
||||||
|
if sane() then
|
||||||
|
local id
|
||||||
|
for id in nixio.fs.dir(sessionpath) do
|
||||||
|
if _checkid(id) then
|
||||||
|
-- reading the session will kill it if it is expired
|
||||||
|
local available = read(id)
|
||||||
|
if available then
|
||||||
|
return available
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function genAuthToken()
|
||||||
|
local id = luci.sys.uniqueid(16)
|
||||||
|
local token = luci.sys.uniqueid(16)
|
||||||
|
write(id, {
|
||||||
|
user="root",
|
||||||
|
token=token,
|
||||||
|
secret=luci.sys.uniqueid(16)
|
||||||
|
})
|
||||||
|
return id, read(id)
|
||||||
|
end
|
||||||
|
|
||||||
|
function noAuthGetToken()
|
||||||
|
local id
|
||||||
|
local data
|
||||||
|
local ret = {}
|
||||||
|
if sessionpath then
|
||||||
|
local ids = nixio.fs.dir(sessionpath)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
if not ids then
|
||||||
|
genAuthToken()
|
||||||
|
end
|
||||||
|
for id in nixio.fs.dir(sessionpath) do
|
||||||
|
if id then
|
||||||
|
read(id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for id in nixio.fs.dir(sessionpath) do
|
||||||
|
if id then
|
||||||
|
ret["sysauth"] = id
|
||||||
|
ret["data"] = read(id)
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
end
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
id, data = genAuthToken()
|
||||||
|
ret["sysauth"] = id
|
||||||
|
ret["data"] = read(id)
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
end
|
103
Me_Lua/r13/meizu/arpmon.lua
Normal file
103
Me_Lua/r13/meizu/arpmon.lua
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
module("meizu.arpmon", package.seeall)
|
||||||
|
--network functions
|
||||||
|
|
||||||
|
local cjson = require "cjson"
|
||||||
|
local lfs = require "lfs"
|
||||||
|
local bfs = require "meizu.bfs"
|
||||||
|
local dbfs = require "meizu.dbfs"
|
||||||
|
local RC = require "meizu.r10config"
|
||||||
|
local sipfs = require "meizu.sipfs"
|
||||||
|
local nwfs = require "meizu.nwfs"
|
||||||
|
|
||||||
|
local lue = require("luci.util").exec
|
||||||
|
|
||||||
|
local bind_router = bfs.bind_router
|
||||||
|
local data_to_json = bfs.data_to_json
|
||||||
|
local exec_cmd_in_sh = bfs.exec_cmd_in_sh
|
||||||
|
local exec_reboot = bfs.exec_reboot
|
||||||
|
local get_device_SN = bfs.get_device_SN
|
||||||
|
local get_device_version = bfs.get_device_version
|
||||||
|
local get_https_data = bfs.get_https_data
|
||||||
|
local rts_get_access_token = bfs.rts_get_access_token
|
||||||
|
local set_passwd = bfs.set_passwd
|
||||||
|
local silent_upgrade = bfs.silent_upgrade
|
||||||
|
local strsplit = bfs.strsplit
|
||||||
|
|
||||||
|
local delete_arp_all_mac = dbfs.delete_arp_all_mac
|
||||||
|
local get_dev_nick_name = dbfs.get_dev_nick_name
|
||||||
|
local init_arp_table = dbfs.init_arp_table
|
||||||
|
local insert_arp_macip = dbfs.insert_arp_macip
|
||||||
|
local fetch_all_arp = dbfs.fetch_all_arp
|
||||||
|
local update_arp = dbfs.update_arp
|
||||||
|
|
||||||
|
local getAllWifiConnetDeviceDict = nwfs.getAllWifiConnetDeviceDict
|
||||||
|
|
||||||
|
function new_device_notify()
|
||||||
|
|
||||||
|
init_arp_table()
|
||||||
|
local ret = {}
|
||||||
|
local cmd = [[cat /proc/net/arp |grep br-lan|awk '{print $1","$4}']]
|
||||||
|
local ipmacs = {}
|
||||||
|
local devs = lue(cmd)
|
||||||
|
if devs ~= "" then
|
||||||
|
ipmacs = strsplit(devs, '\n')
|
||||||
|
end
|
||||||
|
ipmacs[#ipmacs] = nil
|
||||||
|
local new_devs = {}
|
||||||
|
local allarp = fetch_all_arp()
|
||||||
|
local wifiDeviceDict = getAllWifiConnetDeviceDict()
|
||||||
|
if nil == allarp then
|
||||||
|
new_devs = ipmacs
|
||||||
|
else
|
||||||
|
for k, v in pairs(ipmacs) do
|
||||||
|
local ipmac = strsplit(v, ',')
|
||||||
|
local ip = ipmac[1]
|
||||||
|
local mac = ipmac[2]
|
||||||
|
mac = string.upper(mac)
|
||||||
|
local isnew = true
|
||||||
|
local wf = 0
|
||||||
|
for index, value in pairs(allarp) do
|
||||||
|
if mac == string.upper(value["mac"]) then
|
||||||
|
isnew = false
|
||||||
|
wf = value["wifi"]
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if isnew == true then
|
||||||
|
table.insert(new_devs,v)
|
||||||
|
else
|
||||||
|
local wdd = wifiDeviceDict[mac]
|
||||||
|
if nil ~= wdd then
|
||||||
|
wf = wdd.wifiIndex
|
||||||
|
end
|
||||||
|
update_arp(mac, ip, wf)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for k, v in pairs(new_devs) do
|
||||||
|
local ipmac = strsplit(v, ',')
|
||||||
|
local ip = ipmac[1]
|
||||||
|
local mac = string.upper(ipmac[2])
|
||||||
|
if ip ~= "" then
|
||||||
|
local wifi = 0
|
||||||
|
local wdd = wifiDeviceDict[mac]
|
||||||
|
if nil ~= wdd then
|
||||||
|
wifi = wdd.wifiIndex
|
||||||
|
end
|
||||||
|
if "00:00:00:00:00:00" ~= mac then
|
||||||
|
insert_arp_macip(mac, ip, wifi)
|
||||||
|
end
|
||||||
|
local logtype = 1
|
||||||
|
ret["mac_address"] = mac
|
||||||
|
local nickname = get_dev_nick_name(mac)
|
||||||
|
if nickname and nickname ~= "" then
|
||||||
|
ret["name"] = nickname
|
||||||
|
else
|
||||||
|
ret["name"] = ip
|
||||||
|
end
|
||||||
|
local res, code, headers, status = sipfs.upload_router_log(data_to_json(ret), logtype)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
luci.http.write_json(ret)
|
||||||
|
end
|
||||||
|
|
370
Me_Lua/r13/meizu/bfs.lua
Normal file
370
Me_Lua/r13/meizu/bfs.lua
Normal file
@ -0,0 +1,370 @@
|
|||||||
|
module("meizu.bfs", package.seeall)
|
||||||
|
--API base functions
|
||||||
|
|
||||||
|
local cjson = require "cjson"
|
||||||
|
local dbfs = require "meizu.dbfs"
|
||||||
|
|
||||||
|
function cal_str_md5(str)
|
||||||
|
local md5 = ""
|
||||||
|
local cmd = [[/bin/echo -n ']]..str
|
||||||
|
cmd = cmd..[['|/usr/bin/md5sum|/usr/bin/cut -d" " -f1]]
|
||||||
|
local fd = io.popen(cmd)
|
||||||
|
local ln = fd:read("*l")
|
||||||
|
if ln ~= nil then
|
||||||
|
md5 = ln
|
||||||
|
end
|
||||||
|
fd:close()
|
||||||
|
return md5
|
||||||
|
end
|
||||||
|
|
||||||
|
function strsplit(str, delim, maxNb)
|
||||||
|
local result = {}
|
||||||
|
if delim == nil then
|
||||||
|
delim = '\n'
|
||||||
|
end
|
||||||
|
if string.find(str, delim) == nil then
|
||||||
|
return { str }
|
||||||
|
end
|
||||||
|
if maxNb == nil or maxNb < 1 then
|
||||||
|
maxNb = 0
|
||||||
|
end
|
||||||
|
local pat = "(.-)" .. delim .. "()"
|
||||||
|
local nb = 0
|
||||||
|
local lastPos
|
||||||
|
for part, pos in string.gfind(str, pat) do
|
||||||
|
nb = nb + 1
|
||||||
|
result[nb] = part
|
||||||
|
lastPos = pos
|
||||||
|
if nb == maxNb then break end
|
||||||
|
end
|
||||||
|
if nb ~= maxNb then
|
||||||
|
result[nb + 1] = string.sub(str, lastPos)
|
||||||
|
end
|
||||||
|
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
function data_to_json(x)
|
||||||
|
local buf = ""
|
||||||
|
if x == nil then
|
||||||
|
return ""
|
||||||
|
elseif x == "" then
|
||||||
|
return '""'
|
||||||
|
elseif type(x) == "table" then
|
||||||
|
local k, v
|
||||||
|
if type(next(x)) == "number" then
|
||||||
|
buf = buf.."[ "
|
||||||
|
for k, v in ipairs(x) do
|
||||||
|
buf = buf..data_to_json(v)
|
||||||
|
if next(x, k) then
|
||||||
|
buf = buf..", "
|
||||||
|
end
|
||||||
|
end
|
||||||
|
buf = buf.." ]"
|
||||||
|
else
|
||||||
|
buf = buf.."{ "
|
||||||
|
for k, v in pairs(x) do
|
||||||
|
buf = buf..string.format("%q: " % k)
|
||||||
|
buf = buf..data_to_json(v)
|
||||||
|
if next(x, k) then
|
||||||
|
buf = buf..", "
|
||||||
|
end
|
||||||
|
end
|
||||||
|
buf = buf.." }"
|
||||||
|
end
|
||||||
|
elseif type(x) == "number" or type(x) == "boolean" then
|
||||||
|
if (x ~= x) then
|
||||||
|
buf = buf.."Number.NaN"
|
||||||
|
else
|
||||||
|
buf = buf..tostring(x)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
buf = buf..string.format('"%s"' % tostring(x):gsub('[%z\1-\31]', function(c) return '\\u%04x' % c:byte(1) end))
|
||||||
|
end
|
||||||
|
return buf
|
||||||
|
end
|
||||||
|
|
||||||
|
function exec_cmd_in_sh(command)
|
||||||
|
local nio = require("nixio")
|
||||||
|
require "MZLog".log(3, command)
|
||||||
|
local pid = nio.fork()
|
||||||
|
if pid > 0 then
|
||||||
|
return
|
||||||
|
elseif pid == 0 then
|
||||||
|
nio.chdir("/")
|
||||||
|
local null = nio.open("/dev/null", "w+")
|
||||||
|
if null then
|
||||||
|
nio.dup(null, nio.stderr)
|
||||||
|
nio.dup(null, nio.stdout)
|
||||||
|
nio.dup(null, nio.stdin)
|
||||||
|
if null:fileno() > 2 then
|
||||||
|
null:close()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
nio.exec("/bin/sh", "-c", command)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--local get_https_data = function(url, data) return require("ssl.https").request(url, data) end
|
||||||
|
--return res, code, headers, status
|
||||||
|
function get_https_data(url, data)
|
||||||
|
if data ~= nil then
|
||||||
|
return require("ssl.https").request(url, data)
|
||||||
|
else
|
||||||
|
return require("ssl.https").request(url)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function decodeURI(s)
|
||||||
|
local s = string.gsub(s, '%%(%x%x)', function(h) return string.char(tonumber(h, 16)) end)
|
||||||
|
return s
|
||||||
|
end
|
||||||
|
|
||||||
|
function encodeURI(s)
|
||||||
|
local s = string.gsub(s, "([^%w%.%- ])", function(c) return string.format("%%%02X", string.byte(c)) end)
|
||||||
|
return string.gsub(s, " ", "+")
|
||||||
|
end
|
||||||
|
|
||||||
|
function b64enc(data)
|
||||||
|
local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
||||||
|
return ((data:gsub('.', function(x)
|
||||||
|
local r,b='',x:byte()
|
||||||
|
for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end
|
||||||
|
return r;
|
||||||
|
end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x)
|
||||||
|
if (#x < 6) then return '' end
|
||||||
|
local c=0
|
||||||
|
for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end
|
||||||
|
return b:sub(c+1,c+1)
|
||||||
|
end)..({ '', '==', '=' })[#data%3+1])
|
||||||
|
end
|
||||||
|
|
||||||
|
function b64dec(data)
|
||||||
|
local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
||||||
|
data = string.gsub(data, '[^'..b..'=]', '')
|
||||||
|
return (data:gsub('.', function(x)
|
||||||
|
if (x == '=') then return '' end
|
||||||
|
local r,f='',(b:find(x)-1)
|
||||||
|
for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end
|
||||||
|
return r;
|
||||||
|
end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x)
|
||||||
|
if (#x ~= 8) then return '' end
|
||||||
|
local c=0
|
||||||
|
for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(8-i) or 0) end
|
||||||
|
return string.char(c)
|
||||||
|
end))
|
||||||
|
end
|
||||||
|
|
||||||
|
function exec_reboot()
|
||||||
|
--luci.sys.reboot()
|
||||||
|
exec_cmd_in_sh("reboot")
|
||||||
|
end
|
||||||
|
|
||||||
|
function factory_reset()
|
||||||
|
--exec_cmd_in_sh("killall dropbear uhttpd; sleep 1; mtd erase nvram; mtd -r erase rootfs_data")
|
||||||
|
local result = {}
|
||||||
|
result["result"] = true
|
||||||
|
luci.http.write_json(result)
|
||||||
|
exec_cmd_in_sh("killall dropbear uhttpd; sleep 1; /usr/bin/router_reset;/sbin/reboot -f")
|
||||||
|
end
|
||||||
|
|
||||||
|
function set_passwd()
|
||||||
|
local result = {}
|
||||||
|
local p1 = luci.http.formvalue("pwd1")
|
||||||
|
local p2 = luci.http.formvalue("pwd2")
|
||||||
|
local stat = nil
|
||||||
|
if p1 ~= nil and luci.sys.user.checkpasswd("root", p1) then
|
||||||
|
if p2 ~= nil then
|
||||||
|
stat = luci.sys.user.setpasswd("root", p2)
|
||||||
|
result["result"] = true
|
||||||
|
luci.http.write_json(result)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
result["result"] = false
|
||||||
|
luci.http.write_json(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
function rts_get_access_token()
|
||||||
|
local dbfs = require "meizu.dbfs"
|
||||||
|
dbfs.init_access_token_table()
|
||||||
|
local dbdata = dbfs.fetch_access_token()
|
||||||
|
local token
|
||||||
|
if #dbdata > 0 then
|
||||||
|
for _, data in ipairs(dbdata) do
|
||||||
|
local tokenFromdb = data.token
|
||||||
|
local expireTimeFromdb = data.expireTime
|
||||||
|
local nowTime = os.time()
|
||||||
|
if expireTimeFromdb < nowTime then
|
||||||
|
require "MZLog".log(3, "expireTime expire")
|
||||||
|
local httpsData = https_get_access_token()
|
||||||
|
token = httpsData.access_token
|
||||||
|
dbfs.update_access_token(tokenFromdb, token, httpsData.expires_in + os.time() - 10)
|
||||||
|
else
|
||||||
|
require "MZLog".log(3, "token from db")
|
||||||
|
token = tokenFromdb
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local httpsData = https_get_access_token()
|
||||||
|
token = httpsData.access_token
|
||||||
|
require "MZLog".log(3, "token from https")
|
||||||
|
dbfs.add_access_token(token, httpsData.expires_in + os.time() - 10)
|
||||||
|
end
|
||||||
|
return token
|
||||||
|
end
|
||||||
|
|
||||||
|
function https_get_access_token()
|
||||||
|
local url = "https://api.meizu.com/oauth/token?scope=router_trust&device="
|
||||||
|
local suffix = "&password=&grant_type=device_only&client_id=gkzyJzq4RPoaov3BamqsJgg&client_secret=yh9bdKurxxotCjrEvJOiumk2mrzhcyej"
|
||||||
|
local SN = get_device_SN()
|
||||||
|
url = url..SN..suffix
|
||||||
|
local res, code, headers, status = get_https_data(url)
|
||||||
|
local data = cjson.decode(res)
|
||||||
|
return data
|
||||||
|
end
|
||||||
|
|
||||||
|
function get_user_access_token()
|
||||||
|
local res, code, headers, status
|
||||||
|
local url = 'https://api.meizu.com/oauth/token?grant_type=password&client_id=gkzyJzq4RPoaov3BamqsJgg&client_secret=yh9bdKurxxotCjrEvJOiumk2mrzhcyej&username=appadmin@flyme.cn&password=appadmin111&scope=router_trust'
|
||||||
|
local res, code, headers, status = get_https_data(url)
|
||||||
|
local data = cjson.decode(res)
|
||||||
|
return data.access_token
|
||||||
|
end
|
||||||
|
|
||||||
|
function init_bind_router_body(access_token)
|
||||||
|
local body = "access_token="
|
||||||
|
local uat = luci.http.formvalue("uat")
|
||||||
|
body = body..access_token
|
||||||
|
body = body.."&user_access_token="
|
||||||
|
body = body..uat
|
||||||
|
return body
|
||||||
|
end
|
||||||
|
|
||||||
|
function bind_router()
|
||||||
|
local url = "https://router.meizu.com/oauth/router/bindRouter"
|
||||||
|
local access_token = rts_get_access_token()
|
||||||
|
local body = init_bind_router_body(access_token)
|
||||||
|
local https = require("ssl.https")
|
||||||
|
local res, code, headers, status = https.request(url, body)
|
||||||
|
if code == 401 then
|
||||||
|
delete_access_token()
|
||||||
|
access_token = rts_get_access_token()
|
||||||
|
body = init_bind_router_body(access_token)
|
||||||
|
res, code, headers, status = https.request(url, body)
|
||||||
|
end
|
||||||
|
luci.http.write(res)
|
||||||
|
end
|
||||||
|
|
||||||
|
function unbind_router()
|
||||||
|
local url = 'https://router.meizu.com/oauth/user/unbind?access_token='
|
||||||
|
local https = require("ssl.https")
|
||||||
|
local uat = luci.http.formvalue("uat")
|
||||||
|
url = url..uat
|
||||||
|
url = url..'&device='..get_device_SN()
|
||||||
|
local res, code, headers, status = https.request(url)
|
||||||
|
luci.http.write(res)
|
||||||
|
end
|
||||||
|
|
||||||
|
function get_device_SN()
|
||||||
|
local sn = "R13WZLCZ7AC1001"
|
||||||
|
local fd = io.popen("nvram get sn")
|
||||||
|
if fd then
|
||||||
|
local ln = fd:read("*l")
|
||||||
|
if ln ~= nil then
|
||||||
|
sn = ln
|
||||||
|
end
|
||||||
|
fd:close()
|
||||||
|
end
|
||||||
|
return sn
|
||||||
|
end
|
||||||
|
|
||||||
|
function get_device_version()
|
||||||
|
local device_version = "1.0.0"
|
||||||
|
--[[
|
||||||
|
[local pcall, dofile = pcall, dofile
|
||||||
|
[if pcall(dofile, "/etc/openwrt_release") then
|
||||||
|
[ if DISTRIB_RELEASE ~= nil then
|
||||||
|
[ device_version = DISTRIB_RELEASE
|
||||||
|
[ end
|
||||||
|
[end
|
||||||
|
]]
|
||||||
|
local lu = require("luci.util")
|
||||||
|
local cmd = [[cat /etc/openwrt_version|awk '{printf $1}']]
|
||||||
|
local v = lu.exec(cmd)
|
||||||
|
if v ~= nil then
|
||||||
|
device_version = v
|
||||||
|
end
|
||||||
|
return device_version
|
||||||
|
end
|
||||||
|
|
||||||
|
function silent_upgrade()
|
||||||
|
local fd = nil
|
||||||
|
local image = "/tmp/firmware.img"
|
||||||
|
local touchcmd = "touch "..image
|
||||||
|
exec_cmd_in_sh(touchcmd)
|
||||||
|
local function image_supported()
|
||||||
|
return ( 0 == os.execute(
|
||||||
|
". /lib/functions.sh; " ..
|
||||||
|
"include /lib/upgrade; " ..
|
||||||
|
"platform_check_image %q >/dev/null"
|
||||||
|
% image
|
||||||
|
))
|
||||||
|
end
|
||||||
|
if luci.http.formvalue("act") == "update" then
|
||||||
|
luci.http.write("act == update")
|
||||||
|
end
|
||||||
|
if image_supported() then
|
||||||
|
luci.http.write("updating")
|
||||||
|
exec_cmd_in_sh("killall dropbear uhttpd; sleep 1; /sbin/sysupgrade -v %q" %{ image })
|
||||||
|
luci.http.write("update finished!")
|
||||||
|
else
|
||||||
|
luci.http.write("image_supported check failed!")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function table_merge(t1, t2)
|
||||||
|
if (type(t1) == "table") and (type(t2) == "table") then
|
||||||
|
for k, v in pairs(t2) do
|
||||||
|
if (type(v) == "table") and (type(t1[k] or false) == "table") then
|
||||||
|
table_merge(t1[k], t2[k])
|
||||||
|
else
|
||||||
|
t1[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return t1
|
||||||
|
end
|
||||||
|
|
||||||
|
function sysinfo()
|
||||||
|
local LuciNetwork = require("luci.model.network").init()
|
||||||
|
local lanNetwork = LuciNetwork:get_network("lan")
|
||||||
|
local wanNetwork = LuciNetwork:get_network("wan")
|
||||||
|
local wanType = "dhcp"
|
||||||
|
if wanNetwork and lanNetwork then
|
||||||
|
local apc = lanNetwork:get_option_value("apclient")
|
||||||
|
if nil ~= apc and "" ~= apc then
|
||||||
|
wanType = "apclient"
|
||||||
|
else
|
||||||
|
wanType = wanNetwork:proto()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local lue = require("luci.util").exec
|
||||||
|
local ret = {}
|
||||||
|
ret["wanType"] = wanType
|
||||||
|
ret["romversion"] = get_device_version()
|
||||||
|
ret["SN"] = get_device_SN()
|
||||||
|
ret["deviceModel"] = "R13"
|
||||||
|
ret["routername"] = "mzrt"..get_device_SN()
|
||||||
|
local ssid1, ssid2 = require "meizu.nwfs".get_wifi_ssids()
|
||||||
|
ret["ssid1"] = ssid2
|
||||||
|
ret["ssid2"] = ssid1
|
||||||
|
local cmd = [[df /mnt|grep -q sda;echo -n $?]]
|
||||||
|
ret["diskstatus"] = lue(cmd)
|
||||||
|
cmd = [[echo -n $(ifconfig br-lan |grep HWaddr|sed 's/.*HWaddr //' | sed 's/\ .*//')]]
|
||||||
|
ret["brlanmac"] = lue(cmd)
|
||||||
|
cmd = [[echo -n $(ifconfig br-lan |grep 'inet addr'|awk -F':' '{print $2}' |awk '{printf $1}')]]
|
||||||
|
ret["brlanip"] = lue(cmd)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
5
Me_Lua/r13/meizu/build.sh
Normal file
5
Me_Lua/r13/meizu/build.sh
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
/etc/init.d/uhttpd stop
|
||||||
|
rm -rf /tmp/luci-indexcache /tmp/luci-modulecache
|
||||||
|
rm -rf /tmp/luci-sessions
|
||||||
|
/etc/init.d/uhttpd start
|
410
Me_Lua/r13/meizu/dbfs.lua
Normal file
410
Me_Lua/r13/meizu/dbfs.lua
Normal file
@ -0,0 +1,410 @@
|
|||||||
|
module("meizu.dbfs", package.seeall)
|
||||||
|
|
||||||
|
local sqlite3 = require("lsqlite3")
|
||||||
|
local r13db = "/etc/r13db"
|
||||||
|
|
||||||
|
function database_busy()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function updateDeviceNickname(mac, nickname)
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("update maclist set devicename = '%s' where mac = '%s'", nickname, mac)
|
||||||
|
db:exec(sqlStr)
|
||||||
|
return db:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function get_dev_nick_name(mac)
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("select devicename, orgname from maclist where mac like '%s'", mac)
|
||||||
|
local nickname = ""
|
||||||
|
for row in db:rows(sqlStr) do
|
||||||
|
if row[1] ~= "" then
|
||||||
|
nickname = row[1]
|
||||||
|
else
|
||||||
|
if row[2] ~= "" then
|
||||||
|
nickname = row[2]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
db:close()
|
||||||
|
return nickname
|
||||||
|
end
|
||||||
|
|
||||||
|
function fetchDenyDeviceInfo(mac)
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("select * from maclist where mac = '%s'", mac)
|
||||||
|
local result = {}
|
||||||
|
for row in db:rows(sqlStr) do
|
||||||
|
if row then
|
||||||
|
table.insert(result,{
|
||||||
|
["mac"] = row[1],
|
||||||
|
["orgname"] = row[2],
|
||||||
|
["devicename"] = row[3],
|
||||||
|
["ip"] = row[4]
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
db:close()
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
function change_maclist_table()
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("ALTER TABLE maclist ADD COLUMN ip varchar(100)")
|
||||||
|
db:exec(sqlStr)
|
||||||
|
return db:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function fetchAllDeviceInfo()
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("select * from maclist")
|
||||||
|
local result = {}
|
||||||
|
for row in db:rows(sqlStr) do
|
||||||
|
if row then
|
||||||
|
table.insert(result,{
|
||||||
|
["mac"] = row[1],
|
||||||
|
["orgname"] = row[2],
|
||||||
|
["devicename"] = row[3]
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
db:close()
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
function updateDeviceOrgname(mac, orgname)
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("update maclist set orgname = '%s' where mac = '%s'", orgname, mac)
|
||||||
|
db:exec(sqlStr)
|
||||||
|
return db:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function saveDeviceInfo(mac, orgname, devicename, deviceip)
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local fetch = string.format("select * from maclist where mac = '%s'", mac)
|
||||||
|
local exist = false
|
||||||
|
for row in db:rows(fetch) do
|
||||||
|
if row then
|
||||||
|
exist = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local sqlStr
|
||||||
|
if not exist then
|
||||||
|
sqlStr = string.format("insert into maclist values('%s','%s','%s', '%s')", mac, orgname, devicename, deviceip)
|
||||||
|
else
|
||||||
|
sqlStr = string.format("update maclist set mac = '%s', orgname = '%s', devicemame = '%s', ip = '%s' where mac = '%s'", mac, orgname, devicename, deviceip, mac)
|
||||||
|
end
|
||||||
|
db:exec(sqlStr)
|
||||||
|
return db:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function init_arp_table()
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("create table if not exists arp(mac varchar(18), ip varchar(16), wifi integer)")
|
||||||
|
db:exec(sqlStr)
|
||||||
|
return db:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function fetch_all_arp()
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("select * from arp")
|
||||||
|
local result = {}
|
||||||
|
for row in db:rows(sqlStr) do
|
||||||
|
if row then
|
||||||
|
table.insert(result,{
|
||||||
|
["mac"] = row[1],
|
||||||
|
["ip"] = row[2],
|
||||||
|
["wifi"] = row[3]
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
db:close()
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
function fetch_arp(mac)
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("select * from arp where mac = '%s' limit 1", mac)
|
||||||
|
local result = {}
|
||||||
|
for row in db:rows(sqlStr) do
|
||||||
|
if row then
|
||||||
|
table.insert(result,{
|
||||||
|
["mac"] = row[1],
|
||||||
|
["ip"] = row[2],
|
||||||
|
["wifi"] = row[3]
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
db:close()
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
function insert_arp_macip(mac, ip, wifi)
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("delete from ")
|
||||||
|
sqlStr = string.format("insert into arp values('%s', '%s', %d)", mac, ip, wifi)
|
||||||
|
db:exec(sqlStr)
|
||||||
|
return db:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function delete_arp_all_mac()
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("delete from arp")
|
||||||
|
db:exec(sqlStr)
|
||||||
|
return db:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function update_arp(mac, ip, wifi)
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("update arp set ip = '%s', wifi = %d where mac = '%s'", ip, wifi, mac)
|
||||||
|
db:exec(sqlStr)
|
||||||
|
return db:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function init_access_token_table()
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("create table if not exists accessTokenTable(token varchar(100), expireTime bigint)")
|
||||||
|
db:exec(sqlStr)
|
||||||
|
return db:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function add_access_token(token, expireTime)
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("insert into accessTokenTable values('%s', %d)", token, expireTime)
|
||||||
|
db:exec(sqlStr)
|
||||||
|
return db:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function fetch_access_token()
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("select * from accessTokenTable")
|
||||||
|
local result = {}
|
||||||
|
for row in db:rows(sqlStr) do
|
||||||
|
if row then
|
||||||
|
table.insert(result,{
|
||||||
|
["token"] = row[1],
|
||||||
|
["expireTime"] = row[2]
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
db:close()
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
function update_access_token(oldToken, newToken, expireTime)
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("update accessTokenTable set token = '%s', expireTime = %d where token = '%s'", newToken, expireTime, oldToken)
|
||||||
|
db:exec(sqlStr)
|
||||||
|
return db:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function delete_access_token()
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("delete from accessTokenTable")
|
||||||
|
db:exec(sqlStr)
|
||||||
|
return db:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function init_deny_mac_table()
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("create table if not exists denymac(mac varchar(50))")
|
||||||
|
db:exec(sqlStr)
|
||||||
|
return db:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function add_deny_mac(mac)
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("insert into denymac values('%s')", mac)
|
||||||
|
db:exec(sqlStr)
|
||||||
|
return db:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function fetch_all_deny_mac()
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("select * from denymac")
|
||||||
|
local result = {}
|
||||||
|
for row in db:rows(sqlStr) do
|
||||||
|
if row then
|
||||||
|
table.insert(result,{
|
||||||
|
["mac"] = row[1]
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
db:close()
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
function delete_deny_mac(mac)
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("delete from denymac where mac = '%s'", mac)
|
||||||
|
db:exec(sqlStr)
|
||||||
|
return db:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function init_ssid_table()
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("create table if not exists ssid(ssid24 varchar(50), ssid5 varchar(50))")
|
||||||
|
db:exec(sqlStr)
|
||||||
|
return db:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function add_ssid(ssid24, ssid5)
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("insert into ssid values('%s', '%s')", ssid24, ssid5)
|
||||||
|
db:exec(sqlStr)
|
||||||
|
return db:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function fetch_ssid()
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("select ssid24,ssid5 from ssid limit 1")
|
||||||
|
local result = {}
|
||||||
|
for row in db:rows(sqlStr) do
|
||||||
|
if row then
|
||||||
|
table.insert(result,{
|
||||||
|
["ssid24"] = row[1],
|
||||||
|
["ssid5"] = row[2]
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
db:close()
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
function update_ssid(ssid24, ssid5)
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("update ssid set ssid24 = '%s', ssid5 = '%s'", ssid24, ssid5)
|
||||||
|
db:exec(sqlStr)
|
||||||
|
return db:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function initBluetoothTable()
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("create table if not exists blemeshtable(id varchar(100), mac varchar(100), key varchar(100), name varchar(100), deviceType varchar(100), len varchar(100))")
|
||||||
|
db:exec(sqlStr)
|
||||||
|
return db:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function addBluetoothDevice(id, mac, key, name, deviceType, len)
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("insert into blemeshtable values('%s', '%s', '%s', '%s', '%s', '%s')", id, mac, key, name, deviceType, len)
|
||||||
|
db:busy_handler(database_busy)
|
||||||
|
db:exec(sqlStr)
|
||||||
|
return db:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function fetchAllBluetoothDevice()
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("select * from blemeshtable")
|
||||||
|
db:busy_handler(database_busy)
|
||||||
|
local result = {}
|
||||||
|
for row in db:rows(sqlStr) do
|
||||||
|
if row then
|
||||||
|
table.insert(result,{
|
||||||
|
["mac"] = row[2],
|
||||||
|
["deviceType"] = row[5]
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
db:close()
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
function deleteBluetoothDevice(mac)
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("delete from blemeshtable where mac = '%s'", mac)
|
||||||
|
db:busy_handler(database_busy)
|
||||||
|
db:exec(sqlStr)
|
||||||
|
return db:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function updateBluetoothDevice(id, key, name, len, mac)
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("update blemeshtable set id = '%s', key = '%s', name = '%s', len = '%s' where mac = '%s'", id, key, name, len, mac)
|
||||||
|
db:busy_handler(database_busy)
|
||||||
|
db:exec(sqlStr)
|
||||||
|
return db:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function fetchBluetoothDevice(mac)
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("select * from blemeshtable where mac = '%s'", mac)
|
||||||
|
db:busy_handler(database_busy)
|
||||||
|
local result = {}
|
||||||
|
for row in db:rows(sqlStr) do
|
||||||
|
if row then
|
||||||
|
table.insert(result,{
|
||||||
|
["id"] = row[1],
|
||||||
|
["mac"] = row[2],
|
||||||
|
["deviceType"] = row[5],
|
||||||
|
["name"] = row[4]
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
db:close()
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
function fetchBluetoothDeviceKey()
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("select * from blemeshtable where key != ''")
|
||||||
|
db:busy_handler(database_busy)
|
||||||
|
local result = {}
|
||||||
|
for row in db:rows(sqlStr) do
|
||||||
|
if row then
|
||||||
|
table.insert(result,{
|
||||||
|
["mac"] = row[2],
|
||||||
|
["key"] = row[3]
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
db:close()
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
function getBluetoothDevice(id)
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("select * from blemeshtable where id = '%s'", id)
|
||||||
|
db:busy_handler(database_busy)
|
||||||
|
local result = ""
|
||||||
|
for row in db:rows(sqlStr) do
|
||||||
|
if row then
|
||||||
|
result = row[2]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
db:close()
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
function fetchAllBleMeshDevice()
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("select * from blemeshtable where id !=''")
|
||||||
|
db:busy_handler(database_busy)
|
||||||
|
local result = {}
|
||||||
|
for row in db:rows(sqlStr) do
|
||||||
|
if row then
|
||||||
|
table.insert(result,{
|
||||||
|
["mac"] = row[2],
|
||||||
|
["deviceType"] = row[5],
|
||||||
|
["name"] = row[4]
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
db:close()
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
function getBleDeviceNameLength(id)
|
||||||
|
local db = sqlite3.open(r13db)
|
||||||
|
local sqlStr = string.format("select * from blemeshtable where id = '%s'", id)
|
||||||
|
db:busy_handler(database_busy)
|
||||||
|
local result = ""
|
||||||
|
for row in db:rows(sqlStr) do
|
||||||
|
if row then
|
||||||
|
result = row[6]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
db:close()
|
||||||
|
return result
|
||||||
|
end
|
2804
Me_Lua/r13/meizu/nwfs.lua
Normal file
2804
Me_Lua/r13/meizu/nwfs.lua
Normal file
File diff suppressed because it is too large
Load Diff
3
Me_Lua/r13/meizu/r10config.lua
Normal file
3
Me_Lua/r13/meizu/r10config.lua
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
upgradeFlagFile = "/tmp/upgradeFlagFile"
|
||||||
|
upgradeLOCK = "/bin/touch "..upgradeFlagFile
|
||||||
|
upgradeUNLOCK = "/bin/rm "..upgradeFlagFile
|
690
Me_Lua/r13/meizu/sipfs.lua
Normal file
690
Me_Lua/r13/meizu/sipfs.lua
Normal file
@ -0,0 +1,690 @@
|
|||||||
|
module("meizu.sipfs", package.seeall)
|
||||||
|
--sip functions
|
||||||
|
|
||||||
|
local bfs = require "meizu.bfs"
|
||||||
|
local cjson = require "cjson"
|
||||||
|
local nwfs = require "meizu.nwfs"
|
||||||
|
local RC = require "meizu.r10config"
|
||||||
|
local sipfs = require "meizu.sipfs"
|
||||||
|
local upgdfs = require "meizu.upgdfs"
|
||||||
|
|
||||||
|
local b64dec = bfs.b64dec
|
||||||
|
local bind_router = bfs.bind_router
|
||||||
|
local data_to_json = bfs.data_to_json
|
||||||
|
local exec_cmd_in_sh = bfs.exec_cmd_in_sh
|
||||||
|
local exec_reboot = bfs.exec_reboot
|
||||||
|
local get_device_SN = bfs.get_device_SN
|
||||||
|
local get_device_version = bfs.get_device_version
|
||||||
|
local get_https_data = bfs.get_https_data
|
||||||
|
local factory_reset = bfs.factory_reset
|
||||||
|
local rts_get_access_token = bfs.rts_get_access_token
|
||||||
|
local set_passwd = bfs.set_passwd
|
||||||
|
local silent_upgrade = bfs.silent_upgrade
|
||||||
|
|
||||||
|
local real_time_net_speed = nwfs.real_time_net_speed
|
||||||
|
local set_device_name = nwfs.set_device_name
|
||||||
|
local set_wan_switch = nwfs.set_wan_switch
|
||||||
|
local wifi_settings = nwfs.wifi_settings
|
||||||
|
local ww_get_connect_device_list = nwfs.ww_get_connect_device_list
|
||||||
|
local ww_get_device_details = nwfs.ww_get_device_details
|
||||||
|
local ww_get_wifi_settings = nwfs.ww_get_wifi_settings
|
||||||
|
local ww_get_wireless_channel = nwfs.ww_get_wireless_channel
|
||||||
|
local ww_set_wireless_channel = nwfs.ww_set_wireless_channel
|
||||||
|
|
||||||
|
local ww_scan_ble_switch = nwfs.ww_scan_ble_switch
|
||||||
|
local ww_add_ble_mesh_device = nwfs.ww_add_ble_mesh_device
|
||||||
|
local ww_get_ble_device_list = nwfs.ww_get_ble_device_list
|
||||||
|
local ww_get_ble_device_status = nwfs.ww_get_ble_device_status
|
||||||
|
local ww_set_mesh_device_attr = nwfs.ww_set_mesh_device_attr
|
||||||
|
local ww_get_mesh_device_list = nwfs.ww_get_mesh_device_list
|
||||||
|
local ww_reboot_mesh_device = nwfs.ww_reboot_mesh_device
|
||||||
|
local ww_remove_ble_from_mesh = nwfs.ww_remove_ble_from_mesh
|
||||||
|
local ww_unmesh_all_device = nwfs.ww_unmesh_all_device
|
||||||
|
local ww_set_mesh_device_timer = nwfs.ww_set_mesh_device_timer
|
||||||
|
local ww_del_mesh_device_timer = nwfs.ww_del_mesh_device_timer
|
||||||
|
|
||||||
|
local check_upgrade = upgdfs.check_upgrade
|
||||||
|
local do_upgrade = upgdfs.do_upgrade
|
||||||
|
local local_upgrade = upgdfs.local_upgrade
|
||||||
|
|
||||||
|
local table_merge = bfs.table_merge
|
||||||
|
|
||||||
|
function sip_get_parameters(commandId)
|
||||||
|
local url = "https://router.meizu.com/oauth/router/command/routerRequest?"
|
||||||
|
local https = require("ssl.https")
|
||||||
|
local access_token = rts_get_access_token()
|
||||||
|
local newurl = url.."access_token="..access_token
|
||||||
|
newurl = newurl.."&commandId="..commandId
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, url)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
local res, code, headers, status = https.request(newurl)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, code)
|
||||||
|
require "MZLog".log(3, status)
|
||||||
|
require "MZLog".log(3, res)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
if code == 401 then
|
||||||
|
delete_access_token()
|
||||||
|
access_token = rts_get_access_token()
|
||||||
|
local newurl = url.."access_token="..access_token
|
||||||
|
newurl = newurl.."&commandId="..commandId
|
||||||
|
res, code, headers, status = https.request(newurl)
|
||||||
|
end
|
||||||
|
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
|
function sip_response_uploader(cmd, commandId, data, finishstatus)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, data)
|
||||||
|
if data == nil or data == "" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
local url="https://router.meizu.com/oauth/router/command/updateResponse"
|
||||||
|
local https = require("ssl.https")
|
||||||
|
local timemini = os.date("%s")
|
||||||
|
local access_token = rts_get_access_token()
|
||||||
|
local pd = init_update_resp_pd(access_token, commandId, data, finishstatus, timemini)
|
||||||
|
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, url)
|
||||||
|
require "MZLog".log(3, pd)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
local res, code, headers, status = https.request(url, pd)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, code)
|
||||||
|
require "MZLog".log(3, status)
|
||||||
|
require "MZLog".log(3, res)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
if code == 401 then
|
||||||
|
delete_access_token()
|
||||||
|
access_token = rts_get_access_token()
|
||||||
|
pd = init_update_resp_pd(access_token, commandId, data, finishstatus, timemini)
|
||||||
|
res, code, headers, status = https.request(url, pd)
|
||||||
|
end
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
|
function init_update_resp_pd(access_token, commandId, data, finishstatus, timemini)
|
||||||
|
local pd = "access_token="..access_token
|
||||||
|
pd = pd.."&commandId="..commandId
|
||||||
|
pd = pd.."&commandResponse="..(data or "")
|
||||||
|
local status = 2
|
||||||
|
if finishstatus then
|
||||||
|
status = finishstatus
|
||||||
|
end
|
||||||
|
pd = pd.."&status="..status
|
||||||
|
pd = pd.."&lastExcuteTime="..timemini
|
||||||
|
return pd
|
||||||
|
end
|
||||||
|
|
||||||
|
function download_list_post_process(data, refine_cnt)
|
||||||
|
local new_data = {}
|
||||||
|
local jsd = cjson.decode(data)
|
||||||
|
local nd_msg = {}
|
||||||
|
if type(jsd) == "table" then
|
||||||
|
local msg = ""
|
||||||
|
for k, v in pairs(jsd) do
|
||||||
|
if k and k == "message" then
|
||||||
|
msg = v
|
||||||
|
else
|
||||||
|
new_data[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if type(msg) == "table" and _G.next(msg) ~= nil then
|
||||||
|
local cnt = 0
|
||||||
|
for k, v in pairs(msg) do
|
||||||
|
if cnt < refine_cnt then
|
||||||
|
table.insert(nd_msg, v)
|
||||||
|
cnt = cnt + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if _G.next(nd_msg) ~= nil then
|
||||||
|
new_data["message"] = nd_msg
|
||||||
|
else
|
||||||
|
new_data["message"] = "[]"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return nd_msg
|
||||||
|
end
|
||||||
|
|
||||||
|
function download_task_operate_process(cmd, cmdid)
|
||||||
|
local data = sip_get_parameters(cmdid)
|
||||||
|
local jsr = cjson.decode(data)
|
||||||
|
local value = jsr.value
|
||||||
|
local ret = ""
|
||||||
|
if (jsr.code) == "200" then
|
||||||
|
for k, v in pairs(value) do
|
||||||
|
if k == "commandRequest" then
|
||||||
|
local jsr = cjson.decode(v)
|
||||||
|
local gid = jsr.gid
|
||||||
|
ret = download_task_operate(gid, cmd)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
sip_response_uploader(cmd, cmdid, ret)
|
||||||
|
end
|
||||||
|
|
||||||
|
function ww_exec_reboot(cmd, cmdid)
|
||||||
|
local ret = {}
|
||||||
|
ret["result"] = true
|
||||||
|
sip_response_uploader(cmd, cmdid, data_to_json(ret))
|
||||||
|
exec_reboot()
|
||||||
|
end
|
||||||
|
|
||||||
|
sip_cmd_process_action = {
|
||||||
|
["realtimenetspeed"] = function(cmd, cmdid)
|
||||||
|
local data = data_to_json(real_time_net_speed())
|
||||||
|
sip_response_uploader(cmd, cmdid, data, 2)
|
||||||
|
end,
|
||||||
|
["factoryreset"] = function(cmd, cmdid)
|
||||||
|
local data = '{'..'status:"reset factory ok."'..'}'
|
||||||
|
local data = factory_reset()
|
||||||
|
sip_response_uploader(cmd, cmdid, data_to_json(data))
|
||||||
|
end,
|
||||||
|
["getDeviceList"] = function(cmd, cmdid)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
local data = ww_get_connect_device_list()
|
||||||
|
data = data_to_json(data)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, data)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
sip_response_uploader(cmd, cmdid, data)
|
||||||
|
end,
|
||||||
|
["getwifisettings"] = function(cmd, cmdid)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
local data = sip_get_parameters(cmdid)
|
||||||
|
require "MZLog".log(3, data)
|
||||||
|
local app_version = nil
|
||||||
|
local jsr = cjson.decode(data)
|
||||||
|
local value = jsr.value
|
||||||
|
for k, v in pairs(value) do
|
||||||
|
if k == "commandRequest" then
|
||||||
|
if #v > 1 then
|
||||||
|
local value = cjson.decode(v)
|
||||||
|
app_version = value.appVer
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if app_version == nil then
|
||||||
|
app_version = 0
|
||||||
|
end
|
||||||
|
require "MZLog".log(3, app_version)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
local data = ww_get_wifi_settings(app_version)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, data)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
sip_response_uploader(cmd, cmdid, data)
|
||||||
|
end,
|
||||||
|
["setwifisettings"] = function(cmd, cmdid)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
local data = sip_get_parameters(cmdid)
|
||||||
|
local jsr = cjson.decode(data)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
|
||||||
|
local value = jsr.value
|
||||||
|
local switch_2g = nil
|
||||||
|
local switch_5g = nil
|
||||||
|
local ssid_2g = nil
|
||||||
|
local ssid_5g = nil
|
||||||
|
local pwd_2g = nil
|
||||||
|
local pwd_5g = nil
|
||||||
|
local encry_2g = nil
|
||||||
|
local encry_5g = nil
|
||||||
|
|
||||||
|
for k, v in pairs(value) do
|
||||||
|
if k == "commandRequest" then
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, v)
|
||||||
|
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
local value = cjson.decode(v)
|
||||||
|
require "MZLog".log(3, value)
|
||||||
|
local base64 = value.base64
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, base64)
|
||||||
|
local app_version = value.appVer
|
||||||
|
if app_version == nil then
|
||||||
|
app_version = 0
|
||||||
|
end
|
||||||
|
require "MZLog".log(3, app_version)
|
||||||
|
|
||||||
|
if tonumber(app_version) >= 5 then
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, base64)
|
||||||
|
v = b64dec(base64)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, v)
|
||||||
|
local jsr = cjson.decode(v)
|
||||||
|
for key, value in pairs(jsr) do
|
||||||
|
if value.name == "wl0" then
|
||||||
|
switch_2g = value.on
|
||||||
|
ssid_2g = value.ssid
|
||||||
|
pwd_2g = value.pwd
|
||||||
|
encry_2g = value.encryption
|
||||||
|
elseif value.name == "wl1" then
|
||||||
|
switch_5g = value.on
|
||||||
|
ssid_5g = value.ssid
|
||||||
|
pwd_5g = value.pwd
|
||||||
|
encry_5g = value.encryption
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local value = cjson.decode(v)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, value)
|
||||||
|
switch_2g = value.on1
|
||||||
|
ssid_2g = value.ssid1
|
||||||
|
pwd_2g = value.pwd1
|
||||||
|
encry_2g = value.encryption1
|
||||||
|
switch_5g = value.on2
|
||||||
|
ssid_5g = value.ssid2
|
||||||
|
pwd_5g = value.pwd2
|
||||||
|
encry_5g = value.encryption2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local data = wifi_settings(switch_2g, ssid_2g, pwd_2g, encry_2g, switch_5g, ssid_5g, pwd_5g, encry_5g)
|
||||||
|
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
data = cjson.encode(data)
|
||||||
|
require "MZLog".log(3, data)
|
||||||
|
sip_response_uploader(cmd, cmdid, data)
|
||||||
|
end,
|
||||||
|
["checkRouterUpdate"] = function(cmd, cmdid)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
local data = check_upgrade()
|
||||||
|
require "MZLog".log(3, data)
|
||||||
|
sip_response_uploader(cmd, cmdid, data)
|
||||||
|
end,
|
||||||
|
["executeRouterUpdate"] = function(cmd, cmdid)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
local data = do_upgrade()
|
||||||
|
if data ~= "" then
|
||||||
|
require "MZLog".log(3, data)
|
||||||
|
sip_response_uploader(cmd, cmdid, data)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
["setDeviceName"] = function(cmd, cmdid)
|
||||||
|
local data = sip_get_parameters(cmdid)
|
||||||
|
local jsr = cjson.decode(data)
|
||||||
|
local value = jsr.value
|
||||||
|
local mac = nil
|
||||||
|
local devicename = nil
|
||||||
|
|
||||||
|
for k, v in pairs(value) do
|
||||||
|
if k == "commandRequest" then
|
||||||
|
local jsr = cjson.decode(v)
|
||||||
|
mac = jsr.mac
|
||||||
|
devicename = jsr.devicename
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
local data = set_device_name(mac, devicename)
|
||||||
|
require "MZLog".log(3, data)
|
||||||
|
sip_response_uploader(cmd, cmdid, data)
|
||||||
|
end,
|
||||||
|
["setWanSwitch"] = function(cmd, cmdid)
|
||||||
|
local data = sip_get_parameters(cmdid)
|
||||||
|
local jsr = cjson.decode(data)
|
||||||
|
local mac = nil
|
||||||
|
local mode = nil
|
||||||
|
local enable = nil
|
||||||
|
local value = jsr.value
|
||||||
|
for k, v in pairs(value) do
|
||||||
|
if k == "commandRequest" then
|
||||||
|
local jsr = cjson.decode(v)
|
||||||
|
mac = jsr.mac
|
||||||
|
mode = jsr.mode
|
||||||
|
enable = jsr.enable
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local data = set_wan_switch(mac, mode, enable)
|
||||||
|
data = data_to_json(data)
|
||||||
|
require "MZLog".log(3, data)
|
||||||
|
sip_response_uploader(cmd, cmdid, data)
|
||||||
|
end,
|
||||||
|
["setReboot"] = function(cmd, cmdid)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
ww_exec_reboot(cmd, cmdid)
|
||||||
|
end,
|
||||||
|
["getdevicedetails"] = function(cmd, cmdid)
|
||||||
|
local data = sip_get_parameters(cmdid)
|
||||||
|
local jsr = cjson.decode(data)
|
||||||
|
local value = jsr.value
|
||||||
|
local ret = ""
|
||||||
|
if (jsr.code) == "200" then
|
||||||
|
for k, v in pairs(value) do
|
||||||
|
if k == "commandRequest" then
|
||||||
|
local jsr = cjson.decode(v)
|
||||||
|
local mac = jsr.mac
|
||||||
|
ret = data_to_json(ww_get_device_details(mac))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
sip_response_uploader(cmd, cmdid, ret)
|
||||||
|
end,
|
||||||
|
["getsysinfo"] = function(cmd, cmdid)
|
||||||
|
local data = require "meizu.bfs".sysinfo()
|
||||||
|
data = data_to_json(data)
|
||||||
|
sip_response_uploader(cmd, cmdid, data)
|
||||||
|
end,
|
||||||
|
["getWirelessChannel"] = function(cmd, cmdid)
|
||||||
|
local ret = ww_get_wireless_channel()
|
||||||
|
sip_response_uploader(cmd, cmdid, ret)
|
||||||
|
end,
|
||||||
|
["setWirelessChannel"] = function(cmd, cmdid)
|
||||||
|
local data = sip_get_parameters(cmdid)
|
||||||
|
local jsr = cjson.decode(data)
|
||||||
|
local value = jsr.value
|
||||||
|
local ret = ""
|
||||||
|
if (jsr.code) == "200" then
|
||||||
|
for k, v in pairs(value) do
|
||||||
|
if k == "commandRequest" then
|
||||||
|
local jsr = cjson.decode(v)
|
||||||
|
local channel = jsr.channel
|
||||||
|
ret = data_to_json(ww_set_wireless_channel(channel))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
sip_response_uploader(cmd, cmdid, ret)
|
||||||
|
end,
|
||||||
|
["scanBleSwitch"] = function(cmd, cmdid) --scanBleSwitch getMeshDeviceList getBleDeviceList
|
||||||
|
local data = sip_get_parameters(cmdid)
|
||||||
|
local jsr = cjson.decode(data)
|
||||||
|
local value = jsr.value
|
||||||
|
local ret = ""
|
||||||
|
if (jsr.code) == "200" then
|
||||||
|
for k, v in pairs(value) do
|
||||||
|
if k == "commandRequest" then
|
||||||
|
local jsr = cjson.decode(v)
|
||||||
|
local status = jsr.status
|
||||||
|
ret = ww_scan_ble_switch(status)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
require "MZLog".log(3, ret)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
sip_response_uploader(cmd, cmdid, ret)
|
||||||
|
end,
|
||||||
|
["getBleDeviceList"] = function(cmd, cmdid)
|
||||||
|
local data = ww_get_ble_device_list()
|
||||||
|
require "MZLog".log(3, data)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
sip_response_uploader(cmd, cmdid, data)
|
||||||
|
end,
|
||||||
|
["addMeshDevice"] = function(cmd, cmdid)
|
||||||
|
local data = sip_get_parameters(cmdid)
|
||||||
|
local jsr = cjson.decode(data)
|
||||||
|
local value = jsr.value
|
||||||
|
local ret = ""
|
||||||
|
if (jsr.code) == "200" then
|
||||||
|
for k, v in pairs(value) do
|
||||||
|
if k == "commandRequest" then
|
||||||
|
local jsr = cjson.decode(v)
|
||||||
|
local mac = jsr.mac
|
||||||
|
ret = ww_add_ble_mesh_device(mac)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
require "MZLog".log(3, ret)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
sip_response_uploader(cmd, cmdid, ret)
|
||||||
|
end,
|
||||||
|
["getMeshDeviceDetail"] = function(cmd, cmdid)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
local data = sip_get_parameters(cmdid)
|
||||||
|
local jsr = cjson.decode(data)
|
||||||
|
local value = jsr.value
|
||||||
|
local ret = ""
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, value)
|
||||||
|
if (jsr.code) == "200" then
|
||||||
|
for k, v in pairs(value) do
|
||||||
|
if k == "commandRequest" then
|
||||||
|
local jsr = cjson.decode(v)
|
||||||
|
local mac = jsr.mac
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, mac)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
ret = ww_get_ble_device_status(mac)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
require "MZLog".log(3, ret)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
sip_response_uploader(cmd, cmdid, ret)
|
||||||
|
end,
|
||||||
|
["removeblefrommesh"] = function(cmd, cmdid)
|
||||||
|
local data = sip_get_parameters(cmdid)
|
||||||
|
local jsr = cjson.decode(data)
|
||||||
|
local value = jsr.value
|
||||||
|
local ret = ""
|
||||||
|
if (jsr.code) == "200" then
|
||||||
|
for k, v in pairs(value) do
|
||||||
|
if k == "commandRequest" then
|
||||||
|
local jsr = cjson.decode(v)
|
||||||
|
local mac = jsr.mac
|
||||||
|
ret = ww_remove_ble_from_mesh(mac)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
require "MZLog".log(3, ret)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
sip_response_uploader(cmd, cmdid, ret)
|
||||||
|
end,
|
||||||
|
["getMeshDeviceList"] = function(cmd, cmdid)
|
||||||
|
local data = ww_get_mesh_device_list()
|
||||||
|
require "MZLog".log(3, data)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
sip_response_uploader(cmd, cmdid, data)
|
||||||
|
end,
|
||||||
|
["setMeshDeviceAttr"] = function(cmd, cmdid)
|
||||||
|
local data = sip_get_parameters(cmdid)
|
||||||
|
local jsr = cjson.decode(data)
|
||||||
|
local value = jsr.value
|
||||||
|
local ret = ""
|
||||||
|
if (jsr.code) == "200" then
|
||||||
|
for k, v in pairs(value) do
|
||||||
|
if k == "commandRequest" then
|
||||||
|
local jsr = cjson.decode(v)
|
||||||
|
local mac = jsr.mac
|
||||||
|
local key = jsr.key
|
||||||
|
local value = jsr.value
|
||||||
|
ret = ww_set_mesh_device_attr(mac, key, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
require "MZLog".log(3, ret)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
sip_response_uploader(cmd, cmdid, ret)
|
||||||
|
end,
|
||||||
|
["rebootmeshdevice"] = function(cmd, cmdid)
|
||||||
|
local data = sip_get_parameters(cmdid)
|
||||||
|
local jsr = cjson.decode(data)
|
||||||
|
local value = jsr.value
|
||||||
|
local ret = ""
|
||||||
|
if (jsr.code) == "200" then
|
||||||
|
for k, v in pairs(value) do
|
||||||
|
if k == "commandRequest" then
|
||||||
|
local jsr = cjson.decode(v)
|
||||||
|
local mac = jsr.mac
|
||||||
|
ret = ww_reboot_mesh_device(mac)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
require "MZLog".log(3, ret)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
sip_response_uploader(cmd, cmdid, ret)
|
||||||
|
end,
|
||||||
|
["unmeshalldevice"] = function(cmd, cmdid)
|
||||||
|
local data = ww_unmesh_all_device()
|
||||||
|
require "MZLog".log(3, data)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
sip_response_uploader(cmd, cmdid, data)
|
||||||
|
end,
|
||||||
|
["setmeshdevicetimer"] = function(cmd, cmdid)
|
||||||
|
local data = sip_get_parameters(cmdid)
|
||||||
|
local jsr = cjson.decode(data)
|
||||||
|
local value = jsr.value
|
||||||
|
local ret = ""
|
||||||
|
if (jsr.code) == "200" then
|
||||||
|
for k, v in pairs(value) do
|
||||||
|
if k == "commandRequest" then
|
||||||
|
local jsr = cjson.decode(v)
|
||||||
|
local mac = jsr.mac
|
||||||
|
local timer_id = jsr.timerId
|
||||||
|
local flag = jsr.flag
|
||||||
|
local start = jsr.start
|
||||||
|
local ends = jsr.ends
|
||||||
|
ret = ww_set_mesh_device_timer(mac, timer_id, flag, start, ends)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
require "MZLog".log(3, ret)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
sip_response_uploader(cmd, cmdid, ret)
|
||||||
|
end,
|
||||||
|
["setMeashNetWorkPassword"] = function(cmd, cmdid)
|
||||||
|
local data = sip_get_parameters(cmdid)
|
||||||
|
local jsr = cjson.decode(data)
|
||||||
|
local value = jsr.value
|
||||||
|
local ret = ""
|
||||||
|
if (jsr.code) == "200" then
|
||||||
|
for k, v in pairs(value) do
|
||||||
|
if k == "commandRequest" then
|
||||||
|
local jsr = cjson.decode(v)
|
||||||
|
local old_key = jsr.oldkey
|
||||||
|
local new_key = jsr.newkey
|
||||||
|
ret = ww_set_mesh_device_timer(old_key, new_key)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
require "MZLog".log(3, ret)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
sip_response_uploader(cmd, cmdid, ret)
|
||||||
|
end,
|
||||||
|
["setLampBrightness"] = function(cmd, cmdid)
|
||||||
|
local data = sip_get_parameters(cmdid)
|
||||||
|
local jsr = cjson.decode(data)
|
||||||
|
local value = jsr.value
|
||||||
|
local ret = ""
|
||||||
|
if (jsr.code) == "200" then
|
||||||
|
for k, v in pairs(value) do
|
||||||
|
if k == "commandRequest" then
|
||||||
|
local jsr = cjson.decode(v)
|
||||||
|
local mac = jsr.mac
|
||||||
|
local timer_id = jsr.timerId
|
||||||
|
local flag = jsr.flag
|
||||||
|
local start = jsr.start
|
||||||
|
local ends = jsr.ends
|
||||||
|
ret = ww_set_mesh_device_timer(mac, timer_id, flag, start, ends)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
require "MZLog".log(3, ret)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
sip_response_uploader(cmd, cmdid, ret)
|
||||||
|
end,
|
||||||
|
["delmeshdevicetimer"] = function(cmd, cmdid)
|
||||||
|
local data = sip_get_parameters(cmdid)
|
||||||
|
local jsr = cjson.decode(data)
|
||||||
|
local value = jsr.value
|
||||||
|
local ret = ""
|
||||||
|
if (jsr.code) == "200" then
|
||||||
|
for k, v in pairs(value) do
|
||||||
|
if k == "commandRequest" then
|
||||||
|
local jsr = cjson.decode(v)
|
||||||
|
local mac = jsr.mac
|
||||||
|
local timer_id = jsr.timerId
|
||||||
|
ret = ww_del_mesh_device_timer(mac, timer_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
require "MZLog".log(3, ret)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
sip_response_uploader(cmd, cmdid, ret)
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
--"{ \"size\": \"14.12MB\", \"version\": \"1.0.10\" }"
|
||||||
|
function OTA_process_action(vs_info)
|
||||||
|
require "MZLog".log(3, "get OTA new Version:")
|
||||||
|
require "MZLog".log(3, vs_info)
|
||||||
|
require "meizu.upgdfs".push_new_version_msg()
|
||||||
|
end
|
||||||
|
|
||||||
|
--sip data format:
|
||||||
|
--{ "push_event": [ { "appid": "com.meizu.router", "data": { "business": "1", "commandId": "54", "type": "realtimenetspeed" } } ] }
|
||||||
|
--post d = '{"business":"1","commandId":"53","type":"speed"}'
|
||||||
|
function sip()
|
||||||
|
local ret;
|
||||||
|
--local data = '{"business":"1","commandId":"53","type":"speed"}'
|
||||||
|
local data = luci.http.formvalue("d")
|
||||||
|
require "MZLog".log(3, data)
|
||||||
|
if data ~= nil then
|
||||||
|
local data = b64dec(data)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, data)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
local jsr = cjson.decode(data)
|
||||||
|
if jsr.type ~= nil then
|
||||||
|
ret = sip_cmd_process_action[jsr.type](jsr.type, jsr.commandId)
|
||||||
|
else
|
||||||
|
if jsr["com.meizu.router"] ~= nil then
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, "OTA push message:")
|
||||||
|
require "MZLog".log(3, data)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
OTA_process_action(jsr["com.meizu.router"])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
luci.http.write_json("sip done.")
|
||||||
|
end
|
||||||
|
|
||||||
|
function pysip()
|
||||||
|
local ret;
|
||||||
|
local cmd = luci.http.formvalue("cmd")
|
||||||
|
local commandId = luci.http.formvalue("commandId")
|
||||||
|
if cmd ~= nil then
|
||||||
|
ret = sip_cmd_process_action[cmd](cmd, commandId)
|
||||||
|
end
|
||||||
|
luci.http.write_json("pysip: "..cmd.." "..commandId.." done.")
|
||||||
|
luci.http.close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function upload_router_log(logdata, logtype)
|
||||||
|
local https = require("ssl.https")
|
||||||
|
local url="https://router.meizu.com/oauth/router/upLog"
|
||||||
|
local access_token = rts_get_access_token()
|
||||||
|
local pd = init_upload_router_log_pd(access_token, logtype, logdata)
|
||||||
|
local res, code, headers, status = https.request(url, pd)
|
||||||
|
if code == 401 then
|
||||||
|
delete_access_token()
|
||||||
|
access_token = rts_get_access_token()
|
||||||
|
pd = init_upload_router_log_pd(access_token, logtype, logdata)
|
||||||
|
res, code, headers, status = https.request(url, pd)
|
||||||
|
end
|
||||||
|
return res, code, headers, status
|
||||||
|
end
|
||||||
|
|
||||||
|
function init_upload_router_log_pd(access_token, logtype, logdata)
|
||||||
|
local pd = "access_token="..access_token
|
||||||
|
if logtype then
|
||||||
|
pd = pd.."&type="..logtype
|
||||||
|
else
|
||||||
|
pd = pd.."&type=".."4"
|
||||||
|
end
|
||||||
|
pd = pd.."&content="..(logdata or "")
|
||||||
|
return pd
|
||||||
|
end
|
||||||
|
|
231
Me_Lua/r13/meizu/upgdfs.lua
Normal file
231
Me_Lua/r13/meizu/upgdfs.lua
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
module("meizu.upgdfs", package.seeall)
|
||||||
|
|
||||||
|
local cjson = require "cjson"
|
||||||
|
local bfs = require "meizu.bfs"
|
||||||
|
local sipfs = require "meizu.sipfs"
|
||||||
|
|
||||||
|
local b64dec = bfs.b64dec
|
||||||
|
local batchfile_checklist = bfs.batchfile_checklist
|
||||||
|
local batchfile_compare_upload = bfs.batchfile_compare_upload
|
||||||
|
local bind_router = bfs.bind_router
|
||||||
|
local cal_str_md5 = bfs.cal_str_md5
|
||||||
|
local data_to_json = bfs.data_to_json
|
||||||
|
local exec_cmd_in_sh = bfs.exec_cmd_in_sh
|
||||||
|
local exec_reboot = bfs.exec_reboot
|
||||||
|
local findInDir = bfs.findInDir
|
||||||
|
local get_device_SN = bfs.get_device_SN
|
||||||
|
local get_device_version = bfs.get_device_version
|
||||||
|
local get_https_data = bfs.get_https_data
|
||||||
|
local rts_get_access_token = bfs.rts_get_access_token
|
||||||
|
local set_passwd = bfs.set_passwd
|
||||||
|
local silent_upgrade = bfs.silent_upgrade
|
||||||
|
local table_merge = bfs.table_merge
|
||||||
|
|
||||||
|
function upgrade_lock()
|
||||||
|
return os.execute(RC.upgrade_lock)
|
||||||
|
end
|
||||||
|
|
||||||
|
function upgrade_unlock()
|
||||||
|
return os.execute(RC.upgrade_unlock)
|
||||||
|
end
|
||||||
|
|
||||||
|
function push_new_version_msg()
|
||||||
|
--type:4 (有新固件更新)
|
||||||
|
--msg = "{\"size\": \"14.12MB\", \"version\": \"1.0.10\" }"
|
||||||
|
local logtype = 4
|
||||||
|
local msg = check_upgrade()
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, "OTA push_new_version_msg:"..data)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
sipfs.upload_router_log(msg, logtype)
|
||||||
|
end
|
||||||
|
|
||||||
|
function push_fw_upgrading_msg(url)
|
||||||
|
local logtype = 6
|
||||||
|
local msg = {}
|
||||||
|
msg["code"] = 2005
|
||||||
|
msg["result"] = "upgrading...."
|
||||||
|
msg = data_to_json(msg)
|
||||||
|
local res, code, headers, status = sipfs.upload_router_log(msg, logtype)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, res)
|
||||||
|
require "MZLog".log(3, code)
|
||||||
|
require "MZLog".log(3, headers)
|
||||||
|
require "MZLog".log(3, status)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
end
|
||||||
|
|
||||||
|
function push_upgrade_finish_msg()
|
||||||
|
--(5) type:5 (固件更新完成)
|
||||||
|
local logtype = 5
|
||||||
|
local msg = {}
|
||||||
|
--"content": "{ \"version\": \"5.0\", \"size\": \"14088999\" }"
|
||||||
|
msg["version"] = get_device_version()
|
||||||
|
msg["size"] = 0
|
||||||
|
msg = data_to_json(msg)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, "push_upgrade_finish_msg:"..msg)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
local res, code, headers, status = sipfs.upload_router_log(msg, logtype)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, res)
|
||||||
|
require "MZLog".log(3, code)
|
||||||
|
require "MZLog".log(3, headers)
|
||||||
|
require "MZLog".log(3, status)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
end
|
||||||
|
|
||||||
|
function subscribe_auto_upgrade()
|
||||||
|
local http = require("socket.http")
|
||||||
|
local url = "http://u.meizu.com/api/v1/upgrade/subscribe"
|
||||||
|
local serviceCode = "com.meizu.router"
|
||||||
|
local pd = "serviceCode="..serviceCode
|
||||||
|
local sn = get_device_SN()
|
||||||
|
local sipToken = sn.."100032"
|
||||||
|
pd = pd.."&sipToken="..sipToken
|
||||||
|
local device = sn
|
||||||
|
pd = pd.."&device="..device
|
||||||
|
local version = get_device_version()
|
||||||
|
pd = pd.."&version="..version
|
||||||
|
local deviceModel = "R13"
|
||||||
|
pd = pd.."&deviceModel="..deviceModel
|
||||||
|
local key = "2635881a7ab0593849fe89e685fc56cd"
|
||||||
|
local toSignStr = serviceCode..sipToken..version..key
|
||||||
|
require "MZLog".log(3, url)
|
||||||
|
require "MZLog".log(3, pd)
|
||||||
|
pd = pd.."&sign="..cal_str_md5(toSignStr)
|
||||||
|
local res, code, headers, status = http.request(url, pd)
|
||||||
|
|
||||||
|
require "MZLog".log(3, res, code, headers, status)
|
||||||
|
return res, code, headers, status
|
||||||
|
end
|
||||||
|
|
||||||
|
function gen_check_fw_url_pd()
|
||||||
|
local serviceCode = "com.meizu.router"
|
||||||
|
local pd = "serviceCode="..serviceCode
|
||||||
|
local sn = get_device_SN()
|
||||||
|
local device = sn
|
||||||
|
pd = pd.."&device="..device
|
||||||
|
local deviceModel = "R13"
|
||||||
|
pd = pd.."&deviceModel="..deviceModel
|
||||||
|
local root = "true"
|
||||||
|
pd = pd.."&root="..root
|
||||||
|
local version = get_device_version()
|
||||||
|
pd = pd.."&version="..version
|
||||||
|
local key = "2635881a7ab0593849fe89e685fc56cd"
|
||||||
|
local toSignStr = serviceCode..device..deviceModel..root..version..key
|
||||||
|
pd = pd.."&sign="..cal_str_md5(toSignStr)
|
||||||
|
|
||||||
|
return pd
|
||||||
|
end
|
||||||
|
|
||||||
|
function check_upgrade()
|
||||||
|
local ret = {}
|
||||||
|
local http = require("socket.http")
|
||||||
|
local url = "http://u.meizu.com/api/v1/upgrade/check/router"
|
||||||
|
local pd = gen_check_fw_url_pd()
|
||||||
|
local res, code, headers, status = http.request(url, pd)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, pd)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
if res == nil then
|
||||||
|
require "MZLog".log(3, "get "..url.." failed!")
|
||||||
|
ret["code"] = code;
|
||||||
|
return data_to_json(ret)
|
||||||
|
else
|
||||||
|
return res;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function do_upgrade()
|
||||||
|
local ret = {}
|
||||||
|
local http = require("socket.http")
|
||||||
|
local url = "http://u.meizu.com/api/v1/upgrade/check/router"
|
||||||
|
local serviceCode = "com.meizu.router"
|
||||||
|
local pd = gen_check_fw_url_pd()
|
||||||
|
local res, code, headers, status = http.request(url, pd)
|
||||||
|
if res == nil then
|
||||||
|
require "MZLog".log(3, "do_upgrade get "..url.." failed!")
|
||||||
|
ret["result"] = code;
|
||||||
|
return data_to_json(ret)
|
||||||
|
end
|
||||||
|
local data = cjson.decode(res)
|
||||||
|
local value = data.value
|
||||||
|
local digest = ""
|
||||||
|
local filesize = 0
|
||||||
|
local upgrade_url = ""
|
||||||
|
if (data.code) == 200 then
|
||||||
|
for k,v in pairs(value) do
|
||||||
|
if k == "size" then
|
||||||
|
filesize = v
|
||||||
|
end
|
||||||
|
if k == "url" then
|
||||||
|
upgrade_url = v
|
||||||
|
end
|
||||||
|
if k == "digest" then
|
||||||
|
digest = v
|
||||||
|
end
|
||||||
|
if k == "version" then
|
||||||
|
version = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if upgrade_url ~= "" then
|
||||||
|
require "MZLog".log(3, upgrade_urogtype)
|
||||||
|
push_fw_upgrading_msg(upgrade_url)
|
||||||
|
local ota_img = "/tmp/ota.trx"
|
||||||
|
local cmd = "wget '"..upgrade_url.."' -O "..ota_img..[[;]]
|
||||||
|
cmd = cmd..[[nvram set upgrading=1;nvram commit;]]
|
||||||
|
cmd = cmd..[[killall dropbear uhttpd; sleep 1;]]
|
||||||
|
--cmd = cmd..[[/sbin/router_reset; sleep 2;]]
|
||||||
|
--cmd = cmd..[[/sbin/sysupgrade -n -v ]]..ota_img..[[|tee -a /tmp/ota.log;]]
|
||||||
|
cmd = cmd..[[/sbin/sysupgrade -v ]]..ota_img..[[|tee -a /tmp/ota.log;]]
|
||||||
|
ret = exec_cmd_in_sh(cmd)
|
||||||
|
--to do : add UCI set upgrade flag .
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function local_upgrade()
|
||||||
|
local fd = nil
|
||||||
|
local nixio = require "nixio"
|
||||||
|
local image = "/tmp/ota.trx"
|
||||||
|
local touchcmd = "touch "..image
|
||||||
|
exec_cmd_in_sh(touchcmd)
|
||||||
|
local function image_supported()
|
||||||
|
return ( 0 == os.execute(
|
||||||
|
". /lib/functions.sh; " ..
|
||||||
|
"include /lib/upgrade; " ..
|
||||||
|
"platform_check_image %q >/dev/null"
|
||||||
|
% image
|
||||||
|
))
|
||||||
|
end
|
||||||
|
luci.http.setfilehandler(
|
||||||
|
function(field, chunk, eof)
|
||||||
|
if not fd then
|
||||||
|
fd = nixio.open(image, "w")
|
||||||
|
end
|
||||||
|
fd:write(chunk)
|
||||||
|
if eof and fd then
|
||||||
|
fd:close()
|
||||||
|
fd = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
|
local clean = (luci.http.formvalue("clean") == "1") and "-n" or ""
|
||||||
|
if image_supported() then
|
||||||
|
local lue = require"luci.util".exec
|
||||||
|
local cmd = [[nvram set upgrading=1;nvram commit;]]
|
||||||
|
lue(cmd)
|
||||||
|
luci.http.write("updating")
|
||||||
|
exec_cmd_in_sh("killall dropbear uhttpd; sleep 1; /sbin/sysupgrade -v %s %q" %{ clean, image })
|
||||||
|
luci.http.write("update finished!")
|
||||||
|
else
|
||||||
|
luci.http.write("image_supported check failed!")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--push_new_version_msg("test")
|
||||||
|
--subscribe_auto_upgrade()
|
||||||
|
--local res = check_upgrade()
|
||||||
|
--print(res)
|
||||||
|
--do_upgrade()
|
90
Me_Lua/r13/mime.lua
Normal file
90
Me_Lua/r13/mime.lua
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- MIME support for the Lua language.
|
||||||
|
-- Author: Diego Nehab
|
||||||
|
-- Conforming to RFCs 2045-2049
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Declare module and import dependencies
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
local base = _G
|
||||||
|
local ltn12 = require("ltn12")
|
||||||
|
local mime = require("mime.core")
|
||||||
|
local io = require("io")
|
||||||
|
local string = require("string")
|
||||||
|
local _M = mime
|
||||||
|
|
||||||
|
-- encode, decode and wrap algorithm tables
|
||||||
|
local encodet, decodet, wrapt = {},{},{}
|
||||||
|
|
||||||
|
_M.encodet = encodet
|
||||||
|
_M.decodet = decodet
|
||||||
|
_M.wrapt = wrapt
|
||||||
|
|
||||||
|
-- creates a function that chooses a filter by name from a given table
|
||||||
|
local function choose(table)
|
||||||
|
return function(name, opt1, opt2)
|
||||||
|
if base.type(name) ~= "string" then
|
||||||
|
name, opt1, opt2 = "default", name, opt1
|
||||||
|
end
|
||||||
|
local f = table[name or "nil"]
|
||||||
|
if not f then
|
||||||
|
base.error("unknown key (" .. base.tostring(name) .. ")", 3)
|
||||||
|
else return f(opt1, opt2) end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- define the encoding filters
|
||||||
|
encodet['base64'] = function()
|
||||||
|
return ltn12.filter.cycle(_M.b64, "")
|
||||||
|
end
|
||||||
|
|
||||||
|
encodet['quoted-printable'] = function(mode)
|
||||||
|
return ltn12.filter.cycle(_M.qp, "",
|
||||||
|
(mode == "binary") and "=0D=0A" or "\r\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- define the decoding filters
|
||||||
|
decodet['base64'] = function()
|
||||||
|
return ltn12.filter.cycle(_M.unb64, "")
|
||||||
|
end
|
||||||
|
|
||||||
|
decodet['quoted-printable'] = function()
|
||||||
|
return ltn12.filter.cycle(_M.unqp, "")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function format(chunk)
|
||||||
|
if chunk then
|
||||||
|
if chunk == "" then return "''"
|
||||||
|
else return string.len(chunk) end
|
||||||
|
else return "nil" end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- define the line-wrap filters
|
||||||
|
wrapt['text'] = function(length)
|
||||||
|
length = length or 76
|
||||||
|
return ltn12.filter.cycle(_M.wrp, length, length)
|
||||||
|
end
|
||||||
|
wrapt['base64'] = wrapt['text']
|
||||||
|
wrapt['default'] = wrapt['text']
|
||||||
|
|
||||||
|
wrapt['quoted-printable'] = function()
|
||||||
|
return ltn12.filter.cycle(_M.qpwrp, 76, 76)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- function that choose the encoding, decoding or wrap algorithm
|
||||||
|
_M.encode = choose(encodet)
|
||||||
|
_M.decode = choose(decodet)
|
||||||
|
_M.wrap = choose(wrapt)
|
||||||
|
|
||||||
|
-- define the end-of-line normalization filter
|
||||||
|
function _M.normalize(marker)
|
||||||
|
return ltn12.filter.cycle(_M.eol, 0, marker)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- high level stuffing filter
|
||||||
|
function _M.stuff()
|
||||||
|
return ltn12.filter.cycle(_M.dot, 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
return _M
|
BIN
Me_Lua/r13/mime.so.1.0.3
Normal file
BIN
Me_Lua/r13/mime.so.1.0.3
Normal file
Binary file not shown.
BIN
Me_Lua/r13/mime/core.so
Normal file
BIN
Me_Lua/r13/mime/core.so
Normal file
Binary file not shown.
BIN
Me_Lua/r13/posix.so
Normal file
BIN
Me_Lua/r13/posix.so
Normal file
Binary file not shown.
136
Me_Lua/r13/routerReport.lua
Normal file
136
Me_Lua/r13/routerReport.lua
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
local bfs = require "meizu.bfs"
|
||||||
|
local dbfs = require("meizu.dbfs")
|
||||||
|
local upgdfs = require("meizu.upgdfs")
|
||||||
|
|
||||||
|
local get_device_SN = bfs.get_device_SN
|
||||||
|
local get_device_version = bfs.get_device_version
|
||||||
|
local get_https_data = bfs.get_https_data
|
||||||
|
local rts_get_access_token = bfs.rts_get_access_token
|
||||||
|
|
||||||
|
local delete_access_token = dbfs.delete_access_token
|
||||||
|
|
||||||
|
function getBasicInfo()
|
||||||
|
local sn = get_device_SN()
|
||||||
|
local url = "https://router.meizu.com/oauth/router/getBasicInfo?access_token="
|
||||||
|
local access_token = rts_get_access_token()
|
||||||
|
local newurl = url..access_token.."&device="..sn
|
||||||
|
local res, code, headers, status = get_https_data(newurl)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, newurl)
|
||||||
|
require "MZLog".log(3, res)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
if code == 401 then
|
||||||
|
delete_access_token()
|
||||||
|
access_token = rts_get_access_token()
|
||||||
|
newurl = url..access_token.."&device="..sn
|
||||||
|
res, code, headers, status = get_https_data(newurl)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function upRouterPushId()
|
||||||
|
local sn = get_device_SN()
|
||||||
|
local pushId = sn.."100032"
|
||||||
|
local url="https://router.meizu.com/oauth/router/upRouterPushId"
|
||||||
|
local access_token = rts_get_access_token()
|
||||||
|
local postData = "access_token="..access_token.."&pushId="..pushId
|
||||||
|
local res, code, headers, status = get_https_data(url, postData)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, url)
|
||||||
|
require "MZLog".log(3, res)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
if code == 401 then
|
||||||
|
delete_access_token()
|
||||||
|
access_token = rts_get_access_token()
|
||||||
|
postData = "access_token="..access_token.."&pushId="..pushId
|
||||||
|
res, code, headers, status = get_https_data(url, postData)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function report_rom_version()
|
||||||
|
local ver = get_device_version()
|
||||||
|
local url="https://router.meizu.com/oauth/router/updateStatus"
|
||||||
|
local access_token = rts_get_access_token()
|
||||||
|
local data = "&name=romversion&value="..ver
|
||||||
|
local pd = "access_token="..access_token..data
|
||||||
|
local res, code, headers, status = get_https_data(url, pd)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, url)
|
||||||
|
require "MZLog".log(3, res)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
if code == 401 then
|
||||||
|
delete_access_token()
|
||||||
|
access_token = rts_get_access_token()
|
||||||
|
pd = "access_token="..access_token..data
|
||||||
|
res, code, headers, status = get_https_data(url, pd)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function check_upgrade_status()
|
||||||
|
local lu = require("luci.util")
|
||||||
|
local cmd = [[nvram get upgrading|awk '{printf $1}']]
|
||||||
|
local ret = lu.exec(cmd)
|
||||||
|
if ret == "1" then
|
||||||
|
local res, code, headers, status = upgdfs.push_upgrade_finish_msg()
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
require "MZLog".log(3, "check_upgrade_status")
|
||||||
|
require "MZLog".log(3, res)
|
||||||
|
require "MZLog".log(3, code)
|
||||||
|
require "MZLog".log(3, headers)
|
||||||
|
require "MZLog".log(3, status)
|
||||||
|
require "MZLog".log(3, debug.getinfo(1).currentline)
|
||||||
|
cmd = [[nvram unset upgrading;nvram commit;]]
|
||||||
|
lu.exec(cmd)
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
function ping_rts_server()
|
||||||
|
local lu = require("luci.util")
|
||||||
|
local cmd = "sleep 2;ping -W 2 -c 1 router.meizu.com > /dev/null ;echo -n $?"
|
||||||
|
local ret = lu.exec(cmd)
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
function ut()
|
||||||
|
local lu = require("luci.util")
|
||||||
|
local cmd = "uptime"
|
||||||
|
local ret = lu.exec(cmd)
|
||||||
|
require "MZLog".log(3, ret)
|
||||||
|
end
|
||||||
|
|
||||||
|
function init_ssid_dbdata()
|
||||||
|
dbfs.init_ssid_table()
|
||||||
|
local ssidtable = dbfs.fetch_ssid()
|
||||||
|
if nil == ssidtable or 0 == #ssidtable then
|
||||||
|
local network = require "luci.model.network".init()
|
||||||
|
local wifi_net_ra0 = network:get_wifinet('mt7628.network1')
|
||||||
|
local ssid24 = wifi_net_ra0:get("ssid")
|
||||||
|
local wifi_net_rai0 = network:get_wifinet('mt7610e.network1')
|
||||||
|
local ssid5 = wifi_net_rai0:get("ssid")
|
||||||
|
dbfs.add_ssid(ssid24, ssid5)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
init_ssid_dbdata()
|
||||||
|
dbfs.init_deny_mac_table()
|
||||||
|
|
||||||
|
ut()
|
||||||
|
require "MZLog".log(3, "start ping_rts_server()")
|
||||||
|
local ret = ping_rts_server()
|
||||||
|
while ret ~= "0" do
|
||||||
|
ret = ping_rts_server()
|
||||||
|
end
|
||||||
|
ut()
|
||||||
|
require "MZLog".log(3, "end ping_rts_server()")
|
||||||
|
require "MZLog".log(3, "getBasicInfo()")
|
||||||
|
getBasicInfo()
|
||||||
|
require "MZLog".log(3, "upRouterPushId()")
|
||||||
|
upRouterPushId()
|
||||||
|
ut()
|
||||||
|
require "MZLog".log(3, "upgdfs.subscribe_auto_upgrade")
|
||||||
|
local res, code, headers, status = upgdfs.subscribe_auto_upgrade()
|
||||||
|
ut()
|
||||||
|
require "MZLog".log(3, res, code, headers, status)
|
||||||
|
ut()
|
||||||
|
check_upgrade_status()
|
||||||
|
report_rom_version()
|
149
Me_Lua/r13/socket.lua
Normal file
149
Me_Lua/r13/socket.lua
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- LuaSocket helper module
|
||||||
|
-- Author: Diego Nehab
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Declare module and import dependencies
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
local base = _G
|
||||||
|
local string = require("string")
|
||||||
|
local math = require("math")
|
||||||
|
local socket = require("socket.core")
|
||||||
|
|
||||||
|
local _M = socket
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Exported auxiliar functions
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
function _M.connect4(address, port, laddress, lport)
|
||||||
|
return socket.connect(address, port, laddress, lport, "inet")
|
||||||
|
end
|
||||||
|
|
||||||
|
function _M.connect6(address, port, laddress, lport)
|
||||||
|
return socket.connect(address, port, laddress, lport, "inet6")
|
||||||
|
end
|
||||||
|
|
||||||
|
function _M.bind(host, port, backlog)
|
||||||
|
if host == "*" then host = "0.0.0.0" end
|
||||||
|
local addrinfo, err = socket.dns.getaddrinfo(host);
|
||||||
|
if not addrinfo then return nil, err end
|
||||||
|
local sock, res
|
||||||
|
err = "no info on address"
|
||||||
|
for i, alt in base.ipairs(addrinfo) do
|
||||||
|
if alt.family == "inet" then
|
||||||
|
sock, err = socket.tcp()
|
||||||
|
else
|
||||||
|
sock, err = socket.tcp6()
|
||||||
|
end
|
||||||
|
if not sock then return nil, err end
|
||||||
|
sock:setoption("reuseaddr", true)
|
||||||
|
res, err = sock:bind(alt.addr, port)
|
||||||
|
if not res then
|
||||||
|
sock:close()
|
||||||
|
else
|
||||||
|
res, err = sock:listen(backlog)
|
||||||
|
if not res then
|
||||||
|
sock:close()
|
||||||
|
else
|
||||||
|
return sock
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
|
||||||
|
_M.try = _M.newtry()
|
||||||
|
|
||||||
|
function _M.choose(table)
|
||||||
|
return function(name, opt1, opt2)
|
||||||
|
if base.type(name) ~= "string" then
|
||||||
|
name, opt1, opt2 = "default", name, opt1
|
||||||
|
end
|
||||||
|
local f = table[name or "nil"]
|
||||||
|
if not f then base.error("unknown key (".. base.tostring(name) ..")", 3)
|
||||||
|
else return f(opt1, opt2) end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Socket sources and sinks, conforming to LTN12
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- create namespaces inside LuaSocket namespace
|
||||||
|
local sourcet, sinkt = {}, {}
|
||||||
|
_M.sourcet = sourcet
|
||||||
|
_M.sinkt = sinkt
|
||||||
|
|
||||||
|
_M.BLOCKSIZE = 2048
|
||||||
|
|
||||||
|
sinkt["close-when-done"] = function(sock)
|
||||||
|
return base.setmetatable({
|
||||||
|
getfd = function() return sock:getfd() end,
|
||||||
|
dirty = function() return sock:dirty() end
|
||||||
|
}, {
|
||||||
|
__call = function(self, chunk, err)
|
||||||
|
if not chunk then
|
||||||
|
sock:close()
|
||||||
|
return 1
|
||||||
|
else return sock:send(chunk) end
|
||||||
|
end
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
sinkt["keep-open"] = function(sock)
|
||||||
|
return base.setmetatable({
|
||||||
|
getfd = function() return sock:getfd() end,
|
||||||
|
dirty = function() return sock:dirty() end
|
||||||
|
}, {
|
||||||
|
__call = function(self, chunk, err)
|
||||||
|
if chunk then return sock:send(chunk)
|
||||||
|
else return 1 end
|
||||||
|
end
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
sinkt["default"] = sinkt["keep-open"]
|
||||||
|
|
||||||
|
_M.sink = _M.choose(sinkt)
|
||||||
|
|
||||||
|
sourcet["by-length"] = function(sock, length)
|
||||||
|
return base.setmetatable({
|
||||||
|
getfd = function() return sock:getfd() end,
|
||||||
|
dirty = function() return sock:dirty() end
|
||||||
|
}, {
|
||||||
|
__call = function()
|
||||||
|
if length <= 0 then return nil end
|
||||||
|
local size = math.min(socket.BLOCKSIZE, length)
|
||||||
|
local chunk, err = sock:receive(size)
|
||||||
|
if err then return nil, err end
|
||||||
|
length = length - string.len(chunk)
|
||||||
|
return chunk
|
||||||
|
end
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
sourcet["until-closed"] = function(sock)
|
||||||
|
local done
|
||||||
|
return base.setmetatable({
|
||||||
|
getfd = function() return sock:getfd() end,
|
||||||
|
dirty = function() return sock:dirty() end
|
||||||
|
}, {
|
||||||
|
__call = function()
|
||||||
|
if done then return nil end
|
||||||
|
local chunk, err, partial = sock:receive(socket.BLOCKSIZE)
|
||||||
|
if not err then return chunk
|
||||||
|
elseif err == "closed" then
|
||||||
|
sock:close()
|
||||||
|
done = 1
|
||||||
|
return partial
|
||||||
|
else return nil, err end
|
||||||
|
end
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
sourcet["default"] = sourcet["until-closed"]
|
||||||
|
|
||||||
|
_M.source = _M.choose(sourcet)
|
||||||
|
|
||||||
|
return _M
|
BIN
Me_Lua/r13/socket.so.3.0-rc1
Normal file
BIN
Me_Lua/r13/socket.so.3.0-rc1
Normal file
Binary file not shown.
BIN
Me_Lua/r13/socket/core.so
Normal file
BIN
Me_Lua/r13/socket/core.so
Normal file
Binary file not shown.
285
Me_Lua/r13/socket/ftp.lua
Normal file
285
Me_Lua/r13/socket/ftp.lua
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- FTP support for the Lua language
|
||||||
|
-- LuaSocket toolkit.
|
||||||
|
-- Author: Diego Nehab
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Declare module and import dependencies
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
local base = _G
|
||||||
|
local table = require("table")
|
||||||
|
local string = require("string")
|
||||||
|
local math = require("math")
|
||||||
|
local socket = require("socket")
|
||||||
|
local url = require("socket.url")
|
||||||
|
local tp = require("socket.tp")
|
||||||
|
local ltn12 = require("ltn12")
|
||||||
|
socket.ftp = {}
|
||||||
|
local _M = socket.ftp
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Program constants
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- timeout in seconds before the program gives up on a connection
|
||||||
|
_M.TIMEOUT = 60
|
||||||
|
-- default port for ftp service
|
||||||
|
_M.PORT = 21
|
||||||
|
-- this is the default anonymous password. used when no password is
|
||||||
|
-- provided in url. should be changed to your e-mail.
|
||||||
|
_M.USER = "ftp"
|
||||||
|
_M.PASSWORD = "anonymous@anonymous.org"
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Low level FTP API
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
local metat = { __index = {} }
|
||||||
|
|
||||||
|
function _M.open(server, port, create)
|
||||||
|
local tp = socket.try(tp.connect(server, port or _M.PORT, _M.TIMEOUT, create))
|
||||||
|
local f = base.setmetatable({ tp = tp }, metat)
|
||||||
|
-- make sure everything gets closed in an exception
|
||||||
|
f.try = socket.newtry(function() f:close() end)
|
||||||
|
return f
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:portconnect()
|
||||||
|
self.try(self.server:settimeout(_M.TIMEOUT))
|
||||||
|
self.data = self.try(self.server:accept())
|
||||||
|
self.try(self.data:settimeout(_M.TIMEOUT))
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:pasvconnect()
|
||||||
|
self.data = self.try(socket.tcp())
|
||||||
|
self.try(self.data:settimeout(_M.TIMEOUT))
|
||||||
|
self.try(self.data:connect(self.pasvt.ip, self.pasvt.port))
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:login(user, password)
|
||||||
|
self.try(self.tp:command("user", user or _M.USER))
|
||||||
|
local code, reply = self.try(self.tp:check{"2..", 331})
|
||||||
|
if code == 331 then
|
||||||
|
self.try(self.tp:command("pass", password or _M.PASSWORD))
|
||||||
|
self.try(self.tp:check("2.."))
|
||||||
|
end
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:pasv()
|
||||||
|
self.try(self.tp:command("pasv"))
|
||||||
|
local code, reply = self.try(self.tp:check("2.."))
|
||||||
|
local pattern = "(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)"
|
||||||
|
local a, b, c, d, p1, p2 = socket.skip(2, string.find(reply, pattern))
|
||||||
|
self.try(a and b and c and d and p1 and p2, reply)
|
||||||
|
self.pasvt = {
|
||||||
|
ip = string.format("%d.%d.%d.%d", a, b, c, d),
|
||||||
|
port = p1*256 + p2
|
||||||
|
}
|
||||||
|
if self.server then
|
||||||
|
self.server:close()
|
||||||
|
self.server = nil
|
||||||
|
end
|
||||||
|
return self.pasvt.ip, self.pasvt.port
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:port(ip, port)
|
||||||
|
self.pasvt = nil
|
||||||
|
if not ip then
|
||||||
|
ip, port = self.try(self.tp:getcontrol():getsockname())
|
||||||
|
self.server = self.try(socket.bind(ip, 0))
|
||||||
|
ip, port = self.try(self.server:getsockname())
|
||||||
|
self.try(self.server:settimeout(_M.TIMEOUT))
|
||||||
|
end
|
||||||
|
local pl = math.mod(port, 256)
|
||||||
|
local ph = (port - pl)/256
|
||||||
|
local arg = string.gsub(string.format("%s,%d,%d", ip, ph, pl), "%.", ",")
|
||||||
|
self.try(self.tp:command("port", arg))
|
||||||
|
self.try(self.tp:check("2.."))
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:send(sendt)
|
||||||
|
self.try(self.pasvt or self.server, "need port or pasv first")
|
||||||
|
-- if there is a pasvt table, we already sent a PASV command
|
||||||
|
-- we just get the data connection into self.data
|
||||||
|
if self.pasvt then self:pasvconnect() end
|
||||||
|
-- get the transfer argument and command
|
||||||
|
local argument = sendt.argument or
|
||||||
|
url.unescape(string.gsub(sendt.path or "", "^[/\\]", ""))
|
||||||
|
if argument == "" then argument = nil end
|
||||||
|
local command = sendt.command or "stor"
|
||||||
|
-- send the transfer command and check the reply
|
||||||
|
self.try(self.tp:command(command, argument))
|
||||||
|
local code, reply = self.try(self.tp:check{"2..", "1.."})
|
||||||
|
-- if there is not a a pasvt table, then there is a server
|
||||||
|
-- and we already sent a PORT command
|
||||||
|
if not self.pasvt then self:portconnect() end
|
||||||
|
-- get the sink, source and step for the transfer
|
||||||
|
local step = sendt.step or ltn12.pump.step
|
||||||
|
local readt = {self.tp.c}
|
||||||
|
local checkstep = function(src, snk)
|
||||||
|
-- check status in control connection while downloading
|
||||||
|
local readyt = socket.select(readt, nil, 0)
|
||||||
|
if readyt[tp] then code = self.try(self.tp:check("2..")) end
|
||||||
|
return step(src, snk)
|
||||||
|
end
|
||||||
|
local sink = socket.sink("close-when-done", self.data)
|
||||||
|
-- transfer all data and check error
|
||||||
|
self.try(ltn12.pump.all(sendt.source, sink, checkstep))
|
||||||
|
if string.find(code, "1..") then self.try(self.tp:check("2..")) end
|
||||||
|
-- done with data connection
|
||||||
|
self.data:close()
|
||||||
|
-- find out how many bytes were sent
|
||||||
|
local sent = socket.skip(1, self.data:getstats())
|
||||||
|
self.data = nil
|
||||||
|
return sent
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:receive(recvt)
|
||||||
|
self.try(self.pasvt or self.server, "need port or pasv first")
|
||||||
|
if self.pasvt then self:pasvconnect() end
|
||||||
|
local argument = recvt.argument or
|
||||||
|
url.unescape(string.gsub(recvt.path or "", "^[/\\]", ""))
|
||||||
|
if argument == "" then argument = nil end
|
||||||
|
local command = recvt.command or "retr"
|
||||||
|
self.try(self.tp:command(command, argument))
|
||||||
|
local code,reply = self.try(self.tp:check{"1..", "2.."})
|
||||||
|
if (code >= 200) and (code <= 299) then
|
||||||
|
recvt.sink(reply)
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
if not self.pasvt then self:portconnect() end
|
||||||
|
local source = socket.source("until-closed", self.data)
|
||||||
|
local step = recvt.step or ltn12.pump.step
|
||||||
|
self.try(ltn12.pump.all(source, recvt.sink, step))
|
||||||
|
if string.find(code, "1..") then self.try(self.tp:check("2..")) end
|
||||||
|
self.data:close()
|
||||||
|
self.data = nil
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:cwd(dir)
|
||||||
|
self.try(self.tp:command("cwd", dir))
|
||||||
|
self.try(self.tp:check(250))
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:type(type)
|
||||||
|
self.try(self.tp:command("type", type))
|
||||||
|
self.try(self.tp:check(200))
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:greet()
|
||||||
|
local code = self.try(self.tp:check{"1..", "2.."})
|
||||||
|
if string.find(code, "1..") then self.try(self.tp:check("2..")) end
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:quit()
|
||||||
|
self.try(self.tp:command("quit"))
|
||||||
|
self.try(self.tp:check("2.."))
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:close()
|
||||||
|
if self.data then self.data:close() end
|
||||||
|
if self.server then self.server:close() end
|
||||||
|
return self.tp:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- High level FTP API
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
local function override(t)
|
||||||
|
if t.url then
|
||||||
|
local u = url.parse(t.url)
|
||||||
|
for i,v in base.pairs(t) do
|
||||||
|
u[i] = v
|
||||||
|
end
|
||||||
|
return u
|
||||||
|
else return t end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function tput(putt)
|
||||||
|
putt = override(putt)
|
||||||
|
socket.try(putt.host, "missing hostname")
|
||||||
|
local f = _M.open(putt.host, putt.port, putt.create)
|
||||||
|
f:greet()
|
||||||
|
f:login(putt.user, putt.password)
|
||||||
|
if putt.type then f:type(putt.type) end
|
||||||
|
f:pasv()
|
||||||
|
local sent = f:send(putt)
|
||||||
|
f:quit()
|
||||||
|
f:close()
|
||||||
|
return sent
|
||||||
|
end
|
||||||
|
|
||||||
|
local default = {
|
||||||
|
path = "/",
|
||||||
|
scheme = "ftp"
|
||||||
|
}
|
||||||
|
|
||||||
|
local function parse(u)
|
||||||
|
local t = socket.try(url.parse(u, default))
|
||||||
|
socket.try(t.scheme == "ftp", "wrong scheme '" .. t.scheme .. "'")
|
||||||
|
socket.try(t.host, "missing hostname")
|
||||||
|
local pat = "^type=(.)$"
|
||||||
|
if t.params then
|
||||||
|
t.type = socket.skip(2, string.find(t.params, pat))
|
||||||
|
socket.try(t.type == "a" or t.type == "i",
|
||||||
|
"invalid type '" .. t.type .. "'")
|
||||||
|
end
|
||||||
|
return t
|
||||||
|
end
|
||||||
|
|
||||||
|
local function sput(u, body)
|
||||||
|
local putt = parse(u)
|
||||||
|
putt.source = ltn12.source.string(body)
|
||||||
|
return tput(putt)
|
||||||
|
end
|
||||||
|
|
||||||
|
_M.put = socket.protect(function(putt, body)
|
||||||
|
if base.type(putt) == "string" then return sput(putt, body)
|
||||||
|
else return tput(putt) end
|
||||||
|
end)
|
||||||
|
|
||||||
|
local function tget(gett)
|
||||||
|
gett = override(gett)
|
||||||
|
socket.try(gett.host, "missing hostname")
|
||||||
|
local f = _M.open(gett.host, gett.port, gett.create)
|
||||||
|
f:greet()
|
||||||
|
f:login(gett.user, gett.password)
|
||||||
|
if gett.type then f:type(gett.type) end
|
||||||
|
f:pasv()
|
||||||
|
f:receive(gett)
|
||||||
|
f:quit()
|
||||||
|
return f:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function sget(u)
|
||||||
|
local gett = parse(u)
|
||||||
|
local t = {}
|
||||||
|
gett.sink = ltn12.sink.table(t)
|
||||||
|
tget(gett)
|
||||||
|
return table.concat(t)
|
||||||
|
end
|
||||||
|
|
||||||
|
_M.command = socket.protect(function(cmdt)
|
||||||
|
cmdt = override(cmdt)
|
||||||
|
socket.try(cmdt.host, "missing hostname")
|
||||||
|
socket.try(cmdt.command, "missing command")
|
||||||
|
local f = open(cmdt.host, cmdt.port, cmdt.create)
|
||||||
|
f:greet()
|
||||||
|
f:login(cmdt.user, cmdt.password)
|
||||||
|
f.try(f.tp:command(cmdt.command, cmdt.argument))
|
||||||
|
if cmdt.check then f.try(f.tp:check(cmdt.check)) end
|
||||||
|
f:quit()
|
||||||
|
return f:close()
|
||||||
|
end)
|
||||||
|
|
||||||
|
_M.get = socket.protect(function(gett)
|
||||||
|
if base.type(gett) == "string" then return sget(gett)
|
||||||
|
else return tget(gett) end
|
||||||
|
end)
|
||||||
|
|
||||||
|
return _M
|
104
Me_Lua/r13/socket/headers.lua
Normal file
104
Me_Lua/r13/socket/headers.lua
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Canonic header field capitalization
|
||||||
|
-- LuaSocket toolkit.
|
||||||
|
-- Author: Diego Nehab
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
local socket = require("socket")
|
||||||
|
socket.headers = {}
|
||||||
|
local _M = socket.headers
|
||||||
|
|
||||||
|
_M.canonic = {
|
||||||
|
["accept"] = "Accept",
|
||||||
|
["accept-charset"] = "Accept-Charset",
|
||||||
|
["accept-encoding"] = "Accept-Encoding",
|
||||||
|
["accept-language"] = "Accept-Language",
|
||||||
|
["accept-ranges"] = "Accept-Ranges",
|
||||||
|
["action"] = "Action",
|
||||||
|
["alternate-recipient"] = "Alternate-Recipient",
|
||||||
|
["age"] = "Age",
|
||||||
|
["allow"] = "Allow",
|
||||||
|
["arrival-date"] = "Arrival-Date",
|
||||||
|
["authorization"] = "Authorization",
|
||||||
|
["bcc"] = "Bcc",
|
||||||
|
["cache-control"] = "Cache-Control",
|
||||||
|
["cc"] = "Cc",
|
||||||
|
["comments"] = "Comments",
|
||||||
|
["connection"] = "Connection",
|
||||||
|
["content-description"] = "Content-Description",
|
||||||
|
["content-disposition"] = "Content-Disposition",
|
||||||
|
["content-encoding"] = "Content-Encoding",
|
||||||
|
["content-id"] = "Content-ID",
|
||||||
|
["content-language"] = "Content-Language",
|
||||||
|
["content-length"] = "Content-Length",
|
||||||
|
["content-location"] = "Content-Location",
|
||||||
|
["content-md5"] = "Content-MD5",
|
||||||
|
["content-range"] = "Content-Range",
|
||||||
|
["content-transfer-encoding"] = "Content-Transfer-Encoding",
|
||||||
|
["content-type"] = "Content-Type",
|
||||||
|
["cookie"] = "Cookie",
|
||||||
|
["date"] = "Date",
|
||||||
|
["diagnostic-code"] = "Diagnostic-Code",
|
||||||
|
["dsn-gateway"] = "DSN-Gateway",
|
||||||
|
["etag"] = "ETag",
|
||||||
|
["expect"] = "Expect",
|
||||||
|
["expires"] = "Expires",
|
||||||
|
["final-log-id"] = "Final-Log-ID",
|
||||||
|
["final-recipient"] = "Final-Recipient",
|
||||||
|
["from"] = "From",
|
||||||
|
["host"] = "Host",
|
||||||
|
["if-match"] = "If-Match",
|
||||||
|
["if-modified-since"] = "If-Modified-Since",
|
||||||
|
["if-none-match"] = "If-None-Match",
|
||||||
|
["if-range"] = "If-Range",
|
||||||
|
["if-unmodified-since"] = "If-Unmodified-Since",
|
||||||
|
["in-reply-to"] = "In-Reply-To",
|
||||||
|
["keywords"] = "Keywords",
|
||||||
|
["last-attempt-date"] = "Last-Attempt-Date",
|
||||||
|
["last-modified"] = "Last-Modified",
|
||||||
|
["location"] = "Location",
|
||||||
|
["max-forwards"] = "Max-Forwards",
|
||||||
|
["message-id"] = "Message-ID",
|
||||||
|
["mime-version"] = "MIME-Version",
|
||||||
|
["original-envelope-id"] = "Original-Envelope-ID",
|
||||||
|
["original-recipient"] = "Original-Recipient",
|
||||||
|
["pragma"] = "Pragma",
|
||||||
|
["proxy-authenticate"] = "Proxy-Authenticate",
|
||||||
|
["proxy-authorization"] = "Proxy-Authorization",
|
||||||
|
["range"] = "Range",
|
||||||
|
["received"] = "Received",
|
||||||
|
["received-from-mta"] = "Received-From-MTA",
|
||||||
|
["references"] = "References",
|
||||||
|
["referer"] = "Referer",
|
||||||
|
["remote-mta"] = "Remote-MTA",
|
||||||
|
["reply-to"] = "Reply-To",
|
||||||
|
["reporting-mta"] = "Reporting-MTA",
|
||||||
|
["resent-bcc"] = "Resent-Bcc",
|
||||||
|
["resent-cc"] = "Resent-Cc",
|
||||||
|
["resent-date"] = "Resent-Date",
|
||||||
|
["resent-from"] = "Resent-From",
|
||||||
|
["resent-message-id"] = "Resent-Message-ID",
|
||||||
|
["resent-reply-to"] = "Resent-Reply-To",
|
||||||
|
["resent-sender"] = "Resent-Sender",
|
||||||
|
["resent-to"] = "Resent-To",
|
||||||
|
["retry-after"] = "Retry-After",
|
||||||
|
["return-path"] = "Return-Path",
|
||||||
|
["sender"] = "Sender",
|
||||||
|
["server"] = "Server",
|
||||||
|
["smtp-remote-recipient"] = "SMTP-Remote-Recipient",
|
||||||
|
["status"] = "Status",
|
||||||
|
["subject"] = "Subject",
|
||||||
|
["te"] = "TE",
|
||||||
|
["to"] = "To",
|
||||||
|
["trailer"] = "Trailer",
|
||||||
|
["transfer-encoding"] = "Transfer-Encoding",
|
||||||
|
["upgrade"] = "Upgrade",
|
||||||
|
["user-agent"] = "User-Agent",
|
||||||
|
["vary"] = "Vary",
|
||||||
|
["via"] = "Via",
|
||||||
|
["warning"] = "Warning",
|
||||||
|
["will-retry-until"] = "Will-Retry-Until",
|
||||||
|
["www-authenticate"] = "WWW-Authenticate",
|
||||||
|
["x-mailer"] = "X-Mailer",
|
||||||
|
}
|
||||||
|
|
||||||
|
return _M
|
356
Me_Lua/r13/socket/http.lua
Normal file
356
Me_Lua/r13/socket/http.lua
Normal file
@ -0,0 +1,356 @@
|
|||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- HTTP/1.1 client support for the Lua language.
|
||||||
|
-- LuaSocket toolkit.
|
||||||
|
-- Author: Diego Nehab
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Declare module and import dependencies
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
local socket = require("socket")
|
||||||
|
local url = require("socket.url")
|
||||||
|
local ltn12 = require("ltn12")
|
||||||
|
local mime = require("mime")
|
||||||
|
local string = require("string")
|
||||||
|
local headers = require("socket.headers")
|
||||||
|
local base = _G
|
||||||
|
local table = require("table")
|
||||||
|
socket.http = {}
|
||||||
|
local _M = socket.http
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Program constants
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- connection timeout in seconds
|
||||||
|
_M.TIMEOUT = 60
|
||||||
|
-- default port for document retrieval
|
||||||
|
_M.PORT = 80
|
||||||
|
-- user agent field sent in request
|
||||||
|
_M.USERAGENT = socket._VERSION
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Reads MIME headers from a connection, unfolding where needed
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
local function receiveheaders(sock, headers)
|
||||||
|
local line, name, value, err
|
||||||
|
headers = headers or {}
|
||||||
|
-- get first line
|
||||||
|
line, err = sock:receive()
|
||||||
|
if err then return nil, err end
|
||||||
|
-- headers go until a blank line is found
|
||||||
|
while line ~= "" do
|
||||||
|
-- get field-name and value
|
||||||
|
name, value = socket.skip(2, string.find(line, "^(.-):%s*(.*)"))
|
||||||
|
if not (name and value) then return nil, "malformed reponse headers" end
|
||||||
|
name = string.lower(name)
|
||||||
|
-- get next line (value might be folded)
|
||||||
|
line, err = sock:receive()
|
||||||
|
if err then return nil, err end
|
||||||
|
-- unfold any folded values
|
||||||
|
while string.find(line, "^%s") do
|
||||||
|
value = value .. line
|
||||||
|
line = sock:receive()
|
||||||
|
if err then return nil, err end
|
||||||
|
end
|
||||||
|
-- save pair in table
|
||||||
|
if headers[name] then headers[name] = headers[name] .. ", " .. value
|
||||||
|
else headers[name] = value end
|
||||||
|
end
|
||||||
|
return headers
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Extra sources and sinks
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
socket.sourcet["http-chunked"] = function(sock, headers)
|
||||||
|
return base.setmetatable({
|
||||||
|
getfd = function() return sock:getfd() end,
|
||||||
|
dirty = function() return sock:dirty() end
|
||||||
|
}, {
|
||||||
|
__call = function()
|
||||||
|
-- get chunk size, skip extention
|
||||||
|
local line, err = sock:receive()
|
||||||
|
if err then return nil, err end
|
||||||
|
local size = base.tonumber(string.gsub(line, ";.*", ""), 16)
|
||||||
|
if not size then return nil, "invalid chunk size" end
|
||||||
|
-- was it the last chunk?
|
||||||
|
if size > 0 then
|
||||||
|
-- if not, get chunk and skip terminating CRLF
|
||||||
|
local chunk, err, part = sock:receive(size)
|
||||||
|
if chunk then sock:receive() end
|
||||||
|
return chunk, err
|
||||||
|
else
|
||||||
|
-- if it was, read trailers into headers table
|
||||||
|
headers, err = receiveheaders(sock, headers)
|
||||||
|
if not headers then return nil, err end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
socket.sinkt["http-chunked"] = function(sock)
|
||||||
|
return base.setmetatable({
|
||||||
|
getfd = function() return sock:getfd() end,
|
||||||
|
dirty = function() return sock:dirty() end
|
||||||
|
}, {
|
||||||
|
__call = function(self, chunk, err)
|
||||||
|
if not chunk then return sock:send("0\r\n\r\n") end
|
||||||
|
local size = string.format("%X\r\n", string.len(chunk))
|
||||||
|
return sock:send(size .. chunk .. "\r\n")
|
||||||
|
end
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Low level HTTP API
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
local metat = { __index = {} }
|
||||||
|
|
||||||
|
function _M.open(host, port, create)
|
||||||
|
-- create socket with user connect function, or with default
|
||||||
|
local c = socket.try((create or socket.tcp)())
|
||||||
|
local h = base.setmetatable({ c = c }, metat)
|
||||||
|
-- create finalized try
|
||||||
|
h.try = socket.newtry(function() h:close() end)
|
||||||
|
-- set timeout before connecting
|
||||||
|
h.try(c:settimeout(_M.TIMEOUT))
|
||||||
|
h.try(c:connect(host, port or _M.PORT))
|
||||||
|
-- here everything worked
|
||||||
|
return h
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:sendrequestline(method, uri)
|
||||||
|
local reqline = string.format("%s %s HTTP/1.1\r\n", method or "GET", uri)
|
||||||
|
return self.try(self.c:send(reqline))
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:sendheaders(tosend)
|
||||||
|
local canonic = headers.canonic
|
||||||
|
local h = "\r\n"
|
||||||
|
for f, v in base.pairs(tosend) do
|
||||||
|
h = (canonic[f] or f) .. ": " .. v .. "\r\n" .. h
|
||||||
|
end
|
||||||
|
self.try(self.c:send(h))
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:sendbody(headers, source, step)
|
||||||
|
source = source or ltn12.source.empty()
|
||||||
|
step = step or ltn12.pump.step
|
||||||
|
-- if we don't know the size in advance, send chunked and hope for the best
|
||||||
|
local mode = "http-chunked"
|
||||||
|
if headers["content-length"] then mode = "keep-open" end
|
||||||
|
return self.try(ltn12.pump.all(source, socket.sink(mode, self.c), step))
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:receivestatusline()
|
||||||
|
local status = self.try(self.c:receive(5))
|
||||||
|
-- identify HTTP/0.9 responses, which do not contain a status line
|
||||||
|
-- this is just a heuristic, but is what the RFC recommends
|
||||||
|
if status ~= "HTTP/" then return nil, status end
|
||||||
|
-- otherwise proceed reading a status line
|
||||||
|
status = self.try(self.c:receive("*l", status))
|
||||||
|
local code = socket.skip(2, string.find(status, "HTTP/%d*%.%d* (%d%d%d)"))
|
||||||
|
return self.try(base.tonumber(code), status)
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:receiveheaders()
|
||||||
|
return self.try(receiveheaders(self.c))
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:receivebody(headers, sink, step)
|
||||||
|
sink = sink or ltn12.sink.null()
|
||||||
|
step = step or ltn12.pump.step
|
||||||
|
local length = base.tonumber(headers["content-length"])
|
||||||
|
local t = headers["transfer-encoding"] -- shortcut
|
||||||
|
local mode = "default" -- connection close
|
||||||
|
if t and t ~= "identity" then mode = "http-chunked"
|
||||||
|
elseif base.tonumber(headers["content-length"]) then mode = "by-length" end
|
||||||
|
return self.try(ltn12.pump.all(socket.source(mode, self.c, length),
|
||||||
|
sink, step))
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:receive09body(status, sink, step)
|
||||||
|
local source = ltn12.source.rewind(socket.source("until-closed", self.c))
|
||||||
|
source(status)
|
||||||
|
return self.try(ltn12.pump.all(source, sink, step))
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:close()
|
||||||
|
return self.c:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- High level HTTP API
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
local function adjusturi(reqt)
|
||||||
|
local u = reqt
|
||||||
|
-- if there is a proxy, we need the full url. otherwise, just a part.
|
||||||
|
if not reqt.proxy and not _M.PROXY then
|
||||||
|
u = {
|
||||||
|
path = socket.try(reqt.path, "invalid path 'nil'"),
|
||||||
|
params = reqt.params,
|
||||||
|
query = reqt.query,
|
||||||
|
fragment = reqt.fragment
|
||||||
|
}
|
||||||
|
end
|
||||||
|
return url.build(u)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function adjustproxy(reqt)
|
||||||
|
local proxy = reqt.proxy or _M.PROXY
|
||||||
|
if proxy then
|
||||||
|
proxy = url.parse(proxy)
|
||||||
|
return proxy.host, proxy.port or 3128
|
||||||
|
else
|
||||||
|
return reqt.host, reqt.port
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function adjustheaders(reqt)
|
||||||
|
-- default headers
|
||||||
|
local host = reqt.host
|
||||||
|
if reqt.port then host = host .. ":" .. reqt.port end
|
||||||
|
local lower = {
|
||||||
|
["user-agent"] = _M.USERAGENT,
|
||||||
|
["host"] = host,
|
||||||
|
["connection"] = "close, TE",
|
||||||
|
["te"] = "trailers"
|
||||||
|
}
|
||||||
|
-- if we have authentication information, pass it along
|
||||||
|
if reqt.user and reqt.password then
|
||||||
|
lower["authorization"] =
|
||||||
|
"Basic " .. (mime.b64(reqt.user .. ":" .. reqt.password))
|
||||||
|
end
|
||||||
|
-- override with user headers
|
||||||
|
for i,v in base.pairs(reqt.headers or lower) do
|
||||||
|
lower[string.lower(i)] = v
|
||||||
|
end
|
||||||
|
return lower
|
||||||
|
end
|
||||||
|
|
||||||
|
-- default url parts
|
||||||
|
local default = {
|
||||||
|
host = "",
|
||||||
|
port = _M.PORT,
|
||||||
|
path ="/",
|
||||||
|
scheme = "http"
|
||||||
|
}
|
||||||
|
|
||||||
|
local function adjustrequest(reqt)
|
||||||
|
-- parse url if provided
|
||||||
|
local nreqt = reqt.url and url.parse(reqt.url, default) or {}
|
||||||
|
-- explicit components override url
|
||||||
|
for i,v in base.pairs(reqt) do nreqt[i] = v end
|
||||||
|
if nreqt.port == "" then nreqt.port = 80 end
|
||||||
|
socket.try(nreqt.host and nreqt.host ~= "",
|
||||||
|
"invalid host '" .. base.tostring(nreqt.host) .. "'")
|
||||||
|
-- compute uri if user hasn't overriden
|
||||||
|
nreqt.uri = reqt.uri or adjusturi(nreqt)
|
||||||
|
-- ajust host and port if there is a proxy
|
||||||
|
nreqt.host, nreqt.port = adjustproxy(nreqt)
|
||||||
|
-- adjust headers in request
|
||||||
|
nreqt.headers = adjustheaders(nreqt)
|
||||||
|
return nreqt
|
||||||
|
end
|
||||||
|
|
||||||
|
local function shouldredirect(reqt, code, headers)
|
||||||
|
return headers.location and
|
||||||
|
string.gsub(headers.location, "%s", "") ~= "" and
|
||||||
|
(reqt.redirect ~= false) and
|
||||||
|
(code == 301 or code == 302 or code == 303 or code == 307) and
|
||||||
|
(not reqt.method or reqt.method == "GET" or reqt.method == "HEAD")
|
||||||
|
and (not reqt.nredirects or reqt.nredirects < 5)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function shouldreceivebody(reqt, code)
|
||||||
|
if reqt.method == "HEAD" then return nil end
|
||||||
|
if code == 204 or code == 304 then return nil end
|
||||||
|
if code >= 100 and code < 200 then return nil end
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- forward declarations
|
||||||
|
local trequest, tredirect
|
||||||
|
|
||||||
|
--[[local]] function tredirect(reqt, location)
|
||||||
|
local result, code, headers, status = trequest {
|
||||||
|
-- the RFC says the redirect URL has to be absolute, but some
|
||||||
|
-- servers do not respect that
|
||||||
|
url = url.absolute(reqt.url, location),
|
||||||
|
source = reqt.source,
|
||||||
|
sink = reqt.sink,
|
||||||
|
headers = reqt.headers,
|
||||||
|
proxy = reqt.proxy,
|
||||||
|
nredirects = (reqt.nredirects or 0) + 1,
|
||||||
|
create = reqt.create
|
||||||
|
}
|
||||||
|
-- pass location header back as a hint we redirected
|
||||||
|
headers = headers or {}
|
||||||
|
headers.location = headers.location or location
|
||||||
|
return result, code, headers, status
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[local]] function trequest(reqt)
|
||||||
|
-- we loop until we get what we want, or
|
||||||
|
-- until we are sure there is no way to get it
|
||||||
|
local nreqt = adjustrequest(reqt)
|
||||||
|
local h = _M.open(nreqt.host, nreqt.port, nreqt.create)
|
||||||
|
-- send request line and headers
|
||||||
|
h:sendrequestline(nreqt.method, nreqt.uri)
|
||||||
|
h:sendheaders(nreqt.headers)
|
||||||
|
-- if there is a body, send it
|
||||||
|
if nreqt.source then
|
||||||
|
h:sendbody(nreqt.headers, nreqt.source, nreqt.step)
|
||||||
|
end
|
||||||
|
local code, status = h:receivestatusline()
|
||||||
|
-- if it is an HTTP/0.9 server, simply get the body and we are done
|
||||||
|
if not code then
|
||||||
|
h:receive09body(status, nreqt.sink, nreqt.step)
|
||||||
|
return 1, 200
|
||||||
|
end
|
||||||
|
local headers
|
||||||
|
-- ignore any 100-continue messages
|
||||||
|
while code == 100 do
|
||||||
|
headers = h:receiveheaders()
|
||||||
|
code, status = h:receivestatusline()
|
||||||
|
end
|
||||||
|
headers = h:receiveheaders()
|
||||||
|
-- at this point we should have a honest reply from the server
|
||||||
|
-- we can't redirect if we already used the source, so we report the error
|
||||||
|
if shouldredirect(nreqt, code, headers) and not nreqt.source then
|
||||||
|
h:close()
|
||||||
|
return tredirect(reqt, headers.location)
|
||||||
|
end
|
||||||
|
-- here we are finally done
|
||||||
|
if shouldreceivebody(nreqt, code) then
|
||||||
|
h:receivebody(headers, nreqt.sink, nreqt.step)
|
||||||
|
end
|
||||||
|
h:close()
|
||||||
|
return 1, code, headers, status
|
||||||
|
end
|
||||||
|
|
||||||
|
local function srequest(u, b)
|
||||||
|
local t = {}
|
||||||
|
local reqt = {
|
||||||
|
url = u,
|
||||||
|
sink = ltn12.sink.table(t)
|
||||||
|
}
|
||||||
|
if b then
|
||||||
|
reqt.source = ltn12.source.string(b)
|
||||||
|
reqt.headers = {
|
||||||
|
["content-length"] = string.len(b),
|
||||||
|
["content-type"] = "application/x-www-form-urlencoded"
|
||||||
|
}
|
||||||
|
reqt.method = "POST"
|
||||||
|
end
|
||||||
|
local code, headers, status = socket.skip(1, trequest(reqt))
|
||||||
|
return table.concat(t), code, headers, status
|
||||||
|
end
|
||||||
|
|
||||||
|
_M.request = socket.protect(function(reqt, body)
|
||||||
|
if base.type(reqt) == "string" then return srequest(reqt, body)
|
||||||
|
else return trequest(reqt) end
|
||||||
|
end)
|
||||||
|
|
||||||
|
return _M
|
256
Me_Lua/r13/socket/smtp.lua
Normal file
256
Me_Lua/r13/socket/smtp.lua
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- SMTP client support for the Lua language.
|
||||||
|
-- LuaSocket toolkit.
|
||||||
|
-- Author: Diego Nehab
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Declare module and import dependencies
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
local base = _G
|
||||||
|
local coroutine = require("coroutine")
|
||||||
|
local string = require("string")
|
||||||
|
local math = require("math")
|
||||||
|
local os = require("os")
|
||||||
|
local socket = require("socket")
|
||||||
|
local tp = require("socket.tp")
|
||||||
|
local ltn12 = require("ltn12")
|
||||||
|
local headers = require("socket.headers")
|
||||||
|
local mime = require("mime")
|
||||||
|
|
||||||
|
socket.smtp = {}
|
||||||
|
local _M = socket.smtp
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Program constants
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- timeout for connection
|
||||||
|
_M.TIMEOUT = 60
|
||||||
|
-- default server used to send e-mails
|
||||||
|
_M.SERVER = "localhost"
|
||||||
|
-- default port
|
||||||
|
_M.PORT = 25
|
||||||
|
-- domain used in HELO command and default sendmail
|
||||||
|
-- If we are under a CGI, try to get from environment
|
||||||
|
_M.DOMAIN = os.getenv("SERVER_NAME") or "localhost"
|
||||||
|
-- default time zone (means we don't know)
|
||||||
|
_M.ZONE = "-0000"
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
-- Low level SMTP API
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
local metat = { __index = {} }
|
||||||
|
|
||||||
|
function metat.__index:greet(domain)
|
||||||
|
self.try(self.tp:check("2.."))
|
||||||
|
self.try(self.tp:command("EHLO", domain or _M.DOMAIN))
|
||||||
|
return socket.skip(1, self.try(self.tp:check("2..")))
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:mail(from)
|
||||||
|
self.try(self.tp:command("MAIL", "FROM:" .. from))
|
||||||
|
return self.try(self.tp:check("2.."))
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:rcpt(to)
|
||||||
|
self.try(self.tp:command("RCPT", "TO:" .. to))
|
||||||
|
return self.try(self.tp:check("2.."))
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:data(src, step)
|
||||||
|
self.try(self.tp:command("DATA"))
|
||||||
|
self.try(self.tp:check("3.."))
|
||||||
|
self.try(self.tp:source(src, step))
|
||||||
|
self.try(self.tp:send("\r\n.\r\n"))
|
||||||
|
return self.try(self.tp:check("2.."))
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:quit()
|
||||||
|
self.try(self.tp:command("QUIT"))
|
||||||
|
return self.try(self.tp:check("2.."))
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:close()
|
||||||
|
return self.tp:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:login(user, password)
|
||||||
|
self.try(self.tp:command("AUTH", "LOGIN"))
|
||||||
|
self.try(self.tp:check("3.."))
|
||||||
|
self.try(self.tp:send(mime.b64(user) .. "\r\n"))
|
||||||
|
self.try(self.tp:check("3.."))
|
||||||
|
self.try(self.tp:send(mime.b64(password) .. "\r\n"))
|
||||||
|
return self.try(self.tp:check("2.."))
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:plain(user, password)
|
||||||
|
local auth = "PLAIN " .. mime.b64("\0" .. user .. "\0" .. password)
|
||||||
|
self.try(self.tp:command("AUTH", auth))
|
||||||
|
return self.try(self.tp:check("2.."))
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:auth(user, password, ext)
|
||||||
|
if not user or not password then return 1 end
|
||||||
|
if string.find(ext, "AUTH[^\n]+LOGIN") then
|
||||||
|
return self:login(user, password)
|
||||||
|
elseif string.find(ext, "AUTH[^\n]+PLAIN") then
|
||||||
|
return self:plain(user, password)
|
||||||
|
else
|
||||||
|
self.try(nil, "authentication not supported")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- send message or throw an exception
|
||||||
|
function metat.__index:send(mailt)
|
||||||
|
self:mail(mailt.from)
|
||||||
|
if base.type(mailt.rcpt) == "table" then
|
||||||
|
for i,v in base.ipairs(mailt.rcpt) do
|
||||||
|
self:rcpt(v)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self:rcpt(mailt.rcpt)
|
||||||
|
end
|
||||||
|
self:data(ltn12.source.chain(mailt.source, mime.stuff()), mailt.step)
|
||||||
|
end
|
||||||
|
|
||||||
|
function _M.open(server, port, create)
|
||||||
|
local tp = socket.try(tp.connect(server or _M.SERVER, port or _M.PORT,
|
||||||
|
_M.TIMEOUT, create))
|
||||||
|
local s = base.setmetatable({tp = tp}, metat)
|
||||||
|
-- make sure tp is closed if we get an exception
|
||||||
|
s.try = socket.newtry(function()
|
||||||
|
s:close()
|
||||||
|
end)
|
||||||
|
return s
|
||||||
|
end
|
||||||
|
|
||||||
|
-- convert headers to lowercase
|
||||||
|
local function lower_headers(headers)
|
||||||
|
local lower = {}
|
||||||
|
for i,v in base.pairs(headers or lower) do
|
||||||
|
lower[string.lower(i)] = v
|
||||||
|
end
|
||||||
|
return lower
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
-- Multipart message source
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- returns a hopefully unique mime boundary
|
||||||
|
local seqno = 0
|
||||||
|
local function newboundary()
|
||||||
|
seqno = seqno + 1
|
||||||
|
return string.format('%s%05d==%05u', os.date('%d%m%Y%H%M%S'),
|
||||||
|
math.random(0, 99999), seqno)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- send_message forward declaration
|
||||||
|
local send_message
|
||||||
|
|
||||||
|
-- yield the headers all at once, it's faster
|
||||||
|
local function send_headers(tosend)
|
||||||
|
local canonic = headers.canonic
|
||||||
|
local h = "\r\n"
|
||||||
|
for f,v in base.pairs(tosend) do
|
||||||
|
h = (canonic[f] or f) .. ': ' .. v .. "\r\n" .. h
|
||||||
|
end
|
||||||
|
coroutine.yield(h)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- yield multipart message body from a multipart message table
|
||||||
|
local function send_multipart(mesgt)
|
||||||
|
-- make sure we have our boundary and send headers
|
||||||
|
local bd = newboundary()
|
||||||
|
local headers = lower_headers(mesgt.headers or {})
|
||||||
|
headers['content-type'] = headers['content-type'] or 'multipart/mixed'
|
||||||
|
headers['content-type'] = headers['content-type'] ..
|
||||||
|
'; boundary="' .. bd .. '"'
|
||||||
|
send_headers(headers)
|
||||||
|
-- send preamble
|
||||||
|
if mesgt.body.preamble then
|
||||||
|
coroutine.yield(mesgt.body.preamble)
|
||||||
|
coroutine.yield("\r\n")
|
||||||
|
end
|
||||||
|
-- send each part separated by a boundary
|
||||||
|
for i, m in base.ipairs(mesgt.body) do
|
||||||
|
coroutine.yield("\r\n--" .. bd .. "\r\n")
|
||||||
|
send_message(m)
|
||||||
|
end
|
||||||
|
-- send last boundary
|
||||||
|
coroutine.yield("\r\n--" .. bd .. "--\r\n\r\n")
|
||||||
|
-- send epilogue
|
||||||
|
if mesgt.body.epilogue then
|
||||||
|
coroutine.yield(mesgt.body.epilogue)
|
||||||
|
coroutine.yield("\r\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- yield message body from a source
|
||||||
|
local function send_source(mesgt)
|
||||||
|
-- make sure we have a content-type
|
||||||
|
local headers = lower_headers(mesgt.headers or {})
|
||||||
|
headers['content-type'] = headers['content-type'] or
|
||||||
|
'text/plain; charset="iso-8859-1"'
|
||||||
|
send_headers(headers)
|
||||||
|
-- send body from source
|
||||||
|
while true do
|
||||||
|
local chunk, err = mesgt.body()
|
||||||
|
if err then coroutine.yield(nil, err)
|
||||||
|
elseif chunk then coroutine.yield(chunk)
|
||||||
|
else break end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- yield message body from a string
|
||||||
|
local function send_string(mesgt)
|
||||||
|
-- make sure we have a content-type
|
||||||
|
local headers = lower_headers(mesgt.headers or {})
|
||||||
|
headers['content-type'] = headers['content-type'] or
|
||||||
|
'text/plain; charset="iso-8859-1"'
|
||||||
|
send_headers(headers)
|
||||||
|
-- send body from string
|
||||||
|
coroutine.yield(mesgt.body)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- message source
|
||||||
|
function send_message(mesgt)
|
||||||
|
if base.type(mesgt.body) == "table" then send_multipart(mesgt)
|
||||||
|
elseif base.type(mesgt.body) == "function" then send_source(mesgt)
|
||||||
|
else send_string(mesgt) end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- set defaul headers
|
||||||
|
local function adjust_headers(mesgt)
|
||||||
|
local lower = lower_headers(mesgt.headers)
|
||||||
|
lower["date"] = lower["date"] or
|
||||||
|
os.date("!%a, %d %b %Y %H:%M:%S ") .. (mesgt.zone or _M.ZONE)
|
||||||
|
lower["x-mailer"] = lower["x-mailer"] or socket._VERSION
|
||||||
|
-- this can't be overriden
|
||||||
|
lower["mime-version"] = "1.0"
|
||||||
|
return lower
|
||||||
|
end
|
||||||
|
|
||||||
|
function _M.message(mesgt)
|
||||||
|
mesgt.headers = adjust_headers(mesgt)
|
||||||
|
-- create and return message source
|
||||||
|
local co = coroutine.create(function() send_message(mesgt) end)
|
||||||
|
return function()
|
||||||
|
local ret, a, b = coroutine.resume(co)
|
||||||
|
if ret then return a, b
|
||||||
|
else return nil, a end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
-- High level SMTP API
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
_M.send = socket.protect(function(mailt)
|
||||||
|
local s = _M.open(mailt.server, mailt.port, mailt.create)
|
||||||
|
local ext = s:greet(mailt.domain)
|
||||||
|
s:auth(mailt.user, mailt.password, ext)
|
||||||
|
s:send(mailt)
|
||||||
|
s:quit()
|
||||||
|
return s:close()
|
||||||
|
end)
|
||||||
|
|
||||||
|
return _M
|
126
Me_Lua/r13/socket/tp.lua
Normal file
126
Me_Lua/r13/socket/tp.lua
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Unified SMTP/FTP subsystem
|
||||||
|
-- LuaSocket toolkit.
|
||||||
|
-- Author: Diego Nehab
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Declare module and import dependencies
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
local base = _G
|
||||||
|
local string = require("string")
|
||||||
|
local socket = require("socket")
|
||||||
|
local ltn12 = require("ltn12")
|
||||||
|
|
||||||
|
socket.tp = {}
|
||||||
|
local _M = socket.tp
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Program constants
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
_M.TIMEOUT = 60
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Implementation
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- gets server reply (works for SMTP and FTP)
|
||||||
|
local function get_reply(c)
|
||||||
|
local code, current, sep
|
||||||
|
local line, err = c:receive()
|
||||||
|
local reply = line
|
||||||
|
if err then return nil, err end
|
||||||
|
code, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
|
||||||
|
if not code then return nil, "invalid server reply" end
|
||||||
|
if sep == "-" then -- reply is multiline
|
||||||
|
repeat
|
||||||
|
line, err = c:receive()
|
||||||
|
if err then return nil, err end
|
||||||
|
current, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
|
||||||
|
reply = reply .. "\n" .. line
|
||||||
|
-- reply ends with same code
|
||||||
|
until code == current and sep == " "
|
||||||
|
end
|
||||||
|
return code, reply
|
||||||
|
end
|
||||||
|
|
||||||
|
-- metatable for sock object
|
||||||
|
local metat = { __index = {} }
|
||||||
|
|
||||||
|
function metat.__index:check(ok)
|
||||||
|
local code, reply = get_reply(self.c)
|
||||||
|
if not code then return nil, reply end
|
||||||
|
if base.type(ok) ~= "function" then
|
||||||
|
if base.type(ok) == "table" then
|
||||||
|
for i, v in base.ipairs(ok) do
|
||||||
|
if string.find(code, v) then
|
||||||
|
return base.tonumber(code), reply
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil, reply
|
||||||
|
else
|
||||||
|
if string.find(code, ok) then return base.tonumber(code), reply
|
||||||
|
else return nil, reply end
|
||||||
|
end
|
||||||
|
else return ok(base.tonumber(code), reply) end
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:command(cmd, arg)
|
||||||
|
cmd = string.upper(cmd)
|
||||||
|
if arg then
|
||||||
|
return self.c:send(cmd .. " " .. arg.. "\r\n")
|
||||||
|
else
|
||||||
|
return self.c:send(cmd .. "\r\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:sink(snk, pat)
|
||||||
|
local chunk, err = c:receive(pat)
|
||||||
|
return snk(chunk, err)
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:send(data)
|
||||||
|
return self.c:send(data)
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:receive(pat)
|
||||||
|
return self.c:receive(pat)
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:getfd()
|
||||||
|
return self.c:getfd()
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:dirty()
|
||||||
|
return self.c:dirty()
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:getcontrol()
|
||||||
|
return self.c
|
||||||
|
end
|
||||||
|
|
||||||
|
function metat.__index:source(source, step)
|
||||||
|
local sink = socket.sink("keep-open", self.c)
|
||||||
|
local ret, err = ltn12.pump.all(source, sink, step or ltn12.pump.step)
|
||||||
|
return ret, err
|
||||||
|
end
|
||||||
|
|
||||||
|
-- closes the underlying c
|
||||||
|
function metat.__index:close()
|
||||||
|
self.c:close()
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- connect with server and return c object
|
||||||
|
function _M.connect(host, port, timeout, create)
|
||||||
|
local c, e = (create or socket.tcp)()
|
||||||
|
if not c then return nil, e end
|
||||||
|
c:settimeout(timeout or _M.TIMEOUT)
|
||||||
|
local r, e = c:connect(host, port)
|
||||||
|
if not r then
|
||||||
|
c:close()
|
||||||
|
return nil, e
|
||||||
|
end
|
||||||
|
return base.setmetatable({c = c}, metat)
|
||||||
|
end
|
||||||
|
|
||||||
|
return _M
|
307
Me_Lua/r13/socket/url.lua
Normal file
307
Me_Lua/r13/socket/url.lua
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- URI parsing, composition and relative URL resolution
|
||||||
|
-- LuaSocket toolkit.
|
||||||
|
-- Author: Diego Nehab
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Declare module
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
local string = require("string")
|
||||||
|
local base = _G
|
||||||
|
local table = require("table")
|
||||||
|
local socket = require("socket")
|
||||||
|
|
||||||
|
socket.url = {}
|
||||||
|
local _M = socket.url
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Module version
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
_M._VERSION = "URL 1.0.3"
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Encodes a string into its escaped hexadecimal representation
|
||||||
|
-- Input
|
||||||
|
-- s: binary string to be encoded
|
||||||
|
-- Returns
|
||||||
|
-- escaped representation of string binary
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
function _M.escape(s)
|
||||||
|
return (string.gsub(s, "([^A-Za-z0-9_])", function(c)
|
||||||
|
return string.format("%%%02x", string.byte(c))
|
||||||
|
end))
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Protects a path segment, to prevent it from interfering with the
|
||||||
|
-- url parsing.
|
||||||
|
-- Input
|
||||||
|
-- s: binary string to be encoded
|
||||||
|
-- Returns
|
||||||
|
-- escaped representation of string binary
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
local function make_set(t)
|
||||||
|
local s = {}
|
||||||
|
for i,v in base.ipairs(t) do
|
||||||
|
s[t[i]] = 1
|
||||||
|
end
|
||||||
|
return s
|
||||||
|
end
|
||||||
|
|
||||||
|
-- these are allowed withing a path segment, along with alphanum
|
||||||
|
-- other characters must be escaped
|
||||||
|
local segment_set = make_set {
|
||||||
|
"-", "_", ".", "!", "~", "*", "'", "(",
|
||||||
|
")", ":", "@", "&", "=", "+", "$", ",",
|
||||||
|
}
|
||||||
|
|
||||||
|
local function protect_segment(s)
|
||||||
|
return string.gsub(s, "([^A-Za-z0-9_])", function (c)
|
||||||
|
if segment_set[c] then return c
|
||||||
|
else return string.format("%%%02x", string.byte(c)) end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Encodes a string into its escaped hexadecimal representation
|
||||||
|
-- Input
|
||||||
|
-- s: binary string to be encoded
|
||||||
|
-- Returns
|
||||||
|
-- escaped representation of string binary
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
function _M.unescape(s)
|
||||||
|
return (string.gsub(s, "%%(%x%x)", function(hex)
|
||||||
|
return string.char(base.tonumber(hex, 16))
|
||||||
|
end))
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Builds a path from a base path and a relative path
|
||||||
|
-- Input
|
||||||
|
-- base_path
|
||||||
|
-- relative_path
|
||||||
|
-- Returns
|
||||||
|
-- corresponding absolute path
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
local function absolute_path(base_path, relative_path)
|
||||||
|
if string.sub(relative_path, 1, 1) == "/" then return relative_path end
|
||||||
|
local path = string.gsub(base_path, "[^/]*$", "")
|
||||||
|
path = path .. relative_path
|
||||||
|
path = string.gsub(path, "([^/]*%./)", function (s)
|
||||||
|
if s ~= "./" then return s else return "" end
|
||||||
|
end)
|
||||||
|
path = string.gsub(path, "/%.$", "/")
|
||||||
|
local reduced
|
||||||
|
while reduced ~= path do
|
||||||
|
reduced = path
|
||||||
|
path = string.gsub(reduced, "([^/]*/%.%./)", function (s)
|
||||||
|
if s ~= "../../" then return "" else return s end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
path = string.gsub(reduced, "([^/]*/%.%.)$", function (s)
|
||||||
|
if s ~= "../.." then return "" else return s end
|
||||||
|
end)
|
||||||
|
return path
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Parses a url and returns a table with all its parts according to RFC 2396
|
||||||
|
-- The following grammar describes the names given to the URL parts
|
||||||
|
-- <url> ::= <scheme>://<authority>/<path>;<params>?<query>#<fragment>
|
||||||
|
-- <authority> ::= <userinfo>@<host>:<port>
|
||||||
|
-- <userinfo> ::= <user>[:<password>]
|
||||||
|
-- <path> :: = {<segment>/}<segment>
|
||||||
|
-- Input
|
||||||
|
-- url: uniform resource locator of request
|
||||||
|
-- default: table with default values for each field
|
||||||
|
-- Returns
|
||||||
|
-- table with the following fields, where RFC naming conventions have
|
||||||
|
-- been preserved:
|
||||||
|
-- scheme, authority, userinfo, user, password, host, port,
|
||||||
|
-- path, params, query, fragment
|
||||||
|
-- Obs:
|
||||||
|
-- the leading '/' in {/<path>} is considered part of <path>
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
function _M.parse(url, default)
|
||||||
|
-- initialize default parameters
|
||||||
|
local parsed = {}
|
||||||
|
for i,v in base.pairs(default or parsed) do parsed[i] = v end
|
||||||
|
-- empty url is parsed to nil
|
||||||
|
if not url or url == "" then return nil, "invalid url" end
|
||||||
|
-- remove whitespace
|
||||||
|
-- url = string.gsub(url, "%s", "")
|
||||||
|
-- get fragment
|
||||||
|
url = string.gsub(url, "#(.*)$", function(f)
|
||||||
|
parsed.fragment = f
|
||||||
|
return ""
|
||||||
|
end)
|
||||||
|
-- get scheme
|
||||||
|
url = string.gsub(url, "^([%w][%w%+%-%.]*)%:",
|
||||||
|
function(s) parsed.scheme = s; return "" end)
|
||||||
|
-- get authority
|
||||||
|
url = string.gsub(url, "^//([^/]*)", function(n)
|
||||||
|
parsed.authority = n
|
||||||
|
return ""
|
||||||
|
end)
|
||||||
|
-- get query string
|
||||||
|
url = string.gsub(url, "%?(.*)", function(q)
|
||||||
|
parsed.query = q
|
||||||
|
return ""
|
||||||
|
end)
|
||||||
|
-- get params
|
||||||
|
url = string.gsub(url, "%;(.*)", function(p)
|
||||||
|
parsed.params = p
|
||||||
|
return ""
|
||||||
|
end)
|
||||||
|
-- path is whatever was left
|
||||||
|
if url ~= "" then parsed.path = url end
|
||||||
|
local authority = parsed.authority
|
||||||
|
if not authority then return parsed end
|
||||||
|
authority = string.gsub(authority,"^([^@]*)@",
|
||||||
|
function(u) parsed.userinfo = u; return "" end)
|
||||||
|
authority = string.gsub(authority, ":([^:%]]*)$",
|
||||||
|
function(p) parsed.port = p; return "" end)
|
||||||
|
if authority ~= "" then
|
||||||
|
-- IPv6?
|
||||||
|
parsed.host = string.match(authority, "^%[(.+)%]$") or authority
|
||||||
|
end
|
||||||
|
local userinfo = parsed.userinfo
|
||||||
|
if not userinfo then return parsed end
|
||||||
|
userinfo = string.gsub(userinfo, ":([^:]*)$",
|
||||||
|
function(p) parsed.password = p; return "" end)
|
||||||
|
parsed.user = userinfo
|
||||||
|
return parsed
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Rebuilds a parsed URL from its components.
|
||||||
|
-- Components are protected if any reserved or unallowed characters are found
|
||||||
|
-- Input
|
||||||
|
-- parsed: parsed URL, as returned by parse
|
||||||
|
-- Returns
|
||||||
|
-- a stringing with the corresponding URL
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
function _M.build(parsed)
|
||||||
|
local ppath = _M.parse_path(parsed.path or "")
|
||||||
|
local url = _M.build_path(ppath)
|
||||||
|
if parsed.params then url = url .. ";" .. parsed.params end
|
||||||
|
if parsed.query then url = url .. "?" .. parsed.query end
|
||||||
|
local authority = parsed.authority
|
||||||
|
if parsed.host then
|
||||||
|
authority = parsed.host
|
||||||
|
if string.find(authority, ":") then -- IPv6?
|
||||||
|
authority = "[" .. authority .. "]"
|
||||||
|
end
|
||||||
|
if parsed.port then authority = authority .. ":" .. parsed.port end
|
||||||
|
local userinfo = parsed.userinfo
|
||||||
|
if parsed.user then
|
||||||
|
userinfo = parsed.user
|
||||||
|
if parsed.password then
|
||||||
|
userinfo = userinfo .. ":" .. parsed.password
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if userinfo then authority = userinfo .. "@" .. authority end
|
||||||
|
end
|
||||||
|
if authority then url = "//" .. authority .. url end
|
||||||
|
if parsed.scheme then url = parsed.scheme .. ":" .. url end
|
||||||
|
if parsed.fragment then url = url .. "#" .. parsed.fragment end
|
||||||
|
-- url = string.gsub(url, "%s", "")
|
||||||
|
return url
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Builds a absolute URL from a base and a relative URL according to RFC 2396
|
||||||
|
-- Input
|
||||||
|
-- base_url
|
||||||
|
-- relative_url
|
||||||
|
-- Returns
|
||||||
|
-- corresponding absolute url
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
function _M.absolute(base_url, relative_url)
|
||||||
|
if base.type(base_url) == "table" then
|
||||||
|
base_parsed = base_url
|
||||||
|
base_url = _M.build(base_parsed)
|
||||||
|
else
|
||||||
|
base_parsed = _M.parse(base_url)
|
||||||
|
end
|
||||||
|
local relative_parsed = _M.parse(relative_url)
|
||||||
|
if not base_parsed then return relative_url
|
||||||
|
elseif not relative_parsed then return base_url
|
||||||
|
elseif relative_parsed.scheme then return relative_url
|
||||||
|
else
|
||||||
|
relative_parsed.scheme = base_parsed.scheme
|
||||||
|
if not relative_parsed.authority then
|
||||||
|
relative_parsed.authority = base_parsed.authority
|
||||||
|
if not relative_parsed.path then
|
||||||
|
relative_parsed.path = base_parsed.path
|
||||||
|
if not relative_parsed.params then
|
||||||
|
relative_parsed.params = base_parsed.params
|
||||||
|
if not relative_parsed.query then
|
||||||
|
relative_parsed.query = base_parsed.query
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
relative_parsed.path = absolute_path(base_parsed.path or "",
|
||||||
|
relative_parsed.path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return _M.build(relative_parsed)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Breaks a path into its segments, unescaping the segments
|
||||||
|
-- Input
|
||||||
|
-- path
|
||||||
|
-- Returns
|
||||||
|
-- segment: a table with one entry per segment
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
function _M.parse_path(path)
|
||||||
|
local parsed = {}
|
||||||
|
path = path or ""
|
||||||
|
--path = string.gsub(path, "%s", "")
|
||||||
|
string.gsub(path, "([^/]+)", function (s) table.insert(parsed, s) end)
|
||||||
|
for i = 1, #parsed do
|
||||||
|
parsed[i] = _M.unescape(parsed[i])
|
||||||
|
end
|
||||||
|
if string.sub(path, 1, 1) == "/" then parsed.is_absolute = 1 end
|
||||||
|
if string.sub(path, -1, -1) == "/" then parsed.is_directory = 1 end
|
||||||
|
return parsed
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Builds a path component from its segments, escaping protected characters.
|
||||||
|
-- Input
|
||||||
|
-- parsed: path segments
|
||||||
|
-- unsafe: if true, segments are not protected before path is built
|
||||||
|
-- Returns
|
||||||
|
-- path: corresponding path stringing
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
function _M.build_path(parsed, unsafe)
|
||||||
|
local path = ""
|
||||||
|
local n = #parsed
|
||||||
|
if unsafe then
|
||||||
|
for i = 1, n-1 do
|
||||||
|
path = path .. parsed[i]
|
||||||
|
path = path .. "/"
|
||||||
|
end
|
||||||
|
if n > 0 then
|
||||||
|
path = path .. parsed[n]
|
||||||
|
if parsed.is_directory then path = path .. "/" end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for i = 1, n-1 do
|
||||||
|
path = path .. protect_segment(parsed[i])
|
||||||
|
path = path .. "/"
|
||||||
|
end
|
||||||
|
if n > 0 then
|
||||||
|
path = path .. protect_segment(parsed[n])
|
||||||
|
if parsed.is_directory then path = path .. "/" end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if parsed.is_absolute then path = "/" .. path end
|
||||||
|
return path
|
||||||
|
end
|
||||||
|
|
||||||
|
return _M
|
168
Me_Lua/r13/ssl.lua
Normal file
168
Me_Lua/r13/ssl.lua
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- LuaSec 0.5
|
||||||
|
-- Copyright (C) 2006-2014 Bruno Silvestre
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local core = require("ssl.core")
|
||||||
|
local context = require("ssl.context")
|
||||||
|
local x509 = require("ssl.x509")
|
||||||
|
|
||||||
|
module("ssl", package.seeall)
|
||||||
|
|
||||||
|
_VERSION = "0.5.PR"
|
||||||
|
_COPYRIGHT = core.copyright()
|
||||||
|
|
||||||
|
-- Export
|
||||||
|
loadcertificate = x509.load
|
||||||
|
|
||||||
|
-- We must prevent the contexts to be collected before the connections,
|
||||||
|
-- otherwise the C registry will be cleared.
|
||||||
|
local registry = setmetatable({}, {__mode="k"})
|
||||||
|
|
||||||
|
--
|
||||||
|
--
|
||||||
|
--
|
||||||
|
local function optexec(func, param, ctx)
|
||||||
|
if param then
|
||||||
|
if type(param) == "table" then
|
||||||
|
return func(ctx, unpack(param))
|
||||||
|
else
|
||||||
|
return func(ctx, param)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
--
|
||||||
|
--
|
||||||
|
function newcontext(cfg)
|
||||||
|
local succ, msg, ctx
|
||||||
|
-- Create the context
|
||||||
|
ctx, msg = context.create(cfg.protocol)
|
||||||
|
if not ctx then return nil, msg end
|
||||||
|
-- Mode
|
||||||
|
succ, msg = context.setmode(ctx, cfg.mode)
|
||||||
|
if not succ then return nil, msg end
|
||||||
|
-- Load the key
|
||||||
|
if cfg.key then
|
||||||
|
if cfg.password and
|
||||||
|
type(cfg.password) ~= "function" and
|
||||||
|
type(cfg.password) ~= "string"
|
||||||
|
then
|
||||||
|
return nil, "invalid password type"
|
||||||
|
end
|
||||||
|
succ, msg = context.loadkey(ctx, cfg.key, cfg.password)
|
||||||
|
if not succ then return nil, msg end
|
||||||
|
end
|
||||||
|
-- Load the certificate
|
||||||
|
if cfg.certificate then
|
||||||
|
succ, msg = context.loadcert(ctx, cfg.certificate)
|
||||||
|
if not succ then return nil, msg end
|
||||||
|
end
|
||||||
|
-- Load the CA certificates
|
||||||
|
if cfg.cafile or cfg.capath then
|
||||||
|
succ, msg = context.locations(ctx, cfg.cafile, cfg.capath)
|
||||||
|
if not succ then return nil, msg end
|
||||||
|
end
|
||||||
|
-- Set SSL ciphers
|
||||||
|
if cfg.ciphers then
|
||||||
|
succ, msg = context.setcipher(ctx, cfg.ciphers)
|
||||||
|
if not succ then return nil, msg end
|
||||||
|
end
|
||||||
|
-- Set the verification options
|
||||||
|
succ, msg = optexec(context.setverify, cfg.verify, ctx)
|
||||||
|
if not succ then return nil, msg end
|
||||||
|
-- Set SSL options
|
||||||
|
succ, msg = optexec(context.setoptions, cfg.options, ctx)
|
||||||
|
if not succ then return nil, msg end
|
||||||
|
-- Set the depth for certificate verification
|
||||||
|
if cfg.depth then
|
||||||
|
succ, msg = context.setdepth(ctx, cfg.depth)
|
||||||
|
if not succ then return nil, msg end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- NOTE: Setting DH parameters and elliptic curves needs to come after
|
||||||
|
-- setoptions(), in case the user has specified the single_{dh,ecdh}_use
|
||||||
|
-- options.
|
||||||
|
|
||||||
|
-- Set DH parameters
|
||||||
|
if cfg.dhparam then
|
||||||
|
if type(cfg.dhparam) ~= "function" then
|
||||||
|
return nil, "invalid DH parameter type"
|
||||||
|
end
|
||||||
|
context.setdhparam(ctx, cfg.dhparam)
|
||||||
|
end
|
||||||
|
-- Set elliptic curve
|
||||||
|
if cfg.curve then
|
||||||
|
succ, msg = context.setcurve(ctx, cfg.curve)
|
||||||
|
if not succ then return nil, msg end
|
||||||
|
end
|
||||||
|
-- Set extra verification options
|
||||||
|
if cfg.verifyext and ctx.setverifyext then
|
||||||
|
succ, msg = optexec(ctx.setverifyext, cfg.verifyext, ctx)
|
||||||
|
if not succ then return nil, msg end
|
||||||
|
end
|
||||||
|
|
||||||
|
return ctx
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
--
|
||||||
|
--
|
||||||
|
function wrap(sock, cfg)
|
||||||
|
local ctx, msg
|
||||||
|
if type(cfg) == "table" then
|
||||||
|
ctx, msg = newcontext(cfg)
|
||||||
|
if not ctx then return nil, msg end
|
||||||
|
else
|
||||||
|
ctx = cfg
|
||||||
|
end
|
||||||
|
local s, msg = core.create(ctx)
|
||||||
|
if s then
|
||||||
|
core.setfd(s, sock:getfd())
|
||||||
|
sock:setfd(core.invalidfd)
|
||||||
|
registry[s] = ctx
|
||||||
|
return s
|
||||||
|
end
|
||||||
|
return nil, msg
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Extract connection information.
|
||||||
|
--
|
||||||
|
local function info(ssl, field)
|
||||||
|
local str, comp, err, protocol
|
||||||
|
comp, err = core.compression(ssl)
|
||||||
|
if err then
|
||||||
|
return comp, err
|
||||||
|
end
|
||||||
|
-- Avoid parser
|
||||||
|
if field == "compression" then
|
||||||
|
return comp
|
||||||
|
end
|
||||||
|
local info = {compression = comp}
|
||||||
|
str, info.bits, info.algbits, protocol = core.info(ssl)
|
||||||
|
if str then
|
||||||
|
info.cipher, info.protocol, info.key,
|
||||||
|
info.authentication, info.encryption, info.mac =
|
||||||
|
string.match(str,
|
||||||
|
"^(%S+)%s+(%S+)%s+Kx=(%S+)%s+Au=(%S+)%s+Enc=(%S+)%s+Mac=(%S+)")
|
||||||
|
info.export = (string.match(str, "%sexport%s*$") ~= nil)
|
||||||
|
end
|
||||||
|
if protocol then
|
||||||
|
info.protocol = protocol
|
||||||
|
end
|
||||||
|
if field then
|
||||||
|
return info[field]
|
||||||
|
end
|
||||||
|
-- Empty?
|
||||||
|
return ( (next(info)) and info )
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Set method for SSL connections.
|
||||||
|
--
|
||||||
|
core.setmethod("info", info)
|
||||||
|
|
BIN
Me_Lua/r13/ssl.so
Normal file
BIN
Me_Lua/r13/ssl.so
Normal file
Binary file not shown.
138
Me_Lua/r13/ssl/https.lua
Normal file
138
Me_Lua/r13/ssl/https.lua
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
----------------------------------------------------------------------------
|
||||||
|
-- LuaSec 0.5
|
||||||
|
-- Copyright (C) 2009-2014 PUC-Rio
|
||||||
|
--
|
||||||
|
-- Author: Pablo Musa
|
||||||
|
-- Author: Tomas Guisasola
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local socket = require("socket")
|
||||||
|
local ssl = require("ssl")
|
||||||
|
local ltn12 = require("ltn12")
|
||||||
|
local http = require("socket.http")
|
||||||
|
local url = require("socket.url")
|
||||||
|
|
||||||
|
local table = require("table")
|
||||||
|
local string = require("string")
|
||||||
|
|
||||||
|
local try = socket.try
|
||||||
|
local type = type
|
||||||
|
local pairs = pairs
|
||||||
|
local getmetatable = getmetatable
|
||||||
|
|
||||||
|
module("ssl.https")
|
||||||
|
|
||||||
|
_VERSION = "0.5"
|
||||||
|
_COPYRIGHT = "LuaSec 0.5 - Copyright (C) 2009-2014 PUC-Rio"
|
||||||
|
|
||||||
|
-- Default settings
|
||||||
|
PORT = 443
|
||||||
|
|
||||||
|
local cfg = {
|
||||||
|
protocol = "tlsv1",
|
||||||
|
options = "all",
|
||||||
|
verify = "none",
|
||||||
|
}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
-- Auxiliar Functions
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- Insert default HTTPS port.
|
||||||
|
local function default_https_port(u)
|
||||||
|
return url.build(url.parse(u, {port = PORT}))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Convert an URL to a table according to Luasocket needs.
|
||||||
|
local function urlstring_totable(url, body, result_table)
|
||||||
|
url = {
|
||||||
|
url = default_https_port(url),
|
||||||
|
method = body and "POST" or "GET",
|
||||||
|
sink = ltn12.sink.table(result_table)
|
||||||
|
}
|
||||||
|
if body then
|
||||||
|
url.source = ltn12.source.string(body)
|
||||||
|
url.headers = {
|
||||||
|
["content-length"] = #body,
|
||||||
|
["content-type"] = "application/x-www-form-urlencoded",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
return url
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Forward calls to the real connection object.
|
||||||
|
local function reg(conn)
|
||||||
|
local mt = getmetatable(conn.sock).__index
|
||||||
|
for name, method in pairs(mt) do
|
||||||
|
if type(method) == "function" then
|
||||||
|
conn[name] = function (self, ...)
|
||||||
|
return method(self.sock, ...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return a function which performs the SSL/TLS connection.
|
||||||
|
local function tcp(params)
|
||||||
|
params = params or {}
|
||||||
|
-- Default settings
|
||||||
|
for k, v in pairs(cfg) do
|
||||||
|
params[k] = params[k] or v
|
||||||
|
end
|
||||||
|
-- Force client mode
|
||||||
|
params.mode = "client"
|
||||||
|
-- 'create' function for LuaSocket
|
||||||
|
return function ()
|
||||||
|
local conn = {}
|
||||||
|
conn.sock = try(socket.tcp())
|
||||||
|
local st = getmetatable(conn.sock).__index.settimeout
|
||||||
|
function conn:settimeout(...)
|
||||||
|
return st(self.sock, ...)
|
||||||
|
end
|
||||||
|
-- Replace TCP's connection function
|
||||||
|
function conn:connect(host, port)
|
||||||
|
try(self.sock:connect(host, port))
|
||||||
|
self.sock = try(ssl.wrap(self.sock, params))
|
||||||
|
try(self.sock:dohandshake())
|
||||||
|
reg(self, getmetatable(self.sock))
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
return conn
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
-- Main Function
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- Make a HTTP request over secure connection. This function receives
|
||||||
|
-- the same parameters of LuaSocket's HTTP module (except 'proxy' and
|
||||||
|
-- 'redirect') plus LuaSec parameters.
|
||||||
|
--
|
||||||
|
-- @param url mandatory (string or table)
|
||||||
|
-- @param body optional (string)
|
||||||
|
-- @return (string if url == string or 1), code, headers, status
|
||||||
|
--
|
||||||
|
function request(url, body)
|
||||||
|
local result_table = {}
|
||||||
|
local stringrequest = type(url) == "string"
|
||||||
|
if stringrequest then
|
||||||
|
url = urlstring_totable(url, body, result_table)
|
||||||
|
else
|
||||||
|
url.url = default_https_port(url.url)
|
||||||
|
end
|
||||||
|
if http.PROXY or url.proxy then
|
||||||
|
return nil, "proxy not supported"
|
||||||
|
elseif url.redirect then
|
||||||
|
return nil, "redirect not supported"
|
||||||
|
elseif url.create then
|
||||||
|
return nil, "create function not permitted"
|
||||||
|
end
|
||||||
|
-- New 'create' function to establish a secure connection
|
||||||
|
url.create = tcp(url)
|
||||||
|
local res, code, headers, status = http.request(url)
|
||||||
|
if res and stringrequest then
|
||||||
|
return table.concat(result_table), code, headers, status
|
||||||
|
end
|
||||||
|
return res, code, headers, status
|
||||||
|
end
|
669
Me_Lua/r13/tags
Normal file
669
Me_Lua/r13/tags
Normal file
@ -0,0 +1,669 @@
|
|||||||
|
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
|
||||||
|
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
|
||||||
|
!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
|
||||||
|
!_TAG_PROGRAM_NAME Exuberant Ctags //
|
||||||
|
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
|
||||||
|
!_TAG_PROGRAM_VERSION 5.9~svn20110310 //
|
||||||
|
"Failed to execute " .. (type(c.target) ./luci/dispatcher.lua /^ "Failed to execute " .. (type(c.target) == "function" and "function" or c.target.type or "unknown") ..$/;" f
|
||||||
|
M.strsplit ./Posix.lua /^function M.strsplit(str, delim, maxNb)$/;" f
|
||||||
|
M.timeradd ./Posix.lua /^function M.timeradd (x,y)$/;" f
|
||||||
|
M.timercmp ./Posix.lua /^function M.timercmp (x, y)$/;" f
|
||||||
|
M.timersub ./Posix.lua /^function M.timersub (x,y)$/;" f
|
||||||
|
M.timesleep ./Posix.lua /^function M.timesleep (x)$/;" f
|
||||||
|
M.var_dump ./Posix.lua /^function M.var_dump(data, max_level, prefix)$/;" f
|
||||||
|
OTA_process_action ./meizu/sipfs.lua /^function OTA_process_action(vs_info)$/;" f
|
||||||
|
["addMeshDevice"] ./meizu/sipfs.lua /^ ["addMeshDevice"] = function(cmd, cmdid) $/;" f
|
||||||
|
["checkRouterUpdate"] ./meizu/sipfs.lua /^ ["checkRouterUpdate"] = function(cmd, cmdid)$/;" f
|
||||||
|
["delmeshdevicetimer"] ./meizu/sipfs.lua /^ ["delmeshdevicetimer"] = function(cmd, cmdid)$/;" f
|
||||||
|
["executeRouterUpdate"] ./meizu/sipfs.lua /^ ["executeRouterUpdate"] = function(cmd, cmdid)$/;" f
|
||||||
|
["factoryreset"] ./meizu/sipfs.lua /^ ["factoryreset"] = function(cmd, cmdid)$/;" f
|
||||||
|
["getBleDeviceList"] ./meizu/sipfs.lua /^ ["getBleDeviceList"] = function(cmd, cmdid)$/;" f
|
||||||
|
["getDeviceList"] ./meizu/sipfs.lua /^ ["getDeviceList"] = function(cmd, cmdid)$/;" f
|
||||||
|
["getMeshDeviceDetail"] ./meizu/sipfs.lua /^ ["getMeshDeviceDetail"] = function(cmd, cmdid) $/;" f
|
||||||
|
["getMeshDeviceList"] ./meizu/sipfs.lua /^ ["getMeshDeviceList"] = function(cmd, cmdid)$/;" f
|
||||||
|
["getWirelessChannel"] ./meizu/sipfs.lua /^ ["getWirelessChannel"] = function(cmd, cmdid)$/;" f
|
||||||
|
["getdevicedetails"] ./meizu/sipfs.lua /^ ["getdevicedetails"] = function(cmd, cmdid)$/;" f
|
||||||
|
["getsysinfo"] ./meizu/sipfs.lua /^ ["getsysinfo"] = function(cmd, cmdid)$/;" f
|
||||||
|
["getwifisettings"] ./meizu/sipfs.lua /^ ["getwifisettings"] = function(cmd, cmdid)$/;" f
|
||||||
|
["realtimenetspeed"] ./meizu/sipfs.lua /^ ["realtimenetspeed"] = function(cmd, cmdid)$/;" f
|
||||||
|
["rebootmeshdevice"] ./meizu/sipfs.lua /^ ["rebootmeshdevice"] = function(cmd, cmdid)$/;" f
|
||||||
|
["removeblefrommesh"] ./meizu/sipfs.lua /^ ["removeblefrommesh"] = function(cmd, cmdid)$/;" f
|
||||||
|
["scanBleSwitch"] ./meizu/sipfs.lua /^ ["scanBleSwitch"] = function(cmd, cmdid) --scanBleSwitch getMeshDeviceList getBleDeviceList$/;" f
|
||||||
|
["setDeviceName"] ./meizu/sipfs.lua /^ ["setDeviceName"] = function(cmd, cmdid)$/;" f
|
||||||
|
["setLampBrightness"] ./meizu/sipfs.lua /^ ["setLampBrightness"] = function(cmd, cmdid)$/;" f
|
||||||
|
["setMeashNetWorkPassword"] ./meizu/sipfs.lua /^ ["setMeashNetWorkPassword"] = function(cmd, cmdid)$/;" f
|
||||||
|
["setMeshDeviceAttr"] ./meizu/sipfs.lua /^ ["setMeshDeviceAttr"] = function(cmd, cmdid)$/;" f
|
||||||
|
["setReboot"] ./meizu/sipfs.lua /^ ["setReboot"] = function(cmd, cmdid)$/;" f
|
||||||
|
["setWanSwitch"] ./meizu/sipfs.lua /^ ["setWanSwitch"] = function(cmd, cmdid)$/;" f
|
||||||
|
["setWirelessChannel"] ./meizu/sipfs.lua /^ ["setWirelessChannel"] = function(cmd, cmdid)$/;" f
|
||||||
|
["setmeshdevicetimer"] ./meizu/sipfs.lua /^ ["setmeshdevicetimer"] = function(cmd, cmdid)$/;" f
|
||||||
|
["setwifisettings"] ./meizu/sipfs.lua /^ ["setwifisettings"] = function(cmd, cmdid)$/;" f
|
||||||
|
["unmeshalldevice"] ./meizu/sipfs.lua /^ ["unmeshalldevice"] = function(cmd, cmdid)$/;" f
|
||||||
|
_ ./luci/dispatcher.lua /^function _(text)$/;" f
|
||||||
|
_M.absolute ./socket/url.lua /^function _M.absolute(base_url, relative_url)$/;" f
|
||||||
|
_M.bind ./socket.lua /^function _M.bind(host, port, backlog)$/;" f
|
||||||
|
_M.build ./socket/url.lua /^function _M.build(parsed)$/;" f
|
||||||
|
_M.build_path ./socket/url.lua /^function _M.build_path(parsed, unsafe)$/;" f
|
||||||
|
_M.choose ./socket.lua /^function _M.choose(table)$/;" f
|
||||||
|
_M.command ./socket/ftp.lua /^_M.command = socket.protect(function(cmdt)$/;" f
|
||||||
|
_M.connect ./socket/tp.lua /^function _M.connect(host, port, timeout, create)$/;" f
|
||||||
|
_M.connect4 ./socket.lua /^function _M.connect4(address, port, laddress, lport)$/;" f
|
||||||
|
_M.connect6 ./socket.lua /^function _M.connect6(address, port, laddress, lport)$/;" f
|
||||||
|
_M.escape ./socket/url.lua /^function _M.escape(s)$/;" f
|
||||||
|
_M.get ./socket/ftp.lua /^_M.get = socket.protect(function(gett)$/;" f
|
||||||
|
_M.message ./socket/smtp.lua /^function _M.message(mesgt)$/;" f
|
||||||
|
_M.normalize ./mime.lua /^function _M.normalize(marker)$/;" f
|
||||||
|
_M.open ./socket/ftp.lua /^function _M.open(server, port, create)$/;" f
|
||||||
|
_M.open ./socket/http.lua /^function _M.open(host, port, create)$/;" f
|
||||||
|
_M.open ./socket/smtp.lua /^function _M.open(server, port, create)$/;" f
|
||||||
|
_M.parse ./socket/url.lua /^function _M.parse(url, default)$/;" f
|
||||||
|
_M.parse_path ./socket/url.lua /^function _M.parse_path(path)$/;" f
|
||||||
|
_M.put ./socket/ftp.lua /^_M.put = socket.protect(function(putt, body)$/;" f
|
||||||
|
_M.request ./socket/http.lua /^_M.request = socket.protect(function(reqt, body)$/;" f
|
||||||
|
_M.send ./socket/smtp.lua /^_M.send = socket.protect(function(mailt)$/;" f
|
||||||
|
_M.stuff ./mime.lua /^function _M.stuff()$/;" f
|
||||||
|
_M.unescape ./socket/url.lua /^function _M.unescape(s)$/;" f
|
||||||
|
__call ./socket.lua /^ __call = function()$/;" f
|
||||||
|
__call ./socket.lua /^ __call = function(self, chunk, err)$/;" f
|
||||||
|
__call ./socket/http.lua /^ __call = function()$/;" f
|
||||||
|
__call ./socket/http.lua /^ __call = function(self, chunk, err)$/;" f
|
||||||
|
_append ./luci/model/network.lua /^function _append(c, s, o, a)$/;" f
|
||||||
|
_arcombine ./luci/dispatcher.lua /^local function _arcombine(self, ...)$/;" f
|
||||||
|
_call ./luci/dispatcher.lua /^local function _call(self, ...)$/;" f
|
||||||
|
_cbi ./luci/dispatcher.lua /^local function _cbi(self, ...)$/;" f
|
||||||
|
_checkid ./luci/sauth.lua /^local function _checkid(id)$/;" f
|
||||||
|
_create_node ./luci/dispatcher.lua /^function _create_node(path)$/;" f
|
||||||
|
_filter ./luci/model/network.lua /^function _filter(c, s, o, r)$/;" f
|
||||||
|
_firstchild ./luci/dispatcher.lua /^function _firstchild()$/;" f
|
||||||
|
_form ./luci/dispatcher.lua /^local function _form(self, ...)$/;" f
|
||||||
|
_get ./luci/model/network.lua /^function _get(c, s, o)$/;" f
|
||||||
|
_iface_ignore ./luci/model/network.lua /^function _iface_ignore(x)$/;" f
|
||||||
|
_iface_virtual ./luci/model/network.lua /^function _iface_virtual(x)$/;" f
|
||||||
|
_ifattr ./luci/dispatcher.lua /^ local function _ifattr(cond, key, val)$/;" f
|
||||||
|
_read ./luci/sauth.lua /^local function _read(id)$/;" f
|
||||||
|
_resolve_path ./luci/dispatcher.lua /^ local function _resolve_path(path)$/;" f
|
||||||
|
_set ./luci/model/network.lua /^function _set(c, s, o, v)$/;" f
|
||||||
|
_stror ./luci/model/network.lua /^function _stror(s1, s2)$/;" f
|
||||||
|
_wifi_iface ./luci/model/network.lua /^function _wifi_iface(x)$/;" f
|
||||||
|
_wifi_lookup ./luci/model/network.lua /^function _wifi_lookup(ifn)$/;" f
|
||||||
|
_wifi_state ./luci/model/network.lua /^function _wifi_state(key, val, field)$/;" f
|
||||||
|
_write ./luci/sauth.lua /^local function _write(id, data)$/;" f
|
||||||
|
absolute_path ./socket/url.lua /^local function absolute_path(base_path, relative_path)$/;" f
|
||||||
|
addBluetoothDevice ./meizu/dbfs.lua /^function addBluetoothDevice(id, mac, key, name, deviceType, len)$/;" f
|
||||||
|
add_access_token ./meizu/dbfs.lua /^function add_access_token(token, expireTime)$/;" f
|
||||||
|
add_ble_mesh_device ./meizu/nwfs.lua /^function add_ble_mesh_device(mac)$/;" f
|
||||||
|
add_deny_mac ./meizu/dbfs.lua /^function add_deny_mac(mac)$/;" f
|
||||||
|
add_network ./luci/model/network.lua /^function add_network(self, n, options)$/;" f
|
||||||
|
add_ssid ./meizu/dbfs.lua /^function add_ssid(ssid24, ssid5)$/;" f
|
||||||
|
add_wifinet ./luci/model/network.lua /^function add_wifinet(self, net, options)$/;" f
|
||||||
|
adjust_headers ./socket/smtp.lua /^local function adjust_headers(mesgt)$/;" f
|
||||||
|
adjustheaders ./socket/http.lua /^local function adjustheaders(reqt)$/;" f
|
||||||
|
adjustproxy ./socket/http.lua /^local function adjustproxy(reqt)$/;" f
|
||||||
|
adjustrequest ./socket/http.lua /^local function adjustrequest(reqt)$/;" f
|
||||||
|
adjusturi ./socket/http.lua /^local function adjusturi(reqt)$/;" f
|
||||||
|
alias ./luci/dispatcher.lua /^function alias(...)$/;" f
|
||||||
|
apk ./luci/controller/bs/index.lua /^function apk()$/;" f
|
||||||
|
arcombine ./luci/dispatcher.lua /^function arcombine(trg1, trg2)$/;" f
|
||||||
|
assert(type(func) ./luci/dispatcher.lua /^ assert(type(func) == "function",$/;" f
|
||||||
|
assert(type(idx) ./luci/dispatcher.lua /^ assert(type(idx) == "function",$/;" f
|
||||||
|
assign ./luci/dispatcher.lua /^function assign(path, clone, title, order)$/;" f
|
||||||
|
attr ./luci/dispatcher.lua /^ attr = function(...) return _ifattr(true, ...) end;$/;" f
|
||||||
|
authen ./luci/dispatcher.lua /^ authen = function() return eu end$/;" f
|
||||||
|
authenticator.htmlauth ./luci/dispatcher.lua /^function authenticator.htmlauth(validator, accs, default)$/;" f
|
||||||
|
available ./luci/sauth.lua /^function available()$/;" f
|
||||||
|
b64dec ./meizu/bfs.lua /^function b64dec(data)$/;" f
|
||||||
|
b64enc ./meizu/bfs.lua /^function b64enc(data)$/;" f
|
||||||
|
bind_router ./meizu/bfs.lua /^function bind_router()$/;" f
|
||||||
|
bluetooth_info ./meizu/nwfs.lua /^function bluetooth_info()$/;" f
|
||||||
|
buf ./meizu/bfs.lua /^ buf = buf..string.format('"%s"' % tostring(x):gsub('[%z\\1-\\31]', function(c) return '\\\\u%04x' % c:byte(1) end))$/;" f
|
||||||
|
build_url ./luci/dispatcher.lua /^function build_url(...)$/;" f
|
||||||
|
cal_str_md5 ./meizu/bfs.lua /^function cal_str_md5(str)$/;" f
|
||||||
|
call ./luci/dispatcher.lua /^function call(name, ...)$/;" f
|
||||||
|
cancelapclient ./meizu/nwfs.lua /^function cancelapclient()$/;" f
|
||||||
|
cbi ./luci/dispatcher.lua /^function cbi(model, config)$/;" f
|
||||||
|
change_maclist_table ./meizu/dbfs.lua /^function change_maclist_table()$/;" f
|
||||||
|
check_ssid ./meizu/nwfs.lua /^function check_ssid(ssid)$/;" f
|
||||||
|
check_sys_password ./meizu/nwfs.lua /^function check_sys_password(password)$/;" f
|
||||||
|
check_sys_pwd ./meizu/nwfs.lua /^function check_sys_pwd(oldPassword)$/;" f
|
||||||
|
check_upgrade ./meizu/upgdfs.lua /^function check_upgrade()$/;" f
|
||||||
|
check_upgrade_status ./routerReport.lua /^function check_upgrade_status()$/;" f
|
||||||
|
check_wifi_passwd ./meizu/nwfs.lua /^function check_wifi_passwd(passwd,encryption)$/;" f
|
||||||
|
choose ./mime.lua /^local function choose(table)$/;" f
|
||||||
|
commit ./luci/model/network.lua /^function commit(self, ...)$/;" f
|
||||||
|
conn:connect ./ssl/https.lua /^ function conn:connect(host, port)$/;" f
|
||||||
|
conn:settimeout ./ssl/https.lua /^ function conn:settimeout(...)$/;" f
|
||||||
|
conn[name] ./ssl/https.lua /^ conn[name] = function (self, ...)$/;" f
|
||||||
|
createindex ./luci/dispatcher.lua /^function createindex()$/;" f
|
||||||
|
createindex_fastindex ./luci/dispatcher.lua /^function createindex_fastindex(path, suffixes)$/;" f
|
||||||
|
createindex_plain ./luci/dispatcher.lua /^function createindex_plain(path, suffixes)$/;" f
|
||||||
|
createtree ./luci/dispatcher.lua /^function createtree()$/;" f
|
||||||
|
data_to_json ./meizu/bfs.lua /^function data_to_json(x)$/;" f
|
||||||
|
database_busy ./meizu/dbfs.lua /^function database_busy()$/;" f
|
||||||
|
decodeURI ./meizu/bfs.lua /^function decodeURI(s)$/;" f
|
||||||
|
decodet['base64'] ./mime.lua /^decodet['base64'] = function()$/;" f
|
||||||
|
decodet['quoted-printable'] ./mime.lua /^decodet['quoted-printable'] = function()$/;" f
|
||||||
|
default_https_port ./ssl/https.lua /^local function default_https_port(u)$/;" f
|
||||||
|
del_mesh_device_timer ./meizu/nwfs.lua /^function del_mesh_device_timer(mac, timer_id)$/;" f
|
||||||
|
del_network ./luci/model/network.lua /^function del_network(self, n)$/;" f
|
||||||
|
del_wifinet ./luci/model/network.lua /^function del_wifinet(self, net)$/;" f
|
||||||
|
deleteBluetoothDevice ./meizu/dbfs.lua /^function deleteBluetoothDevice(mac)$/;" f
|
||||||
|
delete_access_token ./meizu/dbfs.lua /^function delete_access_token()$/;" f
|
||||||
|
delete_arp_all_mac ./meizu/dbfs.lua /^function delete_arp_all_mac()$/;" f
|
||||||
|
delete_deny_mac ./meizu/dbfs.lua /^function delete_deny_mac(mac)$/;" f
|
||||||
|
devip ./luci/controller/bs/index.lua /^function devip()$/;" f
|
||||||
|
diag_command ./luci/controller/admin/network.lua /^function diag_command(cmd, addr)$/;" f
|
||||||
|
diag_nslookup ./luci/controller/admin/network.lua /^function diag_nslookup(addr)$/;" f
|
||||||
|
diag_ping ./luci/controller/admin/network.lua /^function diag_ping(addr)$/;" f
|
||||||
|
diag_ping6 ./luci/controller/admin/network.lua /^function diag_ping6(addr)$/;" f
|
||||||
|
diag_traceroute ./luci/controller/admin/network.lua /^function diag_traceroute(addr)$/;" f
|
||||||
|
diag_traceroute6 ./luci/controller/admin/network.lua /^function diag_traceroute6(addr)$/;" f
|
||||||
|
dirty ./socket.lua /^ dirty = function() return sock:dirty() end$/;" f
|
||||||
|
dirty ./socket/http.lua /^ dirty = function() return sock:dirty() end$/;" f
|
||||||
|
dismiss_mesh ./meizu/nwfs.lua /^function dismiss_mesh()$/;" f
|
||||||
|
dispatch ./luci/dispatcher.lua /^function dispatch(request)$/;" f
|
||||||
|
do_upgrade ./meizu/upgdfs.lua /^function do_upgrade()$/;" f
|
||||||
|
download_list_post_process ./meizu/sipfs.lua /^function download_list_post_process(data, refine_cnt)$/;" f
|
||||||
|
download_task_operate_process ./meizu/sipfs.lua /^function download_task_operate_process(cmd, cmdid)$/;" f
|
||||||
|
elseif base.type(mesgt.body) ./socket/smtp.lua /^ elseif base.type(mesgt.body) == "function" then send_source(mesgt)$/;" f
|
||||||
|
empty ./ltn12.lua /^local function empty()$/;" f
|
||||||
|
encodeURI ./meizu/bfs.lua /^function encodeURI(s)$/;" f
|
||||||
|
encodet['base64'] ./mime.lua /^encodet['base64'] = function()$/;" f
|
||||||
|
encodet['quoted-printable'] ./mime.lua /^encodet['quoted-printable'] = function(mode)$/;" f
|
||||||
|
entry ./luci/dispatcher.lua /^function entry(path, target, title, order)$/;" f
|
||||||
|
error404 ./luci/dispatcher.lua /^function error404(message)$/;" f
|
||||||
|
error500 ./luci/dispatcher.lua /^function error500(message)$/;" f
|
||||||
|
exec_cmd_in_sh ./meizu/bfs.lua /^function exec_cmd_in_sh(command)$/;" f
|
||||||
|
exec_reboot ./meizu/bfs.lua /^function exec_reboot()$/;" f
|
||||||
|
export ./luci/dispatcher.lua /^ export = function(k, v) if tpl.context.viewns[k] == nil then tpl.context.viewns[k] = v end end;$/;" f
|
||||||
|
f.try ./socket/ftp.lua /^ f.try = socket.newtry(function() f:close() end)$/;" f
|
||||||
|
factory_reset ./meizu/bfs.lua /^function factory_reset()$/;" f
|
||||||
|
fetchAllBleMeshDevice ./meizu/dbfs.lua /^function fetchAllBleMeshDevice()$/;" f
|
||||||
|
fetchAllBluetoothDevice ./meizu/dbfs.lua /^function fetchAllBluetoothDevice()$/;" f
|
||||||
|
fetchAllDeviceInfo ./meizu/dbfs.lua /^function fetchAllDeviceInfo()$/;" f
|
||||||
|
fetchBluetoothDevice ./meizu/dbfs.lua /^function fetchBluetoothDevice(mac)$/;" f
|
||||||
|
fetchBluetoothDeviceKey ./meizu/dbfs.lua /^function fetchBluetoothDeviceKey()$/;" f
|
||||||
|
fetchDenyDeviceInfo ./meizu/dbfs.lua /^function fetchDenyDeviceInfo(mac)$/;" f
|
||||||
|
fetch_access_token ./meizu/dbfs.lua /^function fetch_access_token()$/;" f
|
||||||
|
fetch_all_arp ./meizu/dbfs.lua /^function fetch_all_arp()$/;" f
|
||||||
|
fetch_all_deny_mac ./meizu/dbfs.lua /^function fetch_all_deny_mac()$/;" f
|
||||||
|
fetch_arp ./meizu/dbfs.lua /^function fetch_arp(mac)$/;" f
|
||||||
|
fetch_ssid ./meizu/dbfs.lua /^function fetch_ssid()$/;" f
|
||||||
|
filter.chain ./ltn12.lua /^function filter.chain(...)$/;" f
|
||||||
|
filter.cycle ./ltn12.lua /^function filter.cycle(low, ctx, extra)$/;" f
|
||||||
|
firstchild ./luci/dispatcher.lua /^function firstchild()$/;" f
|
||||||
|
fork_restart_network ./meizu/nwfs.lua /^function fork_restart_network()$/;" f
|
||||||
|
fork_restart_wifi ./meizu/nwfs.lua /^function fork_restart_wifi()$/;" f
|
||||||
|
form ./luci/dispatcher.lua /^function form(model)$/;" f
|
||||||
|
format ./mime.lua /^local function format(chunk)$/;" f
|
||||||
|
function(p) parsed.password ./socket/url.lua /^ function(p) parsed.password = p; return "" end)$/;" f
|
||||||
|
function(p) parsed.port ./socket/url.lua /^ function(p) parsed.port = p; return "" end)$/;" f
|
||||||
|
function(s) parsed.scheme ./socket/url.lua /^ function(s) parsed.scheme = s; return "" end)$/;" f
|
||||||
|
function(s) return (s.interface ./luci/model/network.lua /^ function(s) return (s.interface == n) end)$/;" f
|
||||||
|
function(s) wfd[#wfd+1] ./luci/model/network.lua /^ function(s) wfd[#wfd+1] = s['.name'] end)$/;" f
|
||||||
|
function(u) parsed.userinfo ./socket/url.lua /^ function(u) parsed.userinfo = u; return "" end)$/;" f
|
||||||
|
genAuthToken ./luci/sauth.lua /^function genAuthToken()$/;" f
|
||||||
|
gen_check_fw_url_pd ./meizu/upgdfs.lua /^function gen_check_fw_url_pd()$/;" f
|
||||||
|
get ./luci/dispatcher.lua /^function get(...)$/;" f
|
||||||
|
getAllWifiConnetDeviceDict ./meizu/nwfs.lua /^function getAllWifiConnetDeviceDict()$/;" f
|
||||||
|
getBasicInfo ./routerReport.lua /^function getBasicInfo()$/;" f
|
||||||
|
getBleDeviceNameLength ./meizu/dbfs.lua /^function getBleDeviceNameLength(id)$/;" f
|
||||||
|
getBluetoothDevice ./meizu/dbfs.lua /^function getBluetoothDevice(id)$/;" f
|
||||||
|
getDHCPDict ./meizu/nwfs.lua /^function getDHCPDict()$/;" f
|
||||||
|
getDHCPIpDicts ./meizu/nwfs.lua /^function getDHCPIpDicts()$/;" f
|
||||||
|
getDHCPLists ./meizu/nwfs.lua /^function getDHCPLists()$/;" f
|
||||||
|
getDeviceInfoFromDB ./meizu/nwfs.lua /^function getDeviceInfoFromDB()$/;" f
|
||||||
|
getNetConnect ./meizu/nwfs.lua /^function getNetConnect(ip)$/;" f
|
||||||
|
getWanEth ./meizu/nwfs.lua /^function getWanEth()$/;" f
|
||||||
|
getWifiConnectDeviceList ./meizu/nwfs.lua /^function getWifiConnectDeviceList(wifiIndex)$/;" f
|
||||||
|
getWifiSettings ./luci/controller/admin/network.lua /^function getWifiSettings()$/;" f
|
||||||
|
get_ble_device_key ./meizu/nwfs.lua /^function get_ble_device_key()$/;" f
|
||||||
|
get_ble_device_list ./meizu/nwfs.lua /^function get_ble_device_list()$/;" f
|
||||||
|
get_ble_device_status ./meizu/nwfs.lua /^function get_ble_device_status(mac)$/;" f
|
||||||
|
get_bluetooth_info ./meizu/nwfs.lua /^function get_bluetooth_info()$/;" f
|
||||||
|
get_connect_device_list ./meizu/nwfs.lua /^function get_connect_device_list()$/;" f
|
||||||
|
get_connect_device_list_router ./meizu/nwfs.lua /^function get_connect_device_list_router()$/;" f
|
||||||
|
get_dev_nick_name ./meizu/dbfs.lua /^function get_dev_nick_name(mac)$/;" f
|
||||||
|
get_device_SN ./meizu/bfs.lua /^function get_device_SN()$/;" f
|
||||||
|
get_device_details ./meizu/nwfs.lua /^function get_device_details(mac)$/;" f
|
||||||
|
get_device_version ./meizu/bfs.lua /^function get_device_version()$/;" f
|
||||||
|
get_https_data ./meizu/bfs.lua /^function get_https_data(url, data)$/;" f
|
||||||
|
get_interface ./luci/model/network.lua /^function get_interface(self, i)$/;" f
|
||||||
|
get_interfaces ./luci/model/network.lua /^function get_interfaces(self)$/;" f
|
||||||
|
get_lan_ip ./meizu/nwfs.lua /^function get_lan_ip()$/;" f
|
||||||
|
get_mesh_device_list ./meizu/nwfs.lua /^function get_mesh_device_list()$/;" f
|
||||||
|
get_net_device ./meizu/nwfs.lua /^function get_net_device()$/;" f
|
||||||
|
get_network ./luci/model/network.lua /^function get_network(self, n)$/;" f
|
||||||
|
get_networks ./luci/model/network.lua /^function get_networks(self)$/;" f
|
||||||
|
get_protocol ./luci/model/network.lua /^function get_protocol(self, protoname, netname)$/;" f
|
||||||
|
get_protocols ./luci/model/network.lua /^function get_protocols(self)$/;" f
|
||||||
|
get_reply ./socket/tp.lua /^local function get_reply(c)$/;" f
|
||||||
|
get_status_by_address ./luci/model/network.lua /^function get_status_by_address(self, addr)$/;" f
|
||||||
|
get_status_by_route ./luci/model/network.lua /^function get_status_by_route(self, addr, mask)$/;" f
|
||||||
|
get_user_access_token ./meizu/bfs.lua /^function get_user_access_token()$/;" f
|
||||||
|
get_wan6dev ./luci/model/network.lua /^function get_wan6dev(self)$/;" f
|
||||||
|
get_wan6net ./luci/model/network.lua /^function get_wan6net(self)$/;" f
|
||||||
|
get_wan_type ./meizu/nwfs.lua /^function get_wan_type()$/;" f
|
||||||
|
get_wandev ./luci/model/network.lua /^function get_wandev(self)$/;" f
|
||||||
|
get_wannet ./luci/model/network.lua /^function get_wannet(self)$/;" f
|
||||||
|
get_wifi_settings ./meizu/nwfs.lua /^function get_wifi_settings(app_version)$/;" f
|
||||||
|
get_wifi_ssids ./meizu/nwfs.lua /^function get_wifi_ssids()$/;" f
|
||||||
|
get_wifidev ./luci/model/network.lua /^function get_wifidev(self, dev)$/;" f
|
||||||
|
get_wifidevs ./luci/model/network.lua /^function get_wifidevs(self)$/;" f
|
||||||
|
get_wifinet ./luci/model/network.lua /^function get_wifinet(self, net)$/;" f
|
||||||
|
get_wireless_channel ./meizu/nwfs.lua /^function get_wireless_channel()$/;" f
|
||||||
|
getfd ./socket.lua /^ getfd = function() return sock:getfd() end,$/;" f
|
||||||
|
getfd ./socket/http.lua /^ getfd = function() return sock:getfd() end,$/;" f
|
||||||
|
h.try ./socket/http.lua /^ h.try = socket.newtry(function() h:close() end)$/;" f
|
||||||
|
has_ipv6 ./luci/model/network.lua /^function has_ipv6(self)$/;" f
|
||||||
|
httpdispatch ./luci/dispatcher.lua /^function httpdispatch(request, prefix)$/;" f
|
||||||
|
https_get_access_token ./meizu/bfs.lua /^function https_get_access_token()$/;" f
|
||||||
|
if base.type(ok) ~ ./socket/tp.lua /^ if base.type(ok) ~= "function" then$/;" f
|
||||||
|
if c and (c.index or type(target) ./luci/dispatcher.lua /^ if c and (c.index or type(target) == "function") then$/;" f
|
||||||
|
if type(c.target) ./luci/dispatcher.lua /^ if type(c.target) == "function" then$/;" f
|
||||||
|
if type(cfg.dhparam) ~ ./ssl.lua /^ if type(cfg.dhparam) ~= "function" then$/;" f
|
||||||
|
if type(method) ./ssl/https.lua /^ if type(method) == "function" then$/;" f
|
||||||
|
if type(target) ./luci/dispatcher.lua /^ if type(target) == "function" then$/;" f
|
||||||
|
iface_delete ./luci/controller/admin/network.lua /^function iface_delete(iface)$/;" f
|
||||||
|
iface_reconnect ./luci/controller/admin/network.lua /^function iface_reconnect(iface)$/;" f
|
||||||
|
iface_shutdown ./luci/controller/admin/network.lua /^function iface_shutdown(iface)$/;" f
|
||||||
|
iface_status ./luci/controller/admin/network.lua /^function iface_status(ifaces)$/;" f
|
||||||
|
ifattr ./luci/dispatcher.lua /^ ifattr = function(...) return _ifattr(...) end;$/;" f
|
||||||
|
ifnameof ./luci/model/network.lua /^function ifnameof(self, x)$/;" f
|
||||||
|
ignore_interface ./luci/model/network.lua /^function ignore_interface(self, x)$/;" f
|
||||||
|
image_supported ./meizu/bfs.lua /^ local function image_supported()$/;" f
|
||||||
|
image_supported ./meizu/upgdfs.lua /^ local function image_supported()$/;" f
|
||||||
|
include ./luci/dispatcher.lua /^ include = function(name) tpl.Template(name):render(getfenv(2)) end;$/;" f
|
||||||
|
index ./luci/controller/admin/network.lua /^function index()$/;" f
|
||||||
|
index ./luci/controller/api/index.lua /^function index()$/;" f
|
||||||
|
index ./luci/controller/bs/index.lua /^function index()$/;" f
|
||||||
|
info ./luci/controller/bs/index.lua /^function info()$/;" f
|
||||||
|
info ./ssl.lua /^local function info(ssl, field)$/;" f
|
||||||
|
init ./luci/model/network.lua /^function init(cursor)$/;" f
|
||||||
|
initBluetoothTable ./meizu/dbfs.lua /^function initBluetoothTable()$/;" f
|
||||||
|
init_access_token_table ./meizu/dbfs.lua /^function init_access_token_table()$/;" f
|
||||||
|
init_arp_table ./meizu/dbfs.lua /^function init_arp_table()$/;" f
|
||||||
|
init_bind_router_body ./meizu/bfs.lua /^function init_bind_router_body(access_token)$/;" f
|
||||||
|
init_deny_mac_table ./meizu/dbfs.lua /^function init_deny_mac_table()$/;" f
|
||||||
|
init_ssid_dbdata ./routerReport.lua /^function init_ssid_dbdata()$/;" f
|
||||||
|
init_ssid_table ./meizu/dbfs.lua /^function init_ssid_table()$/;" f
|
||||||
|
init_update_resp_pd ./meizu/sipfs.lua /^function init_update_resp_pd(access_token, commandId, data, finishstatus, timemini)$/;" f
|
||||||
|
init_upload_router_log_pd ./meizu/sipfs.lua /^function init_upload_router_log_pd(access_token, logtype, logdata)$/;" f
|
||||||
|
insert_arp_macip ./meizu/dbfs.lua /^function insert_arp_macip(mac, ip, wifi)$/;" f
|
||||||
|
interface.__init__ ./luci/model/network.lua /^function interface.__init__(self, ifname, network)$/;" f
|
||||||
|
interface._ubus ./luci/model/network.lua /^function interface._ubus(self, field)$/;" f
|
||||||
|
interface.adminlink ./luci/model/network.lua /^function interface.adminlink(self)$/;" f
|
||||||
|
interface.bridge_id ./luci/model/network.lua /^function interface.bridge_id(self)$/;" f
|
||||||
|
interface.bridge_stp ./luci/model/network.lua /^function interface.bridge_stp(self)$/;" f
|
||||||
|
interface.get_i18n ./luci/model/network.lua /^function interface.get_i18n(self)$/;" f
|
||||||
|
interface.get_network ./luci/model/network.lua /^function interface.get_network(self)$/;" f
|
||||||
|
interface.get_networks ./luci/model/network.lua /^function interface.get_networks(self)$/;" f
|
||||||
|
interface.get_type_i18n ./luci/model/network.lua /^function interface.get_type_i18n(self)$/;" f
|
||||||
|
interface.get_wifinet ./luci/model/network.lua /^function interface.get_wifinet(self)$/;" f
|
||||||
|
interface.ip6addrs ./luci/model/network.lua /^function interface.ip6addrs(self)$/;" f
|
||||||
|
interface.ipaddrs ./luci/model/network.lua /^function interface.ipaddrs(self)$/;" f
|
||||||
|
interface.is_bridge ./luci/model/network.lua /^function interface.is_bridge(self)$/;" f
|
||||||
|
interface.is_bridgeport ./luci/model/network.lua /^function interface.is_bridgeport(self)$/;" f
|
||||||
|
interface.is_up ./luci/model/network.lua /^function interface.is_up(self)$/;" f
|
||||||
|
interface.mac ./luci/model/network.lua /^function interface.mac(self)$/;" f
|
||||||
|
interface.name ./luci/model/network.lua /^function interface.name(self)$/;" f
|
||||||
|
interface.ports ./luci/model/network.lua /^function interface.ports(self)$/;" f
|
||||||
|
interface.rx_bytes ./luci/model/network.lua /^function interface.rx_bytes(self)$/;" f
|
||||||
|
interface.rx_packets ./luci/model/network.lua /^function interface.rx_packets(self)$/;" f
|
||||||
|
interface.shortname ./luci/model/network.lua /^function interface.shortname(self)$/;" f
|
||||||
|
interface.tx_bytes ./luci/model/network.lua /^function interface.tx_bytes(self)$/;" f
|
||||||
|
interface.tx_packets ./luci/model/network.lua /^function interface.tx_packets(self)$/;" f
|
||||||
|
interface.type ./luci/model/network.lua /^function interface.type(self)$/;" f
|
||||||
|
is_del_timer_ok ./meizu/nwfs.lua /^function is_del_timer_ok(mac, timer_id)$/;" f
|
||||||
|
is_device_online ./meizu/nwfs.lua /^function is_device_online(ip)$/;" f
|
||||||
|
is_file_exist ./meizu/nwfs.lua /^function is_file_exist(TMP)$/;" f
|
||||||
|
is_receive_id ./meizu/nwfs.lua /^function is_receive_id(mac)$/;" f
|
||||||
|
is_remove_ble_from_mesh ./meizu/nwfs.lua /^function is_remove_ble_from_mesh()$/;" f
|
||||||
|
is_set_key_ok ./meizu/nwfs.lua /^function is_set_key_ok()$/;" f
|
||||||
|
is_set_name_ok ./meizu/nwfs.lua /^function is_set_name_ok(mac)$/;" f
|
||||||
|
is_set_timer_ok ./meizu/nwfs.lua /^function is_set_timer_ok(mac, timer_id)$/;" f
|
||||||
|
is_str_nil ./meizu/nwfs.lua /^function is_str_nil(str)$/;" f
|
||||||
|
is_switch_off ./meizu/nwfs.lua /^function is_switch_off(mac)$/;" f
|
||||||
|
is_switch_on ./meizu/nwfs.lua /^function is_switch_on(mac)$/;" f
|
||||||
|
is_wan_connected ./meizu/nwfs.lua /^function is_wan_connected()$/;" f
|
||||||
|
kill ./luci/sauth.lua /^function kill(id)$/;" f
|
||||||
|
lease_status ./luci/controller/admin/network.lua /^function lease_status()$/;" f
|
||||||
|
local _template ./luci/dispatcher.lua /^local _template = function(self, ...)$/;" f
|
||||||
|
local authen ./luci/dispatcher.lua /^ local authen = type(track.sysauth_authenticator) == "function"$/;" f
|
||||||
|
local checkstep ./socket/ftp.lua /^ local checkstep = function(src, snk)$/;" f
|
||||||
|
local co ./socket/smtp.lua /^ local co = coroutine.create(function() send_message(mesgt) end)$/;" f
|
||||||
|
local f ./ltn12.lua /^ local f = function(chunk, err)$/;" f
|
||||||
|
local s ./meizu/bfs.lua /^ local s = string.gsub(s, "([^%w%.%- ])", function(c) return string.format("%%%02X", string.byte(c)) end)$/;" f
|
||||||
|
local s ./meizu/bfs.lua /^ local s = string.gsub(s, '%%(%x%x)', function(h) return string.char(tonumber(h, 16)) end)$/;" f
|
||||||
|
local stat, err ./luci/dispatcher.lua /^ local stat, err = util.coxpcall(function()$/;" f
|
||||||
|
local_upgrade ./meizu/upgdfs.lua /^function local_upgrade()$/;" f
|
||||||
|
log ./MZLog.lua /^function log(...)$/;" f
|
||||||
|
lower_headers ./socket/smtp.lua /^local function lower_headers(headers)$/;" f
|
||||||
|
macFormat ./meizu/nwfs.lua /^function macFormat(mac)$/;" f
|
||||||
|
make_set ./socket/url.lua /^local function make_set(t)$/;" f
|
||||||
|
metat.__index:auth ./socket/smtp.lua /^function metat.__index:auth(user, password, ext)$/;" f
|
||||||
|
metat.__index:check ./socket/tp.lua /^function metat.__index:check(ok)$/;" f
|
||||||
|
metat.__index:close ./socket/ftp.lua /^function metat.__index:close()$/;" f
|
||||||
|
metat.__index:close ./socket/http.lua /^function metat.__index:close()$/;" f
|
||||||
|
metat.__index:close ./socket/smtp.lua /^function metat.__index:close()$/;" f
|
||||||
|
metat.__index:close ./socket/tp.lua /^function metat.__index:close()$/;" f
|
||||||
|
metat.__index:command ./socket/tp.lua /^function metat.__index:command(cmd, arg)$/;" f
|
||||||
|
metat.__index:cwd ./socket/ftp.lua /^function metat.__index:cwd(dir)$/;" f
|
||||||
|
metat.__index:data ./socket/smtp.lua /^function metat.__index:data(src, step)$/;" f
|
||||||
|
metat.__index:dirty ./socket/tp.lua /^function metat.__index:dirty()$/;" f
|
||||||
|
metat.__index:getcontrol ./socket/tp.lua /^function metat.__index:getcontrol()$/;" f
|
||||||
|
metat.__index:getfd ./socket/tp.lua /^function metat.__index:getfd()$/;" f
|
||||||
|
metat.__index:greet ./socket/ftp.lua /^function metat.__index:greet()$/;" f
|
||||||
|
metat.__index:greet ./socket/smtp.lua /^function metat.__index:greet(domain)$/;" f
|
||||||
|
metat.__index:login ./socket/ftp.lua /^function metat.__index:login(user, password)$/;" f
|
||||||
|
metat.__index:login ./socket/smtp.lua /^function metat.__index:login(user, password)$/;" f
|
||||||
|
metat.__index:mail ./socket/smtp.lua /^function metat.__index:mail(from)$/;" f
|
||||||
|
metat.__index:pasv ./socket/ftp.lua /^function metat.__index:pasv()$/;" f
|
||||||
|
metat.__index:pasvconnect ./socket/ftp.lua /^function metat.__index:pasvconnect()$/;" f
|
||||||
|
metat.__index:plain ./socket/smtp.lua /^function metat.__index:plain(user, password)$/;" f
|
||||||
|
metat.__index:port ./socket/ftp.lua /^function metat.__index:port(ip, port)$/;" f
|
||||||
|
metat.__index:portconnect ./socket/ftp.lua /^function metat.__index:portconnect()$/;" f
|
||||||
|
metat.__index:quit ./socket/ftp.lua /^function metat.__index:quit()$/;" f
|
||||||
|
metat.__index:quit ./socket/smtp.lua /^function metat.__index:quit()$/;" f
|
||||||
|
metat.__index:rcpt ./socket/smtp.lua /^function metat.__index:rcpt(to)$/;" f
|
||||||
|
metat.__index:receive ./socket/ftp.lua /^function metat.__index:receive(recvt)$/;" f
|
||||||
|
metat.__index:receive ./socket/tp.lua /^function metat.__index:receive(pat)$/;" f
|
||||||
|
metat.__index:receive09body ./socket/http.lua /^function metat.__index:receive09body(status, sink, step)$/;" f
|
||||||
|
metat.__index:receivebody ./socket/http.lua /^function metat.__index:receivebody(headers, sink, step)$/;" f
|
||||||
|
metat.__index:receiveheaders ./socket/http.lua /^function metat.__index:receiveheaders()$/;" f
|
||||||
|
metat.__index:receivestatusline ./socket/http.lua /^function metat.__index:receivestatusline()$/;" f
|
||||||
|
metat.__index:send ./socket/ftp.lua /^function metat.__index:send(sendt)$/;" f
|
||||||
|
metat.__index:send ./socket/smtp.lua /^function metat.__index:send(mailt)$/;" f
|
||||||
|
metat.__index:send ./socket/tp.lua /^function metat.__index:send(data)$/;" f
|
||||||
|
metat.__index:sendbody ./socket/http.lua /^function metat.__index:sendbody(headers, source, step)$/;" f
|
||||||
|
metat.__index:sendheaders ./socket/http.lua /^function metat.__index:sendheaders(tosend)$/;" f
|
||||||
|
metat.__index:sendrequestline ./socket/http.lua /^function metat.__index:sendrequestline(method, uri)$/;" f
|
||||||
|
metat.__index:sink ./socket/tp.lua /^function metat.__index:sink(snk, pat)$/;" f
|
||||||
|
metat.__index:source ./socket/tp.lua /^function metat.__index:source(source, step)$/;" f
|
||||||
|
metat.__index:type ./socket/ftp.lua /^function metat.__index:type(type)$/;" f
|
||||||
|
modifier ./luci/dispatcher.lua /^function modifier(func, order)$/;" f
|
||||||
|
modisort ./luci/dispatcher.lua /^ local function modisort(a,b)$/;" f
|
||||||
|
netspeed_channel ./meizu/nwfs.lua /^function netspeed_channel(cmd)$/;" f
|
||||||
|
network ./luci/model/network.lua /^function network(name, proto)$/;" f
|
||||||
|
new_device_notify ./meizu/arpmon.lua /^function new_device_notify()$/;" f
|
||||||
|
newboundary ./socket/smtp.lua /^local function newboundary()$/;" f
|
||||||
|
newcontext ./ssl.lua /^function newcontext(cfg)$/;" f
|
||||||
|
noAuthGetToken ./luci/sauth.lua /^function noAuthGetToken()$/;" f
|
||||||
|
node ./luci/dispatcher.lua /^function node(...)$/;" f
|
||||||
|
node_childs ./luci/dispatcher.lua /^function node_childs(node)$/;" f
|
||||||
|
node_visible ./luci/dispatcher.lua /^function node_visible(node)$/;" f
|
||||||
|
normip ./luci/controller/bs/index.lua /^function normip()$/;" f
|
||||||
|
null ./ltn12.lua /^local function null()$/;" f
|
||||||
|
nw_add_ble_mesh_device ./meizu/nwfs.lua /^function nw_add_ble_mesh_device()$/;" f
|
||||||
|
nw_check_sys_password ./meizu/nwfs.lua /^function nw_check_sys_password()$/;" f
|
||||||
|
nw_check_upgrade ./luci/controller/api/index.lua /^function nw_check_upgrade()$/;" f
|
||||||
|
nw_del_mesh_device_timer ./meizu/nwfs.lua /^function nw_del_mesh_device_timer()$/;" f
|
||||||
|
nw_dismiss_mesh ./meizu/nwfs.lua /^function nw_dismiss_mesh()$/;" f
|
||||||
|
nw_do_upgrade ./luci/controller/api/index.lua /^function nw_do_upgrade()$/;" f
|
||||||
|
nw_exec_reboot ./luci/controller/api/index.lua /^function nw_exec_reboot()$/;" f
|
||||||
|
nw_get_ble_device_list ./meizu/nwfs.lua /^function nw_get_ble_device_list()$/;" f
|
||||||
|
nw_get_ble_device_status ./meizu/nwfs.lua /^function nw_get_ble_device_status()$/;" f
|
||||||
|
nw_get_bluetooth_info ./meizu/nwfs.lua /^function nw_get_bluetooth_info()$/;" f
|
||||||
|
nw_get_connect_device_list ./meizu/nwfs.lua /^function nw_get_connect_device_list()$/;" f
|
||||||
|
nw_get_device_details ./meizu/nwfs.lua /^function nw_get_device_details()$/;" f
|
||||||
|
nw_get_mesh_device_list ./meizu/nwfs.lua /^function nw_get_mesh_device_list()$/;" f
|
||||||
|
nw_get_wan_type ./meizu/nwfs.lua /^function nw_get_wan_type()$/;" f
|
||||||
|
nw_get_wifi_settings ./meizu/nwfs.lua /^function nw_get_wifi_settings()$/;" f
|
||||||
|
nw_get_wireless_channel ./meizu/nwfs.lua /^function nw_get_wireless_channel()$/;" f
|
||||||
|
nw_real_time_net_speed ./luci/controller/api/index.lua /^function nw_real_time_net_speed()$/;" f
|
||||||
|
nw_reboot_mesh_device ./meizu/nwfs.lua /^function nw_reboot_mesh_device()$/;" f
|
||||||
|
nw_remove_ble_from_mesh ./meizu/nwfs.lua /^function nw_remove_ble_from_mesh()$/;" f
|
||||||
|
nw_scan_ble_switch ./meizu/nwfs.lua /^function nw_scan_ble_switch()$/;" f
|
||||||
|
nw_search_router ./luci/controller/api/index.lua /^function nw_search_router()$/;" f
|
||||||
|
nw_set_bluetooth ./meizu/nwfs.lua /^function nw_set_bluetooth()$/;" f
|
||||||
|
nw_set_device_name ./meizu/nwfs.lua /^function nw_set_device_name()$/;" f
|
||||||
|
nw_set_lamp_brightness ./meizu/nwfs.lua /^function nw_set_lamp_brightness()$/;" f
|
||||||
|
nw_set_mesh_device_attr ./meizu/nwfs.lua /^function nw_set_mesh_device_attr()$/;" f
|
||||||
|
nw_set_mesh_device_timer ./meizu/nwfs.lua /^function nw_set_mesh_device_timer()$/;" f
|
||||||
|
nw_set_mesh_network_pwd ./meizu/nwfs.lua /^function nw_set_mesh_network_pwd()$/;" f
|
||||||
|
nw_set_wan_switch ./meizu/nwfs.lua /^function nw_set_wan_switch()$/;" f
|
||||||
|
nw_set_wan_type ./meizu/nwfs.lua /^function nw_set_wan_type()$/;" f
|
||||||
|
nw_set_wireless_channel ./meizu/nwfs.lua /^function nw_set_wireless_channel(channel, extch)$/;" f
|
||||||
|
nw_unmesh_all_device ./meizu/nwfs.lua /^function nw_unmesh_all_device()$/;" f
|
||||||
|
nw_wifi_settings ./meizu/nwfs.lua /^function nw_wifi_settings()$/;" f
|
||||||
|
optexec ./ssl.lua /^local function optexec(func, param, ctx)$/;" f
|
||||||
|
or (scope and type(scope[key]) ~ ./luci/dispatcher.lua /^ or (scope and type(scope[key]) ~= "function" and scope[key])$/;" f
|
||||||
|
or (type(env[key]) ~ ./luci/dispatcher.lua /^ or (type(env[key]) ~= "function" and env[key])$/;" f
|
||||||
|
override ./socket/ftp.lua /^local function override(t)$/;" f
|
||||||
|
param ./luci/controller/admin/network.lua /^ local function param(x)$/;" f
|
||||||
|
parse ./socket/ftp.lua /^local function parse(u)$/;" f
|
||||||
|
path ./socket/url.lua /^ path = string.gsub(reduced, "([^\/]*\/%.%.\/)", function (s)$/;" f
|
||||||
|
path ./socket/url.lua /^ path = string.gsub(path, "([^\/]*%.\/)", function (s)$/;" f
|
||||||
|
path ./socket/url.lua /^ path = string.gsub(reduced, "([^\/]*\/%.%.)$", function (s)$/;" f
|
||||||
|
ping_rts_server ./routerReport.lua /^function ping_rts_server()$/;" f
|
||||||
|
prepare ./luci/sauth.lua /^function prepare()$/;" f
|
||||||
|
protect_segment ./socket/url.lua /^local function protect_segment(s)$/;" f
|
||||||
|
proto.__init__ ./luci/model/network.lua /^ function proto.__init__(self, name)$/;" f
|
||||||
|
proto.proto ./luci/model/network.lua /^ function proto.proto(self)$/;" f
|
||||||
|
protocol.__init__ ./luci/model/network.lua /^function protocol.__init__(self, name)$/;" f
|
||||||
|
protocol._get ./luci/model/network.lua /^function protocol._get(self, opt)$/;" f
|
||||||
|
protocol._ubus ./luci/model/network.lua /^function protocol._ubus(self, field)$/;" f
|
||||||
|
protocol.add_interface ./luci/model/network.lua /^function protocol.add_interface(self, ifname)$/;" f
|
||||||
|
protocol.adminlink ./luci/model/network.lua /^function protocol.adminlink(self)$/;" f
|
||||||
|
protocol.contains_interface ./luci/model/network.lua /^function protocol.contains_interface(self, ifname)$/;" f
|
||||||
|
protocol.del_interface ./luci/model/network.lua /^function protocol.del_interface(self, ifname)$/;" f
|
||||||
|
protocol.dns6addrs ./luci/model/network.lua /^function protocol.dns6addrs(self)$/;" f
|
||||||
|
protocol.dnsaddrs ./luci/model/network.lua /^function protocol.dnsaddrs(self)$/;" f
|
||||||
|
protocol.expires ./luci/model/network.lua /^function protocol.expires(self)$/;" f
|
||||||
|
protocol.get ./luci/model/network.lua /^function protocol.get(self, opt)$/;" f
|
||||||
|
protocol.get_i18n ./luci/model/network.lua /^function protocol.get_i18n(self)$/;" f
|
||||||
|
protocol.get_interface ./luci/model/network.lua /^function protocol.get_interface(self)$/;" f
|
||||||
|
protocol.get_interfaces ./luci/model/network.lua /^function protocol.get_interfaces(self)$/;" f
|
||||||
|
protocol.get_option_value ./luci/model/network.lua /^function protocol.get_option_value(self,name)$/;" f
|
||||||
|
protocol.gw6addr ./luci/model/network.lua /^function protocol.gw6addr(self)$/;" f
|
||||||
|
protocol.gwaddr ./luci/model/network.lua /^function protocol.gwaddr(self)$/;" f
|
||||||
|
protocol.ifname ./luci/model/network.lua /^function protocol.ifname(self)$/;" f
|
||||||
|
protocol.ip6addr ./luci/model/network.lua /^function protocol.ip6addr(self)$/;" f
|
||||||
|
protocol.ipaddr ./luci/model/network.lua /^function protocol.ipaddr(self)$/;" f
|
||||||
|
protocol.is_bridge ./luci/model/network.lua /^function protocol.is_bridge(self)$/;" f
|
||||||
|
protocol.is_empty ./luci/model/network.lua /^function protocol.is_empty(self)$/;" f
|
||||||
|
protocol.is_floating ./luci/model/network.lua /^function protocol.is_floating(self)$/;" f
|
||||||
|
protocol.is_installed ./luci/model/network.lua /^function protocol.is_installed(self)$/;" f
|
||||||
|
protocol.is_virtual ./luci/model/network.lua /^function protocol.is_virtual(self)$/;" f
|
||||||
|
protocol.metric ./luci/model/network.lua /^function protocol.metric(self)$/;" f
|
||||||
|
protocol.name ./luci/model/network.lua /^function protocol.name(self)$/;" f
|
||||||
|
protocol.netmask ./luci/model/network.lua /^function protocol.netmask(self)$/;" f
|
||||||
|
protocol.opkg_package ./luci/model/network.lua /^function protocol.opkg_package(self)$/;" f
|
||||||
|
protocol.proto ./luci/model/network.lua /^function protocol.proto(self)$/;" f
|
||||||
|
protocol.set ./luci/model/network.lua /^function protocol.set(self, opt, val)$/;" f
|
||||||
|
protocol.status ./luci/model/network.lua /^function protocol.status(self)$/;" f
|
||||||
|
protocol.type ./luci/model/network.lua /^function protocol.type(self)$/;" f
|
||||||
|
protocol.uptime ./luci/model/network.lua /^function protocol.uptime(self)$/;" f
|
||||||
|
ptable ./luci/controller/admin/network.lua /^ local function ptable(x)$/;" f
|
||||||
|
pump.all ./ltn12.lua /^function pump.all(src, snk, step)$/;" f
|
||||||
|
pump.step ./ltn12.lua /^function pump.step(src, snk)$/;" f
|
||||||
|
push_fw_upgrading_msg ./meizu/upgdfs.lua /^function push_fw_upgrading_msg(url)$/;" f
|
||||||
|
push_new_version_msg ./meizu/upgdfs.lua /^function push_new_version_msg()$/;" f
|
||||||
|
push_upgrade_finish_msg ./meizu/upgdfs.lua /^function push_upgrade_finish_msg()$/;" f
|
||||||
|
pysip ./meizu/sipfs.lua /^function pysip()$/;" f
|
||||||
|
read ./luci/sauth.lua /^function read(id)$/;" f
|
||||||
|
real_time_net_speed ./meizu/nwfs.lua /^function real_time_net_speed()$/;" f
|
||||||
|
reap ./luci/sauth.lua /^function reap()$/;" f
|
||||||
|
reboot_mesh_device ./meizu/nwfs.lua /^function reboot_mesh_device(mac)$/;" f
|
||||||
|
receiveheaders ./socket/http.lua /^local function receiveheaders(sock, headers)$/;" f
|
||||||
|
reg ./ssl/https.lua /^local function reg(conn)$/;" f
|
||||||
|
register_pattern_virtual ./luci/model/network.lua /^function register_pattern_virtual(self, pat)$/;" f
|
||||||
|
register_protocol ./luci/model/network.lua /^function register_protocol(self, protoname)$/;" f
|
||||||
|
remove_ble_from_mesh ./meizu/nwfs.lua /^function remove_ble_from_mesh(mac)$/;" f
|
||||||
|
rename_network ./luci/model/network.lua /^function rename_network(self, old, new)$/;" f
|
||||||
|
report_rom_version ./routerReport.lua /^function report_rom_version()$/;" f
|
||||||
|
request ./ssl/https.lua /^function request(url, body)$/;" f
|
||||||
|
rewrite ./luci/dispatcher.lua /^function rewrite(n, ...)$/;" f
|
||||||
|
rts_get_access_token ./meizu/bfs.lua /^function rts_get_access_token()$/;" f
|
||||||
|
s.try ./socket/smtp.lua /^ s.try = socket.newtry(function()$/;" f
|
||||||
|
sane ./luci/sauth.lua /^function sane(file)$/;" f
|
||||||
|
save ./luci/model/network.lua /^function save(self, ...)$/;" f
|
||||||
|
saveDeviceInfo ./meizu/dbfs.lua /^function saveDeviceInfo(mac, orgname, devicename, deviceip)$/;" f
|
||||||
|
save_device_name ./meizu/nwfs.lua /^function save_device_name(mac,name)$/;" f
|
||||||
|
scan_ble_switch ./meizu/nwfs.lua /^function scan_ble_switch(status)$/;" f
|
||||||
|
send_headers ./socket/smtp.lua /^local function send_headers(tosend)$/;" f
|
||||||
|
send_message ./socket/smtp.lua /^function send_message(mesgt)$/;" f
|
||||||
|
send_multipart ./socket/smtp.lua /^local function send_multipart(mesgt)$/;" f
|
||||||
|
send_source ./socket/smtp.lua /^local function send_source(mesgt)$/;" f
|
||||||
|
send_string ./socket/smtp.lua /^local function send_string(mesgt)$/;" f
|
||||||
|
setWanDHCP ./meizu/nwfs.lua /^function setWanDHCP()$/;" f
|
||||||
|
setWanPPPoE ./meizu/nwfs.lua /^function setWanPPPoE(name, password)$/;" f
|
||||||
|
set_ap_client ./meizu/nwfs.lua /^function set_ap_client(channel, ssid, mac, sec, extch, wl_type_val, key)$/;" f
|
||||||
|
set_bluetooth ./meizu/nwfs.lua /^function set_bluetooth(id, status)$/;" f
|
||||||
|
set_device_name ./meizu/nwfs.lua /^function set_device_name(mac,devicename)$/;" f
|
||||||
|
set_lamp_brightness ./meizu/nwfs.lua /^function set_lamp_brightness()$/;" f
|
||||||
|
set_mesh_device_attr ./meizu/nwfs.lua /^function set_mesh_device_attr(mac, key, value)$/;" f
|
||||||
|
set_mesh_device_timer ./meizu/nwfs.lua /^function set_mesh_device_timer(mac, timer_id, flag, start_time, end_time)$/;" f
|
||||||
|
set_mesh_network_pwd ./meizu/nwfs.lua /^function set_mesh_network_pwd(old_key, new_key)$/;" f
|
||||||
|
set_passwd ./meizu/bfs.lua /^function set_passwd()$/;" f
|
||||||
|
set_wan_switch ./meizu/nwfs.lua /^function set_wan_switch(mac, mode, enable)$/;" f
|
||||||
|
set_wan_type ./meizu/nwfs.lua /^function set_wan_type(wan_type, pppoe_name, pppoe_pwd)$/;" f
|
||||||
|
set_wifi_basic_info ./meizu/nwfs.lua /^function set_wifi_basic_info(wifi_index, ssid, password, encryption, on)$/;" f
|
||||||
|
set_wireless_channel ./meizu/nwfs.lua /^function set_wireless_channel(channel, extch)$/;" f
|
||||||
|
sget ./socket/ftp.lua /^local function sget(u)$/;" f
|
||||||
|
shouldreceivebody ./socket/http.lua /^local function shouldreceivebody(reqt, code)$/;" f
|
||||||
|
shouldredirect ./socket/http.lua /^local function shouldredirect(reqt, code, headers)$/;" f
|
||||||
|
show_hosts ./luci/controller/bs/index.lua /^function show_hosts()$/;" f
|
||||||
|
silent_upgrade ./meizu/bfs.lua /^function silent_upgrade()$/;" f
|
||||||
|
sink.chain ./ltn12.lua /^function sink.chain(f, snk, ...)$/;" f
|
||||||
|
sink.error ./ltn12.lua /^function sink.error(err)$/;" f
|
||||||
|
sink.file ./ltn12.lua /^function sink.file(handle, io_err)$/;" f
|
||||||
|
sink.null ./ltn12.lua /^function sink.null()$/;" f
|
||||||
|
sink.simplify ./ltn12.lua /^function sink.simplify(snk)$/;" f
|
||||||
|
sink.table ./ltn12.lua /^function sink.table(t)$/;" f
|
||||||
|
sinkt["close-when-done"] ./socket.lua /^sinkt["close-when-done"] = function(sock)$/;" f
|
||||||
|
sinkt["keep-open"] ./socket.lua /^sinkt["keep-open"] = function(sock)$/;" f
|
||||||
|
sip ./meizu/sipfs.lua /^function sip()$/;" f
|
||||||
|
sip_get_parameters ./meizu/sipfs.lua /^function sip_get_parameters(commandId)$/;" f
|
||||||
|
sip_response_uploader ./meizu/sipfs.lua /^function sip_response_uploader(cmd, commandId, data, finishstatus)$/;" f
|
||||||
|
socket.sinkt["http-chunked"] ./socket/http.lua /^socket.sinkt["http-chunked"] = function(sock)$/;" f
|
||||||
|
socket.sourcet["http-chunked"] ./socket/http.lua /^socket.sourcet["http-chunked"] = function(sock, headers)$/;" f
|
||||||
|
source.cat ./ltn12.lua /^function source.cat(...)$/;" f
|
||||||
|
source.chain ./ltn12.lua /^function source.chain(src, f, ...)$/;" f
|
||||||
|
source.empty ./ltn12.lua /^function source.empty()$/;" f
|
||||||
|
source.error ./ltn12.lua /^function source.error(err)$/;" f
|
||||||
|
source.file ./ltn12.lua /^function source.file(handle, io_err)$/;" f
|
||||||
|
source.rewind ./ltn12.lua /^function source.rewind(src)$/;" f
|
||||||
|
source.simplify ./ltn12.lua /^function source.simplify(src)$/;" f
|
||||||
|
source.string ./ltn12.lua /^function source.string(s)$/;" f
|
||||||
|
sourcet["by-length"] ./socket.lua /^sourcet["by-length"] = function(sock, length)$/;" f
|
||||||
|
sourcet["until-closed"] ./socket.lua /^sourcet["until-closed"] = function(sock)$/;" f
|
||||||
|
sput ./socket/ftp.lua /^local function sput(u, body)$/;" f
|
||||||
|
srequest ./socket/http.lua /^local function srequest(u, b)$/;" f
|
||||||
|
strsplit ./meizu/bfs.lua /^function strsplit(str, delim, maxNb)$/;" f
|
||||||
|
subscribe_auto_upgrade ./meizu/upgdfs.lua /^function subscribe_auto_upgrade()$/;" f
|
||||||
|
switch_status ./luci/controller/admin/network.lua /^function switch_status(switches)$/;" f
|
||||||
|
sysinfo ./meizu/bfs.lua /^function sysinfo()$/;" f
|
||||||
|
table_merge ./meizu/bfs.lua /^function table_merge(t1, t2)$/;" f
|
||||||
|
tcp ./ssl/https.lua /^local function tcp(params)$/;" f
|
||||||
|
template ./luci/dispatcher.lua /^function template(name)$/;" f
|
||||||
|
testip ./luci/controller/bs/index.lua /^function testip()$/;" f
|
||||||
|
tget ./socket/ftp.lua /^local function tget(gett)$/;" f
|
||||||
|
token ./luci/controller/bs/index.lua /^function token()$/;" f
|
||||||
|
tput ./socket/ftp.lua /^local function tput(putt)$/;" f
|
||||||
|
type(cfg.password) ~ ./ssl.lua /^ type(cfg.password) ~= "function" and$/;" f
|
||||||
|
unbind_router ./meizu/bfs.lua /^function unbind_router()$/;" f
|
||||||
|
unmesh_all_device ./meizu/nwfs.lua /^function unmesh_all_device()$/;" f
|
||||||
|
upRouterPushId ./routerReport.lua /^function upRouterPushId()$/;" f
|
||||||
|
updateBluetoothDevice ./meizu/dbfs.lua /^function updateBluetoothDevice(id, key, name, len, mac)$/;" f
|
||||||
|
updateDeviceNickname ./meizu/dbfs.lua /^function updateDeviceNickname(mac, nickname)$/;" f
|
||||||
|
updateDeviceOrgname ./meizu/dbfs.lua /^function updateDeviceOrgname(mac, orgname)$/;" f
|
||||||
|
update_access_token ./meizu/dbfs.lua /^function update_access_token(oldToken, newToken, expireTime)$/;" f
|
||||||
|
update_arp ./meizu/dbfs.lua /^function update_arp(mac, ip, wifi)$/;" f
|
||||||
|
update_ssid ./meizu/dbfs.lua /^function update_ssid(ssid24, ssid5)$/;" f
|
||||||
|
upgrade_lock ./meizu/upgdfs.lua /^function upgrade_lock()$/;" f
|
||||||
|
upgrade_unlock ./meizu/upgdfs.lua /^function upgrade_unlock()$/;" f
|
||||||
|
upload_router_log ./meizu/sipfs.lua /^function upload_router_log(logdata, logtype)$/;" f
|
||||||
|
url ./socket/url.lua /^ url = string.gsub(url, "#(.*)$", function(f)$/;" f
|
||||||
|
url ./socket/url.lua /^ url = string.gsub(url, "%;(.*)", function(p)$/;" f
|
||||||
|
url ./socket/url.lua /^ url = string.gsub(url, "%?(.*)", function(q)$/;" f
|
||||||
|
url ./socket/url.lua /^ url = string.gsub(url, "^\/\/([^\/]*)", function(n)$/;" f
|
||||||
|
urlstring_totable ./ssl/https.lua /^local function urlstring_totable(url, body, result_table)$/;" f
|
||||||
|
ut ./routerReport.lua /^function ut()$/;" f
|
||||||
|
wanRestart ./meizu/nwfs.lua /^function wanRestart()$/;" f
|
||||||
|
wifiNetwork ./luci/controller/admin/network.lua /^function wifiNetwork(wifiDeviceName)$/;" f
|
||||||
|
wifiNetworks ./luci/controller/admin/network.lua /^function wifiNetworks()$/;" f
|
||||||
|
wifi_add ./luci/controller/admin/network.lua /^function wifi_add()$/;" f
|
||||||
|
wifi_delete ./luci/controller/admin/network.lua /^function wifi_delete(network)$/;" f
|
||||||
|
wifi_join ./luci/controller/admin/network.lua /^function wifi_join()$/;" f
|
||||||
|
wifi_network ./meizu/nwfs.lua /^function wifi_network(wifi_device_name)$/;" f
|
||||||
|
wifi_networks ./meizu/nwfs.lua /^function wifi_networks()$/;" f
|
||||||
|
wifi_reconnect ./luci/controller/admin/network.lua /^function wifi_reconnect(wnet)$/;" f
|
||||||
|
wifi_reconnect ./meizu/nwfs.lua /^function wifi_reconnect(wnet)$/;" f
|
||||||
|
wifi_reconnect_shutdown ./luci/controller/admin/network.lua /^local function wifi_reconnect_shutdown(shutdown, wnet)$/;" f
|
||||||
|
wifi_reconnect_shutdown ./meizu/nwfs.lua /^local function wifi_reconnect_shutdown(shutdown, wnet)$/;" f
|
||||||
|
wifi_settings ./meizu/nwfs.lua /^function wifi_settings(on1, ssid1, pwd1, encry1, on2, ssid2, pwd2, encry2)$/;" f
|
||||||
|
wifi_shutdown ./luci/controller/admin/network.lua /^function wifi_shutdown(wnet)$/;" f
|
||||||
|
wifi_shutdown ./meizu/nwfs.lua /^function wifi_shutdown(wnet)$/;" f
|
||||||
|
wifi_status ./luci/controller/admin/network.lua /^function wifi_status(devs)$/;" f
|
||||||
|
wifidev.__init__ ./luci/model/network.lua /^function wifidev.__init__(self, dev)$/;" f
|
||||||
|
wifidev.add_wifinet ./luci/model/network.lua /^function wifidev.add_wifinet(self, options)$/;" f
|
||||||
|
wifidev.del_wifinet ./luci/model/network.lua /^function wifidev.del_wifinet(self, net)$/;" f
|
||||||
|
wifidev.get ./luci/model/network.lua /^function wifidev.get(self, opt)$/;" f
|
||||||
|
wifidev.get_i18n ./luci/model/network.lua /^function wifidev.get_i18n(self)$/;" f
|
||||||
|
wifidev.get_wifinet ./luci/model/network.lua /^function wifidev.get_wifinet(self, net)$/;" f
|
||||||
|
wifidev.get_wifinets ./luci/model/network.lua /^function wifidev.get_wifinets(self)$/;" f
|
||||||
|
wifidev.hwmodes ./luci/model/network.lua /^function wifidev.hwmodes(self)$/;" f
|
||||||
|
wifidev.is_up ./luci/model/network.lua /^function wifidev.is_up(self)$/;" f
|
||||||
|
wifidev.name ./luci/model/network.lua /^function wifidev.name(self)$/;" f
|
||||||
|
wifidev.set ./luci/model/network.lua /^function wifidev.set(self, opt, val)$/;" f
|
||||||
|
wifinet.__init__ ./luci/model/network.lua /^function wifinet.__init__(self, net, data)$/;" f
|
||||||
|
wifinet.active_bssid ./luci/model/network.lua /^function wifinet.active_bssid(self)$/;" f
|
||||||
|
wifinet.active_encryption ./luci/model/network.lua /^function wifinet.active_encryption(self)$/;" f
|
||||||
|
wifinet.active_mode ./luci/model/network.lua /^function wifinet.active_mode(self)$/;" f
|
||||||
|
wifinet.active_mode_i18n ./luci/model/network.lua /^function wifinet.active_mode_i18n(self)$/;" f
|
||||||
|
wifinet.active_ssid ./luci/model/network.lua /^function wifinet.active_ssid(self)$/;" f
|
||||||
|
wifinet.adminlink ./luci/model/network.lua /^function wifinet.adminlink(self)$/;" f
|
||||||
|
wifinet.assoclist ./luci/model/network.lua /^function wifinet.assoclist(self)$/;" f
|
||||||
|
wifinet.bitrate ./luci/model/network.lua /^function wifinet.bitrate(self)$/;" f
|
||||||
|
wifinet.bssid ./luci/model/network.lua /^function wifinet.bssid(self)$/;" f
|
||||||
|
wifinet.channel ./luci/model/network.lua /^function wifinet.channel(self)$/;" f
|
||||||
|
wifinet.country ./luci/model/network.lua /^function wifinet.country(self)$/;" f
|
||||||
|
wifinet.frequency ./luci/model/network.lua /^function wifinet.frequency(self)$/;" f
|
||||||
|
wifinet.get ./luci/model/network.lua /^function wifinet.get(self, opt)$/;" f
|
||||||
|
wifinet.get_device ./luci/model/network.lua /^function wifinet.get_device(self)$/;" f
|
||||||
|
wifinet.get_i18n ./luci/model/network.lua /^function wifinet.get_i18n(self)$/;" f
|
||||||
|
wifinet.get_interface ./luci/model/network.lua /^function wifinet.get_interface(self)$/;" f
|
||||||
|
wifinet.get_network ./luci/model/network.lua /^function wifinet.get_network(self)$/;" f
|
||||||
|
wifinet.get_networks ./luci/model/network.lua /^function wifinet.get_networks(self)$/;" f
|
||||||
|
wifinet.id ./luci/model/network.lua /^function wifinet.id(self)$/;" f
|
||||||
|
wifinet.ifname ./luci/model/network.lua /^function wifinet.ifname(self)$/;" f
|
||||||
|
wifinet.is_up ./luci/model/network.lua /^function wifinet.is_up(self)$/;" f
|
||||||
|
wifinet.mode ./luci/model/network.lua /^function wifinet.mode(self)$/;" f
|
||||||
|
wifinet.name ./luci/model/network.lua /^function wifinet.name(self)$/;" f
|
||||||
|
wifinet.network ./luci/model/network.lua /^function wifinet.network(self)$/;" f
|
||||||
|
wifinet.noise ./luci/model/network.lua /^function wifinet.noise(self)$/;" f
|
||||||
|
wifinet.set ./luci/model/network.lua /^function wifinet.set(self, opt, val)$/;" f
|
||||||
|
wifinet.shortname ./luci/model/network.lua /^function wifinet.shortname(self)$/;" f
|
||||||
|
wifinet.signal ./luci/model/network.lua /^function wifinet.signal(self)$/;" f
|
||||||
|
wifinet.signal_level ./luci/model/network.lua /^function wifinet.signal_level(self, s, n)$/;" f
|
||||||
|
wifinet.signal_percent ./luci/model/network.lua /^function wifinet.signal_percent(self)$/;" f
|
||||||
|
wifinet.ssid ./luci/model/network.lua /^function wifinet.ssid(self)$/;" f
|
||||||
|
wifinet.txpower ./luci/model/network.lua /^function wifinet.txpower(self)$/;" f
|
||||||
|
wifinet.txpower_offset ./luci/model/network.lua /^function wifinet.txpower_offset(self)$/;" f
|
||||||
|
wrap ./ssl.lua /^function wrap(sock, cfg)$/;" f
|
||||||
|
wrapt['quoted-printable'] ./mime.lua /^wrapt['quoted-printable'] = function()$/;" f
|
||||||
|
wrapt['text'] ./mime.lua /^wrapt['text'] = function(length)$/;" f
|
||||||
|
write ./luci/sauth.lua /^function write(id, data)$/;" f
|
||||||
|
ww_add_ble_mesh_device ./meizu/nwfs.lua /^function ww_add_ble_mesh_device(mac)$/;" f
|
||||||
|
ww_del_mesh_device_timer ./meizu/nwfs.lua /^function ww_del_mesh_device_timer(mac, timer_id)$/;" f
|
||||||
|
ww_exec_reboot ./meizu/sipfs.lua /^function ww_exec_reboot(cmd, cmdid)$/;" f
|
||||||
|
ww_get_ble_device_list ./meizu/nwfs.lua /^function ww_get_ble_device_list()$/;" f
|
||||||
|
ww_get_ble_device_status ./meizu/nwfs.lua /^function ww_get_ble_device_status(mac)$/;" f
|
||||||
|
ww_get_bluetooth_info ./meizu/nwfs.lua /^function ww_get_bluetooth_info()$/;" f
|
||||||
|
ww_get_connect_device_list ./meizu/nwfs.lua /^function ww_get_connect_device_list()$/;" f
|
||||||
|
ww_get_device_details ./meizu/nwfs.lua /^function ww_get_device_details(mac)$/;" f
|
||||||
|
ww_get_mesh_device_list ./meizu/nwfs.lua /^function ww_get_mesh_device_list()$/;" f
|
||||||
|
ww_get_wan_type ./meizu/nwfs.lua /^function ww_get_wan_type()$/;" f
|
||||||
|
ww_get_wifi_settings ./meizu/nwfs.lua /^function ww_get_wifi_settings(app_version)$/;" f
|
||||||
|
ww_get_wireless_channel ./meizu/nwfs.lua /^function ww_get_wireless_channel()$/;" f
|
||||||
|
ww_reboot_mesh_device ./meizu/nwfs.lua /^function ww_reboot_mesh_device(mac)$/;" f
|
||||||
|
ww_remove_ble_from_mesh ./meizu/nwfs.lua /^function ww_remove_ble_from_mesh(mac)$/;" f
|
||||||
|
ww_scan_ble_switch ./meizu/nwfs.lua /^function ww_scan_ble_switch(status)$/;" f
|
||||||
|
ww_set_bluetooth ./meizu/nwfs.lua /^function ww_set_bluetooth()$/;" f
|
||||||
|
ww_set_lamp_brightness ./meizu/nwfs.lua /^function ww_set_lamp_brightness()$/;" f
|
||||||
|
ww_set_mesh_device_attr ./meizu/nwfs.lua /^function ww_set_mesh_device_attr(mac, key, value)$/;" f
|
||||||
|
ww_set_mesh_device_timer ./meizu/nwfs.lua /^function ww_set_mesh_device_timer(mac, timer_id, flag, start, ends)$/;" f
|
||||||
|
ww_set_mesh_network_pwd ./meizu/nwfs.lua /^function ww_set_mesh_network_pwd (old_key, new_key)$/;" f
|
||||||
|
ww_set_wireless_channel ./meizu/nwfs.lua /^function ww_set_wireless_channel(channel, extch)$/;" f
|
||||||
|
ww_unmesh_all_device ./meizu/nwfs.lua /^function ww_unmesh_all_device()$/;" f
|
||||||
|
}, {__index ./luci/dispatcher.lua /^ }, {__index=function(table, key)$/;" f
|
113
Mi_Lua/Posix.lua
Normal file
113
Mi_Lua/Posix.lua
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
local base = _G
|
||||||
|
local string = require("string")
|
||||||
|
local M = require "posix"
|
||||||
|
|
||||||
|
function M.timeradd (x,y)
|
||||||
|
local sec, usec = 0, 0
|
||||||
|
if x.sec then sec = sec + x.sec end
|
||||||
|
if y.sec then sec = sec + y.sec end
|
||||||
|
if x.usec then usec = usec + x.usec end
|
||||||
|
if y.usec then usec = usec + y.usec end
|
||||||
|
if usec > 1000000 then
|
||||||
|
sec = sec + 1
|
||||||
|
usec = usec - 1000000
|
||||||
|
end
|
||||||
|
|
||||||
|
return { sec = sec, usec = usec }
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function M.timercmp (x, y)
|
||||||
|
local x = { sec = x.sec or 0, usec = x.usec or 0 }
|
||||||
|
local y = { sec = y.sec or 0, usec = y.usec or 0 }
|
||||||
|
if x.sec ~= y.sec then
|
||||||
|
return x.sec - y.sec
|
||||||
|
else
|
||||||
|
return x.usec - y.usec
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function M.timersub (x,y)
|
||||||
|
local sec, usec = 0, 0
|
||||||
|
if x.sec then sec = x.sec end
|
||||||
|
if y.sec then sec = sec - y.sec end
|
||||||
|
if x.usec then usec = x.usec end
|
||||||
|
if y.usec then usec = usec - y.usec end
|
||||||
|
if usec < 0 then
|
||||||
|
sec = sec - 1
|
||||||
|
usec = usec + 1000000
|
||||||
|
end
|
||||||
|
|
||||||
|
return { sec = sec, usec = usec }
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.timesleep (x)
|
||||||
|
local sec, nsec = 0, 0
|
||||||
|
y = M.gettimeofday();
|
||||||
|
if( M.timercmp(x, y) > 0 ) then
|
||||||
|
sec = x.sec - y.sec
|
||||||
|
nsec = (x.usec - y.usec) * 1000
|
||||||
|
if nsec < 0 then
|
||||||
|
sec = sec - 1
|
||||||
|
nsec = nsec + 1000000000
|
||||||
|
end
|
||||||
|
M.nanosleep(sec, nsec)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.strsplit(str, delim, maxNb)
|
||||||
|
-- Eliminate bad cases...
|
||||||
|
if string.find(str, delim) == nil then
|
||||||
|
return { str }
|
||||||
|
end
|
||||||
|
if maxNb == nil or maxNb < 1 then
|
||||||
|
maxNb = 0 -- No limit
|
||||||
|
end
|
||||||
|
local result = {}
|
||||||
|
local pat = "(.-)" .. delim .. "()"
|
||||||
|
local nb = 0
|
||||||
|
local lastPos
|
||||||
|
for part, pos in string.gfind(str, pat) do
|
||||||
|
nb = nb + 1
|
||||||
|
result[nb] = part
|
||||||
|
lastPos = pos
|
||||||
|
if nb == maxNb then break end
|
||||||
|
end
|
||||||
|
-- Handle the last field
|
||||||
|
if nb ~= maxNb then
|
||||||
|
result[nb + 1] = string.sub(str, lastPos)
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.var_dump(data, max_level, prefix)
|
||||||
|
if type(prefix) ~= "string" then
|
||||||
|
prefix = ""
|
||||||
|
end
|
||||||
|
if type(data) ~= "table" then
|
||||||
|
print(prefix .. tostring(data))
|
||||||
|
else
|
||||||
|
print(data)
|
||||||
|
if max_level ~= 0 then
|
||||||
|
local prefix_next = prefix .. " "
|
||||||
|
print(prefix .. "{")
|
||||||
|
for k,v in pairs(data) do
|
||||||
|
io.stdout:write(prefix_next .. k .. " = ")
|
||||||
|
if type(v) ~= "table" or (type(max_level) == "number" and max_level <= 1) then
|
||||||
|
print(v)
|
||||||
|
else
|
||||||
|
if max_level == nil then
|
||||||
|
M.var_dump(v, nil, prefix_next)
|
||||||
|
else
|
||||||
|
M.var_dump(v, max_level - 1, prefix_next)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
print(prefix .. "}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return M
|
15
Mi_Lua/bit.lua
Normal file
15
Mi_Lua/bit.lua
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
--[[
|
||||||
|
nixio - Linux I/O library for lua
|
||||||
|
|
||||||
|
Copyright 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$
|
||||||
|
]]--
|
||||||
|
|
||||||
|
return require "nixio".bit
|
BIN
Mi_Lua/cjson.so
Normal file
BIN
Mi_Lua/cjson.so
Normal file
Binary file not shown.
BIN
Mi_Lua/iproute.so
Normal file
BIN
Mi_Lua/iproute.so
Normal file
Binary file not shown.
BIN
Mi_Lua/iwinfo.so
Normal file
BIN
Mi_Lua/iwinfo.so
Normal file
Binary file not shown.
376
Mi_Lua/json.lua
Normal file
376
Mi_Lua/json.lua
Normal file
@ -0,0 +1,376 @@
|
|||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- JSON4Lua: JSON encoding / decoding support for the Lua language.
|
||||||
|
-- json Module.
|
||||||
|
-- Author: Craig Mason-Jones
|
||||||
|
-- Homepage: http://json.luaforge.net/
|
||||||
|
-- Version: 0.9.40
|
||||||
|
-- This module is released under the MIT License (MIT).
|
||||||
|
-- Please see LICENCE.txt for details.
|
||||||
|
--
|
||||||
|
-- USAGE:
|
||||||
|
-- This module exposes two functions:
|
||||||
|
-- encode(o)
|
||||||
|
-- Returns the table / string / boolean / number / nil / json.null value as a JSON-encoded string.
|
||||||
|
-- decode(json_string)
|
||||||
|
-- Returns a Lua object populated with the data encoded in the JSON string json_string.
|
||||||
|
--
|
||||||
|
-- REQUIREMENTS:
|
||||||
|
-- compat-5.1 if using Lua 5.0
|
||||||
|
--
|
||||||
|
-- CHANGELOG
|
||||||
|
-- 0.9.20 Introduction of local Lua functions for private functions (removed _ function prefix).
|
||||||
|
-- Fixed Lua 5.1 compatibility issues.
|
||||||
|
-- Introduced json.null to have null values in associative arrays.
|
||||||
|
-- encode() performance improvement (more than 50%) through table.concat rather than ..
|
||||||
|
-- Introduced decode ability to ignore /**/ comments in the JSON string.
|
||||||
|
-- 0.9.10 Fix to array encoding / decoding to correctly manage nil/null values in arrays.
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Imports and dependencies
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
local math = require('math')
|
||||||
|
local string = require("string")
|
||||||
|
local table = require("table")
|
||||||
|
|
||||||
|
local base = _G
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Module declaration
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
module("json")
|
||||||
|
|
||||||
|
-- Public functions
|
||||||
|
|
||||||
|
-- Private functions
|
||||||
|
local decode_scanArray
|
||||||
|
local decode_scanComment
|
||||||
|
local decode_scanConstant
|
||||||
|
local decode_scanNumber
|
||||||
|
local decode_scanObject
|
||||||
|
local decode_scanString
|
||||||
|
local decode_scanWhitespace
|
||||||
|
local encodeString
|
||||||
|
local isArray
|
||||||
|
local isEncodable
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- PUBLIC FUNCTIONS
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
--- Encodes an arbitrary Lua object / variable.
|
||||||
|
-- @param v The Lua object / variable to be JSON encoded.
|
||||||
|
-- @return String containing the JSON encoding in internal Lua string format (i.e. not unicode)
|
||||||
|
function encode (v)
|
||||||
|
-- Handle nil values
|
||||||
|
if v==nil then
|
||||||
|
return "null"
|
||||||
|
end
|
||||||
|
|
||||||
|
local vtype = base.type(v)
|
||||||
|
|
||||||
|
-- Handle strings
|
||||||
|
if vtype=='string' then
|
||||||
|
return '"' .. encodeString(v) .. '"' -- Need to handle encoding in string
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Handle booleans
|
||||||
|
if vtype=='number' or vtype=='boolean' then
|
||||||
|
return base.tostring(v)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Handle tables
|
||||||
|
if vtype=='table' then
|
||||||
|
local rval = {}
|
||||||
|
-- Consider arrays separately
|
||||||
|
local bArray, maxCount = isArray(v)
|
||||||
|
if bArray then
|
||||||
|
for i = 1,maxCount do
|
||||||
|
table.insert(rval, encode(v[i]))
|
||||||
|
end
|
||||||
|
else -- An object, not an array
|
||||||
|
for i,j in base.pairs(v) do
|
||||||
|
if isEncodable(i) and isEncodable(j) then
|
||||||
|
table.insert(rval, '"' .. encodeString(i) .. '":' .. encode(j))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if bArray then
|
||||||
|
return '[' .. table.concat(rval,',') ..']'
|
||||||
|
else
|
||||||
|
return '{' .. table.concat(rval,',') .. '}'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Handle null values
|
||||||
|
if vtype=='function' and v==null then
|
||||||
|
return 'null'
|
||||||
|
end
|
||||||
|
|
||||||
|
base.assert(false,'encode attempt to encode unsupported type ' .. vtype .. ':' .. base.tostring(v))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Decodes a JSON string and returns the decoded value as a Lua data structure / value.
|
||||||
|
-- @param s The string to scan.
|
||||||
|
-- @param [startPos] Optional starting position where the JSON string is located. Defaults to 1.
|
||||||
|
-- @param Lua object, number The object that was scanned, as a Lua table / string / number / boolean or nil,
|
||||||
|
-- and the position of the first character after
|
||||||
|
-- the scanned JSON object.
|
||||||
|
function decode(s, startPos)
|
||||||
|
startPos = startPos and startPos or 1
|
||||||
|
startPos = decode_scanWhitespace(s,startPos)
|
||||||
|
base.assert(startPos<=string.len(s), 'Unterminated JSON encoded object found at position in [' .. s .. ']')
|
||||||
|
local curChar = string.sub(s,startPos,startPos)
|
||||||
|
-- Object
|
||||||
|
if curChar=='{' then
|
||||||
|
return decode_scanObject(s,startPos)
|
||||||
|
end
|
||||||
|
-- Array
|
||||||
|
if curChar=='[' then
|
||||||
|
return decode_scanArray(s,startPos)
|
||||||
|
end
|
||||||
|
-- Number
|
||||||
|
if string.find("+-0123456789.e", curChar, 1, true) then
|
||||||
|
return decode_scanNumber(s,startPos)
|
||||||
|
end
|
||||||
|
-- String
|
||||||
|
if curChar==[["]] or curChar==[[']] then
|
||||||
|
return decode_scanString(s,startPos)
|
||||||
|
end
|
||||||
|
if string.sub(s,startPos,startPos+1)=='/*' then
|
||||||
|
return decode(s, decode_scanComment(s,startPos))
|
||||||
|
end
|
||||||
|
-- Otherwise, it must be a constant
|
||||||
|
return decode_scanConstant(s,startPos)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- The null function allows one to specify a null value in an associative array (which is otherwise
|
||||||
|
-- discarded if you set the value with 'nil' in Lua. Simply set t = { first=json.null }
|
||||||
|
function null()
|
||||||
|
return null -- so json.null() will also return null ;-)
|
||||||
|
end
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Internal, PRIVATE functions.
|
||||||
|
-- Following a Python-like convention, I have prefixed all these 'PRIVATE'
|
||||||
|
-- functions with an underscore.
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Scans an array from JSON into a Lua object
|
||||||
|
-- startPos begins at the start of the array.
|
||||||
|
-- Returns the array and the next starting position
|
||||||
|
-- @param s The string being scanned.
|
||||||
|
-- @param startPos The starting position for the scan.
|
||||||
|
-- @return table, int The scanned array as a table, and the position of the next character to scan.
|
||||||
|
function decode_scanArray(s,startPos)
|
||||||
|
local array = {} -- The return value
|
||||||
|
local stringLen = string.len(s)
|
||||||
|
base.assert(string.sub(s,startPos,startPos)=='[','decode_scanArray called but array does not start at position ' .. startPos .. ' in string:\n'..s )
|
||||||
|
startPos = startPos + 1
|
||||||
|
-- Infinite loop for array elements
|
||||||
|
repeat
|
||||||
|
startPos = decode_scanWhitespace(s,startPos)
|
||||||
|
base.assert(startPos<=stringLen,'JSON String ended unexpectedly scanning array.')
|
||||||
|
local curChar = string.sub(s,startPos,startPos)
|
||||||
|
if (curChar==']') then
|
||||||
|
return array, startPos+1
|
||||||
|
end
|
||||||
|
if (curChar==',') then
|
||||||
|
startPos = decode_scanWhitespace(s,startPos+1)
|
||||||
|
end
|
||||||
|
base.assert(startPos<=stringLen, 'JSON String ended unexpectedly scanning array.')
|
||||||
|
object, startPos = decode(s,startPos)
|
||||||
|
table.insert(array,object)
|
||||||
|
until false
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Scans a comment and discards the comment.
|
||||||
|
-- Returns the position of the next character following the comment.
|
||||||
|
-- @param string s The JSON string to scan.
|
||||||
|
-- @param int startPos The starting position of the comment
|
||||||
|
function decode_scanComment(s, startPos)
|
||||||
|
base.assert( string.sub(s,startPos,startPos+1)=='/*', "decode_scanComment called but comment does not start at position " .. startPos)
|
||||||
|
local endPos = string.find(s,'*/',startPos+2)
|
||||||
|
base.assert(endPos~=nil, "Unterminated comment in string at " .. startPos)
|
||||||
|
return endPos+2
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Scans for given constants: true, false or null
|
||||||
|
-- Returns the appropriate Lua type, and the position of the next character to read.
|
||||||
|
-- @param s The string being scanned.
|
||||||
|
-- @param startPos The position in the string at which to start scanning.
|
||||||
|
-- @return object, int The object (true, false or nil) and the position at which the next character should be
|
||||||
|
-- scanned.
|
||||||
|
function decode_scanConstant(s, startPos)
|
||||||
|
local consts = { ["true"] = true, ["false"] = false, ["null"] = nil }
|
||||||
|
local constNames = {"true","false","null"}
|
||||||
|
|
||||||
|
for i,k in base.pairs(constNames) do
|
||||||
|
--print ("[" .. string.sub(s,startPos, startPos + string.len(k) -1) .."]", k)
|
||||||
|
if string.sub(s,startPos, startPos + string.len(k) -1 )==k then
|
||||||
|
return consts[k], startPos + string.len(k)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
base.assert(nil, 'Failed to scan constant from string ' .. s .. ' at starting position ' .. startPos)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Scans a number from the JSON encoded string.
|
||||||
|
-- (in fact, also is able to scan numeric +- eqns, which is not
|
||||||
|
-- in the JSON spec.)
|
||||||
|
-- Returns the number, and the position of the next character
|
||||||
|
-- after the number.
|
||||||
|
-- @param s The string being scanned.
|
||||||
|
-- @param startPos The position at which to start scanning.
|
||||||
|
-- @return number, int The extracted number and the position of the next character to scan.
|
||||||
|
function decode_scanNumber(s,startPos)
|
||||||
|
local endPos = startPos+1
|
||||||
|
local stringLen = string.len(s)
|
||||||
|
local acceptableChars = "+-0123456789.e"
|
||||||
|
while (string.find(acceptableChars, string.sub(s,endPos,endPos), 1, true)
|
||||||
|
and endPos<=stringLen
|
||||||
|
) do
|
||||||
|
endPos = endPos + 1
|
||||||
|
end
|
||||||
|
local stringValue = 'return ' .. string.sub(s,startPos, endPos-1)
|
||||||
|
local stringEval = base.loadstring(stringValue)
|
||||||
|
base.assert(stringEval, 'Failed to scan number [ ' .. stringValue .. '] in JSON string at position ' .. startPos .. ' : ' .. endPos)
|
||||||
|
return stringEval(), endPos
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Scans a JSON object into a Lua object.
|
||||||
|
-- startPos begins at the start of the object.
|
||||||
|
-- Returns the object and the next starting position.
|
||||||
|
-- @param s The string being scanned.
|
||||||
|
-- @param startPos The starting position of the scan.
|
||||||
|
-- @return table, int The scanned object as a table and the position of the next character to scan.
|
||||||
|
function decode_scanObject(s,startPos)
|
||||||
|
local object = {}
|
||||||
|
local stringLen = string.len(s)
|
||||||
|
local key, value
|
||||||
|
base.assert(string.sub(s,startPos,startPos)=='{','decode_scanObject called but object does not start at position ' .. startPos .. ' in string:\n' .. s)
|
||||||
|
startPos = startPos + 1
|
||||||
|
repeat
|
||||||
|
startPos = decode_scanWhitespace(s,startPos)
|
||||||
|
base.assert(startPos<=stringLen, 'JSON string ended unexpectedly while scanning object.')
|
||||||
|
local curChar = string.sub(s,startPos,startPos)
|
||||||
|
if (curChar=='}') then
|
||||||
|
return object,startPos+1
|
||||||
|
end
|
||||||
|
if (curChar==',') then
|
||||||
|
startPos = decode_scanWhitespace(s,startPos+1)
|
||||||
|
end
|
||||||
|
base.assert(startPos<=stringLen, 'JSON string ended unexpectedly scanning object.')
|
||||||
|
-- Scan the key
|
||||||
|
key, startPos = decode(s,startPos)
|
||||||
|
base.assert(startPos<=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key)
|
||||||
|
startPos = decode_scanWhitespace(s,startPos)
|
||||||
|
base.assert(startPos<=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key)
|
||||||
|
base.assert(string.sub(s,startPos,startPos)==':','JSON object key-value assignment mal-formed at ' .. startPos)
|
||||||
|
startPos = decode_scanWhitespace(s,startPos+1)
|
||||||
|
base.assert(startPos<=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key)
|
||||||
|
value, startPos = decode(s,startPos)
|
||||||
|
object[key]=value
|
||||||
|
until false -- infinite loop while key-value pairs are found
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Scans a JSON string from the opening inverted comma or single quote to the
|
||||||
|
-- end of the string.
|
||||||
|
-- Returns the string extracted as a Lua string,
|
||||||
|
-- and the position of the next non-string character
|
||||||
|
-- (after the closing inverted comma or single quote).
|
||||||
|
-- @param s The string being scanned.
|
||||||
|
-- @param startPos The starting position of the scan.
|
||||||
|
-- @return string, int The extracted string as a Lua string, and the next character to parse.
|
||||||
|
function decode_scanString(s,startPos)
|
||||||
|
base.assert(startPos, 'decode_scanString(..) called without start position')
|
||||||
|
local startChar = string.sub(s,startPos,startPos)
|
||||||
|
base.assert(startChar==[[']] or startChar==[["]],'decode_scanString called for a non-string')
|
||||||
|
local escaped = false
|
||||||
|
local endPos = startPos + 1
|
||||||
|
local bEnded = false
|
||||||
|
local stringLen = string.len(s)
|
||||||
|
repeat
|
||||||
|
local curChar = string.sub(s,endPos,endPos)
|
||||||
|
-- Character escaping is only used to escape the string delimiters
|
||||||
|
if not escaped then
|
||||||
|
if curChar==[[\]] then
|
||||||
|
escaped = true
|
||||||
|
else
|
||||||
|
bEnded = curChar==startChar
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- If we're escaped, we accept the current character come what may
|
||||||
|
escaped = false
|
||||||
|
end
|
||||||
|
endPos = endPos + 1
|
||||||
|
base.assert(endPos <= stringLen+1, "String decoding failed: unterminated string at position " .. endPos)
|
||||||
|
until bEnded
|
||||||
|
local stringValue = 'return ' .. string.sub(s, startPos, endPos-1)
|
||||||
|
local stringEval = base.loadstring(stringValue)
|
||||||
|
base.assert(stringEval, 'Failed to load string [ ' .. stringValue .. '] in JSON4Lua.decode_scanString at position ' .. startPos .. ' : ' .. endPos)
|
||||||
|
return stringEval(), endPos
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Scans a JSON string skipping all whitespace from the current start position.
|
||||||
|
-- Returns the position of the first non-whitespace character, or nil if the whole end of string is reached.
|
||||||
|
-- @param s The string being scanned
|
||||||
|
-- @param startPos The starting position where we should begin removing whitespace.
|
||||||
|
-- @return int The first position where non-whitespace was encountered, or string.len(s)+1 if the end of string
|
||||||
|
-- was reached.
|
||||||
|
function decode_scanWhitespace(s,startPos)
|
||||||
|
local whitespace=" \n\r\t"
|
||||||
|
local stringLen = string.len(s)
|
||||||
|
while ( string.find(whitespace, string.sub(s,startPos,startPos), 1, true) and startPos <= stringLen) do
|
||||||
|
startPos = startPos + 1
|
||||||
|
end
|
||||||
|
return startPos
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Encodes a string to be JSON-compatible.
|
||||||
|
-- This just involves back-quoting inverted commas, back-quotes and newlines, I think ;-)
|
||||||
|
-- @param s The string to return as a JSON encoded (i.e. backquoted string)
|
||||||
|
-- @return The string appropriately escaped.
|
||||||
|
function encodeString(s)
|
||||||
|
s = string.gsub(s,'\\','\\\\')
|
||||||
|
s = string.gsub(s,'"','\\"')
|
||||||
|
s = string.gsub(s,"'","\\'")
|
||||||
|
s = string.gsub(s,'\n','\\n')
|
||||||
|
s = string.gsub(s,'\t','\\t')
|
||||||
|
return s
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Determines whether the given Lua type is an array or a table / dictionary.
|
||||||
|
-- We consider any table an array if it has indexes 1..n for its n items, and no
|
||||||
|
-- other data in the table.
|
||||||
|
-- I think this method is currently a little 'flaky', but can't think of a good way around it yet...
|
||||||
|
-- @param t The table to evaluate as an array
|
||||||
|
-- @return boolean, number True if the table can be represented as an array, false otherwise. If true,
|
||||||
|
-- the second returned value is the maximum
|
||||||
|
-- number of indexed elements in the array.
|
||||||
|
function isArray(t)
|
||||||
|
-- Next we count all the elements, ensuring that any non-indexed elements are not-encodable
|
||||||
|
-- (with the possible exception of 'n')
|
||||||
|
local maxIndex = 0
|
||||||
|
for k,v in base.pairs(t) do
|
||||||
|
if (base.type(k)=='number' and math.floor(k)==k and 1<=k) then -- k,v is an indexed pair
|
||||||
|
if (not isEncodable(v)) then return false end -- All array elements must be encodable
|
||||||
|
maxIndex = math.max(maxIndex,k)
|
||||||
|
else
|
||||||
|
if (k=='n') then
|
||||||
|
if v ~= table.getn(t) then return false end -- False if n does not hold the number of elements
|
||||||
|
else -- Else of (k=='n')
|
||||||
|
if isEncodable(v) then return false end
|
||||||
|
end -- End of (k~='n')
|
||||||
|
end -- End of k,v not an indexed pair
|
||||||
|
end -- End of loop across all pairs
|
||||||
|
return true, maxIndex
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Determines whether the given Lua object / table / variable can be JSON encoded. The only
|
||||||
|
-- types that are JSON encodable are: string, boolean, number, nil, table and json.null.
|
||||||
|
-- In this implementation, all other types are ignored.
|
||||||
|
-- @param o The object to examine.
|
||||||
|
-- @return boolean True if the object should be JSON encoded, false if it should be ignored.
|
||||||
|
function isEncodable(o)
|
||||||
|
local t = base.type(o)
|
||||||
|
return (t=='string' or t=='boolean' or t=='number' or t=='nil' or t=='table') or (t=='function' and o==null)
|
||||||
|
end
|
201
Mi_Lua/logging.lua
Normal file
201
Mi_Lua/logging.lua
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- includes a new tostring function that handles tables recursively
|
||||||
|
--
|
||||||
|
-- @author Danilo Tuler (tuler@ideais.com.br)
|
||||||
|
-- @author Andre Carregal (info@keplerproject.org)
|
||||||
|
-- @author Thiago Costa Ponte (thiago@ideais.com.br)
|
||||||
|
--
|
||||||
|
-- @copyright 2004-2013 Kepler Project
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local type, table, string, _tostring, tonumber = type, table, string, tostring, tonumber
|
||||||
|
local select = select
|
||||||
|
local error = error
|
||||||
|
local format = string.format
|
||||||
|
local pairs = pairs
|
||||||
|
local ipairs = ipairs
|
||||||
|
|
||||||
|
local logging = {
|
||||||
|
|
||||||
|
-- Meta information
|
||||||
|
_COPYRIGHT = "Copyright (C) 2004-2013 Kepler Project",
|
||||||
|
_DESCRIPTION = "A simple API to use logging features in Lua",
|
||||||
|
_VERSION = "LuaLogging 1.3.0",
|
||||||
|
|
||||||
|
-- The DEBUG Level designates fine-grained instring.formational events that are most
|
||||||
|
-- useful to debug an application
|
||||||
|
DEBUG = "DEBUG",
|
||||||
|
|
||||||
|
-- The INFO level designates instring.formational messages that highlight the
|
||||||
|
-- progress of the application at coarse-grained level
|
||||||
|
INFO = "INFO",
|
||||||
|
|
||||||
|
-- The WARN level designates potentially harmful situations
|
||||||
|
WARN = "WARN",
|
||||||
|
|
||||||
|
-- The ERROR level designates error events that might still allow the
|
||||||
|
-- application to continue running
|
||||||
|
ERROR = "ERROR",
|
||||||
|
|
||||||
|
-- The FATAL level designates very severe error events that will presumably
|
||||||
|
-- lead the application to abort
|
||||||
|
FATAL = "FATAL",
|
||||||
|
}
|
||||||
|
|
||||||
|
local LEVEL = {"DEBUG", "INFO", "WARN", "ERROR", "FATAL"}
|
||||||
|
local MAX_LEVELS = #LEVEL
|
||||||
|
-- make level names to order
|
||||||
|
for i=1,MAX_LEVELS do
|
||||||
|
LEVEL[LEVEL[i]] = i
|
||||||
|
end
|
||||||
|
|
||||||
|
-- private log function, with support for formating a complex log message.
|
||||||
|
local function LOG_MSG(self, level, fmt, ...)
|
||||||
|
local f_type = type(fmt)
|
||||||
|
if f_type == 'string' then
|
||||||
|
if select('#', ...) > 0 then
|
||||||
|
return self:append(level, format(fmt, ...))
|
||||||
|
else
|
||||||
|
-- only a single string, no formating needed.
|
||||||
|
return self:append(level, fmt)
|
||||||
|
end
|
||||||
|
elseif f_type == 'function' then
|
||||||
|
-- fmt should be a callable function which returns the message to log
|
||||||
|
return self:append(level, fmt(...))
|
||||||
|
end
|
||||||
|
-- fmt is not a string and not a function, just call tostring() on it.
|
||||||
|
return self:append(level, logging.tostring(fmt))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- create the proxy functions for each log level.
|
||||||
|
local LEVEL_FUNCS = {}
|
||||||
|
for i=1,MAX_LEVELS do
|
||||||
|
local level = LEVEL[i]
|
||||||
|
LEVEL_FUNCS[i] = function(self, ...)
|
||||||
|
-- no level checking needed here, this function will only be called if it's level is active.
|
||||||
|
return LOG_MSG(self, level, ...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- do nothing function for disabled levels.
|
||||||
|
local function disable_level() end
|
||||||
|
|
||||||
|
-- improved assertion function.
|
||||||
|
local function assert(exp, ...)
|
||||||
|
-- if exp is true, we are finished so don't do any processing of the parameters
|
||||||
|
if exp then return exp, ... end
|
||||||
|
-- assertion failed, raise error
|
||||||
|
error(format(...), 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Creates a new logger object
|
||||||
|
-- @param append Function used by the logger to append a message with a
|
||||||
|
-- log-level to the log stream.
|
||||||
|
-- @return Table representing the new logger object.
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
function logging.new(append)
|
||||||
|
if type(append) ~= "function" then
|
||||||
|
return nil, "Appender must be a function."
|
||||||
|
end
|
||||||
|
|
||||||
|
local logger = {}
|
||||||
|
logger.append = append
|
||||||
|
|
||||||
|
logger.setLevel = function (self, level)
|
||||||
|
local order = LEVEL[level]
|
||||||
|
assert(order, "undefined level `%s'", _tostring(level))
|
||||||
|
if self.level then
|
||||||
|
self:log(logging.WARN, "Logger: changing loglevel from %s to %s", self.level, level)
|
||||||
|
end
|
||||||
|
self.level = level
|
||||||
|
self.level_order = order
|
||||||
|
-- enable/disable levels
|
||||||
|
for i=1,MAX_LEVELS do
|
||||||
|
local name = LEVEL[i]:lower()
|
||||||
|
if i >= order then
|
||||||
|
self[name] = LEVEL_FUNCS[i]
|
||||||
|
else
|
||||||
|
self[name] = disable_level
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- generic log function.
|
||||||
|
logger.log = function (self, level, ...)
|
||||||
|
local order = LEVEL[level]
|
||||||
|
assert(order, "undefined level `%s'", _tostring(level))
|
||||||
|
if order < self.level_order then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
return LOG_MSG(self, level, ...)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- initialize log level.
|
||||||
|
logger:setLevel(logging.DEBUG)
|
||||||
|
return logger
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Prepares the log message
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
function logging.prepareLogMsg(pattern, dt, level, message)
|
||||||
|
local logMsg = pattern or "%date %level %message\n"
|
||||||
|
message = string.gsub(message, "%%", "%%%%")
|
||||||
|
logMsg = string.gsub(logMsg, "%%date", dt)
|
||||||
|
logMsg = string.gsub(logMsg, "%%level", level)
|
||||||
|
logMsg = string.gsub(logMsg, "%%message", message)
|
||||||
|
return logMsg
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Converts a Lua value to a string
|
||||||
|
--
|
||||||
|
-- Converts Table fields in alphabetical order
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
local function tostring(value)
|
||||||
|
local str = ''
|
||||||
|
|
||||||
|
if (type(value) ~= 'table') then
|
||||||
|
if (type(value) == 'string') then
|
||||||
|
str = string.format("%q", value)
|
||||||
|
else
|
||||||
|
str = _tostring(value)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local auxTable = {}
|
||||||
|
for key in pairs(value) do
|
||||||
|
if (tonumber(key) ~= key) then
|
||||||
|
table.insert(auxTable, key)
|
||||||
|
else
|
||||||
|
table.insert(auxTable, tostring(key))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.sort(auxTable)
|
||||||
|
|
||||||
|
str = str..'{'
|
||||||
|
local separator = ""
|
||||||
|
local entry = ""
|
||||||
|
for _, fieldName in ipairs(auxTable) do
|
||||||
|
if ((tonumber(fieldName)) and (tonumber(fieldName) > 0)) then
|
||||||
|
entry = tostring(value[tonumber(fieldName)])
|
||||||
|
else
|
||||||
|
entry = fieldName.." = "..tostring(value[fieldName])
|
||||||
|
end
|
||||||
|
str = str..separator..entry
|
||||||
|
separator = ", "
|
||||||
|
end
|
||||||
|
str = str..'}'
|
||||||
|
end
|
||||||
|
return str
|
||||||
|
end
|
||||||
|
logging.tostring = tostring
|
||||||
|
|
||||||
|
if _VERSION ~= 'Lua 5.2' then
|
||||||
|
-- still create 'logging' global for Lua versions < 5.2
|
||||||
|
_G.logging = logging
|
||||||
|
end
|
||||||
|
|
||||||
|
return logging
|
20
Mi_Lua/logging/console.lua
Normal file
20
Mi_Lua/logging/console.lua
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Prints logging information to console
|
||||||
|
--
|
||||||
|
-- @author Thiago Costa Ponte (thiago@ideais.com.br)
|
||||||
|
--
|
||||||
|
-- @copyright 2004-2013 Kepler Project
|
||||||
|
--
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local logging = require"logging"
|
||||||
|
|
||||||
|
function logging.console(logPattern)
|
||||||
|
return logging.new( function(self, level, message)
|
||||||
|
io.stdout:write(logging.prepareLogMsg(logPattern, os.date(), level, message))
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
return logging.console
|
||||||
|
|
43
Mi_Lua/logging/email.lua
Normal file
43
Mi_Lua/logging/email.lua
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Emails logging information to the given recipient
|
||||||
|
--
|
||||||
|
-- @author Thiago Costa Ponte (thiago@ideais.com.br)
|
||||||
|
--
|
||||||
|
-- @copyright 2004-2013 Kepler Project
|
||||||
|
--
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local logging = require"logging"
|
||||||
|
local smtp = require"socket.smtp"
|
||||||
|
|
||||||
|
function logging.email(params)
|
||||||
|
params = params or {}
|
||||||
|
params.headers = params.headers or {}
|
||||||
|
|
||||||
|
if params.from == nil then
|
||||||
|
return nil, "'from' parameter is required"
|
||||||
|
end
|
||||||
|
if params.rcpt == nil then
|
||||||
|
return nil, "'rcpt' parameter is required"
|
||||||
|
end
|
||||||
|
|
||||||
|
return logging.new( function(self, level, message)
|
||||||
|
local s = logging.prepareLogMsg(params.logPattern, os.date(), level, message)
|
||||||
|
if params.headers.subject then
|
||||||
|
params.headers.subject =
|
||||||
|
logging.prepareLogMsg(params.headers.subject, os.date(), level, message)
|
||||||
|
end
|
||||||
|
local msg = { headers = params.headers, body = s }
|
||||||
|
params.source = smtp.message(msg)
|
||||||
|
|
||||||
|
local r, e = smtp.send(params)
|
||||||
|
if not r then
|
||||||
|
return nil, e
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
return logging.email
|
||||||
|
|
49
Mi_Lua/logging/file.lua
Normal file
49
Mi_Lua/logging/file.lua
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Saves logging information in a file
|
||||||
|
--
|
||||||
|
-- @author Thiago Costa Ponte (thiago@ideais.com.br)
|
||||||
|
--
|
||||||
|
-- @copyright 2004-2013 Kepler Project
|
||||||
|
--
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local logging = require"logging"
|
||||||
|
|
||||||
|
local lastFileNameDatePattern
|
||||||
|
local lastFileHandler
|
||||||
|
|
||||||
|
local openFileLogger = function (filename, datePattern)
|
||||||
|
local filename = string.format(filename, os.date(datePattern))
|
||||||
|
if (lastFileNameDatePattern ~= filename) then
|
||||||
|
local f = io.open(filename, "a")
|
||||||
|
if (f) then
|
||||||
|
f:setvbuf ("line")
|
||||||
|
lastFileNameDatePattern = filename
|
||||||
|
lastFileHandler = f
|
||||||
|
return f
|
||||||
|
else
|
||||||
|
return nil, string.format("file `%s' could not be opened for writing", filename)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return lastFileHandler
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function logging.file(filename, datePattern, logPattern)
|
||||||
|
if type(filename) ~= "string" then
|
||||||
|
filename = "lualogging.log"
|
||||||
|
end
|
||||||
|
|
||||||
|
return logging.new( function(self, level, message)
|
||||||
|
local f, msg = openFileLogger(filename, datePattern)
|
||||||
|
if not f then
|
||||||
|
return nil, msg
|
||||||
|
end
|
||||||
|
local s = logging.prepareLogMsg(logPattern, os.date(), level, message)
|
||||||
|
f:write(s)
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
return logging.file
|
||||||
|
|
79
Mi_Lua/logging/rolling_file.lua
Normal file
79
Mi_Lua/logging/rolling_file.lua
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
---------------------------------------------------------------------------
|
||||||
|
-- RollingFileAppender is a FileAppender that rolls over the logfile
|
||||||
|
-- once it has reached a certain size limit. It also mantains a
|
||||||
|
-- maximum number of log files.
|
||||||
|
--
|
||||||
|
-- @author Tiago Cesar Katcipis (tiagokatcipis@gmail.com)
|
||||||
|
--
|
||||||
|
-- @copyright 2004-2013 Kepler Project
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local logging = require"logging"
|
||||||
|
|
||||||
|
local function openFile(self)
|
||||||
|
self.file = io.open(self.filename, "a")
|
||||||
|
if not self.file then
|
||||||
|
return nil, string.format("file `%s' could not be opened for writing", self.filename)
|
||||||
|
end
|
||||||
|
self.file:setvbuf ("line")
|
||||||
|
return self.file
|
||||||
|
end
|
||||||
|
|
||||||
|
local rollOver = function (self)
|
||||||
|
for i = self.maxIndex - 1, 1, -1 do
|
||||||
|
-- files may not exist yet, lets ignore the possible errors.
|
||||||
|
os.rename(self.filename.."."..i, self.filename.."."..i+1)
|
||||||
|
end
|
||||||
|
|
||||||
|
self.file:close()
|
||||||
|
self.file = nil
|
||||||
|
|
||||||
|
local _, msg = os.rename(self.filename, self.filename..".".."1")
|
||||||
|
|
||||||
|
if msg then
|
||||||
|
return nil, string.format("error %s on log rollover", msg)
|
||||||
|
end
|
||||||
|
|
||||||
|
return openFile(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local openRollingFileLogger = function (self)
|
||||||
|
if not self.file then
|
||||||
|
return openFile(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
local filesize = self.file:seek("end", 0)
|
||||||
|
|
||||||
|
if (filesize < self.maxSize) then
|
||||||
|
return self.file
|
||||||
|
end
|
||||||
|
|
||||||
|
return rollOver(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function logging.rolling_file(filename, maxFileSize, maxBackupIndex, logPattern)
|
||||||
|
if type(filename) ~= "string" then
|
||||||
|
filename = "lualogging.log"
|
||||||
|
end
|
||||||
|
|
||||||
|
local obj = {
|
||||||
|
filename = filename,
|
||||||
|
maxSize = maxFileSize,
|
||||||
|
maxIndex = maxBackupIndex or 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return logging.new( function(self, level, message)
|
||||||
|
local f, msg = openRollingFileLogger(obj)
|
||||||
|
if not f then
|
||||||
|
return nil, msg
|
||||||
|
end
|
||||||
|
local s = logging.prepareLogMsg(logPattern, os.date(), level, message)
|
||||||
|
f:write(s)
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
return logging.rolling_file
|
||||||
|
|
33
Mi_Lua/logging/socket.lua
Normal file
33
Mi_Lua/logging/socket.lua
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Sends the logging information through a socket using luasocket
|
||||||
|
--
|
||||||
|
-- @author Thiago Costa Ponte (thiago@ideais.com.br)
|
||||||
|
--
|
||||||
|
-- @copyright 2004-2013 Kepler Project
|
||||||
|
--
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local logging = require"logging"
|
||||||
|
local socket = require"socket"
|
||||||
|
|
||||||
|
function logging.socket(address, port, logPattern)
|
||||||
|
return logging.new( function(self, level, message)
|
||||||
|
local s = logging.prepareLogMsg(logPattern, os.date(), level, message)
|
||||||
|
|
||||||
|
local socket, err = socket.connect(address, port)
|
||||||
|
if not socket then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
|
||||||
|
local cond, err = socket:send(s)
|
||||||
|
if not cond then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
socket:close()
|
||||||
|
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
return logging.socket
|
||||||
|
|
62
Mi_Lua/logging/sql.lua
Normal file
62
Mi_Lua/logging/sql.lua
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Saves the logging information in a table using luasql
|
||||||
|
--
|
||||||
|
-- @author Thiago Costa Ponte (thiago@ideais.com.br)
|
||||||
|
--
|
||||||
|
-- @copyright 2004-2013 Kepler Project
|
||||||
|
--
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local logging = require"logging"
|
||||||
|
|
||||||
|
function logging.sql(params)
|
||||||
|
params = params or {}
|
||||||
|
params.tablename = params.tablename or "LogTable"
|
||||||
|
params.logdatefield = params.logdatefield or "LogDate"
|
||||||
|
params.loglevelfield = params.loglevelfield or "LogLevel"
|
||||||
|
params.logmessagefield = params.logmessagefield or "LogMessage"
|
||||||
|
|
||||||
|
if params.connectionfactory == nil or type(params.connectionfactory) ~= "function" then
|
||||||
|
return nil, "No specified connection factory function"
|
||||||
|
end
|
||||||
|
|
||||||
|
local con, err
|
||||||
|
if params.keepalive then
|
||||||
|
con, err = params.connectionfactory()
|
||||||
|
end
|
||||||
|
|
||||||
|
return logging.new( function(self, level, message)
|
||||||
|
if (not params.keepalive) or (con == nil) then
|
||||||
|
con, err = params.connectionfactory()
|
||||||
|
if not con then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local logDate = os.date("%Y-%m-%d %H:%M:%S")
|
||||||
|
local insert = string.format("INSERT INTO %s (%s, %s, %s) VALUES ('%s', '%s', '%s')",
|
||||||
|
params.tablename, params.logdatefield, params.loglevelfield,
|
||||||
|
params.logmessagefield, logDate, level, string.gsub(message, "'", "''"))
|
||||||
|
|
||||||
|
local ret, err = pcall(con.execute, con, insert)
|
||||||
|
if not ret then
|
||||||
|
con, err = params.connectionfactory()
|
||||||
|
if not con then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
ret, err = con:execute(insert)
|
||||||
|
if not ret then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not params.keepalive then
|
||||||
|
con:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
return logging.sql
|
||||||
|
|
BIN
Mi_Lua/lsqlite3.so
Normal file
BIN
Mi_Lua/lsqlite3.so
Normal file
Binary file not shown.
292
Mi_Lua/ltn12.lua
Normal file
292
Mi_Lua/ltn12.lua
Normal file
@ -0,0 +1,292 @@
|
|||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- LTN12 - Filters, sources, sinks and pumps.
|
||||||
|
-- LuaSocket toolkit.
|
||||||
|
-- Author: Diego Nehab
|
||||||
|
-- RCS ID: $Id: ltn12.lua,v 1.31 2006/04/03 04:45:42 diego Exp $
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Declare module
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
local string = require("string")
|
||||||
|
local table = require("table")
|
||||||
|
local base = _G
|
||||||
|
module("ltn12")
|
||||||
|
|
||||||
|
filter = {}
|
||||||
|
source = {}
|
||||||
|
sink = {}
|
||||||
|
pump = {}
|
||||||
|
|
||||||
|
-- 2048 seems to be better in windows...
|
||||||
|
BLOCKSIZE = 2048
|
||||||
|
_VERSION = "LTN12 1.0.1"
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Filter stuff
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- returns a high level filter that cycles a low-level filter
|
||||||
|
function filter.cycle(low, ctx, extra)
|
||||||
|
base.assert(low)
|
||||||
|
return function(chunk)
|
||||||
|
local ret
|
||||||
|
ret, ctx = low(ctx, chunk, extra)
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- chains a bunch of filters together
|
||||||
|
-- (thanks to Wim Couwenberg)
|
||||||
|
function filter.chain(...)
|
||||||
|
local n = table.getn(arg)
|
||||||
|
local top, index = 1, 1
|
||||||
|
local retry = ""
|
||||||
|
return function(chunk)
|
||||||
|
retry = chunk and retry
|
||||||
|
while true do
|
||||||
|
if index == top then
|
||||||
|
chunk = arg[index](chunk)
|
||||||
|
if chunk == "" or top == n then return chunk
|
||||||
|
elseif chunk then index = index + 1
|
||||||
|
else
|
||||||
|
top = top+1
|
||||||
|
index = top
|
||||||
|
end
|
||||||
|
else
|
||||||
|
chunk = arg[index](chunk or "")
|
||||||
|
if chunk == "" then
|
||||||
|
index = index - 1
|
||||||
|
chunk = retry
|
||||||
|
elseif chunk then
|
||||||
|
if index == n then return chunk
|
||||||
|
else index = index + 1 end
|
||||||
|
else base.error("filter returned inappropriate nil") end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Source stuff
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- create an empty source
|
||||||
|
local function empty()
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function source.empty()
|
||||||
|
return empty
|
||||||
|
end
|
||||||
|
|
||||||
|
-- returns a source that just outputs an error
|
||||||
|
function source.error(err)
|
||||||
|
return function()
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- creates a file source
|
||||||
|
function source.file(handle, io_err)
|
||||||
|
if handle then
|
||||||
|
return function()
|
||||||
|
local chunk = handle:read(BLOCKSIZE)
|
||||||
|
if not chunk then handle:close() end
|
||||||
|
return chunk
|
||||||
|
end
|
||||||
|
else return source.error(io_err or "unable to open file") end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- turns a fancy source into a simple source
|
||||||
|
function source.simplify(src)
|
||||||
|
base.assert(src)
|
||||||
|
return function()
|
||||||
|
local chunk, err_or_new = src()
|
||||||
|
src = err_or_new or src
|
||||||
|
if not chunk then return nil, err_or_new
|
||||||
|
else return chunk end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- creates string source
|
||||||
|
function source.string(s)
|
||||||
|
if s then
|
||||||
|
local i = 1
|
||||||
|
return function()
|
||||||
|
local chunk = string.sub(s, i, i+BLOCKSIZE-1)
|
||||||
|
i = i + BLOCKSIZE
|
||||||
|
if chunk ~= "" then return chunk
|
||||||
|
else return nil end
|
||||||
|
end
|
||||||
|
else return source.empty() end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- creates rewindable source
|
||||||
|
function source.rewind(src)
|
||||||
|
base.assert(src)
|
||||||
|
local t = {}
|
||||||
|
return function(chunk)
|
||||||
|
if not chunk then
|
||||||
|
chunk = table.remove(t)
|
||||||
|
if not chunk then return src()
|
||||||
|
else return chunk end
|
||||||
|
else
|
||||||
|
table.insert(t, chunk)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function source.chain(src, f)
|
||||||
|
base.assert(src and f)
|
||||||
|
local last_in, last_out = "", ""
|
||||||
|
local state = "feeding"
|
||||||
|
local err
|
||||||
|
return function()
|
||||||
|
if not last_out then
|
||||||
|
base.error('source is empty!', 2)
|
||||||
|
end
|
||||||
|
while true do
|
||||||
|
if state == "feeding" then
|
||||||
|
last_in, err = src()
|
||||||
|
if err then return nil, err end
|
||||||
|
last_out = f(last_in)
|
||||||
|
if not last_out then
|
||||||
|
if last_in then
|
||||||
|
base.error('filter returned inappropriate nil')
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
elseif last_out ~= "" then
|
||||||
|
state = "eating"
|
||||||
|
if last_in then last_in = "" end
|
||||||
|
return last_out
|
||||||
|
end
|
||||||
|
else
|
||||||
|
last_out = f(last_in)
|
||||||
|
if last_out == "" then
|
||||||
|
if last_in == "" then
|
||||||
|
state = "feeding"
|
||||||
|
else
|
||||||
|
base.error('filter returned ""')
|
||||||
|
end
|
||||||
|
elseif not last_out then
|
||||||
|
if last_in then
|
||||||
|
base.error('filter returned inappropriate nil')
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return last_out
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- creates a source that produces contents of several sources, one after the
|
||||||
|
-- other, as if they were concatenated
|
||||||
|
-- (thanks to Wim Couwenberg)
|
||||||
|
function source.cat(...)
|
||||||
|
local src = table.remove(arg, 1)
|
||||||
|
return function()
|
||||||
|
while src do
|
||||||
|
local chunk, err = src()
|
||||||
|
if chunk then return chunk end
|
||||||
|
if err then return nil, err end
|
||||||
|
src = table.remove(arg, 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Sink stuff
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- creates a sink that stores into a table
|
||||||
|
function sink.table(t)
|
||||||
|
t = t or {}
|
||||||
|
local f = function(chunk, err)
|
||||||
|
if chunk then table.insert(t, chunk) end
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
return f, t
|
||||||
|
end
|
||||||
|
|
||||||
|
-- turns a fancy sink into a simple sink
|
||||||
|
function sink.simplify(snk)
|
||||||
|
base.assert(snk)
|
||||||
|
return function(chunk, err)
|
||||||
|
local ret, err_or_new = snk(chunk, err)
|
||||||
|
if not ret then return nil, err_or_new end
|
||||||
|
snk = err_or_new or snk
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- creates a file sink
|
||||||
|
function sink.file(handle, io_err)
|
||||||
|
if handle then
|
||||||
|
return function(chunk, err)
|
||||||
|
if not chunk then
|
||||||
|
handle:close()
|
||||||
|
return 1
|
||||||
|
else return handle:write(chunk) end
|
||||||
|
end
|
||||||
|
else return sink.error(io_err or "unable to open file") end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- creates a sink that discards data
|
||||||
|
local function null()
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
function sink.null()
|
||||||
|
return null
|
||||||
|
end
|
||||||
|
|
||||||
|
-- creates a sink that just returns an error
|
||||||
|
function sink.error(err)
|
||||||
|
return function()
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- chains a sink with a filter
|
||||||
|
function sink.chain(f, snk)
|
||||||
|
base.assert(f and snk)
|
||||||
|
return function(chunk, err)
|
||||||
|
if chunk ~= "" then
|
||||||
|
local filtered = f(chunk)
|
||||||
|
local done = chunk and ""
|
||||||
|
while true do
|
||||||
|
local ret, snkerr = snk(filtered, err)
|
||||||
|
if not ret then return nil, snkerr end
|
||||||
|
if filtered == done then return 1 end
|
||||||
|
filtered = f(done)
|
||||||
|
end
|
||||||
|
else return 1 end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- Pump stuff
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- pumps one chunk from the source to the sink
|
||||||
|
function pump.step(src, snk)
|
||||||
|
local chunk, src_err = src()
|
||||||
|
local ret, snk_err = snk(chunk, src_err)
|
||||||
|
if chunk and ret then return 1
|
||||||
|
else return nil, src_err or snk_err end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- pumps all data from a source to a sink, using a step function
|
||||||
|
function pump.all(src, snk, step)
|
||||||
|
base.assert(src and snk)
|
||||||
|
step = step or pump.step
|
||||||
|
while true do
|
||||||
|
local ret, err = step(src, snk)
|
||||||
|
if not ret then
|
||||||
|
if err then return nil, err
|
||||||
|
else return 1 end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
23
Mi_Lua/luci/cacheloader.lua
Normal file
23
Mi_Lua/luci/cacheloader.lua
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
--[[
|
||||||
|
LuCI - Lua Configuration Interface
|
||||||
|
|
||||||
|
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||||
|
Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
|
||||||
|
|
||||||
|
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 config = require "luci.config"
|
||||||
|
local ccache = require "luci.ccache"
|
||||||
|
|
||||||
|
module "luci.cacheloader"
|
||||||
|
|
||||||
|
if config.ccache and config.ccache.enable == "1" then
|
||||||
|
ccache.cache_ondemand()
|
||||||
|
end
|
1850
Mi_Lua/luci/cbi.lua
Normal file
1850
Mi_Lua/luci/cbi.lua
Normal file
File diff suppressed because it is too large
Load Diff
345
Mi_Lua/luci/cbi/datatypes.lua
Normal file
345
Mi_Lua/luci/cbi/datatypes.lua
Normal file
@ -0,0 +1,345 @@
|
|||||||
|
--[[
|
||||||
|
|
||||||
|
LuCI - Configuration Bind Interface - Datatype Tests
|
||||||
|
(c) 2010 Jo-Philipp Wich <xm@subsignal.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: datatypes.lua 9352 2012-10-06 23:50:52Z jow $
|
||||||
|
|
||||||
|
]]--
|
||||||
|
|
||||||
|
local fs = require "nixio.fs"
|
||||||
|
local ip = require "luci.ip"
|
||||||
|
local math = require "math"
|
||||||
|
local util = require "luci.util"
|
||||||
|
local tonumber, tostring, type, unpack, select = tonumber, tostring, type, unpack, select
|
||||||
|
|
||||||
|
|
||||||
|
module "luci.cbi.datatypes"
|
||||||
|
|
||||||
|
|
||||||
|
_M['or'] = function(v, ...)
|
||||||
|
local i
|
||||||
|
for i = 1, select('#', ...), 2 do
|
||||||
|
local f = select(i, ...)
|
||||||
|
local a = select(i+1, ...)
|
||||||
|
if type(f) ~= "function" then
|
||||||
|
if f == v then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
i = i - 1
|
||||||
|
elseif f(v, unpack(a)) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
_M['and'] = function(v, ...)
|
||||||
|
local i
|
||||||
|
for i = 1, select('#', ...), 2 do
|
||||||
|
local f = select(i, ...)
|
||||||
|
local a = select(i+1, ...)
|
||||||
|
if type(f) ~= "function" then
|
||||||
|
if f ~= v then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
i = i - 1
|
||||||
|
elseif not f(v, unpack(a)) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function neg(v, ...)
|
||||||
|
return _M['or'](v:gsub("^%s*!%s*", ""), ...)
|
||||||
|
end
|
||||||
|
|
||||||
|
function list(v, subvalidator, subargs)
|
||||||
|
if type(subvalidator) ~= "function" then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local token
|
||||||
|
for token in v:gmatch("%S+") do
|
||||||
|
if not subvalidator(token, unpack(subargs)) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function bool(val)
|
||||||
|
if val == "1" or val == "yes" or val == "on" or val == "true" then
|
||||||
|
return true
|
||||||
|
elseif val == "0" or val == "no" or val == "off" or val == "false" then
|
||||||
|
return true
|
||||||
|
elseif val == "" or val == nil then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function uinteger(val)
|
||||||
|
local n = tonumber(val)
|
||||||
|
if n ~= nil and math.floor(n) == n and n >= 0 then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function integer(val)
|
||||||
|
local n = tonumber(val)
|
||||||
|
if n ~= nil and math.floor(n) == n then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function ufloat(val)
|
||||||
|
local n = tonumber(val)
|
||||||
|
return ( n ~= nil and n >= 0 )
|
||||||
|
end
|
||||||
|
|
||||||
|
function float(val)
|
||||||
|
return ( tonumber(val) ~= nil )
|
||||||
|
end
|
||||||
|
|
||||||
|
function ipaddr(val)
|
||||||
|
return ip4addr(val) or ip6addr(val)
|
||||||
|
end
|
||||||
|
|
||||||
|
function ip4addr(val)
|
||||||
|
if val then
|
||||||
|
return ip.IPv4(val) and true or false
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function ip4prefix(val)
|
||||||
|
val = tonumber(val)
|
||||||
|
return ( val and val >= 0 and val <= 32 )
|
||||||
|
end
|
||||||
|
|
||||||
|
function ip6addr(val)
|
||||||
|
if val then
|
||||||
|
return ip.IPv6(val) and true or false
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function ip6prefix(val)
|
||||||
|
val = tonumber(val)
|
||||||
|
return ( val and val >= 0 and val <= 128 )
|
||||||
|
end
|
||||||
|
|
||||||
|
function port(val)
|
||||||
|
val = tonumber(val)
|
||||||
|
return ( val and val >= 0 and val <= 65535 )
|
||||||
|
end
|
||||||
|
|
||||||
|
function portrange(val)
|
||||||
|
local p1, p2 = val:match("^(%d+)%-(%d+)$")
|
||||||
|
if p1 and p2 and port(p1) and port(p2) then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return port(val)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function macaddr(val)
|
||||||
|
if val and val:match(
|
||||||
|
"^[a-fA-F0-9]+:[a-fA-F0-9]+:[a-fA-F0-9]+:" ..
|
||||||
|
"[a-fA-F0-9]+:[a-fA-F0-9]+:[a-fA-F0-9]+$"
|
||||||
|
) then
|
||||||
|
local parts = util.split( val, ":" )
|
||||||
|
|
||||||
|
for i = 1,6 do
|
||||||
|
parts[i] = tonumber( parts[i], 16 )
|
||||||
|
if parts[i] < 0 or parts[i] > 255 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function hostname(val)
|
||||||
|
if val and (#val < 254) and (
|
||||||
|
val:match("^[a-zA-Z_]+$") or
|
||||||
|
(val:match("^[a-zA-Z0-9_][a-zA-Z0-9_%-%.]*[a-zA-Z0-9]$") and
|
||||||
|
val:match("[^0-9%.]"))
|
||||||
|
) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function host(val)
|
||||||
|
return hostname(val) or ipaddr(val)
|
||||||
|
end
|
||||||
|
|
||||||
|
function network(val)
|
||||||
|
return uciname(val) or host(val)
|
||||||
|
end
|
||||||
|
|
||||||
|
function wpakey(val)
|
||||||
|
if #val == 64 then
|
||||||
|
return (val:match("^[a-fA-F0-9]+$") ~= nil)
|
||||||
|
else
|
||||||
|
return (#val >= 8) and (#val <= 63)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function wepkey(val)
|
||||||
|
if val:sub(1, 2) == "s:" then
|
||||||
|
val = val:sub(3)
|
||||||
|
end
|
||||||
|
|
||||||
|
if (#val == 10) or (#val == 26) then
|
||||||
|
return (val:match("^[a-fA-F0-9]+$") ~= nil)
|
||||||
|
else
|
||||||
|
return (#val == 5) or (#val == 13)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function string(val)
|
||||||
|
return true -- Everything qualifies as valid string
|
||||||
|
end
|
||||||
|
|
||||||
|
function directory( val, seen )
|
||||||
|
local s = fs.stat(val)
|
||||||
|
seen = seen or { }
|
||||||
|
|
||||||
|
if s and not seen[s.ino] then
|
||||||
|
seen[s.ino] = true
|
||||||
|
if s.type == "dir" then
|
||||||
|
return true
|
||||||
|
elseif s.type == "lnk" then
|
||||||
|
return directory( fs.readlink(val), seen )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function file( val, seen )
|
||||||
|
local s = fs.stat(val)
|
||||||
|
seen = seen or { }
|
||||||
|
|
||||||
|
if s and not seen[s.ino] then
|
||||||
|
seen[s.ino] = true
|
||||||
|
if s.type == "reg" then
|
||||||
|
return true
|
||||||
|
elseif s.type == "lnk" then
|
||||||
|
return file( fs.readlink(val), seen )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function device( val, seen )
|
||||||
|
local s = fs.stat(val)
|
||||||
|
seen = seen or { }
|
||||||
|
|
||||||
|
if s and not seen[s.ino] then
|
||||||
|
seen[s.ino] = true
|
||||||
|
if s.type == "chr" or s.type == "blk" then
|
||||||
|
return true
|
||||||
|
elseif s.type == "lnk" then
|
||||||
|
return device( fs.readlink(val), seen )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function uciname(val)
|
||||||
|
return (val:match("^[a-zA-Z0-9_]+$") ~= nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
function range(val, min, max)
|
||||||
|
val = tonumber(val)
|
||||||
|
min = tonumber(min)
|
||||||
|
max = tonumber(max)
|
||||||
|
|
||||||
|
if val ~= nil and min ~= nil and max ~= nil then
|
||||||
|
return ((val >= min) and (val <= max))
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function min(val, min)
|
||||||
|
val = tonumber(val)
|
||||||
|
min = tonumber(min)
|
||||||
|
|
||||||
|
if val ~= nil and min ~= nil then
|
||||||
|
return (val >= min)
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function max(val, max)
|
||||||
|
val = tonumber(val)
|
||||||
|
max = tonumber(max)
|
||||||
|
|
||||||
|
if val ~= nil and max ~= nil then
|
||||||
|
return (val <= max)
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function rangelength(val, min, max)
|
||||||
|
val = tostring(val)
|
||||||
|
min = tonumber(min)
|
||||||
|
max = tonumber(max)
|
||||||
|
|
||||||
|
if val ~= nil and min ~= nil and max ~= nil then
|
||||||
|
return ((#val >= min) and (#val <= max))
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function minlength(val, min)
|
||||||
|
val = tostring(val)
|
||||||
|
min = tonumber(min)
|
||||||
|
|
||||||
|
if val ~= nil and min ~= nil then
|
||||||
|
return (#val >= min)
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function maxlength(val, max)
|
||||||
|
val = tostring(val)
|
||||||
|
max = tonumber(max)
|
||||||
|
|
||||||
|
if val ~= nil and max ~= nil then
|
||||||
|
return (#val <= max)
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function phonedigit(val)
|
||||||
|
return (val:match("^[0-9\*#]+$") ~= nil)
|
||||||
|
end
|
87
Mi_Lua/luci/ccache.lua
Normal file
87
Mi_Lua/luci/ccache.lua
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
--[[
|
||||||
|
LuCI - Lua Configuration Interface
|
||||||
|
|
||||||
|
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||||
|
Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
|
||||||
|
|
||||||
|
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 io = require "io"
|
||||||
|
local fs = require "nixio.fs"
|
||||||
|
local util = require "luci.util"
|
||||||
|
local nixio = require "nixio"
|
||||||
|
local debug = require "debug"
|
||||||
|
local string = require "string"
|
||||||
|
local package = require "package"
|
||||||
|
|
||||||
|
local type, loadfile = type, loadfile
|
||||||
|
|
||||||
|
|
||||||
|
module "luci.ccache"
|
||||||
|
|
||||||
|
function cache_ondemand(...)
|
||||||
|
if debug.getinfo(1, 'S').source ~= "=?" then
|
||||||
|
cache_enable(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function cache_enable(cachepath, mode)
|
||||||
|
cachepath = cachepath or "/tmp/luci-modulecache"
|
||||||
|
mode = mode or "r--r--r--"
|
||||||
|
|
||||||
|
local loader = package.loaders[2]
|
||||||
|
local uid = nixio.getuid()
|
||||||
|
|
||||||
|
if not fs.stat(cachepath) then
|
||||||
|
fs.mkdir(cachepath)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function _encode_filename(name)
|
||||||
|
local encoded = ""
|
||||||
|
for i=1, #name do
|
||||||
|
encoded = encoded .. ("%2X" % string.byte(name, i))
|
||||||
|
end
|
||||||
|
return encoded
|
||||||
|
end
|
||||||
|
|
||||||
|
local function _load_sane(file)
|
||||||
|
local stat = fs.stat(file)
|
||||||
|
if stat and stat.uid == uid and stat.modestr == mode then
|
||||||
|
return loadfile(file)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function _write_sane(file, func)
|
||||||
|
if nixio.getuid() == uid then
|
||||||
|
local fp = io.open(file, "w")
|
||||||
|
if fp then
|
||||||
|
fp:write(util.get_bytecode(func))
|
||||||
|
fp:close()
|
||||||
|
fs.chmod(file, mode)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
package.loaders[2] = function(mod)
|
||||||
|
local encoded = cachepath .. "/" .. _encode_filename(mod)
|
||||||
|
local modcons = _load_sane(encoded)
|
||||||
|
|
||||||
|
if modcons then
|
||||||
|
return modcons
|
||||||
|
end
|
||||||
|
|
||||||
|
-- No cachefile
|
||||||
|
modcons = loader(mod)
|
||||||
|
if type(modcons) == "function" then
|
||||||
|
_write_sane(encoded, modcons)
|
||||||
|
end
|
||||||
|
return modcons
|
||||||
|
end
|
||||||
|
end
|
42
Mi_Lua/luci/config.lua
Normal file
42
Mi_Lua/luci/config.lua
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
--[[
|
||||||
|
LuCI - Configuration
|
||||||
|
|
||||||
|
Description:
|
||||||
|
Some LuCI configuration values read from uci file "luci"
|
||||||
|
|
||||||
|
|
||||||
|
FileId:
|
||||||
|
$Id: config.lua 3856 2008-12-05 15:36:44Z Cyrus $
|
||||||
|
|
||||||
|
License:
|
||||||
|
Copyright 2008 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
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
]]--
|
||||||
|
|
||||||
|
local util = require "luci.util"
|
||||||
|
module("luci.config",
|
||||||
|
function(m)
|
||||||
|
if pcall(require, "luci.model.uci") then
|
||||||
|
local config = util.threadlocal()
|
||||||
|
setmetatable(m, {
|
||||||
|
__index = function(tbl, key)
|
||||||
|
if not config[key] then
|
||||||
|
config[key] = luci.model.uci.cursor():get_all("luci", key)
|
||||||
|
end
|
||||||
|
return config[key]
|
||||||
|
end
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end)
|
10
Mi_Lua/luci/controller/api/index.lua
Normal file
10
Mi_Lua/luci/controller/api/index.lua
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
module("luci.controller.api.index", package.seeall)
|
||||||
|
function index()
|
||||||
|
local page = node("api")
|
||||||
|
page.target = firstchild()
|
||||||
|
page.title = _("")
|
||||||
|
page.order = 10
|
||||||
|
page.sysauth = "admin"
|
||||||
|
page.sysauth_authenticator = "jsonauth"
|
||||||
|
page.index = true
|
||||||
|
end
|
336
Mi_Lua/luci/controller/api/xqdatacenter.lua
Normal file
336
Mi_Lua/luci/controller/api/xqdatacenter.lua
Normal file
@ -0,0 +1,336 @@
|
|||||||
|
module("luci.controller.api.xqdatacenter", package.seeall)
|
||||||
|
|
||||||
|
function index()
|
||||||
|
local page = node("api","xqdatacenter")
|
||||||
|
page.target = firstchild()
|
||||||
|
page.title = ("")
|
||||||
|
page.order = 300
|
||||||
|
page.sysauth = "admin"
|
||||||
|
page.sysauth_authenticator = "jsonauth"
|
||||||
|
page.index = true
|
||||||
|
entry({"api", "xqdatacenter"}, firstchild(), _(""), 300)
|
||||||
|
entry({"api", "xqdatacenter", "request"}, call("tunnelRequest"), _(""), 301)
|
||||||
|
entry({"api", "xqdatacenter", "identify_device"}, call("identifyDevice"), _(""), 302, 0x08)
|
||||||
|
entry({"api", "xqdatacenter", "download"}, call("download"), _(""), 303)
|
||||||
|
entry({"api", "xqdatacenter", "upload"}, call("upload"), _(""), 304)
|
||||||
|
entry({"api", "xqdatacenter", "thumb"}, call("getThumb"), _(""), 305)
|
||||||
|
entry({"api", "xqdatacenter", "device_id"}, call("getDeviceId"), _(""), 306)
|
||||||
|
entry({"api", "xqdatacenter", "check_file_exist"}, call("checkFileExist"), _(""), 307)
|
||||||
|
entry({"api", "xqdatacenter", "plugin_ssh"}, call("pluginSSH"), _(""), 308)
|
||||||
|
entry({"api", "xqdatacenter", "plugin_ssh_status"}, call("pluginSSHStatus"), _(""), 309)
|
||||||
|
end
|
||||||
|
|
||||||
|
local LuciHttp = require("luci.http")
|
||||||
|
local LuciJson = require("json")
|
||||||
|
local XQConfigs = require("xiaoqiang.common.XQConfigs")
|
||||||
|
local XQFunction = require("xiaoqiang.common.XQFunction")
|
||||||
|
local XQErrorUtil = require("xiaoqiang.util.XQErrorUtil")
|
||||||
|
|
||||||
|
function tunnelRequest()
|
||||||
|
local XQCryptoUtil = require("xiaoqiang.util.XQCryptoUtil")
|
||||||
|
local payload = XQCryptoUtil.binaryBase64Enc(LuciHttp.formvalue("payload"))
|
||||||
|
local cmd = XQConfigs.THRIFT_TUNNEL_TO_DATACENTER % payload
|
||||||
|
local LuciUtil = require("luci.util")
|
||||||
|
LuciHttp.write(LuciUtil.exec(cmd))
|
||||||
|
end
|
||||||
|
|
||||||
|
function identifyDevice()
|
||||||
|
local cmd = XQConfigs.THRIFT_TO_MQTT_IDENTIFY_DEVICE
|
||||||
|
local LuciUtil = require("luci.util")
|
||||||
|
local result = {}
|
||||||
|
result["code"] = 0
|
||||||
|
result["info"] = LuciUtil.exec(cmd)
|
||||||
|
LuciHttp.write_json(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
function getDeviceId()
|
||||||
|
local cmd = XQConfigs.THRIFT_TO_MQTT_GET_DEVICEID
|
||||||
|
local LuciUtil = require("luci.util")
|
||||||
|
local result = {}
|
||||||
|
result["code"] = 0
|
||||||
|
result["deviceId"] = LuciUtil.exec(cmd)
|
||||||
|
LuciHttp.write_json(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
function download()
|
||||||
|
local fs = require("nixio.fs")
|
||||||
|
local mime = require("luci.http.protocol.mime")
|
||||||
|
local ltn12 = require("luci.ltn12")
|
||||||
|
local log = require("xiaoqiang.XQLog")
|
||||||
|
|
||||||
|
local path = LuciHttp.formvalue("path")
|
||||||
|
if XQFunction.isStrNil(path) then
|
||||||
|
LuciHttp.status(404, _("no Such file"))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local constPrefix1 = "/userdisk/data/"
|
||||||
|
local constPrefix2 = "/extdisks/"
|
||||||
|
local constPrefix3 = "/userdisk/privacyData/"
|
||||||
|
if (string.sub(path, 1, string.len(constPrefix1)) ~= constPrefix1) and (string.sub(path, 1, string.len(constPrefix2)) ~= constPrefix2) and (string.sub(path, 1, string.len(constPrefix3)) ~= constPrefix3) then
|
||||||
|
LuciHttp.status(403, _("no permission"))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- check privacy disk permission by md5 device mac address
|
||||||
|
--[[if string.sub(path, 1, string.len(constPrefix3)) == constPrefix3 then
|
||||||
|
local secret = LuciHttp.formvalue("secret")
|
||||||
|
if XQFunction.isStrNil(secret) then
|
||||||
|
LuciHttp.status(403, _("no permission"))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
log.log(3, "=============secret = " .. secret)
|
||||||
|
|
||||||
|
local access = false
|
||||||
|
local XQCryptoUtil = require("xiaoqiang.util.XQCryptoUtil")
|
||||||
|
local XQDeviceUtil = require("xiaoqiang.util.XQDeviceUtil")
|
||||||
|
local macfilterInfoList = XQDeviceUtil.getMacfilterInfoList()
|
||||||
|
for _,value in ipairs(macfilterInfoList) do
|
||||||
|
if XQFunction.isStrNil(value.mac) == false then
|
||||||
|
log.log(3, "=============mac = " .. value.mac)
|
||||||
|
if string.lower(XQCryptoUtil.md5Str(string.lower(value.mac))) == string.lower(secret) then
|
||||||
|
log.log(3, "=============device found")
|
||||||
|
if value.pridisk then
|
||||||
|
access = true
|
||||||
|
end
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if access == false then
|
||||||
|
LuciHttp.status(403, _("no permission"))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end]]
|
||||||
|
|
||||||
|
log.log(3, "=============path = " .. path)
|
||||||
|
local stat = fs.stat(path)
|
||||||
|
if not stat then
|
||||||
|
LuciHttp.status(404, _("no Such file"))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
LuciHttp.header("Accept-Ranges", "bytes")
|
||||||
|
LuciHttp.header("Content-Type", mime.to_mime(path))
|
||||||
|
local range = LuciHttp.getenv("HTTP_RANGE")
|
||||||
|
-- format: bytes=123-
|
||||||
|
if range then
|
||||||
|
LuciHttp.status(206)
|
||||||
|
range = string.gsub(range, "bytes=", "")
|
||||||
|
range = string.gsub(range, "-", "")
|
||||||
|
else
|
||||||
|
range = 0
|
||||||
|
end
|
||||||
|
log.log(3, "=============range = " .. range)
|
||||||
|
-- format: bytes 123-456/457
|
||||||
|
local contentRange = "bytes " .. range .. "-" .. (stat.size - 1) .. "/" .. stat.size
|
||||||
|
log.log(3, "=============contentRange = " .. contentRange)
|
||||||
|
LuciHttp.header("Content-Length", stat.size - range)
|
||||||
|
LuciHttp.header("Content-Range", contentRange)
|
||||||
|
LuciHttp.header("Content-Disposition", "attachment; filename=" .. fs.basename(path))
|
||||||
|
|
||||||
|
if string.sub(path, 1, string.len(constPrefix1)) == constPrefix1 then
|
||||||
|
LuciHttp.header("X-Accel-Redirect", "/download-userdisk/" .. string.sub(path, string.len(constPrefix1) + 1, string.len(path)))
|
||||||
|
elseif string.sub(path, 1, string.len(constPrefix2)) == constPrefix2 then
|
||||||
|
LuciHttp.header("X-Accel-Redirect", "/download-extdisks/" .. string.sub(path, string.len(constPrefix2) + 1, string.len(path)))
|
||||||
|
elseif string.sub(path, 1, string.len(constPrefix3)) == constPrefix3 then
|
||||||
|
LuciHttp.header("X-Accel-Redirect", "/download-pridisk/" .. string.sub(path, string.len(constPrefix3) + 1, string.len(path)))
|
||||||
|
end
|
||||||
|
|
||||||
|
--local file = io.open(path, "r")
|
||||||
|
--local position = file:seek("set", range)
|
||||||
|
--log.log(3, "=============position = " .. position)
|
||||||
|
--ltn12.pump.all(ltn12.source.file(file), LuciHttp.write)
|
||||||
|
end
|
||||||
|
|
||||||
|
function upload()
|
||||||
|
local fp
|
||||||
|
local log = require("xiaoqiang.XQLog")
|
||||||
|
local fs = require("luci.fs")
|
||||||
|
local tmpfile = "/userdisk/upload.tmp"
|
||||||
|
if fs.isfile(tmpfile) then
|
||||||
|
fs.unlink(tmpfile)
|
||||||
|
end
|
||||||
|
local filename
|
||||||
|
LuciHttp.setfilehandler(
|
||||||
|
function(meta, chunk, eof)
|
||||||
|
if not fp then
|
||||||
|
if meta and meta.name == "file" then
|
||||||
|
fp = io.open(tmpfile, "w")
|
||||||
|
filename = meta.file
|
||||||
|
filename = string.gsub(filename, "+", " ")
|
||||||
|
filename = string.gsub(filename, "%%(%x%x)",
|
||||||
|
function(h)
|
||||||
|
return string.char(tonumber(h, 16))
|
||||||
|
end)
|
||||||
|
filename = filename.gsub(filename, "\r\n", "\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if chunk then
|
||||||
|
fp:write(chunk)
|
||||||
|
end
|
||||||
|
if eof then
|
||||||
|
fp:close()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|
||||||
|
local path = LuciHttp.formvalue("target")
|
||||||
|
if string.match(path, "\/$") == nil then
|
||||||
|
path = path .. "/"
|
||||||
|
end
|
||||||
|
fs.mkdir(path, true)
|
||||||
|
|
||||||
|
local savename = filename
|
||||||
|
if fs.isfile(path .. savename) then
|
||||||
|
local basename = savename
|
||||||
|
local index = basename:match(".+()%.%w+$")
|
||||||
|
if index then
|
||||||
|
basename = basename:sub(1, index - 1)
|
||||||
|
end
|
||||||
|
local extension = savename:match(".+%.(%w+)$")
|
||||||
|
for i = 1, 100, 1 do
|
||||||
|
local tmpname = basename .. "(" .. i .. ")"
|
||||||
|
if extension then
|
||||||
|
tmpname = tmpname .. "." .. extension
|
||||||
|
end
|
||||||
|
if not fs.isfile(path .. tmpname) then
|
||||||
|
savename = tmpname
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local dest = path .. savename
|
||||||
|
log.log(3, "dest=" .. dest)
|
||||||
|
fs.rename(tmpfile, dest)
|
||||||
|
|
||||||
|
local result = {}
|
||||||
|
result["code"] = 0
|
||||||
|
LuciHttp.write_json(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
function getThumb()
|
||||||
|
local LuciUtil = require("luci.util")
|
||||||
|
local fs = require("nixio.fs")
|
||||||
|
local mime = require("luci.http.protocol.mime")
|
||||||
|
local ltn12 = require("luci.ltn12")
|
||||||
|
local log = require("xiaoqiang.XQLog")
|
||||||
|
|
||||||
|
local realPath = LuciHttp.formvalue("filePath")
|
||||||
|
log.log(3, "realPath = ", realPath)
|
||||||
|
if (realPath == nil) then
|
||||||
|
LuciHttp.status(404, _("no Such file"))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local XQCryptoUtil = require("xiaoqiang.util.XQCryptoUtil")
|
||||||
|
local payload = "{\"api\":10, \"files\":[\"" ..realPath.. "\"]}"
|
||||||
|
local thumbResponse = XQFunction.thrift_tunnel_to_datacenter(payload)
|
||||||
|
if thumbResponse and thumbResponse.code == 0 then
|
||||||
|
local thumbPath = thumbResponse.thumbnails[1]
|
||||||
|
local stat = fs.stat(thumbPath)
|
||||||
|
LuciHttp.header("Content-Type", mime.to_mime(thumbPath))
|
||||||
|
LuciHttp.header("Content-Length", stat.size)
|
||||||
|
ltn12.pump.all(ltn12.source.file(io.open(thumbPath, "r")), LuciHttp.write)
|
||||||
|
else
|
||||||
|
LuciHttp.status(404, _("no Such thumb file"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function checkFileExist()
|
||||||
|
local fs = require("nixio.fs")
|
||||||
|
|
||||||
|
local exist = true
|
||||||
|
local path = LuciHttp.formvalue("filePath")
|
||||||
|
if XQFunction.isStrNil(path) then
|
||||||
|
exist = false
|
||||||
|
else
|
||||||
|
local stat = fs.stat(path)
|
||||||
|
if not stat then
|
||||||
|
exist = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local result = {}
|
||||||
|
result["code"] = 0
|
||||||
|
result['exist'] = exist
|
||||||
|
LuciHttp.write_json(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
function pluginSSH()
|
||||||
|
local LuciUtil = require("luci.util")
|
||||||
|
local XQLog = require("xiaoqiang.XQLog")
|
||||||
|
local code = 0
|
||||||
|
local result = {}
|
||||||
|
local pluginID = LuciHttp.formvalue("pluginID")
|
||||||
|
local capabilitystr = LuciHttp.formvalue("capability")
|
||||||
|
local open = tonumber(LuciHttp.formvalue("open") or 0)
|
||||||
|
XQLog.check(0, XQLog.KEY_FUNC_PLUGIN, 1)
|
||||||
|
if open and open == 1 then
|
||||||
|
if pluginID and capabilitystr then
|
||||||
|
local payload = {
|
||||||
|
["api"] = 611,
|
||||||
|
["pluginID"] = pluginID,
|
||||||
|
["capability"] = LuciUtil.split(capabilitystr, ",")
|
||||||
|
}
|
||||||
|
local datacenter = XQFunction.thrift_tunnel_to_datacenter(LuciJson.encode(payload))
|
||||||
|
if datacenter and datacenter.code ~= 0 then
|
||||||
|
code = 1595
|
||||||
|
end
|
||||||
|
else
|
||||||
|
code = 1537
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local payload = {
|
||||||
|
["api"] = 613
|
||||||
|
}
|
||||||
|
local datacenter = XQFunction.thrift_tunnel_to_datacenter(LuciJson.encode(payload))
|
||||||
|
if datacenter and datacenter.code == 0 then
|
||||||
|
code = 0
|
||||||
|
else
|
||||||
|
code = 1601
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if code ~= 0 then
|
||||||
|
result["msg"] = XQErrorUtil.getErrorMessage(code)
|
||||||
|
end
|
||||||
|
result["code"] = code
|
||||||
|
LuciHttp.write_json(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
function pluginSSHStatus()
|
||||||
|
local code = 0
|
||||||
|
local result = {}
|
||||||
|
local datacenter = XQFunction.thrift_tunnel_to_datacenter([[{"api":612}]])
|
||||||
|
local capability = XQFunction.thrift_tunnel_to_datacenter([[{"api":621}]])
|
||||||
|
if datacenter and datacenter.code == 0 and capability and datacenter.code == 0 then
|
||||||
|
local capabilitylist = {}
|
||||||
|
result["enable"] = datacenter.status == 1 and 1 or 0
|
||||||
|
local encapability = {}
|
||||||
|
if result.enable == 1 then
|
||||||
|
local pluginSSH = datacenter.plugin_ssh_status
|
||||||
|
result["pluginID"] = pluginSSH.pluginID
|
||||||
|
encapability = pluginSSH.capability
|
||||||
|
end
|
||||||
|
for _, item in ipairs(capability.list) do
|
||||||
|
item.enable = 0
|
||||||
|
for _, capa in ipairs(encapability) do
|
||||||
|
if item.key == capa then
|
||||||
|
item.enable = 1
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.insert(capabilitylist, item)
|
||||||
|
end
|
||||||
|
result["capability"] = capabilitylist
|
||||||
|
else
|
||||||
|
code = 1600
|
||||||
|
end
|
||||||
|
if code ~= 0 then
|
||||||
|
result["msg"] = XQErrorUtil.getErrorMessage(code)
|
||||||
|
end
|
||||||
|
result["code"] = code
|
||||||
|
LuciHttp.write_json(result)
|
||||||
|
end
|
293
Mi_Lua/luci/controller/api/xqnetdetect.lua
Normal file
293
Mi_Lua/luci/controller/api/xqnetdetect.lua
Normal file
@ -0,0 +1,293 @@
|
|||||||
|
module("luci.controller.api.xqnetdetect", package.seeall)
|
||||||
|
|
||||||
|
function index()
|
||||||
|
local page = node("api","xqnetdetect")
|
||||||
|
page.target = firstchild()
|
||||||
|
page.title = ("")
|
||||||
|
page.order = 350
|
||||||
|
page.sysauth = "admin"
|
||||||
|
page.sysauth_authenticator = "jsonauth"
|
||||||
|
page.index = true
|
||||||
|
entry({"api", "xqnetdetect"}, firstchild(), _(""), 350)
|
||||||
|
entry({"api", "xqnetdetect", "wan_status"}, call("getWanStatus"), _(""), 351, 0x01)
|
||||||
|
entry({"api", "xqnetdetect", "sys_info"}, call("getSysInfo"), (""), 352, 0x01)
|
||||||
|
entry({"api", "xqnetdetect", "ping_test"}, call("pingTest"), (""), 353, 0x01)
|
||||||
|
entry({"api", "xqnetdetect", "detect"}, call("systemDiagnostics"), (""), 354, 0x01)
|
||||||
|
entry({"api", "xqnetdetect", "sys_status"}, call("systemStatus"), (""), 355, 0x01)
|
||||||
|
entry({"api", "xqnetdetect", "netspeed"}, call("netspeed"), (""), 356)
|
||||||
|
entry({"api", "xqnetdetect", "uploadspeed"}, call("uploadSpeed"), (""), 357)
|
||||||
|
end
|
||||||
|
|
||||||
|
local LuciHttp = require("luci.http")
|
||||||
|
local XQFunction = require("xiaoqiang.common.XQFunction")
|
||||||
|
local XQErrorUtil = require("xiaoqiang.util.XQErrorUtil")
|
||||||
|
|
||||||
|
function getWanStatus()
|
||||||
|
local XQLanWanUtil = require("xiaoqiang.util.XQLanWanUtil")
|
||||||
|
local result = {}
|
||||||
|
local wanType = XQLanWanUtil.getAutoWanType()
|
||||||
|
local wanInfo = XQLanWanUtil.getLanWanInfo("wan")
|
||||||
|
local wanMonitor = XQLanWanUtil.getWanMonitorStat()
|
||||||
|
result["code"] = 0
|
||||||
|
result["wanLink"] = wanType == 99 and 0 or 1
|
||||||
|
result["wanType"] = wanType
|
||||||
|
result["wanInfo"] = wanInfo
|
||||||
|
result["wanMonitor"] = wanMonitor
|
||||||
|
LuciHttp.write_json(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
function getSysInfo()
|
||||||
|
local LuciSys = require("luci.sys")
|
||||||
|
local result = {}
|
||||||
|
local cpu = {}
|
||||||
|
local mem = {}
|
||||||
|
local system, model, memtotal, memcached, membuffers, memfree, bogomips = LuciSys.sysinfo()
|
||||||
|
cpu["info"] = system
|
||||||
|
mem["total"] = memtotal
|
||||||
|
mem["free"] = memfree
|
||||||
|
result["code"] = 0
|
||||||
|
result["cpuInfo"] = cpu
|
||||||
|
result["memInfo"] = mem
|
||||||
|
LuciHttp.write_json(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
function pingTest()
|
||||||
|
local LuciSys = require("luci.sys")
|
||||||
|
local pingUrl = LuciHttp.formvalue("url")
|
||||||
|
local ping = LuciSys.net.pingtest(pingUrl)
|
||||||
|
local result = {}
|
||||||
|
result["code"] = 0
|
||||||
|
result["result"] = ping == 0 and 1 or 0
|
||||||
|
LuciHttp.write_json(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[
|
||||||
|
simple : 0/1/2 (正常模式,时间长上传log/简单模式,时间短,不上传log/简单模式,时间短,上传log)
|
||||||
|
]]--
|
||||||
|
function systemDiagnostics()
|
||||||
|
local XQLog = require("xiaoqiang.XQLog")
|
||||||
|
local XQSysUtil = require("xiaoqiang.util.XQSysUtil")
|
||||||
|
local XQSecureUtil = require("xiaoqiang.util.XQSecureUtil")
|
||||||
|
local XQWifiUtil = require("xiaoqiang.util.XQWifiUtil")
|
||||||
|
local XQDeviceUtil = require("xiaoqiang.util.XQDeviceUtil")
|
||||||
|
|
||||||
|
local lan = XQDeviceUtil.getWanLanNetworkStatistics("lan")
|
||||||
|
local wan = XQDeviceUtil.getWanLanNetworkStatistics("wan")
|
||||||
|
local speed = {}
|
||||||
|
speed["lan"] = tonumber(lan.downspeed)
|
||||||
|
speed["wan"] = tonumber(wan.downspeed)
|
||||||
|
|
||||||
|
local simple = tonumber(LuciHttp.formvalue("simple") or 0)
|
||||||
|
local target = LuciHttp.formvalue("target")
|
||||||
|
local result = {}
|
||||||
|
local code = 0
|
||||||
|
local status = 0
|
||||||
|
local count = 0
|
||||||
|
local cpuTemperature = XQSysUtil.getCpuTemperature()
|
||||||
|
local network = XQSysUtil.getNetworkDetectInfo(simple,target)
|
||||||
|
XQSysUtil.setDetectionTimestamp()
|
||||||
|
|
||||||
|
local wifiInfo = XQWifiUtil.getAllWifiInfo()
|
||||||
|
local same = false
|
||||||
|
local strong = true
|
||||||
|
local wifi = {}
|
||||||
|
for i=1, #wifiInfo do
|
||||||
|
if XQSecureUtil.checkPlaintextPwd("admin", wifiInfo[i].password) then
|
||||||
|
same = true
|
||||||
|
end
|
||||||
|
if XQSecureUtil.checkStrong(wifiInfo[i].password) < 2 then
|
||||||
|
strong = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
wifi["same"] = same and 1 or 0
|
||||||
|
wifi["strong"] = strong and 1 or 0
|
||||||
|
|
||||||
|
local disk = {}
|
||||||
|
local diskinfo = XQFunction.thrift_tunnel_to_datacenter([[{"api":26}]])
|
||||||
|
if diskinfo and diskinfo.code == 0 then
|
||||||
|
local capacity = tonumber(diskinfo.capacity)
|
||||||
|
local free = tonumber(diskinfo.free)
|
||||||
|
disk["Used"] = string.format("%.3fG", (capacity - free)/1073741824)
|
||||||
|
disk["Available"] = string.format("%.3fG", free/1073741824)
|
||||||
|
end
|
||||||
|
|
||||||
|
if network then
|
||||||
|
local cputemp = {}
|
||||||
|
cputemp["temperature"] = cpuTemperature
|
||||||
|
if cpuTemperature > 70 then
|
||||||
|
count = count + 1
|
||||||
|
status = 1
|
||||||
|
cputemp["status"] = 0
|
||||||
|
else
|
||||||
|
cputemp["status"] = 1
|
||||||
|
end
|
||||||
|
local cpuavg = {}
|
||||||
|
cpuavg["loadavg"] = network.cpu
|
||||||
|
if tonumber(network.cpu) > 90 then
|
||||||
|
count = count + 1
|
||||||
|
status = 1
|
||||||
|
cpuavg["status"] = 0
|
||||||
|
else
|
||||||
|
cpuavg["status"] = 1
|
||||||
|
end
|
||||||
|
local memoryuse = {}
|
||||||
|
memoryuse["use"] = network.memory
|
||||||
|
if tonumber(network.memory) > 90 then
|
||||||
|
count = count + 1
|
||||||
|
status = 1
|
||||||
|
memoryuse["status"] = 0
|
||||||
|
else
|
||||||
|
memoryuse["status"] = 1
|
||||||
|
end
|
||||||
|
local link = {}
|
||||||
|
if network.wanLink ~= 1 then
|
||||||
|
count = count + 1
|
||||||
|
status = 2
|
||||||
|
link["status"] = 0
|
||||||
|
else
|
||||||
|
link["status"] = 1
|
||||||
|
end
|
||||||
|
local wan = {}
|
||||||
|
wan["type"] = network.wanType
|
||||||
|
if tonumber(network.wanLink) ~= 1 then
|
||||||
|
count = count + 1
|
||||||
|
status = 2
|
||||||
|
wan["status"] = 0
|
||||||
|
else
|
||||||
|
wan["status"] = 1
|
||||||
|
end
|
||||||
|
local gateway = {}
|
||||||
|
gateway["lost"] = network.gw
|
||||||
|
if tonumber(network.gw) > 80 then
|
||||||
|
count = count + 1
|
||||||
|
status = 1
|
||||||
|
gateway["status"] = 0
|
||||||
|
else
|
||||||
|
gateway["status"] = 1
|
||||||
|
end
|
||||||
|
local dnsstatus = {}
|
||||||
|
if tonumber(network.dns) ~= 1 then
|
||||||
|
count = count + 1
|
||||||
|
status = 2
|
||||||
|
dnsstatus["status"] = 0
|
||||||
|
else
|
||||||
|
dnsstatus["status"] = 1
|
||||||
|
end
|
||||||
|
local ping = {}
|
||||||
|
ping["lost"] = network.pingLost
|
||||||
|
if tonumber(network.pingLost) > 80 then
|
||||||
|
count = count + 1
|
||||||
|
status = 2
|
||||||
|
ping["status"] = 0
|
||||||
|
else
|
||||||
|
ping["status"] = 1
|
||||||
|
end
|
||||||
|
result = network
|
||||||
|
result["count"] = count
|
||||||
|
result["status"] = status
|
||||||
|
result["cpuavg"] = cpuavg
|
||||||
|
result["memoryuse"] = memoryuse
|
||||||
|
result["cputemp"] = cputemp
|
||||||
|
result["link"] = link
|
||||||
|
result["wan"] = wan
|
||||||
|
result["gateway"] = gateway
|
||||||
|
result["dnsstatus"] = dnsstatus
|
||||||
|
result["ping"] = ping
|
||||||
|
result["cpuTemperature"] = cpuTemperature
|
||||||
|
result["wifi"] = wifi
|
||||||
|
result["speed"] = speed
|
||||||
|
result["disk"] = disk
|
||||||
|
if count > 0 then
|
||||||
|
XQLog.check(0, XQLog.KEY_DETECT_ERROR, 1)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
code = 1567
|
||||||
|
end
|
||||||
|
if code ~= 0 then
|
||||||
|
result["msg"] = XQErrorUtil.getErrorMessage(code)
|
||||||
|
else
|
||||||
|
local XQPushHelper = require("xiaoqiang.XQPushHelper")
|
||||||
|
local LuciJson = require("json")
|
||||||
|
local payload = {
|
||||||
|
["type"] = 6,
|
||||||
|
["data"] = {
|
||||||
|
["lan"] = speed.lan,
|
||||||
|
["wan"] = speed.wan
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XQPushHelper.push_request(LuciJson.encode(payload))
|
||||||
|
end
|
||||||
|
result["code"] = code
|
||||||
|
LuciHttp.write_json(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
function systemStatus()
|
||||||
|
local XQSysUtil = require("xiaoqiang.util.XQSysUtil")
|
||||||
|
local count = 0
|
||||||
|
local result = {}
|
||||||
|
local status = XQSysUtil.checkSystemStatus()
|
||||||
|
result["code"] = 0
|
||||||
|
result["status"] = 0
|
||||||
|
if (status.cpu and status.cpu > 90) then
|
||||||
|
count = count + 1
|
||||||
|
result["status"] = 1
|
||||||
|
end
|
||||||
|
if (status.mem and status.mem > 90) then
|
||||||
|
count = count + 1
|
||||||
|
result["status"] = 1
|
||||||
|
end
|
||||||
|
if (status.tmp and status.tmp > 70) then
|
||||||
|
count = count + 1
|
||||||
|
result["status"] = 1
|
||||||
|
end
|
||||||
|
if not status.wan or not status.link then
|
||||||
|
count = count + 1
|
||||||
|
result["status"] = 2
|
||||||
|
end
|
||||||
|
result["count"] = count
|
||||||
|
LuciHttp.write_json(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
function netspeed()
|
||||||
|
local XQPreference = require("xiaoqiang.XQPreference")
|
||||||
|
local XQNSTUtil = require("xiaoqiang.module.XQNetworkSpeedTest")
|
||||||
|
local code = 0
|
||||||
|
local result = {}
|
||||||
|
local history = LuciHttp.formvalue("history")
|
||||||
|
if history then
|
||||||
|
result["bandwidth"] = tonumber(XQPreference.get("BANDWIDTH", 0, "xiaoqiang"))
|
||||||
|
result["download"] = tonumber(string.format("%.2f", 128 * result.bandwidth))
|
||||||
|
else
|
||||||
|
local download = XQNSTUtil.downloadSpeedTest()
|
||||||
|
if download then
|
||||||
|
result["download"] = download
|
||||||
|
result["bandwidth"] = tonumber(string.format("%.2f", 8 * download/1024))
|
||||||
|
XQPreference.set("BANDWIDTH", tostring(result.bandwidth), "xiaoqiang")
|
||||||
|
else
|
||||||
|
code = 1588
|
||||||
|
end
|
||||||
|
if code ~= 0 then
|
||||||
|
result["msg"] = XQErrorUtil.getErrorMessage(code)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
result["code"] = code
|
||||||
|
LuciHttp.write_json(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
function uploadSpeed()
|
||||||
|
local XQNSTUtil = require("xiaoqiang.module.XQNetworkSpeedTest")
|
||||||
|
local code = 0
|
||||||
|
local result = {}
|
||||||
|
local upload = XQNSTUtil.uploadSpeedTest()
|
||||||
|
if upload then
|
||||||
|
result["upload"] = upload
|
||||||
|
result["bandwidth"] = tonumber(string.format("%.2f", 8 * upload/1024))
|
||||||
|
else
|
||||||
|
code = 1588
|
||||||
|
end
|
||||||
|
if code ~= 0 then
|
||||||
|
result["msg"] = XQErrorUtil.getErrorMessage(code)
|
||||||
|
end
|
||||||
|
result["code"] = code
|
||||||
|
LuciHttp.write_json(result)
|
||||||
|
end
|
1310
Mi_Lua/luci/controller/api/xqnetwork.lua
Normal file
1310
Mi_Lua/luci/controller/api/xqnetwork.lua
Normal file
File diff suppressed because it is too large
Load Diff
316
Mi_Lua/luci/controller/api/xqpassport.lua
Normal file
316
Mi_Lua/luci/controller/api/xqpassport.lua
Normal file
@ -0,0 +1,316 @@
|
|||||||
|
module("luci.controller.api.xqpassport", package.seeall)
|
||||||
|
|
||||||
|
function index()
|
||||||
|
local page = node("api","xqpassport")
|
||||||
|
page.target = firstchild()
|
||||||
|
page.title = ("")
|
||||||
|
page.order = 400
|
||||||
|
page.sysauth = "admin"
|
||||||
|
page.sysauth_authenticator = "jsonauth"
|
||||||
|
page.index = true
|
||||||
|
entry({"api", "xqpassport"}, firstchild(), (""), 400)
|
||||||
|
entry({"api", "xqpassport", "login"}, call("passportLogin"), (""), 401, 0x01)
|
||||||
|
entry({"api", "xqpassport", "userInfo"}, call("getUserInfo"), (""), 402)
|
||||||
|
entry({"api", "xqpassport", "rigister"}, call("routerRegister"), (""), 405, 0x01)
|
||||||
|
entry({"api", "xqpassport", "binded"}, call("getBindInfo"), (""), 406, 0x01)
|
||||||
|
entry({"api", "xqpassport", "plugin_list"}, call("pluginList"), (""), 407)
|
||||||
|
entry({"api", "xqpassport", "plugin_enable"}, call("pluginEnable"), (""), 408)
|
||||||
|
entry({"api", "xqpassport", "plugin_disable"}, call("pluginDisable"), (""), 409)
|
||||||
|
entry({"api", "xqpassport", "plugin_detail"}, call("pluginDetail"), (""), 410)
|
||||||
|
entry({"api", "xqpassport", "unbound"}, call("unboundRouter"), (""), 411)
|
||||||
|
end
|
||||||
|
|
||||||
|
local LuciHttp = require("luci.http")
|
||||||
|
local XQErrorUtil = require("xiaoqiang.util.XQErrorUtil")
|
||||||
|
|
||||||
|
function getBindInfo()
|
||||||
|
local XQNetUtil = require("xiaoqiang.util.XQNetUtil")
|
||||||
|
local XQSysUtil = require("xiaoqiang.util.XQSysUtil")
|
||||||
|
local uuid = LuciHttp.formvalue("uuid") or ""
|
||||||
|
local force = tonumber(LuciHttp.formvalue("force") or "0")
|
||||||
|
local result = {}
|
||||||
|
local code = 0
|
||||||
|
local bindUUID = XQSysUtil.getPassportBindInfo()
|
||||||
|
if bindUUID then
|
||||||
|
result["bind"] = 1
|
||||||
|
local info = XQSysUtil.getBindUserInfo()
|
||||||
|
if info == nil or force ~= 0 then
|
||||||
|
info = XQNetUtil.getUserInfo(uuid)
|
||||||
|
end
|
||||||
|
if info then
|
||||||
|
if info.miliaoNick and info.miliaoNick ~= "" then
|
||||||
|
info.aliasNick = info.miliaoNick
|
||||||
|
end
|
||||||
|
result["info"] = info
|
||||||
|
else
|
||||||
|
info = {}
|
||||||
|
info["aliasNick"] = bindUUID
|
||||||
|
info["miliaoIcon"] = ""
|
||||||
|
info["miliaoIconOrig"] = ""
|
||||||
|
info["miliaoNick"] = ""
|
||||||
|
info["userId"] = bindUUID
|
||||||
|
result["info"] = info
|
||||||
|
end
|
||||||
|
else
|
||||||
|
result["bind"] = 0
|
||||||
|
end
|
||||||
|
result["routerName"] = XQSysUtil.getRouterName()
|
||||||
|
|
||||||
|
if code ~= 0 then
|
||||||
|
result["msg"] = XQErrorUtil.getErrorMessage(code)
|
||||||
|
end
|
||||||
|
result["code"] = code
|
||||||
|
LuciHttp.write_json(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
function unboundRouter()
|
||||||
|
local XQNetUtil = require("xiaoqiang.util.XQNetUtil")
|
||||||
|
local XQDBUtil = require("xiaoqiang.util.XQDBUtil")
|
||||||
|
local XQSysUtil = require("xiaoqiang.util.XQSysUtil")
|
||||||
|
local result = {}
|
||||||
|
local code = 0
|
||||||
|
local uuid = LuciHttp.formvalue("uuid")
|
||||||
|
local password = LuciHttp.formvalue("password")
|
||||||
|
if uuid == nil or uuid == "" then
|
||||||
|
uuid = XQSysUtil.getBindUUID()
|
||||||
|
end
|
||||||
|
if password ~= nil then
|
||||||
|
local login = XQNetUtil.xiaomiLogin(uuid,password)
|
||||||
|
if login and login.code == 0 then
|
||||||
|
if XQSysUtil.getPassportBindInfo() then
|
||||||
|
local unbound = XQNetUtil.dismissAccount(nil,uuid)
|
||||||
|
if unbound and (tonumber(unbound.code) == 0 or tonumber(unbound.code) == 3001 or tonumber(unbound.code) == 3002) then
|
||||||
|
XQSysUtil.setPassportBound(false,uuid)
|
||||||
|
else
|
||||||
|
code = 1550
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
code = 1556
|
||||||
|
end
|
||||||
|
else
|
||||||
|
code = 1557
|
||||||
|
end
|
||||||
|
if code ~= 0 then
|
||||||
|
result["msg"] = XQErrorUtil.getErrorMessage(code)
|
||||||
|
else
|
||||||
|
LuciHttp.header("Set-Cookie", "psp=admin|||2|||0;path=/;")
|
||||||
|
end
|
||||||
|
result["code"] = code
|
||||||
|
LuciHttp.write_json(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
function passportLogin()
|
||||||
|
local XQNetUtil = require("xiaoqiang.util.XQNetUtil")
|
||||||
|
local XQDBUtil = require("xiaoqiang.util.XQDBUtil")
|
||||||
|
local XQSysUtil = require("xiaoqiang.util.XQSysUtil")
|
||||||
|
local result = {}
|
||||||
|
local code = 0
|
||||||
|
local uuid = LuciHttp.formvalue("uuid")
|
||||||
|
local password = LuciHttp.formvalue("password")
|
||||||
|
local encrypt = LuciHttp.formvalue("encrypt")
|
||||||
|
local login = XQNetUtil.xiaomiLogin(uuid,password)
|
||||||
|
if login and login.code == 0 then
|
||||||
|
local bindInfo = XQSysUtil.getPassportBindInfo()
|
||||||
|
if bindInfo then
|
||||||
|
if login.uuid == bindInfo then
|
||||||
|
local adminList = XQNetUtil.getAdminList()
|
||||||
|
if adminList and type(adminList) == "table" then
|
||||||
|
if tonumber(adminList.code) == 0 then
|
||||||
|
code = 0
|
||||||
|
LuciHttp.header("Set-Cookie", "psp=" .. login.uuid .. "|||" .. 1 .. "|||" .. login.token .. ";path=/;")
|
||||||
|
elseif tonumber(adminList.code) == 401 then
|
||||||
|
code = 1551
|
||||||
|
else
|
||||||
|
code = 1549
|
||||||
|
XQSysUtil.setPassportBound(false,login.uuid)
|
||||||
|
LuciHttp.header("Set-Cookie", "psp=admin|||2|||0;path=/;")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
code = 1551
|
||||||
|
if adminList and adminList.msg then
|
||||||
|
result["errorDetail"] = adminList.msg
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
code = 1548
|
||||||
|
end
|
||||||
|
else
|
||||||
|
XQSysUtil.setBindUUID(login.uuid)
|
||||||
|
end
|
||||||
|
result["token"] = login.token
|
||||||
|
result["uuid"] = login.uuid
|
||||||
|
elseif login and login.code ~= 0 then
|
||||||
|
if login.code == 1 then
|
||||||
|
code = 1564
|
||||||
|
elseif login.code == 2 then
|
||||||
|
code = 1565
|
||||||
|
else
|
||||||
|
code = 1566
|
||||||
|
end
|
||||||
|
else
|
||||||
|
code = 1538
|
||||||
|
end
|
||||||
|
if code ~= 0 then
|
||||||
|
local XQFunction = require("xiaoqiang.common.XQFunction")
|
||||||
|
XQFunction.forkExec("/usr/sbin/ntpsetclock 99999 log >/dev/null 2>&1")
|
||||||
|
result["msg"] = XQErrorUtil.getErrorMessage(code)
|
||||||
|
end
|
||||||
|
result["code"] = code
|
||||||
|
LuciHttp.write_json(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
function routerAdminList()
|
||||||
|
local XQNetUtil = require("xiaoqiang.util.XQNetUtil")
|
||||||
|
local XQSysUtil = require("xiaoqiang.util.XQSysUtil")
|
||||||
|
local result = {}
|
||||||
|
local code = 0
|
||||||
|
local uuid = LuciHttp.formvalue("uuid") or ""
|
||||||
|
if not XQSysUtil.getPassportBindInfo() then
|
||||||
|
code = 1542
|
||||||
|
else
|
||||||
|
local admin = XQNetUtil.getAdminList(uuid)
|
||||||
|
if admin and tonumber(admin.code) == 0 then
|
||||||
|
result["list"] = admin.adminList
|
||||||
|
elseif admin and tonumber(admin.code) == 401 then
|
||||||
|
code = 1581
|
||||||
|
else
|
||||||
|
code = 1543
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if code ~= 0 then
|
||||||
|
result["msg"] = XQErrorUtil.getErrorMessage(code)
|
||||||
|
end
|
||||||
|
result["code"] = code
|
||||||
|
LuciHttp.write_json(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
function routerRegister()
|
||||||
|
local XQSysUtil = require("xiaoqiang.util.XQSysUtil")
|
||||||
|
local XQNetUtil = require("xiaoqiang.util.XQNetUtil")
|
||||||
|
local XQDBUtil = require("xiaoqiang.util.XQDBUtil")
|
||||||
|
local result = {}
|
||||||
|
local code = 0
|
||||||
|
local uuid = LuciHttp.formvalue("uuid")
|
||||||
|
local register = XQNetUtil.routerRegister(uuid)
|
||||||
|
local passport = XQNetUtil.getPassport(uuid)
|
||||||
|
if register and tonumber(register.code) == 0 then
|
||||||
|
result["deviceID"] = register.id
|
||||||
|
XQSysUtil.setPassportBound(true,passport.uuid)
|
||||||
|
else
|
||||||
|
XQSysUtil.setPassportBound(false,nil)
|
||||||
|
code = 1541
|
||||||
|
end
|
||||||
|
if code ~= 0 then
|
||||||
|
local XQFunction = require("xiaoqiang.common.XQFunction")
|
||||||
|
XQFunction.forkExec("/usr/sbin/ntpsetclock 99999 log >/dev/null 2>&1")
|
||||||
|
result["msg"] = XQErrorUtil.getErrorMessage(code)
|
||||||
|
else
|
||||||
|
LuciHttp.header("Set-Cookie", "psp=" .. uuid .. "|||" .. 1 .. "|||" .. passport.token .. ";path=/;")
|
||||||
|
end
|
||||||
|
result["code"] = code
|
||||||
|
LuciHttp.write_json(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
function getUserInfo()
|
||||||
|
local XQNetUtil = require("xiaoqiang.util.XQNetUtil")
|
||||||
|
local result = {}
|
||||||
|
local code = 0
|
||||||
|
local uuid = LuciHttp.formvalue("uuid") or ""
|
||||||
|
local info = XQNetUtil.getUserInfo(uuid)
|
||||||
|
if info then
|
||||||
|
result["userInfo"] = info
|
||||||
|
else
|
||||||
|
code = 1539
|
||||||
|
end
|
||||||
|
if code ~= 0 then
|
||||||
|
result["msg"] = XQErrorUtil.getErrorMessage(code)
|
||||||
|
end
|
||||||
|
result["code"] = code
|
||||||
|
LuciHttp.write_json(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
function pluginList()
|
||||||
|
local XQNetUtil = require("xiaoqiang.util.XQNetUtil")
|
||||||
|
local result = {}
|
||||||
|
local uuid = LuciHttp.formvalue("uuid") or ""
|
||||||
|
local pList = XQNetUtil.pluginList(uuid)
|
||||||
|
if pList and tonumber(pList.code) == 0 then
|
||||||
|
result["code"] = 0
|
||||||
|
result["list"] = pList
|
||||||
|
elseif pList and tonumber(pList.code) == 401 then
|
||||||
|
result["code"] = 1581
|
||||||
|
elseif pList and tonumber(pList.code) == 3001 then
|
||||||
|
result["code"] = 1580
|
||||||
|
else
|
||||||
|
result["code"] = 1544
|
||||||
|
end
|
||||||
|
if result.code ~= 0 then
|
||||||
|
result["msg"] = XQErrorUtil.getErrorMessage(result.code)
|
||||||
|
end
|
||||||
|
LuciHttp.write_json(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
function pluginEnable()
|
||||||
|
local XQNetUtil = require("xiaoqiang.util.XQNetUtil")
|
||||||
|
local result = {}
|
||||||
|
local uuid = LuciHttp.formvalue("uuid") or ""
|
||||||
|
local pluginId = LuciHttp.formvalue("pluginId")
|
||||||
|
local enable = XQNetUtil.pluginEnable(uuid,pluginId)
|
||||||
|
if enable and tonumber(enable.code) == 0 then
|
||||||
|
result["code"] = 0
|
||||||
|
elseif enable and tonumber(enable.code) == 401 then
|
||||||
|
result["code"] = 1581
|
||||||
|
elseif enable and tonumber(enable.code) == 3001 then
|
||||||
|
result["code"] = 1580
|
||||||
|
else
|
||||||
|
result["code"] = 1545
|
||||||
|
end
|
||||||
|
if result.code ~= 0 then
|
||||||
|
result["msg"] = XQErrorUtil.getErrorMessage(result.code)
|
||||||
|
end
|
||||||
|
LuciHttp.write_json(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
function pluginDisable()
|
||||||
|
local XQNetUtil = require("xiaoqiang.util.XQNetUtil")
|
||||||
|
local result = {}
|
||||||
|
local uuid = LuciHttp.formvalue("uuid") or ""
|
||||||
|
local pluginId = LuciHttp.formvalue("pluginId")
|
||||||
|
local disable = XQNetUtil.pluginDisable(uuid,pluginId)
|
||||||
|
if disable and tonumber(disable.code) == 0 then
|
||||||
|
result["code"] = 0
|
||||||
|
elseif disable and tonumber(disable.code) == 401 then
|
||||||
|
result["code"] = 1581
|
||||||
|
elseif disable and tonumber(disable.code) == 3001 then
|
||||||
|
result["code"] = 1580
|
||||||
|
else
|
||||||
|
result["code"] = 1546
|
||||||
|
end
|
||||||
|
if result.code ~= 0 then
|
||||||
|
result["msg"] = XQErrorUtil.getErrorMessage(result.code)
|
||||||
|
end
|
||||||
|
LuciHttp.write_json(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
function pluginDetail()
|
||||||
|
local XQNetUtil = require("xiaoqiang.util.XQNetUtil")
|
||||||
|
local result = {}
|
||||||
|
local uuid = LuciHttp.formvalue("uuid") or ""
|
||||||
|
local pluginId = LuciHttp.formvalue("pluginId")
|
||||||
|
local plugin = XQNetUtil.pluginDetail(uuid,pluginId)
|
||||||
|
if plugin and tonumber(plugin.code) == 0 then
|
||||||
|
result["code"] = 0
|
||||||
|
result["detail"] = plugin
|
||||||
|
elseif plugin and tonumber(plugin.code) == 401 then
|
||||||
|
result["code"] = 1581
|
||||||
|
elseif plugin and tonumber(plugin.code) == 3001 then
|
||||||
|
result["code"] = 1580
|
||||||
|
else
|
||||||
|
result["code"] = 1547
|
||||||
|
end
|
||||||
|
if result.code ~= 0 then
|
||||||
|
result["msg"] = XQErrorUtil.getErrorMessage(result.code)
|
||||||
|
end
|
||||||
|
LuciHttp.write_json(result)
|
||||||
|
end
|
67
Mi_Lua/luci/controller/api/xqsmarthome.lua
Normal file
67
Mi_Lua/luci/controller/api/xqsmarthome.lua
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
module("luci.controller.api.xqsmarthome", package.seeall)
|
||||||
|
|
||||||
|
function index()
|
||||||
|
local page = node("api","xqsmarthome")
|
||||||
|
page.target = firstchild()
|
||||||
|
page.title = ("")
|
||||||
|
page.order = 500
|
||||||
|
page.sysauth = "admin"
|
||||||
|
page.sysauth_authenticator = "jsonauth"
|
||||||
|
page.index = true
|
||||||
|
entry({"api", "xqsmarthome"}, firstchild(), _(""), 500)
|
||||||
|
entry({"api", "xqsmarthome", "request"}, call("tunnelSmartHomeRequest"), _(""), 501)
|
||||||
|
entry({"api", "xqsmarthome", "request_smartcontroller"}, call("tunnelSmartControllerRequest"), _(""), 502)
|
||||||
|
entry({"api", "xqsmarthome", "request_miio"}, call("tunnelMiioRequest"), _(""), 503)
|
||||||
|
entry({"api", "xqsmarthome", "request_mitv"}, call("requestMitv"), _(""), 504)
|
||||||
|
entry({"api", "xqsmarthome", "request_yeelink"}, call("tunnelYeelink"), _(""), 505)
|
||||||
|
entry({"api", "xqsmarthome", "request_camera"}, call("requestCamera"), _(""), 506)
|
||||||
|
end
|
||||||
|
|
||||||
|
local LuciHttp = require("luci.http")
|
||||||
|
local XQConfigs = require("xiaoqiang.common.XQConfigs")
|
||||||
|
local XQFunction = require("xiaoqiang.common.XQFunction")
|
||||||
|
|
||||||
|
function tunnelSmartHomeRequest()
|
||||||
|
local XQCryptoUtil = require("xiaoqiang.util.XQCryptoUtil")
|
||||||
|
local payload = XQCryptoUtil.binaryBase64Enc(LuciHttp.formvalue("payload"))
|
||||||
|
local cmd = XQConfigs.THRIFT_TUNNEL_TO_SMARTHOME % payload
|
||||||
|
local LuciUtil = require("luci.util")
|
||||||
|
LuciHttp.write(LuciUtil.exec(cmd))
|
||||||
|
end
|
||||||
|
|
||||||
|
function tunnelSmartControllerRequest()
|
||||||
|
local XQCryptoUtil = require("xiaoqiang.util.XQCryptoUtil")
|
||||||
|
local payload = XQCryptoUtil.binaryBase64Enc(LuciHttp.formvalue("payload"))
|
||||||
|
local cmd = XQConfigs.THRIFT_TUNNEL_TO_SMARTHOME_CONTROLLER % payload
|
||||||
|
local LuciUtil = require("luci.util")
|
||||||
|
LuciHttp.write(LuciUtil.exec(cmd))
|
||||||
|
end
|
||||||
|
|
||||||
|
function tunnelMiioRequest()
|
||||||
|
local XQCryptoUtil = require("xiaoqiang.util.XQCryptoUtil")
|
||||||
|
local payload = XQCryptoUtil.binaryBase64Enc(LuciHttp.formvalue("payload"))
|
||||||
|
local cmd = XQConfigs.THRIFT_TUNNEL_TO_MIIO % payload
|
||||||
|
local LuciUtil = require("luci.util")
|
||||||
|
LuciHttp.write(LuciUtil.exec(cmd))
|
||||||
|
end
|
||||||
|
|
||||||
|
function tunnelYeelink()
|
||||||
|
local XQCryptoUtil = require("xiaoqiang.util.XQCryptoUtil")
|
||||||
|
local payload = XQCryptoUtil.binaryBase64Enc(LuciHttp.formvalue("payload"))
|
||||||
|
-- merge yeelink daemon into miio, so tunnel into miio
|
||||||
|
local cmd = XQConfigs.THRIFT_TUNNEL_TO_MIIO % payload
|
||||||
|
local LuciUtil = require("luci.util")
|
||||||
|
LuciHttp.write(LuciUtil.exec(cmd))
|
||||||
|
end
|
||||||
|
|
||||||
|
function requestMitv()
|
||||||
|
local payload = LuciHttp.formvalue("payload");
|
||||||
|
local MitvUtil = require("xiaoqiang.util.XQMitvUtil");
|
||||||
|
LuciHttp.write(MitvUtil.request(payload));
|
||||||
|
end
|
||||||
|
|
||||||
|
function requestCamera()
|
||||||
|
local payload = LuciHttp.formvalue("payload");
|
||||||
|
local CamUtil = require("xiaoqiang.util.XQCameraUtil");
|
||||||
|
LuciHttp.write(CamUtil.request(payload));
|
||||||
|
end
|
1598
Mi_Lua/luci/controller/api/xqsystem.lua
Normal file
1598
Mi_Lua/luci/controller/api/xqsystem.lua
Normal file
File diff suppressed because it is too large
Load Diff
53
Mi_Lua/luci/controller/api/xqtunnel.lua
Normal file
53
Mi_Lua/luci/controller/api/xqtunnel.lua
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
module("luci.controller.api.xqtunnel", package.seeall)
|
||||||
|
|
||||||
|
function index()
|
||||||
|
local page = node("api","xqtunnel")
|
||||||
|
page.target = firstchild()
|
||||||
|
page.title = ("")
|
||||||
|
page.order = 300
|
||||||
|
page.sysauth = "admin"
|
||||||
|
page.sysauth_authenticator = "jsonauth"
|
||||||
|
page.index = true
|
||||||
|
entry({"api", "xqtunnel", "request"}, call("tunnelRequest"), _(""), 301)
|
||||||
|
end
|
||||||
|
|
||||||
|
local LuciHttp = require("luci.http")
|
||||||
|
local XQConfigs = require("xiaoqiang.common.XQConfigs")
|
||||||
|
|
||||||
|
local base64chars = {
|
||||||
|
['A']=true,['B']=true,['C']=true,['D']=true,
|
||||||
|
['E']=true,['F']=true,['G']=true,['H']=true,
|
||||||
|
['I']=true,['J']=true,['K']=true,['L']=true,
|
||||||
|
['M']=true,['N']=true,['O']=true,['P']=true,
|
||||||
|
['Q']=true,['R']=true,['S']=true,['T']=true,
|
||||||
|
['U']=true,['V']=true,['W']=true,['X']=true,
|
||||||
|
['Y']=true,['Z']=true,['a']=true,['b']=true,
|
||||||
|
['c']=true,['d']=true,['e']=true,['f']=true,
|
||||||
|
['g']=true,['h']=true,['i']=true,['j']=true,
|
||||||
|
['k']=true,['l']=true,['m']=true,['n']=true,
|
||||||
|
['o']=true,['p']=true,['q']=true,['r']=true,
|
||||||
|
['s']=true,['t']=true,['u']=true,['v']=true,
|
||||||
|
['w']=true,['x']=true,['y']=true,['z']=true,
|
||||||
|
['0']=true,['1']=true,['2']=true,['3']=true,
|
||||||
|
['4']=true,['5']=true,['6']=true,['7']=true,
|
||||||
|
['8']=true,['9']=true,['-']=true,['_']=true,
|
||||||
|
['+']=true,['/']=true,['=']=true
|
||||||
|
}
|
||||||
|
|
||||||
|
local function base64filter(input)
|
||||||
|
local result = ""
|
||||||
|
for i = 1, #input do
|
||||||
|
local c = input:sub(i,i)
|
||||||
|
if base64chars[c] ~= nil and base64chars[c] then
|
||||||
|
result = result .. c
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
function tunnelRequest()
|
||||||
|
local payload = LuciHttp.formvalue("payloadB64")
|
||||||
|
local cmd = XQConfigs.TUNNEL_TOOL % base64filter(payload)
|
||||||
|
local LuciUtil = require("luci.util")
|
||||||
|
LuciHttp.write(LuciUtil.exec(cmd))
|
||||||
|
end
|
18
Mi_Lua/luci/controller/dispatch/index.lua
Normal file
18
Mi_Lua/luci/controller/dispatch/index.lua
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
module("luci.controller.dispatch.index", package.seeall)
|
||||||
|
|
||||||
|
function index()
|
||||||
|
local root = node()
|
||||||
|
if not root.target then
|
||||||
|
root.target = alias("dispatch")
|
||||||
|
root.index = true
|
||||||
|
end
|
||||||
|
local page = node("dispatch")
|
||||||
|
page.target = firstchild()
|
||||||
|
page.title = _("")
|
||||||
|
page.order = 1
|
||||||
|
page.sysauth = "admin"
|
||||||
|
page.mediaurlbase = "/xiaoqiang/dispatch"
|
||||||
|
page.sysauth_authenticator = "htmlauth"
|
||||||
|
page.index = true
|
||||||
|
entry({"dispatch"}, template("index"), _("跳转"), 1, 0x09)
|
||||||
|
end
|
23
Mi_Lua/luci/controller/firewall.lua
Normal file
23
Mi_Lua/luci/controller/firewall.lua
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
module("luci.controller.firewall", package.seeall)
|
||||||
|
|
||||||
|
function index()
|
||||||
|
-- entry({"admin", "network", "firewall"},
|
||||||
|
-- alias("admin", "network", "firewall", "zones"),
|
||||||
|
-- _("Firewall"), 60)
|
||||||
|
--
|
||||||
|
-- entry({"admin", "network", "firewall", "zones"},
|
||||||
|
-- arcombine(cbi("firewall/zones"), cbi("firewall/zone-details")),
|
||||||
|
-- _("General Settings"), 10).leaf = true
|
||||||
|
--
|
||||||
|
-- entry({"admin", "network", "firewall", "forwards"},
|
||||||
|
-- arcombine(cbi("firewall/forwards"), cbi("firewall/forward-details")),
|
||||||
|
-- _("Port Forwards"), 20).leaf = true
|
||||||
|
--
|
||||||
|
-- entry({"admin", "network", "firewall", "rules"},
|
||||||
|
-- arcombine(cbi("firewall/rules"), cbi("firewall/rule-details")),
|
||||||
|
-- _("Traffic Rules"), 30).leaf = true
|
||||||
|
--
|
||||||
|
-- entry({"admin", "network", "firewall", "custom"},
|
||||||
|
-- cbi("firewall/custom"),
|
||||||
|
-- _("Custom Rules"), 40).leaf = true
|
||||||
|
end
|
32
Mi_Lua/luci/controller/mobile/index.lua
Normal file
32
Mi_Lua/luci/controller/mobile/index.lua
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
module("luci.controller.mobile.index", package.seeall)
|
||||||
|
function index()
|
||||||
|
local root = node()
|
||||||
|
if not root.target then
|
||||||
|
root.target = alias("mobile")
|
||||||
|
root.index = true
|
||||||
|
end
|
||||||
|
local page = node("mobile")
|
||||||
|
page.target = firstchild()
|
||||||
|
page.title = _("")
|
||||||
|
page.order = 110
|
||||||
|
page.sysauth = "admin"
|
||||||
|
page.mediaurlbase = "/xiaoqiang/mobile"
|
||||||
|
page.sysauth_authenticator = "htmlauth_moblie"
|
||||||
|
page.index = true
|
||||||
|
entry({"mobile"}, template("mobile/home"), _("首页"), 1, 0x08)
|
||||||
|
entry({"mobile", "logout"}, call("action_logout"), 2, 0x09)
|
||||||
|
entry({"mobile", "hello"}, template("mobile/init/hello"), _("初始化欢迎界面"), 3, 0x09)
|
||||||
|
entry({"mobile", "agreement"}, template("mobile/init/agreement"), _("查看协议"), 4, 0x09)
|
||||||
|
entry({"mobile", "guide"}, template("mobile/init/guide"), _("初始化引导"), 5, 0x08)
|
||||||
|
end
|
||||||
|
|
||||||
|
function action_logout()
|
||||||
|
local dsp = require "luci.dispatcher"
|
||||||
|
local sauth = require "luci.sauth"
|
||||||
|
if dsp.context.authsession then
|
||||||
|
sauth.kill(dsp.context.authsession)
|
||||||
|
dsp.context.urltoken.stok = nil
|
||||||
|
end
|
||||||
|
luci.http.header("Set-Cookie", "sysauth=; path=" .. dsp.build_url())
|
||||||
|
luci.http.redirect(luci.dispatcher.build_url().."/mobile")
|
||||||
|
end
|
382
Mi_Lua/luci/controller/service/datacenter.lua
Normal file
382
Mi_Lua/luci/controller/service/datacenter.lua
Normal file
@ -0,0 +1,382 @@
|
|||||||
|
module("luci.controller.service.datacenter", package.seeall)
|
||||||
|
|
||||||
|
function index()
|
||||||
|
local page = node("service","datacenter")
|
||||||
|
page.target = firstchild()
|
||||||
|
page.title = ("")
|
||||||
|
page.order = nil
|
||||||
|
page.sysauth = "admin"
|
||||||
|
page.sysauth_authenticator = "jsonauth"
|
||||||
|
page.index = true
|
||||||
|
entry({"service", "datacenter", "download_file"}, call("downloadFile"), _(""), nil, 0x11)
|
||||||
|
entry({"service", "datacenter", "device_id"}, call("getDeviceID"), _(""), nil, 0x11)
|
||||||
|
entry({"service", "datacenter", "download_info"}, call("getDownloadInfo"), _(""), nil, 0x11)
|
||||||
|
entry({"service", "datacenter", "upload_file"}, call("uploadFile"), _(""), nil, 0x11)
|
||||||
|
entry({"service", "datacenter", "batch_download_info"}, call("getBatchDownloadInfo"), _(""), nil, 0x11)
|
||||||
|
entry({"service", "datacenter", "config_info"}, call("getConfigInfo"), _(""), nil, 0x11)
|
||||||
|
entry({"service", "datacenter", "set_config"}, call("setConfigInfo"), _(""), nil, 0x11)
|
||||||
|
entry({"service", "datacenter", "plugin_enable"}, call("enablePlugin"), _(""), nil, 0x11)
|
||||||
|
entry({"service", "datacenter", "plugin_download_info"}, call("pluginDownloadInfo"), _(""), nil, 0x11)
|
||||||
|
entry({"service", "datacenter", "plugin_disable"}, call("disablePlugin"), _(""), nil, 0x11)
|
||||||
|
entry({"service", "datacenter", "plugin_control"}, call("controlPlugin"), _(""), nil, 0x11)
|
||||||
|
entry({"service", "datacenter", "download_delete"}, call("deleteDownload"), _(""), nil, 0x11)
|
||||||
|
entry({"service", "datacenter", "get_plugin_status"}, call("pluginStatus"), _(""), nil, 0x11)
|
||||||
|
entry({"service", "datacenter", "get_connected_device"}, call("connectedDevice"), _(""), nil, 0x11)
|
||||||
|
entry({"service", "datacenter", "get_router_mac"}, call("getMac"), _(""), nil, 0x11)
|
||||||
|
entry({"service", "datacenter", "set_wan_access"}, call("setWanAccess"), _(""), nil, 0x11)
|
||||||
|
entry({"service", "datacenter", "get_router_info"}, call("getRouterInfo"), _(""), nil, 0x11)
|
||||||
|
entry({"service", "datacenter", "xunlei_notify"}, call("xunleiNotify"), _(""), nil, 0x11)
|
||||||
|
end
|
||||||
|
|
||||||
|
local LuciHttp = require("luci.http")
|
||||||
|
local XQConfigs = require("xiaoqiang.common.XQConfigs")
|
||||||
|
local ServiceErrorUtil = require("service.util.ServiceErrorUtil")
|
||||||
|
|
||||||
|
function xunleiNotify()
|
||||||
|
local payload = {}
|
||||||
|
payload["api"] = 519
|
||||||
|
payload["info"] = LuciHttp.formvalue("tasks")
|
||||||
|
tunnelRequestDatacenter(payload)
|
||||||
|
end
|
||||||
|
|
||||||
|
function tunnelRequestDatacenter(payload)
|
||||||
|
local LuciJson = require("cjson")
|
||||||
|
local LuciUtil = require("luci.util")
|
||||||
|
local XQCryptoUtil = require("xiaoqiang.util.XQCryptoUtil")
|
||||||
|
payload = LuciJson.encode(payload)
|
||||||
|
payload = XQCryptoUtil.binaryBase64Enc(payload)
|
||||||
|
local cmd = XQConfigs.THRIFT_TUNNEL_TO_DATACENTER % payload
|
||||||
|
LuciHttp.write(LuciUtil.exec(cmd))
|
||||||
|
end
|
||||||
|
|
||||||
|
function requestDatacenter(payload)
|
||||||
|
local LuciJson = require("cjson")
|
||||||
|
local LuciUtil = require("luci.util")
|
||||||
|
local XQCryptoUtil = require("xiaoqiang.util.XQCryptoUtil")
|
||||||
|
payload = LuciJson.encode(payload)
|
||||||
|
payload = XQCryptoUtil.binaryBase64Enc(payload)
|
||||||
|
local cmd = XQConfigs.THRIFT_TUNNEL_TO_DATACENTER % payload
|
||||||
|
return LuciUtil.exec(cmd)
|
||||||
|
end
|
||||||
|
|
||||||
|
function downloadFile()
|
||||||
|
local payload = {}
|
||||||
|
payload["api"] = 1101
|
||||||
|
payload["appid"] = LuciHttp.formvalue("appId")
|
||||||
|
payload["path"] = LuciHttp.formvalue("path")
|
||||||
|
payload["url"] = LuciHttp.formvalue("url")
|
||||||
|
payload["name"] = LuciHttp.formvalue("downloadName")
|
||||||
|
payload["tag"] = LuciHttp.formvalue("tag")
|
||||||
|
payload["hidden"] = false
|
||||||
|
if LuciHttp.formvalue("hidden") == "true" then
|
||||||
|
payload["hidden"] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
payload["redownload"] = 0
|
||||||
|
if LuciHttp.formvalue("redownload") == "1" then
|
||||||
|
payload["redownload"] = 1
|
||||||
|
end
|
||||||
|
|
||||||
|
payload["dupId"] = LuciHttp.formvalue("dupId")
|
||||||
|
tunnelRequestDatacenter(payload)
|
||||||
|
end
|
||||||
|
|
||||||
|
function setWanAccess()
|
||||||
|
local payload = {}
|
||||||
|
payload["api"] = 618
|
||||||
|
payload["appid"] = LuciHttp.formvalue("appId")
|
||||||
|
payload["mac"] = LuciHttp.formvalue("mac")
|
||||||
|
payload["enable"] = false
|
||||||
|
if LuciHttp.formvalue("enable") == "true" then
|
||||||
|
payload["enable"] = true
|
||||||
|
end
|
||||||
|
tunnelRequestDatacenter(payload)
|
||||||
|
end
|
||||||
|
|
||||||
|
function getDeviceID()
|
||||||
|
local payload = {}
|
||||||
|
payload["api"] = 1103
|
||||||
|
payload["appid"] = LuciHttp.formvalue("appId")
|
||||||
|
tunnelRequestDatacenter(payload)
|
||||||
|
end
|
||||||
|
|
||||||
|
function getMac()
|
||||||
|
local payload = {}
|
||||||
|
payload["api"] = 617
|
||||||
|
payload["appid"] = LuciHttp.formvalue("appId")
|
||||||
|
tunnelRequestDatacenter(payload)
|
||||||
|
end
|
||||||
|
|
||||||
|
function getRouterInfo()
|
||||||
|
local payload = {}
|
||||||
|
payload["api"] = 622
|
||||||
|
payload["appid"] = LuciHttp.formvalue("appId")
|
||||||
|
tunnelRequestDatacenter(payload)
|
||||||
|
end
|
||||||
|
|
||||||
|
function getOperateDeviceID()
|
||||||
|
local payload = {}
|
||||||
|
payload["api"] = 1103
|
||||||
|
payload["appid"] = LuciHttp.formvalue("appId")
|
||||||
|
|
||||||
|
local result = requestDatacenter(payload)
|
||||||
|
if result then
|
||||||
|
local LuciJson = require("cjson")
|
||||||
|
result = LuciJson.decode(result)
|
||||||
|
if result then
|
||||||
|
if result.code == 0 then
|
||||||
|
local deviceid = result["deviceid"]
|
||||||
|
if deviceid then
|
||||||
|
return 0, deviceid
|
||||||
|
end
|
||||||
|
elseif result.code == 5 then
|
||||||
|
return 5, nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return 1559, nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function urlEncode(url)
|
||||||
|
if url then
|
||||||
|
url = string.gsub(url, "\n", "\r\n")
|
||||||
|
url = string.gsub(url, "([^0-9a-zA-Z/])",
|
||||||
|
function(c) return string.format ("%%%02X", string.byte(c)) end)
|
||||||
|
end
|
||||||
|
return url
|
||||||
|
end
|
||||||
|
|
||||||
|
function generateUrlFromPath(path)
|
||||||
|
if path then
|
||||||
|
path = urlEncode(path)
|
||||||
|
local url, count = string.gsub (path, "^/userdisk/data/", "http://miwifi.com/api-third-party/download/public/")
|
||||||
|
if count == 1 then
|
||||||
|
return url
|
||||||
|
end
|
||||||
|
|
||||||
|
url, count = string.gsub (path, "^/userdisk/appdata/", "http://miwifi.com/api-third-party/download/private/")
|
||||||
|
if count == 1 then
|
||||||
|
return url
|
||||||
|
end
|
||||||
|
|
||||||
|
url, count = string.gsub (path, "^/extdisks/", "http://miwifi.com/api-third-party/download/extdisks/")
|
||||||
|
if count == 1 then
|
||||||
|
return url
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function generateResponseFromCode(code)
|
||||||
|
local response = {}
|
||||||
|
response["code"] = code
|
||||||
|
response["msg"] = ServiceErrorUtil.getErrorMessage(code)
|
||||||
|
return response
|
||||||
|
end
|
||||||
|
|
||||||
|
function getDownloadInfo()
|
||||||
|
local LuciJson = require("cjson")
|
||||||
|
local payload = {}
|
||||||
|
payload["api"] = 1102
|
||||||
|
payload["appid"] = LuciHttp.formvalue("appId")
|
||||||
|
payload["deviceId"] = LuciHttp.formvalue("deviceId")
|
||||||
|
payload["downloadId"] = LuciHttp.formvalue("downloadId")
|
||||||
|
payload["hidden"] = false
|
||||||
|
if LuciHttp.formvalue("hidden") == "true" then
|
||||||
|
payload["hidden"] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
local response = {}
|
||||||
|
local result = requestDatacenter(payload)
|
||||||
|
if result then
|
||||||
|
result = LuciJson.decode(result)
|
||||||
|
if result and result.code == 0 then
|
||||||
|
local url = generateUrlFromPath(result["path"])
|
||||||
|
if url then
|
||||||
|
response["code"] = result["code"]
|
||||||
|
response["msg"] = result["msg"]
|
||||||
|
response["url"] = url
|
||||||
|
else
|
||||||
|
response = generateResponseFromCode(1559)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
response = result
|
||||||
|
end
|
||||||
|
else
|
||||||
|
response = generateResponseFromCode(1559)
|
||||||
|
end
|
||||||
|
|
||||||
|
LuciHttp.write_json(response)
|
||||||
|
LuciHttp.close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function uploadFile()
|
||||||
|
local fp
|
||||||
|
local log = require("xiaoqiang.XQLog")
|
||||||
|
local fs = require("luci.fs")
|
||||||
|
local tmpfile = "/userdisk/upload.tmp"
|
||||||
|
if fs.isfile(tmpfile) then
|
||||||
|
fs.unlink(tmpfile)
|
||||||
|
end
|
||||||
|
|
||||||
|
local filename
|
||||||
|
LuciHttp.setfilehandler(
|
||||||
|
function(meta, chunk, eof)
|
||||||
|
if not fp then
|
||||||
|
if meta and meta.name == "file" then
|
||||||
|
fp = io.open(tmpfile, "w")
|
||||||
|
filename = meta.file
|
||||||
|
filename = string.gsub(filename, "+", " ")
|
||||||
|
filename = string.gsub(filename, "%%(%x%x)",
|
||||||
|
function(h)
|
||||||
|
return string.char(tonumber(h, 16))
|
||||||
|
end)
|
||||||
|
filename = filename.gsub(filename, "\r\n", "\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if chunk then
|
||||||
|
fp:write(chunk)
|
||||||
|
end
|
||||||
|
if eof then
|
||||||
|
fp:close()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|
||||||
|
local code, deviceId = getOperateDeviceID()
|
||||||
|
if code ~= 0 then
|
||||||
|
return LuciHttp.write_json(generateResponseFromCode(code))
|
||||||
|
end
|
||||||
|
|
||||||
|
local path
|
||||||
|
local appid = LuciHttp.formvalue("appId")
|
||||||
|
local saveType = LuciHttp.formvalue("saveType")
|
||||||
|
if saveType == "public" then
|
||||||
|
path = "/userdisk/data/上传/"
|
||||||
|
elseif saveType == "private" then
|
||||||
|
path = "/userdisk/appdata/" .. appid .. "/"
|
||||||
|
else
|
||||||
|
return LuciHttp.write_json(generateResponseFromCode(3))
|
||||||
|
end
|
||||||
|
fs.mkdir(path, true)
|
||||||
|
|
||||||
|
local savename = fs.basename(filename)
|
||||||
|
if fs.isfile(path .. savename) then
|
||||||
|
local basename = savename
|
||||||
|
local index = basename:match(".+()%.%w+$")
|
||||||
|
if index then
|
||||||
|
basename = basename:sub(1, index - 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
local extension = savename:match(".+%.(%w+)$")
|
||||||
|
for i = 1, 100, 1 do
|
||||||
|
local tmpname = basename .. "(" .. i .. ")"
|
||||||
|
if extension then
|
||||||
|
tmpname = tmpname .. "." .. extension
|
||||||
|
end
|
||||||
|
if not fs.isfile(path .. tmpname) then
|
||||||
|
savename = tmpname
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local dest = path .. savename
|
||||||
|
log.log("dest=" .. dest)
|
||||||
|
fs.rename(tmpfile, dest)
|
||||||
|
|
||||||
|
local response = {}
|
||||||
|
response["code"] = 0
|
||||||
|
response["url"] = generateUrlFromPath(dest)
|
||||||
|
response["deviceId"] = deviceId
|
||||||
|
response["msg"] = ""
|
||||||
|
LuciHttp.write_json(response)
|
||||||
|
LuciHttp.close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function getBatchDownloadInfo()
|
||||||
|
local payload = {}
|
||||||
|
payload["api"] = 1105
|
||||||
|
payload["appid"] = LuciHttp.formvalue("appId")
|
||||||
|
payload["ids"] = LuciHttp.formvalue("ids")
|
||||||
|
payload["hidden"] = false
|
||||||
|
if LuciHttp.formvalue("hidden") == "true" then
|
||||||
|
payload["hidden"] = true
|
||||||
|
end
|
||||||
|
tunnelRequestDatacenter(payload)
|
||||||
|
end
|
||||||
|
|
||||||
|
function getConfigInfo()
|
||||||
|
local payload = {}
|
||||||
|
payload["api"] = 1106
|
||||||
|
payload["appid"] = LuciHttp.formvalue("appId")
|
||||||
|
payload["key"] = LuciHttp.formvalue("key")
|
||||||
|
tunnelRequestDatacenter(payload)
|
||||||
|
end
|
||||||
|
function connectedDevice()
|
||||||
|
local payload = {}
|
||||||
|
payload["api"] = 616
|
||||||
|
payload["appid"] = LuciHttp.formvalue("appId")
|
||||||
|
tunnelRequestDatacenter(payload)
|
||||||
|
end
|
||||||
|
function setConfigInfo()
|
||||||
|
local payload = {}
|
||||||
|
payload["api"] = 1107
|
||||||
|
payload["appid"] = LuciHttp.formvalue("appId")
|
||||||
|
payload["key"] = LuciHttp.formvalue("key")
|
||||||
|
payload["value"] = LuciHttp.formvalue("value")
|
||||||
|
tunnelRequestDatacenter(payload)
|
||||||
|
end
|
||||||
|
function enablePlugin()
|
||||||
|
local payload = {}
|
||||||
|
payload["api"] = 1108
|
||||||
|
payload["appid"] = LuciHttp.formvalue("appId")
|
||||||
|
payload["status"] = 5
|
||||||
|
tunnelRequestDatacenter(payload)
|
||||||
|
end
|
||||||
|
function disablePlugin ()
|
||||||
|
local payload = {}
|
||||||
|
payload["api"] = 1108
|
||||||
|
payload["appid"] = LuciHttp.formvalue("appId")
|
||||||
|
payload["status"] = 6
|
||||||
|
tunnelRequestDatacenter(payload)
|
||||||
|
end
|
||||||
|
function controlPlugin()
|
||||||
|
local payload = {}
|
||||||
|
payload["api"] = 600
|
||||||
|
payload["pluginID"] = LuciHttp.formvalue("appId")
|
||||||
|
payload["info"] = LuciHttp.formvalue("info")
|
||||||
|
tunnelRequestDatacenter(payload)
|
||||||
|
end
|
||||||
|
function deleteDownload()
|
||||||
|
local payload = {}
|
||||||
|
payload["api"] = 1110
|
||||||
|
payload["appid"] = LuciHttp.formvalue("appId")
|
||||||
|
payload["idList"] = LuciHttp.formvalue("idList")
|
||||||
|
payload["deletefile"] = false
|
||||||
|
if LuciHttp.formvalue("deletefile") == "true" then
|
||||||
|
payload["deletefile"] = true
|
||||||
|
end
|
||||||
|
tunnelRequestDatacenter(payload)
|
||||||
|
end
|
||||||
|
function pluginStatus()
|
||||||
|
local payload = {}
|
||||||
|
payload["api"] = 1111
|
||||||
|
payload["appid"] = LuciHttp.formvalue("appId")
|
||||||
|
tunnelRequestDatacenter(payload)
|
||||||
|
end
|
||||||
|
function pluginDownloadInfo()
|
||||||
|
local payload = {}
|
||||||
|
payload["api"] = 1109
|
||||||
|
payload["appid"] = LuciHttp.formvalue("appId")
|
||||||
|
payload["hidden"] = false
|
||||||
|
if LuciHttp.formvalue("hidden") == "true" then
|
||||||
|
payload["hidden"] = true
|
||||||
|
end
|
||||||
|
payload["lite"] = false
|
||||||
|
if LuciHttp.formvalue("lite") == "true" then
|
||||||
|
payload["lite"] = true
|
||||||
|
end
|
||||||
|
tunnelRequestDatacenter(payload)
|
||||||
|
end
|
10
Mi_Lua/luci/controller/service/index.lua
Normal file
10
Mi_Lua/luci/controller/service/index.lua
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
module("luci.controller.service.index", package.seeall)
|
||||||
|
function index()
|
||||||
|
local page = node("service")
|
||||||
|
page.target = firstchild()
|
||||||
|
page.title = _("")
|
||||||
|
page.order = nil
|
||||||
|
page.sysauth = "admin"
|
||||||
|
page.sysauth_authenticator = "jsonauth"
|
||||||
|
page.index = true
|
||||||
|
end
|
96
Mi_Lua/luci/controller/web/index.lua
Normal file
96
Mi_Lua/luci/controller/web/index.lua
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
module("luci.controller.web.index", package.seeall)
|
||||||
|
|
||||||
|
function index()
|
||||||
|
local root = node()
|
||||||
|
if not root.target then
|
||||||
|
root.target = alias("web")
|
||||||
|
root.index = true
|
||||||
|
end
|
||||||
|
local page = node("web")
|
||||||
|
page.target = firstchild()
|
||||||
|
page.title = _("")
|
||||||
|
page.order = 10
|
||||||
|
page.sysauth = "admin"
|
||||||
|
page.mediaurlbase = "/xiaoqiang/web"
|
||||||
|
page.sysauth_authenticator = "htmlauth"
|
||||||
|
page.index = true
|
||||||
|
entry({"web"}, template("web/index"), _("路由器状态"), 10, 0x08)
|
||||||
|
entry({"web", "home"}, template("web/index"), _("路由器状态"), 70, 0x08)
|
||||||
|
entry({"web", "manager"}, template("web/manager"), _("终端管理"), 71)
|
||||||
|
--entry({"web", "plugin"}, template("web/plugin"), _("插件管理"), 72)
|
||||||
|
--entry({"web", "plugin", "kuaipan"}, template("web/plugins/kuaipan"), _("插件管理_快盘"), 72)
|
||||||
|
--entry({"web", "plugin", "guest"}, template("web/plugins/guest"), _("插件管理_访客"), 72)
|
||||||
|
entry({"web", "logout"}, call("action_logout"), 11, 0x09)
|
||||||
|
entry({"web", "init"}, template("web/init/hello"), _("初始化引导"), 190, 0x09)
|
||||||
|
entry({"web", "init", "hello"}, template("web/init/hello"), _("欢迎界面"), 198, 0x09) --不需要登录
|
||||||
|
entry({"web", "init", "agreement"}, template("web/init/agreement"), _("用户协议"), 198, 0x09) --不需要登录
|
||||||
|
entry({"web", "init", "guide"}, template("web/init/guide"), _("引导模式"), 190, 0x08)
|
||||||
|
|
||||||
|
entry({"web", "netset"}, template("web/netset"), _("路由设置"), 73)
|
||||||
|
entry({"web", "sysset"}, template("web/sysset"), _("路由设置"), 73)
|
||||||
|
entry({"web", "sysset", "passport"}, template("web/setting/passport"), _("路由器权限"), 18)
|
||||||
|
entry({"web", "sysset", "reboot"}, template("web/setting/reboot"), _("重启路由器"), 73)
|
||||||
|
entry({"web", "sysset", "reset"}, template("web/setting/reset"), _("恢复出厂设置"), 73)
|
||||||
|
|
||||||
|
entry({"web", "netset", "wifi"}, template("web/setting/wifi_set"), _("WIFI网络设置"), 20)
|
||||||
|
entry({"web", "netset", "wifi_mini"}, template("web/setting/wifi_set_mini"), _("WIFI网络快捷设置"), 20)
|
||||||
|
entry({"web", "netset", "wifi_pro"}, template("web/setting/wifi_set_pro"), _("WIFI网络高级设置"), 60)
|
||||||
|
entry({"web", "netset", "wifi_txpwr"}, template("web/setting/wifi_txpwr"), _("WIFI强度设置"), 60)
|
||||||
|
entry({"web", "netset", "wifi_filter"}, template("web/setting/wifi_filter"), _("WIFI访问控制"), 60)
|
||||||
|
|
||||||
|
entry({"web", "netset" ,"net_wan"}, template("web/setting/net_wan"), _("网络设置WAN"), 20)
|
||||||
|
entry({"web", "netset", "net_lan"}, template("web/setting/net_lan"), _("网络设置LAN"), 30)
|
||||||
|
entry({"web", "netset", "mac"}, template("web/setting/net_setup_mac"), _("mac 设置"), 40)
|
||||||
|
entry({"web", "netset", "ipmacband"}, template("web/setting/net_ipmacband"), _("mac 设置"), 40)
|
||||||
|
entry({"web", "sysset", "qos_pro"}, template("web/setting/qos_pro"), _("QoS 设置"), 40)
|
||||||
|
|
||||||
|
|
||||||
|
entry({"web", "sysset", "upgrade"}, template("web/setting/upgrade"), _("路由器固件升级"), 198, 0x01)
|
||||||
|
entry({"web", "sysset", "upgrade_manual"}, template("web/setting/upgrade_manual", _("路由器手动升级"), 200))
|
||||||
|
entry({"web", "sysset", "log"}, template("web/setting/log", _("上传日志"), 201))
|
||||||
|
--entry({"web", "sysset", "upload_config"}, template("web/setting/upload_config"), _("上传配置信息"), 202)
|
||||||
|
|
||||||
|
--entry({"web", "setting", "sys_psp"}, template("web/setting/sys_psp"), _("管理小米账号"), 73)
|
||||||
|
entry({"web", "sysset", "sys_status"}, template("web/setting/sys_status"), _("系统状态"), 73)
|
||||||
|
|
||||||
|
entry({"web", "sysset", "diskformat"}, template("web/setting/diskformat"), _("格式化小强盘"), 202)
|
||||||
|
entry({"web", "sysset", "nginx"}, template("web/setting/nginx"), _("关闭NGINX"), 203)
|
||||||
|
entry({"web", "sysset", "upnp"}, template("web/setting/upnp"), _("upnp"), 204)
|
||||||
|
-- entry({"web", "sysset", "lamp"}, template("web/setting/lamp"), _("LAMP Settings"), 204)
|
||||||
|
entry({"web", "sysset", "qos"}, template("web/setting/qos"), _("应用限速"), 204)
|
||||||
|
entry({"web", "sysset", "vpn"}, template("web/setting/vpn"), _("VPN"), 204)
|
||||||
|
|
||||||
|
entry({"web", "sysset", "developer"}, template("web/setting/developer"), _("开发者选项"), 205)
|
||||||
|
entry({"web", "sysset", "dmz"}, template("web/setting/dmz"), _("DMZ"), 205)
|
||||||
|
entry({"web", "sysset", "ddns"}, template("web/setting/ddns"), _("DDNS"), 204)
|
||||||
|
entry({"web", "sysset", "nat"}, template("web/setting/nat"), _("端口转发"), 206)
|
||||||
|
entry({"web", "sysset", "noflushd"}, template("web/setting/noflushd"), _("磁盘休眠"), 207)
|
||||||
|
--entry({"web", "sysset", "predownload"}, template("web/setting/predownload"), _("预下载"), 208)
|
||||||
|
|
||||||
|
entry({"web", "detecte"}, template("web/netdetection"), _("网络检测"), 74, 0x01)
|
||||||
|
entry({"web", "detecte_pro"}, template("web/urldetection"), _("网络高级检测"), 75, 0x01)
|
||||||
|
entry({"web", "xmaccount"}, template("web/xmaccount"), _("小米帐号验证"), 75, 0x01)
|
||||||
|
-- entry({"web", "safeurl"}, call("action_safeurl"), _(""), 75, 0x09)
|
||||||
|
|
||||||
|
entry({"web", "webinitrdr"}, template("web/init/webinitrdr"), _("劫持页面"), 300, 0x09) --不需要登录
|
||||||
|
end
|
||||||
|
function action_logout()
|
||||||
|
local dsp = require "luci.dispatcher"
|
||||||
|
local sauth = require "luci.sauth"
|
||||||
|
if dsp.context.authsession then
|
||||||
|
sauth.kill(dsp.context.authsession)
|
||||||
|
dsp.context.urltoken.stok = nil
|
||||||
|
end
|
||||||
|
luci.http.header("Set-Cookie", "sysauth=; path=" .. dsp.build_url())
|
||||||
|
luci.http.header("Set-Cookie", "autologin_v2=;expires=-1;path=/;")
|
||||||
|
luci.http.redirect(luci.dispatcher.build_url())
|
||||||
|
end
|
||||||
|
|
||||||
|
function action_safeurl()
|
||||||
|
|
||||||
|
local safeUrl = luci.http.formvalue("safeurl")
|
||||||
|
require("luci.template")
|
||||||
|
luci.template.render("web/safeurl", {safeurl=safeUrl})
|
||||||
|
|
||||||
|
end
|
||||||
|
|
BIN
Mi_Lua/luci/datacentertunnel.so
Normal file
BIN
Mi_Lua/luci/datacentertunnel.so
Normal file
Binary file not shown.
37
Mi_Lua/luci/debug.lua
Normal file
37
Mi_Lua/luci/debug.lua
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
local debug = require "debug"
|
||||||
|
local io = require "io"
|
||||||
|
local collectgarbage, floor = collectgarbage, math.floor
|
||||||
|
|
||||||
|
module "luci.debug"
|
||||||
|
__file__ = debug.getinfo(1, 'S').source:sub(2)
|
||||||
|
|
||||||
|
-- Enables the memory tracer with given flags and returns a function to disable the tracer again
|
||||||
|
function trap_memtrace(flags, dest)
|
||||||
|
flags = flags or "clr"
|
||||||
|
local tracefile = io.open(dest or "/tmp/memtrace", "w")
|
||||||
|
local peak = 0
|
||||||
|
|
||||||
|
local function trap(what, line)
|
||||||
|
local info = debug.getinfo(2, "Sn")
|
||||||
|
local size = floor(collectgarbage("count"))
|
||||||
|
if size > peak then
|
||||||
|
peak = size
|
||||||
|
end
|
||||||
|
if tracefile then
|
||||||
|
tracefile:write(
|
||||||
|
"[", what, "] ", info.source, ":", (line or "?"), "\t",
|
||||||
|
(info.namewhat or ""), "\t",
|
||||||
|
(info.name or ""), "\t",
|
||||||
|
size, " (", peak, ")\n"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
debug.sethook(trap, flags)
|
||||||
|
|
||||||
|
return function()
|
||||||
|
debug.sethook()
|
||||||
|
tracefile:close()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
1037
Mi_Lua/luci/dispatcher.lua
Normal file
1037
Mi_Lua/luci/dispatcher.lua
Normal file
File diff suppressed because it is too large
Load Diff
244
Mi_Lua/luci/fs.lua
Normal file
244
Mi_Lua/luci/fs.lua
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
--[[
|
||||||
|
LuCI - Filesystem tools
|
||||||
|
|
||||||
|
Description:
|
||||||
|
A module offering often needed filesystem manipulation functions
|
||||||
|
|
||||||
|
FileId:
|
||||||
|
$Id: fs.lua 5134 2009-07-24 17:34:40Z Cyrus $
|
||||||
|
|
||||||
|
License:
|
||||||
|
Copyright 2008 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
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
]]--
|
||||||
|
|
||||||
|
local io = require "io"
|
||||||
|
local os = require "os"
|
||||||
|
local ltn12 = require "luci.ltn12"
|
||||||
|
local fs = require "nixio.fs"
|
||||||
|
local nutil = require "nixio.util"
|
||||||
|
|
||||||
|
local type = type
|
||||||
|
|
||||||
|
--- LuCI filesystem library.
|
||||||
|
module "luci.fs"
|
||||||
|
|
||||||
|
--- Test for file access permission on given path.
|
||||||
|
-- @class function
|
||||||
|
-- @name access
|
||||||
|
-- @param str String value containing the path
|
||||||
|
-- @return Number containing the return code, 0 on sucess or nil on error
|
||||||
|
-- @return String containing the error description (if any)
|
||||||
|
-- @return Number containing the os specific errno (if any)
|
||||||
|
access = fs.access
|
||||||
|
|
||||||
|
--- Evaluate given shell glob pattern and return a table containing all matching
|
||||||
|
-- file and directory entries.
|
||||||
|
-- @class function
|
||||||
|
-- @name glob
|
||||||
|
-- @param filename String containing the path of the file to read
|
||||||
|
-- @return Table containing file and directory entries or nil if no matches
|
||||||
|
-- @return String containing the error description (if no matches)
|
||||||
|
-- @return Number containing the os specific errno (if no matches)
|
||||||
|
function glob(...)
|
||||||
|
local iter, code, msg = fs.glob(...)
|
||||||
|
if iter then
|
||||||
|
return nutil.consume(iter)
|
||||||
|
else
|
||||||
|
return nil, code, msg
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Checks wheather the given path exists and points to a regular file.
|
||||||
|
-- @param filename String containing the path of the file to test
|
||||||
|
-- @return Boolean indicating wheather given path points to regular file
|
||||||
|
function isfile(filename)
|
||||||
|
return fs.stat(filename, "type") == "reg"
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Checks wheather the given path exists and points to a directory.
|
||||||
|
-- @param dirname String containing the path of the directory to test
|
||||||
|
-- @return Boolean indicating wheather given path points to directory
|
||||||
|
function isdirectory(dirname)
|
||||||
|
return fs.stat(dirname, "type") == "dir"
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Read the whole content of the given file into memory.
|
||||||
|
-- @param filename String containing the path of the file to read
|
||||||
|
-- @return String containing the file contents or nil on error
|
||||||
|
-- @return String containing the error message on error
|
||||||
|
readfile = fs.readfile
|
||||||
|
|
||||||
|
--- Write the contents of given string to given file.
|
||||||
|
-- @param filename String containing the path of the file to read
|
||||||
|
-- @param data String containing the data to write
|
||||||
|
-- @return Boolean containing true on success or nil on error
|
||||||
|
-- @return String containing the error message on error
|
||||||
|
writefile = fs.writefile
|
||||||
|
|
||||||
|
--- Copies a file.
|
||||||
|
-- @param source Source file
|
||||||
|
-- @param dest Destination
|
||||||
|
-- @return Boolean containing true on success or nil on error
|
||||||
|
copy = fs.datacopy
|
||||||
|
|
||||||
|
--- Renames a file.
|
||||||
|
-- @param source Source file
|
||||||
|
-- @param dest Destination
|
||||||
|
-- @return Boolean containing true on success or nil on error
|
||||||
|
rename = fs.move
|
||||||
|
|
||||||
|
--- Get the last modification time of given file path in Unix epoch format.
|
||||||
|
-- @param path String containing the path of the file or directory to read
|
||||||
|
-- @return Number containing the epoch time or nil on error
|
||||||
|
-- @return String containing the error description (if any)
|
||||||
|
-- @return Number containing the os specific errno (if any)
|
||||||
|
function mtime(path)
|
||||||
|
return fs.stat(path, "mtime")
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the last modification time of given file path in Unix epoch format.
|
||||||
|
-- @param path String containing the path of the file or directory to read
|
||||||
|
-- @param mtime Last modification timestamp
|
||||||
|
-- @param atime Last accessed timestamp
|
||||||
|
-- @return 0 in case of success nil on error
|
||||||
|
-- @return String containing the error description (if any)
|
||||||
|
-- @return Number containing the os specific errno (if any)
|
||||||
|
function utime(path, mtime, atime)
|
||||||
|
return fs.utimes(path, atime, mtime)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Return the last element - usually the filename - from the given path with
|
||||||
|
-- the directory component stripped.
|
||||||
|
-- @class function
|
||||||
|
-- @name basename
|
||||||
|
-- @param path String containing the path to strip
|
||||||
|
-- @return String containing the base name of given path
|
||||||
|
-- @see dirname
|
||||||
|
basename = fs.basename
|
||||||
|
|
||||||
|
--- Return the directory component of the given path with the last element
|
||||||
|
-- stripped of.
|
||||||
|
-- @class function
|
||||||
|
-- @name dirname
|
||||||
|
-- @param path String containing the path to strip
|
||||||
|
-- @return String containing the directory component of given path
|
||||||
|
-- @see basename
|
||||||
|
dirname = fs.dirname
|
||||||
|
|
||||||
|
--- Return a table containing all entries of the specified directory.
|
||||||
|
-- @class function
|
||||||
|
-- @name dir
|
||||||
|
-- @param path String containing the path of the directory to scan
|
||||||
|
-- @return Table containing file and directory entries or nil on error
|
||||||
|
-- @return String containing the error description on error
|
||||||
|
-- @return Number containing the os specific errno on error
|
||||||
|
function dir(...)
|
||||||
|
local iter, code, msg = fs.dir(...)
|
||||||
|
if iter then
|
||||||
|
local t = nutil.consume(iter)
|
||||||
|
t[#t+1] = "."
|
||||||
|
t[#t+1] = ".."
|
||||||
|
return t
|
||||||
|
else
|
||||||
|
return nil, code, msg
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Create a new directory, recursively on demand.
|
||||||
|
-- @param path String with the name or path of the directory to create
|
||||||
|
-- @param recursive Create multiple directory levels (optional, default is true)
|
||||||
|
-- @return Number with the return code, 0 on sucess or nil on error
|
||||||
|
-- @return String containing the error description on error
|
||||||
|
-- @return Number containing the os specific errno on error
|
||||||
|
function mkdir(path, recursive)
|
||||||
|
return recursive and fs.mkdirr(path) or fs.mkdir(path)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Remove the given empty directory.
|
||||||
|
-- @class function
|
||||||
|
-- @name rmdir
|
||||||
|
-- @param path String containing the path of the directory to remove
|
||||||
|
-- @return Number with the return code, 0 on sucess or nil on error
|
||||||
|
-- @return String containing the error description on error
|
||||||
|
-- @return Number containing the os specific errno on error
|
||||||
|
rmdir = fs.rmdir
|
||||||
|
|
||||||
|
local stat_tr = {
|
||||||
|
reg = "regular",
|
||||||
|
dir = "directory",
|
||||||
|
lnk = "link",
|
||||||
|
chr = "character device",
|
||||||
|
blk = "block device",
|
||||||
|
fifo = "fifo",
|
||||||
|
sock = "socket"
|
||||||
|
}
|
||||||
|
--- Get information about given file or directory.
|
||||||
|
-- @class function
|
||||||
|
-- @name stat
|
||||||
|
-- @param path String containing the path of the directory to query
|
||||||
|
-- @return Table containing file or directory properties or nil on error
|
||||||
|
-- @return String containing the error description on error
|
||||||
|
-- @return Number containing the os specific errno on error
|
||||||
|
function stat(path, key)
|
||||||
|
local data, code, msg = fs.stat(path)
|
||||||
|
if data then
|
||||||
|
data.mode = data.modestr
|
||||||
|
data.type = stat_tr[data.type] or "?"
|
||||||
|
end
|
||||||
|
return key and data and data[key] or data, code, msg
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set permissions on given file or directory.
|
||||||
|
-- @class function
|
||||||
|
-- @name chmod
|
||||||
|
-- @param path String containing the path of the directory
|
||||||
|
-- @param perm String containing the permissions to set ([ugoa][+-][rwx])
|
||||||
|
-- @return Number with the return code, 0 on sucess or nil on error
|
||||||
|
-- @return String containing the error description on error
|
||||||
|
-- @return Number containing the os specific errno on error
|
||||||
|
chmod = fs.chmod
|
||||||
|
|
||||||
|
--- Create a hard- or symlink from given file (or directory) to specified target
|
||||||
|
-- file (or directory) path.
|
||||||
|
-- @class function
|
||||||
|
-- @name link
|
||||||
|
-- @param path1 String containing the source path to link
|
||||||
|
-- @param path2 String containing the destination path for the link
|
||||||
|
-- @param symlink Boolean indicating wheather to create a symlink (optional)
|
||||||
|
-- @return Number with the return code, 0 on sucess or nil on error
|
||||||
|
-- @return String containing the error description on error
|
||||||
|
-- @return Number containing the os specific errno on error
|
||||||
|
function link(src, dest, sym)
|
||||||
|
return sym and fs.symlink(src, dest) or fs.link(src, dest)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Remove the given file.
|
||||||
|
-- @class function
|
||||||
|
-- @name unlink
|
||||||
|
-- @param path String containing the path of the file to remove
|
||||||
|
-- @return Number with the return code, 0 on sucess or nil on error
|
||||||
|
-- @return String containing the error description on error
|
||||||
|
-- @return Number containing the os specific errno on error
|
||||||
|
unlink = fs.unlink
|
||||||
|
|
||||||
|
--- Retrieve target of given symlink.
|
||||||
|
-- @class function
|
||||||
|
-- @name readlink
|
||||||
|
-- @param path String containing the path of the symlink to read
|
||||||
|
-- @return String containing the link target or nil on error
|
||||||
|
-- @return String containing the error description on error
|
||||||
|
-- @return Number containing the os specific errno on error
|
||||||
|
readlink = fs.readlink
|
336
Mi_Lua/luci/http.lua
Normal file
336
Mi_Lua/luci/http.lua
Normal file
@ -0,0 +1,336 @@
|
|||||||
|
--[[
|
||||||
|
LuCI - HTTP-Interaction
|
||||||
|
|
||||||
|
Description:
|
||||||
|
HTTP-Header manipulator and form variable preprocessor
|
||||||
|
|
||||||
|
License:
|
||||||
|
Copyright 2008 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
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
]]--
|
||||||
|
|
||||||
|
local ltn12 = require "luci.ltn12"
|
||||||
|
local protocol = require "luci.http.protocol"
|
||||||
|
local util = require "luci.util"
|
||||||
|
local string = require "string"
|
||||||
|
local coroutine = require "coroutine"
|
||||||
|
local table = require "table"
|
||||||
|
|
||||||
|
local ipairs, pairs, next, type, tostring, error =
|
||||||
|
ipairs, pairs, next, type, tostring, error
|
||||||
|
|
||||||
|
--- LuCI Web Framework high-level HTTP functions.
|
||||||
|
module ("luci.http", package.seeall)
|
||||||
|
|
||||||
|
context = util.threadlocal()
|
||||||
|
|
||||||
|
Request = util.class()
|
||||||
|
function Request.__init__(self, env, sourcein, sinkerr)
|
||||||
|
self.input = sourcein
|
||||||
|
self.error = sinkerr
|
||||||
|
|
||||||
|
|
||||||
|
-- File handler
|
||||||
|
self.filehandler = function() end
|
||||||
|
|
||||||
|
-- HTTP-Message table
|
||||||
|
self.message = {
|
||||||
|
env = env,
|
||||||
|
headers = {},
|
||||||
|
params = protocol.urldecode_params(env.QUERY_STRING or ""),
|
||||||
|
}
|
||||||
|
|
||||||
|
self.parsed_input = false
|
||||||
|
end
|
||||||
|
|
||||||
|
function Request.formvalue(self, name, noparse)
|
||||||
|
if not noparse and not self.parsed_input then
|
||||||
|
self:_parse_input()
|
||||||
|
end
|
||||||
|
|
||||||
|
if name then
|
||||||
|
return self.message.params[name]
|
||||||
|
else
|
||||||
|
return self.message.params
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Request.formvaluetable(self, prefix)
|
||||||
|
local vals = {}
|
||||||
|
prefix = prefix and prefix .. "." or "."
|
||||||
|
|
||||||
|
if not self.parsed_input then
|
||||||
|
self:_parse_input()
|
||||||
|
end
|
||||||
|
|
||||||
|
local void = self.message.params[nil]
|
||||||
|
for k, v in pairs(self.message.params) do
|
||||||
|
if k:find(prefix, 1, true) == 1 then
|
||||||
|
vals[k:sub(#prefix + 1)] = tostring(v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return vals
|
||||||
|
end
|
||||||
|
|
||||||
|
function Request.content(self)
|
||||||
|
if not self.parsed_input then
|
||||||
|
self:_parse_input()
|
||||||
|
end
|
||||||
|
|
||||||
|
return self.message.content, self.message.content_length
|
||||||
|
end
|
||||||
|
|
||||||
|
function Request.getcookie(self, name)
|
||||||
|
local c = string.gsub(";" .. (self:getenv("HTTP_COOKIE") or "") .. ";", "%s*;%s*", ";")
|
||||||
|
local p = ";" .. name .. "=(.-);"
|
||||||
|
local i, j, value = c:find(p)
|
||||||
|
return value and urldecode(value)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Request.getenv(self, name)
|
||||||
|
if name then
|
||||||
|
return self.message.env[name]
|
||||||
|
else
|
||||||
|
return self.message.env
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Request.setfilehandler(self, callback)
|
||||||
|
self.filehandler = callback
|
||||||
|
end
|
||||||
|
|
||||||
|
function Request._parse_input(self)
|
||||||
|
protocol.parse_message_body(
|
||||||
|
self.input,
|
||||||
|
self.message,
|
||||||
|
self.filehandler
|
||||||
|
)
|
||||||
|
self.parsed_input = true
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Close the HTTP-Connection.
|
||||||
|
function close()
|
||||||
|
if not context.eoh then
|
||||||
|
context.eoh = true
|
||||||
|
coroutine.yield(3)
|
||||||
|
end
|
||||||
|
|
||||||
|
if not context.closed then
|
||||||
|
context.closed = true
|
||||||
|
coroutine.yield(5)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Return the request content if the request was of unknown type.
|
||||||
|
-- @return HTTP request body
|
||||||
|
-- @return HTTP request body length
|
||||||
|
function content()
|
||||||
|
return context.request:content()
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get a certain HTTP input value or a table of all input values.
|
||||||
|
-- @param name Name of the GET or POST variable to fetch
|
||||||
|
-- @param noparse Don't parse POST data before getting the value
|
||||||
|
-- @return HTTP input value or table of all input value
|
||||||
|
function formvalue(name, noparse)
|
||||||
|
return context.request:formvalue(name, noparse)
|
||||||
|
end
|
||||||
|
|
||||||
|
function xqformvalue(name, noparse)
|
||||||
|
local XQSecureUtil = require("xiaoqiang.util.XQSecureUtil")
|
||||||
|
local value = context.request:formvalue(name, noparse)
|
||||||
|
return XQSecureUtil.xssCheck(value)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get a table of all HTTP input values with a certain prefix.
|
||||||
|
-- @param prefix Prefix
|
||||||
|
-- @return Table of all HTTP input values with given prefix
|
||||||
|
function formvaluetable(prefix)
|
||||||
|
return context.request:formvaluetable(prefix)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the value of a certain HTTP-Cookie.
|
||||||
|
-- @param name Cookie Name
|
||||||
|
-- @return String containing cookie data
|
||||||
|
function getcookie(name)
|
||||||
|
return context.request:getcookie(name)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the value of a certain HTTP environment variable
|
||||||
|
-- or the environment table itself.
|
||||||
|
-- @param name Environment variable
|
||||||
|
-- @return HTTP environment value or environment table
|
||||||
|
function getenv(name)
|
||||||
|
return context.request:getenv(name)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set a handler function for incoming user file uploads.
|
||||||
|
-- @param callback Handler function
|
||||||
|
function setfilehandler(callback)
|
||||||
|
return context.request:setfilehandler(callback)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Send a HTTP-Header.
|
||||||
|
-- @param key Header key
|
||||||
|
-- @param value Header value
|
||||||
|
function header(key, value)
|
||||||
|
if not context.headers then
|
||||||
|
context.headers = {}
|
||||||
|
end
|
||||||
|
context.headers[key:lower()] = value
|
||||||
|
coroutine.yield(2, key, value)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the mime type of following content data.
|
||||||
|
-- @param mime Mimetype of following content
|
||||||
|
function prepare_content(mime)
|
||||||
|
if not context.headers or not context.headers["content-type"] then
|
||||||
|
if mime == "application/xhtml+xml" then
|
||||||
|
if not getenv("HTTP_ACCEPT") or
|
||||||
|
not getenv("HTTP_ACCEPT"):find("application/xhtml+xml", nil, true) then
|
||||||
|
mime = "text/html; charset=UTF-8"
|
||||||
|
end
|
||||||
|
header("Vary", "Accept")
|
||||||
|
end
|
||||||
|
header("Content-Type", mime)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the RAW HTTP input source
|
||||||
|
-- @return HTTP LTN12 source
|
||||||
|
function source()
|
||||||
|
return context.request.input
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the HTTP status code and status message.
|
||||||
|
-- @param code Status code
|
||||||
|
-- @param message Status message
|
||||||
|
function status(code, message)
|
||||||
|
code = code or 200
|
||||||
|
message = message or "OK"
|
||||||
|
context.status = code
|
||||||
|
coroutine.yield(1, code, message)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Send a chunk of content data to the client.
|
||||||
|
-- This function is as a valid LTN12 sink.
|
||||||
|
-- If the content chunk is nil this function will automatically invoke close.
|
||||||
|
-- @param content Content chunk
|
||||||
|
-- @param src_err Error object from source (optional)
|
||||||
|
-- @see close
|
||||||
|
function write(content, src_err)
|
||||||
|
if not content then
|
||||||
|
if src_err then
|
||||||
|
error(src_err)
|
||||||
|
else
|
||||||
|
close()
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
elseif #content == 0 then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
if not context.eoh then
|
||||||
|
if not context.status then
|
||||||
|
status()
|
||||||
|
end
|
||||||
|
if not context.headers or not context.headers["content-type"] then
|
||||||
|
header("Content-Type", "text/html; charset=utf-8")
|
||||||
|
end
|
||||||
|
if not context.headers["cache-control"] then
|
||||||
|
header("Cache-Control", "no-cache")
|
||||||
|
header("Expires", "0")
|
||||||
|
end
|
||||||
|
|
||||||
|
context.eoh = true
|
||||||
|
coroutine.yield(3)
|
||||||
|
end
|
||||||
|
coroutine.yield(4, content)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Splice data from a filedescriptor to the client.
|
||||||
|
-- @param fp File descriptor
|
||||||
|
-- @param size Bytes to splice (optional)
|
||||||
|
function splice(fd, size)
|
||||||
|
coroutine.yield(6, fd, size)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Redirects the client to a new URL and closes the connection.
|
||||||
|
-- @param url Target URL
|
||||||
|
function redirect(url)
|
||||||
|
status(302, "Found")
|
||||||
|
header("Location", url)
|
||||||
|
close()
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Create a querystring out of a table of key - value pairs.
|
||||||
|
-- @param table Query string source table
|
||||||
|
-- @return Encoded HTTP query string
|
||||||
|
function build_querystring(q)
|
||||||
|
local s = { "?" }
|
||||||
|
|
||||||
|
for k, v in pairs(q) do
|
||||||
|
if #s > 1 then s[#s+1] = "&" end
|
||||||
|
|
||||||
|
s[#s+1] = urldecode(k)
|
||||||
|
s[#s+1] = "="
|
||||||
|
s[#s+1] = urldecode(v)
|
||||||
|
end
|
||||||
|
|
||||||
|
return table.concat(s, "")
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Return the URL-decoded equivalent of a string.
|
||||||
|
-- @param str URL-encoded string
|
||||||
|
-- @param no_plus Don't decode + to " "
|
||||||
|
-- @return URL-decoded string
|
||||||
|
-- @see urlencode
|
||||||
|
urldecode = protocol.urldecode
|
||||||
|
|
||||||
|
--- Return the URL-encoded equivalent of a string.
|
||||||
|
-- @param str Source string
|
||||||
|
-- @return URL-encoded string
|
||||||
|
-- @see urldecode
|
||||||
|
urlencode = protocol.urlencode
|
||||||
|
|
||||||
|
function writeJsonNoLog(x)
|
||||||
|
if x == nil then
|
||||||
|
write("null")
|
||||||
|
elseif type(x) == "table" then
|
||||||
|
local json = require("luci.json")
|
||||||
|
write(json.encode(x))
|
||||||
|
elseif type(x) == "number" or type(x) == "boolean" then
|
||||||
|
if (x ~= x) then
|
||||||
|
-- NaN is the only value that doesn't equal to itself.
|
||||||
|
write("Number.NaN")
|
||||||
|
else
|
||||||
|
write(tostring(x))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
write('"%s"' % tostring(x):gsub('["%z\1-\31]', function(c)
|
||||||
|
return '\\u%04x' % c:byte(1)
|
||||||
|
end))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Send the given data as JSON encoded string.
|
||||||
|
-- @param data Data to send
|
||||||
|
function write_json(x)
|
||||||
|
local XQLog = require("xiaoqiang.XQLog")
|
||||||
|
XQLog.log(7,x)
|
||||||
|
writeJsonNoLog(x)
|
||||||
|
end
|
727
Mi_Lua/luci/http/protocol.lua
Normal file
727
Mi_Lua/luci/http/protocol.lua
Normal file
@ -0,0 +1,727 @@
|
|||||||
|
--[[
|
||||||
|
|
||||||
|
HTTP protocol implementation for LuCI
|
||||||
|
(c) 2008 Freifunk Leipzig / Jo-Philipp Wich <xm@leipzig.freifunk.net>
|
||||||
|
|
||||||
|
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: protocol.lua 9195 2012-08-29 13:06:58Z jow $
|
||||||
|
|
||||||
|
]]--
|
||||||
|
|
||||||
|
--- LuCI http protocol class.
|
||||||
|
-- This class contains several functions useful for http message- and content
|
||||||
|
-- decoding and to retrive form data from raw http messages.
|
||||||
|
module("luci.http.protocol", package.seeall)
|
||||||
|
|
||||||
|
local util = require "luci.util"
|
||||||
|
local ltn12 = require("luci.ltn12")
|
||||||
|
|
||||||
|
HTTP_MAX_CONTENT = 1024*32 -- 8 kB maximum content size
|
||||||
|
|
||||||
|
--- Decode an urlencoded string - optionally without decoding
|
||||||
|
-- the "+" sign to " " - and return the decoded string.
|
||||||
|
-- @param str Input string in x-www-urlencoded format
|
||||||
|
-- @param no_plus Don't decode "+" signs to spaces
|
||||||
|
-- @return The decoded string
|
||||||
|
-- @see urlencode
|
||||||
|
function urldecode( str, no_plus )
|
||||||
|
|
||||||
|
local function __chrdec( hex )
|
||||||
|
return string.char( tonumber( hex, 16 ) )
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(str) == "string" then
|
||||||
|
if not no_plus then
|
||||||
|
str = str:gsub( "+", " " )
|
||||||
|
end
|
||||||
|
|
||||||
|
str = str:gsub( "%%([a-fA-F0-9][a-fA-F0-9])", __chrdec )
|
||||||
|
end
|
||||||
|
|
||||||
|
return str
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Extract and split urlencoded data pairs, separated bei either "&" or ";"
|
||||||
|
-- from given url or string. Returns a table with urldecoded values.
|
||||||
|
-- Simple parameters are stored as string values associated with the parameter
|
||||||
|
-- name within the table. Parameters with multiple values are stored as array
|
||||||
|
-- containing the corresponding values.
|
||||||
|
-- @param url The url or string which contains x-www-urlencoded form data
|
||||||
|
-- @param tbl Use the given table for storing values (optional)
|
||||||
|
-- @return Table containing the urldecoded parameters
|
||||||
|
-- @see urlencode_params
|
||||||
|
function urldecode_params( url, tbl )
|
||||||
|
|
||||||
|
local params = tbl or { }
|
||||||
|
|
||||||
|
if url:find("?") then
|
||||||
|
url = url:gsub( "^.+%?([^?]+)", "%1" )
|
||||||
|
end
|
||||||
|
|
||||||
|
for pair in url:gmatch( "[^&;]+" ) do
|
||||||
|
|
||||||
|
-- find key and value
|
||||||
|
local key = urldecode( pair:match("^([^=]+)") )
|
||||||
|
local val = urldecode( pair:match("^[^=]+=(.+)$") )
|
||||||
|
|
||||||
|
-- store
|
||||||
|
if type(key) == "string" and key:len() > 0 then
|
||||||
|
if type(val) ~= "string" then val = "" end
|
||||||
|
|
||||||
|
if not params[key] then
|
||||||
|
params[key] = val
|
||||||
|
elseif type(params[key]) ~= "table" then
|
||||||
|
params[key] = { params[key], val }
|
||||||
|
else
|
||||||
|
table.insert( params[key], val )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return params
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Encode given string to x-www-urlencoded format.
|
||||||
|
-- @param str String to encode
|
||||||
|
-- @return String containing the encoded data
|
||||||
|
-- @see urldecode
|
||||||
|
function urlencode( str )
|
||||||
|
|
||||||
|
local function __chrenc( chr )
|
||||||
|
return string.format(
|
||||||
|
"%%%02x", string.byte( chr )
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(str) == "string" then
|
||||||
|
str = str:gsub(
|
||||||
|
"([^a-zA-Z0-9$_%-%.%+!*'(),])",
|
||||||
|
__chrenc
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
return str
|
||||||
|
end
|
||||||
|
|
||||||
|
function xqurlencode(str)
|
||||||
|
if (str) then
|
||||||
|
--Ensure all newlines are in CRLF form
|
||||||
|
str = string.gsub (str, "\r?\n", "\r\n")
|
||||||
|
|
||||||
|
--Percent-encode all non-unreserved characters
|
||||||
|
--as per RFC 3986, Section 2.3
|
||||||
|
--(except for space, which gets plus-encoded)
|
||||||
|
str = string.gsub (str, "([^%w%-%.%_%~ ])",
|
||||||
|
function (c) return string.format ("%%%02X", string.byte(c)) end)
|
||||||
|
|
||||||
|
--Convert spaces to plus signs
|
||||||
|
str = string.gsub (str, " ", "+")
|
||||||
|
end
|
||||||
|
return str
|
||||||
|
end
|
||||||
|
|
||||||
|
function xq_urlencode_params( tbl )
|
||||||
|
local enc = ""
|
||||||
|
|
||||||
|
for k, v in pairs(tbl) do
|
||||||
|
if type(v) == "table" then
|
||||||
|
for i, v2 in ipairs(v) do
|
||||||
|
enc = enc .. ( #enc > 0 and "&" or "" ) ..
|
||||||
|
urlencode(k) .. "=" .. xqurlencode(v2)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
enc = (enc .. ( #enc > 0 and "&" or "" ) ..
|
||||||
|
urlencode(k) .. "=" .. xqurlencode(v))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return enc
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Encode each key-value-pair in given table to x-www-urlencoded format,
|
||||||
|
-- separated by "&". Tables are encoded as parameters with multiple values by
|
||||||
|
-- repeating the parameter name with each value.
|
||||||
|
-- @param tbl Table with the values
|
||||||
|
-- @return String containing encoded values
|
||||||
|
-- @see urldecode_params
|
||||||
|
function urlencode_params( tbl )
|
||||||
|
local enc = ""
|
||||||
|
|
||||||
|
for k, v in pairs(tbl) do
|
||||||
|
if type(v) == "table" then
|
||||||
|
for i, v2 in ipairs(v) do
|
||||||
|
enc = enc .. ( #enc > 0 and "&" or "" ) ..
|
||||||
|
urlencode(k) .. "=" .. urlencode(v2)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
enc = (enc .. ( #enc > 0 and "&" or "" ) ..
|
||||||
|
urlencode(k) .. "=" .. urlencode(v))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return enc
|
||||||
|
end
|
||||||
|
|
||||||
|
-- (Internal function)
|
||||||
|
-- Initialize given parameter and coerce string into table when the parameter
|
||||||
|
-- already exists.
|
||||||
|
-- @param tbl Table where parameter should be created
|
||||||
|
-- @param key Parameter name
|
||||||
|
-- @return Always nil
|
||||||
|
local function __initval( tbl, key )
|
||||||
|
if tbl[key] == nil then
|
||||||
|
tbl[key] = ""
|
||||||
|
elseif type(tbl[key]) == "string" then
|
||||||
|
tbl[key] = { tbl[key], "" }
|
||||||
|
else
|
||||||
|
table.insert( tbl[key], "" )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- (Internal function)
|
||||||
|
-- Append given data to given parameter, either by extending the string value
|
||||||
|
-- or by appending it to the last string in the parameter's value table.
|
||||||
|
-- @param tbl Table containing the previously initialized parameter value
|
||||||
|
-- @param key Parameter name
|
||||||
|
-- @param chunk String containing the data to append
|
||||||
|
-- @return Always nil
|
||||||
|
-- @see __initval
|
||||||
|
local function __appendval( tbl, key, chunk )
|
||||||
|
if type(tbl[key]) == "table" then
|
||||||
|
tbl[key][#tbl[key]] = tbl[key][#tbl[key]] .. chunk
|
||||||
|
else
|
||||||
|
tbl[key] = tbl[key] .. chunk
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- (Internal function)
|
||||||
|
-- Finish the value of given parameter, either by transforming the string value
|
||||||
|
-- or - in the case of multi value parameters - the last element in the
|
||||||
|
-- associated values table.
|
||||||
|
-- @param tbl Table containing the previously initialized parameter value
|
||||||
|
-- @param key Parameter name
|
||||||
|
-- @param handler Function which transforms the parameter value
|
||||||
|
-- @return Always nil
|
||||||
|
-- @see __initval
|
||||||
|
-- @see __appendval
|
||||||
|
local function __finishval( tbl, key, handler )
|
||||||
|
if handler then
|
||||||
|
if type(tbl[key]) == "table" then
|
||||||
|
tbl[key][#tbl[key]] = handler( tbl[key][#tbl[key]] )
|
||||||
|
else
|
||||||
|
tbl[key] = handler( tbl[key] )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Table of our process states
|
||||||
|
local process_states = { }
|
||||||
|
|
||||||
|
-- Extract "magic", the first line of a http message.
|
||||||
|
-- Extracts the message type ("get", "post" or "response"), the requested uri
|
||||||
|
-- or the status code if the line descripes a http response.
|
||||||
|
process_states['magic'] = function( msg, chunk, err )
|
||||||
|
|
||||||
|
if chunk ~= nil then
|
||||||
|
-- ignore empty lines before request
|
||||||
|
if #chunk == 0 then
|
||||||
|
return true, nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Is it a request?
|
||||||
|
local method, uri, http_ver = chunk:match("^([A-Z]+) ([^ ]+) HTTP/([01]%.[019])$")
|
||||||
|
|
||||||
|
-- Yup, it is
|
||||||
|
if method then
|
||||||
|
|
||||||
|
msg.type = "request"
|
||||||
|
msg.request_method = method:lower()
|
||||||
|
msg.request_uri = uri
|
||||||
|
msg.http_version = tonumber( http_ver )
|
||||||
|
msg.headers = { }
|
||||||
|
|
||||||
|
-- We're done, next state is header parsing
|
||||||
|
return true, function( chunk )
|
||||||
|
return process_states['headers']( msg, chunk )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Is it a response?
|
||||||
|
else
|
||||||
|
|
||||||
|
local http_ver, code, message = chunk:match("^HTTP/([01]%.[019]) ([0-9]+) ([^\r\n]+)$")
|
||||||
|
|
||||||
|
-- Is a response
|
||||||
|
if code then
|
||||||
|
|
||||||
|
msg.type = "response"
|
||||||
|
msg.status_code = code
|
||||||
|
msg.status_message = message
|
||||||
|
msg.http_version = tonumber( http_ver )
|
||||||
|
msg.headers = { }
|
||||||
|
|
||||||
|
-- We're done, next state is header parsing
|
||||||
|
return true, function( chunk )
|
||||||
|
return process_states['headers']( msg, chunk )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Can't handle it
|
||||||
|
return nil, "Invalid HTTP message magic"
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Extract headers from given string.
|
||||||
|
process_states['headers'] = function( msg, chunk )
|
||||||
|
|
||||||
|
if chunk ~= nil then
|
||||||
|
|
||||||
|
-- Look for a valid header format
|
||||||
|
local hdr, val = chunk:match( "^([A-Za-z][A-Za-z0-9%-_]+): +(.+)$" )
|
||||||
|
|
||||||
|
if type(hdr) == "string" and hdr:len() > 0 and
|
||||||
|
type(val) == "string" and val:len() > 0
|
||||||
|
then
|
||||||
|
msg.headers[hdr] = val
|
||||||
|
|
||||||
|
-- Valid header line, proceed
|
||||||
|
return true, nil
|
||||||
|
|
||||||
|
elseif #chunk == 0 then
|
||||||
|
-- Empty line, we won't accept data anymore
|
||||||
|
return false, nil
|
||||||
|
else
|
||||||
|
-- Junk data
|
||||||
|
return nil, "Invalid HTTP header received"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return nil, "Unexpected EOF"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Creates a ltn12 source from the given socket. The source will return it's
|
||||||
|
-- data line by line with the trailing \r\n stripped of.
|
||||||
|
-- @param sock Readable network socket
|
||||||
|
-- @return Ltn12 source function
|
||||||
|
function header_source( sock )
|
||||||
|
return ltn12.source.simplify( function()
|
||||||
|
|
||||||
|
local chunk, err, part = sock:receive("*l")
|
||||||
|
|
||||||
|
-- Line too long
|
||||||
|
if chunk == nil then
|
||||||
|
if err ~= "timeout" then
|
||||||
|
return nil, part
|
||||||
|
and "Line exceeds maximum allowed length"
|
||||||
|
or "Unexpected EOF"
|
||||||
|
else
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Line ok
|
||||||
|
elseif chunk ~= nil then
|
||||||
|
|
||||||
|
-- Strip trailing CR
|
||||||
|
chunk = chunk:gsub("\r$","")
|
||||||
|
|
||||||
|
return chunk, nil
|
||||||
|
end
|
||||||
|
end )
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Decode a mime encoded http message body with multipart/form-data
|
||||||
|
-- Content-Type. Stores all extracted data associated with its parameter name
|
||||||
|
-- in the params table withing the given message object. Multiple parameter
|
||||||
|
-- values are stored as tables, ordinary ones as strings.
|
||||||
|
-- If an optional file callback function is given then it is feeded with the
|
||||||
|
-- file contents chunk by chunk and only the extracted file name is stored
|
||||||
|
-- within the params table. The callback function will be called subsequently
|
||||||
|
-- with three arguments:
|
||||||
|
-- o Table containing decoded (name, file) and raw (headers) mime header data
|
||||||
|
-- o String value containing a chunk of the file data
|
||||||
|
-- o Boolean which indicates wheather the current chunk is the last one (eof)
|
||||||
|
-- @param src Ltn12 source function
|
||||||
|
-- @param msg HTTP message object
|
||||||
|
-- @param filecb File callback function (optional)
|
||||||
|
-- @return Value indicating successful operation (not nil means "ok")
|
||||||
|
-- @return String containing the error if unsuccessful
|
||||||
|
-- @see parse_message_header
|
||||||
|
function mimedecode_message_body( src, msg, filecb )
|
||||||
|
|
||||||
|
if msg and msg.env.CONTENT_TYPE then
|
||||||
|
msg.mime_boundary = msg.env.CONTENT_TYPE:match("^multipart/form%-data; boundary=(.+)$")
|
||||||
|
end
|
||||||
|
|
||||||
|
if not msg.mime_boundary then
|
||||||
|
return nil, "Invalid Content-Type found"
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local tlen = 0
|
||||||
|
local inhdr = false
|
||||||
|
local field = nil
|
||||||
|
local store = nil
|
||||||
|
local lchunk = nil
|
||||||
|
|
||||||
|
local function parse_headers( chunk, field )
|
||||||
|
|
||||||
|
local stat
|
||||||
|
repeat
|
||||||
|
chunk, stat = chunk:gsub(
|
||||||
|
"^([A-Z][A-Za-z0-9%-_]+): +([^\r\n]+)\r\n",
|
||||||
|
function(k,v)
|
||||||
|
field.headers[k] = v
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
)
|
||||||
|
until stat == 0
|
||||||
|
|
||||||
|
chunk, stat = chunk:gsub("^\r\n","")
|
||||||
|
|
||||||
|
-- End of headers
|
||||||
|
if stat > 0 then
|
||||||
|
if field.headers["Content-Disposition"] then
|
||||||
|
if field.headers["Content-Disposition"]:match("^form%-data; ") then
|
||||||
|
field.name = field.headers["Content-Disposition"]:match('name="(.-)"')
|
||||||
|
field.file = field.headers["Content-Disposition"]:match('filename="(.+)"$')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not field.headers["Content-Type"] then
|
||||||
|
field.headers["Content-Type"] = "text/plain"
|
||||||
|
end
|
||||||
|
|
||||||
|
if field.name and field.file and filecb then
|
||||||
|
__initval( msg.params, field.name )
|
||||||
|
__appendval( msg.params, field.name, field.file )
|
||||||
|
|
||||||
|
store = filecb
|
||||||
|
elseif field.name then
|
||||||
|
__initval( msg.params, field.name )
|
||||||
|
|
||||||
|
store = function( hdr, buf, eof )
|
||||||
|
__appendval( msg.params, field.name, buf )
|
||||||
|
end
|
||||||
|
else
|
||||||
|
store = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
return chunk, true
|
||||||
|
end
|
||||||
|
|
||||||
|
return chunk, false
|
||||||
|
end
|
||||||
|
|
||||||
|
local function snk( chunk )
|
||||||
|
|
||||||
|
tlen = tlen + ( chunk and #chunk or 0 )
|
||||||
|
|
||||||
|
if msg.env.CONTENT_LENGTH and tlen > tonumber(msg.env.CONTENT_LENGTH) + 2 then
|
||||||
|
return nil, "Message body size exceeds Content-Length"
|
||||||
|
end
|
||||||
|
|
||||||
|
if chunk and not lchunk then
|
||||||
|
lchunk = "\r\n" .. chunk
|
||||||
|
|
||||||
|
elseif lchunk then
|
||||||
|
local data = lchunk .. ( chunk or "" )
|
||||||
|
local spos, epos, found
|
||||||
|
|
||||||
|
repeat
|
||||||
|
spos, epos = data:find( "\r\n--" .. msg.mime_boundary .. "\r\n", 1, true )
|
||||||
|
|
||||||
|
if not spos then
|
||||||
|
spos, epos = data:find( "\r\n--" .. msg.mime_boundary .. "--\r\n", 1, true )
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
if spos then
|
||||||
|
local predata = data:sub( 1, spos - 1 )
|
||||||
|
|
||||||
|
if inhdr then
|
||||||
|
predata, eof = parse_headers( predata, field )
|
||||||
|
|
||||||
|
if not eof then
|
||||||
|
return nil, "Invalid MIME section header"
|
||||||
|
elseif not field.name then
|
||||||
|
return nil, "Invalid Content-Disposition header"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if store then
|
||||||
|
store( field, predata, true )
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
field = { headers = { } }
|
||||||
|
found = found or true
|
||||||
|
|
||||||
|
data, eof = parse_headers( data:sub( epos + 1, #data ), field )
|
||||||
|
inhdr = not eof
|
||||||
|
end
|
||||||
|
until not spos
|
||||||
|
|
||||||
|
if found then
|
||||||
|
-- We found at least some boundary. Save
|
||||||
|
-- the unparsed remaining data for the
|
||||||
|
-- next chunk.
|
||||||
|
lchunk, data = data, nil
|
||||||
|
else
|
||||||
|
-- There was a complete chunk without a boundary. Parse it as headers or
|
||||||
|
-- append it as data, depending on our current state.
|
||||||
|
if inhdr then
|
||||||
|
lchunk, eof = parse_headers( data, field )
|
||||||
|
inhdr = not eof
|
||||||
|
else
|
||||||
|
-- We're inside data, so append the data. Note that we only append
|
||||||
|
-- lchunk, not all of data, since there is a chance that chunk
|
||||||
|
-- contains half a boundary. Assuming that each chunk is at least the
|
||||||
|
-- boundary in size, this should prevent problems
|
||||||
|
store( field, lchunk, false )
|
||||||
|
lchunk, chunk = chunk, nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return ltn12.pump.all( src, snk )
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Decode an urlencoded http message body with application/x-www-urlencoded
|
||||||
|
-- Content-Type. Stores all extracted data associated with its parameter name
|
||||||
|
-- in the params table withing the given message object. Multiple parameter
|
||||||
|
-- values are stored as tables, ordinary ones as strings.
|
||||||
|
-- @param src Ltn12 source function
|
||||||
|
-- @param msg HTTP message object
|
||||||
|
-- @return Value indicating successful operation (not nil means "ok")
|
||||||
|
-- @return String containing the error if unsuccessful
|
||||||
|
-- @see parse_message_header
|
||||||
|
function urldecode_message_body( src, msg )
|
||||||
|
|
||||||
|
local tlen = 0
|
||||||
|
local lchunk = nil
|
||||||
|
|
||||||
|
local function snk( chunk )
|
||||||
|
|
||||||
|
tlen = tlen + ( chunk and #chunk or 0 )
|
||||||
|
|
||||||
|
if msg.env.CONTENT_LENGTH and tlen > tonumber(msg.env.CONTENT_LENGTH) + 2 then
|
||||||
|
return nil, "Message body size exceeds Content-Length"
|
||||||
|
elseif tlen > HTTP_MAX_CONTENT then
|
||||||
|
return nil, "Message body size exceeds maximum allowed length"
|
||||||
|
end
|
||||||
|
|
||||||
|
if not lchunk and chunk then
|
||||||
|
lchunk = chunk
|
||||||
|
|
||||||
|
elseif lchunk then
|
||||||
|
local data = lchunk .. ( chunk or "&" )
|
||||||
|
local spos, epos
|
||||||
|
|
||||||
|
repeat
|
||||||
|
spos, epos = data:find("^.-[;&]")
|
||||||
|
|
||||||
|
if spos then
|
||||||
|
local pair = data:sub( spos, epos - 1 )
|
||||||
|
local key = pair:match("^(.-)=")
|
||||||
|
local val = pair:match("=([^%s]*)%s*$")
|
||||||
|
|
||||||
|
if key and #key > 0 then
|
||||||
|
__initval( msg.params, key )
|
||||||
|
__appendval( msg.params, key, val )
|
||||||
|
__finishval( msg.params, key, urldecode )
|
||||||
|
else
|
||||||
|
key = "invalid_param"
|
||||||
|
__initval( msg.params, key )
|
||||||
|
__appendval( msg.params, key, pair )
|
||||||
|
__finishval( msg.params, key, urldecode )
|
||||||
|
end
|
||||||
|
|
||||||
|
data = data:sub( epos + 1, #data )
|
||||||
|
end
|
||||||
|
until not spos
|
||||||
|
|
||||||
|
lchunk = data
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return ltn12.pump.all( src, snk )
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Try to extract an http message header including information like protocol
|
||||||
|
-- version, message headers and resulting CGI environment variables from the
|
||||||
|
-- given ltn12 source.
|
||||||
|
-- @param src Ltn12 source function
|
||||||
|
-- @return HTTP message object
|
||||||
|
-- @see parse_message_body
|
||||||
|
function parse_message_header( src )
|
||||||
|
|
||||||
|
local ok = true
|
||||||
|
local msg = { }
|
||||||
|
|
||||||
|
local sink = ltn12.sink.simplify(
|
||||||
|
function( chunk )
|
||||||
|
return process_states['magic']( msg, chunk )
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|
||||||
|
-- Pump input data...
|
||||||
|
while ok do
|
||||||
|
|
||||||
|
-- get data
|
||||||
|
ok, err = ltn12.pump.step( src, sink )
|
||||||
|
|
||||||
|
-- error
|
||||||
|
if not ok and err then
|
||||||
|
return nil, err
|
||||||
|
|
||||||
|
-- eof
|
||||||
|
elseif not ok then
|
||||||
|
|
||||||
|
-- Process get parameters
|
||||||
|
if ( msg.request_method == "get" or msg.request_method == "post" ) and
|
||||||
|
msg.request_uri:match("?")
|
||||||
|
then
|
||||||
|
msg.params = urldecode_params( msg.request_uri )
|
||||||
|
else
|
||||||
|
msg.params = { }
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Populate common environment variables
|
||||||
|
msg.env = {
|
||||||
|
CONTENT_LENGTH = msg.headers['Content-Length'];
|
||||||
|
CONTENT_TYPE = msg.headers['Content-Type'] or msg.headers['Content-type'];
|
||||||
|
REQUEST_METHOD = msg.request_method:upper();
|
||||||
|
REQUEST_URI = msg.request_uri;
|
||||||
|
SCRIPT_NAME = msg.request_uri:gsub("?.+$","");
|
||||||
|
SCRIPT_FILENAME = ""; -- XXX implement me
|
||||||
|
SERVER_PROTOCOL = "HTTP/" .. string.format("%.1f", msg.http_version);
|
||||||
|
QUERY_STRING = msg.request_uri:match("?")
|
||||||
|
and msg.request_uri:gsub("^.+?","") or ""
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Populate HTTP_* environment variables
|
||||||
|
for i, hdr in ipairs( {
|
||||||
|
'Accept',
|
||||||
|
'Accept-Charset',
|
||||||
|
'Accept-Encoding',
|
||||||
|
'Accept-Language',
|
||||||
|
'Connection',
|
||||||
|
'Cookie',
|
||||||
|
'Host',
|
||||||
|
'Referer',
|
||||||
|
'User-Agent',
|
||||||
|
} ) do
|
||||||
|
local var = 'HTTP_' .. hdr:upper():gsub("%-","_")
|
||||||
|
local val = msg.headers[hdr]
|
||||||
|
|
||||||
|
msg.env[var] = val
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return msg
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Try to extract and decode a http message body from the given ltn12 source.
|
||||||
|
-- This function will examine the Content-Type within the given message object
|
||||||
|
-- to select the appropriate content decoder.
|
||||||
|
-- Currently the application/x-www-urlencoded and application/form-data
|
||||||
|
-- mime types are supported. If the encountered content encoding can't be
|
||||||
|
-- handled then the whole message body will be stored unaltered as "content"
|
||||||
|
-- property within the given message object.
|
||||||
|
-- @param src Ltn12 source function
|
||||||
|
-- @param msg HTTP message object
|
||||||
|
-- @param filecb File data callback (optional, see mimedecode_message_body())
|
||||||
|
-- @return Value indicating successful operation (not nil means "ok")
|
||||||
|
-- @return String containing the error if unsuccessful
|
||||||
|
-- @see parse_message_header
|
||||||
|
function parse_message_body( src, msg, filecb )
|
||||||
|
-- Is it multipart/mime ?
|
||||||
|
if msg.env.REQUEST_METHOD == "POST" and msg.env.CONTENT_TYPE and
|
||||||
|
msg.env.CONTENT_TYPE:match("^multipart/form%-data")
|
||||||
|
then
|
||||||
|
|
||||||
|
return mimedecode_message_body( src, msg, filecb )
|
||||||
|
|
||||||
|
-- Is it application/x-www-form-urlencoded ?
|
||||||
|
elseif msg.env.REQUEST_METHOD == "POST" and msg.env.CONTENT_TYPE and
|
||||||
|
msg.env.CONTENT_TYPE:match("^application/x%-www%-form%-urlencoded")
|
||||||
|
then
|
||||||
|
return urldecode_message_body( src, msg, filecb )
|
||||||
|
|
||||||
|
|
||||||
|
-- Unhandled encoding
|
||||||
|
-- If a file callback is given then feed it chunk by chunk, else
|
||||||
|
-- store whole buffer in message.content
|
||||||
|
else
|
||||||
|
|
||||||
|
local sink
|
||||||
|
|
||||||
|
-- If we have a file callback then feed it
|
||||||
|
if type(filecb) == "function" then
|
||||||
|
sink = filecb
|
||||||
|
|
||||||
|
-- ... else append to .content
|
||||||
|
else
|
||||||
|
msg.content = ""
|
||||||
|
msg.content_length = 0
|
||||||
|
|
||||||
|
sink = function( chunk, err )
|
||||||
|
if chunk then
|
||||||
|
if ( msg.content_length + #chunk ) <= HTTP_MAX_CONTENT then
|
||||||
|
msg.content = msg.content .. chunk
|
||||||
|
msg.content_length = msg.content_length + #chunk
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return nil, "POST data exceeds maximum allowed length"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Pump data...
|
||||||
|
while true do
|
||||||
|
local ok, err = ltn12.pump.step( src, sink )
|
||||||
|
|
||||||
|
if not ok and err then
|
||||||
|
return nil, err
|
||||||
|
elseif not err then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Table containing human readable messages for several http status codes.
|
||||||
|
-- @class table
|
||||||
|
statusmsg = {
|
||||||
|
[200] = "OK",
|
||||||
|
[206] = "Partial Content",
|
||||||
|
[301] = "Moved Permanently",
|
||||||
|
[302] = "Found",
|
||||||
|
[304] = "Not Modified",
|
||||||
|
[400] = "Bad Request",
|
||||||
|
[403] = "Forbidden",
|
||||||
|
[404] = "Not Found",
|
||||||
|
[405] = "Method Not Allowed",
|
||||||
|
[408] = "Request Time-out",
|
||||||
|
[411] = "Length Required",
|
||||||
|
[412] = "Precondition Failed",
|
||||||
|
[416] = "Requested range not satisfiable",
|
||||||
|
[500] = "Internal Server Error",
|
||||||
|
[503] = "Server Unavailable",
|
||||||
|
}
|
153
Mi_Lua/luci/http/protocol/conditionals.lua
Normal file
153
Mi_Lua/luci/http/protocol/conditionals.lua
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
--[[
|
||||||
|
|
||||||
|
HTTP protocol implementation for LuCI - RFC2616 / 14.19, 14.24 - 14.28
|
||||||
|
(c) 2008 Freifunk Leipzig / Jo-Philipp Wich <xm@leipzig.freifunk.net>
|
||||||
|
|
||||||
|
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: conditionals.lua 5637 2009-12-20 18:35:05Z jow $
|
||||||
|
|
||||||
|
]]--
|
||||||
|
|
||||||
|
--- LuCI http protocol implementation - HTTP/1.1 bits.
|
||||||
|
-- This class provides basic ETag handling and implements most of the
|
||||||
|
-- conditional HTTP/1.1 headers specified in RFC2616 Sct. 14.24 - 14.28 .
|
||||||
|
module("luci.http.protocol.conditionals", package.seeall)
|
||||||
|
|
||||||
|
local date = require("luci.http.protocol.date")
|
||||||
|
|
||||||
|
|
||||||
|
--- Implement 14.19 / ETag.
|
||||||
|
-- @param stat A file.stat structure
|
||||||
|
-- @return String containing the generated tag suitable for ETag headers
|
||||||
|
function mk_etag( stat )
|
||||||
|
if stat ~= nil then
|
||||||
|
return string.format( '"%x-%x-%x"', stat.ino, stat.size, stat.mtime )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- 14.24 / If-Match
|
||||||
|
-- Test whether the given message object contains an "If-Match" header and
|
||||||
|
-- compare it against the given stat object.
|
||||||
|
-- @param req HTTP request message object
|
||||||
|
-- @param stat A file.stat object
|
||||||
|
-- @return Boolean indicating whether the precondition is ok
|
||||||
|
-- @return Alternative status code if the precondition failed
|
||||||
|
function if_match( req, stat )
|
||||||
|
local h = req.headers
|
||||||
|
local etag = mk_etag( stat )
|
||||||
|
|
||||||
|
-- Check for matching resource
|
||||||
|
if type(h['If-Match']) == "string" then
|
||||||
|
for ent in h['If-Match']:gmatch("([^, ]+)") do
|
||||||
|
if ( ent == '*' or ent == etag ) and stat ~= nil then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return false, 412
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
--- 14.25 / If-Modified-Since
|
||||||
|
-- Test whether the given message object contains an "If-Modified-Since" header
|
||||||
|
-- and compare it against the given stat object.
|
||||||
|
-- @param req HTTP request message object
|
||||||
|
-- @param stat A file.stat object
|
||||||
|
-- @return Boolean indicating whether the precondition is ok
|
||||||
|
-- @return Alternative status code if the precondition failed
|
||||||
|
-- @return Table containing extra HTTP headers if the precondition failed
|
||||||
|
function if_modified_since( req, stat )
|
||||||
|
local h = req.headers
|
||||||
|
|
||||||
|
-- Compare mtimes
|
||||||
|
if type(h['If-Modified-Since']) == "string" then
|
||||||
|
local since = date.to_unix( h['If-Modified-Since'] )
|
||||||
|
|
||||||
|
if stat == nil or since < stat.mtime then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return false, 304, {
|
||||||
|
["ETag"] = mk_etag( stat );
|
||||||
|
["Date"] = date.to_http( os.time() );
|
||||||
|
["Last-Modified"] = date.to_http( stat.mtime )
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
--- 14.26 / If-None-Match
|
||||||
|
-- Test whether the given message object contains an "If-None-Match" header and
|
||||||
|
-- compare it against the given stat object.
|
||||||
|
-- @param req HTTP request message object
|
||||||
|
-- @param stat A file.stat object
|
||||||
|
-- @return Boolean indicating whether the precondition is ok
|
||||||
|
-- @return Alternative status code if the precondition failed
|
||||||
|
-- @return Table containing extra HTTP headers if the precondition failed
|
||||||
|
function if_none_match( req, stat )
|
||||||
|
local h = req.headers
|
||||||
|
local etag = mk_etag( stat )
|
||||||
|
local method = req.env and req.env.REQUEST_METHOD or "GET"
|
||||||
|
|
||||||
|
-- Check for matching resource
|
||||||
|
if type(h['If-None-Match']) == "string" then
|
||||||
|
for ent in h['If-None-Match']:gmatch("([^, ]+)") do
|
||||||
|
if ( ent == '*' or ent == etag ) and stat ~= nil then
|
||||||
|
if method == "GET" or method == "HEAD" then
|
||||||
|
return false, 304, {
|
||||||
|
["ETag"] = etag;
|
||||||
|
["Date"] = date.to_http( os.time() );
|
||||||
|
["Last-Modified"] = date.to_http( stat.mtime )
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false, 412
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
--- 14.27 / If-Range
|
||||||
|
-- The If-Range header is currently not implemented due to the lack of general
|
||||||
|
-- byte range stuff in luci.http.protocol . This function will always return
|
||||||
|
-- false, 412 to indicate a failed precondition.
|
||||||
|
-- @param req HTTP request message object
|
||||||
|
-- @param stat A file.stat object
|
||||||
|
-- @return Boolean indicating whether the precondition is ok
|
||||||
|
-- @return Alternative status code if the precondition failed
|
||||||
|
function if_range( req, stat )
|
||||||
|
-- Sorry, no subranges (yet)
|
||||||
|
return false, 412
|
||||||
|
end
|
||||||
|
|
||||||
|
--- 14.28 / If-Unmodified-Since
|
||||||
|
-- Test whether the given message object contains an "If-Unmodified-Since"
|
||||||
|
-- header and compare it against the given stat object.
|
||||||
|
-- @param req HTTP request message object
|
||||||
|
-- @param stat A file.stat object
|
||||||
|
-- @return Boolean indicating whether the precondition is ok
|
||||||
|
-- @return Alternative status code if the precondition failed
|
||||||
|
function if_unmodified_since( req, stat )
|
||||||
|
local h = req.headers
|
||||||
|
|
||||||
|
-- Compare mtimes
|
||||||
|
if type(h['If-Unmodified-Since']) == "string" then
|
||||||
|
local since = date.to_unix( h['If-Unmodified-Since'] )
|
||||||
|
|
||||||
|
if stat ~= nil and since <= stat.mtime then
|
||||||
|
return false, 412
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
115
Mi_Lua/luci/http/protocol/date.lua
Normal file
115
Mi_Lua/luci/http/protocol/date.lua
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
--[[
|
||||||
|
|
||||||
|
HTTP protocol implementation for LuCI - date handling
|
||||||
|
(c) 2008 Freifunk Leipzig / Jo-Philipp Wich <xm@leipzig.freifunk.net>
|
||||||
|
|
||||||
|
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: date.lua 3860 2008-12-06 03:18:14Z jow $
|
||||||
|
|
||||||
|
]]--
|
||||||
|
|
||||||
|
--- LuCI http protocol implementation - date helper class.
|
||||||
|
-- This class contains functions to parse, compare and format http dates.
|
||||||
|
module("luci.http.protocol.date", package.seeall)
|
||||||
|
|
||||||
|
require("luci.sys.zoneinfo")
|
||||||
|
|
||||||
|
|
||||||
|
MONTHS = {
|
||||||
|
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
|
||||||
|
"Sep", "Oct", "Nov", "Dec"
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Return the time offset in seconds between the UTC and given time zone.
|
||||||
|
-- @param tz Symbolic or numeric timezone specifier
|
||||||
|
-- @return Time offset to UTC in seconds
|
||||||
|
function tz_offset(tz)
|
||||||
|
|
||||||
|
if type(tz) == "string" then
|
||||||
|
|
||||||
|
-- check for a numeric identifier
|
||||||
|
local s, v = tz:match("([%+%-])([0-9]+)")
|
||||||
|
if s == '+' then s = 1 else s = -1 end
|
||||||
|
if v then v = tonumber(v) end
|
||||||
|
|
||||||
|
if s and v then
|
||||||
|
return s * 60 * ( math.floor( v / 100 ) * 60 + ( v % 100 ) )
|
||||||
|
|
||||||
|
-- lookup symbolic tz
|
||||||
|
elseif luci.sys.zoneinfo.OFFSET[tz:lower()] then
|
||||||
|
return luci.sys.zoneinfo.OFFSET[tz:lower()]
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- bad luck
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Parse given HTTP date string and convert it to unix epoch time.
|
||||||
|
-- @param data String containing the date
|
||||||
|
-- @return Unix epoch time
|
||||||
|
function to_unix(date)
|
||||||
|
|
||||||
|
local wd, day, mon, yr, hr, min, sec, tz = date:match(
|
||||||
|
"([A-Z][a-z][a-z]), ([0-9]+) " ..
|
||||||
|
"([A-Z][a-z][a-z]) ([0-9]+) " ..
|
||||||
|
"([0-9]+):([0-9]+):([0-9]+) " ..
|
||||||
|
"([A-Z0-9%+%-]+)"
|
||||||
|
)
|
||||||
|
|
||||||
|
if day and mon and yr and hr and min and sec then
|
||||||
|
-- find month
|
||||||
|
local month = 1
|
||||||
|
for i = 1, 12 do
|
||||||
|
if MONTHS[i] == mon then
|
||||||
|
month = i
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- convert to epoch time
|
||||||
|
return tz_offset(tz) + os.time( {
|
||||||
|
year = yr,
|
||||||
|
month = month,
|
||||||
|
day = day,
|
||||||
|
hour = hr,
|
||||||
|
min = min,
|
||||||
|
sec = sec
|
||||||
|
} )
|
||||||
|
end
|
||||||
|
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Convert the given unix epoch time to valid HTTP date string.
|
||||||
|
-- @param time Unix epoch time
|
||||||
|
-- @return String containing the formatted date
|
||||||
|
function to_http(time)
|
||||||
|
return os.date( "%a, %d %b %Y %H:%M:%S GMT", time )
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Compare two dates which can either be unix epoch times or HTTP date strings.
|
||||||
|
-- @param d1 The first date or epoch time to compare
|
||||||
|
-- @param d2 The first date or epoch time to compare
|
||||||
|
-- @return -1 - if d1 is lower then d2
|
||||||
|
-- @return 0 - if both dates are equal
|
||||||
|
-- @return 1 - if d1 is higher then d2
|
||||||
|
function compare(d1, d2)
|
||||||
|
|
||||||
|
if d1:match("[^0-9]") then d1 = to_unix(d1) end
|
||||||
|
if d2:match("[^0-9]") then d2 = to_unix(d2) end
|
||||||
|
|
||||||
|
if d1 == d2 then
|
||||||
|
return 0
|
||||||
|
elseif d1 < d2 then
|
||||||
|
return -1
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
end
|
99
Mi_Lua/luci/http/protocol/mime.lua
Normal file
99
Mi_Lua/luci/http/protocol/mime.lua
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
--[[
|
||||||
|
|
||||||
|
HTTP protocol implementation for LuCI - mime handling
|
||||||
|
(c) 2008 Freifunk Leipzig / Jo-Philipp Wich <xm@leipzig.freifunk.net>
|
||||||
|
|
||||||
|
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: mime.lua 5327 2009-09-11 01:55:10Z jow $
|
||||||
|
|
||||||
|
]]--
|
||||||
|
|
||||||
|
--- LuCI http protocol implementation - mime helper class.
|
||||||
|
-- This class provides functions to guess mime types from file extensions and
|
||||||
|
-- vice versa.
|
||||||
|
module("luci.http.protocol.mime", package.seeall)
|
||||||
|
|
||||||
|
require("luci.util")
|
||||||
|
|
||||||
|
--- MIME mapping table containg extension - mimetype relations.
|
||||||
|
-- @class table
|
||||||
|
MIME_TYPES = {
|
||||||
|
["txt"] = "text/plain";
|
||||||
|
["js"] = "text/javascript";
|
||||||
|
["css"] = "text/css";
|
||||||
|
["htm"] = "text/html";
|
||||||
|
["html"] = "text/html";
|
||||||
|
["patch"] = "text/x-patch";
|
||||||
|
["c"] = "text/x-csrc";
|
||||||
|
["h"] = "text/x-chdr";
|
||||||
|
["o"] = "text/x-object";
|
||||||
|
["ko"] = "text/x-object";
|
||||||
|
|
||||||
|
["bmp"] = "image/bmp";
|
||||||
|
["gif"] = "image/gif";
|
||||||
|
["png"] = "image/png";
|
||||||
|
["jpg"] = "image/jpeg";
|
||||||
|
["jpeg"] = "image/jpeg";
|
||||||
|
["svg"] = "image/svg+xml";
|
||||||
|
|
||||||
|
["zip"] = "application/zip";
|
||||||
|
["pdf"] = "application/pdf";
|
||||||
|
["xml"] = "application/xml";
|
||||||
|
["xsl"] = "application/xml";
|
||||||
|
["doc"] = "application/msword";
|
||||||
|
["ppt"] = "application/vnd.ms-powerpoint";
|
||||||
|
["xls"] = "application/vnd.ms-excel";
|
||||||
|
["odt"] = "application/vnd.oasis.opendocument.text";
|
||||||
|
["odp"] = "application/vnd.oasis.opendocument.presentation";
|
||||||
|
["pl"] = "application/x-perl";
|
||||||
|
["sh"] = "application/x-shellscript";
|
||||||
|
["php"] = "application/x-php";
|
||||||
|
["deb"] = "application/x-deb";
|
||||||
|
["iso"] = "application/x-cd-image";
|
||||||
|
["tgz"] = "application/x-compressed-tar";
|
||||||
|
|
||||||
|
["mp3"] = "audio/mpeg";
|
||||||
|
["ogg"] = "audio/x-vorbis+ogg";
|
||||||
|
["wav"] = "audio/x-wav";
|
||||||
|
|
||||||
|
["mpg"] = "video/mpeg";
|
||||||
|
["mpeg"] = "video/mpeg";
|
||||||
|
["avi"] = "video/x-msvideo";
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Extract extension from a filename and return corresponding mime-type or
|
||||||
|
-- "application/octet-stream" if the extension is unknown.
|
||||||
|
-- @param filename The filename for which the mime type is guessed
|
||||||
|
-- @return String containign the determined mime type
|
||||||
|
function to_mime(filename)
|
||||||
|
if type(filename) == "string" then
|
||||||
|
local ext = filename:match("[^%.]+$")
|
||||||
|
|
||||||
|
if ext and MIME_TYPES[ext:lower()] then
|
||||||
|
return MIME_TYPES[ext:lower()]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return "application/octet-stream"
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Return corresponding extension for a given mime type or nil if the
|
||||||
|
-- given mime-type is unknown.
|
||||||
|
-- @param mimetype The mimetype to retrieve the extension from
|
||||||
|
-- @return String with the extension or nil for unknown type
|
||||||
|
function to_ext(mimetype)
|
||||||
|
if type(mimetype) == "string" then
|
||||||
|
for ext, type in luci.util.kspairs( MIME_TYPES ) do
|
||||||
|
if type == mimetype then
|
||||||
|
return ext
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
104
Mi_Lua/luci/i18n.lua
Normal file
104
Mi_Lua/luci/i18n.lua
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
--[[
|
||||||
|
LuCI - Internationalisation
|
||||||
|
|
||||||
|
Description:
|
||||||
|
A very minimalistic but yet effective internationalisation module
|
||||||
|
|
||||||
|
FileId:
|
||||||
|
$Id: i18n.lua 9558 2012-12-18 13:58:22Z jow $
|
||||||
|
|
||||||
|
License:
|
||||||
|
Copyright 2008 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
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
]]--
|
||||||
|
|
||||||
|
--- LuCI translation library.
|
||||||
|
module("luci.i18n", package.seeall)
|
||||||
|
require("luci.util")
|
||||||
|
|
||||||
|
local tparser = require "luci.template.parser"
|
||||||
|
|
||||||
|
table = {}
|
||||||
|
i18ndir = luci.util.libpath() .. "/i18n/"
|
||||||
|
loaded = {}
|
||||||
|
context = luci.util.threadlocal()
|
||||||
|
default = "en"
|
||||||
|
|
||||||
|
--- Clear the translation table.
|
||||||
|
function clear()
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Load a translation and copy its data into the translation table.
|
||||||
|
-- @param file Language file
|
||||||
|
-- @param lang Two-letter language code
|
||||||
|
-- @param force Force reload even if already loaded (optional)
|
||||||
|
-- @return Success status
|
||||||
|
function load(file, lang, force)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Load a translation file using the default translation language.
|
||||||
|
-- Alternatively load the translation of the fallback language.
|
||||||
|
-- @param file Language file
|
||||||
|
-- @param force Force reload even if already loaded (optional)
|
||||||
|
function loadc(file, force)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the context default translation language.
|
||||||
|
-- @param lang Two-letter language code
|
||||||
|
function setlanguage(lang)
|
||||||
|
context.lang = lang:gsub("_", "-")
|
||||||
|
context.parent = (context.lang:match("^([a-z][a-z])_"))
|
||||||
|
if not tparser.load_catalog(context.lang, i18ndir) then
|
||||||
|
if context.parent then
|
||||||
|
tparser.load_catalog(context.parent, i18ndir)
|
||||||
|
return context.parent
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return context.lang
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Return the translated value for a specific translation key.
|
||||||
|
-- @param key Default translation text
|
||||||
|
-- @return Translated string
|
||||||
|
function translate(key)
|
||||||
|
return tparser.translate(key) or key
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Return the translated value for a specific translation key and use it as sprintf pattern.
|
||||||
|
-- @param key Default translation text
|
||||||
|
-- @param ... Format parameters
|
||||||
|
-- @return Translated and formatted string
|
||||||
|
function translatef(key, ...)
|
||||||
|
return tostring(translate(key)):format(...)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Return the translated value for a specific translation key
|
||||||
|
-- and ensure that the returned value is a Lua string value.
|
||||||
|
-- This is the same as calling <code>tostring(translate(...))</code>
|
||||||
|
-- @param key Default translation text
|
||||||
|
-- @return Translated string
|
||||||
|
function string(key)
|
||||||
|
return tostring(translate(key))
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Return the translated value for a specific translation key and use it as sprintf pattern.
|
||||||
|
-- Ensure that the returned value is a Lua string value.
|
||||||
|
-- This is the same as calling <code>tostring(translatef(...))</code>
|
||||||
|
-- @param key Default translation text
|
||||||
|
-- @param ... Format parameters
|
||||||
|
-- @return Translated and formatted string
|
||||||
|
function stringf(key, ...)
|
||||||
|
return tostring(translate(key)):format(...)
|
||||||
|
end
|
BIN
Mi_Lua/luci/i18n/base.en.lmo
Normal file
BIN
Mi_Lua/luci/i18n/base.en.lmo
Normal file
Binary file not shown.
BIN
Mi_Lua/luci/i18n/base.zh-cn.lmo
Normal file
BIN
Mi_Lua/luci/i18n/base.zh-cn.lmo
Normal file
Binary file not shown.
BIN
Mi_Lua/luci/i18n/firewall.ca.lmo
Normal file
BIN
Mi_Lua/luci/i18n/firewall.ca.lmo
Normal file
Binary file not shown.
BIN
Mi_Lua/luci/i18n/firewall.cs.lmo
Normal file
BIN
Mi_Lua/luci/i18n/firewall.cs.lmo
Normal file
Binary file not shown.
BIN
Mi_Lua/luci/i18n/firewall.de.lmo
Normal file
BIN
Mi_Lua/luci/i18n/firewall.de.lmo
Normal file
Binary file not shown.
BIN
Mi_Lua/luci/i18n/firewall.el.lmo
Normal file
BIN
Mi_Lua/luci/i18n/firewall.el.lmo
Normal file
Binary file not shown.
BIN
Mi_Lua/luci/i18n/firewall.es.lmo
Normal file
BIN
Mi_Lua/luci/i18n/firewall.es.lmo
Normal file
Binary file not shown.
BIN
Mi_Lua/luci/i18n/firewall.fr.lmo
Normal file
BIN
Mi_Lua/luci/i18n/firewall.fr.lmo
Normal file
Binary file not shown.
BIN
Mi_Lua/luci/i18n/firewall.hu.lmo
Normal file
BIN
Mi_Lua/luci/i18n/firewall.hu.lmo
Normal file
Binary file not shown.
BIN
Mi_Lua/luci/i18n/firewall.it.lmo
Normal file
BIN
Mi_Lua/luci/i18n/firewall.it.lmo
Normal file
Binary file not shown.
BIN
Mi_Lua/luci/i18n/firewall.ja.lmo
Normal file
BIN
Mi_Lua/luci/i18n/firewall.ja.lmo
Normal file
Binary file not shown.
BIN
Mi_Lua/luci/i18n/firewall.no.lmo
Normal file
BIN
Mi_Lua/luci/i18n/firewall.no.lmo
Normal file
Binary file not shown.
BIN
Mi_Lua/luci/i18n/firewall.pl.lmo
Normal file
BIN
Mi_Lua/luci/i18n/firewall.pl.lmo
Normal file
Binary file not shown.
BIN
Mi_Lua/luci/i18n/firewall.pt-br.lmo
Normal file
BIN
Mi_Lua/luci/i18n/firewall.pt-br.lmo
Normal file
Binary file not shown.
BIN
Mi_Lua/luci/i18n/firewall.pt.lmo
Normal file
BIN
Mi_Lua/luci/i18n/firewall.pt.lmo
Normal file
Binary file not shown.
BIN
Mi_Lua/luci/i18n/firewall.ro.lmo
Normal file
BIN
Mi_Lua/luci/i18n/firewall.ro.lmo
Normal file
Binary file not shown.
BIN
Mi_Lua/luci/i18n/firewall.ru.lmo
Normal file
BIN
Mi_Lua/luci/i18n/firewall.ru.lmo
Normal file
Binary file not shown.
BIN
Mi_Lua/luci/i18n/firewall.uk.lmo
Normal file
BIN
Mi_Lua/luci/i18n/firewall.uk.lmo
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user