mirror of
https://git.openwrt.org/project/luci.git
synced 2025-10-14 01:32:18 +08:00
luci-base: convert JavaScript code to ES6 style
Convert existing JavaScript code in LuCI base to utilize ES6 standard features such as spread arguments, arrow functions, object method declarations etc. This makes the code somewhat easier to follow and slightly smaller. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -2,10 +2,10 @@
|
||||
'require baseclass';
|
||||
'require request';
|
||||
|
||||
var rpcRequestID = 1,
|
||||
rpcSessionID = L.env.sessionid || '00000000000000000000000000000000',
|
||||
rpcBaseURL = L.url('admin/ubus'),
|
||||
rpcInterceptorFns = [];
|
||||
let rpcRequestID = 1;
|
||||
let rpcSessionID = L.env.sessionid ?? '00000000000000000000000000000000';
|
||||
let rpcBaseURL = L.url('admin/ubus');
|
||||
const rpcInterceptorFns = [];
|
||||
|
||||
/**
|
||||
* @class rpc
|
||||
@@ -18,14 +18,14 @@ var rpcRequestID = 1,
|
||||
*/
|
||||
return baseclass.extend(/** @lends LuCI.rpc.prototype */ {
|
||||
/* privates */
|
||||
call: function(req, cb, nobatch) {
|
||||
var q = '';
|
||||
call(req, cb, nobatch) {
|
||||
let q = '';
|
||||
|
||||
if (Array.isArray(req)) {
|
||||
if (req.length == 0)
|
||||
return Promise.resolve([]);
|
||||
|
||||
for (var i = 0; i < req.length; i++)
|
||||
for (let i = 0; i < req.length; i++)
|
||||
if (req[i].params)
|
||||
q += '%s%s.%s'.format(
|
||||
q ? ';' : '/',
|
||||
@@ -35,14 +35,14 @@ return baseclass.extend(/** @lends LuCI.rpc.prototype */ {
|
||||
}
|
||||
|
||||
return request.post(rpcBaseURL + q, req, {
|
||||
timeout: (L.env.rpctimeout || 20) * 1000,
|
||||
nobatch: nobatch,
|
||||
timeout: (L.env.rpctimeout ?? 20) * 1000,
|
||||
nobatch,
|
||||
credentials: true
|
||||
}).then(cb, cb);
|
||||
},
|
||||
|
||||
parseCallReply: function(req, res) {
|
||||
var msg = null;
|
||||
parseCallReply(req, res) {
|
||||
let msg = null;
|
||||
|
||||
if (res instanceof Error)
|
||||
return req.reject(res);
|
||||
@@ -62,14 +62,14 @@ return baseclass.extend(/** @lends LuCI.rpc.prototype */ {
|
||||
* The interceptor args are intentionally swapped.
|
||||
* Response is passed as first arg to align with Request class interceptors
|
||||
*/
|
||||
Promise.all(rpcInterceptorFns.map(function(fn) { return fn(msg, req) }))
|
||||
Promise.all(rpcInterceptorFns.map(fn => fn(msg, req)))
|
||||
.then(this.handleCallReply.bind(this, req, msg))
|
||||
.catch(req.reject);
|
||||
},
|
||||
|
||||
handleCallReply: function(req, msg) {
|
||||
var type = Object.prototype.toString,
|
||||
ret = null;
|
||||
handleCallReply(req, msg) {
|
||||
const type = Object.prototype.toString;
|
||||
let ret = null;
|
||||
|
||||
try {
|
||||
/* verify message frame */
|
||||
@@ -98,7 +98,7 @@ return baseclass.extend(/** @lends LuCI.rpc.prototype */ {
|
||||
}
|
||||
|
||||
if (req.expect) {
|
||||
for (var key in req.expect) {
|
||||
for (const key in req.expect) {
|
||||
if (ret != null && key != '')
|
||||
ret = ret[key];
|
||||
|
||||
@@ -140,20 +140,17 @@ return baseclass.extend(/** @lends LuCI.rpc.prototype */ {
|
||||
* more arguments, a promise resolving to an object describing the method
|
||||
* signatures of each requested `ubus` object name will be returned.
|
||||
*/
|
||||
list: function() {
|
||||
var msg = {
|
||||
list(...args) {
|
||||
const msg = {
|
||||
jsonrpc: '2.0',
|
||||
id: rpcRequestID++,
|
||||
method: 'list',
|
||||
params: arguments.length ? this.varargs(arguments) : undefined
|
||||
params: args.length ? args : undefined
|
||||
};
|
||||
|
||||
return new Promise(L.bind(function(resolveFn, rejectFn) {
|
||||
return new Promise(L.bind(function(resolve, reject) {
|
||||
/* store request info */
|
||||
var req = {
|
||||
resolve: resolveFn,
|
||||
reject: rejectFn
|
||||
};
|
||||
const req = { resolve, reject };
|
||||
|
||||
/* call rpc */
|
||||
this.call(msg, this.parseCallReply.bind(this, req));
|
||||
@@ -296,37 +293,36 @@ return baseclass.extend(/** @lends LuCI.rpc.prototype */ {
|
||||
* Returns a new function implementing the method call described in
|
||||
* `options`.
|
||||
*/
|
||||
declare: function(options) {
|
||||
return Function.prototype.bind.call(function(rpc, options) {
|
||||
var args = this.varargs(arguments, 2);
|
||||
return new Promise(function(resolveFn, rejectFn) {
|
||||
declare(options) {
|
||||
return Function.prototype.bind.call(function(rpc, options, ...args) {
|
||||
return new Promise((resolve, reject) => {
|
||||
/* build parameter object */
|
||||
var p_off = 0;
|
||||
var params = { };
|
||||
let p_off = 0;
|
||||
const params = { };
|
||||
if (Array.isArray(options.params))
|
||||
for (p_off = 0; p_off < options.params.length; p_off++)
|
||||
params[options.params[p_off]] = args[p_off];
|
||||
|
||||
/* all remaining arguments are private args */
|
||||
var priv = [ undefined, undefined ];
|
||||
const priv = [ undefined, undefined ];
|
||||
for (; p_off < args.length; p_off++)
|
||||
priv.push(args[p_off]);
|
||||
|
||||
/* store request info */
|
||||
var req = {
|
||||
const req = {
|
||||
expect: options.expect,
|
||||
filter: options.filter,
|
||||
resolve: resolveFn,
|
||||
reject: rejectFn,
|
||||
params: params,
|
||||
priv: priv,
|
||||
resolve,
|
||||
reject,
|
||||
params,
|
||||
priv,
|
||||
object: options.object,
|
||||
method: options.method,
|
||||
raise: options.reject
|
||||
};
|
||||
|
||||
/* build message object */
|
||||
var msg = {
|
||||
const msg = {
|
||||
jsonrpc: '2.0',
|
||||
id: rpcRequestID++,
|
||||
method: 'call',
|
||||
@@ -351,7 +347,7 @@ return baseclass.extend(/** @lends LuCI.rpc.prototype */ {
|
||||
* Returns the 32 byte session ID string used for authenticating remote
|
||||
* requests.
|
||||
*/
|
||||
getSessionID: function() {
|
||||
getSessionID() {
|
||||
return rpcSessionID;
|
||||
},
|
||||
|
||||
@@ -362,7 +358,7 @@ return baseclass.extend(/** @lends LuCI.rpc.prototype */ {
|
||||
* Sets the 32 byte session ID string used for authenticating remote
|
||||
* requests.
|
||||
*/
|
||||
setSessionID: function(sid) {
|
||||
setSessionID(sid) {
|
||||
rpcSessionID = sid;
|
||||
},
|
||||
|
||||
@@ -372,7 +368,7 @@ return baseclass.extend(/** @lends LuCI.rpc.prototype */ {
|
||||
* @returns {string}
|
||||
* Returns the RPC URL endpoint to issue requests against.
|
||||
*/
|
||||
getBaseURL: function() {
|
||||
getBaseURL() {
|
||||
return rpcBaseURL;
|
||||
},
|
||||
|
||||
@@ -382,7 +378,7 @@ return baseclass.extend(/** @lends LuCI.rpc.prototype */ {
|
||||
* @param {string} url
|
||||
* Sets the RPC URL endpoint to issue requests against.
|
||||
*/
|
||||
setBaseURL: function(url) {
|
||||
setBaseURL(url) {
|
||||
rpcBaseURL = url;
|
||||
},
|
||||
|
||||
@@ -396,7 +392,7 @@ return baseclass.extend(/** @lends LuCI.rpc.prototype */ {
|
||||
* @returns {string}
|
||||
* Returns the textual description of the code.
|
||||
*/
|
||||
getStatusText: function(statusCode) {
|
||||
getStatusText(statusCode) {
|
||||
switch (statusCode) {
|
||||
case 0: return _('Command OK');
|
||||
case 1: return _('Invalid command');
|
||||
@@ -459,9 +455,10 @@ return baseclass.extend(/** @lends LuCI.rpc.prototype */ {
|
||||
* @returns {LuCI.rpc~interceptorFn}
|
||||
* Returns the given function value.
|
||||
*/
|
||||
addInterceptor: function(interceptorFn) {
|
||||
addInterceptor(interceptorFn) {
|
||||
if (typeof(interceptorFn) == 'function')
|
||||
rpcInterceptorFns.push(interceptorFn);
|
||||
|
||||
return interceptorFn;
|
||||
},
|
||||
|
||||
@@ -475,11 +472,14 @@ return baseclass.extend(/** @lends LuCI.rpc.prototype */ {
|
||||
* Returns `true` if the given function has been removed or `false`
|
||||
* if it has not been found.
|
||||
*/
|
||||
removeInterceptor: function(interceptorFn) {
|
||||
var oldlen = rpcInterceptorFns.length, i = oldlen;
|
||||
removeInterceptor(interceptorFn) {
|
||||
const oldlen = rpcInterceptorFns.length;
|
||||
let i = oldlen;
|
||||
|
||||
while (i--)
|
||||
if (rpcInterceptorFns[i] === interceptorFn)
|
||||
rpcInterceptorFns.splice(i, 1);
|
||||
|
||||
return (rpcInterceptorFns.length < oldlen);
|
||||
}
|
||||
});
|
||||
|
@@ -3,7 +3,7 @@
|
||||
'require baseclass';
|
||||
|
||||
function isEmpty(object, ignore) {
|
||||
for (var property in object)
|
||||
for (const property in object)
|
||||
if (object.hasOwnProperty(property) && property != ignore)
|
||||
return false;
|
||||
|
||||
@@ -22,7 +22,7 @@ function isEmpty(object, ignore) {
|
||||
* UCI configuration data.
|
||||
*/
|
||||
return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
__init__: function() {
|
||||
__init__() {
|
||||
this.state = {
|
||||
newidx: 0,
|
||||
values: { },
|
||||
@@ -100,14 +100,14 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
* A newly generated, unique section ID in the form `newXXXXXX`
|
||||
* where `X` denotes a hexadecimal digit.
|
||||
*/
|
||||
createSID: function(conf) {
|
||||
var v = this.state.values,
|
||||
n = this.state.creates,
|
||||
sid;
|
||||
createSID(conf) {
|
||||
const v = this.state.values;
|
||||
const n = this.state.creates;
|
||||
let sid;
|
||||
|
||||
do {
|
||||
sid = "new%06x".format(Math.random() * 0xFFFFFF);
|
||||
} while ((n[conf] && n[conf][sid]) || (v[conf] && v[conf][sid]));
|
||||
} while ((n[conf]?.[sid]) || (v[conf]?.[sid]));
|
||||
|
||||
return sid;
|
||||
},
|
||||
@@ -131,30 +131,30 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
* not in extended notation. Returns `null` when an extended ID could
|
||||
* not be resolved to existing section ID.
|
||||
*/
|
||||
resolveSID: function(conf, sid) {
|
||||
resolveSID(conf, sid) {
|
||||
if (typeof(sid) != 'string')
|
||||
return sid;
|
||||
|
||||
var m = /^@([a-zA-Z0-9_-]+)\[(-?[0-9]+)\]$/.exec(sid);
|
||||
const m = /^@([a-zA-Z0-9_-]+)\[(-?[0-9]+)\]$/.exec(sid);
|
||||
|
||||
if (m) {
|
||||
var type = m[1],
|
||||
pos = +m[2],
|
||||
sections = this.sections(conf, type),
|
||||
section = sections[pos >= 0 ? pos : sections.length + pos];
|
||||
const type = m[1];
|
||||
const pos = +m[2];
|
||||
const sections = this.sections(conf, type);
|
||||
const section = sections[pos >= 0 ? pos : sections.length + pos];
|
||||
|
||||
return section ? section['.name'] : null;
|
||||
return section?.['.name'] ?? null;
|
||||
}
|
||||
|
||||
return sid;
|
||||
},
|
||||
|
||||
/* private */
|
||||
reorderSections: function() {
|
||||
var v = this.state.values,
|
||||
n = this.state.creates,
|
||||
r = this.state.reorder,
|
||||
tasks = [];
|
||||
reorderSections() {
|
||||
const v = this.state.values;
|
||||
const n = this.state.creates;
|
||||
const r = this.state.reorder;
|
||||
const tasks = [];
|
||||
|
||||
if (Object.keys(r).length === 0)
|
||||
return Promise.resolve();
|
||||
@@ -163,24 +163,22 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
gather all created and existing sections, sort them according
|
||||
to their index value and issue an uci order call
|
||||
*/
|
||||
for (var c in r) {
|
||||
var o = [ ];
|
||||
for (const c in r) {
|
||||
const o = [ ];
|
||||
|
||||
if (n[c])
|
||||
for (var s in n[c])
|
||||
for (const s in n[c])
|
||||
o.push(n[c][s]);
|
||||
|
||||
for (var s in v[c])
|
||||
for (const s in v[c])
|
||||
o.push(v[c][s]);
|
||||
|
||||
if (o.length > 0) {
|
||||
o.sort(function(a, b) {
|
||||
return (a['.index'] - b['.index']);
|
||||
});
|
||||
o.sort((a, b) => a['.index'] - b['.index']);
|
||||
|
||||
var sids = [ ];
|
||||
const sids = [ ];
|
||||
|
||||
for (var i = 0; i < o.length; i++)
|
||||
for (let i = 0; i < o.length; i++)
|
||||
sids.push(o[i]['.name']);
|
||||
|
||||
tasks.push(this.callOrder(c, sids));
|
||||
@@ -192,7 +190,7 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
},
|
||||
|
||||
/* private */
|
||||
loadPackage: function(packageName) {
|
||||
loadPackage(packageName) {
|
||||
if (this.loaded[packageName] == null)
|
||||
return (this.loaded[packageName] = this.callLoad(packageName));
|
||||
|
||||
@@ -217,22 +215,22 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
* Returns a promise resolving to the names of the configurations
|
||||
* that have been successfully loaded.
|
||||
*/
|
||||
load: function(packages) {
|
||||
var self = this,
|
||||
pkgs = [ ],
|
||||
tasks = [];
|
||||
load(packages) {
|
||||
const self = this;
|
||||
const pkgs = [ ];
|
||||
const tasks = [];
|
||||
|
||||
if (!Array.isArray(packages))
|
||||
packages = [ packages ];
|
||||
|
||||
for (var i = 0; i < packages.length; i++)
|
||||
for (let i = 0; i < packages.length; i++)
|
||||
if (!self.state.values[packages[i]]) {
|
||||
pkgs.push(packages[i]);
|
||||
tasks.push(self.loadPackage(packages[i]));
|
||||
}
|
||||
|
||||
return Promise.all(tasks).then(function(responses) {
|
||||
for (var i = 0; i < responses.length; i++)
|
||||
return Promise.all(tasks).then(responses => {
|
||||
for (let i = 0; i < responses.length; i++)
|
||||
self.state.values[pkgs[i]] = responses[i];
|
||||
|
||||
if (responses.length)
|
||||
@@ -249,11 +247,11 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
* The name of the configuration or an array of configuration
|
||||
* names to unload.
|
||||
*/
|
||||
unload: function(packages) {
|
||||
unload(packages) {
|
||||
if (!Array.isArray(packages))
|
||||
packages = [ packages ];
|
||||
|
||||
for (var i = 0; i < packages.length; i++) {
|
||||
for (let i = 0; i < packages.length; i++) {
|
||||
delete this.state.values[packages[i]];
|
||||
delete this.state.creates[packages[i]];
|
||||
delete this.state.changes[packages[i]];
|
||||
@@ -281,13 +279,11 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
* Returns the section ID of the newly added section which is equivalent
|
||||
* to the given name for non-anonymous sections.
|
||||
*/
|
||||
add: function(conf, type, name) {
|
||||
var n = this.state.creates,
|
||||
sid = name || this.createSID(conf);
|
||||
|
||||
if (!n[conf])
|
||||
n[conf] = { };
|
||||
add(conf, type, name) {
|
||||
const n = this.state.creates;
|
||||
const sid = name || this.createSID(conf);
|
||||
|
||||
n[conf] ??= { };
|
||||
n[conf][sid] = {
|
||||
'.type': type,
|
||||
'.name': sid,
|
||||
@@ -308,23 +304,20 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
* @param {string} sid
|
||||
* The ID of the section to remove.
|
||||
*/
|
||||
remove: function(conf, sid) {
|
||||
var v = this.state.values,
|
||||
n = this.state.creates,
|
||||
c = this.state.changes,
|
||||
d = this.state.deletes;
|
||||
remove(conf, sid) {
|
||||
const v = this.state.values;
|
||||
const n = this.state.creates;
|
||||
const c = this.state.changes;
|
||||
const d = this.state.deletes;
|
||||
|
||||
/* requested deletion of a just created section */
|
||||
if (n[conf] && n[conf][sid]) {
|
||||
if (n[conf]?.[sid]) {
|
||||
delete n[conf][sid];
|
||||
}
|
||||
else if (v[conf] && v[conf][sid]) {
|
||||
if (c[conf])
|
||||
delete c[conf][sid];
|
||||
|
||||
if (!d[conf])
|
||||
d[conf] = { };
|
||||
else if (v[conf]?.[sid]) {
|
||||
delete c[conf]?.[sid];
|
||||
|
||||
d[conf] ??= { };
|
||||
d[conf][sid] = true;
|
||||
}
|
||||
},
|
||||
@@ -397,35 +390,35 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
* Returns a sorted array of the section objects within the given
|
||||
* configuration, filtered by type of a type has been specified.
|
||||
*/
|
||||
sections: function(conf, type, cb) {
|
||||
var sa = [ ],
|
||||
v = this.state.values[conf],
|
||||
n = this.state.creates[conf],
|
||||
c = this.state.changes[conf],
|
||||
d = this.state.deletes[conf];
|
||||
sections(conf, type, cb) {
|
||||
const sa = [ ];
|
||||
const v = this.state.values[conf];
|
||||
const n = this.state.creates[conf];
|
||||
const c = this.state.changes[conf];
|
||||
const d = this.state.deletes[conf];
|
||||
|
||||
if (!v)
|
||||
return sa;
|
||||
|
||||
for (var s in v)
|
||||
for (const s in v)
|
||||
if (!d || d[s] !== true)
|
||||
if (!type || v[s]['.type'] == type)
|
||||
sa.push(Object.assign({ }, v[s], c ? c[s] : null));
|
||||
|
||||
if (n)
|
||||
for (var s in n)
|
||||
for (const s in n)
|
||||
if (!type || n[s]['.type'] == type)
|
||||
sa.push(Object.assign({ }, n[s]));
|
||||
|
||||
sa.sort(function(a, b) {
|
||||
sa.sort((a, b) => {
|
||||
return a['.index'] - b['.index'];
|
||||
});
|
||||
|
||||
for (var i = 0; i < sa.length; i++)
|
||||
for (let i = 0; i < sa.length; i++)
|
||||
sa[i]['.index'] = i;
|
||||
|
||||
if (typeof(cb) == 'function')
|
||||
for (var i = 0; i < sa.length; i++)
|
||||
for (let i = 0; i < sa.length; i++)
|
||||
cb.call(this, sa[i], sa[i]['.name']);
|
||||
|
||||
return sa;
|
||||
@@ -456,11 +449,11 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
* - Returns `null` if the config, section or option has not been
|
||||
* found or if the corresponding configuration is not loaded.
|
||||
*/
|
||||
get: function(conf, sid, opt) {
|
||||
var v = this.state.values,
|
||||
n = this.state.creates,
|
||||
c = this.state.changes,
|
||||
d = this.state.deletes;
|
||||
get(conf, sid, opt) {
|
||||
const v = this.state.values;
|
||||
const n = this.state.creates;
|
||||
const c = this.state.changes;
|
||||
const d = this.state.deletes;
|
||||
|
||||
sid = this.resolveSID(conf, sid);
|
||||
|
||||
@@ -468,10 +461,7 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
return null;
|
||||
|
||||
/* requested option in a just created section */
|
||||
if (n[conf] && n[conf][sid]) {
|
||||
if (!n[conf])
|
||||
return null;
|
||||
|
||||
if (n[conf]?.[sid]) {
|
||||
if (opt == null)
|
||||
return n[conf][sid];
|
||||
|
||||
@@ -481,16 +471,16 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
/* requested an option value */
|
||||
if (opt != null) {
|
||||
/* check whether option was deleted */
|
||||
if (d[conf] && d[conf][sid])
|
||||
if (d[conf]?.[sid])
|
||||
if (d[conf][sid] === true || d[conf][sid][opt])
|
||||
return null;
|
||||
|
||||
/* check whether option was changed */
|
||||
if (c[conf] && c[conf][sid] && c[conf][sid][opt] != null)
|
||||
if (c[conf]?.[sid][opt] != null)
|
||||
return c[conf][sid][opt];
|
||||
|
||||
/* return base value */
|
||||
if (v[conf] && v[conf][sid])
|
||||
if (v[conf]?.[sid])
|
||||
return v[conf][sid][opt];
|
||||
|
||||
return null;
|
||||
@@ -499,21 +489,21 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
/* requested an entire section */
|
||||
if (v[conf]) {
|
||||
/* check whether entire section was deleted */
|
||||
if (d[conf] && d[conf][sid] === true)
|
||||
if (d[conf]?.[sid] === true)
|
||||
return null;
|
||||
|
||||
var s = v[conf][sid] || null;
|
||||
const s = v[conf][sid] || null;
|
||||
|
||||
if (s) {
|
||||
/* merge changes */
|
||||
if (c[conf] && c[conf][sid])
|
||||
for (var opt in c[conf][sid])
|
||||
if (c[conf]?.[sid])
|
||||
for (const opt in c[conf][sid])
|
||||
if (c[conf][sid][opt] != null)
|
||||
s[opt] = c[conf][sid][opt];
|
||||
|
||||
/* merge deletions */
|
||||
if (d[conf] && d[conf][sid])
|
||||
for (var opt in d[conf][sid])
|
||||
if (d[conf]?.[sid])
|
||||
for (const opt in d[conf][sid])
|
||||
delete s[opt];
|
||||
}
|
||||
|
||||
@@ -544,18 +534,18 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
* the option will be removed, otherwise it will be set or overwritten
|
||||
* with the given value.
|
||||
*/
|
||||
set: function(conf, sid, opt, val) {
|
||||
var v = this.state.values,
|
||||
n = this.state.creates,
|
||||
c = this.state.changes,
|
||||
d = this.state.deletes;
|
||||
set(conf, sid, opt, val) {
|
||||
const v = this.state.values;
|
||||
const n = this.state.creates;
|
||||
const c = this.state.changes;
|
||||
const d = this.state.deletes;
|
||||
|
||||
sid = this.resolveSID(conf, sid);
|
||||
|
||||
if (sid == null || opt == null || opt.charAt(0) == '.')
|
||||
return;
|
||||
|
||||
if (n[conf] && n[conf][sid]) {
|
||||
if (n[conf]?.[sid]) {
|
||||
if (val != null)
|
||||
n[conf][sid][opt] = val;
|
||||
else
|
||||
@@ -567,17 +557,14 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
return;
|
||||
|
||||
/* only set in existing sections */
|
||||
if (!v[conf] || !v[conf][sid])
|
||||
if (!v[conf]?.[sid])
|
||||
return;
|
||||
|
||||
if (!c[conf])
|
||||
c[conf] = {};
|
||||
|
||||
if (!c[conf][sid])
|
||||
c[conf][sid] = {};
|
||||
c[conf] ??= {};
|
||||
c[conf][sid] ??= {};
|
||||
|
||||
/* undelete option */
|
||||
if (d[conf] && d[conf][sid]) {
|
||||
if (d[conf]?.[sid]) {
|
||||
if (isEmpty(d[conf][sid], opt))
|
||||
delete d[conf][sid];
|
||||
else
|
||||
@@ -588,7 +575,7 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
}
|
||||
else {
|
||||
/* revert any change for to-be-deleted option */
|
||||
if (c[conf] && c[conf][sid]) {
|
||||
if (c[conf]?.[sid]) {
|
||||
if (isEmpty(c[conf][sid], opt))
|
||||
delete c[conf][sid];
|
||||
else
|
||||
@@ -596,12 +583,9 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
}
|
||||
|
||||
/* only delete existing options */
|
||||
if (v[conf] && v[conf][sid] && v[conf][sid].hasOwnProperty(opt)) {
|
||||
if (!d[conf])
|
||||
d[conf] = { };
|
||||
|
||||
if (!d[conf][sid])
|
||||
d[conf][sid] = { };
|
||||
if (v[conf]?.[sid].hasOwnProperty(opt)) {
|
||||
d[conf] ??= { };
|
||||
d[conf][sid] ??= { };
|
||||
|
||||
if (d[conf][sid] !== true)
|
||||
d[conf][sid][opt] = true;
|
||||
@@ -625,7 +609,7 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
* @param {string} opt
|
||||
* The name of the option to remove.
|
||||
*/
|
||||
unset: function(conf, sid, opt) {
|
||||
unset(conf, sid, opt) {
|
||||
return this.set(conf, sid, opt, null);
|
||||
},
|
||||
|
||||
@@ -656,12 +640,11 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
* - Returns `null` if the config, section or option has not been
|
||||
* found or if the corresponding configuration is not loaded.
|
||||
*/
|
||||
get_first: function(conf, type, opt) {
|
||||
var sid = null;
|
||||
get_first(conf, type, opt) {
|
||||
let sid = null;
|
||||
|
||||
this.sections(conf, type, function(s) {
|
||||
if (sid == null)
|
||||
sid = s['.name'];
|
||||
this.sections(conf, type, s => {
|
||||
sid ??= s['.name'];
|
||||
});
|
||||
|
||||
return this.get(conf, sid, opt);
|
||||
@@ -691,12 +674,11 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
* the option will be removed, otherwise it will be set or overwritten
|
||||
* with the given value.
|
||||
*/
|
||||
set_first: function(conf, type, opt, val) {
|
||||
var sid = null;
|
||||
set_first(conf, type, opt, val) {
|
||||
let sid = null;
|
||||
|
||||
this.sections(conf, type, function(s) {
|
||||
if (sid == null)
|
||||
sid = s['.name'];
|
||||
this.sections(conf, type, s => {
|
||||
sid ??= s['.name'];
|
||||
});
|
||||
|
||||
return this.set(conf, sid, opt, val);
|
||||
@@ -721,7 +703,7 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
* @param {string} opt
|
||||
* The option name to set the value for.
|
||||
*/
|
||||
unset_first: function(conf, type, opt) {
|
||||
unset_first(conf, type, opt) {
|
||||
return this.set_first(conf, type, opt, null);
|
||||
},
|
||||
|
||||
@@ -756,14 +738,15 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
* Returns `true` when the section was successfully moved, or `false`
|
||||
* when either the section specified by `sid1` or by `sid2` is not found.
|
||||
*/
|
||||
move: function(conf, sid1, sid2, after) {
|
||||
var sa = this.sections(conf),
|
||||
s1 = null, s2 = null;
|
||||
move(conf, sid1, sid2, after) {
|
||||
const sa = this.sections(conf);
|
||||
let s1 = null;
|
||||
let s2 = null;
|
||||
|
||||
sid1 = this.resolveSID(conf, sid1);
|
||||
sid2 = this.resolveSID(conf, sid2);
|
||||
|
||||
for (var i = 0; i < sa.length; i++) {
|
||||
for (let i = 0; i < sa.length; i++) {
|
||||
if (sa[i]['.name'] != sid1)
|
||||
continue;
|
||||
|
||||
@@ -779,7 +762,7 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
sa.push(s1);
|
||||
}
|
||||
else {
|
||||
for (var i = 0; i < sa.length; i++) {
|
||||
for (let i = 0; i < sa.length; i++) {
|
||||
if (sa[i]['.name'] != sid2)
|
||||
continue;
|
||||
|
||||
@@ -792,7 +775,7 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = 0; i < sa.length; i++)
|
||||
for (let i = 0; i < sa.length; i++)
|
||||
this.get(conf, sa[i]['.name'])['.index'] = i;
|
||||
|
||||
this.state.reorder[conf] = true;
|
||||
@@ -810,21 +793,21 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
* Returns a promise resolving to an array of configuration names which
|
||||
* have been reloaded by the save operation.
|
||||
*/
|
||||
save: function() {
|
||||
var v = this.state.values,
|
||||
n = this.state.creates,
|
||||
c = this.state.changes,
|
||||
d = this.state.deletes,
|
||||
r = this.state.reorder,
|
||||
self = this,
|
||||
snew = [ ],
|
||||
pkgs = { },
|
||||
tasks = [];
|
||||
save() {
|
||||
const v = this.state.values;
|
||||
const n = this.state.creates;
|
||||
const c = this.state.changes;
|
||||
const d = this.state.deletes;
|
||||
const r = this.state.reorder;
|
||||
const self = this;
|
||||
const snew = [ ];
|
||||
let pkgs = { };
|
||||
const tasks = [];
|
||||
|
||||
if (d)
|
||||
for (var conf in d) {
|
||||
for (var sid in d[conf]) {
|
||||
var o = d[conf][sid];
|
||||
for (const conf in d) {
|
||||
for (const sid in d[conf]) {
|
||||
const o = d[conf][sid];
|
||||
|
||||
if (o === true)
|
||||
tasks.push(self.callDelete(conf, sid, null));
|
||||
@@ -836,14 +819,14 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
}
|
||||
|
||||
if (n)
|
||||
for (var conf in n) {
|
||||
for (var sid in n[conf]) {
|
||||
var p = {
|
||||
for (const conf in n) {
|
||||
for (const sid in n[conf]) {
|
||||
const p = {
|
||||
config: conf,
|
||||
values: { }
|
||||
};
|
||||
|
||||
for (var k in n[conf][sid]) {
|
||||
for (const k in n[conf][sid]) {
|
||||
if (k == '.type')
|
||||
p.type = n[conf][sid][k];
|
||||
else if (k == '.create')
|
||||
@@ -860,27 +843,27 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
}
|
||||
|
||||
if (c)
|
||||
for (var conf in c) {
|
||||
for (var sid in c[conf])
|
||||
for (const conf in c) {
|
||||
for (const sid in c[conf])
|
||||
tasks.push(self.callSet(conf, sid, c[conf][sid]));
|
||||
|
||||
pkgs[conf] = true;
|
||||
}
|
||||
|
||||
if (r)
|
||||
for (var conf in r)
|
||||
for (const conf in r)
|
||||
pkgs[conf] = true;
|
||||
|
||||
return Promise.all(tasks).then(function(responses) {
|
||||
return Promise.all(tasks).then(responses => {
|
||||
/*
|
||||
array "snew" holds references to the created uci sections,
|
||||
use it to assign the returned names of the new sections
|
||||
*/
|
||||
for (var i = 0; i < snew.length; i++)
|
||||
for (let i = 0; i < snew.length; i++)
|
||||
snew[i]['.name'] = responses[i];
|
||||
|
||||
return self.reorderSections();
|
||||
}).then(function() {
|
||||
}).then(() => {
|
||||
pkgs = Object.keys(pkgs);
|
||||
|
||||
self.unload(pkgs);
|
||||
@@ -900,20 +883,20 @@ return baseclass.extend(/** @lends LuCI.uci.prototype */ {
|
||||
* @returns {Promise<number>}
|
||||
* Returns a promise resolving/rejecting with the `ubus` RPC status code.
|
||||
*/
|
||||
apply: function(timeout) {
|
||||
var self = this,
|
||||
date = new Date();
|
||||
apply(timeout) {
|
||||
const self = this;
|
||||
const date = new Date();
|
||||
|
||||
if (typeof(timeout) != 'number' || timeout < 1)
|
||||
timeout = 10;
|
||||
|
||||
return self.callApply(timeout, true).then(function(rv) {
|
||||
return self.callApply(timeout, true).then(rv => {
|
||||
if (rv != 0)
|
||||
return Promise.reject(rv);
|
||||
|
||||
var try_deadline = date.getTime() + 1000 * timeout;
|
||||
var try_confirm = function() {
|
||||
return self.callConfirm().then(function(rv) {
|
||||
const try_deadline = date.getTime() + 1000 * timeout;
|
||||
const try_confirm = () => {
|
||||
return self.callConfirm().then(rv => {
|
||||
if (rv != 0) {
|
||||
if (date.getTime() < try_deadline)
|
||||
window.setTimeout(try_confirm, 250);
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -5,10 +5,10 @@ function bytelen(x) {
|
||||
return new Blob([x]).size;
|
||||
}
|
||||
|
||||
var Validator = baseclass.extend({
|
||||
const Validator = baseclass.extend({
|
||||
__name__: 'Validation',
|
||||
|
||||
__init__: function(field, type, optional, vfunc, validatorFactory) {
|
||||
__init__(field, type, optional, vfunc, validatorFactory) {
|
||||
this.field = field;
|
||||
this.optional = optional;
|
||||
this.vfunc = vfunc;
|
||||
@@ -16,7 +16,7 @@ var Validator = baseclass.extend({
|
||||
this.factory = validatorFactory;
|
||||
},
|
||||
|
||||
assert: function(condition, message) {
|
||||
assert(condition, message) {
|
||||
if (!condition) {
|
||||
this.field.classList.add('cbi-input-invalid');
|
||||
this.error = message;
|
||||
@@ -28,8 +28,8 @@ var Validator = baseclass.extend({
|
||||
return true;
|
||||
},
|
||||
|
||||
apply: function(name, value, args) {
|
||||
var func;
|
||||
apply(name, value, args) {
|
||||
let func;
|
||||
|
||||
if (typeof(name) === 'function')
|
||||
func = name;
|
||||
@@ -44,7 +44,7 @@ var Validator = baseclass.extend({
|
||||
return func.apply(this, args);
|
||||
},
|
||||
|
||||
validate: function() {
|
||||
validate() {
|
||||
/* element is detached */
|
||||
if (!findParent(this.field, 'body') && !findParent(this.field, '[data-field]'))
|
||||
return true;
|
||||
@@ -53,7 +53,7 @@ var Validator = baseclass.extend({
|
||||
this.value = (this.field.value != null) ? this.field.value : '';
|
||||
this.error = null;
|
||||
|
||||
var valid;
|
||||
let valid;
|
||||
|
||||
if (this.value.length === 0)
|
||||
valid = this.assert(this.optional, _('non-empty value'));
|
||||
@@ -61,7 +61,7 @@ var Validator = baseclass.extend({
|
||||
valid = this.vstack[0].apply(this, this.vstack[1]);
|
||||
|
||||
if (valid !== true) {
|
||||
var message = _('Expecting: %s').format(this.error);
|
||||
const message = _('Expecting: %s').format(this.error);
|
||||
this.field.setAttribute('data-tooltip', message);
|
||||
this.field.setAttribute('data-tooltip-style', 'error');
|
||||
this.field.dispatchEvent(new CustomEvent('validation-failure', {
|
||||
@@ -97,22 +97,22 @@ var Validator = baseclass.extend({
|
||||
|
||||
});
|
||||
|
||||
var ValidatorFactory = baseclass.extend({
|
||||
const ValidatorFactory = baseclass.extend({
|
||||
__name__: 'ValidatorFactory',
|
||||
|
||||
create: function(field, type, optional, vfunc) {
|
||||
create(field, type, optional, vfunc) {
|
||||
return new Validator(field, type, optional, vfunc, this);
|
||||
},
|
||||
|
||||
compile: function(code) {
|
||||
var pos = 0;
|
||||
var esc = false;
|
||||
var depth = 0;
|
||||
var stack = [ ];
|
||||
compile(code) {
|
||||
let pos = 0;
|
||||
let esc = false;
|
||||
let depth = 0;
|
||||
const stack = [ ];
|
||||
|
||||
code += ',';
|
||||
|
||||
for (var i = 0; i < code.length; i++) {
|
||||
for (let i = 0; i < code.length; i++) {
|
||||
if (esc) {
|
||||
esc = false;
|
||||
continue;
|
||||
@@ -128,7 +128,7 @@ var ValidatorFactory = baseclass.extend({
|
||||
case 44:
|
||||
if (depth <= 0) {
|
||||
if (pos < i) {
|
||||
var label = code.substring(pos, i);
|
||||
let label = code.substring(pos, i);
|
||||
label = label.replace(/\\(.)/g, '$1');
|
||||
label = label.replace(/^[ \t]+/g, '');
|
||||
label = label.replace(/[ \t]+$/g, '');
|
||||
@@ -170,15 +170,15 @@ var ValidatorFactory = baseclass.extend({
|
||||
return stack;
|
||||
},
|
||||
|
||||
parseInteger: function(x) {
|
||||
parseInteger(x) {
|
||||
return (/^-?\d+$/.test(x) ? +x : NaN);
|
||||
},
|
||||
|
||||
parseDecimal: function(x) {
|
||||
parseDecimal(x) {
|
||||
return (/^-?\d+(?:\.\d+)?$/.test(x) ? +x : NaN);
|
||||
},
|
||||
|
||||
parseIPv4: function(x) {
|
||||
parseIPv4(x) {
|
||||
if (!x.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/))
|
||||
return null;
|
||||
|
||||
@@ -188,34 +188,35 @@ var ValidatorFactory = baseclass.extend({
|
||||
return [ +RegExp.$1, +RegExp.$2, +RegExp.$3, +RegExp.$4 ];
|
||||
},
|
||||
|
||||
parseIPv6: function(x) {
|
||||
parseIPv6(x) {
|
||||
if (x.match(/^([a-fA-F0-9:]+):(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/)) {
|
||||
var v6 = RegExp.$1, v4 = this.parseIPv4(RegExp.$2);
|
||||
const v6 = RegExp.$1;
|
||||
const v4 = this.parseIPv4(RegExp.$2);
|
||||
|
||||
if (!v4)
|
||||
return null;
|
||||
|
||||
x = v6 + ':' + (v4[0] * 256 + v4[1]).toString(16)
|
||||
+ ':' + (v4[2] * 256 + v4[3]).toString(16);
|
||||
x = `${v6}:${(v4[0] * 256 + v4[1]).toString(16)}:${(v4[2] * 256 + v4[3]).toString(16)}`;
|
||||
}
|
||||
|
||||
if (!x.match(/^[a-fA-F0-9:]+$/))
|
||||
return null;
|
||||
|
||||
var prefix_suffix = x.split(/::/);
|
||||
const prefix_suffix = x.split(/::/);
|
||||
|
||||
if (prefix_suffix.length > 2)
|
||||
return null;
|
||||
|
||||
var prefix = (prefix_suffix[0] || '0').split(/:/);
|
||||
var suffix = prefix_suffix.length > 1 ? (prefix_suffix[1] || '0').split(/:/) : [];
|
||||
const prefix = (prefix_suffix[0] || '0').split(/:/);
|
||||
const suffix = prefix_suffix.length > 1 ? (prefix_suffix[1] || '0').split(/:/) : [];
|
||||
|
||||
if (suffix.length ? (prefix.length + suffix.length > 7)
|
||||
: ((prefix_suffix.length < 2 && prefix.length < 8) || prefix.length > 8))
|
||||
: ((prefix_suffix.length < 2 && prefix.length < 8) || prefix.length > 8))
|
||||
return null;
|
||||
|
||||
var i, word;
|
||||
var words = [];
|
||||
let i;
|
||||
let word;
|
||||
const words = [];
|
||||
|
||||
for (i = 0, word = parseInt(prefix[0], 16); i < prefix.length; word = parseInt(prefix[++i], 16))
|
||||
if (prefix[i].length <= 4 && !isNaN(word) && word <= 0xFFFF)
|
||||
@@ -236,112 +237,112 @@ var ValidatorFactory = baseclass.extend({
|
||||
},
|
||||
|
||||
types: {
|
||||
integer: function() {
|
||||
integer() {
|
||||
return this.assert(!isNaN(this.factory.parseInteger(this.value)), _('valid integer value'));
|
||||
},
|
||||
|
||||
uinteger: function() {
|
||||
uinteger() {
|
||||
return this.assert(this.factory.parseInteger(this.value) >= 0, _('positive integer value'));
|
||||
},
|
||||
|
||||
float: function() {
|
||||
float() {
|
||||
return this.assert(!isNaN(this.factory.parseDecimal(this.value)), _('valid decimal value'));
|
||||
},
|
||||
|
||||
ufloat: function() {
|
||||
ufloat() {
|
||||
return this.assert(this.factory.parseDecimal(this.value) >= 0, _('positive decimal value'));
|
||||
},
|
||||
|
||||
ipaddr: function(nomask) {
|
||||
ipaddr(nomask) {
|
||||
return this.assert(this.apply('ip4addr', null, [nomask]) || this.apply('ip6addr', null, [nomask]),
|
||||
nomask ? _('valid IP address') : _('valid IP address or prefix'));
|
||||
},
|
||||
|
||||
ip4addr: function(nomask) {
|
||||
var re = nomask ? /^(\d+\.\d+\.\d+\.\d+)$/ : /^(\d+\.\d+\.\d+\.\d+)(?:\/(\d+\.\d+\.\d+\.\d+)|\/(\d{1,2}))?$/,
|
||||
m = this.value.match(re);
|
||||
ip4addr(nomask) {
|
||||
const re = nomask ? /^(\d+\.\d+\.\d+\.\d+)$/ : /^(\d+\.\d+\.\d+\.\d+)(?:\/(\d+\.\d+\.\d+\.\d+)|\/(\d{1,2}))?$/;
|
||||
const m = this.value.match(re);
|
||||
|
||||
return this.assert(m && this.factory.parseIPv4(m[1]) && (m[2] ? this.factory.parseIPv4(m[2]) : (m[3] ? this.apply('ip4prefix', m[3]) : true)),
|
||||
nomask ? _('valid IPv4 address') : _('valid IPv4 address or network'));
|
||||
},
|
||||
|
||||
ip6addr: function(nomask) {
|
||||
var re = nomask ? /^([0-9a-fA-F:.]+)$/ : /^([0-9a-fA-F:.]+)(?:\/(\d{1,3}))?$/,
|
||||
m = this.value.match(re);
|
||||
ip6addr(nomask) {
|
||||
const re = nomask ? /^([0-9a-fA-F:.]+)$/ : /^([0-9a-fA-F:.]+)(?:\/(\d{1,3}))?$/;
|
||||
const m = this.value.match(re);
|
||||
|
||||
return this.assert(m && this.factory.parseIPv6(m[1]) && (m[2] ? this.apply('ip6prefix', m[2]) : true),
|
||||
nomask ? _('valid IPv6 address') : _('valid IPv6 address or prefix'));
|
||||
},
|
||||
|
||||
ip4prefix: function() {
|
||||
ip4prefix() {
|
||||
return this.assert(!isNaN(this.value) && this.value >= 0 && this.value <= 32,
|
||||
_('valid IPv4 prefix value (0-32)'));
|
||||
},
|
||||
|
||||
ip6prefix: function() {
|
||||
ip6prefix() {
|
||||
return this.assert(!isNaN(this.value) && this.value >= 0 && this.value <= 128,
|
||||
_('valid IPv6 prefix value (0-128)'));
|
||||
},
|
||||
|
||||
cidr: function(negative) {
|
||||
cidr(negative) {
|
||||
return this.assert(this.apply('cidr4', null, [negative]) || this.apply('cidr6', null, [negative]),
|
||||
_('valid IPv4 or IPv6 CIDR'));
|
||||
},
|
||||
|
||||
cidr4: function(negative) {
|
||||
var m = this.value.match(/^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\/(-)?(\d{1,2})$/);
|
||||
cidr4(negative) {
|
||||
const m = this.value.match(/^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\/(-)?(\d{1,2})$/);
|
||||
return this.assert(m && this.factory.parseIPv4(m[1]) && (negative || !m[2]) && this.apply('ip4prefix', m[3]),
|
||||
_('valid IPv4 CIDR'));
|
||||
},
|
||||
|
||||
cidr6: function(negative) {
|
||||
var m = this.value.match(/^([0-9a-fA-F:.]+)\/(-)?(\d{1,3})$/);
|
||||
cidr6(negative) {
|
||||
const m = this.value.match(/^([0-9a-fA-F:.]+)\/(-)?(\d{1,3})$/);
|
||||
return this.assert(m && this.factory.parseIPv6(m[1]) && (negative || !m[2]) && this.apply('ip6prefix', m[3]),
|
||||
_('valid IPv6 CIDR'));
|
||||
},
|
||||
|
||||
ipnet4: function() {
|
||||
var m = this.value.match(/^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/);
|
||||
ipnet4() {
|
||||
const m = this.value.match(/^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/);
|
||||
return this.assert(m && this.factory.parseIPv4(m[1]) && this.factory.parseIPv4(m[2]), _('IPv4 network in address/netmask notation'));
|
||||
},
|
||||
|
||||
ipnet6: function() {
|
||||
var m = this.value.match(/^([0-9a-fA-F:.]+)\/([0-9a-fA-F:.]+)$/);
|
||||
ipnet6() {
|
||||
const m = this.value.match(/^([0-9a-fA-F:.]+)\/([0-9a-fA-F:.]+)$/);
|
||||
return this.assert(m && this.factory.parseIPv6(m[1]) && this.factory.parseIPv6(m[2]), _('IPv6 network in address/netmask notation'));
|
||||
},
|
||||
|
||||
ip6hostid: function() {
|
||||
ip6hostid() {
|
||||
if (this.value == "eui64" || this.value == "random")
|
||||
return true;
|
||||
|
||||
var v6 = this.factory.parseIPv6(this.value);
|
||||
const v6 = this.factory.parseIPv6(this.value);
|
||||
return this.assert(!(!v6 || v6[0] || v6[1] || v6[2] || v6[3]), _('valid IPv6 host id'));
|
||||
},
|
||||
|
||||
ipmask: function(negative) {
|
||||
ipmask(negative) {
|
||||
return this.assert(this.apply('ipmask4', null, [negative]) || this.apply('ipmask6', null, [negative]),
|
||||
_('valid network in address/netmask notation'));
|
||||
},
|
||||
|
||||
ipmask4: function(negative) {
|
||||
ipmask4(negative) {
|
||||
return this.assert(this.apply('cidr4', null, [negative]) || this.apply('ipnet4') || this.apply('ip4addr'),
|
||||
_('valid IPv4 network'));
|
||||
},
|
||||
|
||||
ipmask6: function(negative) {
|
||||
ipmask6(negative) {
|
||||
return this.assert(this.apply('cidr6', null, [negative]) || this.apply('ipnet6') || this.apply('ip6addr'),
|
||||
_('valid IPv6 network'));
|
||||
},
|
||||
|
||||
port: function() {
|
||||
var p = this.factory.parseInteger(this.value);
|
||||
port() {
|
||||
const p = this.factory.parseInteger(this.value);
|
||||
return this.assert(p >= 0 && p <= 65535, _('valid port value'));
|
||||
},
|
||||
|
||||
portrange: function() {
|
||||
portrange() {
|
||||
if (this.value.match(/^(\d+)-(\d+)$/)) {
|
||||
var p1 = +RegExp.$1;
|
||||
var p2 = +RegExp.$2;
|
||||
const p1 = +RegExp.$1;
|
||||
const p2 = +RegExp.$2;
|
||||
return this.assert(p1 <= p2 && p2 <= 65535,
|
||||
_('valid port or port range (port1-port2)'));
|
||||
}
|
||||
@@ -349,18 +350,18 @@ var ValidatorFactory = baseclass.extend({
|
||||
return this.assert(this.apply('port'), _('valid port or port range (port1-port2)'));
|
||||
},
|
||||
|
||||
macaddr: function(multicast) {
|
||||
var m = this.value.match(/^([a-fA-F0-9]{2}):([a-fA-F0-9]{2}:){4}[a-fA-F0-9]{2}$/);
|
||||
macaddr(multicast) {
|
||||
const m = this.value.match(/^([a-fA-F0-9]{2}):([a-fA-F0-9]{2}:){4}[a-fA-F0-9]{2}$/);
|
||||
return this.assert(m != null && !(+m[1] & 1) == !multicast,
|
||||
multicast ? _('valid multicast MAC address') : _('valid MAC address'));
|
||||
},
|
||||
|
||||
host: function(ipv4only) {
|
||||
host(ipv4only) {
|
||||
return this.assert(this.apply('hostname') || this.apply(ipv4only == 1 ? 'ip4addr' : 'ipaddr', null, ['nomask']),
|
||||
_('valid hostname or IP address'));
|
||||
},
|
||||
|
||||
hostname: function(strict) {
|
||||
hostname(strict) {
|
||||
if (this.value.length <= 253)
|
||||
return this.assert(
|
||||
(this.value.match(/^[a-zA-Z0-9_]+$/) != null ||
|
||||
@@ -372,26 +373,26 @@ var ValidatorFactory = baseclass.extend({
|
||||
return this.assert(false, _('valid hostname'));
|
||||
},
|
||||
|
||||
network: function() {
|
||||
network() {
|
||||
return this.assert(this.apply('uciname') || this.apply('hostname') || this.apply('ip4addr') || this.apply('ip6addr'),
|
||||
_('valid UCI identifier, hostname or IP address range'));
|
||||
},
|
||||
|
||||
hostport: function(ipv4only) {
|
||||
var hp = this.value.split(/:/);
|
||||
hostport(ipv4only) {
|
||||
const hp = this.value.split(/:/);
|
||||
return this.assert(hp.length == 2 && this.apply('host', hp[0], [ipv4only]) && this.apply('port', hp[1]),
|
||||
_('valid host:port'));
|
||||
},
|
||||
|
||||
ip4addrport: function() {
|
||||
var hp = this.value.split(/:/);
|
||||
ip4addrport() {
|
||||
const hp = this.value.split(/:/);
|
||||
return this.assert(hp.length == 2 && this.apply('ip4addr', hp[0], [true]) && this.apply('port', hp[1]),
|
||||
_('valid IPv4 address:port'));
|
||||
},
|
||||
|
||||
ipaddrport: function(bracket) {
|
||||
var m4 = this.value.match(/^([^\[\]:]+):(\d+)$/),
|
||||
m6 = this.value.match((bracket == 1) ? /^\[(.+)\]:(\d+)$/ : /^([^\[\]]+):(\d+)$/);
|
||||
ipaddrport(bracket) {
|
||||
const m4 = this.value.match(/^([^\[\]:]+):(\d+)$/);
|
||||
const m6 = this.value.match((bracket == 1) ? /^\[(.+)\]:(\d+)$/ : /^([^\[\]]+):(\d+)$/);
|
||||
|
||||
if (m4)
|
||||
return this.assert(this.apply('ip4addr', m4[1], [true]) && this.apply('port', m4[2]),
|
||||
@@ -401,8 +402,8 @@ var ValidatorFactory = baseclass.extend({
|
||||
_('valid address:port'));
|
||||
},
|
||||
|
||||
wpakey: function() {
|
||||
var v = this.value;
|
||||
wpakey() {
|
||||
const v = this.value;
|
||||
|
||||
if (v.length == 64)
|
||||
return this.assert(v.match(/^[a-fA-F0-9]{64}$/), _('valid hexadecimal WPA key'));
|
||||
@@ -410,8 +411,8 @@ var ValidatorFactory = baseclass.extend({
|
||||
return this.assert((v.length >= 8) && (v.length <= 63), _('key between 8 and 63 characters'));
|
||||
},
|
||||
|
||||
wepkey: function() {
|
||||
var v = this.value;
|
||||
wepkey() {
|
||||
let v = this.value;
|
||||
|
||||
if (v.substr(0, 2) === 's:')
|
||||
v = v.substr(2);
|
||||
@@ -422,12 +423,12 @@ var ValidatorFactory = baseclass.extend({
|
||||
return this.assert((v.length === 5) || (v.length === 13), _('key with either 5 or 13 characters'));
|
||||
},
|
||||
|
||||
uciname: function() {
|
||||
uciname() {
|
||||
return this.assert(this.value.match(/^[a-zA-Z0-9_]+$/), _('valid UCI identifier'));
|
||||
},
|
||||
|
||||
netdevname: function() {
|
||||
var v = this.value;
|
||||
netdevname() {
|
||||
const v = this.value;
|
||||
|
||||
if (v == '.' || v == '..')
|
||||
return this.assert(false, _('valid network device name, not "." or ".."'));
|
||||
@@ -435,44 +436,44 @@ var ValidatorFactory = baseclass.extend({
|
||||
return this.assert(v.match(/^[^:\/%\s]{1,15}$/), _('valid network device name between 1 and 15 characters not containing ":", "/", "%" or spaces'));
|
||||
},
|
||||
|
||||
range: function(min, max) {
|
||||
var val = this.factory.parseDecimal(this.value);
|
||||
range(min, max) {
|
||||
const val = this.factory.parseDecimal(this.value);
|
||||
return this.assert(val >= +min && val <= +max, _('value between %f and %f').format(min, max));
|
||||
},
|
||||
|
||||
min: function(min) {
|
||||
min(min) {
|
||||
return this.assert(this.factory.parseDecimal(this.value) >= +min, _('value greater or equal to %f').format(min));
|
||||
},
|
||||
|
||||
max: function(max) {
|
||||
max(max) {
|
||||
return this.assert(this.factory.parseDecimal(this.value) <= +max, _('value smaller or equal to %f').format(max));
|
||||
},
|
||||
|
||||
length: function(len) {
|
||||
length(len) {
|
||||
return this.assert(bytelen(this.value) == +len,
|
||||
_('value with %d characters').format(len));
|
||||
},
|
||||
|
||||
rangelength: function(min, max) {
|
||||
var len = bytelen(this.value);
|
||||
rangelength(min, max) {
|
||||
const len = bytelen(this.value);
|
||||
return this.assert((len >= +min) && (len <= +max),
|
||||
_('value between %d and %d characters').format(min, max));
|
||||
},
|
||||
|
||||
minlength: function(min) {
|
||||
minlength(min) {
|
||||
return this.assert(bytelen(this.value) >= +min,
|
||||
_('value with at least %d characters').format(min));
|
||||
},
|
||||
|
||||
maxlength: function(max) {
|
||||
maxlength(max) {
|
||||
return this.assert(bytelen(this.value) <= +max,
|
||||
_('value with at most %d characters').format(max));
|
||||
},
|
||||
|
||||
or: function() {
|
||||
var errors = [];
|
||||
or() {
|
||||
const errors = [];
|
||||
|
||||
for (var i = 0; i < arguments.length; i += 2) {
|
||||
for (let i = 0; i < arguments.length; i += 2) {
|
||||
if (typeof arguments[i] != 'function') {
|
||||
if (arguments[i] == this.value)
|
||||
return this.assert(true);
|
||||
@@ -487,13 +488,13 @@ var ValidatorFactory = baseclass.extend({
|
||||
}
|
||||
}
|
||||
|
||||
var t = _('One of the following: %s');
|
||||
const t = _('One of the following: %s');
|
||||
|
||||
return this.assert(false, t.format('\n - ' + errors.join('\n - ')));
|
||||
return this.assert(false, t.format(`\n - ${errors.join('\n - ')}`));
|
||||
},
|
||||
|
||||
and: function() {
|
||||
for (var i = 0; i < arguments.length; i += 2) {
|
||||
and() {
|
||||
for (let i = 0; i < arguments.length; i += 2) {
|
||||
if (typeof arguments[i] != 'function') {
|
||||
if (arguments[i] != this.value)
|
||||
return this.assert(false, '"%s"'.format(arguments[i]));
|
||||
@@ -507,7 +508,7 @@ var ValidatorFactory = baseclass.extend({
|
||||
return this.assert(true);
|
||||
},
|
||||
|
||||
neg: function() {
|
||||
neg() {
|
||||
this.value = this.value.replace(/^[ \t]*![ \t]*/, '');
|
||||
|
||||
if (arguments[0].apply(this, arguments[1]))
|
||||
@@ -516,64 +517,58 @@ var ValidatorFactory = baseclass.extend({
|
||||
return this.assert(false, _('Potential negation of: %s').format(this.error));
|
||||
},
|
||||
|
||||
list: function(subvalidator, subargs) {
|
||||
list(subvalidator, subargs) {
|
||||
this.field.setAttribute('data-is-list', 'true');
|
||||
|
||||
var tokens = this.value.match(/[^ \t]+/g);
|
||||
for (var i = 0; i < tokens.length; i++)
|
||||
const tokens = this.value.match(/[^ \t]+/g);
|
||||
for (let i = 0; i < tokens.length; i++)
|
||||
if (!this.apply(subvalidator, tokens[i], subargs))
|
||||
return this.assert(false, this.error);
|
||||
|
||||
return this.assert(true);
|
||||
},
|
||||
|
||||
phonedigit: function() {
|
||||
phonedigit() {
|
||||
return this.assert(this.value.match(/^[0-9\*#!\.]+$/),
|
||||
_('valid phone digit (0-9, "*", "#", "!" or ".")'));
|
||||
},
|
||||
|
||||
timehhmmss: function() {
|
||||
timehhmmss() {
|
||||
return this.assert(this.value.match(/^[0-6][0-9]:[0-6][0-9]:[0-6][0-9]$/),
|
||||
_('valid time (HH:MM:SS)'));
|
||||
},
|
||||
|
||||
dateyyyymmdd: function() {
|
||||
dateyyyymmdd() {
|
||||
if (this.value.match(/^(\d\d\d\d)-(\d\d)-(\d\d)/)) {
|
||||
var year = +RegExp.$1,
|
||||
month = +RegExp.$2,
|
||||
day = +RegExp.$3,
|
||||
days_in_month = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];
|
||||
const year = +RegExp.$1;
|
||||
const month = +RegExp.$2;
|
||||
const day = +RegExp.$3;
|
||||
const days_in_month = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];
|
||||
|
||||
var is_leap_year = function(year) {
|
||||
return ((!(year % 4) && (year % 100)) || !(year % 400));
|
||||
}
|
||||
|
||||
var get_days_in_month = function(month, year) {
|
||||
return (month === 2 && is_leap_year(year)) ? 29 : days_in_month[month - 1];
|
||||
}
|
||||
const is_leap_year = year => (!(year % 4) && (year % 100)) || !(year % 400);
|
||||
const get_days_in_month = (month, year) => (month === 2 && is_leap_year(year)) ? 29 : days_in_month[month - 1];
|
||||
|
||||
/* Firewall rules in the past don't make sense */
|
||||
return this.assert(year >= 2015 && month && month <= 12 && day && day <= get_days_in_month(month, year),
|
||||
_('valid date (YYYY-MM-DD)'));
|
||||
|
||||
}
|
||||
|
||||
return this.assert(false, _('valid date (YYYY-MM-DD)'));
|
||||
},
|
||||
|
||||
unique: function(subvalidator, subargs) {
|
||||
var ctx = this,
|
||||
option = findParent(ctx.field, '[data-widget][data-name]'),
|
||||
section = findParent(option, '.cbi-section'),
|
||||
query = '[data-widget="%s"][data-name="%s"]'.format(option.getAttribute('data-widget'), option.getAttribute('data-name')),
|
||||
unique = true;
|
||||
unique(subvalidator, subargs) {
|
||||
const ctx = this;
|
||||
const option = findParent(ctx.field, '[data-widget][data-name]');
|
||||
const section = findParent(option, '.cbi-section');
|
||||
const query = '[data-widget="%s"][data-name="%s"]'.format(option.getAttribute('data-widget'), option.getAttribute('data-name'));
|
||||
let unique = true;
|
||||
|
||||
section.querySelectorAll(query).forEach(function(sibling) {
|
||||
section.querySelectorAll(query).forEach(sibling => {
|
||||
if (sibling === option)
|
||||
return;
|
||||
|
||||
var input = sibling.querySelector('[data-type]'),
|
||||
values = input ? (input.getAttribute('data-is-list') ? input.value.match(/[^ \t]+/g) : [ input.value ]) : null;
|
||||
const input = sibling.querySelector('[data-type]');
|
||||
const values = input ? (input.getAttribute('data-is-list') ? input.value.match(/[^ \t]+/g) : [ input.value ]) : null;
|
||||
|
||||
if (values !== null && values.indexOf(ctx.value) !== -1)
|
||||
unique = false;
|
||||
@@ -588,24 +583,24 @@ var ValidatorFactory = baseclass.extend({
|
||||
return this.assert(true);
|
||||
},
|
||||
|
||||
hexstring: function() {
|
||||
hexstring() {
|
||||
return this.assert(this.value.match(/^([a-f0-9][a-f0-9]|[A-F0-9][A-F0-9])+$/),
|
||||
_('hexadecimal encoded value'));
|
||||
},
|
||||
|
||||
string: function() {
|
||||
string() {
|
||||
return true;
|
||||
},
|
||||
|
||||
directory: function() {
|
||||
directory() {
|
||||
return true;
|
||||
},
|
||||
|
||||
file: function() {
|
||||
file() {
|
||||
return true;
|
||||
},
|
||||
|
||||
device: function() {
|
||||
device() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user