6 'require tools.widgets as widgets';
8 var callGetLogServices
, callInitAction
, callDDnsGetStatus
;
10 var NextUpdateStrings
= {};
13 'Verify' : _("Verify"),
14 'Run once' : _("Run once"),
15 'Disabled' : _("Disabled"),
16 'Stopped' : _("Stopped")
20 time_res
['seconds'] = 1;
21 time_res
['minutes'] = 60;
22 time_res
['hours'] = 3600;
24 callGetLogServices
= rpc
.declare({
26 method
: 'get_services_log',
27 params
: [ 'service_name' ],
31 callInitAction
= rpc
.declare({
33 method
: 'setInitAction',
34 params
: [ 'name', 'action' ],
35 expect
: { result
: false }
38 callDDnsGetStatus
= rpc
.declare({
40 method
: 'get_ddns_state',
44 return L
.view
.extend({
46 callDDnsGetEnv
: rpc
.declare({
52 callDDnsGetServicesStatus
: rpc
.declare({
54 method
: 'get_services_status',
58 poll_status: function(map
, data
) {
59 var status
= data
[1] || [], service
= data
[0] || [], rows
= map
.querySelectorAll('.cbi-section-table-row[data-sid]'),
60 section_id
, cfg_detail_ip
, cfg_update
, cfg_status
, host
, ip
, last_update
,
61 next_update
, service_status
, reload
, cfg_enabled
, stop
,
62 ddns_enabled
= map
.querySelector('[data-name="_enabled"]').querySelector('.cbi-value-field'),
63 ddns_toggle
= map
.querySelector('[data-name="_toggle"]').querySelector('button');
65 ddns_toggle
.innerHTML
= status
['_enabled'] ? _('Stop DDNS') : _('Start DDNS')
67 L
.dom
.content(ddns_enabled
, function() {
69 E('div', {}, status
['_enabled'] ? _('DDNS Autostart enabled') : [
70 _('DDNS Autostart disabled'),
71 E('div', { 'class' : 'cbi-value-description' },
72 _("Currently DDNS updates are not started at boot or on interface events.") + "<br />" +
73 _("This is the default if you run DDNS scripts by yourself (i.e. via cron with force_interval set to '0')"))
77 for (var i
= 0; i
< rows
.length
; i
++) {
78 section_id
= rows
[i
].getAttribute('data-sid');
79 cfg_detail_ip
= rows
[i
].querySelector('[data-name="_cfg_detail_ip"]');
80 cfg_update
= rows
[i
].querySelector('[data-name="_cfg_update"]');
81 cfg_status
= rows
[i
].querySelector('[data-name="_cfg_status"]');
82 reload
= rows
[i
].querySelector('.cbi-section-actions .reload');
83 stop
= rows
[i
].querySelector('.cbi-section-actions .stop');
84 cfg_enabled
= uci
.get('ddns', section_id
, 'enabled');
86 reload
.disabled
= (status
['_enabled'] == 0 || cfg_enabled
== 0);
88 host
= uci
.get('ddns', section_id
, 'lookup_host') || _('Configuration Error');
90 last_update
= _('Never');
91 next_update
= _('Unknown');
92 service_status
= '<b>' + _('Not Running') + '</b>';
94 if (service
[section_id
]) {
95 stop
.disabled
= (!service
[section_id
].pid
|| (service
[section_id
].pid
&& cfg_enabled
== '1'));
96 if (service
[section_id
].ip
)
97 ip
= service
[section_id
].ip
;
98 if (service
[section_id
].last_update
)
99 last_update
= service
[section_id
].last_update
;
100 if (service
[section_id
].next_update
)
101 next_update
= NextUpdateStrings
[service
[section_id
].next_update
] || service
[section_id
].next_update
;
102 if (service
[section_id
].pid
)
103 service_status
= '<b>' + _('Running') + '</b> : ' + service
[section_id
].pid
;
106 cfg_detail_ip
.innerHTML
= host
+ '<br />' + ip
;
107 cfg_update
.innerHTML
= last_update
+ '<br />' + next_update
;
108 cfg_status
.innerHTML
= service_status
;
116 this.callDDnsGetServicesStatus(),
118 this.callDDnsGetEnv(),
119 fs
.lines('/etc/ddns/services'),
120 fs
.lines('/etc/ddns/services_ipv6'),
125 render: function(data
) {
126 var resolved
= data
[0] || [];
127 var status
= data
[1] || [];
128 var env
= data
[2] || [];
129 var logdir
= uci
.get('ddns', 'global', 'ddns_logdir') || "/var/log/ddns";
134 data
[3].forEach(function(item
) {
135 if (!item
.startsWith("#")) {
136 services4
.push(item
.split('\t')[0].slice(1,-1));
140 data
[4].forEach(function(item
) {
141 if (!item
.startsWith("#")) {
142 services6
.push(item
.split('\t')[0].slice(1,-1));
148 m
= new form
.Map('ddns', _('Dynamic DNS'));
150 var is
= m
.section(form
.NamedSection
, 'global', 'ddns', _('Information'));
154 o
= s
.option(form
.DummyValue
, '_version', _('Dynamic DNS Version'));
155 o
.cfgvalue = function() {
156 return status
[this.option
];
159 o
= s
.option(form
.DummyValue
, '_enabled', _('State'));
160 o
.cfgvalue = function() {
161 var res
= status
[this.option
];
163 this.description
= _("Currently DDNS updates are not started at boot or on interface events.") + "<br />" +
164 _("This is the default if you run DDNS scripts by yourself (i.e. via cron with force_interval set to '0')")
166 return res
? _('DDNS Autostart enabled') : _('DDNS Autostart disabled')
169 o
= s
.option(form
.DummyValue
, '_toggle', ' ');
170 o
.cfgvalue = function() {
171 var action
= status
['_enabled'] ? 'stop' : 'start';
174 'class': 'cbi-button cbi-button-apply',
175 'click': L
.ui
.createHandlerFn(this, function() {
176 return callDDnsGetStatus().then(L
.bind(function(data
) {
177 return callInitAction('ddns', action
== 'stop' ? 'disable' : 'enable').then(function() {
178 return callInitAction('ddns', action
);
180 }, this)).then(L
.bind(m
.render
, m
));
182 }, _(action
.toUpperCase() + ' DDns'))]);
185 o
= s
.option(form
.DummyValue
, '_restart', ' ');
186 o
.cfgvalue = function() {
189 'class': 'cbi-button cbi-button-apply',
190 'click': L
.ui
.createHandlerFn(this, function() {
191 return callInitAction('ddns', 'restart').then(L
.bind(m
.render
, m
));
193 }, _('Restart DDns'))]);
198 if (!env
['has_ipv6']) {
199 o
= s
.option(form
.DummyValue
, '_no_ipv6');
201 o
.title
= '<b>' + _("IPv6 not supported") + '</b>';
202 o
.cfgvalue = function() { return _("IPv6 is currently not (fully) supported by this system") + "<br />" +
203 _("Please follow the instructions on OpenWrt's homepage to enable IPv6 support") + "<br />" +
204 _("or update your system to the latest OpenWrt Release")};
207 if (!env
['has_ssl']) {
208 o
= s
.option(form
.DummyValue
, '_no_https');
209 o
.titleref
= L
.url("admin", "system", "opkg")
211 o
.title
= '<b>' + _("HTTPS not supported") + '</b>';
212 o
.cfgvalue = function() { return _("Neither GNU Wget with SSL nor cURL installed to support secure updates via HTTPS protocol.") +
214 _("You should install 'wget' or 'curl' or 'uclient-fetch' with 'libustream-*ssl' package.") +
216 _("In some versions cURL/libcurl in OpenWrt is compiled without proxy support.")};
219 if (!env
['has_bindnet']) {
220 o
= s
.option(form
.DummyValue
, '_no_bind_network');
221 o
.titleref
= L
.url("admin", "system", "opkg")
223 o
.title
= '<b>' + _("Binding to a specific network not supported") + '</b>';
224 o
.cfgvalue = function() { return _("Neither GNU Wget with SSL nor cURL installed to select a network to use for communication.") +
226 _("You should install 'wget' or 'curl' package.") +
228 _("GNU Wget will use the IP of given network, cURL will use the physical interface.") +
230 _("In some versions cURL/libcurl in OpenWrt is compiled without proxy support.")};
233 if (!env
['has_proxy']) {
234 o
= s
.option(form
.DummyValue
, '_no_proxy');
235 o
.titleref
= L
.url("admin", "system", "opkg")
237 o
.title
= '<b>' + _("cURL without Proxy Support") + '</b>';
238 o
.cfgvalue = function() { return _("cURL is installed, but libcurl was compiled without proxy support.") +
240 _("You should install 'wget' or 'uclient-fetch' package or replace libcurl.") +
242 _("In some versions cURL/libcurl in OpenWrt is compiled without proxy support.")};
245 if (!env
['has_forceip']) {
246 o
= s
.option(form
.DummyValue
, '_no_force_ip');
247 o
.titleref
= L
.url("admin", "system", "opkg")
249 o
.title
= '<b>' + _("Force IP Version not supported") + '</b>';
250 o
.cfgvalue = function() { return _("BusyBox's nslookup and Wget do not support to specify " +
251 "the IP version to use for communication with DDNS Provider!") +
252 "<br />- " + _("You should install 'wget' or 'curl' or 'uclient-fetch' package.")
256 if (!env
['has_bindhost']) {
257 o
= s
.option(form
.DummyValue
, '_no_dnstcp');
258 o
.titleref
= L
.url("admin", "system", "opkg")
260 o
.title
= '<b>' + _("DNS requests via TCP not supported") + '</b>';
261 o
.cfgvalue = function() { return _("BusyBox's nslookup and hostip do not support to specify to use TCP " +
262 "instead of default UDP when requesting DNS server!") +
264 _("You should install 'bind-host' or 'knot-host' or 'drill' package for DNS requests.")};
267 if (!env
['has_dnsserver']) {
268 o
= s
.option(form
.DummyValue
, '_no_dnsserver');
269 o
.titleref
= L
.url("admin", "system", "opkg")
271 o
.title
= '<b>' + _("Using specific DNS Server not supported") + '</b>';
272 o
.cfgvalue = function() { return _("BusyBox's nslookup in the current compiled version " +
273 "does not handle given DNS Servers correctly!") +
275 _("You should install 'bind-host' or 'knot-host' or 'drill' or 'hostip' package, " +
276 "if you need to specify a DNS server to detect your registered IP.")};
279 if (env
['has_ssl'] && !env
['has_cacerts']) {
280 o
= s
.option(form
.DummyValue
, '_no_certs');
281 o
.titleref
= L
.url("admin", "system", "opkg")
283 o
.title
= '<b>' + _("No certificates found") + '</b>';
284 o
.cfgvalue = function() { return _("If using secure communication you should verify server certificates!") +
286 _("Install 'ca-certificates' package or needed certificates " +
287 "by hand into /etc/ssl/certs default directory")};
291 s
= m
.section(form
.GridSection
, 'service', _('Services'));
294 s
.addbtntitle
= _('Add new services...');
300 s
.handleAdd = function(ev
) {
301 var m2
= new form
.Map('ddns'),
302 s2
= m2
.section(form
.NamedSection
, '_new_');
304 s2
.render = function() {
307 this.renderUCISection('_new_')
308 ]).then(this.renderContents
.bind(this));
311 name
= s2
.option(form
.Value
, 'name', _('Name'));
312 name
.rmempty
= false;
313 name
.datatype
= 'uciname';
314 name
.placeholder
= _('New DDns Service…');
315 name
.validate = function(section_id
, value
) {
316 if (uci
.get('ddns', value
) != null)
317 return _('The service name is already used');
322 m2
.render().then(L
.bind(function(nodes
) {
323 L
.ui
.showModal(_('Add new services...'), [
325 E('div', { 'class': 'right' }, [
328 'click': L
.ui
.hideModal
329 }, _('Cancel')), ' ',
331 'class': 'cbi-button cbi-button-positive important',
332 'click': L
.ui
.createHandlerFn(this, function(ev
) {
333 var nameval
= name
.isValid('_new_') ? name
.formvalue('_new_') : null;
335 if (nameval
== null || nameval
== '')
338 return m
.save(function() {
339 uci
.add('ddns', 'service', nameval
);
340 }).then(L
.bind(m
.children
[1].renderMoreOptionsModal
, m
.children
[1], nameval
));
342 }, _('Create service'))
346 nodes
.querySelector('[id="%s"] input[type="text"]'.format(name
.cbid('_new_'))).focus();
350 s
.renderRowActions = function(section_id
) {
351 var tdEl
= this.super('renderRowActions', [ section_id
, _('Edit') ]),
352 cfg_enabled
= uci
.get('ddns', section_id
, 'enabled'),
354 'class': 'cbi-button cbi-button-neutral reload',
355 'click': L
.ui
.createHandlerFn(this, function() {
356 return fs
.exec('/usr/lib/ddns/dynamic_dns_lucihelper.sh',
357 [ '-S', section_id
, '--', 'start' ]).then(L
.bind(m
.render
, m
));
359 'title': _('Reload this service'),
362 'class': 'cbi-button cbi-button-neutral stop',
363 'click': L
.ui
.createHandlerFn(this, function() {
364 return fs
.exec('/usr/lib/ddns/dynamic_dns_lucihelper.sh',
365 [ '-S', section_id
, '--', 'start' ]).then(L
.bind(m
.render
, m
));
367 'title': _('Stop this service'),
370 if (status
['_enabled'] == 0 || cfg_enabled
== 0)
371 reload_opt
['disabled'] = 'disabled';
373 if (!resolved
[section_id
] || !resolved
[section_id
].pid
||
374 (resolved
[section_id
].pid
&& cfg_enabled
== '1'))
375 stop_opt
['disabled'] = 'disabled';
377 L
.dom
.content(tdEl
.lastChild
, [
378 E('button', stop_opt
, _('Stop')),
379 E('button', reload_opt
, _('Reload')),
380 tdEl
.lastChild
.childNodes
[0],
381 tdEl
.lastChild
.childNodes
[1],
382 tdEl
.lastChild
.childNodes
[2]
388 o
= s
.option(form
.DummyValue
, '_cfg_name', _('Name'));
390 o
.textvalue = function(section_id
) {
391 return '<b>' + section_id
+ '</b>';
394 o
= s
.option(form
.DummyValue
, '_cfg_detail_ip', _('Lookup Hostname') + "<br />" + _('Registered IP'));
397 o
.textvalue = function(section_id
) {
398 var host
= uci
.get('ddns', section_id
, 'lookup_host') || _('Configuration Error'),
400 if (resolved
[section_id
] && resolved
[section_id
].ip
)
401 ip
= resolved
[section_id
].ip
;
403 return host
+ '<br />' + ip
;
406 o
= s
.option(form
.Flag
, 'enabled', _('Enabled'));
411 o
= s
.option(form
.DummyValue
, '_cfg_update', _('Last Update') + "<br />" + _('Next Update'));
414 o
.textvalue = function(section_id
) {
415 var last_update
= _('Never'), next_update
= _('Unknown');
416 if (resolved
[section_id
]) {
417 if (resolved
[section_id
].last_update
)
418 last_update
= resolved
[section_id
].last_update
;
419 if (resolved
[section_id
].next_update
)
420 next_update
= NextUpdateStrings
[resolved
[section_id
].next_update
] || resolved
[section_id
].next_update
;
423 return last_update
+ '<br />' + next_update
;
426 s
.modaltitle = function(section_id
) {
427 return _('DDns Service') + ' » ' + section_id
;
430 o
= s
.option(form
.DummyValue
, '_cfg_status', _('Status'));
432 o
.textvalue = function(section_id
) {
433 var text
= '<b>' + _('Not Running') + '</b>';
435 if (resolved
[section_id
] && resolved
[section_id
].pid
)
436 text
= '<b>' + _('Running') + '</b> : ' + resolved
[section_id
].pid
;
442 s
.tab('basic', _('Basic Settings'));
443 s
.tab('advanced', _('Advanced Settings'));
444 s
.tab('timer', _('Timer Settings'));
445 s
.tab('logview', _('Log File Viewer'));
450 o
= s
.taboption('basic', form
.Flag
, 'enabled', _('Enabled'),_("If this service section is disabled it could not be started." + "<br />" +
451 "Neither from LuCI interface nor from console"));
458 o
= s
.taboption('basic', form
.Value
, 'lookup_host', _("Lookup Hostname"),
459 _("Hostname/FQDN to validate, if IP update happen or necessary") );
461 o
.placeholder
= "myhost.example.com";
462 o
.datatype
= 'and(minlength(3),hostname("strict"))';
467 o
= s
.taboption('basic', form
.ListValue
, 'use_ipv6', _("IP address version"),
468 _("Defines which IP address 'IPv4/IPv6' is send to the DDNS provider"));
473 o
.value("0", _("IPv4-Address"))
475 o
.value("1", _("IPv6-Address"))
479 o
= s
.taboption('basic', form
.ListValue
, 'ipv4_service_name', _("DDNS Service provider") + " [IPv4]");
480 o
.depends("use_ipv6", "0")
483 for (var i
= 0; i
< services4
.length
; i
++)
484 o
.value(services4
[i
]);
486 o
.value('-',"-- " + _("custom") + " --");
488 o
.cfgvalue = function(section_id
) {
489 return uci
.get('ddns', section_id
, 'service_name');
492 o
.write = function(section_id
, formvalue
) {
493 if (formvalue
!= '-') {
494 uci
.set('ddns', section_id
, 'update_url', null);
495 uci
.set('ddns', section_id
, 'update_script', null);
496 return uci
.set('ddns', section_id
, 'service_name', formvalue
);
498 return uci
.set('ddns', section_id
, 'service_name', null);
501 o
= s
.taboption('basic', form
.ListValue
, 'ipv6_service_name', _("DDNS Service provider") + " [IPv6]");
502 o
.depends("use_ipv6", "1")
505 for (var i
= 0; i
< services6
.length
; i
++)
506 o
.value(services6
[i
]);
508 o
.value('-',"-- " + _("custom") + " --");
510 o
.cfgvalue = function(section_id
) {
511 return uci
.get('ddns', section_id
, 'service_name');
514 o
.write = function(section_id
, formvalue
) {
515 if (formvalue
!= '-') {
516 uci
.set('ddns', section_id
, 'update_url', null);
517 uci
.set('ddns', section_id
, 'update_script', null);
518 return uci
.set('ddns', section_id
, 'service_name', formvalue
);
520 return uci
.set('ddns', section_id
, 'service_name', null);
525 o
= s
.taboption('basic', form
.Value
, 'update_url', _("Custom update-URL"),
526 _("Update URL to be used for updating your DDNS Provider." + "<br />" +
527 "Follow instructions you will find on their WEB page."));
530 o
.depends("ipv6_service_name","-");
531 o
.depends("ipv4_service_name","-");
535 o
= s
.taboption('basic', form
.Value
, 'update_script', _("Custom update-script"),
536 _("Custom update script to be used for updating your DDNS Provider."));
539 o
.depends("ipv6_service_name","-");
540 o
.depends("ipv4_service_name","-");
544 o
= s
.taboption('basic', form
.Value
, 'domain', _("Domain"),
545 _("Replaces [USERNAME] in Update-URL (URL-encoded)"));
551 o
= s
.taboption('basic', form
.Value
, 'username', _("Username"),
552 _("Replaces [USERNAME] in Update-URL (URL-encoded)"));
559 o
= s
.taboption('basic', form
.Value
, 'password', _("Password"),
560 _("Replaces [PASSWORD] in Update-URL (URL-encoded)"));
567 o
= s
.taboption('basic', form
.Value
, 'param_enc', _("Optional Encoded Parameter"),
568 _("Optional: Replaces [PARAMENC] in Update-URL (URL-encoded)"));
574 o
= s
.taboption('basic', form
.Value
, 'param_opt', _("Optional Parameter"),
575 _("Optional: Replaces [PARAMOPT] in Update-URL (NOT URL-encoded)"));
581 if (env
['has_ssl']) {
582 o
= s
.taboption('basic', form
.Flag
, 'use_https', _("Use HTTP Secure"),
583 _("Enable secure communication with DDNS provider"));
587 o
= s
.taboption('basic', form
.Value
, 'cacert',
588 _("Path to CA-Certificate"),
589 _("directory or path/file") + "<br />" +
590 _("or") + '<b>' + " IGNORE " + '</b>' +
591 _("to run HTTPS without verification of server certificates (insecure)"));
593 o
.depends("use_https", "1");
594 o
.placeholder
= "/etc/ssl/certs";
602 o
= s
.taboption('advanced', form
.ListValue
, 'ip_source', _("IP address source"),
603 _("Defines the source to read systems IP-Address from, that will be send to the DDNS provider"));
606 o
.default = "network";
607 o
.value("network", _("Network"));
608 o
.value("web", _("URL"));
609 o
.value("interface", _("Interface"));
610 o
.value("script", _("Script"));
612 o
.write = function(section_id
, formvalue
) {
615 uci
.set('ddns', section_id
, "ip_url",null);
616 uci
.set('ddns', section_id
, "ip_interface",null);
617 uci
.set('ddns', section_id
, "ip_script",null);
620 uci
.set('ddns', section_id
, "ip_network",null);
621 uci
.set('ddns', section_id
, "ip_interface",null);
622 uci
.set('ddns', section_id
, "ip_script",null);
625 uci
.set('ddns', section_id
, "ip_network",null);
626 uci
.set('ddns', section_id
, "ip_url",null);
627 uci
.set('ddns', section_id
, "ip_script",null);
630 uci
.set('ddns', section_id
, "ip_network",null);
631 uci
.set('ddns', section_id
, "ip_url",null);
632 uci
.set('ddns', section_id
, "ip_interface",null);
638 return uci
.set('ddns', section_id
, 'ip_source', formvalue
)
643 o
= s
.taboption('advanced', widgets
.NetworkSelect
, 'ip_network', _("Network"),
644 _("Defines the network to read systems IP-Address from"));
645 o
.depends('ip_source','network');
652 o
= s
.taboption('advanced', form
.Value
, 'ip_url', _("URL to detect"),
653 _("Defines the Web page to read systems IP-Address from" + '<br />' +
654 _('Example for IPv4' + ': http://checkip.dyndns.com') + '<br />' +
655 _('Example for IPv6' + ': http://checkipv6.dyndns.com')));
656 o
.depends("ip_source", "web")
662 o
= s
.taboption('advanced', widgets
.DeviceSelect
, 'ip_interface', _("Interface"),
663 _("Defines the interface to read systems IP-Address from"));
666 o
.depends("ip_source", "interface")
672 o
= s
.taboption('advanced', form
.Value
, 'ip_script', _("Script"),
673 _("User defined script to read systems IP-Address"));
676 o
.depends("ip_source", "script")
677 o
.placeholder
= "/path/to/script.sh"
681 o
= s
.taboption('advanced', widgets
.DeviceSelect
, 'interface', _("Event Network"),
682 _("Network on which the ddns-updater scripts will be started"));
687 o
.depends("ip_source", "web");
688 o
.depends("ip_source", "script");
692 o
= s
.taboption('advanced', form
.DummyValue
, '_interface', _("Event Network"),
693 _("Network on which the ddns-updater scripts will be started"));
694 o
.depends("ip_source", "interface");
695 o
.depends("ip_source", "network");
698 o
.cfgvalue = function(section_id
) {
699 return uci
.get('ddns', section_id
, 'interface') || _('This will be autoset to the selected interface');
701 o
.write = function(section_id
) {
702 var opt
= this.section
.children
.filter(function(o
) { return o
.option
== 'ip_source' })[0].formvalue(section_id
);
703 var val
= this.section
.children
.filter(function(o
) { return o
.option
== 'ip_'+opt
})[0].formvalue(section_id
);
704 return uci
.set('ddns', section_id
, 'interface', val
);
709 if (env
['has_bindnet']) {
710 o
= s
.taboption('advanced', widgets
.ZoneSelect
, 'bind_network', _("Bind Network"),
711 _('OPTIONAL: Network to use for communication') + '<br />' +
712 _("Network on which the ddns-updater scripts will be started"));
713 o
.depends("ip_source", "web");
721 if (env
['has_forceip']) {
722 o
= s
.taboption('advanced', form
.Flag
, 'force_ipversion', _("Force IP Version"),
723 _('OPTIONAL: Force the usage of pure IPv4/IPv6 only communication.'));
731 if (env
['has_dnsserver']) {
732 o
= s
.taboption("advanced", form
.Value
, "dns_server",
734 _("OPTIONAL: Use non-default DNS-Server to detect 'Registered IP'.") + "<br />" +
735 _("Format: IP or FQDN"));
736 o
.placeholder
= "mydns.lan"
744 if (env
['has_bindhost']) {
745 o
= s
.taboption("advanced", form
.Flag
, "force_dnstcp",
746 _("Force TCP on DNS"),
747 _("OPTIONAL: Force the use of TCP instead of default UDP on DNS requests."));
755 if (env
['has_proxy']) {
756 o
= s
.taboption("advanced", form
.Value
, "proxy", _("PROXY-Server"),
757 _("OPTIONAL: Proxy-Server for detection and updates.") + "<br />" +
758 _("Format") + ": " + '<b>' + "[user:password@]proxyhost:port" + '</b>' + "<br />" +
759 _("IPv6 address must be given in square brackets") + ": " +
760 '<b>' + " [2001:db8::1]:8080" + '</b>');
768 o
= s
.taboption("advanced", form
.ListValue
, "use_syslog", _("Log to syslog"),
769 _("Writes log messages to syslog. Critical Errors will always be written to syslog."));
773 o
.value("0", _("No logging"))
774 o
.value("1", _("Info"))
775 o
.value("2", _("Notice"))
776 o
.value("3", _("Warning"))
777 o
.value("4", _("Error"))
781 o
= s
.taboption("advanced", form
.Flag
, "use_logfile", _("Log to file"));
785 o
.cfgvalue = function(section_id
) {
786 this.description
= _("Writes detailed messages to log file. File will be truncated automatically.") + "<br />" +
787 _("File") + ': "' + logdir
+ '/' + section_id
+ '.log"';
788 return uci
.get('ddns', section_id
, 'use_logfile');
794 o
= s
.taboption("timer", form
.Value
, "check_interval", _("Check Interval"));
795 o
.placeholder
= "30";
797 o
.datatype
= 'uinteger';
799 o
.validate = function(section_id
, formvalue
) {
800 var unit
= this.section
.children
.filter(function(o
) { return o
.option
== 'check_unit' })[0].formvalue(section_id
),
801 time_to_sec
= time_res
[unit
|| 'minutes'] * formvalue
;
803 if (formvalue
&& time_to_sec
< 300)
804 return _('Values below 5 minutes == 300 seconds are not supported');
811 o
= s
.taboption("timer", form
.ListValue
, "check_unit",'Check Unit');
812 o
.description
= _("Interval unit to check for changed IP");
814 o
.default = "minutes"
815 o
.value("seconds", _("seconds"));
816 o
.value("minutes", _("minutes"));
817 o
.value("hours", _("hours"));
821 o
= s
.taboption("timer", form
.Value
, "force_interval", _("Force Interval"));
822 o
.description
= _("Interval to force updates send to DDNS Provider" + "<br />" +
823 "Setting this parameter to 0 will force the script to only run once");
824 o
.placeholder
= "72";
827 o
.datatype
= 'uinteger';
829 o
.validate = function(section_id
, formvalue
) {
834 var check_unit
= this.section
.children
.filter(function(o
) { return o
.option
== 'check_unit' })[0].formvalue(section_id
),
835 check_val
= this.section
.children
.filter(function(o
) { return o
.option
== 'check_interval' })[0].formvalue(section_id
),
836 force_unit
= this.section
.children
.filter(function(o
) { return o
.option
== 'force_unit' })[0].formvalue(section_id
),
837 check_to_sec
= time_res
[check_unit
|| 'minutes'] * ( check_val
|| '30'),
838 force_to_sec
= time_res
[force_unit
|| 'minutes'] * formvalue
;
840 if (force_to_sec
!= 0 && force_to_sec
< check_to_sec
)
841 return _("Values lower 'Check Interval' except '0' are not supported");
848 o
= s
.taboption("timer", form
.ListValue
, "force_unit",'Force Unit');
849 o
.description
= _("Interval unit to force updates send to DDNS Provider");
852 o
.default = "minutes"
853 o
.value("minutes", _("minutes"));
854 o
.value("hours", _("hours"));
855 o
.value("days", _("days"));
859 o
= s
.taboption("timer", form
.Value
, "retry_count", _("Error Retry Counter"));
860 o
.description
= _("On Error the script will stop execution after given number of retrys")
862 + _("The default setting of '0' will retry infinite.");
866 o
.datatype
= 'uinteger';
870 o
= s
.taboption("timer", form
.Value
, "retry_interval", _("Error Retry Interval"));
871 o
.description
= _("On Error the script will stop execution after given number of retrys")
873 + _("The default setting of '0' will retry infinite.");
874 o
.placeholder
= "60";
877 o
.datatype
= 'uinteger';
881 o
= s
.taboption("timer", form
.ListValue
, "retry_unit",'Retry Unit');
882 o
.description
= _("On Error the script will retry the failed action after given time");
885 o
.default = "seconds"
886 o
.value("seconds", _("seconds"));
887 o
.value("minutes", _("minutes"));
891 o
= s
.taboption("logview", form
.DummyValue
, '_read_log', '');
892 o
.depends('use_logfile','1');
894 o
.cfgvalue = function(section_id
) {
897 'class': 'cbi-button cbi-button-apply',
898 'click': L
.ui
.createHandlerFn(this, function() {
899 var o
= this.section
.children
.filter(function(o
) { return o
.option
== '_logview' })[0];
900 return callGetLogServices(section_id
).then(L
.bind(o
.update_log
, o
));
902 }, _('Read / Reread log file'))]);
905 o
= s
.taboption("logview", form
.DummyValue
, "_logview");
906 o
.depends('use_logfile','1');
909 o
.update_log
= L
.bind(function(view
, log_data
) {
910 return document
.getElementById('log_area').textContent
= log_data
.result
;
913 o
.render
= L
.bind(function() {
915 E('p', {}, _('This is the current content of the log file in ') + logdir
+ ' for this service.'),
916 E('p', {}, E('textarea', { 'style': 'width:100%', 'rows': 20, 'readonly' : 'readonly', 'id' : 'log_area' }, _('Please press [Read] button') ))
921 // Advanced Configuration Section
923 s
= m
.section(form
.NamedSection
, 'global', 'ddns', _('Global Configuration'));
924 s
.description
= _('Configure here the details for all Dynamic DNS services including this LuCI application.')
926 + _("It is NOT recommended for casual users to change settings on this page.")
928 + '<a href="https://openwrt.org/docs/guide-user/base-system/ddns#section_ddns" target="_blank">'
929 + _('For detailed information about parameter settings look here.')
933 o
= s
.option(form
.Flag
, 'upd_privateip', _("Allow non-public IP's"));
934 o
.description
= _("Non-public and by default blocked IP's") + ':'
935 + '<br /><strong>IPv4: </strong>'
936 + '0/8, 10/8, 100.64/10, 127/8, 169.254/16, 172.16/12, 192.168/16'
937 + '<br /><strong>IPv6: </strong>'
938 + '::/32, f000::/4"';
942 o
= s
.option(form
.Value
, 'ddns_dateformat', _('Date format'));
943 o
.description
= '<a href="http://www.cplusplus.com/reference/ctime/strftime/" target="_blank">'
944 + _("For supported codes look here")
946 _('Current setting: ') + '<b>' + status
['_curr_dateformat'] + '</b>';
951 o
= s
.option(form
.Value
, 'ddns_rundir', _('Status directory'));
952 o
.description
= _('Directory contains PID and other status information for each running section.');
953 o
.default = "/var/run/ddns";
957 o
= s
.option(form
.Value
, 'ddns_logdir', _('Log directory'));
958 o
.description
= _('Directory contains Log files for each running section.');
959 o
.default = "/var/log/ddns";
962 o
.validate = function(section_id
, formvalue
) {
963 if (formvalue
.indexOf('../') !== -1)
964 return _('"../" not allowed in path for Security Reason.')
969 o
= s
.option(form
.Value
, 'ddns_loglines', _('Log length'));
970 o
.description
= _('Number of last lines stored in log files');
971 o
.datatype
= 'min(1)';
974 if (env
['has_wget'] && env
['has_curl']) {
976 o
= s
.option(form
.Flag
, 'use_curl', _('Use cURL'));
977 o
.description
= _('If Wget and cURL package are installed, Wget is used for communication by default.');
984 return m
.render().then(L
.bind(function(m
, nodes
) {
985 L
.Poll
.add(L
.bind(function() {
987 this.callDDnsGetServicesStatus(),
989 ]).then(L
.bind(this.poll_status
, this, nodes
));