]> git.proxmox.com Git - pve-manager.git/blame - www/manager6/Parser.js
ui: add ACMEAPiSelector field
[pve-manager.git] / www / manager6 / Parser.js
CommitLineData
fcb64fe4
DM
1// Some configuration values are complex strings -
2// so we need parsers/generators for them.
3
4Ext.define('PVE.Parser', { statics: {
5
6 // this class only contains static functions
7
488be4c2
DC
8 parseACME: function(value) {
9 if (!value) {
10 return;
11 }
12
13 var res = {};
08a61c7b 14 var error;
488be4c2
DC
15
16 Ext.Array.each(value.split(','), function(p) {
08a61c7b
FG
17 var kv = p.split('=', 2);
18 if (Ext.isDefined(kv[1])) {
19 res[kv[0]] = kv[1];
488be4c2 20 } else {
08a61c7b 21 error = 'Failed to parse key-value pair: '+p;
488be4c2
DC
22 return false;
23 }
24 });
25
08a61c7b
FG
26 if (error !== undefined) {
27 console.error(error);
488be4c2
DC
28 return;
29 }
30
08a61c7b
FG
31 if (res.domains !== undefined) {
32 res.domains = res.domains.split(/;/);
33 }
34
488be4c2
DC
35 return res;
36 },
37
4c1c0d5d 38 parseBoolean: function(value, default_value) {
84de645d 39 if (!Ext.isDefined(value)) {
4c1c0d5d 40 return default_value;
84de645d 41 }
4c1c0d5d 42 value = value.toLowerCase();
ec0bd652 43 return value === '1' ||
4c1c0d5d
EK
44 value === 'on' ||
45 value === 'yes' ||
46 value === 'true';
47 },
48
3d6189d3
SI
49 parsePropertyString: function(value, defaultKey) {
50 var res = {},
9bbdcdff 51 error;
3d6189d3 52
4a7248d4
TL
53 if (typeof value !== 'string' || value === '') {
54 return res;
55 }
56
3d6189d3
SI
57 Ext.Array.each(value.split(','), function(p) {
58 var kv = p.split('=', 2);
59 if (Ext.isDefined(kv[1])) {
60 res[kv[0]] = kv[1];
61 } else if (Ext.isDefined(defaultKey)) {
62 if (Ext.isDefined(res[defaultKey])) {
9bbdcdff
TL
63 error = 'defaultKey may be only defined once in propertyString';
64 return false; // break
3d6189d3
SI
65 }
66 res[defaultKey] = kv[0];
67 } else {
9bbdcdff 68 error = 'invalid propertyString, not a key=value pair and no defaultKey defined';
3d6189d3
SI
69 return false; // break
70 }
71 });
72
9bbdcdff
TL
73 if (error !== undefined) {
74 console.error(error);
3d6189d3
SI
75 return;
76 }
77
78 return res;
79 },
80
81 printPropertyString: function(data, defaultKey) {
6de2baee
TL
82 var stringparts = [],
83 gotDefaultKeyVal = false,
84 defaultKeyVal;
3d6189d3
SI
85
86 Ext.Object.each(data, function(key, value) {
8007aaaf 87 if (defaultKey !== undefined && key === defaultKey) {
6de2baee
TL
88 gotDefaultKeyVal = true;
89 defaultKeyVal = value;
08e38f03 90 } else if (value !== '') {
8007aaaf 91 stringparts.push(key + '=' + value);
3d6189d3 92 }
3d6189d3
SI
93 });
94
6de2baee
TL
95 stringparts = stringparts.sort();
96 if (gotDefaultKeyVal) {
97 stringparts.unshift(defaultKeyVal);
98 }
99
3d6189d3
SI
100 return stringparts.join(',');
101 },
102
fcb64fe4
DM
103 parseQemuNetwork: function(key, value) {
104 if (!(key && value)) {
105 return;
106 }
107
108 var res = {};
109
110 var errors = false;
111 Ext.Array.each(value.split(','), function(p) {
112 if (!p || p.match(/^\s*$/)) {
113 return; // continue
114 }
115
116 var match_res;
117
118 if ((match_res = p.match(/^(ne2k_pci|e1000|e1000-82540em|e1000-82544gc|e1000-82545em|vmxnet3|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i)) !== null) {
119 res.model = match_res[1].toLowerCase();
120 if (match_res[3]) {
121 res.macaddr = match_res[3];
122 }
123 } else if ((match_res = p.match(/^bridge=(\S+)$/)) !== null) {
124 res.bridge = match_res[1];
125 } else if ((match_res = p.match(/^rate=(\d+(\.\d+)?)$/)) !== null) {
126 res.rate = match_res[1];
127 } else if ((match_res = p.match(/^tag=(\d+(\.\d+)?)$/)) !== null) {
63e62a6f 128 res.tag = match_res[1];
fcb64fe4 129 } else if ((match_res = p.match(/^firewall=(\d+)$/)) !== null) {
63e62a6f 130 res.firewall = match_res[1];
fcb64fe4 131 } else if ((match_res = p.match(/^link_down=(\d+)$/)) !== null) {
63e62a6f 132 res.disconnect = match_res[1];
fcb64fe4 133 } else if ((match_res = p.match(/^queues=(\d+)$/)) !== null) {
63e62a6f 134 res.queues = match_res[1];
a2ed0697
WB
135 } else if ((match_res = p.match(/^trunks=(\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*)$/)) !== null) {
136 res.trunks = match_res[1];
fcb64fe4
DM
137 } else {
138 errors = true;
139 return false; // break
140 }
141 });
142
143 if (errors || !res.model) {
144 return;
145 }
146
147 return res;
148 },
149
150 printQemuNetwork: function(net) {
151
152 var netstr = net.model;
153 if (net.macaddr) {
154 netstr += "=" + net.macaddr;
155 }
156 if (net.bridge) {
157 netstr += ",bridge=" + net.bridge;
158 if (net.tag) {
159 netstr += ",tag=" + net.tag;
160 }
161 if (net.firewall) {
162 netstr += ",firewall=" + net.firewall;
163 }
164 }
165 if (net.rate) {
166 netstr += ",rate=" + net.rate;
167 }
168 if (net.queues) {
169 netstr += ",queues=" + net.queues;
170 }
171 if (net.disconnect) {
172 netstr += ",link_down=" + net.disconnect;
173 }
a2ed0697
WB
174 if (net.trunks) {
175 netstr += ",trunks=" + net.trunks;
176 }
fcb64fe4
DM
177 return netstr;
178 },
179
180 parseQemuDrive: function(key, value) {
181 if (!(key && value)) {
182 return;
183 }
184
185 var res = {};
186
187 var match_res = key.match(/^([a-z]+)(\d+)$/);
188 if (!match_res) {
189 return;
190 }
191 res['interface'] = match_res[1];
192 res.index = match_res[2];
193
194 var errors = false;
195 Ext.Array.each(value.split(','), function(p) {
196 if (!p || p.match(/^\s*$/)) {
197 return; // continue
198 }
199 var match_res = p.match(/^([a-z_]+)=(\S+)$/);
200 if (!match_res) {
201 if (!p.match(/\=/)) {
202 res.file = p;
203 return; // continue
204 }
205 errors = true;
206 return false; // break
207 }
208 var k = match_res[1];
209 if (k === 'volume') {
210 k = 'file';
211 }
212
213 if (Ext.isDefined(res[k])) {
214 errors = true;
215 return false; // break
216 }
217
218 var v = match_res[2];
219
220 if (k === 'cache' && v === 'off') {
221 v = 'none';
222 }
223
224 res[k] = v;
225 });
226
227 if (errors || !res.file) {
228 return;
229 }
230
231 return res;
232 },
233
234 printQemuDrive: function(drive) {
235
236 var drivestr = drive.file;
237
238 Ext.Object.each(drive, function(key, value) {
239 if (!Ext.isDefined(value) || key === 'file' ||
240 key === 'index' || key === 'interface') {
241 return; // continue
242 }
243 drivestr += ',' + key + '=' + value;
244 });
245
246 return drivestr;
247 },
248
01e02121
DC
249 parseIPConfig: function(key, value) {
250 if (!(key && value)) {
251 return;
252 }
253
254 var res = {};
255
256 var errors = false;
257 Ext.Array.each(value.split(','), function(p) {
258 if (!p || p.match(/^\s*$/)) {
259 return; // continue
260 }
261
262 var match_res;
263 if ((match_res = p.match(/^ip=(\S+)$/)) !== null) {
264 res.ip = match_res[1];
265 } else if ((match_res = p.match(/^gw=(\S+)$/)) !== null) {
266 res.gw = match_res[1];
267 } else if ((match_res = p.match(/^ip6=(\S+)$/)) !== null) {
268 res.ip6 = match_res[1];
269 } else if ((match_res = p.match(/^gw6=(\S+)$/)) !== null) {
270 res.gw6 = match_res[1];
271 } else {
272 errors = true;
273 return false; // break
274 }
275 });
276
277 if (errors) {
278 return;
279 }
280
281 return res;
282 },
283
284 printIPConfig: function(cfg) {
285 var c = "";
286 var str = "";
287 if (cfg.ip) {
288 str += "ip=" + cfg.ip;
289 c = ",";
290 }
291 if (cfg.gw) {
292 str += c + "gw=" + cfg.gw;
293 c = ",";
294 }
295 if (cfg.ip6) {
296 str += c + "ip6=" + cfg.ip6;
297 c = ",";
298 }
299 if (cfg.gw6) {
300 str += c + "gw6=" + cfg.gw6;
301 c = ",";
302 }
303 return str;
304 },
305
fcb64fe4
DM
306 parseOpenVZNetIf: function(value) {
307 if (!value) {
308 return;
309 }
310
311 var res = {};
312
313 var errors = false;
314 Ext.Array.each(value.split(';'), function(item) {
315 if (!item || item.match(/^\s*$/)) {
316 return; // continue
317 }
318
319 var data = {};
320 Ext.Array.each(item.split(','), function(p) {
321 if (!p || p.match(/^\s*$/)) {
322 return; // continue
323 }
324 var match_res = p.match(/^(ifname|mac|bridge|host_ifname|host_mac|mac_filter)=(\S+)$/);
325 if (!match_res) {
326 errors = true;
327 return false; // break
328 }
329 if (match_res[1] === 'bridge'){
330 var bridgevlanf = match_res[2];
331 var bridge_res = bridgevlanf.match(/^(vmbr(\d+))(v(\d+))?(f)?$/);
332 if (!bridge_res) {
333 errors = true;
334 return false; // break
335 }
ec0bd652
DC
336 data.bridge = bridge_res[1];
337 data.tag = bridge_res[4];
338 /*jslint confusion: true*/
339 data.firewall = bridge_res[5] ? 1 : 0;
340 /*jslint confusion: false*/
fcb64fe4
DM
341 } else {
342 data[match_res[1]] = match_res[2];
343 }
344 });
345
346 if (errors || !data.ifname) {
347 errors = true;
348 return false; // break
349 }
350
351 data.raw = item;
352
353 res[data.ifname] = data;
354 });
355
356 return errors ? undefined: res;
357 },
358
359 printOpenVZNetIf: function(netif) {
360 var netarray = [];
361
362 Ext.Object.each(netif, function(iface, data) {
363 var tmparray = [];
364 Ext.Array.each(['ifname', 'mac', 'bridge', 'host_ifname' , 'host_mac', 'mac_filter', 'tag', 'firewall'], function(key) {
365 var value = data[key];
366 if (key === 'bridge'){
ec0bd652
DC
367 if(data.tag){
368 value = value + 'v' + data.tag;
fcb64fe4 369 }
ec0bd652 370 if (data.firewall){
fcb64fe4
DM
371 value = value + 'f';
372 }
373 }
374 if (value) {
375 tmparray.push(key + '=' + value);
376 }
377
378 });
379 netarray.push(tmparray.join(','));
380 });
381
382 return netarray.join(';');
383 },
384
385 parseLxcNetwork: function(value) {
386 if (!value) {
387 return;
388 }
389
390 var data = {};
391 Ext.Array.each(value.split(','), function(p) {
392 if (!p || p.match(/^\s*$/)) {
393 return; // continue
394 }
95e77b22
TL
395 var match_res = p.match(/^(bridge|hwaddr|mtu|name|ip|ip6|gw|gw6|tag|rate)=(\S+)$/);
396 if (match_res) {
397 data[match_res[1]] = match_res[2];
398 } else if ((match_res = p.match(/^firewall=(\d+)$/)) !== null) {
805a7cb8 399 data.firewall = PVE.Parser.parseBoolean(match_res[1]);
95e77b22 400 } else {
fcb64fe4
DM
401 // todo: simply ignore errors ?
402 return; // continue
403 }
fcb64fe4
DM
404 });
405
406 return data;
407 },
408
409 printLxcNetwork: function(data) {
410 var tmparray = [];
411 Ext.Array.each(['bridge', 'hwaddr', 'mtu', 'name', 'ip',
412 'gw', 'ip6', 'gw6', 'firewall', 'tag'], function(key) {
413 var value = data[key];
414 if (value) {
415 tmparray.push(key + '=' + value);
416 }
417 });
519ca7fa 418
ec0bd652 419 /*jslint confusion: true*/
6efbc4cb 420 if (data.rate > 0) {
519ca7fa
DM
421 tmparray.push('rate=' + data.rate);
422 }
ec0bd652 423 /*jslint confusion: false*/
fcb64fe4
DM
424 return tmparray.join(',');
425 },
426
4c1c0d5d
EK
427 parseLxcMountPoint: function(value) {
428 if (!value) {
429 return;
430 }
431
432 var res = {};
433
434 var errors = false;
435 Ext.Array.each(value.split(','), function(p) {
436 if (!p || p.match(/^\s*$/)) {
437 return; // continue
438 }
a108c35a 439 var match_res = p.match(/^([a-z_]+)=(.+)$/);
4c1c0d5d
EK
440 if (!match_res) {
441 if (!p.match(/\=/)) {
442 res.file = p;
443 return; // continue
444 }
445 errors = true;
446 return false; // break
447 }
448 var k = match_res[1];
449 if (k === 'volume') {
450 k = 'file';
451 }
452
453 if (Ext.isDefined(res[k])) {
454 errors = true;
455 return false; // break
456 }
457
458 var v = match_res[2];
459
460 res[k] = v;
461 });
462
463 if (errors || !res.file) {
464 return;
465 }
466
283b450e 467 var m = res.file.match(/^([a-z][a-z0-9\-\_\.]*[a-z0-9]):/i);
4c1c0d5d
EK
468 if (m) {
469 res.storage = m[1];
470 res.type = 'volume';
471 } else if (res.file.match(/^\/dev\//)) {
472 res.type = 'device';
473 } else {
474 res.type = 'bind';
475 }
476
477 return res;
478 },
479
480 printLxcMountPoint: function(mp) {
481 var drivestr = mp.file;
482
483 Ext.Object.each(mp, function(key, value) {
484 if (!Ext.isDefined(value) || key === 'file' ||
485 key === 'type' || key === 'storage') {
486 return; // continue
487 }
488 drivestr += ',' + key + '=' + value;
489 });
490
491 return drivestr;
492 },
493
fcb64fe4
DM
494 parseStartup: function(value) {
495 if (value === undefined) {
496 return;
497 }
498
499 var res = {};
500
501 var errors = false;
502 Ext.Array.each(value.split(','), function(p) {
503 if (!p || p.match(/^\s*$/)) {
504 return; // continue
505 }
506
507 var match_res;
508
509 if ((match_res = p.match(/^(order)?=(\d+)$/)) !== null) {
510 res.order = match_res[2];
511 } else if ((match_res = p.match(/^up=(\d+)$/)) !== null) {
512 res.up = match_res[1];
513 } else if ((match_res = p.match(/^down=(\d+)$/)) !== null) {
514 res.down = match_res[1];
515 } else {
516 errors = true;
517 return false; // break
518 }
519 });
520
521 if (errors) {
522 return;
523 }
524
525 return res;
526 },
527
528 printStartup: function(startup) {
529 var arr = [];
530 if (startup.order !== undefined && startup.order !== '') {
531 arr.push('order=' + startup.order);
532 }
533 if (startup.up !== undefined && startup.up !== '') {
534 arr.push('up=' + startup.up);
535 }
536 if (startup.down !== undefined && startup.down !== '') {
537 arr.push('down=' + startup.down);
538 }
539
540 return arr.join(',');
541 },
542
543 parseQemuSmbios1: function(value) {
150ad74a
CE
544 var res = value.split(',').reduce(function (accumulator, currentValue) {
545 var splitted = currentValue.split(new RegExp("=(.+)"));
546 accumulator[splitted[0]] = splitted[1];
547 return accumulator;
548 }, {});
549
550 if (PVE.Parser.parseBoolean(res.base64, false)) {
551 Ext.Object.each(res, function(key, value) {
552 if (key === 'uuid') { return; }
553 res[key] = Ext.util.Base64.decode(value);
554 });
555 }
fcb64fe4
DM
556
557 return res;
558 },
559
560 printQemuSmbios1: function(data) {
561
562 var datastr = '';
150ad74a 563 var base64 = false;
fcb64fe4 564 Ext.Object.each(data, function(key, value) {
84de645d 565 if (value === '') { return; }
150ad74a
CE
566 if (key === 'uuid') {
567 datastr += (datastr !== '' ? ',' : '') + key + '=' + value;
568 } else {
569 // values should be base64 encoded from now on, mark config strings correspondingly
570 if (!base64) {
571 base64 = true;
572 datastr += (datastr !== '' ? ',' : '') + 'base64=1';
573 }
574 datastr += (datastr !== '' ? ',' : '') + key + '=' + Ext.util.Base64.encode(value);
575 }
fcb64fe4
DM
576 });
577
578 return datastr;
579 },
580
581 parseTfaConfig: function(value) {
582 var res = {};
583
584 Ext.Array.each(value.split(','), function(p) {
ec0bd652 585 var kva = p.split('=', 2);
fcb64fe4
DM
586 res[kva[0]] = kva[1];
587 });
588
589 return res;
4c1c0d5d
EK
590 },
591
1cdb49c1 592 parseTfaType: function(value) {
f92943e2 593 /*jslint confusion: true*/
1cdb49c1
WB
594 var match;
595 if (!value || !value.length) {
596 return undefined;
597 } else if (value === 'x!oath') {
598 return 'totp';
f92943e2 599 } else if (!!(match = value.match(/^x!(.+)$/))) {
1cdb49c1
WB
600 return match[1];
601 } else {
602 return 1;
603 }
604 },
605
4c1c0d5d
EK
606 parseQemuCpu: function(value) {
607 if (!value) {
608 return {};
609 }
610
611 var res = {};
612
613 var errors = false;
614 Ext.Array.each(value.split(','), function(p) {
615 if (!p || p.match(/^\s*$/)) {
616 return; // continue
617 }
fcb64fe4 618
ec0bd652
DC
619 if (!p.match(/\=/)) {
620 if (Ext.isDefined(res.cpu)) {
4c1c0d5d
EK
621 errors = true;
622 return false; // break
623 }
624 res.cputype = p;
625 return; // continue
626 }
627
628 var match_res = p.match(/^([a-z_]+)=(\S+)$/);
629 if (!match_res) {
630 errors = true;
631 return false; // break
632 }
633
634 var k = match_res[1];
635 if (Ext.isDefined(res[k])) {
636 errors = true;
637 return false; // break
638 }
639
640 res[k] = match_res[2];
641 });
642
643 if (errors || !res.cputype) {
644 return;
645 }
646
647 return res;
648 },
649
650 printQemuCpu: function(cpu) {
651 var cpustr = cpu.cputype;
652 var optstr = '';
653
654 Ext.Object.each(cpu, function(key, value) {
655 if (!Ext.isDefined(value) || key === 'cputype') {
656 return; // continue
657 }
658 optstr += ',' + key + '=' + value;
659 });
660
661 if (!cpustr) {
84de645d 662 if (optstr) {
4c1c0d5d 663 return 'kvm64' + optstr;
84de645d 664 }
4c1c0d5d
EK
665 return;
666 }
667
668 return cpustr + optstr;
b1339314
WB
669 },
670
671 parseSSHKey: function(key) {
672 // |--- options can have quotes--| type key comment
673 var keyre = /^(?:((?:[^\s"]|\"(?:\\.|[^"\\])*")+)\s+)?(\S+)\s+(\S+)(?:\s+(.*))?$/;
674 var typere = /^(?:ssh-(?:dss|rsa|ed25519)|ecdsa-sha2-nistp\d+)$/;
675
676 var m = key.match(keyre);
677 if (!m) {
678 return null;
679 }
680 if (m.length < 3 || !m[2]) { // [2] is always either type or key
681 return null;
682 }
683 if (m[1] && m[1].match(typere)) {
684 return {
685 type: m[1],
686 key: m[2],
687 comment: m[3]
688 };
689 }
690 if (m[2].match(typere)) {
691 return {
692 options: m[1],
693 type: m[2],
694 key: m[3],
695 comment: m[4]
696 };
697 }
698 return null;
22f2f9d6 699 }
fcb64fe4 700}});