This app provides monitoring and information features for the common freifunk user and the technical stuff of a freifunk community.
Code base is taken from a TUM Practical Course project and added here to see if Freifunk Altdorf can use it.
https://www.freifunk-altdorf.de
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
200 lines
5.1 KiB
200 lines
5.1 KiB
|
|
/** |
|
* Module dependencies. |
|
*/ |
|
|
|
var deprecate = require('util-deprecate'); |
|
var DOMParser = require('xmldom').DOMParser; |
|
|
|
/** |
|
* Module exports. |
|
*/ |
|
|
|
exports.parse = parse; |
|
exports.parseString = deprecate(parseString, '`parseString()` is deprecated. ' + |
|
'It\'s not actually async. Use `parse()` instead.'); |
|
exports.parseStringSync = deprecate(parseStringSync, '`parseStringSync()` is ' + |
|
'deprecated. Use `parse()` instead.'); |
|
|
|
/** |
|
* 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 === 3 // text |
|
|| node.nodeType === 8 // comment |
|
|| node.nodeType === 4; // cdata |
|
} |
|
|
|
|
|
/** |
|
* 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); |
|
if (doc.documentElement.nodeName !== 'plist') { |
|
throw new Error('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; |
|
} |
|
|
|
/** |
|
* Parses a Plist XML string. Returns an Object. Takes a `callback` function. |
|
* |
|
* @param {String} xml - the XML String to decode |
|
* @param {Function} callback - callback function |
|
* @returns {Mixed} the decoded value from the Plist XML |
|
* @api public |
|
* @deprecated not actually async. use parse() instead |
|
*/ |
|
|
|
function parseString (xml, callback) { |
|
var doc, error, plist; |
|
try { |
|
doc = new DOMParser().parseFromString(xml); |
|
plist = parsePlistXML(doc.documentElement); |
|
} catch(e) { |
|
error = e; |
|
} |
|
callback(error, plist); |
|
} |
|
|
|
/** |
|
* Parses a Plist XML string. Returns an Object. |
|
* |
|
* @param {String} xml - the XML String to decode |
|
* @param {Function} callback - callback function |
|
* @returns {Mixed} the decoded value from the Plist XML |
|
* @api public |
|
* @deprecated use parse() instead |
|
*/ |
|
|
|
function parseStringSync (xml) { |
|
var doc = new DOMParser().parseFromString(xml); |
|
var plist; |
|
if (doc.documentElement.nodeName !== 'plist') { |
|
throw new Error('malformed document. First element should be <plist>'); |
|
} |
|
plist = parsePlistXML(doc.documentElement); |
|
|
|
// if the plist is an array with 1 element, pull it out of the array |
|
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, d; |
|
|
|
if (!node) |
|
return null; |
|
|
|
if (node.nodeName === 'plist') { |
|
new_arr = []; |
|
for (i=0; i < node.childNodes.length; i++) { |
|
// ignore comment nodes (text) |
|
if (!shouldIgnoreNode(node.childNodes[i])) { |
|
new_arr.push( parsePlistXML(node.childNodes[i])); |
|
} |
|
} |
|
return new_arr; |
|
|
|
} else if (node.nodeName === 'dict') { |
|
new_obj = {}; |
|
key = null; |
|
for (i=0; i < node.childNodes.length; i++) { |
|
// ignore comment nodes (text) |
|
if (!shouldIgnoreNode(node.childNodes[i])) { |
|
if (key === null) { |
|
key = parsePlistXML(node.childNodes[i]); |
|
} else { |
|
new_obj[key] = parsePlistXML(node.childNodes[i]); |
|
key = null; |
|
} |
|
} |
|
} |
|
return new_obj; |
|
|
|
} else if (node.nodeName === 'array') { |
|
new_arr = []; |
|
for (i=0; i < node.childNodes.length; i++) { |
|
// ignore comment nodes (text) |
|
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') { |
|
return node.childNodes[0].nodeValue; |
|
|
|
} else if (node.nodeName === 'string') { |
|
res = ''; |
|
for (d=0; d < node.childNodes.length; d++) { |
|
res += node.childNodes[d].nodeValue; |
|
} |
|
return res; |
|
|
|
} else if (node.nodeName === 'integer') { |
|
// parse as base 10 integer |
|
return parseInt(node.childNodes[0].nodeValue, 10); |
|
|
|
} else if (node.nodeName === 'real') { |
|
res = ''; |
|
for (d=0; d < node.childNodes.length; d++) { |
|
if (node.childNodes[d].nodeType === 3) { |
|
res += node.childNodes[d].nodeValue; |
|
} |
|
} |
|
return parseFloat(res); |
|
|
|
} else if (node.nodeName === 'data') { |
|
res = ''; |
|
for (d=0; d < node.childNodes.length; d++) { |
|
if (node.childNodes[d].nodeType === 3) { |
|
res += node.childNodes[d].nodeValue.replace(/\s+/g, ''); |
|
} |
|
} |
|
|
|
// decode base64 data to a Buffer instance |
|
return new Buffer(res, 'base64'); |
|
|
|
} else if (node.nodeName === 'date') { |
|
return new Date(node.childNodes[0].nodeValue); |
|
|
|
} else if (node.nodeName === 'true') { |
|
return true; |
|
|
|
} else if (node.nodeName === 'false') { |
|
return false; |
|
} |
|
}
|
|
|