luci-app-travelmate: typo fix
[project/luci.git] / applications / luci-app-travelmate / htdocs / luci-static / resources / view / travelmate / stations.js
1 'use strict';
2 'require view';
3 'require poll';
4 'require fs';
5 'require ui';
6 'require uci';
7 'require form';
8 'require network';
9 'require tools.widgets as widgets';
10
11 /*
12 change the status of travelmate stations
13 */
14 function handleToggle(sid) {
15 var w_device, w_ssid, w_bssid, t_sections, row, element, value, enabled;
16
17 w_device = uci.get('wireless', sid, 'device');
18 w_ssid = uci.get('wireless', sid, 'ssid');
19 w_bssid = uci.get('wireless', sid, 'bssid');
20 t_sections = uci.sections('travelmate', 'uplink');
21
22 for (var i = 0; i < t_sections.length; i++) {
23 if (t_sections[i].device === w_device && t_sections[i].ssid === w_ssid && t_sections[i].bssid === w_bssid) {
24 value = t_sections[i]['enabled'];
25 value = (value == 0 ? 1 : 0);
26 enabled = (value == 0 ? 'No' : 'Yes');
27 uci.set('travelmate', t_sections[i]['.name'], 'enabled', value);
28 uci.save().then(function () {
29 row = document.querySelector('.cbi-section-table-row[data-sid="%s"]'.format(sid));
30 element = row.querySelector('.cbi-value-field');
31 element.textContent = enabled;
32 row.setAttribute('style', 'opacity: 0.5; color: #37c !important;');
33 });
34 }
35 }
36 }
37
38 /*
39 remove wireless and stale travelmate sections
40 */
41 function handleRemove(sid) {
42 var w_sections, t_sections, match, row;
43
44 uci.remove('wireless', sid);
45 w_sections = uci.sections('wireless', 'wifi-iface');
46 t_sections = uci.sections('travelmate', 'uplink');
47 for (var i = 0; i < t_sections.length; i++) {
48 match = false;
49 for (var j = 0; j < w_sections.length; j++) {
50 if (t_sections[i].device === w_sections[j].device && t_sections[i].ssid === w_sections[j].ssid && t_sections[i].bssid === w_sections[j].bssid) {
51 match = true;
52 break;
53 }
54 }
55 if (match === false) {
56 uci.remove('travelmate', t_sections[i]['.name']);
57 }
58 }
59 return uci.save().then(function () {
60 row = document.querySelector('.cbi-section-table-row[data-sid="%s"]'.format(sid));
61 row.setAttribute('style', 'opacity: 0.5; color: #a22 !important;');
62 });
63 }
64
65 /*
66 add missing travelmate sections
67 */
68 function handleSectionsAdd(iface) {
69 var w_sections, t_sections, match;
70
71 w_sections = uci.sections('wireless', 'wifi-iface');
72 t_sections = uci.sections('travelmate', 'uplink');
73
74 for (var i = 0; i < w_sections.length; i++) {
75 if (w_sections[i].mode !== 'sta' || w_sections[i].network !== iface) {
76 continue;
77 }
78 match = false;
79 for (var j = 0; j < t_sections.length; j++) {
80 if (w_sections[i].device === t_sections[j].device && w_sections[i].ssid === t_sections[j].ssid && w_sections[i].bssid === t_sections[j].bssid) {
81 match = true;
82 break;
83 }
84 }
85 if (match === false) {
86 var vpn_stdservice = uci.get('travelmate', 'global', 'trm_stdvpnservice');
87 var vpn_stdiface = uci.get('travelmate', 'global', 'trm_stdvpniface');
88 var sid = uci.add('travelmate', 'uplink');
89
90 uci.set('travelmate', sid, 'enabled', '1');
91 uci.set('travelmate', sid, 'device', w_sections[i].device);
92 uci.set('travelmate', sid, 'ssid', w_sections[i].ssid);
93 uci.set('travelmate', sid, 'bssid', w_sections[i].bssid);
94 uci.set('travelmate', sid, 'con_start_expiry', '0');
95 uci.set('travelmate', sid, 'con_end_expiry', '0');
96 if (vpn_stdservice && vpn_stdiface) {
97 uci.set('travelmate', sid, 'vpn', '1');
98 uci.set('travelmate', sid, 'vpnservice', vpn_stdservice);
99 uci.set('travelmate', sid, 'vpniface', vpn_stdiface);
100 }
101 }
102 }
103 }
104
105 /*
106 update travelmate sections
107 */
108 function handleSectionsVal(action, section_id, option, value) {
109 var date, oldValue, w_device, w_ssid, w_bssid, t_sections;
110
111 w_device = uci.get('wireless', section_id, 'device');
112 w_ssid = uci.get('wireless', section_id, 'ssid');
113 w_bssid = uci.get('wireless', section_id, 'bssid');
114 t_sections = uci.sections('travelmate', 'uplink');
115
116 for (var i = 0; i < t_sections.length; i++) {
117 if (t_sections[i].device === w_device && t_sections[i].ssid === w_ssid && t_sections[i].bssid === w_bssid) {
118 if (action === 'get') {
119 return t_sections[i][option];
120 }
121 else if (action === 'set') {
122 if (option === 'enabled') {
123 oldValue = t_sections[i][option];
124 if (oldValue !== value && value === '0') {
125 date = new Date(new Date().getTime() - new Date().getTimezoneOffset() * 60 * 1000).toISOString().substr(0, 19).replace(/-/g, '.').replace('T', '-');
126 uci.set('travelmate', t_sections[i]['.name'], 'con_end', date);
127 }
128 else if (oldValue !== value && value === '1') {
129 uci.unset('travelmate', t_sections[i]['.name'], 'con_end');
130 }
131 }
132 return uci.set('travelmate', t_sections[i]['.name'], option, value);
133 }
134 else if (action === 'del') {
135 return uci.unset('travelmate', t_sections[i]['.name'], option);
136 }
137 }
138 }
139 }
140
141 /*
142 update travelmate status
143 */
144 function handleStatus() {
145 poll.add(function () {
146 L.resolveDefault(fs.stat('/var/state/travelmate.refresh'), null).then(function (res) {
147 if (res) {
148 L.resolveDefault(fs.read_direct('/var/state/travelmate.refresh'), null).then(async function (res) {
149 fs.remove('/var/state/travelmate.refresh');
150 if (res && res === 'ui_reload') {
151 location.reload();
152 }
153 else if (res && res === 'cfg_reload') {
154 if (document.readyState === 'complete') {
155 uci.unload('wireless');
156 uci.unload('travelmate');
157 }
158 await Promise.all([
159 uci.load('wireless'),
160 uci.load('travelmate')
161 ]);
162 var rows, item, value;
163 rows = document.querySelectorAll('.cbi-section-table-row[data-sid]');
164 for (var i = 0; i < rows.length; i++) {
165 item = rows[i].querySelector('.cbi-value-field[data-title="Enabled"]');
166 value = handleSectionsVal('get', rows[i].getAttribute('data-sid'), 'enabled');
167 item.textContent = (value == 0 ? 'No' : 'Yes');
168 }
169 }
170 });
171 }
172 });
173 return L.resolveDefault(fs.stat('/tmp/trm_runtime.json'), null).then(function (res) {
174 if (res) {
175 L.resolveDefault(fs.read_direct('/tmp/trm_runtime.json'), null).then(function (res) {
176 if (res) {
177 var info = JSON.parse(res);
178 if (info) {
179 var t_device, t_ssid, t_bssid, oldUplinkView, newUplinkView, uplinkColor,
180 uplinkId = info.data.station_id.trim().split('/'),
181 oldUplinkView = document.getElementsByName('uplinkStation'),
182 w_sections = uci.sections('wireless', 'wifi-iface'),
183 vpnStatus = info.data.ext_hooks.substr(13, 1);
184 t_device = uplinkId[0];
185 t_bssid = uplinkId[uplinkId.length - 1];
186 for (var i = 1; i < uplinkId.length - 1; i++) {
187 if (!t_ssid) {
188 t_ssid = uplinkId[i];
189 }
190 else {
191 t_ssid = t_ssid + '/' + uplinkId[i];
192 }
193 }
194 if (t_ssid === '-') {
195 if (oldUplinkView.length > 0) {
196 oldUplinkView[0].removeAttribute('style');
197 oldUplinkView[0].removeAttribute('name', 'uplinkStation');
198 }
199 }
200 else {
201 uplinkColor = (vpnStatus === "✔" ? 'rgb(68, 170, 68)' : 'rgb(51, 119, 204)');
202 for (var i = 0; i < w_sections.length; i++) {
203 newUplinkView = document.getElementById('cbi-wireless-' + w_sections[i]['.name']);
204 if (t_device === w_sections[i].device && t_ssid === w_sections[i].ssid && t_bssid === (w_sections[i].bssid || '-')) {
205 if (oldUplinkView.length === 0 && newUplinkView) {
206 newUplinkView.setAttribute('name', 'uplinkStation');
207 newUplinkView.setAttribute('style', 'text-align: left !important; color: ' + uplinkColor + ' !important;font-weight: bold !important;');
208 }
209 else if (oldUplinkView.length > 0 && newUplinkView && oldUplinkView[0].getAttribute('id') !== newUplinkView.getAttribute('id')) {
210 oldUplinkView[0].removeAttribute('style');
211 oldUplinkView[0].removeAttribute('name', 'uplinkStation');
212 newUplinkView.setAttribute('name', 'uplinkStation');
213 newUplinkView.setAttribute('style', 'text-align: left !important; color: ' + uplinkColor + ' !important;font-weight: bold !important;');
214 }
215 else if (newUplinkView && newUplinkView.style.color != uplinkColor) {
216 newUplinkView.setAttribute('style', 'text-align: left !important; color: ' + uplinkColor + ' !important;font-weight: bold !important;');
217 }
218 }
219 }
220 }
221 }
222 }
223 });
224 }
225 });
226 }, 1);
227 }
228
229 return view.extend({
230 load: function () {
231 return Promise.all([
232 L.resolveDefault(fs.exec_direct('/etc/init.d/travelmate', ['assoc']), {}),
233 uci.load('wireless'),
234 uci.load('travelmate')
235 ]);
236 },
237
238 render: function (result) {
239 var m, s, o,
240 iface = uci.get('travelmate', 'global', 'trm_iface') || 'trm_wwan';
241
242 m = new form.Map('wireless');
243 m.chain('travelmate');
244 s = m.section(form.GridSection, 'wifi-iface', null, _('Overview of all configured uplinks for travelmate. \
245 You can edit, remove or prioritize existing uplinks by drag \&#38; drop and scan for new ones.<br /> \
246 The currently used uplink connection is emphasized in <span style="color:rgb(51, 119, 204);font-weight:bold">blue</span>, \
247 an encrypted VPN uplink connection is emphasized in <span style="color:rgb(68, 170, 68);font-weight:bold">green</span>.'));
248 s.anonymous = true;
249 s.sortable = true;
250 s.filter = function (section_id) {
251 return (uci.get('wireless', section_id, 'network') == iface && uci.get('wireless', section_id, 'mode') == 'sta');
252 };
253 s.tab('wireless', _('Wireless Settings'));
254 s.tab('travelmate', _('Travelmate Settings'));
255 s.tab('vpn', _('VPN Settings'));
256 s.renderRowActions = function (section_id) {
257 var btns;
258 btns = [
259 E('button', {
260 'class': 'btn cbi-button drag-handle center',
261 'title': _('Drag to reorder'),
262 'style': 'cursor:move',
263 'disabled': this.map.readonly || null
264 }, '☰'),
265 E('button', {
266 'class': 'cbi-button cbi-button-action important',
267 'title': _('Edit this network'),
268 'click': ui.createHandlerFn(this, 'renderMoreOptionsModal', section_id)
269 }, _('Edit')),
270 E('button', {
271 'class': 'cbi-button cbi-button-apply',
272 'title': _('Enable/Disable this network'),
273 'click': ui.createHandlerFn(this, handleToggle, section_id)
274 }, _('On/Off')),
275 E('button', {
276 'class': 'cbi-button cbi-button-negative remove',
277 'title': _('Remove this network'),
278 'click': ui.createHandlerFn(this, handleRemove, section_id)
279 }, _('Remove'))
280 ];
281 return E('td', { 'class': 'td middle cbi-section-actions' }, E('div', btns));
282 };
283
284 o = s.taboption('travelmate', form.Flag, '_enabled', _('Enabled'));
285 o.uciconfig = 'travelmate';
286 o.ucisection = 'uplink';
287 o.ucioption = 'enabled';
288 o.rmempty = false;
289 o.cfgvalue = function (section_id) {
290 return handleSectionsVal('get', section_id, 'enabled');
291 }
292 o.write = function (section_id, value) {
293 return handleSectionsVal('set', section_id, 'enabled', value);
294 }
295
296 o = s.taboption('wireless', form.Value, 'device', _('Device'));
297 o.readonly = true;
298
299 o = s.taboption('wireless', form.Value, 'ssid', _('SSID'));
300 o.datatype = 'maxlength(32)';
301 o.readonly = true;
302
303 o = s.taboption('wireless', form.Value, 'bssid', _('BSSID'));
304 o.datatype = 'macaddr';
305 o.readonly = true;
306
307 o = s.taboption('wireless', form.ListValue, 'encryption', _('Encryption'));
308 o.value('sae', _('WPA3 Pers. (SAE)'));
309 o.value('sae-mixed', _('WPA2/WPA3 Pers. (CCMP)'));
310 o.value('psk2', _('WPA2 Pers.'));
311 o.value('psk2+ccmp', _('WPA2 Pers. (CCMP)'));
312 o.value('psk2+tkip', _('WPA2 Pers. (TKIP)'));
313 o.value('psk', _('WPA Pers.'));
314 o.value('psk+ccmp', _('WPA Pers. (CCMP)'));
315 o.value('psk+tkip', _('WPA Pers. (TKIP)'));
316 o.value('psk-mixed+ccmp', _('WPA/WPA2 Pers. (CCMP)'));
317 o.value('psk-mixed+tkip', _('WPA/WPA2 Pers. (TKIP)'));
318 o.value('wpa3', _('WPA3 Ent. (CCMP)'));
319 o.value('wpa3-mixed', _('WPA2/WPA3 Ent. (CCMP)'));
320 o.value('wpa2', _('WPA2 Ent.'));
321 o.value('wpa2+ccmp', _('WPA2 Ent. (CCMP)'));
322 o.value('wpa2+tkip', _('WPA2 Ent. (TKIP)'));
323 o.value('wpa+ccmp', _('WPA Ent. (CCMP)'));
324 o.value('wpa+tkip', _('WPA Ent. (TKIP)'));
325 o.value('wpa-mixed+ccmp', _('WPA/WPA2 Ent. (CCMP)'));
326 o.value('wpa-mixed+tkip', _('WPA/WPA2 Ent. (TKIP)'));
327 o.value('owe', _('OWE'));
328 o.value('none', _('none'));
329 o.default = 'none';
330 o.textvalue = function (section_id) {
331 var cfgvalue = this.map.data.get('wireless', section_id, 'encryption');
332 switch (cfgvalue) {
333 case 'sae':
334 cfgvalue = 'WPA3 Pers. (SAE)';
335 break;
336 case 'sae-mixed':
337 cfgvalue = 'WPA2/WPA3 Pers. (CCMP)';
338 break;
339 case 'psk2':
340 cfgvalue = 'WPA2 Pers.';
341 break;
342 case 'psk2+ccmp':
343 cfgvalue = 'WPA2 Pers. (CCMP)';
344 break;
345 case 'psk2+tkip':
346 cfgvalue = 'WPA2 Pers. (TKIP)';
347 break;
348 case 'psk':
349 cfgvalue = 'WPA Pers.';
350 break;
351 case 'psk-mixed+ccmp':
352 cfgvalue = 'WPA/WPA2 Pers. (CCMP)';
353 break;
354 case 'psk-mixed+tkip':
355 cfgvalue = 'WPA/WPA2 Pers. (TKIP)';
356 break;
357 case 'wpa3':
358 cfgvalue = 'WPA3 Ent. (CCMP)';
359 break;
360 case 'wpa3-mixed':
361 cfgvalue = 'WPA2/WPA3 Ent. (CCMP)';
362 break;
363 case 'wpa2':
364 cfgvalue = 'WPA2 Ent.';
365 break;
366 case 'wpa2+ccmp':
367 cfgvalue = 'WPA2 Ent. (CCMP)';
368 break;
369 case 'wpa2+tkip':
370 cfgvalue = 'WPA2 Ent. (TKIP)';
371 break;
372 case 'wpa+ccmp':
373 cfgvalue = 'WPA Ent. (CCMP)';
374 break;
375 case 'wpa+tkip':
376 cfgvalue = 'WPA Ent. (TKIP)';
377 break;
378 case 'wpa-mixed+ccmp':
379 cfgvalue = 'WPA/WPA2 Ent. (CCMP)';
380 break;
381 case 'wpa-mixed+tkip':
382 cfgvalue = 'WPA/WPA2 Ent. (TKIP)';
383 break;
384 case 'owe':
385 cfgvalue = 'WPA3 OWE (CCMP)';
386 break;
387 case 'none':
388 cfgvalue = 'none';
389 break;
390 }
391 return cfgvalue;
392 };
393 handleStatus();
394
395 /*
396 modal wireless tab
397 */
398 o = s.taboption('wireless', form.Value, 'key', _('Password'));
399 o.datatype = 'wpakey';
400 o.depends({ encryption: 'sae', '!contains': true });
401 o.depends({ encryption: 'psk', '!contains': true });
402 o.modalonly = true;
403 o.password = true;
404
405 o = s.taboption('wireless', form.Value, 'password', _('Password'));
406 o.datatype = 'wpakey';
407 o.depends({ encryption: 'wpa', '!contains': true });
408 o.modalonly = true;
409 o.password = true;
410
411 o = s.taboption('wireless', form.ListValue, 'eap_type', _('EAP-Method'));
412 o.depends({ encryption: 'wpa', '!contains': true });
413 o.value('tls', _('TLS'));
414 o.value('ttls', _('TTLS'));
415 o.value('peap', _('PEAP'));
416 o.value('fast', _('FAST'));
417 o.default = 'peap';
418 o.modalonly = true;
419
420 o = s.taboption('wireless', form.ListValue, 'auth', _('Authentication'));
421 o.value('PAP', _('PAP'));
422 o.value('CHAP', _('CHAP'));
423 o.value('MSCHAP', _('MSCHAP'));
424 o.value('MSCHAPV2', _('MSCHAPV2'));
425 o.value('EAP-GTC', _('EAP-GTC'));
426 o.value('EAP-MD5', _('EAP-MD5'));
427 o.value('EAP-MSCHAPV2', _('EAP-MSCHAPV2'));
428 o.value('EAP-TLS', _('EAP-TLS'));
429 o.value('auth=PAP', _('auth=PAP'));
430 o.value('auth=MSCHAPV2', _('auth=MSCHAPV2'));
431 o.default = 'EAP-MSCHAPV2';
432 o.depends({ encryption: 'wpa', '!contains': true });
433 o.modalonly = true;
434
435 o = s.taboption('wireless', form.Value, 'identity', _('Identity'));
436 o.depends({ encryption: 'wpa', '!contains': true });
437 o.modalonly = true;
438
439 o = s.taboption('wireless', form.Value, 'anonymous_identity', _('Anonymous Identity'));
440 o.depends({ encryption: 'wpa', '!contains': true });
441 o.modalonly = true;
442
443 o = s.taboption('wireless', form.ListValue, 'ieee80211w', _('Mgmt. Frame Protection'));
444 o.depends({ encryption: 'sae', '!contains': true });
445 o.depends({ encryption: 'owe', '!contains': true });
446 o.depends({ encryption: 'wpa', '!contains': true });
447 o.depends({ encryption: 'psk', '!contains': true });
448 o.value('', _('Disabled'));
449 o.value('1', _('Optional'));
450 o.value('2', _('Required'));
451 o.modalonly = true;
452 o.defaults = {
453 '2': [{ encryption: 'sae' }, { encryption: 'owe' }, { encryption: 'wpa3' }, { encryption: 'wpa3-mixed' }],
454 '1': [{ encryption: 'sae-mixed' }],
455 '': []
456 };
457
458 o = s.taboption('wireless', form.Flag, 'ca_cert_usesystem', _('Use system certificates'), _("Validate server certificate using built-in system CA bundle"));
459 o.depends({ encryption: 'wpa', '!contains': true });
460 o.enabled = '1';
461 o.disabled = '0';
462 o.modalonly = true;
463 o.default = o.disabled;
464
465 o = s.taboption('wireless', form.Value, 'ca_cert', _('Path to CA-Certificate'));
466 o.depends({ encryption: 'wpa', '!contains': true });
467 o.depends({ ca_cert_usesystem: '0' });
468 o.modalonly = true;
469 o.rmempty = true;
470
471 o = s.taboption('wireless', form.Value, 'client_cert', _('Path to Client-Certificate'));
472 o.depends({ eap_type: 'tls' });
473 o.modalonly = true;
474 o.rmempty = true;
475
476 o = s.taboption('wireless', form.Value, 'priv_key', _('Path to Private Key'));
477 o.depends({ eap_type: 'tls' });
478 o.modalonly = true;
479 o.rmempty = true;
480
481 o = s.taboption('wireless', form.Value, 'priv_key_pwd', _('Password of Private Key'));
482 o.depends({ eap_type: 'tls' });
483 o.modalonly = true;
484 o.password = true;
485 o.rmempty = true;
486
487 /*
488 modal travelmate tab
489 */
490 var mac, mac_array = [];
491 if (result[0]) {
492 mac_array = result[0].trim().split('\n');
493 }
494
495 o = s.taboption('travelmate', form.Value, '_ssid', _('SSID'));
496 o.modalonly = true;
497 o.uciconfig = 'travelmate';
498 o.ucisection = 'uplink';
499 o.ucioption = 'ssid';
500 o.rmempty = false;
501 o.readonly = true;
502 o.cfgvalue = function (section_id) {
503 return handleSectionsVal('get', section_id, 'ssid');
504 }
505
506 o = s.taboption('travelmate', form.Value, '_bssid', _('BSSID'));
507 o.modalonly = true;
508 o.uciconfig = 'travelmate';
509 o.ucisection = 'uplink';
510 o.ucioption = 'bssid';
511 o.rmempty = true;
512 o.readonly = true;
513 o.cfgvalue = function (section_id) {
514 return handleSectionsVal('get', section_id, 'bssid');
515 }
516
517 o = s.taboption('travelmate', form.Value, '_con_start', _('Connection Start'));
518 o.modalonly = true;
519 o.uciconfig = 'travelmate';
520 o.ucisection = 'uplink';
521 o.ucioption = 'con_start';
522 o.rmempty = true;
523 o.readonly = true;
524 o.cfgvalue = function (section_id) {
525 return handleSectionsVal('get', section_id, 'con_start');
526 }
527
528 o = s.taboption('travelmate', form.Value, '_con_end', _('Connection End'));
529 o.modalonly = true;
530 o.uciconfig = 'travelmate';
531 o.ucisection = 'uplink';
532 o.ucioption = 'con_end';
533 o.rmempty = true;
534 o.readonly = true;
535 o.cfgvalue = function (section_id) {
536 return handleSectionsVal('get', section_id, 'con_end');
537 }
538
539 o = s.taboption('travelmate', form.Flag, '_opensta', _('Auto Added Open Uplink'),
540 _('This option is selected by default if this uplink was added automatically and counts as \'Open Uplink\'.'));
541 o.rmempty = true;
542 o.modalonly = true;
543 o.uciconfig = 'travelmate';
544 o.ucisection = 'uplink';
545 o.ucioption = 'opensta';
546 o.cfgvalue = function (section_id) {
547 return handleSectionsVal('get', section_id, 'opensta');
548 }
549 o.write = function (section_id, value) {
550 return handleSectionsVal('set', section_id, 'opensta', value);
551 }
552 o.remove = function (section_id, value) {
553 return handleSectionsVal('set', section_id, 'opensta', value);
554 }
555
556 o = s.taboption('travelmate', form.Value, '_macaddr', _('MAC Address'),
557 _('Use the specified MAC address for this uplink.'));
558 for (var i = 0; i < mac_array.length; i++) {
559 if (mac_array[i].match(/^\s+([0-9A-Fa-f]{2}[:]?){5}[0-9A-Fa-f]{2}/)) {
560 mac = mac_array[i].slice(4).trim();
561 o.value(mac);
562 }
563 }
564 o.modalonly = true;
565 o.uciconfig = 'travelmate';
566 o.ucisection = 'uplink';
567 o.ucioption = 'macaddr';
568 o.nocreate = false;
569 o.rmempty = true;
570 o.datatype = 'macaddr';
571 o.cfgvalue = function (section_id) {
572 return handleSectionsVal('get', section_id, 'macaddr');
573 }
574 o.write = function (section_id, value) {
575 return handleSectionsVal('set', section_id, 'macaddr', value);
576 }
577 o.remove = function (section_id, value) {
578 return handleSectionsVal('set', section_id, 'macaddr', value);
579 }
580
581 o = s.taboption('travelmate', form.Value, '_con_start_expiry', _('Connection Start Expiry'),
582 _('Automatically disable the uplink after <em>n</em> minutes, e.g. for timed connections.<br /> \
583 The default of \'0\' disables this feature.'));
584 o.modalonly = true;
585 o.uciconfig = 'travelmate';
586 o.ucisection = 'uplink';
587 o.ucioption = 'con_start_expiry';
588 o.rmempty = false;
589 o.placeholder = '0';
590 o.default = '0';
591 o.datatype = 'range(0,720)';
592 o.cfgvalue = function (section_id) {
593 return handleSectionsVal('get', section_id, 'con_start_expiry');
594 }
595 o.write = function (section_id, value) {
596 return handleSectionsVal('set', section_id, 'con_start_expiry', value);
597 }
598
599 o = s.taboption('travelmate', form.Value, '_con_end_expiry', _('Connection End Expiry'),
600 _('Automatically (re-)enable the uplink after <em>n</em> minutes, e.g. after failed login attempts.<br /> \
601 The default of \'0\' disables this feature.'));
602 o.modalonly = true;
603 o.uciconfig = 'travelmate';
604 o.ucisection = 'uplink';
605 o.ucioption = 'con_end_expiry';
606 o.rmempty = false;
607 o.placeholder = '0';
608 o.default = '0';
609 o.datatype = 'range(0,720)';
610 o.cfgvalue = function (section_id) {
611 return handleSectionsVal('get', section_id, 'con_end_expiry');
612 }
613 o.write = function (section_id, value) {
614 return handleSectionsVal('set', section_id, 'con_end_expiry', value);
615 }
616
617 o = s.taboption('travelmate', form.FileUpload, '_script', _('Auto Login Script'),
618 _('External script reference which will be called for automated captive portal logins.'));
619 o.root_directory = '/etc/travelmate';
620 o.enable_remove = false;
621 o.enable_upload = false;
622 o.modalonly = true;
623 o.uciconfig = 'travelmate';
624 o.ucisection = 'uplink';
625 o.ucioption = 'script';
626 o.renderWidget = function (section_id, option_index, cfgvalue) {
627 var browserEl = new ui.FileUpload((cfgvalue != null) ? cfgvalue : this.default, {
628 id: this.cbid(section_id),
629 name: this.cbid(section_id),
630 show_hidden: this.show_hidden,
631 enable_upload: this.enable_upload,
632 enable_remove: this.enable_remove,
633 root_directory: this.root_directory,
634 disabled: (this.readonly != null) ? this.readonly : this.map.readonly
635 });
636 browserEl.renderListing = function (container, path, list) {
637 return ui.FileUpload.prototype.renderListing.apply(this, [
638 container, path,
639 list.filter(function (entry) {
640 return ((entry.type == 'directory') || (entry.type == 'file' && entry.name.match(/\.login$/)));
641 })
642 ]);
643 };
644 return browserEl.render();
645 };
646 o.cfgvalue = function (section_id) {
647 return handleSectionsVal('get', section_id, 'script');
648 }
649 o.write = function (section_id, value) {
650 return handleSectionsVal('set', section_id, 'script', value);
651 }
652 o.remove = function (section_id) {
653 return handleSectionsVal('del', section_id, 'script');
654 }
655
656 o = s.taboption('travelmate', form.Value, '_args', _('Script Arguments'),
657 _('Space separated list of additional arguments passed to the Auto Login Script, i.e. username and password'));
658 o.modalonly = true;
659 o.uciconfig = 'travelmate';
660 o.ucisection = 'uplink';
661 o.ucioption = 'script_args';
662 o.rmempty = true;
663 o.depends({ _script: '/etc/travelmate', '!contains': true });
664 o.cfgvalue = function (section_id) {
665 return handleSectionsVal('get', section_id, 'script_args');
666 }
667 o.write = function (section_id, value) {
668 return handleSectionsVal('set', section_id, 'script_args', value);
669 }
670 o.remove = function (section_id) {
671 return handleSectionsVal('del', section_id, 'script_args');
672 }
673
674 /*
675 modal vpn tab
676 */
677 o = s.taboption('vpn', form.Flag, '_vpn', _('VPN Hook'), _('Automatically handle VPN connections.<br /> \
678 Please note: This feature requires the additional configuration of <em>Wireguard</em> or <em>OpenVPN</em>.'));
679 o.rmempty = true;
680 o.modalonly = true;
681 o.uciconfig = 'travelmate';
682 o.ucisection = 'uplink';
683 o.ucioption = 'vpn';
684 o.cfgvalue = function (section_id) {
685 return handleSectionsVal('get', section_id, 'vpn');
686 }
687 o.write = function (section_id, value) {
688 return handleSectionsVal('set', section_id, 'vpn', value);
689 }
690 o.remove = function (section_id, value) {
691 return handleSectionsVal('set', section_id, 'vpn', value);
692 }
693
694 o = s.taboption('vpn', form.ListValue, '_vpnservice', _('VPN Service'));
695 o.value('wireguard');
696 o.value('openvpn');
697 o.optional = true;
698 o.modalonly = true;
699 o.uciconfig = 'travelmate';
700 o.ucisection = 'uplink';
701 o.ucioption = 'vpnservice';
702 o.cfgvalue = function (section_id) {
703 return handleSectionsVal('get', section_id, 'vpnservice');
704 }
705 o.write = function (section_id, value) {
706 return handleSectionsVal('set', section_id, 'vpnservice', value);
707 }
708
709 o = s.taboption('vpn', widgets.NetworkSelect, '_vpniface', _('VPN Interface'), _('The logical vpn network interface like \'wg0\'.'));
710 o.nocreate = true;
711 o.optional = true;
712 o.modalonly = true;
713 o.uciconfig = 'travelmate';
714 o.ucisection = 'uplink';
715 o.ucioption = 'vpniface';
716 o.cfgvalue = function (section_id) {
717 return handleSectionsVal('get', section_id, 'vpniface');
718 }
719 o.write = function (section_id, value) {
720 return handleSectionsVal('set', section_id, 'vpniface', value);
721 }
722
723 /*
724 scan buttons
725 */
726 s = m.section(form.GridSection, 'wifi-device');
727 s.anonymous = true;
728 s.addremove = false;
729 s.render = function () {
730 return network.getWifiDevices().then(L.bind(function (radios) {
731 var radio, ifname, btns = [];
732 for (var i = 0; i < radios.length; i++) {
733 radio = radios[i].sid;
734 if (radio) {
735 btns.push(E('button', {
736 'class': 'cbi-button cbi-button-apply',
737 'id': radio,
738 'click': ui.createHandlerFn(this, 'handleScan', radio)
739 }, [_('Scan on ' + radio + '...')]),
740 '\xa0')
741 }
742 }
743 return E('div', { 'class': 'left', 'style': 'display:flex; flex-direction:column' }, E('div', { 'class': 'left', 'style': 'padding-top:5px; padding-bottom:5px' }, btns));
744 }, this))
745 };
746
747 /*
748 modal 'scan' dialog
749 */
750 s.handleScan = function (radio) {
751 var table = E('table', { 'class': 'table' }, [
752 E('tr', { 'class': 'tr table-titles' }, [
753 E('th', { 'class': 'th col-1 middle left' }, _('Strength')),
754 E('th', { 'class': 'th col-1 middle left hide-xs' }, _('Channel')),
755 E('th', { 'class': 'th col-2 middle left' }, _('SSID')),
756 E('th', { 'class': 'th col-2 middle left' }, _('BSSID')),
757 E('th', { 'class': 'th col-3 middle left' }, _('Encryption')),
758 E('th', { 'class': 'th cbi-section-actions right' }, '\xa0')
759 ])
760 ]);
761 cbi_update_table(table, [], E('em', { class: 'spinning' }, _('Starting wireless scan on \'' + radio + '\'...')));
762
763 var md = ui.showModal(_('Wireless Scan'), [
764 table,
765 E('div', { 'class': 'right' }, [
766 E('button', {
767 'class': 'btn',
768 'click': ui.hideModal
769 }, _('Dismiss')),
770 '\xa0',
771 E('button', {
772 'class': 'cbi-button cbi-button-positive important',
773 'click': L.bind(this.handleScan, this, radio)
774 }, _('Repeat Scan'))
775 ])
776 ]);
777
778 md.style.maxWidth = '90%';
779 md.style.maxHeight = 'none';
780
781 return L.resolveDefault(fs.exec_direct('/etc/init.d/travelmate', ['scan', radio]), null)
782 .then(L.bind(function (res) {
783 var lines, strength, channel, encryption, tbl_encryption, bssid, ssid, tbl_ssid, rows = [];
784 if (res) {
785 lines = res.trim().split('\n');
786 for (var i = 0; i < lines.length; i++) {
787 if (lines[i].match(/^\s+[0-9]/)) {
788 encryption = lines[i].slice(80).trim();
789 if (!encryption.includes('WEP')) {
790 strength = lines[i].slice(4, 7).trim();
791 channel = lines[i].slice(15, 18).trim();
792 bssid = lines[i].slice(60, 77).trim();
793 ssid = lines[i].slice(25, 59).trim();
794 if (ssid.startsWith('"')) {
795 ssid = ssid.slice(1, ssid.length - 1);
796 tbl_ssid = ssid;
797 }
798 else {
799 ssid = "hidden";
800 tbl_ssid = "<em>hidden</em>";
801 }
802 switch (encryption) {
803 case 'WPA3 PSK (SAE)':
804 encryption = 'sae';
805 tbl_encryption = 'WPA3 Pers. (SAE)';
806 break;
807 case 'mixed WPA2/WPA3 PSK/SAE (CCMP)':
808 encryption = 'sae-mixed';
809 tbl_encryption = 'WPA2/WPA3 Pers. (CCMP)';
810 break;
811 case 'WPA2 PSK (CCMP)':
812 encryption = 'psk2+ccmp';
813 tbl_encryption = 'WPA2 Pers. (CCMP)';
814 break;
815 case 'WPA2 PSK (TKIP)':
816 encryption = 'psk2+tkip';
817 tbl_encryption = 'WPA2 Pers. (TKIP)';
818 break;
819 case 'mixed WPA/WPA2 PSK (TKIP, CCMP)':
820 encryption = 'psk-mixed+ccmp';
821 tbl_encryption = 'WPA/WPA2 Pers. (CCMP)';
822 break;
823 case 'WPA PSK (CCMP)':
824 encryption = 'psk2+ccmp';
825 tbl_encryption = 'WPA Pers. (CCMP)';
826 break;
827 case 'WPA PSK (TKIP)':
828 encryption = 'psk2+tkip';
829 tbl_encryption = 'WPA Pers. (TKIP)';
830 break;
831 case 'WPA3 802.1X (CCMP)':
832 encryption = 'wpa3';
833 tbl_encryption = 'WPA3 Ent. (CCMP)';
834 break;
835 case 'mixed WPA2/WPA3 802.1X (CCMP)':
836 encryption = 'wpa3-mixed';
837 tbl_encryption = 'WPA2/WPA3 Ent. (CCMP)';
838 break;
839 case 'WPA2 802.1X':
840 encryption = 'wpa2';
841 tbl_encryption = 'WPA2 Ent.';
842 break;
843 case 'WPA2 802.1X (CCMP)':
844 encryption = 'wpa2+ccmp';
845 tbl_encryption = 'WPA2 Ent. (CCMP)';
846 break;
847 case 'WPA3 OWE (CCMP)':
848 encryption = 'owe';
849 tbl_encryption = 'WPA3 OWE (CCMP)';
850 break;
851 case 'none':
852 encryption = 'none';
853 tbl_encryption = 'none';
854 break;
855 }
856 rows.push([
857 strength,
858 channel,
859 tbl_ssid,
860 bssid,
861 tbl_encryption,
862 E('div', { 'class': 'right' }, E('button', {
863 'class': 'cbi-button cbi-button-action',
864 'click': ui.createHandlerFn(this, 'handleAdd', radio, iface, ssid, bssid, encryption)
865 }, _('Add Uplink...')))
866 ]);
867 }
868 }
869 else if (lines[i] === '::: Empty resultset') {
870 rows.push([
871 'No scan results (empty resultset)'
872 ]);
873 }
874 }
875 }
876 else {
877 rows.push([
878 'No scan results (timeout)'
879 ]);
880 }
881 cbi_update_table(table, rows);
882 }, this));
883 };
884
885 /*
886 modal 'add' dialog
887 */
888 s.handleAdd = function (radio, iface, ssid, bssid, encryption, ev) {
889 var m2, s2, o2;
890
891 m2 = new form.Map('wireless'),
892 s2 = m2.section(form.NamedSection, '_add_trm');
893
894 s2.render = function () {
895 return Promise.all([
896 {},
897 this.renderUCISection('_add_trm')
898 ]).then(this.renderContents.bind(this));
899 };
900
901 o2 = s2.option(form.Value, 'device', _('Device Name'));
902 o2.default = radio;
903 o2.readonly = true;
904
905 o2 = s2.option(form.Value, 'network', _('Interface Name'));
906 o2.default = iface;
907 o2.readonly = true;
908
909 if (ssid === "hidden") {
910 o2 = s2.option(form.Value, 'ssid', _('SSID (hidden)'));
911 o2.placeholder = 'hidden SSID';
912 }
913 else {
914 o2 = s2.option(form.Value, 'ssid', _('SSID'));
915 o2.default = ssid;
916 }
917 o2.datatype = 'maxlength(32)';
918 o2.rmempty = false;
919
920 o2 = s2.option(form.Flag, 'ignore_bssid', _('Ignore BSSID'));
921 if (ssid === "hidden") {
922 o2.default = '0';
923 }
924 else {
925 o2.default = '1';
926 }
927
928 o2 = s2.option(form.Value, 'bssid', _('BSSID'));
929 o2.depends({ ignore_bssid: '0' });
930 o2.datatype = 'macaddr';
931 o2.rmempty = true;
932 o2.default = bssid;
933
934 o2 = s2.option(form.ListValue, 'encryption', _('Encryption'));
935 o2.value('sae', _('WPA3 Pers. (SAE)'));
936 o2.value('sae-mixed', _('WPA2/WPA3 Pers. (CCMP)'));
937 o2.value('psk2', _('WPA2 Pers.'));
938 o2.value('psk2+ccmp', _('WPA2 Pers. (CCMP)'));
939 o2.value('psk2+tkip', _('WPA2 Pers. (TKIP)'));
940 o2.value('psk', _('WPA Pers.'));
941 o2.value('psk+ccmp', _('WPA Pers. (CCMP)'));
942 o2.value('psk+tkip', _('WPA Pers. (TKIP)'));
943 o2.value('psk-mixed+ccmp', _('WPA/WPA2 Pers. (CCMP)'));
944 o2.value('psk-mixed+tkip', _('WPA/WPA2 Pers. (TKIP)'));
945 o2.value('wpa3', _('WPA3 Ent.'));
946 o2.value('wpa3-mixed', _('WPA2/WPA3 Ent.'));
947 o2.value('wpa2', _('WPA2 Ent.'));
948 o2.value('wpa2+ccmp', _('WPA2 Ent. (CCMP)'));
949 o2.value('wpa2+tkip', _('WPA2 Ent. (TKIP)'));
950 o2.value('wpa+ccmp', _('WPA Ent. (CCMP)'));
951 o2.value('wpa+tkip', _('WPA Ent. (TKIP)'));
952 o2.value('wpa-mixed+ccmp', _('WPA/WPA2 Ent. (CCMP)'));
953 o2.value('wpa-mixed+tkip', _('WPA/WPA2 Ent. (TKIP)'));
954 o2.value('owe', _('WPA3 OWE (CCMP)'));
955 o2.value('none', _('none'));
956 o2.default = encryption;
957
958 o2 = s2.option(form.Value, 'key', _('Password'));
959 o2.depends({ encryption: 'sae', '!contains': true });
960 o2.depends({ encryption: 'psk', '!contains': true });
961 o2.datatype = 'wpakey';
962 o2.password = true;
963
964 o2 = s2.option(form.Value, 'password', _('Password'));
965 o2.depends({ encryption: 'wpa', '!contains': true });
966 o2.datatype = 'wpakey';
967 o2.password = true;
968
969 o2 = s2.option(form.ListValue, 'eap_type', _('EAP-Method'));
970 o2.depends({ encryption: 'wpa', '!contains': true });
971 o2.value('tls', _('TLS'));
972 o2.value('ttls', _('TTLS'));
973 o2.value('peap', _('PEAP'));
974 o2.value('fast', _('FAST'));
975 o2.default = 'peap';
976
977 o2 = s2.option(form.ListValue, 'auth', _('Authentication'));
978 o2.depends({ encryption: 'wpa', '!contains': true });
979 o2.value('PAP', _('PAP'));
980 o2.value('CHAP', _('CHAP'));
981 o2.value('MSCHAP', _('MSCHAP'));
982 o2.value('MSCHAPV2', _('MSCHAPV2'));
983 o2.value('EAP-GTC', _('EAP-GTC'));
984 o2.value('EAP-MD5', _('EAP-MD5'));
985 o2.value('EAP-MSCHAPV2', _('EAP-MSCHAPV2'));
986 o2.value('EAP-TLS', _('EAP-TLS'));
987 o2.value('auth=PAP', _('auth=PAP'));
988 o2.value('auth=MSCHAPV2', _('auth=MSCHAPV2'));
989 o2.default = 'EAP-MSCHAPV2';
990
991 o2 = s2.option(form.Value, 'identity', _('Identity'));
992 o2.depends({ encryption: 'wpa', '!contains': true });
993
994 o2 = s2.option(form.Value, 'anonymous_identity', _('Anonymous Identity'));
995 o2.depends({ encryption: 'wpa', '!contains': true });
996 o2.rmempty = true;
997
998 o2 = s2.option(form.ListValue, 'ieee80211w', _('Mgmt. Frame Protection'));
999 o2.depends({ encryption: 'sae', '!contains': true });
1000 o2.depends({ encryption: 'owe', '!contains': true });
1001 o2.depends({ encryption: 'wpa', '!contains': true });
1002 o2.depends({ encryption: 'psk', '!contains': true });
1003 o2.value('', _('Disabled'));
1004 o2.value('1', _('Optional'));
1005 o2.value('2', _('Required'));
1006 o2.defaults = {
1007 '2': [{ encryption: 'sae' }, { encryption: 'owe' }, { encryption: 'wpa3' }, { encryption: 'wpa3-mixed' }],
1008 '1': [{ encryption: 'sae-mixed' }],
1009 '': []
1010 };
1011
1012 o2 = s2.option(form.Flag, 'ca_cert_usesystem', _('Use system certificates'), _("Validate server certificate using built-in system CA bundle"));
1013 o2.depends({ encryption: 'wpa', '!contains': true });
1014 o2.enabled = '1';
1015 o2.disabled = '0';
1016 o2.default = o.disabled;
1017
1018 o2 = s2.option(form.Value, 'ca_cert', _('Path to CA-Certificate'));
1019 o2.depends({ encryption: 'wpa', '!contains': true });
1020 o2.depends({ ca_cert_usesystem: '0' });
1021 o2.rmempty = true;
1022
1023 o2 = s2.option(form.Value, 'client_cert', _('Path to Client-Certificate'));
1024 o2.depends({ eap_type: 'tls' });
1025 o2.rmempty = true;
1026
1027 o2 = s2.option(form.Value, 'priv_key', _('Path to Private Key'));
1028 o2.depends({ eap_type: 'tls' });
1029 o2.rmempty = true;
1030
1031 o2 = s2.option(form.Value, 'priv_key_pwd', _('Password of Private Key'));
1032 o2.depends({ eap_type: 'tls' });
1033 o2.password = true;
1034 o2.rmempty = true;
1035
1036 return m2.render().then(L.bind(function (elements) {
1037 ui.showModal(_('Add Uplink %q').replace(/%q/, '"%h"'.format(ssid)), [
1038 elements,
1039 E('div', { 'class': 'right' }, [
1040 E('button', {
1041 'class': 'btn',
1042 'click': ui.hideModal
1043 }, _('Dismiss')),
1044 '\xa0',
1045 E('button', {
1046 'class': 'cbi-button cbi-button-positive important',
1047 'click': ui.createHandlerFn(this, 'handleCommit', m2)
1048 }, _('Save'))
1049 ])
1050 ]);
1051 }, this));
1052 };
1053
1054 /*
1055 save new uplink
1056 */
1057 s.handleCommit = function (map, ev) {
1058 var w_sections = uci.sections('wireless', 'wifi-iface'),
1059 device = L.toArray(map.lookupOption('device', '_add_trm'))[0].formvalue('_add_trm'),
1060 network = L.toArray(map.lookupOption('network', '_add_trm'))[0].formvalue('_add_trm'),
1061 ssid = L.toArray(map.lookupOption('ssid', '_add_trm'))[0].formvalue('_add_trm'),
1062 ignore_bssid = L.toArray(map.lookupOption('ignore_bssid', '_add_trm'))[0].formvalue('_add_trm'),
1063 bssid = L.toArray(map.lookupOption('bssid', '_add_trm'))[0].formvalue('_add_trm'),
1064 encryption = L.toArray(map.lookupOption('encryption', '_add_trm'))[0].formvalue('_add_trm');
1065 if (encryption.includes('wpa')) {
1066 var eap_type = L.toArray(map.lookupOption('eap_type', '_add_trm'))[0].formvalue('_add_trm'),
1067 auth = L.toArray(map.lookupOption('auth', '_add_trm'))[0].formvalue('_add_trm'),
1068 identity = L.toArray(map.lookupOption('identity', '_add_trm'))[0].formvalue('_add_trm'),
1069 anonymous_identity = L.toArray(map.lookupOption('anonymous_identity', '_add_trm'))[0].formvalue('_add_trm'),
1070 password = L.toArray(map.lookupOption('password', '_add_trm'))[0].formvalue('_add_trm'),
1071 ca_cert_usesystem = L.toArray(map.lookupOption('ca_cert_usesystem', '_add_trm'))[0].formvalue('_add_trm'),
1072 ca_cert = L.toArray(map.lookupOption('ca_cert', '_add_trm'))[0].formvalue('_add_trm'),
1073 ieee80211w = L.toArray(map.lookupOption('ieee80211w', '_add_trm'))[0].formvalue('_add_trm');
1074 if (eap_type.includes('tls')) {
1075 var client_cert = L.toArray(map.lookupOption('client_cert', '_add_trm'))[0].formvalue('_add_trm'),
1076 priv_key = L.toArray(map.lookupOption('priv_key', '_add_trm'))[0].formvalue('_add_trm'),
1077 priv_key_pwd = L.toArray(map.lookupOption('priv_key_pwd', '_add_trm'))[0].formvalue('_add_trm');
1078 }
1079 } else {
1080 var password = L.toArray(map.lookupOption('key', '_add_trm'))[0].formvalue('_add_trm');
1081 }
1082 if (!ssid || ((encryption.includes('psk') || encryption.includes('wpa') || encryption.includes('sae')) && !password)) {
1083 if (!ssid) {
1084 ui.addNotification(null, E('p', 'Empty SSID, the uplink station could not be saved.'), 'error');
1085 }
1086 else {
1087 ui.addNotification(null, E('p', 'Empty Password, the uplink station could not be saved.'), 'error');
1088 }
1089 return ui.hideModal();
1090 }
1091 for (var i = 0; i < w_sections.length; i++) {
1092 if (w_sections[i].device === device && w_sections[i].ssid === ssid) {
1093 if (ignore_bssid === '1' || (ignore_bssid === '0' && w_sections[i].bssid === bssid)) {
1094 ui.addNotification(null, E('p', 'Duplicate wireless entry, the uplink station could not be saved.'), 'error');
1095 return ui.hideModal();
1096 }
1097 }
1098 }
1099
1100 var offset = w_sections.length,
1101 new_sid = 'trm_uplink' + (++offset);
1102 while (uci.get('wireless', new_sid)) {
1103 new_sid = 'trm_uplink' + (++offset);
1104 }
1105 uci.add('wireless', 'wifi-iface', new_sid);
1106 uci.set('wireless', new_sid, 'device', device);
1107 uci.set('wireless', new_sid, 'mode', 'sta');
1108 uci.set('wireless', new_sid, 'network', network);
1109 uci.set('wireless', new_sid, 'ssid', ssid);
1110 if (ignore_bssid === '0') {
1111 uci.set('wireless', new_sid, 'bssid', bssid);
1112 }
1113 uci.set('wireless', new_sid, 'encryption', encryption);
1114 if (encryption.includes('wpa')) {
1115 uci.set('wireless', new_sid, 'eap_type', eap_type);
1116 uci.set('wireless', new_sid, 'auth', auth);
1117 uci.set('wireless', new_sid, 'identity', identity);
1118 uci.set('wireless', new_sid, 'anonymous_identity', anonymous_identity);
1119 uci.set('wireless', new_sid, 'password', password);
1120 uci.set('wireless', new_sid, 'ca_cert_usesystem', ca_cert_usesystem);
1121 uci.set('wireless', new_sid, 'ca_cert', ca_cert);
1122 uci.set('wireless', new_sid, 'ieee80211w', ieee80211w);
1123 if (eap_type.includes('tls')) {
1124 uci.set('wireless', new_sid, 'client_cert', client_cert);
1125 uci.set('wireless', new_sid, 'priv_key', priv_key);
1126 uci.set('wireless', new_sid, 'priv_key_pwd', priv_key_pwd);
1127 }
1128 } else {
1129 uci.set('wireless', new_sid, 'key', password);
1130 }
1131 uci.set('wireless', new_sid, 'disabled', '1');
1132 handleSectionsAdd(network);
1133 uci.save()
1134 .then(L.bind(this.map.load, this.map))
1135 .then(L.bind(this.map.reset, this.map))
1136 .then(function () {
1137 var row = document.querySelector('.cbi-section-table-row[data-sid="%s"]'.format(new_sid));
1138 row.setAttribute('style', 'opacity: 0.5; color: #4a4 !important;');
1139 })
1140 .then(ui.hideModal)
1141 };
1142 return m.render();
1143 },
1144 handleReset: null
1145 });