@decaf-ts/decorator-validation
Version:
simple decorator based validation engine
262 lines • 35.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.dateFromFormat = dateFromFormat;
exports.bindDateToString = bindDateToString;
exports.isValidDate = isValidDate;
exports.twoDigitPad = twoDigitPad;
exports.formatDate = formatDate;
exports.parseDate = parseDate;
require("reflect-metadata");
const constants_1 = require("./../validation/Validators/constants.cjs");
const strings_1 = require("./strings.cjs");
/**
* @summary Reverses the process from {@link formatDate}
*
* @param {string} date the date string to be converted back into date
* @param {string} format the date format
* @return {Date} the date from the format or the standard new Date({@prop date}) if the string couldn't be parsed (are you sure the format matches the string?)
*
* @function dateFromFormat
* @memberOf module:decorator-validation
* @category Model
*/
function dateFromFormat(date, format) {
let formatRegexp = format;
// Hour
if (formatRegexp.match(/hh/))
formatRegexp = formatRegexp.replace("hh", "(?<hour>\\d{2})");
else if (formatRegexp.match(/h/))
formatRegexp = formatRegexp.replace("h", "(?<hour>\\d{1,2})");
else if (formatRegexp.match(/HH/))
formatRegexp = formatRegexp.replace("HH", "(?<hour>\\d{2})");
else if (formatRegexp.match(/H/))
formatRegexp = formatRegexp.replace("H", "(?<hour>\\d{1,2})");
// Minutes
if (formatRegexp.match(/mm/))
formatRegexp = formatRegexp.replace("mm", "(?<minutes>\\d{2})");
else if (formatRegexp.match(/m/))
formatRegexp = formatRegexp.replace("m", "(?<minutes>\\d{1,2})");
// Seconds
if (formatRegexp.match(/ss/))
formatRegexp = formatRegexp.replace("ss", "(?<seconds>\\d{2})");
else if (formatRegexp.match(/s/))
formatRegexp = formatRegexp.replace("s", "(?<seconds>\\d{1,2})");
// Day
if (formatRegexp.match(/dd/))
formatRegexp = formatRegexp.replace("dd", "(?<day>\\d{2})");
else if (formatRegexp.match(/d/))
formatRegexp = formatRegexp.replace("d", "(?<day>\\d{1,2})");
// Day Of Week
if (formatRegexp.match(/EEEE/))
formatRegexp = formatRegexp.replace("EEEE", "(?<dayofweek>\\w+)");
// eslint-disable-next-line no-dupe-else-if
else if (formatRegexp.match(/EEEE/))
formatRegexp = formatRegexp.replace("EEE", "(?<dayofweek>\\w+)");
// Year
if (formatRegexp.match(/yyyy/))
formatRegexp = formatRegexp.replace("yyyy", "(?<year>\\d{4})");
else if (formatRegexp.match(/yy/))
formatRegexp = formatRegexp.replace("yy", "(?<year>\\d{2})");
// Month
if (formatRegexp.match(/MMMM/))
formatRegexp = formatRegexp.replace("MMMM", "(?<monthname>\\w+)");
else if (formatRegexp.match(/MMM/))
formatRegexp = formatRegexp.replace("MMM", "(?<monthnamesmall>\\w+)");
if (formatRegexp.match(/MM/))
formatRegexp = formatRegexp.replace("MM", "(?<month>\\d{2})");
else if (formatRegexp.match(/M/))
formatRegexp = formatRegexp.replace("M", "(?<month>\\d{1,2})");
// Milis and Am Pm
formatRegexp = formatRegexp
.replace("S", "(?<milis>\\d{1,3})")
.replace("aaa", "(?<ampm>\\w{2})");
const regexp = new RegExp(formatRegexp, "g");
const match = regexp.exec(date);
if (!match || !match.groups)
return new Date(date);
const safeParseInt = function (n) {
if (!n)
return 0;
const result = parseInt(n);
return isNaN(result) ? 0 : result;
};
const year = safeParseInt(match.groups.year);
const day = safeParseInt(match.groups.day);
const amPm = match.groups.ampm;
let hour = safeParseInt(match.groups.hour);
if (amPm)
hour = amPm === "PM" ? hour + 12 : hour;
const minutes = safeParseInt(match.groups.minutes);
const seconds = safeParseInt(match.groups.seconds);
const ms = safeParseInt(match.groups.milis);
const monthName = match.groups.monthname;
const monthNameSmall = match.groups.monthnamesmall;
let month = match.groups.month;
if (monthName)
month = constants_1.MONTH_NAMES.indexOf(monthName);
else if (monthNameSmall) {
const m = constants_1.MONTH_NAMES.find((m) => m.toLowerCase().startsWith(monthNameSmall.toLowerCase()));
if (!m)
return new Date(date);
month = constants_1.MONTH_NAMES.indexOf(m);
}
else
month = safeParseInt(`${month}`);
return new Date(year, month - 1, day, hour, minutes, seconds, ms);
}
/**
* @description Binds a specific date format to a Date object's toString and toISOString methods
* @summary Modifies a Date object to return a formatted string when toString or toISOString is called.
* This function overrides the default toString and toISOString methods of the Date object to return
* the date formatted according to the specified format string.
* @param {Date} [date] The Date object to modify
* @param {string} [format] The format string to use for formatting the date
* @return {Date|undefined} The modified Date object or undefined if no date was provided
* @function bindDateToString
* @memberOf module:decorator-validation
* @category Model
*/
function bindDateToString(date, format) {
if (!date)
return;
const func = () => formatDate(date, format);
Object.defineProperty(date, "toISOString", {
enumerable: false,
configurable: false,
value: func,
});
Object.defineProperty(date, "toString", {
enumerable: false,
configurable: false,
value: func,
});
// Object.setPrototypeOf(date, Date.prototype);
return date;
}
/**
* @description Safely checks if a value is a valid Date object
* @summary A utility function that determines if a value is a valid Date object.
* This function is more reliable than using instanceof Date as it also checks
* that the date is not NaN, which can happen with invalid date strings.
* @param {any} date The value to check
* @return {boolean} True if the value is a valid Date object, false otherwise
* @function isValidDate
* @memberOf module:decorator-validation
* @category Validation
*/
function isValidDate(date) {
return (date &&
Object.prototype.toString.call(date) === "[object Date]" &&
!Number.isNaN(date));
}
/**
* @summary Util function to pad numbers
* @param {number} num
*
* @return {string}
*
* @function twoDigitPad
* @memberOf module:decorator-validation
* @category Model
*/
function twoDigitPad(num) {
return num < 10 ? "0" + num : num.toString();
}
/**
* @summary Date Format Handling
* @description Code from {@link https://stackoverflow.com/questions/3552461/how-to-format-a-javascript-date}
*
* <pre>
* Using similar formatting as Moment.js, Class DateTimeFormatter (Java), and Class SimpleDateFormat (Java),
* I implemented a comprehensive solution formatDate(date, patternStr) where the code is easy to read and modify.
* You can display date, time, AM/PM, etc.
*
* Date and Time Patterns
* yy = 2-digit year; yyyy = full year
* M = digit month; MM = 2-digit month; MMM = short month name; MMMM = full month name
* EEEE = full weekday name; EEE = short weekday name
* d = digit day; dd = 2-digit day
* h = hours am/pm; hh = 2-digit hours am/pm; H = hours; HH = 2-digit hours
* m = minutes; mm = 2-digit minutes; aaa = AM/PM
* s = seconds; ss = 2-digit seconds
* S = miliseconds
* </pre>
*
* @param {Date} date
* @param {string} [patternStr] defaults to 'yyyy/MM/dd'
* @return {string} the formatted date
*
* @function formatDate
* @memberOf module:decorator-validation
* @category Model
*/
function formatDate(date, patternStr = "yyyy/MM/dd") {
const day = date.getDate(), month = date.getMonth(), year = date.getFullYear(), hour = date.getHours(), minute = date.getMinutes(), second = date.getSeconds(), miliseconds = date.getMilliseconds(), h = hour % 12, hh = twoDigitPad(h), HH = twoDigitPad(hour), mm = twoDigitPad(minute), ss = twoDigitPad(second), aaa = hour < 12 ? "AM" : "PM", EEEE = constants_1.DAYS_OF_WEEK_NAMES[date.getDay()], EEE = EEEE.substr(0, 3), dd = twoDigitPad(day), M = month + 1, MM = twoDigitPad(M), MMMM = constants_1.MONTH_NAMES[month], MMM = MMMM.substr(0, 3), yyyy = year + "", yy = yyyy.substr(2, 2);
// checks to see if month name will be used
patternStr = patternStr
.replace("hh", hh)
.replace("h", h.toString())
.replace("HH", HH)
.replace("H", hour.toString())
.replace("mm", mm)
.replace("m", minute.toString())
.replace("ss", ss)
.replace("s", second.toString())
.replace("S", miliseconds.toString())
.replace("dd", dd)
.replace("d", day.toString())
.replace("EEEE", EEEE)
.replace("EEE", EEE)
.replace("yyyy", yyyy)
.replace("yy", yy)
.replace("aaa", aaa);
if (patternStr.indexOf("MMM") > -1) {
patternStr = patternStr.replace("MMMM", MMMM).replace("MMM", MMM);
}
else {
patternStr = patternStr.replace("MM", MM).replace("M", M.toString());
}
return patternStr;
}
/**
* @summary Parses a date from a specified format
* @param {string} format
* @param {string | Date | number} [v]
* @memberOf module:decorator-validation
* @category Model
*/
function parseDate(format, v) {
let value = undefined;
if (!v)
return undefined;
if (v instanceof Date)
try {
value = dateFromFormat(formatDate(v, format), format);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
}
catch (e) {
throw new Error((0, strings_1.sf)("Could not convert date {0} to format: {1}", v.toString(), format));
}
else if (typeof v === "string") {
value = dateFromFormat(v, format);
}
else if (typeof v === "number") {
const d = new Date(v);
value = dateFromFormat(formatDate(d, format), format);
}
else if (isValidDate(v)) {
try {
const d = new Date(v);
value = dateFromFormat(formatDate(d, format), format);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
}
catch (e) {
throw new Error((0, strings_1.sf)("Could not convert date {0} to format: {1}", v, format));
}
}
else {
throw new Error(`Invalid value provided ${v}`);
}
return bindDateToString(value, format);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvZGF0ZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFrQkEsd0NBOEdDO0FBY0QsNENBZUM7QUFhRCxrQ0FNQztBQVlELGtDQUVDO0FBOEJELGdDQWdEQztBQVNELDhCQWlDQztBQXRURCw0QkFBMEI7QUFDMUIsd0VBRzRDO0FBQzVDLDJDQUErQjtBQUUvQjs7Ozs7Ozs7OztHQVVHO0FBQ0gsU0FBZ0IsY0FBYyxDQUFDLElBQVksRUFBRSxNQUFjO0lBQ3pELElBQUksWUFBWSxHQUFXLE1BQU0sQ0FBQztJQUVsQyxPQUFPO0lBQ1AsSUFBSSxZQUFZLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQztRQUMxQixZQUFZLEdBQUcsWUFBWSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztTQUMxRCxJQUFJLFlBQVksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDO1FBQzlCLFlBQVksR0FBRyxZQUFZLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxtQkFBbUIsQ0FBQyxDQUFDO1NBQzNELElBQUksWUFBWSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUM7UUFDL0IsWUFBWSxHQUFHLFlBQVksQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLGlCQUFpQixDQUFDLENBQUM7U0FDMUQsSUFBSSxZQUFZLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQztRQUM5QixZQUFZLEdBQUcsWUFBWSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsbUJBQW1CLENBQUMsQ0FBQztJQUVoRSxVQUFVO0lBQ1YsSUFBSSxZQUFZLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQztRQUMxQixZQUFZLEdBQUcsWUFBWSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsb0JBQW9CLENBQUMsQ0FBQztTQUM3RCxJQUFJLFlBQVksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDO1FBQzlCLFlBQVks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QUUsTUFBTSxDQUFDLENBQ3RFLENBQUM7UUFDSixDQUFDO1NBQ0UsSUFBSSxPQUFPLENBQUMsS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUMvQixLQUFLLEdBQUcsY0FBYyxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUNwQyxDQUFDO1NBQU0sSUFBSSxPQUFPLENBQUMsS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUNqQyxNQUFNLENBQUMsR0FBRyxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN0QixLQUFLLEdBQUcsY0FBYyxDQUFDLFVBQVUsQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDeEQsQ0FBQztTQUFNLElBQUksV0FBVyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDMUIsSUFBSSxDQUFDO1lBQ0gsTUFBTSxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDdEIsS0FBSyxHQUFHLGNBQWMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQ3RELDZEQUE2RDtRQUMvRCxDQUFDO1FBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNYLE1BQU0sSUFBSSxLQUFLLENBQ2IsSUFBQSxZQUFFLEVBQUMsMkNBQTJDLEVBQUUsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUMzRCxDQUFDO1FBQ0osQ0FBQztJQUNILENBQUM7U0FBTSxDQUFDO1FBQ04sTUFBTSxJQUFJLEtBQUssQ0FBQywwQkFBMEIsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNqRCxDQUFDO0lBQ0QsT0FBTyxnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7QUFDekMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBcInJlZmxlY3QtbWV0YWRhdGFcIjtcbmltcG9ydCB7XG4gIERBWVNfT0ZfV0VFS19OQU1FUyxcbiAgTU9OVEhfTkFNRVMsXG59IGZyb20gXCIuLi92YWxpZGF0aW9uL1ZhbGlkYXRvcnMvY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBzZiB9IGZyb20gXCIuL3N0cmluZ3NcIjtcblxuLyoqXG4gKiBAc3VtbWFyeSBSZXZlcnNlcyB0aGUgcHJvY2VzcyBmcm9tIHtAbGluayBmb3JtYXREYXRlfVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBkYXRlIHRoZSBkYXRlIHN0cmluZyB0byBiZSBjb252ZXJ0ZWQgYmFjayBpbnRvIGRhdGVcbiAqIEBwYXJhbSB7c3RyaW5nfSBmb3JtYXQgdGhlIGRhdGUgZm9ybWF0XG4gKiBAcmV0dXJuIHtEYXRlfSB0aGUgZGF0ZSBmcm9tIHRoZSBmb3JtYXQgb3IgdGhlIHN0YW5kYXJkIG5ldyBEYXRlKHtAcHJvcCBkYXRlfSkgaWYgdGhlIHN0cmluZyBjb3VsZG4ndCBiZSBwYXJzZWQgKGFyZSB5b3Ugc3VyZSB0aGUgZm9ybWF0IG1hdGNoZXMgdGhlIHN0cmluZz8pXG4gKlxuICogQGZ1bmN0aW9uIGRhdGVGcm9tRm9ybWF0XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRvci12YWxpZGF0aW9uXG4gKiBAY2F0ZWdvcnkgTW9kZWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRhdGVGcm9tRm9ybWF0KGRhdGU6IHN0cmluZywgZm9ybWF0OiBzdHJpbmcpIHtcbiAgbGV0IGZvcm1hdFJlZ2V4cDogc3RyaW5nID0gZm9ybWF0O1xuXG4gIC8vIEhvdXJcbiAgaWYgKGZvcm1hdFJlZ2V4cC5tYXRjaCgvaGgvKSlcbiAgICBmb3JtYXRSZWdleHAgPSBmb3JtYXRSZWdleHAucmVwbGFjZShcImhoXCIsIFwiKD88aG91cj5cXFxcZHsyfSlcIik7XG4gIGVsc2UgaWYgKGZvcm1hdFJlZ2V4cC5tYXRjaCgvaC8pKVxuICAgIGZvcm1hdFJlZ2V4cCA9IGZvcm1hdFJlZ2V4cC5yZXBsYWNlKFwiaFwiLCBcIig/PGhvdXI+XFxcXGR7MSwyfSlcIik7XG4gIGVsc2UgaWYgKGZvcm1hdFJlZ2V4cC5tYXRjaCgvSEgvKSlcbiAgICBmb3JtYXRSZWdleHAgPSBmb3JtYXRSZWdleHAucmVwbGFjZShcIkhIXCIsIFwiKD88aG91cj5cXFxcZHsyfSlcIik7XG4gIGVsc2UgaWYgKGZvcm1hdFJlZ2V4cC5tYXRjaCgvSC8pKVxuICAgIGZvcm1hdFJlZ2V4cCA9IGZvcm1hdFJlZ2V4cC5yZXBsYWNlKFwiSFwiLCBcIig/PGhvdXI+XFxcXGR7MSwyfSlcIik7XG5cbiAgLy8gTWludXRlc1xuICBpZiAoZm9ybWF0UmVnZXhwLm1hdGNoKC9tbS8pKVxuICAgIGZvcm1hdFJlZ2V4cCA9IGZvcm1hdFJlZ2V4cC5yZXBsYWNlKFwibW1cIiwgXCIoPzxtaW51dGVzPlxcXFxkezJ9KVwiKTtcbiAgZWxzZSBpZiAoZm9ybWF0UmVnZXhwLm1hdGNoKC9tLykpXG4gICAgZm9ybWF0UmVnZXhwID0gZm9ybWF0UmVnZXhwLnJlcGxhY2UoXCJtXCIsIFwiKD88bWludXRlcz5cXFxcZHsxLDJ9KVwiKTtcblxuICAvLyBTZWNvbmRzXG4gIGlmIChmb3JtYXRSZWdleHAubWF0Y2goL3NzLykpXG4gICAgZm9ybWF0UmVnZXhwID0gZm9ybWF0UmVnZXhwLnJlcGxhY2UoXCJzc1wiLCBcIig/PHNlY29uZHM+XFxcXGR7Mn0pXCIpO1xuICBlbHNlIGlmIChmb3JtYXRSZWdleHAubWF0Y2goL3MvKSlcbiAgICBmb3JtYXRSZWdleHAgPSBmb3JtYXRSZWdleHAucmVwbGFjZShcInNcIiwgXCIoPzxzZWNvbmRzPlxcXFxkezEsMn0pXCIpO1xuXG4gIC8vIERheVxuICBpZiAoZm9ybWF0UmVnZXhwLm1hdGNoKC9kZC8pKVxuICAgIGZvcm1hdFJlZ2V4cCA9IGZvcm1hdFJlZ2V4cC5yZXBsYWNlKFwiZGRcIiwgXCIoPzxkYXk+XFxcXGR7Mn0pXCIpO1xuICBlbHNlIGlmIChmb3JtYXRSZWdleHAubWF0Y2goL2QvKSlcbiAgICBmb3JtYXRSZWdleHAgPSBmb3JtYXRSZWdleHAucmVwbGFjZShcImRcIiwgXCIoPzxkYXk+XFxcXGR7MSwyfSlcIik7XG5cbiAgLy8gRGF5IE9mIFdlZWtcbiAgaWYgKGZvcm1hdFJlZ2V4cC5tYXRjaCgvRUVFRS8pKVxuICAgIGZvcm1hdFJlZ2V4cCA9IGZvcm1hdFJlZ2V4cC5yZXBsYWNlKFwiRUVFRVwiLCBcIig/PGRheW9md2Vlaz5cXFxcdyspXCIpO1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tZHVwZS1lbHNlLWlmXG4gIGVsc2UgaWYgKGZvcm1hdFJlZ2V4cC5tYXRjaCgvRUVFRS8pKVxuICAgIGZvcm1hdFJlZ2V4cCA9IGZvcm1hdFJlZ2V4cC5yZXBsYWNlKFwiRUVFXCIsIFwiKD88ZGF5b2Z3ZWVrPlxcXFx3KylcIik7XG5cbiAgLy8gWWVhclxuICBpZiAoZm9ybWF0UmVnZXhwLm1hdGNoKC95eXl5LykpXG4gICAgZm9ybWF0UmVnZXhwID0gZm9ybWF0UmVnZXhwLnJlcGxhY2UoXCJ5eXl5XCIsIFwiKD88eWVhcj5cXFxcZHs0fSlcIik7XG4gIGVsc2UgaWYgKGZvcm1hdFJlZ2V4cC5tYXRjaCgveXkvKSlcbiAgICBmb3JtYXRSZWdleHAgPSBmb3JtYXRSZWdleHAucmVwbGFjZShcInl5XCIsIFwiKD88eWVhcj5cXFxcZHsyfSlcIik7XG5cbiAgLy8gTW9udGhcbiAgaWYgKGZvcm1hdFJlZ2V4cC5tYXRjaCgvTU1NTS8pKVxuICAgIGZvcm1hdFJlZ2V4cCA9IGZvcm1hdFJlZ2V4cC5yZXBsYWNlKFwiTU1NTVwiLCBcIig/PG1vbnRobmFtZT5cXFxcdyspXCIpO1xuICBlbHNlIGlmIChmb3JtYXRSZWdleHAubWF0Y2goL01NTS8pKVxuICAgIGZvcm1hdFJlZ2V4cCA9IGZvcm1hdFJlZ2V4cC5yZXBsYWNlKFwiTU1NXCIsIFwiKD88bW9udGhuYW1lc21hbGw+XFxcXHcrKVwiKTtcbiAgaWYgKGZvcm1hdFJlZ2V4cC5tYXRjaCgvTU0vKSlcbiAgICBmb3JtYXRSZWdleHAgPSBmb3JtYXRSZWdleHAucmVwbGFjZShcIk1NXCIsIFwiKD88bW9udGg+XFxcXGR7Mn0pXCIpO1xuICBlbHNlIGlmIChmb3JtYXRSZWdleHAubWF0Y2goL00vKSlcbiAgICBmb3JtYXRSZWdleHAgPSBmb3JtYXRSZWdleHAucmVwbGFjZShcIk1cIiwgXCIoPzxtb250aD5cXFxcZHsxLDJ9KVwiKTtcblxuICAvLyBNaWxpcyBhbmQgQW0gUG1cbiAgZm9ybWF0UmVnZXhwID0gZm9ybWF0UmVnZXhwXG4gICAgLnJlcGxhY2UoXCJTXCIsIFwiKD88bWlsaXM+XFxcXGR7MSwzfSlcIilcbiAgICAucmVwbGFjZShcImFhYVwiLCBcIig/PGFtcG0+XFxcXHd7Mn0pXCIpO1xuXG4gIGNvbnN0IHJlZ2V4cCA9IG5ldyBSZWdFeHAoZm9ybWF0UmVnZXhwLCBcImdcIik7XG5cbiAgY29uc3QgbWF0Y2g6IHtcbiAgICBncm91cHM6IHtcbiAgICAgIHllYXI/OiBzdHJpbmc7XG4gICAgICBkYXk/OiBzdHJpbmc7XG4gICAgICBhbXBtPzogc3RyaW5nO1xuICAgICAgaG91cj86IHN0cmluZztcbiAgICAgIG1pbnV0ZXM/OiBzdHJpbmc7XG4gICAgICBzZWNvbmRzPzogc3RyaW5nO1xuICAgICAgbWlsaXM/OiBzdHJpbmc7XG4gICAgICBtb250aG5hbWU/OiBzdHJpbmc7XG4gICAgICBtb250aG5hbWVzbWFsbD86IHN0cmluZztcbiAgICAgIG1vbnRoPzogc3RyaW5nO1xuICAgIH07XG4gIH0gPSByZWdleHAuZXhlYyhkYXRlKSBhcyBhbnk7XG5cbiAgaWYgKCFtYXRjaCB8fCAhbWF0Y2guZ3JvdXBzKSByZXR1cm4gbmV3IERhdGUoZGF0ZSk7XG5cbiAgY29uc3Qgc2FmZVBhcnNlSW50ID0gZnVuY3Rpb24gKG4/OiBzdHJpbmcpIHtcbiAgICBpZiAoIW4pIHJldHVybiAwO1xuICAgIGNvbnN0IHJlc3VsdCA9IHBhcnNlSW50KG4pO1xuXG4gICAgcmV0dXJuIGlzTmFOKHJlc3VsdCkgPyAwIDogcmVzdWx0O1xuICB9O1xuXG4gIGNvbnN0IHllYXIgPSBzYWZlUGFyc2VJbnQobWF0Y2guZ3JvdXBzLnllYXIpO1xuICBjb25zdCBkYXkgPSBzYWZlUGFyc2VJbnQobWF0Y2guZ3JvdXBzLmRheSk7XG5cbiAgY29uc3QgYW1QbSA9IG1hdGNoLmdyb3Vwcy5hbXBtO1xuICBsZXQgaG91ciA9IHNhZmVQYXJzZUludChtYXRjaC5ncm91cHMuaG91cik7XG5cbiAgaWYgKGFtUG0pIGhvdXIgPSBhbVBtID09PSBcIlBNXCIgPyBob3VyICsgMTIgOiBob3VyO1xuXG4gIGNvbnN0IG1pbnV0ZXMgPSBzYWZlUGFyc2VJbnQobWF0Y2guZ3JvdXBzLm1pbnV0ZXMpO1xuICBjb25zdCBzZWNvbmRzID0gc2FmZVBhcnNlSW50KG1hdGNoLmdyb3Vwcy5zZWNvbmRzKTtcbiAgY29uc3QgbXMgPSBzYWZlUGFyc2VJbnQobWF0Y2guZ3JvdXBzLm1pbGlzKTtcblxuICBjb25zdCBtb250aE5hbWUgPSBtYXRjaC5ncm91cHMubW9udGhuYW1lO1xuICBjb25zdCBtb250aE5hbWVTbWFsbCA9IG1hdGNoLmdyb3Vwcy5tb250aG5hbWVzbWFsbDtcbiAgbGV0IG1vbnRoOiBudW1iZXIgfCBzdHJpbmcgPSBtYXRjaC5ncm91cHMubW9udGggYXMgc3RyaW5nO1xuICBpZiAobW9udGhOYW1lKSBtb250aCA9IE1PTlRIX05BTUVTLmluZGV4T2YobW9udGhOYW1lKTtcbiAgZWxzZSBpZiAobW9udGhOYW1lU21hbGwpIHtcbiAgICBjb25zdCBtID0gTU9OVEhfTkFNRVMuZmluZCgobSkgPT5cbiAgICAgIG0udG9Mb3dlckNhc2UoKS5zdGFydHNXaXRoKG1vbnRoTmFtZVNtYWxsLnRvTG93ZXJDYXNlKCkpXG4gICAgKTtcbiAgICBpZiAoIW0pIHJldHVybiBuZXcgRGF0ZShkYXRlKTtcbiAgICBtb250aCA9IE1PTlRIX05BTUVTLmluZGV4T2YobSk7XG4gIH0gZWxzZSBtb250aCA9IHNhZmVQYXJzZUludChgJHttb250aH1gKTtcblxuICByZXR1cm4gbmV3IERhdGUoeWVhciwgbW9udGggLSAxLCBkYXksIGhvdXIsIG1pbnV0ZXMsIHNlY29uZHMsIG1zKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQmluZHMgYSBzcGVjaWZpYyBkYXRlIGZvcm1hdCB0byBhIERhdGUgb2JqZWN0J3MgdG9TdHJpbmcgYW5kIHRvSVNPU3RyaW5nIG1ldGhvZHNcbiAqIEBzdW1tYXJ5IE1vZGlmaWVzIGEgRGF0ZSBvYmplY3QgdG8gcmV0dXJuIGEgZm9ybWF0dGVkIHN0cmluZyB3aGVuIHRvU3RyaW5nIG9yIHRvSVNPU3RyaW5nIGlzIGNhbGxlZC5cbiAqIFRoaXMgZnVuY3Rpb24gb3ZlcnJpZGVzIHRoZSBkZWZhdWx0IHRvU3RyaW5nIGFuZCB0b0lTT1N0cmluZyBtZXRob2RzIG9mIHRoZSBEYXRlIG9iamVjdCB0byByZXR1cm5cbiAqIHRoZSBkYXRlIGZvcm1hdHRlZCBhY2NvcmRpbmcgdG8gdGhlIHNwZWNpZmllZCBmb3JtYXQgc3RyaW5nLlxuICogQHBhcmFtIHtEYXRlfSBbZGF0ZV0gVGhlIERhdGUgb2JqZWN0IHRvIG1vZGlmeVxuICogQHBhcmFtIHtzdHJpbmd9IFtmb3JtYXRdIFRoZSBmb3JtYXQgc3RyaW5nIHRvIHVzZSBmb3IgZm9ybWF0dGluZyB0aGUgZGF0ZVxuICogQHJldHVybiB7RGF0ZXx1bmRlZmluZWR9IFRoZSBtb2RpZmllZCBEYXRlIG9iamVjdCBvciB1bmRlZmluZWQgaWYgbm8gZGF0ZSB3YXMgcHJvdmlkZWRcbiAqIEBmdW5jdGlvbiBiaW5kRGF0ZVRvU3RyaW5nXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRvci12YWxpZGF0aW9uXG4gKiBAY2F0ZWdvcnkgTW9kZWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJpbmREYXRlVG9TdHJpbmcoZGF0ZTogRGF0ZSB8IHVuZGVmaW5lZCwgZm9ybWF0OiBzdHJpbmcpIHtcbiAgaWYgKCFkYXRlKSByZXR1cm47XG4gIGNvbnN0IGZ1bmMgPSAoKSA9PiBmb3JtYXREYXRlKGRhdGUsIGZvcm1hdCk7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShkYXRlLCBcInRvSVNPU3RyaW5nXCIsIHtcbiAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICBjb25maWd1cmFibGU6IGZhbHNlLFxuICAgIHZhbHVlOiBmdW5jLFxuICB9KTtcbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGRhdGUsIFwidG9TdHJpbmdcIiwge1xuICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgIGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gICAgdmFsdWU6IGZ1bmMsXG4gIH0pO1xuICAvLyBPYmplY3Quc2V0UHJvdG90eXBlT2YoZGF0ZSwgRGF0ZS5wcm90b3R5cGUpO1xuICByZXR1cm4gZGF0ZTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gU2FmZWx5IGNoZWNrcyBpZiBhIHZhbHVlIGlzIGEgdmFsaWQgRGF0ZSBvYmplY3RcbiAqIEBzdW1tYXJ5IEEgdXRpbGl0eSBmdW5jdGlvbiB0aGF0IGRldGVybWluZXMgaWYgYSB2YWx1ZSBpcyBhIHZhbGlkIERhdGUgb2JqZWN0LlxuICogVGhpcyBmdW5jdGlvbiBpcyBtb3JlIHJlbGlhYmxlIHRoYW4gdXNpbmcgaW5zdGFuY2VvZiBEYXRlIGFzIGl0IGFsc28gY2hlY2tzXG4gKiB0aGF0IHRoZSBkYXRlIGlzIG5vdCBOYU4sIHdoaWNoIGNhbiBoYXBwZW4gd2l0aCBpbnZhbGlkIGRhdGUgc3RyaW5ncy5cbiAqIEBwYXJhbSB7YW55fSBkYXRlIFRoZSB2YWx1ZSB0byBjaGVja1xuICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgdmFsdWUgaXMgYSB2YWxpZCBEYXRlIG9iamVjdCwgZmFsc2Ugb3RoZXJ3aXNlXG4gKiBAZnVuY3Rpb24gaXNWYWxpZERhdGVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdG9yLXZhbGlkYXRpb25cbiAqIEBjYXRlZ29yeSBWYWxpZGF0aW9uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1ZhbGlkRGF0ZShkYXRlOiBhbnkpOiBib29sZWFuIHtcbiAgcmV0dXJuIChcbiAgICBkYXRlICYmXG4gICAgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGRhdGUpID09PSBcIltvYmplY3QgRGF0ZV1cIiAmJlxuICAgICFOdW1iZXIuaXNOYU4oZGF0ZSlcbiAgKTtcbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBVdGlsIGZ1bmN0aW9uIHRvIHBhZCBudW1iZXJzXG4gKiBAcGFyYW0ge251bWJlcn0gbnVtXG4gKlxuICogQHJldHVybiB7c3RyaW5nfVxuICpcbiAqIEBmdW5jdGlvbiB0d29EaWdpdFBhZFxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0b3ItdmFsaWRhdGlvblxuICogQGNhdGVnb3J5IE1vZGVsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0d29EaWdpdFBhZChudW06IG51bWJlcik6IHN0cmluZyB7XG4gIHJldHVybiBudW0gPCAxMCA/IFwiMFwiICsgbnVtIDogbnVtLnRvU3RyaW5nKCk7XG59XG5cbi8qKlxuICogQHN1bW1hcnkgRGF0ZSBGb3JtYXQgSGFuZGxpbmdcbiAqIEBkZXNjcmlwdGlvbiBDb2RlIGZyb20ge0BsaW5rIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzM1NTI0NjEvaG93LXRvLWZvcm1hdC1hLWphdmFzY3JpcHQtZGF0ZX1cbiAqXG4gKiA8cHJlPlxuICogICAgICBVc2luZyBzaW1pbGFyIGZvcm1hdHRpbmcgYXMgTW9tZW50LmpzLCBDbGFzcyBEYXRlVGltZUZvcm1hdHRlciAoSmF2YSksIGFuZCBDbGFzcyBTaW1wbGVEYXRlRm9ybWF0IChKYXZhKSxcbiAqICAgICAgSSBpbXBsZW1lbnRlZCBhIGNvbXByZWhlbnNpdmUgc29sdXRpb24gZm9ybWF0RGF0ZShkYXRlLCBwYXR0ZXJuU3RyKSB3aGVyZSB0aGUgY29kZSBpcyBlYXN5IHRvIHJlYWQgYW5kIG1vZGlmeS5cbiAqICAgICAgWW91IGNhbiBkaXNwbGF5IGRhdGUsIHRpbWUsIEFNL1BNLCBldGMuXG4gKlxuICogICAgICBEYXRlIGFuZCBUaW1lIFBhdHRlcm5zXG4gKiAgICAgIHl5ID0gMi1kaWdpdCB5ZWFyOyB5eXl5ID0gZnVsbCB5ZWFyXG4gKiAgICAgIE0gPSBkaWdpdCBtb250aDsgTU0gPSAyLWRpZ2l0IG1vbnRoOyBNTU0gPSBzaG9ydCBtb250aCBuYW1lOyBNTU1NID0gZnVsbCBtb250aCBuYW1lXG4gKiAgICAgIEVFRUUgPSBmdWxsIHdlZWtkYXkgbmFtZTsgRUVFID0gc2hvcnQgd2Vla2RheSBuYW1lXG4gKiAgICAgIGQgPSBkaWdpdCBkYXk7IGRkID0gMi1kaWdpdCBkYXlcbiAqICAgICAgaCA9IGhvdXJzIGFtL3BtOyBoaCA9IDItZGlnaXQgaG91cnMgYW0vcG07IEggPSBob3VyczsgSEggPSAyLWRpZ2l0IGhvdXJzXG4gKiAgICAgIG0gPSBtaW51dGVzOyBtbSA9IDItZGlnaXQgbWludXRlczsgYWFhID0gQU0vUE1cbiAqICAgICAgcyA9IHNlY29uZHM7IHNzID0gMi1kaWdpdCBzZWNvbmRzXG4gKiAgICAgIFMgPSBtaWxpc2Vjb25kc1xuICogPC9wcmU+XG4gKlxuICogQHBhcmFtIHtEYXRlfSBkYXRlXG4gKiBAcGFyYW0ge3N0cmluZ30gW3BhdHRlcm5TdHJdIGRlZmF1bHRzIHRvICd5eXl5L01NL2RkJ1xuICogQHJldHVybiB7c3RyaW5nfSB0aGUgZm9ybWF0dGVkIGRhdGVcbiAqXG4gKiBAZnVuY3Rpb24gZm9ybWF0RGF0ZVxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0b3ItdmFsaWRhdGlvblxuICogQGNhdGVnb3J5IE1vZGVsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmb3JtYXREYXRlKGRhdGU6IERhdGUsIHBhdHRlcm5TdHI6IHN0cmluZyA9IFwieXl5eS9NTS9kZFwiKSB7XG4gIGNvbnN0IGRheTogbnVtYmVyID0gZGF0ZS5nZXREYXRlKCksXG4gICAgbW9udGg6IG51bWJlciA9IGRhdGUuZ2V0TW9udGgoKSxcbiAgICB5ZWFyOiBudW1iZXIgPSBkYXRlLmdldEZ1bGxZZWFyKCksXG4gICAgaG91cjogbnVtYmVyID0gZGF0ZS5nZXRIb3VycygpLFxuICAgIG1pbnV0ZTogbnVtYmVyID0gZGF0ZS5nZXRNaW51dGVzKCksXG4gICAgc2Vjb25kOiBudW1iZXIgPSBkYXRlLmdldFNlY29uZHMoKSxcbiAgICBtaWxpc2Vjb25kczogbnVtYmVyID0gZGF0ZS5nZXRNaWxsaXNlY29uZHMoKSxcbiAgICBoOiBudW1iZXIgPSBob3VyICUgMTIsXG4gICAgaGg6IHN0cmluZyA9IHR3b0RpZ2l0UGFkKGgpLFxuICAgIEhIOiBzdHJpbmcgPSB0d29EaWdpdFBhZChob3VyKSxcbiAgICBtbTogc3RyaW5nID0gdHdvRGlnaXRQYWQobWludXRlKSxcbiAgICBzczogc3RyaW5nID0gdHdvRGlnaXRQYWQoc2Vjb25kKSxcbiAgICBhYWE6IHN0cmluZyA9IGhvdXIgPCAxMiA/IFwiQU1cIiA6IFwiUE1cIixcbiAgICBFRUVFOiBzdHJpbmcgPSBEQVlTX09GX1dFRUtfTkFNRVNbZGF0ZS5nZXREYXkoKV0sXG4gICAgRUVFOiBzdHJpbmcgPSBFRUVFLnN1YnN0cigwLCAzKSxcbiAgICBkZDogc3RyaW5nID0gdHdvRGlnaXRQYWQoZGF5KSxcbiAgICBNOiBudW1iZXIgPSBtb250aCArIDEsXG4gICAgTU06IHN0cmluZyA9IHR3b0RpZ2l0UGFkKE0pLFxuICAgIE1NTU06IHN0cmluZyA9IE1PTlRIX05BTUVTW21vbnRoXSxcbiAgICBNTU06IHN0cmluZyA9IE1NTU0uc3Vic3RyKDAsIDMpLFxuICAgIHl5eXk6IHN0cmluZyA9IHllYXIgKyBcIlwiLFxuICAgIHl5OiBzdHJpbmcgPSB5eXl5LnN1YnN0cigyLCAyKTtcbiAgLy8gY2hlY2tzIHRvIHNlZSBpZiBtb250aCBuYW1lIHdpbGwgYmUgdXNlZFxuICBwYXR0ZXJuU3RyID0gcGF0dGVyblN0clxuICAgIC5yZXBsYWNlKFwiaGhcIiwgaGgpXG4gICAgLnJlcGxhY2UoXCJoXCIsIGgudG9TdHJpbmcoKSlcbiAgICAucmVwbGFjZShcIkhIXCIsIEhIKVxuICAgIC5yZXBsYWNlKFwiSFwiLCBob3VyLnRvU3RyaW5nKCkpXG4gICAgLnJlcGxhY2UoXCJtbVwiLCBtbSlcbiAgICAucmVwbGFjZShcIm1cIiwgbWludXRlLnRvU3RyaW5nKCkpXG4gICAgLnJlcGxhY2UoXCJzc1wiLCBzcylcbiAgICAucmVwbGFjZShcInNcIiwgc2Vjb25kLnRvU3RyaW5nKCkpXG4gICAgLnJlcGxhY2UoXCJTXCIsIG1pbGlzZWNvbmRzLnRvU3RyaW5nKCkpXG4gICAgLnJlcGxhY2UoXCJkZFwiLCBkZClcbiAgICAucmVwbGFjZShcImRcIiwgZGF5LnRvU3RyaW5nKCkpXG5cbiAgICAucmVwbGFjZShcIkVFRUVcIiwgRUVFRSlcbiAgICAucmVwbGFjZShcIkVFRVwiLCBFRUUpXG4gICAgLnJlcGxhY2UoXCJ5eXl5XCIsIHl5eXkpXG4gICAgLnJlcGxhY2UoXCJ5eVwiLCB5eSlcbiAgICAucmVwbGFjZShcImFhYVwiLCBhYWEpO1xuICBpZiAocGF0dGVyblN0ci5pbmRleE9mKFwiTU1NXCIpID4gLTEpIHtcbiAgICBwYXR0ZXJuU3RyID0gcGF0dGVyblN0ci5yZXBsYWNlKFwiTU1NTVwiLCBNTU1NKS5yZXBsYWNlKFwiTU1NXCIsIE1NTSk7XG4gIH0gZWxzZSB7XG4gICAgcGF0dGVyblN0ciA9IHBhdHRlcm5TdHIucmVwbGFjZShcIk1NXCIsIE1NKS5yZXBsYWNlKFwiTVwiLCBNLnRvU3RyaW5nKCkpO1xuICB9XG4gIHJldHVybiBwYXR0ZXJuU3RyO1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IFBhcnNlcyBhIGRhdGUgZnJvbSBhIHNwZWNpZmllZCBmb3JtYXRcbiAqIEBwYXJhbSB7c3RyaW5nfSBmb3JtYXRcbiAqIEBwYXJhbSB7c3RyaW5nIHwgRGF0ZSB8IG51bWJlcn0gW3ZdXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRvci12YWxpZGF0aW9uXG4gKiBAY2F0ZWdvcnkgTW9kZWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlRGF0ZShmb3JtYXQ6IHN0cmluZywgdj86IHN0cmluZyB8IERhdGUgfCBudW1iZXIpIHtcbiAgbGV0IHZhbHVlOiBEYXRlIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuXG4gIGlmICghdikgcmV0dXJuIHVuZGVmaW5lZDtcblxuICBpZiAodiBpbnN0YW5jZW9mIERhdGUpXG4gICAgdHJ5IHtcbiAgICAgIHZhbHVlID0gZGF0ZUZyb21Gb3JtYXQoZm9ybWF0RGF0ZSh2IGFzIERhdGUsIGZvcm1hdCksIGZvcm1hdCk7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIHNmKFwiQ291bGQgbm90IGNvbnZlcnQgZGF0ZSB7MH0gdG8gZm9ybWF0OiB7MX1cIiwgdi50b1N0cmluZygpLCBmb3JtYXQpXG4gICAgICApO1xuICAgIH1cbiAgZWxzZSBpZiAodHlwZW9mIHYgPT09IFwic3RyaW5nXCIpIHtcbiAgICB2YWx1ZSA9IGRhdGVGcm9tRm9ybWF0KHYsIGZvcm1hdCk7XG4gIH0gZWxzZSBpZiAodHlwZW9mIHYgPT09IFwibnVtYmVyXCIpIHtcbiAgICBjb25zdCBkID0gbmV3IERhdGUodik7XG4gICAgdmFsdWUgPSBkYXRlRnJvbUZvcm1hdChmb3JtYXREYXRlKGQsIGZvcm1hdCksIGZvcm1hdCk7XG4gIH0gZWxzZSBpZiAoaXNWYWxpZERhdGUodikpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgZCA9IG5ldyBEYXRlKHYpO1xuICAgICAgdmFsdWUgPSBkYXRlRnJvbUZvcm1hdChmb3JtYXREYXRlKGQsIGZvcm1hdCksIGZvcm1hdCk7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBzZihcIkNvdWxkIG5vdCBjb252ZXJ0IGRhdGUgezB9IHRvIGZvcm1hdDogezF9XCIsIHYsIGZvcm1hdClcbiAgICAgICk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCB2YWx1ZSBwcm92aWRlZCAke3Z9YCk7XG4gIH1cbiAgcmV0dXJuIGJpbmREYXRlVG9TdHJpbmcodmFsdWUsIGZvcm1hdCk7XG59XG4iXX0=