From 7f115bf4581b8511e5a4a548e55f74d0beef6680 Mon Sep 17 00:00:00 2001 From: Kevin Chung Date: Thu, 28 Jan 2021 16:55:15 -0500 Subject: [PATCH] Add length error content that is too long (#1787) * Add length checking to some sensitive fields in Pages and Challenges. * Works on #1786 This is enough to fix most of the issues but this is really a systemic problem for most of the API endpoints. We should have something that verifies data consistency. Marshmallow is not good enough at this. Pydantic seems like it would be superior here. --- CTFd/api/v1/challenges.py | 16 ++++++++++ CTFd/schemas/challenges.py | 29 +++++++++++++++++++ CTFd/schemas/pages.py | 29 +++++++++++++++++-- .../themes/admin/assets/js/pages/challenge.js | 24 +++++++++++++++ CTFd/themes/admin/assets/js/pages/editor.js | 18 +++++++++++- .../admin/static/js/pages/challenge.dev.js | 2 +- .../admin/static/js/pages/challenge.min.js | 2 +- .../admin/static/js/pages/editor.dev.js | 2 +- .../admin/static/js/pages/editor.min.js | 2 +- 9 files changed, 116 insertions(+), 8 deletions(-) diff --git a/CTFd/api/v1/challenges.py b/CTFd/api/v1/challenges.py index 1cc8eb92..4690f5fa 100644 --- a/CTFd/api/v1/challenges.py +++ b/CTFd/api/v1/challenges.py @@ -23,6 +23,7 @@ from CTFd.models import ( db, ) from CTFd.plugins.challenges import CHALLENGE_CLASSES, get_chal_class +from CTFd.schemas.challenges import ChallengeSchema from CTFd.schemas.flags import FlagSchema from CTFd.schemas.hints import HintSchema from CTFd.schemas.tags import TagSchema @@ -223,6 +224,13 @@ class ChallengeList(Resource): ) def post(self): data = request.form or request.get_json() + + # Load data through schema for validation but not for insertion + schema = ChallengeSchema() + response = schema.load(data) + if response.errors: + return {"success": False, "errors": response.errors}, 400 + challenge_type = data["type"] challenge_class = get_chal_class(challenge_type) challenge = challenge_class.create(request) @@ -427,6 +435,14 @@ class Challenge(Resource): }, ) def patch(self, challenge_id): + data = request.get_json() + + # Load data through schema for validation but not for insertion + schema = ChallengeSchema() + response = schema.load(data) + if response.errors: + return {"success": False, "errors": response.errors}, 400 + challenge = Challenges.query.filter_by(id=challenge_id).first_or_404() challenge_class = get_chal_class(challenge.type) challenge = challenge_class.update(challenge, request) diff --git a/CTFd/schemas/challenges.py b/CTFd/schemas/challenges.py index ca1b8773..312347dc 100644 --- a/CTFd/schemas/challenges.py +++ b/CTFd/schemas/challenges.py @@ -1,3 +1,5 @@ +from marshmallow import ValidationError, pre_load + from CTFd.models import Challenges, ma @@ -6,3 +8,30 @@ class ChallengeSchema(ma.ModelSchema): model = Challenges include_fk = True dump_only = ("id",) + + @pre_load + def validate_name(self, data): + name = data.get("name", "") + if len(name) > 80: + raise ValidationError( + "Challenge could not be saved. Challenge name too long", + field_names=["name"], + ) + + @pre_load + def validate_category(self, data): + category = data.get("category", "") + if len(category) > 80: + raise ValidationError( + "Challenge could not be saved. Challenge category too long", + field_names=["category"], + ) + + @pre_load + def validate_description(self, data): + description = data.get("description", "") + if len(description) >= 65536: + raise ValidationError( + "Challenge could not be saved. Challenge description is too long.", + field_names=["description"], + ) diff --git a/CTFd/schemas/pages.py b/CTFd/schemas/pages.py index 0e1801a9..8c889c73 100644 --- a/CTFd/schemas/pages.py +++ b/CTFd/schemas/pages.py @@ -1,4 +1,4 @@ -from marshmallow import pre_load +from marshmallow import ValidationError, pre_load from CTFd.models import Pages, ma from CTFd.utils import string_types @@ -10,11 +10,34 @@ class PageSchema(ma.ModelSchema): include_fk = True dump_only = ("id",) + @pre_load + def validate_title(self, data): + title = data.get("title", "") + if len(title) > 128: + raise ValidationError( + "Page could not be saved. Your title is too long.", + field_names=["title"], + ) + @pre_load def validate_route(self, data): - route = data.get("route") - if route and route.startswith("/"): + route = data.get("route", "") + if route.startswith("/"): data["route"] = route.strip("/") + if len(route) > 128: + raise ValidationError( + "Page could not be saved. Your route is too long.", + field_names=["route"], + ) + + @pre_load + def validate_content(self, data): + content = data.get("content", "") + if len(content) >= 65536: + raise ValidationError( + "Page could not be saved. Your content is too long.", + field_names=["content"], + ) def __init__(self, view=None, *args, **kwargs): if view: diff --git a/CTFd/themes/admin/assets/js/pages/challenge.js b/CTFd/themes/admin/assets/js/pages/challenge.js index 421fe615..6ae10204 100644 --- a/CTFd/themes/admin/assets/js/pages/challenge.js +++ b/CTFd/themes/admin/assets/js/pages/challenge.js @@ -149,6 +149,18 @@ function loadChalTemplate(challenge) { response.data.id ); $("#challenge-create-options").modal(); + } else { + let body = ""; + for (const k in response.errors) { + body += response.errors[k].join("\n"); + body += "\n"; + } + + ezAlert({ + title: "Error", + body: body, + button: "OK" + }); } }); }); @@ -385,6 +397,18 @@ $(() => { title: "Success", body: "Your challenge has been updated!" }); + } else { + let body = ""; + for (const k in response.errors) { + body += response.errors[k].join("\n"); + body += "\n"; + } + + ezAlert({ + title: "Error", + body: body, + button: "OK" + }); } }); }; diff --git a/CTFd/themes/admin/assets/js/pages/editor.js b/CTFd/themes/admin/assets/js/pages/editor.js index b51855f5..d0d99c5e 100644 --- a/CTFd/themes/admin/assets/js/pages/editor.js +++ b/CTFd/themes/admin/assets/js/pages/editor.js @@ -5,7 +5,7 @@ import $ from "jquery"; import CTFd from "core/CTFd"; import CodeMirror from "codemirror"; import "codemirror/mode/htmlmixed/htmlmixed.js"; -import { ezToast } from "core/ezq"; +import { ezAlert, ezToast } from "core/ezq"; import Vue from "vue/dist/vue.esm.browser"; import CommentBox from "../components/comments/CommentBox.vue"; @@ -35,6 +35,22 @@ function submit_form() { return response.json(); }) .then(function(response) { + // Show errors reported by API + if (response.success === false) { + let body = ""; + for (const k in response.errors) { + body += response.errors[k].join("\n"); + body += "\n"; + } + + ezAlert({ + title: "Error", + body: body, + button: "OK" + }); + return; + } + if (method === "PATCH" && response.success) { ezToast({ title: "Saved", diff --git a/CTFd/themes/admin/static/js/pages/challenge.dev.js b/CTFd/themes/admin/static/js/pages/challenge.dev.js index c4408aaa..fc0c99b9 100644 --- a/CTFd/themes/admin/static/js/pages/challenge.dev.js +++ b/CTFd/themes/admin/static/js/pages/challenge.dev.js @@ -162,7 +162,7 @@ /***/ (function(module, exports, __webpack_require__) { ; -eval("\n\n__webpack_require__(/*! ./main */ \"./CTFd/themes/admin/assets/js/pages/main.js\");\n\nvar _utils = __webpack_require__(/*! core/utils */ \"./CTFd/themes/core/assets/js/utils.js\");\n\nvar _jquery = _interopRequireDefault(__webpack_require__(/*! jquery */ \"./node_modules/jquery/dist/jquery.js\"));\n\n__webpack_require__(/*! bootstrap/js/dist/tab */ \"./node_modules/bootstrap/js/dist/tab.js\");\n\nvar _CTFd = _interopRequireDefault(__webpack_require__(/*! core/CTFd */ \"./CTFd/themes/core/assets/js/CTFd.js\"));\n\nvar _ezq = __webpack_require__(/*! core/ezq */ \"./CTFd/themes/core/assets/js/ezq.js\");\n\nvar _helpers = _interopRequireDefault(__webpack_require__(/*! core/helpers */ \"./CTFd/themes/core/assets/js/helpers.js\"));\n\nvar _styles = __webpack_require__(/*! ../styles */ \"./CTFd/themes/admin/assets/js/styles.js\");\n\nvar _vueEsm = _interopRequireDefault(__webpack_require__(/*! vue/dist/vue.esm.browser */ \"./node_modules/vue/dist/vue.esm.browser.js\"));\n\nvar _CommentBox = _interopRequireDefault(__webpack_require__(/*! ../components/comments/CommentBox.vue */ \"./CTFd/themes/admin/assets/js/components/comments/CommentBox.vue\"));\n\nvar _FlagList = _interopRequireDefault(__webpack_require__(/*! ../components/flags/FlagList.vue */ \"./CTFd/themes/admin/assets/js/components/flags/FlagList.vue\"));\n\nvar _Requirements = _interopRequireDefault(__webpack_require__(/*! ../components/requirements/Requirements.vue */ \"./CTFd/themes/admin/assets/js/components/requirements/Requirements.vue\"));\n\nvar _TagsList = _interopRequireDefault(__webpack_require__(/*! ../components/tags/TagsList.vue */ \"./CTFd/themes/admin/assets/js/components/tags/TagsList.vue\"));\n\nvar _ChallengeFilesList = _interopRequireDefault(__webpack_require__(/*! ../components/files/ChallengeFilesList.vue */ \"./CTFd/themes/admin/assets/js/components/files/ChallengeFilesList.vue\"));\n\nvar _HintsList = _interopRequireDefault(__webpack_require__(/*! ../components/hints/HintsList.vue */ \"./CTFd/themes/admin/assets/js/components/hints/HintsList.vue\"));\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\nvar displayHint = function displayHint(data) {\n (0, _ezq.ezAlert)({\n title: \"Hint\",\n body: data.html,\n button: \"Got it!\"\n });\n};\n\nvar loadHint = function loadHint(id) {\n _CTFd[\"default\"].api.get_hint({\n hintId: id,\n preview: true\n }).then(function (response) {\n if (response.data.content) {\n displayHint(response.data);\n return;\n } // displayUnlock(id);\n\n });\n};\n\nfunction renderSubmissionResponse(response, cb) {\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\"])(\"#submission-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 (0, _jquery[\"default\"])(\".challenge-solves\").text(parseInt((0, _jquery[\"default\"])(\".challenge-solves\").text().split(\" \")[0]) + 1 + \" Solves\");\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 if (cb) {\n cb(result);\n }\n}\n\nfunction loadChalTemplate(challenge) {\n _CTFd[\"default\"]._internal.challenge = {};\n\n _jquery[\"default\"].getScript(_CTFd[\"default\"].config.urlRoot + challenge.scripts.view, function () {\n var template_data = challenge.create;\n (0, _jquery[\"default\"])(\"#create-chal-entry-div\").html(template_data);\n (0, _styles.bindMarkdownEditors)();\n\n _jquery[\"default\"].getScript(_CTFd[\"default\"].config.urlRoot + challenge.scripts.create, function () {\n (0, _jquery[\"default\"])(\"#create-chal-entry-div form\").submit(function (event) {\n event.preventDefault();\n var params = (0, _jquery[\"default\"])(\"#create-chal-entry-div form\").serializeJSON();\n\n _CTFd[\"default\"].fetch(\"/api/v1/challenges\", {\n method: \"POST\",\n credentials: \"same-origin\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(params)\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n if (response.success) {\n (0, _jquery[\"default\"])(\"#challenge-create-options #challenge_id\").val(response.data.id);\n (0, _jquery[\"default\"])(\"#challenge-create-options\").modal();\n }\n });\n });\n });\n });\n}\n\nfunction handleChallengeOptions(event) {\n event.preventDefault();\n var params = (0, _jquery[\"default\"])(event.target).serializeJSON(true);\n var flag_params = {\n challenge_id: params.challenge_id,\n content: params.flag || \"\",\n type: params.flag_type,\n data: params.flag_data ? params.flag_data : \"\"\n }; // Define a save_challenge function\n\n var save_challenge = function save_challenge() {\n _CTFd[\"default\"].fetch(\"/api/v1/challenges/\" + params.challenge_id, {\n method: \"PATCH\",\n credentials: \"same-origin\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify({\n state: params.state\n })\n }).then(function (response) {\n return response.json();\n }).then(function (data) {\n if (data.success) {\n setTimeout(function () {\n window.location = _CTFd[\"default\"].config.urlRoot + \"/admin/challenges/\" + params.challenge_id;\n }, 700);\n }\n });\n };\n\n Promise.all([// Save flag\n new Promise(function (resolve, _reject) {\n if (flag_params.content.length == 0) {\n resolve();\n return;\n }\n\n _CTFd[\"default\"].fetch(\"/api/v1/flags\", {\n method: \"POST\",\n credentials: \"same-origin\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(flag_params)\n }).then(function (response) {\n resolve(response.json());\n });\n }), // Upload files\n new Promise(function (resolve, _reject) {\n var form = event.target;\n var data = {\n challenge: params.challenge_id,\n type: \"challenge\"\n };\n var filepath = (0, _jquery[\"default\"])(form.elements[\"file\"]).val();\n\n if (filepath) {\n _helpers[\"default\"].files.upload(form, data);\n }\n\n resolve();\n })]).then(function (_responses) {\n save_challenge();\n });\n}\n\n(0, _jquery[\"default\"])(function () {\n (0, _jquery[\"default\"])(\".preview-challenge\").click(function (_e) {\n _CTFd[\"default\"]._internal.challenge = {};\n\n _jquery[\"default\"].get(_CTFd[\"default\"].config.urlRoot + \"/api/v1/challenges/\" + window.CHALLENGE_ID, function (response) {\n // Preview should not show any solves\n var challenge_data = response.data;\n challenge_data[\"solves\"] = null;\n\n _jquery[\"default\"].getScript(_CTFd[\"default\"].config.urlRoot + challenge_data.type_data.scripts.view, function () {\n var challenge = _CTFd[\"default\"]._internal.challenge; // Inject challenge data into the plugin\n\n challenge.data = response.data;\n (0, _jquery[\"default\"])(\"#challenge-window\").empty(); // Call preRender function in plugin\n\n challenge.preRender();\n (0, _jquery[\"default\"])(\"#challenge-window\").append(challenge_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 (0, _jquery[\"default\"])(\".challenge-solves\").hide();\n (0, _jquery[\"default\"])(\".nav-tabs a\").click(function (e) {\n e.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 (e) {\n e.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(true).then(renderSubmissionResponse); // Preview passed as true\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 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] + \"#preview\");\n (0, _jquery[\"default\"])(\"#challenge-window\").modal();\n });\n });\n });\n (0, _jquery[\"default\"])(\".delete-challenge\").click(function (_e) {\n (0, _ezq.ezQuery)({\n title: \"Delete Challenge\",\n body: \"Are you sure you want to delete {0}\".format(\"\" + (0, _utils.htmlEntities)(window.CHALLENGE_NAME) + \"\"),\n success: function success() {\n _CTFd[\"default\"].fetch(\"/api/v1/challenges/\" + window.CHALLENGE_ID, {\n method: \"DELETE\"\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n if (response.success) {\n window.location = _CTFd[\"default\"].config.urlRoot + \"/admin/challenges\";\n }\n });\n }\n });\n });\n (0, _jquery[\"default\"])(\"#challenge-update-container > form\").submit(function (e) {\n e.preventDefault();\n var params = (0, _jquery[\"default\"])(e.target).serializeJSON(true);\n\n _CTFd[\"default\"].fetch(\"/api/v1/challenges/\" + window.CHALLENGE_ID + \"/flags\", {\n method: \"GET\",\n credentials: \"same-origin\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\"\n }\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n var update_challenge = function update_challenge() {\n _CTFd[\"default\"].fetch(\"/api/v1/challenges/\" + window.CHALLENGE_ID, {\n method: \"PATCH\",\n credentials: \"same-origin\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(params)\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n if (response.success) {\n (0, _jquery[\"default\"])(\".challenge-state\").text(response.data.state);\n\n switch (response.data.state) {\n case \"visible\":\n (0, _jquery[\"default\"])(\".challenge-state\").removeClass(\"badge-danger\").addClass(\"badge-success\");\n break;\n\n case \"hidden\":\n (0, _jquery[\"default\"])(\".challenge-state\").removeClass(\"badge-success\").addClass(\"badge-danger\");\n break;\n\n default:\n break;\n }\n\n (0, _ezq.ezToast)({\n title: \"Success\",\n body: \"Your challenge has been updated!\"\n });\n }\n });\n }; // Check if the challenge doesn't have any flags before marking visible\n\n\n if (response.data.length === 0 && params.state === \"visible\") {\n (0, _ezq.ezQuery)({\n title: \"Missing Flags\",\n body: \"This challenge does not have any flags meaning it may be unsolveable. Are you sure you'd like to update this challenge?\",\n success: update_challenge\n });\n } else {\n update_challenge();\n }\n });\n });\n (0, _jquery[\"default\"])(\"#challenge-create-options form\").submit(handleChallengeOptions); // Load FlagList component\n\n if (document.querySelector(\"#challenge-flags\")) {\n var flagList = _vueEsm[\"default\"].extend(_FlagList[\"default\"]);\n\n var vueContainer = document.createElement(\"div\");\n document.querySelector(\"#challenge-flags\").appendChild(vueContainer);\n new flagList({\n propsData: {\n challenge_id: window.CHALLENGE_ID\n }\n }).$mount(vueContainer);\n } // Load TagsList component\n\n\n if (document.querySelector(\"#challenge-tags\")) {\n var tagList = _vueEsm[\"default\"].extend(_TagsList[\"default\"]);\n\n var _vueContainer = document.createElement(\"div\");\n\n document.querySelector(\"#challenge-tags\").appendChild(_vueContainer);\n new tagList({\n propsData: {\n challenge_id: window.CHALLENGE_ID\n }\n }).$mount(_vueContainer);\n } // Load Requirements component\n\n\n if (document.querySelector(\"#prerequisite-add-form\")) {\n var reqsComponent = _vueEsm[\"default\"].extend(_Requirements[\"default\"]);\n\n var _vueContainer2 = document.createElement(\"div\");\n\n document.querySelector(\"#prerequisite-add-form\").appendChild(_vueContainer2);\n new reqsComponent({\n propsData: {\n challenge_id: window.CHALLENGE_ID\n }\n }).$mount(_vueContainer2);\n } // Load ChallengeFilesList component\n\n\n if (document.querySelector(\"#challenge-files\")) {\n var challengeFilesList = _vueEsm[\"default\"].extend(_ChallengeFilesList[\"default\"]);\n\n var _vueContainer3 = document.createElement(\"div\");\n\n document.querySelector(\"#challenge-files\").appendChild(_vueContainer3);\n new challengeFilesList({\n propsData: {\n challenge_id: window.CHALLENGE_ID\n }\n }).$mount(_vueContainer3);\n } // Load HintsList component\n\n\n if (document.querySelector(\"#challenge-hints\")) {\n var hintsList = _vueEsm[\"default\"].extend(_HintsList[\"default\"]);\n\n var _vueContainer4 = document.createElement(\"div\");\n\n document.querySelector(\"#challenge-hints\").appendChild(_vueContainer4);\n new hintsList({\n propsData: {\n challenge_id: window.CHALLENGE_ID\n }\n }).$mount(_vueContainer4);\n } // Because this JS is shared by a few pages,\n // we should only insert the CommentBox if it's actually in use\n\n\n if (document.querySelector(\"#comment-box\")) {\n // Insert CommentBox element\n var commentBox = _vueEsm[\"default\"].extend(_CommentBox[\"default\"]);\n\n var _vueContainer5 = document.createElement(\"div\");\n\n document.querySelector(\"#comment-box\").appendChild(_vueContainer5);\n new commentBox({\n propsData: {\n type: \"challenge\",\n id: window.CHALLENGE_ID\n }\n }).$mount(_vueContainer5);\n }\n\n _jquery[\"default\"].get(_CTFd[\"default\"].config.urlRoot + \"/api/v1/challenges/types\", function (response) {\n var data = response.data;\n loadChalTemplate(data[\"standard\"]);\n (0, _jquery[\"default\"])(\"#create-chals-select input[name=type]\").change(function () {\n var challenge = data[this.value];\n loadChalTemplate(challenge);\n });\n });\n});\n\n//# sourceURL=webpack:///./CTFd/themes/admin/assets/js/pages/challenge.js?"); +eval("\n\n__webpack_require__(/*! ./main */ \"./CTFd/themes/admin/assets/js/pages/main.js\");\n\nvar _utils = __webpack_require__(/*! core/utils */ \"./CTFd/themes/core/assets/js/utils.js\");\n\nvar _jquery = _interopRequireDefault(__webpack_require__(/*! jquery */ \"./node_modules/jquery/dist/jquery.js\"));\n\n__webpack_require__(/*! bootstrap/js/dist/tab */ \"./node_modules/bootstrap/js/dist/tab.js\");\n\nvar _CTFd = _interopRequireDefault(__webpack_require__(/*! core/CTFd */ \"./CTFd/themes/core/assets/js/CTFd.js\"));\n\nvar _ezq = __webpack_require__(/*! core/ezq */ \"./CTFd/themes/core/assets/js/ezq.js\");\n\nvar _helpers = _interopRequireDefault(__webpack_require__(/*! core/helpers */ \"./CTFd/themes/core/assets/js/helpers.js\"));\n\nvar _styles = __webpack_require__(/*! ../styles */ \"./CTFd/themes/admin/assets/js/styles.js\");\n\nvar _vueEsm = _interopRequireDefault(__webpack_require__(/*! vue/dist/vue.esm.browser */ \"./node_modules/vue/dist/vue.esm.browser.js\"));\n\nvar _CommentBox = _interopRequireDefault(__webpack_require__(/*! ../components/comments/CommentBox.vue */ \"./CTFd/themes/admin/assets/js/components/comments/CommentBox.vue\"));\n\nvar _FlagList = _interopRequireDefault(__webpack_require__(/*! ../components/flags/FlagList.vue */ \"./CTFd/themes/admin/assets/js/components/flags/FlagList.vue\"));\n\nvar _Requirements = _interopRequireDefault(__webpack_require__(/*! ../components/requirements/Requirements.vue */ \"./CTFd/themes/admin/assets/js/components/requirements/Requirements.vue\"));\n\nvar _TagsList = _interopRequireDefault(__webpack_require__(/*! ../components/tags/TagsList.vue */ \"./CTFd/themes/admin/assets/js/components/tags/TagsList.vue\"));\n\nvar _ChallengeFilesList = _interopRequireDefault(__webpack_require__(/*! ../components/files/ChallengeFilesList.vue */ \"./CTFd/themes/admin/assets/js/components/files/ChallengeFilesList.vue\"));\n\nvar _HintsList = _interopRequireDefault(__webpack_require__(/*! ../components/hints/HintsList.vue */ \"./CTFd/themes/admin/assets/js/components/hints/HintsList.vue\"));\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\nvar displayHint = function displayHint(data) {\n (0, _ezq.ezAlert)({\n title: \"Hint\",\n body: data.html,\n button: \"Got it!\"\n });\n};\n\nvar loadHint = function loadHint(id) {\n _CTFd[\"default\"].api.get_hint({\n hintId: id,\n preview: true\n }).then(function (response) {\n if (response.data.content) {\n displayHint(response.data);\n return;\n } // displayUnlock(id);\n\n });\n};\n\nfunction renderSubmissionResponse(response, cb) {\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\"])(\"#submission-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 (0, _jquery[\"default\"])(\".challenge-solves\").text(parseInt((0, _jquery[\"default\"])(\".challenge-solves\").text().split(\" \")[0]) + 1 + \" Solves\");\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 if (cb) {\n cb(result);\n }\n}\n\nfunction loadChalTemplate(challenge) {\n _CTFd[\"default\"]._internal.challenge = {};\n\n _jquery[\"default\"].getScript(_CTFd[\"default\"].config.urlRoot + challenge.scripts.view, function () {\n var template_data = challenge.create;\n (0, _jquery[\"default\"])(\"#create-chal-entry-div\").html(template_data);\n (0, _styles.bindMarkdownEditors)();\n\n _jquery[\"default\"].getScript(_CTFd[\"default\"].config.urlRoot + challenge.scripts.create, function () {\n (0, _jquery[\"default\"])(\"#create-chal-entry-div form\").submit(function (event) {\n event.preventDefault();\n var params = (0, _jquery[\"default\"])(\"#create-chal-entry-div form\").serializeJSON();\n\n _CTFd[\"default\"].fetch(\"/api/v1/challenges\", {\n method: \"POST\",\n credentials: \"same-origin\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(params)\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n if (response.success) {\n (0, _jquery[\"default\"])(\"#challenge-create-options #challenge_id\").val(response.data.id);\n (0, _jquery[\"default\"])(\"#challenge-create-options\").modal();\n } else {\n var body = \"\";\n\n for (var k in response.errors) {\n body += response.errors[k].join(\"\\n\");\n body += \"\\n\";\n }\n\n (0, _ezq.ezAlert)({\n title: \"Error\",\n body: body,\n button: \"OK\"\n });\n }\n });\n });\n });\n });\n}\n\nfunction handleChallengeOptions(event) {\n event.preventDefault();\n var params = (0, _jquery[\"default\"])(event.target).serializeJSON(true);\n var flag_params = {\n challenge_id: params.challenge_id,\n content: params.flag || \"\",\n type: params.flag_type,\n data: params.flag_data ? params.flag_data : \"\"\n }; // Define a save_challenge function\n\n var save_challenge = function save_challenge() {\n _CTFd[\"default\"].fetch(\"/api/v1/challenges/\" + params.challenge_id, {\n method: \"PATCH\",\n credentials: \"same-origin\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify({\n state: params.state\n })\n }).then(function (response) {\n return response.json();\n }).then(function (data) {\n if (data.success) {\n setTimeout(function () {\n window.location = _CTFd[\"default\"].config.urlRoot + \"/admin/challenges/\" + params.challenge_id;\n }, 700);\n }\n });\n };\n\n Promise.all([// Save flag\n new Promise(function (resolve, _reject) {\n if (flag_params.content.length == 0) {\n resolve();\n return;\n }\n\n _CTFd[\"default\"].fetch(\"/api/v1/flags\", {\n method: \"POST\",\n credentials: \"same-origin\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(flag_params)\n }).then(function (response) {\n resolve(response.json());\n });\n }), // Upload files\n new Promise(function (resolve, _reject) {\n var form = event.target;\n var data = {\n challenge: params.challenge_id,\n type: \"challenge\"\n };\n var filepath = (0, _jquery[\"default\"])(form.elements[\"file\"]).val();\n\n if (filepath) {\n _helpers[\"default\"].files.upload(form, data);\n }\n\n resolve();\n })]).then(function (_responses) {\n save_challenge();\n });\n}\n\n(0, _jquery[\"default\"])(function () {\n (0, _jquery[\"default\"])(\".preview-challenge\").click(function (_e) {\n _CTFd[\"default\"]._internal.challenge = {};\n\n _jquery[\"default\"].get(_CTFd[\"default\"].config.urlRoot + \"/api/v1/challenges/\" + window.CHALLENGE_ID, function (response) {\n // Preview should not show any solves\n var challenge_data = response.data;\n challenge_data[\"solves\"] = null;\n\n _jquery[\"default\"].getScript(_CTFd[\"default\"].config.urlRoot + challenge_data.type_data.scripts.view, function () {\n var challenge = _CTFd[\"default\"]._internal.challenge; // Inject challenge data into the plugin\n\n challenge.data = response.data;\n (0, _jquery[\"default\"])(\"#challenge-window\").empty(); // Call preRender function in plugin\n\n challenge.preRender();\n (0, _jquery[\"default\"])(\"#challenge-window\").append(challenge_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 (0, _jquery[\"default\"])(\".challenge-solves\").hide();\n (0, _jquery[\"default\"])(\".nav-tabs a\").click(function (e) {\n e.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 (e) {\n e.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(true).then(renderSubmissionResponse); // Preview passed as true\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 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] + \"#preview\");\n (0, _jquery[\"default\"])(\"#challenge-window\").modal();\n });\n });\n });\n (0, _jquery[\"default\"])(\".delete-challenge\").click(function (_e) {\n (0, _ezq.ezQuery)({\n title: \"Delete Challenge\",\n body: \"Are you sure you want to delete {0}\".format(\"\" + (0, _utils.htmlEntities)(window.CHALLENGE_NAME) + \"\"),\n success: function success() {\n _CTFd[\"default\"].fetch(\"/api/v1/challenges/\" + window.CHALLENGE_ID, {\n method: \"DELETE\"\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n if (response.success) {\n window.location = _CTFd[\"default\"].config.urlRoot + \"/admin/challenges\";\n }\n });\n }\n });\n });\n (0, _jquery[\"default\"])(\"#challenge-update-container > form\").submit(function (e) {\n e.preventDefault();\n var params = (0, _jquery[\"default\"])(e.target).serializeJSON(true);\n\n _CTFd[\"default\"].fetch(\"/api/v1/challenges/\" + window.CHALLENGE_ID + \"/flags\", {\n method: \"GET\",\n credentials: \"same-origin\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\"\n }\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n var update_challenge = function update_challenge() {\n _CTFd[\"default\"].fetch(\"/api/v1/challenges/\" + window.CHALLENGE_ID, {\n method: \"PATCH\",\n credentials: \"same-origin\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(params)\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n if (response.success) {\n (0, _jquery[\"default\"])(\".challenge-state\").text(response.data.state);\n\n switch (response.data.state) {\n case \"visible\":\n (0, _jquery[\"default\"])(\".challenge-state\").removeClass(\"badge-danger\").addClass(\"badge-success\");\n break;\n\n case \"hidden\":\n (0, _jquery[\"default\"])(\".challenge-state\").removeClass(\"badge-success\").addClass(\"badge-danger\");\n break;\n\n default:\n break;\n }\n\n (0, _ezq.ezToast)({\n title: \"Success\",\n body: \"Your challenge has been updated!\"\n });\n } else {\n var body = \"\";\n\n for (var k in response.errors) {\n body += response.errors[k].join(\"\\n\");\n body += \"\\n\";\n }\n\n (0, _ezq.ezAlert)({\n title: \"Error\",\n body: body,\n button: \"OK\"\n });\n }\n });\n }; // Check if the challenge doesn't have any flags before marking visible\n\n\n if (response.data.length === 0 && params.state === \"visible\") {\n (0, _ezq.ezQuery)({\n title: \"Missing Flags\",\n body: \"This challenge does not have any flags meaning it may be unsolveable. Are you sure you'd like to update this challenge?\",\n success: update_challenge\n });\n } else {\n update_challenge();\n }\n });\n });\n (0, _jquery[\"default\"])(\"#challenge-create-options form\").submit(handleChallengeOptions); // Load FlagList component\n\n if (document.querySelector(\"#challenge-flags\")) {\n var flagList = _vueEsm[\"default\"].extend(_FlagList[\"default\"]);\n\n var vueContainer = document.createElement(\"div\");\n document.querySelector(\"#challenge-flags\").appendChild(vueContainer);\n new flagList({\n propsData: {\n challenge_id: window.CHALLENGE_ID\n }\n }).$mount(vueContainer);\n } // Load TagsList component\n\n\n if (document.querySelector(\"#challenge-tags\")) {\n var tagList = _vueEsm[\"default\"].extend(_TagsList[\"default\"]);\n\n var _vueContainer = document.createElement(\"div\");\n\n document.querySelector(\"#challenge-tags\").appendChild(_vueContainer);\n new tagList({\n propsData: {\n challenge_id: window.CHALLENGE_ID\n }\n }).$mount(_vueContainer);\n } // Load Requirements component\n\n\n if (document.querySelector(\"#prerequisite-add-form\")) {\n var reqsComponent = _vueEsm[\"default\"].extend(_Requirements[\"default\"]);\n\n var _vueContainer2 = document.createElement(\"div\");\n\n document.querySelector(\"#prerequisite-add-form\").appendChild(_vueContainer2);\n new reqsComponent({\n propsData: {\n challenge_id: window.CHALLENGE_ID\n }\n }).$mount(_vueContainer2);\n } // Load ChallengeFilesList component\n\n\n if (document.querySelector(\"#challenge-files\")) {\n var challengeFilesList = _vueEsm[\"default\"].extend(_ChallengeFilesList[\"default\"]);\n\n var _vueContainer3 = document.createElement(\"div\");\n\n document.querySelector(\"#challenge-files\").appendChild(_vueContainer3);\n new challengeFilesList({\n propsData: {\n challenge_id: window.CHALLENGE_ID\n }\n }).$mount(_vueContainer3);\n } // Load HintsList component\n\n\n if (document.querySelector(\"#challenge-hints\")) {\n var hintsList = _vueEsm[\"default\"].extend(_HintsList[\"default\"]);\n\n var _vueContainer4 = document.createElement(\"div\");\n\n document.querySelector(\"#challenge-hints\").appendChild(_vueContainer4);\n new hintsList({\n propsData: {\n challenge_id: window.CHALLENGE_ID\n }\n }).$mount(_vueContainer4);\n } // Because this JS is shared by a few pages,\n // we should only insert the CommentBox if it's actually in use\n\n\n if (document.querySelector(\"#comment-box\")) {\n // Insert CommentBox element\n var commentBox = _vueEsm[\"default\"].extend(_CommentBox[\"default\"]);\n\n var _vueContainer5 = document.createElement(\"div\");\n\n document.querySelector(\"#comment-box\").appendChild(_vueContainer5);\n new commentBox({\n propsData: {\n type: \"challenge\",\n id: window.CHALLENGE_ID\n }\n }).$mount(_vueContainer5);\n }\n\n _jquery[\"default\"].get(_CTFd[\"default\"].config.urlRoot + \"/api/v1/challenges/types\", function (response) {\n var data = response.data;\n loadChalTemplate(data[\"standard\"]);\n (0, _jquery[\"default\"])(\"#create-chals-select input[name=type]\").change(function () {\n var challenge = data[this.value];\n loadChalTemplate(challenge);\n });\n });\n});\n\n//# sourceURL=webpack:///./CTFd/themes/admin/assets/js/pages/challenge.js?"); /***/ }) diff --git a/CTFd/themes/admin/static/js/pages/challenge.min.js b/CTFd/themes/admin/static/js/pages/challenge.min.js index 15b5d763..49e1e653 100644 --- a/CTFd/themes/admin/static/js/pages/challenge.min.js +++ b/CTFd/themes/admin/static/js/pages/challenge.min.js @@ -1 +1 @@ -!function(d){function e(e){for(var t,n,i=e[0],o=e[1],a=e[2],r=0,s=[];r"+(0,u.htmlEntities)(window.CHALLENGE_NAME)+""),success:function(){m.default.fetch("/api/v1/challenges/"+window.CHALLENGE_ID,{method:"DELETE"}).then(function(e){return e.json()}).then(function(e){e.success&&(window.location=m.default.config.urlRoot+"/admin/challenges")})}})}),(0,f.default)("#challenge-update-container > form").submit(function(e){e.preventDefault();var n=(0,f.default)(e.target).serializeJSON(!0);m.default.fetch("/api/v1/challenges/"+window.CHALLENGE_ID+"/flags",{method:"GET",credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json"}}).then(function(e){return e.json()}).then(function(e){function t(){m.default.fetch("/api/v1/challenges/"+window.CHALLENGE_ID,{method:"PATCH",credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify(n)}).then(function(e){return e.json()}).then(function(e){if(e.success){switch((0,f.default)(".challenge-state").text(e.data.state),e.data.state){case"visible":(0,f.default)(".challenge-state").removeClass("badge-danger").addClass("badge-success");break;case"hidden":(0,f.default)(".challenge-state").removeClass("badge-success").addClass("badge-danger")}(0,h.ezToast)({title:"Success",body:"Your challenge has been updated!"})}})}0===e.data.length&&"visible"===n.state?(0,h.ezQuery)({title:"Missing Flags",body:"This challenge does not have any flags meaning it may be unsolveable. Are you sure you'd like to update this challenge?",success:t}):t()})}),(0,f.default)("#challenge-create-options form").submit(I),document.querySelector("#challenge-flags")&&(e=g.default.extend(y.default),t=document.createElement("div"),document.querySelector("#challenge-flags").appendChild(t),new e({propsData:{challenge_id:window.CHALLENGE_ID}}).$mount(t)),document.querySelector("#challenge-tags")&&(n=g.default.extend(_.default),i=document.createElement("div"),document.querySelector("#challenge-tags").appendChild(i),new n({propsData:{challenge_id:window.CHALLENGE_ID}}).$mount(i)),document.querySelector("#prerequisite-add-form")&&(o=g.default.extend(j.default),a=document.createElement("div"),document.querySelector("#prerequisite-add-form").appendChild(a),new o({propsData:{challenge_id:window.CHALLENGE_ID}}).$mount(a)),document.querySelector("#challenge-files")&&(r=g.default.extend(b.default),s=document.createElement("div"),document.querySelector("#challenge-files").appendChild(s),new r({propsData:{challenge_id:window.CHALLENGE_ID}}).$mount(s)),document.querySelector("#challenge-hints")&&(d=g.default.extend(T.default),c=document.createElement("div"),document.querySelector("#challenge-hints").appendChild(c),new d({propsData:{challenge_id:window.CHALLENGE_ID}}).$mount(c)),document.querySelector("#comment-box")&&(l=g.default.extend(v.default),p=document.createElement("div"),document.querySelector("#comment-box").appendChild(p),new l({propsData:{type:"challenge",id:window.CHALLENGE_ID}}).$mount(p)),f.default.get(m.default.config.urlRoot+"/api/v1/challenges/types",function(e){var t=e.data;E(t.standard),(0,f.default)("#create-chals-select input[name=type]").change(function(){E(t[this.value])})})})},"./CTFd/themes/admin/assets/js/pages/main.js":function(e,t,n){var i=f(n("./CTFd/themes/core/assets/js/CTFd.js")),o=f(n("./node_modules/jquery/dist/jquery.js")),a=f(n("./node_modules/dayjs/dayjs.min.js")),r=f(n("./node_modules/dayjs/plugin/advancedFormat.js")),s=f(n("./node_modules/nunjucks/browser/nunjucks.js")),d=n("./node_modules/howler/dist/howler.js"),c=f(n("./CTFd/themes/core/assets/js/events.js")),l=f(n("./CTFd/themes/core/assets/js/times.js")),p=f(n("./CTFd/themes/admin/assets/js/styles.js")),u=f(n("./CTFd/themes/core/assets/js/helpers.js"));function f(e){return e&&e.__esModule?e:{default:e}}a.default.extend(r.default),i.default.init(window.init),window.CTFd=i.default,window.helpers=u.default,window.$=o.default,window.dayjs=a.default,window.nunjucks=s.default,window.Howl=d.Howl,(0,o.default)(function(){(0,p.default)(),(0,l.default)(),(0,c.default)(i.default.config.urlRoot)})},"./CTFd/themes/admin/assets/js/styles.js":function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.showMediaLibrary=l,t.bindMarkdownEditor=p,t.bindMarkdownEditors=u,t.default=void 0,n("./node_modules/bootstrap/dist/js/bootstrap.bundle.js");var i=n("./CTFd/themes/core/assets/js/utils.js"),o=c(n("./node_modules/jquery/dist/jquery.js")),a=c(n("./node_modules/easymde/src/js/easymde.js")),r=c(n("./node_modules/vue/dist/vue.esm.browser.js")),s=c(n("./CTFd/themes/admin/assets/js/components/files/MediaLibrary.vue")),d=c(n("./node_modules/highlight.js/lib/index.js"));function c(e){return e&&e.__esModule?e:{default:e}}function l(e){var t=r.default.extend(s.default),n=document.createElement("div");document.querySelector("main").appendChild(n);var i=new t({propsData:{editor:e}}).$mount(n);(0,o.default)("#media-modal").on("hidden.bs.modal",function(e){i.$destroy(),(0,o.default)("#media-modal").remove()}),(0,o.default)("#media-modal").modal()}function p(e){var t;!1===e.hasOwnProperty("mde")&&(t=new a.default({autoDownloadFontAwesome:!1,toolbar:["bold","italic","heading","|","quote","unordered-list","ordered-list","|","link","image",{name:"media",action:function(e){l(e)},className:"fas fa-file-upload",title:"Media Library"},"|","preview","guide"],element:e,initialValue:(0,o.default)(e).val(),forceSync:!0,minHeight:"200px",renderingConfig:{codeSyntaxHighlighting:!0,hljs:d.default}}),e.mde=t,e.codemirror=t.codemirror,(0,o.default)(e).on("change keyup paste",function(){t.codemirror.getDoc().setValue((0,o.default)(e).val()),t.codemirror.refresh()}))}function u(){(0,o.default)("textarea.markdown").each(function(e,t){p(t)})}t.default=function(){(0,o.default)(":input").each(function(){(0,o.default)(this).data("initial",(0,o.default)(this).val())}),(0,o.default)(function(){(0,o.default)("tr[data-href], td[data-href]").click(function(){var e;return getSelection().toString()||(e=(0,o.default)(this).attr("data-href"))&&(window.location=e),!1}),(0,o.default)("[data-checkbox]").click(function(e){(0,o.default)(e.target).is("input[type=checkbox]")||(0,o.default)(this).find("input[type=checkbox]").click(),e.stopImmediatePropagation()}),(0,o.default)("[data-checkbox-all]").on("click change",function(e){var t=(0,o.default)(this).prop("checked"),n=(0,o.default)(this).index()+1;(0,o.default)(this).closest("table").find("tr td:nth-child(".concat(n,") input[type=checkbox]")).prop("checked",t),e.stopImmediatePropagation()}),(0,o.default)("tr[data-href] a, tr[data-href] button").click(function(e){(0,o.default)(this).attr("data-dismiss")||e.stopPropagation()}),(0,o.default)(".page-select").change(function(){var e=new URL(window.location);e.searchParams.set("page",this.value),window.location.href=e.toString()}),(0,o.default)('a[data-toggle="tab"]').on("shown.bs.tab",function(e){sessionStorage.setItem("activeTab",(0,o.default)(e.target).attr("href"))});var e,t=sessionStorage.getItem("activeTab");t&&((e=(0,o.default)('.nav-tabs a[href="'.concat(t,'"], .nav-pills a[href="').concat(t,'"]'))).length?e.tab("show"):sessionStorage.removeItem("activeTab")),u(),(0,i.makeSortableTables)(),(0,o.default)('[data-toggle="tooltip"]').tooltip(),document.querySelectorAll("pre code").forEach(function(e){d.default.highlightBlock(e)})})}},"./CTFd/themes/core/assets/js/CTFd.js":function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=c(n("./CTFd/themes/core/assets/js/fetch.js")),o=c(n("./CTFd/themes/core/assets/js/config.js")),a=n("./CTFd/themes/core/assets/js/api.js");n("./CTFd/themes/core/assets/js/patch.js");var r=c(n("./node_modules/markdown-it/index.js")),s=c(n("./node_modules/jquery/dist/jquery.js")),d=c(n("./CTFd/themes/core/assets/js/ezq.js"));function c(e){return e&&e.__esModule?e:{default:e}}function l(t,e){var n,i=Object.keys(t);return Object.getOwnPropertySymbols&&(n=Object.getOwnPropertySymbols(t),e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),i.push.apply(i,n)),i}function p(o){for(var e=1;e".concat(e.body,"

")):n.find(".modal-body").append((0,s.default)(e.body));var i=(0,s.default)(p.format(e.button));return e.success&&(0,s.default)(i).click(function(){e.success()}),e.large&&n.find(".modal-dialog").addClass("modal-lg"),n.find(".modal-footer").append(i),n.find("pre code").each(function(e){a.default.highlightBlock(this)}),(0,s.default)("main").append(n),n.modal("show"),(0,s.default)(n).on("hidden.bs.modal",function(){(0,s.default)(this).modal("dispose")}),n}function h(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,n=d.format(e.title,e.body),i=(0,s.default)(n);e.onclose&&(0,s.default)(i).find("button[data-dismiss=toast]").click(function(){e.onclose()}),e.onclick&&((t=(0,s.default)(i).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(i),i.toast({autohide:o,delay:r,animation:a}),i.toast("show"),i}function g(e){var t=r.format(e.title),n=(0,s.default)(t);"string"==typeof e.body?n.find(".modal-body").append("

".concat(e.body,"

")):n.find(".modal-body").append((0,s.default)(e.body));var i=(0,s.default)(f),o=(0,s.default)(u);return n.find(".modal-footer").append(o),n.find(".modal-footer").append(i),n.find("pre code").each(function(e){a.default.highlightBlock(this)}),(0,s.default)("main").append(n),(0,s.default)(n).on("hidden.bs.modal",function(){(0,s.default)(this).modal("dispose")}),(0,s.default)(i).click(function(){e.success()}),n.modal("show"),n}function v(e){if(e.target){var t=(0,s.default)(e.target);return t.find(".progress-bar").css("width",e.width+"%"),t}var n=c.format(e.width),i=r.format(e.title),o=(0,s.default)(i);return o.find(".modal-body").append((0,s.default)(n)),(0,s.default)("main").append(o),o.modal("show")}function y(e){var t={success:l,error:o}[e.type].format(e.body);return(0,s.default)(t)}var j={ezAlert:m,ezToast:h,ezQuery:g,ezProgressBar:v,ezBadge:y};t.default=j},"./CTFd/themes/core/assets/js/fetch.js":function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0,n("./node_modules/whatwg-fetch/fetch.js");var i,o=(i=n("./CTFd/themes/core/assets/js/config.js"))&&i.__esModule?i:{default:i};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/patch.js":function(e,t,n){var i,s=(i=n("./node_modules/q/q.js"))&&i.__esModule?i:{default:i},o=n("./CTFd/themes/core/assets/js/api.js");function r(t,e){var n,i=Object.keys(t);return Object.getOwnPropertySymbols&&(n=Object.getOwnPropertySymbols(t),e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),i.push.apply(i,n)),i}function a(o){for(var e=1;e>4*o&255).toString(16)).substr(-2)}return i},t.htmlEntities=function(e){return(0,r.default)("
").text(e).html()},t.cumulativeSum=function(e){for(var t=e.concat(),n=0;n'),(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 n=a(e,o),i=a(t,o);return r.default.isNumeric(n)&&r.default.isNumeric(i)?n-i:n.toString().localeCompare(i)}));this.asc=!this.asc,this.asc||(t=t.reverse());for(var n=0;n"+(0,u.htmlEntities)(window.CHALLENGE_NAME)+""),success:function(){m.default.fetch("/api/v1/challenges/"+window.CHALLENGE_ID,{method:"DELETE"}).then(function(e){return e.json()}).then(function(e){e.success&&(window.location=m.default.config.urlRoot+"/admin/challenges")})}})}),(0,f.default)("#challenge-update-container > form").submit(function(e){e.preventDefault();var n=(0,f.default)(e.target).serializeJSON(!0);m.default.fetch("/api/v1/challenges/"+window.CHALLENGE_ID+"/flags",{method:"GET",credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json"}}).then(function(e){return e.json()}).then(function(e){function t(){m.default.fetch("/api/v1/challenges/"+window.CHALLENGE_ID,{method:"PATCH",credentials:"same-origin",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify(n)}).then(function(e){return e.json()}).then(function(e){if(e.success){switch((0,f.default)(".challenge-state").text(e.data.state),e.data.state){case"visible":(0,f.default)(".challenge-state").removeClass("badge-danger").addClass("badge-success");break;case"hidden":(0,f.default)(".challenge-state").removeClass("badge-success").addClass("badge-danger")}(0,h.ezToast)({title:"Success",body:"Your challenge has been updated!"})}else{var t,n="";for(t in e.errors)n+=e.errors[t].join("\n"),n+="\n";(0,h.ezAlert)({title:"Error",body:n,button:"OK"})}})}0===e.data.length&&"visible"===n.state?(0,h.ezQuery)({title:"Missing Flags",body:"This challenge does not have any flags meaning it may be unsolveable. Are you sure you'd like to update this challenge?",success:t}):t()})}),(0,f.default)("#challenge-create-options form").submit(I),document.querySelector("#challenge-flags")&&(e=g.default.extend(y.default),t=document.createElement("div"),document.querySelector("#challenge-flags").appendChild(t),new e({propsData:{challenge_id:window.CHALLENGE_ID}}).$mount(t)),document.querySelector("#challenge-tags")&&(n=g.default.extend(_.default),i=document.createElement("div"),document.querySelector("#challenge-tags").appendChild(i),new n({propsData:{challenge_id:window.CHALLENGE_ID}}).$mount(i)),document.querySelector("#prerequisite-add-form")&&(o=g.default.extend(j.default),a=document.createElement("div"),document.querySelector("#prerequisite-add-form").appendChild(a),new o({propsData:{challenge_id:window.CHALLENGE_ID}}).$mount(a)),document.querySelector("#challenge-files")&&(r=g.default.extend(b.default),s=document.createElement("div"),document.querySelector("#challenge-files").appendChild(s),new r({propsData:{challenge_id:window.CHALLENGE_ID}}).$mount(s)),document.querySelector("#challenge-hints")&&(d=g.default.extend(T.default),l=document.createElement("div"),document.querySelector("#challenge-hints").appendChild(l),new d({propsData:{challenge_id:window.CHALLENGE_ID}}).$mount(l)),document.querySelector("#comment-box")&&(c=g.default.extend(v.default),p=document.createElement("div"),document.querySelector("#comment-box").appendChild(p),new c({propsData:{type:"challenge",id:window.CHALLENGE_ID}}).$mount(p)),f.default.get(m.default.config.urlRoot+"/api/v1/challenges/types",function(e){var t=e.data;E(t.standard),(0,f.default)("#create-chals-select input[name=type]").change(function(){E(t[this.value])})})})},"./CTFd/themes/admin/assets/js/pages/main.js":function(e,t,n){var i=f(n("./CTFd/themes/core/assets/js/CTFd.js")),o=f(n("./node_modules/jquery/dist/jquery.js")),a=f(n("./node_modules/dayjs/dayjs.min.js")),r=f(n("./node_modules/dayjs/plugin/advancedFormat.js")),s=f(n("./node_modules/nunjucks/browser/nunjucks.js")),d=n("./node_modules/howler/dist/howler.js"),l=f(n("./CTFd/themes/core/assets/js/events.js")),c=f(n("./CTFd/themes/core/assets/js/times.js")),p=f(n("./CTFd/themes/admin/assets/js/styles.js")),u=f(n("./CTFd/themes/core/assets/js/helpers.js"));function f(e){return e&&e.__esModule?e:{default:e}}a.default.extend(r.default),i.default.init(window.init),window.CTFd=i.default,window.helpers=u.default,window.$=o.default,window.dayjs=a.default,window.nunjucks=s.default,window.Howl=d.Howl,(0,o.default)(function(){(0,p.default)(),(0,c.default)(),(0,l.default)(i.default.config.urlRoot)})},"./CTFd/themes/admin/assets/js/styles.js":function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.showMediaLibrary=c,t.bindMarkdownEditor=p,t.bindMarkdownEditors=u,t.default=void 0,n("./node_modules/bootstrap/dist/js/bootstrap.bundle.js");var i=n("./CTFd/themes/core/assets/js/utils.js"),o=l(n("./node_modules/jquery/dist/jquery.js")),a=l(n("./node_modules/easymde/src/js/easymde.js")),r=l(n("./node_modules/vue/dist/vue.esm.browser.js")),s=l(n("./CTFd/themes/admin/assets/js/components/files/MediaLibrary.vue")),d=l(n("./node_modules/highlight.js/lib/index.js"));function l(e){return e&&e.__esModule?e:{default:e}}function c(e){var t=r.default.extend(s.default),n=document.createElement("div");document.querySelector("main").appendChild(n);var i=new t({propsData:{editor:e}}).$mount(n);(0,o.default)("#media-modal").on("hidden.bs.modal",function(e){i.$destroy(),(0,o.default)("#media-modal").remove()}),(0,o.default)("#media-modal").modal()}function p(e){var t;!1===e.hasOwnProperty("mde")&&(t=new a.default({autoDownloadFontAwesome:!1,toolbar:["bold","italic","heading","|","quote","unordered-list","ordered-list","|","link","image",{name:"media",action:function(e){c(e)},className:"fas fa-file-upload",title:"Media Library"},"|","preview","guide"],element:e,initialValue:(0,o.default)(e).val(),forceSync:!0,minHeight:"200px",renderingConfig:{codeSyntaxHighlighting:!0,hljs:d.default}}),e.mde=t,e.codemirror=t.codemirror,(0,o.default)(e).on("change keyup paste",function(){t.codemirror.getDoc().setValue((0,o.default)(e).val()),t.codemirror.refresh()}))}function u(){(0,o.default)("textarea.markdown").each(function(e,t){p(t)})}t.default=function(){(0,o.default)(":input").each(function(){(0,o.default)(this).data("initial",(0,o.default)(this).val())}),(0,o.default)(function(){(0,o.default)("tr[data-href], td[data-href]").click(function(){var e;return getSelection().toString()||(e=(0,o.default)(this).attr("data-href"))&&(window.location=e),!1}),(0,o.default)("[data-checkbox]").click(function(e){(0,o.default)(e.target).is("input[type=checkbox]")||(0,o.default)(this).find("input[type=checkbox]").click(),e.stopImmediatePropagation()}),(0,o.default)("[data-checkbox-all]").on("click change",function(e){var t=(0,o.default)(this).prop("checked"),n=(0,o.default)(this).index()+1;(0,o.default)(this).closest("table").find("tr td:nth-child(".concat(n,") input[type=checkbox]")).prop("checked",t),e.stopImmediatePropagation()}),(0,o.default)("tr[data-href] a, tr[data-href] button").click(function(e){(0,o.default)(this).attr("data-dismiss")||e.stopPropagation()}),(0,o.default)(".page-select").change(function(){var e=new URL(window.location);e.searchParams.set("page",this.value),window.location.href=e.toString()}),(0,o.default)('a[data-toggle="tab"]').on("shown.bs.tab",function(e){sessionStorage.setItem("activeTab",(0,o.default)(e.target).attr("href"))});var e,t=sessionStorage.getItem("activeTab");t&&((e=(0,o.default)('.nav-tabs a[href="'.concat(t,'"], .nav-pills a[href="').concat(t,'"]'))).length?e.tab("show"):sessionStorage.removeItem("activeTab")),u(),(0,i.makeSortableTables)(),(0,o.default)('[data-toggle="tooltip"]').tooltip(),document.querySelectorAll("pre code").forEach(function(e){d.default.highlightBlock(e)})})}},"./CTFd/themes/core/assets/js/CTFd.js":function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=l(n("./CTFd/themes/core/assets/js/fetch.js")),o=l(n("./CTFd/themes/core/assets/js/config.js")),a=n("./CTFd/themes/core/assets/js/api.js");n("./CTFd/themes/core/assets/js/patch.js");var r=l(n("./node_modules/markdown-it/index.js")),s=l(n("./node_modules/jquery/dist/jquery.js")),d=l(n("./CTFd/themes/core/assets/js/ezq.js"));function l(e){return e&&e.__esModule?e:{default:e}}function c(t,e){var n,i=Object.keys(t);return Object.getOwnPropertySymbols&&(n=Object.getOwnPropertySymbols(t),e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),i.push.apply(i,n)),i}function p(o){for(var e=1;e".concat(e.body,"

")):n.find(".modal-body").append((0,s.default)(e.body));var i=(0,s.default)(p.format(e.button));return e.success&&(0,s.default)(i).click(function(){e.success()}),e.large&&n.find(".modal-dialog").addClass("modal-lg"),n.find(".modal-footer").append(i),n.find("pre code").each(function(e){a.default.highlightBlock(this)}),(0,s.default)("main").append(n),n.modal("show"),(0,s.default)(n).on("hidden.bs.modal",function(){(0,s.default)(this).modal("dispose")}),n}function h(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,n=d.format(e.title,e.body),i=(0,s.default)(n);e.onclose&&(0,s.default)(i).find("button[data-dismiss=toast]").click(function(){e.onclose()}),e.onclick&&((t=(0,s.default)(i).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(i),i.toast({autohide:o,delay:r,animation:a}),i.toast("show"),i}function g(e){var t=r.format(e.title),n=(0,s.default)(t);"string"==typeof e.body?n.find(".modal-body").append("

".concat(e.body,"

")):n.find(".modal-body").append((0,s.default)(e.body));var i=(0,s.default)(f),o=(0,s.default)(u);return n.find(".modal-footer").append(o),n.find(".modal-footer").append(i),n.find("pre code").each(function(e){a.default.highlightBlock(this)}),(0,s.default)("main").append(n),(0,s.default)(n).on("hidden.bs.modal",function(){(0,s.default)(this).modal("dispose")}),(0,s.default)(i).click(function(){e.success()}),n.modal("show"),n}function v(e){if(e.target){var t=(0,s.default)(e.target);return t.find(".progress-bar").css("width",e.width+"%"),t}var n=l.format(e.width),i=r.format(e.title),o=(0,s.default)(i);return o.find(".modal-body").append((0,s.default)(n)),(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:m,ezToast:h,ezQuery:g,ezProgressBar:v,ezBadge:y};t.default=j},"./CTFd/themes/core/assets/js/fetch.js":function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0,n("./node_modules/whatwg-fetch/fetch.js");var i,o=(i=n("./CTFd/themes/core/assets/js/config.js"))&&i.__esModule?i:{default:i};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/patch.js":function(e,t,n){var i,s=(i=n("./node_modules/q/q.js"))&&i.__esModule?i:{default:i},o=n("./CTFd/themes/core/assets/js/api.js");function r(t,e){var n,i=Object.keys(t);return Object.getOwnPropertySymbols&&(n=Object.getOwnPropertySymbols(t),e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),i.push.apply(i,n)),i}function a(o){for(var e=1;e>4*o&255).toString(16)).substr(-2)}return i},t.htmlEntities=function(e){return(0,r.default)("
").text(e).html()},t.cumulativeSum=function(e){for(var t=e.concat(),n=0;n'),(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 n=a(e,o),i=a(t,o);return r.default.isNumeric(n)&&r.default.isNumeric(i)?n-i:n.toString().localeCompare(i)}));this.asc=!this.asc,this.asc||(t=t.reverse());for(var n=0;n".concat(e.body,"

")):i.find(".modal-body").append((0,s.default)(e.body));var o=(0,s.default)(l.format(e.button));return e.success&&(0,s.default)(o).click(function(){e.success()}),e.large&&i.find(".modal-dialog").addClass("modal-lg"),i.find(".modal-footer").append(o),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 h(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),o=(0,s.default)(i);e.onclose&&(0,s.default)(o).find("button[data-dismiss=toast]").click(function(){e.onclose()}),e.onclick&&((t=(0,s.default)(o).find(".toast-body")).addClass("cursor-pointer"),t.click(function(){e.onclick()}));var n=!1!==e.autohide,a=!1!==e.animation,r=e.delay||1e4;return(0,s.default)("#ezq--notifications-toast-container").prepend(o),o.toast({autohide:n,delay:r,animation:a}),o.toast("show"),o}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 o=(0,s.default)(f),n=(0,s.default)(u);return i.find(".modal-footer").append(n),i.find(".modal-footer").append(o),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)(o).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=c.format(e.width),o=r.format(e.title),n=(0,s.default)(o);return n.find(".modal-body").append((0,s.default)(i)),(0,s.default)("main").append(n),n.modal("show")}function j(e){var t={success:p,error:n}[e.type].format(e.body);return(0,s.default)(t)}var y={ezAlert:m,ezToast:h,ezQuery:g,ezProgressBar:v,ezBadge:j};t.default=y},"./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 o,n=(o=i("./CTFd/themes/core/assets/js/config.js"))&&o.__esModule?o:{default:o};var a=window.fetch;t.default=function(e,t){return void 0===t&&(t={method:"GET",credentials:"same-origin",headers:{}}),e=n.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"]=n.default.csrfNonce,a(e,t)}},"./CTFd/themes/core/assets/js/patch.js":function(e,t,i){var o,s=(o=i("./node_modules/q/q.js"))&&o.__esModule?o:{default:o},n=i("./CTFd/themes/core/assets/js/api.js");function r(t,e){var i,o=Object.keys(t);return Object.getOwnPropertySymbols&&(i=Object.getOwnPropertySymbols(t),e&&(i=i.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),o.push.apply(o,i)),o}function a(n){for(var e=1;e>4*n&255).toString(16)).substr(-2)}return o},t.htmlEntities=function(e){return(0,r.default)("
").text(e).html()},t.cumulativeSum=function(e){for(var t=e.concat(),i=0;i'),(0,r.default)("th.sort-col").click(function(){var n,e=(0,r.default)(this).parents("table").eq(0),t=e.find("tr:gt(0)").toArray().sort((n=(0,r.default)(this).index(),function(e,t){var i=a(e,n),o=a(t,n);return r.default.isNumeric(i)&&r.default.isNumeric(o)?i-o:i.toString().localeCompare(o)}));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 o=(0,s.default)(l.format(e.button));return e.success&&(0,s.default)(o).click(function(){e.success()}),e.large&&i.find(".modal-dialog").addClass("modal-lg"),i.find(".modal-footer").append(o),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 h(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),o=(0,s.default)(i);e.onclose&&(0,s.default)(o).find("button[data-dismiss=toast]").click(function(){e.onclose()}),e.onclick&&((t=(0,s.default)(o).find(".toast-body")).addClass("cursor-pointer"),t.click(function(){e.onclick()}));var n=!1!==e.autohide,a=!1!==e.animation,r=e.delay||1e4;return(0,s.default)("#ezq--notifications-toast-container").prepend(o),o.toast({autohide:n,delay:r,animation:a}),o.toast("show"),o}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 o=(0,s.default)(f),n=(0,s.default)(u);return i.find(".modal-footer").append(n),i.find(".modal-footer").append(o),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)(o).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=c.format(e.width),o=r.format(e.title),n=(0,s.default)(o);return n.find(".modal-body").append((0,s.default)(i)),(0,s.default)("main").append(n),n.modal("show")}function j(e){var t={success:p,error:n}[e.type].format(e.body);return(0,s.default)(t)}var y={ezAlert:m,ezToast:h,ezQuery:g,ezProgressBar:v,ezBadge:j};t.default=y},"./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 o,n=(o=i("./CTFd/themes/core/assets/js/config.js"))&&o.__esModule?o:{default:o};var a=window.fetch;t.default=function(e,t){return void 0===t&&(t={method:"GET",credentials:"same-origin",headers:{}}),e=n.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"]=n.default.csrfNonce,a(e,t)}},"./CTFd/themes/core/assets/js/patch.js":function(e,t,i){var o,s=(o=i("./node_modules/q/q.js"))&&o.__esModule?o:{default:o},n=i("./CTFd/themes/core/assets/js/api.js");function r(t,e){var i,o=Object.keys(t);return Object.getOwnPropertySymbols&&(i=Object.getOwnPropertySymbols(t),e&&(i=i.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),o.push.apply(o,i)),o}function a(n){for(var e=1;e>4*n&255).toString(16)).substr(-2)}return o},t.htmlEntities=function(e){return(0,r.default)("
").text(e).html()},t.cumulativeSum=function(e){for(var t=e.concat(),i=0;i'),(0,r.default)("th.sort-col").click(function(){var n,e=(0,r.default)(this).parents("table").eq(0),t=e.find("tr:gt(0)").toArray().sort((n=(0,r.default)(this).index(),function(e,t){var i=a(e,n),o=a(t,n);return r.default.isNumeric(i)&&r.default.isNumeric(o)?i-o:i.toString().localeCompare(o)}));this.asc=!this.asc,this.asc||(t=t.reverse());for(var i=0;i