diff --git a/Me_Lua/h10/MZLog.lua b/Me_Lua/h10/MZLog.lua new file mode 100644 index 0000000..c4a1177 --- /dev/null +++ b/Me_Lua/h10/MZLog.lua @@ -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 diff --git a/Me_Lua/h10/Posix.lua b/Me_Lua/h10/Posix.lua new file mode 100644 index 0000000..7536a2a --- /dev/null +++ b/Me_Lua/h10/Posix.lua @@ -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 diff --git a/Me_Lua/h10/cjson.so b/Me_Lua/h10/cjson.so new file mode 100644 index 0000000..cec1fb6 Binary files /dev/null and b/Me_Lua/h10/cjson.so differ diff --git a/Me_Lua/h10/lfs.so b/Me_Lua/h10/lfs.so new file mode 100755 index 0000000..1bc10df Binary files /dev/null and b/Me_Lua/h10/lfs.so differ diff --git a/Me_Lua/h10/lsqlite3.so b/Me_Lua/h10/lsqlite3.so new file mode 100644 index 0000000..8b8db6e Binary files /dev/null and b/Me_Lua/h10/lsqlite3.so differ diff --git a/Me_Lua/h10/ltn12.lua b/Me_Lua/h10/ltn12.lua new file mode 100644 index 0000000..1014de2 --- /dev/null +++ b/Me_Lua/h10/ltn12.lua @@ -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 diff --git a/Me_Lua/h10/luci/controller/admin/network.lua b/Me_Lua/h10/luci/controller/admin/network.lua new file mode 100644 index 0000000..5dee531 --- /dev/null +++ b/Me_Lua/h10/luci/controller/admin/network.lua @@ -0,0 +1,610 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2011 Jo-Philipp Wich + +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 + +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 + +function wifi_reconnect(wnet) + wifi_reconnect_shutdown(false, wnet) +end + +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 + diff --git a/Me_Lua/h10/luci/controller/api/index.lua b/Me_Lua/h10/luci/controller/api/index.lua new file mode 100644 index 0000000..37a0689 --- /dev/null +++ b/Me_Lua/h10/luci/controller/api/index.lua @@ -0,0 +1,308 @@ +module("luci.controller.api.index", package.seeall) + +local bfs = require "meizu.bfs" +local cjson = require "cjson" +local disk = require "meizu.disk" +local dlfs = require "meizu.dlfs" +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" +local btfs = require "meizu.btfs" + +b64dec = bfs.b64dec +batchfile_checklist = bfs.batchfile_checklist +batchfile_compare_upload = bfs.batchfile_compare_upload +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 +findInDir = bfs.findInDir +get_device_SN = bfs.get_device_SN +get_device_version = bfs.get_device_version +get_https_data = bfs.get_https_data +getFilesList = bfs.getFilesList +factory_reset = bfs.factory_reset +rts_get_access_token = bfs.rts_get_access_token +set_passwd = bfs.set_passwd +silent_upgrade = bfs.silent_upgrade + +nw_get_disk_info = disk.nw_get_disk_info +disk_formatting = disk.disk_formatting + +sip = sipfs.sip +pysip = sipfs.pysip +upload_router_log = sipfs.upload_router_log + +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_smbswitch = nwfs.nw_get_smbswitch +nw_get_wifi_settings = nwfs.nw_get_wifi_settings +nw_set_device_name = nwfs.nw_set_device_name +nw_set_disk_access = nwfs.nw_set_disk_access +nw_set_wan_switch = nwfs.nw_set_wan_switch +nw_set_wan_type = nwfs.nw_set_wan_type +nw_set_smbswitch = nwfs.nw_set_smbswitch +nw_wifi_settings = nwfs.nw_wifi_settings +nw_get_tx_power_mode = nwfs.nw_get_tx_power_mode +nw_set_tx_power_mode = nwfs.nw_set_tx_power_mode +nw_get_wireless_channel = nwfs.nw_get_wireless_channel +nw_set_wireless_channel = nwfs.nw_set_wireless_channel + +get_connect_info = nwfs.get_connect_info +get_net_device = nwfs.get_net_device +real_time_net_speed = nwfs.real_time_net_speed + +nw_scan_ble_switch = btfs.nw_scan_ble_switch +nw_get_ble_device_list = btfs.nw_get_ble_device_list +nw_add_ble_mesh_device = btfs.nw_add_ble_mesh_device +nw_get_ble_device_status = btfs.nw_get_ble_device_status +nw_get_mesh_device_list = btfs.nw_get_mesh_device_list +nw_remove_ble_from_mesh = btfs.nw_remove_ble_from_mesh +nw_dismiss_mesh = btfs.nw_dismiss_mesh +nw_set_mesh_device_attr = btfs.nw_set_mesh_device_attr +nw_reboot_mesh_device = btfs.nw_reboot_mesh_device +nw_unmesh_all_device = btfs.nw_unmesh_all_device +nw_set_mesh_device_timer = btfs.nw_set_mesh_device_timer +nw_del_mesh_device_timer = btfs.nw_del_mesh_device_timer +nw_set_mesh_network_pwd = btfs.nw_set_mesh_network_pwd +nw_set_lamp_brightness = btfs.nw_set_lamp_brightness + +check_upgrade = upgdfs.check_upgrade +do_upgrade = upgdfs.do_upgrade +local_upgrade = upgdfs.local_upgrade + +nw_download_task_operate = dlfs.nw_download_task_operate +nw_get_active_list = dlfs.nw_get_active_list +nw_get_history_list = dlfs.nw_get_history_list +--nw_get_pause_list = dlfs.nw_get_pause_list +nw_thunder_get_bind_code = dlfs.nw_thunder_get_bind_code + +nw_download_task_start = dlfs.nw_download_task_start + +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", "getUserAccessToken"}, call("get_user_access_token"), nil, nil) + --page.leaf = true + page = entry({"api", "bindRouter"}, call("bind_router"), nil, nil) + page.leaf = true + --page = entry({"api", "unbindRouter"}, call("unbind_router"), nil, nil) + --page.leaf = true + --page = entry({"api", "getDeviceAccessToken"}, call("rts_get_access_token"), 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", "getconnectinfo"}, call("get_connect_info"), 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", "setDiskAccess"}, call("nw_set_disk_access"), 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", "gettxpowermode"}, call("nw_get_tx_power_mode"), nil) + page.leaf = true + page = entry({"api", "settxpowermode"}, call("nw_set_tx_power_mode"), 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", "diskinfo"}, call("nw_get_disk_info"), nil) + page.leaf = true + page = entry({"api", "diskformat"}, call("disk_formatting"), nil, 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", "downloadstart"}, call("nw_download_task_start"), nil, nil) + page.leaf = true + page = entry({"api", "getActiveList"}, call("nw_get_active_list"), nil, nil) + page.leaf = true + page = entry({"api", "getHistoryList"}, call("nw_get_history_list"), nil, nil) + page.leaf = true + page = entry({"api", "operateTask"}, call("nw_download_task_operate"), nil, nil) + page.leaf = true + page = entry({"api", "getPauseList"}, call("nw_get_pause_list"), nil, nil) + page.leaf = true + page = entry({"api", "thunder_get_bind_code"}, call("nw_thunder_get_bind_code"), nil, nil) + page.leaf = true + + page = entry({"api", "batchFileCompareUpload"}, call("batchfile_compare_upload"), nil, nil) + page.leaf = true + page = entry({"api", "batchFileCheckList"}, call("batchfile_checklist"), nil, nil) + page.leaf = true + page = entry({"api", "getFilesList"}, call("getFilesList"), nil, nil) + page.leaf = true + --page = entry({"api", "setPPPoE"}, call("set_pppoe"), nil) + --page.leaf = true + + page = entry({"api", "checkupgrade"}, call("nw_check_upgrade"), nil) + page.leaf = true + page = entry({"api", "doupgrade"}, call("nw_do_upgrade"), nil) + page.leaf = true + + page = entry({"api", "setsmbsingleswitch"}, call("setsmbsingleswitch"),nil) + page.leaf = true + page = entry({"api", "setsmbswitch"}, call("nw_set_smbswitch"), nil) + page.leaf = true + page = entry({"api", "getsmbsingleswitch"}, call("getsmbsingleswitch"),nil) + page.leaf = true + page = entry({"api", "getsmbswitch"}, call("nw_get_smbswitch"), 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) +end + +function nw_do_upgrade() + local ret = {} + luci.http.status(200, "upgrading....") + ret["code"] = 2004 + ret["result"] = "upgrading...." + luci.http.write(data_to_json(ret)) + 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 setsmbsingleswitch() + --local mac = luci.http.formvalue("mac") + --generate a white/black list to store this mac. + --if you want a mac not rw hdd, then write his mac into deny list. + --if you want a mac rw hdd, write his mac into allow list. + --modify smb.conf to ban this user's access. + --restart samba service +end + +function setsmbswitch() + local result = {} + local code = false + local onoff = luci.http.formvalue("smbswitch") + if (tonumber)(onoff) == 1 then + luci.sys.init.enable("samba") + exec_cmd_in_sh("sleep 1") + if luci.sys.init.enabled("samba") == true then + code = true + else + code = false + end + elseif (tonumber)(onoff) == 0 then + luci.sys.init.disable("samba") + exec_cmd_in_sh("sleep 1") + if luci.sys.init.enabled("samba") == true then + code = false + else + code = true + end + end + + result["result"] = code + luci.http.write_json(result) + +end + +function getsmbsingleswitch() +-- +end + +function getsmbswitch() + local smbswitch = {} + local code = false + code = luci.sys.init.enabled("samba") + smbswitch["smbswitch"] = code + luci.http.write_json(smbswitch) +end + +function nw_exec_reboot() + local ret = {} + ret["result"] = true + luci.http.write_json(ret) + exec_reboot() +end diff --git a/Me_Lua/h10/luci/controller/bs/index.lua b/Me_Lua/h10/luci/controller/bs/index.lua new file mode 100644 index 0000000..bb93e3e --- /dev/null +++ b/Me_Lua/h10/luci/controller/bs/index.lua @@ -0,0 +1,149 @@ +module("luci.controller.bs.index", package.seeall) + + +local arpmon = require "meizu.arpmon" +local bfs = require "meizu.bfs" +local btfs = require "meizu.btfs" + +nw_get_bluetooth_info = btfs.nw_get_bluetooth_info +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 + + page = entry({"bs", "getToken"}, call("get_token"), nil) + page.leaf = true + page = entry({"bs", "sysauth"}, call("sysauth"), nil) + page.leaf = true + + page = entry({"bs", "getBluetoothInfo"}, call("nw_get_bluetooth_info"), 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 httpHandler = require("socket.http") + local usernm = luci.http.formvalue("username") + local passwd = luci.http.formvalue("password") + if usernm == nil and passwd == nil then + local sauth = require "luci.sauth" + local token = sauth.noAuthGetToken() + if token then + luci.http.write_json(token) + end + else + local ret = luci.sys.user.checkpasswd(usernm, passwd) + if ret == true then + local sauth = require "luci.sauth" + local token = sauth.noAuthGetToken() + if token then + luci.http.write_json(token) + end + end + 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 + +function sysauth() + local res = {} + local usernm = luci.http.formvalue("username") + local passwd = luci.http.formvalue("password") + res["result"] = luci.sys.user.checkpasswd(usernm, passwd) + luci.http.write_json(res) +end + +function get_token() + local res = {} + local sauth = require "luci.sauth" + local sess = luci.http.getcookie("sysauth") + sess = sess and sess:match("^[a-f0-9]*$") + local sdat = sauth.read(sess) + res["sysauth"] = sess + res["token"] = sdat.token + luci.http.write_json(res) +end diff --git a/Me_Lua/h10/luci/dispatcher.lua b/Me_Lua/h10/luci/dispatcher.lua new file mode 100644 index 0000000..a8b7fd1 --- /dev/null +++ b/Me_Lua/h10/luci/dispatcher.lua @@ -0,0 +1,965 @@ +--[[ +LuCI - Dispatcher + +Description: +The request dispatcher and module dispatcher generators + +FileId: +$Id$ + +License: +Copyright 2008 Steven Barth + +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 diff --git a/Me_Lua/h10/luci/model/network.lua b/Me_Lua/h10/luci/model/network.lua new file mode 100644 index 0000000..41b0e99 --- /dev/null +++ b/Me_Lua/h10/luci/model/network.lua @@ -0,0 +1,1632 @@ +--[[ +LuCI - Network model + +Copyright 2009-2010 Jo-Philipp Wich + +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 type, next, pairs, ipairs, loadfile, table + = type, next, pairs, ipairs, loadfile, table + +local tonumber, tostring, math = tonumber, tostring, math + +local require = require + +local bus = require "ubus" +local nxo = require "nixio" +local nfs = require "nixio.fs" +local ipc = require "luci.ip" +local sys = require "luci.sys" +local utl = require "luci.util" +local dsp = require "luci.dispatcher" +local uci = require "luci.model.uci" +local lng = require "luci.i18n" + +module "luci.model.network" + + +IFACE_PATTERNS_VIRTUAL = { } +IFACE_PATTERNS_IGNORE = { "^wmaster%d", "^wifi%d", "^hwsim%d", "^imq%d", "^ifb%d", "^mon%.wlan%d", "^sit%d", "^gre%d", "^lo$" } +IFACE_PATTERNS_WIRELESS = { "^wlan%d", "^wl%d", "^ath%d", "^%w+%.network%d" } + + +protocol = utl.class() + +local _protocols = { } + +local _interfaces, _bridge, _switch, _tunnel +local _ubus, _ubusnetcache, _ubusdevcache, _ubuswificache +local _uci_real, _uci_state + +function _filter(c, s, o, r) + local val = _uci_real:get(c, s, o) + if val then + local l = { } + if type(val) == "string" then + for val in val:gmatch("%S+") do + if val ~= r then + l[#l+1] = val + end + end + if #l > 0 then + _uci_real:set(c, s, o, table.concat(l, " ")) + else + _uci_real:delete(c, s, o) + end + elseif type(val) == "table" then + for _, val in ipairs(val) do + if val ~= r then + l[#l+1] = val + end + end + if #l > 0 then + _uci_real:set(c, s, o, l) + else + _uci_real:delete(c, s, o) + end + end + end +end + +function _append(c, s, o, a) + local val = _uci_real:get(c, s, o) or "" + if type(val) == "string" then + local l = { } + for val in val:gmatch("%S+") do + if val ~= a then + l[#l+1] = val + end + end + l[#l+1] = a + _uci_real:set(c, s, o, table.concat(l, " ")) + elseif type(val) == "table" then + local l = { } + for _, val in ipairs(val) do + if val ~= a then + l[#l+1] = val + end + end + l[#l+1] = a + _uci_real:set(c, s, o, l) + end +end + +function _stror(s1, s2) + if not s1 or #s1 == 0 then + return s2 and #s2 > 0 and s2 + else + return s1 + end +end + +function _get(c, s, o) + return _uci_real:get(c, s, o) +end + +function _set(c, s, o, v) + if v ~= nil then + if type(v) == "boolean" then v = v and "1" or "0" end + return _uci_real:set(c, s, o, v) + else + return _uci_real:delete(c, s, o) + end +end + +function _wifi_iface(x) + local _, p + for _, p in ipairs(IFACE_PATTERNS_WIRELESS) do + if x:match(p) then + return true + end + end + return false +end + +function _wifi_state(key, val, field) + if not next(_ubuswificache) then + _ubuswificache = _ubus:call("network.wireless", "status", {}) or {} + end + + local radio, radiostate + for radio, radiostate in pairs(_ubuswificache) do + local ifc, ifcstate + for ifc, ifcstate in pairs(radiostate.interfaces) do + if ifcstate[key] == val then + return ifcstate[field] + end + end + end +end + +function _wifi_lookup(ifn) + -- got a radio#.network# pseudo iface, locate the corresponding section + local radio, ifnidx = ifn:match("^(%w+)%.network(%d+)$") + if radio and ifnidx then + local sid = nil + local num = 0 + + ifnidx = tonumber(ifnidx) + _uci_real:foreach("wireless", "wifi-iface", + function(s) + if s.device == radio then + num = num + 1 + if num == ifnidx then + sid = s['.name'] + return false + end + end + end) + + return sid + + -- looks like wifi, try to locate the section via state vars + elseif _wifi_iface(ifn) then + local sid = _wifi_state("ifname", ifn, "section") + if not sid then + _uci_state:foreach("wireless", "wifi-iface", + function(s) + if s.ifname == ifn then + sid = s['.name'] + return false + end + end) + end + + return sid + end +end + +function _iface_virtual(x) + local _, p + for _, p in ipairs(IFACE_PATTERNS_VIRTUAL) do + if x:match(p) then + return true + end + end + return false +end + +function _iface_ignore(x) + local _, p + for _, p in ipairs(IFACE_PATTERNS_IGNORE) do + if x:match(p) then + return true + end + end + return _iface_virtual(x) +end + + +function init(cursor) + _uci_real = cursor or _uci_real or uci.cursor() + _uci_state = _uci_real:substate() + + _interfaces = { } + _bridge = { } + _switch = { } + _tunnel = { } + + _ubus = bus.connect() + _ubusnetcache = { } + _ubusdevcache = { } + _ubuswificache = { } + + -- read interface information + local n, i + for n, i in ipairs(nxo.getifaddrs()) do + local name = i.name:match("[^:]+") + local prnt = name:match("^([^%.]+)%.") + + if _iface_virtual(name) then + _tunnel[name] = true + end + + if _tunnel[name] or not _iface_ignore(name) then + _interfaces[name] = _interfaces[name] or { + idx = i.ifindex or n, + name = name, + rawname = i.name, + flags = { }, + ipaddrs = { }, + ip6addrs = { } + } + + if prnt then + _switch[name] = true + _switch[prnt] = true + end + + if i.family == "packet" then + _interfaces[name].flags = i.flags + _interfaces[name].stats = i.data + _interfaces[name].macaddr = i.addr + elseif i.family == "inet" then + _interfaces[name].ipaddrs[#_interfaces[name].ipaddrs+1] = ipc.IPv4(i.addr, i.netmask) + elseif i.family == "inet6" then + _interfaces[name].ip6addrs[#_interfaces[name].ip6addrs+1] = ipc.IPv6(i.addr, i.netmask) + end + end + end + + -- read bridge informaton + local b, l + for l in utl.execi("brctl show") do + if not l:match("STP") then + local r = utl.split(l, "%s+", nil, true) + if #r == 4 then + b = { + name = r[1], + id = r[2], + stp = r[3] == "yes", + ifnames = { _interfaces[r[4]] } + } + if b.ifnames[1] then + b.ifnames[1].bridge = b + end + _bridge[r[1]] = b + elseif b then + b.ifnames[#b.ifnames+1] = _interfaces[r[2]] + b.ifnames[#b.ifnames].bridge = b + end + end + end + + return _M +end + +function save(self, ...) + _uci_real:save(...) + _uci_real:load(...) +end + +function commit(self, ...) + _uci_real:commit(...) + _uci_real:load(...) +end + +function ifnameof(self, x) + if utl.instanceof(x, interface) then + return x:name() + elseif utl.instanceof(x, protocol) then + return x:ifname() + elseif type(x) == "string" then + return x:match("^[^:]+") + end +end + +function get_protocol(self, protoname, netname) + local v = _protocols[protoname] + if v then + return v(netname or "__dummy__") + end +end + +function get_protocols(self) + local p = { } + local _, v + for _, v in ipairs(_protocols) do + p[#p+1] = v("__dummy__") + end + return p +end + +function register_protocol(self, protoname) + local proto = utl.class(protocol) + + function proto.__init__(self, name) + self.sid = name + end + + function proto.proto(self) + return protoname + end + + _protocols[#_protocols+1] = proto + _protocols[protoname] = proto + + return proto +end + +function register_pattern_virtual(self, pat) + IFACE_PATTERNS_VIRTUAL[#IFACE_PATTERNS_VIRTUAL+1] = pat +end + + +function has_ipv6(self) + return nfs.access("/proc/net/ipv6_route") +end + +function add_network(self, n, options) + local oldnet = self:get_network(n) + if n and #n > 0 and n:match("^[a-zA-Z0-9_]+$") and not oldnet then + if _uci_real:section("network", "interface", n, options) then + return network(n) + end + elseif oldnet and oldnet:is_empty() then + if options then + local k, v + for k, v in pairs(options) do + oldnet:set(k, v) + end + end + return oldnet + end +end + +function get_network(self, n) + if n and _uci_real:get("network", n) == "interface" then + return network(n) + end +end + +function get_networks(self) + local nets = { } + local nls = { } + + _uci_real:foreach("network", "interface", + function(s) + nls[s['.name']] = network(s['.name']) + end) + + local n + for n in utl.kspairs(nls) do + nets[#nets+1] = nls[n] + end + + return nets +end + +function del_network(self, n) + local r = _uci_real:delete("network", n) + if r then + _uci_real:delete_all("network", "alias", + function(s) return (s.interface == n) end) + + _uci_real:delete_all("network", "route", + function(s) return (s.interface == n) end) + + _uci_real:delete_all("network", "route6", + function(s) return (s.interface == n) end) + + _uci_real:foreach("wireless", "wifi-iface", + function(s) + local net + local rest = { } + for net in utl.imatch(s.network) do + if net ~= n then + rest[#rest+1] = net + end + end + if #rest > 0 then + _uci_real:set("wireless", s['.name'], "network", + table.concat(rest, " ")) + else + _uci_real:delete("wireless", s['.name'], "network") + end + end) + end + return r +end + +function rename_network(self, old, new) + local r + if new and #new > 0 and new:match("^[a-zA-Z0-9_]+$") and not self:get_network(new) then + r = _uci_real:section("network", "interface", new, _uci_real:get_all("network", old)) + + if r then + _uci_real:foreach("network", "alias", + function(s) + if s.interface == old then + _uci_real:set("network", s['.name'], "interface", new) + end + end) + + _uci_real:foreach("network", "route", + function(s) + if s.interface == old then + _uci_real:set("network", s['.name'], "interface", new) + end + end) + + _uci_real:foreach("network", "route6", + function(s) + if s.interface == old then + _uci_real:set("network", s['.name'], "interface", new) + end + end) + + _uci_real:foreach("wireless", "wifi-iface", + function(s) + local net + local list = { } + for net in utl.imatch(s.network) do + if net == old then + list[#list+1] = new + else + list[#list+1] = net + end + end + if #list > 0 then + _uci_real:set("wireless", s['.name'], "network", + table.concat(list, " ")) + end + end) + + _uci_real:delete("network", old) + end + end + return r or false +end + +function get_interface(self, i) + if _interfaces[i] or _wifi_iface(i) then + return interface(i) + else + local ifc + local num = { } + _uci_real:foreach("wireless", "wifi-iface", + function(s) + if s.device then + num[s.device] = num[s.device] and num[s.device] + 1 or 1 + if s['.name'] == i then + ifc = interface( + "%s.network%d" %{s.device, num[s.device] }) + return false + end + end + end) + return ifc + end +end + +function get_interfaces(self) + local iface + local ifaces = { } + local seen = { } + local nfs = { } + local baseof = { } + + -- find normal interfaces + _uci_real:foreach("network", "interface", + function(s) + for iface in utl.imatch(s.ifname) do + if not _iface_ignore(iface) and not _wifi_iface(iface) then + seen[iface] = true + nfs[iface] = interface(iface) + end + end + end) + + for iface in utl.kspairs(_interfaces) do + if not (seen[iface] or _iface_ignore(iface) or _wifi_iface(iface)) then + nfs[iface] = interface(iface) + end + end + + -- find vlan interfaces + _uci_real:foreach("network", "switch_vlan", + function(s) + if not s.device then + return + end + + local base = baseof[s.device] + if not base then + if not s.device:match("^eth%d") then + local l + for l in utl.execi("swconfig dev %q help 2>/dev/null" % s.device) do + if not base then + base = l:match("^%w+: (%w+)") + end + end + if not base or not base:match("^eth%d") then + base = "eth0" + end + else + base = s.device + end + baseof[s.device] = base + end + + local vid = tonumber(s.vid or s.vlan) + if vid ~= nil and vid >= 0 and vid <= 4095 then + local iface = "%s.%d" %{ base, vid } + if not seen[iface] then + seen[iface] = true + nfs[iface] = interface(iface) + end + end + end) + + for iface in utl.kspairs(nfs) do + ifaces[#ifaces+1] = nfs[iface] + end + + -- find wifi interfaces + local num = { } + local wfs = { } + _uci_real:foreach("wireless", "wifi-iface", + function(s) + if s.device then + num[s.device] = num[s.device] and num[s.device] + 1 or 1 + local i = "%s.network%d" %{ s.device, num[s.device] } + wfs[i] = interface(i) + end + end) + + for iface in utl.kspairs(wfs) do + ifaces[#ifaces+1] = wfs[iface] + end + + return ifaces +end + +function ignore_interface(self, x) + return _iface_ignore(x) +end + +function get_wifidev(self, dev) + if _uci_real:get("wireless", dev) == "wifi-device" then + return wifidev(dev) + end +end + +function get_wifidevs(self) + local devs = { } + local wfd = { } + + _uci_real:foreach("wireless", "wifi-device", + function(s) wfd[#wfd+1] = s['.name'] end) + + local dev + for _, dev in utl.vspairs(wfd) do + devs[#devs+1] = wifidev(dev) + end + + return devs +end + +function get_wifinet(self, net) + local wnet = _wifi_lookup(net) + if wnet then + return wifinet(wnet) + end +end + +function add_wifinet(self, net, options) + if type(options) == "table" and options.device and + _uci_real:get("wireless", options.device) == "wifi-device" + then + local wnet = _uci_real:section("wireless", "wifi-iface", nil, options) + return wifinet(wnet) + end +end + +function del_wifinet(self, net) + local wnet = _wifi_lookup(net) + if wnet then + _uci_real:delete("wireless", wnet) + return true + end + return false +end + +function get_status_by_route(self, addr, mask) + local _, object + for _, object in ipairs(_ubus:objects()) do + local net = object:match("^network%.interface%.(.+)") + if net then + local s = _ubus:call(object, "status", {}) + if s and s.route then + local rt + for _, rt in ipairs(s.route) do + if not rt.table and rt.target == addr and rt.mask == mask then + return net, s + end + end + end + end + end +end + +function get_status_by_address(self, addr) + local _, object + for _, object in ipairs(_ubus:objects()) do + local net = object:match("^network%.interface%.(.+)") + if net then + local s = _ubus:call(object, "status", {}) + if s and s['ipv4-address'] then + local a + for _, a in ipairs(s['ipv4-address']) do + if a.address == addr then + return net, s + end + end + end + if s and s['ipv6-address'] then + local a + for _, a in ipairs(s['ipv6-address']) do + if a.address == addr then + return net, s + end + end + end + end + end +end + +function get_wannet(self) + local net = self:get_status_by_route("0.0.0.0", 0) + return net and network(net) +end + +function get_wandev(self) + local _, stat = self:get_status_by_route("0.0.0.0", 0) + return stat and interface(stat.l3_device or stat.device) +end + +function get_wan6net(self) + local net = self:get_status_by_route("::", 0) + return net and network(net) +end + +function get_wan6dev(self) + local _, stat = self:get_status_by_route("::", 0) + return stat and interface(stat.l3_device or stat.device) +end + + +function network(name, proto) + if name then + local p = proto or _uci_real:get("network", name, "proto") + local c = p and _protocols[p] or protocol + return c(name) + end +end + +function protocol.__init__(self, name) + self.sid = name +end + +function protocol._get(self, opt) + local v = _uci_real:get("network", self.sid, opt) + if type(v) == "table" then + return table.concat(v, " ") + end + return v or "" +end + +function protocol._ubus(self, field) + if not _ubusnetcache[self.sid] then + _ubusnetcache[self.sid] = _ubus:call("network.interface.%s" % self.sid, + "status", { }) + end + if _ubusnetcache[self.sid] and field then + return _ubusnetcache[self.sid][field] + end + return _ubusnetcache[self.sid] +end + +function protocol.get(self, opt) + return _get("network", self.sid, opt) +end + +function protocol.set(self, opt, val) + return _set("network", self.sid, opt, val) +end + +function protocol.ifname(self) + local ifname + if self:is_floating() then + ifname = self:_ubus("l3_device") + else + ifname = self:_ubus("device") + end + if not ifname then + local num = { } + _uci_real:foreach("wireless", "wifi-iface", + function(s) + if s.device then + num[s.device] = num[s.device] + and num[s.device] + 1 or 1 + + local net + for net in utl.imatch(s.network) do + if net == self.sid then + ifname = "%s.network%d" %{ s.device, num[s.device] } + return false + end + end + end + end) + end + return ifname +end + +function protocol.proto(self) + return "none" +end + +function protocol.get_i18n(self) + local p = self:proto() + if p == "none" then + return lng.translate("Unmanaged") + elseif p == "static" then + return lng.translate("Static address") + elseif p == "dhcp" then + return lng.translate("DHCP client") + else + return lng.translate("Unknown") + end +end + +function protocol.type(self) + return self:_get("type") +end + +function protocol.name(self) + return self.sid +end + +function protocol.uptime(self) + return self:_ubus("uptime") or 0 +end + +function protocol.expires(self) + local a = tonumber(_uci_state:get("network", self.sid, "lease_acquired")) + local l = tonumber(_uci_state:get("network", self.sid, "lease_lifetime")) + if a and l then + l = l - (nxo.sysinfo().uptime - a) + return l > 0 and l or 0 + end + return -1 +end + +function protocol.metric(self) + return tonumber(_uci_state:get("network", self.sid, "metric")) or 0 +end + +function protocol.ipaddr(self) + local addrs = self:_ubus("ipv4-address") + return addrs and #addrs > 0 and addrs[1].address +end + +function protocol.netmask(self) + local addrs = self:_ubus("ipv4-address") + return addrs and #addrs > 0 and + ipc.IPv4("0.0.0.0/%d" % addrs[1].mask):mask():string() +end + +function protocol.gwaddr(self) + local _, route + for _, route in ipairs(self:_ubus("route") or { }) do + if route.target == "0.0.0.0" and route.mask == 0 then + return route.nexthop + end + end +end + +function protocol.dnsaddrs(self) + local dns = { } + local _, addr + for _, addr in ipairs(self:_ubus("dns-server") or { }) do + if not addr:match(":") then + dns[#dns+1] = addr + end + end + return dns +end + +function protocol.ip6addr(self) + local addrs = self:_ubus("ipv6-address") + if addrs and #addrs > 0 then + return "%s/%d" %{ addrs[1].address, addrs[1].mask } + else + addrs = self:_ubus("ipv6-prefix-assignment") + if addrs and #addrs > 0 then + return "%s/%d" %{ addrs[1].address, addrs[1].mask } + end + end +end + +function protocol.gw6addr(self) + local _, route + for _, route in ipairs(self:_ubus("route") or { }) do + if route.target == "::" and route.mask == 0 then + return ipc.IPv6(route.nexthop):string() + end + end +end + +function protocol.dns6addrs(self) + local dns = { } + local _, addr + for _, addr in ipairs(self:_ubus("dns-server") or { }) do + if addr:match(":") then + dns[#dns+1] = addr + end + end + return dns +end + +function protocol.is_bridge(self) + return (not self:is_virtual() and self:type() == "bridge") +end + +function protocol.opkg_package(self) + return nil +end + +function protocol.is_installed(self) + return true +end + +function protocol.is_virtual(self) + return false +end + +function protocol.is_floating(self) + return false +end + +function protocol.is_empty(self) + if self:is_floating() then + return false + else + local rv = true + + if (self:_get("ifname") or ""):match("%S+") then + rv = false + end + + _uci_real:foreach("wireless", "wifi-iface", + function(s) + local n + for n in utl.imatch(s.network) do + if n == self.sid then + rv = false + return false + end + end + end) + + return rv + end +end + +function protocol.add_interface(self, ifname) + ifname = _M:ifnameof(ifname) + if ifname and not self:is_floating() then + -- if its a wifi interface, change its network option + local wif = _wifi_lookup(ifname) + if wif then + _append("wireless", wif, "network", self.sid) + + -- add iface to our iface list + else + _append("network", self.sid, "ifname", ifname) + end + end +end + +function protocol.del_interface(self, ifname) + ifname = _M:ifnameof(ifname) + if ifname and not self:is_floating() then + -- if its a wireless interface, clear its network option + local wif = _wifi_lookup(ifname) + if wif then _filter("wireless", wif, "network", self.sid) end + + -- remove the interface + _filter("network", self.sid, "ifname", ifname) + end +end + +function protocol.get_interface(self) + if self:is_virtual() then + _tunnel[self:proto() .. "-" .. self.sid] = true + return interface(self:proto() .. "-" .. self.sid, self) + elseif self:is_bridge() then + _bridge["br-" .. self.sid] = true + return interface("br-" .. self.sid, self) + else + local ifn = nil + local num = { } + for ifn in utl.imatch(_uci_real:get("network", self.sid, "ifname")) do + ifn = ifn:match("^[^:/]+") + return ifn and interface(ifn, self) + end + ifn = nil + _uci_real:foreach("wireless", "wifi-iface", + function(s) + if s.device then + num[s.device] = num[s.device] and num[s.device] + 1 or 1 + + local net + for net in utl.imatch(s.network) do + if net == self.sid then + ifn = "%s.network%d" %{ s.device, num[s.device] } + return false + end + end + end + end) + return ifn and interface(ifn, self) + end +end + +function protocol.get_interfaces(self) + if self:is_bridge() or (self:is_virtual() and not self:is_floating()) then + local ifaces = { } + + local ifn + local nfs = { } + for ifn in utl.imatch(self:get("ifname")) do + ifn = ifn:match("^[^:/]+") + nfs[ifn] = interface(ifn, self) + end + + for ifn in utl.kspairs(nfs) do + ifaces[#ifaces+1] = nfs[ifn] + end + + local num = { } + local wfs = { } + _uci_real:foreach("wireless", "wifi-iface", + function(s) + if s.device then + num[s.device] = num[s.device] and num[s.device] + 1 or 1 + + local net + for net in utl.imatch(s.network) do + if net == self.sid then + ifn = "%s.network%d" %{ s.device, num[s.device] } + wfs[ifn] = interface(ifn, self) + end + end + end + end) + + for ifn in utl.kspairs(wfs) do + ifaces[#ifaces+1] = wfs[ifn] + end + + return ifaces + end +end + +function protocol.contains_interface(self, ifname) + ifname = _M:ifnameof(ifname) + if not ifname then + return false + elseif self:is_virtual() and self:proto() .. "-" .. self.sid == ifname then + return true + elseif self:is_bridge() and "br-" .. self.sid == ifname then + return true + else + local ifn + for ifn in utl.imatch(self:get("ifname")) do + ifn = ifn:match("[^:]+") + if ifn == ifname then + return true + end + end + + local wif = _wifi_lookup(ifname) + if wif then + local n + for n in utl.imatch(_uci_real:get("wireless", wif, "network")) do + if n == self.sid then + return true + end + end + end + end + + return false +end + +function protocol.adminlink(self) + return dsp.build_url("admin", "network", "network", self.sid) +end + +function protocol.get_option_value(self,name) + return self:_get(name) +end + +function protocol.status(self) + local iface = uci.cursor_state():get_all("network", self.sid) + local proto = iface["proto"] + local ifname = iface["ifname"] + local device = iface["device"] + local up = tonumber(iface["up"]) + if proto == "pppoe" then + if device == nil then + return "down" + end + if up == nil then + return "connection" + end + if up == 1 then + return "up" + end + elseif proto == "3g" then + if device ~= ifname and up==nil then + return "down" + end + if device == ifname and up == nil then + return "connection" + end + if up == 1 then + return "up" + end + elseif proto == "static" then + if up == nil then + return "down" + end + if up == 1 then + return "up" + end + elseif proto == "dhcp" then + if up == nil then + return "down" + end + if up == 1 then + return "up" + end + end + return "unkown" +end + +interface = utl.class() + +function interface.__init__(self, ifname, network) + local wif = _wifi_lookup(ifname) + if wif then + self.wif = wifinet(wif) + self.ifname = _wifi_state("section", wif, "ifname") + end + + self.ifname = self.ifname or ifname + self.dev = _interfaces[self.ifname] + self.network = network +end + +function interface._ubus(self, field) + if not _ubusdevcache[self.ifname] then + _ubusdevcache[self.ifname] = _ubus:call("network.device", "status", + { name = self.ifname }) + end + if _ubusdevcache[self.ifname] and field then + return _ubusdevcache[self.ifname][field] + end + return _ubusdevcache[self.ifname] +end + +function interface.name(self) + return self.wif and self.wif:ifname() or self.ifname +end + +function interface.mac(self) + return (self:_ubus("macaddr") or "00:00:00:00:00:00"):upper() +end + +function interface.ipaddrs(self) + return self.dev and self.dev.ipaddrs or { } +end + +function interface.ip6addrs(self) + return self.dev and self.dev.ip6addrs or { } +end + +function interface.type(self) + if self.wif or _wifi_iface(self.ifname) then + return "wifi" + elseif _bridge[self.ifname] then + return "bridge" + elseif _tunnel[self.ifname] then + return "tunnel" + elseif self.ifname:match("%.") then + return "vlan" + elseif _switch[self.ifname] then + return "switch" + else + return "ethernet" + end +end + +function interface.shortname(self) + if self.wif then + return "%s %q" %{ + self.wif:active_mode(), + self.wif:active_ssid() or self.wif:active_bssid() + } + else + return self.ifname + end +end + +function interface.get_i18n(self) + if self.wif then + return "%s: %s %q" %{ + lng.translate("Wireless Network"), + self.wif:active_mode(), + self.wif:active_ssid() or self.wif:active_bssid() + } + else + return "%s: %q" %{ self:get_type_i18n(), self:name() } + end +end + +function interface.get_type_i18n(self) + local x = self:type() + if x == "wifi" then + return lng.translate("Wireless Adapter") + elseif x == "bridge" then + return lng.translate("Bridge") + elseif x == "switch" then + return lng.translate("Ethernet Switch") + elseif x == "vlan" then + return lng.translate("VLAN Interface") + elseif x == "tunnel" then + return lng.translate("Tunnel Interface") + else + return lng.translate("Ethernet Adapter") + end +end + +function interface.adminlink(self) + if self.wif then + return self.wif:adminlink() + end +end + +function interface.ports(self) + local members = self:_ubus("bridge-members") + if members then + local _, iface + local ifaces = { } + for _, iface in ipairs(members) do + ifaces[#ifaces+1] = interface(iface) + end + end +end + +function interface.bridge_id(self) + if self.br then + return self.br.id + else + return nil + end +end + +function interface.bridge_stp(self) + if self.br then + return self.br.stp + else + return false + end +end + +function interface.is_up(self) + return self:_ubus("up") or false +end + +function interface.is_bridge(self) + return (self:type() == "bridge") +end + +function interface.is_bridgeport(self) + return self.dev and self.dev.bridge and true or false +end + +function interface.tx_bytes(self) + local stat = self:_ubus("statistics") + return stat and stat.tx_bytes or 0 +end + +function interface.rx_bytes(self) + local stat = self:_ubus("statistics") + return stat and stat.rx_bytes or 0 +end + +function interface.tx_packets(self) + local stat = self:_ubus("statistics") + return stat and stat.tx_packets or 0 +end + +function interface.rx_packets(self) + local stat = self:_ubus("statistics") + return stat and stat.rx_packets or 0 +end + +function interface.get_network(self) + return self:get_networks()[1] +end + +function interface.get_networks(self) + if not self.networks then + local nets = { } + local _, net + for _, net in ipairs(_M:get_networks()) do + if net:contains_interface(self.ifname) or + net:ifname() == self.ifname + then + nets[#nets+1] = net + end + end + table.sort(nets, function(a, b) return a.sid < b.sid end) + self.networks = nets + return nets + else + return self.networks + end +end + +function interface.get_wifinet(self) + return self.wif +end + + +wifidev = utl.class() + +function wifidev.__init__(self, dev) + self.sid = dev + self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { } +end + +function wifidev.get(self, opt) + return _get("wireless", self.sid, opt) +end + +function wifidev.set(self, opt, val) + return _set("wireless", self.sid, opt, val) +end + +function wifidev.name(self) + return self.sid +end + +function wifidev.hwmodes(self) + local l = self.iwinfo.hwmodelist + if l and next(l) then + return l + else + return { b = true, g = true } + end +end + +function wifidev.get_i18n(self) + local t = "Generic" + if self.iwinfo.type == "wl" then + t = "Broadcom" + elseif self.iwinfo.type == "madwifi" then + t = "Atheros" + end + + local m = "" + local l = self:hwmodes() + if l.a then m = m .. "a" end + if l.b then m = m .. "b" end + if l.g then m = m .. "g" end + if l.n then m = m .. "n" end + if l.ac then m = "ac" end + + return "%s 802.11%s Wireless Controller (%s)" %{ t, m, self:name() } +end + +function wifidev.is_up(self) + if _ubuswificache[self.sid] then + return (_ubuswificache[self.sid].up == true) + end + + local up = false + _uci_state:foreach("wireless", "wifi-iface", + function(s) + if s.device == self.sid then + if s.up == "1" then + up = true + return false + end + end + end) + + return up +end + +function wifidev.get_wifinet(self, net) + if _uci_real:get("wireless", net) == "wifi-iface" then + return wifinet(net) + else + local wnet = _wifi_lookup(net) + if wnet then + return wifinet(wnet) + end + end +end + +function wifidev.get_wifinets(self) + local nets = { } + + _uci_real:foreach("wireless", "wifi-iface", + function(s) + if s.device == self.sid then + nets[#nets+1] = wifinet(s['.name']) + end + end) + + return nets +end + +function wifidev.add_wifinet(self, options) + options = options or { } + options.device = self.sid + + local wnet = _uci_real:section("wireless", "wifi-iface", nil, options) + if wnet then + return wifinet(wnet, options) + end +end + +function wifidev.del_wifinet(self, net) + if utl.instanceof(net, wifinet) then + net = net.sid + elseif _uci_real:get("wireless", net) ~= "wifi-iface" then + net = _wifi_lookup(net) + end + + if net and _uci_real:get("wireless", net, "device") == self.sid then + _uci_real:delete("wireless", net) + return true + end + + return false +end + + +wifinet = utl.class() + +function wifinet.__init__(self, net, data) + self.sid = net + + local num = { } + local netid + _uci_real:foreach("wireless", "wifi-iface", + function(s) + if s.device then + num[s.device] = num[s.device] and num[s.device] + 1 or 1 + if s['.name'] == self.sid then + netid = "%s.network%d" %{ s.device, num[s.device] } + return false + end + end + end) + + local dev = _wifi_state("section", self.sid, "ifname") or netid + + self.netid = netid + self.wdev = dev + self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { } + self.iwdata = data or _uci_state:get_all("wireless", self.sid) or + _uci_real:get_all("wireless", self.sid) or { } +end + +function wifinet.get(self, opt) + return _get("wireless", self.sid, opt) +end + +function wifinet.set(self, opt, val) + return _set("wireless", self.sid, opt, val) +end + +function wifinet.mode(self) + return _uci_state:get("wireless", self.sid, "mode") or "ap" +end + +function wifinet.ssid(self) + return _uci_state:get("wireless", self.sid, "ssid") +end + +function wifinet.bssid(self) + return _uci_state:get("wireless", self.sid, "bssid") +end + +function wifinet.network(self) + return _uci_state:get("wifinet", self.sid, "network") +end + +function wifinet.id(self) + return self.netid +end + +function wifinet.name(self) + return self.sid +end + +function wifinet.ifname(self) + local ifname = self.iwinfo.ifname + if not ifname or ifname:match("^wifi%d") or ifname:match("^radio%d") then + ifname = self.wdev + end + return ifname +end + +function wifinet.get_device(self) + if self.iwdata.device then + return wifidev(self.iwdata.device) + end +end + +function wifinet.is_up(self) + local ifc = self:get_interface() + return (ifc and ifc:is_up() or false) +end + +function wifinet.active_mode(self) + local m = _stror(self.iwinfo.mode, self.iwdata.mode) or "ap" + + if m == "ap" then m = "Master" + elseif m == "sta" then m = "Client" + elseif m == "adhoc" then m = "Ad-Hoc" + elseif m == "mesh" then m = "Mesh" + elseif m == "monitor" then m = "Monitor" + end + + return m +end + +function wifinet.active_mode_i18n(self) + return lng.translate(self:active_mode()) +end + +function wifinet.active_ssid(self) + return _stror(self.iwinfo.ssid, self.iwdata.ssid) +end + +function wifinet.active_bssid(self) + return _stror(self.iwinfo.bssid, self.iwdata.bssid) or "00:00:00:00:00:00" +end + +function wifinet.active_encryption(self) + local enc = self.iwinfo and self.iwinfo.encryption + return enc and enc.description or "-" +end + +function wifinet.assoclist(self) + return self.iwinfo.assoclist or { } +end + +function wifinet.frequency(self) + local freq = self.iwinfo.frequency + if freq and freq > 0 then + return "%.03f" % (freq / 1000) + end +end + +function wifinet.bitrate(self) + local rate = self.iwinfo.bitrate + if rate and rate > 0 then + return (rate / 1000) + end +end + +function wifinet.channel(self) + return self.iwinfo.channel or + tonumber(_uci_state:get("wireless", self.iwdata.device, "channel")) +end + +function wifinet.signal(self) + return self.iwinfo.signal or 0 +end + +function wifinet.noise(self) + return self.iwinfo.noise or 0 +end + +function wifinet.country(self) + return self.iwinfo.country or "00" +end + +function wifinet.txpower(self) + local pwr = (self.iwinfo.txpower or 0) + return pwr + self:txpower_offset() +end + +function wifinet.txpower_offset(self) + return self.iwinfo.txpower_offset or 0 +end + +function wifinet.signal_level(self, s, n) + if self:active_bssid() ~= "00:00:00:00:00:00" then + local signal = s or self:signal() + local noise = n or self:noise() + + if signal < 0 and noise < 0 then + local snr = -1 * (noise - signal) + return math.floor(snr / 5) + else + return 0 + end + else + return -1 + end +end + +function wifinet.signal_percent(self) + local qc = self.iwinfo.quality or 0 + local qm = self.iwinfo.quality_max or 0 + + if qc > 0 and qm > 0 then + return math.floor((100 / qm) * qc) + else + return 0 + end +end + +function wifinet.shortname(self) + return "%s %q" %{ + lng.translate(self:active_mode()), + self:active_ssid() or self:active_bssid() + } +end + +function wifinet.get_i18n(self) + return "%s: %s %q (%s)" %{ + lng.translate("Wireless Network"), + lng.translate(self:active_mode()), + self:active_ssid() or self:active_bssid(), + self:ifname() + } +end + +function wifinet.adminlink(self) + return dsp.build_url("admin", "network", "wireless", self.netid) +end + +function wifinet.get_network(self) + return self:get_networks()[1] +end + +function wifinet.get_networks(self) + local nets = { } + local net + for net in utl.imatch(tostring(self.iwdata.network)) do + if _uci_real:get("network", net) == "interface" then + nets[#nets+1] = network(net) + end + end + table.sort(nets, function(a, b) return a.sid < b.sid end) + return nets +end + +function wifinet.get_interface(self) + return interface(self:ifname()) +end + + +-- setup base protocols +_M:register_protocol("static") +_M:register_protocol("dhcp") +_M:register_protocol("none") + +-- load protocol extensions +local exts = nfs.dir(utl.libpath() .. "/model/network") +if exts then + local ext + for ext in exts do + if ext:match("%.lua$") then + require("luci.model.network." .. ext:gsub("%.lua$", "")) + end + end +end diff --git a/Me_Lua/h10/luci/sauth.lua b/Me_Lua/h10/luci/sauth.lua new file mode 100644 index 0000000..ec02be8 --- /dev/null +++ b/Me_Lua/h10/luci/sauth.lua @@ -0,0 +1,200 @@ +--[[ + +Session authentication +(c) 2008 Steven Barth + +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 diff --git a/Me_Lua/h10/meizu/arpmon.lua b/Me_Lua/h10/meizu/arpmon.lua new file mode 100644 index 0000000..e0f7160 --- /dev/null +++ b/Me_Lua/h10/meizu/arpmon.lua @@ -0,0 +1,99 @@ +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 fetch_arp_mac = dbfs.fetch_arp_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 + +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 + local new_devs = {} + ipmacs[#ipmacs] = nil + local wifiDeviceDict = nwfs.getAllWifiConnetDeviceDict() + for k, v in pairs(ipmacs) do + local ipmac = strsplit(v, ',') + local ip = ipmac[1] + local mac = ipmac[2] + mac = string.upper(mac) + local wifiType = wifiDeviceDict[mac] + local data = dbfs.fetch_wireless_device_mac(mac) + if wifiType ~= nil then + --local res = dbfs.fetch_wireless_device_mac(mac) + if data == "" then + dbfs.insert_wireless_device_mac(mac) + end + else + local ret = dbfs.fetch_wire_device_mac(mac) + local res = nwfs.is_device_online(ip) + if res == false and ret == "" and data == "" then + dbfs.insert_wireless_device_mac(mac) + elseif res == true and ret == "" then + dbfs.insert_wire_device_mac(mac, ip) + end + end + + if ip ~= "" then + if fetch_arp_mac(mac) == "" then + table.insert(new_devs, v) + end + end + end + delete_arp_all_mac() + for k, v in pairs(ipmacs) do + local ipmac = strsplit(v, ',') + local ip = ipmac[1] + local mac = ipmac[2] + if ip ~= "" then + insert_arp_macip(mac, ip) + end + end + for k, v in pairs(new_devs) do + local ipmac = strsplit(v, ',') + local ip = ipmac[1] + local mac = ipmac[2] + if ip ~= "" then + 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 diff --git a/Me_Lua/h10/meizu/bfs.lua b/Me_Lua/h10/meizu/bfs.lua new file mode 100644 index 0000000..b62ae41 --- /dev/null +++ b/Me_Lua/h10/meizu/bfs.lua @@ -0,0 +1,511 @@ +module("meizu.bfs", package.seeall) +--API base functions + +local cjson = require "cjson" +local dbfs = require "meizu.dbfs" + +local delete_access_token = dbfs.delete_access_token + +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 -f") +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; /sbin/router_reset;/sbin/reboot") +end + +function set_passwd() + 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) + luci.http.status(200, "setpasswd successful!") + luci.http.write("setpasswd successful!") + return + end + end + luci.http.status(500, "Bad passwd!") + --luci.http.write("setpasswd failed!") +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 = "" + 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 batchfile_checklist() + local IMEI = luci.http.formvalue("imei") + local dbfs = require "meizu.dbfs" + local searchEndFlag = "searchend" + local flag = dbfs.fetchBatchFileEndFlag(searchEndFlag, IMEI) + dbfs.deleteBatchFileEndFlag(searchEndFlag, IMEI) + local res = dbfs.fetchAllBatchFile(IMEI) + local result = res + dbfs.deleteBatchFile(IMEI) + res = cjson.encode(res) + + if next(result) ~= nil then + if flag.hashCode ~= nil then + res = '{"status":"2002", "data":'..res.."}" + else + res = '{"status":"2001", "data":'..res.."}" + end + else + res = '{"status":"2003"}' + end + luci.http.write(res) + return res +end + +function findInDir(rootpath, wefind, hashCode, md5sum, IMEI) + local dbfs = require "meizu.dbfs" + local flag = 0 + local ret, files, iter = pcall(lfs.dir, rootpath) + if ret == false then + return nil + end + for entry in files, iter do + if entry ~= '.' and entry ~= '..' then + local f = rootpath .. '/' .. entry + local filename = string.match(f, ".+/([^/]*%.%w+)$") + + if wefind == filename then + flag = 1 + if(md5sum == luci.sys.exec("md5sum %q" % f):match("^([^%s]+)")) then + require "MZLog".log(3, debug.getinfo(1).currentline) + else + dbfs.addBatchFile(hashCode, IMEI) + end + end + end + end + return flag +end + +function batchfile_compare_upload() + local data = luci.http.formvalue("data") + local tableData = cjson.decode(data) + local dbfs = require "meizu.dbfs" + dbfs.initBatchFileTable() + local LuciUtil = require("luci.util") + local sharePath = "/mnt/Image" + local ID = nil + for key, value in pairs(tableData) do + local wefind = value.fileName + local md5sum = value.md5 + local hashCode = value.hashCode + local IMEI = value.imei + local rootpath = sharePath + ID = IMEI + + local ret, files, iter = pcall(lfs.dir, rootpath) + if ret == false then + dbfs.addBatchFile(hashCode, IMEI) + end + local flag = findInDir(rootpath, wefind, hashCode, md5sum, IMEI) + if flag == 0 then + dbfs.addBatchFile(hashCode, IMEI) + end + end + local searchEndFlag = "searchend" + dbfs.addBatchFile(searchEndFlag, ID) +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 get_files_list(path, start, count, ID) + local result = {} + local ret, files, iter = pcall(lfs.dir, path) + local cmd_file = "ls -al " .. '"'.. path ..'"'.. " | awk '/^-/' | wc -l" + local cmd_dir = "ls -al " .. '"'.. path ..'"'.. " | awk '/^d/' | wc -l" + local luaUtil = require"luci.util" + local file_num = luaUtil.exec(cmd_file) + local dir_num = luaUtil.exec(cmd_dir) + local total_num = file_num + dir_num - 2 + local start = tonumber(start) + local count = tonumber(count) + local fs = require "nixio.fs" + + if ret == true then + for file in lfs.dir(path) do + if file ~= "." and file ~= ".." then + local f = path..'/'..file + local fname = file + local attr = lfs.attributes(f) + assert (type(attr) == "table") + + if attr.mode == "directory" then + local res = {name = "", isfile = nil, size = nil, time = nil} + local cmd_file = "ls -al " .. '"'.. f ..'"'.. " | awk '/^-/' | wc -l" + local cmd_dir = "ls -al " .. '"'.. f ..'"'.. " | awk '/^d/' | wc -l" + local size_file = luaUtil.exec(cmd_file) + local size_dir = luaUtil.exec(cmd_dir) + local size = size_file + size_dir - 2 + local name = fname + local stat = fs.stat(f) + local time = stat.mtime + res.name = fname + res.isfile = 0 + res.size = size + res.time = time + + table.insert(result, res) + else + local res = {name = "", isfile = nil, size = nil, time = nil} + local name = fname + local stat = fs.stat(f) + local time = stat.mtime + local size = nixio.fs.stat(f).size + res.name = fname + res.isfile = 1 + res.size = size + res.time = time + + table.insert(result, res) + end + end + end + if total_num > count then + total_num = count + end + + table.sort(result, function(a, b) return (a.isfile < b.isfile) end) + local res = {} + for i = start + 1, start + count do + table.insert(res, result[i]) + end + + local res = cjson.encode(res) + path = string.gsub(path, "mnt", "router") + res = '{"result":true, "start":'..start..', "count":'..total_num..', "path":"'..path..'", "fileinfo":'..res.."}" + luci.http.write(res) + return res + end +end + +function getFilesList() + local path = luci.http.formvalue("path") + local start = luci.http.formvalue("start") + local count = luci.http.formvalue("count") + local ID = luci.http.formvalue("ID") + local result = get_files_list(path, start, count, ID) + --luci.http.write(result) + return result +end + +function sysinfo() + local lue = require("luci.util").exec + local ret = {} + ret["romversion"] = get_device_version() + ret["SN"] = get_device_SN() + ret["deviceModel"] = "R10" + ret["routername"] = "mzrt"..get_device_SN() + local ssid1, ssid2 = require "meizu.nwfs".get_wifi_ssids() + ret["ssid1"] = ssid1 + ret["ssid2"] = ssid2 + local cmd = [[df /mnt|grep -q sda;echo -n $?]] + ret["diskstatus"] = lue(cmd) + return ret +end diff --git a/Me_Lua/h10/meizu/btfs.lua b/Me_Lua/h10/meizu/btfs.lua new file mode 100644 index 0000000..4c16467 --- /dev/null +++ b/Me_Lua/h10/meizu/btfs.lua @@ -0,0 +1,1442 @@ +module("meizu.btfs", package.seeall) +--network functions + +local cjson = require "cjson" +local lfs = require "lfs" +local bfs = require "meizu.bfs" +local RC = require "meizu.r10config" +local dbfs = require("meizu.dbfs") +local posix = require("Posix") + +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 b64dec = bfs.b64dec +local b64enc = bfs.b64enc + +local lue = require("luci.util").exec + +------------------------ bluetooth -------------------- + +----------------------- receive data -------------------- +function bluetooth_info() + dbfs.initBluetoothTable() + local value = luci.http.formvalue("data") + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, value) + local ret = {} + local types = string.sub(value, 1, 2) + + if types == "00" then + local id = string.sub(value, 3, 4) + local status = string.format("%d", "0x" .. string.sub(value, 5, 6)) + local temp1 = string.sub(value, 7, 8) + local temp2 = string.sub(value, 9, 10) + local temp = temp2..temp1 + temp = string.format("%d", "0x" .. temp) + local rh1 = string.sub(value, 11, 12) + local rh2 = string.sub(value, 13, 14) + local rh = rh2..rh1 + rh = string.format("%d", "0x" .. rh) + local light1 = string.sub(value, 15, 16) + local light2 = string.sub(value, 17, 18) + local light = light2..light1 + light = string.format("%d", "0x" .. light) + local mac = dbfs.getBluetoothDevice(id) + local TMP = "/tmp/"..mac.."0" + + ret["mac"] = mac + ret["id"] = id + if status == "1" then + ret["onoff"] = "on" + else + ret["onoff"] = "off" + end + local timer_id = "" + local flag = "" + local start = "" + local ends = "" + local fd = io.open(TMP, "r") + + if fd then + local res = fd:read() + fd:close() + res = cjson.decode(res) + timer_id = res.timerId + flag = res.flag + start = res.start + ends = res.ends + end + + ret["timerId"] = timer_id + ret["flag"] = flag + ret["start"] = start + ret["ends"] = ends + ret["temp"] = temp + ret["hemi"] = rh + ret["light"] = light + ret["time"] = os.time() + + local result = data_to_json(ret) + --[[ + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, id) + require "MZLog".log(3, result) + require "MZLog".log(3, ret) + ]] + local fd = assert(io.open(TMP, "w")) + fd:write(result) + fd:close() + + elseif types == "01" then + local id = string.sub(value, 3, 4) + local voltage1 = string.sub(value, 5, 6) + local voltage2 = string.sub(value, 7, 8) + local voltage = voltage2..voltage1 + voltage = string.format("%d", "0x" .. voltage) + local electricity1 = string.format("%d", "0x" .. string.sub(value, 9, 10)) + local electricity2 = string.format("%d", "0x" .. string.sub(value, 11, 12)) + local electricity = electricity2..electricity1 + electricity = string.format("%d", "0x" .. electricity) + local power1 = string.sub(value, 13, 14) + local power2 = string.sub(value, 15, 16) + local power = power2..power1 + power = string.format("%d", "0x" .. power) + local electric1 = string.sub(value, 17, 18) + local electric2 = string.sub(value, 19, 20) + local electric = electric2..electric1 + electric = string.format("%d", "0x" .. electric) + local mac = dbfs.getBluetoothDevice(id) + local TMP = "/tmp/"..mac.."1" + local timer_id = "" + local fd = io.open(TMP, "r") + if fd then + local res = fd:read() + fd:close() + res = cjson.decode(res) + timer_id = res.timerId + end + + ret["timerId"] = timer_id + ret["mac"] = mac + ret["id"] = id + ret["voltage"] = voltage + ret["current"] = electricity + ret["power"] = power + ret["energy"] = electric + + local result = data_to_json(ret) + local fd = assert(io.open(TMP, "w")) + fd:write(result) + fd:close() + + elseif types == "02" then + require "MZLog".log(3, debug.getinfo(1).currentline) + local id = string.sub(value, 3, 4) + local TYPE = string.sub(value, 5, 6) + local mac1 = string.sub(value, 7, 8) + local mac2 = string.sub(value, 9, 10) + local mac3 = string.sub(value, 11, 12) + local mac4 = string.sub(value, 13, 14) + local mac5 = string.sub(value, 15, 16) + local mac6 = string.sub(value, 17, 18) + local mac = mac6..mac5..mac4..mac3..mac2..mac1 + + mac = string.upper(mac) + local ID = "" + local res = dbfs.fetchBluetoothDevice(mac) + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, #res) + require "MZLog".log(3, res) + if #res > 0 then + for k, v in pairs(res) do + ID = v.id + end + end + if id ~= ID then + dbfs.updateBluetoothDevice(id, "", "", "", mac) + end + local TMP = "/tmp/"..mac.."0" + local fd = io.open(TMP, "r") + + if fd then + local res = fd:read() + fd:close() + res = cjson.decode(res) + res["time"] = os.time() + res = cjson.encode(res) + local fd = io.open(TMP, "w") + fd:write(res) + fd:close() + end + require "MZLog".log(3, id) + require "MZLog".log(3, mac) + require "MZLog".log(3, debug.getinfo(1).currentline) + + elseif types == "09" then + local deviceType = string.sub(value, 3, 4) + local mac1 = string.sub(value, 5, 6) + local mac2 = string.sub(value, 7, 8) + local mac3 = string.sub(value, 9, 10) + local mac4 = string.sub(value, 11, 12) + local mac5 = string.sub(value, 13, 14) + local mac6 = string.sub(value, 15, 16) + local mac = mac6..mac5..mac4..mac3..mac2..mac1 + mac = string.upper(mac) + + local res = dbfs.fetchBluetoothDevice(mac) + local ret = nil + local id = nil + if #res > 0 then + for k, v in pairs(res) do + ret = v.mac + id = v.id + end + end + if id then + dbfs.updateBluetoothDevice("", "", "", "", mac) + end + if ret == nil then + dbfs.addBluetoothDevice("", mac, "", "", deviceType, "") + local TMP = "/tmp/"..mac + local fd = io.open(TMP, "w") + fd:write(os.time()) + fd:close() + else + local TMP = "/tmp/"..mac + local fd = io.open(TMP, "w") + fd:write(os.time()) + fd:close() + end + + elseif types == "04" then + local data = string.format("%d", "0x" .. string.sub(value, 3, 4)) + ret["data"] = data + + elseif types == "03" then + require "MZLog".log(3, debug.getinfo(1).currentline) + local id = string.sub(value, 3, 4) + local flag = string.sub(value, 5, 6) + local timer_id = string.sub(value, 7, 8) + local start = string.sub(value, 9, 16) + local ends = string.sub(value, 17, 24) + local mac = dbfs.getBluetoothDevice(id) + local TMP = "/tmp/"..mac.."1" + local fd = io.open(TMP, "r") + + if fd then + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, timer_id) + require "MZLog".log(3, flag) + local res = fd:read() + res = cjson.decode(res) + if timer_id == res["timerId"] then + local TMP = "/tmp/"..mac.."0" + local fd = io.open(TMP, "r") + local res = fd:read() + res = cjson.decode(res) + res["flag"] = flag + res["timerId"] = timer_id + res["start"] = start + res["ends"] = ends + res = cjson.encode(res) + local fd = io.open(TMP, "w") + fd:write(res) + fd:close() + end + end + + elseif types == "06" then + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, debug.getinfo(1).currentline) + local id = string.sub(value, 3, 4) + local mac = dbfs.getBluetoothDevice(id) + local len = tonumber(dbfs.getBleDeviceNameLength(id)) + local str = string.sub(value, 5, len + 4) + --local res = {} + --[[ + for i = 1, #str, 2 do + res[#res + 1] = (tonumber(string.format("%d", "0x"..string.sub(str, i, i+1)))) + end + ]] + local device_name = str + --[[ + if #res == 1 then + device_name = string.char(res[1]) + elseif #res == 2 then + device_name = string.char(res[1], res[2]) + elseif #res == 3 then + device_name = string.char(res[1], res[2], res[3]) + elseif #res == 4 then + device_name = string.char(res[1], res[2], res[3], res[4]) + elseif #res == 5 then + device_name = string.char(res[1], res[2], res[3], res[4], res[5]) + elseif #res == 6 then + device_name = string.char(res[1], res[2], res[3], res[4], res[5], res[6]) + elseif #res == 7 then + device_name = string.char(res[1], res[2], res[3], res[4], res[5], res[6], res[7]) + elseif #res == 8 then + device_name = string.char(res[1], res[2], res[3], res[4], res[5], res[6], res[7], res[8]) + elseif #res == 9 then + device_name = string.char(res[1], res[2], res[3], res[4], res[5], res[6], res[7], res[8], res[9]) + elseif #res == 10 then + device_name = string.char(res[1], res[2], res[3], res[4], res[5], res[6], res[7], res[8], res[9], res[10]) + end + ]] + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, str) + require "MZLog".log(3, device_name) + dbfs.updateBluetoothDevice(id, "", device_name, len, mac) + require "MZLog".log(3, debug.getinfo(1).currentline) + + elseif types == "07" then + local data = string.format("%d", "0x" .. string.sub(value, 3, 4)) + ret["data"] = data + + elseif types == "0b" then + local key_ack = string.sub(value, 3, 4) + local TMP = "/tmp/0b0b" + local fd = io.open(TMP, "w") + fd:write(key_ack) + fd:close() + + elseif types == "0c" then + local id = string.sub(value, 3, 4) + local status = string.sub(value, 5, 6) + local mac = dbfs.getBluetoothDevice(id) + local TMP = "/tmp/"..mac.."0" + local fd = io.open(TMP, "r") + local res = nil + require "MZLog".log(3, debug.getinfo(1).currentline) + + if fd then + res = fd:read() + fd:close() + res = cjson.decode(res) + if status == "01" then + res["onoff"] = "on" + else + res["onoff"] = "off" + end + res = cjson.encode(res) + local fd = io.open(TMP, "w") + fd:write(res) + fd:close() + end + require "MZLog".log(3, res) + + elseif types == "0d" then + local id = string.sub(value, 3, 4) + local led_light = string.sub(value, 5, 6) + local temp1 = string.sub(value, 7, 8) + local temp2 = string.sub(value, 9, 10) + led_light = string.format("%d", "0x" .. led_light) + local led_temp = temp2..temp1 + temp = string.format("%d", "0x" .. temp) + + local TMP = "/tmp/"..mac.."0" + local fd = io.open(TMP, "r") + local res = nil + require "MZLog".log(3, debug.getinfo(1).currentline) + + if fd then + res = fd:read() + fd:close() + res = cjson.decode(res) + res["led_light"] = led_light + res["led_temp"] = led_temp + + res = cjson.encode(res) + local fd = io.open(TMP, "w") + fd:write(res) + fd:close() + end + + elseif types == "0e" then + local id = string.sub(value, 3, 4) + local wait_time = string.format("%d", "0x" .. string.sub(value, 5, 6)) + --local mac = dbfs.getBluetoothDevice(id) + local TMP = "/tmp/0e0e" + local fd = io.open(TMP, "w") + fd:write(wait_time) + fd:close() + + elseif types == "10" then + local mac1 = string.sub(value, 3, 4) + local mac2 = string.sub(value, 5, 6) + local mac3 = string.sub(value, 7, 8) + local mac4 = string.sub(value, 9, 10) + local mac5 = string.sub(value, 11, 12) + local mac6 = string.sub(value, 13, 14) + local mac = mac6..mac5..mac4..mac3..mac2..mac1 + mac = string.upper(mac) + + local res = dbfs.fetchBluetoothDevice(mac) + if #res == 0 then + dbfs.addBluetoothDevice("", mac, "0123", "", "", "") + end + --[[ + if ret == nil then + dbfs.addBluetoothDevice("", mac, "", "", deviceType, "") + local TMP = "/tmp/"..mac + local fd = io.open(TMP, "w") + fd:write(os.time()) + fd:close() + else + local TMP = "/tmp/"..mac + local fd = io.open(TMP, "w") + ]] + end + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, ret) + return ret +end + +function nw_get_bluetooth_info() + require "MZLog".log(3, debug.getinfo(1).currentline) + local res = bluetooth_info() + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + luci.http.write_json(res) +end + +function ww_get_bluetooth_info() + require "MZLog".log(3, debug.getinfo(1).currentline) + local res = bluetooth_info() + require "MZLog".log(3, debug.getinfo(1).currentline) + return res +end + +----------------------- scan_ble_device -------------------- +function scan_ble_switch(status) + local res = {} + if status == "on" then + local cmd = "bt_daemon -s ".."16".." 255" + lue(cmd) + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, cmd) + posix.sleep(1) + res["result"] = true + elseif status == "off" then + local cmd = "bt_daemon -s ".."18".." 255" + lue(cmd) + posix.sleep(1) + res["result"] = false + end + return res +end + +function nw_scan_ble_switch() + local status = luci.http.formvalue("status") + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, status) + local res = scan_ble_switch(status) + require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + luci.http.write_json(res) +end + +function ww_scan_ble_switch(status) + local res = scan_ble_switch(status) + require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + return cjson.encode(res) +end + +----------------------- get_ble_device_list -------------------- +function get_ble_device_list() + local res = dbfs.fetchAllBluetoothDevice() + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, res) + local result = {} + if #res > 0 then + for k, v in pairs(res) do + local TMP = "/tmp/"..v.mac + local fd = io.open(TMP, "r") + if fd then + local time = fd:read() + fd:close() + if tonumber(os.time()) - tonumber(time) < 5 then + table.insert(result, v) + end + end + end + end + return result +end + +function nw_get_ble_device_list() + local res = get_ble_device_list() + require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + if #res == 0 then + require "MZLog".log(3, debug.getinfo(1).currentline) + luci.http.write("[]") + else + luci.http.write_json(res) + end +end + +function ww_get_ble_device_list() + local res = get_ble_device_list() + require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + if #res == 0 then + return "[]" + else + return cjson.encode(res) + end +end + +----------------------- add_ble_mesh_device -------------------- +function is_receive_id(mac) + local id = "" + local ret = dbfs.fetchBluetoothDevice(mac) + for k, v in pairs(ret) do + id = v.id + end + return id +end + +function add_ble_mesh_device(mac) + local res = {} + local id = "" + local mac1 = string.format("%d", "0x" .. string.sub(mac, 1, 2)) + local mac2 = string.format("%d", "0x" .. string.sub(mac, 3, 4)) + local mac3 = string.format("%d", "0x" .. string.sub(mac, 5, 6)) + local mac4 = string.format("%d", "0x" .. string.sub(mac, 7, 8)) + local mac5 = string.format("%d", "0x" .. string.sub(mac, 9, 10)) + local mac6 = string.format("%d", "0x" .. string.sub(mac, 11, 12)) + local macs = mac6.." "..mac5.." "..mac4.." "..mac3.." "..mac2.." "..mac1 + + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, mac) + local cmd = "bt_daemon -s ".."17 "..macs + lue(cmd) + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, cmd) + + for i = 1, 20 do + posix.sleep(1) + id = is_receive_id(mac) + if id ~= "" then + break + end + end + if id ~= "" then + res["result"] = true + res["id"] = id + res["mac"] = mac + else + res["result"] = false + res["mac"] = mac + end + return res +end + +function nw_add_ble_mesh_device() + local mac = luci.http.formvalue("mac") + local res = add_ble_mesh_device(mac) + require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + luci.http.write_json(res) +end + +function ww_add_ble_mesh_device(mac) + local res = add_ble_mesh_device(mac) + require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + return cjson.encode(res) +end + +----------------------- get_ble_device_detail -------------------- +function get_ble_device_status(mac) + local TMP1 = "/tmp/"..mac.."0" + local TMP2 = "/tmp/"..mac.."1" + local fd1 = io.open(TMP1, "r") + local fd2 = io.open(TMP2, "r") + if fd1 and fd2 then + local res1 = fd1:read() + local res2 = fd2:read() + fd1:close() + fd2:close() + --require "MZLog".log(3, res1) + --require "MZLog".log(3, res2) + if res1 ~= nil and res2 ~= nil then + res1 = cjson.decode(res1) + res2 = cjson.decode(res2) + res1["voltage"] = res2.voltage + res1["current"] = res2.current + res1["power"] = res2.power + res1["energy"] = res2.energy + + local ret = dbfs.fetchBluetoothDevice(mac) + local deviceType = nil + local name = nil + for k, v in pairs(ret) do + deviceType = v.deviceType + name = v.name + end + + res1["name"] = name + res1["type"] = deviceType + res1["time"] = nil + --require "MZLog".log(3, res1) + require "MZLog".log(3, debug.getinfo(1).currentline) + end + if res1 == "" then + res1 = "{}" + end + return res1 + else + return "{}" + end +end + +function nw_get_ble_device_status() + local mac = luci.http.formvalue("mac") + local res = get_ble_device_status(mac) + --require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + if res == "{}" then + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, res) + luci.http.write(res) + else + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, res) + luci.http.write_json(res) + end +end + +function ww_get_ble_device_status(mac) + local res = get_ble_device_status(mac) + require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + if res == "{}" then + return res + else + return cjson.encode(res) + end +end + +----------------------- remove_ble_from_mesh -------------------- +function is_remove_ble_from_mesh() + local res = nil + local TMP = "/tmp/0e0e" + local fd = io.open(TMP, "r") + if fd then + local ret = fd:read() + fd:close() + if ret ~= "" and ret ~= nil then + return ret + else + return nil + end + else + return nil + end +end + +function remove_ble_from_mesh(mac) + local res = {} + local ret = dbfs.fetchBluetoothDevice(mac) + local id = nil + for k, v in pairs(ret) do + id = v.id + end + if id ~= nil and id ~= "" then + local cmd = "bt_daemon -s ".."3 "..string.format("%d", "0x"..id) + lue(cmd) + local wait_time = nil + for i = 1, 20 do + posix.sleep(1) + wait_time = is_remove_ble_from_mesh(mac) + if wait_time ~= nil then + break + end + end + if wait_time then + res["result"] = true + res["waitTime"] = wait_time + res["mac"] = mac + res["id"] =id + else + res["result"] = false + res["mac"] = mac + res["id"] = id + end + else + res["result"] = false + res["mac"] = mac + end + return res +end + +function nw_remove_ble_from_mesh() + local mac = luci.http.formvalue("mac") + local res = remove_ble_from_mesh(mac) + require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + luci.http.write_json(res) +end + +function ww_remove_ble_from_mesh(mac) + local res = remove_ble_from_mesh(mac) + require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + return cjson.encode(res) +end + +----------------------- get_mesh_device_list -------------------- +function is_file_exist(TMP) + local fd = io.open(TMP, "r") + if fd then + return fd + else + require "MZLog".log(3, debug.getinfo(1).currentline) + return false + end +end + +function get_mesh_device_list() + local result = {} + local ret = dbfs.fetchAllBleMeshDevice() + if #ret > 0 then + for k, v in pairs(ret) do + local res = {} + local TMP = "/tmp/" .. v.mac .."0" + local fd = nil + fd = is_file_exist(TMP) + --[[ + for i = 1, 5 do + fd = is_file_exist(TMP) + if fd then + break + else + posix.sleep(1) + end + end + ]] + if fd then + local value = fd:read() + if value ~= nil then + value = cjson.decode(value) + end + res["mac"] = v.mac + --res["online"] = true + res["name"] = v.name + res["type"] = v.deviceType + if value["onoff"] == "on" then + res["onoff"] = "on" + else + res["onoff"] = "off" + end + + if tonumber(os.time()) - tonumber(value.time) > 60 then + res["online"] = false + else + res["online"] = true + end + + if res["online"] == false then + res = nil + end + table.insert(result, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + + else + res["mac"] = v.mac + res["name"] = v.name + res["type"] = v.deviceType + res["onoff"] = "off" + res["online"] = false + table.insert(result, res) + require "MZLog".log (3, debug.getinfo(1).currentline) + end + end + end + return result +end + +function nw_get_mesh_device_list() + local res = get_mesh_device_list() + --require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + if #res == 0 then + luci.http.write("[]") + else + luci.http.write_json(res) + end +end + +function ww_get_mesh_device_list() + local res = get_mesh_device_list() + require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + if #res == 0 then + return "[]" + else + return cjson.encode(res) + end +end + +----------------------- dismiss_mesh -------------------- +function dismiss_mesh() + local res = {} + local cmd = "bt_daemon -s ".."3 ".." 255" + lue(cmd) + res["result"] = true +end +function nw_dismiss_mesh() + local res = dismiss_mesh() + require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + luci.http.write_json(res) +end + +----------------------- set_mesh_device_attr -------------------- +function is_switch_on(mac) + local TMP = "/tmp/"..mac.."0" + local fd = io.open(TMP, "r") + if fd then + local res = fd:read() + fd:close() + res = cjson.decode(res) + if res["onoff"] == "on" then + return true + else + return nil + end + end +end + +function is_switch_off(mac) + local TMP = "/tmp/"..mac.."0" + local fd = io.open(TMP, "r") + if fd then + local res = fd:read() + fd:close() + res = cjson.decode(res) + if res["onoff"] == "off" then + return true + else + return nil + end + end +end + +function is_set_name_ok(mac) + local name = "" + local ret = dbfs.fetchBluetoothDevice(mac) + for k, v in pairs(ret) do + name = v.name + end + return name +end + +function set_mesh_device_attr(mac, key, value) + local res = {} + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, mac) + require "MZLog".log(3, key) + require "MZLog".log(3, value) + + local fd = io.open("/tmp/meshDeviceFlag", "r") + if fd then + local time = tonumber(fd:read()) + if os.time() - time < 50 then + local res = {} + res["result"] = true + return res + end + end + + local ret = dbfs.fetchBluetoothDevice(mac) + local id = nil + if #ret > 0 then + for k, v in pairs(ret) do + id = v.id + end + end + --[[ + local fd1 = io.open("/tmp/tmp", "a") + fd1:write(key) + fd1:write(value) + ]] + + + if id ~= nil then + --local cmd = "touch /tmp/flag" + --lue(cmd) + local fd = io.open("/tmp/meshDeviceFlag", "w") + fd:write(os.time()) + fd:close() + + if key == "8" and value == "true" then + local cmd = "bt_daemon -s ".."1 "..string.format("%d", "0x"..id).." 1" + lue(cmd) + local flag = nil + for i = 1, 10 do + flag = is_switch_on(mac) + if flag then + break + else + posix.sleep(1) + end + end + if flag then + res["result"] = true + res["mac"] = mac + res["key"] = key + res["onoff"] = " on" + else + res["result"] = false + res["mac"] = mac + res["key"] = key + res["onoff"] = "off" + end + + elseif key == "8" and value == "false" then + local cmd = "bt_daemon -s ".."1 "..string.format("%d", "0x"..id).." 0" + lue(cmd) + local flag = nil + for i = 1, 10 do + flag = is_switch_off(mac) + if flag then + break + else + posix.sleep(1) + end + end + if flag then + res["result"] = true + res["mac"] = mac + res["key"] = key + res[ "onoff"] = "off" + else + res[ "result"] = false + res["mac"] = mac + res["key"] = key + res["onoff"] = "on" + end + + elseif key == "0" then + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, value) + if #value > 20 then + value = string.sub(value, 1, 20) + end + require "MZLog".log(3, debug.getinfo(1).currentline) + local name = "" + for i = 1, #value, 2 do + name = name.." "..string.format("%d", "0x"..string.sub(value, i, i+1)) + end + + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, name) + local len = #value + if len > 20 then + len = 20 + end + require "MZLog".log(3, len) + dbfs.updateBluetoothDevice(id, "", "", len, mac) + require "MZLog".log(3, debug.getinfo(1).currentline) + local cmd = "bt_daemon -s ".."13 "..string.format("%d", "0x"..id).." "..name + lue(cmd) + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, cmd) + + local name = "" + for i = 1, 10 do + posix.sleep(1) + name = is_set_name_ok(mac) + if name ~= "" then + break + end + end + + if name ~= "" and name ~= nil then + res ["result"] = true + res["mac"] = mac + res["key"] = key + else + res[ "result"] = false + res["mac"] = mac + res["key"] = key + end + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, debug.getinfo(1).currentline) + end + else + res["result"] = false + res["mac"] = mac + res["key"] = key + end + --[[ + fd1:write(cjson.encode(res)) + fd1:write("\n") + fd1:close() + ]] + return res +end + +function nw_set_mesh_device_attr() + local mac = luci.http.formvalue("mac") + local key = luci.http.formvalue("key") + local value = luci.http.formvalue("value") + local res = set_mesh_device_attr(mac, key, value) + require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + local cmd = "rm /tmp/meshDeviceFlag" + lue(cmd) + + luci.http.write_json(res) +end + +function ww_set_mesh_device_attr(mac, key, value) + local res = set_mesh_device_attr(mac, key, value) + require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + local cmd = "rm /tmp/meshDeviceFlag" + lue(cmd) + return cjson.encode(res) +end + +----------------------- reboot_mesh_device -------------------- +function reboot_mesh_device(mac) + local res = {} + local ret = dbfs.fetchBluetoothDevice(mac) + local id = nil + for k, v in pairs(ret) do + id = v.id + end + + local cmd = "bt_daemon -s ".."4 "..string.format("%d", "0x"..id) + lue(cmd) + posix.sleep(2) + res["result"] = true +end + +function nw_reboot_mesh_device() + local mac = luci.http.formvalue("mac") + local res = reboot_mesh_device(mac) + require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + luci.http.write_json(res) +end + +function ww_reboot_mesh_device(mac) + local res = reboot_mesh_device(mac) + require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + return cjson.encode(res) +end + +----------------------- unmesh_all_device -------------------- +function unmesh_all_device() + local res = {} + local cmd = "bt_daemon -s ".."3 ".."255" + lue(cmd) + require "MZLog".log(3, debug.getinfo(1).currentline) + local wait_time = nil + for i = 1, 20 do + wait_time = is_remove_ble_from_mesh() + if wait_time ~= nil then + break + else + posix.sleep(1) + end + end + if wait_time then + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, debug.getinfo(1).currentline) + res["result"] = true + else + res["result"] = false + end + require "MZLog".log(3, debug.getinfo(1).currentline) + return res +end + +function nw_unmesh_all_device() + local res = unmesh_all_device() + require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + luci.http.write_json(res) +end + +function ww_unmesh_all_device() + local res = unmesh_all_device() + require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + return cjson.encode(res) +end + +----------------------- set_mesh_device_timer -------------------- +function is_set_timer_ok(mac, timer_id) + local TMP = "/tmp/"..mac.."0" + local fd = io.open(TMP, "r") + if fd then + local ret = fd:read() + ret = cjson.decode(ret) + fd:close() + if ret["timerId"] == timer_id then + return true + else + return nil + end + else + return nil + end +end +function set_mesh_device_timer(mac, timer_id, flag, start_time, end_time) + local res = {} + local ret = dbfs.fetchBluetoothDevice(mac) + local id = nil + for k ,v in pairs(ret) do + id = v.id + end + local ret = dbfs.getBleTimerId(id, timer_id) + if ret == "" then + dbfs.addBleTimer(id, timer_id, flag, start_time, end_time) + end + --[[ + local start = start + local ends = ends + if string.len(start) == 6 then + start = "00"..start + elseif string.len(start) == 5 then + start = "000"..start + elseif string.len(start) == 4 then + start = "0000"..start + end + + if string.len(ends) == 6 then + ends = "00"..ends + elseif string.len(ends) == 5 then + ends = "000"..ends + elseif string.len(ends) == 4 then + ends = "0000"..ends + end + require "MZLog".log(3, mac) + require "MZLog".log(3, timer_id) + require "MZLog".log(3, flag) + require "MZLog".log(3, start) + require "MZLog".log(3, ends) + + local TMP = "/tmp/"..mac.."1" + local fd = io.open(TMP, "r") + if fd then + local res = fd:read() + res = cjson.decode(res) + res["timerId"] = timer_id + res = cjson.encode(res) + local fd = io.open(TMP, "w") + fd:write(res) + fd:close() + end + + local start1 = string.sub(start, 1, 2) + local start2 = string.sub(start, 3, 4) + local start3 = string.sub(start, 5, 6) + local start4 = string.sub(start, 7, 8) + local end1 = string.sub(ends, 1, 2) + local end2 = string.sub(ends, 3, 4) + local end3 = string.sub(ends, 5, 6) + local end4 = string.sub(ends, 7, 8) + if id then + local start = string.format("%d", "0x"..start1).." ".. + string.format("%d", "0x"..start2).." ".. + string.format("%d", "0x"..start3).." ".. + string.format("%d", "0x"..start4) + local ends = string.format("%d", "0x"..end1).." ".. + string.format("%d", "0x"..end2).." ".. + string.format("%d", "0x"..end3).." ".. + string.format("%d", "0x"..end4) + + local cmd = "/root/spi_send ".."6 "..string.format("%d", "0x"..id).. + " "..string.format("%d", "0x"..flag).." ".. + string.format("%d", "0x"..timer_id).." "..start.." "..ends + require "MZLog".log(3, cmd) + lue(cmd) + + local times = tonumber(os.time()) - 1420041600 + local res = string.format("%x", times) + local time = "" + for i = 1, #res, 2 do + time = time.." "..string.format("%d", "0x"..string.sub(res, i, i+1)) + end + local cmd = "/root/spi_send ".."7 "..string.format("%d", "0x"..id).." "..time + lue(cmd) + end + + local flag = nil + for i = 1, 10 do + posix.sleep(1) + flag = is_set_timer_ok(mac, timer_id) + if flag then + break + end + end + if flag then + res["result"] = true + res["mac"] = mac + res["timerId"] = timer_id + else + res["result"] = false + res["mac"] = mac + res["timerId"] = timer_id + end + return res + ]] +end + +function nw_set_mesh_device_timer() + local mac = luci.http.formvalue("mac") + local timer_id = luci.http.formvalue("timerId") + local flag = luci.http.formvalue("flag") + local start_time = luci.http.formvalue("start") + local end_time = luci.http.formvalue("ends") + local timer = luci.http.formvalue("timer") + local res = set_mesh_device_timer(mac, timer_id, flag, start_time, end_time) + require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + luci.http.write_json(res) +end + +function ww_set_mesh_device_timer(mac, timer_id, flag, start, ends) + local res = set_mesh_device_timer(mac, timer_id, flag, start, ends) + require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + return cjson.encode(res) +end + +----------------------- del_mesh_device_timer -------------------- +function is_del_timer_ok(mac, timer_id) + local TMP = "/tmp/"..mac.."0" + local fd = io.open(TMP, r) + if fd then + local ret = fd:read() + ret = cjson.decode(ret) + fd:close() + if ret["timerId"] ~= timer_id then + return true + else + return nil + end + else + return nil + end +end + +function del_mesh_device_timer(mac, timer_id) + local res = {} + local ret = dbfs.fetchBluetoothDevice(mac) + local id = nil + for k ,v in pairs(ret) do + id = v.id + end + local ret = dbfs.getBleTimerId(id, timer_id) + if ret ~= "" then + dbfs.deleteBleTimer(id, timer_id) + end + + --[[ + local cmd = "/root/spi_send ".."10 "..string.format("%d", "0x"..id).. + " "..string.format("%d", "0x"..timer_id) + lue(cmd) + local flag = nil + for i = 1, 10 do + posix.sleep(1) + flag = is_del_timer_ok(mac, timer_id) + if flag then + break + end + end + if flag then + res["result"] = true + res["mac"] = mac + res["timerId"] = timer_id + else + res["result"] = false + res["mac"] = mac + res["timerId"] = timer_id + end + return res + ]] +end + +function nw_del_mesh_device_timer() + local mac = luci.http.formvalue("mac") + local timer_id = luci.http.formvalue("timerId") + local res = del_mesh_device_timer(mac, timer_id) + require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + luci.http.write_json(res) +end + +function ww_del_mesh_device_timer(mac, timer_id) + local res = del_mesh_device_timer(mac, timer_id) + require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + return cjson.encode(res) +end + +----------------------- set_encry_info -------------------- +function is_set_key_ok() + local TMP = "/tmp/0b0b" + local fd = io.open(TMP, "r") + require "MZLog".log(3, debug.getinfo(1).currentline) + if fd then + local file = fd:read() + fd:close() + if file == "00" then + local cmd = "rm /tmp/0b0b" + lue(cmd) + return true + elseif file == "01" then + return false + end + end +end + +function get_ble_device_key() + local ret = dbfs.fetchBluetoothDeviceKey() + if #ret > 0 then + return ret + else + return nil + end +end + +function set_mesh_network_pwd(old_key, new_key) + --local TMP = "/tmp/"..new_key + --local fd = io.open(TMP, "w") + --fd:write(new_key) + --fd:close() + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, old_key) + local key = new_key + require "MZLog".log(3, new_key) + local cmd = "bt_daemon -s 21" + lue(cmd) + local ret = nil + for i = 1, 10 do + ret = get_ble_device_key() + if ret then + break + else + posix.sleep(1) + end + end + + if #ret > 0 then + for k, v in pairs(ret) do + if v.key ~= old_key then + old_key = v.key + end + end + end + + local res = {} + require "MZLog".log(3, old_key) + require "MZLog".log(3, new_key) + local old_key1 = string.sub(old_key, 1, 1) + local old_key2 = string.sub(old_key, 2, 2) + local old_key3 = string.sub(old_key, 3, 3) + local old_key4 = string.sub(old_key, 4, 4) + local new_key1 = string.sub(new_key, 1, 1) + local new_key2 = string.sub(new_key, 2, 2) + local new_key3 = string.sub(new_key, 3, 3) + local new_key4 = string.sub(new_key, 4, 4) + require "MZLog".log(3, old_key1) + require "MZLog".log(3, old_key2) + require "MZLog".log(3, old_key3) + require "MZLog".log(3, old_key4) + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, debug.getinfo(1).currentline) + + --bt_daemon -s 21 + + local old_key = old_key1.." "..old_key2.." "..old_key3.." "..old_key4 + local new_key = new_key1.." "..new_key2.." "..new_key3.." "..new_key4 + local cmd = "bt_daemon -s ".."9 "..old_key.." "..new_key + lue(cmd) + require "MZLog".log(3, cmd) + local flag = nil + for i = 1, 10 do + flag = is_set_key_ok() + if flag ~= nil then + break + else + posix.sleep(1) + end + end + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, ret) + if flag then + if #ret > 0 then + for k, v in pairs(ret) do + local mac = v.mac + dbfs.updateBluetoothDevice("", key, "", "", mac) + end + end + end + + if flag then + res["result"] = true + res["newKey"] = key + else + res["result"] = false + res["newKey"] = key + end + return res +end + +function nw_set_mesh_network_pwd() + local old_key = luci.http.formvalue("oldKey") + local new_key = luci.http.formvalue("newKey") + local res = set_mesh_network_pwd(old_key, new_key) + require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + luci.http.write_json(res) +end + +function ww_set_mesh_network_pwd (old_key, new_key) + local res = set_mesh_network_pwd(old_key, new_key) + require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + return cjson.encode(res) +end + +function set_lamp_brightness() + +end + +function nw_set_lamp_brightness() + local res = set_lamp_brightness() + require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + luci.http.write_json(res) +end + +function ww_set_lamp_brightness() + local res = set_lamp_brightness() + require "MZLog".log(3, res) + require "MZLog".log(3, debug.getinfo(1).currentline) + luci.http.write_json(res) +end + +------------------------ bluetooth -------------------- diff --git a/Me_Lua/h10/meizu/dbfs.lua b/Me_Lua/h10/meizu/dbfs.lua new file mode 100644 index 0000000..2629b16 --- /dev/null +++ b/Me_Lua/h10/meizu/dbfs.lua @@ -0,0 +1,604 @@ +module ("meizu.dbfs", package.seeall) + +local sqlite3 = require("lsqlite3") +local r10db = "/etc/r10db" + +function database_busy() + return true +end + +function updateDeviceNickname(mac, nickname) + local db = sqlite3.open(r10db) + local sqlStr = string.format("update maclist set devicename = '%s' where mac = '%s'", nickname, mac) + db:busy_handler(database_busy) + db:exec(sqlStr) + return db:close() +end + +function get_dev_nick_name(mac) + local db = sqlite3.open(r10db) + local sqlStr = string.format("select devicename, orgname from maclist where mac like '%s'", mac) + db:busy_handler(database_busy) + 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 initSmbBanTable() + local db = sqlite3.open(r10db) + local sqlStr = string.format("create table if not exists SmbBanTable(mac varchar(100), smb_ban varchar(100))") + db:exec(sqlStr) + return db:close() +end + +function addSmbBanList(mac, smb_ban) + local db = sqlite3.open(r10db) + local sqlStr = string.format("insert into SmbBanTable values('%s', '%s')", mac, smb_ban) + db:busy_handler(database_busy) + db:exec(sqlStr) + return db:close() +end + +function fetchSmbBanList() + local db = sqlite3.open(r10db) + local sqlStr = string.format("select * from SmbBanTable where smb_ban = 'true'") + db:busy_handler(database_busy) + 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 deleteSmbBanList(mac) + local db = sqlite3.open(r10db) + local sqlStr = string.format("delete from SmbBanTable where mac = '%s' and smb_ban = 'true'", mac) + db:busy_handler(database_busy) + db:exec(sqlStr) + return db:close() +end + +function fetchDenyDeviceInfo(mac) + local db = sqlite3.open(r10db) + local sqlStr = string.format("select * from maclist where mac = '%s'", mac) + db:busy_handler(database_busy) + 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(r10db) + local sqlStr = string.format("ALTER TABLE maclist ADD COLUMN ip varchar(100)") + db:busy_handler(database_busy) + db:exec(sqlStr) + return db:close() +end + +function fetchAllDeviceInfo() + local db = sqlite3.open(r10db) + local sqlStr = string.format("select * from maclist") + db:busy_handler(database_busy) + 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(r10db) + local sqlStr = string.format("update maclist set orgname = '%s' where mac = '%s'", orgname, mac) + db:busy_handler(database_busy) + db:exec(sqlStr) + return db:close() +end + +function saveDeviceInfo(mac, orgname, devicename, deviceip) + local db = sqlite3.open(r10db) + local fetch = string.format("select * from maclist where mac = '%s'", mac) + db:busy_handler(database_busy) + 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 initBatchFileTable() + local db = sqlite3.open(r10db) + local sqlStr = string.format("create table if not exists batchFilesTables(hashCode varchar(100), IMEI varchar(100))") + db:exec(sqlStr) + return db:close() +end + +function fetchAllFilesIndex(ID, path) + local db = sqlite3.open(r10db) + local sqlStr = string.format("select * from FilesListTable where ID = '%s' and path = '%s'", ID, path) + db:busy_handler(database_busy) + local result = {} + for row in db:rows(sqlStr) do + if row then + table.insert(result,{ + ["name"] = row[3] + }) + end + end + db:close() + return result +end + +function fetchAllFilesList(ID, start, fetchEnd, path) + local db = sqlite3.open(r10db) + local sqlStr = string.format("select * from FilesListTable where ID = '%s' and path = '%s' ORDER BY isfile, name limit '%s' offset '%s' ", ID, path, fetchEnd, start) + db:busy_handler(database_busy) + local result = {} + for row in db:rows(sqlStr) do + if row then + table.insert(result,{ + ["name"] = row[3], + ["isfile"] = row[4], + ["size"] = row[5], + ["time"] = row[6] + }) + end + end + db:close() + return result +end + + + +function addBatchFile(hashCode, IMEI) + local db = sqlite3.open(r10db) + local sqlStr = string.format("insert into batchFilesTables values('%s', '%s')", hashCode, IMEI) + db:busy_handler(database_busy) + db:exec(sqlStr) + return db:close() +end + +function fetchAllBatchFile(IMEI) + local db = sqlite3.open(r10db) + local sqlStr = string.format("select * from batchFilesTables where IMEI = '%s'",IMEI ) + db:busy_handler(database_busy) + local result = {} + for row in db:rows(sqlStr) do + if row then + table.insert(result,{ + ["hashCode"] = row[1] + }) + end + end + db:close() + return result +end + +function fetchBatchFileEndFlag(flag, IMEI) + local db = sqlite3.open(r10db) + local sqlStr = string.format("select * from batchFilesTables where hashCode = '%s' and IMEI = '%s'", flag, IMEI) + db:busy_handler(database_busy) + local result = {} + for row in db:rows(sqlStr) do + if row then + result = { + ["hashCode"] = row[1] + } + end + end + db:close() + return result +end + +function deleteBatchFileEndFlag(flag, IMEI) + local db = sqlite3.open(r10db) + local sqlStr = string.format("delete from batchFilesTables where hashCode = '%s' and IMEI = '%s'", flag, IMEI) + db:busy_handler(database_busy) + db:exec(sqlStr) + return db:close() +end + +function deleteBatchFile(IMEI) + local db = sqlite3.open(r10db) + local sqlStr = string.format("delete from batchFilesTables where IMEI = '%s'", IMEI) + db:busy_handler(database_busy) + db:exec(sqlStr) + return db:close() +end + +function init_arp_table() + local db = sqlite3.open(r10db) + local sqlStr = string.format("create table if not exists arp(mac varchar(18), ip varchar(16))") + db:exec(sqlStr) + return db:close() +end + +function fetch_arp_mac(mac) + local db = sqlite3.open(r10db) + local sqlStr = string.format("select * from arp where mac like '%s'", mac) + db:busy_handler(database_busy) + local result = "" + for row in db:rows(sqlStr) do + if row then + result = row[1] + end + end + db:close() + return result +end + +function insert_arp_macip(mac, ip) + local db = sqlite3.open(r10db) + local sqlStr = string.format("delete from ") + sqlStr = string.format("insert into arp values('%s', '%s')", mac, ip) + db:busy_handler(database_busy) + db:exec(sqlStr) + return db:close() +end + +function delete_arp_all_mac() + local db = sqlite3.open(r10db) + local sqlStr = string.format("delete from arp") + db:busy_handler(database_busy) + db:exec(sqlStr) + return db:close() +end + +function init_wireless_device_table() + local db = sqlite3.open(r10db) + local sqlStr = string.format("create table if not exists wireless_table(mac varchar(100))") + db:exec(sqlStr) + return db:close() +end + +function fetch_wireless_device_mac(mac) + local db = sqlite3.open(r10db) + local sqlStr = string.format("select * from wireless_table where mac = '%s'", mac) + db:busy_handler(database_busy) + local result = "" + for row in db:rows(sqlStr) do + if row then + result = row[1] + end + end + db:close() + return result +end + +function fetch_all_wireless_device() + local db = sqlite3.open(r10db) + local sqlStr = string.format("select * from wireless_table") + db:busy_handler(database_busy) + 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 insert_wireless_device_mac(mac) + local db = sqlite3.open(r10db) + local sqlStr = string.format("insert into wireless_table values('%s')", mac) + db:busy_handler(database_busy) + db:exec(sqlStr) + return db:close() +end + +function init_wire_device_table() + local db = sqlite3.open(r10db) + local sqlStr = string.format("create table if not exists wire_table(mac varchar(100), ip varchar(100))") + db:exec(sqlStr) + return db:close() +end + +function fetch_wire_device_mac(mac) + local db = sqlite3.open(r10db) + local sqlStr = string.format("select * from wire_table where mac = '%s'", mac) + db:busy_handler(database_busy) + local result = "" + for row in db:rows(sqlStr) do + if row then + result = row[1] + end + end + db:close() + return result +end + +function fetch_all_wire_device() + local db = sqlite3.open(r10db) + local sqlStr = string.format("select * from wire_table") + db:busy_handler(database_busy) + local result = {} + for row in db:rows(sqlStr) do + if row then + table.insert(result,{ + ["mac"] = row[1], + ["ip"] = row[2] + }) + end + end + db:close() + return result +end + +function insert_wire_device_mac(mac, ip) + local db = sqlite3.open(r10db) + local sqlStr = string.format("insert into wire_table values('%s','%s')", mac, ip) + db:busy_handler(database_busy) + db:exec(sqlStr) + return db:close() +end + +function update_wire_device_ip(mac, ip) + local db = sqlite3.open(r10db) + local sqlStr = string.format("update wire_table set ip = '%s' where mac = '%s'", ip, mac) + db:busy_handler(database_busy) + db:exec(sqlStr) + return db:close() +end + +function delete_wire__device(mac) + local db = sqlite3.open(r10db) + local sqlStr = string.format("delete from wire_table where mac = '%s'", mac) + db:busy_handler(database_busy) + db:exec(sqlStr) + return db:close() +end + +function init_access_token_table() + local db = sqlite3.open(r10db) + 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(r10db) + local sqlStr = string.format("insert into accessTokenTable values('%s', %d)", token, expireTime) + db:busy_handler(database_busy) + db:exec(sqlStr) + return db:close() +end + +function fetch_access_token() + local db = sqlite3.open(r10db) + local sqlStr = string.format("select * from accessTokenTable") + db:busy_handler(database_busy) + 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(r10db) + local sqlStr = string.format("update accessTokenTable set token = '%s', expireTime = %d where token = '%s'", newToken, expireTime, oldToken) + db:busy_handler(database_busy) + db:exec(sqlStr) + return db:close() +end + +function delete_access_token() + local db = sqlite3.open(r10db) + local sqlStr = string.format("delete from accessTokenTable") + db:busy_handler(database_busy) + db:exec(sqlStr) + return db:close() +end + +function initBluetoothTable() + local db = sqlite3.open(r10db) + 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(r10db) + 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(r10db) + 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(r10db) + 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(r10db) + 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(r10db) + 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(r10db) + 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(r10db) + 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(r10db) + 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(r10db) + 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 +--[[ +function initBleTimerTable() + local db = sqlite3.open(r10db) + local sqlStr = string.format("create table if not exists bletimertable(id varchar(100), timer_id varchar(100), flag varchar(100), start_time varchar(100), end_time varchar(100))") + db:exec(sqlStr) + return db:close() +end + +function addBleTimer(id, timer_id, flag, start_time, end_time) + local db = sqlite3.open(r10db) + local sqlStr = string.format("insert into bletimertable values('%s', '%s', '%s', '%s', '%s')", id, timer_id, flag, start_time, end_time) + db:exec(sqlStr) + return db:close() +end + +function deleteBleTimer(id, timer_id) + local db = sqlite3.open(r10db) + local sqlStr = string.format("delete from bletimertable where id = '%s' and timer_id = '%s'", id, timer_id) + db:exec(sqlStr) + return db:close() +end + +function getBleTimerId(id, timer_id) + local db = sqlite3.open(r10db) + local sqlStr = string.format("select * from bletimertable where id = '%s' and timer = '%s'", id, timer_id) + local result = "" + for row in db:rows(sqlStr) do + if row then + result = row[2] + end + end + db:close() + return result +end +]] \ No newline at end of file diff --git a/Me_Lua/h10/meizu/disk.lua b/Me_Lua/h10/meizu/disk.lua new file mode 100644 index 0000000..1b1cfc8 --- /dev/null +++ b/Me_Lua/h10/meizu/disk.lua @@ -0,0 +1,63 @@ +module("meizu.disk", package.seeall) + +local bfs = require "meizu.bfs" +local exec_cmd_in_sh = bfs.exec_cmd_in_sh +local lue = require("luci.util").exec + +function get_disk_space() + local lu = require("luci.util") + local cmd = "df -k | grep ' /mnt' | awk '{printf $2}'" + local disk = lue(cmd) + if disk ~= "" then + return disk + else + return "0" + end +end + +function get_available_disk() + local lu = require("luci.util") + local cmd = "df -k | grep ' /mnt' | awk '{printf $4}'" + local disk = lue(cmd) + if disk ~= "" then + return disk + else + return "0" + end +end + +function get_info_imp() + local ret = {} + ret["total"] = get_disk_space() + ret["free"] = get_available_disk() + return ret; +end + +function nw_get_disk_info() + luci.http.prepare_content("application/json") + local ret = get_info_imp() + luci.http.write_json(ret) +end + +function ww_get_disk_info() + local res = {} + res = get_info_imp() + return res +end + +function disk_formatting() + local result = {} + result["result"] = false + local cmd = [[ls /dev/sda |grep -E "/dev/sd.$" |wc -l|awk '{printf $1}']] + local res = lue(cmd) + + if res == "1" then + result["result"] = true + luci.http.write_json(result) + local cmd = "hd_part.sh /dev/sda;echo $?" + exec_cmd_in_sh(cmd) + else + result["code"] = res + luci.http.write_json(result) + end +end diff --git a/Me_Lua/h10/meizu/dlfs.lua b/Me_Lua/h10/meizu/dlfs.lua new file mode 100644 index 0000000..ef2b32f --- /dev/null +++ b/Me_Lua/h10/meizu/dlfs.lua @@ -0,0 +1,670 @@ +module("meizu.dlfs", package.seeall) +-- download functions + +local cjson = require "cjson" +local lfs = require "lfs" +local bfs = require "meizu.bfs" +local RC = require "meizu.r10config" +local nixio = require "nixio" + +local b64dec = bfs.b64dec +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 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 + +local aria2rpc = "http://127.0.0.1:6800/jsonrpc" +local httpreq = require("socket.http").request +local lue = require("luci.util").exec + +function aria2_make_req_param(method, gid) + local p = [[{"jsonrpc":"2.0", "method":"]] + p = p..method..[[", ]] + p = p..[["id":1, "params":["]] + p = p..gid..'"]}' + p = p..'{"Accept=application/json, text/javascript, */*; q=0.01"}' + p = p..'{"Accept-Encoding=gzip, deflate"}' + p = p..'{"Content-Type=application/x-www-form-urlencoded; charset=UTF-8"}' + p = p..'{"Pragma=no-cache"}' + p = p..'{"Cache-Control=no-cache"}' + + return p +end + +function aria2_make_status_param(method, params) + local p = [[{"jsonrpc":"2.0", "method":"]] + p = p..method..[[", ]] + p = p..[["id":1]] + if params == "" then + p = p..'}' + else + p = p..[[, "params":[]] + p = p..params..']}' + end + p = p..'{"Accept=application/json, text/javascript, */*; q=0.01"}' + p = p..'{"Accept-Encoding=gzip, deflate"}' + p = p..'{"Content-Type=application/x-www-form-urlencoded; charset=UTF-8"}' + p = p..'{"Pragma=no-cache"}' + p = p..'{"Cache-Control=no-cache"}' + + return p +end + +function aria2_success_res(command, gid, status) + local res = [[{"result":true, "command":"]]..command..[[", "gid":"]]..gid..[[", "message":"]]..status..[["}]] + + return res +end + +function aria2_failed_res(command, gid, status) + local res = [[{"result":flase, "command":"]]..command..[[", "gid":"]]..gid..[[", "message":"]]..status..[["}]] + + return res +end + +function aria2_download_task_pause(gid, command) + local param = aria2_make_req_param("aria2.pause", gid) + local res, code, headers, status = httpreq(aria2rpc, param) + local success_res = aria2_success_res(command, gid, status) + local failed_res = aria2_failed_res(command, gid, status) + + if code == 200 then + return success_res + else + return failed_res + end +end + +function aria2_download_task_unpause(gid, command) + local param = aria2_make_req_param("aria2.unpause", gid) + local res, code, headers, status = httpreq(aria2rpc,param) + local success_res = aria2_success_res(command, gid, status) + local failed_res = aria2_failed_res(command, gid, status) + + if code == 200 then + return success_res + else + return failed_res + end +end + +function aria2_download_task_remove(gid, command) + local param = aria2_make_req_param("aria2.removeDownloadResult", gid) + local res, code, headers, status = httpreq(aria2rpc,param) + local success_res = aria2_success_res(command, gid, status) + local failed_res = aria2_failed_res(command, gid, status) + + if code == 200 then + return success_res + else + return failed_res + end +end + +function aria2_get_active_list() + local result = {} + local param = aria2_make_status_param("aria2.tellActive", "") + local res, code, headers, status = httpreq(aria2rpc, param) + + if code == 200 then + local jsd = cjson.decode(res) + for key, value in pairs(jsd.result) do + local data = {status = "", speed = nil, total = nil, + completed = nil, gid = "", file = ""} + + data.status = value.status + data.speed = tonumber(value.downloadSpeed) + data.total = tonumber(value.totalLength) + data.completed = tonumber(value.completedLength) + data.gid = value.gid + local jsd = cjson.encode(value.files) + jsd = string.sub(jsd, 2, -2) + local fn = cjson.decode(jsd) + data.file = "" + if string.match(fn.path, ".+/([^/]*%.%w+)$") then + data.file = string.match(fn.path, ".+/([^/]*%.%w+)$") + end + table.insert(result, data) + end + end + + return result +end + +function aria2_get_pause_list() + local param = aria2_make_status_param("aria2.tellWaiting", "0, 1000") + local res, code, headers, status = httpreq(aria2rpc,param) + local result = {} + if code == 200 then + local jsd = cjson.decode(res) + + for key, value in pairs(jsd.result) do + local data = {status = "", speed = nil, total = nil, + completed = nil, gid = "", file = ""} + data.status = value.status + data.speed = tonumber(value.downloadSpeed) + data.total = tonumber(value.totalLength) + data.completed = tonumber(value.completedLength) + data.gid = value.gid + local jsd = cjson.encode(value.files) + jsd = string.sub(jsd, 2, -2) + local fn = cjson.decode(jsd) + data.file = "" + if string.match(fn.path, ".+/([^/]*%.%w+)$") then + data.file = string.match(fn.path, ".+/([^/]*%.%w+)$") + end + table.insert(result, data) + end + end + + return result; +end + +function aria2_get_history_list() + local param = aria2_make_status_param("aria2.tellStopped", "0, 1000") + local result = {} + local res, code, headers, status = httpreq(aria2rpc, param) + if code == 200 then + local jsd = cjson.decode(res) + for key, value in pairs(jsd.result) do + local data = {status = "", speed = nil, total = nil, + completed = nil, gid = "", file = ""} + data.speed = tonumber(value.downloadSpeed) + data.total = tonumber(value.totalLength) + data.completed = tonumber(value.completedLength) + local jsd = cjson.encode(value.files) + jsd = string.sub(jsd, 2, -2) + local fn = cjson.decode(jsd) + data.status = value.status + data.gid = value.gid + data.file = "" + if string.match(fn.path, ".+/([^/]*%.%w+)$") then + data.file = string.match(fn.path, ".+/([^/]*%.%w+)$") + end + table.insert(result, data) + end + end + + return result +end + +function aria2_download_task_start(url) + local param = '[{"jsonrpc":"2.0", "method":"aria2.addUri", "id":"1",'.. + '"params":[['..'"'..url..'"'.."]]}]" + local res, code, headers, status = httpreq(aria2rpc, param) + local jsd = nil + if code == 200 then + res = string.sub(res, 2, -2) + jsd = cjson.decode(res) + end + local success_res = '{"result":true, "gid":'..'"'..jsd.result..'"'.. + ', "message":'..'"'..status..'"'.."}" + local failed_res = '{"result":false, "message":'..'"'..status..'"'.."}" + + if code == 200 then + return success_res + else + return failed_res + end +end + +function thunder_clean_list_log() + if nixio.fs.access("/tmp/tdal.log") then + nixio.fs.unlink("/tmp/tdal.log") + end + if nixio.fs.access("/tmp/tdhl.log") then + nixio.fs.unlink("/tmp/tdhl.log") + end +end + +function thunder_download_task_pause(gid, command) + thunder_clean_list_log() + local success_res = '{"result":true, "command":'..'"'..command..'"'.. + ', "gid":'..'"'..gid..'"'.. + ', "message":'..'"success"'.."}" + local cmd = "/usr/bin/xunleiR.py pause "..gid + local ret = lue(cmd) + + return success_res +end + +function download_task_pause(gid, command) + if string.match(gid, "^tdid_") then + local tdid = string.sub(gid, 6) + return thunder_download_task_pause(tdid, command) + else + return aria2_download_task_pause(gid, command) + end +end + +function thunder_download_task_unpause(gid, command) + thunder_clean_list_log() + local success_res = '{"result":true, "command":'.. + '"'..command..'"'..', "gid":'.. + '"'..gid..'"'..', "message":'..'"success"'.."}" + local cmd = "/usr/bin/xunleiR.py start "..gid + local ret = lue(cmd) + + return success_res +end + +function download_task_unpause(gid, command) + if string.match(gid, "^tdid_") then + local tdid = string.sub(gid, 6) + return thunder_download_task_unpause(tdid, command) + else + return aria2_download_task_unpause(gid, command) + end +end + +function thunder_download_task_remove(gid, command) + thunder_clean_list_log() + local success_res = '{"result":true, "command":'.. + '"'..command..'"'..', "gid":'.. + '"'..gid..'"'..', "message":'..'"success"'.."}" + --local cmd = "/usr/bin/xunleiR.py remove "..gid + local cmd = "/usr/bin/xunleiR.py delete "..gid + local ret = lue(cmd) + require "MZLog".log(3, ret) + + return success_res +end + +function download_task_remove(gid, command) + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, gid) + require "MZLog".log(3, debug.getinfo(1).currentline) + if string.match(gid, "^tdid_") then + local tdid = string.sub(gid, 6) + return thunder_download_task_remove(tdid, command) + else + return aria2_download_task_remove(gid, command) + end +end + +function get_pause_list() + local result = aria2_get_pause_list() + local ret_msg = "" + if nil ~= next(result) then + --result = cjson.encode(result) + local jsr = data_to_json(result) + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, jsr) + require "MZLog".log(3, debug.getinfo(1).currentline) + ret_msg = '{"result":true, "message":'..jsr.."}" + else + ret_msg = '{"result":false, "message":[]}' + end + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, ret_msg) + require "MZLog".log(3, debug.getinfo(1).currentline) + + return ret_msg +end + +function nw_get_pause_list() + local data = get_pause_list() + luci.http.write(data) +end + +function thunder_get_bind_code() + local ret = {} + local lue = require"luci.util".exec + local cmd = [[/usr/bin/xunleiR.py sysinfo|awk -F',' '{print $5}']] + local code = lue(cmd) + ret = '{"code":'..code..'}' + + return ret +end + +function nw_thunder_get_bind_code() + local data = thunder_get_bind_code() + luci.http.write(data) +end + +function ww_thunder_get_bind_code() + return thunder_get_bind_code() +end + +function thunder_state_code(code) + local ret = "active" + if code == 0 or code == 8 or code == 13 or code == 14 or code == 37 then + ret = "active" + end + if code == 9 or code == 10 then + ret = "paused" + end + if code == 11 or code == 15 then + ret = "complete" + end + + return ret +end + +function thunder_localpath_translate(path) + if type(path) == "string" then + path = string.gsub(path, "/opt/xware/mnt/", "/router/Thunder/") + end + return path +end + +function thunder_get_active_list() + local cmd = "/usr/bin/xunleiR.py list" + local ret + require "MZLog".log(3, debug.getinfo(1).currentline) + if nixio.fs.access("/tmp/tdal.log") then + local fp = io.open("/tmp/tdal.log", "r") + local data = fp:read("*a") + ret = data + fp:close() + else + ret = lue(cmd) + local fp = io.open("/tmp/tdal.log", "wb") + fp:write(ret) + fp:close() + end + local result = {} + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, ret) + require "MZLog".log(3, debug.getinfo(1).currentline) + if ret then + require "MZLog".log(3, debug.getinfo(1).currentline) + local jsd = cjson.decode(ret) + local tasks = jsd.tasks + for k, v in pairs(tasks) do + local data = {} + if (_G.next(v) ~= nil) then + data.speed = v.speed + data.status = thunder_state_code(v.state) + data.total = tonumber(v.size) + data.completed = tonumber(data.total * tonumber(v.progress)/10000) + data.file = v.name + data.path = thunder_localpath_translate(v.path) + data.gid = 'tdid_'..v.id + end + table.insert(result, data) + end + end + + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, data_to_json(result)) + require "MZLog".log(3, debug.getinfo(1).currentline) + return result +end + +function thunder_get_rlist() + thunder_clean_list_log() + local cmd = "/usr/bin/xunleiR.py rlist" + local ret = lue(cmd) + local jsd = cjson.decode(ret) + local tasks = jsd.tasks + local result = {} + for k, v in pairs(tasks) do + local data = {} + if (_G.next(v) ~= nil) then + data.speed = v.speed + data.status = thunder_state_code(v.state) + data.total = tonumber(v.size) + data.completed = tonumber(data.total * tonumber(v.progress)/10000) + data.file = v.name + data.gid = 'tdid_'..v.id + end + table.insert(result, data) + end + + return result +end + +function get_active_list(start, refine_cnt) + local s = 0 + local cnt + if start then + s = start + end + local result = {} + local aria2_alist = aria2_get_active_list() + local thunder_alist = thunder_get_active_list() + local aria2_plist = aria2_get_pause_list() + --local thunder_rlist = thunder_get_rlist() + if _G.next(aria2_alist) then + result = table_merge(result, aria2_alist) + end + if _G.next(thunder_alist) then + result = table_merge(result, thunder_alist) + end + if _G.next(aria2_plist) then + result = table_merge(result, aria2_plist) + end + + local ret_msg = {} + local total = require("table").getn(result) + ret_msg["total"] = total + ret_msg["result"] = false + local ret = {} + if _G.next(result) then + if refine_cnt then + cnt = refine_cnt + else + cnt = total + end + local pos = 0 + for k, v in pairs(result) do + if pos >= s and (pos - s + 1 <= cnt) then + table.insert(ret, v) + pos = pos + 1 + end + end + ret_msg["result"] = true + ret_msg["message"] = ret + else + ret_msg["message"] = "[]" + end + ret_msg["start"] = s + if ret and type(ret) == "table" and _G.next(ret) then + ret_msg["count"] = require("table").getn(ret) + else + ret_msg["count"] = 0 + end + ret_msg = data_to_json(ret_msg) + require "MZLog".log(3, ret_msg) + + return ret_msg +end + +function nw_get_active_list() + local data = get_active_list() + luci.http.write(data) +end + +function thunder_get_history_list() + local cmd = "/usr/bin/xunleiR.py clist" + local ret + if nixio.fs.access("/tmp/tdhl.log") then + local fp = io.open("/tmp/tdhl.log", "r") + local data = nixio.fs.readfile("/tmp/tdhl.log") + ret = data + else + ret = lue(cmd) + local fp = io.open("/tmp/tdhl.log", "wb") + fp:write(ret) + fp:close() + end + + local jsd = cjson.decode(ret) + local tasks = jsd.tasks + local result = {} + for k, v in pairs(tasks) do + local data = {} + if (_G.next(v) ~= nil) then + data.speed = v.speed + data.total = tonumber(v.size) + data.completed = v.size + data.status = thunder_state_code(v.state) + data.file = v.name + data.path = thunder_localpath_translate(v.path) + data.gid = 'tdid_'..v.id + end + table.insert(result, data) + end + return result +end + +function get_history_list(start, refine_cnt) + local s = 0 + local cnt + require "MZLog".log(3, debug.getinfo(1).currentline) + if start then + s = start + require "MZLog".log(3, start) + end + if refine_cnt then + require "MZLog".log(3, refine_cnt) + end + require "MZLog".log(3, debug.getinfo(1).currentline) + local result = {} + local aria2_ret = aria2_get_history_list() + local thunder_ret = thunder_get_history_list() + + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, data_to_json(aria2_ret)) + require "MZLog".log(3, debug.getinfo(1).currentline) + + if nil ~= _G.next(aria2_ret) then + table_merge(result, aria2_ret) + end + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, data_to_json(thunder_ret)) + require "MZLog".log(3, debug.getinfo(1).currentline) + if _G.next(thunder_ret) then + table_merge(result, thunder_ret) + end + + require "MZLog".log(3, debug.getinfo(1).currentline) + local total = require("table").getn(result) + local ret_msg = {} + require "MZLog".log(3, debug.getinfo(1).currentline) + ret_msg["total"] = total + ret_msg["result"] = false + if _G.next(result) then + require "MZLog".log(3, debug.getinfo(1).currentline) + local cnt + if refine_cnt then + cnt = refine_cnt + else + cnt = total + end + local ret = {} + local pos = 0 + for k, v in pairs(result) do + if pos >= s and (pos - s + 1 <= cnt) then + table.insert(ret, v) + pos = pos + 1 + end + end + ret_msg["count"] = require("table").getn(ret) + local jsd = data_to_json(ret) + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, jsd) + require "MZLog".log(3, debug.getinfo(1).currentline) + ret_msg["result"] = true + --ret_msg["message"] = jsd + ret_msg["message"] = ret + else + ret_msg["message"] = "[]" + end + ret_msg["start"] = s + if ret and type(ret) == "table" and _G.next(ret) then + ret_msg["count"] = require("table").getn(ret) + else + ret_msg["count"] = 0 + end + require "MZLog".log(3, debug.getinfo(1).currentline) + ret_msg = data_to_json(ret_msg) + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, ret_msg) + require "MZLog".log(3, debug.getinfo(1).currentline) + + return ret_msg +end + +function nw_get_history_list() + local data = get_history_list() + luci.http.write(data) +end + +function thunder_download_task_start(url) + thunder_clean_list_log() + local ret = "" + local cmd = [[/usr/bin/xunleiR.py download ']]..url..[[']] + require "MZLog".log(3, cmd) + ret = lue(cmd) + require "MZLog".log(3, ret) + local jsr = cjson.decode(ret) + ret = {} + ret["message"] = "" + ret["result"] = false + if jsr and jsr.rtn then + require "MZLog".log(3, jsr.rtn) + ret["rtn"] = jsr.rtn + if jsr.rtn == 0 or jsr.rtn == 202 then + ret["result"] = true + end + end + + if jsr and jsr.id then + ret["gid"] = "tdid_"..jsr.id + else + ret["gid"] = "tdid_0" + end + + return data_to_json(ret) +end + +function download_task_start(url, dltype) + require "MZLog".log(3, url) + require "MZLog".log(3, dltype) + local res = "" + if dltype == "thunder" then + res = thunder_download_task_start(url) + else + res = aria2_download_task_start(url) + end + require "MZLog".log(3, res) + + return res +end + +function nw_download_task_start() + local url = luci.http.formvalue("url") + local dltype = luci.http.formvalue("type") + local res = download_task_start(url, dltype) + luci.http.write(res) + + return res +end + +function download_task_operate(gid, command) + if command == "downloadpause" then + return download_task_pause(gid, command) + elseif command == "downloadunpause" then + return download_task_unpause(gid, command) + elseif command == "downloadremove" then + return download_task_remove(gid, command) + end +end + +function nw_download_task_operate() + local command = luci.http.formvalue("command") + local gid = luci.http.formvalue("gid") + local ret = download_task_operate(gid, command) + + luci.http.write(ret) +end diff --git a/Me_Lua/h10/meizu/nwfs.lua b/Me_Lua/h10/meizu/nwfs.lua new file mode 100644 index 0000000..417c120 --- /dev/null +++ b/Me_Lua/h10/meizu/nwfs.lua @@ -0,0 +1,1747 @@ +module("meizu.nwfs", package.seeall) +--network functions + +local cjson = require "cjson" +local lfs = require "lfs" +local bfs = require "meizu.bfs" +local RC = require "meizu.r10config" + +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 b64dec = bfs.b64dec +local b64enc = bfs.b64enc + +local lue = require("luci.util").exec + +function get_connect_info() + --usr/lib/lua/luci/controller/admin/network.lua lease_status() + local rv = { } + local s = require "luci.tools.status" + + luci.http.prepare_content("application/json") + rv = s.dhcp_leases() + for k, v in pairs(rv) do + v.netswitch = "true" + v.diskswitch = "true" + v.netspeed = 0 + v.onnettime = 0 + v.netflow = 0 + end + luci.http.write_json(rv) +end + +function wifi_network(wifi_device_name) + local network = require "luci.model.network".init() + local wifi_net = network:get_wifinet(wifi_device_name) + if wifi_net then + local dev = wifi_net:get_device() + if dev then + return { + id = wifi_device_name, + name = wifi_net:shortname(), + up = wifi_net:is_up(), + mode = wifi_net:active_mode(), + ssid = wifi_net:active_ssid(), + bssid = wifi_net:active_bssid(), + encryption = wifi_net:active_encryption(), + encryption_src = wifi_net:get("encryption"), + frequency = wifi_net:frequency(), + bitrate = wifi_net:bitrate(), + ifname = wifi_net:ifname(), + assoclist = wifi_net:assoclist(), + country = wifi_net:country(), + key = wifi_net:get("key"), + key1 = wifi_net:get("key1"), + hidden = wifi_net:get("hidden"), + device = { + up = dev:is_up(), + device = dev:name(), + name = dev:get_i18n() + } + } + end + end + return {} +end + +function wifi_networks() + 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 wifi_net + for _, wifi_net in ipairs(dev:get_wifinets()) do + rd.networks[#rd.networks+1] = { + name = wifi_net:shortname(), + up = wifi_net:is_up(), + mode = wifi_net:active_mode(), + ssid = wifi_net:active_ssid(), + bssid = wifi_net:active_bssid(), + encryption = wifi_net:active_encryption(), + frequency = wifi_net:frequency(), + channel = wifi_net:channel(), + signal = wifi_net:signal(), + quality = wifi_net:signal_percent(), + noise = wifi_net:noise(), + bitrate = wifi_net:bitrate(), + ifname = wifi_net:ifname(), + assoclist = wifi_net:assoclist(), + country = wifi_net:country(), + key = wifi_net:get("key"), + key1 = wifi_net:get("key1"), + encryption_src = wifi_net:get("encryption"), + hidden = wifi_net:get("hidden"), + } + end + result[#result+1] = rd + end + return result +end + +function nw_get_wifi_settings() + luci.http.prepare_content("application/json") + local app_version = luci.http.formvalue("appVer") + if app_version == nil then + app_version = 0 + end + local list = get_wifi_settings(app_version) + luci.http.write(list) +end + +function ww_get_wifi_settings(app_version) + local list = get_wifi_settings(app_version) + --return data_to_json(list) + return list +end + +function get_wifi_settings(app_version) + local network = require "luci.model.network".init() + local info_list = {} + local wifis = wifi_networks() + for i,wifi_net in ipairs(wifis) do + local item = {} + local index = 1 + + if wifi_net.device == "wl0" then + local wifi_net_wl0 = network:get_wifinet('wl0.network1') + if wifi_net_wl0:get("disabled") == "1" then + item["status"] = "false" + else + item["status"] = "true" + end + end + + if wifi_net.device == "wl1" then + local wifi_net_wl1 = network:get_wifinet('wl1.network1') + if wifi_net_wl1:get("disabled") == "1" then + item["status"] = "false" + else + item["status"] = "true" + end + end + + local encryption = wifi_net.networks[index].encryption_src + local key = wifi_net.networks[index].key + if encryption == "wep-open" then + key = wifi_net.networks[index].key1 + if key:len()>4 and key:sub(0,2)=="s:" then + key = key:sub(3) + end + end + item["name"] = wifi_net.networks[index].ifname + item["ssid"] = wifi_net.networks[index].ssid + if key == nil then + key = "" + end + item["password"] = key + item["encryption"] = encryption + info_list[#wifis+1-i] = item + end + local guestwifi = get_guest_wifi(1) + if guestwifi then + table.insert(info_list, guestwifi) + end + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, info_list) + if tonumber(app_version) >= 5 then + return b64enc(cjson.encode(info_list)) + else + return cjson.encode(info_list) + end +end + +function get_wifi_ssids() + local wifis = wifi_networks() + local ssid1 = "" + local ssid2 = "" + for i, wifi_net in ipairs(wifis) do + if i == 1 then + ssid1 = wifi_net.networks[1].ssid + end + if i == 2 then + ssid2 = wifi_net.networks[1].ssid + end + end + + return ssid1, ssid2 +end + +function nw_wifi_settings() + + luci.http.prepare_content("application/json") + local data = luci.http.formvalue("data") + local app_version = luci.http.formvalue("appVer") + if app_version == nil then + app_version = 0 + end + local switch_2g = nil + local switch_5g = nil + local switch_guest = nil + local ssid_2g = nil + local ssid_5g = nil + local ssid_guest = nil + local pwd_2g = nil + local pwd_5g = nil + local pwd_guest = nil + local encry_2g = nil + local encry_5g = nil + local encry_guest = nil + + if tonumber(app_version) >= 5 then + local data = b64dec(data) + data = cjson.decode(data) + + for k, v in pairs(data) do + if v.name == "wl0" then + switch_2g = v.on + ssid_2g = v.ssid + pwd_2g = v.pwd + encry_2g = v.encryption + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, debug.getinfo(1).currentline) + elseif v.name == "wl1" then + switch_5g = v.on + ssid_5g = v.ssid + pwd_5g = v.pwd + encry_5g = v.encryption + else + switch_guest = v.on + ssid_guest = v.ssid + pwd_guest = v.pwd + encry_guest = v.encryption + end + end + else + switch_2g = luci.http.formvalue("on1") + ssid_2g = luci.http.formvalue("ssid1") + pwd_2g = luci.http.formvalue("pwd1") + encry_2g = luci.http.formvalue("encryption1") + + switch_5g = luci.http.formvalue("on2") + ssid_5g = luci.http.formvalue("ssid2") + pwd_5g = luci.http.formvalue("pwd2") + encry_5g = luci.http.formvalue("encryption2") + + switch_guest = luci.http.formvalue("on3") + ssid_guest = luci.http.formvalue("ssid3") + pwd_guest = luci.http.formvalue("pwd3") + encry_guest = luci.http.formvalue("encryption3") + end + + local res = wifi_settings(switch_2g, ssid_2g, pwd_2g, encry_2g, switch_5g, ssid_5g, pwd_5g, encry_5g, switch_guest, ssid_guest, pwd_guest, encry_guest) + luci.http.write_json(res) +end + +function wifi_settings(switch_2g, ssid_2g, pwd_2g, encry_2g, switch_5g, ssid_5g, pwd_5g, encry_5g, switch_guest, ssid_guest, pwd_guest, encry_guest) + local result = {} + local res = {} + local details = {} + --local code = 0 + local code_2g = 0 + local code_5g = 0 + local code_guest = 0 + local code_2g = check_ssid(ssid_2g, 31) + local code_5g = check_ssid(ssid_5g, 31) + local code_guest = check_ssid(ssid_guest, 31) + local succeed_2g = false + local succeed_5g = false + local succeed_guest = false + + if switch_2g == "false" then + succeed_2g = set_wifi_basic_info(1, nil, nil, nil, switch_2g) + else + if code_2g == 1 then + succeed_2g = set_wifi_basic_info(1, ssid_2g, pwd_2g, encry_2g, switch_2g) + end + end + + if switch_5g == "false" then + succeed_5g = set_wifi_basic_info(2, nil, nil, nil, switch_5g) + else + if code_5g == 1 then + succeed_5g = set_wifi_basic_info(2, ssid_5g, pwd_5g, encry_5g, switch_5g) + end + end + + local wifirestart = true + if switch_guest == "true" then + switch_guest = 1 + if set_guest(1, ssid_guest, encry_guest, pwd_guest, 1, switch_guest) then + succeed_guest = true + --code = 0 + else + succeed_guest = false + wifirestart = false + end + elseif switch_guest == "false" then + switch_guest = 0 + if set_guest(1, nil, nil, nil, 0, switch_guest) then + succeed_guest = true + end + else + return nil + end + + if code_2g ~= 0 and code_5g ~= 0 and code_guest ~= 0 and succeed_2g ~= false + and succeed_5g ~= false and succeed_guest ~= false then + + res["result"] = true + if wifirestart then + fork_restart_wifi() + end + else + res["result"] = false + end + + return res +end + +function set_wifi_basic_info(wifi_index, ssid, password, encryption, on) + + local network = require "luci.model.network".init() + if wifi_index == 1 then + wifi_net = network:get_wifinet('wl0.network1') + wifi_dev = network:get_wifidev('wl0') + end + + if wifi_index == 2 then + wifi_net = network:get_wifinet('wl1.network1') + wifi_dev = network:get_wifidev('wl1') + end + + if wifi_net == nil then + return false + end + + if wifi_dev then + if on == "true" then + wifi_net:set("disabled", "0") + elseif on == "false" then + wifi_net:set("disabled", "1") + end + end + + if not is_str_nil(ssid) and check_ssid(ssid) then + wifi_net:set("ssid",ssid) + end + + local code = check_wifi_passwd(password,encryption) + if code == 0 then + wifi_net:set("encryption",encryption) + wifi_net:set("key",password) + if encryption == "none" then + wifi_net:set("key","") + elseif encryption == "wep-open" then + wifi_net:set("key1","s:"..password) + wifi_net:set("key",1) + end + elseif code > 1502 then + return false + end + + network:save("wireless") + network:commit("wireless") + return true +end + +function is_str_nil(str) + return (str == nil or str == "") +end + +function check_ssid(ssid) + if is_str_nil(ssid) then + return 0 + end + + return 1 + --[[ + if string.match(ssid,"^%w[%w_.-]*%w$") or string.match(ssid, "^%w$") or + string.match(ssid, "^%w[%w_.-]*$") or string.match(ssid,"^[%w_.-]*$") or + string.match(ssid, "^[%w_.-]*%w$") then + return 1 + else + return 0 + end + ]] +end + +function check_wifi_passwd(passwd,encryption) + if is_str_nil(encryption) or (encryption and encryption ~= "none" and is_str_nil(passwd)) then + return 1502 + end + if encryption == "psk" or encryption == "psk2" then + if passwd:len() < 8 then + return 1520 + end + elseif encryption == "mixed-psk" then + if passwd:len()<8 or passwd:len()>63 then + return 1521 + end + elseif encryption == "wep-open" then + if passwd:len()~=5 and passwd:len()~=13 then + return 1522 + end + end + --[[ + if passwd ~= "" then + local ret = string.match(passwd, "^%w[^&\\%%+]*%w$") or string.match(passwd, "^%w[^&\\%%+]*$") + if ret == nil or string.find(passwd,'"') then + return 1523 + end + end + ]] + return 0 +end + +function fork_restart_wifi() + local FORK_RESTART_WIFI = "sleep 1; /sbin/wifi >/dev/null 2>/dev/null; /etc/init.d/minidlna restart; /etc/init.d/samba restart; /usr/bin/gettraffic flush_wl_dev >/dev/null 2>/dev/null" + exec_cmd_in_sh(FORK_RESTART_WIFI) +end + +function fork_restart_network() + local FORK_RESTART_WORK= "/etc/init.d/network restart" + exec_cmd_in_sh(FORK_RESTART_WORK) +end + +function check_guest_wifi() + local uci = require("luci.model.uci").cursor() + local guest = uci:get_all("network", "eth0_3") + if guest then + return true + else + return false + end +end + +function set_guest(wifi_index, ssid, encryption, key, enabled, open) + local success = set_guest_wifi(wifi_index, ssid, encryption, key, enabled, open) + if not success then + return false + end + local networkrestart = true + if check_guest_wifi() then + networkrestart = false + end + if networkrestart then + local lanip = get_lan_ip() + local lan = lanip:gsub(".%d+.%d+$", "") + local cip = tonumber(lanip:match(".(%d+).%d+$")) + local nixio = require("nixio") + local bit = nixio.bit + cip = bit.bor(bit.band(1, cip + 1), bit.lshift(bit.rshift(cip, 1), 1)) + lanip = lan.."."..tostring(cip)..".1" + exec_cmd_in_sh("sleep 4; /usr/sbin/guest_ssid_network start "..lanip.." 255.255.255.0 >/dev/null 2>/dev/null") + else + fork_restart_wifi() + end + return true +end + +function set_guest_wifi(wifi_index, ssid, encryption, key, enabled, open) + local uci = require("luci.model.uci").cursor() + local wifinetid, ifname + local enabled = tonumber(enabled) == 1 and 1 or 0 + local open = tonumber(open) == 1 and 1 or 0 + if tonumber(wifi_index) == 1 then + wifinetid = "wl0iface1" + ifname = uci:get_all("wireless", "@wifi-iface[1]","ifname") + else + return false + end + guestwifi = uci:get_all("wireless", wifinetid) + if guestwifi then + guestwifi["ifname"] = ifname + if not is_str_nil(ssid) and check_ssid(ssid) then + guestwifi["ssid"] = ssid + end + if encryption and string.lower(tostring(encryption)) == "none" then + guestwifi["encryption"] = "none" + guestwifi["key"] = "" + end + if enabled == 1 then + guestwifi["disabled"] = 0 + elseif enabled == 0 then + guestwifi["disabled"] = 1 + else + end + + if open then + guestwifi["open"] = open + end + if encryption and string.lower(tostring(encryption)) ~= "none" and not is_str_nil(key) then + local check = check_wifi_passwd(key,encryption) + if check == 0 then + guestwifi["encryption"] = encryption + guestwifi["key"] = key + else + return false + end + end + else + if is_str_nil(ssid) or is_str_nil(encryption) then + return false + end + guestwifi = { + ["ifname"] = ifname, + ["network"] = "guest", + ["ssid"] = ssid, + ["mode"] = "ap", + ["encryption"] = encryption, + ["key"] = key, + ["open"] = open, + ["enabled"] = enabled + } + end + uci:section("wireless", "wifi-iface", wifinetid, guestwifi) + uci:commit("wireless") + return true +end + +function get_lan_ip() + local uci = require("luci.model.uci").cursor() + local lan = uci:get_all("network", "lan") + return lan.ipaddr +end + +function get_guest_wifi(wifiIndex) + local uci = require("luci.model.uci").cursor() + local index = tonumber(wifiIndex) + local status + local guestwifi + guestwifi = uci:get_all("wireless","wl0iface1") + if guestwifi then + if guestwifi.disabled == "1" then + status = "false" + else + status = "true" + end + + if guestwifi.key == nil then + guestwifi.key = "none" + end + + return { + ["name"] = "guest", + ["ssid"] = guestwifi.ssid, + ["encryption"] = guestwifi.encryption, + ["password"] = guestwifi.key, + ["status"] = status, + } + end + return guestwifi +end + +function macFormat(mac) + if mac then + return string.upper(string.gsub(mac, "-", ":")) + else + return "" + end +end + +function getAllWifiConnetDeviceDict() + local result = {} + for index = 1,3 do + local wifilist = getWifiConnectDeviceList(index) + for _, mac in pairs(wifilist) do + local item = {} + item['wifiIndex'] = index + result[macFormat(mac)] = item + end + end + return result +end + +function getWifiConnectDeviceList(wifiIndex) + local assoclist = {} + if tonumber(wifiIndex) == 1 then + assoclist = wifi_network('wl0.network1').assoclist or {} + elseif tonumber(wifiIndex) == 2 then + assoclist = wifi_network('wl1.network1').assoclist or {} + else + assoclist = wifi_network('wl0.network2').assoclist or {} + end + local dlist = {} + for mac, info in pairs(assoclist) do + table.insert(dlist, macFormat(mac)) + end + return dlist +end + +function getDHCPLists() + local NixioFs = require("nixio.fs") + local LuciUci = require("luci.model.uci") + local uci = LuciUci.cursor() + local result = {} + local leasefile = "/var/dhcp.leases" + uci:foreach("dhcp", "dnsmasq", + function(s) + if s.leasefile and NixioFs.access(s.leasefile) then + leasefile = s.leasefile + return false + end + end) + local dhcp = io.open(leasefile, "r") + if dhcp then + for line in dhcp:lines() do + if line then + local ts, mac, ip, name = line:match("^(%d+) (%S+) (%S+) (%S+)") + if name == "*" then + name = "" + end + if ts and mac and ip and name then + result[#result+1] = { + mac = macFormat(mac), + ip = ip, + name = name, + sp = 0 + } + end + end + end + dhcp:close() + return result + else + return false + end +end + +function getDHCPDict() + local dhcpDict = {} + local dhcpList = getDHCPLists() + for _,value in ipairs(dhcpList) do + dhcpDict[value.mac] = value + end + return dhcpDict +end + +function getDHCPIpDicts() + local dhcpDict = {} + local dhcpList = getDHCPLists() + for _,value in ipairs(dhcpList) do + dhcpDict[value.ip] = value + end + return dhcpDict +end + +function getDeviceInfoFromDB() + local dbfs = require("meizu.dbfs") + local result = {} + local deviceList = dbfs.fetchAllDeviceInfo() + if #deviceList > 0 then + for _, device in ipairs(deviceList) do + result[device.mac] = device + end + end + return result +end + +function is_device_online(ip) + local lu = require("luci.util") + --local cmd = "ping -W 2 -c 1 www.baidu.com > /dev/null ;echo -n $?" + local cmd = "ping -W 2 -c 1 " .. ip .. " > /dev/null ;echo -n $?" + local pingresult = lu.exec(cmd) + + local res = nil + if pingresult == "0" then + res = true + else + res = false + + end + + return res +end + +function get_connect_device_list() + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, require"socket".gettime()*1000) + local dbfs = require("meizu.dbfs") + dbfs.change_maclist_table() + local LuciUtil = require("luci.util") + local deviceList = {} + local dhcpDeviceDict = getDHCPDict() + local wifiDeviceDict = getAllWifiConnetDeviceDict() + -- local dhcpDevIpDict = getNetConnect() + + local blacklist0 = getMacfilterList(0) + if next(blacklist0) ~= nil then + for _, mac in pairs(blacklist0) do + local flag = 0 + for key, value in pairs(dhcpDeviceDict) do + if value.mac == mac then + flag = 1 + break + end + end + if flag == 0 then + local res = dbfs.fetchDenyDeviceInfo(mac) + if #res > 0 then + for _, device in ipairs(res) do + dhcpDeviceDict[device.mac] = device + end + end + end + end + end + + 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 wire_table = {} + for k, v in pairs(ipmacs) do + local ipmac = strsplit(v, ',') + local ip = ipmac[1] + local mac = string.upper(ipmac[2]) + local flag = false + local res = dbfs.fetch_all_wireless_device() + + if #res > 0 then + for key, value in pairs(res) do + if mac == value.mac then + flag = true + break + end + end + end + if flag == false then + local res = {} + res.mac = mac + res.ip = ip + res.name = "" + table.insert(wire_table, res) + end + end + + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, wire_table) + for k, v in pairs(wire_table) do + local flag = false + for key, value in pairs(dhcpDeviceDict) do + local mac = macFormat(key) + + if v.mac == mac then + local dhcpinfo = dhcpDeviceDict[mac] + v["name"] = dhcpinfo.name + dbfs.updateDeviceOrgname(mac, dhcpinfo.name) + flag = true + break + end + end + if flag == false then + dhcpDeviceDict[v.mac] = v + end + end + + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, debug.getinfo(1).currentline) + + local deviceDBDict = getDeviceInfoFromDB() + for key, item in pairs(dhcpDeviceDict) do + local item = {} + local mac = macFormat(key) + local deviceDB = deviceDBDict[mac] + local dhcpinfo = dhcpDeviceDict[mac] + if deviceDB ~= nil then + item["devicename"] = deviceDB.orgname + if deviceDB.devicename ~= '' then + item["devicename"] = deviceDB.devicename + end + else + item["devicename"] = dhcpinfo.name + dbfs.saveDeviceInfo(mac, dhcpinfo.name, "", dhcpinfo.ip) + end + + local black0 = blacklist0[mac] + if black0 ~= nil then + item["enable"] = false + else + item["enable"] = true + end + + local wifiType = wifiDeviceDict[mac] + local online = dhcpDeviceDict[mac] + if wifiType ~= nil then + if wifiType.wifiIndex == 1 or wifiType.wifiIndex == 3 then + item["type"] = "2.4G" + elseif wifiType.wifiIndex == 2 then + item["type"] = "5G" + end + elseif wifiType == nil and online ~= nil and black0 == nil then + local wireless_res = dbfs.fetch_wireless_device_mac(mac) + if wireless_res == "" and mac ~= "00:00:00:00:00:00" then + item["type"] = "wire" + else + item["type"] = "unknown" + end + else + item["type"] = "unknown" + end + + if online ~= nil and black0 == nil and item["type"] ~= "unknown" then + item["online"] = true + else + item["online"] = false + end + + item["ip"] = dhcpinfo.ip + item["mac"] = mac + -- item["netSpeed"] = tostring(dhcpinfo.ip.rx_bytes or 0) + deviceList[#deviceList+1] = item + end + --[[ + if blacklist0 ~= nil then + for _, mac in pairs(blacklist0) do + local item = {} + local mac = macFormat(mac) + local deviceDB = deviceDBDict[mac] + local dhcpdevice = dhcpDeviceDict[mac] + if dhcpdevice == nil then + if deviceDB ~= nil then + item["devicename"] = deviceDB.orgname + if deviceDB.devicename ~= '' then + item["devicename"] = deviceDB.devicename + end + end + local wifiType = wifiDeviceDict[mac] + if wifiType ~= nil then + if wifiType.wifiIndex == 1 then + item["type"] = "2.4G" + elseif wifiType.wifiIndex == 2 then + item["type"] = "5G" + end + else + item["type"] = "lan" + end + item["enable"] = false + item["online"] = false + item["ip"] = "null" + item["mac"] = mac + --item["diskaccess"] = false + -- item["netSpeed"] = tostring(dhcpinfo.ip.rx_bytes or 0) + deviceList[#deviceList+1] = item + end + end + end + if blacklist1 ~= nil then + for _,mac in pairs(blacklist1) do + local item = {} + local mac = macFormat(mac) + local deviceDB = deviceDBDict[mac] + local dhcpdevice = dhcpDeviceDict[mac] + if dhcpdevice == nil then + if deviceDB ~= nil then + item["devicename"] = deviceDB.orgname + if deviceDB.devicename ~= '' then + item["devicename"] = deviceDB.devicename + end + end + + local wifiType = wifiDeviceDict[mac] + if wifiType ~= nil then + if wifiType.wifiIndex == 1 then + item["type"] = "2.4G" + elseif wifiType.wifiIndex == 2 then + item["type"] = "5G" + end + else + item["type"] = "lan" + end + item["enable"] = false + item["online"] = false + item["ip"] = "null" + item["mac"] = mac + --item["diskaccess"] = false + -- item["netSpeed"] = tostring(dhcpinfo.ip.rx_bytes or 0) + deviceList[#deviceList+1] = item + end + end + end + ]] + --[[ + local str = 0xffdddddd + str = string.format("%u",str) + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, str) + require "MZLog".log(3, debug.getinfo(1).currentline) + ]] + require "MZLog".log(3, require"socket".gettime()*1000) + return deviceList +end + +function ww_get_connect_device_list() + local result = get_connect_device_list() + return result +end + +function nw_get_connect_device_list() + luci.http.prepare_content("application/json") + local result = get_connect_device_list() + luci.http.write_json(result) +end + +function nw_set_device_name() + local mac = luci.http.formvalue("mac") + local devicename = luci.http.formvalue("devicename") + set_device_name(mac,devicename) +end + +function set_device_name(mac,devicename) + local code = 0 + local deviceList = {} + local dbfs = require("meizu.dbfs") + + if is_str_nil(mac) or is_str_nil(devicename) then + code = 1502 + else + code = save_device_name(mac,devicename) + end + return code +end + +function save_device_name(mac,name) + local code = 0 + local dbfs = require("meizu.dbfs") + local code = dbfs.updateDeviceNickname(macFormat(mac),name) + if code == 0 then + return true + else + return false + end +end + +function getMacfilterList(mode) + mode = tonumber(mode) + local maclist = {} + local dlist = {} + local uci = require("luci.model.uci").cursor() + if mode == 0 then + maclist = uci:get_list("wireless", "wl0iface0", "maclist") + else + maclist = uci:get_list("wireless", "wl1iface0", "maclist") + end + if #maclist > 0 then + for _, mac in pairs(maclist) do + dlist[macFormat(mac)] = mac + end + end + return dlist +end + +function set_disk_access(mac, enable) + + local result = {} + local code = false + local uci = require("luci.model.uci").cursor() + local dbfs = require("meizu.dbfs") + dbfs.initSmbBanTable() + if is_str_nil(mac) then + return + else + mac = macFormat(mac) + enable = tonumber(enable) + end + if enable == 0 then + local cmd = "samba_ban add "..mac + local smb_ban = "true" + exec_cmd_in_sh(cmd) + dbfs.addSmbBanList(mac, smb_ban) + code = false + else + local cmd = "samba_ban remove "..mac + exec_cmd_in_sh(cmd) + dbfs.deleteSmbBanList(mac) + code = true + end + result["result"] = code + return result +end + +function set_wan_switch(mac, mode, enable) + local result = {} + local code = false + local uci = require("luci.model.uci").cursor() + if is_str_nil(mac) then + return + else + mac = macFormat(mac) + enable = tonumber(enable) + end + uci:set("wireless", "wl0iface0", "macfilter", "deny") + local maclist = uci:get_list("wireless", "wl0iface0", "maclist") + if enable == 0 then + for _, macaddr in ipairs(maclist) do + if mac == macaddr then + code = "same black" + return code + end + end + table.insert(maclist, mac) + code = true + else + local pos = -1 + for i, macaddr in ipairs(maclist) do + if mac == macaddr then + pos = i + end + end + if pos >= 0 then + table.remove(maclist, pos) + code = true + else + code = "same white" + return code + end + end + if #maclist > 0 then + uci:set_list("wireless", "wl0iface0", "maclist", maclist) + else + uci:delete("wireless", "wl0iface0", "maclist") + end + + uci:set("wireless", "wl0iface1", "macfilter", "deny") + local maclist = uci:get_list("wireless", "wl0iface1", "maclist") + if enable == 0 then + for _, macaddr in ipairs(maclist) do + if mac == macaddr then + code = "same black" + return code + end + end + table.insert(maclist, mac) + code = true + else + local pos = -1 + for i, macaddr in ipairs(maclist) do + if mac == macaddr then + pos = i + end + end + if pos >= 0 then + table.remove(maclist, pos) + code = true + else + code = "same white" + return code + end + end + if #maclist > 0 then + uci:set_list("wireless", "wl0iface1", "maclist", maclist) + else + uci:delete("wireless", "wl0iface1", "maclist") + end + + uci:set("wireless", "wl1iface0", "macfilter", "deny") + local maclist = uci:get_list("wireless", "wl1iface0", "maclist") + if enable == 0 then + for _, macaddr in ipairs(maclist) do + if mac == macaddr then + code = "same black" + return code + end + end + table.insert(maclist, mac) + code = true + else + local pos = -1 + for i, macaddr in ipairs(maclist) do + if mac == macaddr then + pos = i + end + end + if pos >= 0 then + table.remove(maclist, pos) + code = true + else + code = "same white" + return code + end + end + if #maclist > 0 then + uci:set_list("wireless", "wl1iface0", "maclist", maclist) + else + uci:delete("wireless", "wl1iface0", "maclist") + end + uci:commit("wireless") + fork_restart_wifi() + result["result"] = code + + return result +end + +function nw_set_wan_switch() + local result = {} + local code = false + local mac = luci.http.formvalue("mac") + local mode = luci.http.formvalue("mode") + local enable = luci.http.formvalue("enable") + + code = set_wan_switch(mac,mode,enable) + result["result"] = code + luci.http.write_json(result) +end + +function nw_set_disk_access() + local result = {} + local code = false + local mac = luci.http.formvalue("mac") + local enable = luci.http.formvalue("enable") + code = set_disk_access(mac,enable) + result["enable"] = enable + luci.http.write_json(result) +end + +function getNetConnect(ip) + local sys = require "luci.sys" + local res = {} + res["bytes"] = 0 + local conn = sys.net.conntrack() + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, debug.getinfo(1).currentline) + require "MZLog".log(3, conn) + for _, value in pairs(conn) do + if value.src == ip then + res["bytes"] = value.bytes + res["bytes"] + end + end + return res + --[[ + table.sort(conn, function(a,b) + return(a.src < b.src) + end) + local dhcpDevIpDict = getDHCPIpDicts() + for _,ip in pairs(conn) do + if dhcpDevIpDict[ip.src] ~= nil then + dhcpDevIpDict[ip.src].sp = dhcpDevIpDict[ip.src].sp + ip.bytes + + end + end + + return dhcpDevIpDict + ]] +end + +function get_net_device() + local ntm = require "luci.model.network".init() + local dev + local devices = { } + for _, dev in luci.util.vspairs(luci.sys.net.devices()) do + if dev ~= "lo" and not ntm:ignore_interface(dev) then + devices[#devices+1] = dev + end + end + local curdev = luci.dispatcher.context.requestpath + curdev = curdev[#curdev] ~= "bandwidth" and curdev[#curdev] or devices[1] + luci.http.write_json(devices) +end + +function nw_check_sys_password() + local password = luci.http.formvalue("password") + check_sys_password(password) +end + +function check_sys_password(password) + local result={} + if not is_str_nil(password) then + local check = check_sys_pwd(password) + if check then + code = true + else + code = false + end + end + result["result"] = code + luci.http.write_json(result) +end + +function get_wan_type() + local LuciNetwork = require("luci.model.network").init() + local wanNetwork = LuciNetwork:get_network("wan") + local wanDetails = {} + if wanNetwork then + local wanType = wanNetwork:proto() + + if wanType == "static" then + wanDetails["ipaddr"] = wanNetwork:get_option_value("ipaddr") + wanDetails["netmask"] = wanNetwork:get_option_value("netmask") + wanDetails["gateway"] = wanNetwork:get_option_value("gateway") + elseif wanType == "pppoe" then + wanDetails["type"] = "pppoe" + wanDetails["pppoeName"] = wanNetwork:get_option_value("username") + wanDetails["pppoePwd"] = wanNetwork:get_option_value("password") + elseif wanType == "dhcp" then + wanDetails["type"] = "dhcp" + wanDetails["pppoeName"] = "" + wanDetails["pppoePwd"] = "" + end + return wanDetails + else + return nil + end +end + +function ww_get_wan_type() + local result = get_wan_type() + return data_to_json(result) +end + +function nw_get_wan_type() + local result = get_wan_type() + luci.http.write_json(result) +end + +function nw_set_wan_type() + local wan_type = luci.http.formvalue("type") + local pppoe_name = luci.http.formvalue("pppoeName") + local pppoe_pwd = luci.http.formvalue("pppoePwd") + set_wan_type(wan_type, pppoe_name, pppoe_pwd) +end + +function set_wan_type(wan_type, pppoe_name, pppoe_pwd) + local result = {} + local code = true + local needRestartWifi = false + if not is_str_nil(wan_type) then + local succeed + if wan_type == "pppoe" and not is_str_nil(pppoe_name) and not is_str_nil(pppoe_pwd) then + succeed = setWanPPPoE(pppoe_name, pppoe_pwd) + elseif wan_type == "dhcp" then + succeed = setWanDHCP() + end + if not succeed then + code = false + else + needRestartWifi = true + end + end + result["result"] = code + luci.http.write_json(result) + if needRestartWifi then + fork_restart_network() + end + luci.http.close() +end + +function setWanPPPoE(name, password) + local LuciNetwork = require("luci.model.network").init() + local uci = require("luci.model.uci").cursor() + local iface = "wan" + local ifname = getWanEth() + local oldconf = uci:get_all("network", "wan") or {} + local wanrestart = true + if oldconf.username == name and oldconf.password == password then + wanrestart = false + end + local wanNet = LuciNetwork:del_network(iface) + local mtuvalue = 1480 + wanNet = LuciNetwork:add_network( + iface, { + proto ="pppoe", + ifname = ifname, + username = name, + password = password, + mtu = mtuvalue + }) + if wanNet then + LuciNetwork:save("network") + LuciNetwork:commit("network") + if wanrestart then + wanRestart() + end + return true + else + return false + end +end + +function setWanDHCP() + local LuciNetwork = require("luci.model.network").init() + local uci = require("luci.model.uci").cursor() + local oldconf = uci:get_all("network", "wan") or {} + local iface = "wan" + local ifname = getWanEth() + local wanrestart = true + + local wanNet = LuciNetwork:del_network(iface) + if oldconf.proto == "dhcp" then + wanrestart = false + end + local network = { + proto = "dhcp", + ifname = ifname + } + wanNet = LuciNetwork:add_network(iface, network) + if wanNet then + LuciNetwork:save("network") + LuciNetwork:commit("network") + if wanrestart then + wanRestart() + end + return true + else + return false + end +end + +function check_sys_pwd(oldPassword) + local LuciSys = require("luci.sys") + return LuciSys.user.checkpasswd("root", oldPassword) +end + +function getWanEth() + local LuciNetwork = require("luci.model.network").init() + local wanNetwork = LuciNetwork:get_network("wan") + return wanNetwork:get_option_value("ifname") +end + +function wanRestart() + local LuciUtil = require("luci.util") + LuciUtil.exec("env -i /sbin/ifup wan") +end + +function real_time_net_speed() + local res = {} + local cmd = [[luci-bwc -i eth0.2|tail -n 5|sed -e 's#.*\[\s*\(.*\)\s*\].*#\1#']] + local eth02_speed = io.popen(cmd) + local speed_table = {} + for line in eth02_speed:lines() do + table.insert(speed_table, line) + end + eth02_speed:close() + local rx = 0 + local tx = 0 + local speed, tb, rxb, txb + local n = 0 + for k, v in ipairs(speed_table) do + speed = strsplit(v, ',') + if (k == 1) then + tb = tonumber(speed[1]) + rxb = tonumber(speed[2]) + txb = tonumber(speed[4]) + else + n = n + 1 + local tmp + local td + tmp = tonumber(speed[1]) + td = tmp - tb + tb = tmp + + tmp = tonumber(speed[2]) + rx = rx + (tmp - rxb) / td + rxb = tmp + + tmp = tonumber(speed[4]) + tx = tx + (tmp - txb) / td + txb = tmp + end + end + res["rx"] = string.format("%6.2f", rx/n) + res["tx"] = string.format("%6.2f", tx/n) + + return res +end + +function set_smb_switch(smbswitch) + local result = {} + local code = false + local onoff = smbswitch + if (tonumber)(onoff) == 1 then + luci.sys.init.enable("samba") + exec_cmd_in_sh("sleep 1") + if luci.sys.init.enabled("samba") == true then + code = true + else + code = false + end + elseif (tonumber)(onoff) == 0 then + luci.sys.init.disable("samba") + exec_cmd_in_sh("sleep 1") + if luci.sys.init.enabled("samba") == true then + code = false + else + code = true + end + end + + result["result"] = code + return data_to_json(result) + +end + +function get_smb_switch() + local smbswitch = {} + local code = false + code = luci.sys.init.enabled("samba") + smbswitch["smbswitch"] = code + return data_to_json(smbswitch) +end + +function nw_set_smbswitch() + local res = {} + local smbswitch = luci.http.formvalue("smbswitch") + res = set_smb_switch(smbswitch) + luci.http.write(res) +end + +function nw_get_smbswitch() + local res = {} + res = get_smb_switch() + luci.http.write(res) +end + +function make_get_device_details_cmd(mac, patten) + local cmd = [[((wl -i wl0 sta_info ]]..mac..[[ 2>/dev/null| ]] + cmd = cmd..[[grep -E ']]..patten..[[')||]] + cmd = cmd..[[(wl -i wl1 sta_info ]]..mac..[[ 2>/dev/null| ]] + cmd = cmd..[[grep -E ']]..patten..[[')||]] + cmd = cmd..[[(wl -i wl0.1 sta_info ]]..mac..[[ 2>/dev/null| ]] + cmd = cmd..[[grep -E ']]..patten..[['))]] + cmd = cmd..[[|sed -e 's/[^0-9]//g'|awk '{printf $1}']] + return cmd +end + +function get_device_details_duration(mac) + local patten = "in network" + local cmd = make_get_device_details_cmd(mac, patten) + local ret = lue(cmd) + if ret == "" then + ret = "0" + end + + return ret +end + +function get_device_details_tx(mac) + local patten = "tx data bytes" + local cmd = make_get_device_details_cmd(mac, patten) + local ret = lue(cmd) + if ret == "" then + ret = "0" + end + + return ret +end + +function get_device_details_rx(mac) + local patten = "rx data bytes" + local cmd = make_get_device_details_cmd(mac, patten) + local ret = lue(cmd) + if ret == "" then + ret = "0" + end + + return ret +end + +function get_device_details(mac) + local dbfs = require("meizu.dbfs") + dbfs.change_maclist_table() + local item = {} + mac = string.upper(mac) + local sec = 0 + local tx = 0 + local rx = 0 + local smbBanList = {} + dbfs.initSmbBanTable() + smbBanList = dbfs.fetchSmbBanList() + local flag = 0 + if next(smbBanList) ~= nil then + for _, value in pairs(smbBanList) do + if value.mac == mac then + flag = 1 + break + end + end + end + + if flag == 0 then + item["diskaccess"] = true + else + item["diskaccess"] = false + end + + local blacklist0 = getMacfilterList(0) + local black0 = blacklist0[mac] + if black0 ~= nil then + item["enable"] = false + else + item["enable"] = true + end + + local dhcpDeviceDict = getDHCPDict() + local res = dbfs.fetch_all_wire_device() + if #res > 0 then + for k, v in pairs(res) do + v["name"] = "" + for key, value in pairs(dhcpDeviceDict) do + local mac = macFormat(key) + if v.mac == mac then + local dhcpinfo = dhcpDeviceDict[mac] + v["name"] = dhcpinfo.name + --dbfs.saveDeviceInfo(mac, dhcpinfo.name, "", dhcpinfo.ip) + dbfs.updateDeviceOrgname(mac, dhcpinfo.name) + break + end + end + dhcpDeviceDict[v.mac] = v + end + end + + local dhcpinfo = dhcpDeviceDict[mac] + local online = dhcpDeviceDict[mac] + local wifiDeviceDict = getAllWifiConnetDeviceDict() + local wifiType = wifiDeviceDict[mac] + if wifiType ~= nil then + sec = get_device_details_duration(mac) + tx = get_device_details_tx(mac) + rx = get_device_details_rx(mac) + if wifiType.wifiIndex == 1 or wifiType.wifiIndex == 3 then + item["type"] = "2.4G" + elseif wifiType.wifiIndex == 2 then + item["type"] = "5G" + end + elseif wifiType == nil and black0 == nil then + local wireless_res = dbfs.fetch_wireless_device_mac(mac) + if wireless_res == "" and mac ~= "00:00:00:00:00:00" then + item["type"] = "wire" + local ret = getNetConnect(dhcpinfo.ip) + tx = ret.bytes or 0 + else + item["type"] = "unknown" + end + else + item["type"] = "unknown" + end + + if black0 == nil and item["type"] ~= "unknown" then + item["online"] = true + else + item["online"] = false + end + if dhcpinfo then + item["ip"] = dhcpinfo.ip + else + item["ip"] = "" + end + local deviceDBDict = getDeviceInfoFromDB() + local deviceDB = deviceDBDict[mac] + item["devicename"] = "" + if deviceDB ~= nil then + item["devicename"] = deviceDB.orgname + if deviceDB.devicename ~= '' then + item["devicename"] = deviceDB.devicename + end + else + if dhcpinfo then + dbfs.saveDeviceInfo(mac, dhcpinfo.name, "", dhcpinfo.ip) + end + end + + item["mac"] = mac + item["speed"] = 0 + item["time"] = sec + item["upload"] = rx + item["download"] = tx + + return item +end + +function nw_get_device_details() + local mac = luci.http.formvalue("mac") + local res = get_device_details(mac) + luci.http.write_json(res) +end + +function get_wireless_channel() + local res = false + local uci = require("luci.model.uci").cursor() + local channel = uci.get("wireless", "wl0", "channel") + local htmode = uci.get("wireless", "wl0", "htmode") + local extch = 1 + if "auto" == channel then + channel = "0" + end + local mode = string.sub(htmode,3,4) + if "20" == mode then + extch = 0 +end + + local ret = {} + ret["channel"] = channel + ret["extch"] = extch + return ret +end +function nw_get_wireless_channel() + local ret = get_wireless_channel() + luci.http.write_json(ret) +end + +function ww_get_wireless_channel() + local ret = get_wireless_channel() + return cjson.encode(ret) +end + +function set_wireless_channel(channel, extch) + local res = false + local uci = require("luci.model.uci").cursor() + if "0" == channel then + res = uci.set("wireless", "wl0", "channel", "auto") + else + local c = tonumber(channel) + local tab = "+" + local mode = "40" + if c >= 7 and c <= 13 then + tab = "-" + end + if extch == "0" then + mode = "20" + end + local htmode = "HT"..mode..tab + res = uci.set("wireless", "wl0", "channel", channel) + res = uci.set("wireless", "wl0", "htmode", htmode) + end + uci.commit("wireless") + fork_restart_wifi() + + return res +end + +function nw_set_wireless_channel(channel, extch) + local channel = luci.http.formvalue("channel") + local extch = luci.http.formvalue("extch") + local res = set_wireless_channel(channel, extch) + local ret = {} + ret["result"] = res + luci.http.write_json(ret) +end + +function ww_set_wireless_channel(channel, extch) + local res = set_wireless_channel(channel, extch) + local ret = {} + ret["result"] = res + return ret +end + +function ww_get_device_details(mac) + local res = get_device_details(mac) + return res +end + +function get_tx_power_mode(mode) + local res = false + local uci = require("luci.model.uci").cursor() + local txpower = tonumber(uci.get("wireless", "wl0", "txpower")); + local mode = "normal" + if txpower > 15 then + mode = "enhance" + --[[ + [else + [ if txpower < 12 then + [ mode = "green" + [ end + ]] + end + + return mode +end + +function nw_get_tx_power_mode(mode) + local mode = get_tx_power_mode() + local ret = {} + ret["mode"] = mode + luci.http.write_json(ret) +end + +function ww_get_tx_power_mode(mode) + local ret = {} + local mode = get_tx_power_mode(mode) + ret["mode"] = mode + return data_to_json(ret) +end + +function set_tx_power_mode(mode) + local res = false + local uci = require("luci.model.uci").cursor() + if mode == "normal" then + res = uci.set("wireless", "wl0", "txpower", "15") + res = uci.set("wireless", "wl1", "txpower", "15") + else + if mode == "enhance" then + res = uci.set("wireless", "wl0", "txpower", "22") + res = uci.set("wireless", "wl1", "txpower", "22") + end + end + uci.commit("wireless") + + return res +end + +function nw_set_tx_power_mode(mode) + local mode = luci.http.formvalue("mode") + local res = set_tx_power_mode(mode) + local ret = {} + ret["result"] = res + luci.http.write_json(ret) +end + +function ww_set_tx_power_mode(mode) + local ret = {} + local res = set_tx_power_mode(mode) + ret["result"] = res + return ret +end + +function is_wan_connected() + local lu = require("luci.util") + local cmd = "ping -W 2 -c 1 www.baidu.com > /dev/null ;echo -n $?" + local pingresult = lu.exec(cmd) + + local res = {} + if pingresult == "0" then + res["result"] = true + else + res["result"] = false + + end + + return res +end diff --git a/Me_Lua/h10/meizu/r10config.lua b/Me_Lua/h10/meizu/r10config.lua new file mode 100644 index 0000000..e3fdb3c --- /dev/null +++ b/Me_Lua/h10/meizu/r10config.lua @@ -0,0 +1,3 @@ +upgradeFlagFile = "/tmp/upgradeFlagFile" +upgradeLOCK = "/bin/touch "..upgradeFlagFile +upgradeUNLOCK = "/bin/rm "..upgradeFlagFile diff --git a/Me_Lua/h10/meizu/sipfs.lua b/Me_Lua/h10/meizu/sipfs.lua new file mode 100644 index 0000000..21b5f44 --- /dev/null +++ b/Me_Lua/h10/meizu/sipfs.lua @@ -0,0 +1,906 @@ +module("meizu.sipfs", package.seeall) +--sip functions + +local bfs = require "meizu.bfs" +local cjson = require "cjson" +local disk = require "meizu.disk" +local dlfs = require "meizu.dlfs" +local nwfs = require "meizu.nwfs" +local RC = require "meizu.r10config" +local sipfs = require "meizu.sipfs" +local upgdfs = require "meizu.upgdfs" +local dbfs = require "meizu.dbfs" +local btfs = require "meizu.btfs" + +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 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 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 get_files_list = bfs.get_files_list + +local ww_get_disk_info = disk.ww_get_disk_info + +local get_smb_switch = nwfs.get_smb_switch +local real_time_net_speed = nwfs.real_time_net_speed +local set_device_name = nwfs.set_device_name +local set_disk_access = nwfs.set_disk_access +local set_smb_switch = nwfs.set_smb_switch +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_tx_power_mode = nwfs.ww_get_tx_power_mode +local ww_set_tx_power_mode = nwfs.ww_set_tx_power_mode +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 = btfs.ww_scan_ble_switch +local ww_add_ble_mesh_device = btfs.ww_add_ble_mesh_device +local ww_get_ble_device_list = btfs.ww_get_ble_device_list +local ww_get_ble_device_status = btfs.ww_get_ble_device_status +local ww_set_mesh_device_attr = btfs.ww_set_mesh_device_attr +local ww_get_mesh_device_list = btfs.ww_get_mesh_device_list +local ww_unmesh_all_device = btfs.ww_unmesh_all_device +local ww_set_mesh_network_pwd = btfs.ww_set_mesh_network_pwd +local ww_set_lamp_brightness = btfs.ww_set_lamp_brightness + +local check_upgrade = upgdfs.check_upgrade +local do_upgrade = upgdfs.do_upgrade +local local_upgrade = upgdfs.local_upgrade + +local download_task_operate = dlfs.download_task_operate +local get_active_list = dlfs.get_active_list +local get_history_list = dlfs.get_history_list +local get_pause_list = dlfs.get_pause_list +local remove_download_result = dlfs.remove_download_result +local download_task_start = dlfs.download_task_start +local start_download_intranet = dlfs.start_download_intranet +local ww_thunder_get_bind_code = dlfs.ww_thunder_get_bind_code + +local table_merge = bfs.table_merge + +local delete_access_token = dbfs.delete_access_token + +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 + local data = data + if (type(data) == "string") then + data = require("luci.http").urlencode(data) + 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, "sip_response_uploader data len:"..string.len(pd)) + require "MZLog".log(3, pd) + 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 = { + ["getFilesList"] = function (cmd, cmdid) + local data = sip_get_parameters(cmdid) + require "MZLog".log(3, debug.getinfo(1).currentline) + local jsr = cjson.decode(data) + local value = jsr.value + local path = nil + local start = nil + local count = nil + local IMEI = nil + for k, v in pairs(value) do + if k == "commandRequest" then + require "MZLog".log(3, v) + local jsr = cjson.decode(v) + path = jsr.path + start = jsr.start + count = jsr.count + IMEI = jsr.IMEI + require "MZLog".log(3, path) + require "MZLog".log(3, start) + require "MZLog".log(3, count) + require "MZLog".log(3, IMEI) + end + end + path = string.gsub(path, "router", "mnt") + require "MZLog".log(3, path) + local data = get_files_list(path, start, count, IMEI) + require "MZLog".log(3, data) + --luci.http.write(data) + sip_response_uploader(cmd, cmdid, data) + end, + ["downloadstart"] = 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 url_jsr = cjson.decode(v) + local url = url_jsr.url + local dltype = url_jsr.type + require "MZLog".log(3, url) + require "MZLog".log(3, dltype) + ret = download_task_start(url, dltype) + require "MZLog".log(3, ret) + end + end + end + sip_response_uploader(cmd, cmdid, ret) + end, + ["downloadpause"] = function (cmd, cmdid) + download_task_operate_process(cmd, cmdid) + end, + ["downloadunpause"] = function (cmd, cmdid) + download_task_operate_process(cmd, cmdid) + end, + ["downloadremove"] = function (cmd, cmdid) + download_task_operate_process(cmd, cmdid) + end, + ["getPauseList"] = function (cmd, cmdid) + local data = get_pause_list() + --data = download_list_post_process(data, 4) + sip_response_uploader(cmd, cmdid, data) + end, + ["getActiveList"] = function (cmd, cmdid) + require "MZLog".log(3, debug.getinfo(1).currentline) + local data = sip_get_parameters(cmdid) + require "MZLog".log(3, data) + local jsr = cjson.decode(data) + local value = jsr.value + local ret = "" + if (jsr.code) == "200" then + require "MZLog".log(3, debug.getinfo(1).currentline) + for k, v in pairs(value) do + require "MZLog".log(3, debug.getinfo(1).currentline) + if k == "commandRequest" then + local cr_jsr = cjson.decode(v) + local start = cr_jsr.start + local count = cr_jsr.count + ret = get_active_list(start, count) + end + end + end + sip_response_uploader(cmd, cmdid, ret) + end, + ["getHistoryList"] = function (cmd, cmdid) + require "MZLog".log(3, debug.getinfo(1).currentline) + local data = sip_get_parameters(cmdid) + require "MZLog".log(3, data) + local jsr = cjson.decode(data) + local value = jsr.value + local ret = "" + if (jsr.code) == "200" then + require "MZLog".log(3, debug.getinfo(1).currentline) + for k, v in pairs(value) do + require "MZLog".log(3, debug.getinfo(1).currentline) + if k == "commandRequest" then + local cr_jsr = cjson.decode(v) + local start = cr_jsr.start + local count = cr_jsr.count + ret = get_history_list(start, count) + end + end + end + sip_response_uploader(cmd, cmdid, ret) + end, + ["thundergetbindcode"] = function (cmd, cmdid) + local data = ww_thunder_get_bind_code() + sip_response_uploader(cmd, cmdid, data) + end, + ["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 switch_guest = nil + local ssid_2g = nil + local ssid_5g = nil + local ssid_guest = nil + local pwd_2g = nil + local pwd_5g = nil + local pwd_guest = nil + local encry_2g = nil + local encry_5g = nil + local encry_guest = 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 + else + switch_guest = value.on + ssid_guest = value.ssid + pwd_guest = value.pwd + encry_guest = 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 + switch_guest = value.on3 + ssid_guest = value.ssid3 + pwd_guest = value.pwd3 + encry_guest = value.encryption3 + end + end + end + local data = wifi_settings(switch_2g, ssid_2g, pwd_2g, encry_2g, switch_5g, ssid_5g, pwd_5g, encry_5g, switch_guest, ssid_guest, pwd_guest, encry_guest) + + 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, + ["setDiskAccess"] = function(cmd, cmdid) + require "MZLog".log(3, debug.getinfo(1).currentline) + local data = sip_get_parameters(cmdid) + local jsr = cjson.decode(data) + local mac = 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 + enable = jsr.enable + end + end + local data = set_disk_access(mac, enable) + require "MZLog".log(3, data) + data = data_to_json(data) + sip_response_uploader(cmd, cmdid, data) + end, + ["getSmbSwitch"] = function(cmd, cmdid) + require "MZLog".log(3, debug.getinfo(1).currentline) + local data = get_smb_switch() + require "MZLog".log(3, data) + sip_response_uploader(cmd, cmdid, data) + end, + ["setSmbSwitch"] = function(cmd, cmdid) + require "MZLog".log(3, debug.getinfo(1).currentline) + local data = sip_get_parameters(cmdid) + local jsr = cjson.decode(data) + local smbswitch = nil + local value = jsr.value + + for k, v in pairs(value) do + if k == "commandRequest" then + local jsr = cjson.decode(v) + smbswitch = jsr.smbswitch + end + end + local data = set_smb_switch(smbswitch) + 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, + ["getDiskInfo"] = function(cmd, cmdid) + local data = ww_get_disk_info() + data = data_to_json(data) + sip_response_uploader(cmd, cmdid, data) + end, + ["getsysinfo"] = function(cmd, cmdid) + local data = require "meizu.bfs".sysinfo() + data = data_to_json(data) + sip_response_uploader(cmd, cmdid, data) + end, + ["gettxpowermode"] = function(cmd, cmdid) + local ret = ww_get_tx_power_mode() + sip_response_uploader(cmd, cmdid, ret) + end, + ["settxpowermode"] = 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 mode = jsr.mode + ret = data_to_json(ww_set_tx_power_mode(mode)) + end + end + end + sip_response_uploader(cmd, cmdid, ret) + 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 + end, + + ["scanBleSwitch"] = 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 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, + ["setMeshNetWorkPassword"] = 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_network_pwd(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_lamp_brightness(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 diff --git a/Me_Lua/h10/meizu/upgdfs.lua b/Me_Lua/h10/meizu/upgdfs.lua new file mode 100644 index 0000000..11559ff --- /dev/null +++ b/Me_Lua/h10/meizu/upgdfs.lua @@ -0,0 +1,256 @@ +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 = "R10" + 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 = "R10" + 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/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 check_mandatory_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) + local upgrade_url = "" + local flag = false + if code == 200 then + local data = cjson.decode(res) + local value = data.value + if (data.code) == 200 then + for k, v in pairs(value) do + if k == "url" then + upgrade_url = v + end + if k == "mandatoryClear" and v == true then + flag = true + end + end + if flag then + do_upgrade() + end + end + 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() diff --git a/Me_Lua/h10/mime.lua b/Me_Lua/h10/mime.lua new file mode 100644 index 0000000..f559150 --- /dev/null +++ b/Me_Lua/h10/mime.lua @@ -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 \ No newline at end of file diff --git a/Me_Lua/h10/mime.so.1.0.3 b/Me_Lua/h10/mime.so.1.0.3 new file mode 100644 index 0000000..022ab11 Binary files /dev/null and b/Me_Lua/h10/mime.so.1.0.3 differ diff --git a/Me_Lua/h10/mime/core.so b/Me_Lua/h10/mime/core.so new file mode 100644 index 0000000..022ab11 Binary files /dev/null and b/Me_Lua/h10/mime/core.so differ diff --git a/Me_Lua/h10/posix.so b/Me_Lua/h10/posix.so new file mode 100644 index 0000000..21d530b Binary files /dev/null and b/Me_Lua/h10/posix.so differ diff --git a/Me_Lua/h10/routerReport.lua b/Me_Lua/h10/routerReport.lua new file mode 100644 index 0000000..2377014 --- /dev/null +++ b/Me_Lua/h10/routerReport.lua @@ -0,0 +1,144 @@ +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 report_uptime() + local timestamp = os.time() + local url="https://router.meizu.com/oauth/router/updateStatus" + local access_token = rts_get_access_token() + local data = "&name=uptime&value="..timestamp + 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 + + +ut() + +dbfs.init_wireless_device_table() +dbfs.init_wire_device_table() + +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() +report_rom_version() +report_uptime() +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() diff --git a/Me_Lua/h10/socket.lua b/Me_Lua/h10/socket.lua new file mode 100644 index 0000000..8f2d159 --- /dev/null +++ b/Me_Lua/h10/socket.lua @@ -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 diff --git a/Me_Lua/h10/socket.so.3.0-rc1 b/Me_Lua/h10/socket.so.3.0-rc1 new file mode 100644 index 0000000..c1aa8a2 Binary files /dev/null and b/Me_Lua/h10/socket.so.3.0-rc1 differ diff --git a/Me_Lua/h10/socket/core.so b/Me_Lua/h10/socket/core.so new file mode 100644 index 0000000..c1aa8a2 Binary files /dev/null and b/Me_Lua/h10/socket/core.so differ diff --git a/Me_Lua/h10/socket/ftp.lua b/Me_Lua/h10/socket/ftp.lua new file mode 100644 index 0000000..ea1145b --- /dev/null +++ b/Me_Lua/h10/socket/ftp.lua @@ -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 \ No newline at end of file diff --git a/Me_Lua/h10/socket/headers.lua b/Me_Lua/h10/socket/headers.lua new file mode 100644 index 0000000..1eb8223 --- /dev/null +++ b/Me_Lua/h10/socket/headers.lua @@ -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 \ No newline at end of file diff --git a/Me_Lua/h10/socket/http.lua b/Me_Lua/h10/socket/http.lua new file mode 100644 index 0000000..4f8c1c8 --- /dev/null +++ b/Me_Lua/h10/socket/http.lua @@ -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 \ No newline at end of file diff --git a/Me_Lua/h10/socket/smtp.lua b/Me_Lua/h10/socket/smtp.lua new file mode 100644 index 0000000..b113d00 --- /dev/null +++ b/Me_Lua/h10/socket/smtp.lua @@ -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 \ No newline at end of file diff --git a/Me_Lua/h10/socket/tp.lua b/Me_Lua/h10/socket/tp.lua new file mode 100644 index 0000000..cbeff56 --- /dev/null +++ b/Me_Lua/h10/socket/tp.lua @@ -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 \ No newline at end of file diff --git a/Me_Lua/h10/socket/url.lua b/Me_Lua/h10/socket/url.lua new file mode 100644 index 0000000..92ba7fd --- /dev/null +++ b/Me_Lua/h10/socket/url.lua @@ -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 +-- ::= :///;?# +-- ::= @: +-- ::= [:] +-- :: = {/} +-- 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 {/} is considered part of +----------------------------------------------------------------------------- +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 diff --git a/Me_Lua/h10/ssl.lua b/Me_Lua/h10/ssl.lua new file mode 100644 index 0000000..1cf2e39 --- /dev/null +++ b/Me_Lua/h10/ssl.lua @@ -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) + diff --git a/Me_Lua/h10/ssl.so b/Me_Lua/h10/ssl.so new file mode 100644 index 0000000..81e80a2 Binary files /dev/null and b/Me_Lua/h10/ssl.so differ diff --git a/Me_Lua/h10/ssl/https.lua b/Me_Lua/h10/ssl/https.lua new file mode 100644 index 0000000..d010669 --- /dev/null +++ b/Me_Lua/h10/ssl/https.lua @@ -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