mirror of
https://github.com/openwrt/luci.git
synced 2025-02-07 13:59:54 +00:00
and the Alias Interface is likely what we want for the default. Signed-off-by: Jan Pazdziora <jan.pazdziora@code.adelton.com>
1188 lines
41 KiB
JavaScript
1188 lines
41 KiB
JavaScript
'use strict';
|
|
'require ui';
|
|
'require view';
|
|
'require dom';
|
|
'require poll';
|
|
'require uci';
|
|
'require rpc';
|
|
'require fs';
|
|
'require form';
|
|
'require network';
|
|
'require tools.widgets as widgets';
|
|
|
|
return view.extend({
|
|
|
|
NextUpdateStrings : {
|
|
'Verify' : _("Verify"),
|
|
'Run once' : _("Run once"),
|
|
'Disabled' : _("Disabled"),
|
|
'Stopped' : _("Stopped")
|
|
},
|
|
|
|
time_res : {
|
|
seconds : 1,
|
|
minutes : 60,
|
|
hours : 3600,
|
|
},
|
|
|
|
callGetLogServices: rpc.declare({
|
|
object: 'luci.ddns',
|
|
method: 'get_services_log',
|
|
params: [ 'service_name' ],
|
|
expect: { },
|
|
}),
|
|
|
|
callInitAction: rpc.declare({
|
|
object: 'luci',
|
|
method: 'setInitAction',
|
|
params: [ 'name', 'action' ],
|
|
expect: { result: false }
|
|
}),
|
|
|
|
callDDnsGetStatus: rpc.declare({
|
|
object: 'luci.ddns',
|
|
method: 'get_ddns_state',
|
|
expect: { }
|
|
}),
|
|
|
|
callDDnsGetEnv: rpc.declare({
|
|
object: 'luci.ddns',
|
|
method: 'get_env',
|
|
expect: { }
|
|
}),
|
|
|
|
callDDnsGetServicesStatus: rpc.declare({
|
|
object: 'luci.ddns',
|
|
method: 'get_services_status',
|
|
expect: { }
|
|
}),
|
|
|
|
services: {},
|
|
|
|
/*
|
|
* Services list is generated by 3 different sources:
|
|
* 1. /usr/share/ddns/default contains the service installed by package-manager
|
|
* 2. /usr/share/ddns/custom contains any service installed by the
|
|
* user or the ddns script (for example when services are
|
|
* downloaded)
|
|
* 3. /usr/share/ddns/list contains all the services that can be
|
|
* downloaded by using the ddns script ('service on demand' feature)
|
|
*
|
|
* (Special services that requires a dedicated package ARE NOT
|
|
* supported by the 'service on demand' feature)
|
|
*/
|
|
callGenServiceList: function(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;
|
|
|
|
this.services = {};
|
|
|
|
default_service.forEach(function (service) {
|
|
_this.services[service.name.replace('.json','')] = true
|
|
});
|
|
|
|
custom_service.forEach(function (service) {
|
|
_this.services[service.name.replace('.json','')] = true
|
|
});
|
|
|
|
this.services = Object.fromEntries(Object.entries(this.services).sort());
|
|
|
|
list_service.forEach(function (service) {
|
|
if (!_this.services[service])
|
|
_this.services[service] = false;
|
|
});
|
|
}, this))
|
|
},
|
|
|
|
/*
|
|
* 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) {
|
|
return network.getDevice('wan').then(dev => dev.getName())
|
|
.catch(err => network.getNetwork('wan').then(net => '@' + net.getName()))
|
|
.catch(err => null);
|
|
},
|
|
|
|
/*
|
|
* Check whether or not the service is supported.
|
|
* If the script doesn't find any JSON, assume a 'service on demand' install.
|
|
* 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) {
|
|
|
|
var value = service_name.formvalue(section_id);
|
|
s.service_supported = null;
|
|
service_name.triggerValidation(section_id);
|
|
|
|
return this.handleGetServiceData(value)
|
|
.then(L.bind(function (service_data) {
|
|
if (value != '-' && service_data) {
|
|
service_data = JSON.parse(service_data);
|
|
if (ipv6.formvalue(section_id) == "1" && !service_data.ipv6) {
|
|
s.service_supported = false;
|
|
return;
|
|
}
|
|
}
|
|
s.service_supported = true;
|
|
}, service_name))
|
|
.then(L.bind(service_name.triggerValidation, service_name, section_id))
|
|
},
|
|
|
|
handleGetServiceData: function(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)
|
|
]).then(function(data) {
|
|
return data[0] || data[1] || null;
|
|
})
|
|
},
|
|
|
|
handleInstallService: function(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))
|
|
.then(L.bind(m.render, m))
|
|
.then(L.bind(this.renderMoreOptionsModal, this, section))
|
|
.catch(function(e) { ui.addNotification(null, E('p', e.message)) });
|
|
},
|
|
|
|
handleRefreshServicesList: function(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) {
|
|
return fs.exec('/usr/lib/ddns/dynamic_dns_lucihelper.sh',
|
|
[ '-S', section_id, '--', 'start' ])
|
|
.then(L.bind(m.load, m))
|
|
.then(L.bind(m.render, m))
|
|
.catch(function(e) { ui.addNotification(null, E('p', e.message)) });
|
|
},
|
|
|
|
HandleStopDDnsRule: function(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) {
|
|
return this.callInitAction('ddns', 'enable')
|
|
.then(L.bind(function (action) { return this.callInitAction('ddns', action ? 'disable' : 'enable')}, this))
|
|
.then(L.bind(function (action) { return this.callInitAction('ddns', action ? 'stop' : 'start')}, this))
|
|
.then(L.bind(m.render, m))
|
|
.catch(function(e) { ui.addNotification(null, E('p', e.message)) });
|
|
},
|
|
|
|
handleRestartDDns: function(m, ev) {
|
|
return this.callInitAction('ddns', 'restart')
|
|
.then(L.bind(m.render, m));
|
|
},
|
|
|
|
poll_status: function(map, data) {
|
|
var status = data[1] || [], service = data[0] || [], rows = map.querySelectorAll('.cbi-section-table-row[data-sid]'),
|
|
section_id, cfg_detail_ip, cfg_update, cfg_status, host, ip, last_update,
|
|
next_update, service_status, reload, cfg_enabled, stop,
|
|
ddns_enabled = map.querySelector('[data-name="_enabled"]').querySelector('.cbi-value-field'),
|
|
ddns_toggle = map.querySelector('[data-name="_toggle"]').querySelector('button'),
|
|
services_list = map.querySelector('[data-name="_services_list"]').querySelector('.cbi-value-field');
|
|
|
|
ddns_toggle.innerHTML = status['_enabled'] ? _('Stop DDNS') : _('Start DDNS')
|
|
services_list.innerHTML = status['_services_list'];
|
|
|
|
dom.content(ddns_enabled, function() {
|
|
return E([], [
|
|
E('div', {}, status['_enabled'] ? _('DDNS Autostart enabled') : [
|
|
_('DDNS Autostart disabled'),
|
|
E('div', { 'class' : 'cbi-value-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')"))
|
|
]),]);
|
|
});
|
|
|
|
for (var i = 0; i < rows.length; i++) {
|
|
section_id = rows[i].getAttribute('data-sid');
|
|
cfg_detail_ip = rows[i].querySelector('[data-name="_cfg_detail_ip"]');
|
|
cfg_update = rows[i].querySelector('[data-name="_cfg_update"]');
|
|
cfg_status = rows[i].querySelector('[data-name="_cfg_status"]');
|
|
reload = rows[i].querySelector('.cbi-section-actions .reload');
|
|
stop = rows[i].querySelector('.cbi-section-actions .stop');
|
|
cfg_enabled = uci.get('ddns', section_id, 'enabled');
|
|
|
|
reload.disabled = (status['_enabled'] == 0 || cfg_enabled == 0);
|
|
|
|
host = uci.get('ddns', section_id, 'lookup_host') || _('Configuration Error');
|
|
ip = _('No Data');
|
|
last_update = _('Never');
|
|
next_update = _('Unknown');
|
|
service_status = '<b>' + _('Not Running') + '</b>';
|
|
|
|
if (service[section_id]) {
|
|
stop.disabled = (!service[section_id].pid);
|
|
if (service[section_id].ip)
|
|
ip = service[section_id].ip;
|
|
if (service[section_id].last_update)
|
|
last_update = service[section_id].last_update;
|
|
if (service[section_id].next_update)
|
|
next_update = this.NextUpdateStrings[service[section_id].next_update] || service[section_id].next_update;
|
|
if (service[section_id].pid)
|
|
service_status = '<b>' + _('Running') + '</b> : ' + service[section_id].pid;
|
|
}
|
|
|
|
cfg_detail_ip.innerHTML = host + '<br />' + ip;
|
|
cfg_update.innerHTML = last_update + '<br />' + next_update;
|
|
cfg_status.innerHTML = service_status;
|
|
}
|
|
|
|
return;
|
|
},
|
|
|
|
load: function() {
|
|
return Promise.all([
|
|
this.callDDnsGetServicesStatus(),
|
|
this.callDDnsGetStatus(),
|
|
this.callDDnsGetEnv(),
|
|
this.callGenServiceList(),
|
|
uci.load('ddns'),
|
|
this.callGetWanInterface()
|
|
]);
|
|
},
|
|
|
|
render: function(data) {
|
|
var resolved = data[0] || [];
|
|
var status = data[1] || [];
|
|
var env = data[2] || [];
|
|
var logdir = uci.get('ddns', 'global', 'ddns_logdir') || "/var/log/ddns";
|
|
var wan_interface = data[5];
|
|
|
|
var _this = this;
|
|
|
|
let m, s, o;
|
|
|
|
m = new form.Map('ddns', _('Dynamic DNS'));
|
|
|
|
s = m.section(form.NamedSection, 'global', 'ddns',);
|
|
|
|
s.tab('info', _('Information'));
|
|
s.tab('global', _('Global Settings'));
|
|
|
|
o = s.taboption('info', form.DummyValue, '_version', _('Dynamic DNS Version'));
|
|
o.cfgvalue = function() {
|
|
return status[this.option];
|
|
};
|
|
|
|
o = s.taboption('info', form.DummyValue, '_enabled', _('State'));
|
|
o.cfgvalue = function() {
|
|
var 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')")
|
|
}
|
|
return res ? _('DDNS Autostart enabled') : _('DDNS Autostart disabled')
|
|
};
|
|
|
|
o = s.taboption('info', form.Button, '_toggle');
|
|
o.title = ' ';
|
|
o.inputtitle = _((status['_enabled'] ? 'stop' : 'start').toUpperCase() + ' DDns');
|
|
o.inputstyle = 'apply';
|
|
o.onclick = L.bind(this.handleToggleDDns, this, m);
|
|
|
|
o = s.taboption('info', form.Button, '_restart');
|
|
o.title = ' ';
|
|
o.inputtitle = _('Restart DDns');
|
|
o.inputstyle = 'apply';
|
|
o.onclick = L.bind(this.handleRestartDDns, this, m);
|
|
|
|
o = s.taboption('info', form.DummyValue, '_services_list', _('Services list last update'));
|
|
o.cfgvalue = function() {
|
|
return status[this.option];
|
|
};
|
|
|
|
o = s.taboption('info', form.Button, '_refresh_services');
|
|
o.title = ' ';
|
|
o.inputtitle = _('Update DDns Services List');
|
|
o.inputstyle = 'apply';
|
|
o.onclick = L.bind(this.handleRefreshServicesList, this, m);
|
|
|
|
// DDns hints
|
|
|
|
if (!env['has_ipv6']) {
|
|
o = s.taboption('info', form.DummyValue, '_no_ipv6');
|
|
o.rawhtml = true;
|
|
o.title = '<b>' + _("IPv6 not supported") + '</b>';
|
|
o.cfgvalue = function() { return _("IPv6 is not supported by this system") + "<br />" +
|
|
_("Please follow the instructions on OpenWrt's homepage to enable IPv6 support") + "<br />" +
|
|
_("or update your system to the latest OpenWrt Release")};
|
|
}
|
|
|
|
if (!env['has_ssl']) {
|
|
o = s.taboption('info', form.DummyValue, '_no_https');
|
|
o.titleref = L.url("admin", "system", "package-manager")
|
|
o.rawhtml = true;
|
|
o.title = '<b>' + _("HTTPS not supported") + '</b>';
|
|
o.cfgvalue = function() { return _("Neither GNU Wget with SSL nor cURL is installed to support secure updates via HTTPS protocol.") +
|
|
"<br />- " +
|
|
_("You should install 'wget' or 'curl' or 'uclient-fetch' with 'libustream-*ssl' package.") +
|
|
"<br />- " +
|
|
_("In some versions cURL/libcurl in OpenWrt is compiled without proxy support.")};
|
|
}
|
|
|
|
if (!env['has_bindnet']) {
|
|
o = s.taboption('info', form.DummyValue, '_no_bind_network');
|
|
o.titleref = L.url("admin", "system", "package-manager")
|
|
o.rawhtml = true;
|
|
o.title = '<b>' + _("Binding to a specific network not supported") + '</b>';
|
|
o.cfgvalue = function() { return _("Neither GNU Wget with SSL nor cURL is installed to select a network to use for communication.") +
|
|
"<br />- " +
|
|
_("This is only a problem with multiple WAN interfaces and your DDNS provider is unreachable via one of them.") +
|
|
"<br />- " +
|
|
_("You should install 'wget' or 'curl' package.") +
|
|
"<br />- " +
|
|
_("GNU Wget will use the IP of given network, cURL will use the physical interface.") +
|
|
"<br />- " +
|
|
_("In some versions cURL/libcurl in OpenWrt is compiled without proxy support.")};
|
|
}
|
|
|
|
if (!env['has_proxy']) {
|
|
o = s.taboption('info', form.DummyValue, '_no_proxy');
|
|
o.titleref = L.url("admin", "system", "package-manager")
|
|
o.rawhtml = true;
|
|
o.title = '<b>' + _("cURL without Proxy Support") + '</b>';
|
|
o.cfgvalue = function() { return _("cURL is installed, but libcurl was compiled without proxy support.") +
|
|
"<br />- " +
|
|
_("You should install 'wget' or 'uclient-fetch' package or replace libcurl.") +
|
|
"<br />- " +
|
|
_("In some versions cURL/libcurl in OpenWrt is compiled without proxy support.")};
|
|
}
|
|
|
|
if (!env['has_bindhost']) {
|
|
o = s.taboption('info', form.DummyValue, '_no_dnstcp');
|
|
o.titleref = L.url("admin", "system", "package-manager")
|
|
o.rawhtml = true;
|
|
o.title = '<b>' + _("DNS requests via TCP not supported") + '</b>';
|
|
o.cfgvalue = function() { return _("BusyBox's nslookup and hostip do not support TCP " +
|
|
"instead of the default UDP when sending requests to the DNS server!") +
|
|
"<br />- " +
|
|
_("Install 'bind-host' or 'knot-host' or 'drill' package if you know you need TCP for DNS requests.")};
|
|
}
|
|
|
|
if (!env['has_dnsserver']) {
|
|
o = s.taboption('info', form.DummyValue, '_no_dnsserver');
|
|
o.titleref = L.url("admin", "system", "package-manager")
|
|
o.rawhtml = true;
|
|
o.title = '<b>' + _("Using specific DNS Server not supported") + '</b>';
|
|
o.cfgvalue = function() { return _("BusyBox's nslookup in the current compiled version " +
|
|
"does not handle given DNS Servers correctly!") +
|
|
"<br />- " +
|
|
_("You should install 'bind-host' or 'knot-host' or 'drill' or 'hostip' package, " +
|
|
"if you need to specify a DNS server to detect your registered IP.")};
|
|
}
|
|
|
|
if (env['has_ssl'] && !env['has_cacerts']) {
|
|
o = s.taboption('info', form.DummyValue, '_no_certs');
|
|
o.titleref = L.url("admin", "system", "package-manager")
|
|
o.rawhtml = true;
|
|
o.title = '<b>' + _("No certificates found") + '</b>';
|
|
o.cfgvalue = function() { return _("If using secure communication you should verify server certificates!") +
|
|
"<br />- " +
|
|
_("Install 'ca-certificates' package or needed certificates " +
|
|
"by hand into /etc/ssl/certs default directory")};
|
|
}
|
|
|
|
// Advanced Configuration Section
|
|
|
|
o = s.taboption('global', form.Flag, 'upd_privateip', _("Allow non-public IPs"));
|
|
o.description = _("Non-public and by default blocked IPs") + ':'
|
|
+ '<br /><strong>IPv4: </strong>'
|
|
+ '0/8, 10/8, 100.64/10, 127/8, 169.254/16, 172.16/12, 192.168/16'
|
|
+ '<br /><strong>IPv6: </strong>'
|
|
+ '::/32, f000::/4';
|
|
o.default = "0";
|
|
o.optional = true;
|
|
|
|
o = s.taboption('global', form.Value, 'ddns_dateformat', _('Date format'));
|
|
o.description = '<a href="http://www.cplusplus.com/reference/ctime/strftime/" target="_blank">'
|
|
+ _("For supported codes look here")
|
|
+ '</a><br />' +
|
|
_('Current setting: ') + '<b>' + status['_curr_dateformat'] + '</b>';
|
|
o.default = "%F %R"
|
|
o.optional = true;
|
|
o.rmempty = true;
|
|
|
|
o = s.taboption('global', form.Value, 'ddns_rundir', _('Status directory'));
|
|
o.description = _('Contains PID and other status information for each running section.');
|
|
o.default = "/var/run/ddns";
|
|
o.optional = true;
|
|
o.rmempty = true;
|
|
|
|
o = s.taboption('global', form.Value, 'ddns_logdir', _('Log directory'));
|
|
o.description = _('Contains Log files for each running section.');
|
|
o.default = "/var/log/ddns";
|
|
o.optional = true;
|
|
o.rmempty = true;
|
|
o.validate = function(section_id, formvalue) {
|
|
if (formvalue.indexOf('../') !== -1)
|
|
return _('"../" not allowed in path for Security Reason.')
|
|
|
|
return true;
|
|
}
|
|
|
|
o = s.taboption('global', form.Value, 'ddns_loglines', _('Log length'));
|
|
o.description = _('Number of last lines stored in log files');
|
|
o.datatype = 'min(1)';
|
|
o.default = '250';
|
|
|
|
if (env['has_wget'] && env['has_curl']) {
|
|
|
|
o = s.taboption('global', form.Flag, 'use_curl', _('Use cURL'));
|
|
o.description = _('If Wget and cURL package are installed, Wget is used for communication by default.');
|
|
o.default = "0";
|
|
o.optional = true;
|
|
o.rmempty = true;
|
|
|
|
}
|
|
|
|
o = s.taboption('global', form.Value, 'cacert', _('CA cert bundle file'));
|
|
o.description = _('CA certificate bundle file that will be used to download services data. Set IGNORE to skip certificate validation.');
|
|
o.placeholder = 'IGNORE';
|
|
o.write = function(section_id, value) {
|
|
if(value == 'ignore')
|
|
uci.set('ddns', section_id, 'cacert', value.toUpperCase());
|
|
};
|
|
|
|
o = s.taboption('global', form.Value, 'services_url', _('Services URL Download'));
|
|
o.description = _('Source URL for services file. Defaults to the master openwrt ddns package repo.');
|
|
o.placeholder = 'https://raw.githubusercontent.com/openwrt/packages/master/net/ddns-scripts/files';
|
|
|
|
// DDns services
|
|
s = m.section(form.GridSection, 'service', _('Services'));
|
|
s.anonymous = true;
|
|
s.addremove = true;
|
|
s.addbtntitle = _('Add new services...');
|
|
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;
|
|
|
|
if (!section_id || !service_value || !ipv6_value)
|
|
return;
|
|
|
|
return m.save(function() {
|
|
uci.add('ddns', 'service', section_id);
|
|
if (service_value != '-') {
|
|
uci.set('ddns', section_id, 'service_name', service_value);
|
|
}
|
|
uci.set('ddns', section_id, 'use_ipv6', ipv6_value);
|
|
ui.hideModal();
|
|
}).then(L.bind(m.children[1].renderMoreOptionsModal, m.children[1], section_id));
|
|
};
|
|
|
|
s.handleAdd = function(ev) {
|
|
var m2 = new form.Map('ddns'),
|
|
s2 = m2.section(form.NamedSection, '_new_'),
|
|
name, ipv6, service_name;
|
|
|
|
s2.render = function() {
|
|
return Promise.all([
|
|
{},
|
|
this.renderUCISection('_new_')
|
|
]).then(this.renderContents.bind(this));
|
|
};
|
|
|
|
name = s2.option(form.Value, 'name', _('Name'));
|
|
name.rmempty = false;
|
|
name.datatype = 'uciname';
|
|
name.placeholder = _('New DDns Service…');
|
|
name.validate = function(section_id, value) {
|
|
if (uci.get('ddns', value) != null)
|
|
return _('The service name is already used');
|
|
|
|
return true;
|
|
};
|
|
|
|
ipv6 = s2.option( form.ListValue, 'use_ipv6',
|
|
_("IP address version"),
|
|
_("Which record type to update at the DDNS provider (A/AAAA)"));
|
|
ipv6.default = '0';
|
|
ipv6.value("0", _("IPv4-Address"))
|
|
if (env["has_ipv6"]) {
|
|
ipv6.value("1", _("IPv6-Address"))
|
|
}
|
|
|
|
service_name = s2.option(form.ListValue, 'service_name',
|
|
String.format('%s', _("DDNS Service provider")));
|
|
service_name.value('-',"📝 " + _("custom") );
|
|
Object.keys(_this.services).sort().forEach(name => service_name.value(name));
|
|
service_name.validate = function(section_id, value) {
|
|
if (value == '-') return true;
|
|
if (!value) return _("Select a service");
|
|
if (!s2.service_supported) return _("Service doesn't support this IP type");
|
|
return true;
|
|
};
|
|
|
|
ipv6.onchange = L.bind(_this.handleCheckService, _this, s2, service_name, ipv6);
|
|
service_name.onchange = L.bind(_this.handleCheckService, _this, s2, service_name, ipv6);
|
|
|
|
m2.render().then(L.bind(function(nodes) {
|
|
ui.showModal(_('Add new services...'), [
|
|
nodes,
|
|
E('div', { 'class': 'right' }, [
|
|
E('button', {
|
|
'class': 'btn',
|
|
'click': ui.hideModal
|
|
}, _('Cancel')), ' ',
|
|
E('button', {
|
|
'class': 'cbi-button cbi-button-positive important',
|
|
'click': ui.createHandlerFn(this, 'handleCreateDDnsRule', m, name, service_name, ipv6)
|
|
}, _('Create service'))
|
|
])
|
|
], 'cbi-modal');
|
|
|
|
nodes.querySelector('[id="%s"] input[type="text"]'.format(name.cbid('_new_'))).focus();
|
|
}, this));
|
|
};
|
|
|
|
s.renderRowActions = function(section_id) {
|
|
var tdEl = this.super('renderRowActions', [ section_id, _('Edit') ]),
|
|
cfg_enabled = uci.get('ddns', section_id, 'enabled'),
|
|
reload_opt = {
|
|
'class': 'cbi-button cbi-button-neutral reload',
|
|
'click': ui.createHandlerFn(_this, 'handleReloadDDnsRule', m, section_id),
|
|
'title': _('Reload this service'),
|
|
},
|
|
stop_opt = {
|
|
'class': 'cbi-button cbi-button-neutral stop',
|
|
'click': ui.createHandlerFn(_this, 'HandleStopDDnsRule', m, section_id),
|
|
'title': _('Stop this service'),
|
|
};
|
|
|
|
if (status['_enabled'] == 0 || cfg_enabled == 0)
|
|
reload_opt['disabled'] = 'disabled';
|
|
|
|
if (!resolved[section_id] || !resolved[section_id].pid ||
|
|
(resolved[section_id].pid && cfg_enabled == '1'))
|
|
stop_opt['disabled'] = 'disabled';
|
|
|
|
dom.content(tdEl.lastChild, [
|
|
E('button', stop_opt, _('Stop')),
|
|
E('button', reload_opt, _('Reload')),
|
|
tdEl.lastChild.childNodes[0],
|
|
tdEl.lastChild.childNodes[1],
|
|
tdEl.lastChild.childNodes[2]
|
|
]);
|
|
|
|
return tdEl;
|
|
};
|
|
|
|
s.modaltitle = function(section_id) {
|
|
return _('DDns Service') + ' » ' + section_id;
|
|
};
|
|
|
|
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;
|
|
|
|
return _this.handleGetServiceData(service).then(L.bind(function (service_data) {
|
|
s.service_available = true;
|
|
s.service_supported = true;
|
|
s.url = null;
|
|
|
|
if (service != '-') {
|
|
if (!service_data)
|
|
s.service_available = false;
|
|
else {
|
|
service_data = JSON.parse(service_data);
|
|
if (ipv6 == "1" && !service_data.ipv6)
|
|
s.service_supported = false;
|
|
else if (ipv6 == "1") {
|
|
s.url = service_data.ipv6.url;
|
|
} else {
|
|
s.url = service_data.ipv4.url;
|
|
}
|
|
}
|
|
}
|
|
|
|
s.tab('basic', _('Basic Settings'));
|
|
s.tab('advanced', _('Advanced Settings'));
|
|
s.tab('timer', _('Timer Settings'));
|
|
s.tab('logview', _('Log File Viewer'));
|
|
|
|
o = s.taboption('basic', form.Flag, 'enabled',
|
|
_('Enabled'),
|
|
_("If this service section is disabled it will not be started.")
|
|
+ "<br />" +
|
|
_("Neither from LuCI interface nor from console."));
|
|
o.modalonly = true;
|
|
o.rmempty = false;
|
|
o.default = '1';
|
|
|
|
o = s.taboption('basic', form.Value, 'lookup_host',
|
|
_("Lookup Hostname"),
|
|
_("Hostname/FQDN to validate, whether an IP update is necessary"));
|
|
o.rmempty = false;
|
|
o.placeholder = "myhost.example.com";
|
|
o.datatype = 'and(minlength(3),hostname("strict"))';
|
|
o.modalonly = true;
|
|
|
|
use_ipv6 = s.taboption('basic', form.ListValue, 'use_ipv6',
|
|
_("IP address version"),
|
|
_("Which record type to update at the DDNS provider (A/AAAA)"));
|
|
use_ipv6.default = '0';
|
|
use_ipv6.modalonly = true;
|
|
use_ipv6.rmempty = false;
|
|
use_ipv6.value("0", _("IPv4-Address"))
|
|
if (env["has_ipv6"]) {
|
|
use_ipv6.value("1", _("IPv6-Address"))
|
|
}
|
|
|
|
service_name = s.taboption('basic', form.ListValue, 'service_name',
|
|
String.format('%s', _("DDNS Service provider")));
|
|
service_name.modalonly = true;
|
|
service_name.value('-',"📝 " + _("custom") );
|
|
Object.keys(_this.services).sort().forEach(name => service_name.value(name));
|
|
service_name.cfgvalue = function(section_id) {
|
|
return uci.get('ddns', section_id, 'service_name') || '-';
|
|
};
|
|
service_name.write = function(section_id, service) {
|
|
if (service != '-') {
|
|
uci.unset('ddns', section_id, 'update_url');
|
|
uci.unset('ddns', section_id, 'update_script');
|
|
return uci.set('ddns', section_id, 'service_name', service);
|
|
}
|
|
return uci.unset('ddns', section_id, 'service_name');
|
|
};
|
|
service_name.validate = function(section_id, value) {
|
|
if (value == '-') return true;
|
|
if (!value) return _("Select a service");
|
|
if (!s.service_available) return _('Service not installed');
|
|
if (!s.service_supported) return _("Service doesn't support this IP type");
|
|
return true;
|
|
};
|
|
|
|
service_name.onchange = L.bind(_this.handleCheckService, _this, s, service_name, use_ipv6);
|
|
use_ipv6.onchange = L.bind(_this.handleCheckService, _this, s, service_name, use_ipv6);
|
|
|
|
if (!s.service_available) {
|
|
o = s.taboption('basic', form.Button, '_download_service');
|
|
o.modalonly = true;
|
|
o.title = _('Service not installed');
|
|
o.inputtitle = _('Install Service');
|
|
o.inputstyle = 'apply';
|
|
o.onclick = L.bind(_this.handleInstallService,
|
|
this, m, service_name, section_id, s.section, _this)
|
|
}
|
|
|
|
if (!s.service_supported) {
|
|
o = s.taboption('basic', form.DummyValue, '_not_supported', ' ');
|
|
o.cfgvalue = function () {
|
|
return _("Service doesn't support this IP type")
|
|
};
|
|
}
|
|
|
|
if (Boolean(s.url)) {
|
|
o = s.taboption('basic', form.DummyValue, '_url', _("Update URL"));
|
|
o.rawhtml = true;
|
|
o.default = '<div style="font-family: monospace;">'
|
|
+ s.url.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")
|
|
+ '</div>';
|
|
}
|
|
|
|
var service_switch = s.taboption('basic', form.Button, '_switch_proto');
|
|
service_switch.modalonly = true;
|
|
service_switch.title = _('Really switch service?');
|
|
service_switch.inputtitle = _('Switch service');
|
|
service_switch.inputstyle = 'apply';
|
|
service_switch.onclick = L.bind(function(ev) {
|
|
if (!s.service_supported) return;
|
|
|
|
return s.map.save()
|
|
.then(L.bind(m.load, m))
|
|
.then(L.bind(m.render, m))
|
|
.then(L.bind(this.renderMoreOptionsModal, this, s.section));
|
|
}, this);
|
|
|
|
if (s.service_available && s.service_supported) {
|
|
|
|
o = s.taboption('basic', form.Value, 'update_url',
|
|
_("Custom update-URL"),
|
|
_("Update URL for updating your DDNS Provider.")
|
|
+ "<br />" +
|
|
_("Follow instructions found on their WEB page."));
|
|
o.modalonly = true;
|
|
o.rmempty = true;
|
|
o.optional = true;
|
|
o.depends("service_name","-");
|
|
o.validate = function(section_id, value) {
|
|
var other = this.section.formvalue(section_id, 'update_script');
|
|
if ((!value && !other) || (value && other)) {
|
|
return _("Provide either an Update Script OR an Update URL");
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
o = s.taboption('basic', form.FileUpload, 'update_script',
|
|
_("Custom update-script"),
|
|
_("Custom update script for updating your DDNS Provider."));
|
|
o.root_directory = '/usr/lib/ddns/';
|
|
o.datatype = 'file';
|
|
o.show_hidden = true;
|
|
o.enable_upload = true;
|
|
o.enable_remove = true;
|
|
o.enable_download = true;
|
|
o.modalonly = true;
|
|
o.rmempty = true;
|
|
o.optional = true;
|
|
o.depends("service_name","-");
|
|
o.validate = function(section_id, value) {
|
|
var other = this.section.formvalue(section_id, 'update_url');
|
|
if ((!value && !other) || (value && other)) {
|
|
return _("Provide either an Update Script OR an Update URL");
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
o = s.taboption('basic', form.Value, 'domain',
|
|
_("Domain"),
|
|
_("Replaces [DOMAIN] in Update-URL (URL-encoded)"));
|
|
o.modalonly = true;
|
|
o.rmempty = false;
|
|
|
|
o = s.taboption('basic', form.Value, 'username',
|
|
_("Username"),
|
|
_("Replaces [USERNAME] in Update-URL (URL-encoded)"));
|
|
o.modalonly = true;
|
|
o.rmempty = false;
|
|
|
|
o = s.taboption('basic', form.Value, 'password',
|
|
_("Password"),
|
|
_("Replaces [PASSWORD] in Update-URL (URL-encoded)")
|
|
+ '<br/>' +
|
|
_("A.k.a. the TOKEN at e.g. afraid.org"));
|
|
o.password = true;
|
|
o.modalonly = true;
|
|
o.rmempty = false;
|
|
|
|
o = s.taboption('basic', form.Value, 'param_enc',
|
|
_("Optional Encoded Parameter"),
|
|
_("Optional: Replaces [PARAMENC] in Update-URL (URL-encoded)"));
|
|
o.optional = true;
|
|
o.modalonly = true;
|
|
|
|
o = s.taboption('basic', form.Value, 'param_opt',
|
|
_("Optional Parameter"),
|
|
_("Optional: Replaces [PARAMOPT] in Update-URL (NOT URL-encoded)"));
|
|
o.optional = true;
|
|
o.modalonly = true;
|
|
|
|
if (env['has_ssl']) {
|
|
o = s.taboption('basic', form.Flag, 'use_https',
|
|
_("Use HTTP Secure"),
|
|
_("Enable secure communication with DDNS provider"));
|
|
o.optional = true;
|
|
o.modalonly = true;
|
|
|
|
o = s.taboption('basic', form.Value, 'cacert',
|
|
_("Path to CA-Certificate"),
|
|
_("directory or path/file")
|
|
+ "<br />" +
|
|
_("or")
|
|
+ '<b>' + " IGNORE " + '</b>' +
|
|
_("to run HTTPS without verification of server certificates (insecure)"));
|
|
o.modalonly = true;
|
|
o.depends("use_https", "1");
|
|
o.placeholder = "/etc/ssl/certs";
|
|
o.rmempty = false;
|
|
o.optional = true;
|
|
o.write = function(section_id, value) {
|
|
if(value == 'ignore')
|
|
uci.set('ddns', section_id, 'cacert', value.toUpperCase());
|
|
};
|
|
};
|
|
|
|
|
|
o = s.taboption('advanced', form.ListValue, 'ip_source',
|
|
_("IP address source"),
|
|
_("Method used to determine the system IP-Address to send in updates"));
|
|
o.modalonly = true;
|
|
o.default = "network";
|
|
o.value("network", _("Network"));
|
|
o.value("web", _("URL"));
|
|
o.value("interface", _("Interface"));
|
|
o.value("script", _("Script"));
|
|
o.write = function(section_id, formvalue) {
|
|
switch(formvalue) {
|
|
case 'network':
|
|
uci.unset('ddns', section_id, "ip_url");
|
|
uci.unset('ddns', section_id, "ip_interface");
|
|
uci.unset('ddns', section_id, "ip_script");
|
|
break;
|
|
case 'web':
|
|
uci.unset('ddns', section_id, "ip_network");
|
|
uci.unset('ddns', section_id, "ip_interface");
|
|
uci.unset('ddns', section_id, "ip_script");
|
|
break;
|
|
case 'interface':
|
|
uci.unset('ddns', section_id, "ip_network");
|
|
uci.unset('ddns', section_id, "ip_url");
|
|
uci.unset('ddns', section_id, "ip_script");
|
|
break;
|
|
case 'script':
|
|
uci.unset('ddns', section_id, "ip_network");
|
|
uci.unset('ddns', section_id, "ip_url");
|
|
uci.unset('ddns', section_id, "ip_interface");
|
|
break;
|
|
default:
|
|
break;
|
|
};
|
|
|
|
return uci.set('ddns', section_id, 'ip_source', formvalue )
|
|
};
|
|
|
|
o = s.taboption('advanced', widgets.NetworkSelect, 'ip_network',
|
|
_("Network"),
|
|
_("Defines the network to read systems IP-Address from"));
|
|
o.depends('ip_source','network');
|
|
o.modalonly = true;
|
|
o.default = 'wan';
|
|
o.multiple = false;
|
|
|
|
o = s.taboption('advanced', form.Value, 'ip_url',
|
|
_("URL to detect"),
|
|
_("Defines the Web page to read systems IP-Address from.")
|
|
+ '<br />' +
|
|
String.format('%s %s', _('Example for IPv4'), ': http://checkip.dyndns.com')
|
|
+ '<br />' +
|
|
String.format('%s %s', _('Example for IPv6'), ': http://checkipv6.dyndns.com'));
|
|
o.depends("ip_source", "web")
|
|
o.modalonly = true;
|
|
|
|
o = s.taboption('advanced', widgets.DeviceSelect, 'ip_interface',
|
|
_("Interface"),
|
|
_("Defines the interface to read systems IP-Address from"));
|
|
o.modalonly = true;
|
|
o.depends("ip_source", "interface")
|
|
o.multiple = false;
|
|
o.default = wan_interface;
|
|
|
|
o = s.taboption('advanced', form.Value, 'ip_script',
|
|
_("Script"),
|
|
_("User defined script to read system IP-Address"));
|
|
o.modalonly = true;
|
|
o.depends("ip_source", "script")
|
|
o.placeholder = "/path/to/script.sh"
|
|
|
|
o = s.taboption('advanced', widgets.NetworkSelect, 'interface',
|
|
_("Event Network"),
|
|
_("Network on which the ddns-updater scripts will be started"));
|
|
o.modalonly = true;
|
|
o.multiple = false;
|
|
o.default = 'wan';
|
|
o.depends("ip_source", "web");
|
|
o.depends("ip_source", "script");
|
|
|
|
o = s.taboption('advanced', form.DummyValue, '_interface',
|
|
_("Event Network"),
|
|
_("Network on which the ddns-updater scripts will be started"));
|
|
o.depends("ip_source", "interface");
|
|
o.depends("ip_source", "network");
|
|
o.forcewrite = true;
|
|
o.modalonly = true;
|
|
o.cfgvalue = function(section_id) {
|
|
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);
|
|
return uci.set('ddns', section_id, 'interface', val);
|
|
};
|
|
|
|
if (env['has_bindnet']) {
|
|
o = s.taboption('advanced', widgets.NetworkSelect, 'bind_network',
|
|
_("Bind Network"),
|
|
_('OPTIONAL: Network to use for communication')
|
|
+ '<br />' +
|
|
_("Network on which the ddns-updater scripts will be started"));
|
|
o.depends("ip_source", "web");
|
|
o.optional = true;
|
|
o.rmempty = true;
|
|
o.modalonly = true;
|
|
}
|
|
|
|
if (env['has_forceip']) {
|
|
o = s.taboption('advanced', form.Flag, 'force_ipversion',
|
|
_("Force IP Version"),
|
|
_('OPTIONAL: Force the usage of pure IPv4/IPv6 only communication.'));
|
|
o.optional = true;
|
|
o.rmempty = true;
|
|
o.modalonly = true;
|
|
}
|
|
|
|
if (env['has_dnsserver']) {
|
|
o = s.taboption("advanced", form.Value, "dns_server",
|
|
_("DNS-Server"),
|
|
_("OPTIONAL: Use non-default DNS-Server to detect 'Registered IP'.")
|
|
+ "<br />" +
|
|
_("Format: IP or FQDN"));
|
|
o.placeholder = "mydns.lan"
|
|
o.optional = true;
|
|
o.rmempty = true;
|
|
o.modalonly = true;
|
|
}
|
|
|
|
if (env['has_bindhost']) {
|
|
o = s.taboption("advanced", form.Flag, "force_dnstcp",
|
|
_("Force TCP on DNS"),
|
|
_("OPTIONAL: Force the use of TCP instead of default UDP on DNS requests."));
|
|
o.optional = true;
|
|
o.rmempty = true;
|
|
o.modalonly = true;
|
|
}
|
|
|
|
if (env['has_proxy']) {
|
|
o = s.taboption("advanced", form.Value, "proxy",
|
|
_("PROXY-Server"),
|
|
_("OPTIONAL: Proxy-Server for detection and updates.")
|
|
+ "<br />" +
|
|
String.format('%s: <b>%s</b>', _("Format"), "[user:password@]proxyhost:port")
|
|
+ "<br />" +
|
|
String.format('%s: <b>%s</b>', _("IPv6 address must be given in square brackets"), "[2001:db8::1]:8080"));
|
|
o.optional = true;
|
|
o.rmempty = true;
|
|
o.modalonly = true;
|
|
}
|
|
|
|
o = s.taboption("advanced", form.ListValue, "use_syslog",
|
|
_("Log to syslog"),
|
|
_("Writes log messages to syslog. Critical Errors will always be written to syslog."));
|
|
o.modalonly = true;
|
|
o.default = "2"
|
|
o.optional = true;
|
|
o.value("0", _("No logging"))
|
|
o.value("1", _("Info"))
|
|
o.value("2", _("Notice"))
|
|
o.value("3", _("Warning"))
|
|
o.value("4", _("Error"))
|
|
|
|
o = s.taboption("advanced", form.Flag, "use_logfile",
|
|
_("Log to file"));
|
|
o.default = '1';
|
|
o.optional = true;
|
|
o.modalonly = true;
|
|
o.cfgvalue = function(section_id) {
|
|
this.description = _("Writes detailed messages to log file. File will be truncated automatically.") + "<br />" +
|
|
_("File") + ': "' + logdir + '/' + section_id + '.log"';
|
|
return uci.get('ddns', section_id, 'use_logfile');
|
|
};
|
|
|
|
|
|
o = s.taboption("timer", form.Value, "check_interval",
|
|
_("Check Interval"));
|
|
o.placeholder = "10";
|
|
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;
|
|
|
|
if (formvalue && time_to_sec < 300)
|
|
return _('Values below 5 minutes == 300 seconds are not supported');
|
|
|
|
return true;
|
|
};
|
|
|
|
o = s.taboption("timer", form.ListValue, "check_unit",
|
|
_('Check Unit'),
|
|
_("Interval unit to check for changed IP"));
|
|
o.modalonly = true;
|
|
o.optional = true;
|
|
o.value("seconds", _("seconds"));
|
|
o.value("minutes", _("minutes"));
|
|
o.value("hours", _("hours"));
|
|
|
|
o = s.taboption("timer", form.Value, "force_interval",
|
|
_("Force Interval"),
|
|
_("Interval to force an update at the DDNS Provider")
|
|
+ "<br />" +
|
|
_("Setting this parameter to 0 will force the script to only run once"));
|
|
o.placeholder = "72";
|
|
o.optional = true;
|
|
o.modalonly = true;
|
|
o.datatype = 'uinteger';
|
|
o.validate = function(section_id, formvalue) {
|
|
|
|
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;
|
|
|
|
if (force_to_sec != 0 && force_to_sec < check_to_sec)
|
|
return _("Values lower than 'Check Interval' except '0' are invalid");
|
|
|
|
return true;
|
|
};
|
|
|
|
o = s.taboption("timer", form.ListValue, "force_unit",
|
|
_('Force Unit'),
|
|
_("Interval unit for forced updates sent to DDNS Provider."));
|
|
o.modalonly = true;
|
|
o.optional = true;
|
|
o.value("minutes", _("minutes"));
|
|
o.value("hours", _("hours"));
|
|
o.value("days", _("days"));
|
|
|
|
o = s.taboption("timer", form.Value, "retry_max_count",
|
|
_("Error Max Retry Counter"),
|
|
_("On Error the script will stop execution after the given number of retries.")
|
|
+ "<br />" +
|
|
_("The default setting of '0' will retry infinitely."));
|
|
o.placeholder = "0";
|
|
o.optional = true;
|
|
o.modalonly = true;
|
|
o.datatype = 'uinteger';
|
|
|
|
o = s.taboption("timer", form.Value, "retry_interval",
|
|
_("Error Retry Interval"),
|
|
_("The interval between which each subsequent retry commences."));
|
|
o.placeholder = "60";
|
|
o.optional = true;
|
|
o.modalonly = true;
|
|
o.datatype = 'uinteger';
|
|
|
|
o = s.taboption("timer", form.ListValue, "retry_unit",
|
|
_('Retry Unit'),
|
|
_("Which time units to use for retry counters."));
|
|
o.modalonly = true;
|
|
o.optional = true;
|
|
o.value("seconds", _("seconds"));
|
|
o.value("minutes", _("minutes"));
|
|
|
|
o = s.taboption('logview', form.Button, '_read_log');
|
|
o.title = '';
|
|
o.depends('use_logfile','1');
|
|
o.modalonly = true;
|
|
o.inputtitle = _('Read / Reread log file');
|
|
o.inputstyle = 'apply';
|
|
o.onclick = L.bind(function(ev, section_id) {
|
|
return _this.callGetLogServices(section_id).then(L.bind(log_box.update_log, log_box));
|
|
}, this);
|
|
|
|
var log_box = s.taboption("logview", form.DummyValue, "_logview");
|
|
log_box.depends('use_logfile','1');
|
|
log_box.modalonly = true;
|
|
|
|
log_box.update_log = L.bind(function(view, log_data) {
|
|
return document.getElementById('syslog').textContent = log_data.result;
|
|
}, o, this);
|
|
|
|
log_box.render = L.bind(function() {
|
|
return E([
|
|
E('p', {}, _('This is the current content of the log file in %h for this service.').format(logdir)),
|
|
E('p', {}, E('textarea', { 'style': 'width:100%; font-size: 10px', 'rows': 20, 'readonly' : 'readonly', 'id' : 'syslog' }, _('Please press [Read] button') ))
|
|
]);
|
|
}, o, this);
|
|
}
|
|
|
|
for (var i = 0; i < s.children.length; i++) {
|
|
o = s.children[i];
|
|
switch (o.option) {
|
|
case '_switch_proto':
|
|
o.depends({ service_name : service, use_ipv6: ipv6, "!reverse": true })
|
|
continue;
|
|
case 'enabled':
|
|
case 'service_name':
|
|
case 'use_ipv6':
|
|
case 'update_script':
|
|
case 'update_url':
|
|
case 'lookup_host':
|
|
continue;
|
|
|
|
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;
|
|
}
|
|
else
|
|
o.depends({service_name: service, use_ipv6: ipv6 });
|
|
}
|
|
}
|
|
}, this)
|
|
)};
|
|
|
|
o = s.option(form.DummyValue, '_cfg_status', _('Status'));
|
|
o.modalonly = false;
|
|
o.textvalue = section_id => resolved[section_id]?.pid
|
|
? `<b>${_('Running')}</b> : ${resolved[section_id].pid}`
|
|
: `<b>${_('Not Running')}</b>`;
|
|
|
|
|
|
o = s.option(form.DummyValue, '_cfg_name', _('Name'));
|
|
o.modalonly = false;
|
|
o.textvalue = function(section_id) {
|
|
return '<b>' + section_id + '</b>';
|
|
};
|
|
|
|
o = s.option(form.DummyValue, '_cfg_detail_ip', _('Lookup Hostname') + "<br />" + _('Registered IP'));
|
|
o.rawhtml = true;
|
|
o.modalonly = false;
|
|
o.textvalue = function(section_id) {
|
|
var host = uci.get('ddns', section_id, 'lookup_host') || _('Configuration Error'),
|
|
ip = _('No Data');
|
|
if (resolved[section_id] && resolved[section_id].ip)
|
|
ip = resolved[section_id].ip;
|
|
|
|
return host + '<br />' + ip;
|
|
};
|
|
|
|
o = s.option(form.Flag, 'enabled', _('Enabled'));
|
|
o.rmempty = false;
|
|
o.editable = true;
|
|
o.modalonly = false;
|
|
|
|
o = s.option(form.DummyValue, '_cfg_update', _('Last Update') + "<br />" + _('Next Update'));
|
|
o.rawhtml = true;
|
|
o.modalonly = false;
|
|
o.textvalue = function(section_id) {
|
|
var last_update = _('Never'), next_update = _('Unknown');
|
|
if (resolved[section_id]) {
|
|
if (resolved[section_id].last_update)
|
|
last_update = resolved[section_id].last_update;
|
|
if (resolved[section_id].next_update)
|
|
next_update = _this.NextUpdateStrings[resolved[section_id].next_update] || resolved[section_id].next_update;
|
|
}
|
|
|
|
return last_update + '<br />' + next_update;
|
|
};
|
|
|
|
return m.render().then(L.bind(function(m, nodes) {
|
|
poll.add(L.bind(function() {
|
|
return Promise.all([
|
|
this.callDDnsGetServicesStatus(),
|
|
this.callDDnsGetStatus()
|
|
]).then(L.bind(this.poll_status, this, nodes));
|
|
}, this), 5);
|
|
return nodes;
|
|
}, this, m));
|
|
}
|
|
});
|