diff --git a/luci-base/Makefile b/luci-base/Makefile index da29b58ba..264bfe9f4 100644 --- a/luci-base/Makefile +++ b/luci-base/Makefile @@ -12,8 +12,7 @@ LUCI_TYPE:=mod LUCI_BASENAME:=base LUCI_TITLE:=LuCI core libraries -LUCI_DEPENDS:=+lua +libuci-lua +luci-lib-nixio +luci-lib-ip +rpcd +libubus-lua +luci-lib-jsonc -LUCI_EXTRA_DEPENDS:=libuci-lua (>= 2018-01-01) +LUCI_DEPENDS:=+lua +luci-lib-nixio +luci-lib-ip +rpcd +libubus-lua +luci-lib-jsonc +liblucihttp-lua PKG_SOURCE:=LuaSrcDiet-0.12.1.tar.bz2 PKG_SOURCE_URL:=https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/luasrcdiet diff --git a/luci-base/htdocs/luci-static/resources/cbi.js b/luci-base/htdocs/luci-static/resources/cbi.js index d40ec34bc..6c35372cd 100644 --- a/luci-base/htdocs/luci-static/resources/cbi.js +++ b/luci-base/htdocs/luci-static/resources/cbi.js @@ -218,12 +218,13 @@ var cbi_validators = { ((ipv4only == 1) && cbi_validators.ip4addr.apply(this)); }, - 'hostname': function() + 'hostname': function(strict) { if (this.length <= 253) - return (this.match(/^[a-zA-Z0-9]+$/) != null || + return (this.match(/^[a-zA-Z0-9_]+$/) != null || (this.match(/^[a-zA-Z0-9_][a-zA-Z0-9_\-.]*[a-zA-Z0-9]$/) && - this.match(/[^0-9.]/))); + this.match(/[^0-9.]/))) && + (!strict || !this.match(/^_/)); return false; }, diff --git a/luci-base/htdocs/luci-static/resources/xhr.js b/luci-base/htdocs/luci-static/resources/xhr.js index 3385f8f23..de4476cdd 100644 --- a/luci-base/htdocs/luci-static/resources/xhr.js +++ b/luci-base/htdocs/luci-static/resources/xhr.js @@ -39,7 +39,7 @@ XHR = function() this._xmlHttp.abort(); } - this.get = function(url,data,callback) + this.get = function(url,data,callback,timeout) { this.reinit(); @@ -56,6 +56,9 @@ XHR = function() xhr.open('GET', url, true); + if (!isNaN(timeout)) + xhr.timeout = timeout; + xhr.onreadystatechange = function() { if (xhr.readyState == 4) { @@ -76,7 +79,7 @@ XHR = function() xhr.send(null); } - this.post = function(url,data,callback) + this.post = function(url,data,callback,timeout) { this.reinit(); @@ -90,6 +93,10 @@ XHR = function() } xhr.open('POST', url, true); + + if (!isNaN(timeout)) + xhr.timeout = timeout; + xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); xhr.send(code); } @@ -168,7 +175,7 @@ XHR.get = function(url, data, callback) (new XHR()).get(url, data, callback); } -XHR.poll = function(interval, url, data, callback) +XHR.poll = function(interval, url, data, callback, post) { if (isNaN(interval) || interval < 1) interval = 5; @@ -181,22 +188,38 @@ XHR.poll = function(interval, url, data, callback) 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.get(e.url, e.data, e.callback); + e.xhr[post ? 'post' : 'get'](e.url, e.data, e.callback, e.interval * 1000 - 5); } XHR._t++; }; } - XHR._q.push({ + var e = { interval: interval, callback: callback, url: url, data: data, xhr: new XHR() - }); + }; + XHR._q.push(e); XHR.run(); + + return e; +} + +XHR.stop = function(e) +{ + for (var i = 0; XHR._q && XHR._q[i]; i++) { + if (XHR._q[i] === e) { + e.xhr.cancel(); + XHR._q.splice(i, 1); + return true; + } + } + + return false; } XHR.halt = function() diff --git a/luci-base/luasrc/cbi/datatypes.lua b/luci-base/luasrc/cbi/datatypes.lua index 55cdf8a74..99113e0b7 100644 --- a/luci-base/luasrc/cbi/datatypes.lua +++ b/luci-base/luasrc/cbi/datatypes.lua @@ -199,13 +199,13 @@ function macaddr(val) return ip.checkmac(val) and true or false end -function hostname(val) +function hostname(val, strict) if val and (#val < 254) and ( val:match("^[a-zA-Z_]+$") or (val:match("^[a-zA-Z0-9_][a-zA-Z0-9_%-%.]*[a-zA-Z0-9]$") and val:match("[^0-9%.]")) ) then - return true + return (not strict or not val:match("^_")) end return false end diff --git a/luci-base/luasrc/dispatcher.lua b/luci-base/luasrc/dispatcher.lua index 16b32548e..1984fc4ad 100644 --- a/luci-base/luasrc/dispatcher.lua +++ b/luci-base/luasrc/dispatcher.lua @@ -75,11 +75,16 @@ function error404(message) http.status(404, "Not Found") message = message or "Not Found" - require("luci.template") - if not util.copcall(luci.template.render, "error404") then + local function render() + local template = require "luci.template" + template.render("error404") + end + + if not util.copcall(render) then http.prepare_content("text/plain") http.write(message) end + return false end @@ -113,7 +118,8 @@ function httpdispatch(request, prefix) end end - for node in pathinfo:gmatch("[^/]+") do + local node + for node in pathinfo:gmatch("[^/%z]+") do r[#r+1] = node end @@ -136,8 +142,7 @@ local function require_post_security(target) if (type(required_val) == "string" and request_val ~= required_val) or - (required_val == true and - (request_val == nil or request_val == "")) + (required_val == true and request_val == nil) then return false end @@ -346,15 +351,23 @@ function dispatch(request) ifattr = function(...) return _ifattr(...) end; attr = function(...) return _ifattr(true, ...) end; url = build_url; - }, {__index=function(table, key) + }, {__index=function(tbl, key) if key == "controller" then return build_url() elseif key == "REQUEST_URI" then return build_url(unpack(ctx.requestpath)) + elseif key == "FULL_REQUEST_URI" then + local url = { http.getenv("SCRIPT_NAME"), http.getenv("PATH_INFO") } + local query = http.getenv("QUERY_STRING") + if query and #query > 0 then + url[#url+1] = "?" + url[#url+1] = query + end + return table.concat(url, "") elseif key == "token" then return ctx.authtoken else - return rawget(table, key) or _G[key] + return rawget(tbl, key) or _G[key] end end}) end @@ -429,6 +442,13 @@ function dispatch(request) ctx.authuser = sdat.username end + if track.cors and http.getenv("REQUEST_METHOD") == "OPTIONS" then + luci.http.status(200, "OK") + luci.http.header("Access-Control-Allow-Origin", http.getenv("HTTP_ORIGIN") or "*") + luci.http.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS") + return + end + if c and require_post_security(c.target) then if not test_post_security(c) then return @@ -650,6 +670,23 @@ function node(...) return c end +function lookup(...) + local i, path = nil, {} + for i = 1, select('#', ...) do + local name, arg = nil, tostring(select(i, ...)) + for name in arg:gmatch("[^/]+") do + path[#path+1] = name + end + end + + for i = #path, 1, -1 do + local node = context.treecache[table.concat(path, ".", 1, i)] + if node and (i == #path or node.leaf) then + return node, build_url(unpack(path)) + end + end +end + function _create_node(path) if #path == 0 then return context.tree @@ -791,7 +828,16 @@ local function _cbi(self, ...) local state = nil + local i, res for i, res in ipairs(maps) do + if util.instanceof(res, cbi.SimpleForm) then + io.stderr:write("Model %s returns SimpleForm but is dispatched via cbi(),\n" + % self.model) + + io.stderr:write("please change %s to use the form() action instead.\n" + % table.concat(context.request, "/")) + end + res.flow = config local cstate = res:parse() if cstate and (not state or cstate < state) then @@ -884,7 +930,7 @@ end function cbi(model, config) return { type = "cbi", - post = { ["cbi.submit"] = "1" }, + post = { ["cbi.submit"] = true }, config = config, model = model, target = _cbi @@ -912,6 +958,7 @@ local function _form(self, ...) local maps = luci.cbi.load(self.model, ...) local state = nil + local i, res for i, res in ipairs(maps) do local cstate = res:parse() if cstate and (not state or cstate < state) then @@ -930,7 +977,7 @@ end function form(model) return { type = "cbi", - post = { ["cbi.submit"] = "1" }, + post = { ["cbi.submit"] = true }, model = model, target = _form } diff --git a/luci-base/luasrc/dispatcher.luadoc b/luci-base/luasrc/dispatcher.luadoc index 743463c74..ddf534b3e 100644 --- a/luci-base/luasrc/dispatcher.luadoc +++ b/luci-base/luasrc/dispatcher.luadoc @@ -116,8 +116,8 @@ Create a new dispatching node and define common parameters. ---[[ Fetch or create a dispatching node without setting the target module or - enabling the node. + @class function @name get @param ... Virtual path @@ -133,6 +133,15 @@ Fetch or create a new dispatching node. @return Dispatching tree node ]] +---[[ +Lookup node in dispatching tree. + +@class function +@name lookup +@param ... Virtual path +@return Node object, canonical url or nil if the path was not found. +]] + ---[[ Alias the first (lowest order) page automatically diff --git a/luci-base/luasrc/http.lua b/luci-base/luasrc/http.lua index 9cc985786..16fb04c54 100644 --- a/luci-base/luasrc/http.lua +++ b/luci-base/luasrc/http.lua @@ -1,18 +1,21 @@ -- Copyright 2008 Steven Barth +-- Copyright 2010-2018 Jo-Philipp Wich -- Licensed to the public under the Apache License 2.0. -local ltn12 = require "luci.ltn12" -local protocol = require "luci.http.protocol" local util = require "luci.util" -local string = require "string" local coroutine = require "coroutine" local table = require "table" +local lhttp = require "lucihttp" +local nixio = require "nixio" +local ltn12 = require "luci.ltn12" -local ipairs, pairs, next, type, tostring, error = - ipairs, pairs, next, type, tostring, error +local table, ipairs, pairs, type, tostring, tonumber, error = + table, ipairs, pairs, type, tostring, tonumber, error module "luci.http" +HTTP_MAX_CONTENT = 1024*8 -- 8 kB maximum content size + context = util.threadlocal() Request = util.class() @@ -28,7 +31,7 @@ function Request.__init__(self, env, sourcein, sinkerr) self.message = { env = env, headers = {}, - params = protocol.urldecode_params(env.QUERY_STRING or ""), + params = urldecode_params(env.QUERY_STRING or ""), } self.parsed_input = false @@ -73,10 +76,7 @@ function Request.content(self) end function Request.getcookie(self, name) - local c = string.gsub(";" .. (self:getenv("HTTP_COOKIE") or "") .. ";", "%s*;%s*", ";") - local p = ";" .. name .. "=(.-);" - local i, j, value = c:find(p) - return value and urldecode(value) + return lhttp.header_attribute("cookie; " .. (self:getenv("HTTP_COOKIE") or ""), name) end function Request.getenv(self, name) @@ -90,40 +90,34 @@ end function Request.setfilehandler(self, callback) self.filehandler = callback - -- If input has already been parsed then any files are either in temporary files - -- or are in self.message.params[key] - if self.parsed_input then - for param, value in pairs(self.message.params) do - repeat - -- We're only interested in files - if (not value["file"]) then break end - -- If we were able to write to temporary file - if (value["fd"]) then - fd = value["fd"] - local eof = false - repeat - filedata = fd:read(1024) - if (filedata:len() < 1024) then - eof = true - end - callback({ name=value["name"], file=value["file"] }, filedata, eof) - until (eof) - fd:close() - value["fd"] = nil - -- We had to read into memory - else - -- There should only be one numbered value in table - the data - for k, v in ipairs(value) do - callback({ name=value["name"], file=value["file"] }, v, true) + if not self.parsed_input then + return + end + + -- If input has already been parsed then uploads are stored as unlinked + -- temporary files pointed to by open file handles in the parameter + -- value table. Loop all params, and invoke the file callback for any + -- param with an open file handle. + local name, value + for name, value in pairs(self.message.params) do + if type(value) == "table" then + while value.fd do + local data = value.fd:read(1024) + local eof = (not data or data == "") + + callback(value, data, eof) + + if eof then + value.fd:close() + value.fd = nil end end - until true end end end function Request._parse_input(self) - protocol.parse_message_body( + parse_message_body( self.input, self.message, self.filehandler @@ -254,23 +248,307 @@ function redirect(url) end function build_querystring(q) - local s = { "?" } + local s, n, k, v = {}, 1, nil, nil for k, v in pairs(q) do - if #s > 1 then s[#s+1] = "&" end - - s[#s+1] = urldecode(k) - s[#s+1] = "=" - s[#s+1] = urldecode(v) + s[n+0] = (n == 1) and "?" or "&" + s[n+1] = util.urlencode(k) + s[n+2] = "=" + s[n+3] = util.urlencode(v) + n = n + 4 end return table.concat(s, "") end -urldecode = protocol.urldecode +urldecode = util.urldecode -urlencode = protocol.urlencode +urlencode = util.urlencode function write_json(x) util.serialize_json(x, write) end + +-- from given url or string. Returns a table with urldecoded values. +-- Simple parameters are stored as string values associated with the parameter +-- name within the table. Parameters with multiple values are stored as array +-- containing the corresponding values. +function urldecode_params(url, tbl) + local parser, name + local params = tbl or { } + + parser = lhttp.urlencoded_parser(function (what, buffer, length) + if what == parser.TUPLE then + name, value = nil, nil + elseif what == parser.NAME then + name = lhttp.urldecode(buffer) + elseif what == parser.VALUE and name then + params[name] = lhttp.urldecode(buffer) or "" + end + + return true + end) + + if parser then + parser:parse((url or ""):match("[^?]*$")) + parser:parse(nil) + end + + return params +end + +-- separated by "&". Tables are encoded as parameters with multiple values by +-- repeating the parameter name with each value. +function urlencode_params(tbl) + local k, v + local n, enc = 1, {} + for k, v in pairs(tbl) do + if type(v) == "table" then + local i, v2 + for i, v2 in ipairs(v) do + if enc[1] then + enc[n] = "&" + n = n + 1 + end + + enc[n+0] = lhttp.urlencode(k) + enc[n+1] = "=" + enc[n+2] = lhttp.urlencode(v2) + n = n + 3 + end + else + if enc[1] then + enc[n] = "&" + n = n + 1 + end + + enc[n+0] = lhttp.urlencode(k) + enc[n+1] = "=" + enc[n+2] = lhttp.urlencode(v) + n = n + 3 + end + end + + return table.concat(enc, "") +end + +-- Content-Type. Stores all extracted data associated with its parameter name +-- in the params table within the given message object. Multiple parameter +-- values are stored as tables, ordinary ones as strings. +-- If an optional file callback function is given then it is feeded with the +-- file contents chunk by chunk and only the extracted file name is stored +-- within the params table. The callback function will be called subsequently +-- with three arguments: +-- o Table containing decoded (name, file) and raw (headers) mime header data +-- o String value containing a chunk of the file data +-- o Boolean which indicates wheather the current chunk is the last one (eof) +function mimedecode_message_body(src, msg, file_cb) + local parser, header, field + local len, maxlen = 0, tonumber(msg.env.CONTENT_LENGTH or nil) + + parser, err = lhttp.multipart_parser(msg.env.CONTENT_TYPE, function (what, buffer, length) + if what == parser.PART_INIT then + field = { } + + elseif what == parser.HEADER_NAME then + header = buffer:lower() + + elseif what == parser.HEADER_VALUE and header then + if header:lower() == "content-disposition" and + lhttp.header_attribute(buffer, nil) == "form-data" + then + field.name = lhttp.header_attribute(buffer, "name") + field.file = lhttp.header_attribute(buffer, "filename") + field[1] = field.file + end + + if field.headers then + field.headers[header] = buffer + else + field.headers = { [header] = buffer } + end + + elseif what == parser.PART_BEGIN then + return not field.file + + elseif what == parser.PART_DATA and field.name and length > 0 then + if field.file then + if file_cb then + file_cb(field, buffer, false) + msg.params[field.name] = msg.params[field.name] or field + else + if not field.fd then + field.fd = nixio.mkstemp(field.name) + end + + if field.fd then + field.fd:write(buffer) + msg.params[field.name] = msg.params[field.name] or field + end + end + else + field.value = buffer + end + + elseif what == parser.PART_END and field.name then + if field.file and msg.params[field.name] then + if file_cb then + file_cb(field, "", true) + elseif field.fd then + field.fd:seek(0, "set") + end + else + local val = msg.params[field.name] + + if type(val) == "table" then + val[#val+1] = field.value or "" + elseif val ~= nil then + msg.params[field.name] = { val, field.value or "" } + else + msg.params[field.name] = field.value or "" + end + end + + field = nil + + elseif what == parser.ERROR then + err = buffer + end + + return true + end) + + return ltn12.pump.all(src, function (chunk) + len = len + (chunk and #chunk or 0) + + if maxlen and len > maxlen + 2 then + return nil, "Message body size exceeds Content-Length" + end + + if not parser or not parser:parse(chunk) then + return nil, err + end + + return true + end) +end + +-- Content-Type. Stores all extracted data associated with its parameter name +-- in the params table within the given message object. Multiple parameter +-- values are stored as tables, ordinary ones as strings. +function urldecode_message_body(src, msg) + local err, name, value, parser + local len, maxlen = 0, tonumber(msg.env.CONTENT_LENGTH or nil) + + parser = lhttp.urlencoded_parser(function (what, buffer, length) + if what == parser.TUPLE then + name, value = nil, nil + elseif what == parser.NAME then + name = lhttp.urldecode(buffer, lhttp.DECODE_PLUS) + elseif what == parser.VALUE and name then + local val = msg.params[name] + + if type(val) == "table" then + val[#val+1] = lhttp.urldecode(buffer, lhttp.DECODE_PLUS) or "" + elseif val ~= nil then + msg.params[name] = { val, lhttp.urldecode(buffer, lhttp.DECODE_PLUS) or "" } + else + msg.params[name] = lhttp.urldecode(buffer, lhttp.DECODE_PLUS) or "" + end + elseif what == parser.ERROR then + err = buffer + end + + return true + end) + + return ltn12.pump.all(src, function (chunk) + len = len + (chunk and #chunk or 0) + + if maxlen and len > maxlen + 2 then + return nil, "Message body size exceeds Content-Length" + elseif len > HTTP_MAX_CONTENT then + return nil, "Message body size exceeds maximum allowed length" + end + + if not parser or not parser:parse(chunk) then + return nil, err + end + + return true + end) +end + +-- This function will examine the Content-Type within the given message object +-- to select the appropriate content decoder. +-- Currently the application/x-www-urlencoded and application/form-data +-- mime types are supported. If the encountered content encoding can't be +-- handled then the whole message body will be stored unaltered as "content" +-- property within the given message object. +function parse_message_body(src, msg, filecb) + if msg.env.CONTENT_LENGTH or msg.env.REQUEST_METHOD == "POST" then + local ctype = lhttp.header_attribute(msg.env.CONTENT_TYPE, nil) + + -- Is it multipart/mime ? + if ctype == "multipart/form-data" then + return mimedecode_message_body(src, msg, filecb) + + -- Is it application/x-www-form-urlencoded ? + elseif ctype == "application/x-www-form-urlencoded" then + return urldecode_message_body(src, msg) + + end + + -- Unhandled encoding + -- If a file callback is given then feed it chunk by chunk, else + -- store whole buffer in message.content + local sink + + -- If we have a file callback then feed it + if type(filecb) == "function" then + local meta = { + name = "raw", + encoding = msg.env.CONTENT_TYPE + } + sink = function( chunk ) + if chunk then + return filecb(meta, chunk, false) + else + return filecb(meta, nil, true) + end + end + -- ... else append to .content + else + msg.content = "" + msg.content_length = 0 + + sink = function( chunk ) + if chunk then + if ( msg.content_length + #chunk ) <= HTTP_MAX_CONTENT then + msg.content = msg.content .. chunk + msg.content_length = msg.content_length + #chunk + return true + else + return nil, "POST data exceeds maximum allowed length" + end + end + return true + end + end + + -- Pump data... + while true do + local ok, err = ltn12.pump.step( src, sink ) + + if not ok and err then + return nil, err + elseif not ok then -- eof + return true + end + end + + return true + end + + return false +end diff --git a/luci-base/luasrc/http.luadoc b/luci-base/luasrc/http.luadoc index 8a325db21..f8121230b 100644 --- a/luci-base/luasrc/http.luadoc +++ b/luci-base/luasrc/http.luadoc @@ -6,25 +6,24 @@ module "luci.http" ---[[ Close the HTTP-Connection. - -@class function -@name close +@class function +@name close ]] ---[[ Return the request content if the request was of unknown type. -@class function -@name content -@return HTTP request body -@return HTTP request body length +@class function +@name content +@return HTTP request body +@return HTTP request body length ]] ---[[ Get a certain HTTP input value or a table of all input values. -@class function -@name formvalue +@class function +@name formvalue @param name Name of the GET or POST variable to fetch @param noparse Don't parse POST data before getting the value @return HTTP input value or table of all input value @@ -33,8 +32,8 @@ Get a certain HTTP input value or a table of all input values. ---[[ Get a table of all HTTP input values with a certain prefix. -@class function -@name formvaluetable +@class function +@name formvaluetable @param prefix Prefix @return Table of all HTTP input values with given prefix ]] @@ -42,18 +41,18 @@ Get a table of all HTTP input values with a certain prefix. ---[[ Get the value of a certain HTTP-Cookie. -@class function -@name getcookie +@class function +@name getcookie @param name Cookie Name @return String containing cookie data ]] ---[[ Get the value of a certain HTTP environment variable - or the environment table itself. -@class function -@name getenv + +@class function +@name getenv @param name Environment variable @return HTTP environment value or environment table ]] @@ -61,41 +60,41 @@ or the environment table itself. ---[[ Set a handler function for incoming user file uploads. -@class function -@name setfilehandler +@class function +@name setfilehandler @param callback Handler function ]] ---[[ Send a HTTP-Header. -@class function -@name header -@param key Header key -@param value Header value +@class function +@name header +@param key Header key +@param value Header value ]] ---[[ Set the mime type of following content data. -@class function -@name prepare_content -@param mime Mimetype of following content +@class function +@name prepare_content +@param mime Mimetype of following content ]] ---[[ Get the RAW HTTP input source -@class function -@name source -@return HTTP LTN12 source +@class function +@name source +@return HTTP LTN12 source ]] ---[[ Set the HTTP status code and status message. -@class function -@name status +@class function +@name status @param code Status code @param message Status message ]] @@ -105,8 +104,9 @@ Send a chunk of content data to the client. This function is as a valid LTN12 sink. If the content chunk is nil this function will automatically invoke close. -@class function -@name write + +@class function +@name write @param content Content chunk @param src_err Error object from source (optional) @see close @@ -115,51 +115,146 @@ If the content chunk is nil this function will automatically invoke close. ---[[ Splice data from a filedescriptor to the client. -@class function -@name splice -@param fp File descriptor -@param size Bytes to splice (optional) +@class function +@name splice +@param fp File descriptor +@param size Bytes to splice (optional) ]] ---[[ Redirects the client to a new URL and closes the connection. -@class function -@name redirect -@param url Target URL +@class function +@name redirect +@param url Target URL ]] ---[[ Create a querystring out of a table of key - value pairs. -@class function -@name build_querystring -@param table Query string source table +@class function +@name build_querystring +@param table Query string source table @return Encoded HTTP query string ]] ---[[ Return the URL-decoded equivalent of a string. +@class function +@name urldecode @param str URL-encoded string @param no_plus Don't decode + to " " @return URL-decoded string -@see urlencode +@see urlencode ]] ---[[ Return the URL-encoded equivalent of a string. +@class function +@name urlencode @param str Source string @return URL-encoded string -@see urldecode +@see urldecode ]] ---[[ Send the given data as JSON encoded string. -@class function -@name write_json +@class function +@name write_json @param data Data to send ]] +---[[ +Extract and split urlencoded data pairs, separated bei either "&" or ";" +from given url or string. Returns a table with urldecoded values. + +Simple parameters are stored as string values associated with the parameter +name within the table. Parameters with multiple values are stored as array +containing the corresponding values. + +@class function +@name urldecode_params +@param url The url or string which contains x-www-urlencoded form data +@param tbl Use the given table for storing values (optional) +@return Table containing the urldecoded parameters +@see urlencode_params +]] + +---[[ +Encode each key-value-pair in given table to x-www-urlencoded format, +separated by "&". + +Tables are encoded as parameters with multiple values by repeating the +parameter name with each value. + +@class function +@name urlencode_params +@param tbl Table with the values +@return String containing encoded values +@see urldecode_params +]] + +---[[ +Decode a mime encoded http message body with multipart/form-data Content-Type. + +Stores all extracted data associated with its parameter name +in the params table within the given message object. Multiple parameter +values are stored as tables, ordinary ones as strings. + +If an optional file callback function is given then it is feeded with the +file contents chunk by chunk and only the extracted file name is stored +within the params table. The callback function will be called subsequently +with three arguments: + o Table containing decoded (name, file) and raw (headers) mime header data + o String value containing a chunk of the file data + o Boolean which indicates wheather the current chunk is the last one (eof) + +@class function +@name mimedecode_message_body +@param src Ltn12 source function +@param msg HTTP message object +@param filecb File callback function (optional) +@return Value indicating successful operation (not nil means "ok") +@return String containing the error if unsuccessful +@see parse_message_header +]] + +---[[ +Decode an urlencoded http message body with application/x-www-urlencoded +Content-Type. + +Stores all extracted data associated with its parameter name in the params +table within the given message object. Multiple parameter values are stored +as tables, ordinary ones as strings. + +@class function +@name urldecode_message_body +@param src Ltn12 source function +@param msg HTTP message object +@return Value indicating successful operation (not nil means "ok") +@return String containing the error if unsuccessful +@see parse_message_header +]] + +---[[ +Try to extract and decode a http message body from the given ltn12 source. +This function will examine the Content-Type within the given message object +to select the appropriate content decoder. + +Currently the application/x-www-urlencoded and application/form-data +mime types are supported. If the encountered content encoding can't be +handled then the whole message body will be stored unaltered as "content" +property within the given message object. + +@class function +@name parse_message_body +@param src Ltn12 source function +@param msg HTTP message object +@param filecb File data callback (optional, see mimedecode_message_body()) +@return Value indicating successful operation (not nil means "ok") +@return String containing the error if unsuccessful +@see parse_message_header +]] diff --git a/luci-base/luasrc/http/protocol.lua b/luci-base/luasrc/http/protocol.lua deleted file mode 100644 index 0a8b2fbab..000000000 --- a/luci-base/luasrc/http/protocol.lua +++ /dev/null @@ -1,649 +0,0 @@ --- Copyright 2008 Freifunk Leipzig / Jo-Philipp Wich --- Licensed to the public under the Apache License 2.0. - --- This class contains several functions useful for http message- and content --- decoding and to retrive form data from raw http messages. -module("luci.http.protocol", package.seeall) - -local ltn12 = require("luci.ltn12") - -HTTP_MAX_CONTENT = 1024*8 -- 8 kB maximum content size - --- the "+" sign to " " - and return the decoded string. -function urldecode( str, no_plus ) - - local function __chrdec( hex ) - return string.char( tonumber( hex, 16 ) ) - end - - if type(str) == "string" then - if not no_plus then - str = str:gsub( "+", " " ) - end - - str = str:gsub( "%%([a-fA-F0-9][a-fA-F0-9])", __chrdec ) - end - - return str -end - --- from given url or string. Returns a table with urldecoded values. --- Simple parameters are stored as string values associated with the parameter --- name within the table. Parameters with multiple values are stored as array --- containing the corresponding values. -function urldecode_params( url, tbl ) - - local params = tbl or { } - - if url:find("?") then - url = url:gsub( "^.+%?([^?]+)", "%1" ) - end - - for pair in url:gmatch( "[^&;]+" ) do - - -- find key and value - local key = urldecode( pair:match("^([^=]+)") ) - local val = urldecode( pair:match("^[^=]+=(.+)$") ) - - -- store - if type(key) == "string" and key:len() > 0 then - if type(val) ~= "string" then val = "" end - - if not params[key] then - params[key] = val - elseif type(params[key]) ~= "table" then - params[key] = { params[key], val } - else - table.insert( params[key], val ) - end - end - end - - return params -end - -function urlencode( str ) - - local function __chrenc( chr ) - return string.format( - "%%%02x", string.byte( chr ) - ) - end - - if type(str) == "string" then - str = str:gsub( - "([^a-zA-Z0-9$_%-%.%~])", - __chrenc - ) - end - - return str -end - --- separated by "&". Tables are encoded as parameters with multiple values by --- repeating the parameter name with each value. -function urlencode_params( tbl ) - local enc = "" - - for k, v in pairs(tbl) do - if type(v) == "table" then - for i, v2 in ipairs(v) do - enc = enc .. ( #enc > 0 and "&" or "" ) .. - urlencode(k) .. "=" .. urlencode(v2) - end - else - enc = enc .. ( #enc > 0 and "&" or "" ) .. - urlencode(k) .. "=" .. urlencode(v) - end - end - - return enc -end - --- (Internal function) --- Initialize given parameter and coerce string into table when the parameter --- already exists. -local function __initval( tbl, key ) - if tbl[key] == nil then - tbl[key] = "" - elseif type(tbl[key]) == "string" then - tbl[key] = { tbl[key], "" } - else - table.insert( tbl[key], "" ) - end -end - --- (Internal function) --- Initialize given file parameter. -local function __initfileval( tbl, key, filename, fd ) - if tbl[key] == nil then - tbl[key] = { file=filename, fd=fd, name=key, "" } - else - table.insert( tbl[key], "" ) - end -end - --- (Internal function) --- Append given data to given parameter, either by extending the string value --- or by appending it to the last string in the parameter's value table. -local function __appendval( tbl, key, chunk ) - if type(tbl[key]) == "table" then - tbl[key][#tbl[key]] = tbl[key][#tbl[key]] .. chunk - else - tbl[key] = tbl[key] .. chunk - end -end - --- (Internal function) --- Finish the value of given parameter, either by transforming the string value --- or - in the case of multi value parameters - the last element in the --- associated values table. -local function __finishval( tbl, key, handler ) - if handler then - if type(tbl[key]) == "table" then - tbl[key][#tbl[key]] = handler( tbl[key][#tbl[key]] ) - else - tbl[key] = handler( tbl[key] ) - end - end -end - - --- Table of our process states -local process_states = { } - --- Extract "magic", the first line of a http message. --- Extracts the message type ("get", "post" or "response"), the requested uri --- or the status code if the line descripes a http response. -process_states['magic'] = function( msg, chunk, err ) - - if chunk ~= nil then - -- ignore empty lines before request - if #chunk == 0 then - return true, nil - end - - -- Is it a request? - local method, uri, http_ver = chunk:match("^([A-Z]+) ([^ ]+) HTTP/([01]%.[019])$") - - -- Yup, it is - if method then - - msg.type = "request" - msg.request_method = method:lower() - msg.request_uri = uri - msg.http_version = tonumber( http_ver ) - msg.headers = { } - - -- We're done, next state is header parsing - return true, function( chunk ) - return process_states['headers']( msg, chunk ) - end - - -- Is it a response? - else - - local http_ver, code, message = chunk:match("^HTTP/([01]%.[019]) ([0-9]+) ([^\r\n]+)$") - - -- Is a response - if code then - - msg.type = "response" - msg.status_code = code - msg.status_message = message - msg.http_version = tonumber( http_ver ) - msg.headers = { } - - -- We're done, next state is header parsing - return true, function( chunk ) - return process_states['headers']( msg, chunk ) - end - end - end - end - - -- Can't handle it - return nil, "Invalid HTTP message magic" -end - - --- Extract headers from given string. -process_states['headers'] = function( msg, chunk ) - - if chunk ~= nil then - - -- Look for a valid header format - local hdr, val = chunk:match( "^([A-Za-z][A-Za-z0-9%-_]+): +(.+)$" ) - - if type(hdr) == "string" and hdr:len() > 0 and - type(val) == "string" and val:len() > 0 - then - msg.headers[hdr] = val - - -- Valid header line, proceed - return true, nil - - elseif #chunk == 0 then - -- Empty line, we won't accept data anymore - return false, nil - else - -- Junk data - return nil, "Invalid HTTP header received" - end - else - return nil, "Unexpected EOF" - end -end - - --- data line by line with the trailing \r\n stripped of. -function header_source( sock ) - return ltn12.source.simplify( function() - - local chunk, err, part = sock:receive("*l") - - -- Line too long - if chunk == nil then - if err ~= "timeout" then - return nil, part - and "Line exceeds maximum allowed length" - or "Unexpected EOF" - else - return nil, err - end - - -- Line ok - elseif chunk ~= nil then - - -- Strip trailing CR - chunk = chunk:gsub("\r$","") - - return chunk, nil - end - end ) -end - --- Content-Type. Stores all extracted data associated with its parameter name --- in the params table within the given message object. Multiple parameter --- values are stored as tables, ordinary ones as strings. --- If an optional file callback function is given then it is feeded with the --- file contents chunk by chunk and only the extracted file name is stored --- within the params table. The callback function will be called subsequently --- with three arguments: --- o Table containing decoded (name, file) and raw (headers) mime header data --- o String value containing a chunk of the file data --- o Boolean which indicates wheather the current chunk is the last one (eof) -function mimedecode_message_body( src, msg, filecb ) - - if msg and msg.env.CONTENT_TYPE then - msg.mime_boundary = msg.env.CONTENT_TYPE:match("^multipart/form%-data; boundary=(.+)$") - end - - if not msg.mime_boundary then - return nil, "Invalid Content-Type found" - end - - - local tlen = 0 - local inhdr = false - local field = nil - local store = nil - local lchunk = nil - - local function parse_headers( chunk, field ) - - local stat - repeat - chunk, stat = chunk:gsub( - "^([A-Z][A-Za-z0-9%-_]+): +([^\r\n]+)\r\n", - function(k,v) - field.headers[k] = v - return "" - end - ) - until stat == 0 - - chunk, stat = chunk:gsub("^\r\n","") - - -- End of headers - if stat > 0 then - if field.headers["Content-Disposition"] then - if field.headers["Content-Disposition"]:match("^form%-data; ") then - field.name = field.headers["Content-Disposition"]:match('name="(.-)"') - field.file = field.headers["Content-Disposition"]:match('filename="(.+)"$') - end - end - - if not field.headers["Content-Type"] then - field.headers["Content-Type"] = "text/plain" - end - - if field.name and field.file and filecb then - __initval( msg.params, field.name ) - __appendval( msg.params, field.name, field.file ) - - store = filecb - elseif field.name and field.file then - local nxf = require "nixio" - local fd = nxf.mkstemp(field.name) - __initfileval ( msg.params, field.name, field.file, fd ) - if fd then - store = function(hdr, buf, eof) - fd:write(buf) - if (eof) then - fd:seek(0, "set") - end - end - else - store = function( hdr, buf, eof ) - __appendval( msg.params, field.name, buf ) - end - end - elseif field.name then - __initval( msg.params, field.name ) - - store = function( hdr, buf, eof ) - __appendval( msg.params, field.name, buf ) - end - else - store = nil - end - - return chunk, true - end - - return chunk, false - end - - local function snk( chunk ) - - tlen = tlen + ( chunk and #chunk or 0 ) - - if msg.env.CONTENT_LENGTH and tlen > tonumber(msg.env.CONTENT_LENGTH) + 2 then - return nil, "Message body size exceeds Content-Length" - end - - if chunk and not lchunk then - lchunk = "\r\n" .. chunk - - elseif lchunk then - local data = lchunk .. ( chunk or "" ) - local spos, epos, found - - repeat - spos, epos = data:find( "\r\n--" .. msg.mime_boundary .. "\r\n", 1, true ) - - if not spos then - spos, epos = data:find( "\r\n--" .. msg.mime_boundary .. "--\r\n", 1, true ) - end - - - if spos then - local predata = data:sub( 1, spos - 1 ) - - if inhdr then - predata, eof = parse_headers( predata, field ) - - if not eof then - return nil, "Invalid MIME section header" - elseif not field.name then - return nil, "Invalid Content-Disposition header" - end - end - - if store then - store( field, predata, true ) - end - - - field = { headers = { } } - found = found or true - - data, eof = parse_headers( data:sub( epos + 1, #data ), field ) - inhdr = not eof - end - until not spos - - if found then - -- We found at least some boundary. Save - -- the unparsed remaining data for the - -- next chunk. - lchunk, data = data, nil - else - -- There was a complete chunk without a boundary. Parse it as headers or - -- append it as data, depending on our current state. - if inhdr then - lchunk, eof = parse_headers( data, field ) - inhdr = not eof - else - -- We're inside data, so append the data. Note that we only append - -- lchunk, not all of data, since there is a chance that chunk - -- contains half a boundary. Assuming that each chunk is at least the - -- boundary in size, this should prevent problems - store( field, lchunk, false ) - lchunk, chunk = chunk, nil - end - end - end - - return true - end - - return ltn12.pump.all( src, snk ) -end - --- Content-Type. Stores all extracted data associated with its parameter name --- in the params table within the given message object. Multiple parameter --- values are stored as tables, ordinary ones as strings. -function urldecode_message_body( src, msg ) - - local tlen = 0 - local lchunk = nil - - local function snk( chunk ) - - tlen = tlen + ( chunk and #chunk or 0 ) - - if msg.env.CONTENT_LENGTH and tlen > tonumber(msg.env.CONTENT_LENGTH) + 2 then - return nil, "Message body size exceeds Content-Length" - elseif tlen > HTTP_MAX_CONTENT then - return nil, "Message body size exceeds maximum allowed length" - end - - if not lchunk and chunk then - lchunk = chunk - - elseif lchunk then - local data = lchunk .. ( chunk or "&" ) - local spos, epos - - repeat - spos, epos = data:find("^.-[;&]") - - if spos then - local pair = data:sub( spos, epos - 1 ) - local key = pair:match("^(.-)=") - local val = pair:match("=([^%s]*)%s*$") - - if key and #key > 0 then - __initval( msg.params, key ) - __appendval( msg.params, key, val ) - __finishval( msg.params, key, urldecode ) - end - - data = data:sub( epos + 1, #data ) - end - until not spos - - lchunk = data - end - - return true - end - - return ltn12.pump.all( src, snk ) -end - --- version, message headers and resulting CGI environment variables from the --- given ltn12 source. -function parse_message_header( src ) - - local ok = true - local msg = { } - - local sink = ltn12.sink.simplify( - function( chunk ) - return process_states['magic']( msg, chunk ) - end - ) - - -- Pump input data... - while ok do - - -- get data - ok, err = ltn12.pump.step( src, sink ) - - -- error - if not ok and err then - return nil, err - - -- eof - elseif not ok then - - -- Process get parameters - if ( msg.request_method == "get" or msg.request_method == "post" ) and - msg.request_uri:match("?") - then - msg.params = urldecode_params( msg.request_uri ) - else - msg.params = { } - end - - -- Populate common environment variables - msg.env = { - CONTENT_LENGTH = msg.headers['Content-Length']; - CONTENT_TYPE = msg.headers['Content-Type'] or msg.headers['Content-type']; - REQUEST_METHOD = msg.request_method:upper(); - REQUEST_URI = msg.request_uri; - SCRIPT_NAME = msg.request_uri:gsub("?.+$",""); - SCRIPT_FILENAME = ""; -- XXX implement me - SERVER_PROTOCOL = "HTTP/" .. string.format("%.1f", msg.http_version); - QUERY_STRING = msg.request_uri:match("?") - and msg.request_uri:gsub("^.+?","") or "" - } - - -- Populate HTTP_* environment variables - for i, hdr in ipairs( { - 'Accept', - 'Accept-Charset', - 'Accept-Encoding', - 'Accept-Language', - 'Connection', - 'Cookie', - 'Host', - 'Referer', - 'User-Agent', - } ) do - local var = 'HTTP_' .. hdr:upper():gsub("%-","_") - local val = msg.headers[hdr] - - msg.env[var] = val - end - end - end - - return msg -end - --- This function will examine the Content-Type within the given message object --- to select the appropriate content decoder. --- Currently the application/x-www-urlencoded and application/form-data --- mime types are supported. If the encountered content encoding can't be --- handled then the whole message body will be stored unaltered as "content" --- property within the given message object. -function parse_message_body( src, msg, filecb ) - -- Is it multipart/mime ? - if msg.env.REQUEST_METHOD == "POST" and msg.env.CONTENT_TYPE and - msg.env.CONTENT_TYPE:match("^multipart/form%-data") - then - - return mimedecode_message_body( src, msg, filecb ) - - -- Is it application/x-www-form-urlencoded ? - elseif msg.env.REQUEST_METHOD == "POST" and msg.env.CONTENT_TYPE and - msg.env.CONTENT_TYPE:match("^application/x%-www%-form%-urlencoded") - then - return urldecode_message_body( src, msg, filecb ) - - - -- Unhandled encoding - -- If a file callback is given then feed it chunk by chunk, else - -- store whole buffer in message.content - else - - local sink - - -- If we have a file callback then feed it - if type(filecb) == "function" then - local meta = { - name = "raw", - encoding = msg.env.CONTENT_TYPE - } - sink = function( chunk ) - if chunk then - return filecb(meta, chunk, false) - else - return filecb(meta, nil, true) - end - end - -- ... else append to .content - else - msg.content = "" - msg.content_length = 0 - - sink = function( chunk ) - if chunk then - if ( msg.content_length + #chunk ) <= HTTP_MAX_CONTENT then - msg.content = msg.content .. chunk - msg.content_length = msg.content_length + #chunk - return true - else - return nil, "POST data exceeds maximum allowed length" - end - end - return true - end - end - - -- Pump data... - while true do - local ok, err = ltn12.pump.step( src, sink ) - - if not ok and err then - return nil, err - elseif not ok then -- eof - return true - end - end - - return true - end -end - -statusmsg = { - [200] = "OK", - [206] = "Partial Content", - [301] = "Moved Permanently", - [302] = "Found", - [304] = "Not Modified", - [400] = "Bad Request", - [403] = "Forbidden", - [404] = "Not Found", - [405] = "Method Not Allowed", - [408] = "Request Time-out", - [411] = "Length Required", - [412] = "Precondition Failed", - [416] = "Requested range not satisfiable", - [500] = "Internal Server Error", - [503] = "Server Unavailable", -} diff --git a/luci-base/luasrc/http/protocol.luadoc b/luci-base/luasrc/http/protocol.luadoc deleted file mode 100644 index 19a0a3419..000000000 --- a/luci-base/luasrc/http/protocol.luadoc +++ /dev/null @@ -1,142 +0,0 @@ ----[[ -LuCI http protocol class. - -This class contains several functions useful for http message- and content -decoding and to retrive form data from raw http messages. -]] -module "luci.http.protocol" - ----[[ -Decode an urlencoded string - optionally without decoding - -the "+" sign to " " - and return the decoded string. -@class function -@name urldecode -@param str Input string in x-www-urlencoded format -@param no_plus Don't decode "+" signs to spaces -@return The decoded string -@see urlencode -]] - ----[[ -Extract and split urlencoded data pairs, separated bei either "&" or ";" - -from given url or string. Returns a table with urldecoded values. -Simple parameters are stored as string values associated with the parameter -name within the table. Parameters with multiple values are stored as array -containing the corresponding values. -@class function -@name urldecode_params -@param url The url or string which contains x-www-urlencoded form data -@param tbl Use the given table for storing values (optional) -@return Table containing the urldecoded parameters -@see urlencode_params -]] - ----[[ -Encode given string to x-www-urlencoded format. - -@class function -@name urlencode -@param str String to encode -@return String containing the encoded data -@see urldecode -]] - ----[[ -Encode each key-value-pair in given table to x-www-urlencoded format, - -separated by "&". Tables are encoded as parameters with multiple values by -repeating the parameter name with each value. -@class function -@name urlencode_params -@param tbl Table with the values -@return String containing encoded values -@see urldecode_params -]] - ----[[ -Creates a ltn12 source from the given socket. The source will return it's - -data line by line with the trailing \r\n stripped of. -@class function -@name header_source -@param sock Readable network socket -@return Ltn12 source function -]] - ----[[ -Decode a mime encoded http message body with multipart/form-data - -Content-Type. Stores all extracted data associated with its parameter name -in the params table within the given message object. Multiple parameter -values are stored as tables, ordinary ones as strings. -If an optional file callback function is given then it is feeded with the -file contents chunk by chunk and only the extracted file name is stored -within the params table. The callback function will be called subsequently -with three arguments: - o Table containing decoded (name, file) and raw (headers) mime header data - o String value containing a chunk of the file data - o Boolean which indicates wheather the current chunk is the last one (eof) -@class function -@name mimedecode_message_body -@param src Ltn12 source function -@param msg HTTP message object -@param filecb File callback function (optional) -@return Value indicating successful operation (not nil means "ok") -@return String containing the error if unsuccessful -@see parse_message_header -]] - ----[[ -Decode an urlencoded http message body with application/x-www-urlencoded - -Content-Type. Stores all extracted data associated with its parameter name -in the params table within the given message object. Multiple parameter -values are stored as tables, ordinary ones as strings. -@class function -@name urldecode_message_body -@param src Ltn12 source function -@param msg HTTP message object -@return Value indicating successful operation (not nil means "ok") -@return String containing the error if unsuccessful -@see parse_message_header -]] - ----[[ -Try to extract an http message header including information like protocol - -version, message headers and resulting CGI environment variables from the -given ltn12 source. -@class function -@name parse_message_header -@param src Ltn12 source function -@return HTTP message object -@see parse_message_body -]] - ----[[ -Try to extract and decode a http message body from the given ltn12 source. - -This function will examine the Content-Type within the given message object -to select the appropriate content decoder. -Currently the application/x-www-urlencoded and application/form-data -mime types are supported. If the encountered content encoding can't be -handled then the whole message body will be stored unaltered as "content" -property within the given message object. -@class function -@name parse_message_body -@param src Ltn12 source function -@param msg HTTP message object -@param filecb File data callback (optional, see mimedecode_message_body()) -@return Value indicating successful operation (not nil means "ok") -@return String containing the error if unsuccessful -@see parse_message_header -]] - ----[[ -Table containing human readable messages for several http status codes. - -@class table -]] - diff --git a/luci-base/luasrc/http/protocol/conditionals.lua b/luci-base/luasrc/http/protocol/conditionals.lua deleted file mode 100644 index d31a4e38a..000000000 --- a/luci-base/luasrc/http/protocol/conditionals.lua +++ /dev/null @@ -1,110 +0,0 @@ --- Copyright 2008 Freifunk Leipzig / Jo-Philipp Wich --- Licensed to the public under the Apache License 2.0. - --- This class provides basic ETag handling and implements most of the --- conditional HTTP/1.1 headers specified in RFC2616 Sct. 14.24 - 14.28 . -module("luci.http.protocol.conditionals", package.seeall) - -local date = require("luci.http.protocol.date") - - -function mk_etag( stat ) - if stat ~= nil then - return string.format( '"%x-%x-%x"', stat.ino, stat.size, stat.mtime ) - end -end - --- Test whether the given message object contains an "If-Match" header and --- compare it against the given stat object. -function if_match( req, stat ) - local h = req.headers - local etag = mk_etag( stat ) - - -- Check for matching resource - if type(h['If-Match']) == "string" then - for ent in h['If-Match']:gmatch("([^, ]+)") do - if ( ent == '*' or ent == etag ) and stat ~= nil then - return true - end - end - - return false, 412 - end - - return true -end - --- Test whether the given message object contains an "If-Modified-Since" header --- and compare it against the given stat object. -function if_modified_since( req, stat ) - local h = req.headers - - -- Compare mtimes - if type(h['If-Modified-Since']) == "string" then - local since = date.to_unix( h['If-Modified-Since'] ) - - if stat == nil or since < stat.mtime then - return true - end - - return false, 304, { - ["ETag"] = mk_etag( stat ); - ["Date"] = date.to_http( os.time() ); - ["Last-Modified"] = date.to_http( stat.mtime ) - } - end - - return true -end - --- Test whether the given message object contains an "If-None-Match" header and --- compare it against the given stat object. -function if_none_match( req, stat ) - local h = req.headers - local etag = mk_etag( stat ) - local method = req.env and req.env.REQUEST_METHOD or "GET" - - -- Check for matching resource - if type(h['If-None-Match']) == "string" then - for ent in h['If-None-Match']:gmatch("([^, ]+)") do - if ( ent == '*' or ent == etag ) and stat ~= nil then - if method == "GET" or method == "HEAD" then - return false, 304, { - ["ETag"] = etag; - ["Date"] = date.to_http( os.time() ); - ["Last-Modified"] = date.to_http( stat.mtime ) - } - else - return false, 412 - end - end - end - end - - return true -end - --- The If-Range header is currently not implemented due to the lack of general --- byte range stuff in luci.http.protocol . This function will always return --- false, 412 to indicate a failed precondition. -function if_range( req, stat ) - -- Sorry, no subranges (yet) - return false, 412 -end - --- Test whether the given message object contains an "If-Unmodified-Since" --- header and compare it against the given stat object. -function if_unmodified_since( req, stat ) - local h = req.headers - - -- Compare mtimes - if type(h['If-Unmodified-Since']) == "string" then - local since = date.to_unix( h['If-Unmodified-Since'] ) - - if stat ~= nil and since <= stat.mtime then - return false, 412 - end - end - - return true -end diff --git a/luci-base/luasrc/http/protocol/conditionals.luadoc b/luci-base/luasrc/http/protocol/conditionals.luadoc deleted file mode 100644 index 9cfe02dd5..000000000 --- a/luci-base/luasrc/http/protocol/conditionals.luadoc +++ /dev/null @@ -1,85 +0,0 @@ ----[[ -LuCI http protocol implementation - HTTP/1.1 bits. - -This class provides basic ETag handling and implements most of the -conditional HTTP/1.1 headers specified in RFC2616 Sct. 14.24 - 14.28 . -]] -module "luci.http.protocol.conditionals" - ----[[ -Implement 14.19 / ETag. - -@class function -@name mk_etag -@param stat A file.stat structure -@return String containing the generated tag suitable for ETag headers -]] - ----[[ -14.24 / If-Match - -Test whether the given message object contains an "If-Match" header and -compare it against the given stat object. -@class function -@name if_match -@param req HTTP request message object -@param stat A file.stat object -@return Boolean indicating whether the precondition is ok -@return Alternative status code if the precondition failed -]] - ----[[ -14.25 / If-Modified-Since - -Test whether the given message object contains an "If-Modified-Since" header -and compare it against the given stat object. -@class function -@name if_modified_since -@param req HTTP request message object -@param stat A file.stat object -@return Boolean indicating whether the precondition is ok -@return Alternative status code if the precondition failed -@return Table containing extra HTTP headers if the precondition failed -]] - ----[[ -14.26 / If-None-Match - -Test whether the given message object contains an "If-None-Match" header and -compare it against the given stat object. -@class function -@name if_none_match -@param req HTTP request message object -@param stat A file.stat object -@return Boolean indicating whether the precondition is ok -@return Alternative status code if the precondition failed -@return Table containing extra HTTP headers if the precondition failed -]] - ----[[ -14.27 / If-Range - -The If-Range header is currently not implemented due to the lack of general -byte range stuff in luci.http.protocol . This function will always return -false, 412 to indicate a failed precondition. -@class function -@name if_range -@param req HTTP request message object -@param stat A file.stat object -@return Boolean indicating whether the precondition is ok -@return Alternative status code if the precondition failed -]] - ----[[ -14.28 / If-Unmodified-Since - -Test whether the given message object contains an "If-Unmodified-Since" -header and compare it against the given stat object. -@class function -@name if_unmodified_since -@param req HTTP request message object -@param stat A file.stat object -@return Boolean indicating whether the precondition is ok -@return Alternative status code if the precondition failed -]] - diff --git a/luci-base/luasrc/http/protocol/date.lua b/luci-base/luasrc/http/protocol/date.lua deleted file mode 100644 index e440219a9..000000000 --- a/luci-base/luasrc/http/protocol/date.lua +++ /dev/null @@ -1,87 +0,0 @@ --- Copyright 2008 Freifunk Leipzig / Jo-Philipp Wich --- Licensed to the public under the Apache License 2.0. - --- This class contains functions to parse, compare and format http dates. -module("luci.http.protocol.date", package.seeall) - -require("luci.sys.zoneinfo") - - -MONTHS = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", - "Sep", "Oct", "Nov", "Dec" -} - -function tz_offset(tz) - - if type(tz) == "string" then - - -- check for a numeric identifier - local s, v = tz:match("([%+%-])([0-9]+)") - if s == '+' then s = 1 else s = -1 end - if v then v = tonumber(v) end - - if s and v then - return s * 60 * ( math.floor( v / 100 ) * 60 + ( v % 100 ) ) - - -- lookup symbolic tz - elseif luci.sys.zoneinfo.OFFSET[tz:lower()] then - return luci.sys.zoneinfo.OFFSET[tz:lower()] - end - - end - - -- bad luck - return 0 -end - -function to_unix(date) - - local wd, day, mon, yr, hr, min, sec, tz = date:match( - "([A-Z][a-z][a-z]), ([0-9]+) " .. - "([A-Z][a-z][a-z]) ([0-9]+) " .. - "([0-9]+):([0-9]+):([0-9]+) " .. - "([A-Z0-9%+%-]+)" - ) - - if day and mon and yr and hr and min and sec then - -- find month - local month = 1 - for i = 1, 12 do - if MONTHS[i] == mon then - month = i - break - end - end - - -- convert to epoch time - return tz_offset(tz) + os.time( { - year = yr, - month = month, - day = day, - hour = hr, - min = min, - sec = sec - } ) - end - - return 0 -end - -function to_http(time) - return os.date( "%a, %d %b %Y %H:%M:%S GMT", time ) -end - -function compare(d1, d2) - - if d1:match("[^0-9]") then d1 = to_unix(d1) end - if d2:match("[^0-9]") then d2 = to_unix(d2) end - - if d1 == d2 then - return 0 - elseif d1 < d2 then - return -1 - else - return 1 - end -end diff --git a/luci-base/luasrc/http/protocol/date.luadoc b/luci-base/luasrc/http/protocol/date.luadoc deleted file mode 100644 index d6f1c8d65..000000000 --- a/luci-base/luasrc/http/protocol/date.luadoc +++ /dev/null @@ -1,46 +0,0 @@ ----[[ -LuCI http protocol implementation - date helper class. - -This class contains functions to parse, compare and format http dates. -]] -module "luci.http.protocol.date" - ----[[ -Return the time offset in seconds between the UTC and given time zone. - -@class function -@name tz_offset -@param tz Symbolic or numeric timezone specifier -@return Time offset to UTC in seconds -]] - ----[[ -Parse given HTTP date string and convert it to unix epoch time. - -@class function -@name to_unix -@param data String containing the date -@return Unix epoch time -]] - ----[[ -Convert the given unix epoch time to valid HTTP date string. - -@class function -@name to_http -@param time Unix epoch time -@return String containing the formatted date -]] - ----[[ -Compare two dates which can either be unix epoch times or HTTP date strings. - -@class function -@name compare -@param d1 The first date or epoch time to compare -@param d2 The first date or epoch time to compare -@return -1 - if d1 is lower then d2 -@return 0 - if both dates are equal -@return 1 - if d1 is higher then d2 -]] - diff --git a/luci-base/luasrc/http/protocol/mime.lua b/luci-base/luasrc/http/protocol/mime.lua deleted file mode 100644 index 2b99d8e74..000000000 --- a/luci-base/luasrc/http/protocol/mime.lua +++ /dev/null @@ -1,78 +0,0 @@ --- Copyright 2008 Freifunk Leipzig / Jo-Philipp Wich --- Licensed to the public under the Apache License 2.0. - --- This class provides functions to guess mime types from file extensions and --- vice versa. -module("luci.http.protocol.mime", package.seeall) - -require("luci.util") - -MIME_TYPES = { - ["txt"] = "text/plain"; - ["js"] = "text/javascript"; - ["css"] = "text/css"; - ["htm"] = "text/html"; - ["html"] = "text/html"; - ["patch"] = "text/x-patch"; - ["c"] = "text/x-csrc"; - ["h"] = "text/x-chdr"; - ["o"] = "text/x-object"; - ["ko"] = "text/x-object"; - - ["bmp"] = "image/bmp"; - ["gif"] = "image/gif"; - ["png"] = "image/png"; - ["jpg"] = "image/jpeg"; - ["jpeg"] = "image/jpeg"; - ["svg"] = "image/svg+xml"; - - ["zip"] = "application/zip"; - ["pdf"] = "application/pdf"; - ["xml"] = "application/xml"; - ["xsl"] = "application/xml"; - ["doc"] = "application/msword"; - ["ppt"] = "application/vnd.ms-powerpoint"; - ["xls"] = "application/vnd.ms-excel"; - ["odt"] = "application/vnd.oasis.opendocument.text"; - ["odp"] = "application/vnd.oasis.opendocument.presentation"; - ["pl"] = "application/x-perl"; - ["sh"] = "application/x-shellscript"; - ["php"] = "application/x-php"; - ["deb"] = "application/x-deb"; - ["iso"] = "application/x-cd-image"; - ["tgz"] = "application/x-compressed-tar"; - - ["mp3"] = "audio/mpeg"; - ["ogg"] = "audio/x-vorbis+ogg"; - ["wav"] = "audio/x-wav"; - - ["mpg"] = "video/mpeg"; - ["mpeg"] = "video/mpeg"; - ["avi"] = "video/x-msvideo"; -} - --- "application/octet-stream" if the extension is unknown. -function to_mime(filename) - if type(filename) == "string" then - local ext = filename:match("[^%.]+$") - - if ext and MIME_TYPES[ext:lower()] then - return MIME_TYPES[ext:lower()] - end - end - - return "application/octet-stream" -end - --- given mime-type is unknown. -function to_ext(mimetype) - if type(mimetype) == "string" then - for ext, type in luci.util.kspairs( MIME_TYPES ) do - if type == mimetype then - return ext - end - end - end - - return nil -end diff --git a/luci-base/luasrc/http/protocol/mime.luadoc b/luci-base/luasrc/http/protocol/mime.luadoc deleted file mode 100644 index 195b5fcc8..000000000 --- a/luci-base/luasrc/http/protocol/mime.luadoc +++ /dev/null @@ -1,34 +0,0 @@ ----[[ -LuCI http protocol implementation - mime helper class. - -This class provides functions to guess mime types from file extensions and -vice versa. -]] -module "luci.http.protocol.mime" - ----[[ -MIME mapping table containg extension - mimetype relations. - -@class table -]] - ----[[ -Extract extension from a filename and return corresponding mime-type or - -"application/octet-stream" if the extension is unknown. -@class function -@name to_mime -@param filename The filename for which the mime type is guessed -@return String containign the determined mime type -]] - ----[[ -Return corresponding extension for a given mime type or nil if the - -given mime-type is unknown. -@class function -@name to_ext -@param mimetype The mimetype to retrieve the extension from -@return String with the extension or nil for unknown type -]] - diff --git a/luci-base/luasrc/model/ipkg.lua b/luci-base/luasrc/model/ipkg.lua index e653b0346..e27ea5289 100644 --- a/luci-base/luasrc/model/ipkg.lua +++ b/luci-base/luasrc/model/ipkg.lua @@ -20,12 +20,14 @@ module "luci.model.ipkg" -- Internal action function local function _action(cmd, ...) - local pkg = "" + local cmdline = { ipkg, cmd } + + local k, v for k, v in pairs({...}) do - pkg = pkg .. " '" .. v:gsub("'", "") .. "'" + cmdline[#cmdline+1] = util.shellquote(v) end - local c = "%s %s %s >/tmp/opkg.stdout 2>/tmp/opkg.stderr" %{ ipkg, cmd, pkg } + local c = "%s >/tmp/opkg.stdout 2>/tmp/opkg.stderr" % table.concat(cmdline, " ") local r = os.execute(c) local e = fs.readfile("/tmp/opkg.stderr") local o = fs.readfile("/tmp/opkg.stdout") @@ -74,17 +76,17 @@ local function _parselist(rawdata) end -- Internal lookup function -local function _lookup(act, pkg) - local cmd = ipkg .. " " .. act +local function _lookup(cmd, pkg) + local cmdline = { ipkg, cmd } if pkg then - cmd = cmd .. " '" .. pkg:gsub("'", "") .. "'" + cmdline[#cmdline+1] = util.shellquote(pkg) end -- OPKG sometimes kills the whole machine because it sucks -- Therefore we have to use a sucky approach too and use -- tmpfiles instead of directly reading the output local tmpfile = os.tmpname() - os.execute(cmd .. (" >%s 2>/dev/null" % tmpfile)) + os.execute("%s >%s 2>/dev/null" %{ table.concat(cmdline, " "), tmpfile }) local data = _parselist(io.lines(tmpfile)) os.remove(tmpfile) @@ -123,9 +125,12 @@ end -- List helper local function _list(action, pat, cb) - local fd = io.popen(ipkg .. " " .. action .. - (pat and (" '%s'" % pat:gsub("'", "")) or "")) + local cmdline = { ipkg, action } + if pat then + cmdline[#cmdline+1] = util.shellquote(pat) + end + local fd = io.popen(table.concat(cmdline, " ")) if fd then local name, version, sz, desc while true do diff --git a/luci-base/luasrc/model/network.lua b/luci-base/luasrc/model/network.lua index 056fc67b1..dfe818bcc 100644 --- a/luci-base/luasrc/model/network.lua +++ b/luci-base/luasrc/model/network.lua @@ -629,7 +629,7 @@ function get_interface(self, i) if _interfaces[i] or _wifi_iface(i) then return interface(i) else - local netid = _wifi_netid_by_netname(i) + local netid = _wifi_netid_by_sid(i) return netid and interface(netid) end end diff --git a/luci-base/luasrc/model/uci.lua b/luci-base/luasrc/model/uci.lua index 577c6cde0..fc2a605b3 100644 --- a/luci-base/luasrc/model/uci.lua +++ b/luci-base/luasrc/model/uci.lua @@ -2,13 +2,12 @@ -- Licensed to the public under the Apache License 2.0. local os = require "os" -local uci = require "uci" local util = require "luci.util" local table = require "table" local setmetatable, rawget, rawset = setmetatable, rawget, rawset -local require, getmetatable = require, getmetatable +local require, getmetatable, assert = require, getmetatable, assert local error, pairs, ipairs = error, pairs, ipairs local type, tostring, tonumber, unpack = type, tostring, tonumber, unpack @@ -20,151 +19,436 @@ local type, tostring, tonumber, unpack = type, tostring, tonumber, unpack -- reloaded. module "luci.model.uci" -cursor = uci.cursor +local ERRSTR = { + "Invalid command", + "Invalid argument", + "Method not found", + "Entry not found", + "No data", + "Permission denied", + "Timeout", + "Not supported", + "Unknown error", + "Connection failed" +} -APIVERSION = uci.APIVERSION +local session_id = nil -function cursor_state() - return cursor(nil, "/var/state") +local function call(cmd, args) + if type(args) == "table" and session_id then + args.ubus_rpc_session = session_id + end + return util.ubus("uci", cmd, args) end -inst = cursor() -inst_state = cursor_state() +function cursor() + return _M +end -local Cursor = getmetatable(inst) +function cursor_state() + return _M +end -function Cursor.apply(self, configlist, command) +function substate(self) + return self +end + + +function get_confdir(self) + return "/etc/config" +end + +function get_savedir(self) + return "/tmp/.uci" +end + +function get_session_id(self) + return session_id +end + +function set_confdir(self, directory) + return false +end + +function set_savedir(self, directory) + return false +end + +function set_session_id(self, id) + session_id = id + return true +end + + +function load(self, config) + return true +end + +function save(self, config) + return true +end + +function unload(self, config) + return true +end + + +function changes(self, config) + local rv = call("changes", { config = config }) + local res = {} + + if type(rv) == "table" and type(rv.changes) == "table" then + local package, changes + for package, changes in pairs(rv.changes) do + res[package] = {} + + local _, change + for _, change in ipairs(changes) do + local operation, section, option, value = unpack(change) + if option and value and operation ~= "add" then + res[package][section] = res[package][section] or { } + + if operation == "list-add" then + local v = res[package][section][option] + if type(v) == "table" then + v[#v+1] = value or "" + elseif v ~= nil then + res[package][section][option] = { v, value } + else + res[package][section][option] = { value } + end + else + res[package][section][option] = value or "" + end + else + res[package][section] = res[package][section] or {} + res[package][section][".type"] = option or "" + end + end + end + end + + return res +end + + +function revert(self, config) + local _, err = call("revert", { config = config }) + return (err == nil), ERRSTR[err] +end + +function commit(self, config) + local _, err = call("commit", { config = config }) + return (err == nil), ERRSTR[err] +end + +--[[ +function apply(self, configs, command) + local _, config + + assert(not command, "Apply command not supported anymore") + + if type(configs) == "table" then + for _, config in ipairs(configs) do + call("service", "event", { + type = "config.change", + data = { package = config } + }) + end + end +end +]] + + +function foreach(self, config, stype, callback) + if type(callback) == "function" then + local rv, err = call("get", { + config = config, + type = stype + }) + + if type(rv) == "table" and type(rv.values) == "table" then + local sections = { } + local res = false + local index = 1 + + local _, section + for _, section in pairs(rv.values) do + section[".index"] = section[".index"] or index + sections[index] = section + index = index + 1 + end + + table.sort(sections, function(a, b) + return a[".index"] < b[".index"] + end) + + for _, section in ipairs(sections) do + local continue = callback(section) + res = true + if continue == false then + break + end + end + return res + else + return false, ERRSTR[err] or "No data" + end + else + return false, "Invalid argument" + end +end + +local function _get(self, operation, config, section, option) + if section == nil then + return nil + elseif type(option) == "string" and option:byte(1) ~= 46 then + local rv, err = call(operation, { + config = config, + section = section, + option = option + }) + + if type(rv) == "table" then + return rv.value or nil + elseif err then + return false, ERRSTR[err] + else + return nil + end + elseif option == nil then + local values = self:get_all(config, section) + if values then + return values[".type"], values[".name"] + else + return nil + end + else + return false, "Invalid argument" + end +end + +function get(self, ...) + return _get(self, "get", ...) +end + +function get_state(self, ...) + return _get(self, "state", ...) +end + +function get_all(self, config, section) + local rv, err = call("get", { + config = config, + section = section + }) + + if type(rv) == "table" and type(rv.values) == "table" then + return rv.values + elseif err then + return false, ERRSTR[err] + else + return nil + end +end + +function get_bool(self, ...) + local val = self:get(...) + return (val == "1" or val == "true" or val == "yes" or val == "on") +end + +function get_first(self, config, stype, option, default) + local rv = default + + self:foreach(config, stype, function(s) + local val = not option and s[".name"] or s[option] + + if type(default) == "number" then + val = tonumber(val) + elseif type(default) == "boolean" then + val = (val == "1" or val == "true" or + val == "yes" or val == "on") + end + + if val ~= nil then + rv = val + return false + end + end) + + return rv +end + +function get_list(self, config, section, option) + if config and section and option then + local val = self:get(config, section, option) + return (type(val) == "table" and val or { val }) + end + return { } +end + + +function section(self, config, stype, name, values) + local rv, err = call("add", { + config = config, + type = stype, + name = name, + values = values + }) + + if type(rv) == "table" then + return rv.section + elseif err then + return false, ERRSTR[err] + else + return nil + end +end + + +function add(self, config, stype) + return self:section(config, stype) +end + +function set(self, config, section, option, value) + if value == nil then + local sname, err = self:section(config, option, section) + return (not not sname), err + else + local _, err = call("set", { + config = config, + section = section, + values = { [option] = value } + }) + return (err == nil), ERRSTR[err] + end +end + +function set_list(self, config, section, option, value) + if section == nil or option == nil then + return false + elseif value == nil or (type(value) == "table" and #value == 0) then + return self:delete(config, section, option) + elseif type(value) == "table" then + return self:set(config, section, option, value) + else + return self:set(config, section, option, { value }) + end +end + +function tset(self, config, section, values) + local _, err = call("set", { + config = config, + section = section, + values = values + }) + return (err == nil), ERRSTR[err] +end + +function reorder(self, config, section, index) + local sections + + if type(section) == "string" and type(index) == "number" then + local pos = 0 + + sections = { } + + self:foreach(config, nil, function(s) + if pos == index then + pos = pos + 1 + end + + if s[".name"] ~= section then + pos = pos + 1 + sections[pos] = s[".name"] + else + sections[index + 1] = section + end + end) + elseif type(section) == "table" then + sections = section + else + return false, "Invalid argument" + end + + local _, err = call("order", { + config = config, + sections = sections + }) + + return (err == nil), ERRSTR[err] +end + + +function delete(self, config, section, option) + local _, err = call("delete", { + config = config, + section = section, + option = option + }) + return (err == nil), ERRSTR[err] +end + +function delete_all(self, config, stype, comparator) + local _, err + if type(comparator) == "table" then + _, err = call("delete", { + config = config, + type = stype, + match = comparator + }) + elseif type(comparator) == "function" then + local rv = call("get", { + config = config, + type = stype + }) + + if type(rv) == "table" and type(rv.values) == "table" then + local sname, section + for sname, section in pairs(rv.values) do + if comparator(section) then + _, err = call("delete", { + config = config, + section = sname + }) + end + end + end + elseif comparator == nil then + _, err = call("delete", { + config = config, + type = stype + }) + else + return false, "Invalid argument" + end + + return (err == nil), ERRSTR[err] +end + + +function apply(self, configlist, command) configlist = self:_affected(configlist) if command then return { "/sbin/luci-reload", unpack(configlist) } else return os.execute("/sbin/luci-reload %s >/dev/null 2>&1" - % table.concat(configlist, " ")) + % util.shellquote(table.concat(configlist, " "))) end end - --- returns a boolean whether to delete the current section (optional) -function Cursor.delete_all(self, config, stype, comparator) - local del = {} - - if type(comparator) == "table" then - local tbl = comparator - comparator = function(section) - for k, v in pairs(tbl) do - if section[k] ~= v then - return false - end - end - return true - end - end - - local function helper (section) - - if not comparator or comparator(section) then - del[#del+1] = section[".name"] - end - end - - self:foreach(config, stype, helper) - - for i, j in ipairs(del) do - self:delete(config, j) - end -end - -function Cursor.section(self, config, type, name, values) - local stat = true - if name then - stat = self:set(config, name, type) - else - name = self:add(config, type) - stat = name and true - end - - if stat and values then - stat = self:tset(config, name, values) - end - - return stat and name -end - -function Cursor.tset(self, config, section, values) - local stat = true - for k, v in pairs(values) do - if k:sub(1, 1) ~= "." then - stat = stat and self:set(config, section, k, v) - end - end - return stat -end - -function Cursor.get_bool(self, ...) - local val = self:get(...) - return ( val == "1" or val == "true" or val == "yes" or val == "on" ) -end - -function Cursor.get_list(self, config, section, option) - if config and section and option then - local val = self:get(config, section, option) - return ( type(val) == "table" and val or { val } ) - end - return {} -end - -function Cursor.get_first(self, conf, stype, opt, def) - local rv = def - - self:foreach(conf, stype, - function(s) - local val = not opt and s['.name'] or s[opt] - - if type(def) == "number" then - val = tonumber(val) - elseif type(def) == "boolean" then - val = (val == "1" or val == "true" or - val == "yes" or val == "on") - end - - if val ~= nil then - rv = val - return false - end - end) - - return rv -end - -function Cursor.set_list(self, config, section, option, value) - if config and section and option then - if not value or #value == 0 then - return self:delete(config, section, option) - end - return self:set( - config, section, option, - ( type(value) == "table" and value or { value } ) - ) - end - return false -end - -- Return a list of initscripts affected by configuration changes. -function Cursor._affected(self, configlist) - configlist = type(configlist) == "table" and configlist or {configlist} - - local c = cursor() - c:load("ucitrack") +function _affected(self, configlist) + configlist = type(configlist) == "table" and configlist or { configlist } -- Resolve dependencies - local reloadlist = {} + local reloadlist = { } local function _resolve_deps(name) - local reload = {name} - local deps = {} + local reload = { name } + local deps = { } - c:foreach("ucitrack", name, + self:foreach("ucitrack", name, function(section) if section.affects then for i, aff in ipairs(section.affects) do @@ -173,7 +457,9 @@ function Cursor._affected(self, configlist) end end) + local i, dep for i, dep in ipairs(deps) do + local j, add for j, add in ipairs(_resolve_deps(dep)) do reload[#reload+1] = add end @@ -183,7 +469,9 @@ function Cursor._affected(self, configlist) end -- Collect initscripts + local j, config for j, config in ipairs(configlist) do + local i, e for i, e in ipairs(_resolve_deps(config)) do if not util.contains(reloadlist, e) then reloadlist[#reloadlist+1] = e @@ -193,44 +481,3 @@ function Cursor._affected(self, configlist) return reloadlist end - --- curser, means it the parent unloads or loads configs, the sub state will --- do so as well. -function Cursor.substate(self) - Cursor._substates = Cursor._substates or { } - Cursor._substates[self] = Cursor._substates[self] or cursor_state() - return Cursor._substates[self] -end - -local _load = Cursor.load -function Cursor.load(self, ...) - if Cursor._substates and Cursor._substates[self] then - _load(Cursor._substates[self], ...) - end - return _load(self, ...) -end - -local _unload = Cursor.unload -function Cursor.unload(self, ...) - if Cursor._substates and Cursor._substates[self] then - _unload(Cursor._substates[self], ...) - end - return _unload(self, ...) -end - - - - - - - - - - - - - - - - - diff --git a/luci-base/luasrc/model/uci.luadoc b/luci-base/luasrc/model/uci.luadoc index 49093c793..ef89d09b9 100644 --- a/luci-base/luasrc/model/uci.luadoc +++ b/luci-base/luasrc/model/uci.luadoc @@ -14,224 +14,226 @@ module "luci.model.uci" ---[[ Create a new UCI-Cursor. -@class function -@name cursor -@return UCI-Cursor +@class function +@name cursor +@return UCI-Cursor ]] ---[[ Create a new Cursor initialized to the state directory. -@class function -@name cursor_state -@return UCI cursor +@class function +@name cursor_state +@return UCI cursor ]] ---[[ Applies UCI configuration changes -@class function -@name Cursor.apply -@param configlist List of UCI configurations -@param command Don't apply only return the command +@class function +@name Cursor.apply +@param configlist List of UCI configurations +@param command Don't apply only return the command ]] ---[[ Delete all sections of a given type that match certain criteria. -@class function -@name Cursor.delete_all +@class function +@name Cursor.delete_all @param config UCI config @param type UCI section type -@param comparator Function that will be called for each section and -returns a boolean whether to delete the current section (optional) +@param comparator Function that will be called for each section and returns + a boolean whether to delete the current section (optional) ]] ---[[ Create a new section and initialize it with data. -@class function -@name Cursor.section -@param config UCI config -@param type UCI section type -@param name UCI section name (optional) -@param values Table of key - value pairs to initialize the section with -@return Name of created section +@class function +@name Cursor.section +@param config UCI config +@param type UCI section type +@param name UCI section name (optional) +@param values Table of key - value pairs to initialize the section with +@return Name of created section ]] ---[[ Updated the data of a section using data from a table. -@class function -@name Cursor.tset -@param config UCI config -@param section UCI section name (optional) -@param values Table of key - value pairs to update the section with +@class function +@name Cursor.tset +@param config UCI config +@param section UCI section name (optional) +@param values Table of key - value pairs to update the section with ]] ---[[ Get a boolean option and return it's value as true or false. -@class function -@name Cursor.get_bool -@param config UCI config -@param section UCI section name -@param option UCI option -@return Boolean +@class function +@name Cursor.get_bool +@param config UCI config +@param section UCI section name +@param option UCI option +@return Boolean ]] ---[[ Get an option or list and return values as table. -@class function -@name Cursor.get_list -@param config UCI config -@param section UCI section name -@param option UCI option -@return table. If the option was not found, you will simply get --- an empty table. +@class function +@name Cursor.get_list +@param config UCI config +@param section UCI section name +@param option UCI option +@return table. If the option was not found, you will simply get an empty + table. ]] ---[[ Get the given option from the first section with the given type. -@class function -@name Cursor.get_first -@param config UCI config -@param type UCI section type -@param option UCI option (optional) -@param default Default value (optional) -@return UCI value +@class function +@name Cursor.get_first +@param config UCI config +@param type UCI section type +@param option UCI option (optional) +@param default Default value (optional) +@return UCI value ]] ---[[ Set given values as list. Setting a list option to an empty list has the same effect as deleting the option. -@class function -@name Cursor.set_list -@param config UCI config -@param section UCI section name -@param option UCI option -@param value value or table. Raw values will become a single item table. -@return Boolean whether operation succeeded +@class function +@name Cursor.set_list +@param config UCI config +@param section UCI section name +@param option UCI option +@param value Value or table. Non-table values will be set as single + item UCI list. +@return Boolean whether operation succeeded ]] ---[[ -Create a sub-state of this cursor. The sub-state is tied to the parent +Create a sub-state of this cursor. -curser, means it the parent unloads or loads configs, the sub state will -do so as well. -@class function -@name Cursor.substate -@return UCI state cursor tied to the parent cursor +The sub-state is tied to the parent curser, means it the parent unloads or +loads configs, the sub state will do so as well. + +@class function +@name Cursor.substate +@return UCI state cursor tied to the parent cursor ]] ---[[ Add an anonymous section. -@class function -@name Cursor.add -@param config UCI config -@param type UCI section type -@return Name of created section +@class function +@name Cursor.add +@param config UCI config +@param type UCI section type +@return Name of created section ]] ---[[ Get a table of saved but uncommitted changes. -@class function -@name Cursor.changes -@param config UCI config -@return Table of changes -@see Cursor.save +@class function +@name Cursor.changes +@param config UCI config +@return Table of changes +@see Cursor.save ]] ---[[ Commit saved changes. -@class function -@name Cursor.commit -@param config UCI config -@return Boolean whether operation succeeded -@see Cursor.revert -@see Cursor.save +@class function +@name Cursor.commit +@param config UCI config +@return Boolean whether operation succeeded +@see Cursor.revert +@see Cursor.save ]] ---[[ Deletes a section or an option. -@class function -@name Cursor.delete -@param config UCI config -@param section UCI section name -@param option UCI option (optional) -@return Boolean whether operation succeeded +@class function +@name Cursor.delete +@param config UCI config +@param section UCI section name +@param option UCI option (optional) +@return Boolean whether operation succeeded ]] ---[[ Call a function for every section of a certain type. -@class function -@name Cursor.foreach -@param config UCI config -@param type UCI section type -@param callback Function to be called -@return Boolean whether operation succeeded +@class function +@name Cursor.foreach +@param config UCI config +@param type UCI section type +@param callback Function to be called +@return Boolean whether operation succeeded ]] ---[[ Get a section type or an option -@class function -@name Cursor.get -@param config UCI config -@param section UCI section name -@param option UCI option (optional) -@return UCI value +@class function +@name Cursor.get +@param config UCI config +@param section UCI section name +@param option UCI option (optional) +@return UCI value ]] ---[[ Get all sections of a config or all values of a section. -@class function -@name Cursor.get_all -@param config UCI config -@param section UCI section name (optional) -@return Table of UCI sections or table of UCI values +@class function +@name Cursor.get_all +@param config UCI config +@param section UCI section name (optional) +@return Table of UCI sections or table of UCI values ]] ---[[ Manually load a config. -@class function -@name Cursor.load -@param config UCI config -@return Boolean whether operation succeeded -@see Cursor.save -@see Cursor.unload +@class function +@name Cursor.load +@param config UCI config +@return Boolean whether operation succeeded +@see Cursor.save +@see Cursor.unload ]] ---[[ Revert saved but uncommitted changes. -@class function -@name Cursor.revert -@param config UCI config -@return Boolean whether operation succeeded -@see Cursor.commit -@see Cursor.save +@class function +@name Cursor.revert +@param config UCI config +@return Boolean whether operation succeeded +@see Cursor.commit +@see Cursor.save ]] ---[[ Saves changes made to a config to make them committable. -@class function -@name Cursor.save -@param config UCI config -@return Boolean whether operation succeeded -@see Cursor.load -@see Cursor.unload +@class function +@name Cursor.save +@param config UCI config +@return Boolean whether operation succeeded +@see Cursor.load +@see Cursor.unload ]] ---[[ @@ -243,57 +245,74 @@ then a named section of the given type is created. When invoked with four arguments `config`, `sectionname`, `optionname` and `optionvalue` then the value of the specified option is set to the given value. -@class function -@name Cursor.set -@param config UCI config -@param section UCI section name -@param option UCI option or UCI section type +@class function +@name Cursor.set +@param config UCI config +@param section UCI section name +@param option UCI option or UCI section type @param value UCI value or nothing if you want to create a section -@return Boolean whether operation succeeded +@return Boolean whether operation succeeded ]] ---[[ Get the configuration directory. -@class function -@name Cursor.get_confdir -@return Configuration directory +@class function +@name Cursor.get_confdir +@return Configuration directory ]] ---[[ Get the directory for uncomitted changes. -@class function -@name Cursor.get_savedir -@return Save directory +@class function +@name Cursor.get_savedir +@return Save directory +]] + +---[[ +Get the effective session ID. + +@class function +@name Cursor.get_session_id +@return String containing the session ID ]] ---[[ Set the configuration directory. -@class function -@name Cursor.set_confdir +@class function +@name Cursor.set_confdir @param directory UCI configuration directory -@return Boolean whether operation succeeded +@return Boolean whether operation succeeded ]] ---[[ Set the directory for uncommited changes. -@class function -@name Cursor.set_savedir +@class function +@name Cursor.set_savedir @param directory UCI changes directory -@return Boolean whether operation succeeded +@return Boolean whether operation succeeded +]] + +---[[ +Set the effective session ID. + +@class function +@name Cursor.set_session_id +@param id String containing the session ID to set +@return Boolean whether operation succeeded ]] ---[[ Discard changes made to a config. -@class function -@name Cursor.unload -@param config UCI config -@return Boolean whether operation succeeded -@see Cursor.load -@see Cursor.save +@class function +@name Cursor.unload +@param config UCI config +@return Boolean whether operation succeeded +@see Cursor.load +@see Cursor.save ]] diff --git a/luci-base/luasrc/sys.lua b/luci-base/luasrc/sys.lua index 12b20e4c3..823e20770 100644 --- a/luci-base/luasrc/sys.lua +++ b/luci-base/luasrc/sys.lua @@ -87,10 +87,10 @@ end function httpget(url, stream, target) if not target then local source = stream and io.popen or luci.util.exec - return source("wget -qO- '"..url:gsub("'", "").."'") + return source("wget -qO- %s" % luci.util.shellquote(url)) else - return os.execute("wget -qO '%s' '%s'" % - {target:gsub("'", ""), url:gsub("'", "")}) + return os.execute("wget -qO %s %s" % + {luci.util.shellquote(target), luci.util.shellquote(url)}) end end @@ -443,18 +443,11 @@ function user.checkpasswd(username, pass) end function user.setpasswd(username, password) - if password then - password = password:gsub("'", [['"'"']]) - end - - if username then - username = username:gsub("'", [['"'"']]) - end - - return os.execute( - "(echo '" .. password .. "'; sleep 1; echo '" .. password .. "') | " .. - "passwd '" .. username .. "' >/dev/null 2>&1" - ) + return os.execute("(echo %s; sleep 1; echo %s) | passwd %s >/dev/null 2>&1" %{ + luci.util.shellquote(password), + luci.util.shellquote(password), + luci.util.shellquote(username) + }) end diff --git a/luci-base/luasrc/sys/zoneinfo/tzdata.lua b/luci-base/luasrc/sys/zoneinfo/tzdata.lua index 6668dad83..47cb901a5 100644 --- a/luci-base/luasrc/sys/zoneinfo/tzdata.lua +++ b/luci-base/luasrc/sys/zoneinfo/tzdata.lua @@ -202,7 +202,7 @@ TZ = { { 'America/Winnipeg', 'CST6CDT,M3.2.0,M11.1.0' }, { 'America/Yakutat', 'AKST9AKDT,M3.2.0,M11.1.0' }, { 'America/Yellowknife', 'MST7MDT,M3.2.0,M11.1.0' }, - { 'Antarctica/Casey', '<+11>-11' }, + { 'Antarctica/Casey', '<+08>-8' }, { 'Antarctica/Davis', '<+07>-7' }, { 'Antarctica/DumontDUrville', '<+10>-10' }, { 'Antarctica/Macquarie', '<+11>-11' }, @@ -239,8 +239,8 @@ TZ = { { 'Asia/Dubai', '<+04>-4' }, { 'Asia/Dushanbe', '<+05>-5' }, { 'Asia/Famagusta', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, - { 'Asia/Gaza', 'EET-2EEST,M3.5.6/1,M10.5.6/1' }, - { 'Asia/Hebron', 'EET-2EEST,M3.5.6/1,M10.5.6/1' }, + { 'Asia/Gaza', 'EET-2EEST,M3.4.6/1,M10.5.6/1' }, + { 'Asia/Hebron', 'EET-2EEST,M3.4.6/1,M10.5.6/1' }, { 'Asia/Ho Chi Minh', '<+07>-7' }, { 'Asia/Hong Kong', 'HKT-8' }, { 'Asia/Hovd', '<+07>-7' }, diff --git a/luci-base/luasrc/tools/status.lua b/luci-base/luasrc/tools/status.lua index 501211181..06a9ad415 100644 --- a/luci-base/luasrc/tools/status.lua +++ b/luci-base/luasrc/tools/status.lua @@ -187,7 +187,9 @@ function switch_status(devs) local switches = { } for dev in devs:gmatch("[^%s,]+") do local ports = { } - local swc = io.popen("swconfig dev %q show" % dev, "r") + local swc = io.popen("swconfig dev %s show" + % luci.util.shellquote(dev), "r") + if swc then local l repeat diff --git a/luci-base/luasrc/util.lua b/luci-base/luasrc/util.lua index 0e7334be8..ce42af2fb 100644 --- a/luci-base/luasrc/util.lua +++ b/luci-base/luasrc/util.lua @@ -10,6 +10,7 @@ local string = require "string" local coroutine = require "coroutine" local tparser = require "luci.template.parser" local json = require "luci.jsonc" +local lhttp = require "lucihttp" local _ubus = require "ubus" local _ubus_connection = nil @@ -160,10 +161,33 @@ function pcdata(value) return value and tparser.pcdata(tostring(value)) end +function urlencode(value) + if value ~= nil then + local str = tostring(value) + return lhttp.urlencode(str, lhttp.ENCODE_IF_NEEDED + lhttp.ENCODE_FULL) + or str + end + return nil +end + +function urldecode(value, decode_plus) + if value ~= nil then + local flag = decode_plus and lhttp.DECODE_PLUS or 0 + local str = tostring(value) + return lhttp.urldecode(str, lhttp.DECODE_IF_NEEDED + flag) + or str + end + return nil +end + function striptags(value) return value and tparser.striptags(tostring(value)) end +function shellquote(value) + return string.format("'%s'", string.gsub(value or "", "'", "'\\''")) +end + -- for bash, ash and similar shells single-quoted strings are taken -- literally except for single quotes (which terminate the string) -- (and the exception noted below for dash (-) at the start of a @@ -383,16 +407,6 @@ function clone(object, deep) end -function dtable() - return setmetatable({}, { __index = - function(tbl, key) - return rawget(tbl, key) - or rawget(rawset(tbl, key, dtable()), key) - end - }) -end - - -- Serialize the contents of a table value. function _serialize_table(t, seen) assert(not seen[t], "Recursion detected.") @@ -617,6 +631,20 @@ function execl(command) return data end + +local ubus_codes = { + "INVALID_COMMAND", + "INVALID_ARGUMENT", + "METHOD_NOT_FOUND", + "NOT_FOUND", + "NO_DATA", + "PERMISSION_DENIED", + "TIMEOUT", + "NOT_SUPPORTED", + "UNKNOWN_ERROR", + "CONNECTION_FAILED" +} + function ubus(object, method, data) if not _ubus_connection then _ubus_connection = _ubus.connect() @@ -627,7 +655,8 @@ function ubus(object, method, data) if type(data) ~= "table" then data = { } end - return _ubus_connection:call(object, method, data) + local rv, err = _ubus_connection:call(object, method, data) + return rv, err, ubus_codes[err] elseif object then return _ubus_connection:signatures(object) else @@ -652,10 +681,11 @@ end function checklib(fullpathexe, wantedlib) local fs = require "nixio.fs" local haveldd = fs.access('/usr/bin/ldd') - if not haveldd then + local haveexe = fs.access(fullpathexe) + if not haveldd or not haveexe then return false end - local libs = exec("/usr/bin/ldd " .. fullpathexe) + local libs = exec(string.format("/usr/bin/ldd %s", shellquote(fullpathexe))) if not libs then return false end diff --git a/luci-base/luasrc/util.luadoc b/luci-base/luasrc/util.luadoc index 949aeb21c..c4f28d039 100644 --- a/luci-base/luasrc/util.luadoc +++ b/luci-base/luasrc/util.luadoc @@ -15,126 +15,164 @@ Class can be instantiated by calling them. All parameters will be passed to the __init__ function of this class - if such a function exists. The __init__ function must be used to set any object parameters that are not shared with other objects of this class. Any return values will be ignored. -@class function -@name class -@param base The base class to inherit from (optional) -@return A class object -@see instanceof -@see clone + +@class function +@name class +@param base The base class to inherit from (optional) +@return A class object +@see instanceof +@see clone ]] ---[[ Test whether the given object is an instance of the given class. -@class function -@name instanceof -@param object Object instance +@class function +@name instanceof +@param object Object instance @param class Class object to test against -@return Boolean indicating whether the object is an instance +@return Boolean indicating whether the object is an instance @see class @see clone ]] ---[[ Create a new or get an already existing thread local store associated with +the current active coroutine. -the current active coroutine. A thread local store is private a table object +A thread local store is private a table object whose values can't be accessed from outside of the running coroutine. -@class function -@name threadlocal -@return Table value representing the corresponding thread local store + +@class function +@name threadlocal +@return Table value representing the corresponding thread local store ]] ---[[ Write given object to stderr. -@class function -@name perror -@param obj Value to write to stderr -@return Boolean indicating whether the write operation was successful +@class function +@name perror +@param obj Value to write to stderr +@return Boolean indicating whether the write operation was successful ]] ---[[ Recursively dumps a table to stdout, useful for testing and debugging. -@class function -@name dumptable -@param t Table value to dump -@param maxdepth Maximum depth -@return Always nil +@class function +@name dumptable +@param t Table value to dump +@param maxdepth Maximum depth +@return Always nil ]] ---[[ Create valid XML PCDATA from given string. -@class function -@name pcdata -@param value String value containing the data to escape -@return String value containing the escaped data +@class function +@name pcdata +@param value String value containing the data to escape +@return String value containing the escaped data +]] + +---[[ +Decode an URL-encoded string - optionally decoding the "+" sign to space. + +@class function +@name urldecode +@param str Input string in x-www-urlencoded format +@param decode_plus Decode "+" signs to spaces if true (optional) +@return The decoded string +@see urlencode +]] + +---[[ +URL-encode given string. + +@class function +@name urlencode +@param str String to encode +@return String containing the encoded data +@see urldecode ]] ---[[ Strip HTML tags from given string. -@class function -@name striptags -@param value String containing the HTML text -@return String with HTML tags stripped of +@class function +@name striptags +@param value String containing the HTML text +@return String with HTML tags stripped of +]] + +---[[ +Safely quote value for use in shell commands. + +@class function +@name shellquote +@param value String containing the value to quote +@return Single-quote enclosed string with embedded quotes escaped ]] ---[[ Splits given string on a defined separator sequence and return a table +containing the resulting substrings. -containing the resulting substrings. The optional max parameter specifies -the number of bytes to process, regardless of the actual length of the given -string. The optional last parameter, regex, specifies whether the separator -sequence is interpreted as regular expression. -@class function -@name split -@param str String value containing the data to split up -@param pat String with separator pattern (optional, defaults to "\n") -@param max Maximum times to split (optional) -@param regex Boolean indicating whether to interpret the separator +The optional max parameter specifies the number of bytes to process, +regardless of the actual length of the given string. The optional last +parameter, regex, specifies whether the separator sequence is +nterpreted as regular expression. + +@class function +@name split +@param str String value containing the data to split up +@param pat String with separator pattern (optional, defaults to "\n") +@param max Maximum times to split (optional) +@param regex Boolean indicating whether to interpret the separator -- pattern as regular expression (optional, default is false) -@return Table containing the resulting substrings +@return Table containing the resulting substrings ]] ---[[ Remove leading and trailing whitespace from given string value. -@class function -@name trim -@param str String value containing whitespace padded data -@return String value with leading and trailing space removed +@class function +@name trim +@param str String value containing whitespace padded data +@return String value with leading and trailing space removed ]] ---[[ Count the occurrences of given substring in given string. -@class function -@name cmatch -@param str String to search in -@param pattern String containing pattern to find -@return Number of found occurrences +@class function +@name cmatch +@param str String to search in +@param pattern String containing pattern to find +@return Number of found occurrences ]] ---[[ -Return a matching iterator for the given value. The iterator will return +Return a matching iterator for the given value. -one token per invocation, the tokens are separated by whitespace. If the -input value is a table, it is transformed into a string first. A nil value -will result in a valid interator which aborts with the first invocation. -@class function -@name imatch -@param val The value to scan (table, string or nil) -@return Iterator which returns one token per call +The iterator will return one token per invocation, the tokens are separated by +whitespace. If the input value is a table, it is transformed into a string first. +A nil value will result in a valid interator which aborts with the first invocation. + +@class function +@name imatch +@param val The value to scan (table, string or nil) +@return Iterator which returns one token per call ]] ---[[ Parse certain units from the given string and return the canonical integer +value or 0 if the unit is unknown. -value or 0 if the unit is unknown. Upper- or lower case is irrelevant. +Upper- or lower case is irrelevant. Recognized units are: + -- o "y" - one year (60*60*24*366) o "m" - one month (60*60*24*31) o "w" - one week (60*60*24*7) @@ -147,232 +185,229 @@ Recognized units are: o "kib" - one si kilobyte (1000) o "mib" - one si megabyte (1000*1000) o "gib" - one si gigabyte (1000*1000*1000) -@class function -@name parse_units -@param ustr String containing a numerical value with trailing unit -@return Number containing the canonical value + +@class function +@name parse_units +@param ustr String containing a numerical value with trailing unit +@return Number containing the canonical value ]] ---[[ Appends numerically indexed tables or single objects to a given table. -@class function -@name append -@param src Target table -@param ... Objects to insert -@return Target table +@class function +@name append +@param src Target table +@param ... Objects to insert +@return Target table ]] ---[[ Combines two or more numerically indexed tables and single objects into one table. -@class function -@name combine -@param tbl1 Table value to combine -@param tbl2 Table value to combine -@param ... More tables to combine -@return Table value containing all values of given tables +@class function +@name combine +@param tbl1 Table value to combine +@param tbl2 Table value to combine +@param ... More tables to combine +@return Table value containing all values of given tables ]] ---[[ Checks whether the given table contains the given value. -@class function -@name contains -@param table Table value -@param value Value to search within the given table -@return number indicating the first index at which the given value occurs --- within table or false. +@class function +@name contains +@param table Table value +@param value Value to search within the given table +@return Number indicating the first index at which the given value occurs +-- within table or false. ]] ---[[ Update values in given table with the values from the second given table. Both table are - in fact - merged together. -@class function -@name update + +@class function +@name update @param t Table which should be updated -@param updates Table containing the values to update -@return Always nil +@param updates Table containing the values to update +@return Always nil ]] ---[[ Retrieve all keys of given associative table. -@class function -@name keys -@param t Table to extract keys from -@return Sorted table containing the keys +@class function +@name keys +@param t Table to extract keys from +@return Sorted table containing the keys ]] ---[[ Clones the given object and return it's copy. -@class function -@name clone -@param object Table value to clone -@param deep Boolean indicating whether to do recursive cloning -@return Cloned table value -]] - ----[[ -Create a dynamic table which automatically creates subtables. - -@class function -@name dtable -@return Dynamic Table +@class function +@name clone +@param object Table value to clone +@param deep Boolean indicating whether to do recursive cloning +@return Cloned table value ]] ---[[ Recursively serialize given data to lua code, suitable for restoring - with loadstring(). -@class function -@name serialize_data -@param val Value containing the data to serialize -@return String value containing the serialized code -@see restore_data -@see get_bytecode + +@class function +@name serialize_data +@param val Value containing the data to serialize +@return String value containing the serialized code +@see restore_data +@see get_bytecode ]] ---[[ Restore data previously serialized with serialize_data(). -@class function -@name restore_data -@param str String containing the data to restore -@return Value containing the restored data structure -@see serialize_data -@see get_bytecode +@class function +@name restore_data +@param str String containing the data to restore +@return Value containing the restored data structure +@see serialize_data +@see get_bytecode ]] ---[[ Return the current runtime bytecode of the given data. The byte code - will be stripped before it is returned. -@class function -@name get_bytecode -@param val Value to return as bytecode -@return String value containing the bytecode of the given data + +@class function +@name get_bytecode +@param val Value to return as bytecode +@return String value containing the bytecode of the given data ]] ---[[ -Strips unnescessary lua bytecode from given string. Information like line +Strips unnescessary lua bytecode from given string. -numbers and debugging numbers will be discarded. Original version by -Peter Cawley (http://lua-users.org/lists/lua-l/2008-02/msg01158.html) -@class function -@name strip_bytecode -@param code String value containing the original lua byte code -@return String value containing the stripped lua byte code +Information like line numbers and debugging numbers will be discarded. +Original version by Peter Cawley (http://lua-users.org/lists/lua-l/2008-02/msg01158.html) + +@class function +@name strip_bytecode +@param code String value containing the original lua byte code +@return String value containing the stripped lua byte code ]] ---[[ Return a key, value iterator which returns the values sorted according to - the provided callback function. -@class function -@name spairs -@param t The table to iterate -@param f A callback function to decide the order of elements -@return Function value containing the corresponding iterator + +@class function +@name spairs +@param t The table to iterate +@param f A callback function to decide the order of elements +@return Function value containing the corresponding iterator ]] ---[[ Return a key, value iterator for the given table. The table pairs are sorted by key. -@class function -@name kspairs -@param t The table to iterate -@return Function value containing the corresponding iterator + +@class function +@name kspairs +@param t The table to iterate +@return Function value containing the corresponding iterator ]] ---[[ Return a key, value iterator for the given table. The table pairs are sorted by value. -@class function -@name vspairs -@param t The table to iterate -@return Function value containing the corresponding iterator + +@class function +@name vspairs +@param t The table to iterate +@return Function value containing the corresponding iterator ]] ---[[ Test whether the current system is operating in big endian mode. -@class function -@name bigendian -@return Boolean value indicating whether system is big endian +@class function +@name bigendian +@return Boolean value indicating whether system is big endian ]] ---[[ Execute given commandline and gather stdout. -@class function -@name exec -@param command String containing command to execute -@return String containing the command's stdout +@class function +@name exec +@param command String containing command to execute +@return String containing the command's stdout ]] ---[[ Return a line-buffered iterator over the output of given command. -@class function -@name execi -@param command String containing the command to execute -@return Iterator +@class function +@name execi +@param command String containing the command to execute +@return Iterator ]] ---[[ Issue an ubus call. -@class function -@name ubus +@class function +@name ubus @param object String containing the ubus object to call @param method String containing the ubus method to call @param values Table containing the values to pass -@return Table containin the ubus result +@return Table containin the ubus result ]] ---[[ Convert data structure to JSON -@class function -@name serialize_json -@param data The data to serialize -@param writer A function to write a chunk of JSON data (optional) -@return String containing the JSON if called without write callback +@class function +@name serialize_json +@param data The data to serialize +@param writer A function to write a chunk of JSON data (optional) +@return String containing the JSON if called without write callback ]] ---[[ Returns the absolute path to LuCI base directory. -@class function -@name libpath -@return String containing the directory path +@class function +@name libpath +@return String containing the directory path ]] ---[[ This is a coroutine-safe drop-in replacement for Lua's "xpcall"-function -@class function -@name coxpcall -@param f Lua function to be called protected -@param err Custom error handler -@param ... Parameters passed to the function -@return A boolean whether the function call succeeded and the return --- values of either the function or the error handler +@class function +@name coxpcall +@param f Lua function to be called protected +@param err Custom error handler +@param ... Parameters passed to the function +@return A boolean whether the function call succeeded and the return +-- values of either the function or the error handler ]] ---[[ This is a coroutine-safe drop-in replacement for Lua's "pcall"-function -@class function -@name copcall -@param f Lua function to be called protected -@param ... Parameters passed to the function -@return A boolean whether the function call succeeded and the returns --- values of the function or the error object +@class function +@name copcall +@param f Lua function to be called protected +@param ... Parameters passed to the function +@return A boolean whether the function call succeeded and the returns +-- values of the function or the error object ]] diff --git a/luci-base/luasrc/view/cbi/browser.htm b/luci-base/luasrc/view/cbi/browser.htm index a18120141..2abc975e8 100644 --- a/luci-base/luasrc/view/cbi/browser.htm +++ b/luci-base/luasrc/view/cbi/browser.htm @@ -2,6 +2,7 @@ <%+cbi/valueheader%> /> <%+cbi/valuefooter%> diff --git a/luci-base/luasrc/view/cbi/filebrowser.htm b/luci-base/luasrc/view/cbi/filebrowser.htm index a79beebba..806b1b5f4 100644 --- a/luci-base/luasrc/view/cbi/filebrowser.htm +++ b/luci-base/luasrc/view/cbi/filebrowser.htm @@ -22,9 +22,9 @@ <% end %> + + diff --git a/luci-base/luasrc/view/cbi/tblsection.htm b/luci-base/luasrc/view/cbi/tblsection.htm index 26d13f937..3cb87563f 100644 --- a/luci-base/luasrc/view/cbi/tblsection.htm +++ b/luci-base/luasrc/view/cbi/tblsection.htm @@ -35,7 +35,7 @@ end <%- else -%>   <%- end -%> - <%- end -%> + <%- count = count +1; end -%> <%- for i, k in pairs(self.children) do if not k.optional then -%> > <%- if k.titleref then -%><%- end -%> @@ -44,7 +44,7 @@ end <%- count = count + 1; end; end; if self.sortable then -%> <%:Sort%> - <%- end; if self.extedit or self.addremove then -%> + <%- count = count + 1; end; if self.extedit or self.addremove then -%>   <%- count = count + 1; end -%> diff --git a/luci-base/luasrc/view/error404.htm b/luci-base/luasrc/view/error404.htm index bc7422683..a762f6038 100644 --- a/luci-base/luasrc/view/error404.htm +++ b/luci-base/luasrc/view/error404.htm @@ -7,5 +7,5 @@ <%+header%>

404 <%:Not Found%>

<%:Sorry, the object you requested was not found.%>

-<%:Unable to dispatch%>: <%=luci.http.request.env.PATH_INFO%> +<%:Unable to dispatch%>: <%=url(unpack(luci.dispatcher.context.request))%> <%+footer%> diff --git a/luci-base/luasrc/view/sysauth.htm b/luci-base/luasrc/view/sysauth.htm index f6b0f5706..b3ec9b761 100644 --- a/luci-base/luasrc/view/sysauth.htm +++ b/luci-base/luasrc/view/sysauth.htm @@ -6,7 +6,7 @@ <%+header%> -
"> + <%- if fuser then %>
<%:Invalid username and/or password! Please try again.%>
<% end -%> diff --git a/luci-base/po/ca/base.po b/luci-base/po/ca/base.po index a6a8843a7..b08344b40 100644 --- a/luci-base/po/ca/base.po +++ b/luci-base/po/ca/base.po @@ -743,6 +743,11 @@ msgstr "" msgid "Custom feeds" msgstr "" +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + msgid "" "Customizes the behaviour of the device LEDs if possible." @@ -1012,6 +1017,11 @@ msgstr "Emergència" msgid "Enable" msgstr "Habilita" +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + msgid "Enable STP" msgstr "Habilita l'STP" @@ -1069,6 +1079,9 @@ msgstr "Activa/Desactiva" msgid "Enabled" msgstr "Habilitat" +msgid "Enables IGMP snooping on this bridge" +msgstr "" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -2154,6 +2167,9 @@ msgstr "Avís" msgid "Nslookup" msgstr "Nslookup" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "D'acord" @@ -2913,6 +2929,9 @@ msgstr "Mida" msgid "Size (.ipk)" msgstr "Mida (.ipk)" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Salta" @@ -3305,7 +3324,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" @@ -3526,7 +3545,7 @@ msgstr "" msgid "" "Use the Add Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." diff --git a/luci-base/po/cs/base.po b/luci-base/po/cs/base.po index c69654f1e..aa4144758 100644 --- a/luci-base/po/cs/base.po +++ b/luci-base/po/cs/base.po @@ -737,6 +737,11 @@ msgstr "" msgid "Custom feeds" msgstr "" +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + msgid "" "Customizes the behaviour of the device LEDs if possible." @@ -1012,6 +1017,11 @@ msgstr "Záchrana" msgid "Enable" msgstr "Povolit" +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + msgid "Enable STP" msgstr "Povolit STP" @@ -1069,6 +1079,9 @@ msgstr "Povolit/Zakázat" msgid "Enabled" msgstr "Povoleno" +msgid "Enables IGMP snooping on this bridge" +msgstr "" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -2162,6 +2175,9 @@ msgstr "Oznámení" msgid "Nslookup" msgstr "Nslookup" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -2939,6 +2955,9 @@ msgstr "Velikost" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Přeskočit" @@ -3347,7 +3366,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" @@ -3566,7 +3585,7 @@ msgstr "Použít směrovací tabulku" msgid "" "Use the Add Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." diff --git a/luci-base/po/de/base.po b/luci-base/po/de/base.po index 47472a37c..574ddf184 100644 --- a/luci-base/po/de/base.po +++ b/luci-base/po/de/base.po @@ -763,6 +763,11 @@ msgstr "" msgid "Custom feeds" msgstr "Eigene Repositories" +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + msgid "" "Customizes the behaviour of the device LEDs if possible." @@ -1038,6 +1043,11 @@ msgstr "Notfall" msgid "Enable" msgstr "Aktivieren" +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + msgid "Enable STP" msgstr "STP aktivieren" @@ -1096,6 +1106,9 @@ msgstr "Aktivieren/Deaktivieren" msgid "Enabled" msgstr "Aktiviert" +msgid "Enables IGMP snooping on this bridge" +msgstr "" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -2228,6 +2241,9 @@ msgstr "Notiz" msgid "Nslookup" msgstr "DNS-Auflösung" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -3039,6 +3055,9 @@ msgstr "Größe" msgid "Size (.ipk)" msgstr "Größe (.ipk)" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Überspringen" @@ -3475,15 +3494,15 @@ msgid "" "This is the content of /etc/rc.local. Insert your own commands here (in " "front of 'exit 0') to execute them at the end of the boot process." msgstr "" -"Dies ist der Inhalt von /etc.rc.local. Hier kann man eigene Befehle einfügen " +"Dies ist der Inhalt von /etc/rc.local. Hier kann man eigene Befehle einfügen " "(vor 'exit 0'), die dann am Ende des Bootvorgangs ausgeführt werden." msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" "Dies ist die lokale, vom Broker zugewiesene IPv6-Adresse, sie endet " -"üblicherweise mit :2" +"üblicherweise mit ...:2/64" msgid "" "This is the only DHCPAdd Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." diff --git a/luci-base/po/el/base.po b/luci-base/po/el/base.po index d0b9e240f..f746db32a 100644 --- a/luci-base/po/el/base.po +++ b/luci-base/po/el/base.po @@ -746,6 +746,11 @@ msgstr "" msgid "Custom feeds" msgstr "" +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + msgid "" "Customizes the behaviour of the device LEDs if possible." @@ -1024,6 +1029,11 @@ msgstr "Έκτακτη ανάγκη" msgid "Enable" msgstr "Ενεργοποίηση" +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + msgid "Enable STP" msgstr "Ενεργοποίηση STP" @@ -1081,6 +1091,9 @@ msgstr "Ενεργοποίηση/Απενεργοποίηση" msgid "Enabled" msgstr "Ενεργοποιημένο" +msgid "Enables IGMP snooping on this bridge" +msgstr "" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -2170,6 +2183,9 @@ msgstr "Επισήμανση" msgid "Nslookup" msgstr "" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "Εντάξει" @@ -2931,6 +2947,9 @@ msgstr "Μέγεθος" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Παράκαμψη" @@ -3307,7 +3326,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" @@ -3522,7 +3541,7 @@ msgstr "" msgid "" "Use the Add Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." diff --git a/luci-base/po/en/base.po b/luci-base/po/en/base.po index fbaa03b6f..50a7c9281 100644 --- a/luci-base/po/en/base.po +++ b/luci-base/po/en/base.po @@ -733,6 +733,11 @@ msgstr "" msgid "Custom feeds" msgstr "" +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + msgid "" "Customizes the behaviour of the device LEDs if possible." @@ -1003,6 +1008,11 @@ msgstr "" msgid "Enable" msgstr "" +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + msgid "Enable STP" msgstr "Enable STP" @@ -1060,6 +1070,9 @@ msgstr "Enable/Disable" msgid "Enabled" msgstr "Enabled" +msgid "Enables IGMP snooping on this bridge" +msgstr "" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -2137,6 +2150,9 @@ msgstr "" msgid "Nslookup" msgstr "" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -2895,6 +2911,9 @@ msgstr "Size" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Skip" @@ -3267,7 +3286,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" @@ -3479,7 +3498,7 @@ msgstr "" msgid "" "Use the Add Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." diff --git a/luci-base/po/es/base.po b/luci-base/po/es/base.po index a92bb43c1..8aed2e9ee 100644 --- a/luci-base/po/es/base.po +++ b/luci-base/po/es/base.po @@ -742,6 +742,11 @@ msgstr "" msgid "Custom feeds" msgstr "" +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + msgid "" "Customizes the behaviour of the device LEDs if possible." @@ -1018,6 +1023,11 @@ msgstr "Emergencia" msgid "Enable" msgstr "Activar" +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + msgid "Enable STP" msgstr "Activar STP" @@ -1075,6 +1085,9 @@ msgstr "Activar/Desactivar" msgid "Enabled" msgstr "Activado" +msgid "Enables IGMP snooping on this bridge" +msgstr "" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -2176,6 +2189,9 @@ msgstr "Aviso" msgid "Nslookup" msgstr "NSLookup" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "Aceptar" @@ -2952,6 +2968,9 @@ msgstr "Tamaño" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Saltar" @@ -3372,10 +3391,10 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" "Esta es la dirección de punto final asignada por el broker del túnel, suele " -"terminar con :2" +"terminar con ...:2/64" msgid "" "This is the only DHCPAdd Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." diff --git a/luci-base/po/fr/base.po b/luci-base/po/fr/base.po index cba7caca3..e09343815 100644 --- a/luci-base/po/fr/base.po +++ b/luci-base/po/fr/base.po @@ -749,6 +749,11 @@ msgstr "" msgid "Custom feeds" msgstr "" +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + msgid "" "Customizes the behaviour of the device LEDs if possible." @@ -1028,6 +1033,11 @@ msgstr "Urgence" msgid "Enable" msgstr "Activer" +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + msgid "Enable STP" msgstr "Activer le protocole STP" @@ -1085,6 +1095,9 @@ msgstr "Activer/Désactiver" msgid "Enabled" msgstr "Activé" +msgid "Enables IGMP snooping on this bridge" +msgstr "" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -2190,6 +2203,9 @@ msgstr "Note" msgid "Nslookup" msgstr "Nslookup" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -2966,6 +2982,9 @@ msgstr "Taille" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Passer au suivant" @@ -3387,10 +3406,10 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" "Il s'agit de l'adresse de l'extrémité locale attribuée par le fournisseur de " -"tunnels, elle se termine habituellement avec :2" +"tunnels, elle se termine habituellement avec ...:2/64" msgid "" "This is the only DHCPAdd Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." diff --git a/luci-base/po/he/base.po b/luci-base/po/he/base.po index 6d98134a4..cb4c74a3f 100644 --- a/luci-base/po/he/base.po +++ b/luci-base/po/he/base.po @@ -726,6 +726,11 @@ msgstr "" msgid "Custom feeds" msgstr "" +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + msgid "" "Customizes the behaviour of the device LEDs if possible." @@ -988,6 +993,11 @@ msgstr "מצב חרום" msgid "Enable" msgstr "אפשר" +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + msgid "Enable STP" msgstr "אפשר STP" @@ -1045,6 +1055,9 @@ msgstr "" msgid "Enabled" msgstr "אפשר" +msgid "Enables IGMP snooping on this bridge" +msgstr "" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -2110,6 +2123,9 @@ msgstr "" msgid "Nslookup" msgstr "" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "" @@ -2862,6 +2878,9 @@ msgstr "" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "" @@ -3228,7 +3247,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" @@ -3437,7 +3456,7 @@ msgstr "השתמש בטבלת ניתוב" msgid "" "Use the Add Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." diff --git a/luci-base/po/hu/base.po b/luci-base/po/hu/base.po index e7b3a79bc..e49b5303f 100644 --- a/luci-base/po/hu/base.po +++ b/luci-base/po/hu/base.po @@ -744,6 +744,11 @@ msgstr "" msgid "Custom feeds" msgstr "" +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + msgid "" "Customizes the behaviour of the device LEDs if possible." @@ -1021,6 +1026,11 @@ msgstr "Vészhelyzet" msgid "Enable" msgstr "Engedélyezés" +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + msgid "Enable STP" msgstr "STP engedélyezése" @@ -1078,6 +1088,9 @@ msgstr "Engedélyezés/Letiltás" msgid "Enabled" msgstr "Engedélyezve" +msgid "Enables IGMP snooping on this bridge" +msgstr "" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -2179,6 +2192,9 @@ msgstr "Megjegyzés" msgid "Nslookup" msgstr "Nslookup" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -2957,6 +2973,9 @@ msgstr "Méret" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Ugrás" @@ -3375,10 +3394,10 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" "Ez az alagút közvetítő (tunnel broker) által megadott helyi végpont címe, " -"általában így végződik: :2" +"általában így végződik: ...:2/64" msgid "" "This is the only DHCPAdd Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." diff --git a/luci-base/po/it/base.po b/luci-base/po/it/base.po index 414fddf39..ce866d9e7 100644 --- a/luci-base/po/it/base.po +++ b/luci-base/po/it/base.po @@ -749,6 +749,11 @@ msgstr "" msgid "Custom feeds" msgstr "" +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + msgid "" "Customizes the behaviour of the device LEDs if possible." @@ -1024,6 +1029,11 @@ msgstr "Emergenza" msgid "Enable" msgstr "Abilita" +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + msgid "Enable STP" msgstr "Abilita STP" @@ -1081,6 +1091,9 @@ msgstr "Abilita/Disabilita" msgid "Enabled" msgstr "Abilitato" +msgid "Enables IGMP snooping on this bridge" +msgstr "" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -2179,6 +2192,9 @@ msgstr "Notifica" msgid "Nslookup" msgstr "" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -2941,6 +2957,9 @@ msgstr "Dimensione" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Salta" @@ -3335,7 +3354,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" @@ -3554,7 +3573,7 @@ msgstr "Utilizzare tabella di instradamento" msgid "" "Use the Add Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." diff --git a/luci-base/po/ja/base.po b/luci-base/po/ja/base.po index c06994002..07eeec5ee 100644 --- a/luci-base/po/ja/base.po +++ b/luci-base/po/ja/base.po @@ -3,18 +3,18 @@ msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2009-06-10 03:40+0200\n" -"PO-Revision-Date: 2017-10-20 13:54+0900\n" +"PO-Revision-Date: 2018-05-03 00:23+0900\n" "Last-Translator: INAGAKI Hiroshi \n" "Language: ja\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Poedit 2.0.4\n" +"X-Generator: Poedit 2.0.7\n" "Language-Team: \n" msgid "%.1f dB" -msgstr "" +msgstr "%.1f dB" msgid "%s is untagged in multiple VLANs!" msgstr "%s は複数のVLANにUntaggedしています!" @@ -137,7 +137,7 @@ msgid "MAC-Address" msgstr "MAC-アドレス" msgid "DUID" -msgstr "" +msgstr "DUID" msgid "" "Max. LEDs if possible." @@ -953,7 +962,7 @@ msgid "Domain whitelist" msgstr "ドメイン ホワイトリスト" msgid "Don't Fragment" -msgstr "" +msgstr "非フラグメント化" msgid "" "Don't forward DNS-Requests without " @@ -1024,6 +1033,13 @@ msgstr "緊急" msgid "Enable" msgstr "有効" +msgid "" +"Enable IGMP " +"snooping" +msgstr "" +"IGMP スヌーピングの" +"有効化" + msgid "Enable STP" msgstr "STPを有効にする" @@ -1067,7 +1083,7 @@ msgid "Enable mirroring of outgoing packets" msgstr "送信パケットのミラーリングを有効化" msgid "Enable the DF (Don't Fragment) flag of the encapsulating packets." -msgstr "" +msgstr "カプセル化されたパケットの DF (Don't Fragment) フラグを有効にします。" msgid "Enable this mount" msgstr "マウント設定を有効にする" @@ -1081,6 +1097,9 @@ msgstr "有効/無効" msgid "Enabled" msgstr "有効" +msgid "Enables IGMP snooping on this bridge" +msgstr "ブリッジの IGMP スヌーピングを有効にします" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -1254,7 +1273,7 @@ msgid "Force use of NAT-T" msgstr "NAT-Tの強制使用" msgid "Form token mismatch" -msgstr "" +msgstr "フォーム トークンの不一致" msgid "Forward DHCP traffic" msgstr "DHCPトラフィックを転送する" @@ -1598,6 +1617,8 @@ msgstr "インストール" msgid "Install iputils-traceroute6 for IPv6 traceroute" msgstr "" +"IPv6 の traceroute を使用するには、 iputils-traceroute6 をインストールしま" +"す。" msgid "Install package %q" msgstr "%q パッケージをインストールします" @@ -1661,7 +1682,7 @@ msgstr "" "ユーザー名かパスワード、もしくは両方が不正です!もう一度入力してください。" msgid "Isolate Clients" -msgstr "" +msgstr "クライアント間の分離" msgid "" "It appears that you are trying to flash an image that does not fit into the " @@ -1756,6 +1777,8 @@ msgstr "割り当て数" msgid "Limit DNS service to subnets interfaces on which we are serving DNS." msgstr "" +"DNS サービスを、現在 DNS を提供しているサブネットのインターフェースに限定しま" +"す。" msgid "Limit listening to these interfaces, and loopback." msgstr "待ち受けをこれらのインターフェースとループバックに制限します。" @@ -1840,7 +1863,7 @@ msgid "Local IPv6 address" msgstr "ローカル IPv6 アドレス" msgid "Local Service Only" -msgstr "" +msgstr "ローカルサービスのみ" msgid "Local Startup" msgstr "ローカル スタートアップ" @@ -1855,6 +1878,8 @@ msgid "" "Local domain specification. Names matching this domain are never forwarded " "and are resolved from DHCP or hosts files only" msgstr "" +"ローカル ドメインの定義です。このドメインに一致する名前は転送が行われず、 " +"DHCP または hosts ファイルのみにより解決されます。" msgid "Local domain suffix appended to DHCP names and hosts file entries" msgstr "" @@ -2178,6 +2203,11 @@ msgstr "注意" msgid "Nslookup" msgstr "Nslookup" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" +"キャッシュされる DNS エントリーの数です。(最大 10000 件。 0の場合はキャッ" +"シュしません)" + msgid "OK" msgstr "OK" @@ -2394,7 +2424,7 @@ msgid "Packets" msgstr "パケット" msgid "Part of zone %q" -msgstr "ゾーン %qの一部" +msgstr "ゾーン %q の一部" msgid "Password" msgstr "パスワード" @@ -2962,6 +2992,9 @@ msgstr "サイズ" msgid "Size (.ipk)" msgstr "サイズ (.ipk)" +msgid "Size of DNS query cache" +msgstr "DNS クエリ キャッシュのサイズ" + msgid "Skip" msgstr "スキップ" @@ -3085,10 +3118,10 @@ msgid "Submit" msgstr "送信" msgid "Suppress logging" -msgstr "" +msgstr "ログの抑制" msgid "Suppress logging of the routine operation of these protocols" -msgstr "" +msgstr "これらのプロトコルのルーチン的操作についてのログを抑制します。" msgid "Swap" msgstr "スワップ" @@ -3110,7 +3143,7 @@ msgid "" msgstr "" msgid "Switch Port Mask" -msgstr "" +msgstr "スイッチポート マスク" msgid "Switch VLAN" msgstr "" @@ -3338,13 +3371,16 @@ msgstr "" "サービスを有効にするために、管理者パスワードを設定してください。" msgid "This IPv4 address of the relay" -msgstr "" +msgstr "リレーの IPv4 アドレス" msgid "" "This file may contain lines like 'server=/domain/1.2.3.4' or " "'server=1.2.3.4' fordomain-specific or full upstream DNS servers." msgstr "" +"このファイルは、特定ドメイン用、または上位 DNS サーバーのための 'server=/domain/1.2.3.4' や 'server=1.2.3.4' " +"というような行を含めることができます。" msgid "" "This is a list of shell glob patterns for matching files and directories to " @@ -3369,17 +3405,17 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" "プロバイダからアサインされた、ローカルのエンドポイント アドレスです。通常、" -":2が終端に設定されます。" +"...:2/64が終端に設定されます。" msgid "" "This is the only DHCP in the local network" msgstr "" -"ローカル ネットワーク内のみの DHCPとして使用する" +"これはローカル ネットワーク内のみの DHCP です。" msgid "This is the plain username for logging into the account" msgstr "" @@ -3591,7 +3627,7 @@ msgstr "ルーティング テーブルの使用" msgid "" "Use the Add Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." @@ -3946,24 +3982,3 @@ msgstr "はい" msgid "« Back" msgstr "« 戻る" - -#~ msgid "Action" -#~ msgstr "動作" - -#~ msgid "Buttons" -#~ msgstr "ボタン" - -#~ msgid "Handler" -#~ msgstr "ハンドラ" - -#~ msgid "Maximum hold time" -#~ msgstr "最大保持時間" - -#~ msgid "Minimum hold time" -#~ msgstr "最短保持時間" - -#~ msgid "Path to executable which handles the button event" -#~ msgstr "ボタンイベントをハンドルする実行ファイルのパス" - -#~ msgid "This page allows the configuration of custom button actions" -#~ msgstr "このページでは、ボタンの動作を変更することができます。" diff --git a/luci-base/po/ko/base.po b/luci-base/po/ko/base.po index c56c05e2a..e4f77c78f 100644 --- a/luci-base/po/ko/base.po +++ b/luci-base/po/ko/base.po @@ -731,6 +731,11 @@ msgstr "" msgid "Custom feeds" msgstr "Custom feed 들" +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + msgid "" "Customizes the behaviour of the device LEDs if possible." @@ -1001,6 +1006,11 @@ msgstr "" msgid "Enable" msgstr "활성화" +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + msgid "Enable STP" msgstr "STP 활성화" @@ -1058,6 +1068,9 @@ msgstr "활성/비활성" msgid "Enabled" msgstr "활성화됨" +msgid "Enables IGMP snooping on this bridge" +msgstr "" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -2128,6 +2141,9 @@ msgstr "" msgid "Nslookup" msgstr "" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "" @@ -2890,6 +2906,9 @@ msgstr "Size" msgid "Size (.ipk)" msgstr "크기 (.ipk)" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "" @@ -3270,7 +3289,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" @@ -3484,7 +3503,7 @@ msgstr "Routing table 사용" msgid "" "Use the Add Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." diff --git a/luci-base/po/ms/base.po b/luci-base/po/ms/base.po index ff3324315..d5c889580 100644 --- a/luci-base/po/ms/base.po +++ b/luci-base/po/ms/base.po @@ -711,6 +711,11 @@ msgstr "" msgid "Custom feeds" msgstr "" +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + msgid "" "Customizes the behaviour of the device LEDs if possible." @@ -973,6 +978,11 @@ msgstr "" msgid "Enable" msgstr "" +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + msgid "Enable STP" msgstr "Mengaktifkan STP" @@ -1030,6 +1040,9 @@ msgstr "" msgid "Enabled" msgstr "" +msgid "Enables IGMP snooping on this bridge" +msgstr "" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -2108,6 +2121,9 @@ msgstr "" msgid "Nslookup" msgstr "" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "Baik" @@ -2864,6 +2880,9 @@ msgstr "Saiz" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Skip" @@ -3238,7 +3257,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" @@ -3452,7 +3471,7 @@ msgstr "" msgid "" "Use the Add Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." diff --git a/luci-base/po/no/base.po b/luci-base/po/no/base.po index f8b40c1e8..1805d8e99 100644 --- a/luci-base/po/no/base.po +++ b/luci-base/po/no/base.po @@ -733,6 +733,11 @@ msgstr "" msgid "Custom feeds" msgstr "" +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + msgid "" "Customizes the behaviour of the device LEDs if possible." @@ -1008,6 +1013,11 @@ msgstr "Krisesituasjon" msgid "Enable" msgstr "Aktiver" +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + msgid "Enable STP" msgstr "Aktiver STP" @@ -1065,6 +1075,9 @@ msgstr "Aktiver/Deaktiver" msgid "Enabled" msgstr "Aktivert" +msgid "Enables IGMP snooping on this bridge" +msgstr "" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -2153,6 +2166,9 @@ msgstr "Merk" msgid "Nslookup" msgstr "Nslookup" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -2930,6 +2946,9 @@ msgstr "Størrelse" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Gå videre" @@ -3343,10 +3362,10 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" "Dette er den lokale endepunkt adressen som ble tildelt av tunnel 'broker', " -"adressen ender vanligvis med :2" +"adressen ender vanligvis med ...:2/64" msgid "" "This is the only DHCPAdd Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." diff --git a/luci-base/po/pl/base.po b/luci-base/po/pl/base.po index 9bc33a46c..5e2fbaeee 100644 --- a/luci-base/po/pl/base.po +++ b/luci-base/po/pl/base.po @@ -752,6 +752,11 @@ msgstr "" msgid "Custom feeds" msgstr "" +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + # Spacji zabrało i napisy się skleiły msgid "" "Customizes the behaviour of the device IGMP " +"snooping" +msgstr "" + msgid "Enable STP" msgstr "Włącz STP" @@ -1091,6 +1101,9 @@ msgstr "Wlącz/Wyłącz" msgid "Enabled" msgstr "Włączony" +msgid "Enables IGMP snooping on this bridge" +msgstr "" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -2198,6 +2211,9 @@ msgstr "Spostrzeżenie" msgid "Nslookup" msgstr "Nslookup" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -2978,6 +2994,9 @@ msgstr "Rozmiar" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Pomiń" @@ -3400,10 +3419,10 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" "To jest lokalny adres końcowy przypisany przez tunnel broker'a, zwykle " -"kończący się z :2" +"kończący się z ...:2/64" # w tłumaczeniu pojawiła się spacja po DHCP co powoduje niepoprawne wyświetlanie się strony z lang PL msgid "" @@ -3622,7 +3641,7 @@ msgstr "Użyj tabeli routingu" msgid "" "Use the Add Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." diff --git a/luci-base/po/pt-br/base.po b/luci-base/po/pt-br/base.po index bf0de75dd..a51d11d2a 100644 --- a/luci-base/po/pt-br/base.po +++ b/luci-base/po/pt-br/base.po @@ -786,6 +786,11 @@ msgstr "" msgid "Custom feeds" msgstr "Fontes de pacotes customizadas" +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + msgid "" "Customizes the behaviour of the device LEDs if possible." @@ -1070,6 +1075,11 @@ msgstr "Emergência" msgid "Enable" msgstr "Ativar" +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + msgid "Enable STP" msgstr "Ativar STP" @@ -1127,6 +1137,9 @@ msgstr "Ativar/Desativar" msgid "Enabled" msgstr "Ativado" +msgid "Enables IGMP snooping on this bridge" +msgstr "" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -2279,6 +2292,9 @@ msgstr "Aviso" msgid "Nslookup" msgstr "Nslookup" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -3084,6 +3100,9 @@ msgstr "Tamanho" msgid "Size (.ipk)" msgstr "Tamanho (.ipk)" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Pular" @@ -3519,10 +3538,10 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" "Este é o endereço da ponta local designado pelo agente de túnel. normalmente " -"ele termina com :2" +"ele termina com ...:2/64" msgid "" "This is the only DHCPAdd Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." diff --git a/luci-base/po/pt/base.po b/luci-base/po/pt/base.po index 310990389..843a4cac8 100644 --- a/luci-base/po/pt/base.po +++ b/luci-base/po/pt/base.po @@ -746,6 +746,11 @@ msgstr "" msgid "Custom feeds" msgstr "" +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + msgid "" "Customizes the behaviour of the device LEDs if possible." @@ -1024,6 +1029,11 @@ msgstr "Emergência" msgid "Enable" msgstr "Ativar" +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + msgid "Enable STP" msgstr "Ativar STP" @@ -1081,6 +1091,9 @@ msgstr "Ativar/Desativar" msgid "Enabled" msgstr "Ativado" +msgid "Enables IGMP snooping on this bridge" +msgstr "" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -2177,6 +2190,9 @@ msgstr "Reparo" msgid "Nslookup" msgstr "Nslookup" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -2948,6 +2964,9 @@ msgstr "Tamanho" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Saltar" @@ -3347,7 +3366,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" @@ -3560,7 +3579,7 @@ msgstr "Usar tabela de roteamento" msgid "" "Use the Add Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." diff --git a/luci-base/po/ro/base.po b/luci-base/po/ro/base.po index 955cff650..748bfdbc5 100644 --- a/luci-base/po/ro/base.po +++ b/luci-base/po/ro/base.po @@ -721,6 +721,11 @@ msgstr "" msgid "Custom feeds" msgstr "" +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + msgid "" "Customizes the behaviour of the device LEDs if possible." @@ -979,6 +984,11 @@ msgstr "Urgenta" msgid "Enable" msgstr "Activeaza" +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + msgid "Enable STP" msgstr "Activeaza STP" @@ -1036,6 +1046,9 @@ msgstr "Activeaza/Dezactiveaza" msgid "Enabled" msgstr "Activat" +msgid "Enables IGMP snooping on this bridge" +msgstr "" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -2107,6 +2120,9 @@ msgstr "Notificare" msgid "Nslookup" msgstr "" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -2858,6 +2874,9 @@ msgstr "Marime" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "" @@ -3220,7 +3239,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" @@ -3428,7 +3447,7 @@ msgstr "" msgid "" "Use the Add Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." diff --git a/luci-base/po/ru/base.po b/luci-base/po/ru/base.po index c0b53eb9d..35a697620 100644 --- a/luci-base/po/ru/base.po +++ b/luci-base/po/ru/base.po @@ -777,6 +777,11 @@ msgstr "" msgid "Custom feeds" msgstr "Список custom-ных feed-ов" +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + msgid "" "Customizes the behaviour of the device LEDs if possible." @@ -1055,6 +1060,11 @@ msgstr "Чрезвычайная ситуация" msgid "Enable" msgstr "Включить" +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + msgid "Enable STP" msgstr "Включить STP" @@ -1112,6 +1122,9 @@ msgstr "Включить/выключить" msgid "Enabled" msgstr "Включено" +msgid "Enables IGMP snooping on this bridge" +msgstr "" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -2235,6 +2248,9 @@ msgstr "Заметка" msgid "Nslookup" msgstr "DNS-запрос" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -3043,6 +3059,9 @@ msgstr "Размер" msgid "Size (.ipk)" msgstr "Размер (.ipk)" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Пропустить" @@ -3471,10 +3490,10 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" "Это локальный адрес, назначенный туннельным брокером, обычно заканчивается " -"на :2." +"на ...:2/64." msgid "" "This is the only DHCPAdd Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." diff --git a/luci-base/po/sk/base.po b/luci-base/po/sk/base.po index ec72661dd..acc57792b 100644 --- a/luci-base/po/sk/base.po +++ b/luci-base/po/sk/base.po @@ -704,6 +704,11 @@ msgstr "" msgid "Custom feeds" msgstr "" +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + msgid "" "Customizes the behaviour of the device LEDs if possible." @@ -960,6 +965,11 @@ msgstr "" msgid "Enable" msgstr "" +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + msgid "Enable STP" msgstr "" @@ -1017,6 +1027,9 @@ msgstr "" msgid "Enabled" msgstr "" +msgid "Enables IGMP snooping on this bridge" +msgstr "" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -2082,6 +2095,9 @@ msgstr "" msgid "Nslookup" msgstr "" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "" @@ -2830,6 +2846,9 @@ msgstr "" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "" @@ -3190,7 +3209,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" @@ -3398,7 +3417,7 @@ msgstr "" msgid "" "Use the Add Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." diff --git a/luci-base/po/sv/base.po b/luci-base/po/sv/base.po index a7f906e81..632ea6f74 100644 --- a/luci-base/po/sv/base.po +++ b/luci-base/po/sv/base.po @@ -718,6 +718,11 @@ msgstr "" msgid "Custom feeds" msgstr "Anpassade flöden" +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + msgid "" "Customizes the behaviour of the device LEDs if possible." @@ -980,6 +985,11 @@ msgstr "Nödsituation" msgid "Enable" msgstr "Aktivera" +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + msgid "Enable STP" msgstr "Aktivera STP" @@ -1037,6 +1047,9 @@ msgstr "Aktivera/Inaktivera" msgid "Enabled" msgstr "Aktiverad" +msgid "Enables IGMP snooping on this bridge" +msgstr "" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -2103,6 +2116,9 @@ msgstr "Avisering" msgid "Nslookup" msgstr "Nslookup" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -2853,6 +2869,9 @@ msgstr "Storlek" msgid "Size (.ipk)" msgstr "Storlek (.ipk)" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Hoppa över" @@ -3215,7 +3234,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" @@ -3425,7 +3444,7 @@ msgstr "" msgid "" "Use the Add Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." diff --git a/luci-base/po/templates/base.pot b/luci-base/po/templates/base.pot index a8409213f..ddf2e56fa 100644 --- a/luci-base/po/templates/base.pot +++ b/luci-base/po/templates/base.pot @@ -697,6 +697,11 @@ msgstr "" msgid "Custom feeds" msgstr "" +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + msgid "" "Customizes the behaviour of the device LEDs if possible." @@ -953,6 +958,11 @@ msgstr "" msgid "Enable" msgstr "" +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + msgid "Enable STP" msgstr "" @@ -1010,6 +1020,9 @@ msgstr "" msgid "Enabled" msgstr "" +msgid "Enables IGMP snooping on this bridge" +msgstr "" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -2075,6 +2088,9 @@ msgstr "" msgid "Nslookup" msgstr "" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "" @@ -2823,6 +2839,9 @@ msgstr "" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "" @@ -3183,7 +3202,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" @@ -3391,7 +3410,7 @@ msgstr "" msgid "" "Use the Add Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." diff --git a/luci-base/po/tr/base.po b/luci-base/po/tr/base.po index 496d96f7c..953d1e966 100644 --- a/luci-base/po/tr/base.po +++ b/luci-base/po/tr/base.po @@ -717,6 +717,11 @@ msgstr "" msgid "Custom feeds" msgstr "" +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + msgid "" "Customizes the behaviour of the device LEDs if possible." @@ -973,6 +978,11 @@ msgstr "" msgid "Enable" msgstr "" +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + msgid "Enable STP" msgstr "" @@ -1030,6 +1040,9 @@ msgstr "" msgid "Enabled" msgstr "" +msgid "Enables IGMP snooping on this bridge" +msgstr "" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -2095,6 +2108,9 @@ msgstr "" msgid "Nslookup" msgstr "" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "" @@ -2843,6 +2859,9 @@ msgstr "" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "" @@ -3203,7 +3222,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" @@ -3411,7 +3430,7 @@ msgstr "" msgid "" "Use the Add Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." diff --git a/luci-base/po/uk/base.po b/luci-base/po/uk/base.po index 520bff481..8ead61607 100644 --- a/luci-base/po/uk/base.po +++ b/luci-base/po/uk/base.po @@ -755,6 +755,11 @@ msgstr "" msgid "Custom feeds" msgstr "" +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + msgid "" "Customizes the behaviour of the device LEDs if possible." @@ -1034,6 +1039,11 @@ msgstr "Аварійний" msgid "Enable" msgstr "Увімкнути" +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + msgid "Enable STP" msgstr "Увімкнути STP" @@ -1091,6 +1101,9 @@ msgstr "Увімкнено/Вимкнено" msgid "Enabled" msgstr "Увімкнено" +msgid "Enables IGMP snooping on this bridge" +msgstr "" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -2191,6 +2204,9 @@ msgstr "Попередження" msgid "Nslookup" msgstr "DNS-запит" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -2973,6 +2989,9 @@ msgstr "Розмір" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Пропустити" @@ -3391,10 +3410,10 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" "Це локальна адреса кінцевої точки, присвоєна тунельним брокером, зазвичай " -"закінчується на :2" +"закінчується на ...:2/64" msgid "" "This is the only DHCPAdd Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." diff --git a/luci-base/po/vi/base.po b/luci-base/po/vi/base.po index 2287dfba9..888fc92bf 100644 --- a/luci-base/po/vi/base.po +++ b/luci-base/po/vi/base.po @@ -711,6 +711,11 @@ msgstr "" msgid "Custom feeds" msgstr "" +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + msgid "" "Customizes the behaviour of the device LEDs if possible." @@ -978,6 +983,11 @@ msgstr "" msgid "Enable" msgstr "" +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + msgid "Enable STP" msgstr "Kích hoạt STP" @@ -1035,6 +1045,9 @@ msgstr "Cho kích hoạt/ Vô hiệu hóa" msgid "Enabled" msgstr "" +msgid "Enables IGMP snooping on this bridge" +msgstr "" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -2112,6 +2125,9 @@ msgstr "" msgid "Nslookup" msgstr "" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK " @@ -2870,6 +2886,9 @@ msgstr "Dung lượng " msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "" @@ -3240,7 +3259,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" @@ -3453,7 +3472,7 @@ msgstr "" msgid "" "Use the Add Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." diff --git a/luci-base/po/zh-cn/base.po b/luci-base/po/zh-cn/base.po index c0a535157..df6ce8b74 100644 --- a/luci-base/po/zh-cn/base.po +++ b/luci-base/po/zh-cn/base.po @@ -720,6 +720,12 @@ msgstr "自定义软件源地址,例如:私有的软件源。此文件在系 msgid "Custom feeds" msgstr "自定义软件源" +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" +"自定义文件(证书、脚本)会保留在系统上。若无需保留,请先执行恢复出厂设置。" + msgid "" "Customizes the behaviour of the device LEDs if possible." @@ -987,6 +993,11 @@ msgstr "紧急" msgid "Enable" msgstr "启用" +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + msgid "Enable STP" msgstr "开启 STP" @@ -1044,6 +1055,9 @@ msgstr "启用/禁用" msgid "Enabled" msgstr "启用" +msgid "Enables IGMP snooping on this bridge" +msgstr "" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -2127,6 +2141,9 @@ msgstr "注意" msgid "Nslookup" msgstr "Nslookup" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "缓存的 DNS 条目数量(最大 10000,0 表示不缓存)" + msgid "OK" msgstr "确认" @@ -2900,6 +2917,9 @@ msgstr "大小" msgid "Size (.ipk)" msgstr "大小(.ipk)" +msgid "Size of DNS query cache" +msgstr "DNS 查询缓存的大小" + msgid "Skip" msgstr "跳过" @@ -3283,8 +3303,8 @@ msgstr "启动脚本插入到 'exit 0' 之前即可随系统启动运行。" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" -msgstr "隧道代理分配的本地终端地址,通常以 :2 结尾" +"ends with ...:2/64" +msgstr "隧道代理分配的本地终端地址,通常以 ...:2/64 结尾" msgid "" "This is the only DHCPAdd Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." diff --git a/luci-base/po/zh-tw/base.po b/luci-base/po/zh-tw/base.po index d78223f2a..edc5207bd 100644 --- a/luci-base/po/zh-tw/base.po +++ b/luci-base/po/zh-tw/base.po @@ -722,6 +722,11 @@ msgstr "" msgid "Custom feeds" msgstr "" +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + msgid "" "Customizes the behaviour of the device LEDs if possible." @@ -990,6 +995,11 @@ msgstr "緊急" msgid "Enable" msgstr "啟用" +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + msgid "Enable STP" msgstr "啟用 STP" @@ -1047,6 +1057,9 @@ msgstr "啟用/關閉" msgid "Enabled" msgstr "啟用" +msgid "Enables IGMP snooping on this bridge" +msgstr "" + msgid "" "Enables fast roaming among access points that belong to the same Mobility " "Domain" @@ -2119,6 +2132,9 @@ msgstr "通知" msgid "Nslookup" msgstr "DNS偵錯Nslookup" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "行" @@ -2883,6 +2899,9 @@ msgstr "大小" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "跳過" @@ -3275,8 +3294,8 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" -msgstr "這是由通道代理人指定的本地終端位址, 通常用 :2結尾." +"ends with ...:2/64" +msgstr "這是由通道代理人指定的本地終端位址, 通常用 ...:2/64結尾." msgid "" "This is the only DHCPAdd Button to add a new lease entry. The MAC-Address indentifies the host, the IPv4-Address specifies the fixed " +"em> identifies the host, the IPv4-Address specifies the fixed " "address to use, and the Hostname is assigned as a symbolic name to " "the requesting host. The optional Lease time can be used to set non-" "standard host-specific lease time, e.g. 12h, 3d or infinite." diff --git a/luci-base/root/etc/config/ucitrack b/luci-base/root/etc/config/ucitrack index d08392295..1d4d110f2 100644 --- a/luci-base/root/etc/config/ucitrack +++ b/luci-base/root/etc/config/ucitrack @@ -36,6 +36,7 @@ config qos config system option init led + option exec '/etc/init.d/log reload' list affects luci_statistics list affects dhcp diff --git a/luci-base/root/usr/share/rpcd/acl.d/luci-base.json b/luci-base/root/usr/share/rpcd/acl.d/luci-base.json new file mode 100644 index 000000000..ed7ad8aa8 --- /dev/null +++ b/luci-base/root/usr/share/rpcd/acl.d/luci-base.json @@ -0,0 +1,11 @@ +{ + "uci-access": { + "description": "Grant uci write access to all configurations", + "read": { + "uci": [ "*" ] + }, + "write": { + "uci": [ "*" ] + } + } +} diff --git a/luci-base/src/po2lmo b/luci-base/src/po2lmo new file mode 100755 index 000000000..a9535aeab Binary files /dev/null and b/luci-base/src/po2lmo differ diff --git a/luci-base/src/po2lmo.o b/luci-base/src/po2lmo.o new file mode 100644 index 000000000..5fe6fe2fb Binary files /dev/null and b/luci-base/src/po2lmo.o differ diff --git a/luci-base/src/template_lmo.o b/luci-base/src/template_lmo.o new file mode 100644 index 000000000..45d49f11c Binary files /dev/null and b/luci-base/src/template_lmo.o differ