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