| 1 | /* |
| 2 | Copyright 2018-2021 Intel Corporation |
| 3 | |
| 4 | Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | you may not use this file except in compliance with the License. |
| 6 | You may obtain a copy of the License at |
| 7 | |
| 8 | http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | |
| 10 | Unless required by applicable law or agreed to in writing, software |
| 11 | distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | See the License for the specific language governing permissions and |
| 14 | limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | try { Object.defineProperty(Array.prototype, "peek", { value: function () { return (this.length > 0 ? this[this.length - 1] : undefined); } }); } catch (e) { } |
| 18 | |
| 19 | |
| 20 | // Parse XML and return JSON |
| 21 | module.exports.ParseWsman = function (xml) { |
| 22 | try { |
| 23 | if (!xml.childNodes) xml = _turnToXml(xml); |
| 24 | var r = { Header: {} }, header = xml.getElementsByTagName("Header")[0], t; |
| 25 | if (!header) header = xml.getElementsByTagName("a:Header")[0]; |
| 26 | if (!header) return null; |
| 27 | for (var i = 0; i < header.childNodes.length; i++) { |
| 28 | var child = header.childNodes[i]; |
| 29 | r.Header[child.localName] = child.textContent; |
| 30 | } |
| 31 | var body = xml.getElementsByTagName("Body")[0]; |
| 32 | if (!body) body = xml.getElementsByTagName("a:Body")[0]; |
| 33 | if (!body) return null; |
| 34 | if (body.childNodes.length > 0) { |
| 35 | t = body.childNodes[0].localName; |
| 36 | var x = t.indexOf('_OUTPUT'); |
| 37 | if ((x != -1) && (x == (t.length - 7))) { t = t.substring(0, t.length - 7); } |
| 38 | r.Header['Method'] = t; |
| 39 | r.Body = _ParseWsmanRec(body.childNodes[0]); |
| 40 | } |
| 41 | return r; |
| 42 | } catch (e) { |
| 43 | console.error("Unable to parse XML: " + xml, e); |
| 44 | return null; |
| 45 | } |
| 46 | } |
| 47 | |
| 48 | // Private method |
| 49 | function _ParseWsmanRec(node) { |
| 50 | var data, r = {}; |
| 51 | for (var i = 0; i < node.childNodes.length; i++) { |
| 52 | var child = node.childNodes[i]; |
| 53 | if ((child.childElementCount == null) || (child.childElementCount == 0)) { data = child.textContent; } else { data = _ParseWsmanRec(child); } |
| 54 | if (data == 'true') data = true; // Convert 'true' into true |
| 55 | if (data == 'false') data = false; // Convert 'false' into false |
| 56 | if ((parseInt(data) + '') === data) data = parseInt(data); // Convert integers |
| 57 | |
| 58 | var childObj = data; |
| 59 | if ((child.attributes != null) && (child.attributes.length > 0)) { |
| 60 | childObj = { 'Value': data }; |
| 61 | for (var j = 0; j < child.attributes.length; j++) { |
| 62 | childObj['@' + child.attributes[j].name] = child.attributes[j].value; |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | if (r[child.localName] instanceof Array) { r[child.localName].push(childObj); } |
| 67 | else if (r[child.localName] == null) { r[child.localName] = childObj; } |
| 68 | else { r[child.localName] = [r[child.localName], childObj]; } |
| 69 | } |
| 70 | return r; |
| 71 | } |
| 72 | |
| 73 | function _PutObjToBodyXml(resuri, putObj) { |
| 74 | if (!resuri || putObj == null) return ''; |
| 75 | var objname = obj.GetNameFromUrl(resuri); |
| 76 | var result = '<r:' + objname + ' xmlns:r="' + resuri + '">'; |
| 77 | |
| 78 | for (var prop in putObj) { |
| 79 | if (!putObj.hasOwnProperty(prop) || prop.indexOf('__') === 0 || prop.indexOf('@') === 0) continue; |
| 80 | if (putObj[prop] == null || typeof putObj[prop] === 'function') continue; |
| 81 | if (typeof putObj[prop] === 'object' && putObj[prop]['ReferenceParameters']) { |
| 82 | result += '<r:' + prop + '><a:Address>' + putObj[prop].Address + '</a:Address><a:ReferenceParameters><w:ResourceURI>' + putObj[prop]['ReferenceParameters']["ResourceURI"] + '</w:ResourceURI><w:SelectorSet>'; |
| 83 | var selectorArray = putObj[prop]['ReferenceParameters']['SelectorSet']['Selector']; |
| 84 | if (Array.isArray(selectorArray)) { |
| 85 | for (var i = 0; i < selectorArray.length; i++) { |
| 86 | result += '<w:Selector' + _ObjectToXmlAttributes(selectorArray[i]) + '>' + selectorArray[i]['Value'] + '</w:Selector>'; |
| 87 | } |
| 88 | } |
| 89 | else { |
| 90 | result += '<w:Selector' + _ObjectToXmlAttributes(selectorArray) + '>' + selectorArray['Value'] + '</w:Selector>'; |
| 91 | } |
| 92 | result += '</w:SelectorSet></a:ReferenceParameters></r:' + prop + '>'; |
| 93 | } |
| 94 | else { |
| 95 | if (Array.isArray(putObj[prop])) { |
| 96 | for (var i = 0; i < putObj[prop].length; i++) { |
| 97 | result += '<r:' + prop + '>' + putObj[prop][i].toString() + '</r:' + prop + '>'; |
| 98 | } |
| 99 | } else { |
| 100 | result += '<r:' + prop + '>' + putObj[prop].toString() + '</r:' + prop + '>'; |
| 101 | } |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | result += '</r:' + objname + '>'; |
| 106 | return result; |
| 107 | } |
| 108 | |
| 109 | // This is a drop-in replacement to _turnToXml() that works without xml parser dependency. |
| 110 | function _treeBuilder() { |
| 111 | this.tree = []; |
| 112 | this.push = function (element) { this.tree.push(element); }; |
| 113 | this.pop = function () { var element = this.tree.pop(); if (this.tree.length > 0) { var x = this.tree.peek(); x.childNodes.push(element); x.childElementCount = x.childNodes.length; } return (element); }; |
| 114 | this.peek = function () { return (this.tree.peek()); } |
| 115 | this.addNamespace = function (prefix, namespace) { this.tree.peek().nsTable[prefix] = namespace; if (this.tree.peek().attributes.length > 0) { for (var i = 0; i < this.tree.peek().attributes; ++i) { var a = this.tree.peek().attributes[i]; if (prefix == '*' && a.name == a.localName) { a.namespace = namespace; } else if (prefix != '*' && a.name != a.localName) { var pfx = a.name.split(':')[0]; if (pfx == prefix) { a.namespace = namespace; } } } } } |
| 116 | this.getNamespace = function (prefix) { for (var i = this.tree.length - 1; i >= 0; --i) { if (this.tree[i].nsTable[prefix] != null) { return (this.tree[i].nsTable[prefix]); } } return null; } |
| 117 | } |
| 118 | function _turnToXml(text) { if (text == null) return null; return ({ childNodes: [_turnToXmlRec(text)], getElementsByTagName: _getElementsByTagName, getChildElementsByTagName: _getChildElementsByTagName, getElementsByTagNameNS: _getElementsByTagNameNS }); } |
| 119 | function _getElementsByTagNameNS(ns, name) { var ret = []; _xmlTraverseAllRec(this.childNodes, function (node) { if (node.localName == name && (node.namespace == ns || ns == '*')) { ret.push(node); } }); return ret; } |
| 120 | function _getElementsByTagName(name) { var ret = []; _xmlTraverseAllRec(this.childNodes, function (node) { if (node.localName == name) { ret.push(node); } }); return ret; } |
| 121 | function _getChildElementsByTagName(name) { var ret = []; if (this.childNodes != null) { for (var node in this.childNodes) { if (this.childNodes[node].localName == name) { ret.push(this.childNodes[node]); } } } return (ret); } |
| 122 | function _getChildElementsByTagNameNS(ns, name) { var ret = []; if (this.childNodes != null) { for (var node in this.childNodes) { if (this.childNodes[node].localName == name && (ns == '*' || this.childNodes[node].namespace == ns)) { ret.push(this.childNodes[node]); } } } return (ret); } |
| 123 | function _xmlTraverseAllRec(nodes, func) { for (var i in nodes) { func(nodes[i]); if (nodes[i].childNodes) { _xmlTraverseAllRec(nodes[i].childNodes, func); } } } |
| 124 | function _turnToXmlRec(text) { |
| 125 | try { |
| 126 | if (text == null) return null; |
| 127 | var elementStack = new _treeBuilder(), lastElement = null, x1 = text.split('<'), ret = [], element = null, currentElementName = null; |
| 128 | for (var i in x1) { |
| 129 | var x2 = x1[i].split('>'), x3 = x2[0].split(' '), elementName = x3[0]; |
| 130 | if ((elementName.length > 0) && (elementName[0] != '?')) { |
| 131 | if (elementName[0] != '/') { |
| 132 | var attributes = [], localName, localname2 = elementName.split(' ')[0].split(':'), localName = (localname2.length > 1) ? localname2[1] : localname2[0]; |
| 133 | Object.defineProperty(attributes, "get", |
| 134 | { |
| 135 | value: function () { |
| 136 | if (arguments.length == 1) { |
| 137 | for (var a in this) { if (this[a].name == arguments[0]) { return (this[a]); } } |
| 138 | } |
| 139 | else if (arguments.length == 2) { |
| 140 | for (var a in this) { if (this[a].name == arguments[1] && (arguments[0] == '*' || this[a].namespace == arguments[0])) { return (this[a]); } } |
| 141 | } |
| 142 | else { |
| 143 | throw ('attributes.get(): Invalid number of parameters'); |
| 144 | } |
| 145 | } |
| 146 | }); |
| 147 | elementStack.push({ name: elementName, localName: localName, getChildElementsByTagName: _getChildElementsByTagName, getElementsByTagNameNS: _getElementsByTagNameNS, getChildElementsByTagNameNS: _getChildElementsByTagNameNS, attributes: attributes, childNodes: [], nsTable: {} }); |
| 148 | // Parse Attributes |
| 149 | if (x3.length > 0) { |
| 150 | var skip = false; |
| 151 | for (var j in x3) { |
| 152 | if (x3[j] == '/') { |
| 153 | // This is an empty Element |
| 154 | elementStack.peek().namespace = elementStack.peek().name == elementStack.peek().localName ? elementStack.getNamespace('*') : elementStack.getNamespace(elementStack.peek().name.substring(0, elementStack.peek().name.indexOf(':'))); |
| 155 | elementStack.peek().textContent = ''; |
| 156 | lastElement = elementStack.pop(); |
| 157 | skip = true; |
| 158 | break; |
| 159 | } |
| 160 | var k = x3[j].indexOf('='); |
| 161 | if (k > 0) { |
| 162 | var attrName = x3[j].substring(0, k); |
| 163 | var attrValue = x3[j].substring(k + 2, x3[j].length - 1); |
| 164 | var attrNS = elementStack.getNamespace('*'); |
| 165 | |
| 166 | if (attrName == 'xmlns') { |
| 167 | elementStack.addNamespace('*', attrValue); |
| 168 | attrNS = attrValue; |
| 169 | } else if (attrName.startsWith('xmlns:')) { |
| 170 | elementStack.addNamespace(attrName.substring(6), attrValue); |
| 171 | } else { |
| 172 | var ax = attrName.split(':'); |
| 173 | if (ax.length == 2) { attrName = ax[1]; attrNS = elementStack.getNamespace(ax[0]); } |
| 174 | } |
| 175 | var x = { name: attrName, value: attrValue } |
| 176 | if (attrNS != null) x.namespace = attrNS; |
| 177 | elementStack.peek().attributes.push(x); |
| 178 | } |
| 179 | } |
| 180 | if (skip) { continue; } |
| 181 | } |
| 182 | elementStack.peek().namespace = elementStack.peek().name == elementStack.peek().localName ? elementStack.getNamespace('*') : elementStack.getNamespace(elementStack.peek().name.substring(0, elementStack.peek().name.indexOf(':'))); |
| 183 | if (x2[1]) { elementStack.peek().textContent = x2[1]; } |
| 184 | } else { lastElement = elementStack.pop(); } |
| 185 | } |
| 186 | } |
| 187 | } catch (ex) { return null; } |
| 188 | return lastElement; |
| 189 | } |