You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
186 lines
31 KiB
JavaScript
186 lines
31 KiB
JavaScript
var __create = Object.create;
|
|
var __defProp = Object.defineProperty;
|
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
var __getProtoOf = Object.getPrototypeOf;
|
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
var __copyProps = (to, from, except, desc) => {
|
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
for (let key of __getOwnPropNames(from))
|
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
}
|
|
return to;
|
|
};
|
|
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod));
|
|
var import_chai = __toESM(require("chai"));
|
|
var sinon = __toESM(require("sinon"));
|
|
var import_test_utils = require("../../../test-utils");
|
|
var import_utils = require("../../../../session/utils");
|
|
var import_types = require("../../../../session/types");
|
|
var import_ClosedGroupVisibleMessage = require("../../../../session/messages/outgoing/visibleMessage/ClosedGroupVisibleMessage");
|
|
var import_ConfigurationMessage = require("../../../../session/messages/outgoing/controlMessage/ConfigurationMessage");
|
|
var import_chai_as_promised = __toESM(require("chai-as-promised"));
|
|
var import_ClosedGroupEncryptionPairReplyMessage = require("../../../../session/messages/outgoing/controlMessage/group/ClosedGroupEncryptionPairReplyMessage");
|
|
var import_protobuf = require("../../../../protobuf");
|
|
var import_ClosedGroupAddedMembersMessage = require("../../../../session/messages/outgoing/controlMessage/group/ClosedGroupAddedMembersMessage");
|
|
var import_ClosedGroupEncryptionPairMessage = require("../../../../session/messages/outgoing/controlMessage/group/ClosedGroupEncryptionPairMessage");
|
|
var import_ClosedGroupNameChangeMessage = require("../../../../session/messages/outgoing/controlMessage/group/ClosedGroupNameChangeMessage");
|
|
var import_ClosedGroupNewMessage = require("../../../../session/messages/outgoing/controlMessage/group/ClosedGroupNewMessage");
|
|
var import_ClosedGroupRemovedMembersMessage = require("../../../../session/messages/outgoing/controlMessage/group/ClosedGroupRemovedMembersMessage");
|
|
import_chai.default.use(import_chai_as_promised.default);
|
|
const { expect } = import_chai.default;
|
|
describe("Message Utils", () => {
|
|
const sandbox = sinon.createSandbox();
|
|
afterEach(() => {
|
|
sandbox.restore();
|
|
});
|
|
describe("toRawMessage", () => {
|
|
it("can convert to raw message", async () => {
|
|
const device = import_test_utils.TestUtils.generateFakePubKey();
|
|
const message = import_test_utils.TestUtils.generateVisibleMessage();
|
|
const rawMessage = await import_utils.MessageUtils.toRawMessage(device, message);
|
|
expect(Object.keys(rawMessage)).to.have.length(5);
|
|
expect(rawMessage.identifier).to.exist;
|
|
expect(rawMessage.device).to.exist;
|
|
expect(rawMessage.encryption).to.exist;
|
|
expect(rawMessage.plainTextBuffer).to.exist;
|
|
expect(rawMessage.ttl).to.exist;
|
|
expect(rawMessage.identifier).to.equal(message.identifier);
|
|
expect(rawMessage.device).to.equal(device.key);
|
|
expect(rawMessage.plainTextBuffer).to.deep.equal(message.plainTextBuffer());
|
|
expect(rawMessage.ttl).to.equal(message.ttl());
|
|
});
|
|
it("should generate valid plainTextBuffer", async () => {
|
|
const device = import_test_utils.TestUtils.generateFakePubKey();
|
|
const message = import_test_utils.TestUtils.generateVisibleMessage();
|
|
const rawMessage = await import_utils.MessageUtils.toRawMessage(device, message);
|
|
const rawBuffer = rawMessage.plainTextBuffer;
|
|
const rawBufferJSON = JSON.stringify(rawBuffer);
|
|
const messageBufferJSON = JSON.stringify(message.plainTextBuffer());
|
|
expect(rawBuffer instanceof Uint8Array).to.equal(true, "raw message did not contain a plainTextBuffer");
|
|
expect(rawBufferJSON).to.equal(messageBufferJSON, "plainTextBuffer was not converted correctly");
|
|
});
|
|
it("should maintain pubkey", async () => {
|
|
const device = import_test_utils.TestUtils.generateFakePubKey();
|
|
const message = import_test_utils.TestUtils.generateVisibleMessage();
|
|
const rawMessage = await import_utils.MessageUtils.toRawMessage(device, message);
|
|
const derivedPubKey = import_types.PubKey.from(rawMessage.device);
|
|
expect(derivedPubKey).to.exist;
|
|
expect(derivedPubKey == null ? void 0 : derivedPubKey.isEqual(device)).to.equal(true, "pubkey of message was not converted correctly");
|
|
});
|
|
it("should set encryption to ClosedGroup if a ClosedGroupVisibleMessage is passed in", async () => {
|
|
const device = import_test_utils.TestUtils.generateFakePubKey();
|
|
const groupId = import_test_utils.TestUtils.generateFakePubKey();
|
|
const chatMessage = import_test_utils.TestUtils.generateVisibleMessage();
|
|
const message = new import_ClosedGroupVisibleMessage.ClosedGroupVisibleMessage({ chatMessage, groupId });
|
|
const rawMessage = await import_utils.MessageUtils.toRawMessage(device, message);
|
|
expect(rawMessage.encryption).to.equal(import_types.EncryptionType.ClosedGroup);
|
|
});
|
|
it("should set encryption to Fallback on other messages", async () => {
|
|
const device = import_test_utils.TestUtils.generateFakePubKey();
|
|
const message = import_test_utils.TestUtils.generateVisibleMessage();
|
|
const rawMessage = await import_utils.MessageUtils.toRawMessage(device, message);
|
|
expect(rawMessage.encryption).to.equal(import_types.EncryptionType.Fallback);
|
|
});
|
|
it("passing ClosedGroupNewMessage returns Fallback", async () => {
|
|
const device = import_test_utils.TestUtils.generateFakePubKey();
|
|
const member = import_test_utils.TestUtils.generateFakePubKey().key;
|
|
const msg = new import_ClosedGroupNewMessage.ClosedGroupNewMessage({
|
|
timestamp: Date.now(),
|
|
name: "df",
|
|
members: [member],
|
|
admins: [member],
|
|
groupId: import_test_utils.TestUtils.generateFakePubKey().key,
|
|
keypair: import_test_utils.TestUtils.generateFakeECKeyPair(),
|
|
expireTimer: 0
|
|
});
|
|
const rawMessage = await import_utils.MessageUtils.toRawMessage(device, msg);
|
|
expect(rawMessage.encryption).to.equal(import_types.EncryptionType.Fallback);
|
|
});
|
|
it("passing ClosedGroupNameChangeMessage returns ClosedGroup", async () => {
|
|
const device = import_test_utils.TestUtils.generateFakePubKey();
|
|
const msg = new import_ClosedGroupNameChangeMessage.ClosedGroupNameChangeMessage({
|
|
timestamp: Date.now(),
|
|
name: "df",
|
|
groupId: import_test_utils.TestUtils.generateFakePubKey().key
|
|
});
|
|
const rawMessage = await import_utils.MessageUtils.toRawMessage(device, msg);
|
|
expect(rawMessage.encryption).to.equal(import_types.EncryptionType.ClosedGroup);
|
|
});
|
|
it("passing ClosedGroupAddedMembersMessage returns ClosedGroup", async () => {
|
|
const device = import_test_utils.TestUtils.generateFakePubKey();
|
|
const msg = new import_ClosedGroupAddedMembersMessage.ClosedGroupAddedMembersMessage({
|
|
timestamp: Date.now(),
|
|
addedMembers: [import_test_utils.TestUtils.generateFakePubKey().key],
|
|
groupId: import_test_utils.TestUtils.generateFakePubKey().key
|
|
});
|
|
const rawMessage = await import_utils.MessageUtils.toRawMessage(device, msg);
|
|
expect(rawMessage.encryption).to.equal(import_types.EncryptionType.ClosedGroup);
|
|
});
|
|
it("passing ClosedGroupRemovedMembersMessage returns ClosedGroup", async () => {
|
|
const device = import_test_utils.TestUtils.generateFakePubKey();
|
|
const msg = new import_ClosedGroupRemovedMembersMessage.ClosedGroupRemovedMembersMessage({
|
|
timestamp: Date.now(),
|
|
removedMembers: [import_test_utils.TestUtils.generateFakePubKey().key],
|
|
groupId: import_test_utils.TestUtils.generateFakePubKey().key
|
|
});
|
|
const rawMessage = await import_utils.MessageUtils.toRawMessage(device, msg);
|
|
expect(rawMessage.encryption).to.equal(import_types.EncryptionType.ClosedGroup);
|
|
});
|
|
it("passing ClosedGroupEncryptionPairMessage returns ClosedGroup", async () => {
|
|
const device = import_test_utils.TestUtils.generateFakePubKey();
|
|
const fakeWrappers = new Array();
|
|
fakeWrappers.push(new import_protobuf.SignalService.DataMessage.ClosedGroupControlMessage.KeyPairWrapper({
|
|
publicKey: new Uint8Array(8),
|
|
encryptedKeyPair: new Uint8Array(8)
|
|
}));
|
|
const msg = new import_ClosedGroupEncryptionPairMessage.ClosedGroupEncryptionPairMessage({
|
|
timestamp: Date.now(),
|
|
groupId: import_test_utils.TestUtils.generateFakePubKey().key,
|
|
encryptedKeyPairs: fakeWrappers
|
|
});
|
|
const rawMessage = await import_utils.MessageUtils.toRawMessage(device, msg);
|
|
expect(rawMessage.encryption).to.equal(import_types.EncryptionType.ClosedGroup);
|
|
});
|
|
it("passing ClosedGroupEncryptionKeyPairReply returns Fallback", async () => {
|
|
const device = import_test_utils.TestUtils.generateFakePubKey();
|
|
const fakeWrappers = new Array();
|
|
fakeWrappers.push(new import_protobuf.SignalService.DataMessage.ClosedGroupControlMessage.KeyPairWrapper({
|
|
publicKey: new Uint8Array(8),
|
|
encryptedKeyPair: new Uint8Array(8)
|
|
}));
|
|
const msg = new import_ClosedGroupEncryptionPairReplyMessage.ClosedGroupEncryptionPairReplyMessage({
|
|
timestamp: Date.now(),
|
|
groupId: import_test_utils.TestUtils.generateFakePubKey().key,
|
|
encryptedKeyPairs: fakeWrappers
|
|
});
|
|
const rawMessage = await import_utils.MessageUtils.toRawMessage(device, msg);
|
|
expect(rawMessage.encryption).to.equal(import_types.EncryptionType.Fallback);
|
|
});
|
|
it("passing a ConfigurationMessage returns Fallback", async () => {
|
|
const device = import_test_utils.TestUtils.generateFakePubKey();
|
|
const msg = new import_ConfigurationMessage.ConfigurationMessage({
|
|
timestamp: Date.now(),
|
|
activeOpenGroups: [],
|
|
activeClosedGroups: [],
|
|
displayName: "displayName",
|
|
contacts: []
|
|
});
|
|
const rawMessage = await import_utils.MessageUtils.toRawMessage(device, msg);
|
|
expect(rawMessage.encryption).to.equal(import_types.EncryptionType.Fallback);
|
|
});
|
|
});
|
|
describe("getCurrentConfigurationMessage", () => {
|
|
const ourNumber = import_test_utils.TestUtils.generateFakePubKey().key;
|
|
beforeEach(() => {
|
|
sandbox.stub(import_utils.UserUtils, "getOurPubKeyStrFromCache").resolves(ourNumber);
|
|
sandbox.stub(import_utils.UserUtils, "getOurPubKeyFromCache").resolves(import_types.PubKey.cast(ourNumber));
|
|
});
|
|
beforeEach(() => {
|
|
sandbox.restore();
|
|
});
|
|
});
|
|
});
|
|
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vLi4vdHMvdGVzdC9zZXNzaW9uL3VuaXQvdXRpbHMvTWVzc2FnZXNfdGVzdC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLy8gdHNsaW50OmRpc2FibGU6IG5vLWltcGxpY2l0LWRlcGVuZGVuY2llc1xuXG5pbXBvcnQgY2hhaSBmcm9tICdjaGFpJztcbmltcG9ydCAqIGFzIHNpbm9uIGZyb20gJ3Npbm9uJztcbmltcG9ydCB7IFRlc3RVdGlscyB9IGZyb20gJy4uLy4uLy4uL3Rlc3QtdXRpbHMnO1xuaW1wb3J0IHsgTWVzc2FnZVV0aWxzLCBVc2VyVXRpbHMgfSBmcm9tICcuLi8uLi8uLi8uLi9zZXNzaW9uL3V0aWxzJztcbmltcG9ydCB7IEVuY3J5cHRpb25UeXBlLCBQdWJLZXkgfSBmcm9tICcuLi8uLi8uLi8uLi9zZXNzaW9uL3R5cGVzJztcbmltcG9ydCB7IENsb3NlZEdyb3VwVmlzaWJsZU1lc3NhZ2UgfSBmcm9tICcuLi8uLi8uLi8uLi9zZXNzaW9uL21lc3NhZ2VzL291dGdvaW5nL3Zpc2libGVNZXNzYWdlL0Nsb3NlZEdyb3VwVmlzaWJsZU1lc3NhZ2UnO1xuaW1wb3J0IHsgQ29uZmlndXJhdGlvbk1lc3NhZ2UgfSBmcm9tICcuLi8uLi8uLi8uLi9zZXNzaW9uL21lc3NhZ2VzL291dGdvaW5nL2NvbnRyb2xNZXNzYWdlL0NvbmZpZ3VyYXRpb25NZXNzYWdlJztcblxuaW1wb3J0IGNoYWlBc1Byb21pc2VkIGZyb20gJ2NoYWktYXMtcHJvbWlzZWQnO1xuY2hhaS51c2UoY2hhaUFzUHJvbWlzZWQgYXMgYW55KTtcbmltcG9ydCB7IENsb3NlZEdyb3VwRW5jcnlwdGlvblBhaXJSZXBseU1lc3NhZ2UgfSBmcm9tICcuLi8uLi8uLi8uLi9zZXNzaW9uL21lc3NhZ2VzL291dGdvaW5nL2NvbnRyb2xNZXNzYWdlL2dyb3VwL0Nsb3NlZEdyb3VwRW5jcnlwdGlvblBhaXJSZXBseU1lc3NhZ2UnO1xuaW1wb3J0IHsgU2lnbmFsU2VydmljZSB9IGZyb20gJy4uLy4uLy4uLy4uL3Byb3RvYnVmJztcbmltcG9ydCB7IENsb3NlZEdyb3VwQWRkZWRNZW1iZXJzTWVzc2FnZSB9IGZyb20gJy4uLy4uLy4uLy4uL3Nlc3Npb24vbWVzc2FnZXMvb3V0Z29pbmcvY29udHJvbE1lc3NhZ2UvZ3JvdXAvQ2xvc2VkR3JvdXBBZGRlZE1lbWJlcnNNZXNzYWdlJztcbmltcG9ydCB7IENsb3NlZEdyb3VwRW5jcnlwdGlvblBhaXJNZXNzYWdlIH0gZnJvbSAnLi4vLi4vLi4vLi4vc2Vzc2lvbi9tZXNzYWdlcy9vdXRnb2luZy9jb250cm9sTWVzc2FnZS9ncm91cC9DbG9zZWRHcm91cEVuY3J5cHRpb25QYWlyTWVzc2FnZSc7XG5pbXBvcnQgeyBDbG9zZWRHcm91cE5hbWVDaGFuZ2VNZXNzYWdlIH0gZnJvbSAnLi4vLi4vLi4vLi4vc2Vzc2lvbi9tZXNzYWdlcy9vdXRnb2luZy9jb250cm9sTWVzc2FnZS9ncm91cC9DbG9zZWRHcm91cE5hbWVDaGFuZ2VNZXNzYWdlJztcbmltcG9ydCB7IENsb3NlZEdyb3VwTmV3TWVzc2FnZSB9IGZyb20gJy4uLy4uLy4uLy4uL3Nlc3Npb24vbWVzc2FnZXMvb3V0Z29pbmcvY29udHJvbE1lc3NhZ2UvZ3JvdXAvQ2xvc2VkR3JvdXBOZXdNZXNzYWdlJztcbmltcG9ydCB7IENsb3NlZEdyb3VwUmVtb3ZlZE1lbWJlcnNNZXNzYWdlIH0gZnJvbSAnLi4vLi4vLi4vLi4vc2Vzc2lvbi9tZXNzYWdlcy9vdXRnb2luZy9jb250cm9sTWVzc2FnZS9ncm91cC9DbG9zZWRHcm91cFJlbW92ZWRNZW1iZXJzTWVzc2FnZSc7XG5cbmNvbnN0IHsgZXhwZWN0IH0gPSBjaGFpO1xuXG5kZXNjcmliZSgnTWVzc2FnZSBVdGlscycsICgpID0+IHtcbiAgY29uc3Qgc2FuZGJveCA9IHNpbm9uLmNyZWF0ZVNhbmRib3goKTtcblxuICBhZnRlckVhY2goKCkgPT4ge1xuICAgIHNhbmRib3gucmVzdG9yZSgpO1xuICB9KTtcblxuICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6IG1heC1mdW5jLWJvZHktbGVuZ3RoXG4gIGRlc2NyaWJlKCd0b1Jhd01lc3NhZ2UnLCAoKSA9PiB7XG4gICAgaXQoJ2NhbiBjb252ZXJ0IHRvIHJhdyBtZXNzYWdlJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgZGV2aWNlID0gVGVzdFV0aWxzLmdlbmVyYXRlRmFrZVB1YktleSgpO1xuICAgICAgY29uc3QgbWVzc2FnZSA9IFRlc3RVdGlscy5nZW5lcmF0ZVZpc2libGVNZXNzYWdlKCk7XG5cbiAgICAgIGNvbnN0IHJhd01lc3NhZ2UgPSBhd2FpdCBNZXNzYWdlVXRpbHMudG9SYXdNZXNzYWdlKGRldmljZSwgbWVzc2FnZSk7XG5cbiAgICAgIGV4cGVjdChPYmplY3Qua2V5cyhyYXdNZXNzYWdlKSkudG8uaGF2ZS5sZW5ndGgoNSk7XG4gICAgICBleHBlY3QocmF3TWVzc2FnZS5pZGVudGlmaWVyKS50by5leGlzdDtcbiAgICAgIGV4cGVjdChyYXdNZXNzYWdlLmRldmljZSkudG8uZXhpc3Q7XG4gICAgICBleHBlY3QocmF3TWVzc2FnZS5lbmNyeXB0aW9uKS50by5leGlzdDtcbiAgICAgIGV4cGVjdChyYXdNZXNzYWdlLnBsYWluVGV4dEJ1ZmZlcikudG8uZXhpc3Q7XG4gICAgICBleHBlY3QocmF3TWVzc2FnZS50dGwpLnRvLmV4aXN0O1xuXG4gICAgICBleHBlY3QocmF3TWVzc2FnZS5pZGVudGlmaWVyKS50by5lcXVhbChtZXNzYWdlLmlkZW50aWZpZXIpO1xuICAgICAgZXhwZWN0KHJhd01lc3NhZ2UuZGV2aWNlKS50by5lcXVhbChkZXZpY2Uua2V5KTtcbiAgICAgIGV4cGVjdChyYXdNZXNzYWdlLnBsYWluVGV4dEJ1ZmZlcikudG8uZGVlcC5lcXVhbChtZXNzYWdlLnBsYWluVGV4dEJ1ZmZlcigpKTtcbiAgICAgIGV4cGVjdChyYXdNZXNzYWdlLnR0bCkudG8uZXF1YWwobWVzc2FnZS50dGwoKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGdlbmVyYXRlIHZhbGlkIHBsYWluVGV4dEJ1ZmZlcicsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGRldmljZSA9IFRlc3RVdGlscy5nZW5lcmF0ZUZha2VQdWJLZXkoKTtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBUZXN0VXRpbHMuZ2VuZXJhdGVWaXNpYmxlTWVzc2FnZSgpO1xuXG4gICAgICBjb25zdCByYXdNZXNzYWdlID0gYXdhaXQgTWVzc2FnZVV0aWxzLnRvUmF3TWVzc2FnZShkZXZpY2UsIG1lc3NhZ2UpO1xuXG4gICAgICBjb25zdCByYXdCdWZmZXIgPSByYXdNZXNzYWdlLnBsYWluVGV4dEJ1ZmZlcjtcbiAgICAgIGNvbnN0IHJhd0J1ZmZlckpTT04gPSBKU09OLnN0cmluZ2lmeShyYXdCdWZmZXIpO1xuICAgICAgY29uc3QgbWVzc2FnZUJ1ZmZlckpTT04gPSBKU09OLnN0cmluZ2lmeShtZXNzYWdlLnBsYWluVGV4dEJ1ZmZlcigpKTtcblxuICAgICAgZXhwZWN0KHJhd0J1ZmZlciBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpLnRvLmVxdWFsKFxuICAgICAgICB0cnVlLFxuICAgICAgICAncmF3IG1lc3NhZ2UgZGlkIG5vdCBjb250YWluIGEgcGxhaW5UZXh0QnVmZmVyJ1xuICAgICAgKTtcbiAgICAgIGV4cGVjdChyYXdCdWZmZXJKU09OKS50by5lcXVhbChcbiAgICAgICAgbWVzc2FnZUJ1ZmZlckpTT04sXG4gICAgICAgICdwbGFpblRleHRCdWZmZXIgd2FzIG5vdCBjb252ZXJ0ZWQgY29ycmVjdGx5J1xuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgbWFpbnRhaW4gcHVia2V5JywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgZGV2aWNlID0gVGVzdFV0aWxzLmdlbmVyYXRlRmFrZVB1YktleSgpO1xuICAgICAgY29uc3QgbWVzc2FnZSA9IFRlc3RVdGlscy5nZW5lcmF0ZVZpc2libGVNZXNzYWdlKCk7XG5cbiAgICAgIGNvbnN0IHJhd01lc3NhZ2UgPSBhd2FpdCBNZXNzYWdlVXRpbHMudG9SYXdNZXNzYWdlKGRldmljZSwgbWVzc2FnZSk7XG4gICAgICBjb25zdCBkZXJpdmVkUHViS2V5ID0gUHViS2V5LmZyb20ocmF3TWVzc2FnZS5kZXZpY2UpO1xuXG4gICAgICBleHBlY3QoZGVyaXZlZFB1YktleSkudG8uZXhpc3Q7XG4gICAgICBleHBlY3QoZGVyaXZlZFB1YktleT8uaXNFcXVhbChkZXZpY2UpKS50by5lcXVhbChcbiAgICAgICAgdHJ1ZSxcbiAgICAgICAgJ3B1YmtleSBvZiBtZXNzYWdlIHdhcyBub3QgY29udmVydGVkIGNvcnJlY3RseSdcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHNldCBlbmNyeXB0aW9uIHRvIENsb3NlZEdyb3VwIGlmIGEgQ2xvc2VkR3JvdXBWaXNpYmxlTWVzc2FnZSBpcyBwYXNzZWQgaW4nLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBkZXZpY2UgPSBUZXN0VXRpbHMuZ2VuZXJhdGVGYWtlUHViS2V5KCk7XG4gICAgICBjb25zdCBncm91cElkID0gVGVzdFV0aWxzLmdlbmVyYXRlRmFrZVB1YktleSgpO1xuICAgICAgY29uc3QgY2hhdE1lc3NhZ2UgPSBUZXN0VXRpbHMuZ2VuZXJhdGVWaXNpYmxlTWVzc2FnZSgpO1xuICAgICAgY29uc3QgbWVzc2FnZSA9IG5ldyBDbG9zZWRHcm91cFZpc2libGVNZXNzYWdlKHsgY2hhdE1lc3NhZ2UsIGdyb3VwSWQgfSk7XG5cbiAgICAgIGNvbnN0IHJhd01lc3NhZ2UgPSBhd2FpdCBNZXNzYWdlVXRpbHMudG9SYXdNZXNzYWdlKGRldmljZSwgbWVzc2FnZSk7XG4gICAgICBleHBlY3QocmF3TWVzc2FnZS5lbmNyeXB0aW9uKS50by5lcXVhbChFbmNyeXB0aW9uVHlwZS5DbG9zZWRHcm91cCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHNldCBlbmNyeXB0aW9uIHRvIEZhbGxiYWNrIG9uIG90aGVyIG1lc3NhZ2VzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgZGV2aWNlID0gVGVzdFV0aWxzLmdlbmVyYXRlRmFrZVB1YktleSgpO1xuICAgICAgY29uc3QgbWVzc2FnZSA9IFRlc3RVdGlscy5nZW5lcmF0ZVZpc2libGVNZXNzYWdlKCk7XG4gICAgICBjb25zdCByYXdNZXNzYWdlID0gYXdhaXQgTWVzc2FnZVV0aWxzLnRvUmF3TWVzc2FnZShkZXZpY2UsIG1lc3NhZ2UpO1xuXG4gICAgICBleHBlY3QocmF3TWVzc2FnZS5lbmNyeXB0aW9uKS50by5lcXVhbChFbmNyeXB0aW9uVHlwZS5GYWxsYmFjayk7XG4gICAgfSk7XG5cbiAgICBpdCgncGFzc2luZyBDbG9zZWRHcm91cE5ld01lc3NhZ2UgcmV0dXJucyBGYWxsYmFjaycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGRldmljZSA9IFRlc3RVdGlscy5nZW5lcmF0ZUZha2VQdWJLZXkoKTtcbiAgICAgIGNvbnN0IG1lbWJlciA9IFRlc3RVdGlscy5nZW5lcmF0ZUZha2VQdWJLZXkoKS5rZXk7XG5cbiAgICAgIGNvbnN0IG1zZyA9IG5ldyBDbG9zZWRHcm91cE5ld01lc3NhZ2Uoe1xuICAgICAgICB0aW1lc3RhbXA6IERhdGUubm93KCksXG4gICAgICAgIG5hbWU6ICdkZicsXG4gICAgICAgIG1lbWJlcnM6IFttZW1iZXJdLFxuICAgICAgICBhZG1pbnM6IFttZW1iZXJdLFxuICAgICAgICBncm91cElkOiBUZXN0VXRpbHMuZ2VuZXJhdGVGYWtlUHViS2V5KCkua2V5LFxuICAgICAgICBrZXlwYWlyOiBUZXN0VXRpbHMuZ2VuZXJhdGVGYWtlRUNLZXlQYWlyKCksXG4gICAgICAgIGV4cGlyZVRpbWVyOiAwLFxuICAgICAgfSk7XG4gICAgICBjb25zdCByYXdNZXNzYWdlID0gYXdhaXQgTWVzc2FnZVV0aWxzLnRvUmF3TWVzc2FnZShkZXZpY2UsIG1zZyk7XG4gICAgICBleHBlY3QocmF3TWVzc2FnZS5lbmNyeXB0aW9uKS50by5lcXVhbChFbmNyeXB0aW9uVHlwZS5GYWxsYmFjayk7XG4gICAgfSk7XG5cbiAgICBpdCgncGFzc2luZyBDbG9zZWRHcm91cE5hbWVDaGFuZ2VNZXNzYWdlIHJldHVybnMgQ2xvc2VkR3JvdXAnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBkZXZpY2UgPSBUZXN0VXRpbHMuZ2VuZXJhdGVGYWtlUHViS2V5KCk7XG5cbiAgICAgIGNvbnN0IG1zZyA9IG5ldyBDbG9zZWRHcm91cE5hbWVDaGFuZ2VNZXNzYWdlKHtcbiAgICAgICAgdGltZXN0YW1wOiBEYXRlLm5vdygpLFxuICAgICAgICBuYW1lOiAnZGYnLFxuICAgICAgICBncm91cElkOiBUZXN0VXRpbHMuZ2VuZXJhdGVGYWtlUHViS2V5KCkua2V5LFxuICAgICAgfSk7XG4gICAgICBjb25zdCByYXdNZXNzYWdlID0gYXdhaXQgTWVzc2FnZVV0aWxzLnRvUmF3TWVzc2FnZShkZXZpY2UsIG1zZyk7XG4gICAgICBleHBlY3QocmF3TWVzc2FnZS5lbmNyeXB0aW9uKS50by5lcXVhbChFbmNyeXB0aW9uVHlwZS5DbG9zZWRHcm91cCk7XG4gICAgfSk7XG5cbiAgICBpdCgncGFzc2luZyBDbG9zZWRHcm91cEFkZGVkTWVtYmVyc01lc3NhZ2UgcmV0dXJucyBDbG9zZWRHcm91cCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGRldmljZSA9IFRlc3RVdGlscy5nZW5lcmF0ZUZha2VQdWJLZXkoKTtcblxuICAgICAgY29uc3QgbXNnID0gbmV3IENsb3NlZEdyb3VwQWRkZWRNZW1iZXJzTWVzc2FnZSh7XG4gICAgICAgIHRpbWVzdGFtcDogRGF0ZS5ub3coKSxcbiAgICAgICAgYWRkZWRNZW1iZXJzOiBbVGVzdFV0aWxzLmdlbmVyYXRlRmFrZVB1YktleSgpLmtleV0sXG4gICAgICAgIGdyb3VwSWQ6IFRlc3RVdGlscy5nZW5lcmF0ZUZha2VQdWJLZXkoKS5rZXksXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IHJhd01lc3NhZ2UgPSBhd2FpdCBNZXNzYWdlVXRpbHMudG9SYXdNZXNzYWdlKGRldmljZSwgbXNnKTtcbiAgICAgIGV4cGVjdChyYXdNZXNzYWdlLmVuY3J5cHRpb24pLnRvLmVxdWFsKEVuY3J5cHRpb25UeXBlLkNsb3NlZEdyb3VwKTtcbiAgICB9KTtcblxuICAgIGl0KCdwYXNzaW5nIENsb3NlZEdyb3VwUmVtb3ZlZE1lbWJlcnNNZXNzYWdlIHJldHVybnMgQ2xvc2VkR3JvdXAnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBkZXZpY2UgPSBUZXN0VXRpbHMuZ2VuZXJhdGVGYWtlUHViS2V5KCk7XG5cbiAgICAgIGNvbnN0IG1zZyA9IG5ldyBDbG9zZWRHcm91cFJlbW92ZWRNZW1iZXJzTWVzc2FnZSh7XG4gICAgICAgIHRpbWVzdGFtcDogRGF0ZS5ub3coKSxcbiAgICAgICAgcmVtb3ZlZE1lbWJlcnM6IFtUZXN0VXRpbHMuZ2VuZXJhdGVGYWtlUHViS2V5KCkua2V5XSxcbiAgICAgICAgZ3JvdXBJZDogVGVzdFV0aWxzLmdlbmVyYXRlRmFrZVB1YktleSgpLmtleSxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgcmF3TWVzc2FnZSA9IGF3YWl0IE1lc3NhZ2VVdGlscy50b1Jhd01lc3NhZ2UoZGV2aWNlLCBtc2cpO1xuICAgICAgZXhwZWN0KHJhd01lc3NhZ2UuZW5jcnlwdGlvbikudG8uZXF1YWwoRW5jcnlwdGlvblR5cGUuQ2xvc2VkR3JvdXApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Bhc3NpbmcgQ2xvc2VkR3JvdXBFbmNyeXB0aW9uUGFpck1lc3NhZ2UgcmV0dXJucyBDbG9zZWRHcm91cCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGRldmljZSA9IFRlc3RVdGlscy5nZW5lcmF0ZUZha2VQdWJLZXkoKTtcblxuICAgICAgY29uc3QgZmFrZVdyYXBwZXJzID0gbmV3IEFycmF5PFxuICAgICAgICBTaWduYWxTZXJ2aWNlLkRhdGFNZXNzYWdlLkNsb3NlZEdyb3VwQ29udHJvbE1lc3NhZ2UuS2V5UGFpcldyYXBwZXJcbiAgICAgID4oKTtcbiAgICAgIGZha2VXcmFwcGVycy5wdXNoKFxuICAgICAgICBuZXcgU2lnbmFsU2VydmljZS5EYXRhTWVzc2FnZS5DbG9zZWRHcm91cENvbnRyb2xNZXNzYWdlLktleVBhaXJXcmFwcGVyKHtcbiAgICAgICAgICBwdWJsaWNLZXk6IG5ldyBVaW50OEFycmF5KDgpLFxuICAgICAgICAgIGVuY3J5cHRlZEtleVBhaXI6IG5ldyBVaW50OEFycmF5KDgpLFxuICAgICAgICB9KVxuICAgICAgKTtcbiAgICAgIGNvbnN0IG1zZyA9IG5ldyBDbG9zZWRHcm91cEVuY3J5cHRpb25QYWlyTWVzc2FnZSh7XG4gICAgICAgIHRpbWVzdGFtcDogRGF0ZS5ub3coKSxcbiAgICAgICAgZ3JvdXBJZDogVGVzdFV0aWxzLmdlbmVyYXRlRmFrZVB1YktleSgpLmtleSxcbiAgICAgICAgZW5jcnlwdGVkS2V5UGFpcnM6IGZha2VXcmFwcGVycyxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgcmF3TWVzc2FnZSA9IGF3YWl0IE1lc3NhZ2VVdGlscy50b1Jhd01lc3NhZ2UoZGV2aWNlLCBtc2cpO1xuICAgICAgZXhwZWN0KHJhd01lc3NhZ2UuZW5jcnlwdGlvbikudG8uZXF1YWwoRW5jcnlwdGlvblR5cGUuQ2xvc2VkR3JvdXApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Bhc3NpbmcgQ2xvc2VkR3JvdXBFbmNyeXB0aW9uS2V5UGFpclJlcGx5IHJldHVybnMgRmFsbGJhY2snLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBkZXZpY2UgPSBUZXN0VXRpbHMuZ2VuZXJhdGVGYWtlUHViS2V5KCk7XG5cbiAgICAgIGNvbnN0IGZha2VXcmFwcGVycyA9IG5ldyBBcnJheTxcbiAgICAgICAgU2lnbmFsU2VydmljZS5EYXRhTWVzc2FnZS5DbG9zZWRHcm91cENvbnRyb2xNZXNzYWdlLktleVBhaXJXcmFwcGVyXG4gICAgICA+KCk7XG4gICAgICBmYWtlV3JhcHBlcnMucHVzaChcbiAgICAgICAgbmV3IFNpZ25hbFNlcnZpY2UuRGF0YU1lc3NhZ2UuQ2xvc2VkR3JvdXBDb250cm9sTWVzc2FnZS5LZXlQYWlyV3JhcHBlcih7XG4gICAgICAgICAgcHVibGljS2V5OiBuZXcgVWludDhBcnJheSg4KSxcbiAgICAgICAgICBlbmNyeXB0ZWRLZXlQYWlyOiBuZXcgVWludDhBcnJheSg4KSxcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgICBjb25zdCBtc2cgPSBuZXcgQ2xvc2VkR3JvdXBFbmNyeXB0aW9uUGFpclJlcGx5TWVzc2FnZSh7XG4gICAgICAgIHRpbWVzdGFtcDogRGF0ZS5ub3coKSxcbiAgICAgICAgZ3JvdXBJZDogVGVzdFV0aWxzLmdlbmVyYXRlRmFrZVB1YktleSgpLmtleSxcbiAgICAgICAgZW5jcnlwdGVkS2V5UGFpcnM6IGZha2VXcmFwcGVycyxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgcmF3TWVzc2FnZSA9IGF3YWl0IE1lc3NhZ2VVdGlscy50b1Jhd01lc3NhZ2UoZGV2aWNlLCBtc2cpO1xuICAgICAgZXhwZWN0KHJhd01lc3NhZ2UuZW5jcnlwdGlvbikudG8uZXF1YWwoRW5jcnlwdGlvblR5cGUuRmFsbGJhY2spO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Bhc3NpbmcgYSBDb25maWd1cmF0aW9uTWVzc2FnZSByZXR1cm5zIEZhbGxiYWNrJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgZGV2aWNlID0gVGVzdFV0aWxzLmdlbmVyYXRlRmFrZVB1YktleSgpO1xuXG4gICAgICBjb25zdCBtc2cgPSBuZXcgQ29uZmlndXJhdGlvbk1lc3NhZ2Uoe1xuICAgICAgICB0aW1lc3RhbXA6IERhdGUubm93KCksXG4gICAgICAgIGFjdGl2ZU9wZW5Hcm91cHM6IFtdLFxuICAgICAgICBhY3RpdmVDbG9zZWRHcm91cHM6IFtdLFxuICAgICAgICBkaXNwbGF5TmFtZTogJ2Rpc3BsYXlOYW1lJyxcbiAgICAgICAgY29udGFjdHM6IFtdLFxuICAgICAgfSk7XG4gICAgICBjb25zdCByYXdNZXNzYWdlID0gYXdhaXQgTWVzc2FnZVV0aWxzLnRvUmF3TWVzc2FnZShkZXZpY2UsIG1zZyk7XG4gICAgICBleHBlY3QocmF3TWVzc2FnZS5lbmNyeXB0aW9uKS50by5lcXVhbChFbmNyeXB0aW9uVHlwZS5GYWxsYmFjayk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdnZXRDdXJyZW50Q29uZmlndXJhdGlvbk1lc3NhZ2UnLCAoKSA9PiB7XG4gICAgY29uc3Qgb3VyTnVtYmVyID0gVGVzdFV0aWxzLmdlbmVyYXRlRmFrZVB1YktleSgpLmtleTtcblxuICAgIC8vIGxldCBjb252b3M6IEFycmF5PENvbnZlcnNhdGlvbk1vZGVsPjtcbiAgICAvLyBjb25zdCBtb2NrVmFsaWRPcGVuR3JvdXAgPSBuZXcgTW9ja0NvbnZlcnNhdGlvbih7XG4gICAgLy8gICB0eXBlOiBDb252ZXJzYXRpb25UeXBlRW51bS5HUk9VUCxcbiAgICAvLyAgIGlkOiBgJHtvcGVuR3JvdXBQcmVmaXh9MUBjaGF0LWRldi5sb2tpbmV0Lm9yZ2AsXG4gICAgLy8gfSk7XG5cbiAgICAvLyBjb25zdCBtb2NrVmFsaWRPcGVuR3JvdXAyID0gbmV3IE1vY2tDb252ZXJzYXRpb24oe1xuICAgIC8vICAgdHlwZTogQ29udmVyc2F0aW9uVHlwZUVudW0uR1JPVVAsXG4gICAgLy8gICBpZDogYCR7b3Blbkdyb3VwUHJlZml4fTFAY2hhdC1kZXYyLmxva2luZXQub3JnYCxcbiAgICAvLyB9KTtcblxuICAgIC8vIGNvbnN0IG1vY2tWYWxpZENsb3NlZEdyb3VwID0gbmV3IE1vY2tDb252ZXJzYXRpb24oe1xuICAgIC8vICAgdHlwZTogQ29udmVyc2F0aW9uVHlwZUVudW0uR1JPVVAsXG4gICAgLy8gfSk7XG5cbiAgICAvLyBjb25zdCBtb2NrVmFsaWRQcml2YXRlID0ge1xuICAgIC8vICAgaWQ6IFRlc3RVdGlscy5nZW5lcmF0ZUZha2VQdWJLZXkoKSxcbiAgICAvLyAgIGlzTWVkaXVtR3JvdXA6ICgpID0+IGZhbHNlLFxuICAgIC8vICAgaXNQdWJsaWM6ICgpID0+IGZhbHNlLFxuICAgIC8vIH07XG5cbiAgICBiZWZvcmVFYWNoKCgpID0+IHtcbiAgICAgIC8vIGNvbnZvcyA9IFtdO1xuICAgICAgc2FuZGJveC5zdHViKFVzZXJVdGlscywgJ2dldE91clB1YktleVN0ckZyb21DYWNoZScpLnJlc29sdmVzKG91ck51bWJlcik7XG4gICAgICBzYW5kYm94LnN0dWIoVXNlclV0aWxzLCAnZ2V0T3VyUHViS2V5RnJvbUNhY2hlJykucmVzb2x2ZXMoUHViS2V5LmNhc3Qob3VyTnVtYmVyKSk7XG4gICAgfSk7XG5cbiAgICBiZWZvcmVFYWNoKCgpID0+IHtcbiAgICAgIC8vIGNvbnZvcyA9IFtdO1xuICAgICAgc2FuZGJveC5yZXN0b3JlKCk7XG4gICAgfSk7XG5cbiAgICAvLyBpdCgnZmlsdGVyIG91dCBub24gYWN0aXZlIG9wZW4gZ3JvdXBzJywgYXN5bmMgKCkgPT4ge1xuICAgIC8vICAgLy8gb3ZlcnJpZGUgdGhlIGZpcnN0IG9wZW4gZ3JvdXAgYW5kIG1ha2UgaXQgaW5hY3RpdmVcbiAgICAvLyAgIChtb2NrVmFsaWRPcGVuR3JvdXAgYXMgYW55KS5hdHRyaWJ1dGVzLmFjdGl2ZV9hdCA9IHVuZGVmaW5lZDtcblxuICAgIC8vICAgY29udm9zLnB1c2goXG4gICAgLy8gICAgIG1vY2tWYWxpZE9wZW5Hcm91cCBhcyBhbnksXG4gICAgLy8gICAgIG1vY2tWYWxpZE9wZW5Hcm91cCBhcyBhbnksXG4gICAgLy8gICAgIG1vY2tWYWxpZFByaXZhdGUgYXMgYW55LFxuICAgIC8vICAgICBtb2NrVmFsaWRDbG9zZWRHcm91cCBhcyBhbnksXG4gICAgLy8gICAgIG1vY2tWYWxpZE9wZW5Hcm91cDIgYXMgYW55XG4gICAgLy8gICApO1xuXG4gICAgLy8gICBjb25zdCBjb25maWdNZXNzYWdlID0gYXdhaXQgZ2V0Q3VycmVudENvbmZpZ3VyYXRpb25NZXNzYWdlKGNvbnZvcyk7XG4gICAgLy8gICBleHBlY3QoY29uZmlnTWVzc2FnZS5hY3RpdmVPcGVuR3JvdXBzLmxlbmd0aCkudG8uZXF1YWwoMSk7XG4gICAgLy8gICBleHBlY3QoY29uZmlnTWVzc2FnZS5hY3RpdmVPcGVuR3JvdXBzWzBdKS50by5lcXVhbCgnY2hhdC1kZXYyLmxva2luZXQub3JnJyk7XG4gICAgLy8gfSk7XG4gIH0pO1xufSk7XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7QUFFQSxrQkFBaUI7QUFDakIsWUFBdUI7QUFDdkIsd0JBQTBCO0FBQzFCLG1CQUF3QztBQUN4QyxtQkFBdUM7QUFDdkMsdUNBQTBDO0FBQzFDLGtDQUFxQztBQUVyQyw4QkFBMkI7QUFFM0IsbURBQXNEO0FBQ3RELHNCQUE4QjtBQUM5Qiw0Q0FBK0M7QUFDL0MsOENBQWlEO0FBQ2pELDBDQUE2QztBQUM3QyxtQ0FBc0M7QUFDdEMsOENBQWlEO0FBUGpELG9CQUFLLElBQUksK0JBQXFCO0FBUzlCLE1BQU0sRUFBRSxXQUFXO0FBRW5CLFNBQVMsaUJBQWlCLE1BQU07QUFDOUIsUUFBTSxVQUFVLE1BQU0sY0FBYztBQUVwQyxZQUFVLE1BQU07QUFDZCxZQUFRLFFBQVE7QUFBQSxFQUNsQixDQUFDO0FBR0QsV0FBUyxnQkFBZ0IsTUFBTTtBQUM3QixPQUFHLDhCQUE4QixZQUFZO0FBQzNDLFlBQU0sU0FBUyw0QkFBVSxtQkFBbUI7QUFDNUMsWUFBTSxVQUFVLDRCQUFVLHVCQUF1QjtBQUVqRCxZQUFNLGFBQWEsTUFBTSwwQkFBYSxhQUFhLFFBQVEsT0FBTztBQUVsRSxhQUFPLE9BQU8sS0FBSyxVQUFVLENBQUMsRUFBRSxHQUFHLEtBQUssT0FBTyxDQUFDO0FBQ2hELGFBQU8sV0FBVyxVQUFVLEVBQUUsR0FBRztBQUNqQyxhQUFPLFdBQVcsTUFBTSxFQUFFLEdBQUc7QUFDN0IsYUFBTyxXQUFXLFVBQVUsRUFBRSxHQUFHO0FBQ2pDLGFBQU8sV0FBVyxlQUFlLEVBQUUsR0FBRztBQUN0QyxhQUFPLFdBQVcsR0FBRyxFQUFFLEdBQUc7QUFFMUIsYUFBTyxXQUFXLFVBQVUsRUFBRSxHQUFHLE1BQU0sUUFBUSxVQUFVO0FBQ3pELGFBQU8sV0FBVyxNQUFNLEVBQUUs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
|