UNPKG

@vlad8096/stanza

Version:

Modern XMPP in the browser, with a JSON API

529 lines (528 loc) 20.2 kB
"use strict"; /** * This file is derived from prior work. * * See NOTICE.md for full license text. * * Derived from: ltx, Copyright © 2010 Stephan Maka */ Object.defineProperty(exports, "__esModule", { value: true }); exports.parse = void 0; const tslib_1 = require("tslib"); // tslint:disable cognitive-complexity max-switch-cases const events_1 = require("events"); const Definitions_1 = require("./Definitions"); const Element_1 = tslib_1.__importDefault(require("./Element")); const Error_1 = tslib_1.__importDefault(require("./Error")); function isBasicNameStart(c) { return ((97 /* a */ <= c && c <= 122 /* z */) || (65 /* A */ <= c && c <= 90 /* Z */) || c === 58 /* Colon */ || c === 95 /* Underscore */); } function isExtendedNameStart(c) { return ((0xc0 <= c && c <= 0xd6) || (0xd8 <= c && c <= 0xf6) || (0xf8 <= c && c <= 0x2ff) || (0x370 <= c && c <= 0x37d) || (0x37f <= c && c <= 0x1fff) || (0x200c <= c && c <= 0x200d) || (0x2070 <= c && c <= 0x218f) || (0x2c00 <= c && c <= 0x2fef) || (0x3001 <= c && c <= 0xd7ff) || (0xfdf0 <= c && c <= 0xfffd) || (0x10000 <= c && c <= 0xeffff)); } function isNameStart(c) { return isBasicNameStart(c) || isExtendedNameStart(c); } function isName(c) { return (isBasicNameStart(c) || c === 45 /* Dash */ || c === 46 /* Period */ || (48 /* Zero */ <= c && c <= 57 /* Nine */) || c === 0xb7 || (0x0300 <= c && c <= 0x036f) || (0x203f <= c && c <= 0x2040) || isExtendedNameStart(c)); } function isWhitespace(c) { return (c === 32 /* Space */ || c === 10 /* NewLine */ || c === 13 /* CarriageReturn */ || c === 9 /* Tab */); } class Parser extends events_1.EventEmitter { constructor(opts = {}) { super(); this.allowComments = true; this.attributes = {}; this.state = 34 /* TEXT */; this.tagName = ''; this.haveDeclaration = false; this.recordBuffer = []; if (opts.allowComments !== undefined) { this.allowComments = opts.allowComments; } } write(data) { for (const char of data) { const c = char.codePointAt(0); switch (this.state) { case 34 /* TEXT */: { if (c === 60 /* LessThan */) { let text; try { text = Definitions_1.unescapeXML(this.endRecord()); } catch (err) { this.emit('error', err); return; } if (text) { this.emit('text', text); } this.transition(31 /* TAG_START */); continue; } else { this.record(char); continue; } } case 31 /* TAG_START */: { if (c === 47 /* Slash */) { this.transition(7 /* CLOSING_TAG_START */); continue; } if (c === 33 /* Exclamation */) { this.transition(24 /* START_INSTRUCTION */); continue; } if (c === 63 /* Question */) { if (this.haveDeclaration) { this.restrictedXML(); } this.transition(25 /* START_PROCESSING_INSTRUCTION */); continue; } if (isNameStart(c)) { this.transition(30 /* TAG_NAME */); this.startRecord(char); continue; } return this.notWellFormed(); } case 30 /* TAG_NAME */: { if (isName(c)) { this.record(char); continue; } if (isWhitespace(c)) { this.startTag(); this.transition(32 /* TAG_WAIT_NAME */); continue; } if (c === 47 /* Slash */) { this.startTag(); this.transition(29 /* TAG_END_SLASH */); continue; } if (c === 62 /* GreaterThan */) { this.startTag(); this.transition(34 /* TEXT */); this.emit('startElement', this.tagName, this.attributes); continue; } return this.notWellFormed(); } case 29 /* TAG_END_SLASH */: { if (c === 62 /* GreaterThan */) { this.emit('startElement', this.tagName, this.attributes); this.emit('endElement', this.tagName); this.transition(34 /* TEXT */); continue; } return this.notWellFormed(); } case 33 /* TAG */: { if (isWhitespace(c)) { this.transition(32 /* TAG_WAIT_NAME */); continue; } if (c === 47 /* Slash */) { this.transition(29 /* TAG_END_SLASH */); continue; } if (c === 62 /* GreaterThan */) { this.emit('startElement', this.tagName, this.attributes); this.transition(34 /* TEXT */); continue; } return this.notWellFormed(); } case 32 /* TAG_WAIT_NAME */: { if (isWhitespace(c)) { continue; } if (isNameStart(c)) { this.startRecord(char); this.transition(0 /* ATTR_NAME */); continue; } if (c === 47 /* Slash */) { this.transition(29 /* TAG_END_SLASH */); continue; } if (c === 62 /* GreaterThan */) { this.emit('startElement', this.tagName, this.attributes); this.transition(34 /* TEXT */); continue; } return this.notWellFormed(); } case 7 /* CLOSING_TAG_START */: { if (isNameStart(c)) { this.startRecord(char); this.transition(6 /* CLOSING_TAG_NAME */); continue; } return this.notWellFormed(); } case 6 /* CLOSING_TAG_NAME */: { if (isName(c)) { this.record(char); continue; } if (isWhitespace(c)) { this.transition(8 /* CLOSING_TAG */); continue; } if (c === 62 /* GreaterThan */) { const tag = this.endRecord(); this.emit('endElement', tag, this.attributes); this.transition(34 /* TEXT */); continue; } return this.notWellFormed(); } case 8 /* CLOSING_TAG */: { if (isWhitespace(c)) { continue; } if (c === 62 /* GreaterThan */) { const tag = this.endRecord(); this.emit('endElement', tag, this.attributes); this.transition(34 /* TEXT */); continue; } return this.notWellFormed(); } case 0 /* ATTR_NAME */: { if (isName(c)) { this.record(char); continue; } if (c === 61 /* Equal */) { this.addAttribute(); this.transition(4 /* ATTR_WAIT_QUOTE */); continue; } if (isWhitespace(c)) { this.addAttribute(); this.transition(3 /* ATTR_WAIT_EQ */); continue; } return this.notWellFormed(); } case 3 /* ATTR_WAIT_EQ */: { if (c === 61 /* Equal */) { this.transition(4 /* ATTR_WAIT_QUOTE */); continue; } if (isWhitespace(c)) { continue; } return this.notWellFormed(); } case 4 /* ATTR_WAIT_QUOTE */: { if (c === 34 /* DoubleQuote */) { this.startRecord(); this.transition(1 /* ATTR_QUOTE_DOUBLE */); continue; } if (c === 39 /* SingleQuote */) { this.startRecord(); this.transition(2 /* ATTR_QUOTE_SINGLE */); continue; } if (isWhitespace(c)) { continue; } return this.notWellFormed(); } case 1 /* ATTR_QUOTE_DOUBLE */: case 2 /* ATTR_QUOTE_SINGLE */: { if ((c === 34 /* DoubleQuote */ && this.state === 1 /* ATTR_QUOTE_DOUBLE */) || (c === 39 /* SingleQuote */ && this.state === 2 /* ATTR_QUOTE_SINGLE */)) { const value = this.endRecord(); this.attributes[this.attributeName] = Definitions_1.unescapeXML(value); this.transition(33 /* TAG */); continue; } if (c === 60 /* LessThan */) { return this.notWellFormed(); } this.record(char); continue; } case 24 /* START_INSTRUCTION */: { if (c === 45 /* Dash */) { if (!this.allowComments) { this.restrictedXML(); } this.transition(23 /* START_COMMENT_DASH */); continue; } if (c === 91 /* LeftBracket */) { this.transition(21 /* START_CDATA_LB */); continue; } return this.notWellFormed(); } case 23 /* START_COMMENT_DASH */: { if (c === 45 /* Dash */) { this.transition(14 /* IGNORE_COMMENT */); continue; } return this.notWellFormed(); } case 14 /* IGNORE_COMMENT */: { if (c === 45 /* Dash */) { this.transition(12 /* END_COMMENT_DASH */); } continue; } case 12 /* END_COMMENT_DASH */: { if (c === 45 /* Dash */) { this.transition(11 /* END_COMMENT_DASH_DASH */); } else { this.transition(14 /* IGNORE_COMMENT */); } continue; } case 11 /* END_COMMENT_DASH_DASH */: { if (c === 62 /* GreaterThan */) { this.transition(34 /* TEXT */); } else { this.transition(14 /* IGNORE_COMMENT */); } continue; } case 25 /* START_PROCESSING_INSTRUCTION */: { if (c === 88 /* X */ || c === 120 /* x */) { this.transition(28 /* START_XML_DECLARATION_X */); continue; } return this.notWellFormed(); } case 28 /* START_XML_DECLARATION_X */: { if (c === 77 /* M */ || c === 109 /* m */) { this.transition(27 /* START_XML_DECLARATION_X_M */); continue; } return this.notWellFormed(); } case 27 /* START_XML_DECLARATION_X_M */: { if (c === 76 /* L */ || c === 108 /* l */) { this.transition(26 /* START_XML_DECLARATION_X_M_L */); continue; } return this.notWellFormed(); } case 26 /* START_XML_DECLARATION_X_M_L */: { if (isWhitespace(c)) { this.haveDeclaration = true; this.transition(15 /* IGNORE_INSTRUCTION */); continue; } return this.notWellFormed(); } case 13 /* END_XML_DECLARATION_QM */: { if (c === 62 /* GreaterThan */) { this.transition(34 /* TEXT */); continue; } return this.notWellFormed(); } case 15 /* IGNORE_INSTRUCTION */: { if (c === 63 /* Question */) { this.transition(13 /* END_XML_DECLARATION_QM */); } continue; } case 21 /* START_CDATA_LB */: { this.wait(c, 67 /* C */, 20 /* START_CDATA_LB_C */); continue; } case 20 /* START_CDATA_LB_C */: { this.wait(c, 68 /* D */, 19 /* START_CDATA_LB_C_D */); continue; } case 19 /* START_CDATA_LB_C_D */: { this.wait(c, 65 /* A */, 18 /* START_CDATA_LB_C_D_A */); continue; } case 18 /* START_CDATA_LB_C_D_A */: { this.wait(c, 84 /* T */, 17 /* START_CDATA_LB_C_D_A_T */); continue; } case 17 /* START_CDATA_LB_C_D_A_T */: { this.wait(c, 65 /* A */, 16 /* START_CDATA_LB_C_D_A_T_A */); continue; } case 16 /* START_CDATA_LB_C_D_A_T_A */: { this.wait(c, 91 /* LeftBracket */, 5 /* CDATA */); continue; } case 5 /* CDATA */: { if (c === 93 /* RightBracket */) { this.transition(10 /* END_CDATA_RB */); continue; } this.record(char); continue; } case 10 /* END_CDATA_RB */: { if (c === 93 /* RightBracket */) { this.transition(9 /* END_CDATA_RB_RB */); } else { this.record(String.fromCodePoint(93 /* RightBracket */)); this.record(char); this.transition(5 /* CDATA */); } continue; } case 9 /* END_CDATA_RB_RB */: { if (c === 62 /* GreaterThan */) { const text = this.endRecord(); if (text) { this.emit('text', text); } this.transition(34 /* TEXT */); } else { this.record(String.fromCodePoint(93 /* RightBracket */)); this.record(String.fromCodePoint(93 /* RightBracket */)); this.record(char); this.transition(5 /* CDATA */); } continue; } } } } end(data) { if (data) { this.write(data); } this.write = () => undefined; } record(char) { this.recordBuffer.push(char); } startRecord(char) { this.recordBuffer = []; if (char) { this.recordBuffer.push(char); } } endRecord() { const data = this.recordBuffer; this.recordBuffer = []; return data.join(''); } startTag() { this.tagName = this.endRecord(); this.attributes = {}; } addAttribute() { const name = this.endRecord(); if (this.attributes[name] !== undefined) { return this.notWellFormed(); } this.attributeName = name; this.attributes[name] = ''; } wait(c, nextChar, newState) { if (c === nextChar) { this.transition(newState); return; } return this.notWellFormed(); } transition(state) { this.state = state; if (state === 34 /* TEXT */) { this.startRecord(); } } notWellFormed(msg) { this.emit('error', Error_1.default.notWellFormed(msg)); } restrictedXML(msg) { this.emit('error', Error_1.default.restrictedXML(msg)); } } function parse(data, opts = {}) { const p = new Parser(opts); let result; let element; let error = null; p.on('text', (text) => { if (element) { element.children.push(text); } }); p.on('startElement', (name, attrs) => { const child = new Element_1.default(name, attrs); if (!result) { result = child; } if (!element) { element = child; } else { element = element.appendChild(child); } }); p.on('endElement', (name) => { if (!element) { p.emit('error', Error_1.default.notWellFormed('a')); } else if (name === element.name) { if (element.parent) { element = element.parent; } } else { p.emit('error', Error_1.default.notWellFormed('b')); } }); p.on('error', (e) => { error = e; }); p.write(data); p.end(); if (error) { throw error; } else { return result; } } exports.parse = parse; exports.default = Parser;