@iotize/ionic
Version:
Iotize specific building blocks on top of @ionic/angular.
599 lines • 69.6 kB
JavaScript
import { Validators } from '@angular/forms';
import { bufferToHexString, hexStringToBuffer, } from '@iotize/common/byte-converter';
import { FACTORY_RESET_MODE_VERSION, TapInfo, TAP_MANAGER_APP_ID, } from '@iotize/ionic';
import { HostProtocol, SpecialFeature, TapResponse, TargetProtocol, } from '@iotize/tap';
import { converters } from '@iotize/tap/service/core';
import { NfcConnectionPriority, NfcPairingMode, } from '@iotize/tap/service/impl/interface';
import { WifiKeyVisibility, WifiMode, WifiSSIDVisibility, } from '@iotize/tap/service/impl/wifi';
import { combineLatest } from 'rxjs';
import { map } from 'rxjs/operators';
import { enumToOptions } from './utility';
import { interfaceServiceGetAppPathResolved } from '@iotize/ionic';
const TAP_CONFIG_PATTERN = /^([0-9]+)\.([0-9]+)\.([0-9]+)$/;
const IPV4_PATTERN = /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/;
const IPV4_MASK_PATTERN = /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/;
const SSID_PATTERN = /^[^ !#;+\]\/"\t][^+\]\/"\t]{0,30}[^ !#;+\]\/"\t]$|^[^ !#;+\]\/"\t]$/;
function regexValidator(pattern, message) {
return (control) => {
const value = control.value;
const valueMatchPattern = pattern.test(value);
return !valueMatchPattern
? { invalidFormat: { value: control.value, message } }
: null;
};
}
const validateTapVersion = regexValidator(TAP_CONFIG_PATTERN, `Must be a valid semantic version (Major.Minor.Patch).`);
function enumFormatter(data) {
return (value) => {
if (Array.isArray(value)) {
if (value.length === 0) {
return '-';
}
return value.map((key) => HostProtocol[key]).join(', ');
}
else {
return data[value];
}
};
}
export function isTapConfigured(version) {
return !(version.major === 0 && version.minor === 0 && version.patch === 0);
}
function stringToEnumArray(v, mapping) {
return v
.split(',')
.map((item) => item.trim())
.map((item) => {
if (!(item in mapping)) {
throw new Error(`Invalid value "${item}". Must one of the following: ${Object.keys(mapping).join(', ')}`);
}
return mapping[item];
});
}
var WifiTxPowerEnum;
(function (WifiTxPowerEnum) {
WifiTxPowerEnum[WifiTxPowerEnum["default"] = 0] = "default";
WifiTxPowerEnum[WifiTxPowerEnum["10 dBm"] = 40] = "10 dBm";
WifiTxPowerEnum[WifiTxPowerEnum["12.5 dBm"] = 50] = "12.5 dBm";
WifiTxPowerEnum[WifiTxPowerEnum["15 dBm"] = 60] = "15 dBm";
WifiTxPowerEnum[WifiTxPowerEnum["17.5 dBm"] = 70] = "17.5 dBm";
WifiTxPowerEnum[WifiTxPowerEnum["20 dBm"] = 80] = "20 dBm";
})(WifiTxPowerEnum || (WifiTxPowerEnum = {}));
const IPV4_VALIDATOR = regexValidator(IPV4_PATTERN, `Not a valid IPv4 address (eg 192.168.20.1)`);
export const defaultInfoResolverConfig = [
{
key: TapInfo.HostProtocol,
input: createEnumField('HostProtocol', HostProtocol),
viewFormatter: enumFormatter(HostProtocol),
},
{
key: TapInfo.configVersion,
input: {
formValidators: [validateTapVersion],
},
viewFormatter: (v) => {
if (v === FACTORY_RESET_MODE_VERSION) {
return 'FACTORY RESET';
}
else if (v === '255.255.65535') {
return 'CONFIGURATION MODE';
}
else if (v) {
return `v${v}`;
}
else {
return 'UNKNOWN';
}
},
editFormatter: {
read: (input) => {
return input;
},
write: (v) => {
return v || FACTORY_RESET_MODE_VERSION;
},
},
},
{
key: TapInfo.CloudEndpoint,
getValue: async (tap) => {
const hostname = (await tap.service.mqtt.getBrokerHostname()).body();
const port = (await tap.service.mqtt.getBrokerPort()).body();
return `${hostname}:${port}`;
},
putValue: async (tap, value) => {
const [hostname, port] = value.split(':');
const setPort = await tap.service.mqtt.putBrokerPort(port || '1883');
setPort.successful();
return tap.service.mqtt.putBrokerHostname(hostname);
},
},
{
key: TapInfo.TargetProtocolConfiguration,
viewFormatter: (v) => `${bufferToHexString(v)}`,
editFormatter: {
read: (input) => {
return input ? hexStringToBuffer(input) : new Uint8Array();
},
write: (v) => {
return v ? bufferToHexString(v) : '';
},
},
getValue: async (tap) => {
const result = await tap.service.target.getModbusTcpConfiguration();
result.successful();
return result.rawBody();
},
putValue: async (tap, value) => {
return await tap.lwm2m.put('/1027//21', value);
},
},
{
input: {
type: 'toggle',
},
key: TapInfo.NFCConnectionPriority,
getValue: async (tap) => {
const value = (await tap.service.interface.getNfcConnectionPriority()).body();
return value === NfcConnectionPriority.NFC_PRIORITY;
},
putValue: (tap, val) => {
const mode = val
? NfcConnectionPriority.NFC_NON_PRIORITY
: NfcConnectionPriority.NFC_PRIORITY;
return tap.service.interface.putNfcConnectionPriority(mode);
},
},
{
key: TapInfo.NFCPairingMode,
input: createEnumField('NfcPairingMode', NfcPairingMode),
},
{
key: TapInfo.DataLogMaxPacketCount,
viewFormatter: (v) => {
return v === 0 ? 'NO LIMIT' : v.toString();
},
input: {
type: 'number',
},
},
{
key: TapInfo.IsTargetConnected,
// viewFormatter: (v: boolean) => v ? 'YES' : 'NO',
getValue: (tap) => tap.service.target.isConnected(),
putValue: (tap, enabled) => {
if (enabled) {
return tap.service.target.connect();
}
else {
return tap.service.target.disconnect();
}
},
input: {
type: 'toggle',
},
},
{
key: TapInfo.universalLink,
icon: 'link',
},
{
key: TapInfo.androidApplicationRecord,
// TODO replace with getAndroidApplicationId()
getValue: async (tap) => {
const appPath = (await tap.service.interface.getAppPath()).body();
if (appPath.startsWith('$4/')) {
return appPath.substring(3);
}
else {
return TAP_MANAGER_APP_ID;
}
},
viewFormatter: (input) => {
if (input === TAP_MANAGER_APP_ID) {
return `${input} (Tap Manager)`;
}
return input;
},
putValue: async (tap, value) => {
return tap.service.interface.putAppPath(`$4/${value}`);
},
},
{
key: TapInfo.useEncryption,
input: {
type: 'toggle',
},
editable: false,
getValue: async (tap) => {
const lockOptions = (await tap.service.interface.getSecurityOptions()).body();
return lockOptions.scramActivated;
},
},
{
key: TapInfo.lockFactoryReset,
input: {
type: 'toggle',
},
editable: false,
getValue: async (tap) => {
const lockOptions = (await tap.service.interface.getSecurityOptions()).body();
return !lockOptions.disableHardwareFactoryReset;
},
},
{
key: TapInfo.InterfaceSecurityScramActivated,
input: {
type: 'toggle',
},
editable: false,
getValue: async (tap) => {
const lockOptions = (await tap.service.interface.getSecurityOptions()).body();
return lockOptions.scramActivated;
},
},
{
key: TapInfo.InterfaceSecurityDisableHardwareFactoryReset,
input: {
type: 'toggle',
},
editable: false,
getValue: async (tap) => {
const lockOptions = (await tap.service.interface.getSecurityOptions()).body();
return lockOptions.disableHardwareFactoryReset;
},
},
{
key: TapInfo.InterfaceSecurityDisabledResourceFactoryReset,
input: {
type: 'toggle',
},
editable: false,
getValue: async (tap) => {
const lockOptions = (await tap.service.interface.getSecurityOptions()).body();
return lockOptions.disableResourceFactoryReset;
},
},
{
key: TapInfo.InterfaceSecurityDisabledLoginWithUID,
input: {
type: 'toggle',
},
editable: false,
getValue: async (tap) => {
const lockOptions = (await tap.service.interface.getSecurityOptions()).body();
return lockOptions.disableLoginWithUID;
},
},
{
key: TapInfo.hashPassword,
input: {
type: 'toggle',
},
editable: false,
getValue: async (tap) => {
const lockOptions = (await tap.service.interface.getSecurityOptions()).body();
return lockOptions.hashPassword;
},
},
{
key: TapInfo.isLoginWithUIDEnabled,
input: {
type: 'toggle',
},
editable: false,
getValue: async (tap) => {
const lockOptions = (await tap.service.interface.getSecurityOptions()).body();
return !lockOptions.disableLoginWithUID;
},
},
{
key: TapInfo.isLWM2MFactoryResetEnabled,
input: {
type: 'toggle',
},
editable: false,
getValue: async (tap) => {
const lockOptions = (await tap.service.interface.getSecurityOptions()).body();
return !lockOptions.disableResourceFactoryReset;
},
},
{
key: TapInfo.appPath,
putValue: (tap, value) => {
return tap.service.interface.putAppPath(value);
},
getValue: (tap) => interfaceServiceGetAppPathResolved.call(tap.service.interface),
},
{
key: TapInfo.TargetProtocol,
getValue: (tap) => {
return tap.service.target.getProtocol();
},
putValue: (tap, protocol) => {
return tap.service.target.putProtocol(protocol);
},
setValue: (tap, protocol) => {
return tap.service.target.setProtocol(protocol);
},
viewFormatter: enumFormatter(TargetProtocol),
input: {
type: 'select',
options: enumToOptions(TargetProtocol).filter((f) => {
return f.key !== TargetProtocol.JTAG;
}),
},
},
{
key: '/interface/available-host-protocols',
viewFormatter: enumFormatter(HostProtocol),
editFormatter: {
write: (v) => {
// console.log('Host protocols: ', v);
if (!v || v.length === 0) {
return 'NONE';
}
return v.map((key) => HostProtocol[key]).join(', ');
},
read: (v) => {
return stringToEnumArray(v, HostProtocol);
},
},
},
{
key: TapInfo.authorizedHostProtocols,
input: {
type: 'select',
multiple: true,
options: [],
},
viewFormatter: enumFormatter(HostProtocol),
init: async (_service, config, infoResolver) => {
const hostProtocols = await infoResolver.getValue(TapInfo.availableHostProtocols);
if (config.input !== undefined) {
config.input.options = hostProtocols.map((key) => {
return { key: key, text: HostProtocol[key] };
});
}
},
},
{
key: TapInfo.AdpVersion,
getValue: (tap) => tap.service.tapnpass.getStatus(),
viewFormatter: (stats) => {
const v = stats.header.version;
return `${v.major}.${v.minor}.${v.patch}`;
},
},
{
key: TapInfo.WifiHostname,
viewFormatter: (v) => {
if (v === '0.0.0.0') {
return 'NO IP';
}
return v;
},
},
{
key: TapInfo.WifiSSID,
input: {
formValidators: [
regexValidator(SSID_PATTERN, `This is not a valid SSID. It can be any alphanumeric, case-sensitive entry from 1 to 32 characters. Trailing or leading spaces are not allowed.`),
],
},
},
{
key: TapInfo.WifiSSIDVisibility,
input: createEnumField('WifiSSIDVisibility', WifiSSIDVisibility),
viewFormatter: enumFormatter(WifiSSIDVisibility),
},
{
key: TapInfo.WifiKeyVisibility,
input: createEnumField('WifiKeyVisibility', WifiKeyVisibility),
viewFormatter: enumFormatter(WifiKeyVisibility),
},
{
key: TapInfo.WifiTxPower,
viewFormatter: enumFormatter(WifiTxPowerEnum),
input: createEnumField('WifiTxPowerEnum', WifiTxPowerEnum),
},
{
key: TapInfo.NetworkInfraIp,
input: {
formValidators: [IPV4_VALIDATOR],
},
viewFormatter: (value) => {
if (value === '0.0.0.0') {
return 'Dynamic (DHCP)';
}
return value;
},
},
{
key: TapInfo.NetworkIpMask,
input: {
formValidators: [
regexValidator(IPV4_MASK_PATTERN, `Not a valid IPv4 mask (eg 192.168.20.1)`),
],
},
isDisplayed: ({ tapConfigItemStateService }) => {
return combineLatest([
tapConfigItemStateService.valueChange(TapInfo.WifiMode),
tapConfigItemStateService.valueChange(TapInfo.NetworkInfraIp),
]).pipe(map(([mode, ip]) => {
return mode === WifiMode.NETWORK && ip !== '0.0.0.0';
}));
},
},
{
key: TapInfo.NetworkGatewayIp,
input: {
formValidators: [IPV4_VALIDATOR],
},
isDisplayed: ({ tapConfigItemStateService }) => {
return combineLatest([
tapConfigItemStateService.valueChange(TapInfo.WifiMode),
tapConfigItemStateService.valueChange(TapInfo.NetworkInfraIp),
]).pipe(map(([mode, ip]) => {
return mode === WifiMode.NETWORK && ip !== '0.0.0.0';
}));
},
},
{
key: TapInfo.NetworkDNSIp,
input: {
formValidators: [IPV4_VALIDATOR],
},
isDisplayed: ({ tapConfigItemStateService }) => {
return combineLatest([
tapConfigItemStateService.valueChange(TapInfo.WifiMode),
tapConfigItemStateService.valueChange(TapInfo.NetworkInfraIp),
]).pipe(map(([mode, ip]) => {
return mode === WifiMode.NETWORK && ip !== '0.0.0.0';
}));
},
},
{
key: TapInfo.WifiMode,
input: createEnumField('WifiMode', WifiMode),
},
{
key: TapInfo.isHostProtocolAuthorized,
input: {
type: 'toggle',
},
getValue: async (tap, protocol) => {
if (protocol === undefined) {
throw new Error('Illegal argument error: missing protocol');
}
const protocols = (await tap.service.interface.getAuthorizedHostProtocol()).body();
return protocols.find((p) => p === protocol) !== undefined;
},
putValue: async (tap, value, protocol) => {
const protocols = (await tap.service.interface.getAuthorizedHostProtocol()).body();
if (protocol === undefined) {
throw new Error('Illegal argument error: missing protocol');
}
const indexOfProtocol = protocols.findIndex((p) => p === protocol);
if (value) {
if (indexOfProtocol === -1) {
protocols.push(protocol);
}
}
else {
if (indexOfProtocol >= 0) {
protocols.splice(indexOfProtocol, 1);
}
}
return tap.service.interface.putAuthorizedHostProtocol(protocols);
},
},
{
key: TapInfo.WifiKey,
input: {
type: 'password',
formValidators: [Validators.minLength(8), Validators.maxLength(128)],
},
},
{
key: TapInfo.variableMetaData,
input: {},
getValue: async (tap, variableId) => {
const metaData = (await tap.service.variable.getRawMeta(variableId)).body();
return converters.ascii.decode(metaData);
},
putValue: (tap, value, bundleId) => {
const data = converters.ascii.encode(value);
return tap.service.variable.putRawMeta(bundleId, data);
},
},
{
key: TapInfo.profilePassword,
input: {
type: 'password',
formValidators: [Validators.minLength(1), Validators.maxLength(16)],
},
viewFormatter: () => {
return '********';
},
putValue: async (tap, value, profileId) => {
await tap.auth.changePassword(value, profileId);
return TapResponse.SUCCESS();
},
},
{
key: TapInfo.DeviceMemoryFree,
viewFormatter(value) {
return Math.floor((value / 1024) * 100) / 100 + ' KB';
},
},
{
key: TapInfo.TimeLocalTime,
viewFormatter(localTime) {
if (!localTime) {
return '';
}
const date = new Date(Date.UTC(localTime.year, 0, localTime.dayOfYear));
date.setHours(localTime.hours);
date.setMinutes(localTime.minutes);
date.setSeconds(localTime.seconds);
// {"seconds":54,"minutes":3,"hours":8,"dayOfMonth":8,"month":8,"year":122,"dayOfWeek":4,"dayOfYear":250,"isdst":0}
return `${date.toUTCString()}`;
},
},
{
key: TapInfo.InterfaceSpecialFeatureSWDDirect,
...createSpecialFeatureDAO(SpecialFeature.SWD_DIRECT_ACCESS),
},
{
key: TapInfo.InterfaceSpecialFeatureSerial,
...createSpecialFeatureDAO(SpecialFeature.SERIAL_ACCESS),
},
{
key: TapInfo.InterfaceSpecialFeatureModbusDirect,
...createSpecialFeatureDAO(SpecialFeature.MODBUS_DIRECT_ACCESS),
},
{
key: '/wifi/enabled',
input: {
type: 'toggle',
},
getValue: async (tap) => {
const response = await tap.service.wifi.getDisabled();
return !response.body();
},
putValue: (tap, enabled) => {
return tap.service.wifi.putDisabled(!enabled);
},
},
];
function createSpecialFeatureDAO(feature) {
return {
input: {
type: 'number',
formValidators: [Validators.min(0), Validators.max(65535)],
},
getValue: async (tap) => {
const result = (await tap.service.interface.getSpecialFeatureProfile(feature)).body();
if (result === 65535 - (feature - 100)) {
return 'UNAUTHORIZED';
}
else {
return result;
}
},
putValue: async (tap, body) => {
return await tap.service.interface.putSpecialFeatureProfile(feature, body);
},
};
}
function createEnumField(enumId, enumData) {
return {
type: 'select',
enum: {
id: enumId,
data: enumData,
},
};
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvaW90aXplLWlvbmljL2NvbmZpZy9zcmMvbGliL2NvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQWdDLFVBQVUsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzFFLE9BQU8sRUFDTCxpQkFBaUIsRUFDakIsaUJBQWlCLEdBQ2xCLE1BQU0sK0JBQStCLENBQUM7QUFDdkMsT0FBTyxFQUNMLDBCQUEwQixFQUUxQixPQUFPLEVBQ1Asa0JBQWtCLEdBQ25CLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFDTCxZQUFZLEVBQ1osY0FBYyxFQUVkLFdBQVcsRUFFWCxjQUFjLEdBQ2YsTUFBTSxhQUFhLENBQUM7QUFDckIsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3RELE9BQU8sRUFDTCxxQkFBcUIsRUFDckIsY0FBYyxHQUNmLE1BQU0sb0NBQW9DLENBQUM7QUFFNUMsT0FBTyxFQUNMLGlCQUFpQixFQUNqQixRQUFRLEVBQ1Isa0JBQWtCLEdBQ25CLE1BQU0sK0JBQStCLENBQUM7QUFDdkMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNyQyxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFckMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUMxQyxPQUFPLEVBQUUsa0NBQWtDLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFbkUsTUFBTSxrQkFBa0IsR0FBRyxnQ0FBZ0MsQ0FBQztBQUM1RCxNQUFNLFlBQVksR0FBRyxpQ0FBaUMsQ0FBQztBQUN2RCxNQUFNLGlCQUFpQixHQUFHLGlDQUFpQyxDQUFDO0FBQzVELE1BQU0sWUFBWSxHQUNoQixxRUFBcUUsQ0FBQztBQUV4RSxTQUFTLGNBQWMsQ0FBQyxPQUFlLEVBQUUsT0FBZTtJ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UUFDRCxRQUFRLEVBQUUsS0FBSyxFQUFFLEdBQVEsRUFBRSxFQUFFO1lBQzNCLE1BQU0sTUFBTSxHQUFHLENBQ2IsTUFBTSxHQUFHLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyx3QkFBd0IsQ0FBQyxPQUFPLENBQUMsQ0FDOUQsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNULElBQUksTUFBTSxLQUFLLEtBQUssR0FBRyxDQUFDLE9BQU8sR0FBRyxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUN2QyxPQUFPLGNBQWMsQ0FBQztZQUN4QixDQUFDO2lCQUFNLENBQUM7Z0JBQ04sT0FBTyxNQUFNLENBQUM7WUFDaEIsQ0FBQztRQUNILENBQUM7UUFDRCxRQUFRLEVBQUUsS0FBSyxFQUFFLEdBQVEsRUFBRSxJQUFZLEVBQUUsRUFBRTtZQUN6QyxPQUFPLE1BQU0sR0FBRyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsd0JBQXdCLENBQ3pELE9BQU8sRUFDUCxJQUFJLENBQ0wsQ0FBQztRQUNKLENBQUM7S0FDRixDQUFDO0FBQ0osQ0FBQztBQUVELFNBQVMsZUFBZSxDQUN0QixNQUFjLEVBQ2QsUUFBbUI7SUFFbkIsT0FBTztRQUNMLElBQUksRUFBRSxRQUFRO1FBQ2QsSUFBSSxFQUFFO1lBQ0osRUFBRSxFQUFFLE1BQU07WUFDVixJQUFJLEVBQUUsUUFBUTtTQUNmO0tBQ0YsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBYnN0cmFjdENvbnRyb2wsIFZhbGlkYXRvckZuLCBWYWxpZGF0b3JzIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHtcbiAgYnVmZmVyVG9IZXhTdHJpbmcsXG4gIGhleFN0cmluZ1RvQnVmZmVyLFxufSBmcm9tICdAaW90aXplL2NvbW1vbi9ieXRlLWNvbnZlcnRlcic7XG5pbXBvcnQge1xuICBGQUNUT1JZX1JFU0VUX01PREVfVkVSU0lPTixcbiAgTHdtMm1FbnVtLFxuICBUYXBJbmZvLFxuICBUQVBfTUFOQUdFUl9BUFBfSUQsXG59IGZyb20gJ0Bpb3RpemUvaW9uaWMnO1xuaW1wb3J0IHtcbiAgSG9zdFByb3RvY29sLFxuICBTcGVjaWFsRmVhdHVyZSxcbiAgVGFwLFxuICBUYXBSZXNwb25zZSxcbiAgVGFwVmVyc2lvbixcbiAgVGFyZ2V0UHJvdG9jb2wsXG59IGZyb20gJ0Bpb3RpemUvdGFwJztcbmltcG9ydCB7IGNvbnZlcnRlcnMgfSBmcm9tICdAaW90aXplL3RhcC9zZXJ2aWNlL2NvcmUnO1xuaW1wb3J0IHtcbiAgTmZjQ29ubmVjdGlvblByaW9yaXR5LFxuICBOZmNQYWlyaW5nTW9kZSxcbn0gZnJvbSAnQGlvdGl6ZS90YXAvc2VydmljZS9pbXBsL2ludGVyZmFjZSc7XG5pbXBvcnQgeyBBZHBTdGF0cyB9IGZyb20gJ0Bpb3RpemUvdGFwL3NlcnZpY2UvaW1wbC90YXBucGFzcyc7XG5pbXBvcnQge1xuICBXaWZpS2V5VmlzaWJpbGl0eSxcbiAgV2lmaU1vZGUsXG4gIFdpZmlTU0lEVmlzaWJpbGl0eSxcbn0gZnJvbSAnQGlvdGl6ZS90YXAvc2VydmljZS9pbXBsL3dpZmknO1xuaW1wb3J0IHsgY29tYmluZUxhdGVzdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgbWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgVGFwQ29uZmlnSXRlbUV4dGVuZGVkIH0gZnJvbSAnLi90YXAtY29uZmlnLWl0ZW0vdGFwLWNvbmZpZy1pdGVtLmRlZmluaXRpb24nO1xuaW1wb3J0IHsgZW51bVRvT3B0aW9ucyB9IGZyb20gJy4vdXRpbGl0eSc7XG5pbXBvcnQgeyBpbnRlcmZhY2VTZXJ2aWNlR2V0QXBwUGF0aFJlc29sdmVkIH0gZnJvbSAnQGlvdGl6ZS9pb25pYyc7XG5cbmNvbnN0IFRBUF9DT05GSUdfUEFUVEVSTiA9IC9eKFswLTldKylcXC4oWzAtOV0rKVxcLihbMC05XSspJC87XG5jb25zdCBJUFY0X1BBVFRFUk4gPSAvXig/OlswLTldezEsM31cXC4pezN9WzAtOV17MSwzfSQvO1xuY29uc3QgSVBWNF9NQVNLX1BBVFRFUk4gPSAvXig/OlswLTldezEsM31cXC4pezN9WzAtOV17MSwzfSQvO1xuY29uc3QgU1NJRF9QQVRURVJOID1cbiAgL15bXiAhIzsrXFxdXFwvXCJcXHRdW14rXFxdXFwvXCJcXHRdezAsMzB9W14gISM7K1xcXVxcL1wiXFx0XSR8XlteICEjOytcXF1cXC9cIlxcdF0kLztcblxuZnVuY3Rpb24gcmVnZXhWYWxpZGF0b3IocGF0dGVybjogUmVnRXhwLCBtZXNzYWdlOiBzdHJpbmcpOiBWYWxpZGF0b3JGbiB7XG4gIHJldHVybiAoY29udHJvbDogQWJzdHJhY3RDb250cm9sKTogeyBba2V5OiBzdHJpbmddOiBhbnkgfSB8IG51bGwgPT4ge1xuICAgIGNvbnN0IHZhbHVlID0gY29udHJvbC52YWx1ZTtcbiAgICBjb25zdCB2YWx1ZU1hdGNoUGF0dGVybiA9IHBhdHRlcm4udGVzdCh2YWx1ZSk7XG4gICAgcmV0dXJuICF2YWx1ZU1hdGNoUGF0dGVyblxuICAgICAgPyB7IGludmFsaWRGb3JtYXQ6IHsgdmFsdWU6IGNvbnRyb2wudmFsdWUsIG1lc3NhZ2UgfSB9XG4gICAgICA6IG51bGw7XG4gIH07XG59XG5cbmNvbnN0IHZhbGlkYXRlVGFwVmVyc2lvbjogVmFsaWRhdG9yRm4gPSByZWdleFZhbGlkYXRvcihcbiAgVEFQX0NPTkZJR19QQVRURVJOLFxuICBgTXVzdCBiZSBhIHZhbGlkIHNlbWFudGljIHZlcnNpb24gKE1ham9yLk1pbm9yLlBhdGNoKS5gXG4pO1xuXG5mdW5jdGlvbiBlbnVtRm9ybWF0dGVyKGRhdGE6IGFueSk6ICh2YWx1ZTogYW55KSA9PiBzdHJpbmcge1xuICByZXR1cm4gKHZhbHVlOiBhbnkpID0+IHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgIGlmICh2YWx1ZS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuICctJztcbiAgICAgIH1cbiAgICAgIHJldHVybiB2YWx1ZS5tYXAoKGtleSkgPT4gSG9zdFByb3RvY29sW2tleV0pLmpvaW4oJywgJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBkYXRhW3ZhbHVlXSBhcyBzdHJpbmc7XG4gICAgfVxuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNUYXBDb25maWd1cmVkKHZlcnNpb246IFRhcFZlcnNpb24pIHtcbiAgcmV0dXJuICEodmVyc2lvbi5tYWpvciA9PT0gMCAmJiB2ZXJzaW9uLm1pbm9yID09PSAwICYmIHZlcnNpb24ucGF0Y2ggPT09IDApO1xufVxuXG5mdW5jdGlvbiBzdHJpbmdUb0VudW1BcnJheTxUPih2OiBzdHJpbmcsIG1hcHBpbmc6IGFueSk6IFRbXSB7XG4gIHJldHVybiB2XG4gICAgLnNwbGl0KCcsJylcbiAgICAubWFwKChpdGVtKSA9PiBpdGVtLnRyaW0oKSlcbiAgICAubWFwKChpdGVtKSA9PiB7XG4gICAgICBpZiAoIShpdGVtIGluIG1hcHBpbmcpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgSW52YWxpZCB2YWx1ZSBcIiR7aXRlbX1cIi4gTXVzdCBvbmUgb2YgdGhlIGZvbGxvd2luZzogJHtPYmplY3Qua2V5cyhcbiAgICAgICAgICAgIG1hcHBpbmdcbiAgICAgICAgICApLmpvaW4oJywgJyl9YFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG1hcHBpbmdbaXRlbSBhcyBhbnldIGFzIHVua25vd24gYXMgVDtcbiAgICB9KTtcbn1cblxuZW51bSBXaWZpVHhQb3dlckVudW0ge1xuICAnZGVmYXVsdCcgPSAwLFxuICAnMTAgZEJtJyA9IDQwLFxuICAnMTIuNSBkQm0nID0gNTAsXG4gICcxNSBkQm0nID0gNjAsXG4gICcxNy41IGRCbScgPSA3MCxcbiAgJzIwIGRCbScgPSA4MCxcbn1cblxuY29uc3QgSVBWNF9WQUxJREFUT1IgPSByZWdleFZhbGlkYXRvcihcbiAgSVBWNF9QQVRURVJOLFxuICBgTm90IGEgdmFsaWQgSVB2NCBhZGRyZXNzIChlZyAxOTIuMTY4LjIwLjEpYFxuKTtcblxuZXhwb3J0IGNvbnN0IGRlZmF1bHRJbmZvUmVzb2x2ZXJDb25maWc6IFRhcENvbmZpZ0l0ZW1FeHRlbmRlZFtdID0gW1xuICB7XG4gICAga2V5OiBUYXBJbmZvLkhvc3RQcm90b2NvbCxcbiAgICBpbnB1dDogY3JlYXRlRW51bUZpZWxkKCdIb3N0UHJvdG9jb2wnLCBIb3N0UHJvdG9jb2wpLFxuICAgIHZpZXdGb3JtYXR0ZXI6IGVudW1Gb3JtYXR0ZXIoSG9zdFByb3RvY29sKSxcbiAgfSxcbiAge1xuICAgIGtleTogVGFwSW5mby5jb25maWdWZXJzaW9uLFxuICAgIGlucHV0OiB7XG4gICAgICBmb3JtVmFsaWRhdG9yczogW3ZhbGlkYXRlVGFwVmVyc2lvbl0sXG4gICAgfSxcbiAgICB2aWV3Rm9ybWF0dGVyOiAodjogc3RyaW5nKSA9PiB7XG4gICAgICBpZiAodiA9PT0gRkFDVE9SWV9SRVNFVF9NT0RFX1ZFUlNJT04pIHtcbiAgICAgICAgcmV0dXJuICdGQUNUT1JZIFJFU0VUJztcbiAgICAgIH0gZWxzZSBpZiAodiA9PT0gJzI1NS4yNTUuNjU1MzUnKSB7XG4gICAgICAgIHJldHVybiAnQ09ORklHVVJBVElPTiBNT0RFJztcbiAgICAgIH0gZWxzZSBpZiAodikge1xuICAgICAgICByZXR1cm4gYHYke3Z9YDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiAnVU5LTk9XTic7XG4gICAgICB9XG4gICAgfSxcbiAgICBlZGl0Rm9ybWF0dGVyOiB7XG4gICAgICByZWFkOiAoaW5wdXQ6IHN0cmluZyk6IHN0cmluZyA9PiB7XG4gICAgICAgIHJldHVybiBpbnB1dDtcbiAgICAgIH0sXG4gICAgICB3cml0ZTogKHY6IHN0cmluZyB8IHVuZGVmaW5lZCkgPT4ge1xuICAgICAgICByZXR1cm4gdiB8fCBGQUNUT1JZX1JFU0VUX01PREVfVkVSU0lPTjtcbiAgICAgIH0sXG4gICAgfSxcbiAgfSxcbiAge1xuICAgIGtleTogVGFwSW5mby5DbG91ZEVuZHBvaW50LFxuICAgIGdldFZhbHVlOiBhc3luYyAodGFwKSA9PiB7XG4gICAgICBjb25zdCBob3N0bmFtZSA9IChhd2FpdCB0YXAuc2VydmljZS5tcXR0LmdldEJyb2tlckhvc3RuYW1lKCkpLmJvZHkoKTtcbiAgICAgIGNvbnN0IHBvcnQgPSAoYXdhaXQgdGFwLnNlcnZpY2UubXF0dC5nZXRCcm9rZXJQb3J0KCkpLmJvZHkoKTtcbiAgICAgIHJldHVybiBgJHtob3N0bmFtZX06JHtwb3J0fWA7XG4gICAgfSxcbiAgICBwdXRWYWx1ZTogYXN5bmMgKHRhcDogVGFwLCB2YWx1ZTogc3RyaW5nKSA9PiB7XG4gICAgICBjb25zdCBbaG9zdG5hbWUsIHBvcnRdID0gdmFsdWUuc3BsaXQoJzonKTtcbiAgICAgIGNvbnN0IHNldFBvcnQgPSBhd2FpdCB0YXAuc2VydmljZS5tcXR0LnB1dEJyb2tlclBvcnQocG9ydCB8fCAnMTg4MycpO1xuICAgICAgc2V0UG9ydC5zdWNjZXNzZnVsKCk7XG4gICAgICByZXR1cm4gdGFwLnNlcnZpY2UubXF0dC5wdXRCcm9rZXJIb3N0bmFtZShob3N0bmFtZSk7XG4gICAgfSxcbiAgfSxcbiAge1xuICAgIGtleTogVGFwSW5mby5UYXJnZXRQcm90b2NvbENvbmZpZ3VyYXRpb24sXG4gICAgdmlld0Zvcm1hdHRlcjogKHY6IFVpbnQ4QXJyYXkpID0+IGAke2J1ZmZlclRvSGV4U3RyaW5nKHYpfWAsXG4gICAgZWRpdEZvcm1hdHRlcjoge1xuICAgICAgcmVhZDogKGlucHV0OiBzdHJpbmcpOiBVaW50OEFycmF5ID0+IHtcbiAgICAgICAgcmV0dXJuIGlucHV0ID8gaGV4U3RyaW5nVG9CdWZmZXIoaW5wdXQpIDogbmV3IFVpbnQ4QXJyYXkoKTtcbiAgICAgIH0sXG4gICAgICB3cml0ZTogKHY6IFVpbnQ4QXJyYXkgfCB1bmRlZmluZWQpID0+IHtcbiAgICAgICAgcmV0dXJuIHYgPyBidWZmZXJUb0hleFN0cmluZyh2