diff options
author | RaindropsSys <raindrops@equestria.dev> | 2024-05-12 17:18:54 +0200 |
---|---|---|
committer | RaindropsSys <raindrops@equestria.dev> | 2024-05-12 17:18:54 +0200 |
commit | fcdb5ca193406ef02dba8db4d7684d8c74089552 (patch) | |
tree | 223edcc76b54d18575d2c3bcd87ed321f8a896d6 /generator/node_modules/plist/lib/parse.js | |
parent | d9337f848b94f33aa8641acced33c6c2e5efc26e (diff) | |
download | atomic-fcdb5ca193406ef02dba8db4d7684d8c74089552.tar.gz atomic-fcdb5ca193406ef02dba8db4d7684d8c74089552.tar.bz2 atomic-fcdb5ca193406ef02dba8db4d7684d8c74089552.zip |
Updated 9 files and added 103 files (automated)
Diffstat (limited to 'generator/node_modules/plist/lib/parse.js')
-rw-r--r-- | generator/node_modules/plist/lib/parse.js | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/generator/node_modules/plist/lib/parse.js b/generator/node_modules/plist/lib/parse.js new file mode 100644 index 0000000..b5e7496 --- /dev/null +++ b/generator/node_modules/plist/lib/parse.js @@ -0,0 +1,227 @@ +/** + * Module dependencies. + */ + +const { DOMParser } = require('@xmldom/xmldom'); + +/** + * Module exports. + */ + +exports.parse = parse; + +var TEXT_NODE = 3; +var CDATA_NODE = 4; +var COMMENT_NODE = 8; + + +/** + * We ignore raw text (usually whitespace), <!-- xml comments -->, + * and raw CDATA nodes. + * + * @param {Element} node + * @returns {Boolean} + * @api private + */ + +function shouldIgnoreNode (node) { + return node.nodeType === TEXT_NODE + || node.nodeType === COMMENT_NODE + || node.nodeType === CDATA_NODE; +} + +/** + * Check if the node is empty. Some plist file has such node: + * <key /> + * this node shoud be ignored. + * + * @see https://github.com/TooTallNate/plist.js/issues/66 + * @param {Element} node + * @returns {Boolean} + * @api private + */ +function isEmptyNode(node){ + if(!node.childNodes || node.childNodes.length === 0) { + return true; + } else { + return false; + } +} + +function invariant(test, message) { + if (!test) { + throw new Error(message); + } +} + +/** + * Parses a Plist XML string. Returns an Object. + * + * @param {String} xml - the XML String to decode + * @returns {Mixed} the decoded value from the Plist XML + * @api public + */ + +function parse (xml) { + var doc = new DOMParser().parseFromString(xml); + invariant( + doc.documentElement.nodeName === 'plist', + 'malformed document. First element should be <plist>' + ); + var plist = parsePlistXML(doc.documentElement); + + // the root <plist> node gets interpreted as an Array, + // so pull out the inner data first + if (plist.length == 1) plist = plist[0]; + + return plist; +} + +/** + * Convert an XML based plist document into a JSON representation. + * + * @param {Object} xml_node - current XML node in the plist + * @returns {Mixed} built up JSON object + * @api private + */ + +function parsePlistXML (node) { + var i, new_obj, key, val, new_arr, res, counter, type; + + if (!node) + return null; + + if (node.nodeName === 'plist') { + new_arr = []; + if (isEmptyNode(node)) { + return new_arr; + } + for (i=0; i < node.childNodes.length; i++) { + if (!shouldIgnoreNode(node.childNodes[i])) { + new_arr.push( parsePlistXML(node.childNodes[i])); + } + } + return new_arr; + } else if (node.nodeName === 'dict') { + new_obj = {}; + key = null; + counter = 0; + if (isEmptyNode(node)) { + return new_obj; + } + for (i=0; i < node.childNodes.length; i++) { + if (shouldIgnoreNode(node.childNodes[i])) continue; + if (counter % 2 === 0) { + invariant( + node.childNodes[i].nodeName === 'key', + 'Missing key while parsing <dict/>.' + ); + key = parsePlistXML(node.childNodes[i]); + } else { + invariant( + node.childNodes[i].nodeName !== 'key', + 'Unexpected key "' + + parsePlistXML(node.childNodes[i]) + + '" while parsing <dict/>.' + ); + new_obj[key] = parsePlistXML(node.childNodes[i]); + } + counter += 1; + } + if (counter % 2 === 1) { + new_obj[key] = ''; + } + + return new_obj; + + } else if (node.nodeName === 'array') { + new_arr = []; + if (isEmptyNode(node)) { + return new_arr; + } + for (i=0; i < node.childNodes.length; i++) { + if (!shouldIgnoreNode(node.childNodes[i])) { + res = parsePlistXML(node.childNodes[i]); + if (null != res) new_arr.push(res); + } + } + return new_arr; + + } else if (node.nodeName === '#text') { + // TODO: what should we do with text types? (CDATA sections) + + } else if (node.nodeName === 'key') { + if (isEmptyNode(node)) { + return ''; + } + + invariant( + node.childNodes[0].nodeValue !== '__proto__', + '__proto__ keys can lead to prototype pollution. More details on CVE-2022-22912' + ); + + return node.childNodes[0].nodeValue; + } else if (node.nodeName === 'string') { + res = ''; + if (isEmptyNode(node)) { + return res; + } + for (i=0; i < node.childNodes.length; i++) { + var type = node.childNodes[i].nodeType; + if (type === TEXT_NODE || type === CDATA_NODE) { + res += node.childNodes[i].nodeValue; + } + } + return res; + + } else if (node.nodeName === 'integer') { + invariant( + !isEmptyNode(node), + 'Cannot parse "" as integer.' + ); + return parseInt(node.childNodes[0].nodeValue, 10); + + } else if (node.nodeName === 'real') { + invariant( + !isEmptyNode(node), + 'Cannot parse "" as real.' + ); + res = ''; + for (i=0; i < node.childNodes.length; i++) { + if (node.childNodes[i].nodeType === TEXT_NODE) { + res += node.childNodes[i].nodeValue; + } + } + return parseFloat(res); + + } else if (node.nodeName === 'data') { + res = ''; + if (isEmptyNode(node)) { + return Buffer.from(res, 'base64'); + } + for (i=0; i < node.childNodes.length; i++) { + if (node.childNodes[i].nodeType === TEXT_NODE) { + res += node.childNodes[i].nodeValue.replace(/\s+/g, ''); + } + } + return Buffer.from(res, 'base64'); + + } else if (node.nodeName === 'date') { + invariant( + !isEmptyNode(node), + 'Cannot parse "" as Date.' + ) + return new Date(node.childNodes[0].nodeValue); + + } else if (node.nodeName === 'null') { + return null; + + } else if (node.nodeName === 'true') { + return true; + + } else if (node.nodeName === 'false') { + return false; + } else { + throw new Error('Invalid PLIST tag ' + node.nodeName); + } +} |