diff --git a/luci-base/htdocs/luci-static/resources/cbi.js b/luci-base/htdocs/luci-static/resources/cbi.js index 6a487366f..89dfac9e4 100644 --- a/luci-base/htdocs/luci-static/resources/cbi.js +++ b/luci-base/htdocs/luci-static/resources/cbi.js @@ -1306,6 +1306,28 @@ function cbi_tag_last(container) } } +function cbi_submit(elem, name, value, action) +{ + var form = elem.form || findParent(elem, 'form'); + + if (!form) + return false; + + if (action) + form.action = action; + + if (name) { + var hidden = form.querySelector('input[type="hidden"][name="%s"]'.format(name)) || + E('input', { type: 'hidden', name: name }); + + hidden.value = value || '1'; + form.appendChild(hidden); + } + + form.submit(); + return true; +} + String.prototype.format = function() { if (!RegExp) @@ -1498,6 +1520,15 @@ String.nobr = function() return ''.nobr.apply(arguments[0], a); } +if (window.NodeList && !NodeList.prototype.forEach) { + NodeList.prototype.forEach = function (callback, thisArg) { + thisArg = thisArg || window; + for (var i = 0; i < this.length; i++) { + callback.call(thisArg, this[i], i, this); + } + }; +} + var dummyElem, domParser; @@ -2072,10 +2103,10 @@ function cbi_update_table(table, data, placeholder) { var trow = E('div', { 'class': 'tr' }); for (var i = 0; i < titles.length; i++) { - var text = titles[i].innerText; + var text = (titles[i].innerText || '').trim(); var td = trow.appendChild(E('div', { 'class': titles[i].className, - 'data-title': text ? text.trim() : null + 'data-title': (text !== '') ? text : null }, row[i] || '')); td.classList.remove('th'); diff --git a/luci-base/htdocs/luci-static/resources/icons/alias.png b/luci-base/htdocs/luci-static/resources/icons/alias.png new file mode 100644 index 000000000..8772bbad5 Binary files /dev/null and b/luci-base/htdocs/luci-static/resources/icons/alias.png differ diff --git a/luci-base/htdocs/luci-static/resources/icons/alias_disabled.png b/luci-base/htdocs/luci-static/resources/icons/alias_disabled.png new file mode 100644 index 000000000..38d0531e3 Binary files /dev/null and b/luci-base/htdocs/luci-static/resources/icons/alias_disabled.png differ diff --git a/luci-base/htdocs/luci-static/resources/icons/encryption.png b/luci-base/htdocs/luci-static/resources/icons/encryption.png deleted file mode 100644 index 776283360..000000000 Binary files a/luci-base/htdocs/luci-static/resources/icons/encryption.png and /dev/null differ diff --git a/luci-base/htdocs/luci-static/resources/icons/encryption_disabled.png b/luci-base/htdocs/luci-static/resources/icons/encryption_disabled.png deleted file mode 100644 index 9a8721b02..000000000 Binary files a/luci-base/htdocs/luci-static/resources/icons/encryption_disabled.png and /dev/null differ diff --git a/luci-base/htdocs/luci-static/resources/icons/wifi_big.png b/luci-base/htdocs/luci-static/resources/icons/wifi_big.png deleted file mode 100644 index 9e466aebf..000000000 Binary files a/luci-base/htdocs/luci-static/resources/icons/wifi_big.png and /dev/null differ diff --git a/luci-base/htdocs/luci-static/resources/icons/wifi_big_disabled.png b/luci-base/htdocs/luci-static/resources/icons/wifi_big_disabled.png deleted file mode 100644 index 6f9fff381..000000000 Binary files a/luci-base/htdocs/luci-static/resources/icons/wifi_big_disabled.png and /dev/null differ diff --git a/luci-base/htdocs/luci-static/resources/xhr.js b/luci-base/htdocs/luci-static/resources/xhr.js index f1537a448..62b525ebb 100644 --- a/luci-base/htdocs/luci-static/resources/xhr.js +++ b/luci-base/htdocs/luci-static/resources/xhr.js @@ -43,6 +43,7 @@ XHR = function() { this.reinit(); + var ts = Date.now(); var xhr = this._xmlHttp; var code = this._encode(data); @@ -65,14 +66,14 @@ XHR = function() var json = null; if (xhr.getResponseHeader("Content-Type") == "application/json") { try { - json = eval('(' + xhr.responseText + ')'); + json = JSON.parse(xhr.responseText); } catch(e) { json = null; } } - callback(xhr, json); + callback(xhr, json, Date.now() - ts); } } @@ -83,13 +84,14 @@ XHR = function() { this.reinit(); + var ts = Date.now(); var xhr = this._xmlHttp; var code = this._encode(data); xhr.onreadystatechange = function() { if (xhr.readyState == 4) - callback(xhr); + callback(xhr, null, Date.now() - ts); } xhr.open('POST', url, true); @@ -188,7 +190,7 @@ XHR.poll = function(interval, url, data, callback, post) for (var i = 0, e = XHR._q[0]; i < XHR._q.length; e = XHR._q[++i]) { if (!(XHR._t % e.interval) && !e.xhr.busy()) - e.xhr[post ? 'post' : 'get'](e.url, e.data, e.callback, e.interval * 1000 - 5); + e.xhr[post ? 'post' : 'get'](e.url, e.data, e.callback, e.interval * 1000 * 5 - 5); } XHR._t++; diff --git a/luci-base/luasrc/model/network.lua b/luci-base/luasrc/model/network.lua index d5029ec90..cce559aab 100644 --- a/luci-base/luasrc/model/network.lua +++ b/luci-base/luasrc/model/network.lua @@ -23,6 +23,22 @@ IFACE_PATTERNS_VIRTUAL = { } IFACE_PATTERNS_IGNORE = { "^wmaster%d", "^wifi%d", "^hwsim%d", "^imq%d", "^ifb%d", "^mon%.wlan%d", "^sit%d", "^gre%d", "^gretap%d", "^ip6gre%d", "^ip6tnl%d", "^tunl%d", "^lo$" } IFACE_PATTERNS_WIRELESS = { "^wlan%d", "^wl%d", "^ath%d", "^%w+%.network%d" } +IFACE_ERRORS = { + CONNECT_FAILED = lng.translate("Connection attempt failed"), + INVALID_ADDRESS = lng.translate("IP address in invalid"), + INVALID_GATEWAY = lng.translate("Gateway address is invalid"), + INVALID_LOCAL_ADDRESS = lng.translate("Local IP address is invalid"), + MISSING_ADDRESS = lng.translate("IP address is missing"), + MISSING_PEER_ADDRESS = lng.translate("Peer address is missing"), + NO_DEVICE = lng.translate("Network device is not present"), + NO_IFACE = lng.translate("Unable to determine device name"), + NO_IFNAME = lng.translate("Unable to determine device name"), + NO_WAN_ADDRESS = lng.translate("Unable to determine external IP address"), + NO_WAN_LINK = lng.translate("Unable to determine upstream interface"), + PEER_RESOLVE_FAIL = lng.translate("Unable to resolve peer host name"), + PIN_FAILED = lng.translate("PIN code rejected") +} + protocol = utl.class() @@ -495,6 +511,17 @@ function register_pattern_virtual(self, pat) IFACE_PATTERNS_VIRTUAL[#IFACE_PATTERNS_VIRTUAL+1] = pat end +function register_error_code(self, code, message) + if type(code) == "string" and + type(message) == "string" and + not IFACE_ERRORS[code] + then + IFACE_ERRORS[code] = message + return true + end + + return false +end function has_ipv6(self) return nfs.access("/proc/net/ipv6_route") @@ -520,6 +547,13 @@ end function get_network(self, n) if n and _uci:get("network", n) == "interface" then return network(n) + elseif n then + local stat = utl.ubus("network.interface", "status", { interface = n }) + if type(stat) == "table" and + type(stat.proto) == "string" + then + return network(n, stat.proto) + end end end @@ -532,6 +566,23 @@ function get_networks(self) nls[s['.name']] = network(s['.name']) end) + local dump = utl.ubus("network.interface", "dump", { }) + if type(dump) == "table" and + type(dump.interface) == "table" + then + local _, net + for _, net in ipairs(dump.interface) do + if type(net) == "table" and + type(net.proto) == "string" and + type(net.interface) == "string" + then + if not nls[net.interface] then + nls[net.interface] = network(net.interface, net.proto) + end + end + end + end + local n for n in utl.kspairs(nls) do nets[#nets+1] = nls[n] @@ -929,6 +980,16 @@ function protocol.metric(self) return self:_ubus("metric") or 0 end +function protocol.zonename(self) + local d = self:_ubus("data") + + if type(d) == "table" and type(d.zone) == "string" then + return d.zone + end + + return nil +end + function protocol.ipaddr(self) local addrs = self:_ubus("ipv4-address") return addrs and #addrs > 0 and addrs[1].address @@ -1043,6 +1104,22 @@ function protocol.ip6prefix(self) end end +function protocol.errors(self) + local _, err, rv + local errors = self:_ubus("errors") + if type(errors) == "table" then + for _, err in ipairs(errors) do + if type(err) == "table" and + type(err.code) == "string" + then + rv = rv or { } + rv[#rv+1] = IFACE_ERRORS[err.code] or lng.translatef("Unknown error (%s)", err.code) + end + end + end + return rv +end + function protocol.is_bridge(self) return (not self:is_virtual() and self:type() == "bridge") end @@ -1063,6 +1140,24 @@ function protocol.is_floating(self) return false end +function protocol.is_dynamic(self) + return (self:_ubus("dynamic") == true) +end + +function protocol.is_alias(self) + local ifn, parent = nil, nil + + for ifn in utl.imatch(_uci:get("network", self.sid, "ifname")) do + if #ifn > 1 and ifn:byte(1) == 64 then + parent = ifn:sub(2) + elseif parent ~= nil then + parent = nil + end + end + + return parent +end + function protocol.is_empty(self) if self:is_floating() then return false @@ -1081,6 +1176,10 @@ function protocol.is_empty(self) end end +function protocol.is_up(self) + return (self:_ubus("up") == true) +end + function protocol.add_interface(self, ifname) ifname = _M:ifnameof(ifname) if ifname and not self:is_floating() then @@ -1116,12 +1215,16 @@ function protocol.get_interface(self) _bridge["br-" .. self.sid] = true return interface("br-" .. self.sid, self) else - local ifn = nil - local num = { } + local ifn = self:_ubus("l3_device") or self:_ubus("device") + if ifn then + return interface(ifn, self) + end + for ifn in utl.imatch(_uci:get("network", self.sid, "ifname")) do ifn = ifn:match("^[^:/]+") return ifn and interface(ifn, self) end + ifn = _wifi_netid_by_netname(self.sid) return ifn and interface(ifn, self) end @@ -1245,7 +1348,9 @@ function interface.ip6addrs(self) end function interface.type(self) - if self.wif or _wifi_iface(self.ifname) then + if self.ifname and self.ifname:byte(1) == 64 then + return "alias" + elseif self.wif or _wifi_iface(self.ifname) then return "wifi" elseif _bridge[self.ifname] then return "bridge" @@ -1282,7 +1387,9 @@ end function interface.get_type_i18n(self) local x = self:type() - if x == "wifi" then + if x == "alias" then + return lng.translate("Alias Interface") + elseif x == "wifi" then return lng.translate("Wireless Adapter") elseif x == "bridge" then return lng.translate("Bridge") @@ -1335,7 +1442,11 @@ function interface.bridge_stp(self) end function interface.is_up(self) - return self:_ubus("up") or false + local up = self:_ubus("up") + if up == nil then + up = (self:type() == "alias") + end + return up or false end function interface.is_bridge(self) @@ -1601,7 +1712,7 @@ end function wifinet.ifname(self) local ifname = self:ubus("net", "ifname") or self.iwinfo.ifname if not ifname or ifname:match("^wifi%d") or ifname:match("^radio%d") then - ifname = self.wdev + ifname = self.netid end return ifname end diff --git a/luci-base/luasrc/view/cbi/apply_widget.htm b/luci-base/luasrc/view/cbi/apply_widget.htm index e3090da65..f76846ee8 100644 --- a/luci-base/luasrc/view/cbi/apply_widget.htm +++ b/luci-base/luasrc/view/cbi/apply_widget.htm @@ -1,9 +1,5 @@ <% export("cbi_apply_widget", function(redirect_ok) -%> - + diff --git a/luci-base/luasrc/view/cbi/header.htm b/luci-base/luasrc/view/cbi/header.htm index 9710bae8f..821fa3efa 100644 --- a/luci-base/luasrc/view/cbi/header.htm +++ b/luci-base/luasrc/view/cbi/header.htm @@ -1,18 +1,17 @@ <%+header%> -
+>
- diff --git a/luci-base/luasrc/view/cbi/network_ifacelist.htm b/luci-base/luasrc/view/cbi/network_ifacelist.htm index abfa33e1e..a97e9ef6d 100644 --- a/luci-base/luasrc/view/cbi/network_ifacelist.htm +++ b/luci-base/luasrc/view/cbi/network_ifacelist.htm @@ -26,9 +26,14 @@ else local n = self.network and net:get_network(self.network) if n then - local i - for _, i in ipairs(n:get_interfaces() or { n:get_interface() }) do - checked[i:name()] = true + local a = n:is_alias() + if a then + checked['@' .. a] = true + else + local i + for _, i in ipairs(n:get_interfaces() or { n:get_interface() }) do + checked[i:name()] = true + end end end end @@ -50,7 +55,8 @@ -->