'use strict'; 'require view'; 'require dom'; 'require poll'; 'require uci'; 'require rpc'; 'require fs'; 'require form'; 'require tools.widgets as widgets'; var callGetLogServices, callInitAction, callDDnsGetStatus; var NextUpdateStrings = {}; NextUpdateStrings = { 'Verify' : _("Verify"), 'Run once' : _("Run once"), 'Disabled' : _("Disabled"), 'Stopped' : _("Stopped") } var time_res = {}; time_res['seconds'] = 1; time_res['minutes'] = 60; time_res['hours'] = 3600; callGetLogServices = rpc.declare({ object: 'luci.ddns', method: 'get_services_log', params: [ 'service_name' ], expect: { }, }); callInitAction = rpc.declare({ object: 'luci', method: 'setInitAction', params: [ 'name', 'action' ], expect: { result: false } }); callDDnsGetStatus = rpc.declare({ object: 'luci.ddns', method: 'get_ddns_state', expect: { } }); return view.extend({ callDDnsGetEnv: rpc.declare({ object: 'luci.ddns', method: 'get_env', expect: { } }), callDDnsGetServicesStatus: rpc.declare({ object: 'luci.ddns', method: 'get_services_status', expect: { } }), 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.innerHTML = status['_enabled'] ? _('Stop DDNS') : _('Start DDNS') dom.content(ddns_enabled, function() { return E([], [ E('div', {}, status['_enabled'] ? _('DDNS Autostart enabled') : [ _('DDNS Autostart disabled'), E('div', { 'class' : 'cbi-value-description' }, _("Currently DDNS updates are not started at boot or on interface events.") + "
" + _("This is the default if you run DDNS scripts by yourself (i.e. via cron with force_interval set to '0')")) ]),]); }); for (var i = 0; i < rows.length; i++) { section_id = rows[i].getAttribute('data-sid'); cfg_detail_ip = rows[i].querySelector('[data-name="_cfg_detail_ip"]'); cfg_update = rows[i].querySelector('[data-name="_cfg_update"]'); cfg_status = rows[i].querySelector('[data-name="_cfg_status"]'); reload = rows[i].querySelector('.cbi-section-actions .reload'); stop = rows[i].querySelector('.cbi-section-actions .stop'); cfg_enabled = uci.get('ddns', section_id, 'enabled'); reload.disabled = (status['_enabled'] == 0 || cfg_enabled == 0); host = uci.get('ddns', section_id, 'lookup_host') || _('Configuration Error'); ip = _('No Data'); last_update = _('Never'); next_update = _('Unknown'); service_status = '' + _('Not Running') + ''; if (service[section_id]) { stop.disabled = (!service[section_id].pid || (service[section_id].pid && cfg_enabled == '1')); if (service[section_id].ip) ip = service[section_id].ip; if (service[section_id].last_update) last_update = service[section_id].last_update; if (service[section_id].next_update) next_update = NextUpdateStrings[service[section_id].next_update] || service[section_id].next_update; if (service[section_id].pid) service_status = '' + _('Running') + ' : ' + service[section_id].pid; } cfg_detail_ip.innerHTML = host + '
' + ip; cfg_update.innerHTML = last_update + '
' + next_update; cfg_status.innerHTML = service_status; } return; }, load: function() { return Promise.all([ this.callDDnsGetServicesStatus(), callDDnsGetStatus(), this.callDDnsGetEnv(), fs.lines('/etc/ddns/services'), fs.lines('/etc/ddns/services_ipv6'), uci.load('ddns') ]); }, render: function(data) { var resolved = data[0] || []; var status = data[1] || []; var env = data[2] || []; var logdir = uci.get('ddns', 'global', 'ddns_logdir') || "/var/log/ddns"; var 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 m, s, o; m = new form.Map('ddns', _('Dynamic DNS')); s = m.section(form.NamedSection, 'global', 'ddns',); s.tab('info', _('Information')); s.tab('global', _('Global Settings')); o = s.taboption('info', form.DummyValue, '_version', _('Dynamic DNS Version')); o.cfgvalue = function() { return status[this.option]; }; o = s.taboption('info', form.DummyValue, '_enabled', _('State')); o.cfgvalue = function() { var res = status[this.option]; if (!res) { this.description = _("Currently DDNS updates are not started at boot or on interface events.") + "
" + _("This is the default if you run DDNS scripts by yourself (i.e. via cron with force_interval set to '0')") } return res ? _('DDNS Autostart enabled') : _('DDNS Autostart disabled') }; o = s.taboption('info', form.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.DummyValue, '_restart', ' '); 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'))]); }; // DDns hints if (!env['has_ipv6']) { o = s.taboption('info', form.DummyValue, '_no_ipv6'); o.rawhtml = true; o.title = '' + _("IPv6 not supported") + ''; o.cfgvalue = function() { return _("IPv6 is currently not (fully) supported by this system") + "
" + _("Please follow the instructions on OpenWrt's homepage to enable IPv6 support") + "
" + _("or update your system to the latest OpenWrt Release")}; } if (!env['has_ssl']) { o = s.taboption('info', form.DummyValue, '_no_https'); o.titleref = L.url("admin", "system", "opkg") o.rawhtml = true; o.title = '' + _("HTTPS not supported") + ''; o.cfgvalue = function() { return _("Neither GNU Wget with SSL nor cURL installed to support secure updates via HTTPS protocol.") + "
- " + _("You should install 'wget' or 'curl' or 'uclient-fetch' with 'libustream-*ssl' package.") + "
- " + _("In some versions cURL/libcurl in OpenWrt is compiled without proxy support.")}; } if (!env['has_bindnet']) { o = s.taboption('info', form.DummyValue, '_no_bind_network'); o.titleref = L.url("admin", "system", "opkg") o.rawhtml = true; o.title = '' + _("Binding to a specific network not supported") + ''; o.cfgvalue = function() { return _("Neither GNU Wget with SSL nor cURL installed to select a network to use for communication.") + "
- " + _("You should install 'wget' or 'curl' package.") + "
- " + _("GNU Wget will use the IP of given network, cURL will use the physical interface.") + "
- " + _("In some versions cURL/libcurl in OpenWrt is compiled without proxy support.")}; } if (!env['has_proxy']) { o = s.taboption('info', form.DummyValue, '_no_proxy'); o.titleref = L.url("admin", "system", "opkg") o.rawhtml = true; o.title = '' + _("cURL without Proxy Support") + ''; o.cfgvalue = function() { return _("cURL is installed, but libcurl was compiled without proxy support.") + "
- " + _("You should install 'wget' or 'uclient-fetch' package or replace libcurl.") + "
- " + _("In some versions cURL/libcurl in OpenWrt is compiled without proxy support.")}; } if (!env['has_forceip']) { o = s.taboption('info', form.DummyValue, '_no_force_ip'); o.titleref = L.url("admin", "system", "opkg") o.rawhtml = true; o.title = '' + _("Force IP Version not supported") + ''; o.cfgvalue = function() { return _("BusyBox's nslookup and Wget do not support to specify " + "the IP version to use for communication with DDNS Provider!") + "
- " + _("You should install 'wget' or 'curl' or 'uclient-fetch' package.") }; } if (!env['has_bindhost']) { o = s.taboption('info', form.DummyValue, '_no_dnstcp'); o.titleref = L.url("admin", "system", "opkg") o.rawhtml = true; o.title = '' + _("DNS requests via TCP not supported") + ''; o.cfgvalue = function() { return _("BusyBox's nslookup and hostip do not support to specify to use TCP " + "instead of default UDP when requesting DNS server!") + "
- " + _("You should install 'bind-host' or 'knot-host' or 'drill' package for DNS requests.")}; } if (!env['has_dnsserver']) { o = s.taboption('info', form.DummyValue, '_no_dnsserver'); o.titleref = L.url("admin", "system", "opkg") o.rawhtml = true; o.title = '' + _("Using specific DNS Server not supported") + ''; o.cfgvalue = function() { return _("BusyBox's nslookup in the current compiled version " + "does not handle given DNS Servers correctly!") + "
- " + _("You should install 'bind-host' or 'knot-host' or 'drill' or 'hostip' package, " + "if you need to specify a DNS server to detect your registered IP.")}; } if (env['has_ssl'] && !env['has_cacerts']) { o = s.taboption('info', form.DummyValue, '_no_certs'); o.titleref = L.url("admin", "system", "opkg") o.rawhtml = true; o.title = '' + _("No certificates found") + ''; o.cfgvalue = function() { return _("If using secure communication you should verify server certificates!") + "
- " + _("Install 'ca-certificates' package or needed certificates " + "by hand into /etc/ssl/certs default directory")}; } // Advanced Configuration Section o = s.taboption('global', form.Flag, 'upd_privateip', _("Allow non-public IP's")); o.description = _("Non-public and by default blocked IP's") + ':' + '
IPv4: ' + '0/8, 10/8, 100.64/10, 127/8, 169.254/16, 172.16/12, 192.168/16' + '
IPv6: ' + '::/32, f000::/4"'; o.default = "0"; o.optional = true; o = s.taboption('global', form.Value, 'ddns_dateformat', _('Date format')); o.description = '' + _("For supported codes look here") + '
' + _('Current setting: ') + '' + status['_curr_dateformat'] + ''; o.default = "%F %R" o.optional = true; o.rmempty = true; o = s.taboption('global', form.Value, 'ddns_rundir', _('Status directory')); o.description = _('Directory contains PID and other status information for each running section.'); o.default = "/var/run/ddns"; o.optional = true; o.rmempty = true; o = s.taboption('global', form.Value, 'ddns_logdir', _('Log directory')); o.description = _('Directory contains Log files for each running section.'); o.default = "/var/log/ddns"; o.optional = true; o.rmempty = true; o.validate = function(section_id, formvalue) { if (formvalue.indexOf('../') !== -1) return _('"../" not allowed in path for Security Reason.') return true; } o = s.taboption('global', form.Value, 'ddns_loglines', _('Log length')); o.description = _('Number of last lines stored in log files'); o.datatype = 'min(1)'; o.default = '250'; if (env['has_wget'] && env['has_curl']) { o = s.taboption('global', form.Flag, 'use_curl', _('Use cURL')); o.description = _('If Wget and cURL package are installed, Wget is used for communication by default.'); o.default = "0"; o.optional = true; o.rmempty = true; } // DDns services s = m.section(form.GridSection, 'service', _('Services')); s.anonymous = true; s.addremove = true; s.addbtntitle = _('Add new services...'); s.anonymous = true; s.addremove = true; s.sortable = true; s.handleAdd = function(ev) { var m2 = new form.Map('ddns'), s2 = m2.section(form.NamedSection, '_new_'); s2.render = function() { return Promise.all([ {}, this.renderUCISection('_new_') ]).then(this.renderContents.bind(this)); }; name = s2.option(form.Value, 'name', _('Name')); name.rmempty = false; name.datatype = 'uciname'; name.placeholder = _('New DDns Service…'); name.validate = function(section_id, value) { if (uci.get('ddns', value) != null) return _('The service name is already used'); return true; }; m2.render().then(L.bind(function(nodes) { L.ui.showModal(_('Add new services...'), [ nodes, E('div', { 'class': 'right' }, [ E('button', { 'class': 'btn', 'click': L.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)); }) }, _('Create service')) ]) ], 'cbi-modal'); nodes.querySelector('[id="%s"] input[type="text"]'.format(name.cbid('_new_'))).focus(); }, this)); }; s.renderRowActions = function(section_id) { var tdEl = this.super('renderRowActions', [ section_id, _('Edit') ]), cfg_enabled = uci.get('ddns', section_id, 'enabled'), reload_opt = { 'class': 'cbi-button cbi-button-neutral reload', 'click': 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)); }), '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)); }), 'title': _('Stop this service'), }; if (status['_enabled'] == 0 || cfg_enabled == 0) reload_opt['disabled'] = 'disabled'; if (!resolved[section_id] || !resolved[section_id].pid || (resolved[section_id].pid && cfg_enabled == '1')) stop_opt['disabled'] = 'disabled'; dom.content(tdEl.lastChild, [ E('button', stop_opt, _('Stop')), E('button', reload_opt, _('Reload')), tdEl.lastChild.childNodes[0], tdEl.lastChild.childNodes[1], tdEl.lastChild.childNodes[2] ]); return tdEl; }; o = s.option(form.DummyValue, '_cfg_name', _('Name')); o.modalonly = false; o.textvalue = function(section_id) { return '' + section_id + ''; } o = s.option(form.DummyValue, '_cfg_detail_ip', _('Lookup Hostname') + "
" + _('Registered IP')); o.rawhtml = true; o.modalonly = false; o.textvalue = function(section_id) { var host = uci.get('ddns', section_id, 'lookup_host') || _('Configuration Error'), ip = _('No Data'); if (resolved[section_id] && resolved[section_id].ip) ip = resolved[section_id].ip; return host + '
' + ip; }; o = s.option(form.Flag, 'enabled', _('Enabled')); o.rmempty = false; o.editable = true; o.modalonly = false; o = s.option(form.DummyValue, '_cfg_update', _('Last Update') + "
" + _('Next Update')); o.rawhtml = true; o.modalonly = false; o.textvalue = function(section_id) { var last_update = _('Never'), next_update = _('Unknown'); if (resolved[section_id]) { if (resolved[section_id].last_update) last_update = resolved[section_id].last_update; if (resolved[section_id].next_update) next_update = NextUpdateStrings[resolved[section_id].next_update] || resolved[section_id].next_update; } return last_update + '
' + 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 = '' + _('Not Running') + ''; if (resolved[section_id] && resolved[section_id].pid) text = '' + _('Running') + ' : ' + 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.") + "
" + _("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.") + "
" + _("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") + "
" + _("or") + '' + " IGNORE " + '' + _("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.") + '
' + String.format('%s %s', _('Example for IPv4'), ': http://checkip.dyndns.com') + '
' + 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') + '
' + _("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'.") + "
" + _("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.") + "
" + String.format('%s: %s', _("Format"), "[user:password@]proxyhost:port") + "
" + String.format('%s: %s', _("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.") + "
" + _("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") + "
" + _("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") + "
" + _("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") + "
" + _("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() ]).then(L.bind(this.poll_status, this, nodes)); }, this), 5); return nodes; }, this, m)); } });