summaryrefslogtreecommitdiffhomepage
path: root/applications
diff options
context:
space:
mode:
authorFlorian Eckert <fe@dev.tdt.de>2020-10-02 15:54:25 +0200
committerGitHub <noreply@github.com>2020-10-02 15:54:25 +0200
commitd61a1c1241b4323e60ad7f9724e97e5871ce96ae (patch)
treec1bbd6250a906f1a27b775dee0e5f4de56231506 /applications
parentadc89f77d0bcd4945710a56600c1fbd0c2c73fae (diff)
parente478875c6c8756d3a8ff612c333a38d2f3f9cc8e (diff)
Merge pull request #4471 from Ansuel/ddns-refresh
luci-app-ddns: rework with new ddns changes
Diffstat (limited to 'applications')
-rw-r--r--applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js1344
-rwxr-xr-xapplications/luci-app-ddns/root/usr/libexec/rpcd/luci.ddns3
-rw-r--r--applications/luci-app-ddns/root/usr/share/rpcd/acl.d/luci-app-ddns.json8
3 files changed, 776 insertions, 579 deletions
diff --git a/applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js b/applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js
index 46f33d092..28c96da38 100644
--- a/applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js
+++ b/applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js
@@ -1,4 +1,5 @@
'use strict';
+'require ui';
'require view';
'require dom';
'require poll';
@@ -8,43 +9,40 @@
'require form';
'require tools.widgets as widgets';
-var callGetLogServices, callInitAction, callDDnsGetStatus;
-
-var NextUpdateStrings = {};
-
-NextUpdateStrings = {
- 'Verify' : _("Verify"),
- 'Run once' : _("Run once"),
- 'Disabled' : _("Disabled"),
- 'Stopped' : _("Stopped")
-}
+return view.extend({
-var time_res = {};
-time_res['seconds'] = 1;
-time_res['minutes'] = 60;
-time_res['hours'] = 3600;
+ NextUpdateStrings : {
+ 'Verify' : _("Verify"),
+ 'Run once' : _("Run once"),
+ 'Disabled' : _("Disabled"),
+ 'Stopped' : _("Stopped")
+ },
-callGetLogServices = rpc.declare({
- object: 'luci.ddns',
- method: 'get_services_log',
- params: [ 'service_name' ],
- expect: { },
-});
+ time_res : {
+ seconds : 1,
+ minutes : 60,
+ hours : 3600,
+ },
-callInitAction = rpc.declare({
- object: 'luci',
- method: 'setInitAction',
- params: [ 'name', 'action' ],
- expect: { result: false }
-});
+ callGetLogServices: rpc.declare({
+ object: 'luci.ddns',
+ method: 'get_services_log',
+ params: [ 'service_name' ],
+ expect: { },
+ }),
-callDDnsGetStatus = rpc.declare({
- object: 'luci.ddns',
- method: 'get_ddns_state',
- expect: { }
-});
+ callInitAction: rpc.declare({
+ object: 'luci',
+ method: 'setInitAction',
+ params: [ 'name', 'action' ],
+ expect: { result: false }
+ }),
-return view.extend({
+ callDDnsGetStatus: rpc.declare({
+ object: 'luci.ddns',
+ method: 'get_ddns_state',
+ expect: { }
+ }),
callDDnsGetEnv: rpc.declare({
object: 'luci.ddns',
@@ -58,14 +56,137 @@ return view.extend({
expect: { }
}),
+ services: {},
+
+ /*
+ * Services list is gen by 3 different source:
+ * 1. /usr/share/ddns/default contains the service installed by opkg
+ * 2. /usr/share/ddns/custom contains any service installed by the
+ * user or the ddns script (for example when service are
+ * downloaded)
+ * 3. /usr/share/ddns/list contains all the service 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
+ });
+
+ list_service.forEach(function (service) {
+ if (!_this.services[service])
+ _this.services[service] = false;
+ });
+ }, this))
+ },
+
+ /*
+ * Check if 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 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', 'enabled')
+ .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');
+ 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([], [
@@ -101,7 +222,7 @@ return view.extend({
if (service[section_id].last_update)
last_update = service[section_id].last_update;
if (service[section_id].next_update)
- next_update = NextUpdateStrings[service[section_id].next_update] || 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;
}
@@ -117,10 +238,9 @@ return view.extend({
load: function() {
return Promise.all([
this.callDDnsGetServicesStatus(),
- callDDnsGetStatus(),
+ this.callDDnsGetStatus(),
this.callDDnsGetEnv(),
- fs.lines('/etc/ddns/services'),
- fs.lines('/etc/ddns/services_ipv6'),
+ this.callGenServiceList(),
uci.load('ddns')
]);
},
@@ -131,20 +251,7 @@ return view.extend({
var env = data[2] || [];
var logdir = uci.get('ddns', 'global', 'ddns_logdir') || "/var/log/ddns";
- var services4 = [];
- var services6 = [];
-
- data[3].forEach(function(item) {
- if (!item.startsWith("#")) {
- services4.push(item.split('\t')[0].slice(1,-1));
- }
- });
-
- data[4].forEach(function(item) {
- if (!item.startsWith("#")) {
- services6.push(item.split('\t')[0].slice(1,-1));
- }
- });
+ var _this = this;
var m, s, o;
@@ -170,33 +277,29 @@ return view.extend({
return res ? _('DDNS Autostart enabled') : _('DDNS Autostart disabled')
};
- o = s.taboption('info', form.DummyValue, '_toggle', '&#160;');
- o.cfgvalue = function() {
- var action = status['_enabled'] ? 'stop' : 'start';
- return E([], [
- E('button', {
- 'class': 'cbi-button cbi-button-apply',
- 'click': L.ui.createHandlerFn(this, function() {
- return callDDnsGetStatus().then(L.bind(function(data) {
- return callInitAction('ddns', action == 'stop' ? 'disable' : 'enable').then(function() {
- return callInitAction('ddns', action);
- });
- }, this)).then(L.bind(m.render, m));
- })
- }, _(action.toUpperCase() + ' DDns'))]);
- };
+ o = s.taboption('info', form.Button, '_toggle');
+ o.title = '&#160;';
+ o.inputtitle = _((status['_enabled'] ? 'stop' : 'start').toUpperCase() + ' DDns');
+ o.inputstyle = 'apply';
+ o.onclick = L.bind(this.handleToggleDDns, this, m);
- o = s.taboption('info', form.DummyValue, '_restart', '&#160;');
+ o = s.taboption('info', form.Button, '_restart');
+ o.title = '&#160;';
+ 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 E([], [
- E('button', {
- 'class': 'cbi-button cbi-button-apply',
- 'click': L.ui.createHandlerFn(this, function() {
- return callInitAction('ddns', 'restart').then(L.bind(m.render, m));
- })
- }, _('Restart DDns'))]);
+ return status[this.option];
};
+ o = s.taboption('info', form.Button, '_refresh_services');
+ o.title = '&#160;';
+ o.inputtitle = _('Update DDns Services List');
+ o.inputstyle = 'apply';
+ o.onclick = L.bind(this.handleRefreshServicesList, this, m);
+
// DDns hints
if (!env['has_ipv6']) {
@@ -344,6 +447,14 @@ return view.extend({
}
+ o = s.taboption('global', form.Value, 'cacert', _('Ca Certs path'));
+ o.description = _('Ca Certs path that will be used to download services data. Set IGNORE to skip certificate validation.');
+ o.placeholder = 'IGNORE';
+
+ o = s.taboption('global', form.Value, 'services_url', _('Services URL Download'));
+ o.description = _('Url used to download services file. By default is 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;
@@ -354,9 +465,25 @@ return view.extend({
s.addremove = true;
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 == null || section_id == '' || service_value == null || section_id == '' || ipv6_value == null || ipv6_value == '')
+ return;
+
+ return m.save(function() {
+ uci.add('ddns', 'service', section_id);
+ uci.set('ddns', section_id, 'service_name', service_value);
+ uci.set('ddns', section_id, 'use_ipv6', ipv6_value);
+ }).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_');
+ s2 = m2.section(form.NamedSection, '_new_'),
+ name, ipv6, service_name;
s2.render = function() {
return Promise.all([
@@ -376,26 +503,41 @@ return view.extend({
return true;
};
+ ipv6 = s2.option( form.ListValue, 'use_ipv6',
+ _("IP address version"),
+ _("Defines which IP address 'IPv4/IPv6' is send to the DDNS provider"));
+ 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") + " --");
+ for (var elem in _this.services)
+ service_name.value(elem);
+ 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;
+ };
+
+ 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) {
- L.ui.showModal(_('Add new services...'), [
+ ui.showModal(_('Add new services...'), [
nodes,
E('div', { 'class': 'right' }, [
E('button', {
'class': 'btn',
- 'click': L.ui.hideModal
+ 'click': ui.hideModal
}, _('Cancel')), ' ',
E('button', {
'class': 'cbi-button cbi-button-positive important',
- 'click': L.ui.createHandlerFn(this, function(ev) {
- var nameval = name.isValid('_new_') ? name.formvalue('_new_') : null;
-
- if (nameval == null || nameval == '')
- return;
-
- return m.save(function() {
- uci.add('ddns', 'service', nameval);
- }).then(L.bind(m.children[1].renderMoreOptionsModal, m.children[1], nameval));
- })
+ 'click': ui.createHandlerFn(this, 'handleCreateDDnsRule', m, name, service_name, ipv6)
}, _('Create service'))
])
], 'cbi-modal');
@@ -409,18 +551,12 @@ return view.extend({
cfg_enabled = uci.get('ddns', section_id, 'enabled'),
reload_opt = {
'class': 'cbi-button cbi-button-neutral reload',
- 'click': L.ui.createHandlerFn(this, function() {
- return fs.exec('/usr/lib/ddns/dynamic_dns_lucihelper.sh',
- [ '-S', section_id, '--', 'start' ]).then(L.bind(m.render, m));
- }),
+ 'click': ui.createHandlerFn(_this, 'handleReloadDDnsRule', m, section_id),
'title': _('Reload this service'),
},
stop_opt = {
'class': 'cbi-button cbi-button-neutral stop',
- 'click': L.ui.createHandlerFn(this, function() {
- return fs.exec('/usr/lib/ddns/dynamic_dns_lucihelper.sh',
- [ '-S', section_id, '--', 'start' ]).then(L.bind(m.render, m));
- }),
+ 'click': ui.createHandlerFn(_this, 'HandleStopDDnsRule', m, section_id),
'title': _('Stop this service'),
};
@@ -442,11 +578,544 @@ return view.extend({
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;
+
+ 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;
+ }
+ }
+
+ 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 could 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, if IP update happen or 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"),
+ _("Defines which IP address 'IPv4/IPv6' is send to the DDNS provider"));
+ 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") + " --");
+ for (var elem in _this.services)
+ service_name.value(elem);
+ service_name.cfgvalue = function(section_id) {
+ return uci.get('ddns', section_id, 'service_name') || '-';
+ };
+ service_name.write = function(section_id, service) {
+ if (service != '-') {
+ uci.set('ddns', section_id, 'update_url', null);
+ uci.set('ddns', section_id, 'update_script', null);
+ return uci.set('ddns', section_id, 'service_name', service);
+ }
+ return uci.set('ddns', section_id, 'service_name', null);
+ };
+ 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;
+ };
+
+ 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', '&nbsp');
+ o.cfgvalue = function () {
+ return _("Service doesn't support this ip type")
+ };
+ }
+
+ 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 to be used for updating your DDNS Provider.")
+ + "<br />" +
+ _("Follow instructions you will find 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.children.filter(function(o) { return o.option == 'update_script' })[0].formvalue(section_id);
+
+ if ((value == "" && other == "") || (value != "" && other != "")) {
+ return _("Insert a Update Script OR a Update URL");
+ }
+
+ return true;
+ };
+
+ o = s.taboption('basic', form.Value, 'update_script',
+ _("Custom update-script"),
+ _("Custom update script to be used for updating your DDNS Provider."));
+ 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 a Update Script OR a Update URL");
+ }
+
+ return true;
+ };
+
+ o = s.taboption('basic', form.Value, 'domain',
+ _("Domain"),
+ _("Replaces [USERNAME] 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)"));
+ 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 = 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"));
+ 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.set('ddns', section_id, "ip_url",null);
+ uci.set('ddns', section_id, "ip_interface",null);
+ uci.set('ddns', section_id, "ip_script",null);
+ 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);
+ 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);
+ 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);
+ 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';
+
+ o = s.taboption('advanced', form.Value, 'ip_script',
+ _("Script"),
+ _("User defined script to read systems IP-Address"));
+ o.modalonly = true;
+ o.depends("ip_source", "script")
+ o.placeholder = "/path/to/script.sh"
+
+ o = s.taboption('advanced', widgets.DeviceSelect, '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.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);
+ return uci.set('ddns', section_id, 'interface', val);
+ };
+
+ if (env['has_bindnet']) {
+ o = s.taboption('advanced', widgets.ZoneSelect, '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 = "30";
+ 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),
+ 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.default = "minutes"
+ 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")
+ + "<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.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),
+ 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 'Check Interval' except '0' are not supported");
+
+ return true;
+ };
+
+ o = s.taboption("timer", form.ListValue, "force_unit",
+ _('Force Unit'),
+ _("Interval unit to force updates send to DDNS Provider"));
+ o.modalonly = true;
+ o.optional = true;
+ o.default = "minutes"
+ o.value("minutes", _("minutes"));
+ o.value("hours", _("hours"));
+ o.value("days", _("days"));
+
+ o = s.taboption("timer", form.Value, "retry_count",
+ _("Error Retry Counter"),
+ _("On Error the script will stop execution after given number of retrys")
+ + "<br />" +
+ _("The default setting of '0' will retry infinite."));
+ o.placeholder = "0";
+ o.optional = true;
+ o.modalonly = true;
+ o.datatype = 'uinteger';
+
+ o = s.taboption("timer", form.Value, "retry_interval",
+ _("Error Retry Interval"),
+ _("On Error the script will stop execution after given number of retrys")
+ + "<br />" +
+ _("The default setting of '0' will retry infinite."));
+ o.placeholder = "60";
+ o.optional = true;
+ o.modalonly = true;
+ o.datatype = 'uinteger';
+
+ o = s.taboption("timer", form.ListValue, "retry_unit",
+ _('Retry Unit'),
+ _("On Error the script will retry the failed action after given time"));
+ o.modalonly = true;
+ o.optional = true;
+ o.default = "seconds"
+ 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('log_area').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 ') + logdir + ' for this service.'),
+ E('p', {}, E('textarea', { 'style': 'width:100%', 'rows': 20, 'readonly' : 'readonly', 'id' : 'log_area' }, _('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 = function(section_id) {
+ var text = '<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;
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;
@@ -474,496 +1143,17 @@ return view.extend({
if (resolved[section_id].last_update)
last_update = resolved[section_id].last_update;
if (resolved[section_id].next_update)
- next_update = NextUpdateStrings[resolved[section_id].next_update] || 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;
};
- s.modaltitle = function(section_id) {
- return _('DDns Service') + ' » ' + section_id;
- };
-
- o = s.option(form.DummyValue, '_cfg_status', _('Status'));
- o.modalonly = false;
- o.textvalue = function(section_id) {
- var text = '<b>' + _('Not Running') + '</b>';
-
- if (resolved[section_id] && resolved[section_id].pid)
- text = '<b>' + _('Running') + '</b> : ' + resolved[section_id].pid;
-
- return text;
- }
-
-
- 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 could 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, if IP update happen or necessary"));
- o.rmempty = false;
- o.placeholder = "myhost.example.com";
- o.datatype = 'and(minlength(3),hostname("strict"))';
- o.modalonly = true;
-
- o = s.taboption('basic', form.ListValue, 'use_ipv6',
- _("IP address version"),
- _("Defines which IP address 'IPv4/IPv6' is send to the DDNS provider"));
- o.default = '0';
- o.modalonly = true;
- o.rmempty = false;
- o.value("0", _("IPv4-Address"))
- if (env["has_ipv6"]) {
- o.value("1", _("IPv6-Address"))
- }
-
- o = s.taboption('basic', form.ListValue, 'ipv4_service_name',
- String.format('%s %s', _("DDNS Service provider"), "[IPv4]"));
- o.depends("use_ipv6", "0")
- o.modalonly = true;
- o.value('-',"-- " + _("custom") + " --");
- for (var i = 0; i < services4.length; i++)
- o.value(services4[i]);
- o.cfgvalue = function(section_id) {
- return uci.get('ddns', section_id, 'service_name') || '-';
- };
- o.write = function(section_id, formvalue) {
- if (formvalue != '-') {
- uci.set('ddns', section_id, 'update_url', null);
- uci.set('ddns', section_id, 'update_script', null);
- return uci.set('ddns', section_id, 'service_name', formvalue);
- }
- return uci.set('ddns', section_id, 'service_name', null);
- };
-
- o = s.taboption('basic', form.ListValue, 'ipv6_service_name',
- String.format('%s %s', _("DDNS Service provider"), "[IPv6]"));
- o.depends("use_ipv6", "1")
- o.modalonly = true;
- o.value('-',"-- " + _("custom") + " --");
- for (var i = 0; i < services6.length; i++) {
- o.value(services6[i]);
- }
- o.cfgvalue = function(section_id) {
- var service = uci.get('ddns', section_id, 'service_name'),
- update_script = uci.get('ddns', section_id, 'update_script'),
- update_url = uci.get('ddns', section_id, 'update_url');
-
- if (!service && (update_script || update_url))
- return "-";
-
- return service;
- };
- o.write = function(section_id, formvalue) {
- if (formvalue != '-') {
- uci.set('ddns', section_id, 'update_url', null);
- uci.set('ddns', section_id, 'update_script', null);
- return uci.set('ddns', section_id, 'service_name', formvalue);
- }
- return uci.set('ddns', section_id, 'service_name', null);
- };
-
- o = s.taboption('basic', form.Value, 'update_url',
- _("Custom update-URL"),
- _("Update URL to be used for updating your DDNS Provider.")
- + "<br />" +
- _("Follow instructions you will find on their WEB page."));
- o.modalonly = true;
- o.rmempty = true;
- o.optional = true;
- o.depends("ipv6_service_name","-");
- o.depends("ipv4_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 a Update Script OR a Update URL");
- }
-
- return true;
- };
-
- o = s.taboption('basic', form.Value, 'update_script',
- _("Custom update-script"),
- _("Custom update script to be used for updating your DDNS Provider."));
- o.modalonly = true;
- o.rmempty = true;
- o.optional = true;
- o.depends("ipv6_service_name","-");
- o.depends("ipv4_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 a Update Script OR a Update URL");
- }
-
- return true;
- };
-
- o = s.taboption('basic', form.Value, 'domain',
- _("Domain"),
- _("Replaces [USERNAME] 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)"));
- 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 = 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"));
- 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.set('ddns', section_id, "ip_url",null);
- uci.set('ddns', section_id, "ip_interface",null);
- uci.set('ddns', section_id, "ip_script",null);
- 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);
- 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);
- 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);
- 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';
-
- o = s.taboption('advanced', form.Value, 'ip_script',
- _("Script"),
- _("User defined script to read systems IP-Address"));
- o.modalonly = true;
- o.depends("ip_source", "script")
- o.placeholder = "/path/to/script.sh"
-
- o = s.taboption('advanced', widgets.DeviceSelect, '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.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);
- return uci.set('ddns', section_id, 'interface', val);
- };
-
- if (env['has_bindnet']) {
- o = s.taboption('advanced', widgets.ZoneSelect, '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 = "30";
- 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),
- time_to_sec = 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.default = "minutes"
- 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")
- + "<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.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),
- check_to_sec = time_res[check_unit || 'minutes'] * ( check_val || '30'),
- force_to_sec = time_res[force_unit || 'minutes'] * formvalue;
-
- if (force_to_sec != 0 && force_to_sec < check_to_sec)
- return _("Values lower 'Check Interval' except '0' are not supported");
-
- return true;
- };
-
- o = s.taboption("timer", form.ListValue, "force_unit",
- _('Force Unit'),
- _("Interval unit to force updates send to DDNS Provider"));
- o.modalonly = true;
- o.optional = true;
- o.default = "minutes"
- o.value("minutes", _("minutes"));
- o.value("hours", _("hours"));
- o.value("days", _("days"));
-
- o = s.taboption("timer", form.Value, "retry_count",
- _("Error Retry Counter"),
- _("On Error the script will stop execution after given number of retrys")
- + "<br />" +
- _("The default setting of '0' will retry infinite."));
- o.placeholder = "0";
- o.optional = true;
- o.modalonly = true;
- o.datatype = 'uinteger';
-
- o = s.taboption("timer", form.Value, "retry_interval",
- _("Error Retry Interval"),
- _("On Error the script will stop execution after given number of retrys")
- + "<br />" +
- _("The default setting of '0' will retry infinite."));
- o.placeholder = "60";
- o.optional = true;
- o.modalonly = true;
- o.datatype = 'uinteger';
-
- o = s.taboption("timer", form.ListValue, "retry_unit",
- _('Retry Unit'),
- _("On Error the script will retry the failed action after given time"));
- o.modalonly = true;
- o.optional = true;
- o.default = "seconds"
- o.value("seconds", _("seconds"));
- o.value("minutes", _("minutes"));
-
-
- o = s.taboption("logview", form.DummyValue, '_read_log', '');
- o.depends('use_logfile','1');
- o.modalonly = true;
- o.cfgvalue = function(section_id) {
- return E([], [
- E('button', {
- 'class': 'cbi-button cbi-button-apply',
- 'click': L.ui.createHandlerFn(this, function() {
- var o = this.section.children.filter(function(o) { return o.option == '_logview' })[0];
- return callGetLogServices(section_id).then(L.bind(o.update_log, o));
- })
- }, _('Read / Reread log file'))]);
- };
-
- o = s.taboption("logview", form.DummyValue, "_logview");
- o.depends('use_logfile','1');
- o.modalonly = true;
-
- o.update_log = L.bind(function(view, log_data) {
- return document.getElementById('log_area').textContent = log_data.result;
- }, o, this)
-
- o.render = L.bind(function() {
- return E([
- E('p', {}, _('This is the current content of the log file in ') + logdir + ' for this service.'),
- E('p', {}, E('textarea', { 'style': 'width:100%', 'rows': 20, 'readonly' : 'readonly', 'id' : 'log_area' }, _('Please press [Read] button') ))
- ]);
- }, o, this)
-
return m.render().then(L.bind(function(m, nodes) {
poll.add(L.bind(function() {
return Promise.all([
this.callDDnsGetServicesStatus(),
- callDDnsGetStatus()
+ this.callDDnsGetStatus()
]).then(L.bind(this.poll_status, this, nodes));
}, this), 5);
return nodes;
diff --git a/applications/luci-app-ddns/root/usr/libexec/rpcd/luci.ddns b/applications/luci-app-ddns/root/usr/libexec/rpcd/luci.ddns
index 7710ee66f..0a60142e6 100755
--- a/applications/luci-app-ddns/root/usr/libexec/rpcd/luci.ddns
+++ b/applications/luci-app-ddns/root/usr/libexec/rpcd/luci.ddns
@@ -7,6 +7,7 @@ local UCI = require "luci.model.uci"
local sys = require "luci.sys"
local util = require "luci.util"
+local ddns_package_path = "/usr/share/ddns"
local luci_helper = "/usr/lib/ddns/dynamic_dns_lucihelper.sh"
local srv_name = "ddns-scripts"
@@ -155,6 +156,7 @@ local methods = {
local ipkg = require "luci.model.ipkg"
local uci = UCI.cursor()
local dateformat = uci:get("ddns", "global", "ddns_dateformat") or "%F %R"
+ local services_mtime = fs.stat(ddns_package_path .. "/list", 'mtime')
uci:unload("ddns")
local ver, srv_ver_cmd
local res = {}
@@ -169,6 +171,7 @@ local methods = {
res['_version'] = ver and #ver > 0 and ver or nil
res['_enabled'] = sys.init.enabled("ddns")
res['_curr_dateformat'] = os.date(dateformat)
+ res['_services_list'] = services_mtime and os.date(dateformat, services_mtime) or 'NO_LIST'
return res
end
diff --git a/applications/luci-app-ddns/root/usr/share/rpcd/acl.d/luci-app-ddns.json b/applications/luci-app-ddns/root/usr/share/rpcd/acl.d/luci-app-ddns.json
index 94952792f..298378452 100644
--- a/applications/luci-app-ddns/root/usr/share/rpcd/acl.d/luci-app-ddns.json
+++ b/applications/luci-app-ddns/root/usr/share/rpcd/acl.d/luci-app-ddns.json
@@ -7,8 +7,12 @@
"luci": [ "setInitAction" ]
},
"file": {
- "/etc/ddns/services": [ "read" ],
- "/etc/ddns/services_ipv6": [ "read" ],
+ "/usr/share/ddns/default": [ "list" ],
+ "/usr/share/ddns/default/*": [ "read" ],
+ "/usr/share/ddns/custom": [ "list" ],
+ "/usr/share/ddns/custom/*": [ "read" ],
+ "/usr/share/ddns/list": [ "read" ],
+ "/usr/bin/ddns": [ "exec" ],
"/usr/lib/ddns/dynamic_dns_lucihelper.sh": [ "exec" ]
},
"uci": [ "ddns" ]