PATH: /home/hwyuvbry/public_html/kerbau/assets/vendor/libs/datatables-buttons
FILE_BARU
CREATE
FOLDER_BARU
MKDIR
UPLOAD_FILE
GO
[ .. KEMBALI ]
📄 buttons.colVis.js
↓
X
📄 buttons.colVis.js.LICENSE.txt
↓
X
📄 buttons.html5.js
↓
X
📄 buttons.html5.js.LICENSE.txt
↓
X
📄 buttons.print.js
↓
X
📄 buttons.print.js.LICENSE.txt
↓
X
📄 datatables-buttons.js
↓
X
📄 datatables-buttons.js.LICENSE.txt
↓
X
SAVING...
BERHASIL DIUBAH!
EDITING: buttons.print.js
/* * ATTENTION: An "eval-source-map" devtool has been used. * This devtool is neither made for production nor for readable output files. * It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools. * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) * or disable the default devtool with "devtool: false". * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). */ /******/ (function() { // webpackBootstrap /******/ var __webpack_modules__ = ({ /***/ "./libs/datatables-buttons/buttons.print.js": /*!**************************************************!*\ !*** ./libs/datatables-buttons/buttons.print.js ***! \**************************************************/ /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony import */ var datatables_net_buttons_js_buttons_print__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! datatables.net-buttons/js/buttons.print */ "./node_modules/datatables.net-buttons/js/buttons.print.js"); /* harmony import */ var datatables_net_buttons_js_buttons_print__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(datatables_net_buttons_js_buttons_print__WEBPACK_IMPORTED_MODULE_0__); /***/ }), /***/ "./node_modules/datatables.net-buttons/js/buttons.print.js": /*!*****************************************************************!*\ !*** ./node_modules/datatables.net-buttons/js/buttons.print.js ***! \*****************************************************************/ /***/ (function(module, exports, __webpack_require__) { eval("var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!\n * Print button for Buttons and DataTables.\n * 2016 SpryMedia Ltd - datatables.net/license\n */\n\n(function( factory ){\n\tif ( true ) {\n\t\t// AMD\n\t\t!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! jquery */ \"jquery\"), __webpack_require__(/*! datatables.net */ \"datatables.net\"), __webpack_require__(/*! datatables.net-buttons */ \"./node_modules/datatables.net-buttons/js/dataTables.buttons.js\")], __WEBPACK_AMD_DEFINE_RESULT__ = (function ( $ ) {\n\t\t\treturn factory( $, window, document );\n\t\t}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),\n\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n\t}\n\telse {}\n}(function( $, window, document, undefined ) {\n'use strict';\nvar DataTable = $.fn.dataTable;\n\n\nvar _link = document.createElement( 'a' );\n\n/**\n * Clone link and style tags, taking into account the need to change the source\n * path.\n *\n * @param {node} el Element to convert\n */\nvar _styleToAbs = function( el ) {\n\tvar url;\n\tvar clone = $(el).clone()[0];\n\tvar linkHost;\n\n\tif ( clone.nodeName.toLowerCase() === 'link' ) {\n\t\tclone.href = _relToAbs( clone.href );\n\t}\n\n\treturn clone.outerHTML;\n};\n\n/**\n * Convert a URL from a relative to an absolute address so it will work\n * correctly in the popup window which has no base URL.\n *\n * @param {string} href URL\n */\nvar _relToAbs = function( href ) {\n\t// Assign to a link on the original page so the browser will do all the\n\t// hard work of figuring out where the file actually is\n\t_link.href = href;\n\tvar linkHost = _link.host;\n\n\t// IE doesn't have a trailing slash on the host\n\t// Chrome has it on the pathname\n\tif ( linkHost.indexOf('/') === -1 && _link.pathname.indexOf('/') !== 0) {\n\t\tlinkHost += '/';\n\t}\n\n\treturn _link.protocol+\"//\"+linkHost+_link.pathname+_link.search;\n};\n\n\nDataTable.ext.buttons.print = {\n\tclassName: 'buttons-print',\n\n\ttext: function ( dt ) {\n\t\treturn dt.i18n( 'buttons.print', 'Print' );\n\t},\n\n\taction: function ( e, dt, button, config ) {\n\t\tvar data = dt.buttons.exportData(\n\t\t\t$.extend( {decodeEntities: false}, config.exportOptions ) // XSS protection\n\t\t);\n\t\tvar exportInfo = dt.buttons.exportInfo( config );\n\t\tvar columnClasses = dt\n\t\t\t.columns( config.exportOptions.columns )\n\t\t\t.flatten()\n\t\t\t.map( function (idx) {\n\t\t\t\treturn dt.settings()[0].aoColumns[dt.column(idx).index()].sClass;\n\t\t\t} )\n\t\t\t.toArray();\n\n\t\tvar addRow = function ( d, tag ) {\n\t\t\tvar str = '<tr>';\n\n\t\t\tfor ( var i=0, ien=d.length ; i<ien ; i++ ) {\n\t\t\t\t// null and undefined aren't useful in the print output\n\t\t\t\tvar dataOut = d[i] === null || d[i] === undefined ?\n\t\t\t\t\t'' :\n\t\t\t\t\td[i];\n\t\t\t\tvar classAttr = columnClasses[i] ?\n\t\t\t\t\t'class=\"'+columnClasses[i]+'\"' :\n\t\t\t\t\t'';\n\n\t\t\t\tstr += '<'+tag+' '+classAttr+'>'+dataOut+'</'+tag+'>';\n\t\t\t}\n\n\t\t\treturn str + '</tr>';\n\t\t};\n\n\t\t// Construct a table for printing\n\t\tvar html = '<table class=\"'+dt.table().node().className+'\">';\n\n\t\tif ( config.header ) {\n\t\t\thtml += '<thead>'+ addRow( data.header, 'th' ) +'</thead>';\n\t\t}\n\n\t\thtml += '<tbody>';\n\t\tfor ( var i=0, ien=data.body.length ; i<ien ; i++ ) {\n\t\t\thtml += addRow( data.body[i], 'td' );\n\t\t}\n\t\thtml += '</tbody>';\n\n\t\tif ( config.footer && data.footer ) {\n\t\t\thtml += '<tfoot>'+ addRow( data.footer, 'th' ) +'</tfoot>';\n\t\t}\n\t\thtml += '</table>';\n\n\t\t// Open a new window for the printable table\n\t\tvar win = window.open( '', '' );\n\n\t\tif (! win) {\n\t\t\tdt.buttons.info(\n\t\t\t\tdt.i18n( 'buttons.printErrorTitle', 'Unable to open print view' ),\n\t\t\t\tdt.i18n( 'buttons.printErrorMsg', 'Please allow popups in your browser for this site to be able to view the print view.' ),\n\t\t\t\t5000\n\t\t\t);\n\n\t\t\treturn;\n\t\t}\n\n\t\twin.document.close();\n\n\t\t// Inject the title and also a copy of the style and link tags from this\n\t\t// document so the table can retain its base styling. Note that we have\n\t\t// to use string manipulation as IE won't allow elements to be created\n\t\t// in the host document and then appended to the new window.\n\t\tvar head = '<title>'+exportInfo.title+'</title>';\n\t\t$('style, link').each( function () {\n\t\t\thead += _styleToAbs( this );\n\t\t} );\n\n\t\ttry {\n\t\t\twin.document.head.innerHTML = head; // Work around for Edge\n\t\t}\n\t\tcatch (e) {\n\t\t\t$(win.document.head).html( head ); // Old IE\n\t\t}\n\n\t\t// Inject the table and other surrounding information\n\t\twin.document.body.innerHTML =\n\t\t\t'<h1>'+exportInfo.title+'</h1>'+\n\t\t\t'<div>'+(exportInfo.messageTop || '')+'</div>'+\n\t\t\thtml+\n\t\t\t'<div>'+(exportInfo.messageBottom || '')+'</div>';\n\n\t\t$(win.document.body).addClass('dt-print-view');\n\n\t\t$('img', win.document.body).each( function ( i, img ) {\n\t\t\timg.setAttribute( 'src', _relToAbs( img.getAttribute('src') ) );\n\t\t} );\n\n\t\tif ( config.customize ) {\n\t\t\tconfig.customize( win, config, dt );\n\t\t}\n\n\t\t// Allow stylesheets time to load\n\t\tvar autoPrint = function () {\n\t\t\tif ( config.autoPrint ) {\n\t\t\t\twin.print(); // blocking - so close will not\n\t\t\t\twin.close(); // execute until this is done\n\t\t\t}\n\t\t};\n\n\t\tif ( navigator.userAgent.match(/Trident\\/\\d.\\d/) ) { // IE needs to call this without a setTimeout\n\t\t\tautoPrint();\n\t\t}\n\t\telse {\n\t\t\twin.setTimeout( autoPrint, 1000 );\n\t\t}\n\t},\n\n\ttitle: '*',\n\n\tmessageTop: '*',\n\n\tmessageBottom: '*',\n\n\texportOptions: {},\n\n\theader: true,\n\n\tfooter: false,\n\n\tautoPrint: true,\n\n\tcustomize: null\n};\n\n\nreturn DataTable.Buttons;\n}));\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvZGF0YXRhYmxlcy5uZXQtYnV0dG9ucy9qcy9idXR0b25zLnByaW50LmpzLmpzIiwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsTUFBTSxJQUEwQztBQUNoRDtBQUNBLEVBQUUsaUNBQVEsQ0FBQywyQ0FBUSxFQUFFLDJEQUFnQixFQUFFLG1IQUF3QixDQUFDLG1DQUFFO0FBQ2xFO0FBQ0EsR0FBRztBQUFBLGtHQUFFO0FBQ0w7QUFDQSxNQUFNLEVBcUJKO0FBQ0YsQ0FBQztBQUNEO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSxVQUFVO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLFFBQVE7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsY0FBYyxzQkFBc0I7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTs7QUFFQSxpQ0FBaUMsUUFBUTtBQUN6QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSx3Q0FBd0MsUUFBUTtBQUNoRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQSx1Q0FBdUM7QUFDdkM7QUFDQTtBQUNBLHNDQUFzQztBQUN0Qzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQixpQkFBaUI7QUFDakI7QUFDQTs7QUFFQSx1REFBdUQ7QUFDdkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7O0FBRUE7O0FBRUEsa0JBQWtCOztBQUVsQjs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBLENBQUMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9WdWV4eS8uL25vZGVfbW9kdWxlcy9kYXRhdGFibGVzLm5ldC1idXR0b25zL2pzL2J1dHRvbnMucHJpbnQuanM/NGZiYyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiFcbiAqIFByaW50IGJ1dHRvbiBmb3IgQnV0dG9ucyBhbmQgRGF0YVRhYmxlcy5cbiAqIDIwMTYgU3ByeU1lZGlhIEx0ZCAtIGRhdGF0YWJsZXMubmV0L2xpY2Vuc2VcbiAqL1xuXG4oZnVuY3Rpb24oIGZhY3RvcnkgKXtcblx0aWYgKCB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgKSB7XG5cdFx0Ly8gQU1EXG5cdFx0ZGVmaW5lKCBbJ2pxdWVyeScsICdkYXRhdGFibGVzLm5ldCcsICdkYXRhdGFibGVzLm5ldC1idXR0b25zJ10sIGZ1bmN0aW9uICggJCApIHtcblx0XHRcdHJldHVybiBmYWN0b3J5KCAkLCB3aW5kb3csIGRvY3VtZW50ICk7XG5cdFx0fSApO1xuXHR9XG5cdGVsc2UgaWYgKCB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgKSB7XG5cdFx0Ly8gQ29tbW9uSlNcblx0XHRtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChyb290LCAkKSB7XG5cdFx0XHRpZiAoICEgcm9vdCApIHtcblx0XHRcdFx0cm9vdCA9IHdpbmRvdztcblx0XHRcdH1cblxuXHRcdFx0aWYgKCAhICQgfHwgISAkLmZuLmRhdGFUYWJsZSApIHtcblx0XHRcdFx0JCA9IHJlcXVpcmUoJ2RhdGF0YWJsZXMubmV0Jykocm9vdCwgJCkuJDtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCAhICQuZm4uZGF0YVRhYmxlLkJ1dHRvbnMgKSB7XG5cdFx0XHRcdHJlcXVpcmUoJ2RhdGF0YWJsZXMubmV0LWJ1dHRvbnMnKShyb290LCAkKTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGZhY3RvcnkoICQsIHJvb3QsIHJvb3QuZG9jdW1lbnQgKTtcblx0XHR9O1xuXHR9XG5cdGVsc2Uge1xuXHRcdC8vIEJyb3dzZXJcblx0XHRmYWN0b3J5KCBqUXVlcnksIHdpbmRvdywgZG9jdW1lbnQgKTtcblx0fVxufShmdW5jdGlvbiggJCwgd2luZG93LCBkb2N1bWVudCwgdW5kZWZpbmVkICkge1xuJ3VzZSBzdHJpY3QnO1xudmFyIERhdGFUYWJsZSA9ICQuZm4uZGF0YVRhYmxlO1xuXG5cbnZhciBfbGluayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoICdhJyApO1xuXG4vKipcbiAqIENsb25lIGxpbmsgYW5kIHN0eWxlIHRhZ3MsIHRha2luZyBpbnRvIGFjY291bnQgdGhlIG5lZWQgdG8gY2hhbmdlIHRoZSBzb3VyY2VcbiAqIHBhdGguXG4gKlxuICogQHBhcmFtICB7bm9kZX0gICAgIGVsIEVsZW1lbnQgdG8gY29udmVydFxuICovXG52YXIgX3N0eWxlVG9BYnMgPSBmdW5jdGlvbiggZWwgKSB7XG5cdHZhciB1cmw7XG5cdHZhciBjbG9uZSA9ICQoZWwpLmNsb25lKClbMF07XG5cdHZhciBsaW5rSG9zdDtcblxuXHRpZiAoIGNsb25lLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09ICdsaW5rJyApIHtcblx0XHRjbG9uZS5ocmVmID0gX3JlbFRvQWJzKCBjbG9uZS5ocmVmICk7XG5cdH1cblxuXHRyZXR1cm4gY2xvbmUub3V0ZXJIVE1MO1xufTtcblxuLyoqXG4gKiBDb252ZXJ0IGEgVVJMIGZyb20gYSByZWxhdGl2ZSB0byBhbiBhYnNvbHV0ZSBhZGRyZXNzIHNvIGl0IHdpbGwgd29ya1xuICogY29ycmVjdGx5IGluIHRoZSBwb3B1cCB3aW5kb3cgd2hpY2ggaGFzIG5vIGJhc2UgVVJMLlxuICpcbiAqIEBwYXJhbSAge3N0cmluZ30gaHJlZiBVUkxcbiAqL1xudmFyIF9yZWxUb0FicyA9IGZ1bmN0aW9uKCBocmVmICkge1xuXHQvLyBBc3NpZ24gdG8gYSBsaW5rIG9uIHRoZSBvcmlnaW5hbCBwYWdlIHNvIHRoZSBicm93c2VyIHdpbGwgZG8gYWxsIHRoZVxuXHQvLyBoYXJkIHdvcmsgb2YgZmlndXJpbmcgb3V0IHdoZXJlIHRoZSBmaWxlIGFjdHVhbGx5IGlzXG5cdF9saW5rLmhyZWYgPSBocmVmO1xuXHR2YXIgbGlua0hvc3QgPSBfbGluay5ob3N0O1xuXG5cdC8vIElFIGRvZXNuJ3QgaGF2ZSBhIHRyYWlsaW5nIHNsYXNoIG9uIHRoZSBob3N0XG5cdC8vIENocm9tZSBoYXMgaXQgb24gdGhlIHBhdGhuYW1lXG5cdGlmICggbGlua0hvc3QuaW5kZXhPZignLycpID09PSAtMSAmJiBfbGluay5wYXRobmFtZS5pbmRleE9mKCcvJykgIT09IDApIHtcblx0XHRsaW5rSG9zdCArPSAnLyc7XG5cdH1cblxuXHRyZXR1cm4gX2xpbmsucHJvdG9jb2wrXCIvL1wiK2xpbmtIb3N0K19saW5rLnBhdGhuYW1lK19saW5rLnNlYXJjaDtcbn07XG5cblxuRGF0YVRhYmxlLmV4dC5idXR0b25zLnByaW50ID0ge1xuXHRjbGFzc05hbWU6ICdidXR0b25zLXByaW50JyxcblxuXHR0ZXh0OiBmdW5jdGlvbiAoIGR0ICkge1xuXHRcdHJldHVybiBkdC5pMThuKCAnYnV0dG9ucy5wcmludCcsICdQcmludCcgKTtcblx0fSxcblxuXHRhY3Rpb246IGZ1bmN0aW9uICggZSwgZHQsIGJ1dHRvbiwgY29uZmlnICkge1xuXHRcdHZhciBkYXRhID0gZHQuYnV0dG9ucy5leHBvcnREYXRhKFxuXHRcdFx0JC5leHRlbmQoIHtkZWNvZGVFbnRpdGllczogZmFsc2V9LCBjb25maWcuZXhwb3J0T3B0aW9ucyApIC8vIFhTUyBwcm90ZWN0aW9uXG5cdFx0KTtcblx0XHR2YXIgZXhwb3J0SW5mbyA9IGR0LmJ1dHRvbnMuZXhwb3J0SW5mbyggY29uZmlnICk7XG5cdFx0dmFyIGNvbHVtbkNsYXNzZXMgPSBkdFxuXHRcdFx0LmNvbHVtbnMoIGNvbmZpZy5leHBvcnRPcHRpb25zLmNvbHVtbnMgKVxuXHRcdFx0LmZsYXR0ZW4oKVxuXHRcdFx0Lm1hcCggZnVuY3Rpb24gKGlkeCkge1xuXHRcdFx0XHRyZXR1cm4gZHQuc2V0dGluZ3MoKVswXS5hb0NvbHVtbnNbZHQuY29sdW1uKGlkeCkuaW5kZXgoKV0uc0NsYXNzO1xuXHRcdFx0fSApXG5cdFx0XHQudG9BcnJheSgpO1xuXG5cdFx0dmFyIGFkZFJvdyA9IGZ1bmN0aW9uICggZCwgdGFnICkge1xuXHRcdFx0dmFyIHN0ciA9ICc8dHI+JztcblxuXHRcdFx0Zm9yICggdmFyIGk9MCwgaWVuPWQubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRcdC8vIG51bGwgYW5kIHVuZGVmaW5lZCBhcmVuJ3QgdXNlZnVsIGluIHRoZSBwcmludCBvdXRwdXRcblx0XHRcdFx0dmFyIGRhdGFPdXQgPSBkW2ldID09PSBudWxsIHx8IGRbaV0gPT09IHVuZGVmaW5lZCA/XG5cdFx0XHRcdFx0JycgOlxuXHRcdFx0XHRcdGRbaV07XG5cdFx0XHRcdHZhciBjbGFzc0F0dHIgPSBjb2x1bW5DbGFzc2VzW2ldID9cblx0XHRcdFx0XHQnY2xhc3M9XCInK2NvbHVtbkNsYXNzZXNbaV0rJ1wiJyA6XG5cdFx0XHRcdFx0Jyc7XG5cblx0XHRcdFx0c3RyICs9ICc8Jyt0YWcrJyAnK2NsYXNzQXR0cisnPicrZGF0YU91dCsnPC8nK3RhZysnPic7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBzdHIgKyAnPC90cj4nO1xuXHRcdH07XG5cblx0XHQvLyBDb25zdHJ1Y3QgYSB0YWJsZSBmb3IgcHJpbnRpbmdcblx0XHR2YXIgaHRtbCA9ICc8dGFibGUgY2xhc3M9XCInK2R0LnRhYmxlKCkubm9kZSgpLmNsYXNzTmFtZSsnXCI+JztcblxuXHRcdGlmICggY29uZmlnLmhlYWRlciApIHtcblx0XHRcdGh0bWwgKz0gJzx0aGVhZD4nKyBhZGRSb3coIGRhdGEuaGVhZGVyLCAndGgnICkgKyc8L3RoZWFkPic7XG5cdFx0fVxuXG5cdFx0aHRtbCArPSAnPHRib2R5Pic7XG5cdFx0Zm9yICggdmFyIGk9MCwgaWVuPWRhdGEuYm9keS5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdGh0bWwgKz0gYWRkUm93KCBkYXRhLmJvZHlbaV0sICd0ZCcgKTtcblx0XHR9XG5cdFx0aHRtbCArPSAnPC90Ym9keT4nO1xuXG5cdFx0aWYgKCBjb25maWcuZm9vdGVyICYmIGRhdGEuZm9vdGVyICkge1xuXHRcdFx0aHRtbCArPSAnPHRmb290PicrIGFkZFJvdyggZGF0YS5mb290ZXIsICd0aCcgKSArJzwvdGZvb3Q+Jztcblx0XHR9XG5cdFx0aHRtbCArPSAnPC90YWJsZT4nO1xuXG5cdFx0Ly8gT3BlbiBhIG5ldyB3aW5kb3cgZm9yIHRoZSBwcmludGFibGUgdGFibGVcblx0XHR2YXIgd2luID0gd2luZG93Lm9wZW4oICcnLCAnJyApO1xuXG5cdFx0aWYgKCEgd2luKSB7XG5cdFx0XHRkdC5idXR0b25zLmluZm8oXG5cdFx0XHRcdGR0LmkxOG4oICdidXR0b25zLnByaW50RXJyb3JUaXRsZScsICdVbmFibGUgdG8gb3BlbiBwcmludCB2aWV3JyApLFxuXHRcdFx0XHRkdC5pMThuKCAnYnV0dG9ucy5wcmludEVycm9yTXNnJywgJ1BsZWFzZSBhbGxvdyBwb3B1cHMgaW4geW91ciBicm93c2VyIGZvciB0aGlzIHNpdGUgdG8gYmUgYWJsZSB0byB2aWV3IHRoZSBwcmludCB2aWV3LicgKSxcblx0XHRcdFx0NTAwMFxuXHRcdFx0KTtcblxuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHdpbi5kb2N1bWVudC5jbG9zZSgpO1xuXG5cdFx0Ly8gSW5qZWN0IHRoZSB0aXRsZSBhbmQgYWxzbyBhIGNvcHkgb2YgdGhlIHN0eWxlIGFuZCBsaW5rIHRhZ3MgZnJvbSB0aGlzXG5cdFx0Ly8gZG9jdW1lbnQgc28gdGhlIHRhYmxlIGNhbiByZXRhaW4gaXRzIGJhc2Ugc3R5bGluZy4gTm90ZSB0aGF0IHdlIGhhdmVcblx0XHQvLyB0byB1c2Ugc3RyaW5nIG1hbmlwdWxhdGlvbiBhcyBJRSB3b24ndCBhbGxvdyBlbGVtZW50cyB0byBiZSBjcmVhdGVkXG5cdFx0Ly8gaW4gdGhlIGhvc3QgZG9jdW1lbnQgYW5kIHRoZW4gYXBwZW5kZWQgdG8gdGhlIG5ldyB3aW5kb3cuXG5cdFx0dmFyIGhlYWQgPSAnPHRpdGxlPicrZXhwb3J0SW5mby50aXRsZSsnPC90aXRsZT4nO1xuXHRcdCQoJ3N0eWxlLCBsaW5rJykuZWFjaCggZnVuY3Rpb24gKCkge1xuXHRcdFx0aGVhZCArPSBfc3R5bGVUb0FicyggdGhpcyApO1xuXHRcdH0gKTtcblxuXHRcdHRyeSB7XG5cdFx0XHR3aW4uZG9jdW1lbnQuaGVhZC5pbm5lckhUTUwgPSBoZWFkOyAvLyBXb3JrIGFyb3VuZCBmb3IgRWRnZVxuXHRcdH1cblx0XHRjYXRjaCAoZSkge1xuXHRcdFx0JCh3aW4uZG9jdW1lbnQuaGVhZCkuaHRtbCggaGVhZCApOyAvLyBPbGQgSUVcblx0XHR9XG5cblx0XHQvLyBJbmplY3QgdGhlIHRhYmxlIGFuZCBvdGhlciBzdXJyb3VuZGluZyBpbmZvcm1hdGlvblxuXHRcdHdpbi5kb2N1bWVudC5ib2R5LmlubmVySFRNTCA9XG5cdFx0XHQnPGgxPicrZXhwb3J0SW5mby50aXRsZSsnPC9oMT4nK1xuXHRcdFx0JzxkaXY+JysoZXhwb3J0SW5mby5tZXNzYWdlVG9wIHx8ICcnKSsnPC9kaXY+Jytcblx0XHRcdGh0bWwrXG5cdFx0XHQnPGRpdj4nKyhleHBvcnRJbmZvLm1lc3NhZ2VCb3R0b20gfHwgJycpKyc8L2Rpdj4nO1xuXG5cdFx0JCh3aW4uZG9jdW1lbnQuYm9keSkuYWRkQ2xhc3MoJ2R0LXByaW50LXZpZXcnKTtcblxuXHRcdCQoJ2ltZycsIHdpbi5kb2N1bWVudC5ib2R5KS5lYWNoKCBmdW5jdGlvbiAoIGksIGltZyApIHtcblx0XHRcdGltZy5zZXRBdHRyaWJ1dGUoICdzcmMnLCBfcmVsVG9BYnMoIGltZy5nZXRBdHRyaWJ1dGUoJ3NyYycpICkgKTtcblx0XHR9ICk7XG5cblx0XHRpZiAoIGNvbmZpZy5jdXN0b21pemUgKSB7XG5cdFx0XHRjb25maWcuY3VzdG9taXplKCB3aW4sIGNvbmZpZywgZHQgKTtcblx0XHR9XG5cblx0XHQvLyBBbGxvdyBzdHlsZXNoZWV0cyB0aW1lIHRvIGxvYWRcblx0XHR2YXIgYXV0b1ByaW50ID0gZnVuY3Rpb24gKCkge1xuXHRcdFx0aWYgKCBjb25maWcuYXV0b1ByaW50ICkge1xuXHRcdFx0XHR3aW4ucHJpbnQoKTsgLy8gYmxvY2tpbmcgLSBzbyBjbG9zZSB3aWxsIG5vdFxuXHRcdFx0XHR3aW4uY2xvc2UoKTsgLy8gZXhlY3V0ZSB1bnRpbCB0aGlzIGlzIGRvbmVcblx0XHRcdH1cblx0XHR9O1xuXG5cdFx0aWYgKCBuYXZpZ2F0b3IudXNlckFnZW50Lm1hdGNoKC9UcmlkZW50XFwvXFxkLlxcZC8pICkgeyAvLyBJRSBuZWVkcyB0byBjYWxsIHRoaXMgd2l0aG91dCBhIHNldFRpbWVvdXRcblx0XHRcdGF1dG9QcmludCgpO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdHdpbi5zZXRUaW1lb3V0KCBhdXRvUHJpbnQsIDEwMDAgKTtcblx0XHR9XG5cdH0sXG5cblx0dGl0bGU6ICcqJyxcblxuXHRtZXNzYWdlVG9wOiAnKicsXG5cblx0bWVzc2FnZUJvdHRvbTogJyonLFxuXG5cdGV4cG9ydE9wdGlvbnM6IHt9LFxuXG5cdGhlYWRlcjogdHJ1ZSxcblxuXHRmb290ZXI6IGZhbHNlLFxuXG5cdGF1dG9QcmludDogdHJ1ZSxcblxuXHRjdXN0b21pemU6IG51bGxcbn07XG5cblxucmV0dXJuIERhdGFUYWJsZS5CdXR0b25zO1xufSkpO1xuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/datatables.net-buttons/js/buttons.print.js\n"); /***/ }), /***/ "./node_modules/datatables.net-buttons/js/dataTables.buttons.js": /*!**********************************************************************!*\ !*** ./node_modules/datatables.net-buttons/js/dataTables.buttons.js ***! \**********************************************************************/ /***/ (function(module, exports, __webpack_require__) { eval("var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! Buttons for DataTables 2.2.3\n * ©2016-2022 SpryMedia Ltd - datatables.net/license\n */\n\n(function( factory ){\n\tif ( true ) {\n\t\t// AMD\n\t\t!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! jquery */ \"jquery\"), __webpack_require__(/*! datatables.net */ \"datatables.net\")], __WEBPACK_AMD_DEFINE_RESULT__ = (function ( $ ) {\n\t\t\treturn factory( $, window, document );\n\t\t}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),\n\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n\t}\n\telse {}\n}(function( $, window, document, undefined ) {\n'use strict';\nvar DataTable = $.fn.dataTable;\n\n\n// Used for namespacing events added to the document by each instance, so they\n// can be removed on destroy\nvar _instCounter = 0;\n\n// Button namespacing counter for namespacing events on individual buttons\nvar _buttonCounter = 0;\n\nvar _dtButtons = DataTable.ext.buttons;\n\n// Allow for jQuery slim\nfunction _fadeIn(el, duration, fn) {\n\tif ($.fn.animate) {\n\t\tel\n\t\t\t.stop()\n\t\t\t.fadeIn( duration, fn );\n\n\t}\n\telse {\n\t\tel.css('display', 'block');\n\n\t\tif (fn) {\n\t\t\tfn.call(el);\n\t\t}\n\t}\n}\n\nfunction _fadeOut(el, duration, fn) {\n\tif ($.fn.animate) {\n\t\tel\n\t\t\t.stop()\n\t\t\t.fadeOut( duration, fn );\n\t}\n\telse {\n\t\tel.css('display', 'none');\n\t\t\n\t\tif (fn) {\n\t\t\tfn.call(el);\n\t\t}\n\t}\n}\n\n/**\n * [Buttons description]\n * @param {[type]}\n * @param {[type]}\n */\nvar Buttons = function( dt, config )\n{\n\t// If not created with a `new` keyword then we return a wrapper function that\n\t// will take the settings object for a DT. This allows easy use of new instances\n\t// with the `layout` option - e.g. `topLeft: $.fn.dataTable.Buttons( ... )`.\n\tif ( !(this instanceof Buttons) ) {\n\t\treturn function (settings) {\n\t\t\treturn new Buttons( settings, dt ).container();\n\t\t};\n\t}\n\n\t// If there is no config set it to an empty object\n\tif ( typeof( config ) === 'undefined' ) {\n\t\tconfig = {};\t\n\t}\n\t\n\t// Allow a boolean true for defaults\n\tif ( config === true ) {\n\t\tconfig = {};\n\t}\n\n\t// For easy configuration of buttons an array can be given\n\tif ( Array.isArray( config ) ) {\n\t\tconfig = { buttons: config };\n\t}\n\n\tthis.c = $.extend( true, {}, Buttons.defaults, config );\n\n\t// Don't want a deep copy for the buttons\n\tif ( config.buttons ) {\n\t\tthis.c.buttons = config.buttons;\n\t}\n\n\tthis.s = {\n\t\tdt: new DataTable.Api( dt ),\n\t\tbuttons: [],\n\t\tlistenKeys: '',\n\t\tnamespace: 'dtb'+(_instCounter++)\n\t};\n\n\tthis.dom = {\n\t\tcontainer: $('<'+this.c.dom.container.tag+'/>')\n\t\t\t.addClass( this.c.dom.container.className )\n\t};\n\n\tthis._constructor();\n};\n\n\n$.extend( Buttons.prototype, {\n\t/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n\t * Public methods\n\t */\n\n\t/**\n\t * Get the action of a button\n\t * @param {int|string} Button index\n\t * @return {function}\n\t *//**\n\t * Set the action of a button\n\t * @param {node} node Button element\n\t * @param {function} action Function to set\n\t * @return {Buttons} Self for chaining\n\t */\n\taction: function ( node, action )\n\t{\n\t\tvar button = this._nodeToButton( node );\n\n\t\tif ( action === undefined ) {\n\t\t\treturn button.conf.action;\n\t\t}\n\n\t\tbutton.conf.action = action;\n\n\t\treturn this;\n\t},\n\n\t/**\n\t * Add an active class to the button to make to look active or get current\n\t * active state.\n\t * @param {node} node Button element\n\t * @param {boolean} [flag] Enable / disable flag\n\t * @return {Buttons} Self for chaining or boolean for getter\n\t */\n\tactive: function ( node, flag ) {\n\t\tvar button = this._nodeToButton( node );\n\t\tvar klass = this.c.dom.button.active;\n\t\tvar jqNode = $(button.node);\n\n\t\tif ( flag === undefined ) {\n\t\t\treturn jqNode.hasClass( klass );\n\t\t}\n\n\t\tjqNode.toggleClass( klass, flag === undefined ? true : flag );\n\n\t\treturn this;\n\t},\n\n\t/**\n\t * Add a new button\n\t * @param {object} config Button configuration object, base string name or function\n\t * @param {int|string} [idx] Button index for where to insert the button\n\t * @param {boolean} [draw=true] Trigger a draw. Set a false when adding\n\t * lots of buttons, until the last button.\n\t * @return {Buttons} Self for chaining\n\t */\n\tadd: function ( config, idx, draw )\n\t{\n\t\tvar buttons = this.s.buttons;\n\n\t\tif ( typeof idx === 'string' ) {\n\t\t\tvar split = idx.split('-');\n\t\t\tvar base = this.s;\n\n\t\t\tfor ( var i=0, ien=split.length-1 ; i<ien ; i++ ) {\n\t\t\t\tbase = base.buttons[ split[i]*1 ];\n\t\t\t}\n\n\t\t\tbuttons = base.buttons;\n\t\t\tidx = split[ split.length-1 ]*1;\n\t\t}\n\n\t\tthis._expandButton(\n\t\t\tbuttons,\n\t\t\tconfig,\n\t\t\tconfig !== undefined ? config.split : undefined,\n\t\t\t(config === undefined || config.split === undefined || config.split.length === 0) && base !== undefined,\n\t\t\tfalse,\n\t\t\tidx\n\t\t);\n\n\t\tif (draw === undefined || draw === true) {\n\t\t\tthis._draw();\n\t\t}\n\t\n\t\treturn this;\n\t},\n\n\t/**\n\t * Clear buttons from a collection and then insert new buttons\n\t */\n\tcollectionRebuild: function ( node, newButtons )\n\t{\n\t\tvar button = this._nodeToButton( node );\n\t\t\n\t\tif(newButtons !== undefined) {\n\t\t\tvar i;\n\t\t\t// Need to reverse the array\n\t\t\tfor (i=button.buttons.length-1; i>=0; i--) {\n\t\t\t\tthis.remove(button.buttons[i].node);\n\t\t\t}\n\t\n\t\t\tfor (i=0; i<newButtons.length; i++) {\n\t\t\t\tvar newBtn = newButtons[i];\n\n\t\t\t\tthis._expandButton(\n\t\t\t\t\tbutton.buttons,\n\t\t\t\t\tnewBtn,\n\t\t\t\t\tnewBtn !== undefined && newBtn.config !== undefined && newBtn.config.split !== undefined,\n\t\t\t\t\ttrue,\n\t\t\t\t\tnewBtn.parentConf !== undefined && newBtn.parentConf.split !== undefined,\n\t\t\t\t\ti,\n\t\t\t\t\tnewBtn.parentConf\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tthis._draw(button.collection, button.buttons);\n\t},\n\n\t/**\n\t * Get the container node for the buttons\n\t * @return {jQuery} Buttons node\n\t */\n\tcontainer: function ()\n\t{\n\t\treturn this.dom.container;\n\t},\n\n\t/**\n\t * Disable a button\n\t * @param {node} node Button node\n\t * @return {Buttons} Self for chaining\n\t */\n\tdisable: function ( node ) {\n\t\tvar button = this._nodeToButton( node );\n\n\t\t$(button.node)\n\t\t\t.addClass( this.c.dom.button.disabled )\n\t\t\t.attr('disabled', true);\n\n\t\treturn this;\n\t},\n\n\t/**\n\t * Destroy the instance, cleaning up event handlers and removing DOM\n\t * elements\n\t * @return {Buttons} Self for chaining\n\t */\n\tdestroy: function ()\n\t{\n\t\t// Key event listener\n\t\t$('body').off( 'keyup.'+this.s.namespace );\n\n\t\t// Individual button destroy (so they can remove their own events if\n\t\t// needed). Take a copy as the array is modified by `remove`\n\t\tvar buttons = this.s.buttons.slice();\n\t\tvar i, ien;\n\t\t\n\t\tfor ( i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\tthis.remove( buttons[i].node );\n\t\t}\n\n\t\t// Container\n\t\tthis.dom.container.remove();\n\n\t\t// Remove from the settings object collection\n\t\tvar buttonInsts = this.s.dt.settings()[0];\n\n\t\tfor ( i=0, ien=buttonInsts.length ; i<ien ; i++ ) {\n\t\t\tif ( buttonInsts.inst === this ) {\n\t\t\t\tbuttonInsts.splice( i, 1 );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t/**\n\t * Enable / disable a button\n\t * @param {node} node Button node\n\t * @param {boolean} [flag=true] Enable / disable flag\n\t * @return {Buttons} Self for chaining\n\t */\n\tenable: function ( node, flag )\n\t{\n\t\tif ( flag === false ) {\n\t\t\treturn this.disable( node );\n\t\t}\n\n\t\tvar button = this._nodeToButton( node );\n\t\t$(button.node)\n\t\t\t.removeClass( this.c.dom.button.disabled )\n\t\t\t.removeAttr('disabled');\n\n\t\treturn this;\n\t},\n\n\t/**\n\t * Get a button's index\n\t * \n\t * This is internally recursive\n\t * @param {element} node Button to get the index of\n\t * @return {string} Button index\n\t */\n\tindex: function ( node, nested, buttons )\n\t{\n\t\tif ( ! nested ) {\n\t\t\tnested = '';\n\t\t\tbuttons = this.s.buttons;\n\t\t}\n\n\t\tfor ( var i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\tvar inner = buttons[i].buttons;\n\n\t\t\tif (buttons[i].node === node) {\n\t\t\t\treturn nested + i;\n\t\t\t}\n\n\t\t\tif ( inner && inner.length ) {\n\t\t\t\tvar match = this.index(node, i + '-', inner);\n\n\t\t\t\tif (match !== null) {\n\t\t\t\t\treturn match;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t},\n\n\n\t/**\n\t * Get the instance name for the button set selector\n\t * @return {string} Instance name\n\t */\n\tname: function ()\n\t{\n\t\treturn this.c.name;\n\t},\n\n\t/**\n\t * Get a button's node of the buttons container if no button is given\n\t * @param {node} [node] Button node\n\t * @return {jQuery} Button element, or container\n\t */\n\tnode: function ( node )\n\t{\n\t\tif ( ! node ) {\n\t\t\treturn this.dom.container;\n\t\t}\n\n\t\tvar button = this._nodeToButton( node );\n\t\treturn $(button.node);\n\t},\n\n\t/**\n\t * Set / get a processing class on the selected button\n\t * @param {element} node Triggering button node\n\t * @param {boolean} flag true to add, false to remove, undefined to get\n\t * @return {boolean|Buttons} Getter value or this if a setter.\n\t */\n\tprocessing: function ( node, flag )\n\t{\n\t\tvar dt = this.s.dt;\n\t\tvar button = this._nodeToButton( node );\n\n\t\tif ( flag === undefined ) {\n\t\t\treturn $(button.node).hasClass( 'processing' );\n\t\t}\n\n\t\t$(button.node).toggleClass( 'processing', flag );\n\n\t\t$(dt.table().node()).triggerHandler( 'buttons-processing.dt', [\n\t\t\tflag, dt.button( node ), dt, $(node), button.conf\n\t\t] );\n\n\t\treturn this;\n\t},\n\n\t/**\n\t * Remove a button.\n\t * @param {node} node Button node\n\t * @return {Buttons} Self for chaining\n\t */\n\tremove: function ( node )\n\t{\n\t\tvar button = this._nodeToButton( node );\n\t\tvar host = this._nodeToHost( node );\n\t\tvar dt = this.s.dt;\n\n\t\t// Remove any child buttons first\n\t\tif ( button.buttons.length ) {\n\t\t\tfor ( var i=button.buttons.length-1 ; i>=0 ; i-- ) {\n\t\t\t\tthis.remove( button.buttons[i].node );\n\t\t\t}\n\t\t}\n\n\t\tbutton.conf.destroying = true;\n\n\t\t// Allow the button to remove event handlers, etc\n\t\tif ( button.conf.destroy ) {\n\t\t\tbutton.conf.destroy.call( dt.button(node), dt, $(node), button.conf );\n\t\t}\n\n\t\tthis._removeKey( button.conf );\n\n\t\t$(button.node).remove();\n\n\t\tvar idx = $.inArray( button, host );\n\t\thost.splice( idx, 1 );\n\n\t\treturn this;\n\t},\n\n\t/**\n\t * Get the text for a button\n\t * @param {int|string} node Button index\n\t * @return {string} Button text\n\t *//**\n\t * Set the text for a button\n\t * @param {int|string|function} node Button index\n\t * @param {string} label Text\n\t * @return {Buttons} Self for chaining\n\t */\n\ttext: function ( node, label )\n\t{\n\t\tvar button = this._nodeToButton( node );\n\t\tvar buttonLiner = this.c.dom.collection.buttonLiner;\n\t\tvar linerTag = button.inCollection && buttonLiner && buttonLiner.tag ?\n\t\t\tbuttonLiner.tag :\n\t\t\tthis.c.dom.buttonLiner.tag;\n\t\tvar dt = this.s.dt;\n\t\tvar jqNode = $(button.node);\n\t\tvar text = function ( opt ) {\n\t\t\treturn typeof opt === 'function' ?\n\t\t\t\topt( dt, jqNode, button.conf ) :\n\t\t\t\topt;\n\t\t};\n\n\t\tif ( label === undefined ) {\n\t\t\treturn text( button.conf.text );\n\t\t}\n\n\t\tbutton.conf.text = label;\n\n\t\tif ( linerTag ) {\n\t\t\tjqNode\n\t\t\t\t.children( linerTag )\n\t\t\t\t.eq(0)\n\t\t\t\t.filter(':not(.dt-down-arrow)')\n\t\t\t\t.html( text(label) );\n\t\t}\n\t\telse {\n\t\t\tjqNode.html( text(label) );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\n\t/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n\t * Constructor\n\t */\n\n\t/**\n\t * Buttons constructor\n\t * @private\n\t */\n\t_constructor: function ()\n\t{\n\t\tvar that = this;\n\t\tvar dt = this.s.dt;\n\t\tvar dtSettings = dt.settings()[0];\n\t\tvar buttons = this.c.buttons;\n\n\t\tif ( ! dtSettings._buttons ) {\n\t\t\tdtSettings._buttons = [];\n\t\t}\n\n\t\tdtSettings._buttons.push( {\n\t\t\tinst: this,\n\t\t\tname: this.c.name\n\t\t} );\n\n\t\tfor ( var i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\tthis.add( buttons[i] );\n\t\t}\n\n\t\tdt.on( 'destroy', function ( e, settings ) {\n\t\t\tif ( settings === dtSettings ) {\n\t\t\t\tthat.destroy();\n\t\t\t}\n\t\t} );\n\n\t\t// Global key event binding to listen for button keys\n\t\t$('body').on( 'keyup.'+this.s.namespace, function ( e ) {\n\t\t\tif ( ! document.activeElement || document.activeElement === document.body ) {\n\t\t\t\t// SUse a string of characters for fast lookup of if we need to\n\t\t\t\t// handle this\n\t\t\t\tvar character = String.fromCharCode(e.keyCode).toLowerCase();\n\n\t\t\t\tif ( that.s.listenKeys.toLowerCase().indexOf( character ) !== -1 ) {\n\t\t\t\t\tthat._keypress( character, e );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t},\n\n\n\t/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n\t * Private methods\n\t */\n\n\t/**\n\t * Add a new button to the key press listener\n\t * @param {object} conf Resolved button configuration object\n\t * @private\n\t */\n\t_addKey: function ( conf )\n\t{\n\t\tif ( conf.key ) {\n\t\t\tthis.s.listenKeys += $.isPlainObject( conf.key ) ?\n\t\t\t\tconf.key.key :\n\t\t\t\tconf.key;\n\t\t}\n\t},\n\n\t/**\n\t * Insert the buttons into the container. Call without parameters!\n\t * @param {node} [container] Recursive only - Insert point\n\t * @param {array} [buttons] Recursive only - Buttons array\n\t * @private\n\t */\n\t_draw: function ( container, buttons )\n\t{\n\t\tif ( ! container ) {\n\t\t\tcontainer = this.dom.container;\n\t\t\tbuttons = this.s.buttons;\n\t\t}\n\n\t\tcontainer.children().detach();\n\n\t\tfor ( var i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\tcontainer.append( buttons[i].inserter );\n\t\t\tcontainer.append( ' ' );\n\n\t\t\tif ( buttons[i].buttons && buttons[i].buttons.length ) {\n\t\t\t\tthis._draw( buttons[i].collection, buttons[i].buttons );\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Create buttons from an array of buttons\n\t * @param {array} attachTo Buttons array to attach to\n\t * @param {object} button Button definition\n\t * @param {boolean} inCollection true if the button is in a collection\n\t * @private\n\t */\n\t_expandButton: function ( attachTo, button, split, inCollection, inSplit, attachPoint, parentConf )\n\t{\n\t\tvar dt = this.s.dt;\n\t\tvar buttonCounter = 0;\n\t\tvar isSplit = false;\n\t\tvar buttons = ! Array.isArray( button ) ?\n\t\t\t[ button ] :\n\t\t\tbutton;\n\t\t\n\t\tif(button === undefined ) {\n\t\t\tbuttons = !Array.isArray(split) ?\n\t\t\t\t[ split ] :\n\t\t\t\tsplit;\n\t\t}\n\n\t\tif (button !== undefined && button.split !== undefined) {\n\t\t\tisSplit = true;\n\t\t}\n\t\t\t\n\t\tfor ( var i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\tvar conf = this._resolveExtends( buttons[i] );\n\n\t\t\tif ( ! conf ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif( conf.config !== undefined && conf.config.split) {\n\t\t\t\tisSplit = true;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tisSplit = false;\n\t\t\t}\n\t\t\t\n\t\t\t// If the configuration is an array, then expand the buttons at this\n\t\t\t// point\n\t\t\tif ( Array.isArray( conf ) ) {\n\t\t\t\tthis._expandButton( attachTo, conf, built !== undefined && built.conf !== undefined ? built.conf.split : undefined, inCollection, parentConf !== undefined && parentConf.split !== undefined, attachPoint, parentConf );\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tvar built = this._buildButton( conf, inCollection, conf.split !== undefined || (conf.config !== undefined && conf.config.split !== undefined), inSplit );\n\t\t\tif ( ! built ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( attachPoint !== undefined && attachPoint !== null ) {\n\t\t\t\tattachTo.splice( attachPoint, 0, built );\n\t\t\t\tattachPoint++;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tattachTo.push( built );\n\t\t\t}\n\n\t\t\t\n\t\t\tif ( built.conf.buttons || built.conf.split ) {\n\t\t\t\tbuilt.collection = $('<'+(isSplit ? this.c.dom.splitCollection.tag : this.c.dom.collection.tag)+'/>');\n\n\t\t\t\tbuilt.conf._collection = built.collection;\n\n\t\t\t\tif(built.conf.split) {\n\t\t\t\t\tfor(var j = 0; j < built.conf.split.length; j++) {\n\t\t\t\t\t\tif(typeof built.conf.split[j] === \"object\") {\n\t\t\t\t\t\t\tbuilt.conf.split[j].parent = parentConf;\n\t\t\t\t\t\t\tif(built.conf.split[j].collectionLayout === undefined) {\n\t\t\t\t\t\t\t\tbuilt.conf.split[j].collectionLayout = built.conf.collectionLayout;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(built.conf.split[j].dropup === undefined) {\n\t\t\t\t\t\t\t\tbuilt.conf.split[j].dropup = built.conf.dropup;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(built.conf.split[j].fade === undefined) {\n\t\t\t\t\t\t\t\tbuilt.conf.split[j].fade = built.conf.fade;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t$(built.node).append($('<span class=\"dt-down-arrow\">'+this.c.dom.splitDropdown.text+'</span>'))\n\t\t\t\t}\n\n\t\t\t\tthis._expandButton( built.buttons, built.conf.buttons, built.conf.split, !isSplit, isSplit, attachPoint, built.conf );\n\t\t\t}\n\t\t\tbuilt.conf.parent = parentConf;\n\n\t\t\t// init call is made here, rather than buildButton as it needs to\n\t\t\t// be selectable, and for that it needs to be in the buttons array\n\t\t\tif ( conf.init ) {\n\t\t\t\tconf.init.call( dt.button( built.node ), dt, $(built.node), conf );\n\t\t\t}\n\n\t\t\tbuttonCounter++;\n\t\t}\n\t},\n\n\t/**\n\t * Create an individual button\n\t * @param {object} config Resolved button configuration\n\t * @param {boolean} inCollection `true` if a collection button\n\t * @return {jQuery} Created button node (jQuery)\n\t * @private\n\t */\n\t_buildButton: function ( config, inCollection, isSplit, inSplit )\n\t{\n\t\tvar buttonDom = this.c.dom.button;\n\t\tvar linerDom = this.c.dom.buttonLiner;\n\t\tvar collectionDom = this.c.dom.collection;\n\t\tvar splitDom = this.c.dom.split;\n\t\tvar splitCollectionDom = this.c.dom.splitCollection;\n\t\tvar splitDropdownButton = this.c.dom.splitDropdownButton;\n\t\tvar dt = this.s.dt;\n\t\tvar text = function ( opt ) {\n\t\t\treturn typeof opt === 'function' ?\n\t\t\t\topt( dt, button, config ) :\n\t\t\t\topt;\n\t\t};\n\n\t\t// Spacers don't do much other than insert an element into the DOM\n\t\tif (config.spacer) {\n\t\t\tvar spacer = $('<span></span>')\n\t\t\t\t.addClass('dt-button-spacer ' + config.style + ' ' + buttonDom.spacerClass)\n\t\t\t\t.html(text(config.text));\n\n\t\t\treturn {\n\t\t\t\tconf: config,\n\t\t\t\tnode: spacer,\n\t\t\t\tinserter: spacer,\n\t\t\t\tbuttons: [],\n\t\t\t\tinCollection: inCollection,\n\t\t\t\tisSplit:\t isSplit,\n\t\t\t\tinSplit:\t inSplit,\n\t\t\t\tcollection: null\n\t\t\t};\n\t\t}\n\n\t\tif ( !isSplit && inSplit && splitCollectionDom ) {\n\t\t\tbuttonDom = splitDropdownButton;\n\t\t}\n\t\telse if ( !isSplit && inCollection && collectionDom.button ) {\n\t\t\tbuttonDom = collectionDom.button;\n\t\t} \n\n\t\tif ( !isSplit && inSplit && splitCollectionDom.buttonLiner ) {\n\t\t\tlinerDom = splitCollectionDom.buttonLiner\n\t\t}\n\t\telse if ( !isSplit && inCollection && collectionDom.buttonLiner ) {\n\t\t\tlinerDom = collectionDom.buttonLiner;\n\t\t}\n\n\t\t// Make sure that the button is available based on whatever requirements\n\t\t// it has. For example, PDF button require pdfmake\n\t\tif ( config.available && ! config.available( dt, config ) && !config.hasOwnProperty('html') ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tvar button;\n\t\tif(!config.hasOwnProperty('html')) {\n\t\t\tvar action = function ( e, dt, button, config ) {\n\t\t\t\tconfig.action.call( dt.button( button ), e, dt, button, config );\n\t\n\t\t\t\t$(dt.table().node()).triggerHandler( 'buttons-action.dt', [\n\t\t\t\t\tdt.button( button ), dt, button, config \n\t\t\t\t] );\n\t\t\t};\n\n\t\t\tvar tag = config.tag || buttonDom.tag;\n\t\t\tvar clickBlurs = config.clickBlurs === undefined\n\t\t\t\t? true :\n\t\t\t\tconfig.clickBlurs;\n\n\t\t\tbutton = $('<'+tag+'/>')\n\t\t\t\t.addClass( buttonDom.className )\n\t\t\t\t.addClass( inSplit ? this.c.dom.splitDropdownButton.className : '')\n\t\t\t\t.attr( 'tabindex', this.s.dt.settings()[0].iTabIndex )\n\t\t\t\t.attr( 'aria-controls', this.s.dt.table().node().id )\n\t\t\t\t.on( 'click.dtb', function (e) {\n\t\t\t\t\te.preventDefault();\n\t\n\t\t\t\t\tif ( ! button.hasClass( buttonDom.disabled ) && config.action ) {\n\t\t\t\t\t\taction( e, dt, button, config );\n\t\t\t\t\t}\n\t\t\t\t\tif( clickBlurs ) {\n\t\t\t\t\t\tbutton.trigger('blur');\n\t\t\t\t\t}\n\t\t\t\t} )\n\t\t\t\t.on( 'keypress.dtb', function (e) {\n\t\t\t\t\tif ( e.keyCode === 13 ) {\n\t\t\t\t\t\te.preventDefault();\n\n\t\t\t\t\t\tif ( ! button.hasClass( buttonDom.disabled ) && config.action ) {\n\t\t\t\t\t\t\taction( e, dt, button, config );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\n\t\t\t// Make `a` tags act like a link\n\t\t\tif ( tag.toLowerCase() === 'a' ) {\n\t\t\t\tbutton.attr( 'href', '#' );\n\t\t\t}\n\t\n\t\t\t// Button tags should have `type=button` so they don't have any default behaviour\n\t\t\tif ( tag.toLowerCase() === 'button' ) {\n\t\t\t\tbutton.attr( 'type', 'button' );\n\t\t\t}\n\t\n\t\t\tif ( linerDom.tag ) {\n\t\t\t\tvar liner = $('<'+linerDom.tag+'/>')\n\t\t\t\t\t.html( text( config.text ) )\n\t\t\t\t\t.addClass( linerDom.className );\n\t\n\t\t\t\tif ( linerDom.tag.toLowerCase() === 'a' ) {\n\t\t\t\t\tliner.attr( 'href', '#' );\n\t\t\t\t}\n\t\n\t\t\t\tbutton.append( liner );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbutton.html( text( config.text ) );\n\t\t\t}\n\t\n\t\t\tif ( config.enabled === false ) {\n\t\t\t\tbutton.addClass( buttonDom.disabled );\n\t\t\t}\n\t\n\t\t\tif ( config.className ) {\n\t\t\t\tbutton.addClass( config.className );\n\t\t\t}\n\t\n\t\t\tif ( config.titleAttr ) {\n\t\t\t\tbutton.attr( 'title', text( config.titleAttr ) );\n\t\t\t}\n\t\n\t\t\tif ( config.attr ) {\n\t\t\t\tbutton.attr( config.attr );\n\t\t\t}\n\t\n\t\t\tif ( ! config.namespace ) {\n\t\t\t\tconfig.namespace = '.dt-button-'+(_buttonCounter++);\n\t\t\t}\n\n\t\t\tif ( config.config !== undefined && config.config.split ) {\n\t\t\t\tconfig.split = config.config.split;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tbutton = $(config.html)\n\t\t}\n\t\n\t\tvar buttonContainer = this.c.dom.buttonContainer;\n\t\tvar inserter;\n\t\tif ( buttonContainer && buttonContainer.tag ) {\n\t\t\tinserter = $('<'+buttonContainer.tag+'/>')\n\t\t\t\t.addClass( buttonContainer.className )\n\t\t\t\t.append( button );\n\t\t}\n\t\telse {\n\t\t\tinserter = button;\n\t\t}\n\n\t\tthis._addKey( config );\n\n\t\t// Style integration callback for DOM manipulation\n\t\t// Note that this is _not_ documented. It is currently\n\t\t// for style integration only\n\t\tif( this.c.buttonCreated ) {\n\t\t\tinserter = this.c.buttonCreated( config, inserter );\n\t\t}\n\n\t\tvar splitDiv;\n\t\tif(isSplit) {\n\t\t\tsplitDiv = $('<div/>').addClass(this.c.dom.splitWrapper.className)\n\t\t\tsplitDiv.append(button);\n\t\t\tvar dropButtonConfig = $.extend(config, {\n\t\t\t\ttext: this.c.dom.splitDropdown.text,\n\t\t\t\tclassName: this.c.dom.splitDropdown.className,\n\t\t\t\tcloseButton: false,\n\t\t\t\tattr: {\n\t\t\t\t\t'aria-haspopup': 'dialog',\n\t\t\t\t\t'aria-expanded': false\n\t\t\t\t},\n\t\t\t\talign: this.c.dom.splitDropdown.align,\n\t\t\t\tsplitAlignClass: this.c.dom.splitDropdown.splitAlignClass\n\t\t\t\t\n\t\t\t})\n\n\t\t\tthis._addKey(dropButtonConfig);\n\n\t\t\tvar splitAction = function ( e, dt, button, config ) {\n\t\t\t\t_dtButtons.split.action.call( dt.button($('div.dt-btn-split-wrapper')[0] ), e, dt, button, config );\n\t\n\t\t\t\t$(dt.table().node()).triggerHandler( 'buttons-action.dt', [\n\t\t\t\t\tdt.button( button ), dt, button, config \n\t\t\t\t] );\n\t\t\t\tbutton.attr('aria-expanded', true)\n\t\t\t};\n\t\t\t\n\t\t\tvar dropButton = $('<button class=\"' + this.c.dom.splitDropdown.className + ' dt-button\"><span class=\"dt-btn-split-drop-arrow\">'+this.c.dom.splitDropdown.text+'</span></button>')\n\t\t\t\t.on( 'click.dtb', function (e) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\te.stopPropagation();\n\n\t\t\t\t\tif ( ! dropButton.hasClass( buttonDom.disabled )) {\n\t\t\t\t\t\tsplitAction( e, dt, dropButton, dropButtonConfig );\n\t\t\t\t\t}\n\t\t\t\t\tif ( clickBlurs ) {\n\t\t\t\t\t\tdropButton.trigger('blur');\n\t\t\t\t\t}\n\t\t\t\t} )\n\t\t\t\t.on( 'keypress.dtb', function (e) {\n\t\t\t\t\tif ( e.keyCode === 13 ) {\n\t\t\t\t\t\te.preventDefault();\n\n\t\t\t\t\t\tif ( ! dropButton.hasClass( buttonDom.disabled ) ) {\n\t\t\t\t\t\t\tsplitAction( e, dt, dropButton, dropButtonConfig );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\tif(config.split.length === 0) {\n\t\t\t\tdropButton.addClass('dtb-hide-drop');\n\t\t\t}\n\n\t\t\tsplitDiv.append(dropButton).attr(dropButtonConfig.attr);\n\t\t}\n\n\t\treturn {\n\t\t\tconf: config,\n\t\t\tnode: isSplit ? splitDiv.get(0) : button.get(0),\n\t\t\tinserter: isSplit ? splitDiv : inserter,\n\t\t\tbuttons: [],\n\t\t\tinCollection: inCollection,\n\t\t\tisSplit:\t isSplit,\n\t\t\tinSplit:\t inSplit,\n\t\t\tcollection: null\n\t\t};\n\t},\n\n\t/**\n\t * Get the button object from a node (recursive)\n\t * @param {node} node Button node\n\t * @param {array} [buttons] Button array, uses base if not defined\n\t * @return {object} Button object\n\t * @private\n\t */\n\t_nodeToButton: function ( node, buttons )\n\t{\n\t\tif ( ! buttons ) {\n\t\t\tbuttons = this.s.buttons;\n\t\t}\n\n\t\tfor ( var i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\tif ( buttons[i].node === node ) {\n\t\t\t\treturn buttons[i];\n\t\t\t}\n\n\t\t\tif ( buttons[i].buttons.length ) {\n\t\t\t\tvar ret = this._nodeToButton( node, buttons[i].buttons );\n\n\t\t\t\tif ( ret ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Get container array for a button from a button node (recursive)\n\t * @param {node} node Button node\n\t * @param {array} [buttons] Button array, uses base if not defined\n\t * @return {array} Button's host array\n\t * @private\n\t */\n\t_nodeToHost: function ( node, buttons )\n\t{\n\t\tif ( ! buttons ) {\n\t\t\tbuttons = this.s.buttons;\n\t\t}\n\n\t\tfor ( var i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\tif ( buttons[i].node === node ) {\n\t\t\t\treturn buttons;\n\t\t\t}\n\n\t\t\tif ( buttons[i].buttons.length ) {\n\t\t\t\tvar ret = this._nodeToHost( node, buttons[i].buttons );\n\n\t\t\t\tif ( ret ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Handle a key press - determine if any button's key configured matches\n\t * what was typed and trigger the action if so.\n\t * @param {string} character The character pressed\n\t * @param {object} e Key event that triggered this call\n\t * @private\n\t */\n\t_keypress: function ( character, e )\n\t{\n\t\t// Check if this button press already activated on another instance of Buttons\n\t\tif ( e._buttonsHandled ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar run = function ( conf, node ) {\n\t\t\tif ( ! conf.key ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( conf.key === character ) {\n\t\t\t\te._buttonsHandled = true;\n\t\t\t\t$(node).click();\n\t\t\t}\n\t\t\telse if ( $.isPlainObject( conf.key ) ) {\n\t\t\t\tif ( conf.key.key !== character ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( conf.key.shiftKey && ! e.shiftKey ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( conf.key.altKey && ! e.altKey ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( conf.key.ctrlKey && ! e.ctrlKey ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( conf.key.metaKey && ! e.metaKey ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Made it this far - it is good\n\t\t\t\te._buttonsHandled = true;\n\t\t\t\t$(node).click();\n\t\t\t}\n\t\t};\n\n\t\tvar recurse = function ( a ) {\n\t\t\tfor ( var i=0, ien=a.length ; i<ien ; i++ ) {\n\t\t\t\trun( a[i].conf, a[i].node );\n\n\t\t\t\tif ( a[i].buttons.length ) {\n\t\t\t\t\trecurse( a[i].buttons );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\trecurse( this.s.buttons );\n\t},\n\n\t/**\n\t * Remove a key from the key listener for this instance (to be used when a\n\t * button is removed)\n\t * @param {object} conf Button configuration\n\t * @private\n\t */\n\t_removeKey: function ( conf )\n\t{\n\t\tif ( conf.key ) {\n\t\t\tvar character = $.isPlainObject( conf.key ) ?\n\t\t\t\tconf.key.key :\n\t\t\t\tconf.key;\n\n\t\t\t// Remove only one character, as multiple buttons could have the\n\t\t\t// same listening key\n\t\t\tvar a = this.s.listenKeys.split('');\n\t\t\tvar idx = $.inArray( character, a );\n\t\t\ta.splice( idx, 1 );\n\t\t\tthis.s.listenKeys = a.join('');\n\t\t}\n\t},\n\n\t/**\n\t * Resolve a button configuration\n\t * @param {string|function|object} conf Button config to resolve\n\t * @return {object} Button configuration\n\t * @private\n\t */\n\t_resolveExtends: function ( conf )\n\t{\n\t\tvar that = this;\n\t\tvar dt = this.s.dt;\n\t\tvar i, ien;\n\t\tvar toConfObject = function ( base ) {\n\t\t\tvar loop = 0;\n\n\t\t\t// Loop until we have resolved to a button configuration, or an\n\t\t\t// array of button configurations (which will be iterated\n\t\t\t// separately)\n\t\t\twhile ( ! $.isPlainObject(base) && ! Array.isArray(base) ) {\n\t\t\t\tif ( base === undefined ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( typeof base === 'function' ) {\n\t\t\t\t\tbase = base.call( that, dt, conf );\n\n\t\t\t\t\tif ( ! base ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if ( typeof base === 'string' ) {\n\t\t\t\t\tif ( ! _dtButtons[ base ] ) {\n\t\t\t\t\t\treturn {html: base}\n\t\t\t\t\t}\n\n\t\t\t\t\tbase = _dtButtons[ base ];\n\t\t\t\t}\n\n\t\t\t\tloop++;\n\t\t\t\tif ( loop > 30 ) {\n\t\t\t\t\t// Protect against misconfiguration killing the browser\n\t\t\t\t\tthrow 'Buttons: Too many iterations';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn Array.isArray( base ) ?\n\t\t\t\tbase :\n\t\t\t\t$.extend( {}, base );\n\t\t};\n\n\t\tconf = toConfObject( conf );\n\n\t\twhile ( conf && conf.extend ) {\n\t\t\t// Use `toConfObject` in case the button definition being extended\n\t\t\t// is itself a string or a function\n\t\t\tif ( ! _dtButtons[ conf.extend ] ) {\n\t\t\t\tthrow 'Cannot extend unknown button type: '+conf.extend;\n\t\t\t}\n\n\t\t\tvar objArray = toConfObject( _dtButtons[ conf.extend ] );\n\t\t\tif ( Array.isArray( objArray ) ) {\n\t\t\t\treturn objArray;\n\t\t\t}\n\t\t\telse if ( ! objArray ) {\n\t\t\t\t// This is a little brutal as it might be possible to have a\n\t\t\t\t// valid button without the extend, but if there is no extend\n\t\t\t\t// then the host button would be acting in an undefined state\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Stash the current class name\n\t\t\tvar originalClassName = objArray.className;\n\n\t\t\tif (conf.config !== undefined && objArray.config !== undefined) {\n\t\t\t\tconf.config = $.extend({}, objArray.config, conf.config)\n\t\t\t}\n\n\t\t\tconf = $.extend( {}, objArray, conf );\n\n\t\t\t// The extend will have overwritten the original class name if the\n\t\t\t// `conf` object also assigned a class, but we want to concatenate\n\t\t\t// them so they are list that is combined from all extended buttons\n\t\t\tif ( originalClassName && conf.className !== originalClassName ) {\n\t\t\t\tconf.className = originalClassName+' '+conf.className;\n\t\t\t}\n\n\t\t\t// Buttons to be added to a collection -gives the ability to define\n\t\t\t// if buttons should be added to the start or end of a collection\n\t\t\tvar postfixButtons = conf.postfixButtons;\n\t\t\tif ( postfixButtons ) {\n\t\t\t\tif ( ! conf.buttons ) {\n\t\t\t\t\tconf.buttons = [];\n\t\t\t\t}\n\n\t\t\t\tfor ( i=0, ien=postfixButtons.length ; i<ien ; i++ ) {\n\t\t\t\t\tconf.buttons.push( postfixButtons[i] );\n\t\t\t\t}\n\n\t\t\t\tconf.postfixButtons = null;\n\t\t\t}\n\n\t\t\tvar prefixButtons = conf.prefixButtons;\n\t\t\tif ( prefixButtons ) {\n\t\t\t\tif ( ! conf.buttons ) {\n\t\t\t\t\tconf.buttons = [];\n\t\t\t\t}\n\n\t\t\t\tfor ( i=0, ien=prefixButtons.length ; i<ien ; i++ ) {\n\t\t\t\t\tconf.buttons.splice( i, 0, prefixButtons[i] );\n\t\t\t\t}\n\n\t\t\t\tconf.prefixButtons = null;\n\t\t\t}\n\n\t\t\t// Although we want the `conf` object to overwrite almost all of\n\t\t\t// the properties of the object being extended, the `extend`\n\t\t\t// property should come from the object being extended\n\t\t\tconf.extend = objArray.extend;\n\t\t}\n\n\t\treturn conf;\n\t},\n\n\t/**\n\t * Display (and replace if there is an existing one) a popover attached to a button\n\t * @param {string|node} content Content to show\n\t * @param {DataTable.Api} hostButton DT API instance of the button\n\t * @param {object} inOpts Options (see object below for all options)\n\t */\n\t_popover: function ( content, hostButton, inOpts, e ) {\n\t\tvar dt = hostButton;\n\t\tvar buttonsSettings = this.c;\n\t\tvar closed = false;\n\t\tvar options = $.extend( {\n\t\t\talign: 'button-left', // button-right, dt-container, split-left, split-right\n\t\t\tautoClose: false,\n\t\t\tbackground: true,\n\t\t\tbackgroundClassName: 'dt-button-background',\n\t\t\tcloseButton: true,\n\t\t\tcontentClassName: buttonsSettings.dom.collection.className,\n\t\t\tcollectionLayout: '',\n\t\t\tcollectionTitle: '',\n\t\t\tdropup: false,\n\t\t\tfade: 400,\n\t\t\tpopoverTitle: '',\n\t\t\trightAlignClassName: 'dt-button-right',\n\t\t\ttag: buttonsSettings.dom.collection.tag\n\t\t}, inOpts );\n\n\t\tvar hostNode = hostButton.node();\n\n\t\tvar close = function () {\n\t\t\tclosed = true;\n\n\t\t\t_fadeOut(\n\t\t\t\t$('.dt-button-collection'),\n\t\t\t\toptions.fade,\n\t\t\t\tfunction () {\n\t\t\t\t\t$(this).detach();\n\t\t\t\t}\n\t\t\t);\n\n\t\t\t$(dt.buttons( '[aria-haspopup=\"dialog\"][aria-expanded=\"true\"]' ).nodes())\n\t\t\t\t.attr('aria-expanded', 'false');\n\n\t\t\t$('div.dt-button-background').off( 'click.dtb-collection' );\n\t\t\tButtons.background( false, options.backgroundClassName, options.fade, hostNode );\n\n\t\t\t$(window).off('resize.resize.dtb-collection');\n\t\t\t$('body').off( '.dtb-collection' );\n\t\t\tdt.off( 'buttons-action.b-internal' );\n\t\t\tdt.off( 'destroy' );\n\t\t};\n\n\t\tif (content === false) {\n\t\t\tclose();\n\t\t\treturn;\n\t\t}\n\n\t\tvar existingExpanded = $(dt.buttons( '[aria-haspopup=\"dialog\"][aria-expanded=\"true\"]' ).nodes());\n\t\tif ( existingExpanded.length ) {\n\t\t\t// Reuse the current position if the button that was triggered is inside an existing collection\n\t\t\tif (hostNode.closest('div.dt-button-collection').length) {\n\t\t\t\thostNode = existingExpanded.eq(0);\n\t\t\t}\n\n\t\t\tclose();\n\t\t}\n\n\t\t// Try to be smart about the layout\n\t\tvar cnt = $('.dt-button', content).length;\n\t\tvar mod = '';\n\n\t\tif (cnt === 3) {\n\t\t\tmod = 'dtb-b3';\n\t\t}\n\t\telse if (cnt === 2) {\n\t\t\tmod = 'dtb-b2';\n\t\t}\n\t\telse if (cnt === 1) {\n\t\t\tmod = 'dtb-b1';\n\t\t}\n\n\t\tvar display = $('<div/>')\n\t\t\t.addClass('dt-button-collection')\n\t\t\t.addClass(options.collectionLayout)\n\t\t\t.addClass(options.splitAlignClass)\n\t\t\t.addClass(mod)\n\t\t\t.css('display', 'none')\n\t\t\t.attr({\n\t\t\t\t'aria-modal': true,\n\t\t\t\trole: 'dialog'\n\t\t\t});\n\n\t\tcontent = $(content)\n\t\t\t.addClass(options.contentClassName)\n\t\t\t.attr('role', 'menu')\n\t\t\t.appendTo(display);\n\n\t\thostNode.attr( 'aria-expanded', 'true' );\n\n\t\tif ( hostNode.parents('body')[0] !== document.body ) {\n\t\t\thostNode = document.body.lastChild;\n\t\t}\n\n\t\tif ( options.popoverTitle ) {\n\t\t\tdisplay.prepend('<div class=\"dt-button-collection-title\">'+options.popoverTitle+'</div>');\n\t\t}\n\t\telse if ( options.collectionTitle ) {\n\t\t\tdisplay.prepend('<div class=\"dt-button-collection-title\">'+options.collectionTitle+'</div>');\n\t\t}\n\n\t\tif (options.closeButton) {\n\t\t\tdisplay.prepend('<div class=\"dtb-popover-close\">x</div>').addClass('dtb-collection-closeable')\n\t\t}\n\n\t\t_fadeIn( display.insertAfter( hostNode ), options.fade );\n\n\t\tvar tableContainer = $( hostButton.table().container() );\n\t\tvar position = display.css( 'position' );\n\n\t\tif ( options.span === 'container' || options.align === 'dt-container' ) {\n\t\t\thostNode = hostNode.parent();\n\t\t\tdisplay.css('width', tableContainer.width());\n\t\t}\n\n\t\t// Align the popover relative to the DataTables container\n\t\t// Useful for wide popovers such as SearchPanes\n\t\tif (position === 'absolute') {\n\t\t\t// Align relative to the host button\n\t\t\tvar offsetParent = $(hostNode[0].offsetParent);\n\t\t\tvar buttonPosition = hostNode.position();\n\t\t\tvar buttonOffset = hostNode.offset();\n\t\t\tvar tableSizes = offsetParent.offset();\n\t\t\tvar containerPosition = offsetParent.position();\n\t\t\tvar computed = window.getComputedStyle(offsetParent[0]);\n\n\t\t\ttableSizes.height = offsetParent.outerHeight();\n\t\t\ttableSizes.width = offsetParent.width() + parseFloat(computed.paddingLeft);\n\t\t\ttableSizes.right = tableSizes.left + tableSizes.width;\n\t\t\ttableSizes.bottom = tableSizes.top + tableSizes.height;\n\n\t\t\t// Set the initial position so we can read height / width\n\t\t\tvar top = buttonPosition.top + hostNode.outerHeight();\n\t\t\tvar left = buttonPosition.left;\n\n\t\t\tdisplay.css( {\n\t\t\t\ttop: top,\n\t\t\t\tleft: left\n\t\t\t} );\n\n\t\t\t// Get the popover position\n\t\t\tcomputed = window.getComputedStyle(display[0]);\n\t\t\tvar popoverSizes = display.offset();\n\n\t\t\tpopoverSizes.height = display.outerHeight();\n\t\t\tpopoverSizes.width = display.outerWidth();\n\t\t\tpopoverSizes.right = popoverSizes.left + popoverSizes.width;\n\t\t\tpopoverSizes.bottom = popoverSizes.top + popoverSizes.height;\n\t\t\tpopoverSizes.marginTop = parseFloat(computed.marginTop);\n\t\t\tpopoverSizes.marginBottom = parseFloat(computed.marginBottom);\n\n\t\t\t// First position per the class requirements - pop up and right align\n\t\t\tif (options.dropup) {\n\t\t\t\ttop = buttonPosition.top - popoverSizes.height - popoverSizes.marginTop - popoverSizes.marginBottom;\n\t\t\t}\n\n\t\t\tif (options.align === 'button-right' || display.hasClass( options.rightAlignClassName )) {\n\t\t\t\tleft = buttonPosition.left - popoverSizes.width + hostNode.outerWidth(); \n\t\t\t}\n\n\t\t\t// Container alignment - make sure it doesn't overflow the table container\n\t\t\tif (options.align === 'dt-container' || options.align === 'container') {\n\t\t\t\tif (left < buttonPosition.left) {\n\t\t\t\t\tleft = -buttonPosition.left;\n\t\t\t\t}\n\n\t\t\t\tif (left + popoverSizes.width > tableSizes.width) {\n\t\t\t\t\tleft = tableSizes.width - popoverSizes.width;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Window adjustment\n\t\t\tif (containerPosition.left + left + popoverSizes.width > $(window).width()) {\n\t\t\t\t// Overflowing the document to the right\n\t\t\t\tleft = $(window).width() - popoverSizes.width - containerPosition.left;\n\t\t\t}\n\n\t\t\tif (buttonOffset.left + left < 0) {\n\t\t\t\t// Off to the left of the document\n\t\t\t\tleft = -buttonOffset.left;\n\t\t\t}\n\n\t\t\tif (containerPosition.top + top + popoverSizes.height > $(window).height() + $(window).scrollTop()) {\n\t\t\t\t// Pop up if otherwise we'd need the user to scroll down\n\t\t\t\ttop = buttonPosition.top - popoverSizes.height - popoverSizes.marginTop - popoverSizes.marginBottom;\n\t\t\t}\n\n\t\t\tif (containerPosition.top + top < $(window).scrollTop()) {\n\t\t\t\t// Correction for when the top is beyond the top of the page\n\t\t\t\ttop = buttonPosition.top + hostNode.outerHeight();\n\t\t\t}\n\n\t\t\t// Calculations all done - now set it\n\t\t\tdisplay.css( {\n\t\t\t\ttop: top,\n\t\t\t\tleft: left\n\t\t\t} );\n\t\t}\n\t\telse {\n\t\t\t// Fix position - centre on screen\n\t\t\tvar position = function () {\n\t\t\t\tvar half = $(window).height() / 2;\n\n\t\t\t\tvar top = display.height() / 2;\n\t\t\t\tif ( top > half ) {\n\t\t\t\t\ttop = half;\n\t\t\t\t}\n\n\t\t\t\tdisplay.css( 'marginTop', top*-1 );\n\t\t\t};\n\n\t\t\tposition();\n\n\t\t\t$(window).on('resize.dtb-collection', function () {\n\t\t\t\tposition();\n\t\t\t});\n\t\t}\n\n\t\tif ( options.background ) {\n\t\t\tButtons.background(\n\t\t\t\ttrue,\n\t\t\t\toptions.backgroundClassName,\n\t\t\t\toptions.fade,\n\t\t\t\toptions.backgroundHost || hostNode\n\t\t\t);\n\t\t}\n\n\t\t// This is bonkers, but if we don't have a click listener on the\n\t\t// background element, iOS Safari will ignore the body click\n\t\t// listener below. An empty function here is all that is\n\t\t// required to make it work...\n\t\t$('div.dt-button-background').on( 'click.dtb-collection', function () {} );\n\n\t\tif ( options.autoClose ) {\n\t\t\tsetTimeout( function () {\n\t\t\t\tdt.on( 'buttons-action.b-internal', function (e, btn, dt, node) {\n\t\t\t\t\tif ( node[0] === hostNode[0] ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tclose();\n\t\t\t\t} );\n\t\t\t}, 0);\n\t\t}\n\t\t\n\t\t$(display).trigger('buttons-popover.dt');\n\n\n\t\tdt.on('destroy', close);\n\n\t\tsetTimeout(function() {\n\t\t\tclosed = false;\n\t\t\t$('body')\n\t\t\t\t.on( 'click.dtb-collection', function (e) {\n\t\t\t\t\tif (closed) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// andSelf is deprecated in jQ1.8, but we want 1.7 compat\n\t\t\t\t\tvar back = $.fn.addBack ? 'addBack' : 'andSelf';\n\t\t\t\t\tvar parent = $(e.target).parent()[0];\n\t\n\t\t\t\t\tif (( ! $(e.target).parents()[back]().filter( content ).length && !$(parent).hasClass('dt-buttons')) || $(e.target).hasClass('dt-button-background')) {\n\t\t\t\t\t\tclose();\n\t\t\t\t\t}\n\t\t\t\t} )\n\t\t\t\t.on( 'keyup.dtb-collection', function (e) {\n\t\t\t\t\tif ( e.keyCode === 27 ) {\n\t\t\t\t\t\tclose();\n\t\t\t\t\t}\n\t\t\t\t} )\n\t\t\t\t.on( 'keydown.dtb-collection', function (e) {\n\t\t\t\t\t// Focus trap for tab key\n\t\t\t\t\tvar elements = $('a, button', content);\n\t\t\t\t\tvar active = document.activeElement;\n\n\t\t\t\t\tif (e.keyCode !== 9) { // tab\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (elements.index(active) === -1) {\n\t\t\t\t\t\t// If current focus is not inside the popover\n\t\t\t\t\t\telements.first().focus();\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\telse if (e.shiftKey) {\n\t\t\t\t\t\t// Reverse tabbing order when shift key is pressed\n\t\t\t\t\t\tif (active === elements[0]) {\n\t\t\t\t\t\t\telements.last().focus();\n\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tif (active === elements.last()[0]) {\n\t\t\t\t\t\t\telements.first().focus();\n\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t}, 0);\n\t}\n} );\n\n\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n * Statics\n */\n\n/**\n * Show / hide a background layer behind a collection\n * @param {boolean} Flag to indicate if the background should be shown or\n * hidden \n * @param {string} Class to assign to the background\n * @static\n */\nButtons.background = function ( show, className, fade, insertPoint ) {\n\tif ( fade === undefined ) {\n\t\tfade = 400;\n\t}\n\tif ( ! insertPoint ) {\n\t\tinsertPoint = document.body;\n\t}\n\n\tif ( show ) {\n\t\t_fadeIn(\n\t\t\t$('<div/>')\n\t\t\t\t.addClass( className )\n\t\t\t\t.css( 'display', 'none' )\n\t\t\t\t.insertAfter( insertPoint ),\n\t\t\tfade\n\t\t);\n\t}\n\telse {\n\t\t_fadeOut(\n\t\t\t$('div.'+className),\n\t\t\tfade,\n\t\t\tfunction () {\n\t\t\t\t$(this)\n\t\t\t\t\t.removeClass( className )\n\t\t\t\t\t.remove();\n\t\t\t}\n\t\t);\n\t}\n};\n\n/**\n * Instance selector - select Buttons instances based on an instance selector\n * value from the buttons assigned to a DataTable. This is only useful if\n * multiple instances are attached to a DataTable.\n * @param {string|int|array} Instance selector - see `instance-selector`\n * documentation on the DataTables site\n * @param {array} Button instance array that was attached to the DataTables\n * settings object\n * @return {array} Buttons instances\n * @static\n */\nButtons.instanceSelector = function ( group, buttons )\n{\n\tif ( group === undefined || group === null ) {\n\t\treturn $.map( buttons, function ( v ) {\n\t\t\treturn v.inst;\n\t\t} );\n\t}\n\n\tvar ret = [];\n\tvar names = $.map( buttons, function ( v ) {\n\t\treturn v.name;\n\t} );\n\n\t// Flatten the group selector into an array of single options\n\tvar process = function ( input ) {\n\t\tif ( Array.isArray( input ) ) {\n\t\t\tfor ( var i=0, ien=input.length ; i<ien ; i++ ) {\n\t\t\t\tprocess( input[i] );\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif ( typeof input === 'string' ) {\n\t\t\tif ( input.indexOf( ',' ) !== -1 ) {\n\t\t\t\t// String selector, list of names\n\t\t\t\tprocess( input.split(',') );\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// String selector individual name\n\t\t\t\tvar idx = $.inArray( input.trim(), names );\n\n\t\t\t\tif ( idx !== -1 ) {\n\t\t\t\t\tret.push( buttons[ idx ].inst );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if ( typeof input === 'number' ) {\n\t\t\t// Index selector\n\t\t\tret.push( buttons[ input ].inst );\n\t\t}\n\t\telse if ( typeof input === 'object' ) {\n\t\t\t// Actual instance selector\n\t\t\tret.push( input );\n\t\t}\n\t};\n\t\n\tprocess( group );\n\n\treturn ret;\n};\n\n/**\n * Button selector - select one or more buttons from a selector input so some\n * operation can be performed on them.\n * @param {array} Button instances array that the selector should operate on\n * @param {string|int|node|jQuery|array} Button selector - see\n * `button-selector` documentation on the DataTables site\n * @return {array} Array of objects containing `inst` and `idx` properties of\n * the selected buttons so you know which instance each button belongs to.\n * @static\n */\nButtons.buttonSelector = function ( insts, selector )\n{\n\tvar ret = [];\n\tvar nodeBuilder = function ( a, buttons, baseIdx ) {\n\t\tvar button;\n\t\tvar idx;\n\n\t\tfor ( var i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\tbutton = buttons[i];\n\n\t\t\tif ( button ) {\n\t\t\t\tidx = baseIdx !== undefined ?\n\t\t\t\t\tbaseIdx+i :\n\t\t\t\t\ti+'';\n\n\t\t\t\ta.push( {\n\t\t\t\t\tnode: button.node,\n\t\t\t\t\tname: button.conf.name,\n\t\t\t\t\tidx: idx\n\t\t\t\t} );\n\n\t\t\t\tif ( button.buttons ) {\n\t\t\t\t\tnodeBuilder( a, button.buttons, idx+'-' );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\tvar run = function ( selector, inst ) {\n\t\tvar i, ien;\n\t\tvar buttons = [];\n\t\tnodeBuilder( buttons, inst.s.buttons );\n\n\t\tvar nodes = $.map( buttons, function (v) {\n\t\t\treturn v.node;\n\t\t} );\n\n\t\tif ( Array.isArray( selector ) || selector instanceof $ ) {\n\t\t\tfor ( i=0, ien=selector.length ; i<ien ; i++ ) {\n\t\t\t\trun( selector[i], inst );\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif ( selector === null || selector === undefined || selector === '*' ) {\n\t\t\t// Select all\n\t\t\tfor ( i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\t\tret.push( {\n\t\t\t\t\tinst: inst,\n\t\t\t\t\tnode: buttons[i].node\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t\telse if ( typeof selector === 'number' ) {\n\t\t\t// Main button index selector\n\t\t\tif (inst.s.buttons[ selector ]) {\n\t\t\t\tret.push( {\n\t\t\t\t\tinst: inst,\n\t\t\t\t\tnode: inst.s.buttons[ selector ].node\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t\telse if ( typeof selector === 'string' ) {\n\t\t\tif ( selector.indexOf( ',' ) !== -1 ) {\n\t\t\t\t// Split\n\t\t\t\tvar a = selector.split(',');\n\n\t\t\t\tfor ( i=0, ien=a.length ; i<ien ; i++ ) {\n\t\t\t\t\trun( a[i].trim(), inst );\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if ( selector.match( /^\\d+(\\-\\d+)*$/ ) ) {\n\t\t\t\t// Sub-button index selector\n\t\t\t\tvar indexes = $.map( buttons, function (v) {\n\t\t\t\t\treturn v.idx;\n\t\t\t\t} );\n\n\t\t\t\tret.push( {\n\t\t\t\t\tinst: inst,\n\t\t\t\t\tnode: buttons[ $.inArray( selector, indexes ) ].node\n\t\t\t\t} );\n\t\t\t}\n\t\t\telse if ( selector.indexOf( ':name' ) !== -1 ) {\n\t\t\t\t// Button name selector\n\t\t\t\tvar name = selector.replace( ':name', '' );\n\n\t\t\t\tfor ( i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\t\t\tif ( buttons[i].name === name ) {\n\t\t\t\t\t\tret.push( {\n\t\t\t\t\t\t\tinst: inst,\n\t\t\t\t\t\t\tnode: buttons[i].node\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// jQuery selector on the nodes\n\t\t\t\t$( nodes ).filter( selector ).each( function () {\n\t\t\t\t\tret.push( {\n\t\t\t\t\t\tinst: inst,\n\t\t\t\t\t\tnode: this\n\t\t\t\t\t} );\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t\telse if ( typeof selector === 'object' && selector.nodeName ) {\n\t\t\t// Node selector\n\t\t\tvar idx = $.inArray( selector, nodes );\n\n\t\t\tif ( idx !== -1 ) {\n\t\t\t\tret.push( {\n\t\t\t\t\tinst: inst,\n\t\t\t\t\tnode: nodes[ idx ]\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t};\n\n\n\tfor ( var i=0, ien=insts.length ; i<ien ; i++ ) {\n\t\tvar inst = insts[i];\n\n\t\trun( selector, inst );\n\t}\n\n\treturn ret;\n};\n\n/**\n * Default function used for formatting output data.\n * @param {*} str Data to strip\n */\nButtons.stripData = function ( str, config ) {\n\tif ( typeof str !== 'string' ) {\n\t\treturn str;\n\t}\n\n\t// Always remove script tags\n\tstr = str.replace( /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, '' );\n\n\t// Always remove comments\n\tstr = str.replace( /<!\\-\\-.*?\\-\\->/g, '' );\n\n\tif ( ! config || config.stripHtml ) {\n\t\tstr = str.replace( /<[^>]*>/g, '' );\n\t}\n\n\tif ( ! config || config.trim ) {\n\t\tstr = str.replace( /^\\s+|\\s+$/g, '' );\n\t}\n\n\tif ( ! config || config.stripNewlines ) {\n\t\tstr = str.replace( /\\n/g, ' ' );\n\t}\n\n\tif ( ! config || config.decodeEntities ) {\n\t\t_exportTextarea.innerHTML = str;\n\t\tstr = _exportTextarea.value;\n\t}\n\n\treturn str;\n};\n\n\n/**\n * Buttons defaults. For full documentation, please refer to the docs/option\n * directory or the DataTables site.\n * @type {Object}\n * @static\n */\nButtons.defaults = {\n\tbuttons: [ 'copy', 'excel', 'csv', 'pdf', 'print' ],\n\tname: 'main',\n\ttabIndex: 0,\n\tdom: {\n\t\tcontainer: {\n\t\t\ttag: 'div',\n\t\t\tclassName: 'dt-buttons'\n\t\t},\n\t\tcollection: {\n\t\t\ttag: 'div',\n\t\t\tclassName: ''\n\t\t},\n\t\tbutton: {\n\t\t\ttag: 'button',\n\t\t\tclassName: 'dt-button',\n\t\t\tactive: 'active',\n\t\t\tdisabled: 'disabled',\n\t\t\tspacerClass: ''\n\t\t},\n\t\tbuttonLiner: {\n\t\t\ttag: 'span',\n\t\t\tclassName: ''\n\t\t},\n\t\tsplit: {\n\t\t\ttag: 'div',\n\t\t\tclassName: 'dt-button-split',\n\t\t},\n\t\tsplitWrapper: {\n\t\t\ttag: 'div',\n\t\t\tclassName: 'dt-btn-split-wrapper',\n\t\t},\n\t\tsplitDropdown: {\n\t\t\ttag: 'button',\n\t\t\ttext: '▼',\n\t\t\tclassName: 'dt-btn-split-drop',\n\t\t\talign: 'split-right',\n\t\t\tsplitAlignClass: 'dt-button-split-left'\n\t\t},\n\t\tsplitDropdownButton: {\n\t\t\ttag: 'button',\n\t\t\tclassName: 'dt-btn-split-drop-button dt-button',\n\t\t},\n\t\tsplitCollection: {\n\t\t\ttag: 'div',\n\t\t\tclassName: 'dt-button-split-collection',\n\t\t}\n\t}\n};\n\n/**\n * Version information\n * @type {string}\n * @static\n */\nButtons.version = '2.2.3';\n\n\n$.extend( _dtButtons, {\n\tcollection: {\n\t\ttext: function ( dt ) {\n\t\t\treturn dt.i18n( 'buttons.collection', 'Collection' );\n\t\t},\n\t\tclassName: 'buttons-collection',\n\t\tcloseButton: false,\n\t\tinit: function ( dt, button, config ) {\n\t\t\tbutton.attr( 'aria-expanded', false );\n\t\t},\n\t\taction: function ( e, dt, button, config ) {\n\t\t\tif ( config._collection.parents('body').length ) {\n\t\t\t\tthis.popover(false, config);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis.popover(config._collection, config);\n\t\t\t}\n\n\t\t\t// When activated using a key - auto focus on the\n\t\t\t// first item in the popover\n\t\t\tif (e.type === 'keypress') {\n\t\t\t\t$('a, button', config._collection).eq(0).focus();\n\t\t\t}\n\t\t},\n\t\tattr: {\n\t\t\t'aria-haspopup': 'dialog'\n\t\t}\n\t\t// Also the popover options, defined in Buttons.popover\n\t},\n\tsplit: {\n\t\ttext: function ( dt ) {\n\t\t\treturn dt.i18n( 'buttons.split', 'Split' );\n\t\t},\n\t\tclassName: 'buttons-split',\n\t\tcloseButton: false,\n\t\tinit: function ( dt, button, config ) {\n\t\t\treturn button.attr( 'aria-expanded', false );\n\t\t},\n\t\taction: function ( e, dt, button, config ) {\n\t\t\tthis.popover(config._collection, config);\n\t\t},\n\t\tattr: {\n\t\t\t'aria-haspopup': 'dialog'\n\t\t}\n\t\t// Also the popover options, defined in Buttons.popover\n\t},\n\tcopy: function ( dt, conf ) {\n\t\tif ( _dtButtons.copyHtml5 ) {\n\t\t\treturn 'copyHtml5';\n\t\t}\n\t},\n\tcsv: function ( dt, conf ) {\n\t\tif ( _dtButtons.csvHtml5 && _dtButtons.csvHtml5.available( dt, conf ) ) {\n\t\t\treturn 'csvHtml5';\n\t\t}\n\t},\n\texcel: function ( dt, conf ) {\n\t\tif ( _dtButtons.excelHtml5 && _dtButtons.excelHtml5.available( dt, conf ) ) {\n\t\t\treturn 'excelHtml5';\n\t\t}\n\t},\n\tpdf: function ( dt, conf ) {\n\t\tif ( _dtButtons.pdfHtml5 && _dtButtons.pdfHtml5.available( dt, conf ) ) {\n\t\t\treturn 'pdfHtml5';\n\t\t}\n\t},\n\tpageLength: function ( dt ) {\n\t\tvar lengthMenu = dt.settings()[0].aLengthMenu;\n\t\tvar vals = [];\n\t\tvar lang = [];\n\t\tvar text = function ( dt ) {\n\t\t\treturn dt.i18n( 'buttons.pageLength', {\n\t\t\t\t\"-1\": 'Show all rows',\n\t\t\t\t_: 'Show %d rows'\n\t\t\t}, dt.page.len() );\n\t\t};\n\n\t\t// Support for DataTables 1.x 2D array\n\t\tif (Array.isArray( lengthMenu[0] )) {\n\t\t\tvals = lengthMenu[0];\n\t\t\tlang = lengthMenu[1];\n\t\t}\n\t\telse {\n\t\t\tfor (var i=0 ; i<lengthMenu.length ; i++) {\n\t\t\t\tvar option = lengthMenu[i];\n\n\t\t\t\t// Support for DataTables 2 object in the array\n\t\t\t\tif ($.isPlainObject(option)) {\n\t\t\t\t\tvals.push(option.value);\n\t\t\t\t\tlang.push(option.label);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tvals.push(option);\n\t\t\t\t\tlang.push(option);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\textend: 'collection',\n\t\t\ttext: text,\n\t\t\tclassName: 'buttons-page-length',\n\t\t\tautoClose: true,\n\t\t\tbuttons: $.map( vals, function ( val, i ) {\n\t\t\t\treturn {\n\t\t\t\t\ttext: lang[i],\n\t\t\t\t\tclassName: 'button-page-length',\n\t\t\t\t\taction: function ( e, dt ) {\n\t\t\t\t\t\tdt.page.len( val ).draw();\n\t\t\t\t\t},\n\t\t\t\t\tinit: function ( dt, node, conf ) {\n\t\t\t\t\t\tvar that = this;\n\t\t\t\t\t\tvar fn = function () {\n\t\t\t\t\t\t\tthat.active( dt.page.len() === val );\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tdt.on( 'length.dt'+conf.namespace, fn );\n\t\t\t\t\t\tfn();\n\t\t\t\t\t},\n\t\t\t\t\tdestroy: function ( dt, node, conf ) {\n\t\t\t\t\t\tdt.off( 'length.dt'+conf.namespace );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t} ),\n\t\t\tinit: function ( dt, node, conf ) {\n\t\t\t\tvar that = this;\n\t\t\t\tdt.on( 'length.dt'+conf.namespace, function () {\n\t\t\t\t\tthat.text( conf.text );\n\t\t\t\t} );\n\t\t\t},\n\t\t\tdestroy: function ( dt, node, conf ) {\n\t\t\t\tdt.off( 'length.dt'+conf.namespace );\n\t\t\t}\n\t\t};\n\t},\n\tspacer: {\n\t\tstyle: 'empty',\n\t\tspacer: true,\n\t\ttext: function ( dt ) {\n\t\t\treturn dt.i18n( 'buttons.spacer', '' );\n\t\t}\n\t}\n} );\n\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n * DataTables API\n *\n * For complete documentation, please refer to the docs/api directory or the\n * DataTables site\n */\n\n// Buttons group and individual button selector\nDataTable.Api.register( 'buttons()', function ( group, selector ) {\n\t// Argument shifting\n\tif ( selector === undefined ) {\n\t\tselector = group;\n\t\tgroup = undefined;\n\t}\n\n\tthis.selector.buttonGroup = group;\n\n\tvar res = this.iterator( true, 'table', function ( ctx ) {\n\t\tif ( ctx._buttons ) {\n\t\t\treturn Buttons.buttonSelector(\n\t\t\t\tButtons.instanceSelector( group, ctx._buttons ),\n\t\t\t\tselector\n\t\t\t);\n\t\t}\n\t}, true );\n\n\tres._groupSelector = group;\n\treturn res;\n} );\n\n// Individual button selector\nDataTable.Api.register( 'button()', function ( group, selector ) {\n\t// just run buttons() and truncate\n\tvar buttons = this.buttons( group, selector );\n\n\tif ( buttons.length > 1 ) {\n\t\tbuttons.splice( 1, buttons.length );\n\t}\n\n\treturn buttons;\n} );\n\n// Active buttons\nDataTable.Api.registerPlural( 'buttons().active()', 'button().active()', function ( flag ) {\n\tif ( flag === undefined ) {\n\t\treturn this.map( function ( set ) {\n\t\t\treturn set.inst.active( set.node );\n\t\t} );\n\t}\n\n\treturn this.each( function ( set ) {\n\t\tset.inst.active( set.node, flag );\n\t} );\n} );\n\n// Get / set button action\nDataTable.Api.registerPlural( 'buttons().action()', 'button().action()', function ( action ) {\n\tif ( action === undefined ) {\n\t\treturn this.map( function ( set ) {\n\t\t\treturn set.inst.action( set.node );\n\t\t} );\n\t}\n\n\treturn this.each( function ( set ) {\n\t\tset.inst.action( set.node, action );\n\t} );\n} );\n\n// Collection control\nDataTable.Api.registerPlural( 'buttons().collectionRebuild()', 'button().collectionRebuild()', function ( buttons ) {\n\treturn this.each( function ( set ) {\n\t\tfor(var i = 0; i < buttons.length; i++) {\n\t\t\tif(typeof buttons[i] === 'object') {\n\t\t\t\tbuttons[i].parentConf = set;\n\t\t\t}\n\t\t}\n\t\tset.inst.collectionRebuild( set.node, buttons );\n\t} );\n} );\n\n// Enable / disable buttons\nDataTable.Api.register( ['buttons().enable()', 'button().enable()'], function ( flag ) {\n\treturn this.each( function ( set ) {\n\t\tset.inst.enable( set.node, flag );\n\t} );\n} );\n\n// Disable buttons\nDataTable.Api.register( ['buttons().disable()', 'button().disable()'], function () {\n\treturn this.each( function ( set ) {\n\t\tset.inst.disable( set.node );\n\t} );\n} );\n\n// Button index\nDataTable.Api.register( 'button().index()', function () {\n\tvar idx = null;\n\n\tthis.each( function ( set ) {\n\t\tvar res = set.inst.index( set.node );\n\n\t\tif (res !== null) {\n\t\t\tidx = res;\n\t\t}\n\t} );\n\n\treturn idx;\n} );\n\n// Get button nodes\nDataTable.Api.registerPlural( 'buttons().nodes()', 'button().node()', function () {\n\tvar jq = $();\n\n\t// jQuery will automatically reduce duplicates to a single entry\n\t$( this.each( function ( set ) {\n\t\tjq = jq.add( set.inst.node( set.node ) );\n\t} ) );\n\n\treturn jq;\n} );\n\n// Get / set button processing state\nDataTable.Api.registerPlural( 'buttons().processing()', 'button().processing()', function ( flag ) {\n\tif ( flag === undefined ) {\n\t\treturn this.map( function ( set ) {\n\t\t\treturn set.inst.processing( set.node );\n\t\t} );\n\t}\n\n\treturn this.each( function ( set ) {\n\t\tset.inst.processing( set.node, flag );\n\t} );\n} );\n\n// Get / set button text (i.e. the button labels)\nDataTable.Api.registerPlural( 'buttons().text()', 'button().text()', function ( label ) {\n\tif ( label === undefined ) {\n\t\treturn this.map( function ( set ) {\n\t\t\treturn set.inst.text( set.node );\n\t\t} );\n\t}\n\n\treturn this.each( function ( set ) {\n\t\tset.inst.text( set.node, label );\n\t} );\n} );\n\n// Trigger a button's action\nDataTable.Api.registerPlural( 'buttons().trigger()', 'button().trigger()', function () {\n\treturn this.each( function ( set ) {\n\t\tset.inst.node( set.node ).trigger( 'click' );\n\t} );\n} );\n\n// Button resolver to the popover\nDataTable.Api.register( 'button().popover()', function (content, options) {\n\treturn this.map( function ( set ) {\n\t\treturn set.inst._popover( content, this.button(this[0].node), options );\n\t} );\n} );\n\n// Get the container elements\nDataTable.Api.register( 'buttons().containers()', function () {\n\tvar jq = $();\n\tvar groupSelector = this._groupSelector;\n\n\t// We need to use the group selector directly, since if there are no buttons\n\t// the result set will be empty\n\tthis.iterator( true, 'table', function ( ctx ) {\n\t\tif ( ctx._buttons ) {\n\t\t\tvar insts = Buttons.instanceSelector( groupSelector, ctx._buttons );\n\n\t\t\tfor ( var i=0, ien=insts.length ; i<ien ; i++ ) {\n\t\t\t\tjq = jq.add( insts[i].container() );\n\t\t\t}\n\t\t}\n\t} );\n\n\treturn jq;\n} );\n\nDataTable.Api.register( 'buttons().container()', function () {\n\t// API level of nesting is `buttons()` so we can zip into the containers method\n\treturn this.containers().eq(0);\n} );\n\n// Add a new button\nDataTable.Api.register( 'button().add()', function ( idx, conf, draw ) {\n\tvar ctx = this.context;\n\n\t// Don't use `this` as it could be empty - select the instances directly\n\tif ( ctx.length ) {\n\t\tvar inst = Buttons.instanceSelector( this._groupSelector, ctx[0]._buttons );\n\n\t\tif ( inst.length ) {\n\t\t\tinst[0].add( conf, idx , draw);\n\t\t}\n\t}\n\n\treturn this.button( this._groupSelector, idx );\n} );\n\n// Destroy the button sets selected\nDataTable.Api.register( 'buttons().destroy()', function () {\n\tthis.pluck( 'inst' ).unique().each( function ( inst ) {\n\t\tinst.destroy();\n\t} );\n\n\treturn this;\n} );\n\n// Remove a button\nDataTable.Api.registerPlural( 'buttons().remove()', 'buttons().remove()', function () {\n\tthis.each( function ( set ) {\n\t\tset.inst.remove( set.node );\n\t} );\n\n\treturn this;\n} );\n\n// Information box that can be used by buttons\nvar _infoTimer;\nDataTable.Api.register( 'buttons.info()', function ( title, message, time ) {\n\tvar that = this;\n\n\tif ( title === false ) {\n\t\tthis.off('destroy.btn-info');\n\t\t_fadeOut(\n\t\t\t$('#datatables_buttons_info'),\n\t\t\t400,\n\t\t\tfunction () {\n\t\t\t\t$(this).remove();\n\t\t\t}\n\t\t);\n\t\tclearTimeout( _infoTimer );\n\t\t_infoTimer = null;\n\n\t\treturn this;\n\t}\n\n\tif ( _infoTimer ) {\n\t\tclearTimeout( _infoTimer );\n\t}\n\n\tif ( $('#datatables_buttons_info').length ) {\n\t\t$('#datatables_buttons_info').remove();\n\t}\n\n\ttitle = title ? '<h2>'+title+'</h2>' : '';\n\n\t_fadeIn(\n\t\t$('<div id=\"datatables_buttons_info\" class=\"dt-button-info\"/>')\n\t\t\t.html( title )\n\t\t\t.append( $('<div/>')[ typeof message === 'string' ? 'html' : 'append' ]( message ) )\n\t\t\t.css( 'display', 'none' )\n\t\t\t.appendTo( 'body' )\n\t);\n\n\tif ( time !== undefined && time !== 0 ) {\n\t\t_infoTimer = setTimeout( function () {\n\t\t\tthat.buttons.info( false );\n\t\t}, time );\n\t}\n\n\tthis.on('destroy.btn-info', function () {\n\t\tthat.buttons.info(false);\n\t});\n\n\treturn this;\n} );\n\n// Get data from the table for export - this is common to a number of plug-in\n// buttons so it is included in the Buttons core library\nDataTable.Api.register( 'buttons.exportData()', function ( options ) {\n\tif ( this.context.length ) {\n\t\treturn _exportData( new DataTable.Api( this.context[0] ), options );\n\t}\n} );\n\n// Get information about the export that is common to many of the export data\n// types (DRY)\nDataTable.Api.register( 'buttons.exportInfo()', function ( conf ) {\n\tif ( ! conf ) {\n\t\tconf = {};\n\t}\n\n\treturn {\n\t\tfilename: _filename( conf ),\n\t\ttitle: _title( conf ),\n\t\tmessageTop: _message(this, conf.message || conf.messageTop, 'top'),\n\t\tmessageBottom: _message(this, conf.messageBottom, 'bottom')\n\t};\n} );\n\n\n\n/**\n * Get the file name for an exported file.\n *\n * @param {object}\tconfig Button configuration\n * @param {boolean} incExtension Include the file name extension\n */\nvar _filename = function ( config )\n{\n\t// Backwards compatibility\n\tvar filename = config.filename === '*' && config.title !== '*' && config.title !== undefined && config.title !== null && config.title !== '' ?\n\t\tconfig.title :\n\t\tconfig.filename;\n\n\tif ( typeof filename === 'function' ) {\n\t\tfilename = filename();\n\t}\n\n\tif ( filename === undefined || filename === null ) {\n\t\treturn null;\n\t}\n\n\tif ( filename.indexOf( '*' ) !== -1 ) {\n\t\tfilename = filename.replace( '*', $('head > title').text() ).trim();\n\t}\n\n\t// Strip characters which the OS will object to\n\tfilename = filename.replace(/[^a-zA-Z0-9_\\u00A1-\\uFFFF\\.,\\-_ !\\(\\)]/g, \"\");\n\n\tvar extension = _stringOrFunction( config.extension );\n\tif ( ! extension ) {\n\t\textension = '';\n\t}\n\n\treturn filename + extension;\n};\n\n/**\n * Simply utility method to allow parameters to be given as a function\n *\n * @param {undefined|string|function} option Option\n * @return {null|string} Resolved value\n */\nvar _stringOrFunction = function ( option )\n{\n\tif ( option === null || option === undefined ) {\n\t\treturn null;\n\t}\n\telse if ( typeof option === 'function' ) {\n\t\treturn option();\n\t}\n\treturn option;\n};\n\n/**\n * Get the title for an exported file.\n *\n * @param {object} config\tButton configuration\n */\nvar _title = function ( config )\n{\n\tvar title = _stringOrFunction( config.title );\n\n\treturn title === null ?\n\t\tnull : title.indexOf( '*' ) !== -1 ?\n\t\t\ttitle.replace( '*', $('head > title').text() || 'Exported data' ) :\n\t\t\ttitle;\n};\n\nvar _message = function ( dt, option, position )\n{\n\tvar message = _stringOrFunction( option );\n\tif ( message === null ) {\n\t\treturn null;\n\t}\n\n\tvar caption = $('caption', dt.table().container()).eq(0);\n\tif ( message === '*' ) {\n\t\tvar side = caption.css( 'caption-side' );\n\t\tif ( side !== position ) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn caption.length ?\n\t\t\tcaption.text() :\n\t\t\t'';\n\t}\n\n\treturn message;\n};\n\n\n\n\nvar _exportTextarea = $('<textarea/>')[0];\nvar _exportData = function ( dt, inOpts )\n{\n\tvar config = $.extend( true, {}, {\n\t\trows: null,\n\t\tcolumns: '',\n\t\tmodifier: {\n\t\t\tsearch: 'applied',\n\t\t\torder: 'applied'\n\t\t},\n\t\torthogonal: 'display',\n\t\tstripHtml: true,\n\t\tstripNewlines: true,\n\t\tdecodeEntities: true,\n\t\ttrim: true,\n\t\tformat: {\n\t\t\theader: function ( d ) {\n\t\t\t\treturn Buttons.stripData( d, config );\n\t\t\t},\n\t\t\tfooter: function ( d ) {\n\t\t\t\treturn Buttons.stripData( d, config );\n\t\t\t},\n\t\t\tbody: function ( d ) {\n\t\t\t\treturn Buttons.stripData( d, config );\n\t\t\t}\n\t\t},\n\t\tcustomizeData: null\n\t}, inOpts );\n\n\tvar header = dt.columns( config.columns ).indexes().map( function (idx) {\n\t\tvar el = dt.column( idx ).header();\n\t\treturn config.format.header( el.innerHTML, idx, el );\n\t} ).toArray();\n\n\tvar footer = dt.table().footer() ?\n\t\tdt.columns( config.columns ).indexes().map( function (idx) {\n\t\t\tvar el = dt.column( idx ).footer();\n\t\t\treturn config.format.footer( el ? el.innerHTML : '', idx, el );\n\t\t} ).toArray() :\n\t\tnull;\n\t\n\t// If Select is available on this table, and any rows are selected, limit the export\n\t// to the selected rows. If no rows are selected, all rows will be exported. Specify\n\t// a `selected` modifier to control directly.\n\tvar modifier = $.extend( {}, config.modifier );\n\tif ( dt.select && typeof dt.select.info === 'function' && modifier.selected === undefined ) {\n\t\tif ( dt.rows( config.rows, $.extend( { selected: true }, modifier ) ).any() ) {\n\t\t\t$.extend( modifier, { selected: true } )\n\t\t}\n\t}\n\n\tvar rowIndexes = dt.rows( config.rows, modifier ).indexes().toArray();\n\tvar selectedCells = dt.cells( rowIndexes, config.columns );\n\tvar cells = selectedCells\n\t\t.render( config.orthogonal )\n\t\t.toArray();\n\tvar cellNodes = selectedCells\n\t\t.nodes()\n\t\t.toArray();\n\n\tvar columns = header.length;\n\tvar rows = columns > 0 ? cells.length / columns : 0;\n\tvar body = [];\n\tvar cellCounter = 0;\n\n\tfor ( var i=0, ien=rows ; i<ien ; i++ ) {\n\t\tvar row = [ columns ];\n\n\t\tfor ( var j=0 ; j<columns ; j++ ) {\n\t\t\trow[j] = config.format.body( cells[ cellCounter ], i, j, cellNodes[ cellCounter ] );\n\t\t\tcellCounter++;\n\t\t}\n\n\t\tbody[i] = row;\n\t}\n\n\tvar data = {\n\t\theader: header,\n\t\tfooter: footer,\n\t\tbody: body\n\t};\n\n\tif ( config.customizeData ) {\n\t\tconfig.customizeData( data );\n\t}\n\n\treturn data;\n};\n\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n * DataTables interface\n */\n\n// Attach to DataTables objects for global access\n$.fn.dataTable.Buttons = Buttons;\n$.fn.DataTable.Buttons = Buttons;\n\n\n\n// DataTables creation - check if the buttons have been defined for this table,\n// they will have been if the `B` option was used in `dom`, otherwise we should\n// create the buttons instance here so they can be inserted into the document\n// using the API. Listen for `init` for compatibility with pre 1.10.10, but to\n// be removed in future.\n$(document).on( 'init.dt plugin-init.dt', function (e, settings) {\n\tif ( e.namespace !== 'dt' ) {\n\t\treturn;\n\t}\n\n\tvar opts = settings.oInit.buttons || DataTable.defaults.buttons;\n\n\tif ( opts && ! settings._buttons ) {\n\t\tnew Buttons( settings, opts ).container();\n\t}\n} );\n\nfunction _init ( settings, options ) {\n\tvar api = new DataTable.Api( settings );\n\tvar opts = options\n\t\t? options\n\t\t: api.init().buttons || DataTable.defaults.buttons;\n\n\treturn new Buttons( api, opts ).container();\n}\n\n// DataTables `dom` feature option\nDataTable.ext.feature.push( {\n\tfnInit: _init,\n\tcFeature: \"B\"\n} );\n\n// DataTables 2 layout feature\nif ( DataTable.ext.features ) {\n\tDataTable.ext.features.register( 'buttons', _init );\n}\n\n\nreturn Buttons;\n}));\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvZGF0YXRhYmxlcy5uZXQtYnV0dG9ucy9qcy9kYXRhVGFibGVzLmJ1dHRvbnMuanMuanMiLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsTUFBTSxJQUEwQztBQUNoRDtBQUNBLEVBQUUsaUNBQVEsQ0FBQywyQ0FBUSxFQUFFLDJEQUFnQixDQUFDLG1DQUFFO0FBQ3hDO0FBQ0EsR0FBRztBQUFBLGtHQUFFO0FBQ0w7QUFDQSxNQUFNLEVBaUJKO0FBQ0YsQ0FBQztBQUNEO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7O0FBRUEsNEJBQTRCOztBQUU1QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGFBQWEsWUFBWTtBQUN6QixhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWEsTUFBTTtBQUNuQixhQUFhLFVBQVU7QUFDdkIsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsYUFBYSxNQUFNO0FBQ25CLGFBQWEsU0FBUztBQUN0QixhQUFhLFNBQVM7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxZQUFZLFFBQVE7QUFDcEIsWUFBWSxZQUFZO0FBQ3hCLFlBQVksU0FBUztBQUNyQjtBQUNBLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsdUNBQXVDLFFBQVE7QUFDL0M7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1DQUFtQyxNQUFNO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBLGFBQWEscUJBQXFCO0FBQ2xDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxhQUFhLE1BQU07QUFDbkIsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQ0FBa0MsUUFBUTtBQUMxQztBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxzQ0FBc0MsUUFBUTtBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsYUFBYSxNQUFNO0FBQ25CLGFBQWEsU0FBUztBQUN0QixhQUFhLFNBQVM7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVksU0FBUztBQUNyQixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsc0NBQXNDLFFBQVE7QUFDOUM7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7OztBQUdGO0FBQ0E7QUFDQSxhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxhQUFhLE1BQU07QUFDbkIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsWUFBWSxTQUFTO0FBQ3JCLGFBQWEsU0FBUztBQUN0QixhQUFhLGlCQUFpQjtBQUM5QjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxhQUFhLE1BQU07QUFDbkIsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EseUNBQXlDLE9BQU87QUFDaEQ7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxhQUFhLFlBQVk7QUFDekIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQSxhQUFhLHFCQUFxQjtBQUNsQyxhQUFhLFFBQVE7QUFDckIsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOzs7QUFHRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUosc0NBQXNDLFFBQVE7QUFDOUM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKLEVBQUU7OztBQUdGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsWUFBWSxRQUFRO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLGFBQWEsTUFBTTtBQUNuQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxzQ0FBc0MsUUFBUTtBQUM5QztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCLGFBQWEsUUFBUTtBQUNyQixhQUFhLFNBQVM7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQ0FBc0MsUUFBUTtBQUM5Qzs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0Esb0JBQW9CLDZCQUE2QjtBQUNqRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxhQUFhLFFBQVE7QUFDckIsYUFBYSxTQUFTO0FBQ3RCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07O0FBRU47QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxhQUFhLE1BQU07QUFDbkIsYUFBYSxPQUFPO0FBQ3BCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxzQ0FBc0MsUUFBUTtBQUM5QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsYUFBYSxNQUFNO0FBQ25CLGFBQWEsT0FBTztBQUNwQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsc0NBQXNDLFFBQVE7QUFDOUM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsYUFBYSxRQUFRO0FBQ3JCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxpQ0FBaUMsUUFBUTtBQUN6Qzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLGFBQWEsd0JBQXdCO0FBQ3JDLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLDZCQUE2QjtBQUM3Qjs7QUFFQSxzQkFBc0I7O0FBRXRCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSwyQ0FBMkMsUUFBUTtBQUNuRDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSwwQ0FBMEMsUUFBUTtBQUNsRDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLFlBQVksYUFBYTtBQUN6QixZQUFZLGVBQWU7QUFDM0IsWUFBWSxRQUFRO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkVBQTJFOztBQUUzRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTixJQUFJO0FBQ0o7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTs7QUFFQSw0QkFBNEI7QUFDNUI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ04sR0FBRztBQUNIO0FBQ0EsRUFBRTs7OztBQUlGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsWUFBWSxTQUFTO0FBQ3JCO0FBQ0EsWUFBWSxRQUFRO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLGtCQUFrQjtBQUM5QjtBQUNBLFlBQVksT0FBTztBQUNuQjtBQUNBLFlBQVksT0FBTztBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQyxRQUFRO0FBQzdDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLE9BQU87QUFDbkIsWUFBWSw4QkFBOEI7QUFDMUM7QUFDQSxZQUFZLE9BQU87QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHNDQUFzQyxRQUFRO0FBQzlDOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTs7QUFFTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQSxvQ0FBb0MsUUFBUTtBQUM1QztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsbUNBQW1DLFFBQVE7QUFDM0M7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDhCQUE4QixRQUFRO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTs7QUFFTjtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7O0FBRUEsb0NBQW9DLFFBQVE7QUFDNUM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTs7O0FBR0EsbUNBQW1DLFFBQVE7QUFDM0M7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLEdBQUc7QUFDZDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0Esa0JBQWtCO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLHNCQUFzQjtBQUN4Qzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7OztBQUdGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxpQkFBaUIsb0JBQW9CO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHFDQUFxQyxRQUFRO0FBQzdDO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7OztBQUlGO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixXQUFXLFNBQVM7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsMkJBQTJCO0FBQ3RDLFlBQVksYUFBYTtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQSxnQ0FBZ0M7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0QkFBNEI7QUFDNUI7QUFDQSx5Q0FBeUMsZ0JBQWdCO0FBQ3pELHlCQUF5QixpQkFBaUI7QUFDMUM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDJCQUEyQixRQUFRO0FBQ25DOztBQUVBLGtCQUFrQixZQUFZO0FBQzlCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBLENBQUMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9WdWV4eS8uL25vZGVfbW9kdWxlcy9kYXRhdGFibGVzLm5ldC1idXR0b25zL2pzL2RhdGFUYWJsZXMuYnV0dG9ucy5qcz8xMDUxIl0sInNvdXJjZXNDb250ZW50IjpbIi8qISBCdXR0b25zIGZvciBEYXRhVGFibGVzIDIuMi4zXG4gKiDCqTIwMTYtMjAyMiBTcHJ5TWVkaWEgTHRkIC0gZGF0YXRhYmxlcy5uZXQvbGljZW5zZVxuICovXG5cbihmdW5jdGlvbiggZmFjdG9yeSApe1xuXHRpZiAoIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCApIHtcblx0XHQvLyBBTURcblx0XHRkZWZpbmUoIFsnanF1ZXJ5JywgJ2RhdGF0YWJsZXMubmV0J10sIGZ1bmN0aW9uICggJCApIHtcblx0XHRcdHJldHVybiBmYWN0b3J5KCAkLCB3aW5kb3csIGRvY3VtZW50ICk7XG5cdFx0fSApO1xuXHR9XG5cdGVsc2UgaWYgKCB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgKSB7XG5cdFx0Ly8gQ29tbW9uSlNcblx0XHRtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChyb290LCAkKSB7XG5cdFx0XHRpZiAoICEgcm9vdCApIHtcblx0XHRcdFx0cm9vdCA9IHdpbmRvdztcblx0XHRcdH1cblxuXHRcdFx0aWYgKCAhICQgfHwgISAkLmZuLmRhdGFUYWJsZSApIHtcblx0XHRcdFx0JCA9IHJlcXVpcmUoJ2RhdGF0YWJsZXMubmV0Jykocm9vdCwgJCkuJDtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGZhY3RvcnkoICQsIHJvb3QsIHJvb3QuZG9jdW1lbnQgKTtcblx0XHR9O1xuXHR9XG5cdGVsc2Uge1xuXHRcdC8vIEJyb3dzZXJcblx0XHRmYWN0b3J5KCBqUXVlcnksIHdpbmRvdywgZG9jdW1lbnQgKTtcblx0fVxufShmdW5jdGlvbiggJCwgd2luZG93LCBkb2N1bWVudCwgdW5kZWZpbmVkICkge1xuJ3VzZSBzdHJpY3QnO1xudmFyIERhdGFUYWJsZSA9ICQuZm4uZGF0YVRhYmxlO1xuXG5cbi8vIFVzZWQgZm9yIG5hbWVzcGFjaW5nIGV2ZW50cyBhZGRlZCB0byB0aGUgZG9jdW1lbnQgYnkgZWFjaCBpbnN0YW5jZSwgc28gdGhleVxuLy8gY2FuIGJlIHJlbW92ZWQgb24gZGVzdHJveVxudmFyIF9pbnN0Q291bnRlciA9IDA7XG5cbi8vIEJ1dHRvbiBuYW1lc3BhY2luZyBjb3VudGVyIGZvciBuYW1lc3BhY2luZyBldmVudHMgb24gaW5kaXZpZHVhbCBidXR0b25zXG52YXIgX2J1dHRvbkNvdW50ZXIgPSAwO1xuXG52YXIgX2R0QnV0dG9ucyA9IERhdGFUYWJsZS5leHQuYnV0dG9ucztcblxuLy8gQWxsb3cgZm9yIGpRdWVyeSBzbGltXG5mdW5jdGlvbiBfZmFkZUluKGVsLCBkdXJhdGlvbiwgZm4pIHtcblx0aWYgKCQuZm4uYW5pbWF0ZSkge1xuXHRcdGVsXG5cdFx0XHQuc3RvcCgpXG5cdFx0XHQuZmFkZUluKCBkdXJhdGlvbiwgZm4gKTtcblxuXHR9XG5cdGVsc2Uge1xuXHRcdGVsLmNzcygnZGlzcGxheScsICdibG9jaycpO1xuXG5cdFx0aWYgKGZuKSB7XG5cdFx0XHRmbi5jYWxsKGVsKTtcblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gX2ZhZGVPdXQoZWwsIGR1cmF0aW9uLCBmbikge1xuXHRpZiAoJC5mbi5hbmltYXRlKSB7XG5cdFx0ZWxcblx0XHRcdC5zdG9wKClcblx0XHRcdC5mYWRlT3V0KCBkdXJhdGlvbiwgZm4gKTtcblx0fVxuXHRlbHNlIHtcblx0XHRlbC5jc3MoJ2Rpc3BsYXknLCAnbm9uZScpO1xuXHRcdFxuXHRcdGlmIChmbikge1xuXHRcdFx0Zm4uY2FsbChlbCk7XG5cdFx0fVxuXHR9XG59XG5cbi8qKlxuICogW0J1dHRvbnMgZGVzY3JpcHRpb25dXG4gKiBAcGFyYW0ge1t0eXBlXX1cbiAqIEBwYXJhbSB7W3R5cGVdfVxuICovXG52YXIgQnV0dG9ucyA9IGZ1bmN0aW9uKCBkdCwgY29uZmlnIClcbntcblx0Ly8gSWYgbm90IGNyZWF0ZWQgd2l0aCBhIGBuZXdgIGtleXdvcmQgdGhlbiB3ZSByZXR1cm4gYSB3cmFwcGVyIGZ1bmN0aW9uIHRoYXRcblx0Ly8gd2lsbCB0YWtlIHRoZSBzZXR0aW5ncyBvYmplY3QgZm9yIGEgRFQuIFRoaXMgYWxsb3dzIGVhc3kgdXNlIG9mIG5ldyBpbnN0YW5jZXNcblx0Ly8gd2l0aCB0aGUgYGxheW91dGAgb3B0aW9uIC0gZS5nLiBgdG9wTGVmdDogJC5mbi5kYXRhVGFibGUuQnV0dG9ucyggLi4uIClgLlxuXHRpZiAoICEodGhpcyBpbnN0YW5jZW9mIEJ1dHRvbnMpICkge1xuXHRcdHJldHVybiBmdW5jdGlvbiAoc2V0dGluZ3MpIHtcblx0XHRcdHJldHVybiBuZXcgQnV0dG9ucyggc2V0dGluZ3MsIGR0ICkuY29udGFpbmVyKCk7XG5cdFx0fTtcblx0fVxuXG5cdC8vIElmIHRoZXJlIGlzIG5vIGNvbmZpZyBzZXQgaXQgdG8gYW4gZW1wdHkgb2JqZWN0XG5cdGlmICggdHlwZW9mKCBjb25maWcgKSA9PT0gJ3VuZGVmaW5lZCcgKSB7XG5cdFx0Y29uZmlnID0ge307XHRcblx0fVxuXHRcblx0Ly8gQWxsb3cgYSBib29sZWFuIHRydWUgZm9yIGRlZmF1bHRzXG5cdGlmICggY29uZmlnID09PSB0cnVlICkge1xuXHRcdGNvbmZpZyA9IHt9O1xuXHR9XG5cblx0Ly8gRm9yIGVhc3kgY29uZmlndXJhdGlvbiBvZiBidXR0b25zIGFuIGFycmF5IGNhbiBiZSBnaXZlblxuXHRpZiAoIEFycmF5LmlzQXJyYXkoIGNvbmZpZyApICkge1xuXHRcdGNvbmZpZyA9IHsgYnV0dG9uczogY29uZmlnIH07XG5cdH1cblxuXHR0aGlzLmMgPSAkLmV4dGVuZCggdHJ1ZSwge30sIEJ1dHRvbnMuZGVmYXVsdHMsIGNvbmZpZyApO1xuXG5cdC8vIERvbid0IHdhbnQgYSBkZWVwIGNvcHkgZm9yIHRoZSBidXR0b25zXG5cdGlmICggY29uZmlnLmJ1dHRvbnMgKSB7XG5cdFx0dGhpcy5jLmJ1dHRvbnMgPSBjb25maWcuYnV0dG9ucztcblx0fVxuXG5cdHRoaXMucyA9IHtcblx0XHRkdDogbmV3IERhdGFUYWJsZS5BcGkoIGR0ICksXG5cdFx0YnV0dG9uczogW10sXG5cdFx0bGlzdGVuS2V5czogJycsXG5cdFx0bmFtZXNwYWNlOiAnZHRiJysoX2luc3RDb3VudGVyKyspXG5cdH07XG5cblx0dGhpcy5kb20gPSB7XG5cdFx0Y29udGFpbmVyOiAkKCc8Jyt0aGlzLmMuZG9tLmNvbnRhaW5lci50YWcrJy8+Jylcblx0XHRcdC5hZGRDbGFzcyggdGhpcy5jLmRvbS5jb250YWluZXIuY2xhc3NOYW1lIClcblx0fTtcblxuXHR0aGlzLl9jb25zdHJ1Y3RvcigpO1xufTtcblxuXG4kLmV4dGVuZCggQnV0dG9ucy5wcm90b3R5cGUsIHtcblx0LyogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKlxuXHQgKiBQdWJsaWMgbWV0aG9kc1xuXHQgKi9cblxuXHQvKipcblx0ICogR2V0IHRoZSBhY3Rpb24gb2YgYSBidXR0b25cblx0ICogQHBhcmFtICB7aW50fHN0cmluZ30gQnV0dG9uIGluZGV4XG5cdCAqIEByZXR1cm4ge2Z1bmN0aW9ufVxuXHQgKi8vKipcblx0ICogU2V0IHRoZSBhY3Rpb24gb2YgYSBidXR0b25cblx0ICogQHBhcmFtICB7bm9kZX0gbm9kZSBCdXR0b24gZWxlbWVudFxuXHQgKiBAcGFyYW0gIHtmdW5jdGlvbn0gYWN0aW9uIEZ1bmN0aW9uIHRvIHNldFxuXHQgKiBAcmV0dXJuIHtCdXR0b25zfSBTZWxmIGZvciBjaGFpbmluZ1xuXHQgKi9cblx0YWN0aW9uOiBmdW5jdGlvbiAoIG5vZGUsIGFjdGlvbiApXG5cdHtcblx0XHR2YXIgYnV0dG9uID0gdGhpcy5fbm9kZVRvQnV0dG9uKCBub2RlICk7XG5cblx0XHRpZiAoIGFjdGlvbiA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0cmV0dXJuIGJ1dHRvbi5jb25mLmFjdGlvbjtcblx0XHR9XG5cblx0XHRidXR0b24uY29uZi5hY3Rpb24gPSBhY3Rpb247XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHQvKipcblx0ICogQWRkIGFuIGFjdGl2ZSBjbGFzcyB0byB0aGUgYnV0dG9uIHRvIG1ha2UgdG8gbG9vayBhY3RpdmUgb3IgZ2V0IGN1cnJlbnRcblx0ICogYWN0aXZlIHN0YXRlLlxuXHQgKiBAcGFyYW0gIHtub2RlfSBub2RlIEJ1dHRvbiBlbGVtZW50XG5cdCAqIEBwYXJhbSAge2Jvb2xlYW59IFtmbGFnXSBFbmFibGUgLyBkaXNhYmxlIGZsYWdcblx0ICogQHJldHVybiB7QnV0dG9uc30gU2VsZiBmb3IgY2hhaW5pbmcgb3IgYm9vbGVhbiBmb3IgZ2V0dGVyXG5cdCAqL1xuXHRhY3RpdmU6IGZ1bmN0aW9uICggbm9kZSwgZmxhZyApIHtcblx0XHR2YXIgYnV0dG9uID0gdGhpcy5fbm9kZVRvQnV0dG9uKCBub2RlICk7XG5cdFx0dmFyIGtsYXNzID0gdGhpcy5jLmRvbS5idXR0b24uYWN0aXZlO1xuXHRcdHZhciBqcU5vZGUgPSAkKGJ1dHRvbi5ub2RlKTtcblxuXHRcdGlmICggZmxhZyA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0cmV0dXJuIGpxTm9kZS5oYXNDbGFzcygga2xhc3MgKTtcblx0XHR9XG5cblx0XHRqcU5vZGUudG9nZ2xlQ2xhc3MoIGtsYXNzLCBmbGFnID09PSB1bmRlZmluZWQgPyB0cnVlIDogZmxhZyApO1xuXG5cdFx0cmV0dXJuIHRoaXM7XG5cdH0sXG5cblx0LyoqXG5cdCAqIEFkZCBhIG5ldyBidXR0b25cblx0ICogQHBhcmFtIHtvYmplY3R9IGNvbmZpZyBCdXR0b24gY29uZmlndXJhdGlvbiBvYmplY3QsIGJhc2Ugc3RyaW5nIG5hbWUgb3IgZnVuY3Rpb25cblx0ICogQHBhcmFtIHtpbnR8c3RyaW5nfSBbaWR4XSBCdXR0b24gaW5kZXggZm9yIHdoZXJlIHRvIGluc2VydCB0aGUgYnV0dG9uXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbn0gW2RyYXc9dHJ1ZV0gVHJpZ2dlciBhIGRyYXcuIFNldCBhIGZhbHNlIHdoZW4gYWRkaW5nXG5cdCAqICAgbG90cyBvZiBidXR0b25zLCB1bnRpbCB0aGUgbGFzdCBidXR0b24uXG5cdCAqIEByZXR1cm4ge0J1dHRvbnN9IFNlbGYgZm9yIGNoYWluaW5nXG5cdCAqL1xuXHRhZGQ6IGZ1bmN0aW9uICggY29uZmlnLCBpZHgsIGRyYXcgKVxuXHR7XG5cdFx0dmFyIGJ1dHRvbnMgPSB0aGlzLnMuYnV0dG9ucztcblxuXHRcdGlmICggdHlwZW9mIGlkeCA9PT0gJ3N0cmluZycgKSB7XG5cdFx0XHR2YXIgc3BsaXQgPSBpZHguc3BsaXQoJy0nKTtcblx0XHRcdHZhciBiYXNlID0gdGhpcy5zO1xuXG5cdFx0XHRmb3IgKCB2YXIgaT0wLCBpZW49c3BsaXQubGVuZ3RoLTEgOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdFx0YmFzZSA9IGJhc2UuYnV0dG9uc1sgc3BsaXRbaV0qMSBdO1xuXHRcdFx0fVxuXG5cdFx0XHRidXR0b25zID0gYmFzZS5idXR0b25zO1xuXHRcdFx0aWR4ID0gc3BsaXRbIHNwbGl0Lmxlbmd0aC0xIF0qMTtcblx0XHR9XG5cblx0XHR0aGlzLl9leHBhbmRCdXR0b24oXG5cdFx0XHRidXR0b25zLFxuXHRcdFx0Y29uZmlnLFxuXHRcdFx0Y29uZmlnICE9PSB1bmRlZmluZWQgPyBjb25maWcuc3BsaXQgOiB1bmRlZmluZWQsXG5cdFx0XHQoY29uZmlnID09PSB1bmRlZmluZWQgfHwgY29uZmlnLnNwbGl0ID09PSB1bmRlZmluZWQgfHwgY29uZmlnLnNwbGl0Lmxlbmd0aCA9PT0gMCkgJiYgYmFzZSAhPT0gdW5kZWZpbmVkLFxuXHRcdFx0ZmFsc2UsXG5cdFx0XHRpZHhcblx0XHQpO1xuXG5cdFx0aWYgKGRyYXcgPT09IHVuZGVmaW5lZCB8fCBkcmF3ID09PSB0cnVlKSB7XG5cdFx0XHR0aGlzLl9kcmF3KCk7XG5cdFx0fVxuXHRcblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHQvKipcblx0ICogQ2xlYXIgYnV0dG9ucyBmcm9tIGEgY29sbGVjdGlvbiBhbmQgdGhlbiBpbnNlcnQgbmV3IGJ1dHRvbnNcblx0ICovXG5cdGNvbGxlY3Rpb25SZWJ1aWxkOiBmdW5jdGlvbiAoIG5vZGUsIG5ld0J1dHRvbnMgKVxuXHR7XG5cdFx0dmFyIGJ1dHRvbiA9IHRoaXMuX25vZGVUb0J1dHRvbiggbm9kZSApO1xuXHRcdFxuXHRcdGlmKG5ld0J1dHRvbnMgIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0dmFyIGk7XG5cdFx0XHQvLyBOZWVkIHRvIHJldmVyc2UgdGhlIGFycmF5XG5cdFx0XHRmb3IgKGk9YnV0dG9uLmJ1dHRvbnMubGVuZ3RoLTE7IGk+PTA7IGktLSkge1xuXHRcdFx0XHR0aGlzLnJlbW92ZShidXR0b24uYnV0dG9uc1tpXS5ub2RlKTtcblx0XHRcdH1cblx0XG5cdFx0XHRmb3IgKGk9MDsgaTxuZXdCdXR0b25zLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdHZhciBuZXdCdG4gPSBuZXdCdXR0b25zW2ldO1xuXG5cdFx0XHRcdHRoaXMuX2V4cGFuZEJ1dHRvbihcblx0XHRcdFx0XHRidXR0b24uYnV0dG9ucyxcblx0XHRcdFx0XHRuZXdCdG4sXG5cdFx0XHRcdFx0bmV3QnRuICE9PSB1bmRlZmluZWQgJiYgbmV3QnRuLmNvbmZpZyAhPT0gdW5kZWZpbmVkICYmIG5ld0J0bi5jb25maWcuc3BsaXQgIT09IHVuZGVmaW5lZCxcblx0XHRcdFx0XHR0cnVlLFxuXHRcdFx0XHRcdG5ld0J0bi5wYXJlbnRDb25mICE9PSB1bmRlZmluZWQgJiYgbmV3QnRuLnBhcmVudENvbmYuc3BsaXQgIT09IHVuZGVmaW5lZCxcblx0XHRcdFx0XHRpLFxuXHRcdFx0XHRcdG5ld0J0bi5wYXJlbnRDb25mXG5cdFx0XHRcdCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dGhpcy5fZHJhdyhidXR0b24uY29sbGVjdGlvbiwgYnV0dG9uLmJ1dHRvbnMpO1xuXHR9LFxuXG5cdC8qKlxuXHQgKiBHZXQgdGhlIGNvbnRhaW5lciBub2RlIGZvciB0aGUgYnV0dG9uc1xuXHQgKiBAcmV0dXJuIHtqUXVlcnl9IEJ1dHRvbnMgbm9kZVxuXHQgKi9cblx0Y29udGFpbmVyOiBmdW5jdGlvbiAoKVxuXHR7XG5cdFx0cmV0dXJuIHRoaXMuZG9tLmNvbnRhaW5lcjtcblx0fSxcblxuXHQvKipcblx0ICogRGlzYWJsZSBhIGJ1dHRvblxuXHQgKiBAcGFyYW0gIHtub2RlfSBub2RlIEJ1dHRvbiBub2RlXG5cdCAqIEByZXR1cm4ge0J1dHRvbnN9IFNlbGYgZm9yIGNoYWluaW5nXG5cdCAqL1xuXHRkaXNhYmxlOiBmdW5jdGlvbiAoIG5vZGUgKSB7XG5cdFx0dmFyIGJ1dHRvbiA9IHRoaXMuX25vZGVUb0J1dHRvbiggbm9kZSApO1xuXG5cdFx0JChidXR0b24ubm9kZSlcblx0XHRcdC5hZGRDbGFzcyggdGhpcy5jLmRvbS5idXR0b24uZGlzYWJsZWQgKVxuXHRcdFx0LmF0dHIoJ2Rpc2FibGVkJywgdHJ1ZSk7XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHQvKipcblx0ICogRGVzdHJveSB0aGUgaW5zdGFuY2UsIGNsZWFuaW5nIHVwIGV2ZW50IGhhbmRsZXJzIGFuZCByZW1vdmluZyBET01cblx0ICogZWxlbWVudHNcblx0ICogQHJldHVybiB7QnV0dG9uc30gU2VsZiBmb3IgY2hhaW5pbmdcblx0ICovXG5cdGRlc3Ryb3k6IGZ1bmN0aW9uICgpXG5cdHtcblx0XHQvLyBLZXkgZXZlbnQgbGlzdGVuZXJcblx0XHQkKCdib2R5Jykub2ZmKCAna2V5dXAuJyt0aGlzLnMubmFtZXNwYWNlICk7XG5cblx0XHQvLyBJbmRpdmlkdWFsIGJ1dHRvbiBkZXN0cm95IChzbyB0aGV5IGNhbiByZW1vdmUgdGhlaXIgb3duIGV2ZW50cyBpZlxuXHRcdC8vIG5lZWRlZCkuIFRha2UgYSBjb3B5IGFzIHRoZSBhcnJheSBpcyBtb2RpZmllZCBieSBgcmVtb3ZlYFxuXHRcdHZhciBidXR0b25zID0gdGhpcy5zLmJ1dHRvbnMuc2xpY2UoKTtcblx0XHR2YXIgaSwgaWVuO1xuXHRcdFxuXHRcdGZvciAoIGk9MCwgaWVuPWJ1dHRvbnMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHR0aGlzLnJlbW92ZSggYnV0dG9uc1tpXS5ub2RlICk7XG5cdFx0fVxuXG5cdFx0Ly8gQ29udGFpbmVyXG5cdFx0dGhpcy5kb20uY29udGFpbmVyLnJlbW92ZSgpO1xuXG5cdFx0Ly8gUmVtb3ZlIGZyb20gdGhlIHNldHRpbmdzIG9iamVjdCBjb2xsZWN0aW9uXG5cdFx0dmFyIGJ1dHRvbkluc3RzID0gdGhpcy5zLmR0LnNldHRpbmdzKClbMF07XG5cblx0XHRmb3IgKCBpPTAsIGllbj1idXR0b25JbnN0cy5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdGlmICggYnV0dG9uSW5zdHMuaW5zdCA9PT0gdGhpcyApIHtcblx0XHRcdFx0YnV0dG9uSW5zdHMuc3BsaWNlKCBpLCAxICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdC8qKlxuXHQgKiBFbmFibGUgLyBkaXNhYmxlIGEgYnV0dG9uXG5cdCAqIEBwYXJhbSAge25vZGV9IG5vZGUgQnV0dG9uIG5vZGVcblx0ICogQHBhcmFtICB7Ym9vbGVhbn0gW2ZsYWc9dHJ1ZV0gRW5hYmxlIC8gZGlzYWJsZSBmbGFnXG5cdCAqIEByZXR1cm4ge0J1dHRvbnN9IFNlbGYgZm9yIGNoYWluaW5nXG5cdCAqL1xuXHRlbmFibGU6IGZ1bmN0aW9uICggbm9kZSwgZmxhZyApXG5cdHtcblx0XHRpZiAoIGZsYWcgPT09IGZhbHNlICkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZGlzYWJsZSggbm9kZSApO1xuXHRcdH1cblxuXHRcdHZhciBidXR0b24gPSB0aGlzLl9ub2RlVG9CdXR0b24oIG5vZGUgKTtcblx0XHQkKGJ1dHRvbi5ub2RlKVxuXHRcdFx0LnJlbW92ZUNsYXNzKCB0aGlzLmMuZG9tLmJ1dHRvbi5kaXNhYmxlZCApXG5cdFx0XHQucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcblxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdC8qKlxuXHQgKiBHZXQgYSBidXR0b24ncyBpbmRleFxuXHQgKiBcblx0ICogVGhpcyBpcyBpbnRlcm5hbGx5IHJlY3Vyc2l2ZVxuXHQgKiBAcGFyYW0ge2VsZW1lbnR9IG5vZGUgQnV0dG9uIHRvIGdldCB0aGUgaW5kZXggb2Zcblx0ICogQHJldHVybiB7c3RyaW5nfSBCdXR0b24gaW5kZXhcblx0ICovXG5cdGluZGV4OiBmdW5jdGlvbiAoIG5vZGUsIG5lc3RlZCwgYnV0dG9ucyApXG5cdHtcblx0XHRpZiAoICEgbmVzdGVkICkge1xuXHRcdFx0bmVzdGVkID0gJyc7XG5cdFx0XHRidXR0b25zID0gdGhpcy5zLmJ1dHRvbnM7XG5cdFx0fVxuXG5cdFx0Zm9yICggdmFyIGk9MCwgaWVuPWJ1dHRvbnMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHR2YXIgaW5uZXIgPSBidXR0b25zW2ldLmJ1dHRvbnM7XG5cblx0XHRcdGlmIChidXR0b25zW2ldLm5vZGUgPT09IG5vZGUpIHtcblx0XHRcdFx0cmV0dXJuIG5lc3RlZCArIGk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggaW5uZXIgJiYgaW5uZXIubGVuZ3RoICkge1xuXHRcdFx0XHR2YXIgbWF0Y2ggPSB0aGlzLmluZGV4KG5vZGUsIGkgKyAnLScsIGlubmVyKTtcblxuXHRcdFx0XHRpZiAobWF0Y2ggIT09IG51bGwpIHtcblx0XHRcdFx0XHRyZXR1cm4gbWF0Y2g7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gbnVsbDtcblx0fSxcblxuXG5cdC8qKlxuXHQgKiBHZXQgdGhlIGluc3RhbmNlIG5hbWUgZm9yIHRoZSBidXR0b24gc2V0IHNlbGVjdG9yXG5cdCAqIEByZXR1cm4ge3N0cmluZ30gSW5zdGFuY2UgbmFtZVxuXHQgKi9cblx0bmFtZTogZnVuY3Rpb24gKClcblx0e1xuXHRcdHJldHVybiB0aGlzLmMubmFtZTtcblx0fSxcblxuXHQvKipcblx0ICogR2V0IGEgYnV0dG9uJ3Mgbm9kZSBvZiB0aGUgYnV0dG9ucyBjb250YWluZXIgaWYgbm8gYnV0dG9uIGlzIGdpdmVuXG5cdCAqIEBwYXJhbSAge25vZGV9IFtub2RlXSBCdXR0b24gbm9kZVxuXHQgKiBAcmV0dXJuIHtqUXVlcnl9IEJ1dHRvbiBlbGVtZW50LCBvciBjb250YWluZXJcblx0ICovXG5cdG5vZGU6IGZ1bmN0aW9uICggbm9kZSApXG5cdHtcblx0XHRpZiAoICEgbm9kZSApIHtcblx0XHRcdHJldHVybiB0aGlzLmRvbS5jb250YWluZXI7XG5cdFx0fVxuXG5cdFx0dmFyIGJ1dHRvbiA9IHRoaXMuX25vZGVUb0J1dHRvbiggbm9kZSApO1xuXHRcdHJldHVybiAkKGJ1dHRvbi5ub2RlKTtcblx0fSxcblxuXHQvKipcblx0ICogU2V0IC8gZ2V0IGEgcHJvY2Vzc2luZyBjbGFzcyBvbiB0aGUgc2VsZWN0ZWQgYnV0dG9uXG5cdCAqIEBwYXJhbSB7ZWxlbWVudH0gbm9kZSBUcmlnZ2VyaW5nIGJ1dHRvbiBub2RlXG5cdCAqIEBwYXJhbSAge2Jvb2xlYW59IGZsYWcgdHJ1ZSB0byBhZGQsIGZhbHNlIHRvIHJlbW92ZSwgdW5kZWZpbmVkIHRvIGdldFxuXHQgKiBAcmV0dXJuIHtib29sZWFufEJ1dHRvbnN9IEdldHRlciB2YWx1ZSBvciB0aGlzIGlmIGEgc2V0dGVyLlxuXHQgKi9cblx0cHJvY2Vzc2luZzogZnVuY3Rpb24gKCBub2RlLCBmbGFnIClcblx0e1xuXHRcdHZhciBkdCA9IHRoaXMucy5kdDtcblx0XHR2YXIgYnV0dG9uID0gdGhpcy5fbm9kZVRvQnV0dG9uKCBub2RlICk7XG5cblx0XHRpZiAoIGZsYWcgPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHJldHVybiAkKGJ1dHRvbi5ub2RlKS5oYXNDbGFzcyggJ3Byb2Nlc3NpbmcnICk7XG5cdFx0fVxuXG5cdFx0JChidXR0b24ubm9kZSkudG9nZ2xlQ2xhc3MoICdwcm9jZXNzaW5nJywgZmxhZyApO1xuXG5cdFx0JChkdC50YWJsZSgpLm5vZGUoKSkudHJpZ2dlckhhbmRsZXIoICdidXR0b25zLXByb2Nlc3NpbmcuZHQnLCBbXG5cdFx0XHRmbGFnLCBkdC5idXR0b24oIG5vZGUgKSwgZHQsICQobm9kZSksIGJ1dHRvbi5jb25mXG5cdFx0XSApO1xuXG5cdFx0cmV0dXJuIHRoaXM7XG5cdH0sXG5cblx0LyoqXG5cdCAqIFJlbW92ZSBhIGJ1dHRvbi5cblx0ICogQHBhcmFtICB7bm9kZX0gbm9kZSBCdXR0b24gbm9kZVxuXHQgKiBAcmV0dXJuIHtCdXR0b25zfSBTZWxmIGZvciBjaGFpbmluZ1xuXHQgKi9cblx0cmVtb3ZlOiBmdW5jdGlvbiAoIG5vZGUgKVxuXHR7XG5cdFx0dmFyIGJ1dHRvbiA9IHRoaXMuX25vZGVUb0J1dHRvbiggbm9kZSApO1xuXHRcdHZhciBob3N0ID0gdGhpcy5fbm9kZVRvSG9zdCggbm9kZSApO1xuXHRcdHZhciBkdCA9IHRoaXMucy5kdDtcblxuXHRcdC8vIFJlbW92ZSBhbnkgY2hpbGQgYnV0dG9ucyBmaXJzdFxuXHRcdGlmICggYnV0dG9uLmJ1dHRvbnMubGVuZ3RoICkge1xuXHRcdFx0Zm9yICggdmFyIGk9YnV0dG9uLmJ1dHRvbnMubGVuZ3RoLTEgOyBpPj0wIDsgaS0tICkge1xuXHRcdFx0XHR0aGlzLnJlbW92ZSggYnV0dG9uLmJ1dHRvbnNbaV0ubm9kZSApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGJ1dHRvbi5jb25mLmRlc3Ryb3lpbmcgPSB0cnVlO1xuXG5cdFx0Ly8gQWxsb3cgdGhlIGJ1dHRvbiB0byByZW1vdmUgZXZlbnQgaGFuZGxlcnMsIGV0Y1xuXHRcdGlmICggYnV0dG9uLmNvbmYuZGVzdHJveSApIHtcblx0XHRcdGJ1dHRvbi5jb25mLmRlc3Ryb3kuY2FsbCggZHQuYnV0dG9uKG5vZGUpLCBkdCwgJChub2RlKSwgYnV0dG9uLmNvbmYgKTtcblx0XHR9XG5cblx0XHR0aGlzLl9yZW1vdmVLZXkoIGJ1dHRvbi5jb25mICk7XG5cblx0XHQkKGJ1dHRvbi5ub2RlKS5yZW1vdmUoKTtcblxuXHRcdHZhciBpZHggPSAkLmluQXJyYXkoIGJ1dHRvbiwgaG9zdCApO1xuXHRcdGhvc3Quc3BsaWNlKCBpZHgsIDEgKTtcblxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdC8qKlxuXHQgKiBHZXQgdGhlIHRleHQgZm9yIGEgYnV0dG9uXG5cdCAqIEBwYXJhbSAge2ludHxzdHJpbmd9IG5vZGUgQnV0dG9uIGluZGV4XG5cdCAqIEByZXR1cm4ge3N0cmluZ30gQnV0dG9uIHRleHRcblx0ICovLyoqXG5cdCAqIFNldCB0aGUgdGV4dCBmb3IgYSBidXR0b25cblx0ICogQHBhcmFtICB7aW50fHN0cmluZ3xmdW5jdGlvbn0gbm9kZSBCdXR0b24gaW5kZXhcblx0ICogQHBhcmFtICB7c3RyaW5nfSBsYWJlbCBUZXh0XG5cdCAqIEByZXR1cm4ge0J1dHRvbnN9IFNlbGYgZm9yIGNoYWluaW5nXG5cdCAqL1xuXHR0ZXh0OiBmdW5jdGlvbiAoIG5vZGUsIGxhYmVsIClcblx0e1xuXHRcdHZhciBidXR0b24gPSB0aGlzLl9ub2RlVG9CdXR0b24oIG5vZGUgKTtcblx0XHR2YXIgYnV0dG9uTGluZXIgPSB0aGlzLmMuZG9tLmNvbGxlY3Rpb24uYnV0dG9uTGluZXI7XG5cdFx0dmFyIGxpbmVyVGFnID0gYnV0dG9uLmluQ29sbGVjdGlvbiAmJiBidXR0b25MaW5lciAmJiBidXR0b25MaW5lci50YWcgP1xuXHRcdFx0YnV0dG9uTGluZXIudGFnIDpcblx0XHRcdHRoaXMuYy5kb20uYnV0dG9uTGluZXIudGFnO1xuXHRcdHZhciBkdCA9IHRoaXMucy5kdDtcblx0XHR2YXIganFOb2RlID0gJChidXR0b24ubm9kZSk7XG5cdFx0dmFyIHRleHQgPSBmdW5jdGlvbiAoIG9wdCApIHtcblx0XHRcdHJldHVybiB0eXBlb2Ygb3B0ID09PSAnZnVuY3Rpb24nID9cblx0XHRcdFx0b3B0KCBkdCwganFOb2RlLCBidXR0b24uY29uZiApIDpcblx0XHRcdFx0b3B0O1xuXHRcdH07XG5cblx0XHRpZiAoIGxhYmVsID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRyZXR1cm4gdGV4dCggYnV0dG9uLmNvbmYudGV4dCApO1xuXHRcdH1cblxuXHRcdGJ1dHRvbi5jb25mLnRleHQgPSBsYWJlbDtcblxuXHRcdGlmICggbGluZXJUYWcgKSB7XG5cdFx0XHRqcU5vZGVcblx0XHRcdFx0LmNoaWxkcmVuKCBsaW5lclRhZyApXG5cdFx0XHRcdC5lcSgwKVxuXHRcdFx0XHQuZmlsdGVyKCc6bm90KC5kdC1kb3duLWFycm93KScpXG5cdFx0XHRcdC5odG1sKCB0ZXh0KGxhYmVsKSApO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdGpxTm9kZS5odG1sKCB0ZXh0KGxhYmVsKSApO1xuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cblx0LyogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKlxuXHQgKiBDb25zdHJ1Y3RvclxuXHQgKi9cblxuXHQvKipcblx0ICogQnV0dG9ucyBjb25zdHJ1Y3RvclxuXHQgKiBAcHJpdmF0ZVxuXHQgKi9cblx0X2NvbnN0cnVjdG9yOiBmdW5jdGlvbiAoKVxuXHR7XG5cdFx0dmFyIHRoYXQgPSB0aGlzO1xuXHRcdHZhciBkdCA9IHRoaXMucy5kdDtcblx0XHR2YXIgZHRTZXR0aW5ncyA9IGR0LnNldHRpbmdzKClbMF07XG5cdFx0dmFyIGJ1dHRvbnMgPSAgdGhpcy5jLmJ1dHRvbnM7XG5cblx0XHRpZiAoICEgZHRTZXR0aW5ncy5fYnV0dG9ucyApIHtcblx0XHRcdGR0U2V0dGluZ3MuX2J1dHRvbnMgPSBbXTtcblx0XHR9XG5cblx0XHRkdFNldHRpbmdzLl9idXR0b25zLnB1c2goIHtcblx0XHRcdGluc3Q6IHRoaXMsXG5cdFx0XHRuYW1lOiB0aGlzLmMubmFtZVxuXHRcdH0gKTtcblxuXHRcdGZvciAoIHZhciBpPTAsIGllbj1idXR0b25zLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdFx0dGhpcy5hZGQoIGJ1dHRvbnNbaV0gKTtcblx0XHR9XG5cblx0XHRkdC5vbiggJ2Rlc3Ryb3knLCBmdW5jdGlvbiAoIGUsIHNldHRpbmdzICkge1xuXHRcdFx0aWYgKCBzZXR0aW5ncyA9PT0gZHRTZXR0aW5ncyApIHtcblx0XHRcdFx0dGhhdC5kZXN0cm95KCk7XG5cdFx0XHR9XG5cdFx0fSApO1xuXG5cdFx0Ly8gR2xvYmFsIGtleSBldmVudCBiaW5kaW5nIHRvIGxpc3RlbiBmb3IgYnV0dG9uIGtleXNcblx0XHQkKCdib2R5Jykub24oICdrZXl1cC4nK3RoaXMucy5uYW1lc3BhY2UsIGZ1bmN0aW9uICggZSApIHtcblx0XHRcdGlmICggISBkb2N1bWVudC5hY3RpdmVFbGVtZW50IHx8IGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgPT09IGRvY3VtZW50LmJvZHkgKSB7XG5cdFx0XHRcdC8vIFNVc2UgYSBzdHJpbmcgb2YgY2hhcmFjdGVycyBmb3IgZmFzdCBsb29rdXAgb2YgaWYgd2UgbmVlZCB0b1xuXHRcdFx0XHQvLyBoYW5kbGUgdGhpc1xuXHRcdFx0XHR2YXIgY2hhcmFjdGVyID0gU3RyaW5nLmZyb21DaGFyQ29kZShlLmtleUNvZGUpLnRvTG93ZXJDYXNlKCk7XG5cblx0XHRcdFx0aWYgKCB0aGF0LnMubGlzdGVuS2V5cy50b0xvd2VyQ2FzZSgpLmluZGV4T2YoIGNoYXJhY3RlciApICE9PSAtMSApIHtcblx0XHRcdFx0XHR0aGF0Ll9rZXlwcmVzcyggY2hhcmFjdGVyLCBlICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9ICk7XG5cdH0sXG5cblxuXHQvKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqXG5cdCAqIFByaXZhdGUgbWV0aG9kc1xuXHQgKi9cblxuXHQvKipcblx0ICogQWRkIGEgbmV3IGJ1dHRvbiB0byB0aGUga2V5IHByZXNzIGxpc3RlbmVyXG5cdCAqIEBwYXJhbSB7b2JqZWN0fSBjb25mIFJlc29sdmVkIGJ1dHRvbiBjb25maWd1cmF0aW9uIG9iamVjdFxuXHQgKiBAcHJpdmF0ZVxuXHQgKi9cblx0X2FkZEtleTogZnVuY3Rpb24gKCBjb25mIClcblx0e1xuXHRcdGlmICggY29uZi5rZXkgKSB7XG5cdFx0XHR0aGlzLnMubGlzdGVuS2V5cyArPSAkLmlzUGxhaW5PYmplY3QoIGNvbmYua2V5ICkgP1xuXHRcdFx0XHRjb25mLmtleS5rZXkgOlxuXHRcdFx0XHRjb25mLmtleTtcblx0XHR9XG5cdH0sXG5cblx0LyoqXG5cdCAqIEluc2VydCB0aGUgYnV0dG9ucyBpbnRvIHRoZSBjb250YWluZXIuIENhbGwgd2l0aG91dCBwYXJhbWV0ZXJzIVxuXHQgKiBAcGFyYW0gIHtub2RlfSBbY29udGFpbmVyXSBSZWN1cnNpdmUgb25seSAtIEluc2VydCBwb2ludFxuXHQgKiBAcGFyYW0gIHthcnJheX0gW2J1dHRvbnNdIFJlY3Vyc2l2ZSBvbmx5IC0gQnV0dG9ucyBhcnJheVxuXHQgKiBAcHJpdmF0ZVxuXHQgKi9cblx0X2RyYXc6IGZ1bmN0aW9uICggY29udGFpbmVyLCBidXR0b25zIClcblx0e1xuXHRcdGlmICggISBjb250YWluZXIgKSB7XG5cdFx0XHRjb250YWluZXIgPSB0aGlzLmRvbS5jb250YWluZXI7XG5cdFx0XHRidXR0b25zID0gdGhpcy5zLmJ1dHRvbnM7XG5cdFx0fVxuXG5cdFx0Y29udGFpbmVyLmNoaWxkcmVuKCkuZGV0YWNoKCk7XG5cblx0XHRmb3IgKCB2YXIgaT0wLCBpZW49YnV0dG9ucy5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdGNvbnRhaW5lci5hcHBlbmQoIGJ1dHRvbnNbaV0uaW5zZXJ0ZXIgKTtcblx0XHRcdGNvbnRhaW5lci5hcHBlbmQoICcgJyApO1xuXG5cdFx0XHRpZiAoIGJ1dHRvbnNbaV0uYnV0dG9ucyAmJiBidXR0b25zW2ldLmJ1dHRvbnMubGVuZ3RoICkge1xuXHRcdFx0XHR0aGlzLl9kcmF3KCBidXR0b25zW2ldLmNvbGxlY3Rpb24sIGJ1dHRvbnNbaV0uYnV0dG9ucyApO1xuXHRcdFx0fVxuXHRcdH1cblx0fSxcblxuXHQvKipcblx0ICogQ3JlYXRlIGJ1dHRvbnMgZnJvbSBhbiBhcnJheSBvZiBidXR0b25zXG5cdCAqIEBwYXJhbSAge2FycmF5fSBhdHRhY2hUbyBCdXR0b25zIGFycmF5IHRvIGF0dGFjaCB0b1xuXHQgKiBAcGFyYW0gIHtvYmplY3R9IGJ1dHRvbiBCdXR0b24gZGVmaW5pdGlvblxuXHQgKiBAcGFyYW0gIHtib29sZWFufSBpbkNvbGxlY3Rpb24gdHJ1ZSBpZiB0aGUgYnV0dG9uIGlzIGluIGEgY29sbGVjdGlvblxuXHQgKiBAcHJpdmF0ZVxuXHQgKi9cblx0X2V4cGFuZEJ1dHRvbjogZnVuY3Rpb24gKCBhdHRhY2hUbywgYnV0dG9uLCBzcGxpdCwgaW5Db2xsZWN0aW9uLCBpblNwbGl0LCBhdHRhY2hQb2ludCwgcGFyZW50Q29uZiApXG5cdHtcblx0XHR2YXIgZHQgPSB0aGlzLnMuZHQ7XG5cdFx0dmFyIGJ1dHRvbkNvdW50ZXIgPSAwO1xuXHRcdHZhciBpc1NwbGl0ID0gZmFsc2U7XG5cdFx0dmFyIGJ1dHRvbnMgPSAhIEFycmF5LmlzQXJyYXkoIGJ1dHRvbiApID9cblx0XHRcdFsgYnV0dG9uIF0gOlxuXHRcdFx0YnV0dG9uO1xuXHRcdFxuXHRcdGlmKGJ1dHRvbiA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0YnV0dG9ucyA9ICFBcnJheS5pc0FycmF5KHNwbGl0KSA/XG5cdFx0XHRcdFsgc3BsaXQgXSA6XG5cdFx0XHRcdHNwbGl0O1xuXHRcdH1cblxuXHRcdGlmIChidXR0b24gIT09IHVuZGVmaW5lZCAmJiBidXR0b24uc3BsaXQgIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0aXNTcGxpdCA9IHRydWU7XG5cdFx0fVxuXHRcdFx0XG5cdFx0Zm9yICggdmFyIGk9MCwgaWVuPWJ1dHRvbnMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHR2YXIgY29uZiA9IHRoaXMuX3Jlc29sdmVFeHRlbmRzKCBidXR0b25zW2ldICk7XG5cblx0XHRcdGlmICggISBjb25mICkge1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0aWYoIGNvbmYuY29uZmlnICE9PSB1bmRlZmluZWQgJiYgY29uZi5jb25maWcuc3BsaXQpIHtcblx0XHRcdFx0aXNTcGxpdCA9IHRydWU7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0aXNTcGxpdCA9IGZhbHNlO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHQvLyBJZiB0aGUgY29uZmlndXJhdGlvbiBpcyBhbiBhcnJheSwgdGhlbiBleHBhbmQgdGhlIGJ1dHRvbnMgYXQgdGhpc1xuXHRcdFx0Ly8gcG9pbnRcblx0XHRcdGlmICggQXJyYXkuaXNBcnJheSggY29uZiApICkge1xuXHRcdFx0XHR0aGlzLl9leHBhbmRCdXR0b24oIGF0dGFjaFRvLCBjb25mLCBidWlsdCAhPT0gdW5kZWZpbmVkICYmIGJ1aWx0LmNvbmYgIT09IHVuZGVmaW5lZCA/IGJ1aWx0LmNvbmYuc3BsaXQgOiB1bmRlZmluZWQsIGluQ29sbGVjdGlvbiwgcGFyZW50Q29uZiAhPT0gdW5kZWZpbmVkICYmIHBhcmVudENvbmYuc3BsaXQgIT09IHVuZGVmaW5lZCwgYXR0YWNoUG9pbnQsIHBhcmVudENvbmYgKTtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cblx0XHRcdHZhciBidWlsdCA9IHRoaXMuX2J1aWxkQnV0dG9uKCBjb25mLCBpbkNvbGxlY3Rpb24sIGNvbmYuc3BsaXQgIT09IHVuZGVmaW5lZCB8fCAoY29uZi5jb25maWcgIT09IHVuZGVmaW5lZCAmJiBjb25mLmNvbmZpZy5zcGxpdCAhPT0gdW5kZWZpbmVkKSwgaW5TcGxpdCApO1xuXHRcdFx0aWYgKCAhIGJ1aWx0ICkge1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCBhdHRhY2hQb2ludCAhPT0gdW5kZWZpbmVkICYmIGF0dGFjaFBvaW50ICE9PSBudWxsICkge1xuXHRcdFx0XHRhdHRhY2hUby5zcGxpY2UoIGF0dGFjaFBvaW50LCAwLCBidWlsdCApO1xuXHRcdFx0XHRhdHRhY2hQb2ludCsrO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSB7XG5cdFx0XHRcdGF0dGFjaFRvLnB1c2goIGJ1aWx0ICk7XG5cdFx0XHR9XG5cblx0XHRcdFxuXHRcdFx0aWYgKCBidWlsdC5jb25mLmJ1dHRvbnMgfHwgYnVpbHQuY29uZi5zcGxpdCApIHtcblx0XHRcdFx0YnVpbHQuY29sbGVjdGlvbiA9ICQoJzwnKyhpc1NwbGl0ID8gdGhpcy5jLmRvbS5zcGxpdENvbGxlY3Rpb24udGFnIDogdGhpcy5jLmRvbS5jb2xsZWN0aW9uLnRhZykrJy8+Jyk7XG5cblx0XHRcdFx0YnVpbHQuY29uZi5fY29sbGVjdGlvbiA9IGJ1aWx0LmNvbGxlY3Rpb247XG5cblx0XHRcdFx0aWYoYnVpbHQuY29uZi5zcGxpdCkge1xuXHRcdFx0XHRcdGZvcih2YXIgaiA9IDA7IGogPCBidWlsdC5jb25mLnNwbGl0Lmxlbmd0aDsgaisrKSB7XG5cdFx0XHRcdFx0XHRpZih0eXBlb2YgYnVpbHQuY29uZi5zcGxpdFtqXSA9PT0gXCJvYmplY3RcIikge1xuXHRcdFx0XHRcdFx0XHRidWlsdC5jb25mLnNwbGl0W2pdLnBhcmVudCA9IHBhcmVudENvbmY7XG5cdFx0XHRcdFx0XHRcdGlmKGJ1aWx0LmNvbmYuc3BsaXRbal0uY29sbGVjdGlvbkxheW91dCA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdFx0XHRcdFx0YnVpbHQuY29uZi5zcGxpdFtqXS5jb2xsZWN0aW9uTGF5b3V0ID0gYnVpbHQuY29uZi5jb2xsZWN0aW9uTGF5b3V0O1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdGlmKGJ1aWx0LmNvbmYuc3BsaXRbal0uZHJvcHVwID09PSB1bmRlZmluZWQpIHtcblx0XHRcdFx0XHRcdFx0XHRidWlsdC5jb25mLnNwbGl0W2pdLmRyb3B1cCA9IGJ1aWx0LmNvbmYuZHJvcHVwO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdGlmKGJ1aWx0LmNvbmYuc3BsaXRbal0uZmFkZSA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdFx0XHRcdFx0YnVpbHQuY29uZi5zcGxpdFtqXS5mYWRlID0gYnVpbHQuY29uZi5mYWRlO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdCQoYnVpbHQubm9kZSkuYXBwZW5kKCQoJzxzcGFuIGNsYXNzPVwiZHQtZG93bi1hcnJvd1wiPicrdGhpcy5jLmRvbS5zcGxpdERyb3Bkb3duLnRleHQrJzwvc3Bhbj4nKSlcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHRoaXMuX2V4cGFuZEJ1dHRvbiggYnVpbHQuYnV0dG9ucywgYnVpbHQuY29uZi5idXR0b25zLCBidWlsdC5jb25mLnNwbGl0LCAhaXNTcGxpdCwgaXNTcGxpdCwgYXR0YWNoUG9pbnQsIGJ1aWx0LmNvbmYgKTtcblx0XHRcdH1cblx0XHRcdGJ1aWx0LmNvbmYucGFyZW50ID0gcGFyZW50Q29uZjtcblxuXHRcdFx0Ly8gaW5pdCBjYWxsIGlzIG1hZGUgaGVyZSwgcmF0aGVyIHRoYW4gYnVpbGRCdXR0b24gYXMgaXQgbmVlZHMgdG9cblx0XHRcdC8vIGJlIHNlbGVjdGFibGUsIGFuZCBmb3IgdGhhdCBpdCBuZWVkcyB0byBiZSBpbiB0aGUgYnV0dG9ucyBhcnJheVxuXHRcdFx0aWYgKCBjb25mLmluaXQgKSB7XG5cdFx0XHRcdGNvbmYuaW5pdC5jYWxsKCBkdC5idXR0b24oIGJ1aWx0Lm5vZGUgKSwgZHQsICQoYnVpbHQubm9kZSksIGNvbmYgKTtcblx0XHRcdH1cblxuXHRcdFx0YnV0dG9uQ291bnRlcisrO1xuXHRcdH1cblx0fSxcblxuXHQvKipcblx0ICogQ3JlYXRlIGFuIGluZGl2aWR1YWwgYnV0dG9uXG5cdCAqIEBwYXJhbSAge29iamVjdH0gY29uZmlnICAgICAgICAgICAgUmVzb2x2ZWQgYnV0dG9uIGNvbmZpZ3VyYXRpb25cblx0ICogQHBhcmFtICB7Ym9vbGVhbn0gaW5Db2xsZWN0aW9uIGB0cnVlYCBpZiBhIGNvbGxlY3Rpb24gYnV0dG9uXG5cdCAqIEByZXR1cm4ge2pRdWVyeX0gQ3JlYXRlZCBidXR0b24gbm9kZSAoalF1ZXJ5KVxuXHQgKiBAcHJpdmF0ZVxuXHQgKi9cblx0X2J1aWxkQnV0dG9uOiBmdW5jdGlvbiAoIGNvbmZpZywgaW5Db2xsZWN0aW9uLCBpc1NwbGl0LCBpblNwbGl0IClcblx0e1xuXHRcdHZhciBidXR0b25Eb20gPSB0aGlzLmMuZG9tLmJ1dHRvbjtcblx0XHR2YXIgbGluZXJEb20gPSB0aGlzLmMuZG9tLmJ1dHRvbkxpbmVyO1xuXHRcdHZhciBjb2xsZWN0aW9uRG9tID0gdGhpcy5jLmRvbS5jb2xsZWN0aW9uO1xuXHRcdHZhciBzcGxpdERvbSA9IHRoaXMuYy5kb20uc3BsaXQ7XG5cdFx0dmFyIHNwbGl0Q29sbGVjdGlvbkRvbSA9IHRoaXMuYy5kb20uc3BsaXRDb2xsZWN0aW9uO1xuXHRcdHZhciBzcGxpdERyb3Bkb3duQnV0dG9uID0gdGhpcy5jLmRvbS5zcGxpdERyb3Bkb3duQnV0dG9uO1xuXHRcdHZhciBkdCA9IHRoaXMucy5kdDtcblx0XHR2YXIgdGV4dCA9IGZ1bmN0aW9uICggb3B0ICkge1xuXHRcdFx0cmV0dXJuIHR5cGVvZiBvcHQgPT09ICdmdW5jdGlvbicgP1xuXHRcdFx0XHRvcHQoIGR0LCBidXR0b24sIGNvbmZpZyApIDpcblx0XHRcdFx0b3B0O1xuXHRcdH07XG5cblx0XHQvLyBTcGFjZXJzIGRvbid0IGRvIG11Y2ggb3RoZXIgdGhhbiBpbnNlcnQgYW4gZWxlbWVudCBpbnRvIHRoZSBET01cblx0XHRpZiAoY29uZmlnLnNwYWNlcikge1xuXHRcdFx0dmFyIHNwYWNlciA9ICQoJzxzcGFuPjwvc3Bhbj4nKVxuXHRcdFx0XHQuYWRkQ2xhc3MoJ2R0LWJ1dHRvbi1zcGFjZXIgJyArIGNvbmZpZy5zdHlsZSArICcgJyArIGJ1dHRvbkRvbS5zcGFjZXJDbGFzcylcblx0XHRcdFx0Lmh0bWwodGV4dChjb25maWcudGV4dCkpO1xuXG5cdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRjb25mOiAgICAgICAgIGNvbmZpZyxcblx0XHRcdFx0bm9kZTogICAgICAgICBzcGFjZXIsXG5cdFx0XHRcdGluc2VydGVyOiAgICAgc3BhY2VyLFxuXHRcdFx0XHRidXR0b25zOiAgICAgIFtdLFxuXHRcdFx0XHRpbkNvbGxlY3Rpb246IGluQ29sbGVjdGlvbixcblx0XHRcdFx0aXNTcGxpdDpcdCAgaXNTcGxpdCxcblx0XHRcdFx0aW5TcGxpdDpcdCAgaW5TcGxpdCxcblx0XHRcdFx0Y29sbGVjdGlvbjogICBudWxsXG5cdFx0XHR9O1xuXHRcdH1cblxuXHRcdGlmICggIWlzU3BsaXQgJiYgaW5TcGxpdCAmJiBzcGxpdENvbGxlY3Rpb25Eb20gKSB7XG5cdFx0XHRidXR0b25Eb20gPSBzcGxpdERyb3Bkb3duQnV0dG9uO1xuXHRcdH1cblx0XHRlbHNlIGlmICggIWlzU3BsaXQgJiYgaW5Db2xsZWN0aW9uICYmIGNvbGxlY3Rpb25Eb20uYnV0dG9uICkge1xuXHRcdFx0YnV0dG9uRG9tID0gY29sbGVjdGlvbkRvbS5idXR0b247XG5cdFx0fSBcblxuXHRcdGlmICggIWlzU3BsaXQgJiYgaW5TcGxpdCAmJiBzcGxpdENvbGxlY3Rpb25Eb20uYnV0dG9uTGluZXIgKSB7XG5cdFx0XHRsaW5lckRvbSA9IHNwbGl0Q29sbGVjdGlvbkRvbS5idXR0b25MaW5lclxuXHRcdH1cblx0XHRlbHNlIGlmICggIWlzU3BsaXQgJiYgaW5Db2xsZWN0aW9uICYmIGNvbGxlY3Rpb25Eb20uYnV0dG9uTGluZXIgKSB7XG5cdFx0XHRsaW5lckRvbSA9IGNvbGxlY3Rpb25Eb20uYnV0dG9uTGluZXI7XG5cdFx0fVxuXG5cdFx0Ly8gTWFrZSBzdXJlIHRoYXQgdGhlIGJ1dHRvbiBpcyBhdmFpbGFibGUgYmFzZWQgb24gd2hhdGV2ZXIgcmVxdWlyZW1lbnRzXG5cdFx0Ly8gaXQgaGFzLiBGb3IgZXhhbXBsZSwgUERGIGJ1dHRvbiByZXF1aXJlIHBkZm1ha2Vcblx0XHRpZiAoIGNvbmZpZy5hdmFpbGFibGUgJiYgISBjb25maWcuYXZhaWxhYmxlKCBkdCwgY29uZmlnICkgJiYgIWNvbmZpZy5oYXNPd25Qcm9wZXJ0eSgnaHRtbCcpICkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblxuXHRcdHZhciBidXR0b247XG5cdFx0aWYoIWNvbmZpZy5oYXNPd25Qcm9wZXJ0eSgnaHRtbCcpKSB7XG5cdFx0XHR2YXIgYWN0aW9uID0gZnVuY3Rpb24gKCBlLCBkdCwgYnV0dG9uLCBjb25maWcgKSB7XG5cdFx0XHRcdGNvbmZpZy5hY3Rpb24uY2FsbCggZHQuYnV0dG9uKCBidXR0b24gKSwgZSwgZHQsIGJ1dHRvbiwgY29uZmlnICk7XG5cdFxuXHRcdFx0XHQkKGR0LnRhYmxlKCkubm9kZSgpKS50cmlnZ2VySGFuZGxlciggJ2J1dHRvbnMtYWN0aW9uLmR0JywgW1xuXHRcdFx0XHRcdGR0LmJ1dHRvbiggYnV0dG9uICksIGR0LCBidXR0b24sIGNvbmZpZyBcblx0XHRcdFx0XSApO1xuXHRcdFx0fTtcblxuXHRcdFx0dmFyIHRhZyA9IGNvbmZpZy50YWcgfHwgYnV0dG9uRG9tLnRhZztcblx0XHRcdHZhciBjbGlja0JsdXJzID0gY29uZmlnLmNsaWNrQmx1cnMgPT09IHVuZGVmaW5lZFxuXHRcdFx0XHQ/IHRydWUgOlxuXHRcdFx0XHRjb25maWcuY2xpY2tCbHVycztcblxuXHRcdFx0YnV0dG9uID0gJCgnPCcrdGFnKycvPicpXG5cdFx0XHRcdC5hZGRDbGFzcyggYnV0dG9uRG9tLmNsYXNzTmFtZSApXG5cdFx0XHRcdC5hZGRDbGFzcyggaW5TcGxpdCA/IHRoaXMuYy5kb20uc3BsaXREcm9wZG93bkJ1dHRvbi5jbGFzc05hbWUgOiAnJylcblx0XHRcdFx0LmF0dHIoICd0YWJpbmRleCcsIHRoaXMucy5kdC5zZXR0aW5ncygpWzBdLmlUYWJJbmRleCApXG5cdFx0XHRcdC5hdHRyKCAnYXJpYS1jb250cm9scycsIHRoaXMucy5kdC50YWJsZSgpLm5vZGUoKS5pZCApXG5cdFx0XHRcdC5vbiggJ2NsaWNrLmR0YicsIGZ1bmN0aW9uIChlKSB7XG5cdFx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcblx0XHRcdFx0XHRpZiAoICEgYnV0dG9uLmhhc0NsYXNzKCBidXR0b25Eb20uZGlzYWJsZWQgKSAmJiBjb25maWcuYWN0aW9uICkge1xuXHRcdFx0XHRcdFx0YWN0aW9uKCBlLCBkdCwgYnV0dG9uLCBjb25maWcgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0aWYoIGNsaWNrQmx1cnMgKSB7XG5cdFx0XHRcdFx0XHRidXR0b24udHJpZ2dlcignYmx1cicpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApXG5cdFx0XHRcdC5vbiggJ2tleXByZXNzLmR0YicsIGZ1bmN0aW9uIChlKSB7XG5cdFx0XHRcdFx0aWYgKCBlLmtleUNvZGUgPT09IDEzICkge1xuXHRcdFx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0XHRcdFx0XHRpZiAoICEgYnV0dG9uLmhhc0NsYXNzKCBidXR0b25Eb20uZGlzYWJsZWQgKSAmJiBjb25maWcuYWN0aW9uICkge1xuXHRcdFx0XHRcdFx0XHRhY3Rpb24oIGUsIGR0LCBidXR0b24sIGNvbmZpZyApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApO1xuXHRcblx0XHRcdC8vIE1ha2UgYGFgIHRhZ3MgYWN0IGxpa2UgYSBsaW5rXG5cdFx0XHRpZiAoIHRhZy50b0xvd2VyQ2FzZSgpID09PSAnYScgKSB7XG5cdFx0XHRcdGJ1dHRvbi5hdHRyKCAnaHJlZicsICcjJyApO1xuXHRcdFx0fVxuXHRcblx0XHRcdC8vIEJ1dHRvbiB0YWdzIHNob3VsZCBoYXZlIGB0eXBlPWJ1dHRvbmAgc28gdGhleSBkb24ndCBoYXZlIGFueSBkZWZhdWx0IGJlaGF2aW91clxuXHRcdFx0aWYgKCB0YWcudG9Mb3dlckNhc2UoKSA9PT0gJ2J1dHRvbicgKSB7XG5cdFx0XHRcdGJ1dHRvbi5hdHRyKCAndHlwZScsICdidXR0b24nICk7XG5cdFx0XHR9XG5cdFxuXHRcdFx0aWYgKCBsaW5lckRvbS50YWcgKSB7XG5cdFx0XHRcdHZhciBsaW5lciA9ICQoJzwnK2xpbmVyRG9tLnRhZysnLz4nKVxuXHRcdFx0XHRcdC5odG1sKCB0ZXh0KCBjb25maWcudGV4dCApIClcblx0XHRcdFx0XHQuYWRkQ2xhc3MoIGxpbmVyRG9tLmNsYXNzTmFtZSApO1xuXHRcblx0XHRcdFx0aWYgKCBsaW5lckRvbS50YWcudG9Mb3dlckNhc2UoKSA9PT0gJ2EnICkge1xuXHRcdFx0XHRcdGxpbmVyLmF0dHIoICdocmVmJywgJyMnICk7XG5cdFx0XHRcdH1cblx0XG5cdFx0XHRcdGJ1dHRvbi5hcHBlbmQoIGxpbmVyICk7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0YnV0dG9uLmh0bWwoIHRleHQoIGNvbmZpZy50ZXh0ICkgKTtcblx0XHRcdH1cblx0XG5cdFx0XHRpZiAoIGNvbmZpZy5lbmFibGVkID09PSBmYWxzZSApIHtcblx0XHRcdFx0YnV0dG9uLmFkZENsYXNzKCBidXR0b25Eb20uZGlzYWJsZWQgKTtcblx0XHRcdH1cblx0XG5cdFx0XHRpZiAoIGNvbmZpZy5jbGFzc05hbWUgKSB7XG5cdFx0XHRcdGJ1dHRvbi5hZGRDbGFzcyggY29uZmlnLmNsYXNzTmFtZSApO1xuXHRcdFx0fVxuXHRcblx0XHRcdGlmICggY29uZmlnLnRpdGxlQXR0ciApIHtcblx0XHRcdFx0YnV0dG9uLmF0dHIoICd0aXRsZScsIHRleHQoIGNvbmZpZy50aXRsZUF0dHIgKSApO1xuXHRcdFx0fVxuXHRcblx0XHRcdGlmICggY29uZmlnLmF0dHIgKSB7XG5cdFx0XHRcdGJ1dHRvbi5hdHRyKCBjb25maWcuYXR0ciApO1xuXHRcdFx0fVxuXHRcblx0XHRcdGlmICggISBjb25maWcubmFtZXNwYWNlICkge1xuXHRcdFx0XHRjb25maWcubmFtZXNwYWNlID0gJy5kdC1idXR0b24tJysoX2J1dHRvbkNvdW50ZXIrKyk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICAoIGNvbmZpZy5jb25maWcgIT09IHVuZGVmaW5lZCAmJiBjb25maWcuY29uZmlnLnNwbGl0ICkge1xuXHRcdFx0XHRjb25maWcuc3BsaXQgPSBjb25maWcuY29uZmlnLnNwbGl0O1xuXHRcdFx0fVxuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdGJ1dHRvbiA9ICQoY29uZmlnLmh0bWwpXG5cdFx0fVxuXHRcblx0XHR2YXIgYnV0dG9uQ29udGFpbmVyID0gdGhpcy5jLmRvbS5idXR0b25Db250YWluZXI7XG5cdFx0dmFyIGluc2VydGVyO1xuXHRcdGlmICggYnV0dG9uQ29udGFpbmVyICYmIGJ1dHRvbkNvbnRhaW5lci50YWcgKSB7XG5cdFx0XHRpbnNlcnRlciA9ICQoJzwnK2J1dHRvbkNvbnRhaW5lci50YWcrJy8+Jylcblx0XHRcdFx0LmFkZENsYXNzKCBidXR0b25Db250YWluZXIuY2xhc3NOYW1lIClcblx0XHRcdFx0LmFwcGVuZCggYnV0dG9uICk7XG5cdFx0fVxuXHRcdGVsc2Uge1xuXHRcdFx0aW5zZXJ0ZXIgPSBidXR0b247XG5cdFx0fVxuXG5cdFx0dGhpcy5fYWRkS2V5KCBjb25maWcgKTtcblxuXHRcdC8vIFN0eWxlIGludGVncmF0aW9uIGNhbGxiYWNrIGZvciBET00gbWFuaXB1bGF0aW9uXG5cdFx0Ly8gTm90ZSB0aGF0IHRoaXMgaXMgX25vdF8gZG9jdW1lbnRlZC4gSXQgaXMgY3VycmVudGx5XG5cdFx0Ly8gZm9yIHN0eWxlIGludGVncmF0aW9uIG9ubHlcblx0XHRpZiggdGhpcy5jLmJ1dHRvbkNyZWF0ZWQgKSB7XG5cdFx0XHRpbnNlcnRlciA9IHRoaXMuYy5idXR0b25DcmVhdGVkKCBjb25maWcsIGluc2VydGVyICk7XG5cdFx0fVxuXG5cdFx0dmFyIHNwbGl0RGl2O1xuXHRcdGlmKGlzU3BsaXQpIHtcblx0XHRcdHNwbGl0RGl2ID0gJCgnPGRpdi8+JykuYWRkQ2xhc3ModGhpcy5jLmRvbS5zcGxpdFdyYXBwZXIuY2xhc3NOYW1lKVxuXHRcdFx0c3BsaXREaXYuYXBwZW5kKGJ1dHRvbik7XG5cdFx0XHR2YXIgZHJvcEJ1dHRvbkNvbmZpZyA9ICQuZXh0ZW5kKGNvbmZpZywge1xuXHRcdFx0XHR0ZXh0OiB0aGlzLmMuZG9tLnNwbGl0RHJvcGRvd24udGV4dCxcblx0XHRcdFx0Y2xhc3NOYW1lOiB0aGlzLmMuZG9tLnNwbGl0RHJvcGRvd24uY2xhc3NOYW1lLFxuXHRcdFx0XHRjbG9zZUJ1dHRvbjogZmFsc2UsXG5cdFx0XHRcdGF0dHI6IHtcblx0XHRcdFx0XHQnYXJpYS1oYXNwb3B1cCc6ICdkaWFsb2cnLFxuXHRcdFx0XHRcdCdhcmlhLWV4cGFuZGVkJzogZmFsc2Vcblx0XHRcdFx0fSxcblx0XHRcdFx0YWxpZ246IHRoaXMuYy5kb20uc3BsaXREcm9wZG93bi5hbGlnbixcblx0XHRcdFx0c3BsaXRBbGlnbkNsYXNzOiB0aGlzLmMuZG9tLnNwbGl0RHJvcGRvd24uc3BsaXRBbGlnbkNsYXNzXG5cdFx0XHRcdFxuXHRcdFx0fSlcblxuXHRcdFx0dGhpcy5fYWRkS2V5KGRyb3BCdXR0b25Db25maWcpO1xuXG5cdFx0XHR2YXIgc3BsaXRBY3Rpb24gPSBmdW5jdGlvbiAoIGUsIGR0LCBidXR0b24sIGNvbmZpZyApIHtcblx0XHRcdFx0X2R0QnV0dG9ucy5zcGxpdC5hY3Rpb24uY2FsbCggZHQuYnV0dG9uKCQoJ2Rpdi5kdC1idG4tc3BsaXQtd3JhcHBlcicpWzBdICksIGUsIGR0LCBidXR0b24sIGNvbmZpZyApO1xuXHRcblx0XHRcdFx0JChkdC50YWJsZSgpLm5vZGUoKSkudHJpZ2dlckhhbmRsZXIoICdidXR0b25zLWFjdGlvbi5kdCcsIFtcblx0XHRcdFx0XHRkdC5idXR0b24oIGJ1dHRvbiApLCBkdCwgYnV0dG9uLCBjb25maWcgXG5cdFx0XHRcdF0gKTtcblx0XHRcdFx0YnV0dG9uLmF0dHIoJ2FyaWEtZXhwYW5kZWQnLCB0cnVlKVxuXHRcdFx0fTtcblx0XHRcdFxuXHRcdFx0dmFyIGRyb3BCdXR0b24gPSAkKCc8YnV0dG9uIGNsYXNzPVwiJyArIHRoaXMuYy5kb20uc3BsaXREcm9wZG93bi5jbGFzc05hbWUgKyAnIGR0LWJ1dHRvblwiPjxzcGFuIGNsYXNzPVwiZHQtYnRuLXNwbGl0LWRyb3AtYXJyb3dcIj4nK3RoaXMuYy5kb20uc3BsaXREcm9wZG93bi50ZXh0Kyc8L3NwYW4+PC9idXR0b24+Jylcblx0XHRcdFx0Lm9uKCAnY2xpY2suZHRiJywgZnVuY3Rpb24gKGUpIHtcblx0XHRcdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcdFx0ZS5zdG9wUHJvcGFnYXRpb24oKTtcblxuXHRcdFx0XHRcdGlmICggISBkcm9wQnV0dG9uLmhhc0NsYXNzKCBidXR0b25Eb20uZGlzYWJsZWQgKSkge1xuXHRcdFx0XHRcdFx0c3BsaXRBY3Rpb24oIGUsIGR0LCBkcm9wQnV0dG9uLCBkcm9wQnV0dG9uQ29uZmlnICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmICggY2xpY2tCbHVycyApIHtcblx0XHRcdFx0XHRcdGRyb3BCdXR0b24udHJpZ2dlcignYmx1cicpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApXG5cdFx0XHRcdC5vbiggJ2tleXByZXNzLmR0YicsIGZ1bmN0aW9uIChlKSB7XG5cdFx0XHRcdFx0aWYgKCBlLmtleUNvZGUgPT09IDEzICkge1xuXHRcdFx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0XHRcdFx0XHRpZiAoICEgZHJvcEJ1dHRvbi5oYXNDbGFzcyggYnV0dG9uRG9tLmRpc2FibGVkICkgKSB7XG5cdFx0XHRcdFx0XHRcdHNwbGl0QWN0aW9uKCBlLCBkdCwgZHJvcEJ1dHRvbiwgZHJvcEJ1dHRvbkNvbmZpZyApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApO1xuXG5cdFx0XHRpZihjb25maWcuc3BsaXQubGVuZ3RoID09PSAwKSB7XG5cdFx0XHRcdGRyb3BCdXR0b24uYWRkQ2xhc3MoJ2R0Yi1oaWRlLWRyb3AnKTtcblx0XHRcdH1cblxuXHRcdFx0c3BsaXREaXYuYXBwZW5kKGRyb3BCdXR0b24pLmF0dHIoZHJvcEJ1dHRvbkNvbmZpZy5hdHRyKTtcblx0XHR9XG5cblx0XHRyZXR1cm4ge1xuXHRcdFx0Y29uZjogICAgICAgICBjb25maWcsXG5cdFx0XHRub2RlOiAgICAgICAgIGlzU3BsaXQgPyBzcGxpdERpdi5nZXQoMCkgOiBidXR0b24uZ2V0KDApLFxuXHRcdFx0aW5zZXJ0ZXI6ICAgICBpc1NwbGl0ID8gc3BsaXREaXYgOiBpbnNlcnRlcixcblx0XHRcdGJ1dHRvbnM6ICAgICAgW10sXG5cdFx0XHRpbkNvbGxlY3Rpb246IGluQ29sbGVjdGlvbixcblx0XHRcdGlzU3BsaXQ6XHQgIGlzU3BsaXQsXG5cdFx0XHRpblNwbGl0Olx0ICBpblNwbGl0LFxuXHRcdFx0Y29sbGVjdGlvbjogICBudWxsXG5cdFx0fTtcblx0fSxcblxuXHQvKipcblx0ICogR2V0IHRoZSBidXR0b24gb2JqZWN0IGZyb20gYSBub2RlIChyZWN1cnNpdmUpXG5cdCAqIEBwYXJhbSAge25vZGV9IG5vZGUgQnV0dG9uIG5vZGVcblx0ICogQHBhcmFtICB7YXJyYXl9IFtidXR0b25zXSBCdXR0b24gYXJyYXksIHVzZXMgYmFzZSBpZiBub3QgZGVmaW5lZFxuXHQgKiBAcmV0dXJuIHtvYmplY3R9IEJ1dHRvbiBvYmplY3Rcblx0ICogQHByaXZhdGVcblx0ICovXG5cdF9ub2RlVG9CdXR0b246IGZ1bmN0aW9uICggbm9kZSwgYnV0dG9ucyApXG5cdHtcblx0XHRpZiAoICEgYnV0dG9ucyApIHtcblx0XHRcdGJ1dHRvbnMgPSB0aGlzLnMuYnV0dG9ucztcblx0XHR9XG5cblx0XHRmb3IgKCB2YXIgaT0wLCBpZW49YnV0dG9ucy5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdGlmICggYnV0dG9uc1tpXS5ub2RlID09PSBub2RlICkge1xuXHRcdFx0XHRyZXR1cm4gYnV0dG9uc1tpXTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCBidXR0b25zW2ldLmJ1dHRvbnMubGVuZ3RoICkge1xuXHRcdFx0XHR2YXIgcmV0ID0gdGhpcy5fbm9kZVRvQnV0dG9uKCBub2RlLCBidXR0b25zW2ldLmJ1dHRvbnMgKTtcblxuXHRcdFx0XHRpZiAoIHJldCApIHtcblx0XHRcdFx0XHRyZXR1cm4gcmV0O1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9LFxuXG5cdC8qKlxuXHQgKiBHZXQgY29udGFpbmVyIGFycmF5IGZvciBhIGJ1dHRvbiBmcm9tIGEgYnV0dG9uIG5vZGUgKHJlY3Vyc2l2ZSlcblx0ICogQHBhcmFtICB7bm9kZX0gbm9kZSBCdXR0b24gbm9kZVxuXHQgKiBAcGFyYW0gIHthcnJheX0gW2J1dHRvbnNdIEJ1dHRvbiBhcnJheSwgdXNlcyBiYXNlIGlmIG5vdCBkZWZpbmVkXG5cdCAqIEByZXR1cm4ge2FycmF5fSBCdXR0b24ncyBob3N0IGFycmF5XG5cdCAqIEBwcml2YXRlXG5cdCAqL1xuXHRfbm9kZVRvSG9zdDogZnVuY3Rpb24gKCBub2RlLCBidXR0b25zIClcblx0e1xuXHRcdGlmICggISBidXR0b25zICkge1xuXHRcdFx0YnV0dG9ucyA9IHRoaXMucy5idXR0b25zO1xuXHRcdH1cblxuXHRcdGZvciAoIHZhciBpPTAsIGllbj1idXR0b25zLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdFx0aWYgKCBidXR0b25zW2ldLm5vZGUgPT09IG5vZGUgKSB7XG5cdFx0XHRcdHJldHVybiBidXR0b25zO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIGJ1dHRvbnNbaV0uYnV0dG9ucy5sZW5ndGggKSB7XG5cdFx0XHRcdHZhciByZXQgPSB0aGlzLl9ub2RlVG9Ib3N0KCBub2RlLCBidXR0b25zW2ldLmJ1dHRvbnMgKTtcblxuXHRcdFx0XHRpZiAoIHJldCApIHtcblx0XHRcdFx0XHRyZXR1cm4gcmV0O1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9LFxuXG5cdC8qKlxuXHQgKiBIYW5kbGUgYSBrZXkgcHJlc3MgLSBkZXRlcm1pbmUgaWYgYW55IGJ1dHRvbidzIGtleSBjb25maWd1cmVkIG1hdGNoZXNcblx0ICogd2hhdCB3YXMgdHlwZWQgYW5kIHRyaWdnZXIgdGhlIGFjdGlvbiBpZiBzby5cblx0ICogQHBhcmFtICB7c3RyaW5nfSBjaGFyYWN0ZXIgVGhlIGNoYXJhY3RlciBwcmVzc2VkXG5cdCAqIEBwYXJhbSAge29iamVjdH0gZSBLZXkgZXZlbnQgdGhhdCB0cmlnZ2VyZWQgdGhpcyBjYWxsXG5cdCAqIEBwcml2YXRlXG5cdCAqL1xuXHRfa2V5cHJlc3M6IGZ1bmN0aW9uICggY2hhcmFjdGVyLCBlIClcblx0e1xuXHRcdC8vIENoZWNrIGlmIHRoaXMgYnV0dG9uIHByZXNzIGFscmVhZHkgYWN0aXZhdGVkIG9uIGFub3RoZXIgaW5zdGFuY2Ugb2YgQnV0dG9uc1xuXHRcdGlmICggZS5fYnV0dG9uc0hhbmRsZWQgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dmFyIHJ1biA9IGZ1bmN0aW9uICggY29uZiwgbm9kZSApIHtcblx0XHRcdGlmICggISBjb25mLmtleSApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIGNvbmYua2V5ID09PSBjaGFyYWN0ZXIgKSB7XG5cdFx0XHRcdGUuX2J1dHRvbnNIYW5kbGVkID0gdHJ1ZTtcblx0XHRcdFx0JChub2RlKS5jbGljaygpO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSBpZiAoICQuaXNQbGFpbk9iamVjdCggY29uZi5rZXkgKSApIHtcblx0XHRcdFx0aWYgKCBjb25mLmtleS5rZXkgIT09IGNoYXJhY3RlciApIHtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIGNvbmYua2V5LnNoaWZ0S2V5ICYmICEgZS5zaGlmdEtleSApIHtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIGNvbmYua2V5LmFsdEtleSAmJiAhIGUuYWx0S2V5ICkge1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICggY29uZi5rZXkuY3RybEtleSAmJiAhIGUuY3RybEtleSApIHtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIGNvbmYua2V5Lm1ldGFLZXkgJiYgISBlLm1ldGFLZXkgKSB7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gTWFkZSBpdCB0aGlzIGZhciAtIGl0IGlzIGdvb2Rcblx0XHRcdFx0ZS5fYnV0dG9uc0hhbmRsZWQgPSB0cnVlO1xuXHRcdFx0XHQkKG5vZGUpLmNsaWNrKCk7XG5cdFx0XHR9XG5cdFx0fTtcblxuXHRcdHZhciByZWN1cnNlID0gZnVuY3Rpb24gKCBhICkge1xuXHRcdFx0Zm9yICggdmFyIGk9MCwgaWVuPWEubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRcdHJ1biggYVtpXS5jb25mLCBhW2ldLm5vZGUgKTtcblxuXHRcdFx0XHRpZiAoIGFbaV0uYnV0dG9ucy5sZW5ndGggKSB7XG5cdFx0XHRcdFx0cmVjdXJzZSggYVtpXS5idXR0b25zICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9O1xuXG5cdFx0cmVjdXJzZSggdGhpcy5zLmJ1dHRvbnMgKTtcblx0fSxcblxuXHQvKipcblx0ICogUmVtb3ZlIGEga2V5IGZyb20gdGhlIGtleSBsaXN0ZW5lciBmb3IgdGhpcyBpbnN0YW5jZSAodG8gYmUgdXNlZCB3aGVuIGFcblx0ICogYnV0dG9uIGlzIHJlbW92ZWQpXG5cdCAqIEBwYXJhbSAge29iamVjdH0gY29uZiBCdXR0b24gY29uZmlndXJhdGlvblxuXHQgKiBAcHJpdmF0ZVxuXHQgKi9cblx0X3JlbW92ZUtleTogZnVuY3Rpb24gKCBjb25mIClcblx0e1xuXHRcdGlmICggY29uZi5rZXkgKSB7XG5cdFx0XHR2YXIgY2hhcmFjdGVyID0gJC5pc1BsYWluT2JqZWN0KCBjb25mLmtleSApID9cblx0XHRcdFx0Y29uZi5rZXkua2V5IDpcblx0XHRcdFx0Y29uZi5rZXk7XG5cblx0XHRcdC8vIFJlbW92ZSBvbmx5IG9uZSBjaGFyYWN0ZXIsIGFzIG11bHRpcGxlIGJ1dHRvbnMgY291bGQgaGF2ZSB0aGVcblx0XHRcdC8vIHNhbWUgbGlzdGVuaW5nIGtleVxuXHRcdFx0dmFyIGEgPSB0aGlzLnMubGlzdGVuS2V5cy5zcGxpdCgnJyk7XG5cdFx0XHR2YXIgaWR4ID0gJC5pbkFycmF5KCBjaGFyYWN0ZXIsIGEgKTtcblx0XHRcdGEuc3BsaWNlKCBpZHgsIDEgKTtcblx0XHRcdHRoaXMucy5saXN0ZW5LZXlzID0gYS5qb2luKCcnKTtcblx0XHR9XG5cdH0sXG5cblx0LyoqXG5cdCAqIFJlc29sdmUgYSBidXR0b24gY29uZmlndXJhdGlvblxuXHQgKiBAcGFyYW0gIHtzdHJpbmd8ZnVuY3Rpb258b2JqZWN0fSBjb25mIEJ1dHRvbiBjb25maWcgdG8gcmVzb2x2ZVxuXHQgKiBAcmV0dXJuIHtvYmplY3R9IEJ1dHRvbiBjb25maWd1cmF0aW9uXG5cdCAqIEBwcml2YXRlXG5cdCAqL1xuXHRfcmVzb2x2ZUV4dGVuZHM6IGZ1bmN0aW9uICggY29uZiApXG5cdHtcblx0XHR2YXIgdGhhdCA9IHRoaXM7XG5cdFx0dmFyIGR0ID0gdGhpcy5zLmR0O1xuXHRcdHZhciBpLCBpZW47XG5cdFx0dmFyIHRvQ29uZk9iamVjdCA9IGZ1bmN0aW9uICggYmFzZSApIHtcblx0XHRcdHZhciBsb29wID0gMDtcblxuXHRcdFx0Ly8gTG9vcCB1bnRpbCB3ZSBoYXZlIHJlc29sdmVkIHRvIGEgYnV0dG9uIGNvbmZpZ3VyYXRpb24sIG9yIGFuXG5cdFx0XHQvLyBhcnJheSBvZiBidXR0b24gY29uZmlndXJhdGlvbnMgKHdoaWNoIHdpbGwgYmUgaXRlcmF0ZWRcblx0XHRcdC8vIHNlcGFyYXRlbHkpXG5cdFx0XHR3aGlsZSAoICEgJC5pc1BsYWluT2JqZWN0KGJhc2UpICYmICEgQXJyYXkuaXNBcnJheShiYXNlKSApIHtcblx0XHRcdFx0aWYgKCBiYXNlID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKCB0eXBlb2YgYmFzZSA9PT0gJ2Z1bmN0aW9uJyApIHtcblx0XHRcdFx0XHRiYXNlID0gYmFzZS5jYWxsKCB0aGF0LCBkdCwgY29uZiApO1xuXG5cdFx0XHRcdFx0aWYgKCAhIGJhc2UgKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2UgaWYgKCB0eXBlb2YgYmFzZSA9PT0gJ3N0cmluZycgKSB7XG5cdFx0XHRcdFx0aWYgKCAhIF9kdEJ1dHRvbnNbIGJhc2UgXSApIHtcblx0XHRcdFx0XHRcdHJldHVybiB7aHRtbDogYmFzZX1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRiYXNlID0gX2R0QnV0dG9uc1sgYmFzZSBdO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0bG9vcCsrO1xuXHRcdFx0XHRpZiAoIGxvb3AgPiAzMCApIHtcblx0XHRcdFx0XHQvLyBQcm90ZWN0IGFnYWluc3QgbWlzY29uZmlndXJhdGlvbiBraWxsaW5nIHRoZSBicm93c2VyXG5cdFx0XHRcdFx0dGhyb3cgJ0J1dHRvbnM6IFRvbyBtYW55IGl0ZXJhdGlvbnMnO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBBcnJheS5pc0FycmF5KCBiYXNlICkgP1xuXHRcdFx0XHRiYXNlIDpcblx0XHRcdFx0JC5leHRlbmQoIHt9LCBiYXNlICk7XG5cdFx0fTtcblxuXHRcdGNvbmYgPSB0b0NvbmZPYmplY3QoIGNvbmYgKTtcblxuXHRcdHdoaWxlICggY29uZiAmJiBjb25mLmV4dGVuZCApIHtcblx0XHRcdC8vIFVzZSBgdG9Db25mT2JqZWN0YCBpbiBjYXNlIHRoZSBidXR0b24gZGVmaW5pdGlvbiBiZWluZyBleHRlbmRlZFxuXHRcdFx0Ly8gaXMgaXRzZWxmIGEgc3RyaW5nIG9yIGEgZnVuY3Rpb25cblx0XHRcdGlmICggISBfZHRCdXR0b25zWyBjb25mLmV4dGVuZCBdICkge1xuXHRcdFx0XHR0aHJvdyAnQ2Fubm90IGV4dGVuZCB1bmtub3duIGJ1dHRvbiB0eXBlOiAnK2NvbmYuZXh0ZW5kO1xuXHRcdFx0fVxuXG5cdFx0XHR2YXIgb2JqQXJyYXkgPSB0b0NvbmZPYmplY3QoIF9kdEJ1dHRvbnNbIGNvbmYuZXh0ZW5kIF0gKTtcblx0XHRcdGlmICggQXJyYXkuaXNBcnJheSggb2JqQXJyYXkgKSApIHtcblx0XHRcdFx0cmV0dXJuIG9iakFycmF5O1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSBpZiAoICEgb2JqQXJyYXkgKSB7XG5cdFx0XHRcdC8vIFRoaXMgaXMgYSBsaXR0bGUgYnJ1dGFsIGFzIGl0IG1pZ2h0IGJlIHBvc3NpYmxlIHRvIGhhdmUgYVxuXHRcdFx0XHQvLyB2YWxpZCBidXR0b24gd2l0aG91dCB0aGUgZXh0ZW5kLCBidXQgaWYgdGhlcmUgaXMgbm8gZXh0ZW5kXG5cdFx0XHRcdC8vIHRoZW4gdGhlIGhvc3QgYnV0dG9uIHdvdWxkIGJlIGFjdGluZyBpbiBhbiB1bmRlZmluZWQgc3RhdGVcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBTdGFzaCB0aGUgY3VycmVudCBjbGFzcyBuYW1lXG5cdFx0XHR2YXIgb3JpZ2luYWxDbGFzc05hbWUgPSBvYmpBcnJheS5jbGFzc05hbWU7XG5cblx0XHRcdGlmIChjb25mLmNvbmZpZyAhPT0gdW5kZWZpbmVkICYmIG9iakFycmF5LmNvbmZpZyAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdGNvbmYuY29uZmlnID0gJC5leHRlbmQoe30sIG9iakFycmF5LmNvbmZpZywgY29uZi5jb25maWcpXG5cdFx0XHR9XG5cblx0XHRcdGNvbmYgPSAkLmV4dGVuZCgge30sIG9iakFycmF5LCBjb25mICk7XG5cblx0XHRcdC8vIFRoZSBleHRlbmQgd2lsbCBoYXZlIG92ZXJ3cml0dGVuIHRoZSBvcmlnaW5hbCBjbGFzcyBuYW1lIGlmIHRoZVxuXHRcdFx0Ly8gYGNvbmZgIG9iamVjdCBhbHNvIGFzc2lnbmVkIGEgY2xhc3MsIGJ1dCB3ZSB3YW50IHRvIGNvbmNhdGVuYXRlXG5cdFx0XHQvLyB0aGVtIHNvIHRoZXkgYXJlIGxpc3QgdGhhdCBpcyBjb21iaW5lZCBmcm9tIGFsbCBleHRlbmRlZCBidXR0b25zXG5cdFx0XHRpZiAoIG9yaWdpbmFsQ2xhc3NOYW1lICYmIGNvbmYuY2xhc3NOYW1lICE9PSBvcmlnaW5hbENsYXNzTmFtZSApIHtcblx0XHRcdFx0Y29uZi5jbGFzc05hbWUgPSBvcmlnaW5hbENsYXNzTmFtZSsnICcrY29uZi5jbGFzc05hbWU7XG5cdFx0XHR9XG5cblx0XHRcdC8vIEJ1dHRvbnMgdG8gYmUgYWRkZWQgdG8gYSBjb2xsZWN0aW9uICAtZ2l2ZXMgdGhlIGFiaWxpdHkgdG8gZGVmaW5lXG5cdFx0XHQvLyBpZiBidXR0b25zIHNob3VsZCBiZSBhZGRlZCB0byB0aGUgc3RhcnQgb3IgZW5kIG9mIGEgY29sbGVjdGlvblxuXHRcdFx0dmFyIHBvc3RmaXhCdXR0b25zID0gY29uZi5wb3N0Zml4QnV0dG9ucztcblx0XHRcdGlmICggcG9zdGZpeEJ1dHRvbnMgKSB7XG5cdFx0XHRcdGlmICggISBjb25mLmJ1dHRvbnMgKSB7XG5cdFx0XHRcdFx0Y29uZi5idXR0b25zID0gW107XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRmb3IgKCBpPTAsIGllbj1wb3N0Zml4QnV0dG9ucy5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdFx0XHRjb25mLmJ1dHRvbnMucHVzaCggcG9zdGZpeEJ1dHRvbnNbaV0gKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGNvbmYucG9zdGZpeEJ1dHRvbnMgPSBudWxsO1xuXHRcdFx0fVxuXG5cdFx0XHR2YXIgcHJlZml4QnV0dG9ucyA9IGNvbmYucHJlZml4QnV0dG9ucztcblx0XHRcdGlmICggcHJlZml4QnV0dG9ucyApIHtcblx0XHRcdFx0aWYgKCAhIGNvbmYuYnV0dG9ucyApIHtcblx0XHRcdFx0XHRjb25mLmJ1dHRvbnMgPSBbXTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGZvciAoIGk9MCwgaWVuPXByZWZpeEJ1dHRvbnMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRcdFx0Y29uZi5idXR0b25zLnNwbGljZSggaSwgMCwgcHJlZml4QnV0dG9uc1tpXSApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Y29uZi5wcmVmaXhCdXR0b25zID0gbnVsbDtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQWx0aG91Z2ggd2Ugd2FudCB0aGUgYGNvbmZgIG9iamVjdCB0byBvdmVyd3JpdGUgYWxtb3N0IGFsbCBvZlxuXHRcdFx0Ly8gdGhlIHByb3BlcnRpZXMgb2YgdGhlIG9iamVjdCBiZWluZyBleHRlbmRlZCwgdGhlIGBleHRlbmRgXG5cdFx0XHQvLyBwcm9wZXJ0eSBzaG91bGQgY29tZSBmcm9tIHRoZSBvYmplY3QgYmVpbmcgZXh0ZW5kZWRcblx0XHRcdGNvbmYuZXh0ZW5kID0gb2JqQXJyYXkuZXh0ZW5kO1xuXHRcdH1cblxuXHRcdHJldHVybiBjb25mO1xuXHR9LFxuXG5cdC8qKlxuXHQgKiBEaXNwbGF5IChhbmQgcmVwbGFjZSBpZiB0aGVyZSBpcyBhbiBleGlzdGluZyBvbmUpIGEgcG9wb3ZlciBhdHRhY2hlZCB0byBhIGJ1dHRvblxuXHQgKiBAcGFyYW0ge3N0cmluZ3xub2RlfSBjb250ZW50IENvbnRlbnQgdG8gc2hvd1xuXHQgKiBAcGFyYW0ge0RhdGFUYWJsZS5BcGl9IGhvc3RCdXR0b24gRFQgQVBJIGluc3RhbmNlIG9mIHRoZSBidXR0b25cblx0ICogQHBhcmFtIHtvYmplY3R9IGluT3B0cyBPcHRpb25zIChzZWUgb2JqZWN0IGJlbG93IGZvciBhbGwgb3B0aW9ucylcblx0ICovXG5cdF9wb3BvdmVyOiBmdW5jdGlvbiAoIGNvbnRlbnQsIGhvc3RCdXR0b24sIGluT3B0cywgZSApIHtcblx0XHR2YXIgZHQgPSBob3N0QnV0dG9uO1xuXHRcdHZhciBidXR0b25zU2V0dGluZ3MgPSB0aGlzLmM7XG5cdFx0dmFyIGNsb3NlZCA9IGZhbHNlO1xuXHRcdHZhciBvcHRpb25zID0gJC5leHRlbmQoIHtcblx0XHRcdGFsaWduOiAnYnV0dG9uLWxlZnQnLCAvLyBidXR0b24tcmlnaHQsIGR0LWNvbnRhaW5lciwgc3BsaXQtbGVmdCwgc3BsaXQtcmlnaHRcblx0XHRcdGF1dG9DbG9zZTogZmFsc2UsXG5cdFx0XHRiYWNrZ3JvdW5kOiB0cnVlLFxuXHRcdFx0YmFja2dyb3VuZENsYXNzTmFtZTogJ2R0LWJ1dHRvbi1iYWNrZ3JvdW5kJyxcblx0XHRcdGNsb3NlQnV0dG9uOiB0cnVlLFxuXHRcdFx0Y29udGVudENsYXNzTmFtZTogYnV0dG9uc1NldHRpbmdzLmRvbS5jb2xsZWN0aW9uLmNsYXNzTmFtZSxcblx0XHRcdGNvbGxlY3Rpb25MYXlvdXQ6ICcnLFxuXHRcdFx0Y29sbGVjdGlvblRpdGxlOiAnJyxcblx0XHRcdGRyb3B1cDogZmFsc2UsXG5cdFx0XHRmYWRlOiA0MDAsXG5cdFx0XHRwb3BvdmVyVGl0bGU6ICcnLFxuXHRcdFx0cmlnaHRBbGlnbkNsYXNzTmFtZTogJ2R0LWJ1dHRvbi1yaWdodCcsXG5cdFx0XHR0YWc6IGJ1dHRvbnNTZXR0aW5ncy5kb20uY29sbGVjdGlvbi50YWdcblx0XHR9LCBpbk9wdHMgKTtcblxuXHRcdHZhciBob3N0Tm9kZSA9IGhvc3RCdXR0b24ubm9kZSgpO1xuXG5cdFx0dmFyIGNsb3NlID0gZnVuY3Rpb24gKCkge1xuXHRcdFx0Y2xvc2VkID0gdHJ1ZTtcblxuXHRcdFx0X2ZhZGVPdXQoXG5cdFx0XHRcdCQoJy5kdC1idXR0b24tY29sbGVjdGlvbicpLFxuXHRcdFx0XHRvcHRpb25zLmZhZGUsXG5cdFx0XHRcdGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHQkKHRoaXMpLmRldGFjaCgpO1xuXHRcdFx0XHR9XG5cdFx0XHQpO1xuXG5cdFx0XHQkKGR0LmJ1dHRvbnMoICdbYXJpYS1oYXNwb3B1cD1cImRpYWxvZ1wiXVthcmlhLWV4cGFuZGVkPVwidHJ1ZVwiXScgKS5ub2RlcygpKVxuXHRcdFx0XHQuYXR0cignYXJpYS1leHBhbmRlZCcsICdmYWxzZScpO1xuXG5cdFx0XHQkKCdkaXYuZHQtYnV0dG9uLWJhY2tncm91bmQnKS5vZmYoICdjbGljay5kdGItY29sbGVjdGlvbicgKTtcblx0XHRcdEJ1dHRvbnMuYmFja2dyb3VuZCggZmFsc2UsIG9wdGlvbnMuYmFja2dyb3VuZENsYXNzTmFtZSwgb3B0aW9ucy5mYWRlLCBob3N0Tm9kZSApO1xuXG5cdFx0XHQkKHdpbmRvdykub2ZmKCdyZXNpemUucmVzaXplLmR0Yi1jb2xsZWN0aW9uJyk7XG5cdFx0XHQkKCdib2R5Jykub2ZmKCAnLmR0Yi1jb2xsZWN0aW9uJyApO1xuXHRcdFx0ZHQub2ZmKCAnYnV0dG9ucy1hY3Rpb24uYi1pbnRlcm5hbCcgKTtcblx0XHRcdGR0Lm9mZiggJ2Rlc3Ryb3knICk7XG5cdFx0fTtcblxuXHRcdGlmIChjb250ZW50ID09PSBmYWxzZSkge1xuXHRcdFx0Y2xvc2UoKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR2YXIgZXhpc3RpbmdFeHBhbmRlZCA9ICQoZHQuYnV0dG9ucyggJ1thcmlhLWhhc3BvcHVwPVwiZGlhbG9nXCJdW2FyaWEtZXhwYW5kZWQ9XCJ0cnVlXCJdJyApLm5vZGVzKCkpO1xuXHRcdGlmICggZXhpc3RpbmdFeHBhbmRlZC5sZW5ndGggKSB7XG5cdFx0XHQvLyBSZXVzZSB0aGUgY3VycmVudCBwb3NpdGlvbiBpZiB0aGUgYnV0dG9uIHRoYXQgd2FzIHRyaWdnZXJlZCBpcyBpbnNpZGUgYW4gZXhpc3RpbmcgY29sbGVjdGlvblxuXHRcdFx0aWYgKGhvc3ROb2RlLmNsb3Nlc3QoJ2Rpdi5kdC1idXR0b24tY29sbGVjdGlvbicpLmxlbmd0aCkge1xuXHRcdFx0XHRob3N0Tm9kZSA9IGV4aXN0aW5nRXhwYW5kZWQuZXEoMCk7XG5cdFx0XHR9XG5cblx0XHRcdGNsb3NlKCk7XG5cdFx0fVxuXG5cdFx0Ly8gVHJ5IHRvIGJlIHNtYXJ0IGFib3V0IHRoZSBsYXlvdXRcblx0XHR2YXIgY250ID0gJCgnLmR0LWJ1dHRvbicsIGNvbnRlbnQpLmxlbmd0aDtcblx0XHR2YXIgbW9kID0gJyc7XG5cblx0XHRpZiAoY250ID09PSAzKSB7XG5cdFx0XHRtb2QgPSAnZHRiLWIzJztcblx0XHR9XG5cdFx0ZWxzZSBpZiAoY250ID09PSAyKSB7XG5cdFx0XHRtb2QgPSAnZHRiLWIyJztcblx0XHR9XG5cdFx0ZWxzZSBpZiAoY250ID09PSAxKSB7XG5cdFx0XHRtb2QgPSAnZHRiLWIxJztcblx0XHR9XG5cblx0XHR2YXIgZGlzcGxheSA9ICQoJzxkaXYvPicpXG5cdFx0XHQuYWRkQ2xhc3MoJ2R0LWJ1dHRvbi1jb2xsZWN0aW9uJylcblx0XHRcdC5hZGRDbGFzcyhvcHRpb25zLmNvbGxlY3Rpb25MYXlvdXQpXG5cdFx0XHQuYWRkQ2xhc3Mob3B0aW9ucy5zcGxpdEFsaWduQ2xhc3MpXG5cdFx0XHQuYWRkQ2xhc3MobW9kKVxuXHRcdFx0LmNzcygnZGlzcGxheScsICdub25lJylcblx0XHRcdC5hdHRyKHtcblx0XHRcdFx0J2FyaWEtbW9kYWwnOiB0cnVlLFxuXHRcdFx0XHRyb2xlOiAnZGlhbG9nJ1xuXHRcdFx0fSk7XG5cblx0XHRjb250ZW50ID0gJChjb250ZW50KVxuXHRcdFx0LmFkZENsYXNzKG9wdGlvbnMuY29udGVudENsYXNzTmFtZSlcblx0XHRcdC5hdHRyKCdyb2xlJywgJ21lbnUnKVxuXHRcdFx0LmFwcGVuZFRvKGRpc3BsYXkpO1xuXG5cdFx0aG9zdE5vZGUuYXR0ciggJ2FyaWEtZXhwYW5kZWQnLCAndHJ1ZScgKTtcblxuXHRcdGlmICggaG9zdE5vZGUucGFyZW50cygnYm9keScpWzBdICE9PSBkb2N1bWVudC5ib2R5ICkge1xuXHRcdFx0aG9zdE5vZGUgPSBkb2N1bWVudC5ib2R5Lmxhc3RDaGlsZDtcblx0XHR9XG5cblx0XHRpZiAoIG9wdGlvbnMucG9wb3ZlclRpdGxlICkge1xuXHRcdFx0ZGlzcGxheS5wcmVwZW5kKCc8ZGl2IGNsYXNzPVwiZHQtYnV0dG9uLWNvbGxlY3Rpb24tdGl0bGVcIj4nK29wdGlvbnMucG9wb3ZlclRpdGxlKyc8L2Rpdj4nKTtcblx0XHR9XG5cdFx0ZWxzZSBpZiAoIG9wdGlvbnMuY29sbGVjdGlvblRpdGxlICkge1xuXHRcdFx0ZGlzcGxheS5wcmVwZW5kKCc8ZGl2IGNsYXNzPVwiZHQtYnV0dG9uLWNvbGxlY3Rpb24tdGl0bGVcIj4nK29wdGlvbnMuY29sbGVjdGlvblRpdGxlKyc8L2Rpdj4nKTtcblx0XHR9XG5cblx0XHRpZiAob3B0aW9ucy5jbG9zZUJ1dHRvbikge1xuXHRcdFx0ZGlzcGxheS5wcmVwZW5kKCc8ZGl2IGNsYXNzPVwiZHRiLXBvcG92ZXItY2xvc2VcIj54PC9kaXY+JykuYWRkQ2xhc3MoJ2R0Yi1jb2xsZWN0aW9uLWNsb3NlYWJsZScpXG5cdFx0fVxuXG5cdFx0X2ZhZGVJbiggZGlzcGxheS5pbnNlcnRBZnRlciggaG9zdE5vZGUgKSwgb3B0aW9ucy5mYWRlICk7XG5cblx0XHR2YXIgdGFibGVDb250YWluZXIgPSAkKCBob3N0QnV0dG9uLnRhYmxlKCkuY29udGFpbmVyKCkgKTtcblx0XHR2YXIgcG9zaXRpb24gPSBkaXNwbGF5LmNzcyggJ3Bvc2l0aW9uJyApO1xuXG5cdFx0aWYgKCBvcHRpb25zLnNwYW4gPT09ICdjb250YWluZXInIHx8IG9wdGlvbnMuYWxpZ24gPT09ICdkdC1jb250YWluZXInICkge1xuXHRcdFx0aG9zdE5vZGUgPSBob3N0Tm9kZS5wYXJlbnQoKTtcblx0XHRcdGRpc3BsYXkuY3NzKCd3aWR0aCcsIHRhYmxlQ29udGFpbmVyLndpZHRoKCkpO1xuXHRcdH1cblxuXHRcdC8vIEFsaWduIHRoZSBwb3BvdmVyIHJlbGF0aXZlIHRvIHRoZSBEYXRhVGFibGVzIGNvbnRhaW5lclxuXHRcdC8vIFVzZWZ1bCBmb3Igd2lkZSBwb3BvdmVycyBzdWNoIGFzIFNlYXJjaFBhbmVzXG5cdFx0aWYgKHBvc2l0aW9uID09PSAnYWJzb2x1dGUnKSB7XG5cdFx0XHQvLyBBbGlnbiByZWxhdGl2ZSB0byB0aGUgaG9zdCBidXR0b25cblx0XHRcdHZhciBvZmZzZXRQYXJlbnQgPSAkKGhvc3ROb2RlWzBdLm9mZnNldFBhcmVudCk7XG5cdFx0XHR2YXIgYnV0dG9uUG9zaXRpb24gPSBob3N0Tm9kZS5wb3NpdGlvbigpO1xuXHRcdFx0dmFyIGJ1dHRvbk9mZnNldCA9IGhvc3ROb2RlLm9mZnNldCgpO1xuXHRcdFx0dmFyIHRhYmxlU2l6ZXMgPSBvZmZzZXRQYXJlbnQub2Zmc2V0KCk7XG5cdFx0XHR2YXIgY29udGFpbmVyUG9zaXRpb24gPSBvZmZzZXRQYXJlbnQucG9zaXRpb24oKTtcblx0XHRcdHZhciBjb21wdXRlZCA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKG9mZnNldFBhcmVudFswXSk7XG5cblx0XHRcdHRhYmxlU2l6ZXMuaGVpZ2h0ID0gb2Zmc2V0UGFyZW50Lm91dGVySGVpZ2h0KCk7XG5cdFx0XHR0YWJsZVNpemVzLndpZHRoID0gb2Zmc2V0UGFyZW50LndpZHRoKCkgKyBwYXJzZUZsb2F0KGNvbXB1dGVkLnBhZGRpbmdMZWZ0KTtcblx0XHRcdHRhYmxlU2l6ZXMucmlnaHQgPSB0YWJsZVNpemVzLmxlZnQgKyB0YWJsZVNpemVzLndpZHRoO1xuXHRcdFx0dGFibGVTaXplcy5ib3R0b20gPSB0YWJsZVNpemVzLnRvcCArIHRhYmxlU2l6ZXMuaGVpZ2h0O1xuXG5cdFx0XHQvLyBTZXQgdGhlIGluaXRpYWwgcG9zaXRpb24gc28gd2UgY2FuIHJlYWQgaGVpZ2h0IC8gd2lkdGhcblx0XHRcdHZhciB0b3AgPSBidXR0b25Qb3NpdGlvbi50b3AgKyBob3N0Tm9kZS5vdXRlckhlaWdodCgpO1xuXHRcdFx0dmFyIGxlZnQgPSBidXR0b25Qb3NpdGlvbi5sZWZ0O1xuXG5cdFx0XHRkaXNwbGF5LmNzcygge1xuXHRcdFx0XHR0b3A6IHRvcCxcblx0XHRcdFx0bGVmdDogbGVmdFxuXHRcdFx0fSApO1xuXG5cdFx0XHQvLyBHZXQgdGhlIHBvcG92ZXIgcG9zaXRpb25cblx0XHRcdGNvbXB1dGVkID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZGlzcGxheVswXSk7XG5cdFx0XHR2YXIgcG9wb3ZlclNpemVzID0gZGlzcGxheS5vZmZzZXQoKTtcblxuXHRcdFx0cG9wb3ZlclNpemVzLmhlaWdodCA9IGRpc3BsYXkub3V0ZXJIZWlnaHQoKTtcblx0XHRcdHBvcG92ZXJTaXplcy53aWR0aCA9IGRpc3BsYXkub3V0ZXJXaWR0aCgpO1xuXHRcdFx0cG9wb3ZlclNpemVzLnJpZ2h0ID0gcG9wb3ZlclNpemVzLmxlZnQgKyBwb3BvdmVyU2l6ZXMud2lkdGg7XG5cdFx0XHRwb3BvdmVyU2l6ZXMuYm90dG9tID0gcG9wb3ZlclNpemVzLnRvcCArIHBvcG92ZXJTaXplcy5oZWlnaHQ7XG5cdFx0XHRwb3BvdmVyU2l6ZXMubWFyZ2luVG9wID0gcGFyc2VGbG9hdChjb21wdXRlZC5tYXJnaW5Ub3ApO1xuXHRcdFx0cG9wb3ZlclNpemVzLm1hcmdpbkJvdHRvbSA9IHBhcnNlRmxvYXQoY29tcHV0ZWQubWFyZ2luQm90dG9tKTtcblxuXHRcdFx0Ly8gRmlyc3QgcG9zaXRpb24gcGVyIHRoZSBjbGFzcyByZXF1aXJlbWVudHMgLSBwb3AgdXAgYW5kIHJpZ2h0IGFsaWduXG5cdFx0XHRpZiAob3B0aW9ucy5kcm9wdXApIHtcblx0XHRcdFx0dG9wID0gYnV0dG9uUG9zaXRpb24udG9wIC0gcG9wb3ZlclNpemVzLmhlaWdodCAtIHBvcG92ZXJTaXplcy5tYXJnaW5Ub3AgLSBwb3BvdmVyU2l6ZXMubWFyZ2luQm90dG9tO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAob3B0aW9ucy5hbGlnbiA9PT0gJ2J1dHRvbi1yaWdodCcgfHwgZGlzcGxheS5oYXNDbGFzcyggb3B0aW9ucy5yaWdodEFsaWduQ2xhc3NOYW1lICkpIHtcblx0XHRcdFx0bGVmdCA9IGJ1dHRvblBvc2l0aW9uLmxlZnQgLSBwb3BvdmVyU2l6ZXMud2lkdGggKyBob3N0Tm9kZS5vdXRlcldpZHRoKCk7IFxuXHRcdFx0fVxuXG5cdFx0XHQvLyBDb250YWluZXIgYWxpZ25tZW50IC0gbWFrZSBzdXJlIGl0IGRvZXNuJ3Qgb3ZlcmZsb3cgdGhlIHRhYmxlIGNvbnRhaW5lclxuXHRcdFx0aWYgKG9wdGlvbnMuYWxpZ24gPT09ICdkdC1jb250YWluZXInIHx8IG9wdGlvbnMuYWxpZ24gPT09ICdjb250YWluZXInKSB7XG5cdFx0XHRcdGlmIChsZWZ0IDwgYnV0dG9uUG9zaXRpb24ubGVmdCkge1xuXHRcdFx0XHRcdGxlZnQgPSAtYnV0dG9uUG9zaXRpb24ubGVmdDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmIChsZWZ0ICsgcG9wb3ZlclNpemVzLndpZHRoID4gdGFibGVTaXplcy53aWR0aCkge1xuXHRcdFx0XHRcdGxlZnQgPSB0YWJsZVNpemVzLndpZHRoIC0gcG9wb3ZlclNpemVzLndpZHRoO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdC8vIFdpbmRvdyBhZGp1c3RtZW50XG5cdFx0XHRpZiAoY29udGFpbmVyUG9zaXRpb24ubGVmdCArIGxlZnQgKyBwb3BvdmVyU2l6ZXMud2lkdGggPiAkKHdpbmRvdykud2lkdGgoKSkge1xuXHRcdFx0XHQvLyBPdmVyZmxvd2luZyB0aGUgZG9jdW1lbnQgdG8gdGhlIHJpZ2h0XG5cdFx0XHRcdGxlZnQgPSAkKHdpbmRvdykud2lkdGgoKSAtIHBvcG92ZXJTaXplcy53aWR0aCAtIGNvbnRhaW5lclBvc2l0aW9uLmxlZnQ7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChidXR0b25PZmZzZXQubGVmdCArIGxlZnQgPCAwKSB7XG5cdFx0XHRcdC8vIE9mZiB0byB0aGUgbGVmdCBvZiB0aGUgZG9jdW1lbnRcblx0XHRcdFx0bGVmdCA9IC1idXR0b25PZmZzZXQubGVmdDtcblx0XHRcdH1cblxuXHRcdFx0aWYgKGNvbnRhaW5lclBvc2l0aW9uLnRvcCArIHRvcCArIHBvcG92ZXJTaXplcy5oZWlnaHQgPiAkKHdpbmRvdykuaGVpZ2h0KCkgKyAkKHdpbmRvdykuc2Nyb2xsVG9wKCkpIHtcblx0XHRcdFx0Ly8gUG9wIHVwIGlmIG90aGVyd2lzZSB3ZSdkIG5lZWQgdGhlIHVzZXIgdG8gc2Nyb2xsIGRvd25cblx0XHRcdFx0dG9wID0gYnV0dG9uUG9zaXRpb24udG9wIC0gcG9wb3ZlclNpemVzLmhlaWdodCAtIHBvcG92ZXJTaXplcy5tYXJnaW5Ub3AgLSBwb3BvdmVyU2l6ZXMubWFyZ2luQm90dG9tO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoY29udGFpbmVyUG9zaXRpb24udG9wICsgdG9wIDwgJCh3aW5kb3cpLnNjcm9sbFRvcCgpKSB7XG5cdFx0XHRcdC8vIENvcnJlY3Rpb24gZm9yIHdoZW4gdGhlIHRvcCBpcyBiZXlvbmQgdGhlIHRvcCBvZiB0aGUgcGFnZVxuXHRcdFx0XHR0b3AgPSBidXR0b25Qb3NpdGlvbi50b3AgKyBob3N0Tm9kZS5vdXRlckhlaWdodCgpO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBDYWxjdWxhdGlvbnMgYWxsIGRvbmUgLSBub3cgc2V0IGl0XG5cdFx0XHRkaXNwbGF5LmNzcygge1xuXHRcdFx0XHR0b3A6IHRvcCxcblx0XHRcdFx0bGVmdDogbGVmdFxuXHRcdFx0fSApO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdC8vIEZpeCBwb3NpdGlvbiAtIGNlbnRyZSBvbiBzY3JlZW5cblx0XHRcdHZhciBwb3NpdGlvbiA9IGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0dmFyIGhhbGYgPSAkKHdpbmRvdykuaGVpZ2h0KCkgLyAyO1xuXG5cdFx0XHRcdHZhciB0b3AgPSBkaXNwbGF5LmhlaWdodCgpIC8gMjtcblx0XHRcdFx0aWYgKCB0b3AgPiBoYWxmICkge1xuXHRcdFx0XHRcdHRvcCA9IGhhbGY7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRkaXNwbGF5LmNzcyggJ21hcmdpblRvcCcsIHRvcCotMSApO1xuXHRcdFx0fTtcblxuXHRcdFx0cG9zaXRpb24oKTtcblxuXHRcdFx0JCh3aW5kb3cpLm9uKCdyZXNpemUuZHRiLWNvbGxlY3Rpb24nLCBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdHBvc2l0aW9uKCk7XG5cdFx0XHR9KTtcblx0XHR9XG5cblx0XHRpZiAoIG9wdGlvbnMuYmFja2dyb3VuZCApIHtcblx0XHRcdEJ1dHRvbnMuYmFja2dyb3VuZChcblx0XHRcdFx0dHJ1ZSxcblx0XHRcdFx0b3B0aW9ucy5iYWNrZ3JvdW5kQ2xhc3NOYW1lLFxuXHRcdFx0XHRvcHRpb25zLmZhZGUsXG5cdFx0XHRcdG9wdGlvbnMuYmFja2dyb3VuZEhvc3QgfHwgaG9zdE5vZGVcblx0XHRcdCk7XG5cdFx0fVxuXG5cdFx0Ly8gVGhpcyBpcyBib25rZXJzLCBidXQgaWYgd2UgZG9uJ3QgaGF2ZSBhIGNsaWNrIGxpc3RlbmVyIG9uIHRoZVxuXHRcdC8vIGJhY2tncm91bmQgZWxlbWVudCwgaU9TIFNhZmFyaSB3aWxsIGlnbm9yZSB0aGUgYm9keSBjbGlja1xuXHRcdC8vIGxpc3RlbmVyIGJlbG93LiBBbiBlbXB0eSBmdW5jdGlvbiBoZXJlIGlzIGFsbCB0aGF0IGlzXG5cdFx0Ly8gcmVxdWlyZWQgdG8gbWFrZSBpdCB3b3JrLi4uXG5cdFx0JCgnZGl2LmR0LWJ1dHRvbi1iYWNrZ3JvdW5kJykub24oICdjbGljay5kdGItY29sbGVjdGlvbicsIGZ1bmN0aW9uICgpIHt9ICk7XG5cblx0XHRpZiAoIG9wdGlvbnMuYXV0b0Nsb3NlICkge1xuXHRcdFx0c2V0VGltZW91dCggZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRkdC5vbiggJ2J1dHRvbnMtYWN0aW9uLmItaW50ZXJuYWwnLCBmdW5jdGlvbiAoZSwgYnRuLCBkdCwgbm9kZSkge1xuXHRcdFx0XHRcdGlmICggbm9kZVswXSA9PT0gaG9zdE5vZGVbMF0gKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGNsb3NlKCk7XG5cdFx0XHRcdH0gKTtcblx0XHRcdH0sIDApO1xuXHRcdH1cblx0XHRcblx0XHQkKGRpc3BsYXkpLnRyaWdnZXIoJ2J1dHRvbnMtcG9wb3Zlci5kdCcpO1xuXG5cblx0XHRkdC5vbignZGVzdHJveScsIGNsb3NlKTtcblxuXHRcdHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG5cdFx0XHRjbG9zZWQgPSBmYWxzZTtcblx0XHRcdCQoJ2JvZHknKVxuXHRcdFx0XHQub24oICdjbGljay5kdGItY29sbGVjdGlvbicsIGZ1bmN0aW9uIChlKSB7XG5cdFx0XHRcdFx0aWYgKGNsb3NlZCkge1xuXHRcdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8vIGFuZFNlbGYgaXMgZGVwcmVjYXRlZCBpbiBqUTEuOCwgYnV0IHdlIHdhbnQgMS43IGNvbXBhdFxuXHRcdFx0XHRcdHZhciBiYWNrID0gJC5mbi5hZGRCYWNrID8gJ2FkZEJhY2snIDogJ2FuZFNlbGYnO1xuXHRcdFx0XHRcdHZhciBwYXJlbnQgPSAkKGUudGFyZ2V0KS5wYXJlbnQoKVswXTtcblx0XG5cdFx0XHRcdFx0aWYgKCggISAkKGUudGFyZ2V0KS5wYXJlbnRzKClbYmFja10oKS5maWx0ZXIoIGNvbnRlbnQgKS5sZW5ndGggICYmICEkKHBhcmVudCkuaGFzQ2xhc3MoJ2R0LWJ1dHRvbnMnKSkgfHwgJChlLnRhcmdldCkuaGFzQ2xhc3MoJ2R0LWJ1dHRvbi1iYWNrZ3JvdW5kJykpIHtcblx0XHRcdFx0XHRcdGNsb3NlKCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IClcblx0XHRcdFx0Lm9uKCAna2V5dXAuZHRiLWNvbGxlY3Rpb24nLCBmdW5jdGlvbiAoZSkge1xuXHRcdFx0XHRcdGlmICggZS5rZXlDb2RlID09PSAyNyApIHtcblx0XHRcdFx0XHRcdGNsb3NlKCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IClcblx0XHRcdFx0Lm9uKCAna2V5ZG93bi5kdGItY29sbGVjdGlvbicsIGZ1bmN0aW9uIChlKSB7XG5cdFx0XHRcdFx0Ly8gRm9jdXMgdHJhcCBmb3IgdGFiIGtleVxuXHRcdFx0XHRcdHZhciBlbGVtZW50cyA9ICQoJ2EsIGJ1dHRvbicsIGNvbnRlbnQpO1xuXHRcdFx0XHRcdHZhciBhY3RpdmUgPSBkb2N1bWVudC5hY3RpdmVFbGVtZW50O1xuXG5cdFx0XHRcdFx0aWYgKGUua2V5Q29kZSAhPT0gOSkgeyAvLyB0YWJcblx0XHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoZWxlbWVudHMuaW5kZXgoYWN0aXZlKSA9PT0gLTEpIHtcblx0XHRcdFx0XHRcdC8vIElmIGN1cnJlbnQgZm9jdXMgaXMgbm90IGluc2lkZSB0aGUgcG9wb3ZlclxuXHRcdFx0XHRcdFx0ZWxlbWVudHMuZmlyc3QoKS5mb2N1cygpO1xuXHRcdFx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRlbHNlIGlmIChlLnNoaWZ0S2V5KSB7XG5cdFx0XHRcdFx0XHQvLyBSZXZlcnNlIHRhYmJpbmcgb3JkZXIgd2hlbiBzaGlmdCBrZXkgaXMgcHJlc3NlZFxuXHRcdFx0XHRcdFx0aWYgKGFjdGl2ZSA9PT0gZWxlbWVudHNbMF0pIHtcblx0XHRcdFx0XHRcdFx0ZWxlbWVudHMubGFzdCgpLmZvY3VzKCk7XG5cdFx0XHRcdFx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0XHRpZiAoYWN0aXZlID09PSBlbGVtZW50cy5sYXN0KClbMF0pIHtcblx0XHRcdFx0XHRcdFx0ZWxlbWVudHMuZmlyc3QoKS5mb2N1cygpO1xuXHRcdFx0XHRcdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9ICk7XG5cdFx0fSwgMCk7XG5cdH1cbn0gKTtcblxuXG5cbi8qICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICpcbiAqIFN0YXRpY3NcbiAqL1xuXG4vKipcbiAqIFNob3cgLyBoaWRlIGEgYmFja2dyb3VuZCBsYXllciBiZWhpbmQgYSBjb2xsZWN0aW9uXG4gKiBAcGFyYW0gIHtib29sZWFufSBGbGFnIHRvIGluZGljYXRlIGlmIHRoZSBiYWNrZ3JvdW5kIHNob3VsZCBiZSBzaG93biBvclxuICogICBoaWRkZW4gXG4gKiBAcGFyYW0gIHtzdHJpbmd9IENsYXNzIHRvIGFzc2lnbiB0byB0aGUgYmFja2dyb3VuZFxuICogQHN0YXRpY1xuICovXG5CdXR0b25zLmJhY2tncm91bmQgPSBmdW5jdGlvbiAoIHNob3csIGNsYXNzTmFtZSwgZmFkZSwgaW5zZXJ0UG9pbnQgKSB7XG5cdGlmICggZmFkZSA9PT0gdW5kZWZpbmVkICkge1xuXHRcdGZhZGUgPSA0MDA7XG5cdH1cblx0aWYgKCAhIGluc2VydFBvaW50ICkge1xuXHRcdGluc2VydFBvaW50ID0gZG9jdW1lbnQuYm9keTtcblx0fVxuXG5cdGlmICggc2hvdyApIHtcblx0XHRfZmFkZUluKFxuXHRcdFx0JCgnPGRpdi8+Jylcblx0XHRcdFx0LmFkZENsYXNzKCBjbGFzc05hbWUgKVxuXHRcdFx0XHQuY3NzKCAnZGlzcGxheScsICdub25lJyApXG5cdFx0XHRcdC5pbnNlcnRBZnRlciggaW5zZXJ0UG9pbnQgKSxcblx0XHRcdGZhZGVcblx0XHQpO1xuXHR9XG5cdGVsc2Uge1xuXHRcdF9mYWRlT3V0KFxuXHRcdFx0JCgnZGl2LicrY2xhc3NOYW1lKSxcblx0XHRcdGZhZGUsXG5cdFx0XHRmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdCQodGhpcylcblx0XHRcdFx0XHQucmVtb3ZlQ2xhc3MoIGNsYXNzTmFtZSApXG5cdFx0XHRcdFx0LnJlbW92ZSgpO1xuXHRcdFx0fVxuXHRcdCk7XG5cdH1cbn07XG5cbi8qKlxuICogSW5zdGFuY2Ugc2VsZWN0b3IgLSBzZWxlY3QgQnV0dG9ucyBpbnN0YW5jZXMgYmFzZWQgb24gYW4gaW5zdGFuY2Ugc2VsZWN0b3JcbiAqIHZhbHVlIGZyb20gdGhlIGJ1dHRvbnMgYXNzaWduZWQgdG8gYSBEYXRhVGFibGUuIFRoaXMgaXMgb25seSB1c2VmdWwgaWZcbiAqIG11bHRpcGxlIGluc3RhbmNlcyBhcmUgYXR0YWNoZWQgdG8gYSBEYXRhVGFibGUuXG4gKiBAcGFyYW0gIHtzdHJpbmd8aW50fGFycmF5fSBJbnN0YW5jZSBzZWxlY3RvciAtIHNlZSBgaW5zdGFuY2Utc2VsZWN0b3JgXG4gKiAgIGRvY3VtZW50YXRpb24gb24gdGhlIERhdGFUYWJsZXMgc2l0ZVxuICogQHBhcmFtICB7YXJyYXl9IEJ1dHRvbiBpbnN0YW5jZSBhcnJheSB0aGF0IHdhcyBhdHRhY2hlZCB0byB0aGUgRGF0YVRhYmxlc1xuICogICBzZXR0aW5ncyBvYmplY3RcbiAqIEByZXR1cm4ge2FycmF5fSBCdXR0b25zIGluc3RhbmNlc1xuICogQHN0YXRpY1xuICovXG5CdXR0b25zLmluc3RhbmNlU2VsZWN0b3IgPSBmdW5jdGlvbiAoIGdyb3VwLCBidXR0b25zIClcbntcblx0aWYgKCBncm91cCA9PT0gdW5kZWZpbmVkIHx8IGdyb3VwID09PSBudWxsICkge1xuXHRcdHJldHVybiAkLm1hcCggYnV0dG9ucywgZnVuY3Rpb24gKCB2ICkge1xuXHRcdFx0cmV0dXJuIHYuaW5zdDtcblx0XHR9ICk7XG5cdH1cblxuXHR2YXIgcmV0ID0gW107XG5cdHZhciBuYW1lcyA9ICQubWFwKCBidXR0b25zLCBmdW5jdGlvbiAoIHYgKSB7XG5cdFx0cmV0dXJuIHYubmFtZTtcblx0fSApO1xuXG5cdC8vIEZsYXR0ZW4gdGhlIGdyb3VwIHNlbGVjdG9yIGludG8gYW4gYXJyYXkgb2Ygc2luZ2xlIG9wdGlvbnNcblx0dmFyIHByb2Nlc3MgPSBmdW5jdGlvbiAoIGlucHV0ICkge1xuXHRcdGlmICggQXJyYXkuaXNBcnJheSggaW5wdXQgKSApIHtcblx0XHRcdGZvciAoIHZhciBpPTAsIGllbj1pbnB1dC5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdFx0cHJvY2VzcyggaW5wdXRbaV0gKTtcblx0XHRcdH1cblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAoIHR5cGVvZiBpbnB1dCA9PT0gJ3N0cmluZycgKSB7XG5cdFx0XHRpZiAoIGlucHV0LmluZGV4T2YoICcsJyApICE9PSAtMSApIHtcblx0XHRcdFx0Ly8gU3RyaW5nIHNlbGVjdG9yLCBsaXN0IG9mIG5hbWVzXG5cdFx0XHRcdHByb2Nlc3MoIGlucHV0LnNwbGl0KCcsJykgKTtcblx0XHRcdH1cblx0XHRcdGVsc2Uge1xuXHRcdFx0XHQvLyBTdHJpbmcgc2VsZWN0b3IgaW5kaXZpZHVhbCBuYW1lXG5cdFx0XHRcdHZhciBpZHggPSAkLmluQXJyYXkoIGlucHV0LnRyaW0oKSwgbmFtZXMgKTtcblxuXHRcdFx0XHRpZiAoIGlkeCAhPT0gLTEgKSB7XG5cdFx0XHRcdFx0cmV0LnB1c2goIGJ1dHRvbnNbIGlkeCBdLmluc3QgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XHRlbHNlIGlmICggdHlwZW9mIGlucHV0ID09PSAnbnVtYmVyJyApIHtcblx0XHRcdC8vIEluZGV4IHNlbGVjdG9yXG5cdFx0XHRyZXQucHVzaCggYnV0dG9uc1sgaW5wdXQgXS5pbnN0ICk7XG5cdFx0fVxuXHRcdGVsc2UgaWYgKCB0eXBlb2YgaW5wdXQgPT09ICdvYmplY3QnICkge1xuXHRcdFx0Ly8gQWN0dWFsIGluc3RhbmNlIHNlbGVjdG9yXG5cdFx0XHRyZXQucHVzaCggaW5wdXQgKTtcblx0XHR9XG5cdH07XG5cdFxuXHRwcm9jZXNzKCBncm91cCApO1xuXG5cdHJldHVybiByZXQ7XG59O1xuXG4vKipcbiAqIEJ1dHRvbiBzZWxlY3RvciAtIHNlbGVjdCBvbmUgb3IgbW9yZSBidXR0b25zIGZyb20gYSBzZWxlY3RvciBpbnB1dCBzbyBzb21lXG4gKiBvcGVyYXRpb24gY2FuIGJlIHBlcmZvcm1lZCBvbiB0aGVtLlxuICogQHBhcmFtICB7YXJyYXl9IEJ1dHRvbiBpbnN0YW5jZXMgYXJyYXkgdGhhdCB0aGUgc2VsZWN0b3Igc2hvdWxkIG9wZXJhdGUgb25cbiAqIEBwYXJhbSAge3N0cmluZ3xpbnR8bm9kZXxqUXVlcnl8YXJyYXl9IEJ1dHRvbiBzZWxlY3RvciAtIHNlZVxuICogICBgYnV0dG9uLXNlbGVjdG9yYCBkb2N1bWVudGF0aW9uIG9uIHRoZSBEYXRhVGFibGVzIHNpdGVcbiAqIEByZXR1cm4ge2FycmF5fSBBcnJheSBvZiBvYmplY3RzIGNvbnRhaW5pbmcgYGluc3RgIGFuZCBgaWR4YCBwcm9wZXJ0aWVzIG9mXG4gKiAgIHRoZSBzZWxlY3RlZCBidXR0b25zIHNvIHlvdSBrbm93IHdoaWNoIGluc3RhbmNlIGVhY2ggYnV0dG9uIGJlbG9uZ3MgdG8uXG4gKiBAc3RhdGljXG4gKi9cbkJ1dHRvbnMuYnV0dG9uU2VsZWN0b3IgPSBmdW5jdGlvbiAoIGluc3RzLCBzZWxlY3RvciApXG57XG5cdHZhciByZXQgPSBbXTtcblx0dmFyIG5vZGVCdWlsZGVyID0gZnVuY3Rpb24gKCBhLCBidXR0b25zLCBiYXNlSWR4ICkge1xuXHRcdHZhciBidXR0b247XG5cdFx0dmFyIGlkeDtcblxuXHRcdGZvciAoIHZhciBpPTAsIGllbj1idXR0b25zLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdFx0YnV0dG9uID0gYnV0dG9uc1tpXTtcblxuXHRcdFx0aWYgKCBidXR0b24gKSB7XG5cdFx0XHRcdGlkeCA9IGJhc2VJZHggIT09IHVuZGVmaW5lZCA/XG5cdFx0XHRcdFx0YmFzZUlkeCtpIDpcblx0XHRcdFx0XHRpKycnO1xuXG5cdFx0XHRcdGEucHVzaCgge1xuXHRcdFx0XHRcdG5vZGU6IGJ1dHRvbi5ub2RlLFxuXHRcdFx0XHRcdG5hbWU6IGJ1dHRvbi5jb25mLm5hbWUsXG5cdFx0XHRcdFx0aWR4OiAgaWR4XG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0XHRpZiAoIGJ1dHRvbi5idXR0b25zICkge1xuXHRcdFx0XHRcdG5vZGVCdWlsZGVyKCBhLCBidXR0b24uYnV0dG9ucywgaWR4KyctJyApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9O1xuXG5cdHZhciBydW4gPSBmdW5jdGlvbiAoIHNlbGVjdG9yLCBpbnN0ICkge1xuXHRcdHZhciBpLCBpZW47XG5cdFx0dmFyIGJ1dHRvbnMgPSBbXTtcblx0XHRub2RlQnVpbGRlciggYnV0dG9ucywgaW5zdC5zLmJ1dHRvbnMgKTtcblxuXHRcdHZhciBub2RlcyA9ICQubWFwKCBidXR0b25zLCBmdW5jdGlvbiAodikge1xuXHRcdFx0cmV0dXJuIHYubm9kZTtcblx0XHR9ICk7XG5cblx0XHRpZiAoIEFycmF5LmlzQXJyYXkoIHNlbGVjdG9yICkgfHwgc2VsZWN0b3IgaW5zdGFuY2VvZiAkICkge1xuXHRcdFx0Zm9yICggaT0wLCBpZW49c2VsZWN0b3IubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRcdHJ1biggc2VsZWN0b3JbaV0sIGluc3QgKTtcblx0XHRcdH1cblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAoIHNlbGVjdG9yID09PSBudWxsIHx8IHNlbGVjdG9yID09PSB1bmRlZmluZWQgfHwgc2VsZWN0b3IgPT09ICcqJyApIHtcblx0XHRcdC8vIFNlbGVjdCBhbGxcblx0XHRcdGZvciAoIGk9MCwgaWVuPWJ1dHRvbnMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRcdHJldC5wdXNoKCB7XG5cdFx0XHRcdFx0aW5zdDogaW5zdCxcblx0XHRcdFx0XHRub2RlOiBidXR0b25zW2ldLm5vZGVcblx0XHRcdFx0fSApO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRlbHNlIGlmICggdHlwZW9mIHNlbGVjdG9yID09PSAnbnVtYmVyJyApIHtcblx0XHRcdC8vIE1haW4gYnV0dG9uIGluZGV4IHNlbGVjdG9yXG5cdFx0XHRpZiAoaW5zdC5zLmJ1dHRvbnNbIHNlbGVjdG9yIF0pIHtcblx0XHRcdFx0cmV0LnB1c2goIHtcblx0XHRcdFx0XHRpbnN0OiBpbnN0LFxuXHRcdFx0XHRcdG5vZGU6IGluc3Qucy5idXR0b25zWyBzZWxlY3RvciBdLm5vZGVcblx0XHRcdFx0fSApO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRlbHNlIGlmICggdHlwZW9mIHNlbGVjdG9yID09PSAnc3RyaW5nJyApIHtcblx0XHRcdGlmICggc2VsZWN0b3IuaW5kZXhPZiggJywnICkgIT09IC0xICkge1xuXHRcdFx0XHQvLyBTcGxpdFxuXHRcdFx0XHR2YXIgYSA9IHNlbGVjdG9yLnNwbGl0KCcsJyk7XG5cblx0XHRcdFx0Zm9yICggaT0wLCBpZW49YS5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdFx0XHRydW4oIGFbaV0udHJpbSgpLCBpbnN0ICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdGVsc2UgaWYgKCBzZWxlY3Rvci5tYXRjaCggL15cXGQrKFxcLVxcZCspKiQvICkgKSB7XG5cdFx0XHRcdC8vIFN1Yi1idXR0b24gaW5kZXggc2VsZWN0b3Jcblx0XHRcdFx0dmFyIGluZGV4ZXMgPSAkLm1hcCggYnV0dG9ucywgZnVuY3Rpb24gKHYpIHtcblx0XHRcdFx0XHRyZXR1cm4gdi5pZHg7XG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0XHRyZXQucHVzaCgge1xuXHRcdFx0XHRcdGluc3Q6IGluc3QsXG5cdFx0XHRcdFx0bm9kZTogYnV0dG9uc1sgJC5pbkFycmF5KCBzZWxlY3RvciwgaW5kZXhlcyApIF0ubm9kZVxuXHRcdFx0XHR9ICk7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIGlmICggc2VsZWN0b3IuaW5kZXhPZiggJzpuYW1lJyApICE9PSAtMSApIHtcblx0XHRcdFx0Ly8gQnV0dG9uIG5hbWUgc2VsZWN0b3Jcblx0XHRcdFx0dmFyIG5hbWUgPSBzZWxlY3Rvci5yZXBsYWNlKCAnOm5hbWUnLCAnJyApO1xuXG5cdFx0XHRcdGZvciAoIGk9MCwgaWVuPWJ1dHRvbnMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRcdFx0aWYgKCBidXR0b25zW2ldLm5hbWUgPT09IG5hbWUgKSB7XG5cdFx0XHRcdFx0XHRyZXQucHVzaCgge1xuXHRcdFx0XHRcdFx0XHRpbnN0OiBpbnN0LFxuXHRcdFx0XHRcdFx0XHRub2RlOiBidXR0b25zW2ldLm5vZGVcblx0XHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdGVsc2Uge1xuXHRcdFx0XHQvLyBqUXVlcnkgc2VsZWN0b3Igb24gdGhlIG5vZGVzXG5cdFx0XHRcdCQoIG5vZGVzICkuZmlsdGVyKCBzZWxlY3RvciApLmVhY2goIGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHRyZXQucHVzaCgge1xuXHRcdFx0XHRcdFx0aW5zdDogaW5zdCxcblx0XHRcdFx0XHRcdG5vZGU6IHRoaXNcblx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdH0gKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0ZWxzZSBpZiAoIHR5cGVvZiBzZWxlY3RvciA9PT0gJ29iamVjdCcgJiYgc2VsZWN0b3Iubm9kZU5hbWUgKSB7XG5cdFx0XHQvLyBOb2RlIHNlbGVjdG9yXG5cdFx0XHR2YXIgaWR4ID0gJC5pbkFycmF5KCBzZWxlY3Rvciwgbm9kZXMgKTtcblxuXHRcdFx0aWYgKCBpZHggIT09IC0xICkge1xuXHRcdFx0XHRyZXQucHVzaCgge1xuXHRcdFx0XHRcdGluc3Q6IGluc3QsXG5cdFx0XHRcdFx0bm9kZTogbm9kZXNbIGlkeCBdXG5cdFx0XHRcdH0gKTtcblx0XHRcdH1cblx0XHR9XG5cdH07XG5cblxuXHRmb3IgKCB2YXIgaT0wLCBpZW49aW5zdHMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0dmFyIGluc3QgPSBpbnN0c1tpXTtcblxuXHRcdHJ1biggc2VsZWN0b3IsIGluc3QgKTtcblx0fVxuXG5cdHJldHVybiByZXQ7XG59O1xuXG4vKipcbiAqIERlZmF1bHQgZnVuY3Rpb24gdXNlZCBmb3IgZm9ybWF0dGluZyBvdXRwdXQgZGF0YS5cbiAqIEBwYXJhbSB7Kn0gc3RyIERhdGEgdG8gc3RyaXBcbiAqL1xuQnV0dG9ucy5zdHJpcERhdGEgPSBmdW5jdGlvbiAoIHN0ciwgY29uZmlnICkge1xuXHRpZiAoIHR5cGVvZiBzdHIgIT09ICdzdHJpbmcnICkge1xuXHRcdHJldHVybiBzdHI7XG5cdH1cblxuXHQvLyBBbHdheXMgcmVtb3ZlIHNjcmlwdCB0YWdzXG5cdHN0ciA9IHN0ci5yZXBsYWNlKCAvPHNjcmlwdFxcYltePF0qKD86KD8hPFxcL3NjcmlwdD4pPFtePF0qKSo8XFwvc2NyaXB0Pi9naSwgJycgKTtcblxuXHQvLyBBbHdheXMgcmVtb3ZlIGNvbW1lbnRzXG5cdHN0ciA9IHN0ci5yZXBsYWNlKCAvPCFcXC1cXC0uKj9cXC1cXC0+L2csICcnICk7XG5cblx0aWYgKCAhIGNvbmZpZyB8fCBjb25maWcuc3RyaXBIdG1sICkge1xuXHRcdHN0ciA9IHN0ci5yZXBsYWNlKCAvPFtePl0qPi9nLCAnJyApO1xuXHR9XG5cblx0aWYgKCAhIGNvbmZpZyB8fCBjb25maWcudHJpbSApIHtcblx0XHRzdHIgPSBzdHIucmVwbGFjZSggL15cXHMrfFxccyskL2csICcnICk7XG5cdH1cblxuXHRpZiAoICEgY29uZmlnIHx8IGNvbmZpZy5zdHJpcE5ld2xpbmVzICkge1xuXHRcdHN0ciA9IHN0ci5yZXBsYWNlKCAvXFxuL2csICcgJyApO1xuXHR9XG5cblx0aWYgKCAhIGNvbmZpZyB8fCBjb25maWcuZGVjb2RlRW50aXRpZXMgKSB7XG5cdFx0X2V4cG9ydFRleHRhcmVhLmlubmVySFRNTCA9IHN0cjtcblx0XHRzdHIgPSBfZXhwb3J0VGV4dGFyZWEudmFsdWU7XG5cdH1cblxuXHRyZXR1cm4gc3RyO1xufTtcblxuXG4vKipcbiAqIEJ1dHRvbnMgZGVmYXVsdHMuIEZvciBmdWxsIGRvY3VtZW50YXRpb24sIHBsZWFzZSByZWZlciB0byB0aGUgZG9jcy9vcHRpb25cbiAqIGRpcmVjdG9yeSBvciB0aGUgRGF0YVRhYmxlcyBzaXRlLlxuICogQHR5cGUge09iamVjdH1cbiAqIEBzdGF0aWNcbiAqL1xuQnV0dG9ucy5kZWZhdWx0cyA9IHtcblx0YnV0dG9uczogWyAnY29weScsICdleGNlbCcsICdjc3YnLCAncGRmJywgJ3ByaW50JyBdLFxuXHRuYW1lOiAnbWFpbicsXG5cdHRhYkluZGV4OiAwLFxuXHRkb206IHtcblx0XHRjb250YWluZXI6IHtcblx0XHRcdHRhZzogJ2RpdicsXG5cdFx0XHRjbGFzc05hbWU6ICdkdC1idXR0b25zJ1xuXHRcdH0sXG5cdFx0Y29sbGVjdGlvbjoge1xuXHRcdFx0dGFnOiAnZGl2Jyxcblx0XHRcdGNsYXNzTmFtZTogJydcblx0XHR9LFxuXHRcdGJ1dHRvbjoge1xuXHRcdFx0dGFnOiAnYnV0dG9uJyxcblx0XHRcdGNsYXNzTmFtZTogJ2R0LWJ1dHRvbicsXG5cdFx0XHRhY3RpdmU6ICdhY3RpdmUnLFxuXHRcdFx0ZGlzYWJsZWQ6ICdkaXNhYmxlZCcsXG5cdFx0XHRzcGFjZXJDbGFzczogJydcblx0XHR9LFxuXHRcdGJ1dHRvbkxpbmVyOiB7XG5cdFx0XHR0YWc6ICdzcGFuJyxcblx0XHRcdGNsYXNzTmFtZTogJydcblx0XHR9LFxuXHRcdHNwbGl0OiB7XG5cdFx0XHR0YWc6ICdkaXYnLFxuXHRcdFx0Y2xhc3NOYW1lOiAnZHQtYnV0dG9uLXNwbGl0Jyxcblx0XHR9LFxuXHRcdHNwbGl0V3JhcHBlcjoge1xuXHRcdFx0dGFnOiAnZGl2Jyxcblx0XHRcdGNsYXNzTmFtZTogJ2R0LWJ0bi1zcGxpdC13cmFwcGVyJyxcblx0XHR9LFxuXHRcdHNwbGl0RHJvcGRvd246IHtcblx0XHRcdHRhZzogJ2J1dHRvbicsXG5cdFx0XHR0ZXh0OiAnJiN4MjVCQzsnLFxuXHRcdFx0Y2xhc3NOYW1lOiAnZHQtYnRuLXNwbGl0LWRyb3AnLFxuXHRcdFx0YWxpZ246ICdzcGxpdC1yaWdodCcsXG5cdFx0XHRzcGxpdEFsaWduQ2xhc3M6ICdkdC1idXR0b24tc3BsaXQtbGVmdCdcblx0XHR9LFxuXHRcdHNwbGl0RHJvcGRvd25CdXR0b246IHtcblx0XHRcdHRhZzogJ2J1dHRvbicsXG5cdFx0XHRjbGFzc05hbWU6ICdkdC1idG4tc3BsaXQtZHJvcC1idXR0b24gZHQtYnV0dG9uJyxcblx0XHR9LFxuXHRcdHNwbGl0Q29sbGVjdGlvbjoge1xuXHRcdFx0dGFnOiAnZGl2Jyxcblx0XHRcdGNsYXNzTmFtZTogJ2R0LWJ1dHRvbi1zcGxpdC1jb2xsZWN0aW9uJyxcblx0XHR9XG5cdH1cbn07XG5cbi8qKlxuICogVmVyc2lvbiBpbmZvcm1hdGlvblxuICogQHR5cGUge3N0cmluZ31cbiAqIEBzdGF0aWNcbiAqL1xuQnV0dG9ucy52ZXJzaW9uID0gJzIuMi4zJztcblxuXG4kLmV4dGVuZCggX2R0QnV0dG9ucywge1xuXHRjb2xsZWN0aW9uOiB7XG5cdFx0dGV4dDogZnVuY3Rpb24gKCBkdCApIHtcblx0XHRcdHJldHVybiBkdC5pMThuKCAnYnV0dG9ucy5jb2xsZWN0aW9uJywgJ0NvbGxlY3Rpb24nICk7XG5cdFx0fSxcblx0XHRjbGFzc05hbWU6ICdidXR0b25zLWNvbGxlY3Rpb24nLFxuXHRcdGNsb3NlQnV0dG9uOiBmYWxzZSxcblx0XHRpbml0OiBmdW5jdGlvbiAoIGR0LCBidXR0b24sIGNvbmZpZyApIHtcblx0XHRcdGJ1dHRvbi5hdHRyKCAnYXJpYS1leHBhbmRlZCcsIGZhbHNlICk7XG5cdFx0fSxcblx0XHRhY3Rpb246IGZ1bmN0aW9uICggZSwgZHQsIGJ1dHRvbiwgY29uZmlnICkge1xuXHRcdFx0aWYgKCBjb25maWcuX2NvbGxlY3Rpb24ucGFyZW50cygnYm9keScpLmxlbmd0aCApIHtcblx0XHRcdFx0dGhpcy5wb3BvdmVyKGZhbHNlLCBjb25maWcpO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSB7XG5cdFx0XHRcdHRoaXMucG9wb3Zlcihjb25maWcuX2NvbGxlY3Rpb24sIGNvbmZpZyk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFdoZW4gYWN0aXZhdGVkIHVzaW5nIGEga2V5IC0gYXV0byBmb2N1cyBvbiB0aGVcblx0XHRcdC8vIGZpcnN0IGl0ZW0gaW4gdGhlIHBvcG92ZXJcblx0XHRcdGlmIChlLnR5cGUgPT09ICdrZXlwcmVzcycpIHtcblx0XHRcdFx0JCgnYSwgYnV0dG9uJywgY29uZmlnLl9jb2xsZWN0aW9uKS5lcSgwKS5mb2N1cygpO1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0YXR0cjoge1xuXHRcdFx0J2FyaWEtaGFzcG9wdXAnOiAnZGlhbG9nJ1xuXHRcdH1cblx0XHQvLyBBbHNvIHRoZSBwb3BvdmVyIG9wdGlvbnMsIGRlZmluZWQgaW4gQnV0dG9ucy5wb3BvdmVyXG5cdH0sXG5cdHNwbGl0OiB7XG5cdFx0dGV4dDogZnVuY3Rpb24gKCBkdCApIHtcblx0XHRcdHJldHVybiBkdC5pMThuKCAnYnV0dG9ucy5zcGxpdCcsICdTcGxpdCcgKTtcblx0XHR9LFxuXHRcdGNsYXNzTmFtZTogJ2J1dHRvbnMtc3BsaXQnLFxuXHRcdGNsb3NlQnV0dG9uOiBmYWxzZSxcblx0XHRpbml0OiBmdW5jdGlvbiAoIGR0LCBidXR0b24sIGNvbmZpZyApIHtcblx0XHRcdHJldHVybiBidXR0b24uYXR0ciggJ2FyaWEtZXhwYW5kZWQnLCBmYWxzZSApO1xuXHRcdH0sXG5cdFx0YWN0aW9uOiBmdW5jdGlvbiAoIGUsIGR0LCBidXR0b24sIGNvbmZpZyApIHtcblx0XHRcdHRoaXMucG9wb3Zlcihjb25maWcuX2NvbGxlY3Rpb24sIGNvbmZpZyk7XG5cdFx0fSxcblx0XHRhdHRyOiB7XG5cdFx0XHQnYXJpYS1oYXNwb3B1cCc6ICdkaWFsb2cnXG5cdFx0fVxuXHRcdC8vIEFsc28gdGhlIHBvcG92ZXIgb3B0aW9ucywgZGVmaW5lZCBpbiBCdXR0b25zLnBvcG92ZXJcblx0fSxcblx0Y29weTogZnVuY3Rpb24gKCBkdCwgY29uZiApIHtcblx0XHRpZiAoIF9kdEJ1dHRvbnMuY29weUh0bWw1ICkge1xuXHRcdFx0cmV0dXJuICdjb3B5SHRtbDUnO1xuXHRcdH1cblx0fSxcblx0Y3N2OiBmdW5jdGlvbiAoIGR0LCBjb25mICkge1xuXHRcdGlmICggX2R0QnV0dG9ucy5jc3ZIdG1sNSAmJiBfZHRCdXR0b25zLmNzdkh0bWw1LmF2YWlsYWJsZSggZHQsIGNvbmYgKSApIHtcblx0XHRcdHJldHVybiAnY3N2SHRtbDUnO1xuXHRcdH1cblx0fSxcblx0ZXhjZWw6IGZ1bmN0aW9uICggZHQsIGNvbmYgKSB7XG5cdFx0aWYgKCBfZHRCdXR0b25zLmV4Y2VsSHRtbDUgJiYgX2R0QnV0dG9ucy5leGNlbEh0bWw1LmF2YWlsYWJsZSggZHQsIGNvbmYgKSApIHtcblx0XHRcdHJldHVybiAnZXhjZWxIdG1sNSc7XG5cdFx0fVxuXHR9LFxuXHRwZGY6IGZ1bmN0aW9uICggZHQsIGNvbmYgKSB7XG5cdFx0aWYgKCBfZHRCdXR0b25zLnBkZkh0bWw1ICYmIF9kdEJ1dHRvbnMucGRmSHRtbDUuYXZhaWxhYmxlKCBkdCwgY29uZiApICkge1xuXHRcdFx0cmV0dXJuICdwZGZIdG1sNSc7XG5cdFx0fVxuXHR9LFxuXHRwYWdlTGVuZ3RoOiBmdW5jdGlvbiAoIGR0ICkge1xuXHRcdHZhciBsZW5ndGhNZW51ID0gZHQuc2V0dGluZ3MoKVswXS5hTGVuZ3RoTWVudTtcblx0XHR2YXIgdmFscyA9IFtdO1xuXHRcdHZhciBsYW5nID0gW107XG5cdFx0dmFyIHRleHQgPSBmdW5jdGlvbiAoIGR0ICkge1xuXHRcdFx0cmV0dXJuIGR0LmkxOG4oICdidXR0b25zLnBhZ2VMZW5ndGgnLCB7XG5cdFx0XHRcdFwiLTFcIjogJ1Nob3cgYWxsIHJvd3MnLFxuXHRcdFx0XHRfOiAgICAnU2hvdyAlZCByb3dzJ1xuXHRcdFx0fSwgZHQucGFnZS5sZW4oKSApO1xuXHRcdH07XG5cblx0XHQvLyBTdXBwb3J0IGZvciBEYXRhVGFibGVzIDEueCAyRCBhcnJheVxuXHRcdGlmIChBcnJheS5pc0FycmF5KCBsZW5ndGhNZW51WzBdICkpIHtcblx0XHRcdHZhbHMgPSBsZW5ndGhNZW51WzBdO1xuXHRcdFx0bGFuZyA9IGxlbmd0aE1lbnVbMV07XG5cdFx0fVxuXHRcdGVsc2Uge1xuXHRcdFx0Zm9yICh2YXIgaT0wIDsgaTxsZW5ndGhNZW51Lmxlbmd0aCA7IGkrKykge1xuXHRcdFx0XHR2YXIgb3B0aW9uID0gbGVuZ3RoTWVudVtpXTtcblxuXHRcdFx0XHQvLyBTdXBwb3J0IGZvciBEYXRhVGFibGVzIDIgb2JqZWN0IGluIHRoZSBhcnJheVxuXHRcdFx0XHRpZiAoJC5pc1BsYWluT2JqZWN0KG9wdGlvbikpIHtcblx0XHRcdFx0XHR2YWxzLnB1c2gob3B0aW9uLnZhbHVlKTtcblx0XHRcdFx0XHRsYW5nLnB1c2gob3B0aW9uLmxhYmVsKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHR2YWxzLnB1c2gob3B0aW9uKTtcblx0XHRcdFx0XHRsYW5nLnB1c2gob3B0aW9uKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiB7XG5cdFx0XHRleHRlbmQ6ICdjb2xsZWN0aW9uJyxcblx0XHRcdHRleHQ6IHRleHQsXG5cdFx0XHRjbGFzc05hbWU6ICdidXR0b25zLXBhZ2UtbGVuZ3RoJyxcblx0XHRcdGF1dG9DbG9zZTogdHJ1ZSxcblx0XHRcdGJ1dHRvbnM6ICQubWFwKCB2YWxzLCBmdW5jdGlvbiAoIHZhbCwgaSApIHtcblx0XHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0XHR0ZXh0OiBsYW5nW2ldLFxuXHRcdFx0XHRcdGNsYXNzTmFtZTogJ2J1dHRvbi1wYWdlLWxlbmd0aCcsXG5cdFx0XHRcdFx0YWN0aW9uOiBmdW5jdGlvbiAoIGUsIGR0ICkge1xuXHRcdFx0XHRcdFx0ZHQucGFnZS5sZW4oIHZhbCApLmRyYXcoKTtcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdGluaXQ6IGZ1bmN0aW9uICggZHQsIG5vZGUsIGNvbmYgKSB7XG5cdFx0XHRcdFx0XHR2YXIgdGhhdCA9IHRoaXM7XG5cdFx0XHRcdFx0XHR2YXIgZm4gPSBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0XHRcdHRoYXQuYWN0aXZlKCBkdC5wYWdlLmxlbigpID09PSB2YWwgKTtcblx0XHRcdFx0XHRcdH07XG5cblx0XHRcdFx0XHRcdGR0Lm9uKCAnbGVuZ3RoLmR0Jytjb25mLm5hbWVzcGFjZSwgZm4gKTtcblx0XHRcdFx0XHRcdGZuKCk7XG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRkZXN0cm95OiBmdW5jdGlvbiAoIGR0LCBub2RlLCBjb25mICkge1xuXHRcdFx0XHRcdFx0ZHQub2ZmKCAnbGVuZ3RoLmR0Jytjb25mLm5hbWVzcGFjZSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fTtcblx0XHRcdH0gKSxcblx0XHRcdGluaXQ6IGZ1bmN0aW9uICggZHQsIG5vZGUsIGNvbmYgKSB7XG5cdFx0XHRcdHZhciB0aGF0ID0gdGhpcztcblx0XHRcdFx0ZHQub24oICdsZW5ndGguZHQnK2NvbmYubmFtZXNwYWNlLCBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0dGhhdC50ZXh0KCBjb25mLnRleHQgKTtcblx0XHRcdFx0fSApO1xuXHRcdFx0fSxcblx0XHRcdGRlc3Ryb3k6IGZ1bmN0aW9uICggZHQsIG5vZGUsIGNvbmYgKSB7XG5cdFx0XHRcdGR0Lm9mZiggJ2xlbmd0aC5kdCcrY29uZi5uYW1lc3BhY2UgKTtcblx0XHRcdH1cblx0XHR9O1xuXHR9LFxuXHRzcGFjZXI6IHtcblx0XHRzdHlsZTogJ2VtcHR5Jyxcblx0XHRzcGFjZXI6IHRydWUsXG5cdFx0dGV4dDogZnVuY3Rpb24gKCBkdCApIHtcblx0XHRcdHJldHVybiBkdC5pMThuKCAnYnV0dG9ucy5zcGFjZXInLCAnJyApO1xuXHRcdH1cblx0fVxufSApO1xuXG5cbi8qICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqXG4gKiBEYXRhVGFibGVzIEFQSVxuICpcbiAqIEZvciBjb21wbGV0ZSBkb2N1bWVudGF0aW9uLCBwbGVhc2UgcmVmZXIgdG8gdGhlIGRvY3MvYXBpIGRpcmVjdG9yeSBvciB0aGVcbiAqIERhdGFUYWJsZXMgc2l0ZVxuICovXG5cbi8vIEJ1dHRvbnMgZ3JvdXAgYW5kIGluZGl2aWR1YWwgYnV0dG9uIHNlbGVjdG9yXG5EYXRhVGFibGUuQXBpLnJlZ2lzdGVyKCAnYnV0dG9ucygpJywgZnVuY3Rpb24gKCBncm91cCwgc2VsZWN0b3IgKSB7XG5cdC8vIEFyZ3VtZW50IHNoaWZ0aW5nXG5cdGlmICggc2VsZWN0b3IgPT09IHVuZGVmaW5lZCApIHtcblx0XHRzZWxlY3RvciA9IGdyb3VwO1xuXHRcdGdyb3VwID0gdW5kZWZpbmVkO1xuXHR9XG5cblx0dGhpcy5zZWxlY3Rvci5idXR0b25Hcm91cCA9IGdyb3VwO1xuXG5cdHZhciByZXMgPSB0aGlzLml0ZXJhdG9yKCB0cnVlLCAndGFibGUnLCBmdW5jdGlvbiAoIGN0eCApIHtcblx0XHRpZiAoIGN0eC5fYnV0dG9ucyApIHtcblx0XHRcdHJldHVybiBCdXR0b25zLmJ1dHRvblNlbGVjdG9yKFxuXHRcdFx0XHRCdXR0b25zLmluc3RhbmNlU2VsZWN0b3IoIGdyb3VwLCBjdHguX2J1dHRvbnMgKSxcblx0XHRcdFx0c2VsZWN0b3Jcblx0XHRcdCk7XG5cdFx0fVxuXHR9LCB0cnVlICk7XG5cblx0cmVzLl9ncm91cFNlbGVjdG9yID0gZ3JvdXA7XG5cdHJldHVybiByZXM7XG59ICk7XG5cbi8vIEluZGl2aWR1YWwgYnV0dG9uIHNlbGVjdG9yXG5EYXRhVGFibGUuQXBpLnJlZ2lzdGVyKCAnYnV0dG9uKCknLCBmdW5jdGlvbiAoIGdyb3VwLCBzZWxlY3RvciApIHtcblx0Ly8ganVzdCBydW4gYnV0dG9ucygpIGFuZCB0cnVuY2F0ZVxuXHR2YXIgYnV0dG9ucyA9IHRoaXMuYnV0dG9ucyggZ3JvdXAsIHNlbGVjdG9yICk7XG5cblx0aWYgKCBidXR0b25zLmxlbmd0aCA+IDEgKSB7XG5cdFx0YnV0dG9ucy5zcGxpY2UoIDEsIGJ1dHRvbnMubGVuZ3RoICk7XG5cdH1cblxuXHRyZXR1cm4gYnV0dG9ucztcbn0gKTtcblxuLy8gQWN0aXZlIGJ1dHRvbnNcbkRhdGFUYWJsZS5BcGkucmVnaXN0ZXJQbHVyYWwoICdidXR0b25zKCkuYWN0aXZlKCknLCAnYnV0dG9uKCkuYWN0aXZlKCknLCBmdW5jdGlvbiAoIGZsYWcgKSB7XG5cdGlmICggZmxhZyA9PT0gdW5kZWZpbmVkICkge1xuXHRcdHJldHVybiB0aGlzLm1hcCggZnVuY3Rpb24gKCBzZXQgKSB7XG5cdFx0XHRyZXR1cm4gc2V0Lmluc3QuYWN0aXZlKCBzZXQubm9kZSApO1xuXHRcdH0gKTtcblx0fVxuXG5cdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uICggc2V0ICkge1xuXHRcdHNldC5pbnN0LmFjdGl2ZSggc2V0Lm5vZGUsIGZsYWcgKTtcblx0fSApO1xufSApO1xuXG4vLyBHZXQgLyBzZXQgYnV0dG9uIGFjdGlvblxuRGF0YVRhYmxlLkFwaS5yZWdpc3RlclBsdXJhbCggJ2J1dHRvbnMoKS5hY3Rpb24oKScsICdidXR0b24oKS5hY3Rpb24oKScsIGZ1bmN0aW9uICggYWN0aW9uICkge1xuXHRpZiAoIGFjdGlvbiA9PT0gdW5kZWZpbmVkICkge1xuXHRcdHJldHVybiB0aGlzLm1hcCggZnVuY3Rpb24gKCBzZXQgKSB7XG5cdFx0XHRyZXR1cm4gc2V0Lmluc3QuYWN0aW9uKCBzZXQubm9kZSApO1xuXHRcdH0gKTtcblx0fVxuXG5cdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uICggc2V0ICkge1xuXHRcdHNldC5pbnN0LmFjdGlvbiggc2V0Lm5vZGUsIGFjdGlvbiApO1xuXHR9ICk7XG59ICk7XG5cbi8vIENvbGxlY3Rpb24gY29udHJvbFxuRGF0YVRhYmxlLkFwaS5yZWdpc3RlclBsdXJhbCggJ2J1dHRvbnMoKS5jb2xsZWN0aW9uUmVidWlsZCgpJywgJ2J1dHRvbigpLmNvbGxlY3Rpb25SZWJ1aWxkKCknLCBmdW5jdGlvbiAoIGJ1dHRvbnMgKSB7XG5cdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uICggc2V0ICkge1xuXHRcdGZvcih2YXIgaSA9IDA7IGkgPCBidXR0b25zLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRpZih0eXBlb2YgYnV0dG9uc1tpXSA9PT0gJ29iamVjdCcpIHtcblx0XHRcdFx0YnV0dG9uc1tpXS5wYXJlbnRDb25mID0gc2V0O1xuXHRcdFx0fVxuXHRcdH1cblx0XHRzZXQuaW5zdC5jb2xsZWN0aW9uUmVidWlsZCggc2V0Lm5vZGUsIGJ1dHRvbnMgKTtcblx0fSApO1xufSApO1xuXG4vLyBFbmFibGUgLyBkaXNhYmxlIGJ1dHRvbnNcbkRhdGFUYWJsZS5BcGkucmVnaXN0ZXIoIFsnYnV0dG9ucygpLmVuYWJsZSgpJywgJ2J1dHRvbigpLmVuYWJsZSgpJ10sIGZ1bmN0aW9uICggZmxhZyApIHtcblx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24gKCBzZXQgKSB7XG5cdFx0c2V0Lmluc3QuZW5hYmxlKCBzZXQubm9kZSwgZmxhZyApO1xuXHR9ICk7XG59ICk7XG5cbi8vIERpc2FibGUgYnV0dG9uc1xuRGF0YVRhYmxlLkFwaS5yZWdpc3RlciggWydidXR0b25zKCkuZGlzYWJsZSgpJywgJ2J1dHRvbigpLmRpc2FibGUoKSddLCBmdW5jdGlvbiAoKSB7XG5cdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uICggc2V0ICkge1xuXHRcdHNldC5pbnN0LmRpc2FibGUoIHNldC5ub2RlICk7XG5cdH0gKTtcbn0gKTtcblxuLy8gQnV0dG9uIGluZGV4XG5EYXRhVGFibGUuQXBpLnJlZ2lzdGVyKCAnYnV0dG9uKCkuaW5kZXgoKScsIGZ1bmN0aW9uICgpIHtcblx0dmFyIGlkeCA9IG51bGw7XG5cblx0dGhpcy5lYWNoKCBmdW5jdGlvbiAoIHNldCApIHtcblx0XHR2YXIgcmVzID0gc2V0Lmluc3QuaW5kZXgoIHNldC5ub2RlICk7XG5cblx0XHRpZiAocmVzICE9PSBudWxsKSB7XG5cdFx0XHRpZHggPSByZXM7XG5cdFx0fVxuXHR9ICk7XG5cblx0cmV0dXJuIGlkeDtcbn0gKTtcblxuLy8gR2V0IGJ1dHRvbiBub2Rlc1xuRGF0YVRhYmxlLkFwaS5yZWdpc3RlclBsdXJhbCggJ2J1dHRvbnMoKS5ub2RlcygpJywgJ2J1dHRvbigpLm5vZGUoKScsIGZ1bmN0aW9uICgpIHtcblx0dmFyIGpxID0gJCgpO1xuXG5cdC8vIGpRdWVyeSB3aWxsIGF1dG9tYXRpY2FsbHkgcmVkdWNlIGR1cGxpY2F0ZXMgdG8gYSBzaW5nbGUgZW50cnlcblx0JCggdGhpcy5lYWNoKCBmdW5jdGlvbiAoIHNldCApIHtcblx0XHRqcSA9IGpxLmFkZCggc2V0Lmluc3Qubm9kZSggc2V0Lm5vZGUgKSApO1xuXHR9ICkgKTtcblxuXHRyZXR1cm4ganE7XG59ICk7XG5cbi8vIEdldCAvIHNldCBidXR0b24gcHJvY2Vzc2luZyBzdGF0ZVxuRGF0YVRhYmxlLkFwaS5yZWdpc3RlclBsdXJhbCggJ2J1dHRvbnMoKS5wcm9jZXNzaW5nKCknLCAnYnV0dG9uKCkucHJvY2Vzc2luZygpJywgZnVuY3Rpb24gKCBmbGFnICkge1xuXHRpZiAoIGZsYWcgPT09IHVuZGVmaW5lZCApIHtcblx0XHRyZXR1cm4gdGhpcy5tYXAoIGZ1bmN0aW9uICggc2V0ICkge1xuXHRcdFx0cmV0dXJuIHNldC5pbnN0LnByb2Nlc3NpbmcoIHNldC5ub2RlICk7XG5cdFx0fSApO1xuXHR9XG5cblx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24gKCBzZXQgKSB7XG5cdFx0c2V0Lmluc3QucHJvY2Vzc2luZyggc2V0Lm5vZGUsIGZsYWcgKTtcblx0fSApO1xufSApO1xuXG4vLyBHZXQgLyBzZXQgYnV0dG9uIHRleHQgKGkuZS4gdGhlIGJ1dHRvbiBsYWJlbHMpXG5EYXRhVGFibGUuQXBpLnJlZ2lzdGVyUGx1cmFsKCAnYnV0dG9ucygpLnRleHQoKScsICdidXR0b24oKS50ZXh0KCknLCBmdW5jdGlvbiAoIGxhYmVsICkge1xuXHRpZiAoIGxhYmVsID09PSB1bmRlZmluZWQgKSB7XG5cdFx0cmV0dXJuIHRoaXMubWFwKCBmdW5jdGlvbiAoIHNldCApIHtcblx0XHRcdHJldHVybiBzZXQuaW5zdC50ZXh0KCBzZXQubm9kZSApO1xuXHRcdH0gKTtcblx0fVxuXG5cdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uICggc2V0ICkge1xuXHRcdHNldC5pbnN0LnRleHQoIHNldC5ub2RlLCBsYWJlbCApO1xuXHR9ICk7XG59ICk7XG5cbi8vIFRyaWdnZXIgYSBidXR0b24ncyBhY3Rpb25cbkRhdGFUYWJsZS5BcGkucmVnaXN0ZXJQbHVyYWwoICdidXR0b25zKCkudHJpZ2dlcigpJywgJ2J1dHRvbigpLnRyaWdnZXIoKScsIGZ1bmN0aW9uICgpIHtcblx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24gKCBzZXQgKSB7XG5cdFx0c2V0Lmluc3Qubm9kZSggc2V0Lm5vZGUgKS50cmlnZ2VyKCAnY2xpY2snICk7XG5cdH0gKTtcbn0gKTtcblxuLy8gQnV0dG9uIHJlc29sdmVyIHRvIHRoZSBwb3BvdmVyXG5EYXRhVGFibGUuQXBpLnJlZ2lzdGVyKCAnYnV0dG9uKCkucG9wb3ZlcigpJywgZnVuY3Rpb24gKGNvbnRlbnQsIG9wdGlvbnMpIHtcblx0cmV0dXJuIHRoaXMubWFwKCBmdW5jdGlvbiAoIHNldCApIHtcblx0XHRyZXR1cm4gc2V0Lmluc3QuX3BvcG92ZXIoIGNvbnRlbnQsIHRoaXMuYnV0dG9uKHRoaXNbMF0ubm9kZSksIG9wdGlvbnMgKTtcblx0fSApO1xufSApO1xuXG4vLyBHZXQgdGhlIGNvbnRhaW5lciBlbGVtZW50c1xuRGF0YVRhYmxlLkFwaS5yZWdpc3RlciggJ2J1dHRvbnMoKS5jb250YWluZXJzKCknLCBmdW5jdGlvbiAoKSB7XG5cdHZhciBqcSA9ICQoKTtcblx0dmFyIGdyb3VwU2VsZWN0b3IgPSB0aGlzLl9ncm91cFNlbGVjdG9yO1xuXG5cdC8vIFdlIG5lZWQgdG8gdXNlIHRoZSBncm91cCBzZWxlY3RvciBkaXJlY3RseSwgc2luY2UgaWYgdGhlcmUgYXJlIG5vIGJ1dHRvbnNcblx0Ly8gdGhlIHJlc3VsdCBzZXQgd2lsbCBiZSBlbXB0eVxuXHR0aGlzLml0ZXJhdG9yKCB0cnVlLCAndGFibGUnLCBmdW5jdGlvbiAoIGN0eCApIHtcblx0XHRpZiAoIGN0eC5fYnV0dG9ucyApIHtcblx0XHRcdHZhciBpbnN0cyA9IEJ1dHRvbnMuaW5zdGFuY2VTZWxlY3RvciggZ3JvdXBTZWxlY3RvciwgY3R4Ll9idXR0b25zICk7XG5cblx0XHRcdGZvciAoIHZhciBpPTAsIGllbj1pbnN0cy5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdFx0anEgPSBqcS5hZGQoIGluc3RzW2ldLmNvbnRhaW5lcigpICk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9ICk7XG5cblx0cmV0dXJuIGpxO1xufSApO1xuXG5EYXRhVGFibGUuQXBpLnJlZ2lzdGVyKCAnYnV0dG9ucygpLmNvbnRhaW5lcigpJywgZnVuY3Rpb24gKCkge1xuXHQvLyBBUEkgbGV2ZWwgb2YgbmVzdGluZyBpcyBgYnV0dG9ucygpYCBzbyB3ZSBjYW4gemlwIGludG8gdGhlIGNvbnRhaW5lcnMgbWV0aG9kXG5cdHJldHVybiB0aGlzLmNvbnRhaW5lcnMoKS5lcSgwKTtcbn0gKTtcblxuLy8gQWRkIGEgbmV3IGJ1dHRvblxuRGF0YVRhYmxlLkFwaS5yZWdpc3RlciggJ2J1dHRvbigpLmFkZCgpJywgZnVuY3Rpb24gKCBpZHgsIGNvbmYsIGRyYXcgKSB7XG5cdHZhciBjdHggPSB0aGlzLmNvbnRleHQ7XG5cblx0Ly8gRG9uJ3QgdXNlIGB0aGlzYCBhcyBpdCBjb3VsZCBiZSBlbXB0eSAtIHNlbGVjdCB0aGUgaW5zdGFuY2VzIGRpcmVjdGx5XG5cdGlmICggY3R4Lmxlbmd0aCApIHtcblx0XHR2YXIgaW5zdCA9IEJ1dHRvbnMuaW5zdGFuY2VTZWxlY3RvciggdGhpcy5fZ3JvdXBTZWxlY3RvciwgY3R4WzBdLl9idXR0b25zICk7XG5cblx0XHRpZiAoIGluc3QubGVuZ3RoICkge1xuXHRcdFx0aW5zdFswXS5hZGQoIGNvbmYsIGlkeCAsIGRyYXcpO1xuXHRcdH1cblx0fVxuXG5cdHJldHVybiB0aGlzLmJ1dHRvbiggdGhpcy5fZ3JvdXBTZWxlY3RvciwgaWR4ICk7XG59ICk7XG5cbi8vIERlc3Ryb3kgdGhlIGJ1dHRvbiBzZXRzIHNlbGVjdGVkXG5EYXRhVGFibGUuQXBpLnJlZ2lzdGVyKCAnYnV0dG9ucygpLmRlc3Ryb3koKScsIGZ1bmN0aW9uICgpIHtcblx0dGhpcy5wbHVjayggJ2luc3QnICkudW5pcXVlKCkuZWFjaCggZnVuY3Rpb24gKCBpbnN0ICkge1xuXHRcdGluc3QuZGVzdHJveSgpO1xuXHR9ICk7XG5cblx0cmV0dXJuIHRoaXM7XG59ICk7XG5cbi8vIFJlbW92ZSBhIGJ1dHRvblxuRGF0YVRhYmxlLkFwaS5yZWdpc3RlclBsdXJhbCggJ2J1dHRvbnMoKS5yZW1vdmUoKScsICdidXR0b25zKCkucmVtb3ZlKCknLCBmdW5jdGlvbiAoKSB7XG5cdHRoaXMuZWFjaCggZnVuY3Rpb24gKCBzZXQgKSB7XG5cdFx0c2V0Lmluc3QucmVtb3ZlKCBzZXQubm9kZSApO1xuXHR9ICk7XG5cblx0cmV0dXJuIHRoaXM7XG59ICk7XG5cbi8vIEluZm9ybWF0aW9uIGJveCB0aGF0IGNhbiBiZSB1c2VkIGJ5IGJ1dHRvbnNcbnZhciBfaW5mb1RpbWVyO1xuRGF0YVRhYmxlLkFwaS5yZWdpc3RlciggJ2J1dHRvbnMuaW5mbygpJywgZnVuY3Rpb24gKCB0aXRsZSwgbWVzc2FnZSwgdGltZSApIHtcblx0dmFyIHRoYXQgPSB0aGlzO1xuXG5cdGlmICggdGl0bGUgPT09IGZhbHNlICkge1xuXHRcdHRoaXMub2ZmKCdkZXN0cm95LmJ0bi1pbmZvJyk7XG5cdFx0X2ZhZGVPdXQoXG5cdFx0XHQkKCcjZGF0YXRhYmxlc19idXR0b25zX2luZm8nKSxcblx0XHRcdDQwMCxcblx0XHRcdGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0JCh0aGlzKS5yZW1vdmUoKTtcblx0XHRcdH1cblx0XHQpO1xuXHRcdGNsZWFyVGltZW91dCggX2luZm9UaW1lciApO1xuXHRcdF9pbmZvVGltZXIgPSBudWxsO1xuXG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHRpZiAoIF9pbmZvVGltZXIgKSB7XG5cdFx0Y2xlYXJUaW1lb3V0KCBfaW5mb1RpbWVyICk7XG5cdH1cblxuXHRpZiAoICQoJyNkYXRhdGFibGVzX2J1dHRvbnNfaW5mbycpLmxlbmd0aCApIHtcblx0XHQkKCcjZGF0YXRhYmxlc19idXR0b25zX2luZm8nKS5yZW1vdmUoKTtcblx0fVxuXG5cdHRpdGxlID0gdGl0bGUgPyAnPGgyPicrdGl0bGUrJzwvaDI+JyA6ICcnO1xuXG5cdF9mYWRlSW4oXG5cdFx0JCgnPGRpdiBpZD1cImRhdGF0YWJsZXNfYnV0dG9uc19pbmZvXCIgY2xhc3M9XCJkdC1idXR0b24taW5mb1wiLz4nKVxuXHRcdFx0Lmh0bWwoIHRpdGxlIClcblx0XHRcdC5hcHBlbmQoICQoJzxkaXYvPicpWyB0eXBlb2YgbWVzc2FnZSA9PT0gJ3N0cmluZycgPyAnaHRtbCcgOiAnYXBwZW5kJyBdKCBtZXNzYWdlICkgKVxuXHRcdFx0LmNzcyggJ2Rpc3BsYXknLCAnbm9uZScgKVxuXHRcdFx0LmFwcGVuZFRvKCAnYm9keScgKVxuXHQpO1xuXG5cdGlmICggdGltZSAhPT0gdW5kZWZpbmVkICYmIHRpbWUgIT09IDAgKSB7XG5cdFx0X2luZm9UaW1lciA9IHNldFRpbWVvdXQoIGZ1bmN0aW9uICgpIHtcblx0XHRcdHRoYXQuYnV0dG9ucy5pbmZvKCBmYWxzZSApO1xuXHRcdH0sIHRpbWUgKTtcblx0fVxuXG5cdHRoaXMub24oJ2Rlc3Ryb3kuYnRuLWluZm8nLCBmdW5jdGlvbiAoKSB7XG5cdFx0dGhhdC5idXR0b25zLmluZm8oZmFsc2UpO1xuXHR9KTtcblxuXHRyZXR1cm4gdGhpcztcbn0gKTtcblxuLy8gR2V0IGRhdGEgZnJvbSB0aGUgdGFibGUgZm9yIGV4cG9ydCAtIHRoaXMgaXMgY29tbW9uIHRvIGEgbnVtYmVyIG9mIHBsdWctaW5cbi8vIGJ1dHRvbnMgc28gaXQgaXMgaW5jbHVkZWQgaW4gdGhlIEJ1dHRvbnMgY29yZSBsaWJyYXJ5XG5EYXRhVGFibGUuQXBpLnJlZ2lzdGVyKCAnYnV0dG9ucy5leHBvcnREYXRhKCknLCBmdW5jdGlvbiAoIG9wdGlvbnMgKSB7XG5cdGlmICggdGhpcy5jb250ZXh0Lmxlbmd0aCApIHtcblx0XHRyZXR1cm4gX2V4cG9ydERhdGEoIG5ldyBEYXRhVGFibGUuQXBpKCB0aGlzLmNvbnRleHRbMF0gKSwgb3B0aW9ucyApO1xuXHR9XG59ICk7XG5cbi8vIEdldCBpbmZvcm1hdGlvbiBhYm91dCB0aGUgZXhwb3J0IHRoYXQgaXMgY29tbW9uIHRvIG1hbnkgb2YgdGhlIGV4cG9ydCBkYXRhXG4vLyB0eXBlcyAoRFJZKVxuRGF0YVRhYmxlLkFwaS5yZWdpc3RlciggJ2J1dHRvbnMuZXhwb3J0SW5mbygpJywgZnVuY3Rpb24gKCBjb25mICkge1xuXHRpZiAoICEgY29uZiApIHtcblx0XHRjb25mID0ge307XG5cdH1cblxuXHRyZXR1cm4ge1xuXHRcdGZpbGVuYW1lOiBfZmlsZW5hbWUoIGNvbmYgKSxcblx0XHR0aXRsZTogX3RpdGxlKCBjb25mICksXG5cdFx0bWVzc2FnZVRvcDogX21lc3NhZ2UodGhpcywgY29uZi5tZXNzYWdlIHx8IGNvbmYubWVzc2FnZVRvcCwgJ3RvcCcpLFxuXHRcdG1lc3NhZ2VCb3R0b206IF9tZXNzYWdlKHRoaXMsIGNvbmYubWVzc2FnZUJvdHRvbSwgJ2JvdHRvbScpXG5cdH07XG59ICk7XG5cblxuXG4vKipcbiAqIEdldCB0aGUgZmlsZSBuYW1lIGZvciBhbiBleHBvcnRlZCBmaWxlLlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fVx0Y29uZmlnIEJ1dHRvbiBjb25maWd1cmF0aW9uXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGluY0V4dGVuc2lvbiBJbmNsdWRlIHRoZSBmaWxlIG5hbWUgZXh0ZW5zaW9uXG4gKi9cbnZhciBfZmlsZW5hbWUgPSBmdW5jdGlvbiAoIGNvbmZpZyApXG57XG5cdC8vIEJhY2t3YXJkcyBjb21wYXRpYmlsaXR5XG5cdHZhciBmaWxlbmFtZSA9IGNvbmZpZy5maWxlbmFtZSA9PT0gJyonICYmIGNvbmZpZy50aXRsZSAhPT0gJyonICYmIGNvbmZpZy50aXRsZSAhPT0gdW5kZWZpbmVkICYmIGNvbmZpZy50aXRsZSAhPT0gbnVsbCAmJiBjb25maWcudGl0bGUgIT09ICcnID9cblx0XHRjb25maWcudGl0bGUgOlxuXHRcdGNvbmZpZy5maWxlbmFtZTtcblxuXHRpZiAoIHR5cGVvZiBmaWxlbmFtZSA9PT0gJ2Z1bmN0aW9uJyApIHtcblx0XHRmaWxlbmFtZSA9IGZpbGVuYW1lKCk7XG5cdH1cblxuXHRpZiAoIGZpbGVuYW1lID09PSB1bmRlZmluZWQgfHwgZmlsZW5hbWUgPT09IG51bGwgKSB7XG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cblxuXHRpZiAoIGZpbGVuYW1lLmluZGV4T2YoICcqJyApICE9PSAtMSApIHtcblx0XHRmaWxlbmFtZSA9IGZpbGVuYW1lLnJlcGxhY2UoICcqJywgJCgnaGVhZCA+IHRpdGxlJykudGV4dCgpICkudHJpbSgpO1xuXHR9XG5cblx0Ly8gU3RyaXAgY2hhcmFjdGVycyB3aGljaCB0aGUgT1Mgd2lsbCBvYmplY3QgdG9cblx0ZmlsZW5hbWUgPSBmaWxlbmFtZS5yZXBsYWNlKC9bXmEtekEtWjAtOV9cXHUwMEExLVxcdUZGRkZcXC4sXFwtXyAhXFwoXFwpXS9nLCBcIlwiKTtcblxuXHR2YXIgZXh0ZW5zaW9uID0gX3N0cmluZ09yRnVuY3Rpb24oIGNvbmZpZy5leHRlbnNpb24gKTtcblx0aWYgKCAhIGV4dGVuc2lvbiApIHtcblx0XHRleHRlbnNpb24gPSAnJztcblx0fVxuXG5cdHJldHVybiBmaWxlbmFtZSArIGV4dGVuc2lvbjtcbn07XG5cbi8qKlxuICogU2ltcGx5IHV0aWxpdHkgbWV0aG9kIHRvIGFsbG93IHBhcmFtZXRlcnMgdG8gYmUgZ2l2ZW4gYXMgYSBmdW5jdGlvblxuICpcbiAqIEBwYXJhbSB7dW5kZWZpbmVkfHN0cmluZ3xmdW5jdGlvbn0gb3B0aW9uIE9wdGlvblxuICogQHJldHVybiB7bnVsbHxzdHJpbmd9IFJlc29sdmVkIHZhbHVlXG4gKi9cbnZhciBfc3RyaW5nT3JGdW5jdGlvbiA9IGZ1bmN0aW9uICggb3B0aW9uIClcbntcblx0aWYgKCBvcHRpb24gPT09IG51bGwgfHwgb3B0aW9uID09PSB1bmRlZmluZWQgKSB7XG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cblx0ZWxzZSBpZiAoIHR5cGVvZiBvcHRpb24gPT09ICdmdW5jdGlvbicgKSB7XG5cdFx0cmV0dXJuIG9wdGlvbigpO1xuXHR9XG5cdHJldHVybiBvcHRpb247XG59O1xuXG4vKipcbiAqIEdldCB0aGUgdGl0bGUgZm9yIGFuIGV4cG9ydGVkIGZpbGUuXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IGNvbmZpZ1x0QnV0dG9uIGNvbmZpZ3VyYXRpb25cbiAqL1xudmFyIF90aXRsZSA9IGZ1bmN0aW9uICggY29uZmlnIClcbntcblx0dmFyIHRpdGxlID0gX3N0cmluZ09yRnVuY3Rpb24oIGNvbmZpZy50aXRsZSApO1xuXG5cdHJldHVybiB0aXRsZSA9PT0gbnVsbCA/XG5cdFx0bnVsbCA6IHRpdGxlLmluZGV4T2YoICcqJyApICE9PSAtMSA/XG5cdFx0XHR0aXRsZS5yZXBsYWNlKCAnKicsICQoJ2hlYWQgPiB0aXRsZScpLnRleHQoKSB8fCAnRXhwb3J0ZWQgZGF0YScgKSA6XG5cdFx0XHR0aXRsZTtcbn07XG5cbnZhciBfbWVzc2FnZSA9IGZ1bmN0aW9uICggZHQsIG9wdGlvbiwgcG9zaXRpb24gKVxue1xuXHR2YXIgbWVzc2FnZSA9IF9zdHJpbmdPckZ1bmN0aW9uKCBvcHRpb24gKTtcblx0aWYgKCBtZXNzYWdlID09PSBudWxsICkge1xuXHRcdHJldHVybiBudWxsO1xuXHR9XG5cblx0dmFyIGNhcHRpb24gPSAkKCdjYXB0aW9uJywgZHQudGFibGUoKS5jb250YWluZXIoKSkuZXEoMCk7XG5cdGlmICggbWVzc2FnZSA9PT0gJyonICkge1xuXHRcdHZhciBzaWRlID0gY2FwdGlvbi5jc3MoICdjYXB0aW9uLXNpZGUnICk7XG5cdFx0aWYgKCBzaWRlICE9PSBwb3NpdGlvbiApIHtcblx0XHRcdHJldHVybiBudWxsO1xuXHRcdH1cblxuXHRcdHJldHVybiBjYXB0aW9uLmxlbmd0aCA/XG5cdFx0XHRjYXB0aW9uLnRleHQoKSA6XG5cdFx0XHQnJztcblx0fVxuXG5cdHJldHVybiBtZXNzYWdlO1xufTtcblxuXG5cblxudmFyIF9leHBvcnRUZXh0YXJlYSA9ICQoJzx0ZXh0YXJlYS8+JylbMF07XG52YXIgX2V4cG9ydERhdGEgPSBmdW5jdGlvbiAoIGR0LCBpbk9wdHMgKVxue1xuXHR2YXIgY29uZmlnID0gJC5leHRlbmQoIHRydWUsIHt9LCB7XG5cdFx0cm93czogICAgICAgICAgIG51bGwsXG5cdFx0Y29sdW1uczogICAgICAgICcnLFxuXHRcdG1vZGlmaWVyOiAgICAgICB7XG5cdFx0XHRzZWFyY2g6ICdhcHBsaWVkJyxcblx0XHRcdG9yZGVyOiAgJ2FwcGxpZWQnXG5cdFx0fSxcblx0XHRvcnRob2dvbmFsOiAgICAgJ2Rpc3BsYXknLFxuXHRcdHN0cmlwSHRtbDogICAgICB0cnVlLFxuXHRcdHN0cmlwTmV3bGluZXM6ICB0cnVlLFxuXHRcdGRlY29kZUVudGl0aWVzOiB0cnVlLFxuXHRcdHRyaW06ICAgICAgICAgICB0cnVlLFxuXHRcdGZvcm1hdDogICAgICAgICB7XG5cdFx0XHRoZWFkZXI6IGZ1bmN0aW9uICggZCApIHtcblx0XHRcdFx0cmV0dXJuIEJ1dHRvbnMuc3RyaXBEYXRhKCBkLCBjb25maWcgKTtcblx0XHRcdH0sXG5cdFx0XHRmb290ZXI6IGZ1bmN0aW9uICggZCApIHtcblx0XHRcdFx0cmV0dXJuIEJ1dHRvbnMuc3RyaXBEYXRhKCBkLCBjb25maWcgKTtcblx0XHRcdH0sXG5cdFx0XHRib2R5OiBmdW5jdGlvbiAoIGQgKSB7XG5cdFx0XHRcdHJldHVybiBCdXR0b25zLnN0cmlwRGF0YSggZCwgY29uZmlnICk7XG5cdFx0XHR9XG5cdFx0fSxcblx0XHRjdXN0b21pemVEYXRhOiBudWxsXG5cdH0sIGluT3B0cyApO1xuXG5cdHZhciBoZWFkZXIgPSBkdC5jb2x1bW5zKCBjb25maWcuY29sdW1ucyApLmluZGV4ZXMoKS5tYXAoIGZ1bmN0aW9uIChpZHgpIHtcblx0XHR2YXIgZWwgPSBkdC5jb2x1bW4oIGlkeCApLmhlYWRlcigpO1xuXHRcdHJldHVybiBjb25maWcuZm9ybWF0LmhlYWRlciggZWwuaW5uZXJIVE1MLCBpZHgsIGVsICk7XG5cdH0gKS50b0FycmF5KCk7XG5cblx0dmFyIGZvb3RlciA9IGR0LnRhYmxlKCkuZm9vdGVyKCkgP1xuXHRcdGR0LmNvbHVtbnMoIGNvbmZpZy5jb2x1bW5zICkuaW5kZXhlcygpLm1hcCggZnVuY3Rpb24gKGlkeCkge1xuXHRcdFx0dmFyIGVsID0gZHQuY29sdW1uKCBpZHggKS5mb290ZXIoKTtcblx0XHRcdHJldHVybiBjb25maWcuZm9ybWF0LmZvb3RlciggZWwgPyBlbC5pbm5lckhUTUwgOiAnJywgaWR4LCBlbCApO1xuXHRcdH0gKS50b0FycmF5KCkgOlxuXHRcdG51bGw7XG5cdFxuXHQvLyBJZiBTZWxlY3QgaXMgYXZhaWxhYmxlIG9uIHRoaXMgdGFibGUsIGFuZCBhbnkgcm93cyBhcmUgc2VsZWN0ZWQsIGxpbWl0IHRoZSBleHBvcnRcblx0Ly8gdG8gdGhlIHNlbGVjdGVkIHJvd3MuIElmIG5vIHJvd3MgYXJlIHNlbGVjdGVkLCBhbGwgcm93cyB3aWxsIGJlIGV4cG9ydGVkLiBTcGVjaWZ5XG5cdC8vIGEgYHNlbGVjdGVkYCBtb2RpZmllciB0byBjb250cm9sIGRpcmVjdGx5LlxuXHR2YXIgbW9kaWZpZXIgPSAkLmV4dGVuZCgge30sIGNvbmZpZy5tb2RpZmllciApO1xuXHRpZiAoIGR0LnNlbGVjdCAmJiB0eXBlb2YgZHQuc2VsZWN0LmluZm8gPT09ICdmdW5jdGlvbicgJiYgbW9kaWZpZXIuc2VsZWN0ZWQgPT09IHVuZGVmaW5lZCApIHtcblx0XHRpZiAoIGR0LnJvd3MoIGNvbmZpZy5yb3dzLCAkLmV4dGVuZCggeyBzZWxlY3RlZDogdHJ1ZSB9LCBtb2RpZmllciApICkuYW55KCkgKSB7XG5cdFx0XHQkLmV4dGVuZCggbW9kaWZpZXIsIHsgc2VsZWN0ZWQ6IHRydWUgfSApXG5cdFx0fVxuXHR9XG5cblx0dmFyIHJvd0luZGV4ZXMgPSBkdC5yb3dzKCBjb25maWcucm93cywgbW9kaWZpZXIgKS5pbmRleGVzKCkudG9BcnJheSgpO1xuXHR2YXIgc2VsZWN0ZWRDZWxscyA9IGR0LmNlbGxzKCByb3dJbmRleGVzLCBjb25maWcuY29sdW1ucyApO1xuXHR2YXIgY2VsbHMgPSBzZWxlY3RlZENlbGxzXG5cdFx0LnJlbmRlciggY29uZmlnLm9ydGhvZ29uYWwgKVxuXHRcdC50b0FycmF5KCk7XG5cdHZhciBjZWxsTm9kZXMgPSBzZWxlY3RlZENlbGxzXG5cdFx0Lm5vZGVzKClcblx0XHQudG9BcnJheSgpO1xuXG5cdHZhciBjb2x1bW5zID0gaGVhZGVyLmxlbmd0aDtcblx0dmFyIHJvd3MgPSBjb2x1bW5zID4gMCA/IGNlbGxzLmxlbmd0aCAvIGNvbHVtbnMgOiAwO1xuXHR2YXIgYm9keSA9IFtdO1xuXHR2YXIgY2VsbENvdW50ZXIgPSAwO1xuXG5cdGZvciAoIHZhciBpPTAsIGllbj1yb3dzIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0dmFyIHJvdyA9IFsgY29sdW1ucyBdO1xuXG5cdFx0Zm9yICggdmFyIGo9MCA7IGo8Y29sdW1ucyA7IGorKyApIHtcblx0XHRcdHJvd1tqXSA9IGNvbmZpZy5mb3JtYXQuYm9keSggY2VsbHNbIGNlbGxDb3VudGVyIF0sIGksIGosIGNlbGxOb2Rlc1sgY2VsbENvdW50ZXIgXSApO1xuXHRcdFx0Y2VsbENvdW50ZXIrKztcblx0XHR9XG5cblx0XHRib2R5W2ldID0gcm93O1xuXHR9XG5cblx0dmFyIGRhdGEgPSB7XG5cdFx0aGVhZGVyOiBoZWFkZXIsXG5cdFx0Zm9vdGVyOiBmb290ZXIsXG5cdFx0Ym9keTogICBib2R5XG5cdH07XG5cblx0aWYgKCBjb25maWcuY3VzdG9taXplRGF0YSApIHtcblx0XHRjb25maWcuY3VzdG9taXplRGF0YSggZGF0YSApO1xuXHR9XG5cblx0cmV0dXJuIGRhdGE7XG59O1xuXG5cbi8qICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqXG4gKiBEYXRhVGFibGVzIGludGVyZmFjZVxuICovXG5cbi8vIEF0dGFjaCB0byBEYXRhVGFibGVzIG9iamVjdHMgZm9yIGdsb2JhbCBhY2Nlc3NcbiQuZm4uZGF0YVRhYmxlLkJ1dHRvbnMgPSBCdXR0b25zO1xuJC5mbi5EYXRhVGFibGUuQnV0dG9ucyA9IEJ1dHRvbnM7XG5cblxuXG4vLyBEYXRhVGFibGVzIGNyZWF0aW9uIC0gY2hlY2sgaWYgdGhlIGJ1dHRvbnMgaGF2ZSBiZWVuIGRlZmluZWQgZm9yIHRoaXMgdGFibGUsXG4vLyB0aGV5IHdpbGwgaGF2ZSBiZWVuIGlmIHRoZSBgQmAgb3B0aW9uIHdhcyB1c2VkIGluIGBkb21gLCBvdGhlcndpc2Ugd2Ugc2hvdWxkXG4vLyBjcmVhdGUgdGhlIGJ1dHRvbnMgaW5zdGFuY2UgaGVyZSBzbyB0aGV5IGNhbiBiZSBpbnNlcnRlZCBpbnRvIHRoZSBkb2N1bWVudFxuLy8gdXNpbmcgdGhlIEFQSS4gTGlzdGVuIGZvciBgaW5pdGAgZm9yIGNvbXBhdGliaWxpdHkgd2l0aCBwcmUgMS4xMC4xMCwgYnV0IHRvXG4vLyBiZSByZW1vdmVkIGluIGZ1dHVyZS5cbiQoZG9jdW1lbnQpLm9uKCAnaW5pdC5kdCBwbHVnaW4taW5pdC5kdCcsIGZ1bmN0aW9uIChlLCBzZXR0aW5ncykge1xuXHRpZiAoIGUubmFtZXNwYWNlICE9PSAnZHQnICkge1xuXHRcdHJldHVybjtcblx0fVxuXG5cdHZhciBvcHRzID0gc2V0dGluZ3Mub0luaXQuYnV0dG9ucyB8fCBEYXRhVGFibGUuZGVmYXVsdHMuYnV0dG9ucztcblxuXHRpZiAoIG9wdHMgJiYgISBzZXR0aW5ncy5fYnV0dG9ucyApIHtcblx0XHRuZXcgQnV0dG9ucyggc2V0dGluZ3MsIG9wdHMgKS5jb250YWluZXIoKTtcblx0fVxufSApO1xuXG5mdW5jdGlvbiBfaW5pdCAoIHNldHRpbmdzLCBvcHRpb25zICkge1xuXHR2YXIgYXBpID0gbmV3IERhdGFUYWJsZS5BcGkoIHNldHRpbmdzICk7XG5cdHZhciBvcHRzID0gb3B0aW9uc1xuXHRcdD8gb3B0aW9uc1xuXHRcdDogYXBpLmluaXQoKS5idXR0b25zIHx8IERhdGFUYWJsZS5kZWZhdWx0cy5idXR0b25zO1xuXG5cdHJldHVybiBuZXcgQnV0dG9ucyggYXBpLCBvcHRzICkuY29udGFpbmVyKCk7XG59XG5cbi8vIERhdGFUYWJsZXMgYGRvbWAgZmVhdHVyZSBvcHRpb25cbkRhdGFUYWJsZS5leHQuZmVhdHVyZS5wdXNoKCB7XG5cdGZuSW5pdDogX2luaXQsXG5cdGNGZWF0dXJlOiBcIkJcIlxufSApO1xuXG4vLyBEYXRhVGFibGVzIDIgbGF5b3V0IGZlYXR1cmVcbmlmICggRGF0YVRhYmxlLmV4dC5mZWF0dXJlcyApIHtcblx0RGF0YVRhYmxlLmV4dC5mZWF0dXJlcy5yZWdpc3RlciggJ2J1dHRvbnMnLCBfaW5pdCApO1xufVxuXG5cbnJldHVybiBCdXR0b25zO1xufSkpO1xuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/datatables.net-buttons/js/dataTables.buttons.js\n"); /***/ }), /***/ "datatables.net": /*!*********************************!*\ !*** external "$.fn.dataTable" ***! \*********************************/ /***/ (function(module) { "use strict"; module.exports = window["$.fn.dataTable"]; /***/ }), /***/ "jquery": /*!*************************!*\ !*** external "jQuery" ***! \*************************/ /***/ (function(module) { "use strict"; module.exports = window["jQuery"]; /***/ }) /******/ }); /************************************************************************/ /******/ // The module cache /******/ var __webpack_module_cache__ = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ var cachedModule = __webpack_module_cache__[moduleId]; /******/ if (cachedModule !== undefined) { /******/ return cachedModule.exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = __webpack_module_cache__[moduleId] = { /******/ // no module.id needed /******/ // no module.loaded needed /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /************************************************************************/ /******/ /* webpack/runtime/compat get default export */ /******/ !function() { /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function() { return module['default']; } : /******/ function() { return module; }; /******/ __webpack_require__.d(getter, { a: getter }); /******/ return getter; /******/ }; /******/ }(); /******/ /******/ /* webpack/runtime/define property getters */ /******/ !function() { /******/ // define getter functions for harmony exports /******/ __webpack_require__.d = function(exports, definition) { /******/ for(var key in definition) { /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); /******/ } /******/ } /******/ }; /******/ }(); /******/ /******/ /* webpack/runtime/hasOwnProperty shorthand */ /******/ !function() { /******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } /******/ }(); /******/ /******/ /* webpack/runtime/make namespace object */ /******/ !function() { /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ }(); /******/ /************************************************************************/ /******/ /******/ // startup /******/ // Load entry module and return exports /******/ // This entry module can't be inlined because the eval-source-map devtool is used. /******/ var __webpack_exports__ = __webpack_require__("./libs/datatables-buttons/buttons.print.js"); /******/ var __webpack_export_target__ = window; /******/ for(var i in __webpack_exports__) __webpack_export_target__[i] = __webpack_exports__[i]; /******/ if(__webpack_exports__.__esModule) Object.defineProperty(__webpack_export_target__, "__esModule", { value: true }); /******/ /******/ })() ;
SIMPAN PERUBAHAN