diff options
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', ' '); - 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 = ' '; + 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', ' '); + 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 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 = ' '; + 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', ' '); + 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" ] |