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