Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | 694x 1579802x 1579655x 147x 139x 139x 139x 139x 8x 6x 6x 6x 6x 2x 2x 692x 694x 2x 692x 692x 692x 690x | import { DOMParser, type Document as XmlDocument } from '@xmldom/xmldom';
function hasDoctypeDeclaration(xml: string): boolean {
for (let index = 0; index < xml.length; index += 1) {
if (xml[index] !== '<' || index + 2 >= xml.length || xml[index + 1] !== '!') {
continue;
}
if (xml.startsWith('<!--', index)) {
const commentEnd = xml.indexOf('-->', index + 4);
Iif (commentEnd === -1) {
return false;
}
index = commentEnd + 2;
continue;
}
if (xml.startsWith('<![CDATA[', index)) {
const cdataEnd = xml.indexOf(']]>', index + 9);
Iif (cdataEnd === -1) {
return false;
}
index = cdataEnd + 2;
continue;
}
Eif (xml.slice(index + 2, index + 9).toUpperCase() === 'DOCTYPE') {
return true;
}
}
return false;
}
/**
* Safely parses an XML string, rejecting DOCTYPE declarations to prevent
* entity expansion attacks (e.g. "billion laughs").
*/
export function parseXmlDocument(xml: string): XmlDocument {
if (hasDoctypeDeclaration(xml)) {
throw new Error('DOCTYPE declarations are not supported in BPMN files.');
}
const document = new DOMParser().parseFromString(xml, 'application/xml');
const parserErrors = document.getElementsByTagName('parsererror');
Iif (parserErrors.length > 0) {
throw new Error(parserErrors[0]?.textContent || 'Invalid XML document.');
}
return document;
}
|