appium-ios-simulator
Version:
iOS Simulator interface for Appium.
463 lines (373 loc) • 24.7 kB
JavaScript
;
var _createClass = require('babel-runtime/helpers/create-class')['default'];
var _classCallCheck = require('babel-runtime/helpers/class-call-check')['default'];
var _regeneratorRuntime = require('babel-runtime/regenerator')['default'];
var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default'];
Object.defineProperty(exports, '__esModule', {
value: true
});
var _crypto = require('crypto');
var _crypto2 = _interopRequireDefault(_crypto);
var _bluebird = require('bluebird');
var _bluebird2 = _interopRequireDefault(_bluebird);
var _path = require('path');
var _path2 = _interopRequireDefault(_path);
var _appiumSupport = require('appium-support');
var _utils = require('./utils');
var openssl = _bluebird2['default'].promisify(require('openssl-wrapper').exec);
var tset = '<?xml version="1.0" encoding="UTF-8"?>\n\n <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n <plist version="1.0">\n <array/>\n</plist>';
/**
* Library for programatically adding certificates
*/
var Certificate = (function () {
function Certificate(pemFilename) {
_classCallCheck(this, Certificate);
this.pemFilename = pemFilename;
}
/**
* Interface for adding and removing records to TrustStore.sqlite3 databases that Keychains use
*/
/**
* Add a certificate to the TrustStore
*/
_createClass(Certificate, [{
key: 'add',
value: function add(dir) {
var data, subject, sha1, trustStore;
return _regeneratorRuntime.async(function add$(context$2$0) {
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
context$2$0.next = 2;
return _regeneratorRuntime.awrap(this.getDerData(this.pemFilename));
case 2:
data = context$2$0.sent.toString('hex');
context$2$0.next = 5;
return _regeneratorRuntime.awrap(this.getSubject(this.pemFilename));
case 5:
subject = context$2$0.sent;
context$2$0.next = 8;
return _regeneratorRuntime.awrap(this.getFingerPrint(this.data));
case 8:
sha1 = context$2$0.sent.toString('hex');
trustStore = new TrustStore(dir);
return context$2$0.abrupt('return', trustStore.addRecord(sha1, tset, subject, data));
case 11:
case 'end':
return context$2$0.stop();
}
}, null, this);
}
/**
* Checks if keychain at given directory has this certificate
*/
}, {
key: 'has',
value: function has(dir) {
var subject, trustStore;
return _regeneratorRuntime.async(function has$(context$2$0) {
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
context$2$0.next = 2;
return _regeneratorRuntime.awrap(this.getSubject(this.pemFilename));
case 2:
subject = context$2$0.sent;
trustStore = new TrustStore(dir);
context$2$0.next = 6;
return _regeneratorRuntime.awrap(trustStore.hasRecords(subject));
case 6:
return context$2$0.abrupt('return', context$2$0.sent);
case 7:
case 'end':
return context$2$0.stop();
}
}, null, this);
}
/**
* Remove certificate from the TrustStore
*/
}, {
key: 'remove',
value: function remove(dir) {
var subject, trustStore;
return _regeneratorRuntime.async(function remove$(context$2$0) {
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
context$2$0.next = 2;
return _regeneratorRuntime.awrap(this.getSubject(this.pemFilename));
case 2:
subject = context$2$0.sent;
trustStore = new TrustStore(dir);
return context$2$0.abrupt('return', trustStore.removeRecord(subject));
case 5:
case 'end':
return context$2$0.stop();
}
}, null, this);
}
/**
* Translate PEM file to DER buffer
*/
}, {
key: 'getDerData',
value: function getDerData() {
return _regeneratorRuntime.async(function getDerData$(context$2$0) {
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
if (!this.data) {
context$2$0.next = 2;
break;
}
return context$2$0.abrupt('return', this.data);
case 2:
context$2$0.next = 4;
return _regeneratorRuntime.awrap(openssl('x509', {
outform: 'der',
'in': this.pemFilename
}));
case 4:
this.data = context$2$0.sent;
return context$2$0.abrupt('return', this.data);
case 6:
case 'end':
return context$2$0.stop();
}
}, null, this);
}
/**
* Get SHA1 fingerprint from der data before
*/
}, {
key: 'getFingerPrint',
value: function getFingerPrint() {
var data, shasum;
return _regeneratorRuntime.async(function getFingerPrint$(context$2$0) {
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
if (!this.fingerprint) {
context$2$0.next = 2;
break;
}
return context$2$0.abrupt('return', this.fingerprint);
case 2:
context$2$0.next = 4;
return _regeneratorRuntime.awrap(this.getDerData());
case 4:
data = context$2$0.sent;
shasum = _crypto2['default'].createHash('sha1');
shasum.update(data);
this.fingerprint = shasum.digest();
return context$2$0.abrupt('return', this.fingerprint);
case 9:
case 'end':
return context$2$0.stop();
}
}, null, this);
}
/**
* Parse the subject from the der data
*/
}, {
key: 'getSubject',
value: function getSubject() {
var subject, subRegex;
return _regeneratorRuntime.async(function getSubject$(context$2$0) {
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
if (!this.subject) {
context$2$0.next = 2;
break;
}
return context$2$0.abrupt('return', this.subject);
case 2:
context$2$0.next = 4;
return _regeneratorRuntime.awrap(openssl('x509', {
noout: true,
subject: true,
'in': this.pemFilename
}));
case 4:
subject = context$2$0.sent;
subRegex = /^subject[\w\W]*\/CN=([\w\W]*)(\n)?/;
this.subject = subject.toString().match(subRegex)[1];
return context$2$0.abrupt('return', this.subject);
case 8:
case 'end':
return context$2$0.stop();
}
}, null, this);
}
}]);
return Certificate;
})();
var TrustStore = (function () {
function TrustStore(sharedResourceDir) {
_classCallCheck(this, TrustStore);
this.sharedResourceDir = sharedResourceDir;
}
/**
* Get TrustStore database associated with this simulator
*/
_createClass(TrustStore, [{
key: 'getDB',
value: function getDB() {
var keychainsPath;
return _regeneratorRuntime.async(function getDB$(context$2$0) {
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
if (!this.db) {
context$2$0.next = 2;
break;
}
return context$2$0.abrupt('return', this.db);
case 2:
keychainsPath = _path2['default'].resolve(this.sharedResourceDir, 'Library', 'Keychains');
context$2$0.next = 5;
return _regeneratorRuntime.awrap(_appiumSupport.fs.exists(keychainsPath));
case 5:
if (context$2$0.sent) {
context$2$0.next = 8;
break;
}
context$2$0.next = 8;
return _regeneratorRuntime.awrap((0, _appiumSupport.mkdirp)(keychainsPath));
case 8:
// Open sqlite database
this.db = _path2['default'].resolve(keychainsPath, 'TrustStore.sqlite3');
// If it doesn't have a tsettings table, create one
context$2$0.next = 11;
return _regeneratorRuntime.awrap((0, _utils.execSQLiteQuery)(this.db, 'CREATE TABLE IF NOT EXISTS tsettings (sha1 BLOB NOT NULL DEFAULT \'\', subj BLOB NOT NULL DEFAULT \'\', tset BLOB, data BLOB, PRIMARY KEY(sha1));'));
case 11:
context$2$0.prev = 11;
context$2$0.next = 14;
return _regeneratorRuntime.awrap((0, _utils.execSQLiteQuery)(this.db, 'CREATE INDEX isubj ON tsettings(subj);'));
case 14:
context$2$0.next = 18;
break;
case 16:
context$2$0.prev = 16;
context$2$0.t0 = context$2$0['catch'](11);
case 18:
return context$2$0.abrupt('return', this.db);
case 19:
case 'end':
return context$2$0.stop();
}
}, null, this, [[11, 16]]);
}
/**
* Add record to tsettings
*/
}, {
key: 'addRecord',
value: function addRecord(sha1, tset, subj, data) {
var db;
return _regeneratorRuntime.async(function addRecord$(context$2$0) {
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
context$2$0.next = 2;
return _regeneratorRuntime.awrap(this.getDB());
case 2:
db = context$2$0.sent;
context$2$0.next = 5;
return _regeneratorRuntime.awrap(this.hasRecords(subj));
case 5:
if (!context$2$0.sent) {
context$2$0.next = 11;
break;
}
context$2$0.next = 8;
return _regeneratorRuntime.awrap((0, _utils.execSQLiteQuery)(db, 'UPDATE tsettings SET sha1=x\'?\', tset=\'?\', data=x\'?\' WHERE subj=\'?\'', sha1, tset, data, subj));
case 8:
return context$2$0.abrupt('return', context$2$0.sent);
case 11:
context$2$0.next = 13;
return _regeneratorRuntime.awrap((0, _utils.execSQLiteQuery)(db, 'INSERT INTO tsettings (sha1, subj, tset, data) VALUES (x\'?\', \'?\', \'?\', x\'?\')', sha1, subj, tset, data));
case 13:
return context$2$0.abrupt('return', context$2$0.sent);
case 14:
case 'end':
return context$2$0.stop();
}
}, null, this);
}
/**
* Remove record from tsettings
*/
}, {
key: 'removeRecord',
value: function removeRecord(subj) {
return _regeneratorRuntime.async(function removeRecord$(context$2$0) {
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
context$2$0.t0 = _regeneratorRuntime;
context$2$0.next = 3;
return _regeneratorRuntime.awrap(this.getDB());
case 3:
context$2$0.t1 = context$2$0.sent;
context$2$0.t2 = subj;
context$2$0.t3 = (0, _utils.execSQLiteQuery)(context$2$0.t1, 'DELETE FROM tsettings WHERE subj = \'?\'', context$2$0.t2);
context$2$0.next = 8;
return context$2$0.t0.awrap.call(context$2$0.t0, context$2$0.t3);
case 8:
return context$2$0.abrupt('return', context$2$0.sent);
case 9:
case 'end':
return context$2$0.stop();
}
}, null, this);
}
/**
* Get a record from tsettings
*/
}, {
key: 'hasRecords',
value: function hasRecords(subj) {
return _regeneratorRuntime.async(function hasRecords$(context$2$0) {
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
context$2$0.next = 2;
return _regeneratorRuntime.awrap(this.getRecordCount(subj));
case 2:
context$2$0.t0 = context$2$0.sent;
return context$2$0.abrupt('return', context$2$0.t0 > 0);
case 4:
case 'end':
return context$2$0.stop();
}
}, null, this);
}
}, {
key: 'getRecordCount',
value: function getRecordCount(subj) {
var result;
return _regeneratorRuntime.async(function getRecordCount$(context$2$0) {
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
context$2$0.t0 = _regeneratorRuntime;
context$2$0.next = 3;
return _regeneratorRuntime.awrap(this.getDB());
case 3:
context$2$0.t1 = context$2$0.sent;
context$2$0.t2 = subj;
context$2$0.t3 = (0, _utils.execSQLiteQuery)(context$2$0.t1, 'SELECT count(*) FROM tsettings WHERE subj = \'?\'', context$2$0.t2);
context$2$0.next = 8;
return context$2$0.t0.awrap.call(context$2$0.t0, context$2$0.t3);
case 8:
result = context$2$0.sent.stdout;
return context$2$0.abrupt('return', parseInt(result.split('=')[1], 10));
case 10:
case 'end':
return context$2$0.stop();
}
}, null, this);
}
}]);
return TrustStore;
})();
exports['default'] = Certificate;
exports.Certificate = Certificate;
exports.TrustStore = TrustStore;
// Convert 'pem' file to 'der'
// Convert 'pem' file to 'der'
// If the sim doesn't have a keychains directory, create one
//# sourceMappingURL=data:application/json;charset=utf8;base64,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QUFVLENBQUMsSUFBSSxDQUFDOzs7Ozs7Ozs7NkNBQ2hCLDRCQUFnQixFQUFFLGdGQUF3RSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUM7Ozs7Ozs7NkNBRWpILDRCQUFnQixFQUFFLDBGQUFrRixJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUM7Ozs7Ozs7Ozs7S0FFM0k7Ozs7Ozs7V0FLa0Isc0JBQUMsSUFBSTs7Ozs7OzZDQUNhLElBQUksQ0FBQyxLQUFLLEVBQUU7Ozs7NkJBQTRDLElBQUk7Ozs7Ozs7Ozs7Ozs7S0FDaEc7Ozs7Ozs7V0FLZ0Isb0JBQUMsSUFBSTs7Ozs7NkNBQ04sSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUM7Ozs7aUVBQUksQ0FBQzs7Ozs7OztLQUM3Qzs7O1dBRW9CLHdCQUFDLElBQUk7VUFDcEIsTUFBTTs7Ozs7OzZDQUFpQyxJQUFJLENBQUMsS0FBSyxFQUFFOzs7OzZCQUFxRCxJQUFJOzs7Ozs7QUFBNUcsa0JBQU0sb0JBQXlHLE1BQU07Z0RBQ2xILFFBQVEsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQzs7Ozs7OztLQUMxQzs7O1NBN0RHLFVBQVU7OztxQkFnRUQsV0FBVztRQUNqQixXQUFXLEdBQVgsV0FBVztRQUFFLFVBQVUsR0FBVixVQUFVIiwiZmlsZSI6ImxpYi9jZXJ0aWZpY2F0ZS5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBjcnlwdG8gZnJvbSAnY3J5cHRvJztcbmltcG9ydCBCIGZyb20gJ2JsdWViaXJkJztcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgZnMsIG1rZGlycCB9IGZyb20gJ2FwcGl1bS1zdXBwb3J0JztcbmltcG9ydCB7IGV4ZWNTUUxpdGVRdWVyeSB9IGZyb20gJy4vdXRpbHMnO1xuXG5jb25zdCBvcGVuc3NsID0gQi5wcm9taXNpZnkocmVxdWlyZSgnb3BlbnNzbC13cmFwcGVyJykuZXhlYyk7XG5cbmNvbnN0IHRzZXQgPSBgPD94bWwgdmVyc2lvbj1cIjEuMFwiIGVuY29kaW5nPVwiVVRGLThcIj8+XFxuXG4gICAgPCFET0NUWVBFIHBsaXN0IFBVQkxJQyBcIi0vL0FwcGxlLy9EVEQgUExJU1QgMS4wLy9FTlwiIFwiaHR0cDovL3d3dy5hcHBsZS5jb20vRFREcy9Qcm9wZXJ0eUxpc3QtMS4wLmR0ZFwiPlxuICAgIDxwbGlzdCB2ZXJzaW9uPVwiMS4wXCI+XG4gICAgPGFycmF5Lz5cbjwvcGxpc3Q+YDtcblxuLyoqXG4gKiBMaWJyYXJ5IGZvciBwcm9ncmFtYXRpY2FsbHkgYWRkaW5nIGNlcnRpZmljYXRlc1xuICovXG5jbGFzcyBDZXJ0aWZpY2F0ZSB7XG5cbiAgY29uc3RydWN0b3IgKHBlbUZpbGVuYW1lKSB7XG4gICAgdGhpcy5wZW1GaWxlbmFtZSA9IHBlbUZpbGVuYW1lO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBhIGNlcnRpZmljYXRlIHRvIHRoZSBUcnVzdFN0b3JlXG4gICAqL1xuICBhc3luYyBhZGQgKGRpcikge1xuICAgIGxldCBkYXRhID0gKGF3YWl0IHRoaXMuZ2V0RGVyRGF0YSh0aGlzLnBlbUZpbGVuYW1lKSkudG9TdHJpbmcoJ2hleCcpO1xuICAgIGxldCBzdWJqZWN0ID0gKGF3YWl0IHRoaXMuZ2V0U3ViamVjdCh0aGlzLnBlbUZpbGVuYW1lKSk7XG4gICAgbGV0IHNoYTEgPSAoYXdhaXQgdGhpcy5nZXRGaW5nZXJQcmludCh0aGlzLmRhdGEpKS50b1N0cmluZygnaGV4Jyk7XG5cbiAgICBsZXQgdHJ1c3RTdG9yZSA9IG5ldyBUcnVzdFN0b3JlKGRpcik7XG4gICAgcmV0dXJuIHRydXN0U3RvcmUuYWRkUmVjb3JkKHNoYTEsIHRzZXQsIHN1YmplY3QsIGRhdGEpO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiBrZXljaGFpbiBhdCBnaXZlbiBkaXJlY3RvcnkgaGFzIHRoaXMgY2VydGlmaWNhdGVcbiAgICovXG4gIGFzeW5jIGhhcyAoZGlyKSB7XG4gICAgbGV0IHN1YmplY3QgPSBhd2FpdCB0aGlzLmdldFN1YmplY3QodGhpcy5wZW1GaWxlbmFtZSk7XG4gICAgbGV0IHRydXN0U3RvcmUgPSBuZXcgVHJ1c3RTdG9yZShkaXIpO1xuICAgIHJldHVybiBhd2FpdCB0cnVzdFN0b3JlLmhhc1JlY29yZHMoc3ViamVjdCk7XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlIGNlcnRpZmljYXRlIGZyb20gdGhlIFRydXN0U3RvcmVcbiAgICovXG4gIGFzeW5jIHJlbW92ZSAoZGlyKSB7XG4gICAgbGV0IHN1YmplY3QgPSBhd2FpdCB0aGlzLmdldFN1YmplY3QodGhpcy5wZW1GaWxlbmFtZSk7XG4gICAgbGV0IHRydXN0U3RvcmUgPSBuZXcgVHJ1c3RTdG9yZShkaXIpO1xuICAgIHJldHVybiB0cnVzdFN0b3JlLnJlbW92ZVJlY29yZChzdWJqZWN0KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUcmFuc2xhdGUgUEVNIGZpbGUgdG8gREVSIGJ1ZmZlclxuICAgKi9cbiAgYXN5bmMgZ2V0RGVyRGF0YSAoKSB7XG4gICAgaWYgKHRoaXMuZGF0YSkge1xuICAgICAgcmV0dXJuIHRoaXMuZGF0YTtcbiAgICB9XG5cbiAgICAvLyBDb252ZXJ0ICdwZW0nIGZpbGUgdG8gJ2RlcidcbiAgICB0aGlzLmRhdGEgPSBhd2FpdCBvcGVuc3NsKCd4NTA5Jywge1xuICAgICAgb3V0Zm9ybTogJ2RlcicsXG4gICAgICBpbjogdGhpcy5wZW1GaWxlbmFtZVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHRoaXMuZGF0YTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgU0hBMSBmaW5nZXJwcmludCBmcm9tIGRlciBkYXRhIGJlZm9yZVxuICAgKi9cbiAgYXN5bmMgZ2V0RmluZ2VyUHJpbnQgKCkge1xuICAgIGlmICh0aGlzLmZpbmdlcnByaW50KSB7XG4gICAgICByZXR1cm4gdGhpcy5maW5nZXJwcmludDtcbiAgICB9XG5cbiAgICBsZXQgZGF0YSA9IGF3YWl0IHRoaXMuZ2V0RGVyRGF0YSgpO1xuICAgIGxldCBzaGFzdW0gPSBjcnlwdG8uY3JlYXRlSGFzaCgnc2hhMScpO1xuICAgIHNoYXN1bS51cGRhdGUoZGF0YSk7XG4gICAgdGhpcy5maW5nZXJwcmludCA9IHNoYXN1bS5kaWdlc3QoKTtcbiAgICByZXR1cm4gdGhpcy5maW5nZXJwcmludDtcbiAgfVxuXG4gIC8qKlxuICAgKiBQYXJzZSB0aGUgc3ViamVjdCBmcm9tIHRoZSBkZXIgZGF0YVxuICAgKi9cbiAgYXN5bmMgZ2V0U3ViamVjdCAoKSB7XG4gICAgaWYgKHRoaXMuc3ViamVjdCkge1xuICAgICAgcmV0dXJuIHRoaXMuc3ViamVjdDtcbiAgICB9XG5cbiAgICAvLyBDb252ZXJ0ICdwZW0nIGZpbGUgdG8gJ2RlcidcbiAgICBsZXQgc3ViamVjdCA9IGF3YWl0IG9wZW5zc2woJ3g1MDknLCB7XG4gICAgICBub291dDogdHJ1ZSxcbiAgICAgIHN1YmplY3Q6IHRydWUsXG4gICAgICBpbjogdGhpcy5wZW1GaWxlbmFtZVxuICAgIH0pO1xuICAgIGxldCBzdWJSZWdleCA9IC9ec3ViamVjdFtcXHdcXFddKlxcL0NOPShbXFx3XFxXXSopKFxcbik/LztcbiAgICB0aGlzLnN1YmplY3QgPSBzdWJqZWN0LnRvU3RyaW5nKCkubWF0Y2goc3ViUmVnZXgpWzFdO1xuICAgIHJldHVybiB0aGlzLnN1YmplY3Q7XG4gIH1cblxufVxuXG4vKipcbiAqIEludGVyZmFjZSBmb3IgYWRkaW5nIGFuZCByZW1vdmluZyByZWNvcmRzIHRvIFRydXN0U3RvcmUuc3FsaXRlMyBkYXRhYmFzZXMgdGhhdCBLZXljaGFpbnMgdXNlXG4gKi9cbmNsYXNzIFRydXN0U3RvcmUge1xuICBjb25zdHJ1Y3RvciAoc2hhcmVkUmVzb3VyY2VEaXIpIHtcbiAgICB0aGlzLnNoYXJlZFJlc291cmNlRGlyID0gc2hhcmVkUmVzb3VyY2VEaXI7XG4gIH1cblxuICAvKipcbiAgICogR2V0IFRydXN0U3RvcmUgZGF0YWJhc2UgYXNzb2NpYXRlZCB3aXRoIHRoaXMgc2ltdWxhdG9yXG4gICAqL1xuICBhc3luYyBnZXREQiAoKSB7XG4gICAgaWYgKHRoaXMuZGIpIHtcbiAgICAgIHJldHVybiB0aGlzLmRiO1xuICAgIH1cblxuICAgIC8vIElmIHRoZSBzaW0gZG9lc24ndCBoYXZlIGEga2V5Y2hhaW5zIGRpcmVjdG9yeSwgY3JlYXRlIG9uZVxuICAgIGxldCBrZXljaGFpbnNQYXRoID0gcGF0aC5yZXNvbHZlKHRoaXMuc2hhcmVkUmVzb3VyY2VEaXIsICdMaWJyYXJ5JywgJ0tleWNoYWlucycpO1xuICAgIGlmICghKGF3YWl0IGZzLmV4aXN0cyhrZXljaGFpbnNQYXRoKSkpIHtcbiAgICAgIGF3YWl0IG1rZGlycChrZXljaGFpbnNQYXRoKTtcbiAgICB9XG5cbiAgICAvLyBPcGVuIHNxbGl0ZSBkYXRhYmFzZVxuICAgIHRoaXMuZGIgPSBwYXRoLnJlc29sdmUoa2V5Y2hhaW5zUGF0aCwgJ1RydXN0U3RvcmUuc3FsaXRlMycpO1xuXG4gICAgLy8gSWYgaXQgZG9lc24ndCBoYXZlIGEgdHNldHRpbmdzIHRhYmxlLCBjcmVhdGUgb25lXG4gICAgYXdhaXQgZXhlY1NRTGl0ZVF1ZXJ5KHRoaXMuZGIsIGBDUkVBVEUgVEFCTEUgSUYgTk9UIEVYSVNUUyB0c2V0dGluZ3MgKHNoYTEgQkxPQiBOT1QgTlVMTCBERUZBVUxUICcnLCBzdWJqIEJMT0IgTk9UIE5VTEwgREVGQVVMVCAnJywgdHNldCBCTE9CLCBkYXRhIEJMT0IsIFBSSU1BUlkgS0VZKHNoYTEpKTtgKTtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgZXhlY1NRTGl0ZVF1ZXJ5KHRoaXMuZGIsICdDUkVBVEUgSU5ERVggaXN1YmogT04gdHNldHRpbmdzKHN1YmopOycpO1xuICAgIH0gY2F0Y2ggKGUpIHsgfVxuXG5cbiAgICByZXR1cm4gdGhpcy5kYjtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgcmVjb3JkIHRvIHRzZXR0aW5nc1xuICAgKi9cbiAgYXN5bmMgYWRkUmVjb3JkIChzaGExLCB0c2V0LCBzdWJqLCBkYXRhKSB7XG4gICAgbGV0IGRiID0gYXdhaXQgdGhpcy5nZXREQigpO1xuICAgIGlmIChhd2FpdCB0aGlzLmhhc1JlY29yZHMoc3ViaikpIHtcbiAgICAgIHJldHVybiBhd2FpdCBleGVjU1FMaXRlUXVlcnkoZGIsIGBVUERBVEUgdHNldHRpbmdzIFNFVCBzaGExPXgnPycsIHRzZXQ9Jz8nLCBkYXRhPXgnPycgV0hFUkUgc3Viaj0nPydgLCBzaGExLCB0c2V0LCBkYXRhLCBzdWJqKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGF3YWl0IGV4ZWNTUUxpdGVRdWVyeShkYiwgYElOU0VSVCBJTlRPIHRzZXR0aW5ncyAoc2hhMSwgc3ViaiwgdHNldCwgZGF0YSkgVkFMVUVTICh4Jz8nLCAnPycsICc/JywgeCc/JylgLCBzaGExLCBzdWJqLCB0c2V0LCBkYXRhKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlIHJlY29yZCBmcm9tIHRzZXR0aW5nc1xuICAgKi9cbiAgYXN5bmMgcmVtb3ZlUmVjb3JkIChzdWJqKSB7XG4gICAgcmV0dXJuIGF3YWl0IGV4ZWNTUUxpdGVRdWVyeShhd2FpdCB0aGlzLmdldERCKCksIGBERUxFVEUgRlJPTSB0c2V0dGluZ3MgV0hFUkUgc3ViaiA9ICc/J2AsIHN1YmopO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBhIHJlY29yZCBmcm9tIHRzZXR0aW5nc1xuICAgKi9cbiAgYXN5bmMgaGFzUmVjb3JkcyAoc3Viaikge1xuICAgIHJldHVybiAoYXdhaXQgdGhpcy5nZXRSZWNvcmRDb3VudChzdWJqKSkgPiAwO1xuICB9XG5cbiAgYXN5bmMgZ2V0UmVjb3JkQ291bnQgKHN1YmopIHtcbiAgICBsZXQgcmVzdWx0ID0gIChhd2FpdCBleGVjU1FMaXRlUXVlcnkoYXdhaXQgdGhpcy5nZXREQigpLCBgU0VMRUNUIGNvdW50KCopIEZST00gdHNldHRpbmdzIFdIRVJFIHN1YmogPSAnPydgLCBzdWJqKSkuc3Rkb3V0O1xuICAgIHJldHVybiBwYXJzZUludChyZXN1bHQuc3BsaXQoJz0nKVsxXSwgMTApO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IENlcnRpZmljYXRlO1xuZXhwb3J0IHsgQ2VydGlmaWNhdGUsIFRydXN0U3RvcmUgfTtcbiJdLCJzb3VyY2VSb290IjoiLi4vLi4ifQ==