]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/Parser.js
make jslint happier
[pve-manager.git] / www / manager6 / Parser.js
1 // Some configuration values are complex strings -
2 // so we need parsers/generators for them.
3
4 Ext.define('PVE.Parser', { statics: {
5
6 // this class only contains static functions
7
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
37 parseBoolean: function(value, default_value) {
38 if (!Ext.isDefined(value)) {
39 return default_value;
40 }
41 value = value.toLowerCase();
42 return value === '1' ||
43 value === 'on' ||
44 value === 'yes' ||
45 value === 'true';
46 },
47
48 parsePropertyString: function(value, defaultKey) {
49 var res = {},
50 error;
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])) {
58 error = 'defaultKey may be only defined once in propertyString';
59 return false; // break
60 }
61 res[defaultKey] = kv[0];
62 } else {
63 error = 'invalid propertyString, not a key=value pair and no defaultKey defined';
64 return false; // break
65 }
66 });
67
68 if (error !== undefined) {
69 console.error(error);
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) {
80 if (defaultKey !== undefined && key === defaultKey) {
81 stringparts.unshift(value);
82 } else {
83 stringparts.push(key + '=' + value);
84 }
85 });
86
87 return stringparts.join(',');
88 },
89
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) {
115 res.tag = match_res[1];
116 } else if ((match_res = p.match(/^firewall=(\d+)$/)) !== null) {
117 res.firewall = match_res[1];
118 } else if ((match_res = p.match(/^link_down=(\d+)$/)) !== null) {
119 res.disconnect = match_res[1];
120 } else if ((match_res = p.match(/^queues=(\d+)$/)) !== null) {
121 res.queues = match_res[1];
122 } else if ((match_res = p.match(/^trunks=(\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*)$/)) !== null) {
123 res.trunks = match_res[1];
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 }
161 if (net.trunks) {
162 netstr += ",trunks=" + net.trunks;
163 }
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
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
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 }
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*/
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'){
354 if(data.tag){
355 value = value + 'v' + data.tag;
356 }
357 if (data.firewall){
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 }
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) {
386 data.firewall = PVE.Parser.parseBoolean(match_res[1]);
387 } else {
388 // todo: simply ignore errors ?
389 return; // continue
390 }
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 });
405
406 /*jslint confusion: true*/
407 if (data.rate > 0) {
408 tmparray.push('rate=' + data.rate);
409 }
410 /*jslint confusion: false*/
411 return tmparray.join(',');
412 },
413
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 }
426 var match_res = p.match(/^([a-z_]+)=(.+)$/);
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
454 var m = res.file.match(/^([a-z][a-z0-9\-\_\.]*[a-z0-9]):/i);
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
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) {
531 var res = {};
532
533 Ext.Array.each(value.split(','), function(p) {
534 var kva = p.split('=', 2);
535 res[kva[0]] = kva[1];
536 });
537
538 return res;
539 },
540
541 printQemuSmbios1: function(data) {
542
543 var datastr = '';
544
545 Ext.Object.each(data, function(key, value) {
546 if (value === '') { return; }
547 datastr += (datastr !== '' ? ',' : '') + key + '=' + value;
548 });
549
550 return datastr;
551 },
552
553 parseTfaConfig: function(value) {
554 var res = {};
555
556 Ext.Array.each(value.split(','), function(p) {
557 var kva = p.split('=', 2);
558 res[kva[0]] = kva[1];
559 });
560
561 return res;
562 },
563
564 parseTfaType: function(value) {
565 /*jslint confusion: true*/
566 var match;
567 if (!value || !value.length) {
568 return undefined;
569 } else if (value === 'x!oath') {
570 return 'totp';
571 } else if (!!(match = value.match(/^x!(.+)$/))) {
572 return match[1];
573 } else {
574 return 1;
575 }
576 },
577
578 parseQemuCpu: function(value) {
579 if (!value) {
580 return {};
581 }
582
583 var res = {};
584
585 var errors = false;
586 Ext.Array.each(value.split(','), function(p) {
587 if (!p || p.match(/^\s*$/)) {
588 return; // continue
589 }
590
591 if (!p.match(/\=/)) {
592 if (Ext.isDefined(res.cpu)) {
593 errors = true;
594 return false; // break
595 }
596 res.cputype = p;
597 return; // continue
598 }
599
600 var match_res = p.match(/^([a-z_]+)=(\S+)$/);
601 if (!match_res) {
602 errors = true;
603 return false; // break
604 }
605
606 var k = match_res[1];
607 if (Ext.isDefined(res[k])) {
608 errors = true;
609 return false; // break
610 }
611
612 res[k] = match_res[2];
613 });
614
615 if (errors || !res.cputype) {
616 return;
617 }
618
619 return res;
620 },
621
622 printQemuCpu: function(cpu) {
623 var cpustr = cpu.cputype;
624 var optstr = '';
625
626 Ext.Object.each(cpu, function(key, value) {
627 if (!Ext.isDefined(value) || key === 'cputype') {
628 return; // continue
629 }
630 optstr += ',' + key + '=' + value;
631 });
632
633 if (!cpustr) {
634 if (optstr) {
635 return 'kvm64' + optstr;
636 }
637 return;
638 }
639
640 return cpustr + optstr;
641 },
642
643 parseSSHKey: function(key) {
644 // |--- options can have quotes--| type key comment
645 var keyre = /^(?:((?:[^\s"]|\"(?:\\.|[^"\\])*")+)\s+)?(\S+)\s+(\S+)(?:\s+(.*))?$/;
646 var typere = /^(?:ssh-(?:dss|rsa|ed25519)|ecdsa-sha2-nistp\d+)$/;
647
648 var m = key.match(keyre);
649 if (!m) {
650 return null;
651 }
652 if (m.length < 3 || !m[2]) { // [2] is always either type or key
653 return null;
654 }
655 if (m[1] && m[1].match(typere)) {
656 return {
657 type: m[1],
658 key: m[2],
659 comment: m[3]
660 };
661 }
662 if (m[2].match(typere)) {
663 return {
664 options: m[1],
665 type: m[2],
666 key: m[3],
667 comment: m[4]
668 };
669 }
670 return null;
671 }
672 }});