UNPKG

dynatrace-cordova-outsystems-plugin

Version:

This plugin gives you the ability to use the Dynatrace instrumentation in your hybrid application (Cordova, Ionic, ..). It uses the Mobile Agent, the JavaScript Agent and the Javascript Bridge. The Mobile Agent will give you all device specific values con

303 lines (267 loc) 7.53 kB
"use strict"; const whatwgEncoding = require("whatwg-encoding"); // https://html.spec.whatwg.org/#encoding-sniffing-algorithm module.exports = function sniffHTMLEncoding(buffer, options) { let encoding = whatwgEncoding.getBOMEncoding(buffer); // see https://github.com/whatwg/html/issues/1910 if (options === undefined) { options = {}; } if (encoding === null && options.transportLayerEncodingLabel !== undefined) { encoding = whatwgEncoding.labelToName(options.transportLayerEncodingLabel); } if (encoding === null) { encoding = prescanMetaCharset(buffer); } if (encoding === null && options.defaultEncoding !== undefined) { encoding = options.defaultEncoding; } if (encoding === null) { encoding = "windows-1252"; } return encoding; }; // https://html.spec.whatwg.org/multipage/syntax.html#prescan-a-byte-stream-to-determine-its-encoding function prescanMetaCharset(buffer) { const l = Math.min(buffer.length, 1024); for (let i = 0; i < l; i++) { let c = buffer[i]; if (c === 0x3C) { // "<" let c1 = buffer[i + 1]; let c2 = buffer[i + 2]; const c3 = buffer[i + 3]; const c4 = buffer[i + 4]; const c5 = buffer[i + 5]; // !-- (comment start) if (c1 === 0x21 && c2 === 0x2D && c3 === 0x2D) { i += 4; for (; i < l; i++) { c = buffer[i]; c1 = buffer[i + 1]; c2 = buffer[i + 2]; // --> (comment end) if (c === 0x2D && c1 === 0x2D && c2 === 0x3E) { i += 2; break; } } } else if ((c1 === 0x4D || c1 === 0x6D) && (c2 === 0x45 || c2 === 0x65) && (c3 === 0x54 || c3 === 0x74) && (c4 === 0x41 || c4 === 0x61) && (isSpaceCharacter(c5) || c5 === 0x2F)) { // "meta" + space or / i += 6; let gotPragma = false; let needPragma = null; let charset = null; let attrRes; do { attrRes = getAttribute(buffer, i, l); if (attrRes.attr) { if (attrRes.attr.name === "http-equiv") { gotPragma = attrRes.attr.value === "content-type"; } else if (attrRes.attr.name === "content" && !charset) { charset = extractCharacterEncodingFromMeta(attrRes.attr.value); if (charset !== null) { needPragma = true; } } else if (attrRes.attr.name === "charset") { charset = whatwgEncoding.labelToName(attrRes.attr.value); needPragma = false; } } i = attrRes.i; } while (attrRes.attr); if (needPragma === null) { continue; } if (needPragma === true && gotPragma === false) { continue; } if (charset === null) { continue; } if (charset === "UTF-16LE" || charset === "UTF-16BE") { charset = "UTF-8"; } if (charset === "x-user-defined") { charset = "windows-1252"; } return charset; } else if ((c1 >= 0x41 && c1 <= 0x5A) || (c1 >= 0x61 && c1 <= 0x7A)) { // a-z or A-Z for (i += 2; i < l; i++) { c = buffer[i]; // space or > if (isSpaceCharacter(c) || c === 0x3E) { break; } } let attrRes; do { attrRes = getAttribute(buffer, i, l); i = attrRes.i; } while (attrRes.attr); } else if (c1 === 0x21 || c1 === 0x2F || c1 === 0x3F) { // ! or / or ? for (i += 2; i < l; i++) { c = buffer[i]; // > if (c === 0x3E) { break; } } } } } return null; } // https://html.spec.whatwg.org/multipage/syntax.html#concept-get-attributes-when-sniffing function getAttribute(buffer, i, l) { for (; i < l; i++) { let c = buffer[i]; // space or / if (isSpaceCharacter(c) || c === 0x2F) { continue; } // ">" if (c === 0x3E) { i++; break; } let name = ""; let value = ""; nameLoop:for (; i < l; i++) { c = buffer[i]; // "=" if (c === 0x3D && name !== "") { i++; break; } // space if (isSpaceCharacter(c)) { for (i++; i < l; i++) { c = buffer[i]; // space if (isSpaceCharacter(c)) { continue; } // not "=" if (c !== 0x3D) { return { attr: { name, value }, i }; } i++; break nameLoop; } break; } // / or > if (c === 0x2F || c === 0x3E) { return { attr: { name, value }, i }; } // A-Z if (c >= 0x41 && c <= 0x5A) { name += String.fromCharCode(c + 0x20); // lowercase } else { name += String.fromCharCode(c); } } c = buffer[i]; // space if (isSpaceCharacter(c)) { for (i++; i < l; i++) { c = buffer[i]; // space if (isSpaceCharacter(c)) { continue; } else { break; } } } // " or ' if (c === 0x22 || c === 0x27) { const quote = c; for (i++; i < l; i++) { c = buffer[i]; if (c === quote) { i++; return { attr: { name, value }, i }; } // A-Z if (c >= 0x41 && c <= 0x5A) { value += String.fromCharCode(c + 0x20); // lowercase } else { value += String.fromCharCode(c); } } } // > if (c === 0x3E) { return { attr: { name, value }, i }; } // A-Z if (c >= 0x41 && c <= 0x5A) { value += String.fromCharCode(c + 0x20); // lowercase } else { value += String.fromCharCode(c); } for (i++; i < l; i++) { c = buffer[i]; // space or > if (isSpaceCharacter(c) || c === 0x3E) { return { attr: { name, value }, i }; } // A-Z if (c >= 0x41 && c <= 0x5A) { value += String.fromCharCode(c + 0x20); // lowercase } else { value += String.fromCharCode(c); } } } return { i }; } function extractCharacterEncodingFromMeta(string) { let position = 0; while (true) { let subPosition = string.substring(position).search(/charset/i); if (subPosition === -1) { return null; } subPosition += "charset".length; while (isSpaceCharacter(string[subPosition].charCodeAt(0))) { ++subPosition; } if (string[subPosition] !== "=") { position = subPosition - 1; continue; } ++subPosition; while (isSpaceCharacter(string[subPosition].charCodeAt(0))) { ++subPosition; } position = subPosition; break; } if (string[position] === "\"" || string[position] === "'") { const nextIndex = string.indexOf(string[position], position + 1); if (nextIndex !== -1) { return whatwgEncoding.labelToName(string.substring(position + 1, nextIndex)); } // It is an unmatched quotation mark return null; } if (string.length === position + 1) { return null; } let end = string.substring(position + 1).search(/\x09|\x0A|\x0C|\x0D|\x20|;/); if (end === -1) { end = string.length; } return whatwgEncoding.labelToName(string.substring(position, end)); } function isSpaceCharacter(c) { return c === 0x09 || c === 0x0A || c === 0x0C || c === 0x0D || c === 0x20; }