From 0fdb038c6ce085f80e08403e837e340a7da3ad17 Mon Sep 17 00:00:00 2001 From: Kevin Chung Date: Mon, 22 Mar 2021 20:32:37 -0400 Subject: [PATCH] Use new properties in /api/v1/challenges (#1844) - Switch the challenges page in core to use the new API information in `/api/v1/challenges` to mark solves and display solve counts - Closes #1811 --- CHANGELOG.md | 1 + .../themes/core/assets/js/pages/challenges.js | 33 +++---------------- .../core/static/js/pages/challenges.dev.js | 2 +- .../core/static/js/pages/challenges.min.js | 2 +- 4 files changed, 7 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b2a6e2b..2a91c574 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ - Add styling for the `
` element. - Change `colorHash` function to use HSL color values to avoid generating too light/dark colors - Fix scoreboard table identifier to switch between User/Team depending on configured user mode +- Switch the challenges page in core to use the new API information in `/api/v1/challenges` to mark solves and display solve counts - Switch to using Bootstrap's scss in `core/main.scss` to allow using Bootstrap variables - Consolidate Jinja error handlers into a single function and better handle issues where error templates can't be found diff --git a/CTFd/themes/core/assets/js/pages/challenges.js b/CTFd/themes/core/assets/js/pages/challenges.js index 9d100597..7148659c 100644 --- a/CTFd/themes/core/assets/js/pages/challenges.js +++ b/CTFd/themes/core/assets/js/pages/challenges.js @@ -11,11 +11,6 @@ import hljs from "highlight.js"; dayjs.extend(relativeTime); -const api_func = { - teams: x => CTFd.api.get_team_solves({ teamId: x }), - users: x => CTFd.api.get_user_solves({ userId: x }) -}; - CTFd._internal.challenge = {}; let challenges = []; let solves = []; @@ -232,31 +227,15 @@ function renderSubmissionResponse(response) { } function markSolves() { - return api_func[CTFd.config.userMode]("me").then(function(response) { - const solves = response.data; - for (let i = solves.length - 1; i >= 0; i--) { - const btn = $('button[value="' + solves[i].challenge_id + '"]'); + challenges.map(challenge => { + if (challenge.solved_by_me) { + const btn = $(`button[value="${challenge.id}"]`); btn.addClass("solved-challenge"); btn.prepend(""); } }); } -function loadUserSolves() { - if (CTFd.user.id == 0) { - return Promise.resolve(); - } - - return api_func[CTFd.config.userMode]("me").then(function(response) { - const solves = response.data; - - for (let i = solves.length - 1; i >= 0; i--) { - const chal_id = solves[i].challenge_id; - solves.push(chal_id); - } - }); -} - function getSolves(id) { return CTFd.api.get_challenge_solves({ challengeId: id }).then(response => { const data = response.data; @@ -289,7 +268,6 @@ function loadChals() { $challenges_board.empty(); for (let i = challenges.length - 1; i >= 0; i--) { - challenges[i].solves = 0; if ($.inArray(challenges[i].category, categories) == -1) { const category = challenges[i].category; categories.push(category); @@ -354,15 +332,12 @@ function loadChals() { $(".challenge-button").click(function(_event) { loadChal(this.value); - getSolves(this.value); }); }); } function update() { - return loadUserSolves() // Load the user's solved challenge ids - .then(loadChals) // Load the full list of challenges - .then(markSolves); + return loadChals().then(markSolves); } $(() => { diff --git a/CTFd/themes/core/static/js/pages/challenges.dev.js b/CTFd/themes/core/static/js/pages/challenges.dev.js index b2405449..759f048d 100644 --- a/CTFd/themes/core/static/js/pages/challenges.dev.js +++ b/CTFd/themes/core/static/js/pages/challenges.dev.js @@ -162,7 +162,7 @@ /***/ (function(module, exports, __webpack_require__) { ; -eval("\n\n__webpack_require__(/*! ./main */ \"./CTFd/themes/core/assets/js/pages/main.js\");\n\n__webpack_require__(/*! bootstrap/js/dist/tab */ \"./node_modules/bootstrap/js/dist/tab.js\");\n\nvar _ezq = __webpack_require__(/*! ../ezq */ \"./CTFd/themes/core/assets/js/ezq.js\");\n\nvar _utils = __webpack_require__(/*! ../utils */ \"./CTFd/themes/core/assets/js/utils.js\");\n\nvar _dayjs = _interopRequireDefault(__webpack_require__(/*! dayjs */ \"./node_modules/dayjs/dayjs.min.js\"));\n\nvar _relativeTime = _interopRequireDefault(__webpack_require__(/*! dayjs/plugin/relativeTime */ \"./node_modules/dayjs/plugin/relativeTime.js\"));\n\nvar _jquery = _interopRequireDefault(__webpack_require__(/*! jquery */ \"./node_modules/jquery/dist/jquery.js\"));\n\nvar _CTFd = _interopRequireDefault(__webpack_require__(/*! ../CTFd */ \"./CTFd/themes/core/assets/js/CTFd.js\"));\n\nvar _config = _interopRequireDefault(__webpack_require__(/*! ../config */ \"./CTFd/themes/core/assets/js/config.js\"));\n\nvar _highlight = _interopRequireDefault(__webpack_require__(/*! highlight.js */ \"./node_modules/highlight.js/lib/index.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { \"default\": obj }; }\n\n_dayjs[\"default\"].extend(_relativeTime[\"default\"]);\n\nvar api_func = {\n teams: function teams(x) {\n return _CTFd[\"default\"].api.get_team_solves({\n teamId: x\n });\n },\n users: function users(x) {\n return _CTFd[\"default\"].api.get_user_solves({\n userId: x\n });\n }\n};\n_CTFd[\"default\"]._internal.challenge = {};\nvar challenges = [];\nvar solves = [];\n\nvar loadChal = function loadChal(id) {\n var chal = _jquery[\"default\"].grep(challenges, function (chal) {\n return chal.id == id;\n })[0];\n\n if (chal.type === \"hidden\") {\n (0, _ezq.ezAlert)({\n title: \"Challenge Hidden!\",\n body: \"You haven't unlocked this challenge yet!\",\n button: \"Got it!\"\n });\n return;\n }\n\n displayChal(chal);\n};\n\nvar loadChalByName = function loadChalByName(name) {\n var idx = name.lastIndexOf(\"-\");\n var pieces = [name.slice(0, idx), name.slice(idx + 1)];\n var id = pieces[1];\n\n var chal = _jquery[\"default\"].grep(challenges, function (chal) {\n return chal.id == id;\n })[0];\n\n displayChal(chal);\n};\n\nvar displayChal = function displayChal(chal) {\n return Promise.all([_CTFd[\"default\"].api.get_challenge({\n challengeId: chal.id\n }), _jquery[\"default\"].getScript(_config[\"default\"].urlRoot + chal.script), _jquery[\"default\"].get(_config[\"default\"].urlRoot + chal.template)]).then(function (responses) {\n var challenge = _CTFd[\"default\"]._internal.challenge;\n (0, _jquery[\"default\"])(\"#challenge-window\").empty(); // Inject challenge data into the plugin\n\n challenge.data = responses[0].data; // Call preRender function in plugin\n\n challenge.preRender(); // Build HTML from the Jinja response in API\n\n (0, _jquery[\"default\"])(\"#challenge-window\").append(responses[0].data.view);\n (0, _jquery[\"default\"])(\"#challenge-window #challenge-input\").addClass(\"form-control\");\n (0, _jquery[\"default\"])(\"#challenge-window #challenge-submit\").addClass(\"btn btn-md btn-outline-secondary float-right\");\n var modal = (0, _jquery[\"default\"])(\"#challenge-window\").find(\".modal-dialog\");\n\n if (window.init.theme_settings && window.init.theme_settings.challenge_window_size) {\n switch (window.init.theme_settings.challenge_window_size) {\n case \"sm\":\n modal.addClass(\"modal-sm\");\n break;\n\n case \"lg\":\n modal.addClass(\"modal-lg\");\n break;\n\n case \"xl\":\n modal.addClass(\"modal-xl\");\n break;\n\n default:\n break;\n }\n }\n\n (0, _jquery[\"default\"])(\".challenge-solves\").click(function (_event) {\n getSolves((0, _jquery[\"default\"])(\"#challenge-id\").val());\n });\n (0, _jquery[\"default\"])(\".nav-tabs a\").click(function (event) {\n event.preventDefault();\n (0, _jquery[\"default\"])(this).tab(\"show\");\n }); // Handle modal toggling\n\n (0, _jquery[\"default\"])(\"#challenge-window\").on(\"hide.bs.modal\", function (_event) {\n (0, _jquery[\"default\"])(\"#challenge-input\").removeClass(\"wrong\");\n (0, _jquery[\"default\"])(\"#challenge-input\").removeClass(\"correct\");\n (0, _jquery[\"default\"])(\"#incorrect-key\").slideUp();\n (0, _jquery[\"default\"])(\"#correct-key\").slideUp();\n (0, _jquery[\"default\"])(\"#already-solved\").slideUp();\n (0, _jquery[\"default\"])(\"#too-fast\").slideUp();\n });\n (0, _jquery[\"default\"])(\".load-hint\").on(\"click\", function (_event) {\n loadHint((0, _jquery[\"default\"])(this).data(\"hint-id\"));\n });\n (0, _jquery[\"default\"])(\"#challenge-submit\").click(function (event) {\n event.preventDefault();\n (0, _jquery[\"default\"])(\"#challenge-submit\").addClass(\"disabled-button\");\n (0, _jquery[\"default\"])(\"#challenge-submit\").prop(\"disabled\", true);\n\n _CTFd[\"default\"]._internal.challenge.submit().then(renderSubmissionResponse).then(loadChals).then(markSolves);\n });\n (0, _jquery[\"default\"])(\"#challenge-input\").keyup(function (event) {\n if (event.keyCode == 13) {\n (0, _jquery[\"default\"])(\"#challenge-submit\").click();\n }\n });\n challenge.postRender();\n (0, _jquery[\"default\"])(\"#challenge-window\").find(\"pre code\").each(function (_idx) {\n _highlight[\"default\"].highlightBlock(this);\n });\n window.location.replace(window.location.href.split(\"#\")[0] + \"#\".concat(chal.name, \"-\").concat(chal.id));\n (0, _jquery[\"default\"])(\"#challenge-window\").modal();\n });\n};\n\nfunction renderSubmissionResponse(response) {\n var result = response.data;\n var result_message = (0, _jquery[\"default\"])(\"#result-message\");\n var result_notification = (0, _jquery[\"default\"])(\"#result-notification\");\n var answer_input = (0, _jquery[\"default\"])(\"#challenge-input\");\n result_notification.removeClass();\n result_message.text(result.message);\n\n if (result.status === \"authentication_required\") {\n window.location = _CTFd[\"default\"].config.urlRoot + \"/login?next=\" + _CTFd[\"default\"].config.urlRoot + window.location.pathname + window.location.hash;\n return;\n } else if (result.status === \"incorrect\") {\n // Incorrect key\n result_notification.addClass(\"alert alert-danger alert-dismissable text-center\");\n result_notification.slideDown();\n answer_input.removeClass(\"correct\");\n answer_input.addClass(\"wrong\");\n setTimeout(function () {\n answer_input.removeClass(\"wrong\");\n }, 3000);\n } else if (result.status === \"correct\") {\n // Challenge Solved\n result_notification.addClass(\"alert alert-success alert-dismissable text-center\");\n result_notification.slideDown();\n\n if ((0, _jquery[\"default\"])(\".challenge-solves\").text().trim()) {\n // Only try to increment solves if the text isn't hidden\n (0, _jquery[\"default\"])(\".challenge-solves\").text(parseInt((0, _jquery[\"default\"])(\".challenge-solves\").text().split(\" \")[0]) + 1 + \" Solves\");\n }\n\n answer_input.val(\"\");\n answer_input.removeClass(\"wrong\");\n answer_input.addClass(\"correct\");\n } else if (result.status === \"already_solved\") {\n // Challenge already solved\n result_notification.addClass(\"alert alert-info alert-dismissable text-center\");\n result_notification.slideDown();\n answer_input.addClass(\"correct\");\n } else if (result.status === \"paused\") {\n // CTF is paused\n result_notification.addClass(\"alert alert-warning alert-dismissable text-center\");\n result_notification.slideDown();\n } else if (result.status === \"ratelimited\") {\n // Keys per minute too high\n result_notification.addClass(\"alert alert-warning alert-dismissable text-center\");\n result_notification.slideDown();\n answer_input.addClass(\"too-fast\");\n setTimeout(function () {\n answer_input.removeClass(\"too-fast\");\n }, 3000);\n }\n\n setTimeout(function () {\n (0, _jquery[\"default\"])(\".alert\").slideUp();\n (0, _jquery[\"default\"])(\"#challenge-submit\").removeClass(\"disabled-button\");\n (0, _jquery[\"default\"])(\"#challenge-submit\").prop(\"disabled\", false);\n }, 3000);\n}\n\nfunction markSolves() {\n return api_func[_CTFd[\"default\"].config.userMode](\"me\").then(function (response) {\n var solves = response.data;\n\n for (var i = solves.length - 1; i >= 0; i--) {\n var btn = (0, _jquery[\"default\"])('button[value=\"' + solves[i].challenge_id + '\"]');\n btn.addClass(\"solved-challenge\");\n btn.prepend(\"\");\n }\n });\n}\n\nfunction loadUserSolves() {\n if (_CTFd[\"default\"].user.id == 0) {\n return Promise.resolve();\n }\n\n return api_func[_CTFd[\"default\"].config.userMode](\"me\").then(function (response) {\n var solves = response.data;\n\n for (var i = solves.length - 1; i >= 0; i--) {\n var chal_id = solves[i].challenge_id;\n solves.push(chal_id);\n }\n });\n}\n\nfunction getSolves(id) {\n return _CTFd[\"default\"].api.get_challenge_solves({\n challengeId: id\n }).then(function (response) {\n var data = response.data;\n (0, _jquery[\"default\"])(\".challenge-solves\").text(parseInt(data.length) + \" Solves\");\n var box = (0, _jquery[\"default\"])(\"#challenge-solves-names\");\n box.empty();\n\n for (var i = 0; i < data.length; i++) {\n var _id = data[i].account_id;\n var name = data[i].name;\n var date = (0, _dayjs[\"default\"])(data[i].date).fromNow();\n var account_url = data[i].account_url;\n box.append('{2}{3}'.format(account_url, _id, (0, _utils.htmlEntities)(name), date));\n }\n });\n}\n\nfunction loadChals() {\n return _CTFd[\"default\"].api.get_challenge_list().then(function (response) {\n var categories = [];\n var $challenges_board = (0, _jquery[\"default\"])(\"#challenges-board\");\n challenges = response.data;\n $challenges_board.empty();\n\n for (var i = challenges.length - 1; i >= 0; i--) {\n challenges[i].solves = 0;\n\n if (_jquery[\"default\"].inArray(challenges[i].category, categories) == -1) {\n var category = challenges[i].category;\n categories.push(category);\n var categoryid = category.replace(/ /g, \"-\").hashCode();\n var categoryrow = (0, _jquery[\"default\"])(\"\" + '
'.format(categoryid) + '
' + \"
\" + '
' + '
' + \"
\" + \"
\");\n categoryrow.find(\".category-header\").append((0, _jquery[\"default\"])(\"

\" + category + \"

\"));\n $challenges_board.append(categoryrow);\n }\n }\n\n for (var _i = 0; _i <= challenges.length - 1; _i++) {\n var chalinfo = challenges[_i];\n var chalid = chalinfo.name.replace(/ /g, \"-\").hashCode();\n var catid = chalinfo.category.replace(/ /g, \"-\").hashCode();\n var chalwrap = (0, _jquery[\"default\"])(\"
\".format(chalid));\n var chalbutton = void 0;\n\n if (solves.indexOf(chalinfo.id) == -1) {\n chalbutton = (0, _jquery[\"default\"])(\"\".format(chalinfo.id));\n } else {\n chalbutton = (0, _jquery[\"default\"])(\"\".format(chalinfo.id));\n }\n\n var chalheader = (0, _jquery[\"default\"])(\"

{0}

\".format(chalinfo.name));\n var chalscore = (0, _jquery[\"default\"])(\"{0}\".format(chalinfo.value));\n\n for (var j = 0; j < chalinfo.tags.length; j++) {\n var tag = \"tag-\" + chalinfo.tags[j].value.replace(/ /g, \"-\");\n chalwrap.addClass(tag);\n }\n\n chalbutton.append(chalheader);\n chalbutton.append(chalscore);\n chalwrap.append(chalbutton);\n (0, _jquery[\"default\"])(\"#\" + catid + \"-row\").find(\".category-challenges > .challenges-row\").append(chalwrap);\n }\n\n (0, _jquery[\"default\"])(\".challenge-button\").click(function (_event) {\n loadChal(this.value);\n getSolves(this.value);\n });\n });\n}\n\nfunction update() {\n return loadUserSolves() // Load the user's solved challenge ids\n .then(loadChals) // Load the full list of challenges\n .then(markSolves);\n}\n\n(0, _jquery[\"default\"])(function () {\n update().then(function () {\n if (window.location.hash.length > 0) {\n loadChalByName(decodeURIComponent(window.location.hash.substring(1)));\n }\n });\n (0, _jquery[\"default\"])(\"#challenge-input\").keyup(function (event) {\n if (event.keyCode == 13) {\n (0, _jquery[\"default\"])(\"#challenge-submit\").click();\n }\n });\n (0, _jquery[\"default\"])(\".nav-tabs a\").click(function (event) {\n event.preventDefault();\n (0, _jquery[\"default\"])(this).tab(\"show\");\n });\n (0, _jquery[\"default\"])(\"#challenge-window\").on(\"hidden.bs.modal\", function (_event) {\n (0, _jquery[\"default\"])(\".nav-tabs a:first\").tab(\"show\");\n history.replaceState(\"\", window.document.title, window.location.pathname);\n });\n (0, _jquery[\"default\"])(\".challenge-solves\").click(function (_event) {\n getSolves((0, _jquery[\"default\"])(\"#challenge-id\").val());\n });\n (0, _jquery[\"default\"])(\"#challenge-window\").on(\"hide.bs.modal\", function (_event) {\n (0, _jquery[\"default\"])(\"#challenge-input\").removeClass(\"wrong\");\n (0, _jquery[\"default\"])(\"#challenge-input\").removeClass(\"correct\");\n (0, _jquery[\"default\"])(\"#incorrect-key\").slideUp();\n (0, _jquery[\"default\"])(\"#correct-key\").slideUp();\n (0, _jquery[\"default\"])(\"#already-solved\").slideUp();\n (0, _jquery[\"default\"])(\"#too-fast\").slideUp();\n });\n});\nsetInterval(update, 300000); // Update every 5 minutes.\n\nvar displayHint = function displayHint(data) {\n (0, _ezq.ezAlert)({\n title: \"Hint\",\n body: data.html,\n button: \"Got it!\"\n });\n};\n\nvar displayUnlock = function displayUnlock(id) {\n (0, _ezq.ezQuery)({\n title: \"Unlock Hint?\",\n body: \"Are you sure you want to open this hint?\",\n success: function success() {\n var params = {\n target: id,\n type: \"hints\"\n };\n\n _CTFd[\"default\"].api.post_unlock_list({}, params).then(function (response) {\n if (response.success) {\n _CTFd[\"default\"].api.get_hint({\n hintId: id\n }).then(function (response) {\n displayHint(response.data);\n });\n\n return;\n }\n\n (0, _ezq.ezAlert)({\n title: \"Error\",\n body: response.errors.score,\n button: \"Got it!\"\n });\n });\n }\n });\n};\n\nvar loadHint = function loadHint(id) {\n _CTFd[\"default\"].api.get_hint({\n hintId: id\n }).then(function (response) {\n if (response.data.content) {\n displayHint(response.data);\n return;\n }\n\n displayUnlock(id);\n });\n};\n\n//# sourceURL=webpack:///./CTFd/themes/core/assets/js/pages/challenges.js?"); +eval("\n\n__webpack_require__(/*! ./main */ \"./CTFd/themes/core/assets/js/pages/main.js\");\n\n__webpack_require__(/*! bootstrap/js/dist/tab */ \"./node_modules/bootstrap/js/dist/tab.js\");\n\nvar _ezq = __webpack_require__(/*! ../ezq */ \"./CTFd/themes/core/assets/js/ezq.js\");\n\nvar _utils = __webpack_require__(/*! ../utils */ \"./CTFd/themes/core/assets/js/utils.js\");\n\nvar _dayjs = _interopRequireDefault(__webpack_require__(/*! dayjs */ \"./node_modules/dayjs/dayjs.min.js\"));\n\nvar _relativeTime = _interopRequireDefault(__webpack_require__(/*! dayjs/plugin/relativeTime */ \"./node_modules/dayjs/plugin/relativeTime.js\"));\n\nvar _jquery = _interopRequireDefault(__webpack_require__(/*! jquery */ \"./node_modules/jquery/dist/jquery.js\"));\n\nvar _CTFd = _interopRequireDefault(__webpack_require__(/*! ../CTFd */ \"./CTFd/themes/core/assets/js/CTFd.js\"));\n\nvar _config = _interopRequireDefault(__webpack_require__(/*! ../config */ \"./CTFd/themes/core/assets/js/config.js\"));\n\nvar _highlight = _interopRequireDefault(__webpack_require__(/*! highlight.js */ \"./node_modules/highlight.js/lib/index.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { \"default\": obj }; }\n\n_dayjs[\"default\"].extend(_relativeTime[\"default\"]);\n\n_CTFd[\"default\"]._internal.challenge = {};\nvar challenges = [];\nvar solves = [];\n\nvar loadChal = function loadChal(id) {\n var chal = _jquery[\"default\"].grep(challenges, function (chal) {\n return chal.id == id;\n })[0];\n\n if (chal.type === \"hidden\") {\n (0, _ezq.ezAlert)({\n title: \"Challenge Hidden!\",\n body: \"You haven't unlocked this challenge yet!\",\n button: \"Got it!\"\n });\n return;\n }\n\n displayChal(chal);\n};\n\nvar loadChalByName = function loadChalByName(name) {\n var idx = name.lastIndexOf(\"-\");\n var pieces = [name.slice(0, idx), name.slice(idx + 1)];\n var id = pieces[1];\n\n var chal = _jquery[\"default\"].grep(challenges, function (chal) {\n return chal.id == id;\n })[0];\n\n displayChal(chal);\n};\n\nvar displayChal = function displayChal(chal) {\n return Promise.all([_CTFd[\"default\"].api.get_challenge({\n challengeId: chal.id\n }), _jquery[\"default\"].getScript(_config[\"default\"].urlRoot + chal.script), _jquery[\"default\"].get(_config[\"default\"].urlRoot + chal.template)]).then(function (responses) {\n var challenge = _CTFd[\"default\"]._internal.challenge;\n (0, _jquery[\"default\"])(\"#challenge-window\").empty(); // Inject challenge data into the plugin\n\n challenge.data = responses[0].data; // Call preRender function in plugin\n\n challenge.preRender(); // Build HTML from the Jinja response in API\n\n (0, _jquery[\"default\"])(\"#challenge-window\").append(responses[0].data.view);\n (0, _jquery[\"default\"])(\"#challenge-window #challenge-input\").addClass(\"form-control\");\n (0, _jquery[\"default\"])(\"#challenge-window #challenge-submit\").addClass(\"btn btn-md btn-outline-secondary float-right\");\n var modal = (0, _jquery[\"default\"])(\"#challenge-window\").find(\".modal-dialog\");\n\n if (window.init.theme_settings && window.init.theme_settings.challenge_window_size) {\n switch (window.init.theme_settings.challenge_window_size) {\n case \"sm\":\n modal.addClass(\"modal-sm\");\n break;\n\n case \"lg\":\n modal.addClass(\"modal-lg\");\n break;\n\n case \"xl\":\n modal.addClass(\"modal-xl\");\n break;\n\n default:\n break;\n }\n }\n\n (0, _jquery[\"default\"])(\".challenge-solves\").click(function (_event) {\n getSolves((0, _jquery[\"default\"])(\"#challenge-id\").val());\n });\n (0, _jquery[\"default\"])(\".nav-tabs a\").click(function (event) {\n event.preventDefault();\n (0, _jquery[\"default\"])(this).tab(\"show\");\n }); // Handle modal toggling\n\n (0, _jquery[\"default\"])(\"#challenge-window\").on(\"hide.bs.modal\", function (_event) {\n (0, _jquery[\"default\"])(\"#challenge-input\").removeClass(\"wrong\");\n (0, _jquery[\"default\"])(\"#challenge-input\").removeClass(\"correct\");\n (0, _jquery[\"default\"])(\"#incorrect-key\").slideUp();\n (0, _jquery[\"default\"])(\"#correct-key\").slideUp();\n (0, _jquery[\"default\"])(\"#already-solved\").slideUp();\n (0, _jquery[\"default\"])(\"#too-fast\").slideUp();\n });\n (0, _jquery[\"default\"])(\".load-hint\").on(\"click\", function (_event) {\n loadHint((0, _jquery[\"default\"])(this).data(\"hint-id\"));\n });\n (0, _jquery[\"default\"])(\"#challenge-submit\").click(function (event) {\n event.preventDefault();\n (0, _jquery[\"default\"])(\"#challenge-submit\").addClass(\"disabled-button\");\n (0, _jquery[\"default\"])(\"#challenge-submit\").prop(\"disabled\", true);\n\n _CTFd[\"default\"]._internal.challenge.submit().then(renderSubmissionResponse).then(loadChals).then(markSolves);\n });\n (0, _jquery[\"default\"])(\"#challenge-input\").keyup(function (event) {\n if (event.keyCode == 13) {\n (0, _jquery[\"default\"])(\"#challenge-submit\").click();\n }\n });\n challenge.postRender();\n (0, _jquery[\"default\"])(\"#challenge-window\").find(\"pre code\").each(function (_idx) {\n _highlight[\"default\"].highlightBlock(this);\n });\n window.location.replace(window.location.href.split(\"#\")[0] + \"#\".concat(chal.name, \"-\").concat(chal.id));\n (0, _jquery[\"default\"])(\"#challenge-window\").modal();\n });\n};\n\nfunction renderSubmissionResponse(response) {\n var result = response.data;\n var result_message = (0, _jquery[\"default\"])(\"#result-message\");\n var result_notification = (0, _jquery[\"default\"])(\"#result-notification\");\n var answer_input = (0, _jquery[\"default\"])(\"#challenge-input\");\n result_notification.removeClass();\n result_message.text(result.message);\n\n if (result.status === \"authentication_required\") {\n window.location = _CTFd[\"default\"].config.urlRoot + \"/login?next=\" + _CTFd[\"default\"].config.urlRoot + window.location.pathname + window.location.hash;\n return;\n } else if (result.status === \"incorrect\") {\n // Incorrect key\n result_notification.addClass(\"alert alert-danger alert-dismissable text-center\");\n result_notification.slideDown();\n answer_input.removeClass(\"correct\");\n answer_input.addClass(\"wrong\");\n setTimeout(function () {\n answer_input.removeClass(\"wrong\");\n }, 3000);\n } else if (result.status === \"correct\") {\n // Challenge Solved\n result_notification.addClass(\"alert alert-success alert-dismissable text-center\");\n result_notification.slideDown();\n\n if ((0, _jquery[\"default\"])(\".challenge-solves\").text().trim()) {\n // Only try to increment solves if the text isn't hidden\n (0, _jquery[\"default\"])(\".challenge-solves\").text(parseInt((0, _jquery[\"default\"])(\".challenge-solves\").text().split(\" \")[0]) + 1 + \" Solves\");\n }\n\n answer_input.val(\"\");\n answer_input.removeClass(\"wrong\");\n answer_input.addClass(\"correct\");\n } else if (result.status === \"already_solved\") {\n // Challenge already solved\n result_notification.addClass(\"alert alert-info alert-dismissable text-center\");\n result_notification.slideDown();\n answer_input.addClass(\"correct\");\n } else if (result.status === \"paused\") {\n // CTF is paused\n result_notification.addClass(\"alert alert-warning alert-dismissable text-center\");\n result_notification.slideDown();\n } else if (result.status === \"ratelimited\") {\n // Keys per minute too high\n result_notification.addClass(\"alert alert-warning alert-dismissable text-center\");\n result_notification.slideDown();\n answer_input.addClass(\"too-fast\");\n setTimeout(function () {\n answer_input.removeClass(\"too-fast\");\n }, 3000);\n }\n\n setTimeout(function () {\n (0, _jquery[\"default\"])(\".alert\").slideUp();\n (0, _jquery[\"default\"])(\"#challenge-submit\").removeClass(\"disabled-button\");\n (0, _jquery[\"default\"])(\"#challenge-submit\").prop(\"disabled\", false);\n }, 3000);\n}\n\nfunction markSolves() {\n challenges.map(function (challenge) {\n if (challenge.solved_by_me) {\n var btn = (0, _jquery[\"default\"])(\"button[value=\\\"\".concat(challenge.id, \"\\\"]\"));\n btn.addClass(\"solved-challenge\");\n btn.prepend(\"\");\n }\n });\n}\n\nfunction getSolves(id) {\n return _CTFd[\"default\"].api.get_challenge_solves({\n challengeId: id\n }).then(function (response) {\n var data = response.data;\n (0, _jquery[\"default\"])(\".challenge-solves\").text(parseInt(data.length) + \" Solves\");\n var box = (0, _jquery[\"default\"])(\"#challenge-solves-names\");\n box.empty();\n\n for (var i = 0; i < data.length; i++) {\n var _id = data[i].account_id;\n var name = data[i].name;\n var date = (0, _dayjs[\"default\"])(data[i].date).fromNow();\n var account_url = data[i].account_url;\n box.append('
{2}{3}'.format(account_url, _id, (0, _utils.htmlEntities)(name), date));\n }\n });\n}\n\nfunction loadChals() {\n return _CTFd[\"default\"].api.get_challenge_list().then(function (response) {\n var categories = [];\n var $challenges_board = (0, _jquery[\"default\"])(\"#challenges-board\");\n challenges = response.data;\n $challenges_board.empty();\n\n for (var i = challenges.length - 1; i >= 0; i--) {\n if (_jquery[\"default\"].inArray(challenges[i].category, categories) == -1) {\n var category = challenges[i].category;\n categories.push(category);\n var categoryid = category.replace(/ /g, \"-\").hashCode();\n var categoryrow = (0, _jquery[\"default\"])(\"\" + '
'.format(categoryid) + '
' + \"
\" + '
' + '
' + \"
\" + \"
\");\n categoryrow.find(\".category-header\").append((0, _jquery[\"default\"])(\"

\" + category + \"

\"));\n $challenges_board.append(categoryrow);\n }\n }\n\n for (var _i = 0; _i <= challenges.length - 1; _i++) {\n var chalinfo = challenges[_i];\n var chalid = chalinfo.name.replace(/ /g, \"-\").hashCode();\n var catid = chalinfo.category.replace(/ /g, \"-\").hashCode();\n var chalwrap = (0, _jquery[\"default\"])(\"
\".format(chalid));\n var chalbutton = void 0;\n\n if (solves.indexOf(chalinfo.id) == -1) {\n chalbutton = (0, _jquery[\"default\"])(\"\".format(chalinfo.id));\n } else {\n chalbutton = (0, _jquery[\"default\"])(\"\".format(chalinfo.id));\n }\n\n var chalheader = (0, _jquery[\"default\"])(\"

{0}

\".format(chalinfo.name));\n var chalscore = (0, _jquery[\"default\"])(\"{0}\".format(chalinfo.value));\n\n for (var j = 0; j < chalinfo.tags.length; j++) {\n var tag = \"tag-\" + chalinfo.tags[j].value.replace(/ /g, \"-\");\n chalwrap.addClass(tag);\n }\n\n chalbutton.append(chalheader);\n chalbutton.append(chalscore);\n chalwrap.append(chalbutton);\n (0, _jquery[\"default\"])(\"#\" + catid + \"-row\").find(\".category-challenges > .challenges-row\").append(chalwrap);\n }\n\n (0, _jquery[\"default\"])(\".challenge-button\").click(function (_event) {\n loadChal(this.value);\n });\n });\n}\n\nfunction update() {\n return loadChals().then(markSolves);\n}\n\n(0, _jquery[\"default\"])(function () {\n update().then(function () {\n if (window.location.hash.length > 0) {\n loadChalByName(decodeURIComponent(window.location.hash.substring(1)));\n }\n });\n (0, _jquery[\"default\"])(\"#challenge-input\").keyup(function (event) {\n if (event.keyCode == 13) {\n (0, _jquery[\"default\"])(\"#challenge-submit\").click();\n }\n });\n (0, _jquery[\"default\"])(\".nav-tabs a\").click(function (event) {\n event.preventDefault();\n (0, _jquery[\"default\"])(this).tab(\"show\");\n });\n (0, _jquery[\"default\"])(\"#challenge-window\").on(\"hidden.bs.modal\", function (_event) {\n (0, _jquery[\"default\"])(\".nav-tabs a:first\").tab(\"show\");\n history.replaceState(\"\", window.document.title, window.location.pathname);\n });\n (0, _jquery[\"default\"])(\".challenge-solves\").click(function (_event) {\n getSolves((0, _jquery[\"default\"])(\"#challenge-id\").val());\n });\n (0, _jquery[\"default\"])(\"#challenge-window\").on(\"hide.bs.modal\", function (_event) {\n (0, _jquery[\"default\"])(\"#challenge-input\").removeClass(\"wrong\");\n (0, _jquery[\"default\"])(\"#challenge-input\").removeClass(\"correct\");\n (0, _jquery[\"default\"])(\"#incorrect-key\").slideUp();\n (0, _jquery[\"default\"])(\"#correct-key\").slideUp();\n (0, _jquery[\"default\"])(\"#already-solved\").slideUp();\n (0, _jquery[\"default\"])(\"#too-fast\").slideUp();\n });\n});\nsetInterval(update, 300000); // Update every 5 minutes.\n\nvar displayHint = function displayHint(data) {\n (0, _ezq.ezAlert)({\n title: \"Hint\",\n body: data.html,\n button: \"Got it!\"\n });\n};\n\nvar displayUnlock = function displayUnlock(id) {\n (0, _ezq.ezQuery)({\n title: \"Unlock Hint?\",\n body: \"Are you sure you want to open this hint?\",\n success: function success() {\n var params = {\n target: id,\n type: \"hints\"\n };\n\n _CTFd[\"default\"].api.post_unlock_list({}, params).then(function (response) {\n if (response.success) {\n _CTFd[\"default\"].api.get_hint({\n hintId: id\n }).then(function (response) {\n displayHint(response.data);\n });\n\n return;\n }\n\n (0, _ezq.ezAlert)({\n title: \"Error\",\n body: response.errors.score,\n button: \"Got it!\"\n });\n });\n }\n });\n};\n\nvar loadHint = function loadHint(id) {\n _CTFd[\"default\"].api.get_hint({\n hintId: id\n }).then(function (response) {\n if (response.data.content) {\n displayHint(response.data);\n return;\n }\n\n displayUnlock(id);\n });\n};\n\n//# sourceURL=webpack:///./CTFd/themes/core/assets/js/pages/challenges.js?"); /***/ }) diff --git a/CTFd/themes/core/static/js/pages/challenges.min.js b/CTFd/themes/core/static/js/pages/challenges.min.js index 86e4dd6c..4f73866c 100644 --- a/CTFd/themes/core/static/js/pages/challenges.min.js +++ b/CTFd/themes/core/static/js/pages/challenges.min.js @@ -1 +1 @@ -!function(d){function e(e){for(var t,i,n=e[0],o=e[1],a=e[2],r=0,s=[];r".concat(e.body,"

")):i.find(".modal-body").append((0,s.default)(e.body));var n=(0,s.default)(p.format(e.button));return e.success&&(0,s.default)(n).click(function(){e.success()}),e.large&&i.find(".modal-dialog").addClass("modal-lg"),i.find(".modal-footer").append(n),i.find("pre code").each(function(e){a.default.highlightBlock(this)}),(0,s.default)("main").append(i),i.modal("show"),(0,s.default)(i).on("hidden.bs.modal",function(){(0,s.default)(this).modal("dispose")}),i}function m(e){(0,s.default)("#ezq--notifications-toast-container").length||(0,s.default)("body").append((0,s.default)("
").attr({id:"ezq--notifications-toast-container"}).css({position:"fixed",bottom:"0",right:"0","min-width":"20%"}));var t,i=d.format(e.title,e.body),n=(0,s.default)(i);e.onclose&&(0,s.default)(n).find("button[data-dismiss=toast]").click(function(){e.onclose()}),e.onclick&&((t=(0,s.default)(n).find(".toast-body")).addClass("cursor-pointer"),t.click(function(){e.onclick()}));var o=!1!==e.autohide,a=!1!==e.animation,r=e.delay||1e4;return(0,s.default)("#ezq--notifications-toast-container").prepend(n),n.toast({autohide:o,delay:r,animation:a}),n.toast("show"),n}function g(e){var t=r.format(e.title),i=(0,s.default)(t);"string"==typeof e.body?i.find(".modal-body").append("

".concat(e.body,"

")):i.find(".modal-body").append((0,s.default)(e.body));var n=(0,s.default)(f),o=(0,s.default)(u);return i.find(".modal-footer").append(o),i.find(".modal-footer").append(n),i.find("pre code").each(function(e){a.default.highlightBlock(this)}),(0,s.default)("main").append(i),(0,s.default)(i).on("hidden.bs.modal",function(){(0,s.default)(this).modal("dispose")}),(0,s.default)(n).click(function(){e.success()}),i.modal("show"),i}function v(e){if(e.target){var t=(0,s.default)(e.target);return t.find(".progress-bar").css("width",e.width+"%"),t}var i=l.format(e.width),n=r.format(e.title),o=(0,s.default)(n);return o.find(".modal-body").append((0,s.default)(i)),(0,s.default)("main").append(o),o.modal("show")}function y(e){var t={success:c,error:o}[e.type].format(e.body);return(0,s.default)(t)}var j={ezAlert:h,ezToast:m,ezQuery:g,ezProgressBar:v,ezBadge:y};t.default=j},"./CTFd/themes/core/assets/js/fetch.js":function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0,i("./node_modules/whatwg-fetch/fetch.js");var n,o=(n=i("./CTFd/themes/core/assets/js/config.js"))&&n.__esModule?n:{default:n};var a=window.fetch;t.default=function(e,t){return void 0===t&&(t={method:"GET",credentials:"same-origin",headers:{}}),e=o.default.urlRoot+e,void 0===t.headers&&(t.headers={}),t.credentials="same-origin",t.headers.Accept="application/json",t.headers["Content-Type"]="application/json",t.headers["CSRF-Token"]=o.default.csrfNonce,a(e,t)}},"./CTFd/themes/core/assets/js/pages/challenges.js":function(e,t,i){i("./CTFd/themes/core/assets/js/pages/main.js"),i("./node_modules/bootstrap/js/dist/tab.js");var n=i("./CTFd/themes/core/assets/js/ezq.js"),d=i("./CTFd/themes/core/assets/js/utils.js"),l=c(i("./node_modules/dayjs/dayjs.min.js")),o=c(i("./node_modules/dayjs/plugin/relativeTime.js")),v=c(i("./node_modules/jquery/dist/jquery.js")),a=c(i("./CTFd/themes/core/assets/js/CTFd.js")),r=c(i("./CTFd/themes/core/assets/js/config.js")),s=c(i("./node_modules/highlight.js/lib/index.js"));function c(e){return e&&e.__esModule?e:{default:e}}l.default.extend(o.default);var p={teams:function(e){return a.default.api.get_team_solves({teamId:e})},users:function(e){return a.default.api.get_user_solves({userId:e})}};a.default._internal.challenge={};var y=[],j=[],_=function(t){var e=v.default.grep(y,function(e){return e.id==t})[0];"hidden"!==e.type?u(e):(0,n.ezAlert)({title:"Challenge Hidden!",body:"You haven't unlocked this challenge yet!",button:"Got it!"})},u=function(n){return Promise.all([a.default.api.get_challenge({challengeId:n.id}),v.default.getScript(r.default.urlRoot+n.script),v.default.get(r.default.urlRoot+n.template)]).then(function(e){var t=a.default._internal.challenge;(0,v.default)("#challenge-window").empty(),t.data=e[0].data,t.preRender(),(0,v.default)("#challenge-window").append(e[0].data.view),(0,v.default)("#challenge-window #challenge-input").addClass("form-control"),(0,v.default)("#challenge-window #challenge-submit").addClass("btn btn-md btn-outline-secondary float-right");var i=(0,v.default)("#challenge-window").find(".modal-dialog");if(window.init.theme_settings&&window.init.theme_settings.challenge_window_size)switch(window.init.theme_settings.challenge_window_size){case"sm":i.addClass("modal-sm");break;case"lg":i.addClass("modal-lg");break;case"xl":i.addClass("modal-xl")}(0,v.default)(".challenge-solves").click(function(e){b((0,v.default)("#challenge-id").val())}),(0,v.default)(".nav-tabs a").click(function(e){e.preventDefault(),(0,v.default)(this).tab("show")}),(0,v.default)("#challenge-window").on("hide.bs.modal",function(e){(0,v.default)("#challenge-input").removeClass("wrong"),(0,v.default)("#challenge-input").removeClass("correct"),(0,v.default)("#incorrect-key").slideUp(),(0,v.default)("#correct-key").slideUp(),(0,v.default)("#already-solved").slideUp(),(0,v.default)("#too-fast").slideUp()}),(0,v.default)(".load-hint").on("click",function(e){w((0,v.default)(this).data("hint-id"))}),(0,v.default)("#challenge-submit").click(function(e){e.preventDefault(),(0,v.default)("#challenge-submit").addClass("disabled-button"),(0,v.default)("#challenge-submit").prop("disabled",!0),a.default._internal.challenge.submit().then(f).then(m).then(h)}),(0,v.default)("#challenge-input").keyup(function(e){13==e.keyCode&&(0,v.default)("#challenge-submit").click()}),t.postRender(),(0,v.default)("#challenge-window").find("pre code").each(function(e){s.default.highlightBlock(this)}),window.location.replace(window.location.href.split("#")[0]+"#".concat(n.name,"-").concat(n.id)),(0,v.default)("#challenge-window").modal()})};function f(e){var t=e.data,i=(0,v.default)("#result-message"),n=(0,v.default)("#result-notification"),o=(0,v.default)("#challenge-input");n.removeClass(),i.text(t.message),"authentication_required"!==t.status?("incorrect"===t.status?(n.addClass("alert alert-danger alert-dismissable text-center"),n.slideDown(),o.removeClass("correct"),o.addClass("wrong"),setTimeout(function(){o.removeClass("wrong")},3e3)):"correct"===t.status?(n.addClass("alert alert-success alert-dismissable text-center"),n.slideDown(),(0,v.default)(".challenge-solves").text().trim()&&(0,v.default)(".challenge-solves").text(parseInt((0,v.default)(".challenge-solves").text().split(" ")[0])+1+" Solves"),o.val(""),o.removeClass("wrong"),o.addClass("correct")):"already_solved"===t.status?(n.addClass("alert alert-info alert-dismissable text-center"),n.slideDown(),o.addClass("correct")):"paused"===t.status?(n.addClass("alert alert-warning alert-dismissable text-center"),n.slideDown()):"ratelimited"===t.status&&(n.addClass("alert alert-warning alert-dismissable text-center"),n.slideDown(),o.addClass("too-fast"),setTimeout(function(){o.removeClass("too-fast")},3e3)),setTimeout(function(){(0,v.default)(".alert").slideUp(),(0,v.default)("#challenge-submit").removeClass("disabled-button"),(0,v.default)("#challenge-submit").prop("disabled",!1)},3e3)):window.location=a.default.config.urlRoot+"/login?next="+a.default.config.urlRoot+window.location.pathname+window.location.hash}function h(){return p[a.default.config.userMode]("me").then(function(e){for(var t=e.data,i=t.length-1;0<=i;i--){var n=(0,v.default)('button[value="'+t[i].challenge_id+'"]');n.addClass("solved-challenge"),n.prepend("")}})}function b(e){return a.default.api.get_challenge_solves({challengeId:e}).then(function(e){var t=e.data;(0,v.default)(".challenge-solves").text(parseInt(t.length)+" Solves");var i=(0,v.default)("#challenge-solves-names");i.empty();for(var n=0;n
{2}{3}'.format(s,o,(0,d.htmlEntities)(a),r))}})}function m(){return a.default.api.get_challenge_list().then(function(e){var t=[],i=(0,v.default)("#challenges-board");y=e.data,i.empty();for(var n,o,a,r=y.length-1;0<=r;r--){y[r].solves=0,-1==v.default.inArray(y[r].category,t)&&(n=y[r].category,t.push(n),o=n.replace(/ /g,"-").hashCode(),(a=(0,v.default)('
'.format(o)+'
')).find(".category-header").append((0,v.default)("

"+n+"

")),i.append(a))}for(var s=0;s<=y.length-1;s++){for(var d=y[s],l=d.name.replace(/ /g,"-").hashCode(),c=d.category.replace(/ /g,"-").hashCode(),p=(0,v.default)("
".format(l)),u=void 0,u=-1==j.indexOf(d.id)?(0,v.default)("".format(d.id)):(0,v.default)("".format(d.id)),f=(0,v.default)("

{0}

".format(d.name)),h=(0,v.default)("{0}".format(d.value)),m=0;m .challenges-row").append(p)}(0,v.default)(".challenge-button").click(function(e){_(this.value),b(this.value)})})}function g(){return(0==a.default.user.id?Promise.resolve():p[a.default.config.userMode]("me").then(function(e){for(var t=e.data,i=t.length-1;0<=i;i--){var n=t[i].challenge_id;t.push(n)}})).then(m).then(h)}(0,v.default)(function(){g().then(function(){var e,t,i,n;0").text(e).html()},t.cumulativeSum=function(e){for(var t=e.concat(),i=0;i'),(0,r.default)("th.sort-col").click(function(){var o,e=(0,r.default)(this).parents("table").eq(0),t=e.find("tr:gt(0)").toArray().sort((o=(0,r.default)(this).index(),function(e,t){var i=a(e,o),n=a(t,o);return r.default.isNumeric(i)&&r.default.isNumeric(n)?i-n:i.toString().localeCompare(n)}));this.asc=!this.asc,this.asc||(t=t.reverse());for(var i=0;i".concat(e.body,"

")):i.find(".modal-body").append((0,s.default)(e.body));var n=(0,s.default)(p.format(e.button));return e.success&&(0,s.default)(n).click(function(){e.success()}),e.large&&i.find(".modal-dialog").addClass("modal-lg"),i.find(".modal-footer").append(n),i.find("pre code").each(function(e){a.default.highlightBlock(this)}),(0,s.default)("main").append(i),i.modal("show"),(0,s.default)(i).on("hidden.bs.modal",function(){(0,s.default)(this).modal("dispose")}),i}function m(e){(0,s.default)("#ezq--notifications-toast-container").length||(0,s.default)("body").append((0,s.default)("
").attr({id:"ezq--notifications-toast-container"}).css({position:"fixed",bottom:"0",right:"0","min-width":"20%"}));var t,i=d.format(e.title,e.body),n=(0,s.default)(i);e.onclose&&(0,s.default)(n).find("button[data-dismiss=toast]").click(function(){e.onclose()}),e.onclick&&((t=(0,s.default)(n).find(".toast-body")).addClass("cursor-pointer"),t.click(function(){e.onclick()}));var o=!1!==e.autohide,a=!1!==e.animation,r=e.delay||1e4;return(0,s.default)("#ezq--notifications-toast-container").prepend(n),n.toast({autohide:o,delay:r,animation:a}),n.toast("show"),n}function g(e){var t=r.format(e.title),i=(0,s.default)(t);"string"==typeof e.body?i.find(".modal-body").append("

".concat(e.body,"

")):i.find(".modal-body").append((0,s.default)(e.body));var n=(0,s.default)(f),o=(0,s.default)(u);return i.find(".modal-footer").append(o),i.find(".modal-footer").append(n),i.find("pre code").each(function(e){a.default.highlightBlock(this)}),(0,s.default)("main").append(i),(0,s.default)(i).on("hidden.bs.modal",function(){(0,s.default)(this).modal("dispose")}),(0,s.default)(n).click(function(){e.success()}),i.modal("show"),i}function v(e){if(e.target){var t=(0,s.default)(e.target);return t.find(".progress-bar").css("width",e.width+"%"),t}var i=l.format(e.width),n=r.format(e.title),o=(0,s.default)(n);return o.find(".modal-body").append((0,s.default)(i)),(0,s.default)("main").append(o),o.modal("show")}function y(e){var t={success:c,error:o}[e.type].format(e.body);return(0,s.default)(t)}var j={ezAlert:h,ezToast:m,ezQuery:g,ezProgressBar:v,ezBadge:y};t.default=j},"./CTFd/themes/core/assets/js/fetch.js":function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0,i("./node_modules/whatwg-fetch/fetch.js");var n,o=(n=i("./CTFd/themes/core/assets/js/config.js"))&&n.__esModule?n:{default:n};var a=window.fetch;t.default=function(e,t){return void 0===t&&(t={method:"GET",credentials:"same-origin",headers:{}}),e=o.default.urlRoot+e,void 0===t.headers&&(t.headers={}),t.credentials="same-origin",t.headers.Accept="application/json",t.headers["Content-Type"]="application/json",t.headers["CSRF-Token"]=o.default.csrfNonce,a(e,t)}},"./CTFd/themes/core/assets/js/pages/challenges.js":function(e,t,i){i("./CTFd/themes/core/assets/js/pages/main.js"),i("./node_modules/bootstrap/js/dist/tab.js");var n=i("./CTFd/themes/core/assets/js/ezq.js"),d=i("./CTFd/themes/core/assets/js/utils.js"),l=c(i("./node_modules/dayjs/dayjs.min.js")),o=c(i("./node_modules/dayjs/plugin/relativeTime.js")),v=c(i("./node_modules/jquery/dist/jquery.js")),a=c(i("./CTFd/themes/core/assets/js/CTFd.js")),r=c(i("./CTFd/themes/core/assets/js/config.js")),s=c(i("./node_modules/highlight.js/lib/index.js"));function c(e){return e&&e.__esModule?e:{default:e}}l.default.extend(o.default),a.default._internal.challenge={};var y=[],j=[],_=function(t){var e=v.default.grep(y,function(e){return e.id==t})[0];"hidden"!==e.type?p(e):(0,n.ezAlert)({title:"Challenge Hidden!",body:"You haven't unlocked this challenge yet!",button:"Got it!"})},p=function(n){return Promise.all([a.default.api.get_challenge({challengeId:n.id}),v.default.getScript(r.default.urlRoot+n.script),v.default.get(r.default.urlRoot+n.template)]).then(function(e){var t=a.default._internal.challenge;(0,v.default)("#challenge-window").empty(),t.data=e[0].data,t.preRender(),(0,v.default)("#challenge-window").append(e[0].data.view),(0,v.default)("#challenge-window #challenge-input").addClass("form-control"),(0,v.default)("#challenge-window #challenge-submit").addClass("btn btn-md btn-outline-secondary float-right");var i=(0,v.default)("#challenge-window").find(".modal-dialog");if(window.init.theme_settings&&window.init.theme_settings.challenge_window_size)switch(window.init.theme_settings.challenge_window_size){case"sm":i.addClass("modal-sm");break;case"lg":i.addClass("modal-lg");break;case"xl":i.addClass("modal-xl")}(0,v.default)(".challenge-solves").click(function(e){h((0,v.default)("#challenge-id").val())}),(0,v.default)(".nav-tabs a").click(function(e){e.preventDefault(),(0,v.default)(this).tab("show")}),(0,v.default)("#challenge-window").on("hide.bs.modal",function(e){(0,v.default)("#challenge-input").removeClass("wrong"),(0,v.default)("#challenge-input").removeClass("correct"),(0,v.default)("#incorrect-key").slideUp(),(0,v.default)("#correct-key").slideUp(),(0,v.default)("#already-solved").slideUp(),(0,v.default)("#too-fast").slideUp()}),(0,v.default)(".load-hint").on("click",function(e){T((0,v.default)(this).data("hint-id"))}),(0,v.default)("#challenge-submit").click(function(e){e.preventDefault(),(0,v.default)("#challenge-submit").addClass("disabled-button"),(0,v.default)("#challenge-submit").prop("disabled",!0),a.default._internal.challenge.submit().then(u).then(m).then(f)}),(0,v.default)("#challenge-input").keyup(function(e){13==e.keyCode&&(0,v.default)("#challenge-submit").click()}),t.postRender(),(0,v.default)("#challenge-window").find("pre code").each(function(e){s.default.highlightBlock(this)}),window.location.replace(window.location.href.split("#")[0]+"#".concat(n.name,"-").concat(n.id)),(0,v.default)("#challenge-window").modal()})};function u(e){var t=e.data,i=(0,v.default)("#result-message"),n=(0,v.default)("#result-notification"),o=(0,v.default)("#challenge-input");n.removeClass(),i.text(t.message),"authentication_required"!==t.status?("incorrect"===t.status?(n.addClass("alert alert-danger alert-dismissable text-center"),n.slideDown(),o.removeClass("correct"),o.addClass("wrong"),setTimeout(function(){o.removeClass("wrong")},3e3)):"correct"===t.status?(n.addClass("alert alert-success alert-dismissable text-center"),n.slideDown(),(0,v.default)(".challenge-solves").text().trim()&&(0,v.default)(".challenge-solves").text(parseInt((0,v.default)(".challenge-solves").text().split(" ")[0])+1+" Solves"),o.val(""),o.removeClass("wrong"),o.addClass("correct")):"already_solved"===t.status?(n.addClass("alert alert-info alert-dismissable text-center"),n.slideDown(),o.addClass("correct")):"paused"===t.status?(n.addClass("alert alert-warning alert-dismissable text-center"),n.slideDown()):"ratelimited"===t.status&&(n.addClass("alert alert-warning alert-dismissable text-center"),n.slideDown(),o.addClass("too-fast"),setTimeout(function(){o.removeClass("too-fast")},3e3)),setTimeout(function(){(0,v.default)(".alert").slideUp(),(0,v.default)("#challenge-submit").removeClass("disabled-button"),(0,v.default)("#challenge-submit").prop("disabled",!1)},3e3)):window.location=a.default.config.urlRoot+"/login?next="+a.default.config.urlRoot+window.location.pathname+window.location.hash}function f(){y.map(function(e){var t;e.solved_by_me&&((t=(0,v.default)('button[value="'.concat(e.id,'"]'))).addClass("solved-challenge"),t.prepend(""))})}function h(e){return a.default.api.get_challenge_solves({challengeId:e}).then(function(e){var t=e.data;(0,v.default)(".challenge-solves").text(parseInt(t.length)+" Solves");var i=(0,v.default)("#challenge-solves-names");i.empty();for(var n=0;n
{2}{3}'.format(s,o,(0,d.htmlEntities)(a),r))}})}function m(){return a.default.api.get_challenge_list().then(function(e){var t=[],i=(0,v.default)("#challenges-board");y=e.data,i.empty();for(var n,o,a,r=y.length-1;0<=r;r--){-1==v.default.inArray(y[r].category,t)&&(n=y[r].category,t.push(n),o=n.replace(/ /g,"-").hashCode(),(a=(0,v.default)('
'.format(o)+'
')).find(".category-header").append((0,v.default)("

"+n+"

")),i.append(a))}for(var s=0;s<=y.length-1;s++){for(var d=y[s],l=d.name.replace(/ /g,"-").hashCode(),c=d.category.replace(/ /g,"-").hashCode(),p=(0,v.default)("
".format(l)),u=void 0,u=-1==j.indexOf(d.id)?(0,v.default)("".format(d.id)):(0,v.default)("".format(d.id)),f=(0,v.default)("

{0}

".format(d.name)),h=(0,v.default)("{0}".format(d.value)),m=0;m .challenges-row").append(p)}(0,v.default)(".challenge-button").click(function(e){_(this.value)})})}function g(){return m().then(f)}(0,v.default)(function(){g().then(function(){var e,t,i,n;0").text(e).html()},t.cumulativeSum=function(e){for(var t=e.concat(),i=0;i'),(0,r.default)("th.sort-col").click(function(){var o,e=(0,r.default)(this).parents("table").eq(0),t=e.find("tr:gt(0)").toArray().sort((o=(0,r.default)(this).index(),function(e,t){var i=a(e,o),n=a(t,o);return r.default.isNumeric(i)&&r.default.isNumeric(n)?i-n:i.toString().localeCompare(n)}));this.asc=!this.asc,this.asc||(t=t.reverse());for(var i=0;i