luci-app-ddns: diverse fixes, i18n corrections, and code improvements

-trimmed redundant and repeated code
-fixed adding a new service section, which... never worked.
-removed some defaults
-changed log formatting
-opkg -> package-manager

Signed-off-by: Paul Donald <newtwen+github@gmail.com>
This commit is contained in:
Paul Donald
2024-11-29 03:02:36 +01:00
parent 96afb61faa
commit 8d26279bab
40 changed files with 8835 additions and 8997 deletions

View File

@@ -60,7 +60,7 @@ return view.extend({
/*
* Services list is generated by 3 different sources:
* 1. /usr/share/ddns/default contains the service installed by opkg
* 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)
@@ -167,7 +167,7 @@ return view.extend({
},
handleToggleDDns: function(m, ev) {
return this.callInitAction('ddns', 'enabled')
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))
@@ -218,7 +218,7 @@ return view.extend({
service_status = '<b>' + _('Not Running') + '</b>';
if (service[section_id]) {
stop.disabled = (!service[section_id].pid || (service[section_id].pid && cfg_enabled == '1'));
stop.disabled = (!service[section_id].pid);
if (service[section_id].ip)
ip = service[section_id].ip;
if (service[section_id].last_update)
@@ -308,17 +308,17 @@ return view.extend({
o = s.taboption('info', form.DummyValue, '_no_ipv6');
o.rawhtml = true;
o.title = '<b>' + _("IPv6 not supported") + '</b>';
o.cfgvalue = function() { return _("IPv6 is currently not (fully) supported by this system") + "<br />" +
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", "opkg")
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 installed to support secure updates via HTTPS protocol.") +
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 />- " +
@@ -327,10 +327,12 @@ return view.extend({
if (!env['has_bindnet']) {
o = s.taboption('info', form.DummyValue, '_no_bind_network');
o.titleref = L.url("admin", "system", "opkg")
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 installed to select a network to use for communication.") +
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 />- " +
@@ -341,7 +343,7 @@ return view.extend({
if (!env['has_proxy']) {
o = s.taboption('info', form.DummyValue, '_no_proxy');
o.titleref = L.url("admin", "system", "opkg")
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.") +
@@ -351,43 +353,32 @@ return view.extend({
_("In some versions cURL/libcurl in OpenWrt is compiled without proxy support.")};
}
if (!env['has_forceip']) {
o = s.taboption('info', form.DummyValue, '_no_force_ip');
o.titleref = L.url("admin", "system", "opkg")
o.rawhtml = true;
o.title = '<b>' + _("Force IP Version not supported") + '</b>';
o.cfgvalue = function() { return _("BusyBox's nslookup and Wget do not support to specify " +
"the IP version to use for communication with DDNS Provider!") +
"<br />- " + _("You should install 'wget' or 'curl' or 'uclient-fetch' package.")
};
}
if (!env['has_bindhost']) {
o = s.taboption('info', form.DummyValue, '_no_dnstcp');
o.titleref = L.url("admin", "system", "opkg")
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 to specify to use TCP " +
"instead of default UDP when requesting DNS server!") +
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 />- " +
_("You should install 'bind-host' or 'knot-host' or 'drill' package for DNS requests.")};
_("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", "opkg")
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, " +
"<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", "opkg")
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!") +
@@ -403,7 +394,7 @@ return view.extend({
+ '<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"';
+ '::/32, f000::/4';
o.default = "0";
o.optional = true;
@@ -466,9 +457,6 @@ return view.extend({
s.anonymous = true;
s.addremove = true;
s.addbtntitle = _('Add new services...');
s.anonymous = true;
s.addremove = true;
s.sortable = true;
s.handleCreateDDnsRule = function(m, name, service_name, ipv6, ev) {
@@ -476,7 +464,7 @@ return view.extend({
service_value = service_name.isValid('_new_') ? service_name.formvalue('_new_') : null,
ipv6_value = ipv6.isValid('_new_') ? ipv6.formvalue('_new_') : null;
if (section_id == null || section_id == '' || service_value == null || section_id == '' || ipv6_value == null || ipv6_value == '')
if (!section_id || !service_value || !ipv6_value)
return;
return m.save(function() {
@@ -485,6 +473,7 @@ return view.extend({
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));
};
@@ -513,7 +502,7 @@ return view.extend({
ipv6 = s2.option( form.ListValue, 'use_ipv6',
_("IP address version"),
_("Defines which IP address 'IPv4/IPv6' is send to the DDNS provider"));
_("Which record type to update at the DDNS provider (A/AAAA)"));
ipv6.default = '0';
ipv6.value("0", _("IPv4-Address"))
if (env["has_ipv6"]) {
@@ -522,11 +511,10 @@ return view.extend({
service_name = s2.option(form.ListValue, 'service_name',
String.format('%s', _("DDNS Service provider")));
service_name.value('-',"-- " + _("custom") + " --");
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 _("Select a service");
if (s2.service_supported == null) return _("Checking the service support...");
if (!s2.service_supported) return _("Service doesn't support this IP type");
return true;
};
@@ -632,7 +620,7 @@ return view.extend({
use_ipv6 = s.taboption('basic', form.ListValue, 'use_ipv6',
_("IP address version"),
_("Defines which IP address 'IPv4/IPv6' is send to the DDNS provider"));
_("Which record type to update at the DDNS provider (A/AAAA)"));
use_ipv6.default = '0';
use_ipv6.modalonly = true;
use_ipv6.rmempty = false;
@@ -644,7 +632,7 @@ return view.extend({
service_name = s.taboption('basic', form.ListValue, 'service_name',
String.format('%s', _("DDNS Service provider")));
service_name.modalonly = true;
service_name.value('-',"-- " + _("custom") + " --");
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') || '-';
@@ -659,7 +647,6 @@ return view.extend({
};
service_name.validate = function(section_id, value) {
if (value == '') return _("Select a service");
if (s.service_available == null) return _("Checking the service support...");
if (!s.service_available) return _('Service not installed');
if (!s.service_supported) return _("Service doesn't support this IP type");
return true;
@@ -711,27 +698,31 @@ return view.extend({
o.optional = true;
o.depends("service_name","-");
o.validate = function(section_id, value) {
var other = this.section.children.filter(function(o) { return o.option == 'update_script' })[0].formvalue(section_id);
if ((value == "" && other == "") || (value != "" && other != "")) {
return _("Insert an Update Script OR an Update URL");
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.Value, 'update_script',
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.browser = true;
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.children.filter(function(o) { return o.option == 'update_url' })[0].formvalue(section_id);
if ((value == "" && other == "") || (value != "" && other != "")) {
return _("Insert an Update Script OR an Update URL");
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;
@@ -798,7 +789,7 @@ return view.extend({
o = s.taboption('advanced', form.ListValue, 'ip_source',
_("IP address source"),
_("Defines the source to read systems IP-Address from, that will be send to the DDNS provider"));
_("Method used to determine the system IP-Address to send in updates"));
o.modalonly = true;
o.default = "network";
o.value("network", _("Network"));
@@ -808,24 +799,24 @@ return view.extend({
o.write = function(section_id, formvalue) {
switch(formvalue) {
case 'network':
uci.set('ddns', section_id, "ip_url",null);
uci.set('ddns', section_id, "ip_interface",null);
uci.set('ddns', section_id, "ip_script",null);
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.set('ddns', section_id, "ip_network",null);
uci.set('ddns', section_id, "ip_interface",null);
uci.set('ddns', section_id, "ip_script",null);
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.set('ddns', section_id, "ip_network",null);
uci.set('ddns', section_id, "ip_url",null);
uci.set('ddns', section_id, "ip_script",null);
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.set('ddns', section_id, "ip_network",null);
uci.set('ddns', section_id, "ip_url",null);
uci.set('ddns', section_id, "ip_interface",null);
uci.unset('ddns', section_id, "ip_network");
uci.unset('ddns', section_id, "ip_url");
uci.unset('ddns', section_id, "ip_interface");
break;
default:
break;
@@ -862,7 +853,7 @@ return view.extend({
o = s.taboption('advanced', form.Value, 'ip_script',
_("Script"),
_("User defined script to read systems IP-Address"));
_("User defined script to read system IP-Address"));
o.modalonly = true;
o.depends("ip_source", "script")
o.placeholder = "/path/to/script.sh"
@@ -887,8 +878,8 @@ return view.extend({
return uci.get('ddns', section_id, 'interface') || _('This will be autoset to the selected interface');
};
o.write = function(section_id) {
var opt = this.section.children.filter(function(o) { return o.option == 'ip_source' })[0].formvalue(section_id);
var val = this.section.children.filter(function(o) { return o.option == 'ip_'+opt })[0].formvalue(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);
};
@@ -973,11 +964,11 @@ return view.extend({
o = s.taboption("timer", form.Value, "check_interval",
_("Check Interval"));
o.placeholder = "30";
o.placeholder = "10";
o.modalonly = true;
o.datatype = 'uinteger';
o.validate = function(section_id, formvalue) {
var unit = this.section.children.filter(function(o) { return o.option == 'check_unit' })[0].formvalue(section_id),
var unit = this.section.formvalue(section_id, 'check_unit'),
time_to_sec = _this.time_res[unit || 'minutes'] * formvalue;
if (formvalue && time_to_sec < 300)
@@ -990,14 +981,14 @@ return view.extend({
_('Check Unit'),
_("Interval unit to check for changed IP"));
o.modalonly = true;
o.default = "minutes"
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 updates send to DDNS Provider")
_("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";
@@ -1009,9 +1000,9 @@ return view.extend({
if (!formvalue)
return true;
var check_unit = this.section.children.filter(function(o) { return o.option == 'check_unit' })[0].formvalue(section_id),
check_val = this.section.children.filter(function(o) { return o.option == 'check_interval' })[0].formvalue(section_id),
force_unit = this.section.children.filter(function(o) { return o.option == 'force_unit' })[0].formvalue(section_id),
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;
@@ -1026,7 +1017,6 @@ return view.extend({
_("Interval unit for forced updates sent to DDNS Provider."));
o.modalonly = true;
o.optional = true;
o.default = "minutes"
o.value("minutes", _("minutes"));
o.value("hours", _("hours"));
o.value("days", _("days"));
@@ -1054,7 +1044,6 @@ return view.extend({
_("Which time units to use for retry counters."));
o.modalonly = true;
o.optional = true;
o.default = "seconds"
o.value("seconds", _("seconds"));
o.value("minutes", _("minutes"));
@@ -1073,13 +1062,13 @@ return view.extend({
log_box.modalonly = true;
log_box.update_log = L.bind(function(view, log_data) {
return document.getElementById('log_area').textContent = log_data.result;
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%', 'rows': 20, 'readonly' : 'readonly', 'id' : 'log_area' }, _('Please press [Read] button') ))
E('p', {}, E('textarea', { 'style': 'width:100%; font-size: 10px', 'rows': 20, 'readonly' : 'readonly', 'id' : 'syslog' }, _('Please press [Read] button') ))
]);
}, o, this);
}
@@ -1113,14 +1102,10 @@ return view.extend({
o = s.option(form.DummyValue, '_cfg_status', _('Status'));
o.modalonly = false;
o.textvalue = function(section_id) {
var text = '<b>' + _('Not Running') + '</b>';
o.textvalue = section_id => resolved[section_id]?.pid
? `<b>${_('Running')}</b> : ${resolved[section_id].pid}`
: `<b>${_('Not Running')}</b>`;
if (resolved[section_id] && resolved[section_id].pid)
text = '<b>' + _('Running') + '</b> : ' + resolved[section_id].pid;
return text;
};
o = s.option(form.DummyValue, '_cfg_name', _('Name'));
o.modalonly = false;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -119,7 +119,7 @@ const methods = {
const dnsServer = s['dns_server'] || '';
const forceIpVersion = int(s['force_ipversion'] || 0);
const forceDnsTcp = int(s['force_dnstcp'] || 0);
const isGlue = int(s['is_glue'] || 0);
// const isGlue = int(s['is_glue'] || 0);
const useIpv6 = int(s['use_ipv6'] || 0);
const lookupHost = s['lookup_host'] || '_nolookup_';
let command = [luci_helper];
@@ -127,7 +127,7 @@ const methods = {
if (useIpv6 == 1) push(command, '-6');
if (forceIpVersion == 1) push(command, '-f');
if (forceDnsTcp == 1) push(command, '-t');
if (isGlue == 1) push(command, '-g');
// if (isGlue == 1) push(command, '-g');
push(command, '-l', lookupHost);
push(command, '-S', section);
@@ -148,12 +148,12 @@ const methods = {
let _uptime = int(uptime());
const forceSeconds = calc_seconds(
const forcedUpdateInterval = calc_seconds(
int(s['force_interval']) || 72,
s['force_unit'] || 'hours'
);
const checkSeconds = calc_seconds(
const checkInterval = calc_seconds(
int(s['check_interval']) || 10,
s['check_unit'] || 'minutes'
);
@@ -163,13 +163,13 @@ const methods = {
const epoch = time() - _uptime + lastUpdate;
convertedLastUpdate = epoch2date(epoch);
// convertedLastUpdate = get_date(epoch, dateFormat);
nextUpdate = epoch2date(epoch + forceSeconds + checkSeconds);
// nextUpdate = get_date(epoch + forceSeconds + checkSeconds, dateFormat);
nextUpdate = epoch2date(epoch + forcedUpdateInterval + checkInterval);
// nextUpdate = get_date(epoch + forcedUpdateInterval + checkInterval, dateFormat);
}
if (pid > 0 && (lastUpdate + forceSeconds + checkSeconds - _uptime) <= 0) {
if (pid > 0 && (lastUpdate + forcedUpdateInterval + checkInterval - _uptime) <= 0) {
nextUpdate = 'Verify';
} else if (forceSeconds === 0) {
} else if (forcedUpdateInterval === 0) {
nextUpdate = 'Run once';
} else if (pid == 0 && s['enabled'] == '0') {
nextUpdate = 'Disabled';
@@ -243,6 +243,13 @@ const methods = {
return result;
};
const hasGNUWgetSsl = () => {
if (cache['has_gnuwgetssl']) return cache['has_gnuwgetssl'];
const result = hasWget() && system(`wget -V 2>&1 | grep -iqF '+https'`) == 0 ? true: false;
cache['has_gnuwgetssl'] = result;
return result;
};
const hasCurl = () => {
if (cache['has_curl']) return cache['has_curl'];
const result = hasCommand('curl');
@@ -277,10 +284,10 @@ const methods = {
res['has_wget'] = hasWget();
res['has_curl'] = hasCurl();
res['has_ssl'] = hasWgetSsl() || hasCurlSsl() || (hasFetch() && hasFetchSsl());
res['has_proxy'] = hasWgetSsl() || hasCurlPxy() || hasFetch() || hasBbwget();
res['has_forceip'] = hasWgetSsl() || hasCurl() || hasFetch();
res['has_bindnet'] = hasCurl() || hasWgetSsl();
res['has_ssl'] = hasGNUWgetSsl()|| hasWgetSsl() || hasCurlSsl() || (hasFetch() && hasFetchSsl());
res['has_proxy'] = hasGNUWgetSsl() || hasWgetSsl() || hasCurlPxy() || hasFetch() || hasBbwget();
res['has_forceip'] = hasGNUWgetSsl() || hasWgetSsl() || hasCurl() || hasFetch();
res['has_bindnet'] = hasCurl() || hasGNUWgetSsl();
const hasBindHost = () => {
if (cache['has_bindhost']) return cache['has_bindhost'];