'require form';
'require tools.widgets as widgets';
-var aclList = {};
+const aclList = {};
function globListToRegExp(section_id, option) {
- var list = L.toArray(uci.get('rpcd', section_id, option)),
- positivePatterns = [],
- negativePatterns = [];
+ const list = L.toArray(uci.get('rpcd', section_id, option));
+ const positivePatterns = [];
+ const negativePatterns = [];
if (option == 'read')
list.push.apply(list, L.toArray(uci.get('rpcd', section_id, 'write')));
- for (var i = 0; i < list.length; i++) {
- var array, glob;
+ for (let l of list) {
+ let array, glob;
- if (list[i].match(/^\s*!/)) {
- glob = list[i].replace(/^\s*!/, '').trim();
+ if (l.match(/^\s*!/)) {
+ glob = l.replace(/^\s*!/, '').trim();
array = negativePatterns;
}
else {
- glob = list[i].trim(),
+ glob = l.trim(),
array = positivePatterns;
}
];
}
-var cbiACLLevel = form.DummyValue.extend({
- textvalue: function(section_id) {
- var allowedAclMatches = globListToRegExp(section_id, this.option.match(/read/) ? 'read' : 'write'),
- aclGroupNames = Object.keys(aclList),
- matchingGroupNames = [];
+const cbiACLLevel = form.DummyValue.extend({
+ textvalue(section_id) {
+ const allowedAclMatches = globListToRegExp(section_id, this.option.match(/read/) ? 'read' : 'write');
+ const aclGroupNames = Object.keys(aclList);
+ const matchingGroupNames = [];
- for (var j = 0; j < aclGroupNames.length; j++)
- if (allowedAclMatches[0].test(aclGroupNames[j]) && !allowedAclMatches[1].test(aclGroupNames[j]))
- matchingGroupNames.push(aclGroupNames[j]);
+ for (let gn of aclGroupNames)
+ if (allowedAclMatches[0].test(gn) && !allowedAclMatches[1].test(gn))
+ matchingGroupNames.push(gn);
if (matchingGroupNames.length == aclGroupNames.length)
return E('span', { 'class': 'label' }, [ _('full', 'All permissions granted') ]);
}
});
-var cbiACLSelect = form.Value.extend({
- renderWidget: function(section_id) {
- var readMatches = globListToRegExp(section_id, 'read'),
- writeMatches = globListToRegExp(section_id, 'write');
+const cbiACLSelect = form.Value.extend({
+ renderWidget(section_id) {
+ const readMatches = globListToRegExp(section_id, 'read');
+ const writeMatches = globListToRegExp(section_id, 'write');
- var table = E('table', { 'class': 'table' }, [
+ const table = E('table', { 'class': 'table' }, [
E('tr', { 'class': 'tr' }, [
E('th', { 'class': 'th' }, [ _('ACL group') ]),
E('th', { 'class': 'th' }, [ _('Description') ]),
]);
Object.keys(aclList).sort().forEach(function(aclGroupName) {
- var isRequired = (aclGroupName == 'unauthenticated' || aclGroupName == 'luci-base' || aclGroupName == 'luci-mod-status-index'),
- isReadable = (readMatches[0].test(aclGroupName) && !readMatches[1].test(aclGroupName)) || null,
- isWritable = (writeMatches[0].test(aclGroupName) && !writeMatches[1].test(aclGroupName)) || null;
+ const isRequired = (aclGroupName == 'unauthenticated' || aclGroupName == 'luci-base' || aclGroupName == 'luci-mod-status-index');
+ const isReadable = (readMatches[0].test(aclGroupName) && !readMatches[1].test(aclGroupName)) || null;
+ const isWritable = (writeMatches[0].test(aclGroupName) && !writeMatches[1].test(aclGroupName)) || null;
table.appendChild(E('tr', { 'class': 'tr' }, [
E('td', { 'class': 'td' }, [ aclGroupName ]),
return table;
},
- formvalue: function(section_id) {
- var node = this.map.findElement('data-field', this.cbid(section_id)),
- data = {};
+ formvalue(section_id) {
+ const node = this.map.findElement('data-field', this.cbid(section_id));
+ const data = {};
node.querySelectorAll('[data-acl-group]').forEach(function(select) {
- var aclGroupName = select.getAttribute('data-acl-group'),
- value = select.value;
+ const aclGroupName = select.getAttribute('data-acl-group');
+ const value = select.value;
if (!value)
return;
return data;
},
- write: function(section_id, value) {
+ write(section_id, value) {
uci.unset('rpcd', section_id, 'read');
uci.unset('rpcd', section_id, 'write');
});
return view.extend({
- load: function() {
+ load() {
return L.resolveDefault(fs.list('/usr/share/rpcd/acl.d'), []).then(function(entries) {
- var tasks = [
+ const tasks = [
L.resolveDefault(fs.stat('/usr/sbin/uhttpd'), null),
fs.lines('/etc/passwd')
];
- for (var i = 0; i < entries.length; i++)
- if (entries[i].type == 'file' && entries[i].name.match(/\.json$/))
- tasks.push(L.resolveDefault(fs.read('/usr/share/rpcd/acl.d/' + entries[i].name).then(JSON.parse)));
+ for (let e of entries)
+ if (e.type == 'file' && e.name.match(/\.json$/))
+ tasks.push(L.resolveDefault(fs.read('/usr/share/rpcd/acl.d/' + e.name).then(JSON.parse)));
return Promise.all(tasks);
});
},
- render: function(data) {
+ render([has_uhttpd, passwd, ...acls]) {
ui.addNotification(null, E('p', [
_('The LuCI ACL management is in an experimental stage! It does not yet work reliably with all applications')
]), 'warning');
- var has_uhttpd = data[0],
- known_unix_users = {};
+ const known_unix_users = {};
- for (var i = 0; i < data[1].length; i++) {
- var parts = data[1][i].split(/:/);
+ for (let p of passwd) {
+ const parts = p.split(/:/);
if (parts.length >= 7)
known_unix_users[parts[0]] = true;
}
- for (var i = 2; i < data.length; i++) {
- if (!L.isObject(data[i]))
+ for (let acl of acls) {
+ if (!L.isObject(acl))
continue;
- for (var aclName in data[i]) {
- if (!data[i].hasOwnProperty(aclName))
+ for (let aclName in acl) {
+ if (!acl.hasOwnProperty(aclName))
continue;
- aclList[aclName] = data[i][aclName];
+ aclList[aclName] = acl[aclName];
}
}
};
o = s.option(form.Value, 'username', _('Login name'));
+ for(let user in known_unix_users)
+ o.value(user);
o.rmempty = false;
o = s.option(form.ListValue, '_variant', _('Password variant'));
o.value('shadow', _('Use UNIX password in /etc/shadow'));
o.value('crypted', _('Use encrypted password hash'));
o.cfgvalue = function(section_id) {
- var value = uci.get('rpcd', section_id, 'password') || '';
+ const value = uci.get('rpcd', section_id, 'password') || '';
if (value.substring(0, 3) == '$p$')
return 'shadow';
o.modalonly = true;
o.depends('_variant', 'shadow');
o.cfgvalue = function(section_id) {
- var value = uci.get('rpcd', section_id, 'password') || '';
+ const value = uci.get('rpcd', section_id, 'password') || '';
return value.substring(3);
};
o.write = function(section_id, value) {
o.rmempty = false;
o.depends('_variant', 'crypted');
o.cfgvalue = function(section_id) {
- var value = uci.get('rpcd', section_id, 'password') || '';
+ const value = uci.get('rpcd', section_id, 'password') || '';
return (value.substring(0, 3) == '$p$') ? '' : value;
};
o.validate = function(section_id, value) {
- var variant = this.map.lookupOption('_variant', section_id)[0];
+ const variant = this.map.lookupOption('_variant', section_id)[0];
switch (value.substring(0, 3)) {
case '$p$':
return true;
};
o.write = function(section_id, value) {
- var variant = this.map.lookupOption('_variant', section_id)[0];
+ const variant = this.map.lookupOption('_variant', section_id)[0];
if (variant.formvalue(section_id) == 'crypted' && value.substring(0, 3) != '$1$')
return fs.exec('/usr/sbin/uhttpd', [ '-m', value ]).then(function(res) {
o.default = '300';
o.datatype = 'uinteger';
o.textvalue = function(section_id) {
- var value = uci.get('rpcd', section_id, 'timeout') || this.default;
+ const value = uci.get('rpcd', section_id, 'timeout') || this.default;
return +value ? '%ds'.format(value) : E('em', [ _('does not expire') ]);
};
o.value('read', _('readonly', 'Only read permissions granted'));
o.value('individual', _('individual', 'Select individual permissions manually'));
o.cfgvalue = function(section_id) {
- var readList = L.toArray(uci.get('rpcd', section_id, 'read')),
- writeList = L.toArray(uci.get('rpcd', section_id, 'write'));
+ const readList = L.toArray(uci.get('rpcd', section_id, 'read'));
+ const writeList = L.toArray(uci.get('rpcd', section_id, 'write'));
if (writeList.length == 1 && writeList[0] == '*')
return 'write';
'require uci';
return view.extend({
- load: function() {
+ load() {
return Promise.all([
uci.load('apinger'),
])
},
- render: function(data) {
+ render() {
let m, s, o;
- var a_ifaces, a_down, a_delay, a_loss;
- a_ifaces = uci.sections('apinger', 'interface');
- a_down = uci.sections('apinger', 'alarm_down');
- a_delay = uci.sections('apinger', 'alarm_delay');
- a_loss = uci.sections('apinger', 'alarm_loss');
+ const a_ifaces = uci.sections('apinger', 'interface');
+ const a_down = uci.sections('apinger', 'alarm_down');
+ const a_delay = uci.sections('apinger', 'alarm_delay');
+ const a_loss = uci.sections('apinger', 'alarm_loss');
m = new form.Map('apinger', _('Apinger - Targets'),
_('Interface: Interface to use to track target') + '<br />' +
s.addbtntitle = _('Add Target');
o = s.option(form.ListValue, 'interface', _('Interface'));
- for (var i = 0; i < a_ifaces.length; i++) {
- o.value(a_ifaces[i]['.name']);
+ for (let aif of a_ifaces) {
+ o.value(aif['.name']);
}
o = s.option(form.Value, 'address', _('Address'));
o.default = false;
o = s.option(form.ListValue, 'alarm_down', _('Down Alarm'));
- for (var i = 0; i < a_down.length; i++) {
- o.value(a_down[i]['.name']);
+ for (let ad of a_down) {
+ o.value(ad['.name']);
}
o.optional = true;
o = s.option(form.ListValue, 'alarm_delay', _('Delay Alarm'));
- for (var i = 0; i < a_delay.length; i++) {
- o.value(a_delay[i]['.name']);
+ for (let ad of a_delay) {
+ o.value(ad['.name']);
}
o.optional = true;
o = s.option(form.ListValue, 'alarm_loss', _('Loss Alarm'));
- for (var i = 0; i < a_loss.length; i++) {
- o.value(a_loss[i]['.name']);
+ for (let al of a_loss) {
+ o.value(al['.name']);
}
o.optional = true;
expect: { '': {} }
}),
- load: function() {
+ load() {
return Promise.all([
- L.resolveDefault(L.uci.load('dcwapd'), {}),
this.callLuciWirelessDevices(),
+ L.resolveDefault(L.uci.load('dcwapd'), {}),
]);
},
- render: function(data) {
- var wireless_devices = data[1];
+ render([wireless_devices]) {
- var m = new form.Map('dcwapd', _('Dual Channel Wi-Fi AP Daemon'),
+ let m = new form.Map('dcwapd', _('Dual Channel Wi-Fi AP Daemon'),
_('With %s you can use two simultaneous Wi-Fi connections to decrease wireless traffic congestion and increase throughput.').format('<abbr title="%s">%s</abbr>').format(_('Dual Channel Wi-Fi AP Daemon'), _('Dual Channel WiFi')));
// General section
- var s = m.section(form.NamedSection, 'general', _('General'), _('General Settings'));
+ let s = m.section(form.NamedSection, 'general', _('General'), _('General Settings'));
s.addremove = false;
s.dynamic = false;
s.optional = false;
s.anonymous = true;
// Enabled state option
- var enable = s.option(form.Flag, 'enabled', _('Enable'));
+ let enable = s.option(form.Flag, 'enabled', _('Enable'));
enable.default = false;
enable.optional = false;
enable.rmempty = false;
// Temp dir option
- var tmpdir = s.option(form.Value, 'tmpdir', _('Temp Directory'), _('Specify the temporary directory for dcwapd file storage.'));
+ let tmpdir = s.option(form.Value, 'tmpdir', _('Temp Directory'), _('Specify the temporary directory for dcwapd file storage.'));
tmpdir.optional = false;
tmpdir.rmempty = false;
s.addremove = true;
// SSID option
- var dat_ssid = s.option(form.Value, 'ssid', _('SSID'));
+ let dat_ssid = s.option(form.Value, 'ssid', _('SSID'));
dat_ssid.optional = false;
dat_ssid.rmempty = false;
if (wireless_devices.length > 0) {
}
// Data bridge option
- var dat_bridge = s.option(widgets.DeviceSelect, 'bridge', _('Bridge'));
+ let dat_bridge = s.option(widgets.DeviceSelect, 'bridge', _('Bridge'));
dat_bridge.optional = false;
dat_bridge.rmempty = false;
dat_bridge.nocreate = false;
}
// Data interfaces list
- var ifaces = s.option(form.MultiValue, 'interfaces', _('Interfaces'));
+ let ifaces = s.option(form.MultiValue, 'interfaces', _('Interfaces'));
ifaces.optional = true;
ifaces.rmempty = false;
if (wireless_devices.length > 0) {
s.anonymous = false;
// Enabled state option
- var enable = s.option(form.Flag, 'enabled', _('Enable'));
- enable.default = false;
- enable.optional = false;
- enable.rmempty = false;
+ let set_enable = s.option(form.Flag, 'enabled', _('Enable'));
+ set_enable.default = false;
+ set_enable.optional = false;
+ set_enable.rmempty = false;
// SSID option
- var pri_ssid = s.option(form.Value, 'ssid', _('SSID'));
+ let pri_ssid = s.option(form.Value, 'ssid', _('SSID'));
pri_ssid.optional = false;
pri_ssid.rmempty = false;
if (wireless_devices.length > 0) {
}
// Primary bridge option
- var pri_bridge = s.option(widgets.DeviceSelect, 'bridge', _('Bridge'));
+ let pri_bridge = s.option(widgets.DeviceSelect, 'bridge', _('Bridge'));
pri_bridge.optional = false;
pri_bridge.rmempty = false;
pri_bridge.nocreate = true;
}
// Data channels list
- var data_channels = s.option(form.MultiValue, 'data_channels', _('Data Channels'));
+ let data_channels = s.option(form.MultiValue, 'data_channels', _('Data Channels'));
data_channels.optional = false;
data_channels.rmempty = false;
const dataChannels = L.uci.sections('dcwapd', 'datachannel');
s.sortable = true;
// Packet Size
- var packetsize = s.option(form.Value, 'packet_size', _('Packet size'));
+ let packetsize = s.option(form.Value, 'packet_size', _('Packet size'));
packetsize.rmempty = false;
packetsize.value('*');
packetsize.default = '*';
// Source IP
- var srcip = s.option(form.Value, 'source_ip', _('Source IP'));
+ let srcip = s.option(form.Value, 'source_ip', _('Source IP'));
srcip.rmempty = false;
srcip.value('*');
srcip.default = '*';
// Source Port
- var srcport = s.option(form.Value, 'source_port', _('Source port'));
+ let srcport = s.option(form.Value, 'source_port', _('Source port'));
srcport.rmempty = false;
srcport.value('*');
srcport.default = '*';
// Protocol
- var proto = s.option(form.Value, 'protocol', _('Protocol'));
+ let proto = s.option(form.Value, 'protocol', _('Protocol'));
proto.value('*');
proto.value('tcp', 'TCP');
proto.value('udp', 'UDP');
proto.default = '*';
// Destination Port
- var dstport = s.option(form.Value, 'dest_port', _('Destination port'));
+ let dstport = s.option(form.Value, 'dest_port', _('Destination port'));
dstport.rmempty = false;
dstport.value('*');
dstport.default = '*';
s.optional = false;
// MAC address option
- var mac = s.option(form.Value, 'mac', _('MAC Address'));
+ let mac = s.option(form.Value, 'mac', _('MAC Address'));
mac.optional = false;
mac.rmempty = false;
mac.datatype = 'or(macaddr,"*")';
// Filters list
- var filters = s.option(form.MultiValue, 'filters', _('Filters'));
+ let filters = s.option(form.MultiValue, 'filters', _('Filters'));
filters.optional = false;
filters.rmempty = false;
const filterSections = L.uci.sections('dcwapd', 'filter');
* (Special services that requires a dedicated package ARE NOT
* supported by the 'service on demand' feature)
*/
- callGenServiceList: function(m, ev) {
+ callGenServiceList(m, ev) {
return Promise.all([
L.resolveDefault(fs.list('/usr/share/ddns/default'), []),
L.resolveDefault(fs.list('/usr/share/ddns/custom'), []),
L.resolveDefault(fs.read('/usr/share/ddns/list'), null)
- ]).then(L.bind(function (data) {
- var default_service = data[0],
- custom_service = data[1],
- list_service = data[2] && data[2].split("\n") || [],
- _this = this;
+ ]).then(L.bind(function ([default_service, custom_service, list_service]) {
+
+ list_service = list_service?.split("\n") || [];
+ let _this = this;
this.services = {};
* Figure out what the wan interface on the device is.
* Determine if the physical device exist, or if we should use an alias.
*/
- callGetWanInterface: function(m, ev) {
+ callGetWanInterface(m, ev) {
return network.getDevice('wan').then(dev => dev.getName())
.catch(err => network.getNetwork('wan').then(net => '@' + net.getName()))
.catch(err => null);
* If a JSON is found, check if the IP type is supported.
* Invalidate the service_name if it is not supported.
*/
- handleCheckService : function(s, service_name, ipv6, ev, section_id) {
+ handleCheckService (s, service_name, ipv6, ev, section_id) {
var value = service_name.formvalue(section_id);
s.service_supported = null;
.then(L.bind(service_name.triggerValidation, service_name, section_id))
},
- handleGetServiceData: function(service) {
+ handleGetServiceData(service) {
return Promise.all([
L.resolveDefault(fs.read('/usr/share/ddns/custom/'+service+'.json'), null),
L.resolveDefault(fs.read('/usr/share/ddns/default/'+service+'.json'), null)
})
},
- handleInstallService: function(m, service_name, section_id, section, _this, ev) {
+ handleInstallService(m, service_name, section_id, section, _this, ev) {
var service = service_name.formvalue(section_id)
return fs.exec('/usr/bin/ddns', ['service', 'install', service])
.then(L.bind(_this.callGenServiceList, _this))
.catch(function(e) { ui.addNotification(null, E('p', e.message)) });
},
- handleRefreshServicesList: function(m, ev) {
+ handleRefreshServicesList(m, ev) {
return fs.exec('/usr/bin/ddns', ['service', 'update'])
.then(L.bind(this.load, this))
.then(L.bind(this.render, this))
.catch(function(e) { ui.addNotification(null, E('p', e.message)) });
},
- handleReloadDDnsRule: function(m, section_id, ev) {
+ handleReloadDDnsRule(m, section_id, ev) {
return fs.exec('/usr/lib/ddns/dynamic_dns_lucihelper.sh',
[ '-S', section_id, '--', 'start' ])
.then(L.bind(m.load, m))
.catch(function(e) { ui.addNotification(null, E('p', e.message)) });
},
- HandleStopDDnsRule: function(m, section_id, ev) {
+ HandleStopDDnsRule(m, section_id, ev) {
return fs.exec('/usr/lib/ddns/dynamic_dns_lucihelper.sh',
[ '-S', section_id, '--', 'start' ])
.then(L.bind(m.render, m))
.catch(function(e) { ui.addNotification(null, E('p', e.message)) });
},
- handleToggleDDns: function(m, ev) {
+ handleToggleDDns(m, ev) {
let action = this.status['_enabled'];
return this.callInitAction('ddns', action ? 'disable' : 'enable')
.then(L.bind(function () { return this.callInitAction('ddns', action ? 'stop' : 'start')}, this))
.catch(function(e) { ui.addNotification(null, E('p', e.message)) });
},
- handleRestartDDns: function(m, ev) {
+ handleRestartDDns(m, ev) {
return this.callInitAction('ddns', 'restart')
.then(L.bind(m.render, m));
},
- poll_status: function(map, data) {
+ poll_status(map, data) {
var status = this.status = data[1] || [];
var service = data[0] || [], rows = map.querySelectorAll('.cbi-section-table-row[data-sid]'),
ddns_enabled = map.querySelector('[data-name="_enabled"]').querySelector('.cbi-value-field'),
return;
},
- load: function() {
+ load() {
return Promise.all([
this.callDDnsGetServicesStatus(),
this.callDDnsGetStatus(),
this.callDDnsGetEnv(),
this.callGenServiceList(),
+ this.callGetWanInterface(),
uci.load('ddns'),
- this.callGetWanInterface()
]);
},
- render: function(data) {
- var resolved = data[0] || [];
- var status = this.status = data[1] || [];
- var env = data[2] || [];
- var logdir = uci.get('ddns', 'global', 'ddns_logdir') || "/var/log/ddns";
- var wan_interface = data[5];
+ render([resolved, status, env, , wan_interface]) {
+ this.status = status;
+ const logdir = uci.get('ddns', 'global', 'ddns_logdir') || "/var/log/ddns";
- var _this = this;
+ let _this = this;
let m, s, o;
o = s.taboption('info', form.DummyValue, '_enabled', _('State'));
o.cfgvalue = function() {
- var res = status[this.option];
+ const res = status[this.option];
if (!res) {
this.description = _("Currently DDNS updates are not started at boot or on interface events.") + "<br />" +
_("This is the default if you run DDNS scripts by yourself (i.e. via cron with force_interval set to '0')")
s.sortable = true;
s.handleCreateDDnsRule = function(m, name, service_name, ipv6, ev) {
- var section_id = name.isValid('_new_') ? name.formvalue('_new_') : null,
- service_value = service_name.isValid('_new_') ? service_name.formvalue('_new_') : null,
- ipv6_value = ipv6.isValid('_new_') ? ipv6.formvalue('_new_') : null;
+ const section_id = name.isValid('_new_') ? name.formvalue('_new_') : null;
+ const service_value = service_name.isValid('_new_') ? service_name.formvalue('_new_') : null;
+ const ipv6_value = ipv6.isValid('_new_') ? ipv6.formvalue('_new_') : null;
if (!section_id || !service_value || !ipv6_value)
return;
};
s.handleAdd = function(ev) {
- var m2 = new form.Map('ddns'),
- s2 = m2.section(form.NamedSection, '_new_'),
- name, ipv6, service_name;
+ let m2 = new form.Map('ddns');
+ let s2 = m2.section(form.NamedSection, '_new_');
+ let name, ipv6, service_name;
s2.render = function() {
return Promise.all([
};
s.renderRowActions = function(section_id) {
- var tdEl = this.super('renderRowActions', [ section_id, _('Edit') ]),
+ const tdEl = this.super('renderRowActions', [ section_id, _('Edit') ]),
cfg_enabled = uci.get('ddns', section_id, 'enabled'),
reload_opt = {
'class': 'cbi-button cbi-button-neutral reload',
s.addModalOptions = function(s, section_id) {
- var service = uci.get('ddns', section_id, 'service_name') || '-',
- ipv6 = uci.get('ddns', section_id, 'use_ipv6'), service_name, use_ipv6;
+ const service = uci.get('ddns', section_id, 'service_name') || '-';
+ const ipv6 = uci.get('ddns', section_id, 'use_ipv6');
+ let service_name, use_ipv6;
return _this.handleGetServiceData(service).then(L.bind(function (service_data) {
s.service_available = true;
};
}
- if (Boolean(s.url)) {
+ if (s.url) {
o = s.taboption('basic', form.DummyValue, '_url', _("Update URL"));
o.rawhtml = true;
o.default = '<div style="font-family: monospace;">'
+ '</div>';
}
- var service_switch = s.taboption('basic', form.Button, '_switch_proto');
+ let service_switch = s.taboption('basic', form.Button, '_switch_proto');
service_switch.modalonly = true;
service_switch.title = _('Really switch service?');
service_switch.inputtitle = _('Switch service');
o.optional = true;
o.depends("service_name","-");
o.validate = function(section_id, value) {
- var other = this.section.formvalue(section_id, 'update_script');
+ const other = this.section.formvalue(section_id, 'update_script');
if ((!value && !other) || (value && other)) {
return _("Provide either an Update Script OR an Update URL");
}
o.optional = true;
o.depends("service_name","-");
o.validate = function(section_id, value) {
- var other = this.section.formvalue(section_id, 'update_url');
+ const other = this.section.formvalue(section_id, 'update_url');
if ((!value && !other) || (value && other)) {
return _("Provide either an Update Script OR an Update URL");
}
return uci.get('ddns', section_id, 'interface') || _('This will be autoset to the selected interface');
};
o.write = function(section_id) {
- var opt = this.section.formvalue(section_id, 'ip_source');
- var val = this.section.formvalue(section_id, 'ip_'+opt);
+ const opt = this.section.formvalue(section_id, 'ip_source');
+ const val = this.section.formvalue(section_id, 'ip_'+opt);
return uci.set('ddns', section_id, 'interface', val);
};
o.modalonly = true;
o.datatype = 'uinteger';
o.validate = function(section_id, formvalue) {
- var unit = this.section.formvalue(section_id, 'check_unit'),
- time_to_sec = _this.time_res[unit || 'minutes'] * formvalue;
+ const unit = this.section.formvalue(section_id, 'check_unit');
+ const time_to_sec = _this.time_res[unit || 'minutes'] * formvalue;
if (formvalue && time_to_sec < 300)
return _('Values below 5 minutes == 300 seconds are not supported');
if (!formvalue)
return true;
- var check_unit = this.section.formvalue(section_id, 'check_unit'),
- check_val = this.section.formvalue(section_id, 'check_interval'),
- force_unit = this.section.formvalue(section_id, 'force_unit'),
- check_to_sec = _this.time_res[check_unit || 'minutes'] * ( check_val || '30'),
- force_to_sec = _this.time_res[force_unit || 'minutes'] * formvalue;
+ const check_unit = this.section.formvalue(section_id, 'check_unit');
+ const check_val = this.section.formvalue(section_id, 'check_interval');
+ const force_unit = this.section.formvalue(section_id, 'force_unit');
+ const check_to_sec = _this.time_res[check_unit || 'minutes'] * ( check_val || '30');
+ const force_to_sec = _this.time_res[force_unit || 'minutes'] * formvalue;
if (force_to_sec != 0 && force_to_sec < check_to_sec)
return _("Values lower than 'Check Interval' except '0' are invalid");
return _this.callGetLogServices(section_id).then(L.bind(log_box.update_log, log_box));
}, this);
- var log_box = s.taboption("logview", form.DummyValue, "_logview");
+ const log_box = s.taboption("logview", form.DummyValue, "_logview");
log_box.depends('use_logfile','1');
log_box.modalonly = true;
}, o, this);
}
- for (var i = 0; i < s.children.length; i++) {
- o = s.children[i];
+ for (let o of s.children) {
switch (o.option) {
case '_switch_proto':
o.depends({ service_name : service, use_ipv6: ipv6, "!reverse": true })
default:
if (o.deps.length)
- for (var j = 0; j < o.deps.length; j++) {
- o.deps[j].service_name = service;
- o.deps[j].use_ipv6 = ipv6;
+ for (let d of o.deps) {
+ d.service_name = service;
+ d.use_ipv6 = ipv6;
}
else
o.depends({service_name: service, use_ipv6: ipv6 });
'require tools.widgets as widgets';
// [Widget, Option, Title, Description, {Param: 'Value'}],
-var startupConf = [
+const startupConf = [
[form.Flag, 'stdout', _('Log stdout')],
[form.Flag, 'stderr', _('Log stderr')],
[widgets.UserSelect, 'user', _('Run daemon as user')],
[form.DynamicList, 'conf_inc', _('Additional configs'), _('Config files include in temporary config file'), {placeholder: '/etc/frp/frpc.d/frpc_full.ini'}]
];
-var commonConf = [
+const commonConf = [
[form.Value, 'server_addr', _('Server address'), _('ServerAddr specifies the address of the server to connect to.<br />By default, this value is "127.0.0.1".'), {datatype: 'host'}],
[form.Value, 'server_port', _('Server port'), _('ServerPort specifies the port to connect to the server on.<br />By default, this value is 7000.'), {datatype: 'port'}],
[form.Value, 'http_proxy', _('HTTP proxy'), _('HttpProxy specifies a proxy address to connect to the server through. If this value is "", the server will be connected to directly.<br />By default, this value is read from the "http_proxy" environment variable.')],
[form.DynamicList, '_', _('Additional settings'), _('This list can be used to specify some additional parameters which have not been included in this LuCI.'), {placeholder: 'Key-A=Value-A'}]
];
-var baseProxyConf = [
+const baseProxyConf = [
[form.Value, 'name', _('Proxy name'), undefined, {rmempty: false, optional: false}],
[form.ListValue, 'type', _('Proxy type'), _('ProxyType specifies the type of this proxy. Valid values include "tcp", "udp", "http", "https", "stcp" and "xtcp".<br />By default, this value is "tcp".'), {values: ['tcp', 'udp', 'http', 'https', 'stcp', 'xtcp']}],
[form.Flag, 'use_encryption', _('Encryption'), _('UseEncryption controls whether or not communication with the server will be encrypted. Encryption is done using the tokens supplied in the server and client configuration.<br />By default, this value is false.'), {datatype: 'bool'}],
[form.Value, 'local_port', _('Local port'), _('LocalPort specifies the port to proxy to.'), {datatype: 'port'}],
];
-var bindInfoConf = [
+const bindInfoConf = [
[form.Value, 'remote_port', _('Remote port'), _('If remote_port is 0, frps will assign a random port for you'), {datatype: 'port'}]
];
-var domainConf = [
+const domainConf = [
[form.Value, 'custom_domains', _('Custom domains')],
[form.Value, 'subdomain', _('Subdomain')],
];
-var httpProxyConf = [
+const httpProxyConf = [
[form.Value, 'locations', _('Locations')],
[form.Value, 'http_user', _('HTTP user')],
[form.Value, 'http_pwd', _('HTTP password')],
// [form.Value, 'headers', _('Headers')], // FIXME
];
-var stcpProxyConf = [
+const stcpProxyConf = [
[form.ListValue, 'role', _('Role'), undefined, {values: ['server', 'visitor']}],
[form.Value, 'server_name', _('Server name'), undefined, {depends: [{role: 'visitor'}]}],
[form.Value, 'bind_addr', _('Bind addr'), undefined, {depends: [{role: 'visitor'}]}],
[form.Value, 'sk', _('Sk')],
];
-var pluginConf = [
+const pluginConf = [
[form.ListValue, 'plugin', _('Plugin'), undefined, {values: ['', 'http_proxy', 'socks5', 'unix_domain_socket'], rmempty: true}],
[form.Value, 'plugin_http_user', _('HTTP user'), undefined, {depends: {plugin: 'http_proxy'}}],
[form.Value, 'plugin_http_passwd', _('HTTP password'), undefined, {depends: {plugin: 'http_proxy'}}],
function setParams(o, params) {
if (!params) return;
- for (var key in params) {
- var val = params[key];
+ for (let key in params) {
+ let val = params[key];
if (key === 'values') {
- for (var j = 0; j < val.length; j++) {
- var args = val[j];
+ for (let v of val) {
+ let args = v;
if (!Array.isArray(args))
args = [args];
o.value.apply(o, args);
if (!Array.isArray(val))
val = [val];
- var deps = [];
- for (var j = 0; j < val.length; j++) {
- var d = {};
- for (var vkey in val[j])
- d[vkey] = val[j][vkey];
- for (var k = 0; k < o.deps.length; k++) {
- for (var dkey in o.deps[k]) {
- d[dkey] = o.deps[k][dkey];
+ const deps = [];
+ for (let v of val) {
+ const d = {};
+ for (let vkey in v)
+ d[vkey] = v[vkey];
+ for (let od of o.deps) {
+ for (let dkey in od) {
+ d[dkey] = od[dkey];
}
}
deps.push(d);
}
function defTabOpts(s, t, opts, params) {
- for (var i = 0; i < opts.length; i++) {
- var opt = opts[i];
- var o = s.taboption(t, opt[0], opt[1], opt[2], opt[3]);
+ for (let opt of opts) {
+ const o = s.taboption(t, opt[0], opt[1], opt[2], opt[3]);
setParams(o, opt[4]);
setParams(o, params);
}
}
function defOpts(s, opts, params) {
- for (var i = 0; i < opts.length; i++) {
- var opt = opts[i];
- var o = s.option(opt[0], opt[1], opt[2], opt[3]);
+ for (let opt of opts) {
+ const o = s.option(opt[0], opt[1], opt[2], opt[3]);
setParams(o, opt[4]);
setParams(o, params);
}
function getServiceStatus() {
return L.resolveDefault(callServiceList('frpc'), {}).then(function (res) {
- var isRunning = false;
+ let isRunning = false;
try {
isRunning = res['frpc']['instances']['instance1']['running'];
} catch (e) { }
}
function renderStatus(isRunning) {
- var renderHTML = "";
- var spanTemp = '<em><span style="color:%s"><strong>%s %s</strong></span></em>';
+ let renderHTML = "";
+ const spanTemp = '<em><span style="color:%s"><strong>%s %s</strong></span></em>';
if (isRunning) {
renderHTML += String.format(spanTemp, 'green', _("frp Client"), _("RUNNING"));
}
return view.extend({
- render: function() {
+ render() {
let m, s, o;
m = new form.Map('frpc', _('frp Client'));
s.render = function (section_id) {
L.Poll.add(function () {
return L.resolveDefault(getServiceStatus()).then(function(res) {
- var view = document.getElementById("service_status");
+ const view = document.getElementById("service_status");
view.innerHTML = renderStatus(res);
});
});
o.depends('type', 'tcp');
o.depends('type', 'udp');
o.cfgvalue = function() {
- var v = this.super('cfgvalue', arguments);
+ const v = this.super('cfgvalue', arguments);
return v&&v!='0'?v:'#';
};
'require tools.widgets as widgets';
// [Widget, Option, Title, Description, {Param: 'Value'}],
-var startupConf = [
+const startupConf = [
[form.Flag, 'stdout', _('Log stdout')],
[form.Flag, 'stderr', _('Log stderr')],
[widgets.UserSelect, 'user', _('Run daemon as user')],
[form.DynamicList, 'conf_inc', _('Additional configs'), _('Config files include in temporary config file'), {placeholder: '/etc/frp/frps.d/frps_full.ini'}]
];
-var commonConf = [
+const commonConf = [
[form.Value, 'bind_addr', _('Bind address'), _('BindAddr specifies the address that the server binds to.<br />By default, this value is "0.0.0.0".'), {datatype: 'ipaddr'}],
[form.Value, 'bind_port', _('Bind port'), _('BindPort specifies the port that the server listens on.<br />By default, this value is 7000.'), {datatype: 'port'}],
[form.Value, 'bind_udp_port', _('UDP bind port'), _('BindUdpPort specifies the UDP port that the server listens on. If this value is 0, the server will not listen for UDP connections.<br />By default, this value is 0.'), {datatype: 'port'}],
function setParams(o, params) {
if (!params) return;
- for (var key in params) {
- var val = params[key];
+ for (let key in params) {
+ let val = params[key];
if (key === 'values') {
- for (var j = 0; j < val.length; j++) {
- var args = val[j];
+ for (let v of val) {
+ let args = v;
if (!Array.isArray(args))
args = [args];
o.value.apply(o, args);
} else if (key === 'depends') {
if (!Array.isArray(val))
val = [val];
- for (var j = 0; j < val.length; j++) {
- var args = val[j];
+ for (let v of val) {
+ let args = v;
if (!Array.isArray(args))
args = [args];
o.depends.apply(o, args);
}
function defTabOpts(s, t, opts, params) {
- for (var i = 0; i < opts.length; i++) {
- var opt = opts[i];
- var o = s.taboption(t, opt[0], opt[1], opt[2], opt[3]);
+ for (let opt of opts) {
+ const o = s.taboption(t, opt[0], opt[1], opt[2], opt[3]);
setParams(o, opt[4]);
setParams(o, params);
}
}
function defOpts(s, opts, params) {
- for (var i = 0; i < opts.length; i++) {
- var opt = opts[i];
- var o = s.option(opt[0], opt[1], opt[2], opt[3]);
+ for (let opt of opts) {
+ const o = s.option(opt[0], opt[1], opt[2], opt[3]);
setParams(o, opt[4]);
setParams(o, params);
}
function getServiceStatus() {
return L.resolveDefault(callServiceList('frps'), {}).then(function (res) {
- var isRunning = false;
+ let isRunning = false;
try {
isRunning = res['frps']['instances']['instance1']['running'];
} catch (e) { }
}
function renderStatus(isRunning) {
- var renderHTML = "";
- var spanTemp = '<em><span style="color:%s"><strong>%s %s</strong></span></em>';
+ let renderHTML = "";
+ const spanTemp = '<em><span style="color:%s"><strong>%s %s</strong></span></em>';
if (isRunning) {
renderHTML += String.format(spanTemp, 'green', _("frp Server"), _("RUNNING"));
}
return view.extend({
- render: function() {
+ render() {
let m, s, o;
m = new form.Map('frps', _('frp Server'));
s.render = function (section_id) {
L.Poll.add(function () {
return L.resolveDefault(getServiceStatus()).then(function(res) {
- var view = document.getElementById("service_status");
+ const view = document.getElementById("service_status");
view.innerHTML = renderStatus(res);
});
});
'require ui';
'require tools.widgets as widgets';
-var domparser = new DOMParser();
-var QRCODE_VARIABLES = ['KEY_BASE64', 'KEY', 'HMAC_KEY_BASE64', 'HMAC_KEY'];
-var INVALID_KEYS = ['__CHANGEME__', 'CHANGEME'];
+const domparser = new DOMParser();
+const QRCODE_VARIABLES = ['KEY_BASE64', 'KEY', 'HMAC_KEY_BASE64', 'HMAC_KEY'];
+const INVALID_KEYS = ['__CHANGEME__', 'CHANGEME'];
function setOptionValue(map, section_id, option, value) {
- var option = L.toArray(map.lookupOption(option, section_id))[0];
- var uiEl = option ? option.getUIElement(section_id) : null;
+ const opt = L.toArray(map.lookupOption(option, section_id))[0];
+ const uiEl = opt ? option.getUIElement(section_id) : null;
if (uiEl)
uiEl.setValue(value);
}
function parseLine(rawLine) {
if (rawLine[0] != '#' && rawLine[0] != ';') {
- var line = rawLine.split(/ ([^;]*)/, 2);
+ const line = rawLine.split(/ ([^;]*)/, 2);
if (line.length == 2) {
- var key = line[0].trim();
- var value = line[1].trim();
+ const key = line[0].trim();
+ const value = line[1].trim();
if (key && value)
return [key, value];
}
}
function parseKeys(content) {
- var l = lines(content);
- var keys = {};
- for (var i = 0; i < l.length; i++) {
- var p = l[i].split(/:(.*)/, 2);
+ const l = lines(content);
+ const keys = {};
+ for (let line of l) {
+ const p = line.split(/:(.*)/, 2);
if (p.length == 2)
keys[p[0].trim()] = p[1].trim();
}
return keys;
}
-var KeyTypeValue = form.ListValue.extend({
- __init__: function() {
+const KeyTypeValue = form.ListValue.extend({
+ __init__() {
this.super('__init__', arguments);
this.hidden = false;
},
- cfgvalue: function(section_id) {
+ cfgvalue(section_id) {
for (var i = 0; i < this.keylist.length; i++) {
var value = this.map.data.get(
this.uciconfig || this.section.uciconfig || this.map.config,
return this.keylist[0];
},
- render: function(section_id, option_index, cfgvalue) {
+ render(section_id, option_index, cfgvalue) {
return this.super('render', arguments)
.then(L.bind(function(el) {
// Use direct style to hide, because class .hidden
}, this));
},
- remove: function() {
+ remove() {
// Ignore
},
- write: function() {
+ write() {
// Ignore
},
});
-var YNValue = form.Flag.extend({
- __init__: function() {
+const YNValue = form.Flag.extend({
+ __init__() {
this.super('__init__', arguments);
this.enabled = 'Y';
this.disabled = 'N';
this.default = 'N';
},
- cfgvalue: function(section_id) {
- var value = this.super('cfgvalue', arguments);
+ cfgvalue(section_id) {
+ const value = this.super('cfgvalue', arguments);
return value ? String(value).toUpperCase() : value;
},
- parse: function(section_id) {
- var active = this.isActive(section_id),
- cval = this.cfgvalue(section_id),
- fval = active ? this.formvalue(section_id) : null;
+ parse(section_id) {
+ const active = this.isActive(section_id);
+ const cval = this.cfgvalue(section_id);
+ const fval = active ? this.formvalue(section_id) : null;
if (String(fval).toUpperCase() != cval) {
if (fval == 'Y')
},
});
-var QrCodeValue = form.DummyValue.extend({
- __init__: function() {
+const QrCodeValue = form.DummyValue.extend({
+ __init__() {
this.super('__init__', arguments);
this.needsRefresh = {};
this.components = [];
QRCODE_VARIABLES.forEach(L.bind(function(option) {
this.components.push(option);
- var dep = {};
+ const dep = {};
dep[option] = /.+/;
this.depends(dep);
}, this));
},
- cfgQrCode: function(section_id) {
- var qr = [];
- for (var i = 0; i < this.components.length; i++) {
- var value = this.map.data.get(
+ cfgQrCode(section_id) {
+ const qr = [];
+ for (let comp of this.components) {
+ const value = this.map.data.get(
this.uciconfig || this.section.uciconfig || this.map.config,
this.ucisection || section_id,
- this.components[i]
+ comp
);
if (value)
- qr.push(this.components[i] + ':' + value);
+ qr.push(comp + ':' + value);
}
return qr ? qr.join(' ') : null;
},
- formQrCode: function(section_id) {
- var qr = [];
- for (var i = 0; i < this.components.length; i++) {
- var value = null;
+ formQrCode(section_id) {
+ const qr = [];
+ for (let comp of this.components) {
+ let value = null;
- var uiEl = L.toArray(this.map.lookupOption(this.components[i], section_id))[0];
+ const uiEl = L.toArray(this.map.lookupOption(comp, section_id))[0];
if (uiEl) {
if (uiEl.isActive(section_id))
value = uiEl.formvalue(section_id);
}
if (value)
- qr.push(this.components[i] + ':' + value);
+ qr.push(comp + ':' + value);
}
return qr ? qr.join(' ') : null;
},
- onchange: function(ev, section_id) {
+ onchange(ev, section_id) {
if (this.needsRefresh[section_id] !== undefined)
this.needsRefresh[section_id] = true;
else {
}
},
- refresh: function(section_id) {
- var qrcode = this.formQrCode(section_id);
- var formvalue = this.formvalue(section_id);
+ refresh(section_id) {
+ const qrcode = this.formQrCode(section_id);
+ const formvalue = this.formvalue(section_id);
if (formvalue != qrcode) {
this.getUIElement(section_id).setValue(qrcode);
- var uiEl = document.getElementById(this.cbid(section_id));
+ const uiEl = document.getElementById(this.cbid(section_id));
if (uiEl) {
- var contentEl = uiEl.nextSibling;
+ const contentEl = uiEl.nextSibling;
if (contentEl.childNodes.length == 1) {
dom.append(contentEl, E('em', { 'class': 'spinning', }, [ _('Loading…') ]));
}
.then(L.bind(function(svgEl) {
dom.content(contentEl, svgEl || E('div'));
- var needsAnotherRefresh = this.needsRefresh[section_id];
+ const needsAnotherRefresh = this.needsRefresh[section_id];
delete this.needsRefresh[section_id];
if (needsAnotherRefresh) {
return Promise.resolve(null);
},
- renderWidget: function(section_id) {
- var qrcode = this.cfgQrCode(section_id);
+ renderWidget(section_id) {
+ const qrcode = this.cfgQrCode(section_id);
return this.renderSvg(qrcode)
.then(L.bind(function(svgEl) {
- var uiEl = new ui.Hiddenfield(qrcode, { id: this.cbid(section_id) });
+ const uiEl = new ui.Hiddenfield(qrcode, { id: this.cbid(section_id) });
return E([
uiEl.render(),
E('div', {}, svgEl || E('div'))
}, this));
},
- qrEncodeSvg: function(qrcode) {
+ qrEncodeSvg(qrcode) {
return fs.exec('/usr/bin/qrencode', ['--type', 'svg', '--inline', '-o', '-', qrcode])
.then(function(response) {
return response.stdout;
});
},
- renderSvg: function(qrcode) {
+ renderSvg(qrcode) {
if (qrcode)
return this.qrEncodeSvg(qrcode)
.then(function(rawsvg) {
},
});
-var GenerateButton = form.Button.extend({
- __init__: function() {
+const GenerateButton = form.Button.extend({
+ __init__() {
this.super('__init__', arguments);
this.onclick = L.bind(this.generateKeys, this);
this.keytypes = {};
},
- keytype: function(key, regex) {
+ keytype(key, regex) {
this.keytypes[key] = regex;
},
- qrcode: function(option) {
+ qrcode(option) {
this.qrcode = option;
},
- generateKeys: function(ev, section_id) {
+ generateKeys(ev, section_id) {
return fs.exec('/usr/sbin/fwknopd', ['--key-gen'])
.then(function(response) { return parseKeys(response.stdout); })
.then(L.bind(this.applyKeys, this, section_id))
.catch(L.error);
},
- applyKeys: function(section_id, keys) {
- for (var key in keys) {
+ applyKeys(section_id, keys) {
+ for (let key in keys) {
setOptionValue(this.map, section_id, key, keys[key]);
- for (var type in this.keytypes) {
+ for (let type in this.keytypes) {
if (this.keytypes[type].test(key))
setOptionValue(this.map, section_id, type, key);
}
this.map.checkDepends();
// Refresh QR code
- var option = L.toArray(this.map.lookupOption(this.qrcode, section_id))[0];
+ const option = L.toArray(this.map.lookupOption(this.qrcode, section_id))[0];
if (option)
return option.refresh(section_id);
else
},
});
-var ParseButton = form.Button.extend({
- __init__: function() {
+const ParseButton = form.Button.extend({
+ __init__() {
this.super('__init__', arguments);
this.onclick = L.bind(this.parseAccessConf, this);
},
- parseAccessConf: function() {
+ parseAccessConf() {
this.stanzas = [];
- var ctx = {
+ const ctx = {
processLine: L.bind(this.processAccessLine, this),
remainingLines: [],
stanzas: {
if (ctx.stanzas.all.length > 0)
return this.renderStanzas(ctx.stanzas.all)
.then(function(topEl) {
- var dlg = ui.showModal(_('Firewall Knock Operator Daemon'), [
+ const dlg = ui.showModal(_('Firewall Knock Operator Daemon'), [
topEl,
E('button', {
'class': 'cbi-button cbi-button-neutral',
dlg.parentNode.scrollTop = 0;
});
else {
- var dlg = ui.showModal(_('Firewall Knock Operator Daemon'), [
+ const dlg = ui.showModal(_('Firewall Knock Operator Daemon'), [
E('p', _("No stanza found.")),
E('button', {
'class': 'cbi-button cbi-button-neutral',
});
},
- parseFile: function(ctx, content) {
+ parseFile(ctx, content) {
ctx.remainingLines.unshift.apply(ctx.remainingLines, lines(content));
return this.parseLines(ctx);
},
- parseFolder: function(ctx, folder, entries) {
+ parseFolder(ctx, folder, entries) {
// Parse and process files in order
- var parseJobs = [];
- var parsedLines = [];
+ const parseJobs = [];
+ const parsedLines = [];
entries.sort(function(el1, el2) {
return (el1.name > el2.name) ? 1
: (el1.name < el2.name) ? -1
: 0;
});
entries.forEach(L.bind(function(entry) {
- var ctxLines = [];
+ const ctxLines = [];
parsedLines.unshift(ctxLines);
parseJobs.push(fs.read(folder + '/' + entry.name)
.then(function(content) {
.then(L.bind(this.parseLines, this, ctx));
},
- parseLines: function(ctx) {
+ parseLines(ctx) {
while (ctx.remainingLines.length > 0) {
- var line = parseLine(ctx.remainingLines.shift());
+ const line = parseLine(ctx.remainingLines.shift());
if (line) {
- var result = ctx.processLine.call(this, ctx, line[0], line[1]);
+ const result = ctx.processLine.call(this, ctx, line[0], line[1]);
if (result)
return result;
}
}
},
- processAccessLine: function(ctx, key, value) {
+ processAccessLine(ctx, key, value) {
if (key.endsWith(':')) {
key = key.slice(0, -1);
}
return fs.list(value)
.then(L.bind(this.parseFolder, this, ctx, value));
} else if (key == "%include_keys") {
- var keysCtx = {
+ const keysCtx = {
processLine: L.bind(this.processKeysLine, this),
remainingLines: [],
stanzas: ctx.stanzas
}
},
- processKeysLine: function(ctx, key, value) {
+ processKeysLine(ctx, key, value) {
// Simplification - accept only KEY arguments
if (ctx.stanzas.last && key.match(/KEY/))
ctx.stanzas.last[key] = value;
},
- renderStanzas: function(stanzas) {
- var config = {};
+ renderStanzas(stanzas) {
+ const config = {};
config.access = stanzas;
let m, s, o;
return view.extend({
- load: function() {
+ load() {
return Promise.all([
L.resolveDefault(fs.stat('/etc/fwknop/access.conf'))
]);
},
- render: function(results) {
- var has_access_conf = results[0];
+ render([has_access_conf]) {
let m, s, o;
m = new form.Map('fwknopd', _('Firewall Knock Operator Daemon'));
s.anonymous = true;
s.addremove = true;
- var qrCode = s.option(QrCodeValue, 'qr', _('QR code'), ('QR code to configure fwknopd Android application.'));
+ let qrCode = s.option(QrCodeValue, 'qr', _('QR code'), ('QR code to configure fwknopd Android application.'));
o = s.option(form.Value, 'SOURCE', 'SOURCE', _('The source address from which the SPA packet will be accepted. The string “ANY” is \
also accepted if a valid SPA packet should be honored from any source IP. \
trigger: _('WiFi signal quality (service: rssileds)'),
kernel: false,
addFormOptions(s){
- var o;
+ let o;
o = s.option(widgets.DeviceSelect, '_rssi_iface', _('Device'));
o.rmempty = true;
trigger: _('Switch support (kernel: switch0)'),
kernel: true,
addFormOptions(s){
- var o;
+ let o;
o = s.option(form.Value, 'port_mask', _('Switch Port Mask'));
o.modalonly = true;
trigger: _('Switch support (kernel: switch1)'),
kernel: true,
addFormOptions(s){
- var o;
+ let o;
o = s.option(form.Value, 'port_mask', _('Switch Port Mask'));
o.modalonly = true;
method: 'getUSBDevices',
expect: { 'ports': [] }
});
-
+
return baseclass.extend({
trigger: _('USB (kernel: usbport)'),
description: _('This LED trigger can be used for signalling to the user a presence of USB device in a given port.'),
kernel: true,
addFormOptions(s){
- var o;
+ let o;
o = s.option(form.MultiValue, 'port', _('USB Ports'));
o.depends('trigger', 'usbport');
return Promise.all([
callUSB()
]).then(L.bind(function(usbport){
- for (var i = 0; i < usbport[0].length; i++)
+ for (let i = 0; i < usbport[0].length; i++)
o.value(usbport[0][i].port, _('Port %s').format(usbport[0][i].port));
},this));
};
o.cfgvalue = function(section_id) {
- var ports = [],
- value = uci.get('system', section_id, 'port');
+ const ports = [];
+ let value = uci.get('system', section_id, 'port');
if (!Array.isArray(value))
value = String(value || '').split(/\s+/);
- for (var i = 0; i < value.length; i++)
+ for (let i = 0; i < value.length; i++)
if (value[i].match(/^(\d+)-(\d+)$/))
- ports.push('usb%d-port%d'.format(Regexp.$1, Regexp.$2));
+ ports.push('usb%d-port%d'.format(RegExp.$1, RegExp.$2));
else
ports.push(value[i]);
'require tools.widgets as widgets';
return view.extend({
- load: function() {
+ load() {
return Promise.all([
network.getDevices(),
]);
},
- render: function(data) {
- var netDevs = data[0];
+ render([netDevs]) {
let m, s, o;
m = new form.Map('libreswan', _('IPSec Global Settings'));
o = s.option(form.Value, 'listen', _('Listen Address'),
_('IP address to listen on, default depends on Listen Interface'));
o.datatype = 'ip4addr';
- for (var i = 0; i < netDevs.length; i++) {
- var addrs = netDevs[i].getIPAddrs();
- for (var j = 0; j < addrs.length; j++) {
- o.value(addrs[j].split('/')[0]);
+ for (let nd of netDevs) {
+ var addrs = nd.getIPAddrs();
+ for (let ad of addrs) {
+ o.value(ad.split('/')[0]);
}
}
o.depends({ 'listen_interface' : '' });
return view.extend({
render: function() {
- var table =
+ const table =
E('table', { 'class': 'table lases' }, [
E('tr', { 'class': 'tr table-titles' }, [
E('th', { 'class': 'th' }, _('Name')),
poll.add(function() {
return callLibreswanStatus().then(function(tunnelsInfo) {
- var tunnels = Array.isArray(tunnelsInfo.tunnels) ? tunnelsInfo.tunnels : [];
+ const tunnels = Array.isArray(tunnelsInfo.tunnels) ? tunnelsInfo.tunnels : [];
cbi_update_table(table,
tunnels.map(function(tunnel) {
'require uci';
return view.extend({
- render: function() {
+ render() {
let m, s, o;
m = new form.Map('libreswan', _('IPSec Proposals'));
s.addbtntitle = _('Add Proposal');
s.renderSectionAdd = function(extra_class) {
- var el = form.GridSection.prototype.renderSectionAdd.apply(this, arguments),
+ const el = form.GridSection.prototype.renderSectionAdd.apply(this, arguments),
nameEl = el.querySelector('.cbi-section-create-name');
ui.addValidator(nameEl, 'uciname', true, function(v) {
let sections = [
}
return view.extend({
- load: function() {
+ load() {
return Promise.all([
network.getDevices(),
uci.load('libreswan'),
]);
},
- render: function(data) {
- var netDevs = data[0];
+ render([netDevs]) {
let m, s, o;
- var proposals;
- proposals = uci.sections('libreswan', 'crypto_proposal');
+ let proposals = uci.sections('libreswan', 'crypto_proposal');
if (proposals == '') {
ui.addNotification(null, E('p', _('Proposals must be configured for Tunnels')));
return;
s.addbtntitle = _('Add Tunnel');
s.renderSectionAdd = function(extra_class) {
- var el = form.GridSection.prototype.renderSectionAdd.apply(this, arguments),
- nameEl = el.querySelector('.cbi-section-create-name');
+ const el = form.GridSection.prototype.renderSectionAdd.apply(this, arguments);
+ const nameEl = el.querySelector('.cbi-section-create-name');
ui.addValidator(nameEl, 'uciname', true, function(v) {
let sections = [
...uci.sections('libreswan', 'crypto_proposal'),
o = s.taboption('general', form.DynamicList, 'leftsubnets', _('Local Subnets'));
o.datatype = 'ipaddr';
- for (var i = 0; i < netDevs.length; i++) {
- var addrs = netDevs[i].getIPAddrs();
- for (var j = 0; j < addrs.length; j++) {
- var subnet = calculateNetwork(addrs[j].split('/')[0], addrs[j].split('/')[1]);
+ for (let nd of netDevs) {
+ const addrs = nd.getIPAddrs();
+ for (let ad of addrs) {
+ const subnet = calculateNetwork(ad.split('/')[0], ad.split('/')[1]);
if (subnet) {
o.value(subnet);
}
o.modalonly = true;
o = s.taboption('advanced', form.MultiValue, 'ike', _('Phase1 Proposals'));
- for (var i = 0; i < proposals.length; i++) {
- o.value(proposals[i]['.name']);
+ for (let prop of proposals) {
+ o.value(prop['.name']);
}
o.modalonly = true;
o.optional = false;
o = s.taboption('advanced', form.MultiValue, 'phase2alg', _('Phase2 Proposals'));
- for (var i = 0; i < proposals.length; i++) {
- o.value(proposals[i]['.name']);
+ for (let prop of proposals) {
+ o.value(prop['.name']);
}
o.modalonly = true;
o.optional = true;
o.modalonly = true;
- var interfaces = uci.sections('network', 'interface');
+ let interfaces = uci.sections('network', 'interface');
o = s.taboption('advanced', form.ListValue, 'interface', _('Tunnel Interface'),
_('Lists XFRM interfaces in format "ipsecN", N denotes ifid of xfrm interface') + '<br>' +
_('Lists VTI interfaces configured with ikey and okey'));
if (!value) return true;
let valid = _('valid syntax: %f .. %f [mf]').format(min_alt, max_alt);
valid = (parseFloat(value) >= min_alt && parseFloat(value) <= max_alt) ?
- /^-?\d+(?:\.\d+)?\ [mf]$/.test(value) ? true : valid : valid;
+ /^-?\d+(?:\.\d+)? [mf]$/.test(value) ? true : valid : valid;
return valid;
}
o.load = function(section_id, value) {
expect: {}
});
-var dataMap = {
+const dataMap = {
local: {
localChassis: null,
},
};
return L.view.extend({
- __init__: function() {
+ __init__() {
this.super('__init__', arguments);
this.rowsUnfolded = {};
]);
// Inject CSS
- var head = document.getElementsByTagName('head')[0];
- var css = E('link', { 'href':
+ const head = document.getElementsByTagName('head')[0];
+ const css = E('link', { 'href':
L.resource('lldpd/lldpd.css')
+ '?v=#PKG_VERSION', 'rel': 'stylesheet' });
head.appendChild(css);
},
- load: function() {
+ load() {
return Promise.all([
L.resolveDefault(callLLDPStatus(), {}),
lldpd.init(),
},
/** @private */
- renderParam: function(param, value) {
+ renderParam(param, value) {
if (typeof value === 'undefined')
return '';
},
/** @private */
- renderAge: function(v) {
+ renderAge(v) {
if (typeof v === 'undefined')
return "–";
},
/** @private */
- renderIdType: function(v) {
+ renderIdType(v) {
if (typeof v === 'undefined')
return "–";
},
/** @private */
- renderProtocol: function(v) {
+ renderProtocol(v) {
if (typeof v === 'undefined' || v == 'unknown')
return "–";
},
/** @private */
- renderAdminStatus: function(status) {
+ renderAdminStatus(status) {
if ((typeof status === 'undefined') || !Array.isArray(status))
return '–';
},
/** @private */
- renderNumber: function(v) {
+ renderNumber(v) {
if (parseInt(v))
return v;
},
/** @private */
- renderPort: function(port) {
+ renderPort(port) {
const portData = port?.port?.[0];
const descrValue = portData?.descr?.[0]?.value;
const idValue = portData?.id?.[0]?.value;
},
/** @private */
- renderPortParamTableShort: function(port) {
- var items = [];
+ renderPortParamTableShort(port) {
+ const items = [];
items.push(this.renderParam(_('Name'), port.name));
items.push(this.renderParam(_('Age'), this.renderAge(port.age)));
},
/** @private */
- renderPortParamTable: function(port, only_id_and_ttl) {
+ renderPortParamTable(port, only_id_and_ttl) {
const items = [];
if (!only_id_and_ttl) {
},
/** @private */
- renderChassis: function(ch) {
+ renderChassis(ch) {
const nameValue = ch?.name?.[0]?.value;
const descrValue = ch?.descr?.[0]?.value;
const idValue = ch?.id?.[0]?.value;
},
/** @private */
- renderChassisParamTable: function(ch) {
+ renderChassisParamTable(ch) {
const items = [];
// Add name and description if available
},
/** @private */
- getFoldingImage: function(unfolded) {
+ getFoldingImage(unfolded) {
return L.resource('lldpd/details_' +
(unfolded ? 'hide' : 'show') + '.svg');
},
/** @private */
- generateRowId: function(str) {
+ generateRowId(str) {
return str.replace(/[^a-z0-9]/gi, '-');
},
/** @private */
- handleToggleFoldingRow: function(row, row_id) {
- var e_img = row.querySelector('img');
- var e_folded = row.querySelectorAll('.lldpd-folded');
- var e_unfolded = row.querySelectorAll('.lldpd-unfolded');
+ handleToggleFoldingRow(row, row_id) {
+ const e_img = row.querySelector('img');
+ const e_folded = row.querySelectorAll('.lldpd-folded');
+ const e_unfolded = row.querySelectorAll('.lldpd-unfolded');
if (e_folded.length != e_unfolded.length)
return;
- var do_unfold = (e_folded[0].style.display !== 'none');
+ const do_unfold = (e_folded[0].style.display !== 'none');
this.rowsUnfolded[row_id] = do_unfold;
- for (var i = 0; i < e_folded.length; i++)
+ for (let i = 0; i < e_folded.length; i++)
{
if (do_unfold)
{
},
/** @private */
- makeFoldingTableRow: function(row, unfolded) {
+ makeFoldingTableRow(row, unfolded) {
//
// row[0] - row id
// row[1] - contents for first cell in row
for (let i = 1; i < row.length; i++) {
if (i == 1) {
// Fold/unfold image appears only in first column
- var dImg = E('div', { 'style': 'padding: 0 8px 0 0;' }, [
+ const dImg = E('div', { 'style': 'padding: 0 8px 0 0;' }, [
E('img', { 'width': '16px', 'src': this.getFoldingImage(unfolded) }),
]);
}
},
/** @private */
- makeNeighborsTableRow: function(obj) {
+ makeNeighborsTableRow(obj) {
obj.name = obj?.name ?? 'Unknown';
let new_id = `${obj.name}-${obj.rid}`;
},
/** @private */
- renderInterfaceProtocols: function(iface, neighbors) {
+ renderInterfaceProtocols(iface, neighbors) {
const ifaceName = iface?.name;
const interfaces = neighbors?.lldp?.[0]?.interface;
},
/** @private */
- makeStatisticsTableRow: function(sobj, iobj, neighbors) {
+ makeStatisticsTableRow(sobj, iobj, neighbors) {
const row_id = this.generateRowId(iobj.name);
return this.makeFoldingTableRow([
},
/** @private */
- updateTable: function(table, data, placeholder) {
- var target = isElem(table) ? table : document.querySelector(table);
+ updateTable(table, data, placeholder) {
+ const target = isElem(table) ? table : document.querySelector(table);
if (!isElem(target))
return;
target.querySelectorAll(
'.tr.table-titles, .cbi-section-table-titles').forEach(L.bind(function(thead) {
- var titles = [];
+ const titles = [];
thead.querySelectorAll('.th').forEach(function(th) {
titles.push(th);
});
if (Array.isArray(data)) {
- var n = 0, rows = target.querySelectorAll('.tr');
+ let n = 0, rows = target.querySelectorAll('.tr');
data.forEach(L.bind(function(row) {
- var id = row[0];
- var trow = E('div', { 'class': 'tr', 'click': L.bind(function(ev) {
+ let id = row[0];
+ const trow = E('div', { 'class': 'tr', 'click': L.bind(function(ev) {
this.handleToggleFoldingRow(ev.currentTarget, id);
// lldpd_folding_toggle(ev.currentTarget, id);
}, this) });
- for (var i = 0; i < titles.length; i++) {
- var text = (titles[i].innerText || '').trim();
- var td = trow.appendChild(E('div', {
+ for (let i = 0; i < titles.length; i++) {
+ const text = (titles[i].innerText || '').trim();
+ const td = trow.appendChild(E('div', {
'class': titles[i].className,
'data-title': (text !== '') ? text : null
}, row[i + 1] || ''));
target.removeChild(rows[n]);
if (placeholder && target.firstElementChild === target.lastElementChild) {
- var trow = target.appendChild(
+ const trow = target.appendChild(
E('div', { 'class': 'tr placeholder' }));
- var td = trow.appendChild(
+ const td = trow.appendChild(
E('div', { 'class': 'center ' + titles[0].className }, placeholder));
td.classList.remove('th');
thead.parentNode.querySelectorAll('.tr, .cbi-section-table-row').forEach(function(trow) {
if (trow !== thead) {
- var n = 0;
+ let n = 0;
trow.querySelectorAll('.th, .td').forEach(function(td) {
if (n < titles.length) {
- var text = (titles[n++].innerText || '').trim();
+ const text = (titles[n++].innerText || '').trim();
if (text !== '')
td.setAttribute('data-title', text);
}
},
/** @private */
- startPolling: function() {
+ startPolling() {
poll.add(L.bind(function() {
return callLLDPStatus().then(L.bind(function(data) {
this.renderData(data);
},
/** @private */
- renderDataLocalChassis: function(data) {
+ renderDataLocalChassis(data) {
const chassis = data?.['local-chassis']?.[0]?.chassis?.[0]?.name;
if (chassis)
},
/** @private */
- renderDataNeighbors: function(neighbors) {
+ renderDataNeighbors(neighbors) {
const ifaces = neighbors?.lldp?.[0]?.interface;
return ifaces ? ifaces.map(iface => this.makeNeighborsTableRow(iface)) : [];
},
/** @private */
- renderDataStatistics: function(statistics, interfaces, neighbors) {
+ renderDataStatistics(statistics, interfaces, neighbors) {
const sifaces = statistics?.lldp?.[0]?.interface;
const ifaces = interfaces?.lldp?.[0]?.interface;
},
/** @private */
- renderData: function(data) {
- var r;
+ renderData(data) {
+ let r;
r = this.renderDataLocalChassis(data.chassis);
dom.content(document.getElementById('lldpd-local-chassis'), r);
_('No data to display'));
},
- render: function(data) {
- var m, s, ss, o;
+ render(data) {
+ let m, s, ss, o;
m = new form.JSONMap(dataMap,
_('LLDP Status'),
'require uci';
return view.extend({
- load: function() {
+ load() {
return Promise.all([
uci.load('basicstation')
]);
},
- render: function(data) {
- var m, s, o, options;
+ render() {
+ let m, s, o, options;
/* Advanced Settings */
m = new form.Map('basicstation', _('Advanced Settings'));
o = s.option(form.ListValue, 'useRssiTcomp', _('RSSI Tcomp'),
_('RSSI Tcomp object to be used for this RF configuration'));
options = uci.sections('basicstation', 'rssitcomp')
- for (var i = 0; i < options.length; i++) {
- var value = options[i]['.name'];
- o.value(value);
+ for (let opt of options) {
+ o.value(opt['.name']);
}
o.default = 'std';
o = s.option(form.DynamicList, 'usedBy', _('Used By'),
_('RF configurations that use this tx gain object'));
options = uci.sections('basicstation', 'rfconf');
- for (var i = 0; i < options.length; i++) {
- var value = options[i]['.name'];
- o.value(value);
+ for (let opt of options) {
+ o.value(opt['.name']);
}
return m.render();
'require tools.widgets as widgets';
return view.extend({
- load: function() {
+ load() {
return Promise.all([
uci.load('basicstation')
]);
},
- render: function(data) {
+ render() {
let m, s, o;
/* General Settings */
o.value('1', 'Radio 1');
o.default = '0';
- var options = uci.sections('basicstation', 'rfconf');
+ let options = uci.sections('basicstation', 'rfconf');
o = s.option(form.ListValue, 'radio0', _('Radio 0'),
_('RF configuration for Radio 0'));
- for (var i = 0; i < options.length; i++) {
- var value = options[i]['.name'];
- o.value(value);
+ for (let opt of options) {
+ o.value(opt['.name']);
}
o.default = 'rfconf0';
o = s.option(form.ListValue, 'radio1', _('Radio 1'),
_('RF configuration for Radio 1'));
- for (var i = 0; i < options.length; i++) {
- var value = options[i]['.name'];
- o.value(value);
+ for (let opt of options) {
+ o.value(opt['.name']);
}
o.default = 'rfconf1';
'require fs';
'require ui';
-var isReadonlyView = !L.hasViewPermission() || null;
+const isReadonlyView = !L.hasViewPermission() || null;
return view.extend({
- load: function() {
+ load() {
return L.resolveDefault(fs.read('/etc/mwan3.user'), '');
},
- handleSave: function(ev) {
- var value = (document.querySelector('textarea').value || '').trim().replace(/\r\n/g, '\n') + '\n';
+ handleSave(ev) {
+ const value = (document.querySelector('textarea').value || '').trim().replace(/\r\n/g, '\n') + '\n';
return fs.write('/etc/mwan3.user', value).then(function(rc) {
document.querySelector('textarea').value = value;
});
},
- render: function(mwan3user) {
+ render(mwan3user) {
return E([
E('h2', _('MultiWAN Manager - Notify')),
E('p', { 'class': 'cbi-section-descr' },
- _('This section allows you to modify the content of \"/etc/mwan3.user\".') + '<br/>' +
+ _('This section allows you to modify the content of "/etc/mwan3.user".') + '<br/>' +
_('The file is also preserved during sysupgrade.') + '<br/>' +
'<br />' +
_('Notes:') + '<br />' +
_('* %s: Is called by netifd and mwan3track').format('ifdown') + '<br />' +
_('* %s: Is only called by mwan3track if tracking was successful').format('connected') + '<br />' +
_('* %s: Is only called by mwan3track if tracking has failed').format('disonnected') + '<br />' +
- _('%s: Name of the interface which went up or down (e.g. \"wan\" or \"wwan\")').format('$INTERFACE') + '<br />' +
- _('%s: Name of Physical device which interface went up or down (e.g. \"eth0\" or \"wwan0\")').format('$DEVICE') + '<br />'),
+ _('%s: Name of the interface which went up or down (e.g. "wan" or "wwan")').format('$INTERFACE') + '<br />' +
+ _('%s: Name of Physical device which interface went up or down (e.g. "eth0" or "wwan0")').format('$DEVICE') + '<br />'),
E('p', {}, E('textarea', { 'style': 'width:100%', 'rows': 10, 'disabled': isReadonlyView }, [ mwan3user != null ? mwan3user : '' ]))
]);
},
/* This name length error check can likely be removed when mwan3 migrates to nftables */
s.renderSectionAdd = function(extra_class) {
- var el = form.GridSection.prototype.renderSectionAdd.apply(this, arguments),
- nameEl = el.querySelector('.cbi-section-create-name');
+ const el = form.GridSection.prototype.renderSectionAdd.apply(this, arguments);
+ const nameEl = el.querySelector('.cbi-section-create-name');
ui.addValidator(nameEl, 'uciname', true, function(v) {
let sections = [
...uci.sections('mwan3', 'interface'),
o.value('esp');
o = s.option(form.Value, 'src_ip', _('Source address'),
- _('Supports CIDR notation (eg \"192.168.100.0/24\") without quotes'));
+ _('Supports CIDR notation (eg "192.168.100.0/24") without quotes'));
o.datatype = 'ipaddr';
o = s.option(form.Value, 'src_port', _('Source port'),
- _('May be entered as a single or multiple port(s) (eg \"22\" or \"80,443\") or as a portrange (eg \"1024:2048\") without quotes'));
+ _('May be entered as a single or multiple port(s) (eg "22" or "80,443") or as a portrange (eg "1024:2048") without quotes'));
o.depends('proto', 'tcp');
o.depends('proto', 'udp');
o = s.option(form.Value, 'dest_ip', _('Destination address'),
- _('Supports CIDR notation (eg \"192.168.100.0/24\") without quotes'));
+ _('Supports CIDR notation (eg "192.168.100.0/24") without quotes'));
o.datatype = 'ipaddr';
o = s.option(form.Value, 'dest_port', _('Destination port'),
- _('May be entered as a single or multiple port(s) (eg \"22\" or \"80,443\") or as a portrange (eg \"1024:2048\") without quotes'));
+ _('May be entered as a single or multiple port(s) (eg "22" or "80,443") or as a portrange (eg "1024:2048") without quotes'));
o.depends('proto', 'tcp');
o.depends('proto', 'udp');
o.depends('sticky', '1');
o = s.option(form.Value, 'ipset', _('IPset'),
- _('Name of IPset rule. Requires IPset rule in /etc/dnsmasq.conf (eg \"ipset=/youtube.com/youtube\")'));
+ _('Name of IPset rule. Requires IPset rule in /etc/dnsmasq.conf (eg "ipset=/youtube.com/youtube")'));
o.value('', _('-- Please choose --'));
- var ipsets = data[0].split(/\n/);
- for (var i = 0; i < ipsets.length; i++) {
- if (ipsets[i].length > 0)
- o.value(ipsets[i]);
+ let ipsets = data[0].split(/\n/);
+ for (let ips of ipsets) {
+ if (ips.length > 0)
+ o.value(ips);
}
o.modalonly = true;
o.modalonly = true;
o = s.option(form.ListValue, 'use_policy', _('Policy assigned'));
- var options = uci.sections('mwan3', 'policy')
- for (var i = 0; i < options.length; i++) {
- var value = options[i]['.name'];
- o.value(value);
+ let options = uci.sections('mwan3', 'policy')
+ for (let opt of options) {
+ o.value(opt['.name']);
}
o.value('unreachable', _('unreachable (reject)'));
o.value('blackhole', _('blackhole (drop)'));
expect: { '': {} }
});
-var chartRegistry = {},
- trafficPeriods = [],
- trafficData = { columns: [], data: [] },
- hostNames = {},
- hostInfo = {},
- ouiData = [];
+const chartRegistry = {};
+let trafficPeriods = [];
+let trafficData = { columns: [], data: [] };
+let hostNames = {};
+const hostInfo = {};
+let ouiData = [];
return view.extend({
- load: function() {
+ load() {
return Promise.all([
this.loadHosts(),
this.loadPeriods(),
]);
},
- loadHosts: function() {
+ loadHosts() {
return L.resolveDefault(network.getHostHints()).then(function(res) {
if (res) {
- var hints = res.getMACHints();
+ const hints = res.getMACHints();
- for (var i = 0; i < hints.length; i++) {
- hostInfo[hints[i][0]] = {
- name: res.getHostnameByMACAddr(hints[i][0]),
- ipv6: res.getIP6AddrByMACAddr(hints[i][0]),
- ipv4: res.getIPAddrByMACAddr(hints[i][0])
+ for (let hint of hints) {
+ hostInfo[hint[0]] = {
+ name: res.getHostnameByMACAddr(hint[0]),
+ ipv6: res.getIP6AddrByMACAddr(hint[0]),
+ ipv4: res.getIPAddrByMACAddr(hint[0])
};
}
}
});
},
- loadOUI: function() {
- var url = 'https://raw.githubusercontent.com/jow-/oui-database/master/oui.json';
+ loadOUI() {
+ const url = 'https://raw.githubusercontent.com/jow-/oui-database/master/oui.json';
return L.resolveDefault(request.get(url, { cache: true })).then(function(res) {
res = res ? res.json() : [];
});
},
- loadPeriods: function() {
+ loadPeriods() {
return L.resolveDefault(fs.exec_direct('/usr/libexec/nlbwmon-action', [ 'periods' ], 'json')).then(function(res) {
if (L.isObject(res) && Array.isArray(res.periods))
trafficPeriods = res.periods;
});
},
- loadData: function(period) {
- var args = [ 'download', '-g', 'family,mac,ip,layer7', '-o', '-rx_bytes,-tx_bytes' ];
+ loadData(period) {
+ const args = [ 'download', '-g', 'family,mac,ip,layer7', '-o', '-rx_bytes,-tx_bytes' ];
if (period)
args.push('-t', period);
trafficData = res;
- var addrs = this.query(null, [ 'ip' ], null),
- ipAddrs = [];
+ const addrs = this.query(null, [ 'ip' ], null);
+ const ipAddrs = [];
- for (var i = 0; i < addrs.length; i++)
- if (ipAddrs.indexOf(addrs[i].ip) < 0)
- ipAddrs.push(addrs[i].ip);
+ for (let addr of addrs)
+ if (ipAddrs.indexOf(addr.ip) < 0)
+ ipAddrs.push(addr.ip);
if (ipAddrs.length)
return L.resolveDefault(callNetworkRrdnsLookup(ipAddrs, 1000, 1000), {}).then(function(res) {
});
},
- off: function(elem) {
- var val = [0, 0];
+ off(elem) {
+ const val = [0, 0];
do {
if (!isNaN(elem.offsetLeft) && !isNaN(elem.offsetTop)) {
val[0] += elem.offsetLeft;
return val;
},
- kpi: function(id, val1, val2, val3) {
- var e = L.dom.elem(id) ? id : document.getElementById(id);
+ kpi(id, val1, val2, val3) {
+ const e = L.dom.elem(id) ? id : document.getElementById(id);
if (val1 && val2 && val3)
e.innerHTML = _('%s, %s and %s').format(val1, val2, val3);
e.parentNode.style.display = val1 ? 'list-item' : '';
},
- pie: function(id, data) {
- var total = data.reduce(function(n, d) { return n + d.value }, 0);
+ pie(id, data) {
+ const total = data.reduce(function(n, d) { return n + d.value }, 0);
data.sort(function(a, b) { return b.value - a.value });
label: [ _('no traffic') ]
}];
- for (var i = 0; i < data.length; i++) {
+ for (let i = 0; i < data.length; i++) {
if (!data[i].color) {
- var hue = 120 / (data.length-1) * i;
+ const hue = 120 / (data.length-1) * i;
data[i].color = 'hsl(%u, 80%%, 50%%)'.format(hue);
data[i].label.push(hue);
}
}
- var node = L.dom.elem(id) ? id : document.getElementById(id),
- key = L.dom.elem(id) ? id.id : id,
- ctx = node.getContext('2d');
+ const node = L.dom.elem(id) ? id : document.getElementById(id);
+ const key = L.dom.elem(id) ? id.id : id;
+ const ctx = node.getContext('2d');
if (chartRegistry.hasOwnProperty(key))
chartRegistry[key].destroy();
return chartRegistry[key];
},
- oui: function(mac) {
- var m, l = 0, r = ouiData.length / 3 - 1;
- var mac1 = parseInt(mac.replace(/[^a-fA-F0-9]/g, ''), 16);
+ oui(mac) {
+ let m, l = 0, r = ouiData.length / 3 - 1;
+ const mac1 = parseInt(mac.replace(/[^a-fA-F0-9]/g, ''), 16);
while (l <= r) {
m = l + Math.floor((r - l) / 2);
- var mask = (0xffffffffffff -
+ const mask = (0xffffffffffff -
(Math.pow(2, 48 - ouiData[m * 3 + 1]) - 1));
- var mac1_hi = ((mac1 / 0x10000) & (mask / 0x10000)) >>> 0;
- var mac1_lo = ((mac1 & 0xffff) & (mask & 0xffff)) >>> 0;
+ const mac1_hi = ((mac1 / 0x10000) & (mask / 0x10000)) >>> 0;
+ const mac1_lo = ((mac1 & 0xffff) & (mask & 0xffff)) >>> 0;
- var mac2 = parseInt(ouiData[m * 3], 16);
- var mac2_hi = (mac2 / 0x10000) >>> 0;
- var mac2_lo = (mac2 & 0xffff) >>> 0;
+ const mac2 = parseInt(ouiData[m * 3], 16);
+ const mac2_hi = (mac2 / 0x10000) >>> 0;
+ const mac2_lo = (mac2 & 0xffff) >>> 0;
if (mac1_hi === mac2_hi && mac1_lo === mac2_lo)
return ouiData[m * 3 + 2];
return null;
},
- query: function(filter, group, order) {
- var keys = [], columns = {}, records = {}, result = [];
+ query(filter, group, order) {
+ const columns = {}, records = {}, result = [];
if (typeof(group) !== 'function' && typeof(group) !== 'object')
group = ['mac'];
- for (var i = 0; i < trafficData.columns.length; i++)
+ for (let i = 0; i < trafficData.columns.length; i++)
columns[trafficData.columns[i]] = i;
- for (var i = 0; i < trafficData.data.length; i++) {
- var record = trafficData.data[i];
+ for (let record of trafficData.data) {
if (typeof(filter) === 'function' && filter(columns, record) !== true)
continue;
- var key;
+ let key;
if (typeof(group) === 'function') {
key = group(columns, record);
else {
key = [];
- for (var j = 0; j < group.length; j++)
- if (columns.hasOwnProperty(group[j]))
- key.push(record[columns[group[j]]]);
+ for (let g of group)
+ if (columns.hasOwnProperty(g))
+ key.push(record[columns[g]]);
key = key.join(',');
}
if (!records.hasOwnProperty(key)) {
- var rec = {};
+ const rec = {};
- for (var col in columns)
+ for (let col in columns)
rec[col] = record[columns[col]];
records[key] = rec;
return result;
},
- renderPeriods: function() {
+ renderPeriods() {
if (!trafficPeriods.length)
return E([]);
- var choices = {},
- keys = [];
+ const choices = {};
+ const keys = [];
- for (var e, i = trafficPeriods.length - 1; e = trafficPeriods[i]; i--) {
- var ymd1 = e.split(/-/);
- var d1 = new Date(+ymd1[0], +ymd1[1] - 1, +ymd1[2]);
- var ymd2, d2, pd;
+ for (let i = trafficPeriods.length - 1; i >= 0; i--) {
+ const e = trafficPeriods[i];
- if (i) {
+ const ymd1 = e.split(/-/);
+ const d1 = new Date(+ymd1[0], +ymd1[1] - 1, +ymd1[2]);
+ let ymd2, d2, pd;
+
+ if (i > 0) {
ymd2 = trafficPeriods[i - 1].split(/-/);
d2 = new Date(+ymd2[0], +ymd2[1] - 1, +ymd2[2]);
d2.setDate(d2.getDate() - 1);
);
}
- var dropdown = new ui.Dropdown('-', choices, { sort: keys, optional: false }).render();
+ const dropdown = new ui.Dropdown('-', choices, { sort: keys, optional: false }).render();
dropdown.addEventListener('cbi-dropdown-change', ui.createHandlerFn(this, function(ev) {
ui.hideTooltip(ev);
- var period = ev.detail.value.value != '-' ? ev.detail.value.value : null;
+ const period = ev.detail.value.value != '-' ? ev.detail.value.value : null;
return this.loadData(period).then(L.bind(function() {
this.renderHostData();
]);
},
- formatHostname: function(dns) {
+ formatHostname(dns) {
if (dns === undefined || dns === null || dns === '')
return '-';
return '%h'.format(dns);
},
- renderHostData: function() {
- var trafData = [], connData = [];
- var rx_total = 0, tx_total = 0, conn_total = 0;
+ renderHostData() {
+ const trafData = [], connData = [];
+ let rx_total = 0, tx_total = 0, conn_total = 0;
- var hostData = this.query(
+ const hostData = this.query(
function(c, r) {
return (r[c.rx_bytes] > 0 || r[c.tx_bytes] > 0);
},
}
);
- var rows = [];
+ const rows = [];
- for (var i = 0; i < hostData.length; i++) {
- var rec = hostData[i],
- mac = rec.mac.toUpperCase(),
- key = (mac !== '00:00:00:00:00:00') ? mac : rec.ip,
- dns = hostInfo[mac] ? hostInfo[mac].name : null;
+ for (let rec of hostData) {
+ const mac = rec.mac.toUpperCase();
+ const key = (mac !== '00:00:00:00:00:00') ? mac : rec.ip;
+ const dns = hostInfo[mac] ? hostInfo[mac].name : null;
- var cell = E('div', this.formatHostname(dns));
+ const cell = E('div', this.formatHostname(dns));
rows.push([
cell,
this.kpi('host-total', '%u'.format(hostData.length));
},
- renderLayer7Data: function() {
- var rxData = [], txData = [];
- var topConn = [[0],[0],[0]], topRx = [[0],[0],[0]], topTx = [[0],[0],[0]];
+ renderLayer7Data() {
+ const rxData = [], txData = [];
+ const topConn = [[0],[0],[0]], topRx = [[0],[0],[0]], topTx = [[0],[0],[0]];
- var layer7Data = this.query(
+ const layer7Data = this.query(
null, ['layer7'],
function(r1, r2) {
return ((r2.rx_bytes + r2.tx_bytes) - (r1.rx_bytes + r1.tx_bytes));
}
);
- var rows = [];
+ const rows = [];
- for (var i = 0, c = 0; i < layer7Data.length; i++) {
- var rec = layer7Data[i],
- cell = E('div', rec.layer7 || _('other'));
+ for (let rec of layer7Data) {
+ const cell = E('div', rec.layer7 || _('other'));
rows.push([
cell,
this.kpi('layer7-most-conn', topConn[0][1], topConn[1][1], topConn[2][1]);
},
- renderIPv6Data: function() {
- var col = { },
- rx4_total = 0,
- tx4_total = 0,
- rx6_total = 0,
- tx6_total = 0,
- v4_total = 0,
- v6_total = 0,
- ds_total = 0,
- families = { },
- records = { };
-
- var ipv6Data = this.query(
+ renderIPv6Data() {
+ let rx4_total = 0;
+ let tx4_total = 0;
+ let rx6_total = 0;
+ let tx6_total = 0;
+ let v4_total = 0;
+ let v6_total = 0;
+ let ds_total = 0;
+ const families = { };
+ const records = { };
+
+ const ipv6Data = this.query(
null, ['family', 'mac'],
function(r1, r2) {
return ((r2.rx_bytes + r2.tx_bytes) - (r1.rx_bytes + r1.tx_bytes));
}
);
- for (var i = 0, c = 0; i < ipv6Data.length; i++) {
- var rec = ipv6Data[i],
- mac = rec.mac.toUpperCase(),
- ip = rec.ip,
- fam = families[mac] || 0,
- recs = records[mac] || {};
+ for (let rec of ipv6Data) {
+ const mac = rec.mac.toUpperCase();
+ let fam = families[mac] || 0;
+ const recs = records[mac] || {};
if (rec.family == 4) {
rx4_total += rec.rx_bytes;
families[mac] = fam;
}
- for (var mac in families) {
+ for (let mac in families) {
switch (families[mac])
{
case 3:
}
}
- var rows = [];
+ const rows = [];
- for (var mac in records) {
+ for (let mac in records) {
if (mac === '00:00:00:00:00:00')
continue;
- var dns = hostInfo[mac] ? hostInfo[mac].name : null,
- rec4 = records[mac][4],
- rec6 = records[mac][6];
+ const dns = hostInfo[mac] ? hostInfo[mac].name : null;
+ const rec4 = records[mac][4];
+ const rec6 = records[mac][6];
rows.push([
this.formatHostname(dns),
cbi_update_table('#ipv6-data', rows, E('em', _('No data recorded yet.')));
- var shareData = [], hostsData = [];
+ const shareData = [], hostsData = [];
if (rx4_total > 0 || tx4_total > 0)
shareData.push({
this.kpi('ipv6-tx', '%1024.2mB'.format(tx6_total));
},
- renderHostDetail: function(node, tooltip) {
- var key = node.getAttribute('href').substr(1),
- col = node.getAttribute('data-col'),
- label = node.getAttribute('data-tooltip');
+ renderHostDetail(node, tooltip) {
+ const key = node.getAttribute('href').substr(1);
+ const col = node.getAttribute('data-col');
+ const label = node.getAttribute('data-tooltip');
- var detailData = this.query(
+ const detailData = this.query(
function(c, r) {
return ((r[c.mac] === key || r[c.ip] === key) &&
(r[c.rx_bytes] > 0 || r[c.tx_bytes] > 0));
}
);
- var rxData = [], txData = [];
+ const rxData = [], txData = [];
dom.content(tooltip, [
E('div', { 'class': 'head' }, [
])
]);
- var rows = [];
+ const rows = [];
- for (var i = 0; i < detailData.length; i++) {
- var rec = detailData[i],
- cell = E('div', rec[col] || _('other'));
+ for (let rec of detailData) {
+ const cell = E('div', rec[col] || _('other'));
rows.push([
cell,
this.pie(tooltip.querySelector('#bubble-pie1'), rxData);
this.pie(tooltip.querySelector('#bubble-pie2'), txData);
- var mac = key.toUpperCase();
- var name = hostInfo.hasOwnProperty(mac) ? hostInfo[mac].name : null;
+ const mac = key.toUpperCase();
+ let name = hostInfo.hasOwnProperty(mac) ? hostInfo[mac].name : null;
if (!name)
- for (var i = 0; i < detailData.length; i++)
- if ((name = hostNames[detailData[i].ip]) !== undefined)
+ for (let dd of detailData)
+ if ((name = hostNames[dd.ip]) !== undefined)
break;
if (mac !== '00:00:00:00:00:00') {
this.kpi(tooltip.querySelector('#bubble-vendor'));
}
- var rect = node.getBoundingClientRect(), x, y;
+ const rect = node.getBoundingClientRect()
+ let x, y;
if ('ontouchstart' in window || window.innerWidth <= 992) {
- var vpHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0),
- scrollFrom = window.pageYOffset,
- scrollTo = scrollFrom + rect.top - vpHeight * 0.5,
- start = null;
+ const vpHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
+ const scrollFrom = window.pageYOffset;
+ const scrollTo = scrollFrom + rect.top - vpHeight * 0.5;
+ let start = null;
tooltip.style.top = (rect.top + rect.height + window.pageYOffset) + 'px';
tooltip.style.left = 0;
- var scrollStep = function(timestamp) {
+ const scrollStep = function(timestamp) {
if (!start)
start = timestamp;
- var duration = Math.max(timestamp - start, 1);
+ const duration = Math.max(timestamp - start, 1);
if (duration < 100) {
document.body.scrollTop = scrollFrom + (scrollTo - scrollFrom) * (duration / 100);
window.requestAnimationFrame(scrollStep);
return false;
},
- setupCharts: function() {
+ setupCharts() {
Chart.defaults.global.customTooltips = L.bind(function(tooltip) {
- var tooltipEl = document.getElementById('chartjs-tooltip');
+ let tooltipEl = document.getElementById('chartjs-tooltip');
if (!tooltipEl) {
tooltipEl = document.createElement('div');
return;
}
- var pos = this.off(tooltip.chart.canvas);
+ const pos = this.off(tooltip.chart.canvas);
tooltipEl.className = tooltip.yAlign;
tooltipEl.innerHTML = tooltip.text[0];
tooltipEl.style.left = pos[0] + tooltip.x + 'px';
tooltipEl.style.top = pos[1] + tooltip.y - tooltip.caretHeight - tooltip.caretPadding + 'px';
- var row = findParent(tooltip.text[1], '.tr'),
- hue = tooltip.text[2];
+ const row = findParent(tooltip.text[1], '.tr');
+ const hue = tooltip.text[2];
if (row && !isNaN(hue)) {
row.style.backgroundColor = 'hsl(%u, 100%%, 80%%)'.format(hue);
this.renderIPv6Data();
},
- handleDownload: function(type, group, order) {
- var args = [ 'download', '-f', type ];
+ handleDownload(type, group, order) {
+ const args = [ 'download', '-f', type ];
if (group)
args.push('-g', group);
args.push('-o', order);
return fs.exec_direct('/usr/libexec/nlbwmon-action', args, 'blob').then(function(blob) {
- var data = blob.slice(0, blob.size, (type == 'csv') ? 'text/csv' : 'application/json'),
- name = 'nlbwmon-data.%s'.format(type),
- url = window.URL.createObjectURL(data),
- link = E('a', { 'style': 'display:none', 'href': url, 'download': name });
+ const data = blob.slice(0, blob.size, (type == 'csv') ? 'text/csv' : 'application/json');
+ const name = 'nlbwmon-data.%s'.format(type);
+ const url = window.URL.createObjectURL(data);
+ const link = E('a', { 'style': 'display:none', 'href': url, 'download': name });
document.body.appendChild(link);
link.click();
});
},
- handleCommit: function() {
+ handleCommit() {
return fs.exec('/usr/libexec/nlbwmon-action', [ 'commit' ]).then(function(res) {
if (res.code != 0)
throw new Error(res.stderr || res.stdout);
});
},
- render: function() {
+ render() {
document.addEventListener('tooltip-open', L.bind(function(ev) {
this.renderHostDetail(ev.detail.target, ev.target);
}, this));
if ('ontouchstart' in window) {
document.addEventListener('touchstart', function(ev) {
- var tooltip = document.querySelector('.cbi-tooltip');
+ const tooltip = document.querySelector('.cbi-tooltip');
if (tooltip === ev.target || tooltip.contains(ev.target))
return;
});
}
- var node = E([], [
+ const node = E([], [
E('link', { 'rel': 'stylesheet', 'href': L.resource('view/nlbw.css') }),
E('script', {
'type': 'text/javascript',
});
return L.view.extend({
- load: function() {
+ load() {
return Promise.all([
L.resolveDefault(fs.read('/proc/net/ipv6_route'), null),
L.resolveDefault(fs.exec('/usr/bin/certtool', ['--hash', 'sha256', '--key-id', '--infile', '/etc/ocserv/server-cert.pem']).then(res => res.stdout), null),
]);
},
- render: function([has_ipv6, pki_hash, ca_content]) {
+ render([has_ipv6, pki_hash, ca_content]) {
pki_hash = pki_hash ? 'sha256:' + pki_hash.trim() : '';
const m = new form.Map('ocserv', _('OpenConnect VPN'));
o.default = '0';
// IPv4 Address
- o = s.taboption('general', form.Value, 'ipaddr', _('VPN <abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Network-Address'),
+ o = s.taboption('general', form.Value, 'ipaddr', _('VPN <abbr title="Internet Protocol Version 4">IPv4</abbr>-Network-Address'),
_('The IPv4 subnet address to provide to clients; this should be some private network different than the LAN addresses unless proxy ARP is enabled. Leave empty to attempt auto-configuration.'));
o.datatype = 'ip4addr';
o.default = '192.168.100.1';
// IPv4 Netmask
- o = s.taboption('general', form.Value, 'netmask', _('VPN <abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask'),
+ o = s.taboption('general', form.Value, 'netmask', _('VPN <abbr title="Internet Protocol Version 4">IPv4</abbr>-Netmask'),
_('The mask of the subnet above.'));
o.datatype = 'ip4addr';
o.default = '255.255.255.0';
// IPv6 Address (if available)
if (has_ipv6) {
- o = s.taboption('general', form.Value, 'ip6addr', _('VPN <abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Network-Address'),
+ o = s.taboption('general', form.Value, 'ip6addr', _('VPN <abbr title="Internet Protocol Version 6">IPv6</abbr>-Network-Address'),
_('The IPv6 subnet address to provide to clients; leave empty to attempt auto-configuration.') + '<br />' +
- _('<abbr title=\"Classless Inter-Domain Routing\">CIDR</abbr>-Notation: address/prefix'));
+ _('<abbr title="Classless Inter-Domain Routing">CIDR</abbr>-Notation: address/prefix'));
o.datatype = 'ip6addr';
}
return m.render();
},
- addFooter: function() {
+ addFooter() {
// Override to add custom behavior after form render
},
- handleSave: function(ev) {
+ handleSave(ev) {
return this.super('handleSave', [ev]).then(() => {
// Reload occtl after save
return L.resolveDefault(fs.exec('/usr/bin/occtl', ['reload']), null);
});
},
- handleSaveApply: function(ev) {
+ handleSaveApply(ev) {
return this.handleSave(ev).then(() => {
// Get the enable flag value
const mapNode = document.querySelector('[data-name="ocserv"]');
});
return L.view.extend({
- load: function() {
+ load() {
return Promise.all([
L.resolveDefault(fs.read('/proc/net/ipv6_route'), false),
L.resolveDefault(fs.read('/etc/ocserv/ca.pem'), ''),
]);
},
- render: function([has_ipv6, ca_content]) {
+ render([has_ipv6, ca_content]) {
const m = new form.Map('ocserv', _('OpenConnect VPN'));
o.default = '1';
// IPv4 Address
- o = s.taboption('general', form.Value, 'ipaddr', _('VPN <abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Network-Address'));
+ o = s.taboption('general', form.Value, 'ipaddr', _('VPN <abbr title="Internet Protocol Version 4">IPv4</abbr>-Network-Address'));
o.datatype = 'ip4addr';
o.default = '192.168.100.1';
// IPv4 Netmask
- o = s.taboption('general', form.Value, 'netmask', _('VPN <abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask'));
+ o = s.taboption('general', form.Value, 'netmask', _('VPN <abbr title="Internet Protocol Version 4">IPv4</abbr>-Netmask'));
o.datatype = 'ip4addr';
o.default = '255.255.255.0';
o.value('255.255.255.0');
// IPv6 Address (if available)
if (has_ipv6) {
- o = s.taboption('general', form.Value, 'ip6addr', _('VPN <abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Network-Address'),
- _('<abbr title=\"Classless Inter-Domain Routing\">CIDR</abbr>-Notation: address/prefix'));
+ o = s.taboption('general', form.Value, 'ip6addr', _('VPN <abbr title="Internet Protocol Version 6">IPv6</abbr>-Network-Address'),
+ _('<abbr title="Classless Inter-Domain Routing">CIDR</abbr>-Notation: address/prefix'));
}
// Template editor
return m.render();
},
- handleSave: function(ev) {
+ handleSave(ev) {
return this.super('handleSave', [ev]).then(() => {
// Reload occtl after save
return L.resolveDefault(fs.exec('/usr/bin/occtl', ['reload']), null);
});
},
- handleSaveApply: function(ev) {
+ handleSaveApply(ev) {
return this.handleSave(ev).then(() => {
// Get the enable flag value
const uci = L.uci;
function getServiceStatus() {
return L.resolveDefault(callServiceList('openlist'), {}).then(function (res) {
- var isRunning = false;
+ let isRunning = false;
try {
isRunning = res['openlist']['instances']['instance1']['running'];
} catch (e) { }
}
function renderStatus(isRunning, port) {
- var spanTemp = '<span style="color:%s"><strong>%s %s</strong></span>';
- var renderHTML;
+ const spanTemp = '<span style="color:%s"><strong>%s %s</strong></span>';
+ let renderHTML;
if (isRunning) {
- var button = String.format(' <a class="btn cbi-button" href="http://%s:%s" target="_blank" rel="noreferrer noopener">%s</a>',
+ const button = String.format(' <a class="btn cbi-button" href="http://%s:%s" target="_blank" rel="noreferrer noopener">%s</a>',
window.location.hostname, port, _('Open Web Interface'));
renderHTML = spanTemp.format('green', _('OpenList'), _('RUNNING')) + button;
} else {
return renderHTML;
}
-var stubValidator = {
+const stubValidator = {
factory: validation,
- apply: function(type, value, args) {
+ apply(type, value, args) {
if (value != null)
this.value = value;
return validation.types[type].apply(this, args);
},
- assert: function(condition) {
+ assert(condition) {
return !!condition;
}
};
return view.extend({
- load: function() {
+ load() {
return Promise.all([
uci.load('openlist')
]);
},
- render: function(data) {
+ render(data) {
let m, s, o;
- var webport = uci.get(data[0], 'config', 'listen_http_port') || '5244';
+ const webport = uci.get(data[0], 'config', 'listen_http_port') || '5244';
m = new form.Map('openlist', _('OpenList'),
_('A file list/WebDAV program that supports multiple storages, powered by Gin and Solidjs.') + '<br />' +
s.render = function () {
poll.add(function () {
return L.resolveDefault(getServiceStatus()).then(function (res) {
- var view = document.getElementById('service_status');
+ const view = document.getElementById('service_status');
view.innerHTML = renderStatus(res, webport);
});
});
o.placeholder = '0.0.0.0';
o.validate = function(section_id, value) {
if (section_id && value) {
- var m4 = value.match(/^([^\[\]:]+)$/),
- m6 = value.match(/^\[(.+)\]$/ );
+ const m4 = value.match(/^([^[\]:]+)$/);
+ const m6 = value.match(/^\[(.+)\]$/ );
if ((!m4 && !m6) || !stubValidator.apply('ipaddr', m4 ? m4[1] : m6[1]))
return _('Expecting: %s').format(_('valid IP address'));
'require view';
return view.extend({
- render: function() {
+ render() {
/* Thanks to luci-app-aria2 */
- var css = ' \
+ const css = ' \
#log_textarea { \
padding: 10px; \
text-align: left; \
background-color: #33ccff; \
}';
- var log_textarea = E('div', { 'id': 'log_textarea' },
+ const log_textarea = E('div', { 'id': 'log_textarea' },
E('img', {
'src': L.resource('icons/loading.svg'),
'alt': _('Loading...'),
poll.add(L.bind(function() {
return fs.read_direct('/var/run/openlist/log/openlist.log', 'text')
.then(function(res) {
- var log = E('pre', { 'wrap': 'pre' }, [
+ const log = E('pre', { 'wrap': 'pre' }, [
res.trim() || _('Log is empty.')
]);
dom.content(log_textarea, log);
}).catch(function(err) {
- var log;
+ let log;
if (err.toString().includes('NotFoundError'))
log = E('pre', { 'wrap': 'pre' }, [
'require view';
'require form';
-var desc = _(""
+const desc = _(""
+ "<p/>Note: you need a working PageKite account, or at least, your own running front end for this form to work. "
+ "Visit %s to set up a name for your "
- + "router and get a secret key for the connection."..format(`<a href='https://pagekite.net/home/'>${_('your account')}</a>`)) + '<br/>'
+ + "router and get a secret key for the connection.".format(`<a href='https://pagekite.net/home/'>${_('your account')}</a>`)) + '<br/>'
+ _("<p/><em>Note: this web configurator only supports "
+ "some very very basic uses of pagekite.</em>"
);
return view.extend({
- render: function() {
+ render() {
let m, s, o;
m = new form.Map('pagekitec', _('PageKite'), desc);
});
return view.extend({
- load: function() {
+ load() {
return Promise.all([
- network.getNetworks(),
callHostHints(),
]);
},
- render: function (loaded_promises) {
+ render ([hosts]) {
let m, s, o;
- const networks = loaded_promises[0];
- const hosts = loaded_promises[1];
m = new form.Map('qos', _('Quality of Service'),
- _('With %s you can prioritize network traffic selected by addresses, ports or services.'.format('<abbr title=\"Quality of Service\">QoS</abbr>')));
+ _('With %s you can prioritize network traffic selected by addresses, ports or services.'.format('<abbr title="Quality of Service">QoS</abbr>')));
s = m.section(form.TypedSection, 'interface', _('Interfaces'));
s.anonymous = false;
o.value(n);
});
- var ipaddrs = {};
+ let ipaddrs = {};
Object.keys(hosts).forEach(function(mac) {
L.toArray(hosts[mac].ipaddrs || hosts[mac].ipv4).forEach(function(ip) {
ipaddrs[ip] = mac;
'require rpc';
'require ui';
-var conf = 'smartdns';
+const conf = 'smartdns';
const callServiceList = rpc.declare({
object: 'service',
method: 'list',
params: ['name'],
expect: { '': {} }
});
-var pollAdded = false;
+let pollAdded = false;
function getServiceStatus() {
return L.resolveDefault(callServiceList(conf), {})
.then(function (res) {
- var is_running = false;
+ let is_running = false;
try {
is_running = res[conf]['instances']['smartdns']['running'];
} catch (e) { }
]);
}
-function smartdnsRenderStatus(res) {
- var renderHTML = "";
- var isRunning = res[0];
+function smartdnsRenderStatus(isRunning) {
+ let renderHTML = "";
- var autoSetDnsmasq = uci.get_first('smartdns', 'smartdns', 'auto_set_dnsmasq');
- var smartdnsPort = uci.get_first('smartdns', 'smartdns', 'port');
- var dnsmasqServer = uci.get_first('dhcp', 'dnsmasq', 'server');
+ const autoSetDnsmasq = uci.get_first('smartdns', 'smartdns', 'auto_set_dnsmasq');
+ const smartdnsPort = uci.get_first('smartdns', 'smartdns', 'port');
+ const dnsmasqServer = uci.get_first('dhcp', 'dnsmasq', 'server');
if (isRunning) {
renderHTML += "<span style=\"color:green;font-weight:bold\">SmartDNS - " + _("RUNNING") + "</span>";
}
if (autoSetDnsmasq === '1' && smartdnsPort != '53') {
- var matchLine = "127.0.0.1#" + smartdnsPort;
+ const matchLine = "127.0.0.1#" + smartdnsPort;
uci.unload('dhcp');
uci.load('dhcp');
}
return view.extend({
- load: function () {
+ load() {
return Promise.all([
uci.load('dhcp'),
uci.load('smartdns'),
]);
},
- render: function (stats) {
+ render(stats) {
let m, s, o;
- var ss, so;
- var servers, download_files;
+ let ss, so;
+ let servers, download_files;
m = new form.Map('smartdns', _('SmartDNS'));
m.title = _("SmartDNS Server");
s = m.section(form.NamedSection, '_status');
s.anonymous = true;
s.render = function (section_id) {
- var renderStatus = function () {
+ const renderStatus = function () {
return L.resolveDefault(smartdnsServiceStatus()).then(function (res) {
- var view = document.getElementById("service_status");
+ const view = document.getElementById("service_status");
if (view == null) {
return;
}
return true;
}
- var check_mode = value.split(",")
- for (var i = 0; i < check_mode.length; i++) {
- if (check_mode[i] == "ping") {
+ const check_mode = value.split(",")
+ for (let cm of check_mode) {
+ if (cm == "ping") {
continue;
}
- if (check_mode[i].indexOf("tcp:") == 0) {
- var port = check_mode[i].split(":")[1];
+ if (cm.indexOf("tcp:") == 0) {
+ const port = cm.split(":")[1];
if (port == "") {
return _("TCP port is empty");
}
return true;
}
- var ipset = value.split(",")
- for (var i = 0; i < ipset.length; i++) {
- if (!ipset[i].match(/^(#[4|6]:)?[a-zA-Z0-9\-_]+$/)) {
+ const ipset = value.split(",")
+ for (let ips of ipset) {
+ if (!ips.match(/^(#[4|6]:)?[a-zA-Z0-9\-_]+$/)) {
return _("ipset name format error, format: [#[4|6]:]ipsetname");
}
}
return true;
}
- var nftset = value.split(",")
- for (var i = 0; i < nftset.length; i++) {
- if (!nftset[i].match(/^#[4|6]:[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+$/)) {
+ const nftset = value.split(",")
+ for (let nfts of nftset) {
+ if (!nfts.match(/^#[4|6]:[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+$/)) {
return _("NFTset name format error, format: [#[4|6]:[family#table#set]]");
}
}
download_files = uci.sections('smartdns', 'download-file');
o = s.taboption("advanced", form.DynamicList, "conf_files", _("Include Config Files<br>/etc/smartdns/conf.d"),
_("Include other config files from /etc/smartdns/conf.d or custom path, can be downloaded from the download page."));
- for (var i = 0; i < download_files.length; i++) {
- if (download_files[i].type == undefined) {
+ for (let df of download_files) {
+ if (df.type == undefined) {
continue;
}
- if (download_files[i].type != 'config') {
+ if (df.type != 'config') {
continue
}
- o.value(download_files[i].name);
+ o.value(df.name);
}
///////////////////////////////////////
return true;
}
- var ipset = value.split(",")
- for (var i = 0; i < ipset.length; i++) {
- if (!ipset[i].match(/^(#[4|6]:)?[a-zA-Z0-9\-_]+$/)) {
+ const ipset = value.split(",")
+ for (let ips of ipset) {
+ if (!ips.match(/^(#[4|6]:)?[a-zA-Z0-9\-_]+$/)) {
return _("ipset name format error, format: [#[4|6]:]ipsetname");
}
}
return true;
}
- var nftset = value.split(",")
- for (var i = 0; i < nftset.length; i++) {
- if (!nftset[i].match(/^#[4|6]:[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+$/)) {
+ const nftset = value.split(",")
+ for (let nfts of nftset) {
+ if (!nfts.match(/^#[4|6]:[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+$/)) {
return _("NFTset name format error, format: [#[4|6]:[family#table#set]]");
}
}
o.datatype = "hostname";
o.rempty = true;
servers = uci.sections('smartdns', 'server');
- var groupnames = new Set();
- for (var i = 0; i < servers.length; i++) {
- if (servers[i].server_group == undefined) {
+ let groupnames = new Set();
+ for (let serv of servers) {
+ if (serv.server_group == undefined) {
continue;
}
- groupnames.add(servers[i].server_group);
+ groupnames.add(serv.server_group);
}
for (const groupname of groupnames) {
o.optional = true;
o.rempty = true;
o.validate = function (section_id, value) {
- var flag = this.formvalue(section_id);
+ const flag = this.formvalue(section_id);
if (flag == "0") {
return true;
}
- var proxy_server = uci.sections("smartdns", "smartdns")[0].proxy_server;
- var server_type = this.section.formvalue(section_id, "type");
+ const proxy_server = uci.sections("smartdns", "smartdns")[0].proxy_server;
+ const server_type = this.section.formvalue(section_id, "type");
if (proxy_server == "" || proxy_server == undefined) {
return _("Please set proxy server first.");
}
return true;
}
- var val = uci.sections('smartdns', 'server');
- for (var i = 0; i < val.length; i++) {
- if (value == val[i].server_group) {
+ const val = uci.sections('smartdns', 'server');
+ for (let v of val) {
+ if (value == v.server_group) {
return true;
}
}
return true;
}
- var ipset = value.split(",")
- for (var i = 0; i < ipset.length; i++) {
- if (!ipset[i].match(/^(#[4|6]:)?[a-zA-Z0-9\-_]+$/)) {
+ const ipset = value.split(",")
+ for (let ips of ipset) {
+ if (!ips.match(/^(#[4|6]:)?[a-zA-Z0-9\-_]+$/)) {
return _("ipset name format error, format: [#[4|6]:]ipsetname");
}
}
return true;
}
- var nftset = value.split(",")
- for (var i = 0; i < nftset.length; i++) {
- if (!nftset[i].match(/^#[4|6]:[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+$/)) {
+ const nftset = value.split(",")
+ for (let nfts of nftset) {
+ if (!nfts.match(/^#[4|6]:[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+$/)) {
return _("NFTset name format error, format: [#[4|6]:[family#table#set]]");
}
}
return true;
}
- var val = uci.sections('smartdns', 'server');
- for (var i = 0; i < val.length; i++) {
- if (value == val[i].server_group) {
+ const val = uci.sections('smartdns', 'server');
+ for (let v of val) {
+ if (value == v.server_group) {
return true;
}
}
return true;
}
- var check_mode = value.split(",")
- for (var i = 0; i < check_mode.length; i++) {
- if (check_mode[i] == "ping") {
+ const check_mode = value.split(",")
+ for (let cm of check_mode) {
+ if (cm == "ping") {
continue;
}
- if (check_mode[i].indexOf("tcp:") == 0) {
- var port = check_mode[i].split(":")[1];
+ if (cm.indexOf("tcp:") == 0) {
+ const port = cm.split(":")[1];
if (port == "") {
return _("TCP port is empty");
}
return true;
}
- var nftset = value.split(",")
- for (var i = 0; i < nftset.length; i++) {
- if (!nftset[i].match(/#[4|6]:[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+$/)) {
+ const nftset = value.split(",")
+ for (let nfts of nftset) {
+ if (!nfts.match(/#[4|6]:[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+$/)) {
return _("NFTset name format error, format: [#[4|6]:[family#table#set]]");
}
}
['prfsha512']
]),
- _getAlgorithmNames: function (algorithms) {
+ _getAlgorithmNames(algorithms) {
return Array.from(algorithms.keys());
},
- isInsecure: function (algorithmName) {
+ isInsecure(algorithmName) {
return this._encryptionAlgorithms.get(algorithmName) == true
|| this._authenticatedEncryptionAlgorithms.get(algorithmName) == true
|| this._hashAlgorithms.get(algorithmName) == true
|| this._prfAlgorithms.get(algorithmName) == true;
},
- getEncryptionAlgorithms: function () {
+ getEncryptionAlgorithms() {
return this._getAlgorithmNames(this._encryptionAlgorithms);
},
- getAuthenticatedEncryptionAlgorithms: function () {
+ getAuthenticatedEncryptionAlgorithms() {
return this._getAlgorithmNames(this._authenticatedEncryptionAlgorithms);
},
- getHashAlgorithms: function () {
+ getHashAlgorithms() {
return this._getAlgorithmNames(this._hashAlgorithms);
},
- getDiffieHellmanAlgorithms: function () {
+ getDiffieHellmanAlgorithms() {
return this._getAlgorithmNames(this._dhAlgorithms);
},
- getPrfAlgorithms: function () {
+ getPrfAlgorithms() {
return this._getAlgorithmNames(this._prfAlgorithms);
}
});
'require ui';
function formatTime(seconds, selectCount) {
- var days = Math.floor(seconds / (60 * 60 * 24));
- var hours = Math.floor(seconds / (60 * 60)) % 24;
- var minutes = Math.floor(seconds / 60) % 60;
- var seconds = Math.floor(seconds % 60);
+ const days = Math.floor(seconds / (60 * 60 * 24));
+ const hours = Math.floor(seconds / (60 * 60)) % 24;
+ const minutes = Math.floor(seconds / 60) % 60;
+ seconds = Math.floor(seconds % 60);
- var times = [
+ const times = [
[days, _('Day'), _('Days')],
[hours, _('Hour'), _('Hours')],
[minutes, _('Minute'), _('Minutes')],
return time > 0;
});
- var selectedTimes = times.slice(0, selectCount);
+ const selectedTimes = times.slice(0, selectCount);
return selectedTimes.map(function ([time, singular, plural]) {
- var unit = time > 1 ? plural : singular;
+ const unit = time > 1 ? plural : singular;
return '%d %s'.format(time, unit);
}).join(', ');
}
}
function buildKeyValueTable(kvPairs) {
- var rows = kvPairs.map(function (row) {
+ const rows = kvPairs.map(function (row) {
return E('tr', { 'class': 'tr' }, [
E('td', { 'class': 'td', 'width': '33%' }, E('strong', [row[0]])),
E('td', { 'class': 'td' }, [row[1]])
}
function collectErrorMessages(results) {
- var errorMessages = results.reduce(function (messages, result) {
+ const errorMessages = results.reduce(function (messages, result) {
return messages.concat(result.errors.map(function (error) {
return error.message;
}));
}, []);
- var uniqueErrorMessages = new Set(errorMessages);
+ const uniqueErrorMessages = new Set(errorMessages);
return [...uniqueErrorMessages];
}
return view.extend({
- load: function () {
+ load() {
return Promise.all([
fs.exec_direct('/usr/sbin/swanmon', ['version'], 'json'),
fs.exec_direct('/usr/sbin/swanmon', ['stats'], 'json'),
]);
},
- pollData: function (container) {
+ pollData(container) {
poll.add(L.bind(function () {
return this.load().then(L.bind(function (results) {
dom.content(container, this.renderContent(results));
}, this));
},
- renderContent: function (results) {
- var node = E('div', [E('div')]);
- var firstNode = node.firstElementChild;
+ renderContent(results) {
+ const node = E('div', [E('div')]);
+ const firstNode = node.firstElementChild;
- var errorMessages = collectErrorMessages(results);
+ const errorMessages = collectErrorMessages(results);
if (errorMessages.length > 0) {
- var messageEls = errorMessages.map(function (message) {
+ const messageEls = errorMessages.map(function (message) {
return E('li', message);
});
return node;
}
- var [version, stats, sas] = results.map(function (r) {
+ const [version, stats, sas] = results.map(function (r) {
return r.data;
});
- var uptimeSeconds = (new Date() - new Date(stats.uptime.since)) / 1000;
- var statsSection = buildSection(_('Stats'), buildKeyValueTable([
+ const uptimeSeconds = (new Date() - new Date(stats.uptime.since)) / 1000;
+ const statsSection = buildSection(_('Stats'), buildKeyValueTable([
[_('Version'), version.version],
[_('Uptime'), formatTime(uptimeSeconds, 2)],
[_('Daemon'), version.daemon],
]));
firstNode.appendChild(statsSection);
- var tableRows = sas.map(function (conn) {
- var name = Object.keys(conn)[0];
- var data = conn[name];
- var childSas = [];
+ const tableRows = sas.map(function (conn) {
+ const name = Object.keys(conn)[0];
+ const data = conn[name];
+ const childSas = [];
Object.entries(data['child-sas']).forEach(function ([name, data]) {
- var table = buildKeyValueTable([
+ const table = buildKeyValueTable([
[_('State'), data.state],
[_('Mode'), data.mode],
[_('Protocol'), data.protocol],
}, _('Show Details'))])
]);
});
- var connSection = buildSection(_('Security Associations (SAs)'), buildTable([
+ const connSection = buildSection(_('Security Associations (SAs)'), buildTable([
E('tr', { 'class': 'tr' }, [
E('th', { 'class': 'th' }, [_('Name')]),
E('th', { 'class': 'th' }, [_('State')]),
return node;
},
- render: function (results) {
- var content = E([], [
+ render(results) {
+ const content = E([], [
E('h2', [_('strongSwan Status')]),
E('div')
]);
- var container = content.lastElementChild;
+ const container = content.lastElementChild;
dom.content(container, this.renderContent(results));
this.pollData(container);
'require ui';
'require tools.widgets as widgets';
-var CBIBindSelect = form.ListValue.extend({
+const CBIBindSelect = form.ListValue.extend({
__name__: 'CBI.CBIBindSelect',
- load: function(section_id) {
+ load(section_id) {
return Promise.all([
network.getDevices(),
this.noaliases ? null : network.getNetworks()
}, this));
},
- filter: function(section_id, value) {
+ filter(section_id, value) {
return true;
},
- renderWidget: function(section_id, option_index, cfgvalue) {
- var values = L.toArray((cfgvalue != null) ? cfgvalue : this.default),
- choices = {},
- checked = {},
- order = [];
+ renderWidget(section_id, option_index, cfgvalue) {
+ let values = L.toArray((cfgvalue != null) ? cfgvalue : this.default);
+ const choices = {};
+ const checked = {};
+ const order = [];
- for (var i = 0; i < values.length; i++)
- checked[values[i]] = true;
+ for (let v of values)
+ checked[v] = true;
values = [];
if (!this.multiple && (this.rmempty || this.optional))
choices[''] = E('em', _('unspecified'));
- for (var i = 0; i < this.devices.length; i++) {
- var device = this.devices[i],
- name = device.getName(),
- type = device.getType();
+ for (let device of this.devices) {
+ const name = device.getName();
+ const type = device.getType();
if (name == 'lo' || name == this.exclude || !this.filter(section_id, name))
continue;
if (this.noinactive && device.isUp() == false)
continue;
- var item = E([
+ const item = E([
E('img', {
'title': device.getI18n(),
'src': L.resource('icons/%s%s.svg'.format(type, device.isUp() ? '' : '_disabled'))
E('span', { 'class': 'hide-close'}, [ device.getI18n() ])
]);
- var networks = device.getNetworks();
+ const networks = device.getNetworks();
if (networks.length > 0)
L.dom.append(item.lastChild, [ ' (', networks.map(function(n) { return n.getName() }).join(', '), ')' ]);
}
if (this.networks != null) {
- for (var i = 0; i < this.networks.length; i++) {
- var net = this.networks[i],
- device = network.instantiateDevice('@%s'.format(net.getName()), net),
- name = device.getName();
+ for (let net of this.networks) {
+ const device = network.instantiateDevice('@%s'.format(net.getName()), net);
+ const name = device.getName();
if (name == '@loopback' || name == this.exclude || !this.filter(section_id, name))
continue;
if (this.noinactive && net.isUp() == false)
continue;
- var item = E([
+ const item = E([
E('img', {
'title': device.getI18n(),
'src': L.resource('icons/alias%s.svg'.format(net.isUp() ? '' : '_disabled'))
}
if (!this.nocreate) {
- var keys = Object.keys(checked).sort(L.naturalCompare);
+ const keys = Object.keys(checked).sort(L.naturalCompare);
- for (var i = 0; i < keys.length; i++) {
- if (choices.hasOwnProperty(keys[i]))
+ for (let key of keys) {
+ if (choices.hasOwnProperty(key))
continue;
- choices[keys[i]] = E([
+ choices[key] = E([
E('img', {
'title': _('Absent Interface'),
'src': L.resource('icons/ethernet_disabled.svg')
}),
- E('span', { 'class': 'hide-open' }, [ keys[i] ]),
- E('span', { 'class': 'hide-close'}, [ '%s: "%h"'.format(_('Absent Interface'), keys[i]) ])
+ E('span', { 'class': 'hide-open' }, [ key ]),
+ E('span', { 'class': 'hide-close'}, [ '%s: "%h"'.format(_('Absent Interface'), key) ])
]);
- values.push(keys[i]);
- order.push(keys[i]);
+ values.push(key);
+ order.push(key);
}
}
- var widget = new ui.Dropdown(this.multiple ? values : values[0], choices, {
+ const widget = new ui.Dropdown(this.multiple ? values : values[0], choices, {
id: this.cbid(section_id),
sort: order,
multiple: this.multiple,
});
return view.extend({
- render: function () {
+ render () {
let m, s, o;
m = new form.Map('udpxy', _('udpxy'),
return view.extend({
load() {
return Promise.all([
- uci.load('unbound'),
fs.read(RESOLV_FILE).catch(() => ''),
fs.exec(LOGERR_CMD).catch(() => ''),
- ]).then(([_, resolv, logerr]) => ({
+ uci.load('unbound'),
+ ]).then(([resolv, logerr]) => ({
resolvContent: resolv || '',
logerr: logerr ? logerr.trim().slice(-250) : null,
}));
const s = m.section(form.TableSection, 'zone', _('Zones'),
_('Organize directed forward, stub, and authoritative zones' +
- ' <a href=\"%s\" target=\"_blank\">(help)</a>.'.format(HELP_URL)));
+ ' <a href="%s" target="_blank">(help)</a>.'.format(HELP_URL)));
s.anonymous = false;
s.addremove = true;
s.sortable = true;