UNPKG

matrix-react-sdk

Version:
212 lines (204 loc) 33.1 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.addReplyToMessageContent = addReplyToMessageContent; exports.getNestedReplyText = getNestedReplyText; exports.getParentEventId = getParentEventId; exports.makeReplyMixIn = makeReplyMixIn; exports.shouldDisplayReply = shouldDisplayReply; exports.stripHTMLReply = stripHTMLReply; exports.stripPlainReply = stripPlainReply; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _matrix = require("matrix-js-sdk/src/matrix"); var _sanitizeHtml = _interopRequireDefault(require("sanitize-html")); var _escapeHtml = _interopRequireDefault(require("escape-html")); var _UrlUtils = require("./UrlUtils"); var _Permalinks = require("./permalinks/Permalinks"); var _location = require("./location"); function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } /* * Copyright 2024 New Vector Ltd. * Copyright 2023 The Matrix.org Foundation C.I.C. * Copyright 2021 Šimon Brandner <simon.bra.ag@gmail.com> * * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only * Please see LICENSE files in the repository root for full details. */ function getParentEventId(ev) { if (!ev || ev.isRedacted()) return; if (ev.replyEventId) { return ev.replyEventId; } } // Part of Replies fallback support function stripPlainReply(body) { // Removes lines beginning with `> ` until you reach one that doesn't. const lines = body.split("\n"); while (lines.length && lines[0].startsWith("> ")) lines.shift(); // Reply fallback has a blank line after it, so remove it to prevent leading newline if (lines[0] === "") lines.shift(); return lines.join("\n"); } // Part of Replies fallback support - MUST NOT BE RENDERED DIRECTLY - UNSAFE HTML function stripHTMLReply(html) { // Sanitize the original HTML for inclusion in <mx-reply>. We allow // any HTML, since the original sender could use special tags that we // don't recognize, but want to pass along to any recipients who do // recognize them -- recipients should be sanitizing before displaying // anyways. However, we sanitize to 1) remove any mx-reply, so that we // don't generate a nested mx-reply, and 2) make sure that the HTML is // properly formatted (e.g. tags are closed where necessary) return (0, _sanitizeHtml.default)(html, { allowedTags: false, // false means allow everything allowedAttributes: false, allowVulnerableTags: true, // silence xss warning, we won't be rendering directly this, so it is safe to do // we somehow can't allow all schemes, so we allow all that we // know of and mxc (for img tags) allowedSchemes: [..._UrlUtils.PERMITTED_URL_SCHEMES, "mxc"], exclusiveFilter: frame => frame.tag === "mx-reply" }); } // Part of Replies fallback support function getNestedReplyText(ev, permalinkCreator) { if (!ev) return null; let { body, formatted_body: html, msgtype } = ev.getContent(); if (getParentEventId(ev)) { if (body) body = stripPlainReply(body); } if (!body) body = ""; // Always ensure we have a body, for reasons. if (html) { // sanitize the HTML before we put it in an <mx-reply> html = stripHTMLReply(html); } else { // Escape the body to use as HTML below. // We also run a nl2br over the result to fix the fallback representation. We do this // after converting the text to safe HTML to avoid user-provided BR's from being converted. html = (0, _escapeHtml.default)(body).replace(/\n/g, "<br/>"); } // dev note: do not rely on `body` being safe for HTML usage below. const evLink = permalinkCreator?.forEvent(ev.getId()); const userLink = (0, _Permalinks.makeUserPermalink)(ev.getSender()); const mxid = ev.getSender(); if (_matrix.M_BEACON_INFO.matches(ev.getType())) { const aTheir = (0, _location.isSelfLocation)(ev.getContent()) ? "their" : "a"; return { html: `<mx-reply><blockquote><a href="${evLink}">In reply to</a> <a href="${userLink}">${mxid}</a>` + `<br>shared ${aTheir} live location.</blockquote></mx-reply>`, body: `> <${mxid}> shared ${aTheir} live location.\n\n` }; } if (_matrix.M_POLL_START.matches(ev.getType())) { const extensibleEvent = ev.unstableExtensibleEvent; const question = extensibleEvent?.question?.text; return { html: `<mx-reply><blockquote><a href="${evLink}">In reply to</a> <a href="${userLink}">${mxid}</a>` + `<br>Poll: ${question}</blockquote></mx-reply>`, body: `> <${mxid}> started poll: ${question}\n\n` }; } if (_matrix.M_POLL_END.matches(ev.getType())) { return { html: `<mx-reply><blockquote><a href="${evLink}">In reply to</a> <a href="${userLink}">${mxid}</a>` + `<br>Ended poll</blockquote></mx-reply>`, body: `> <${mxid}>Ended poll\n\n` }; } // This fallback contains text that is explicitly EN. switch (msgtype) { case _matrix.MsgType.Text: case _matrix.MsgType.Notice: { html = `<mx-reply><blockquote><a href="${evLink}">In reply to</a> <a href="${userLink}">${mxid}</a>` + `<br>${html}</blockquote></mx-reply>`; const lines = body.trim().split("\n"); if (lines.length > 0) { lines[0] = `<${mxid}> ${lines[0]}`; body = lines.map(line => `> ${line}`).join("\n") + "\n\n"; } break; } case _matrix.MsgType.Image: html = `<mx-reply><blockquote><a href="${evLink}">In reply to</a> <a href="${userLink}">${mxid}</a>` + `<br>sent an image.</blockquote></mx-reply>`; body = `> <${mxid}> sent an image.\n\n`; break; case _matrix.MsgType.Video: html = `<mx-reply><blockquote><a href="${evLink}">In reply to</a> <a href="${userLink}">${mxid}</a>` + `<br>sent a video.</blockquote></mx-reply>`; body = `> <${mxid}> sent a video.\n\n`; break; case _matrix.MsgType.Audio: html = `<mx-reply><blockquote><a href="${evLink}">In reply to</a> <a href="${userLink}">${mxid}</a>` + `<br>sent an audio file.</blockquote></mx-reply>`; body = `> <${mxid}> sent an audio file.\n\n`; break; case _matrix.MsgType.File: html = `<mx-reply><blockquote><a href="${evLink}">In reply to</a> <a href="${userLink}">${mxid}</a>` + `<br>sent a file.</blockquote></mx-reply>`; body = `> <${mxid}> sent a file.\n\n`; break; case _matrix.MsgType.Location: { const aTheir = (0, _location.isSelfLocation)(ev.getContent()) ? "their" : "a"; html = `<mx-reply><blockquote><a href="${evLink}">In reply to</a> <a href="${userLink}">${mxid}</a>` + `<br>shared ${aTheir} location.</blockquote></mx-reply>`; body = `> <${mxid}> shared ${aTheir} location.\n\n`; break; } case _matrix.MsgType.Emote: { html = `<mx-reply><blockquote><a href="${evLink}">In reply to</a> * ` + `<a href="${userLink}">${mxid}</a><br>${html}</blockquote></mx-reply>`; const lines = body.trim().split("\n"); if (lines.length > 0) { lines[0] = `* <${mxid}> ${lines[0]}`; body = lines.map(line => `> ${line}`).join("\n") + "\n\n"; } break; } default: return null; } return { body, html }; } function makeReplyMixIn(ev) { if (!ev) return {}; const mixin = { "m.in_reply_to": { event_id: ev.getId() } }; if (ev.threadRootId) { mixin.is_falling_back = false; } return mixin; } function shouldDisplayReply(event) { if (event.isRedacted()) { return false; } const inReplyTo = event.getWireContent()?.["m.relates_to"]?.["m.in_reply_to"]; if (!inReplyTo) { return false; } const relation = event.getRelation(); if (relation?.rel_type === _matrix.THREAD_RELATION_TYPE.name && relation?.is_falling_back) { return false; } return !!inReplyTo.event_id; } function addReplyToMessageContent(content, replyToEvent, opts) { content["m.relates_to"] = _objectSpread(_objectSpread({}, content["m.relates_to"] || {}), makeReplyMixIn(replyToEvent)); if (opts.includeLegacyFallback) { // Part of Replies fallback support - prepend the text we're sending with the text we're replying to const nestedReply = getNestedReplyText(replyToEvent, opts.permalinkCreator); if (nestedReply) { if (content.formatted_body) { content.formatted_body = nestedReply.html + content.formatted_body; } content.body = nestedReply.body + content.body; } } } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbWF0cml4IiwicmVxdWlyZSIsIl9zYW5pdGl6ZUh0bWwiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwiX2VzY2FwZUh0bWwiLCJfVXJsVXRpbHMiLCJfUGVybWFsaW5rcyIsIl9sb2NhdGlvbiIsIm93bktleXMiLCJlIiwiciIsInQiLCJPYmplY3QiLCJrZXlzIiwiZ2V0T3duUHJvcGVydHlTeW1ib2xzIiwibyIsImZpbHRlciIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsImVudW1lcmFibGUiLCJwdXNoIiwiYXBwbHkiLCJfb2JqZWN0U3ByZWFkIiwiYXJndW1lbnRzIiwibGVuZ3RoIiwiZm9yRWFjaCIsIl9kZWZpbmVQcm9wZXJ0eTIiLCJkZWZhdWx0IiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyIsImRlZmluZVByb3BlcnRpZXMiLCJkZWZpbmVQcm9wZXJ0eSIsImdldFBhcmVudEV2ZW50SWQiLCJldiIsImlzUmVkYWN0ZWQiLCJyZXBseUV2ZW50SWQiLCJzdHJpcFBsYWluUmVwbHkiLCJib2R5IiwibGluZXMiLCJzcGxpdCIsInN0YXJ0c1dpdGgiLCJzaGlmdCIsImpvaW4iLCJzdHJpcEhUTUxSZXBseSIsImh0bWwiLCJzYW5pdGl6ZUh0bWwiLCJhbGxvd2VkVGFncyIsImFsbG93ZWRBdHRyaWJ1dGVzIiwiYWxsb3dWdWxuZXJhYmxlVGFncyIsImFsbG93ZWRTY2hlbWVzIiwiUEVSTUlUVEVEX1VSTF9TQ0hFTUVTIiwiZXhjbHVzaXZlRmlsdGVyIiwiZnJhbWUiLCJ0YWciLCJnZXROZXN0ZWRSZXBseVRleHQiLCJwZXJtYWxpbmtDcmVhdG9yIiwiZm9ybWF0dGVkX2JvZHkiLCJtc2d0eXBlIiwiZ2V0Q29udGVudCIsImVzY2FwZUh0bWwiLCJyZXBsYWNlIiwiZXZMaW5rIiwiZm9yRXZlbnQiLCJnZXRJZCIsInVzZXJMaW5rIiwibWFrZVVzZXJQZXJtYWxpbmsiLCJnZXRTZW5kZXIiLCJteGlkIiwiTV9CRUFDT05fSU5GTyIsIm1hdGNoZXMiLCJnZXRUeXBlIiwiYVRoZWlyIiwiaXNTZWxmTG9jYXRpb24iLCJNX1BPTExfU1RBUlQiLCJleHRlbnNpYmxlRXZlbnQiLCJ1bnN0YWJsZUV4dGVuc2libGVFdmVudCIsInF1ZXN0aW9uIiwidGV4dCIsIk1fUE9MTF9FTkQiLCJNc2dUeXBlIiwiVGV4dCIsIk5vdGljZSIsInRyaW0iLCJtYXAiLCJsaW5lIiwiSW1hZ2UiLCJWaWRlbyIsIkF1ZGlvIiwiRmlsZSIsIkxvY2F0aW9uIiwiRW1vdGUiLCJtYWtlUmVwbHlNaXhJbiIsIm1peGluIiwiZXZlbnRfaWQiLCJ0aHJlYWRSb290SWQiLCJpc19mYWxsaW5nX2JhY2siLCJzaG91bGREaXNwbGF5UmVwbHkiLCJldmVudCIsImluUmVwbHlUbyIsImdldFdpcmVDb250ZW50IiwicmVsYXRpb24iLCJnZXRSZWxhdGlvbiIsInJlbF90eXBlIiwiVEhSRUFEX1JFTEFUSU9OX1RZUEUiLCJuYW1lIiwiYWRkUmVwbHlUb01lc3NhZ2VDb250ZW50IiwiY29udGVudCIsInJlcGx5VG9FdmVudCIsIm9wdHMiLCJpbmNsdWRlTGVnYWN5RmFsbGJhY2siLCJuZXN0ZWRSZXBseSJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9SZXBseS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IDIwMjQgTmV3IFZlY3RvciBMdGQuXG4gKiBDb3B5cmlnaHQgMjAyMyBUaGUgTWF0cml4Lm9yZyBGb3VuZGF0aW9uIEMuSS5DLlxuICogQ29weXJpZ2h0IDIwMjEgxaBpbW9uIEJyYW5kbmVyIDxzaW1vbi5icmEuYWdAZ21haWwuY29tPlxuICpcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBR1BMLTMuMC1vbmx5IE9SIEdQTC0zLjAtb25seVxuICogUGxlYXNlIHNlZSBMSUNFTlNFIGZpbGVzIGluIHRoZSByZXBvc2l0b3J5IHJvb3QgZm9yIGZ1bGwgZGV0YWlscy5cbiAqL1xuXG5pbXBvcnQge1xuICAgIElDb250ZW50LFxuICAgIElFdmVudFJlbGF0aW9uLFxuICAgIE1hdHJpeEV2ZW50LFxuICAgIE1zZ1R5cGUsXG4gICAgVEhSRUFEX1JFTEFUSU9OX1RZUEUsXG4gICAgTV9CRUFDT05fSU5GTyxcbiAgICBNX1BPTExfRU5ELFxuICAgIE1fUE9MTF9TVEFSVCxcbn0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL21hdHJpeFwiO1xuaW1wb3J0IHNhbml0aXplSHRtbCBmcm9tIFwic2FuaXRpemUtaHRtbFwiO1xuaW1wb3J0IGVzY2FwZUh0bWwgZnJvbSBcImVzY2FwZS1odG1sXCI7XG5pbXBvcnQgeyBQb2xsU3RhcnRFdmVudCB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9leHRlbnNpYmxlX2V2ZW50c192MS9Qb2xsU3RhcnRFdmVudFwiO1xuXG5pbXBvcnQgeyBQRVJNSVRURURfVVJMX1NDSEVNRVMgfSBmcm9tIFwiLi9VcmxVdGlsc1wiO1xuaW1wb3J0IHsgbWFrZVVzZXJQZXJtYWxpbmssIFJvb21QZXJtYWxpbmtDcmVhdG9yIH0gZnJvbSBcIi4vcGVybWFsaW5rcy9QZXJtYWxpbmtzXCI7XG5pbXBvcnQgeyBpc1NlbGZMb2NhdGlvbiB9IGZyb20gXCIuL2xvY2F0aW9uXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRQYXJlbnRFdmVudElkKGV2PzogTWF0cml4RXZlbnQpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIGlmICghZXYgfHwgZXYuaXNSZWRhY3RlZCgpKSByZXR1cm47XG4gICAgaWYgKGV2LnJlcGx5RXZlbnRJZCkge1xuICAgICAgICByZXR1cm4gZXYucmVwbHlFdmVudElkO1xuICAgIH1cbn1cblxuLy8gUGFydCBvZiBSZXBsaWVzIGZhbGxiYWNrIHN1cHBvcnRcbmV4cG9ydCBmdW5jdGlvbiBzdHJpcFBsYWluUmVwbHkoYm9keTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAvLyBSZW1vdmVzIGxpbmVzIGJlZ2lubmluZyB3aXRoIGA+IGAgdW50aWwgeW91IHJlYWNoIG9uZSB0aGF0IGRvZXNuJ3QuXG4gICAgY29uc3QgbGluZXMgPSBib2R5LnNwbGl0KFwiXFxuXCIpO1xuICAgIHdoaWxlIChsaW5lcy5sZW5ndGggJiYgbGluZXNbMF0uc3RhcnRzV2l0aChcIj4gXCIpKSBsaW5lcy5zaGlmdCgpO1xuICAgIC8vIFJlcGx5IGZhbGxiYWNrIGhhcyBhIGJsYW5rIGxpbmUgYWZ0ZXIgaXQsIHNvIHJlbW92ZSBpdCB0byBwcmV2ZW50IGxlYWRpbmcgbmV3bGluZVxuICAgIGlmIChsaW5lc1swXSA9PT0gXCJcIikgbGluZXMuc2hpZnQoKTtcbiAgICByZXR1cm4gbGluZXMuam9pbihcIlxcblwiKTtcbn1cblxuLy8gUGFydCBvZiBSZXBsaWVzIGZhbGxiYWNrIHN1cHBvcnQgLSBNVVNUIE5PVCBCRSBSRU5ERVJFRCBESVJFQ1RMWSAtIFVOU0FGRSBIVE1MXG5leHBvcnQgZnVuY3Rpb24gc3RyaXBIVE1MUmVwbHkoaHRtbDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAvLyBTYW5pdGl6ZSB0aGUgb3JpZ2luYWwgSFRNTCBmb3IgaW5jbHVzaW9uIGluIDxteC1yZXBseT4uICBXZSBhbGxvd1xuICAgIC8vIGFueSBIVE1MLCBzaW5jZSB0aGUgb3JpZ2luYWwgc2VuZGVyIGNvdWxkIHVzZSBzcGVjaWFsIHRhZ3MgdGhhdCB3ZVxuICAgIC8vIGRvbid0IHJlY29nbml6ZSwgYnV0IHdhbnQgdG8gcGFzcyBhbG9uZyB0byBhbnkgcmVjaXBpZW50cyB3aG8gZG9cbiAgICAvLyByZWNvZ25pemUgdGhlbSAtLSByZWNpcGllbnRzIHNob3VsZCBiZSBzYW5pdGl6aW5nIGJlZm9yZSBkaXNwbGF5aW5nXG4gICAgLy8gYW55d2F5cy4gIEhvd2V2ZXIsIHdlIHNhbml0aXplIHRvIDEpIHJlbW92ZSBhbnkgbXgtcmVwbHksIHNvIHRoYXQgd2VcbiAgICAvLyBkb24ndCBnZW5lcmF0ZSBhIG5lc3RlZCBteC1yZXBseSwgYW5kIDIpIG1ha2Ugc3VyZSB0aGF0IHRoZSBIVE1MIGlzXG4gICAgLy8gcHJvcGVybHkgZm9ybWF0dGVkIChlLmcuIHRhZ3MgYXJlIGNsb3NlZCB3aGVyZSBuZWNlc3NhcnkpXG4gICAgcmV0dXJuIHNhbml0aXplSHRtbChodG1sLCB7XG4gICAgICAgIGFsbG93ZWRUYWdzOiBmYWxzZSwgLy8gZmFsc2UgbWVhbnMgYWxsb3cgZXZlcnl0aGluZ1xuICAgICAgICBhbGxvd2VkQXR0cmlidXRlczogZmFsc2UsXG4gICAgICAgIGFsbG93VnVsbmVyYWJsZVRhZ3M6IHRydWUsIC8vIHNpbGVuY2UgeHNzIHdhcm5pbmcsIHdlIHdvbid0IGJlIHJlbmRlcmluZyBkaXJlY3RseSB0aGlzLCBzbyBpdCBpcyBzYWZlIHRvIGRvXG4gICAgICAgIC8vIHdlIHNvbWVob3cgY2FuJ3QgYWxsb3cgYWxsIHNjaGVtZXMsIHNvIHdlIGFsbG93IGFsbCB0aGF0IHdlXG4gICAgICAgIC8vIGtub3cgb2YgYW5kIG14YyAoZm9yIGltZyB0YWdzKVxuICAgICAgICBhbGxvd2VkU2NoZW1lczogWy4uLlBFUk1JVFRFRF9VUkxfU0NIRU1FUywgXCJteGNcIl0sXG4gICAgICAgIGV4Y2x1c2l2ZUZpbHRlcjogKGZyYW1lKSA9PiBmcmFtZS50YWcgPT09IFwibXgtcmVwbHlcIixcbiAgICB9KTtcbn1cblxuLy8gUGFydCBvZiBSZXBsaWVzIGZhbGxiYWNrIHN1cHBvcnRcbmV4cG9ydCBmdW5jdGlvbiBnZXROZXN0ZWRSZXBseVRleHQoXG4gICAgZXY6IE1hdHJpeEV2ZW50LFxuICAgIHBlcm1hbGlua0NyZWF0b3I/OiBSb29tUGVybWFsaW5rQ3JlYXRvcixcbik6IHsgYm9keTogc3RyaW5nOyBodG1sOiBzdHJpbmcgfSB8IG51bGwge1xuICAgIGlmICghZXYpIHJldHVybiBudWxsO1xuXG4gICAgbGV0IHtcbiAgICAgICAgYm9keSxcbiAgICAgICAgZm9ybWF0dGVkX2JvZHk6IGh0bWwsXG4gICAgICAgIG1zZ3R5cGUsXG4gICAgfSA9IGV2LmdldENvbnRlbnQ8e1xuICAgICAgICBib2R5OiBzdHJpbmc7XG4gICAgICAgIG1zZ3R5cGU/OiBzdHJpbmc7XG4gICAgICAgIGZvcm1hdHRlZF9ib2R5Pzogc3RyaW5nO1xuICAgIH0+KCk7XG4gICAgaWYgKGdldFBhcmVudEV2ZW50SWQoZXYpKSB7XG4gICAgICAgIGlmIChib2R5KSBib2R5ID0gc3RyaXBQbGFpblJlcGx5KGJvZHkpO1xuICAgIH1cblxuICAgIGlmICghYm9keSkgYm9keSA9IFwiXCI7IC8vIEFsd2F5cyBlbnN1cmUgd2UgaGF2ZSBhIGJvZHksIGZvciByZWFzb25zLlxuXG4gICAgaWYgKGh0bWwpIHtcbiAgICAgICAgLy8gc2FuaXRpemUgdGhlIEhUTUwgYmVmb3JlIHdlIHB1dCBpdCBpbiBhbiA8bXgtcmVwbHk+XG4gICAgICAgIGh0bWwgPSBzdHJpcEhUTUxSZXBseShodG1sKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBFc2NhcGUgdGhlIGJvZHkgdG8gdXNlIGFzIEhUTUwgYmVsb3cuXG4gICAgICAgIC8vIFdlIGFsc28gcnVuIGEgbmwyYnIgb3ZlciB0aGUgcmVzdWx0IHRvIGZpeCB0aGUgZmFsbGJhY2sgcmVwcmVzZW50YXRpb24uIFdlIGRvIHRoaXNcbiAgICAgICAgLy8gYWZ0ZXIgY29udmVydGluZyB0aGUgdGV4dCB0byBzYWZlIEhUTUwgdG8gYXZvaWQgdXNlci1wcm92aWRlZCBCUidzIGZyb20gYmVpbmcgY29udmVydGVkLlxuICAgICAgICBodG1sID0gZXNjYXBlSHRtbChib2R5KS5yZXBsYWNlKC9cXG4vZywgXCI8YnIvPlwiKTtcbiAgICB9XG5cbiAgICAvLyBkZXYgbm90ZTogZG8gbm90IHJlbHkgb24gYGJvZHlgIGJlaW5nIHNhZmUgZm9yIEhUTUwgdXNhZ2UgYmVsb3cuXG5cbiAgICBjb25zdCBldkxpbmsgPSBwZXJtYWxpbmtDcmVhdG9yPy5mb3JFdmVudChldi5nZXRJZCgpISk7XG4gICAgY29uc3QgdXNlckxpbmsgPSBtYWtlVXNlclBlcm1hbGluayhldi5nZXRTZW5kZXIoKSEpO1xuICAgIGNvbnN0IG14aWQgPSBldi5nZXRTZW5kZXIoKTtcblxuICAgIGlmIChNX0JFQUNPTl9JTkZPLm1hdGNoZXMoZXYuZ2V0VHlwZSgpKSkge1xuICAgICAgICBjb25zdCBhVGhlaXIgPSBpc1NlbGZMb2NhdGlvbihldi5nZXRDb250ZW50KCkpID8gXCJ0aGVpclwiIDogXCJhXCI7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBodG1sOlxuICAgICAgICAgICAgICAgIGA8bXgtcmVwbHk+PGJsb2NrcXVvdGU+PGEgaHJlZj1cIiR7ZXZMaW5rfVwiPkluIHJlcGx5IHRvPC9hPiA8YSBocmVmPVwiJHt1c2VyTGlua31cIj4ke214aWR9PC9hPmAgK1xuICAgICAgICAgICAgICAgIGA8YnI+c2hhcmVkICR7YVRoZWlyfSBsaXZlIGxvY2F0aW9uLjwvYmxvY2txdW90ZT48L214LXJlcGx5PmAsXG4gICAgICAgICAgICBib2R5OiBgPiA8JHtteGlkfT4gc2hhcmVkICR7YVRoZWlyfSBsaXZlIGxvY2F0aW9uLlxcblxcbmAsXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKE1fUE9MTF9TVEFSVC5tYXRjaGVzKGV2LmdldFR5cGUoKSkpIHtcbiAgICAgICAgY29uc3QgZXh0ZW5zaWJsZUV2ZW50ID0gZXYudW5zdGFibGVFeHRlbnNpYmxlRXZlbnQgYXMgUG9sbFN0YXJ0RXZlbnQ7XG4gICAgICAgIGNvbnN0IHF1ZXN0aW9uID0gZXh0ZW5zaWJsZUV2ZW50Py5xdWVzdGlvbj8udGV4dDtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGh0bWw6XG4gICAgICAgICAgICAgICAgYDxteC1yZXBseT48YmxvY2txdW90ZT48YSBocmVmPVwiJHtldkxpbmt9XCI+SW4gcmVwbHkgdG88L2E+IDxhIGhyZWY9XCIke3VzZXJMaW5rfVwiPiR7bXhpZH08L2E+YCArXG4gICAgICAgICAgICAgICAgYDxicj5Qb2xsOiAke3F1ZXN0aW9ufTwvYmxvY2txdW90ZT48L214LXJlcGx5PmAsXG4gICAgICAgICAgICBib2R5OiBgPiA8JHtteGlkfT4gc3RhcnRlZCBwb2xsOiAke3F1ZXN0aW9ufVxcblxcbmAsXG4gICAgICAgIH07XG4gICAgfVxuICAgIGlmIChNX1BPTExfRU5ELm1hdGNoZXMoZXYuZ2V0VHlwZSgpKSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgaHRtbDpcbiAgICAgICAgICAgICAgICBgPG14LXJlcGx5PjxibG9ja3F1b3RlPjxhIGhyZWY9XCIke2V2TGlua31cIj5JbiByZXBseSB0bzwvYT4gPGEgaHJlZj1cIiR7dXNlckxpbmt9XCI+JHtteGlkfTwvYT5gICtcbiAgICAgICAgICAgICAgICBgPGJyPkVuZGVkIHBvbGw8L2Jsb2NrcXVvdGU+PC9teC1yZXBseT5gLFxuICAgICAgICAgICAgYm9keTogYD4gPCR7bXhpZH0+RW5kZWQgcG9sbFxcblxcbmAsXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gVGhpcyBmYWxsYmFjayBjb250YWlucyB0ZXh0IHRoYXQgaXMgZXhwbGljaXRseSBFTi5cbiAgICBzd2l0Y2ggKG1zZ3R5cGUpIHtcbiAgICAgICAgY2FzZSBNc2dUeXBlLlRleHQ6XG4gICAgICAgIGNhc2UgTXNnVHlwZS5Ob3RpY2U6IHtcbiAgICAgICAgICAgIGh0bWwgPVxuICAgICAgICAgICAgICAgIGA8bXgtcmVwbHk+PGJsb2NrcXVvdGU+PGEgaHJlZj1cIiR7ZXZMaW5rfVwiPkluIHJlcGx5IHRvPC9hPiA8YSBocmVmPVwiJHt1c2VyTGlua31cIj4ke214aWR9PC9hPmAgK1xuICAgICAgICAgICAgICAgIGA8YnI+JHtodG1sfTwvYmxvY2txdW90ZT48L214LXJlcGx5PmA7XG4gICAgICAgICAgICBjb25zdCBsaW5lcyA9IGJvZHkudHJpbSgpLnNwbGl0KFwiXFxuXCIpO1xuICAgICAgICAgICAgaWYgKGxpbmVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBsaW5lc1swXSA9IGA8JHtteGlkfT4gJHtsaW5lc1swXX1gO1xuICAgICAgICAgICAgICAgIGJvZHkgPSBsaW5lcy5tYXAoKGxpbmUpID0+IGA+ICR7bGluZX1gKS5qb2luKFwiXFxuXCIpICsgXCJcXG5cXG5cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgTXNnVHlwZS5JbWFnZTpcbiAgICAgICAgICAgIGh0bWwgPVxuICAgICAgICAgICAgICAgIGA8bXgtcmVwbHk+PGJsb2NrcXVvdGU+PGEgaHJlZj1cIiR7ZXZMaW5rfVwiPkluIHJlcGx5IHRvPC9hPiA8YSBocmVmPVwiJHt1c2VyTGlua31cIj4ke214aWR9PC9hPmAgK1xuICAgICAgICAgICAgICAgIGA8YnI+c2VudCBhbiBpbWFnZS48L2Jsb2NrcXVvdGU+PC9teC1yZXBseT5gO1xuICAgICAgICAgICAgYm9keSA9IGA+IDwke214aWR9PiBzZW50IGFuIGltYWdlLlxcblxcbmA7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBNc2dUeXBlLlZpZGVvOlxuICAgICAgICAgICAgaHRtbCA9XG4gICAgICAgICAgICAgICAgYDxteC1yZXBseT48YmxvY2txdW90ZT48YSBocmVmPVwiJHtldkxpbmt9XCI+SW4gcmVwbHkgdG88L2E+IDxhIGhyZWY9XCIke3VzZXJMaW5rfVwiPiR7bXhpZH08L2E+YCArXG4gICAgICAgICAgICAgICAgYDxicj5zZW50IGEgdmlkZW8uPC9ibG9ja3F1b3RlPjwvbXgtcmVwbHk+YDtcbiAgICAgICAgICAgIGJvZHkgPSBgPiA8JHtteGlkfT4gc2VudCBhIHZpZGVvLlxcblxcbmA7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBNc2dUeXBlLkF1ZGlvOlxuICAgICAgICAgICAgaHRtbCA9XG4gICAgICAgICAgICAgICAgYDxteC1yZXBseT48YmxvY2txdW90ZT48YSBocmVmPVwiJHtldkxpbmt9XCI+SW4gcmVwbHkgdG88L2E+IDxhIGhyZWY9XCIke3VzZXJMaW5rfVwiPiR7bXhpZH08L2E+YCArXG4gICAgICAgICAgICAgICAgYDxicj5zZW50IGFuIGF1ZGlvIGZpbGUuPC9ibG9ja3F1b3RlPjwvbXgtcmVwbHk+YDtcbiAgICAgICAgICAgIGJvZHkgPSBgPiA8JHtteGlkfT4gc2VudCBhbiBhdWRpbyBmaWxlLlxcblxcbmA7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBNc2dUeXBlLkZpbGU6XG4gICAgICAgICAgICBodG1sID1cbiAgICAgICAgICAgICAgICBgPG14LXJlcGx5PjxibG9ja3F1b3RlPjxhIGhyZWY9XCIke2V2TGlua31cIj5JbiByZXBseSB0bzwvYT4gPGEgaHJlZj1cIiR7dXNlckxpbmt9XCI+JHtteGlkfTwvYT5gICtcbiAgICAgICAgICAgICAgICBgPGJyPnNlbnQgYSBmaWxlLjwvYmxvY2txdW90ZT48L214LXJlcGx5PmA7XG4gICAgICAgICAgICBib2R5ID0gYD4gPCR7bXhpZH0+IHNlbnQgYSBmaWxlLlxcblxcbmA7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBNc2dUeXBlLkxvY2F0aW9uOiB7XG4gICAgICAgICAgICBjb25zdCBhVGhlaXIgPSBpc1NlbGZMb2NhdGlvbihldi5nZXRDb250ZW50KCkpID8gXCJ0aGVpclwiIDogXCJhXCI7XG4gICAgICAgICAgICBodG1sID1cbiAgICAgICAgICAgICAgICBgPG14LXJlcGx5PjxibG9ja3F1b3RlPjxhIGhyZWY9XCIke2V2TGlua31cIj5JbiByZXBseSB0bzwvYT4gPGEgaHJlZj1cIiR7dXNlckxpbmt9XCI+JHtteGlkfTwvYT5gICtcbiAgICAgICAgICAgICAgICBgPGJyPnNoYXJlZCAke2FUaGVpcn0gbG9jYXRpb24uPC9ibG9ja3F1b3RlPjwvbXgtcmVwbHk+YDtcbiAgICAgICAgICAgIGJvZHkgPSBgPiA8JHtteGlkfT4gc2hhcmVkICR7YVRoZWlyfSBsb2NhdGlvbi5cXG5cXG5gO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgY2FzZSBNc2dUeXBlLkVtb3RlOiB7XG4gICAgICAgICAgICBodG1sID1cbiAgICAgICAgICAgICAgICBgPG14LXJlcGx5PjxibG9ja3F1b3RlPjxhIGhyZWY9XCIke2V2TGlua31cIj5JbiByZXBseSB0bzwvYT4gKiBgICtcbiAgICAgICAgICAgICAgICBgPGEgaHJlZj1cIiR7dXNlckxpbmt9XCI+JHtteGlkfTwvYT48YnI+JHtodG1sfTwvYmxvY2txdW90ZT48L214LXJlcGx5PmA7XG4gICAgICAgICAgICBjb25zdCBsaW5lcyA9IGJvZHkudHJpbSgpLnNwbGl0KFwiXFxuXCIpO1xuICAgICAgICAgICAgaWYgKGxpbmVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBsaW5lc1swXSA9IGAqIDwke214aWR9PiAke2xpbmVzWzBdfWA7XG4gICAgICAgICAgICAgICAgYm9keSA9IGxpbmVzLm1hcCgobGluZSkgPT4gYD4gJHtsaW5lfWApLmpvaW4oXCJcXG5cIikgKyBcIlxcblxcblwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiB7IGJvZHksIGh0bWwgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1ha2VSZXBseU1peEluKGV2PzogTWF0cml4RXZlbnQpOiBJRXZlbnRSZWxhdGlvbiB7XG4gICAgaWYgKCFldikgcmV0dXJuIHt9O1xuXG4gICAgY29uc3QgbWl4aW46IElFdmVudFJlbGF0aW9uID0ge1xuICAgICAgICBcIm0uaW5fcmVwbHlfdG9cIjoge1xuICAgICAgICAgICAgZXZlbnRfaWQ6IGV2LmdldElkKCksXG4gICAgICAgIH0sXG4gICAgfTtcblxuICAgIGlmIChldi50aHJlYWRSb290SWQpIHtcbiAgICAgICAgbWl4aW4uaXNfZmFsbGluZ19iYWNrID0gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIG1peGluO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2hvdWxkRGlzcGxheVJlcGx5KGV2ZW50OiBNYXRyaXhFdmVudCk6IGJvb2xlYW4ge1xuICAgIGlmIChldmVudC5pc1JlZGFjdGVkKCkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGluUmVwbHlUbyA9IGV2ZW50LmdldFdpcmVDb250ZW50KCk/LltcIm0ucmVsYXRlc190b1wiXT8uW1wibS5pbl9yZXBseV90b1wiXTtcbiAgICBpZiAoIWluUmVwbHlUbykge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgcmVsYXRpb24gPSBldmVudC5nZXRSZWxhdGlvbigpO1xuICAgIGlmIChyZWxhdGlvbj8ucmVsX3R5cGUgPT09IFRIUkVBRF9SRUxBVElPTl9UWVBFLm5hbWUgJiYgcmVsYXRpb24/LmlzX2ZhbGxpbmdfYmFjaykge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuICEhaW5SZXBseVRvLmV2ZW50X2lkO1xufVxuXG5pbnRlcmZhY2UgQWRkUmVwbHlPcHRzIHtcbiAgICBwZXJtYWxpbmtDcmVhdG9yPzogUm9vbVBlcm1hbGlua0NyZWF0b3I7XG4gICAgaW5jbHVkZUxlZ2FjeUZhbGxiYWNrOiBmYWxzZTtcbn1cblxuaW50ZXJmYWNlIEluY2x1ZGVMZWdhY3lGZWVkYmFja09wdHMge1xuICAgIHBlcm1hbGlua0NyZWF0b3I/OiBSb29tUGVybWFsaW5rQ3JlYXRvcjtcbiAgICBpbmNsdWRlTGVnYWN5RmFsbGJhY2s6IHRydWU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhZGRSZXBseVRvTWVzc2FnZUNvbnRlbnQoXG4gICAgY29udGVudDogSUNvbnRlbnQsXG4gICAgcmVwbHlUb0V2ZW50OiBNYXRyaXhFdmVudCxcbiAgICBvcHRzOiBBZGRSZXBseU9wdHMgfCBJbmNsdWRlTGVnYWN5RmVlZGJhY2tPcHRzLFxuKTogdm9pZCB7XG4gICAgY29udGVudFtcIm0ucmVsYXRlc190b1wiXSA9IHtcbiAgICAgICAgLi4uKGNvbnRlbnRbXCJtLnJlbGF0ZXNfdG9cIl0gfHwge30pLFxuICAgICAgICAuLi5tYWtlUmVwbHlNaXhJbihyZXBseVRvRXZlbnQpLFxuICAgIH07XG5cbiAgICBpZiAob3B0cy5pbmNsdWRlTGVnYWN5RmFsbGJhY2spIHtcbiAgICAgICAgLy8gUGFydCBvZiBSZXBsaWVzIGZhbGxiYWNrIHN1cHBvcnQgLSBwcmVwZW5kIHRoZSB0ZXh0IHdlJ3JlIHNlbmRpbmcgd2l0aCB0aGUgdGV4dCB3ZSdyZSByZXBseWluZyB0b1xuICAgICAgICBjb25zdCBuZXN0ZWRSZXBseSA9IGdldE5lc3RlZFJlcGx5VGV4dChyZXBseVRvRXZlbnQsIG9wdHMucGVybWFsaW5rQ3JlYXRvcik7XG4gICAgICAgIGlmIChuZXN0ZWRSZXBseSkge1xuICAgICAgICAgICAgaWYgKGNvbnRlbnQuZm9ybWF0dGVkX2JvZHkpIHtcbiAgICAgICAgICAgICAgICBjb250ZW50LmZvcm1hdHRlZF9ib2R5ID0gbmVzdGVkUmVwbHkuaHRtbCArIGNvbnRlbnQuZm9ybWF0dGVkX2JvZHk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb250ZW50LmJvZHkgPSBuZXN0ZWRSZXBseS5ib2R5ICsgY29udGVudC5ib2R5O1xuICAgICAgICB9XG4gICAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7OztBQVNBLElBQUFBLE9BQUEsR0FBQUMsT0FBQTtBQVVBLElBQUFDLGFBQUEsR0FBQUMsc0JBQUEsQ0FBQUYsT0FBQTtBQUNBLElBQUFHLFdBQUEsR0FBQUQsc0JBQUEsQ0FBQUYsT0FBQTtBQUdBLElBQUFJLFNBQUEsR0FBQUosT0FBQTtBQUNBLElBQUFLLFdBQUEsR0FBQUwsT0FBQTtBQUNBLElBQUFNLFNBQUEsR0FBQU4sT0FBQTtBQUE0QyxTQUFBTyxRQUFBQyxDQUFBLEVBQUFDLENBQUEsUUFBQUMsQ0FBQSxHQUFBQyxNQUFBLENBQUFDLElBQUEsQ0FBQUosQ0FBQSxPQUFBRyxNQUFBLENBQUFFLHFCQUFBLFFBQUFDLENBQUEsR0FBQUgsTUFBQSxDQUFBRSxxQkFBQSxDQUFBTCxDQUFBLEdBQUFDLENBQUEs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