├── .codecov.yml ├── .dockerignore ├── .eslintrc.js ├── .flaskenv ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE.md └── workflows │ ├── docker-build.yml │ ├── lint.yml │ ├── mariadb.yml │ ├── mysql.yml │ ├── mysql8.yml │ ├── postgres.yml │ └── sqlite.yml ├── .gitignore ├── .isort.cfg ├── .prettierignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── CTFd ├── __init__.py ├── admin │ ├── __init__.py │ ├── challenges.py │ ├── notifications.py │ ├── pages.py │ ├── scoreboard.py │ ├── statistics.py │ ├── submissions.py │ ├── teams.py │ └── users.py ├── api │ ├── __init__.py │ └── v1 │ │ ├── __init__.py │ │ ├── awards.py │ │ ├── brackets.py │ │ ├── challenges.py │ │ ├── comments.py │ │ ├── config.py │ │ ├── exports.py │ │ ├── files.py │ │ ├── flags.py │ │ ├── helpers │ │ ├── __init__.py │ │ ├── models.py │ │ ├── request.py │ │ └── schemas.py │ │ ├── hints.py │ │ ├── notifications.py │ │ ├── pages.py │ │ ├── schemas │ │ └── __init__.py │ │ ├── scoreboard.py │ │ ├── shares.py │ │ ├── statistics │ │ ├── __init__.py │ │ ├── challenges.py │ │ ├── scores.py │ │ ├── submissions.py │ │ ├── teams.py │ │ └── users.py │ │ ├── submissions.py │ │ ├── tags.py │ │ ├── teams.py │ │ ├── tokens.py │ │ ├── topics.py │ │ ├── unlocks.py │ │ └── users.py ├── auth.py ├── cache │ └── __init__.py ├── challenges.py ├── cli │ └── __init__.py ├── config.ini ├── config.py ├── constants │ ├── __init__.py │ ├── assets.py │ ├── config.py │ ├── languages.py │ ├── plugins.py │ ├── sessions.py │ ├── static.py │ ├── teams.py │ ├── themes.py │ └── users.py ├── errors.py ├── events │ └── __init__.py ├── exceptions │ └── __init__.py ├── fonts │ ├── OFL.txt │ └── OpenSans-Bold.ttf ├── forms │ ├── __init__.py │ ├── auth.py │ ├── awards.py │ ├── challenges.py │ ├── config.py │ ├── email.py │ ├── fields.py │ ├── notifications.py │ ├── pages.py │ ├── self.py │ ├── setup.py │ ├── submissions.py │ ├── teams.py │ └── users.py ├── logs │ └── .gitkeep ├── models │ └── __init__.py ├── plugins │ ├── __init__.py │ ├── challenges │ │ ├── __init__.py │ │ └── assets │ │ │ ├── create.html │ │ │ ├── create.js │ │ │ ├── update.html │ │ │ ├── update.js │ │ │ ├── view.html │ │ │ └── view.js │ ├── ctfd_owl │ │ ├── __init__.py │ │ ├── assets │ │ │ ├── configs.js │ │ │ ├── containers.js │ │ │ ├── create.html │ │ │ ├── create.js │ │ │ ├── update.html │ │ │ ├── update.js │ │ │ ├── view.html │ │ │ └── view.js │ │ ├── challenge_type.py │ │ ├── config.json │ │ ├── control_utils.py │ │ ├── db_utils.py │ │ ├── docker_utils.py │ │ ├── extensions.py │ │ ├── frp_utils.py │ │ ├── models.py │ │ ├── requirements.txt │ │ ├── setup.py │ │ └── templates │ │ │ ├── configs.html │ │ │ ├── configs │ │ │ ├── docker_settings.html │ │ │ └── frp_settings.html │ │ │ └── containers.html │ ├── ctfd_whale │ │ ├── __init__.py │ │ ├── api.py │ │ ├── assets │ │ │ ├── config.js │ │ │ ├── containers.js │ │ │ ├── create.html │ │ │ ├── create.js │ │ │ ├── update.html │ │ │ ├── update.js │ │ │ ├── view.html │ │ │ └── view.js │ │ ├── challenge_type.py │ │ ├── config.json │ │ ├── decorators.py │ │ ├── docs │ │ │ ├── advanced.md │ │ │ ├── advanced.zh-cn.md │ │ │ ├── imgs │ │ │ │ ├── arch.png │ │ │ │ ├── whale-config1.png │ │ │ │ ├── whale-config2.png │ │ │ │ └── whale-config3.png │ │ │ ├── install.md │ │ │ └── install.zh-cn.md │ │ ├── models.py │ │ ├── requirements.txt │ │ ├── templates │ │ │ ├── config │ │ │ │ ├── base.router.config.html │ │ │ │ ├── challenges.config.html │ │ │ │ ├── docker.config.html │ │ │ │ ├── frp.router.config.html │ │ │ │ ├── limits.config.html │ │ │ │ └── trp.router.config.html │ │ │ ├── containers │ │ │ │ ├── card.containers.html │ │ │ │ └── list.containers.html │ │ │ ├── whale_base.html │ │ │ ├── whale_config.html │ │ │ └── whale_containers.html │ │ └── utils │ │ │ ├── __init__.py │ │ │ ├── cache.py │ │ │ ├── checks.py │ │ │ ├── control.py │ │ │ ├── db.py │ │ │ ├── docker.py │ │ │ ├── exceptions.py │ │ │ ├── routers │ │ │ ├── __init__.py │ │ │ ├── base.py │ │ │ ├── frp.py │ │ │ └── trp.py │ │ │ └── setup.py │ ├── dynamic_challenges │ │ ├── .gitignore │ │ ├── README.md │ │ ├── __init__.py │ │ ├── assets │ │ │ ├── create.html │ │ │ ├── create.js │ │ │ ├── update.html │ │ │ ├── update.js │ │ │ ├── view.html │ │ │ └── view.js │ │ ├── decay.py │ │ ├── function.png │ │ └── migrations │ │ │ ├── b37fb68807ea_add_cascading_delete_to_dynamic_.py │ │ │ └── eb68f277ab61_add_func_column_to_dynamic_challenges.py │ ├── flags │ │ ├── __init__.py │ │ ├── assets │ │ │ ├── regex │ │ │ │ ├── create.html │ │ │ │ └── edit.html │ │ │ └── static │ │ │ │ ├── create.html │ │ │ │ └── edit.html │ │ └── tests │ │ │ ├── __init__.py │ │ │ └── test_flags.py │ └── migrations.py ├── schemas │ ├── __init__.py │ ├── awards.py │ ├── brackets.py │ ├── challenges.py │ ├── comments.py │ ├── config.py │ ├── fields.py │ ├── files.py │ ├── flags.py │ ├── hints.py │ ├── notifications.py │ ├── pages.py │ ├── submissions.py │ ├── tags.py │ ├── teams.py │ ├── tokens.py │ ├── topics.py │ ├── unlocks.py │ └── users.py ├── scoreboard.py ├── share.py ├── teams.py ├── themes │ ├── admin │ │ ├── assets │ │ │ ├── css │ │ │ │ ├── admin.scss │ │ │ │ ├── challenge-board.scss │ │ │ │ ├── codemirror.scss │ │ │ │ ├── fonts.scss │ │ │ │ ├── includes │ │ │ │ │ ├── award-icons.scss │ │ │ │ │ ├── easymde.scss │ │ │ │ │ ├── flag-icons.scss │ │ │ │ │ ├── jumbotron.css │ │ │ │ │ ├── min-height.scss │ │ │ │ │ ├── opacity.scss │ │ │ │ │ └── sticky-footer.css │ │ │ │ └── main.scss │ │ │ └── js │ │ │ │ ├── challenges │ │ │ │ ├── challenge.js │ │ │ │ ├── new.js │ │ │ │ └── tags.js │ │ │ │ ├── compat │ │ │ │ ├── CTFd.js │ │ │ │ ├── api.js │ │ │ │ ├── config.js │ │ │ │ ├── events.js │ │ │ │ ├── ezq.js │ │ │ │ ├── fetch.js │ │ │ │ ├── format.js │ │ │ │ ├── graphs.js │ │ │ │ ├── helpers.js │ │ │ │ ├── json.js │ │ │ │ ├── math.js │ │ │ │ ├── patch.js │ │ │ │ ├── styles.js │ │ │ │ ├── times.js │ │ │ │ ├── ui.js │ │ │ │ └── wc.js │ │ │ │ ├── components │ │ │ │ ├── comments │ │ │ │ │ └── CommentBox.vue │ │ │ │ ├── configs │ │ │ │ │ ├── brackets │ │ │ │ │ │ ├── Bracket.vue │ │ │ │ │ │ └── BracketList.vue │ │ │ │ │ └── fields │ │ │ │ │ │ ├── Field.vue │ │ │ │ │ │ └── FieldList.vue │ │ │ │ ├── files │ │ │ │ │ ├── ChallengeFilesList.vue │ │ │ │ │ └── MediaLibrary.vue │ │ │ │ ├── flags │ │ │ │ │ ├── FlagCreationForm.vue │ │ │ │ │ ├── FlagEditForm.vue │ │ │ │ │ └── FlagList.vue │ │ │ │ ├── hints │ │ │ │ │ ├── HintCreationForm.vue │ │ │ │ │ ├── HintEditForm.vue │ │ │ │ │ └── HintsList.vue │ │ │ │ ├── next │ │ │ │ │ └── NextChallenge.vue │ │ │ │ ├── notifications │ │ │ │ │ └── Notification.vue │ │ │ │ ├── requirements │ │ │ │ │ └── Requirements.vue │ │ │ │ ├── tags │ │ │ │ │ └── TagsList.vue │ │ │ │ ├── teams │ │ │ │ │ └── UserAddForm.vue │ │ │ │ └── topics │ │ │ │ │ └── TopicsList.vue │ │ │ │ ├── pages │ │ │ │ ├── challenge.js │ │ │ │ ├── challenges.js │ │ │ │ ├── configs.js │ │ │ │ ├── editor.js │ │ │ │ ├── events.js │ │ │ │ ├── main.js │ │ │ │ ├── notifications.js │ │ │ │ ├── pages.js │ │ │ │ ├── reset.js │ │ │ │ ├── scoreboard.js │ │ │ │ ├── statistics.js │ │ │ │ ├── style.js │ │ │ │ ├── submissions.js │ │ │ │ ├── team.js │ │ │ │ ├── teams.js │ │ │ │ ├── user.js │ │ │ │ └── users.js │ │ │ │ ├── styles.js │ │ │ │ ├── templates │ │ │ │ └── admin-flags-table.njk │ │ │ │ └── timezones.js │ │ ├── package.json │ │ ├── static │ │ │ ├── assets │ │ │ │ ├── CommentBox-B45_juxF.js │ │ │ │ ├── CommentBox-Cv-MSlYY.css │ │ │ │ ├── admin-css-Bj5aeLSk.css │ │ │ │ ├── challenge-DY7T5JQl.css │ │ │ │ ├── challenge-board-css-CpAEjUPb.css │ │ │ │ ├── codemirror-css-DRHJUI8W.css │ │ │ │ ├── echarts-l0sNRNKZ.js │ │ │ │ ├── echarts.common-KFqNeB6w.js │ │ │ │ ├── fonts-css-B0NUqHPX.css │ │ │ │ ├── graphs-DV-0EwZa.js │ │ │ │ ├── htmlmixed-CUbKEe1Y.js │ │ │ │ ├── main-css-CoszOyzj.css │ │ │ │ ├── pages │ │ │ │ │ ├── challenge-CAteT9hJ.js │ │ │ │ │ ├── challenges-XAOKcUfv.js │ │ │ │ │ ├── configs-CJmOQB5a.js │ │ │ │ │ ├── editor-DBDZT6WK.js │ │ │ │ │ ├── main-D_lcMXdT.js │ │ │ │ │ ├── notifications-Cl7lQJK1.js │ │ │ │ │ ├── pages-D6wLDtJe.js │ │ │ │ │ ├── reset-BblvWpk1.js │ │ │ │ │ ├── scoreboard-CgiV4dwR.js │ │ │ │ │ ├── statistics-DaniS7xQ.js │ │ │ │ │ ├── submissions-Cceg-8dz.js │ │ │ │ │ ├── team-Ciwsd6gS.js │ │ │ │ │ ├── teams-DUq0yf4w.js │ │ │ │ │ ├── user-B8_zsUV2.js │ │ │ │ │ └── users-CemV7DCK.js │ │ │ │ └── tab-B9vzLN1E.js │ │ │ ├── img │ │ │ │ ├── README.md │ │ │ │ ├── favicon.ico │ │ │ │ └── logo.png │ │ │ ├── js │ │ │ │ └── jquery.min.js │ │ │ ├── manifest.json │ │ │ ├── sounds │ │ │ │ ├── README.md │ │ │ │ ├── notification.mp3 │ │ │ │ └── notification.webm │ │ │ └── webfonts │ │ │ │ ├── fa-brands-400.ttf │ │ │ │ ├── fa-brands-400.woff2 │ │ │ │ ├── fa-regular-400.ttf │ │ │ │ ├── fa-regular-400.woff2 │ │ │ │ ├── fa-solid-900.ttf │ │ │ │ ├── fa-solid-900.woff2 │ │ │ │ ├── fa-v4compatibility.ttf │ │ │ │ ├── fa-v4compatibility.woff2 │ │ │ │ ├── lato-latin-400-normal.woff │ │ │ │ ├── lato-latin-400-normal.woff2 │ │ │ │ ├── lato-latin-700-normal.woff │ │ │ │ ├── lato-latin-700-normal.woff2 │ │ │ │ ├── lato-latin-ext-400-normal.woff │ │ │ │ ├── lato-latin-ext-400-normal.woff2 │ │ │ │ ├── lato-latin-ext-700-normal.woff │ │ │ │ ├── lato-latin-ext-700-normal.woff2 │ │ │ │ ├── raleway-cyrillic-500-normal.woff │ │ │ │ ├── raleway-cyrillic-500-normal.woff2 │ │ │ │ ├── raleway-cyrillic-ext-500-normal.woff │ │ │ │ ├── raleway-cyrillic-ext-500-normal.woff2 │ │ │ │ ├── raleway-latin-500-normal.woff │ │ │ │ ├── raleway-latin-500-normal.woff2 │ │ │ │ ├── raleway-latin-ext-500-normal.woff │ │ │ │ ├── raleway-latin-ext-500-normal.woff2 │ │ │ │ ├── raleway-vietnamese-500-normal.woff │ │ │ │ └── raleway-vietnamese-500-normal.woff2 │ │ ├── templates │ │ │ ├── base.html │ │ │ ├── challenges │ │ │ │ ├── challenge.html │ │ │ │ ├── challenges.html │ │ │ │ ├── create.html │ │ │ │ ├── new.html │ │ │ │ ├── preview.html │ │ │ │ └── update.html │ │ │ ├── config.html │ │ │ ├── configs │ │ │ │ ├── accounts.html │ │ │ │ ├── backup.html │ │ │ │ ├── brackets.html │ │ │ │ ├── email.html │ │ │ │ ├── fields.html │ │ │ │ ├── general.html │ │ │ │ ├── legal.html │ │ │ │ ├── localization.html │ │ │ │ ├── logo.html │ │ │ │ ├── mlc.html │ │ │ │ ├── pause.html │ │ │ │ ├── registration_code.html │ │ │ │ ├── robots.html │ │ │ │ ├── sanitize.html │ │ │ │ ├── social.html │ │ │ │ ├── theme.html │ │ │ │ ├── time.html │ │ │ │ ├── usermode.html │ │ │ │ └── visibility.html │ │ │ ├── editor.html │ │ │ ├── import.html │ │ │ ├── integrations.html │ │ │ ├── macros │ │ │ │ └── forms.html │ │ │ ├── modals │ │ │ │ ├── awards │ │ │ │ │ └── create.html │ │ │ │ ├── challenges │ │ │ │ │ ├── challenges.html │ │ │ │ │ ├── files.html │ │ │ │ │ ├── flags.html │ │ │ │ │ ├── hints.html │ │ │ │ │ ├── next.html │ │ │ │ │ ├── requirements.html │ │ │ │ │ ├── solves.html │ │ │ │ │ ├── tags.html │ │ │ │ │ └── topics.html │ │ │ │ ├── mail │ │ │ │ │ └── send.html │ │ │ │ ├── teams │ │ │ │ │ ├── addresses.html │ │ │ │ │ ├── captain.html │ │ │ │ │ ├── create.html │ │ │ │ │ ├── edit.html │ │ │ │ │ └── statistics.html │ │ │ │ └── users │ │ │ │ │ ├── addresses.html │ │ │ │ │ ├── create.html │ │ │ │ │ ├── edit.html │ │ │ │ │ └── statistics.html │ │ │ ├── notifications.html │ │ │ ├── page.html │ │ │ ├── pages.html │ │ │ ├── reset.html │ │ │ ├── scoreboard.html │ │ │ ├── scoreboard │ │ │ │ ├── standings.html │ │ │ │ └── users.html │ │ │ ├── statistics.html │ │ │ ├── submissions.html │ │ │ ├── teams │ │ │ │ ├── new.html │ │ │ │ ├── team.html │ │ │ │ └── teams.html │ │ │ └── users │ │ │ │ ├── new.html │ │ │ │ ├── user.html │ │ │ │ └── users.html │ │ ├── vite.config.js │ │ └── yarn.lock │ ├── core-beta │ │ ├── .github │ │ │ └── workflows │ │ │ │ ├── build.yml │ │ │ │ └── prettier.yml │ │ ├── .gitignore │ │ ├── .prettierignore │ │ ├── .prettierrc.json │ │ ├── LICENSE │ │ ├── README.md │ │ ├── assets │ │ │ ├── img │ │ │ │ └── favicon.ico │ │ │ ├── js │ │ │ │ ├── challenges.js │ │ │ │ ├── color_mode_switcher.js │ │ │ │ ├── index.js │ │ │ │ ├── notifications.js │ │ │ │ ├── page.js │ │ │ │ ├── scoreboard.js │ │ │ │ ├── settings.js │ │ │ │ ├── setup.js │ │ │ │ ├── teams │ │ │ │ │ ├── list.js │ │ │ │ │ ├── private.js │ │ │ │ │ └── public.js │ │ │ │ ├── theme │ │ │ │ │ ├── highlight.js │ │ │ │ │ ├── styles.js │ │ │ │ │ └── times.js │ │ │ │ ├── users │ │ │ │ │ ├── list.js │ │ │ │ │ ├── private.js │ │ │ │ │ └── public.js │ │ │ │ └── utils │ │ │ │ │ ├── alerts.js │ │ │ │ │ ├── clipboard.js │ │ │ │ │ ├── collapse.js │ │ │ │ │ ├── graphs │ │ │ │ │ ├── echarts │ │ │ │ │ │ ├── categories.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── scoreboard.js │ │ │ │ │ │ ├── solve-percentage.js │ │ │ │ │ │ └── userscore.js │ │ │ │ │ └── vega │ │ │ │ │ │ ├── categories.js │ │ │ │ │ │ ├── scoreboard.js │ │ │ │ │ │ ├── solve-percentage.js │ │ │ │ │ │ └── userscore.js │ │ │ │ │ ├── math.js │ │ │ │ │ ├── notifications │ │ │ │ │ ├── alerts.js │ │ │ │ │ ├── read.js │ │ │ │ │ └── toasts.js │ │ │ │ │ ├── objects.js │ │ │ │ │ └── tooltips.js │ │ │ └── scss │ │ │ │ ├── includes │ │ │ │ ├── components │ │ │ │ │ ├── _challenge.scss │ │ │ │ │ ├── _graphs.scss │ │ │ │ │ ├── _jumbotron.scss │ │ │ │ │ ├── _sticky-footer.scss │ │ │ │ │ └── _table.scss │ │ │ │ ├── icons │ │ │ │ │ ├── _award-icons.scss │ │ │ │ │ └── _flag-icons.scss │ │ │ │ └── utils │ │ │ │ │ ├── _cursors.scss │ │ │ │ │ ├── _fonts.scss │ │ │ │ │ ├── _lolight.scss │ │ │ │ │ ├── _min-height.scss │ │ │ │ │ └── _opacity.scss │ │ │ │ └── main.scss │ │ ├── package.json │ │ ├── postcss.config.js │ │ ├── static │ │ │ ├── assets │ │ │ │ ├── challenges.369de531.js │ │ │ │ ├── clipboard.0c9c5ddd.js │ │ │ │ ├── color_mode_switcher.52334129.js │ │ │ │ ├── echarts.128204f2.js │ │ │ │ ├── index.1cf73b05.js │ │ │ │ ├── index.2e31e3b8.js │ │ │ │ ├── main.0c7144ba.css │ │ │ │ ├── notifications.91eecfcb.js │ │ │ │ ├── page.3c5083de.js │ │ │ │ ├── scoreboard.b1c04d97.js │ │ │ │ ├── settings.64728c4b.js │ │ │ │ ├── setup.afceeb60.js │ │ │ │ ├── teams_list.22e04d3a.js │ │ │ │ ├── teams_private.32f15dd7.js │ │ │ │ ├── teams_public.621a4659.js │ │ │ │ ├── users_list.e03972e4.js │ │ │ │ ├── users_private.bfcc0675.js │ │ │ │ ├── users_public.158851db.js │ │ │ │ └── userscore.32000323.js │ │ │ ├── img │ │ │ │ └── favicon.ico │ │ │ ├── manifest.json │ │ │ └── webfonts │ │ │ │ ├── fa-brands-400.ttf │ │ │ │ ├── fa-brands-400.woff2 │ │ │ │ ├── fa-regular-400.ttf │ │ │ │ ├── fa-regular-400.woff2 │ │ │ │ ├── fa-solid-900.ttf │ │ │ │ ├── fa-solid-900.woff2 │ │ │ │ ├── fa-v4compatibility.ttf │ │ │ │ ├── fa-v4compatibility.woff2 │ │ │ │ ├── lato-all-400-normal.woff │ │ │ │ ├── lato-all-700-normal.woff │ │ │ │ ├── lato-latin-400-normal.woff │ │ │ │ ├── lato-latin-400-normal.woff2 │ │ │ │ ├── lato-latin-700-normal.woff │ │ │ │ ├── lato-latin-700-normal.woff2 │ │ │ │ ├── lato-latin-ext-400-normal.woff │ │ │ │ ├── lato-latin-ext-400-normal.woff2 │ │ │ │ ├── lato-latin-ext-700-normal.woff │ │ │ │ ├── lato-latin-ext-700-normal.woff2 │ │ │ │ ├── raleway-all-400-normal.woff │ │ │ │ ├── raleway-cyrillic-400-normal.woff │ │ │ │ ├── raleway-cyrillic-400-normal.woff2 │ │ │ │ ├── raleway-cyrillic-ext-400-normal.woff │ │ │ │ ├── raleway-cyrillic-ext-400-normal.woff2 │ │ │ │ ├── raleway-latin-400-normal.woff │ │ │ │ ├── raleway-latin-400-normal.woff2 │ │ │ │ ├── raleway-latin-ext-400-normal.woff │ │ │ │ ├── raleway-latin-ext-400-normal.woff2 │ │ │ │ ├── raleway-vietnamese-400-normal.woff │ │ │ │ └── raleway-vietnamese-400-normal.woff2 │ │ ├── templates │ │ │ ├── base.html │ │ │ ├── challenge.html │ │ │ ├── challenges.html │ │ │ ├── components │ │ │ │ ├── errors.html │ │ │ │ ├── navbar.html │ │ │ │ └── notifications.html │ │ │ ├── config.html │ │ │ ├── confirm.html │ │ │ ├── errors │ │ │ │ ├── 403.html │ │ │ │ ├── 404.html │ │ │ │ ├── 429.html │ │ │ │ ├── 500.html │ │ │ │ └── 502.html │ │ │ ├── login.html │ │ │ ├── macros │ │ │ │ └── forms.html │ │ │ ├── notifications.html │ │ │ ├── page.html │ │ │ ├── register.html │ │ │ ├── reset_password.html │ │ │ ├── scoreboard.html │ │ │ ├── settings.html │ │ │ ├── setup.html │ │ │ ├── teams │ │ │ │ ├── invite.html │ │ │ │ ├── join_team.html │ │ │ │ ├── new_team.html │ │ │ │ ├── private.html │ │ │ │ ├── public.html │ │ │ │ ├── team_enrollment.html │ │ │ │ └── teams.html │ │ │ └── users │ │ │ │ ├── private.html │ │ │ │ ├── public.html │ │ │ │ └── users.html │ │ ├── vite.config.js │ │ └── yarn.lock │ └── core │ │ ├── assets │ │ ├── css │ │ │ ├── challenge-board.scss │ │ │ ├── codemirror.scss │ │ │ ├── core.scss │ │ │ ├── fonts.scss │ │ │ ├── includes │ │ │ │ ├── award-icons.scss │ │ │ │ ├── flag-icons.scss │ │ │ │ ├── jumbotron.css │ │ │ │ ├── sticky-footer.css │ │ │ │ └── utils │ │ │ │ │ ├── min-height.scss │ │ │ │ │ └── opacity.scss │ │ │ └── main.scss │ │ └── js │ │ │ ├── CTFd.js │ │ │ ├── api.js │ │ │ ├── config.js │ │ │ ├── events.js │ │ │ ├── ezq.js │ │ │ ├── fetch.js │ │ │ ├── graphs.js │ │ │ ├── helpers.js │ │ │ ├── pages │ │ │ ├── challenges.js │ │ │ ├── events.js │ │ │ ├── main.js │ │ │ ├── notifications.js │ │ │ ├── scoreboard.js │ │ │ ├── settings.js │ │ │ ├── setup.js │ │ │ ├── stats.js │ │ │ ├── style.js │ │ │ └── teams │ │ │ │ └── private.js │ │ │ ├── patch.js │ │ │ ├── styles.js │ │ │ ├── times.js │ │ │ └── utils.js │ │ ├── static │ │ ├── css │ │ │ ├── challenge-board.dev.css │ │ │ ├── challenge-board.min.css │ │ │ ├── codemirror.dev.css │ │ │ ├── codemirror.min.css │ │ │ ├── core.dev.css │ │ │ ├── core.min.css │ │ │ ├── fonts.dev.css │ │ │ ├── fonts.min.css │ │ │ ├── main.dev.css │ │ │ └── main.min.css │ │ ├── fonts │ │ │ ├── fa-brands-400.eot │ │ │ ├── fa-brands-400.svg │ │ │ ├── fa-brands-400.ttf │ │ │ ├── fa-brands-400.woff │ │ │ ├── fa-brands-400.woff2 │ │ │ ├── fa-regular-400.eot │ │ │ ├── fa-regular-400.svg │ │ │ ├── fa-regular-400.ttf │ │ │ ├── fa-regular-400.woff │ │ │ ├── fa-regular-400.woff2 │ │ │ ├── fa-solid-900.eot │ │ │ ├── fa-solid-900.svg │ │ │ ├── fa-solid-900.ttf │ │ │ ├── fa-solid-900.woff │ │ │ ├── fa-solid-900.woff2 │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.svg │ │ │ ├── fontawesome-webfont.ttf │ │ │ ├── fontawesome-webfont.woff │ │ │ ├── fontawesome-webfont.woff2 │ │ │ ├── lato-latin-100.woff │ │ │ ├── lato-latin-100.woff2 │ │ │ ├── lato-latin-100italic.woff │ │ │ ├── lato-latin-100italic.woff2 │ │ │ ├── lato-latin-300.woff │ │ │ ├── lato-latin-300.woff2 │ │ │ ├── lato-latin-300italic.woff │ │ │ ├── lato-latin-300italic.woff2 │ │ │ ├── lato-latin-400.woff │ │ │ ├── lato-latin-400.woff2 │ │ │ ├── lato-latin-400italic.woff │ │ │ ├── lato-latin-400italic.woff2 │ │ │ ├── lato-latin-700.woff │ │ │ ├── lato-latin-700.woff2 │ │ │ ├── lato-latin-700italic.woff │ │ │ ├── lato-latin-700italic.woff2 │ │ │ ├── lato-latin-900.woff │ │ │ ├── lato-latin-900.woff2 │ │ │ ├── lato-latin-900italic.woff │ │ │ ├── lato-latin-900italic.woff2 │ │ │ ├── raleway-latin-100.woff │ │ │ ├── raleway-latin-100.woff2 │ │ │ ├── raleway-latin-100italic.woff │ │ │ ├── raleway-latin-100italic.woff2 │ │ │ ├── raleway-latin-200.woff │ │ │ ├── raleway-latin-200.woff2 │ │ │ ├── raleway-latin-200italic.woff │ │ │ ├── raleway-latin-200italic.woff2 │ │ │ ├── raleway-latin-300.woff │ │ │ ├── raleway-latin-300.woff2 │ │ │ ├── raleway-latin-300italic.woff │ │ │ ├── raleway-latin-300italic.woff2 │ │ │ ├── raleway-latin-400.woff │ │ │ ├── raleway-latin-400.woff2 │ │ │ ├── raleway-latin-400italic.woff │ │ │ ├── raleway-latin-400italic.woff2 │ │ │ ├── raleway-latin-500.woff │ │ │ ├── raleway-latin-500.woff2 │ │ │ ├── raleway-latin-500italic.woff │ │ │ ├── raleway-latin-500italic.woff2 │ │ │ ├── raleway-latin-600.woff │ │ │ ├── raleway-latin-600.woff2 │ │ │ ├── raleway-latin-600italic.woff │ │ │ ├── raleway-latin-600italic.woff2 │ │ │ ├── raleway-latin-700.woff │ │ │ ├── raleway-latin-700.woff2 │ │ │ ├── raleway-latin-700italic.woff │ │ │ ├── raleway-latin-700italic.woff2 │ │ │ ├── raleway-latin-800.woff │ │ │ ├── raleway-latin-800.woff2 │ │ │ ├── raleway-latin-800italic.woff │ │ │ ├── raleway-latin-800italic.woff2 │ │ │ ├── raleway-latin-900.woff │ │ │ ├── raleway-latin-900.woff2 │ │ │ ├── raleway-latin-900italic.woff │ │ │ └── raleway-latin-900italic.woff2 │ │ ├── img │ │ │ ├── ctfd.ai │ │ │ ├── ctfd.svg │ │ │ ├── ctfd_transfer.svg │ │ │ ├── favicon.ico │ │ │ ├── logo.png │ │ │ ├── logo_old.png │ │ │ └── scoreboard.png │ │ ├── js │ │ │ ├── core.dev.js │ │ │ ├── core.min.js │ │ │ ├── echarts.bundle.dev.js │ │ │ ├── echarts.bundle.min.js │ │ │ ├── helpers.dev.js │ │ │ ├── helpers.min.js │ │ │ ├── pages │ │ │ │ ├── challenges.dev.js │ │ │ │ ├── challenges.min.js │ │ │ │ ├── main.dev.js │ │ │ │ ├── main.min.js │ │ │ │ ├── notifications.dev.js │ │ │ │ ├── notifications.min.js │ │ │ │ ├── scoreboard.dev.js │ │ │ │ ├── scoreboard.min.js │ │ │ │ ├── settings.dev.js │ │ │ │ ├── settings.min.js │ │ │ │ ├── setup.dev.js │ │ │ │ ├── setup.min.js │ │ │ │ ├── stats.dev.js │ │ │ │ ├── stats.min.js │ │ │ │ └── teams │ │ │ │ │ ├── private.dev.js │ │ │ │ │ └── private.min.js │ │ │ ├── vendor.bundle.dev.js │ │ │ └── vendor.bundle.min.js │ │ └── sounds │ │ │ ├── README.md │ │ │ ├── notification.mp3 │ │ │ └── notification.webm │ │ └── templates │ │ ├── base.html │ │ ├── challenge.html │ │ ├── challenges.html │ │ ├── components │ │ ├── errors.html │ │ └── navbar.html │ │ ├── config.html │ │ ├── confirm.html │ │ ├── errors │ │ ├── 403.html │ │ ├── 404.html │ │ ├── 429.html │ │ ├── 500.html │ │ └── 502.html │ │ ├── login.html │ │ ├── macros │ │ └── forms.html │ │ ├── notifications.html │ │ ├── page.html │ │ ├── register.html │ │ ├── reset_password.html │ │ ├── scoreboard.html │ │ ├── settings.html │ │ ├── setup.html │ │ ├── teams │ │ ├── invite.html │ │ ├── join_team.html │ │ ├── new_team.html │ │ ├── private.html │ │ ├── public.html │ │ ├── team_enrollment.html │ │ └── teams.html │ │ └── users │ │ ├── private.html │ │ ├── public.html │ │ └── users.html ├── translations │ ├── ar │ │ └── LC_MESSAGES │ │ │ ├── messages.mo │ │ │ └── messages.po │ ├── ca │ │ └── LC_MESSAGES │ │ │ ├── messages.mo │ │ │ └── messages.po │ ├── de │ │ └── LC_MESSAGES │ │ │ ├── messages.mo │ │ │ └── messages.po │ ├── es │ │ └── LC_MESSAGES │ │ │ ├── messages.mo │ │ │ └── messages.po │ ├── fr │ │ └── LC_MESSAGES │ │ │ ├── messages.mo │ │ │ └── messages.po │ ├── it │ │ └── LC_MESSAGES │ │ │ ├── messages.mo │ │ │ └── messages.po │ ├── ja │ │ └── LC_MESSAGES │ │ │ ├── messages.mo │ │ │ └── messages.po │ ├── ko │ │ └── LC_MESSAGES │ │ │ ├── messages.mo │ │ │ └── messages.po │ ├── pl │ │ └── LC_MESSAGES │ │ │ ├── messages.mo │ │ │ └── messages.po │ ├── pt_BR │ │ └── LC_MESSAGES │ │ │ ├── messages.mo │ │ │ └── messages.po │ ├── ru │ │ └── LC_MESSAGES │ │ │ ├── messages.mo │ │ │ └── messages.po │ ├── sk │ │ └── LC_MESSAGES │ │ │ ├── messages.mo │ │ │ └── messages.po │ ├── uz │ │ └── LC_MESSAGES │ │ │ ├── messages.mo │ │ │ └── messages.po │ ├── vi │ │ └── LC_MESSAGES │ │ │ ├── messages.mo │ │ │ └── messages.po │ ├── zh_Hans_CN │ │ └── LC_MESSAGES │ │ │ ├── messages.mo │ │ │ └── messages.po │ └── zh_Hant_TW │ │ └── LC_MESSAGES │ │ ├── messages.mo │ │ └── messages.po ├── uploads │ └── .gitkeep ├── users.py ├── utils │ ├── __init__.py │ ├── challenges │ │ └── __init__.py │ ├── config │ │ ├── __init__.py │ │ ├── integrations.py │ │ ├── pages.py │ │ └── visibility.py │ ├── countries │ │ ├── __init__.py │ │ └── geoip.py │ ├── crypto │ │ └── __init__.py │ ├── csv │ │ └── __init__.py │ ├── dates │ │ └── __init__.py │ ├── decorators │ │ ├── __init__.py │ │ ├── modes.py │ │ └── visibility.py │ ├── email │ │ ├── __init__.py │ │ ├── mailgun.py │ │ ├── providers │ │ │ ├── __init__.py │ │ │ ├── mailgun.py │ │ │ └── smtp.py │ │ └── smtp.py │ ├── encoding │ │ └── __init__.py │ ├── events │ │ └── __init__.py │ ├── exports │ │ ├── __init__.py │ │ ├── databases.py │ │ ├── freeze.py │ │ └── serializers.py │ ├── formatters │ │ └── __init__.py │ ├── health │ │ └── __init__.py │ ├── helpers │ │ ├── __init__.py │ │ └── models.py │ ├── humanize │ │ ├── __init__.py │ │ ├── numbers.py │ │ └── words.py │ ├── initialization │ │ └── __init__.py │ ├── logging │ │ └── __init__.py │ ├── migrations │ │ └── __init__.py │ ├── modes │ │ └── __init__.py │ ├── notifications │ │ └── __init__.py │ ├── plugins │ │ └── __init__.py │ ├── scores │ │ └── __init__.py │ ├── security │ │ ├── __init__.py │ │ ├── auth.py │ │ ├── csrf.py │ │ ├── passwords.py │ │ ├── sanitize.py │ │ └── signing.py │ ├── sessions │ │ └── __init__.py │ ├── social │ │ └── __init__.py │ ├── updates │ │ └── __init__.py │ ├── uploads │ │ ├── __init__.py │ │ └── uploaders.py │ ├── user │ │ └── __init__.py │ └── validators │ │ └── __init__.py └── views.py ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── SECURITY.md ├── Vagrantfile ├── babel.cfg ├── conf └── nginx │ └── http.conf ├── crowdin.yml ├── development.txt ├── docker-compose.yml ├── docker-entrypoint.sh ├── export.py ├── frpc └── frpc.ini ├── frps ├── 404.html └── frps.ini ├── import.py ├── install.sh ├── linting.txt ├── manage.py ├── messages.pot ├── migrations ├── 1_2_0_upgrade_2_0_0.py ├── alembic.ini ├── env.py ├── script.py.mako └── versions │ ├── 0366ba6575ca_add_table_for_comments.py │ ├── 07dfbe5e1edc_add_format_to_pages.py │ ├── 080d29b15cd3_add_tokens_table.py │ ├── 0def790057c1_add_language_column_to_users_table.py │ ├── 1093835a1051_add_default_email_templates.py │ ├── 46a278193a94_enable_millisecond_precision_in_mysql_.py │ ├── 4d3c1b59d011_add_next_id_to_challenges_table.py │ ├── 4e4d5a9ea000_add_type_to_awards.py │ ├── 4fe3eeed9a9d_add_attribution_to_challenges.py │ ├── 5c4996aeb2cb_add_sha1sum_field_to_files_require_.py │ ├── 6012fe8de495_add_connection_info_column_to_challenges.py │ ├── 75e8ab9a0014_add_fields_and_fieldentries_tables.py │ ├── 8369118943a1_initial_revision.py │ ├── 9889b8c53673_add_brackets_table.py │ ├── 9e6f6578ca84_add_description_column_to_tokens_table.py │ ├── a02c5bf43407_add_link_target_to_pages.py │ ├── a03403986a32_add_theme_code_injections_to_configs.py │ ├── b295b033364d_add_ondelete_cascade_to_foreign_keys.py │ ├── b5551cd26764_add_captain_column_to_teams.py │ └── ef87d69ec29a_add_topics_and_challenge_topics_tables.py ├── package.json ├── ping.py ├── populate.py ├── prepare.sh ├── requirements.in ├── requirements.txt ├── scripts ├── install_docker.sh └── pip-compile.sh ├── sed.sh ├── serve.py ├── setup.cfg ├── tests ├── __init__.py ├── admin │ ├── __init__.py │ ├── test_challenges.py │ ├── test_config.py │ ├── test_csv.py │ ├── test_fields.py │ ├── test_notifications.py │ ├── test_pages.py │ ├── test_scoreboard.py │ ├── test_statistics.py │ ├── test_submissions.py │ ├── test_teams.py │ ├── test_users.py │ └── test_views.py ├── api │ ├── __init__.py │ ├── test_tokens.py │ └── v1 │ │ ├── __init__.py │ │ ├── challenges │ │ └── requirements │ │ │ └── test_requirements.py │ │ ├── statistics │ │ ├── __init__.py │ │ └── test_scores.py │ │ ├── teams │ │ ├── __init__.py │ │ ├── test_scoring.py │ │ ├── test_team_members.py │ │ └── test_teams.py │ │ ├── test_awards.py │ │ ├── test_brackets.py │ │ ├── test_challenges.py │ │ ├── test_comments.py │ │ ├── test_config.py │ │ ├── test_csrf.py │ │ ├── test_exports.py │ │ ├── test_fields.py │ │ ├── test_files.py │ │ ├── test_flags.py │ │ ├── test_hints.py │ │ ├── test_notifications.py │ │ ├── test_pages.py │ │ ├── test_scoreboard.py │ │ ├── test_submissions.py │ │ ├── test_tags.py │ │ ├── test_teams.py │ │ ├── test_tokens.py │ │ ├── test_topics.py │ │ ├── test_users.py │ │ ├── user │ │ ├── __init__.py │ │ ├── test_admin_access.py │ │ ├── test_challenges.py │ │ └── test_hints.py │ │ └── users │ │ ├── __init__.py │ │ ├── test_scoring.py │ │ └── test_users.py ├── brackets │ └── test_brackets.py ├── cache │ ├── __init__.py │ ├── test_cache.py │ └── test_challenges.py ├── challenges │ ├── __init__.py │ ├── test_challenge_types.py │ └── test_dynamic.py ├── constants │ ├── test_constants.py │ └── time.py ├── helpers.py ├── models │ └── test_model_utils.py ├── oauth │ ├── __init__.py │ ├── test_redirect.py │ ├── test_teams.py │ └── test_users.py ├── teams │ ├── __init__.py │ ├── test_auth.py │ ├── test_challenges.py │ ├── test_fields.py │ ├── test_hidden_team_scores.py │ ├── test_hints.py │ ├── test_invites.py │ ├── test_scoreboard.py │ └── test_teams.py ├── test_config.py ├── test_legal.py ├── test_plugin_utils.py ├── test_setup.py ├── test_share.py ├── test_themes.py ├── test_views.py ├── users │ ├── __init__.py │ ├── test_auth.py │ ├── test_challenges.py │ ├── test_fields.py │ ├── test_hints.py │ ├── test_profile.py │ ├── test_scoreboard.py │ ├── test_settings.py │ ├── test_setup.py │ ├── test_submissions.py │ └── test_users.py └── utils │ ├── __init__.py │ ├── test_ctftime.py │ ├── test_email.py │ ├── test_encoding.py │ ├── test_events.py │ ├── test_exports.py │ ├── test_formatters.py │ ├── test_humanize.py │ ├── test_markdown.py │ ├── test_passwords.py │ ├── test_plugins.py │ ├── test_ratelimit.py │ ├── test_sessions.py │ ├── test_updates.py │ ├── test_uploaders.py │ └── test_validators.py └── wsgi.py /.codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | status: 3 | project: 4 | default: 5 | # Fail the status if coverage drops by >= 1% 6 | threshold: 1 7 | patch: 8 | default: 9 | threshold: 1 10 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | CTFd/logs/*.log 2 | CTFd/static/uploads 3 | CTFd/uploads 4 | CTFd/*.db 5 | CTFd/uploads/**/* 6 | .ctfd_secret_key 7 | .data 8 | .git 9 | .codecov.yml 10 | .dockerignore 11 | .github 12 | .gitignore 13 | .prettierignore 14 | .travis.yml 15 | **/node_modules 16 | **/*.pyc 17 | **/__pycache__ 18 | .venv* 19 | venv* -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": true, 4 | "es6": true 5 | }, 6 | "extends": "eslint:recommended", 7 | "globals": { 8 | "Atomics": "readonly", 9 | "SharedArrayBuffer": "readonly" 10 | }, 11 | "parserOptions": { 12 | "ecmaVersion": 2018, 13 | "sourceType": "module" 14 | }, 15 | "rules": { 16 | "no-unused-vars": ["error", { "argsIgnorePattern": "^_" }] 17 | } 18 | }; -------------------------------------------------------------------------------- /.flaskenv: -------------------------------------------------------------------------------- 1 | FLASK_ENV=development 2 | FLASK_RUN_PORT=4000 3 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sh text eol=lf 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | **Environment**: 8 | 9 | - CTFd Version/Commit: 10 | - Operating System: 11 | - Web Browser and Version: 12 | 13 | **What happened?** 14 | 15 | **What did you expect to happen?** 16 | 17 | **How to reproduce your issue** 18 | 19 | **Any associated stack traces or error logs** 20 | -------------------------------------------------------------------------------- /.isort.cfg: -------------------------------------------------------------------------------- 1 | [settings] 2 | multi_line_output=3 3 | include_trailing_comma=True 4 | force_grid_wrap=0 5 | use_parentheses=True 6 | line_length=88 7 | skip=migrations 8 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | CTFd/themes/**/vendor/ 2 | CTFd/themes/core/ 3 | CTFd/themes/core-beta/**/* 4 | CTFd/themes/admin/static/**/* 5 | *.html 6 | *.njk 7 | *.png 8 | *.svg 9 | *.ico 10 | *.ai 11 | *.svg 12 | *.mp3 13 | *.webm 14 | .pytest_cache 15 | venv* 16 | .venv* 17 | -------------------------------------------------------------------------------- /CTFd/admin/notifications.py: -------------------------------------------------------------------------------- 1 | from flask import render_template 2 | 3 | from CTFd.admin import admin 4 | from CTFd.models import Notifications 5 | from CTFd.utils.decorators import admins_only 6 | 7 | 8 | @admin.route("/admin/notifications") 9 | @admins_only 10 | def notifications(): 11 | notifs = Notifications.query.order_by(Notifications.id.desc()).all() 12 | return render_template("admin/notifications.html", notifications=notifs) 13 | -------------------------------------------------------------------------------- /CTFd/admin/scoreboard.py: -------------------------------------------------------------------------------- 1 | from flask import render_template 2 | 3 | from CTFd.admin import admin 4 | from CTFd.utils.config import is_teams_mode 5 | from CTFd.utils.decorators import admins_only 6 | from CTFd.utils.scores import get_standings, get_user_standings 7 | 8 | 9 | @admin.route("/admin/scoreboard") 10 | @admins_only 11 | def scoreboard_listing(): 12 | standings = get_standings(admin=True) 13 | user_standings = get_user_standings(admin=True) if is_teams_mode() else None 14 | return render_template( 15 | "admin/scoreboard.html", standings=standings, user_standings=user_standings 16 | ) 17 | -------------------------------------------------------------------------------- /CTFd/api/v1/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/api/v1/__init__.py -------------------------------------------------------------------------------- /CTFd/api/v1/helpers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/api/v1/helpers/__init__.py -------------------------------------------------------------------------------- /CTFd/api/v1/helpers/models.py: -------------------------------------------------------------------------------- 1 | # This file is no longer used. If you're importing the function from here please update your imports 2 | 3 | from CTFd.utils.helpers.models import build_model_filters as _build_model_filters 4 | 5 | 6 | def build_model_filters(model, query, field): 7 | print("CTFd.api.v1.helpers.models.build_model_filters has been deprecated.") 8 | print("Please switch to using CTFd.utils.helpers.models.build_model_filters") 9 | print( 10 | "This function will raise an exception in a future minor release of CTFd and then be removed in a major release." 11 | ) 12 | return _build_model_filters(model, query, field) 13 | -------------------------------------------------------------------------------- /CTFd/api/v1/shares.py: -------------------------------------------------------------------------------- 1 | from flask import abort, request 2 | from flask_restx import Namespace, Resource 3 | 4 | from CTFd.utils import get_config 5 | from CTFd.utils.decorators import authed_only 6 | from CTFd.utils.social import get_social_share 7 | from CTFd.utils.user import get_current_user_attrs 8 | 9 | shares_namespace = Namespace("shares", description="Endpoint to create Share links") 10 | 11 | 12 | @shares_namespace.route("") 13 | class Share(Resource): 14 | @authed_only 15 | def post(self): 16 | if bool(get_config("social_shares")) is False: 17 | abort(403) 18 | req = request.get_json() 19 | share_type = req.get("type") 20 | 21 | SocialShare = get_social_share(type=share_type) 22 | user = get_current_user_attrs() 23 | share = SocialShare(user_id=user.id) 24 | response = {"url": share.url} 25 | return {"success": True, "data": response} 26 | -------------------------------------------------------------------------------- /CTFd/api/v1/statistics/__init__.py: -------------------------------------------------------------------------------- 1 | from flask_restx import Namespace 2 | 3 | statistics_namespace = Namespace( 4 | "statistics", description="Endpoint to retrieve Statistics" 5 | ) 6 | 7 | # isort:imports-firstparty 8 | from CTFd.api.v1.statistics import challenges # noqa: F401,I001 9 | from CTFd.api.v1.statistics import scores # noqa: F401 10 | from CTFd.api.v1.statistics import submissions # noqa: F401 11 | from CTFd.api.v1.statistics import teams # noqa: F401 12 | from CTFd.api.v1.statistics import users # noqa: F401 13 | -------------------------------------------------------------------------------- /CTFd/api/v1/statistics/submissions.py: -------------------------------------------------------------------------------- 1 | from flask_restx import Resource 2 | from sqlalchemy import func 3 | 4 | from CTFd.api.v1.statistics import statistics_namespace 5 | from CTFd.models import Submissions 6 | from CTFd.utils.decorators import admins_only 7 | 8 | 9 | @statistics_namespace.route("/submissions/") 10 | class SubmissionPropertyCounts(Resource): 11 | @admins_only 12 | def get(self, column): 13 | if column in Submissions.__table__.columns.keys(): 14 | prop = getattr(Submissions, column) 15 | data = ( 16 | Submissions.query.with_entities(prop, func.count(prop)) 17 | .group_by(prop) 18 | .all() 19 | ) 20 | return {"success": True, "data": dict(data)} 21 | else: 22 | response = {"success": False, "errors": "That could not be found"}, 404 23 | return response 24 | -------------------------------------------------------------------------------- /CTFd/api/v1/statistics/teams.py: -------------------------------------------------------------------------------- 1 | from flask_restx import Resource 2 | 3 | from CTFd.api.v1.statistics import statistics_namespace 4 | from CTFd.models import Teams 5 | from CTFd.utils.decorators import admins_only 6 | 7 | 8 | @statistics_namespace.route("/teams") 9 | class TeamStatistics(Resource): 10 | @admins_only 11 | def get(self): 12 | registered = Teams.query.count() 13 | data = {"registered": registered} 14 | return {"success": True, "data": data} 15 | -------------------------------------------------------------------------------- /CTFd/constants/sessions.py: -------------------------------------------------------------------------------- 1 | from flask import session 2 | 3 | 4 | class _SessionWrapper: 5 | @property 6 | def id(self): 7 | return session.get("id", 0) 8 | 9 | @property 10 | def nonce(self): 11 | return session.get("nonce") 12 | 13 | @property 14 | def hash(self): 15 | return session.get("hash") 16 | 17 | 18 | Session = _SessionWrapper() 19 | -------------------------------------------------------------------------------- /CTFd/constants/static.py: -------------------------------------------------------------------------------- 1 | from CTFd.constants import JinjaEnum, RawEnum 2 | 3 | 4 | @JinjaEnum 5 | class CacheKeys(str, RawEnum): 6 | PUBLIC_SCOREBOARD_TABLE = "public_scoreboard_table" 7 | 8 | 9 | # Placeholder object. Not used, just imported to force initialization of any Enums here 10 | class _StaticsWrapper: 11 | pass 12 | 13 | 14 | Static = _StaticsWrapper() 15 | -------------------------------------------------------------------------------- /CTFd/constants/teams.py: -------------------------------------------------------------------------------- 1 | from collections import namedtuple 2 | 3 | TeamAttrs = namedtuple( 4 | "TeamAttrs", 5 | [ 6 | "id", 7 | "oauth_id", 8 | "name", 9 | "email", 10 | "secret", 11 | "website", 12 | "affiliation", 13 | "country", 14 | "bracket_id", 15 | "hidden", 16 | "banned", 17 | "captain_id", 18 | "created", 19 | ], 20 | ) 21 | 22 | 23 | class _TeamAttrsWrapper: 24 | def __getattr__(self, attr): 25 | from CTFd.utils.user import get_current_team_attrs 26 | 27 | attrs = get_current_team_attrs() 28 | return getattr(attrs, attr, None) 29 | 30 | @property 31 | def place(self): 32 | from CTFd.utils.user import get_team_place 33 | 34 | return get_team_place(team_id=self.id) 35 | 36 | @property 37 | def score(self): 38 | from CTFd.utils.user import get_team_score 39 | 40 | return get_team_score(team_id=self.id) 41 | 42 | 43 | Team = _TeamAttrsWrapper() 44 | -------------------------------------------------------------------------------- /CTFd/constants/themes.py: -------------------------------------------------------------------------------- 1 | ADMIN_THEME = "admin" 2 | DEFAULT_THEME = "core" 3 | -------------------------------------------------------------------------------- /CTFd/errors.py: -------------------------------------------------------------------------------- 1 | import jinja2.exceptions 2 | from flask import render_template 3 | from werkzeug.exceptions import InternalServerError 4 | 5 | 6 | def render_error(error): 7 | if ( 8 | isinstance(error, InternalServerError) 9 | and error.description == InternalServerError.description 10 | ): 11 | error.description = "An Internal Server Error has occurred" 12 | try: 13 | return ( 14 | render_template( 15 | "errors/{}.html".format(error.code), 16 | error=error.description, 17 | ), 18 | error.code, 19 | ) 20 | except jinja2.exceptions.TemplateNotFound: 21 | return error.get_response() 22 | -------------------------------------------------------------------------------- /CTFd/events/__init__.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint, Response, current_app, stream_with_context 2 | 3 | from CTFd.models import db 4 | from CTFd.utils import get_app_config 5 | from CTFd.utils.decorators import authed_only, ratelimit 6 | 7 | events = Blueprint("events", __name__) 8 | 9 | 10 | @events.route("/events") 11 | @authed_only 12 | @ratelimit(method="GET", limit=150, interval=60) 13 | def subscribe(): 14 | @stream_with_context 15 | def gen(): 16 | for event in current_app.events_manager.subscribe(): 17 | yield str(event) 18 | 19 | enabled = get_app_config("SERVER_SENT_EVENTS") 20 | if enabled is False: 21 | return ("", 204) 22 | 23 | # Close the db session to avoid OperationalError with MySQL connection errors 24 | db.session.close() 25 | 26 | return Response(gen(), mimetype="text/event-stream") 27 | -------------------------------------------------------------------------------- /CTFd/exceptions/__init__.py: -------------------------------------------------------------------------------- 1 | class UserNotFoundException(Exception): 2 | pass 3 | 4 | 5 | class UserTokenExpiredException(Exception): 6 | pass 7 | 8 | 9 | class TeamTokenExpiredException(Exception): 10 | pass 11 | 12 | 13 | class TeamTokenInvalidException(Exception): 14 | pass 15 | -------------------------------------------------------------------------------- /CTFd/fonts/OpenSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/fonts/OpenSans-Bold.ttf -------------------------------------------------------------------------------- /CTFd/forms/awards.py: -------------------------------------------------------------------------------- 1 | from wtforms import RadioField, StringField, TextAreaField 2 | from wtforms.fields.html5 import IntegerField 3 | 4 | from CTFd.forms import BaseForm 5 | from CTFd.forms.fields import SubmitField 6 | 7 | 8 | class AwardCreationForm(BaseForm): 9 | name = StringField("Name") 10 | value = IntegerField("Value") 11 | category = StringField("Category") 12 | description = TextAreaField("Description") 13 | submit = SubmitField("Create") 14 | icon = RadioField( 15 | "Icon", 16 | choices=[ 17 | ("", "None"), 18 | ("shield", "Shield"), 19 | ("bug", "Bug"), 20 | ("crown", "Crown"), 21 | ("crosshairs", "Crosshairs"), 22 | ("ban", "Ban"), 23 | ("lightning", "Lightning"), 24 | ("skull", "Skull"), 25 | ("brain", "Brain"), 26 | ("code", "Code"), 27 | ("cowboy", "Cowboy"), 28 | ("angry", "Angry"), 29 | ], 30 | ) 31 | -------------------------------------------------------------------------------- /CTFd/forms/challenges.py: -------------------------------------------------------------------------------- 1 | from wtforms import MultipleFileField, SelectField, StringField 2 | from wtforms.validators import InputRequired 3 | 4 | from CTFd.forms import BaseForm 5 | from CTFd.forms.fields import SubmitField 6 | 7 | 8 | class ChallengeSearchForm(BaseForm): 9 | field = SelectField( 10 | "Search Field", 11 | choices=[ 12 | ("name", "Name"), 13 | ("id", "ID"), 14 | ("category", "Category"), 15 | ("type", "Type"), 16 | ], 17 | default="name", 18 | validators=[InputRequired()], 19 | ) 20 | q = StringField("Parameter", validators=[InputRequired()]) 21 | submit = SubmitField("Search") 22 | 23 | 24 | class ChallengeFilesUploadForm(BaseForm): 25 | file = MultipleFileField( 26 | "Upload Files", 27 | description="Attach multiple files using Control+Click or Cmd+Click.", 28 | validators=[InputRequired()], 29 | ) 30 | submit = SubmitField("Upload") 31 | -------------------------------------------------------------------------------- /CTFd/forms/email.py: -------------------------------------------------------------------------------- 1 | from wtforms import TextAreaField 2 | from wtforms.validators import InputRequired 3 | 4 | from CTFd.forms import BaseForm 5 | from CTFd.forms.fields import SubmitField 6 | 7 | 8 | class SendEmailForm(BaseForm): 9 | text = TextAreaField("Message", validators=[InputRequired()]) 10 | submit = SubmitField("Send") 11 | -------------------------------------------------------------------------------- /CTFd/forms/fields.py: -------------------------------------------------------------------------------- 1 | from wtforms import SubmitField as _SubmitField 2 | 3 | 4 | class SubmitField(_SubmitField): 5 | """ 6 | This custom SubmitField exists because wtforms is dumb. 7 | 8 | See https://github.com/wtforms/wtforms/issues/205, https://github.com/wtforms/wtforms/issues/36 9 | The .submit() handler in JS will break if the form has an input with the name or id of "submit" so submit fields need to be changed. 10 | """ 11 | 12 | def __init__(self, *args, **kwargs): 13 | name = kwargs.pop("name", "_submit") 14 | super().__init__(*args, **kwargs) 15 | if self.name == "submit" or name: 16 | self.id = name 17 | self.name = name 18 | -------------------------------------------------------------------------------- /CTFd/forms/notifications.py: -------------------------------------------------------------------------------- 1 | from wtforms import BooleanField, RadioField, StringField, TextAreaField 2 | from wtforms.validators import InputRequired 3 | 4 | from CTFd.forms import BaseForm 5 | from CTFd.forms.fields import SubmitField 6 | 7 | 8 | class NotificationForm(BaseForm): 9 | title = StringField("Title", description="Notification title") 10 | content = TextAreaField( 11 | "Content", 12 | description="Notification contents. Can consist of HTML and/or Markdown.", 13 | ) 14 | type = RadioField( 15 | "Notification Type", 16 | choices=[("toast", "Toast"), ("alert", "Alert"), ("background", "Background")], 17 | default="toast", 18 | description="What type of notification users receive", 19 | validators=[InputRequired()], 20 | ) 21 | sound = BooleanField( 22 | "Play Sound", 23 | default=True, 24 | description="Play sound for users when they receive the notification", 25 | ) 26 | submit = SubmitField("Submit") 27 | -------------------------------------------------------------------------------- /CTFd/forms/submissions.py: -------------------------------------------------------------------------------- 1 | from wtforms import SelectField, StringField 2 | from wtforms.validators import InputRequired 3 | 4 | from CTFd.forms import BaseForm 5 | from CTFd.forms.fields import SubmitField 6 | 7 | 8 | class SubmissionSearchForm(BaseForm): 9 | field = SelectField( 10 | "Search Field", 11 | choices=[ 12 | ("provided", "Provided"), 13 | ("id", "ID"), 14 | ("account_id", "Account ID"), 15 | ("challenge_id", "Challenge ID"), 16 | ("challenge_name", "Challenge Name"), 17 | ], 18 | default="provided", 19 | validators=[InputRequired()], 20 | ) 21 | q = StringField("Parameter", validators=[InputRequired()]) 22 | submit = SubmitField("Search") 23 | -------------------------------------------------------------------------------- /CTFd/logs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/logs/.gitkeep -------------------------------------------------------------------------------- /CTFd/plugins/challenges/assets/create.html: -------------------------------------------------------------------------------- 1 | {% extends "admin/challenges/create.html" %} -------------------------------------------------------------------------------- /CTFd/plugins/challenges/assets/create.js: -------------------------------------------------------------------------------- 1 | CTFd.plugin.run((_CTFd) => { 2 | const $ = _CTFd.lib.$ 3 | const md = _CTFd.lib.markdown() 4 | }) 5 | -------------------------------------------------------------------------------- /CTFd/plugins/challenges/assets/update.html: -------------------------------------------------------------------------------- 1 | {% extends "admin/challenges/update.html" %} -------------------------------------------------------------------------------- /CTFd/plugins/challenges/assets/update.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/plugins/challenges/assets/update.js -------------------------------------------------------------------------------- /CTFd/plugins/challenges/assets/view.html: -------------------------------------------------------------------------------- 1 | {% extends "challenge.html" %} -------------------------------------------------------------------------------- /CTFd/plugins/ctfd_owl/assets/create.js: -------------------------------------------------------------------------------- 1 | CTFd.plugin.run((_CTFd) => { 2 | const $ = _CTFd.lib.$ 3 | const md = _CTFd.lib.markdown() 4 | }) 5 | -------------------------------------------------------------------------------- /CTFd/plugins/ctfd_owl/assets/update.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/plugins/ctfd_owl/assets/update.js -------------------------------------------------------------------------------- /CTFd/plugins/ctfd_owl/assets/view.html: -------------------------------------------------------------------------------- 1 | {% extends "challenge.html" %} 2 | 3 | {% block description %} 4 | {{ challenge.html }} 5 |
7 |
8 |
Instance Info
9 |
10 |
11 | {% endblock %} 12 | 13 | {% block input %} 14 | 15 | 16 | {% endblock %} 17 | 18 | {% block submit %} 19 | 22 | {% endblock %} -------------------------------------------------------------------------------- /CTFd/plugins/ctfd_owl/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CTFd Owl", 3 | "route": "/plugins/ctfd_owl/admin/settings" 4 | } -------------------------------------------------------------------------------- /CTFd/plugins/ctfd_owl/requirements.txt: -------------------------------------------------------------------------------- 1 | #docker-compose 2 | # The version of docker-compose in pypi is too low 3 | -------------------------------------------------------------------------------- /CTFd/plugins/ctfd_owl/setup.py: -------------------------------------------------------------------------------- 1 | from CTFd.utils import set_config 2 | 3 | from .db_utils import DBUtils 4 | 5 | def setup_default_configs(): 6 | config=[ 7 | ['owl_setup', 'yes'], 8 | ['docker_api_url', 'unix:///var/run/docker.sock'], 9 | ['docker_flag_prefix', 'flag'], 10 | ['docker_max_container_count', '100'], 11 | ['docker_max_renew_count', '5'], 12 | ['docker_timeout', '3600'], 13 | ['frp_direct_ip_address', 'direct.test.com'], 14 | ['frp_direct_port_maximum', '10200'], 15 | ['frp_direct_port_minimum', '10101'], 16 | ['frp_http_domain_suffix', 'dynamic.test.com'], 17 | ['frpc_config_template', 18 | '[common]\r\ntoken = YOUR_TOKEN\r\nserver_addr = frps\r\nserver_port = 7000\r\nadmin_addr = 0.0.0.0\r\nadmin_port = 7400'] 19 | ] 20 | DBUtils.save_all_configs(config) -------------------------------------------------------------------------------- /CTFd/plugins/ctfd_whale/assets/config.js: -------------------------------------------------------------------------------- 1 | const $ = CTFd.lib.$; 2 | 3 | $(".config-section > form:not(.form-upload)").submit(async function (event) { 4 | event.preventDefault(); 5 | const obj = $(this).serializeJSON(); 6 | const params = {}; 7 | for (let x in obj) { 8 | if (obj[x] === "true") { 9 | params[x] = true; 10 | } else if (obj[x] === "false") { 11 | params[x] = false; 12 | } else { 13 | params[x] = obj[x]; 14 | } 15 | } 16 | params['whale:refresh'] = btoa(+new Date).slice(-7, -2); 17 | 18 | await CTFd.api.patch_config_list({}, params); 19 | location.reload(); 20 | }); 21 | $(".config-section > form:not(.form-upload) > div > div > div > #router-type").change(async function () { 22 | await CTFd.api.patch_config_list({}, { 23 | 'whale:router_type': $(this).val(), 24 | 'whale:refresh': btoa(+new Date).slice(-7, -2), 25 | }); 26 | location.reload(); 27 | }); 28 | -------------------------------------------------------------------------------- /CTFd/plugins/ctfd_whale/assets/create.js: -------------------------------------------------------------------------------- 1 | // Markdown Preview 2 | if ($ === undefined) $ = CTFd.lib.$ 3 | $('#desc-edit').on('shown.bs.tab', function(event) { 4 | if (event.target.hash == '#desc-preview') { 5 | var editor_value = $('#desc-editor').val(); 6 | $(event.target.hash).html( 7 | CTFd._internal.challenge.render(editor_value) 8 | ); 9 | } 10 | }); 11 | $('#new-desc-edit').on('shown.bs.tab', function(event) { 12 | if (event.target.hash == '#new-desc-preview') { 13 | var editor_value = $('#new-desc-editor').val(); 14 | $(event.target.hash).html( 15 | CTFd._internal.challenge.render(editor_value) 16 | ); 17 | } 18 | }); 19 | $("#solve-attempts-checkbox").change(function() { 20 | if (this.checked) { 21 | $('#solve-attempts-input').show(); 22 | } else { 23 | $('#solve-attempts-input').hide(); 24 | $('#max_attempts').val(''); 25 | } 26 | }); 27 | 28 | $(document).ready(function() { 29 | $('[data-toggle="tooltip"]').tooltip(); 30 | }); -------------------------------------------------------------------------------- /CTFd/plugins/ctfd_whale/assets/view.html: -------------------------------------------------------------------------------- 1 | {% extends "challenge.html" %} 2 | 3 | {% block description %} 4 | {{ challenge.html }} 5 |
6 |
7 | 8 |
9 |
10 | {% endblock %} 11 | 12 | {% block input %} 13 | 14 | 15 | {% endblock %} 16 | 17 | {% block submit %} 18 | 21 | {% endblock %} 22 | -------------------------------------------------------------------------------- /CTFd/plugins/ctfd_whale/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CTFd Whale", 3 | "route": "/plugins/ctfd_whale/admin/settings" 4 | } -------------------------------------------------------------------------------- /CTFd/plugins/ctfd_whale/docs/imgs/arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/plugins/ctfd_whale/docs/imgs/arch.png -------------------------------------------------------------------------------- /CTFd/plugins/ctfd_whale/docs/imgs/whale-config1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/plugins/ctfd_whale/docs/imgs/whale-config1.png -------------------------------------------------------------------------------- /CTFd/plugins/ctfd_whale/docs/imgs/whale-config2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/plugins/ctfd_whale/docs/imgs/whale-config2.png -------------------------------------------------------------------------------- /CTFd/plugins/ctfd_whale/docs/imgs/whale-config3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/plugins/ctfd_whale/docs/imgs/whale-config3.png -------------------------------------------------------------------------------- /CTFd/plugins/ctfd_whale/requirements.txt: -------------------------------------------------------------------------------- 1 | docker==7.1.0 2 | Flask-APScheduler==1.11.0 3 | flask-redis==0.4.0 4 | redis==3.3.11 5 | -------------------------------------------------------------------------------- /CTFd/plugins/ctfd_whale/templates/config/trp.router.config.html: -------------------------------------------------------------------------------- 1 | {% for config, val in { 2 | "API URL": ("trp_api_url", "trp API to connect to"), 3 | "Domain Suffix": ("trp_domain_suffix", "Will be used to generated the access link of a challenge"), 4 | "Listening Port": ("trp_listening_port", "Will be used to generated the access link of a challenge"), 5 | }.items() %} 6 | {% set value = get_config('whale:' + val[0]) %} 7 |
8 | 14 | 16 |
17 | {% endfor %} 18 | -------------------------------------------------------------------------------- /CTFd/plugins/ctfd_whale/templates/whale_base.html: -------------------------------------------------------------------------------- 1 | {% extends "admin/base.html" %} 2 | 3 | {% block content %} 4 |
5 |
6 |

CTFd Whale

7 |
8 |
9 |
10 |
11 |
12 | 16 |
17 |
18 |
19 | {% block panel %} 20 | {% endblock %} 21 |
22 |
23 |
24 |
25 | {% endblock %} 26 | -------------------------------------------------------------------------------- /CTFd/plugins/ctfd_whale/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/plugins/ctfd_whale/utils/__init__.py -------------------------------------------------------------------------------- /CTFd/plugins/ctfd_whale/utils/exceptions.py: -------------------------------------------------------------------------------- 1 | class WhaleError(Exception): 2 | def __init__(self, msg): 3 | super().__init__(msg) 4 | self.message = msg 5 | 6 | 7 | class WhaleWarning(Warning): 8 | pass 9 | -------------------------------------------------------------------------------- /CTFd/plugins/ctfd_whale/utils/routers/__init__.py: -------------------------------------------------------------------------------- 1 | from CTFd.utils import get_config 2 | 3 | from .frp import FrpRouter 4 | from .trp import TrpRouter 5 | 6 | _routers = { 7 | 'frp': FrpRouter, 8 | 'trp': TrpRouter, 9 | } 10 | 11 | 12 | def instanciate(cls): 13 | return cls() 14 | 15 | 16 | @instanciate 17 | class Router: 18 | _name = '' 19 | _router = None 20 | 21 | def __getattr__(self, name: str): 22 | router_conftype = get_config("whale:router_type", "frp") 23 | if Router._name != router_conftype: 24 | Router._router = _routers[router_conftype]() 25 | Router._name = router_conftype 26 | return getattr(Router._router, name) 27 | 28 | @staticmethod 29 | def reset(): 30 | Router._name = '' 31 | Router._router = None 32 | 33 | 34 | __all__ = ["Router"] 35 | -------------------------------------------------------------------------------- /CTFd/plugins/ctfd_whale/utils/routers/base.py: -------------------------------------------------------------------------------- 1 | import typing 2 | 3 | from ...models import WhaleContainer 4 | 5 | 6 | class BaseRouter: 7 | name = None 8 | 9 | def __init__(self): 10 | pass 11 | 12 | def access(self, container: WhaleContainer): 13 | pass 14 | 15 | def register(self, container: WhaleContainer): 16 | pass 17 | 18 | def unregister(self, container: WhaleContainer): 19 | pass 20 | 21 | def reload(self): 22 | pass 23 | 24 | def check_availability(self) -> typing.Tuple[bool, str]: 25 | pass 26 | -------------------------------------------------------------------------------- /CTFd/plugins/dynamic_challenges/.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | *.py[cod] 3 | -------------------------------------------------------------------------------- /CTFd/plugins/dynamic_challenges/assets/create.js: -------------------------------------------------------------------------------- 1 | CTFd.plugin.run((_CTFd) => { 2 | const $ = _CTFd.lib.$ 3 | const md = _CTFd.lib.markdown() 4 | }) 5 | -------------------------------------------------------------------------------- /CTFd/plugins/dynamic_challenges/assets/update.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/plugins/dynamic_challenges/assets/update.js -------------------------------------------------------------------------------- /CTFd/plugins/dynamic_challenges/assets/view.html: -------------------------------------------------------------------------------- 1 | {% extends "challenge.html" %} -------------------------------------------------------------------------------- /CTFd/plugins/dynamic_challenges/function.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/plugins/dynamic_challenges/function.png -------------------------------------------------------------------------------- /CTFd/plugins/flags/assets/regex/edit.html: -------------------------------------------------------------------------------- 1 | 5 |
6 | 7 |
8 |
9 | 13 |
14 | 15 | 16 |
17 |
18 | 19 |
20 | -------------------------------------------------------------------------------- /CTFd/plugins/flags/assets/static/create.html: -------------------------------------------------------------------------------- 1 | 5 |
6 | 7 |
8 |
9 | 13 |
14 | -------------------------------------------------------------------------------- /CTFd/plugins/flags/assets/static/edit.html: -------------------------------------------------------------------------------- 1 | 5 |
6 | 7 |
8 |
9 | 13 |
14 | 15 | 16 |
17 |
18 | 19 |
20 | -------------------------------------------------------------------------------- /CTFd/plugins/flags/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/plugins/flags/tests/__init__.py -------------------------------------------------------------------------------- /CTFd/schemas/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/schemas/__init__.py -------------------------------------------------------------------------------- /CTFd/schemas/brackets.py: -------------------------------------------------------------------------------- 1 | from CTFd.models import Brackets, ma 2 | 3 | 4 | class BracketSchema(ma.ModelSchema): 5 | class Meta: 6 | model = Brackets 7 | include_fk = True 8 | dump_only = ("id",) 9 | -------------------------------------------------------------------------------- /CTFd/schemas/comments.py: -------------------------------------------------------------------------------- 1 | from marshmallow import fields 2 | 3 | from CTFd.models import Comments, ma 4 | from CTFd.schemas.users import UserSchema 5 | 6 | 7 | class CommentSchema(ma.ModelSchema): 8 | class Meta: 9 | model = Comments 10 | include_fk = True 11 | dump_only = ("id", "date", "html", "author", "author_id", "type") 12 | 13 | author = fields.Nested(UserSchema(only=("name",))) 14 | html = fields.String() 15 | -------------------------------------------------------------------------------- /CTFd/schemas/files.py: -------------------------------------------------------------------------------- 1 | from CTFd.models import Files, ma 2 | from CTFd.utils import string_types 3 | 4 | 5 | class FileSchema(ma.ModelSchema): 6 | class Meta: 7 | model = Files 8 | include_fk = True 9 | dump_only = ("id", "type", "location") 10 | 11 | def __init__(self, view=None, *args, **kwargs): 12 | if view: 13 | if isinstance(view, string_types): 14 | kwargs["only"] = self.views[view] 15 | elif isinstance(view, list): 16 | kwargs["only"] = view 17 | 18 | super(FileSchema, self).__init__(*args, **kwargs) 19 | -------------------------------------------------------------------------------- /CTFd/schemas/flags.py: -------------------------------------------------------------------------------- 1 | from CTFd.models import Flags, ma 2 | from CTFd.utils import string_types 3 | 4 | 5 | class FlagSchema(ma.ModelSchema): 6 | class Meta: 7 | model = Flags 8 | include_fk = True 9 | dump_only = ("id",) 10 | 11 | def __init__(self, view=None, *args, **kwargs): 12 | if view: 13 | if isinstance(view, string_types): 14 | kwargs["only"] = self.views[view] 15 | elif isinstance(view, list): 16 | kwargs["only"] = view 17 | 18 | super(FlagSchema, self).__init__(*args, **kwargs) 19 | -------------------------------------------------------------------------------- /CTFd/schemas/notifications.py: -------------------------------------------------------------------------------- 1 | from marshmallow import fields 2 | 3 | from CTFd.models import Notifications, ma 4 | from CTFd.utils import string_types 5 | 6 | 7 | class NotificationSchema(ma.ModelSchema): 8 | class Meta: 9 | model = Notifications 10 | include_fk = True 11 | dump_only = ("id", "date", "html") 12 | 13 | # Used to force the schema to include the html property from the model 14 | html = fields.Str() 15 | 16 | def __init__(self, view=None, *args, **kwargs): 17 | if view: 18 | if isinstance(view, string_types): 19 | kwargs["only"] = self.views[view] 20 | elif isinstance(view, list): 21 | kwargs["only"] = view 22 | 23 | super(NotificationSchema, self).__init__(*args, **kwargs) 24 | -------------------------------------------------------------------------------- /CTFd/schemas/tags.py: -------------------------------------------------------------------------------- 1 | from CTFd.models import Tags, ma 2 | from CTFd.utils import string_types 3 | 4 | 5 | class TagSchema(ma.ModelSchema): 6 | class Meta: 7 | model = Tags 8 | include_fk = True 9 | dump_only = ("id",) 10 | 11 | views = {"admin": ["id", "challenge", "value"], "user": ["value"]} 12 | 13 | def __init__(self, view=None, *args, **kwargs): 14 | if view: 15 | if isinstance(view, string_types): 16 | kwargs["only"] = self.views[view] 17 | elif isinstance(view, list): 18 | kwargs["only"] = view 19 | 20 | super(TagSchema, self).__init__(*args, **kwargs) 21 | -------------------------------------------------------------------------------- /CTFd/schemas/tokens.py: -------------------------------------------------------------------------------- 1 | from CTFd.models import Tokens, ma 2 | from CTFd.utils import string_types 3 | 4 | 5 | class TokenSchema(ma.ModelSchema): 6 | class Meta: 7 | model = Tokens 8 | include_fk = True 9 | dump_only = ("id", "expiration", "type") 10 | 11 | views = { 12 | "admin": [ 13 | "id", 14 | "type", 15 | "user_id", 16 | "created", 17 | "expiration", 18 | "description", 19 | "value", 20 | ], 21 | "user": ["id", "type", "created", "expiration", "description"], 22 | } 23 | 24 | def __init__(self, view=None, *args, **kwargs): 25 | if view: 26 | if isinstance(view, string_types): 27 | kwargs["only"] = self.views[view] 28 | elif isinstance(view, list): 29 | kwargs["only"] = view 30 | 31 | super(TokenSchema, self).__init__(*args, **kwargs) 32 | -------------------------------------------------------------------------------- /CTFd/schemas/unlocks.py: -------------------------------------------------------------------------------- 1 | from CTFd.models import Unlocks, ma 2 | from CTFd.utils import string_types 3 | 4 | 5 | class UnlockSchema(ma.ModelSchema): 6 | class Meta: 7 | model = Unlocks 8 | include_fk = True 9 | dump_only = ("id", "date") 10 | 11 | views = { 12 | "admin": ["user_id", "target", "team_id", "date", "type", "id"], 13 | "user": ["target", "date", "type", "id"], 14 | } 15 | 16 | def __init__(self, view=None, *args, **kwargs): 17 | if view: 18 | if isinstance(view, string_types): 19 | kwargs["only"] = self.views[view] 20 | elif isinstance(view, list): 21 | kwargs["only"] = view 22 | 23 | super(UnlockSchema, self).__init__(*args, **kwargs) 24 | -------------------------------------------------------------------------------- /CTFd/scoreboard.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint, render_template 2 | 3 | from CTFd.utils import config 4 | from CTFd.utils.config.visibility import scores_visible 5 | from CTFd.utils.decorators.visibility import ( 6 | check_account_visibility, 7 | check_score_visibility, 8 | ) 9 | from CTFd.utils.helpers import get_infos 10 | from CTFd.utils.scores import get_standings 11 | from CTFd.utils.user import is_admin 12 | 13 | scoreboard = Blueprint("scoreboard", __name__) 14 | 15 | 16 | @scoreboard.route("/scoreboard") 17 | @check_account_visibility 18 | @check_score_visibility 19 | def listing(): 20 | infos = get_infos() 21 | 22 | if config.is_scoreboard_frozen(): 23 | infos.append("Scoreboard has been frozen") 24 | 25 | if is_admin() is True and scores_visible() is False: 26 | infos.append("Scores are not currently visible to users") 27 | 28 | standings = get_standings() 29 | return render_template("scoreboard.html", standings=standings, infos=infos) 30 | -------------------------------------------------------------------------------- /CTFd/share.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint, abort, request 2 | 3 | from CTFd.utils import get_config 4 | from CTFd.utils.social import get_social_share 5 | 6 | social = Blueprint("social", __name__) 7 | 8 | 9 | @social.route("/share//assets/") 10 | def assets(type, path): 11 | if bool(get_config("social_shares")) is False: 12 | abort(403) 13 | SocialShare = get_social_share(type) 14 | if SocialShare is None: 15 | abort(404) 16 | 17 | s = SocialShare() 18 | if path != s.mac + ".png": 19 | abort(404) 20 | 21 | return s.asset(path) 22 | 23 | 24 | @social.route("/share/") 25 | def share(type): 26 | if bool(get_config("social_shares")) is False: 27 | abort(403) 28 | SocialShare = get_social_share(type) 29 | if SocialShare is None: 30 | abort(404) 31 | 32 | s = SocialShare() 33 | if request.args.get("mac") != s.mac: 34 | abort(404) 35 | 36 | return s.content 37 | -------------------------------------------------------------------------------- /CTFd/themes/admin/assets/css/codemirror.scss: -------------------------------------------------------------------------------- 1 | @import "~/codemirror/lib/codemirror.css"; 2 | @import "includes/easymde.scss"; 3 | .CodeMirror.cm-s-default { 4 | font-size: 12px; 5 | border: 1px solid lightgray; 6 | } 7 | -------------------------------------------------------------------------------- /CTFd/themes/admin/assets/css/fonts.scss: -------------------------------------------------------------------------------- 1 | @use "sass:map"; 2 | @use "~/@fontsource/lato/scss/mixins.scss" as Lato; 3 | @use "~/@fontsource/raleway/scss/mixins.scss" as Raleway; 4 | 5 | @include Lato.faces( 6 | $subsets: all, 7 | $weights: ( 8 | 400, 9 | 700, 10 | ), 11 | $styles: all, 12 | $directory: "../webfonts" 13 | ); 14 | 15 | @include Raleway.faces( 16 | $subsets: all, 17 | $weights: ( 18 | 500, 19 | ), 20 | $styles: all, 21 | $directory: "../webfonts" 22 | ); 23 | 24 | $fa-font-display: auto !default; 25 | @import "~/@fortawesome/fontawesome-free/scss/fontawesome.scss"; 26 | @import "~/@fortawesome/fontawesome-free/scss/regular.scss"; 27 | @import "~/@fortawesome/fontawesome-free/scss/solid.scss"; 28 | @import "~/@fortawesome/fontawesome-free/scss/brands.scss"; 29 | -------------------------------------------------------------------------------- /CTFd/themes/admin/assets/css/includes/award-icons.scss: -------------------------------------------------------------------------------- 1 | .award-icon { 2 | font-family: "Font Awesome 5 Free", "Font Awesome 5 Free Offline"; 3 | font-weight: 900; 4 | -moz-osx-font-smoothing: grayscale; 5 | -webkit-font-smoothing: antialiased; 6 | display: inline-block; 7 | font-style: normal; 8 | font-variant: normal; 9 | text-rendering: auto; 10 | line-height: 1; 11 | } 12 | 13 | .award-shield:before { 14 | content: "\f3ed"; 15 | } 16 | .award-bug:before { 17 | content: "\f188"; 18 | } 19 | .award-crown:before { 20 | content: "\f521"; 21 | } 22 | .award-crosshairs:before { 23 | content: "\f05b"; 24 | } 25 | .award-ban:before { 26 | content: "\f05e"; 27 | } 28 | .award-lightning:before { 29 | content: "\f0e7"; 30 | } 31 | .award-code:before { 32 | content: "\f121"; 33 | } 34 | .award-cowboy:before { 35 | content: "\f8c0"; 36 | } 37 | .award-angry:before { 38 | content: "\f556"; 39 | } 40 | -------------------------------------------------------------------------------- /CTFd/themes/admin/assets/css/includes/jumbotron.css: -------------------------------------------------------------------------------- 1 | /* Move down content because we have a fixed navbar that is 3.5rem tall */ 2 | main { 3 | padding-top: 3.5rem; 4 | } 5 | -------------------------------------------------------------------------------- /CTFd/themes/admin/assets/css/includes/min-height.scss: -------------------------------------------------------------------------------- 1 | .min-vh-0 { 2 | min-height: 0vh !important; 3 | } 4 | .min-vh-25 { 5 | min-height: 25vh !important; 6 | } 7 | .min-vh-50 { 8 | min-height: 50vh !important; 9 | } 10 | .min-vh-75 { 11 | min-height: 75vh !important; 12 | } 13 | .min-vh-100 { 14 | min-height: 100vh !important; 15 | } 16 | -------------------------------------------------------------------------------- /CTFd/themes/admin/assets/css/includes/opacity.scss: -------------------------------------------------------------------------------- 1 | .opacity-0 { 2 | opacity: 0 !important; 3 | } 4 | .opacity-25 { 5 | opacity: 0.25 !important; 6 | } 7 | .opacity-50 { 8 | opacity: 0.5 !important; 9 | } 10 | .opacity-75 { 11 | opacity: 0.75 !important; 12 | } 13 | .opacity-100 { 14 | opacity: 1 !important; 15 | } 16 | -------------------------------------------------------------------------------- /CTFd/themes/admin/assets/css/includes/sticky-footer.css: -------------------------------------------------------------------------------- 1 | /* Sticky footer styles 2 | -------------------------------------------------- */ 3 | html { 4 | position: relative; 5 | min-height: 100%; 6 | } 7 | 8 | body { 9 | margin-bottom: 60px; /* Margin bottom by footer height */ 10 | } 11 | 12 | .footer { 13 | position: absolute; 14 | 15 | /* prevent scrollbars from showing on pages that don't use the full page height */ 16 | bottom: 1px; 17 | 18 | width: 100%; 19 | 20 | /* Set the fixed height of the footer here */ 21 | height: 60px; 22 | 23 | /* Override line-height from core because we have two lines in the admin panel */ 24 | line-height: normal !important; 25 | 26 | /* Avoid covering things */ 27 | z-index: -20; 28 | 29 | /*background-color: #f5f5f5;*/ 30 | } 31 | -------------------------------------------------------------------------------- /CTFd/themes/admin/assets/js/compat/config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | urlRoot: "", 3 | csrfNonce: "", 4 | userMode: "", 5 | }; 6 | -------------------------------------------------------------------------------- /CTFd/themes/admin/assets/js/compat/fetch.js: -------------------------------------------------------------------------------- 1 | import "whatwg-fetch"; 2 | import config from "./config"; 3 | 4 | const fetch = window.fetch; 5 | 6 | export default (url, options) => { 7 | if (options === undefined) { 8 | options = { 9 | method: "GET", 10 | credentials: "same-origin", 11 | headers: {}, 12 | }; 13 | } 14 | url = config.urlRoot + url; 15 | 16 | if (options.headers === undefined) { 17 | options.headers = {}; 18 | } 19 | options.credentials = "same-origin"; 20 | options.headers["Accept"] = "application/json"; 21 | options.headers["Content-Type"] = "application/json"; 22 | options.headers["CSRF-Token"] = config.csrfNonce; 23 | 24 | return fetch(url, options); 25 | }; 26 | -------------------------------------------------------------------------------- /CTFd/themes/admin/assets/js/compat/format.js: -------------------------------------------------------------------------------- 1 | //http://stackoverflow.com/a/2648463 - wizardry! 2 | String.prototype.format = String.prototype.f = function () { 3 | let s = this, 4 | i = arguments.length; 5 | 6 | while (i--) { 7 | s = s.replace(new RegExp("\\{" + i + "\\}", "gm"), arguments[i]); 8 | } 9 | return s; 10 | }; 11 | -------------------------------------------------------------------------------- /CTFd/themes/admin/assets/js/compat/math.js: -------------------------------------------------------------------------------- 1 | export function cumulativeSum(arr) { 2 | let result = arr.concat(); 3 | for (let i = 0; i < arr.length; i++) { 4 | result[i] = arr.slice(0, i + 1).reduce(function (p, i) { 5 | return p + i; 6 | }); 7 | } 8 | return result; 9 | } 10 | -------------------------------------------------------------------------------- /CTFd/themes/admin/assets/js/compat/styles.js: -------------------------------------------------------------------------------- 1 | // https://gist.github.com/0x263b/2bdd90886c2036a1ad5bcf06d6e6fb37 2 | export function colorHash(str) { 3 | let hash = 0; 4 | for (let i = 0; i < str.length; i++) { 5 | hash = str.charCodeAt(i) + ((hash << 5) - hash); 6 | hash = hash & hash; 7 | } 8 | // Range calculation 9 | // diff = max - min; 10 | // x = ((hash % diff) + diff) % diff; 11 | // return x + min; 12 | // Calculate HSL values 13 | // Range from 0 to 360 14 | let h = ((hash % 360) + 360) % 360; 15 | // Range from 75 to 100 16 | let s = (((hash % 25) + 25) % 25) + 75; 17 | // Range from 40 to 60 18 | let l = (((hash % 20) + 20) % 20) + 40; 19 | return `hsl(${h}, ${s}%, ${l}%)`; 20 | } 21 | -------------------------------------------------------------------------------- /CTFd/themes/admin/assets/js/compat/times.js: -------------------------------------------------------------------------------- 1 | import dayjs from "dayjs"; 2 | import advancedFormat from "dayjs/plugin/advancedFormat"; 3 | import $ from "jquery"; 4 | 5 | dayjs.extend(advancedFormat); 6 | 7 | export default () => { 8 | $("[data-time]").each((i, elem) => { 9 | let $elem = $(elem); 10 | let time = $elem.data("time"); 11 | let format = $elem.data("time-format") || "MMMM Do, h:mm:ss A"; 12 | elem.innerText = dayjs(time).format(format); 13 | }); 14 | }; 15 | -------------------------------------------------------------------------------- /CTFd/themes/admin/assets/js/compat/ui.js: -------------------------------------------------------------------------------- 1 | import $ from "jquery"; 2 | 3 | export function copyToClipboard(event, selector) { 4 | // Select element 5 | $(selector).select(); 6 | 7 | // Copy to clipboard 8 | document.execCommand("copy"); 9 | 10 | // Show tooltip to user 11 | $(event.target).tooltip({ 12 | title: "Copied!", 13 | trigger: "manual", 14 | }); 15 | $(event.target).tooltip("show"); 16 | 17 | setTimeout(function () { 18 | $(event.target).tooltip("hide"); 19 | }, 1500); 20 | } 21 | -------------------------------------------------------------------------------- /CTFd/themes/admin/assets/js/pages/events.js: -------------------------------------------------------------------------------- 1 | import $ from "jquery"; 2 | import events from "../compat/events"; 3 | import CTFd from "../../compat/CTFd"; 4 | 5 | $(() => { 6 | events(CTFd.config.urlRoot); 7 | }); 8 | -------------------------------------------------------------------------------- /CTFd/themes/admin/assets/js/pages/main.js: -------------------------------------------------------------------------------- 1 | import CTFd from "../compat/CTFd"; 2 | import Alpine from "alpinejs"; 3 | import $ from "jquery"; 4 | import dayjs from "dayjs"; 5 | import advancedFormat from "dayjs/plugin/advancedFormat"; 6 | import nunjucks from "nunjucks"; 7 | import { Howl } from "howler"; 8 | import events from "../compat/events"; 9 | import times from "../compat/times"; 10 | import "../compat/json"; 11 | import styles from "../styles"; 12 | import { default as helpers } from "../compat/helpers"; 13 | 14 | dayjs.extend(advancedFormat); 15 | 16 | CTFd.init(window.init); 17 | window.CTFd = CTFd; 18 | window.Alpine = Alpine; 19 | window.helpers = helpers; 20 | window.$ = $; 21 | window.dayjs = dayjs; 22 | window.nunjucks = nunjucks; 23 | window.Howl = Howl; 24 | 25 | $(() => { 26 | styles(); 27 | times(); 28 | events(CTFd.config.urlRoot); 29 | }); 30 | -------------------------------------------------------------------------------- /CTFd/themes/admin/assets/js/pages/pages.js: -------------------------------------------------------------------------------- 1 | import "./main"; 2 | import CTFd from "../compat/CTFd"; 3 | import $ from "jquery"; 4 | import { ezQuery } from "../compat/ezq"; 5 | 6 | function deleteSelectedUsers(_event) { 7 | let pageIDs = $("input[data-page-id]:checked").map(function () { 8 | return $(this).data("page-id"); 9 | }); 10 | let target = pageIDs.length === 1 ? "page" : "pages"; 11 | 12 | ezQuery({ 13 | title: "Delete Pages", 14 | body: `Are you sure you want to delete ${pageIDs.length} ${target}?`, 15 | success: function () { 16 | const reqs = []; 17 | for (var pageID of pageIDs) { 18 | reqs.push( 19 | CTFd.fetch(`/api/v1/pages/${pageID}`, { 20 | method: "DELETE", 21 | }), 22 | ); 23 | } 24 | Promise.all(reqs).then((_responses) => { 25 | window.location.reload(); 26 | }); 27 | }, 28 | }); 29 | } 30 | 31 | $(() => { 32 | $("#pages-delete-button").click(deleteSelectedUsers); 33 | }); 34 | -------------------------------------------------------------------------------- /CTFd/themes/admin/assets/js/pages/reset.js: -------------------------------------------------------------------------------- 1 | import "./main"; 2 | import $ from "jquery"; 3 | import { ezQuery } from "../compat/ezq"; 4 | 5 | function reset(event) { 6 | event.preventDefault(); 7 | ezQuery({ 8 | title: "Reset CTF?", 9 | body: "Are you sure you want to reset your CTFd instance?", 10 | success: function () { 11 | $("#reset-ctf-form").off("submit").submit(); 12 | }, 13 | }); 14 | } 15 | 16 | $(() => { 17 | $("#reset-ctf-form").submit(reset); 18 | }); 19 | -------------------------------------------------------------------------------- /CTFd/themes/admin/assets/js/pages/style.js: -------------------------------------------------------------------------------- 1 | import $ from "jquery"; 2 | import styles from "../styles"; 3 | import times from "../compat/times"; 4 | 5 | $(() => { 6 | styles(); 7 | times(); 8 | }); 9 | -------------------------------------------------------------------------------- /CTFd/themes/admin/assets/js/templates/admin-flags-table.njk: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | {% for flag in flags %} 11 | 12 | 13 | 14 | 19 | 20 | {% endfor %} 21 | 22 |
TypeKeySettings
{{flag.type}}
{{flag.content}}
15 | 16 | 17 | 18 |
-------------------------------------------------------------------------------- /CTFd/themes/admin/static/assets/CommentBox-Cv-MSlYY.css: -------------------------------------------------------------------------------- 1 | .card .close[data-v-aa95975f]{opacity:0;transition:.2s}.card:hover .close[data-v-aa95975f]{opacity:.5}.close[data-v-aa95975f]:hover{opacity:.75!important}.comment-card-leave[data-v-aa95975f]{max-height:200px}.comment-card-leave-to[data-v-aa95975f]{max-height:0}.comment-card-active[data-v-aa95975f]{position:absolute}.comment-card-enter-active[data-v-aa95975f],.comment-card-move[data-v-aa95975f],.comment-card-leave-active[data-v-aa95975f]{transition:all .3s} 2 | -------------------------------------------------------------------------------- /CTFd/themes/admin/static/assets/challenge-DY7T5JQl.css: -------------------------------------------------------------------------------- 1 | .flip-list-move[data-v-a3fa86b4]{transition:transform .5s ease}.scrollbox[data-v-a3fa86b4]{overflow:auto;max-height:40vh;background:linear-gradient(#fff 30%,#fff0),linear-gradient(#fff0,#fff 70%) 0 100%,radial-gradient(50% 0,farthest-side,rgba(0,0,0,.2),rgba(0,0,0,0)),radial-gradient(50% 100%,farthest-side,rgba(0,0,0,.2),rgba(0,0,0,0)) 0 100%;background:linear-gradient(#fff 30%,#fff0),linear-gradient(#fff0,#fff 70%) 0 100%,radial-gradient(farthest-side at 50% 0,#0003,#0000),radial-gradient(farthest-side at 50% 100%,#0003,#0000) 0 100%;background-repeat:no-repeat;background-color:#fff;background-size:100% 40px,100% 40px,100% 14px,100% 14px;background-attachment:local,local,scroll,scroll} 2 | -------------------------------------------------------------------------------- /CTFd/themes/admin/static/assets/challenge-board-css-CpAEjUPb.css: -------------------------------------------------------------------------------- 1 | .chal-desc{padding-left:30px;padding-right:30px;font-size:14px}.chal-desc img{max-width:100%;height:auto}.modal-content{border-radius:0;max-width:1000px;padding:1em;margin:0 auto}.btn-info,.badge-info{background-color:#5b7290!important}.challenge-button{box-shadow:3px 3px 3px gray}.solved-challenge{background-color:#37d63e!important;opacity:.4;border:none}.corner-button-check{margin-top:-10px;margin-right:25px;position:absolute;right:0}.key-submit .btn{height:51px}#challenge-window .form-control{position:relative;display:block;padding:.8em;border-radius:0;background:#f0f0f0;color:#aaa;font-weight:400;font-family:Avenir Next,Helvetica Neue,Helvetica,Arial,sans-serif;-webkit-appearance:none;height:auto!important}#challenge-window .form-control:focus{background-color:transparent;border-color:#a3d39c;box-shadow:0 0 0 .1rem #a3d39c;transition:background-color .3s,border-color .3s} 2 | -------------------------------------------------------------------------------- /CTFd/themes/admin/static/assets/echarts-l0sNRNKZ.js: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /CTFd/themes/admin/static/assets/pages/pages-D6wLDtJe.js: -------------------------------------------------------------------------------- 1 | import{$ as e,u as n,C as l}from"./main-D_lcMXdT.js";function r(d){let t=e("input[data-page-id]:checked").map(function(){return e(this).data("page-id")}),s=t.length===1?"page":"pages";n({title:"Delete Pages",body:`Are you sure you want to delete ${t.length} ${s}?`,success:function(){const a=[];for(var o of t)a.push(l.fetch(`/api/v1/pages/${o}`,{method:"DELETE"}));Promise.all(a).then(i=>{window.location.reload()})}})}e(()=>{e("#pages-delete-button").click(r)}); 2 | -------------------------------------------------------------------------------- /CTFd/themes/admin/static/assets/pages/reset-BblvWpk1.js: -------------------------------------------------------------------------------- 1 | import{$ as e,u as s}from"./main-D_lcMXdT.js";function r(t){t.preventDefault(),s({title:"Reset CTF?",body:"Are you sure you want to reset your CTFd instance?",success:function(){e("#reset-ctf-form").off("submit").submit()}})}e(()=>{e("#reset-ctf-form").submit(r)}); 2 | -------------------------------------------------------------------------------- /CTFd/themes/admin/static/img/README.md: -------------------------------------------------------------------------------- 1 | Original Logo by [Laura Barbera](https://dribbble.com/lauragallisa) 2 | Updated by [Kevin Chung](https://github.com/ColdHeat) 3 | -------------------------------------------------------------------------------- /CTFd/themes/admin/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/img/favicon.ico -------------------------------------------------------------------------------- /CTFd/themes/admin/static/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/img/logo.png -------------------------------------------------------------------------------- /CTFd/themes/admin/static/sounds/README.md: -------------------------------------------------------------------------------- 1 | Notification Sound by [Terrence Martin](https://soundcloud.com/tj-martin-composer) 2 | -------------------------------------------------------------------------------- /CTFd/themes/admin/static/sounds/notification.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/sounds/notification.mp3 -------------------------------------------------------------------------------- /CTFd/themes/admin/static/sounds/notification.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/sounds/notification.webm -------------------------------------------------------------------------------- /CTFd/themes/admin/static/webfonts/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/webfonts/fa-brands-400.ttf -------------------------------------------------------------------------------- /CTFd/themes/admin/static/webfonts/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/webfonts/fa-brands-400.woff2 -------------------------------------------------------------------------------- /CTFd/themes/admin/static/webfonts/fa-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/webfonts/fa-regular-400.ttf -------------------------------------------------------------------------------- /CTFd/themes/admin/static/webfonts/fa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/webfonts/fa-regular-400.woff2 -------------------------------------------------------------------------------- /CTFd/themes/admin/static/webfonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/webfonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /CTFd/themes/admin/static/webfonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/webfonts/fa-solid-900.woff2 -------------------------------------------------------------------------------- /CTFd/themes/admin/static/webfonts/fa-v4compatibility.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/webfonts/fa-v4compatibility.ttf -------------------------------------------------------------------------------- /CTFd/themes/admin/static/webfonts/fa-v4compatibility.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/webfonts/fa-v4compatibility.woff2 -------------------------------------------------------------------------------- /CTFd/themes/admin/static/webfonts/lato-latin-400-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/webfonts/lato-latin-400-normal.woff -------------------------------------------------------------------------------- /CTFd/themes/admin/static/webfonts/lato-latin-400-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/webfonts/lato-latin-400-normal.woff2 -------------------------------------------------------------------------------- /CTFd/themes/admin/static/webfonts/lato-latin-700-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/webfonts/lato-latin-700-normal.woff -------------------------------------------------------------------------------- /CTFd/themes/admin/static/webfonts/lato-latin-700-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/webfonts/lato-latin-700-normal.woff2 -------------------------------------------------------------------------------- /CTFd/themes/admin/static/webfonts/lato-latin-ext-400-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/webfonts/lato-latin-ext-400-normal.woff -------------------------------------------------------------------------------- /CTFd/themes/admin/static/webfonts/lato-latin-ext-400-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/webfonts/lato-latin-ext-400-normal.woff2 -------------------------------------------------------------------------------- /CTFd/themes/admin/static/webfonts/lato-latin-ext-700-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/webfonts/lato-latin-ext-700-normal.woff -------------------------------------------------------------------------------- /CTFd/themes/admin/static/webfonts/lato-latin-ext-700-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/webfonts/lato-latin-ext-700-normal.woff2 -------------------------------------------------------------------------------- /CTFd/themes/admin/static/webfonts/raleway-cyrillic-500-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/webfonts/raleway-cyrillic-500-normal.woff -------------------------------------------------------------------------------- /CTFd/themes/admin/static/webfonts/raleway-cyrillic-500-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/webfonts/raleway-cyrillic-500-normal.woff2 -------------------------------------------------------------------------------- /CTFd/themes/admin/static/webfonts/raleway-cyrillic-ext-500-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/webfonts/raleway-cyrillic-ext-500-normal.woff -------------------------------------------------------------------------------- /CTFd/themes/admin/static/webfonts/raleway-cyrillic-ext-500-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/webfonts/raleway-cyrillic-ext-500-normal.woff2 -------------------------------------------------------------------------------- /CTFd/themes/admin/static/webfonts/raleway-latin-500-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/webfonts/raleway-latin-500-normal.woff -------------------------------------------------------------------------------- /CTFd/themes/admin/static/webfonts/raleway-latin-500-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/webfonts/raleway-latin-500-normal.woff2 -------------------------------------------------------------------------------- /CTFd/themes/admin/static/webfonts/raleway-latin-ext-500-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/webfonts/raleway-latin-ext-500-normal.woff -------------------------------------------------------------------------------- /CTFd/themes/admin/static/webfonts/raleway-latin-ext-500-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/webfonts/raleway-latin-ext-500-normal.woff2 -------------------------------------------------------------------------------- /CTFd/themes/admin/static/webfonts/raleway-vietnamese-500-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/webfonts/raleway-vietnamese-500-normal.woff -------------------------------------------------------------------------------- /CTFd/themes/admin/static/webfonts/raleway-vietnamese-500-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/admin/static/webfonts/raleway-vietnamese-500-normal.woff2 -------------------------------------------------------------------------------- /CTFd/themes/admin/templates/configs/brackets.html: -------------------------------------------------------------------------------- 1 |
2 |
Scoreboard Brackets
3 |
4 |
5 |
6 | -------------------------------------------------------------------------------- /CTFd/themes/admin/templates/configs/localization.html: -------------------------------------------------------------------------------- 1 |
2 | {% 3 | with form = Forms.config.LocalizationForm( 4 | default_locale=default_locale 5 | ) 6 | %} 7 |
8 |
9 | {{ form.default_locale.label }} 10 | {{ form.default_locale(class="form-control custom-select") }} 11 | 12 | {{ form.default_locale.description }} 13 | 14 |
15 | 16 | 17 |
18 | {% endwith %} 19 |
20 | -------------------------------------------------------------------------------- /CTFd/themes/admin/templates/configs/pause.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | 9 |
10 | 11 | Prevent users from submitting answers until unpaused. Challenges can still be viewed. 12 | 13 |
14 | 15 | 16 |
17 |
18 | -------------------------------------------------------------------------------- /CTFd/themes/admin/templates/configs/registration_code.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 8 | 10 |
11 | 12 | 13 |
14 |
15 | -------------------------------------------------------------------------------- /CTFd/themes/admin/templates/configs/robots.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 10 | 11 |
12 | 13 |
14 |
15 | -------------------------------------------------------------------------------- /CTFd/themes/admin/templates/configs/social.html: -------------------------------------------------------------------------------- 1 |
2 | {% set social_shares = "true" if social_shares == True else "false" %} 3 | {% with form = Forms.config.SocialSettingsForm(social_shares=social_shares) %} 4 |
5 |
6 | {{ form.social_shares.label }} 7 | {{ form.social_shares(class="form-control", value=social_shares) }} 8 | 9 | {{ form.social_shares.description }} 10 | 11 |
12 | {{ form.submit(class="btn btn-md btn-primary float-right") }} 13 |
14 | {% endwith %} 15 |
16 | -------------------------------------------------------------------------------- /CTFd/themes/admin/templates/integrations.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 |
5 |
6 |
7 |
Integration enabled!
8 |

You may now close this tab.

9 |
10 |
11 |
12 | {% endblock %} 13 | 14 | {% block scripts %} 15 | 27 | {% endblock %} 28 | -------------------------------------------------------------------------------- /CTFd/themes/admin/templates/modals/challenges/challenges.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /CTFd/themes/admin/templates/modals/challenges/files.html: -------------------------------------------------------------------------------- 1 |
2 |
-------------------------------------------------------------------------------- /CTFd/themes/admin/templates/modals/challenges/flags.html: -------------------------------------------------------------------------------- 1 |
2 |
-------------------------------------------------------------------------------- /CTFd/themes/admin/templates/modals/challenges/hints.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /CTFd/themes/admin/templates/modals/challenges/next.html: -------------------------------------------------------------------------------- 1 |
2 |
-------------------------------------------------------------------------------- /CTFd/themes/admin/templates/modals/challenges/requirements.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
-------------------------------------------------------------------------------- /CTFd/themes/admin/templates/modals/challenges/solves.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | {% if solves is defined %} 10 | {% for solve in solves %} 11 | 12 | 17 | 20 | 21 | {% endfor %} 22 | {% endif %} 23 | 24 |
NameDate
13 | 14 | {{ solve.account.name }} 15 | 16 | 18 | 19 |
25 | -------------------------------------------------------------------------------- /CTFd/themes/admin/templates/modals/challenges/tags.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | -------------------------------------------------------------------------------- /CTFd/themes/admin/templates/modals/challenges/topics.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | -------------------------------------------------------------------------------- /CTFd/themes/admin/templates/modals/mail/send.html: -------------------------------------------------------------------------------- 1 | {% with form = Forms.email.SendEmailForm() %} 2 |
3 |
4 | {{ form.text.label }} 5 | {{ form.text(class="form-control", rows="15") }} 6 |
7 |
8 | 9 |
10 | {{ form.submit(class="btn btn-primary float-right") }} 11 |
12 | {% endwith %} 13 | -------------------------------------------------------------------------------- /CTFd/themes/admin/templates/modals/teams/captain.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | 15 |
16 |
17 | 18 |
19 | 22 |
-------------------------------------------------------------------------------- /CTFd/themes/admin/templates/modals/teams/statistics.html: -------------------------------------------------------------------------------- 1 |
2 | {% if solves %} 3 |
4 |
5 | 6 |
7 |
8 |
9 |
10 | 11 |
12 |
13 |
14 |
15 | 16 |
17 |
18 | {% else %} 19 |

20 | No data yet 21 |

22 | {% endif %} 23 |
24 | -------------------------------------------------------------------------------- /CTFd/themes/admin/templates/modals/users/statistics.html: -------------------------------------------------------------------------------- 1 |
2 | {% if solves %} 3 |
4 |
5 | 6 |
7 |
8 |
9 |
10 | 11 |
12 |
13 |
14 |
15 | 16 |
17 |
18 | {% else %} 19 |

20 | No data yet 21 |

22 | {% endif %} 23 |
24 | -------------------------------------------------------------------------------- /CTFd/themes/admin/templates/page.html: -------------------------------------------------------------------------------- 1 | {% extends "admin/base.html" %} 2 | 3 | {% block content %} 4 |
5 | {{ content | safe }} 6 |
7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /CTFd/themes/admin/templates/teams/new.html: -------------------------------------------------------------------------------- 1 | {% extends "admin/base.html" %} 2 | 3 | {% block stylesheets %} 4 | {% endblock %} 5 | 6 | {% block content %} 7 |
8 |
9 |

10 | Create Team 11 |

12 |
13 |
14 | 15 |
16 |
17 |
18 | {% include "admin/modals/teams/create.html" %} 19 |
20 |
21 |
22 | {% endblock %} 23 | 24 | {% block scripts %} 25 | {% endblock %} 26 | 27 | {% block entrypoint %} 28 | {{ Assets.js("assets/js/pages/team.js", theme="admin") }} 29 | {% endblock %} 30 | -------------------------------------------------------------------------------- /CTFd/themes/admin/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {% extends "admin/base.html" %} 2 | 3 | {% block stylesheets %} 4 | {% endblock %} 5 | 6 | {% block content %} 7 |
8 |
9 |

10 | Create User 11 |

12 |
13 |
14 | 15 |
16 |
17 |
18 | {% include "admin/modals/users/create.html" %} 19 |
20 |
21 |
22 | {% endblock %} 23 | 24 | {% block scripts %} 25 | {% endblock %} 26 | 27 | {% block entrypoint %} 28 | {{ Assets.js("assets/js/pages/user.js", theme="admin") }} 29 | {% endblock %} 30 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | push: 5 | branches: main 6 | 7 | jobs: 8 | static: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: actions/checkout@v3 13 | with: 14 | repository: ${{ github.event.pull_request.head.repo.full_name }} 15 | ref: ${{ github.event.pull_request.head.ref }} 16 | - name: Setup node.js 17 | uses: actions/setup-node@v3 18 | with: 19 | node-version: '16.x' 20 | - name: Install dependencies 21 | run: yarn --frozen-lockfile 22 | - name: Format 23 | run: yarn format 24 | - name: Build 25 | run: yarn build 26 | - name: Push built files 27 | uses: EndBug/add-and-commit@v9 28 | with: 29 | default_author: github_actions 30 | message: "chore: yarn build" -------------------------------------------------------------------------------- /CTFd/themes/core-beta/.github/workflows/prettier.yml: -------------------------------------------------------------------------------- 1 | name: prettier 2 | 3 | on: [ pull_request ] 4 | 5 | jobs: 6 | lint: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/checkout@v3 11 | with: 12 | repository: ${{ github.event.pull_request.head.repo.full_name }} 13 | ref: ${{ github.event.pull_request.head.ref }} 14 | - name: Setup node.js 15 | uses: actions/setup-node@v3 16 | with: 17 | node-version: '16.x' 18 | - name: Install dependencies 19 | run: yarn --frozen-lockfile 20 | - name: Lint with prettier 21 | run: yarn lint -------------------------------------------------------------------------------- /CTFd/themes/core-beta/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/.prettierignore: -------------------------------------------------------------------------------- 1 | static 2 | **/*.html -------------------------------------------------------------------------------- /CTFd/themes/core-beta/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 88, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/README.md: -------------------------------------------------------------------------------- 1 | # core-beta 2 | 3 | Rewritten version of the CTFd core theme to use Bootstrap 5, Alpine.js, and vite to improve upon the existing CTFd theme structure. 4 | 5 | ## Subtree Installation 6 | 7 | ### Add repo to themes folder 8 | 9 | ``` 10 | git subtree add --prefix CTFd/themes/core-beta git@github.com:CTFd/core-beta.git main --squash 11 | ``` 12 | 13 | ### Pull latest changes to subtree 14 | ``` 15 | git subtree pull --prefix CTFd/themes/core-beta git@github.com:CTFd/core-beta.git main --squash 16 | ``` 17 | 18 | ### Subtree Gotcha 19 | 20 | Make sure to use Merge Commits when dealing with the subtree here. For some reason Github's squash and commit uses the wrong line ending which causes issues with the subtree script: https://stackoverflow.com/a/47190256. 21 | 22 | ## Todo 23 | 24 | - Document how we are using Vite 25 | - Create a cookie cutter template package to use with Vite 26 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/assets/img/favicon.ico -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/js/index.js: -------------------------------------------------------------------------------- 1 | import CTFd from "@ctfdio/ctfd-js"; 2 | 3 | import dayjs from "dayjs"; 4 | import advancedFormat from "dayjs/plugin/advancedFormat"; 5 | 6 | import times from "./theme/times"; 7 | import styles from "./theme/styles"; 8 | import highlight from "./theme/highlight"; 9 | 10 | import alerts from "./utils/alerts"; 11 | import tooltips from "./utils/tooltips"; 12 | import collapse from "./utils/collapse"; 13 | 14 | import eventAlerts from "./utils/notifications/alerts"; 15 | import eventToasts from "./utils/notifications/toasts"; 16 | import eventRead from "./utils/notifications/read"; 17 | 18 | dayjs.extend(advancedFormat); 19 | CTFd.init(window.init); 20 | 21 | (() => { 22 | styles(); 23 | times(); 24 | highlight(); 25 | 26 | alerts(); 27 | tooltips(); 28 | collapse(); 29 | 30 | eventRead(); 31 | eventAlerts(); 32 | eventToasts(); 33 | })(); 34 | 35 | export default CTFd; 36 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/js/page.js: -------------------------------------------------------------------------------- 1 | import Alpine from "alpinejs"; 2 | import CTFd from "./index"; 3 | 4 | window.CTFd = CTFd; 5 | window.Alpine = Alpine; 6 | 7 | Alpine.start(); 8 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/js/teams/list.js: -------------------------------------------------------------------------------- 1 | import Alpine from "alpinejs"; 2 | import CTFd from "../index"; 3 | 4 | window.CTFd = CTFd; 5 | window.Alpine = Alpine; 6 | 7 | Alpine.start(); 8 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/js/theme/highlight.js: -------------------------------------------------------------------------------- 1 | import CTFd from "../index"; 2 | import lolight from "lolight"; 3 | 4 | export default () => { 5 | if ( 6 | // default to true if config is not defined yet 7 | !CTFd.config.themeSettings.hasOwnProperty("use_builtin_code_highlighter") || 8 | CTFd.config.themeSettings.use_builtin_code_highlighter === true 9 | ) { 10 | lolight("pre code"); 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/js/theme/styles.js: -------------------------------------------------------------------------------- 1 | export default () => { 2 | document.querySelectorAll(".form-control").forEach($el => { 3 | $el.addEventListener("onfocus", () => { 4 | $el.classList.remove("input-filled-invalid"); 5 | $el.classList.add("input-filled-valid"); 6 | }); 7 | 8 | $el.addEventListener("onblur", () => { 9 | if ($el.nodeValue === "") { 10 | $el.classList.remove("input-filled-valid"); 11 | $el.classList.remove("input-filled-invalid"); 12 | } 13 | }); 14 | 15 | if ($el.nodeValue) { 16 | $el.classList.add("input-filled-valid"); 17 | } 18 | }); 19 | 20 | document.querySelectorAll(".page-select").forEach($el => { 21 | $el.addEventListener("change", e => { 22 | const url = new URL(window.location); 23 | url.searchParams.set("page", e.target.value ?? "1"); 24 | window.location.href = url.toString(); 25 | }); 26 | }); 27 | }; 28 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/js/theme/times.js: -------------------------------------------------------------------------------- 1 | import dayjs from "dayjs"; 2 | import advancedFormat from "dayjs/plugin/advancedFormat"; 3 | 4 | dayjs.extend(advancedFormat); 5 | 6 | export default () => { 7 | document.querySelectorAll("[data-time]").forEach($el => { 8 | const time = $el.getAttribute("data-time"); 9 | const format = $el.getAttribute("data-time-format") || "MMMM Do, h:mm:ss A"; 10 | $el.innerText = dayjs(time).format(format); 11 | }); 12 | }; 13 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/js/users/list.js: -------------------------------------------------------------------------------- 1 | import Alpine from "alpinejs"; 2 | import CTFd from "../index"; 3 | 4 | window.CTFd = CTFd; 5 | window.Alpine = Alpine; 6 | 7 | Alpine.start(); 8 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/js/utils/alerts.js: -------------------------------------------------------------------------------- 1 | import { Alert } from "bootstrap"; 2 | 3 | export default () => { 4 | const alertList = [].slice.call(document.querySelectorAll(".alert")); 5 | alertList.map(function (element) { 6 | return new Alert(element); 7 | }); 8 | }; 9 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/js/utils/clipboard.js: -------------------------------------------------------------------------------- 1 | import { Tooltip } from "bootstrap"; 2 | 3 | export function copyToClipboard($input) { 4 | const tooltip = new Tooltip($input, { 5 | title: "Copied!", 6 | trigger: "manual", 7 | }); 8 | 9 | navigator.clipboard.writeText($input.value).then(() => { 10 | tooltip.show(); 11 | setTimeout(() => { 12 | tooltip.hide(); 13 | }, 1500); 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/js/utils/collapse.js: -------------------------------------------------------------------------------- 1 | import { Collapse } from "bootstrap"; 2 | 3 | export default () => { 4 | const collapseList = [].slice.call(document.querySelectorAll(".collapse")); 5 | collapseList.map(element => { 6 | return new Collapse(element, { toggle: false }); 7 | }); 8 | }; 9 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/js/utils/math.js: -------------------------------------------------------------------------------- 1 | export function cumulativeSum(arr) { 2 | let result = arr.concat(); 3 | for (let i = 0; i < arr.length; i++) { 4 | result[i] = arr.slice(0, i + 1).reduce(function (p, i) { 5 | return p + i; 6 | }); 7 | } 8 | return result; 9 | } 10 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/js/utils/notifications/alerts.js: -------------------------------------------------------------------------------- 1 | import Alpine from "alpinejs"; 2 | import { Modal } from "bootstrap"; 3 | 4 | import CTFd from "../../index"; 5 | 6 | export default () => { 7 | Alpine.store("modal", { title: "", html: "" }); 8 | 9 | CTFd._functions.events.eventAlert = data => { 10 | Alpine.store("modal", data); 11 | let modal = new Modal(document.querySelector("[x-ref='modal']")); 12 | // TODO: Get rid of this private attribute access 13 | // See https://github.com/twbs/bootstrap/issues/31266 14 | modal._element.addEventListener( 15 | "hidden.bs.modal", 16 | event => { 17 | CTFd._functions.events.eventRead(data.id); 18 | }, 19 | { once: true }, 20 | ); 21 | modal.show(); 22 | }; 23 | }; 24 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/js/utils/notifications/read.js: -------------------------------------------------------------------------------- 1 | import Alpine from "alpinejs"; 2 | import CTFd from "../../index"; 3 | 4 | export default () => { 5 | CTFd._functions.events.eventCount = count => { 6 | Alpine.store("unread_count", count); 7 | }; 8 | 9 | CTFd._functions.events.eventRead = eventId => { 10 | CTFd.events.counter.read.add(eventId); 11 | let count = CTFd.events.counter.unread.getAll().length; 12 | CTFd.events.controller.broadcast("counter", { count: count }); 13 | Alpine.store("unread_count", count); 14 | }; 15 | 16 | document.addEventListener("alpine:init", () => { 17 | CTFd._functions.events.eventCount(CTFd.events.counter.unread.getAll().length); 18 | }); 19 | }; 20 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/js/utils/notifications/toasts.js: -------------------------------------------------------------------------------- 1 | import Alpine from "alpinejs"; 2 | import { Toast } from "bootstrap"; 3 | import CTFd from "../../index"; 4 | 5 | export default () => { 6 | Alpine.store("toast", { title: "", html: "" }); 7 | 8 | CTFd._functions.events.eventToast = data => { 9 | Alpine.store("toast", data); 10 | let toast = new Toast(document.querySelector("[x-ref='toast']")); 11 | // TODO: Get rid of this private attribute access 12 | // See https://github.com/twbs/bootstrap/issues/31266 13 | let close = toast._element.querySelector("[data-bs-dismiss='toast']"); 14 | let handler = event => { 15 | CTFd._functions.events.eventRead(data.id); 16 | }; 17 | close.addEventListener("click", handler, { once: true }); 18 | toast._element.addEventListener( 19 | "hidden.bs.toast", 20 | event => { 21 | close.removeEventListener("click", handler); 22 | }, 23 | { once: true }, 24 | ); 25 | 26 | toast.show(); 27 | }; 28 | }; 29 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/js/utils/objects.js: -------------------------------------------------------------------------------- 1 | export function mergeObjects(target, source) { 2 | // https://stackoverflow.com/a/65817907 3 | // Iterate through `source` properties and if an `Object` set property to merge of `target` and `source` properties 4 | for (const key of Object.keys(source)) { 5 | if (source[key] instanceof Object) 6 | Object.assign(source[key], mergeObjects(target[key], source[key])); 7 | } 8 | // Join `target` and modified `source` 9 | Object.assign(target || {}, source); 10 | return target; 11 | } 12 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/js/utils/tooltips.js: -------------------------------------------------------------------------------- 1 | import { Tooltip } from "bootstrap"; 2 | 3 | export default () => { 4 | const tooltipList = [].slice.call( 5 | document.querySelectorAll('[data-bs-toggle="tooltip"]'), 6 | ); 7 | tooltipList.map(element => { 8 | return new Tooltip(element); 9 | }); 10 | }; 11 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/scss/includes/components/_challenge.scss: -------------------------------------------------------------------------------- 1 | /* Challenge styles 2 | -------------------------------------------------- */ 3 | 4 | .challenge-desc { 5 | overflow-wrap: anywhere; 6 | 7 | img { 8 | max-width: 100%; 9 | } 10 | } 11 | 12 | [data-bs-theme="light"] .challenge-button { 13 | border: none; 14 | box-shadow: 0 0 15px var(--bs-secondary); 15 | 16 | &.challenge-solved { 17 | background-color: #29c830; 18 | 19 | &:hover { 20 | background-color: #37d63e; 21 | } 22 | } 23 | } 24 | 25 | [data-bs-theme="dark"] .challenge-button { 26 | border: none; 27 | background-color: var(--bs-gray-dark); 28 | 29 | &:hover { 30 | background-color: var(--bs-gray); 31 | } 32 | 33 | &.challenge-solved { 34 | background-color: #29c830; 35 | 36 | &:hover { 37 | background-color: #37d63e; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/scss/includes/components/_graphs.scss: -------------------------------------------------------------------------------- 1 | /* Graph styles 2 | -------------------------------------------------- */ 3 | 4 | #score-graph { 5 | min-height: 400px; 6 | } 7 | 8 | #solves-graph { 9 | display: block; 10 | height: 350px; 11 | } 12 | 13 | #keys-pie-graph { 14 | min-height: 400px; 15 | display: block; 16 | } 17 | 18 | #categories-pie-graph { 19 | min-height: 400px; 20 | display: block; 21 | } 22 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/scss/includes/components/_jumbotron.scss: -------------------------------------------------------------------------------- 1 | /* Jumbotron styles 2 | -------------------------------------------------- */ 3 | 4 | // Move down content because we have a fixed navbar that is 3.5rem tall 5 | main { 6 | padding-top: 3.5rem; 7 | } 8 | 9 | .jumbotron { 10 | padding: 2rem 1rem; 11 | margin-bottom: 2rem; 12 | text-align: center; 13 | 14 | background-color: var(--bs-dark); 15 | color: var(--bs-white); 16 | } 17 | 18 | @media (min-width: 576px) { 19 | .jumbotron { 20 | padding: 4rem 2rem; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/scss/includes/components/_sticky-footer.scss: -------------------------------------------------------------------------------- 1 | /* Sticky footer styles 2 | -------------------------------------------------- */ 3 | html { 4 | position: relative; 5 | min-height: 100%; 6 | } 7 | 8 | main { 9 | /* Margin bottom by footer height */ 10 | margin-bottom: 100px; 11 | } 12 | 13 | .footer { 14 | position: absolute; 15 | 16 | /* prevent scrollbars from showing on pages that don't use the full page height */ 17 | bottom: 1px; 18 | 19 | width: 100%; 20 | 21 | /* Set the fixed height of the footer here */ 22 | height: 60px; 23 | 24 | /* Vertically center the text there */ 25 | line-height: 60px; 26 | 27 | /* Avoid covering things */ 28 | z-index: -20; 29 | 30 | /*background-color: #f5f5f5;*/ 31 | } 32 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/scss/includes/components/_table.scss: -------------------------------------------------------------------------------- 1 | /* Table styles 2 | -------------------------------------------------- */ 3 | 4 | // Center text in table cells, except the first cell 5 | .table tr > :not(:first-child) { 6 | text-align: center; 7 | } 8 | 9 | // Add some default spacing to table cells 10 | .table > tbody > tr > td { 11 | padding: 0.8rem 1rem; 12 | } 13 | 14 | // Add some padding from the edge of table 15 | .table > thead > tr > :first-child { 16 | padding-left: 1rem; 17 | } 18 | 19 | // Do not wrap text in table headers 20 | .table > thead > th { 21 | white-space: nowrap; 22 | } 23 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/scss/includes/icons/_award-icons.scss: -------------------------------------------------------------------------------- 1 | .award-icon { 2 | font-family: "Font Awesome 6 Free"; 3 | font-weight: 900; 4 | -moz-osx-font-smoothing: grayscale; 5 | -webkit-font-smoothing: antialiased; 6 | display: inline-block; 7 | font-style: normal; 8 | font-variant: normal; 9 | text-rendering: auto; 10 | line-height: 1; 11 | } 12 | 13 | .award-shield:before { 14 | content: "\f3ed"; 15 | } 16 | .award-bug:before { 17 | content: "\f188"; 18 | } 19 | .award-crown:before { 20 | content: "\f521"; 21 | } 22 | .award-crosshairs:before { 23 | content: "\f05b"; 24 | } 25 | .award-ban:before { 26 | content: "\f05e"; 27 | } 28 | .award-brain:before { 29 | content: "\f5dc"; 30 | } 31 | .award-lightning:before { 32 | content: "\f0e7"; 33 | } 34 | .award-code:before { 35 | content: "\f121"; 36 | } 37 | .award-cowboy:before { 38 | content: "\f8c0"; 39 | } 40 | .award-angry:before { 41 | content: "\f556"; 42 | } 43 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/scss/includes/utils/_cursors.scss: -------------------------------------------------------------------------------- 1 | .cursor-pointer { 2 | cursor: pointer; 3 | } 4 | 5 | .cursor-help { 6 | cursor: help; 7 | } 8 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/scss/includes/utils/_fonts.scss: -------------------------------------------------------------------------------- 1 | @use "~/@fontsource/lato/scss/mixins" as Lato; 2 | @use "~/@fontsource/raleway/scss/mixins" as Raleway; 3 | 4 | // Include both normal and bold weights 5 | @include Lato.fontFace($fontDir: "../webfonts", $weight: 400); 6 | @include Lato.fontFace($fontDir: "../webfonts", $weight: 700); 7 | 8 | @include Raleway.fontFace($fontDir: "../webfonts"); 9 | 10 | $fa-font-path: "../webfonts"; 11 | @import "~/@fortawesome/fontawesome-free/scss/fontawesome.scss"; 12 | @import "~/@fortawesome/fontawesome-free/scss/solid.scss"; 13 | @import "~/@fortawesome/fontawesome-free/scss/brands.scss"; 14 | 15 | html, 16 | body, 17 | .container { 18 | font-family: "Lato", sans-serif; 19 | } 20 | 21 | .jumbotron .container { 22 | font-family: "Raleway", sans-serif; 23 | } 24 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/scss/includes/utils/_lolight.scss: -------------------------------------------------------------------------------- 1 | .ll-nam { 2 | /* words */ 3 | color: #24292f; 4 | } 5 | .ll-num { 6 | /* numbers */ 7 | color: #005cc5; 8 | } 9 | .ll-str { 10 | /* strings */ 11 | color: #0a3069; 12 | } 13 | .ll-rex { 14 | /* regular expressions */ 15 | color: #032f62; 16 | } 17 | .ll-pct { 18 | /* operators, punctuation */ 19 | color: #24292f; 20 | } 21 | .ll-key { 22 | /* keywords */ 23 | color: #d73a49; 24 | } 25 | .ll-com { 26 | /* comments */ 27 | color: #6a737d; 28 | font-style: italic; 29 | } 30 | 31 | [data-bs-theme="dark"] { 32 | .ll-nam { 33 | color: #c9d1d9; 34 | } 35 | .ll-num { 36 | color: #79c0ff; 37 | } 38 | .ll-str { 39 | color: #a5d6ff; 40 | } 41 | .ll-rex { 42 | color: #96cefb; 43 | } 44 | .ll-pct { 45 | color: #c9d1d9; 46 | } 47 | .ll-key { 48 | color: #ff7b72; 49 | } 50 | .ll-com { 51 | color: #8b949e; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/scss/includes/utils/_min-height.scss: -------------------------------------------------------------------------------- 1 | .min-vh-0 { 2 | min-height: 0 !important; 3 | } 4 | 5 | .min-vh-25 { 6 | min-height: 25vh !important; 7 | } 8 | 9 | .min-vh-50 { 10 | min-height: 50vh !important; 11 | } 12 | 13 | .min-vh-75 { 14 | min-height: 75vh !important; 15 | } 16 | 17 | .min-vh-100 { 18 | min-height: 100vh !important; 19 | } 20 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/assets/scss/includes/utils/_opacity.scss: -------------------------------------------------------------------------------- 1 | .opacity-0 { 2 | opacity: 0 !important; 3 | } 4 | 5 | .opacity-25 { 6 | opacity: 0.25 !important; 7 | } 8 | 9 | .opacity-50 { 10 | opacity: 0.5 !important; 11 | } 12 | 13 | .opacity-75 { 14 | opacity: 0.75 !important; 15 | } 16 | 17 | .opacity-100 { 18 | opacity: 1 !important; 19 | } 20 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "core-beta", 3 | "private": true, 4 | "version": "0.0.1", 5 | "scripts": { 6 | "dev": "vite build --watch", 7 | "build": "vite build", 8 | "format": "prettier --write assets/", 9 | "lint": "prettier --check assets/", 10 | "verify": "vite build; git diff --quiet --exit-code" 11 | }, 12 | "dependencies": { 13 | "@ctfdio/ctfd-js": "^0.0.14", 14 | "@fontsource/lato": "^4.5.3", 15 | "@fontsource/raleway": "^4.5.3", 16 | "@fortawesome/fontawesome-free": "6.5.1", 17 | "@popperjs/core": "^2.11.4", 18 | "alpinejs": "^3.9.1", 19 | "bootstrap": "^5.3.3", 20 | "bootstrap-multimodal": "~1.0.4", 21 | "dayjs": "^1.11.0", 22 | "echarts": "^5.3.2", 23 | "lolight": "^1.4.0", 24 | "vue": "^3.2.25" 25 | }, 26 | "devDependencies": { 27 | "@vitejs/plugin-vue": "^3.0.1", 28 | "prettier": "^3.2.5", 29 | "rollup-plugin-copy": "^3.4.0", 30 | "sass": "^1.49.7", 31 | "vite": "^3.0.5" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/postcss.config.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/postcss.config.js -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/assets/clipboard.0c9c5ddd.js: -------------------------------------------------------------------------------- 1 | import{a as u}from"./index.2e31e3b8.js";function r(a){const t=new FormData(a),c=[];for(const[l,n]of t)c.push({name:l,value:n});return c}function h(a,t,c){let l={},n=r(a);return a.querySelectorAll("input[type=checkbox]:checked").forEach(e=>{n.push({name:e.name,value:!0})}),a.querySelectorAll("input[type=checkbox]:not(:checked)").forEach(e=>{n.push({name:e.name,value:!1})}),n.map(e=>{if(c)if(e.value!==null&&e.value!=="")l[e.name]=e.value;else{let o=a.querySelector(`[name='${e.name}']`);t[o.name]!==o.value&&(l[e.name]=e.value)}else l[e.name]=e.value}),l}function m(a){const t=new u(a,{title:"Copied!",trigger:"manual"});navigator.clipboard.writeText(a.value).then(()=>{t.show(),setTimeout(()=>{t.hide()},1500)})}export{m as c,h as s}; 2 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/assets/color_mode_switcher.52334129.js: -------------------------------------------------------------------------------- 1 | function a(){const t=localStorage.getItem("theme");return t||(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light")}function c(t){const r=document.querySelector(".theme-switch i.fas");r.classList.toggle("fa-moon",t==="dark"),r.classList.toggle("fa-sun",t!=="dark")}let e=a();document.documentElement.setAttribute("data-bs-theme",e);window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",()=>{e=a(),document.documentElement.setAttribute("data-bs-theme",e),c(e)});window.addEventListener("load",()=>{c(e),document.querySelectorAll(".theme-switch").forEach(t=>{t.addEventListener("click",r=>{e=e==="light"?"dark":"light",document.documentElement.setAttribute("data-bs-theme",e),localStorage.setItem("theme",e),c(e),r.preventDefault()})})}); 2 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/assets/index.1cf73b05.js: -------------------------------------------------------------------------------- 1 | import{u as l,i as e,a as c,b as o,c as f,d as u,e as r,f as $,g as b,h as m,j as d,k as j,l as O,m as g}from"./echarts.128204f2.js";function h(n,t){for(const s of Object.keys(t))t[s]instanceof Object&&Object.assign(t[s],h(n[s],t[s]));return Object.assign(n||{},t),n}function p(n){let t=n.concat();for(let s=0;s{s&&s.resize()})}export{p as c,v as e,h as m}; 2 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/assets/notifications.91eecfcb.js: -------------------------------------------------------------------------------- 1 | import{C as e,m as n}from"./index.2e31e3b8.js";window.CTFd=e;window.Alpine=n;let l=e.events.counter.read.getLast();e.fetch(`/api/v1/notifications?since_id=${l}`).then(t=>t.json()).then(t=>{let a=t.data,o=e.events.counter.read.getAll();a.forEach(d=>{o.push(d.id)}),e.events.counter.read.setAll(o),e.events.counter.unread.readAll();let r=e.events.counter.unread.getAll().length;e.events.controller.broadcast("counter",{count:r}),n.store("unread_count",r)});n.start(); 2 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/assets/page.3c5083de.js: -------------------------------------------------------------------------------- 1 | import{C as o,m as d}from"./index.2e31e3b8.js";window.CTFd=o;window.Alpine=d;d.start(); 2 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/assets/teams_list.22e04d3a.js: -------------------------------------------------------------------------------- 1 | import{C as o,m as d}from"./index.2e31e3b8.js";window.CTFd=o;window.Alpine=d;d.start(); 2 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/assets/users_list.e03972e4.js: -------------------------------------------------------------------------------- 1 | import{C as o,m as d}from"./index.2e31e3b8.js";window.CTFd=o;window.Alpine=d;d.start(); 2 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/assets/userscore.32000323.js: -------------------------------------------------------------------------------- 1 | import{d as u,c}from"./index.2e31e3b8.js";import{c as m,m as h}from"./index.1cf73b05.js";function y(l,a,p,d,i){let e={title:{left:"center",text:"Score over Time"},tooltip:{trigger:"axis",axisPointer:{type:"cross"}},legend:{type:"scroll",orient:"horizontal",align:"left",bottom:0,data:[a]},toolbox:{feature:{saveAsImage:{}}},grid:{containLabel:!0},xAxis:[{type:"category",boundaryGap:!1,data:[]}],yAxis:[{type:"value"}],dataZoom:[{id:"dataZoomX",type:"slider",xAxisIndex:[0],filterMode:"filter",height:20,top:35,fillerColor:"rgba(233, 236, 241, 0.4)"}],series:[]};const n=[],r=[],o=p.concat(d);o.sort((t,s)=>new Date(t.date)-new Date(s.date));for(let t=0;t{e.xAxis[0].data.push(t)}),e.series.push({name:a,type:"line",label:{normal:{show:!0,position:"top"}},areaStyle:{normal:{color:c(a+l)}},itemStyle:{normal:{color:c(a+l)}},data:m(r)}),i&&(e=h(e,i)),e}export{y as g}; 2 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/img/favicon.ico -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/fa-brands-400.ttf -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/fa-brands-400.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/fa-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/fa-regular-400.ttf -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/fa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/fa-regular-400.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/fa-solid-900.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/fa-v4compatibility.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/fa-v4compatibility.ttf -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/fa-v4compatibility.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/fa-v4compatibility.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/lato-all-400-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/lato-all-400-normal.woff -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/lato-all-700-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/lato-all-700-normal.woff -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/lato-latin-400-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/lato-latin-400-normal.woff -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/lato-latin-400-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/lato-latin-400-normal.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/lato-latin-700-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/lato-latin-700-normal.woff -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/lato-latin-700-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/lato-latin-700-normal.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/lato-latin-ext-400-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/lato-latin-ext-400-normal.woff -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/lato-latin-ext-400-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/lato-latin-ext-400-normal.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/lato-latin-ext-700-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/lato-latin-ext-700-normal.woff -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/lato-latin-ext-700-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/lato-latin-ext-700-normal.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/raleway-all-400-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/raleway-all-400-normal.woff -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/raleway-cyrillic-400-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/raleway-cyrillic-400-normal.woff -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/raleway-cyrillic-400-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/raleway-cyrillic-400-normal.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/raleway-cyrillic-ext-400-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/raleway-cyrillic-ext-400-normal.woff -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/raleway-cyrillic-ext-400-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/raleway-cyrillic-ext-400-normal.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/raleway-latin-400-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/raleway-latin-400-normal.woff -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/raleway-latin-400-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/raleway-latin-400-normal.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/raleway-latin-ext-400-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/raleway-latin-ext-400-normal.woff -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/raleway-latin-ext-400-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/raleway-latin-ext-400-normal.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/raleway-vietnamese-400-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/raleway-vietnamese-400-normal.woff -------------------------------------------------------------------------------- /CTFd/themes/core-beta/static/webfonts/raleway-vietnamese-400-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core-beta/static/webfonts/raleway-vietnamese-400-normal.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core-beta/templates/components/errors.html: -------------------------------------------------------------------------------- 1 |
2 | {% for info in infos %} 3 | 9 | {% endfor %} 10 | 11 | {% for error in errors %} 12 | 18 | {% endfor %} 19 |
-------------------------------------------------------------------------------- /CTFd/themes/core-beta/templates/errors/403.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | 5 |
6 |
7 |
8 |
9 |

{{ error }}

10 |
11 |
12 |

{% trans %}403 Forbidden{% endtrans %}

13 |
14 |
15 |
16 |
17 | 18 | {% endblock %} 19 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/templates/errors/404.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | 5 |
6 |
7 |
8 |
9 |

{% trans %}File not found{% endtrans %}

10 |
11 |
12 |

{% trans %}404 Not Found{% endtrans %}

13 |
14 |
15 |
16 |
17 | 18 | 19 | {% endblock %} 20 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/templates/errors/429.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | 5 |
6 |
7 |
8 |
9 |

{% trans %}Too many requests{% endtrans %}

10 |

{% trans %}Please slow down!{% endtrans %}

11 |
12 |
13 |

{% trans %}429 Too Many Requests{% endtrans %}

14 |
15 |
16 |
17 |
18 | 19 | 20 | {% endblock %} 21 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/templates/errors/500.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | 5 |
6 |
7 |
8 |
9 |

500

10 |
11 |
12 |

{{ error }}

13 |
14 |
15 |
16 |
17 | 18 | 19 | {% endblock %} 20 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/templates/errors/502.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | 5 |
6 |
7 |
8 |
9 |

502

10 |
11 |
12 |

{% trans %}502 Bad Gateway{% endtrans %}

13 |
14 |
15 |
16 |
17 | 18 | 19 | {% endblock %} 20 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/templates/notifications.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 |
5 |
6 |

7 | {% trans %}Notifications{% endtrans %} 8 |

9 |
10 |
11 |
12 | {% if not notifications %} 13 |

14 | {% trans %}There are no notifications yet{% endtrans %} 15 |

16 | {% endif %} 17 | {% for notification in notifications %} 18 |
19 |
20 |

{{ notification.title }}

21 |
22 |

{{ notification.html }}

23 | 24 |
25 |
26 |
27 | {% endfor %} 28 |
29 | {% endblock %} 30 | 31 | {% block scripts %} 32 | {{ Assets.js("assets/js/notifications.js") }} 33 | {% endblock %} 34 | 35 | -------------------------------------------------------------------------------- /CTFd/themes/core-beta/templates/page.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 |
5 | {{ content | safe }} 6 |
7 | {% endblock %} 8 | 9 | {% block scripts %} 10 | {{ Assets.js("assets/js/page.js") }} 11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /CTFd/themes/core/assets/css/challenge-board.scss: -------------------------------------------------------------------------------- 1 | .chal-desc { 2 | padding-left: 30px; 3 | padding-right: 30px; 4 | font-size: 14px; 5 | } 6 | 7 | .chal-desc img { 8 | max-width: 100%; 9 | height: auto; 10 | } 11 | 12 | .modal-content { 13 | border-radius: 0px; 14 | max-width: 1000px; 15 | padding: 1em; 16 | margin: 0 auto; 17 | } 18 | 19 | .btn-info { 20 | background-color: #5b7290 !important; 21 | } 22 | 23 | .badge-info { 24 | background-color: #5b7290 !important; 25 | } 26 | 27 | .challenge-button { 28 | box-shadow: 3px 3px 3px grey; 29 | } 30 | 31 | .solved-challenge { 32 | background-color: #37d63e !important; 33 | opacity: 0.4; 34 | border: none; 35 | } 36 | 37 | .corner-button-check { 38 | margin-top: -10px; 39 | margin-right: 25px; 40 | position: absolute; 41 | right: 0; 42 | } 43 | 44 | .key-submit .btn { 45 | height: 51px; 46 | } 47 | -------------------------------------------------------------------------------- /CTFd/themes/core/assets/css/codemirror.scss: -------------------------------------------------------------------------------- 1 | @import "~codemirror/lib/codemirror.css"; 2 | -------------------------------------------------------------------------------- /CTFd/themes/core/assets/css/fonts.scss: -------------------------------------------------------------------------------- 1 | $fa-font-path: "~@fortawesome/fontawesome-free/webfonts" !default; 2 | $fa-font-display: auto !default; 3 | @import "~@fortawesome/fontawesome-free/scss/fontawesome.scss"; 4 | @import "~@fortawesome/fontawesome-free/scss/regular.scss"; 5 | @import "~@fortawesome/fontawesome-free/scss/solid.scss"; 6 | @import "~@fortawesome/fontawesome-free/scss/brands.scss"; 7 | 8 | @import "~typeface-lato/index.css"; 9 | @import "~typeface-raleway/index.css"; 10 | -------------------------------------------------------------------------------- /CTFd/themes/core/assets/css/includes/award-icons.scss: -------------------------------------------------------------------------------- 1 | .award-icon { 2 | font-family: "Font Awesome 5 Free", "Font Awesome 5 Free Offline"; 3 | font-weight: 900; 4 | -moz-osx-font-smoothing: grayscale; 5 | -webkit-font-smoothing: antialiased; 6 | display: inline-block; 7 | font-style: normal; 8 | font-variant: normal; 9 | text-rendering: auto; 10 | line-height: 1; 11 | } 12 | 13 | .award-shield:before { 14 | content: "\f3ed"; 15 | } 16 | .award-bug:before { 17 | content: "\f188"; 18 | } 19 | .award-crown:before { 20 | content: "\f521"; 21 | } 22 | .award-crosshairs:before { 23 | content: "\f05b"; 24 | } 25 | .award-ban:before { 26 | content: "\f05e"; 27 | } 28 | .award-lightning:before { 29 | content: "\f0e7"; 30 | } 31 | .award-code:before { 32 | content: "\f121"; 33 | } 34 | .award-cowboy:before { 35 | content: "\f8c0"; 36 | } 37 | .award-angry:before { 38 | content: "\f556"; 39 | } 40 | -------------------------------------------------------------------------------- /CTFd/themes/core/assets/css/includes/jumbotron.css: -------------------------------------------------------------------------------- 1 | /* Move down content because we have a fixed navbar that is 3.5rem tall */ 2 | main { 3 | padding-top: 3.5rem; 4 | } 5 | -------------------------------------------------------------------------------- /CTFd/themes/core/assets/css/includes/sticky-footer.css: -------------------------------------------------------------------------------- 1 | /* Sticky footer styles 2 | -------------------------------------------------- */ 3 | html { 4 | position: relative; 5 | min-height: 100%; 6 | } 7 | 8 | main { 9 | /* Margin bottom by footer height */ 10 | margin-bottom: 100px; 11 | } 12 | 13 | .footer { 14 | position: absolute; 15 | 16 | /* prevent scrollbars from showing on pages that don't use the full page height */ 17 | bottom: 1px; 18 | 19 | width: 100%; 20 | 21 | /* Set the fixed height of the footer here */ 22 | height: 60px; 23 | 24 | /* Vertically center the text there */ 25 | line-height: 60px; 26 | 27 | /* Avoid covering things */ 28 | z-index: -20; 29 | 30 | /*background-color: #f5f5f5;*/ 31 | } 32 | -------------------------------------------------------------------------------- /CTFd/themes/core/assets/css/includes/utils/min-height.scss: -------------------------------------------------------------------------------- 1 | .min-vh-0 { 2 | min-height: 0vh !important; 3 | } 4 | .min-vh-25 { 5 | min-height: 25vh !important; 6 | } 7 | .min-vh-50 { 8 | min-height: 50vh !important; 9 | } 10 | .min-vh-75 { 11 | min-height: 75vh !important; 12 | } 13 | .min-vh-100 { 14 | min-height: 100vh !important; 15 | } 16 | -------------------------------------------------------------------------------- /CTFd/themes/core/assets/css/includes/utils/opacity.scss: -------------------------------------------------------------------------------- 1 | .opacity-0 { 2 | opacity: 0 !important; 3 | } 4 | .opacity-25 { 5 | opacity: 0.25 !important; 6 | } 7 | .opacity-50 { 8 | opacity: 0.5 !important; 9 | } 10 | .opacity-75 { 11 | opacity: 0.75 !important; 12 | } 13 | .opacity-100 { 14 | opacity: 1 !important; 15 | } 16 | -------------------------------------------------------------------------------- /CTFd/themes/core/assets/js/config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | urlRoot: "", 3 | csrfNonce: "", 4 | userMode: "" 5 | }; 6 | -------------------------------------------------------------------------------- /CTFd/themes/core/assets/js/fetch.js: -------------------------------------------------------------------------------- 1 | import "whatwg-fetch"; 2 | import config from "./config"; 3 | 4 | const fetch = window.fetch; 5 | 6 | export default (url, options) => { 7 | if (options === undefined) { 8 | options = { 9 | method: "GET", 10 | credentials: "same-origin", 11 | headers: {} 12 | }; 13 | } 14 | url = config.urlRoot + url; 15 | 16 | if (options.headers === undefined) { 17 | options.headers = {}; 18 | } 19 | options.credentials = "same-origin"; 20 | options.headers["Accept"] = "application/json"; 21 | options.headers["Content-Type"] = "application/json"; 22 | options.headers["CSRF-Token"] = config.csrfNonce; 23 | 24 | return fetch(url, options); 25 | }; 26 | -------------------------------------------------------------------------------- /CTFd/themes/core/assets/js/pages/events.js: -------------------------------------------------------------------------------- 1 | import $ from "jquery"; 2 | import events from "../events"; 3 | import config from "../config"; 4 | 5 | $(() => { 6 | events(config.urlRoot); 7 | }); 8 | -------------------------------------------------------------------------------- /CTFd/themes/core/assets/js/pages/main.js: -------------------------------------------------------------------------------- 1 | import CTFd from "../CTFd"; 2 | import $ from "jquery"; 3 | import dayjs from "dayjs"; 4 | import advancedFormat from "dayjs/plugin/advancedFormat"; 5 | import nunjucks from "nunjucks"; 6 | import { Howl } from "howler"; 7 | import events from "../events"; 8 | import config from "../config"; 9 | import styles from "../styles"; 10 | import times from "../times"; 11 | import { default as helpers } from "../helpers"; 12 | 13 | dayjs.extend(advancedFormat); 14 | 15 | CTFd.init(window.init); 16 | window.CTFd = CTFd; 17 | window.helpers = helpers; 18 | window.$ = $; 19 | window.dayjs = dayjs; 20 | window.nunjucks = nunjucks; 21 | window.Howl = Howl; 22 | 23 | $(() => { 24 | styles(); 25 | times(); 26 | events(config.urlRoot); 27 | }); 28 | -------------------------------------------------------------------------------- /CTFd/themes/core/assets/js/pages/notifications.js: -------------------------------------------------------------------------------- 1 | import "./main"; 2 | import $ from "jquery"; 3 | import { clear_notification_counter } from "../utils"; 4 | 5 | $(() => { 6 | clear_notification_counter(); 7 | }); 8 | -------------------------------------------------------------------------------- /CTFd/themes/core/assets/js/pages/style.js: -------------------------------------------------------------------------------- 1 | import $ from "jquery"; 2 | import styles from "../styles"; 3 | import times from "../times"; 4 | 5 | $(() => { 6 | styles(); 7 | times(); 8 | }); 9 | -------------------------------------------------------------------------------- /CTFd/themes/core/assets/js/times.js: -------------------------------------------------------------------------------- 1 | import dayjs from "dayjs"; 2 | import advancedFormat from "dayjs/plugin/advancedFormat"; 3 | import $ from "jquery"; 4 | 5 | dayjs.extend(advancedFormat); 6 | 7 | export default () => { 8 | $("[data-time]").each((i, elem) => { 9 | let $elem = $(elem); 10 | let time = $elem.data("time"); 11 | let format = $elem.data("time-format") || "MMMM Do, h:mm:ss A"; 12 | elem.innerText = dayjs(time).format(format); 13 | }); 14 | }; 15 | -------------------------------------------------------------------------------- /CTFd/themes/core/static/css/challenge-board.dev.css: -------------------------------------------------------------------------------- 1 | .chal-desc{padding-left:30px;padding-right:30px;font-size:14px}.chal-desc img{max-width:100%;height:auto}.modal-content{border-radius:0px;max-width:1000px;padding:1em;margin:0 auto}.btn-info{background-color:#5b7290 !important}.badge-info{background-color:#5b7290 !important}.challenge-button{box-shadow:3px 3px 3px gray}.solved-challenge{background-color:#37d63e !important;opacity:.4;border:none}.corner-button-check{margin-top:-10px;margin-right:25px;position:absolute;right:0}.key-submit .btn{height:51px} 2 | -------------------------------------------------------------------------------- /CTFd/themes/core/static/css/challenge-board.min.css: -------------------------------------------------------------------------------- 1 | .chal-desc{padding-left:30px;padding-right:30px;font-size:14px}.chal-desc img{max-width:100%;height:auto}.modal-content{border-radius:0;max-width:1000px;padding:1em;margin:0 auto}.badge-info,.btn-info{background-color:#5b7290!important}.challenge-button{box-shadow:3px 3px 3px grey}.solved-challenge{background-color:#37d63e!important;opacity:.4;border:none}.corner-button-check{margin-top:-10px;margin-right:25px;position:absolute;right:0}.key-submit .btn{height:51px} -------------------------------------------------------------------------------- /CTFd/themes/core/static/css/core.dev.css: -------------------------------------------------------------------------------- 1 | .jumbotron{background-color:#343a40;color:#fff}.form-control{padding:.8em !important;background:#f0f0f0;color:#aaa;height:auto !important}select.form-control{height:auto !important}.custom-select{background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px !important}.card{border-radius:0 !important}#score-graph{min-height:400px;display:block;clear:both}#solves-graph{display:block;height:350px}#keys-pie-graph{min-height:400px;display:block}#categories-pie-graph{min-height:400px;display:block}.form-control{position:relative;display:block;padding:.8em !important;border-radius:0;background:#f0f0f0;color:#aaa;font-weight:400;font-family:"Avenir Next","Helvetica Neue",Helvetica,Arial,sans-serif;-webkit-appearance:none;height:auto !important}.challenge-desc{overflow-wrap:anywhere}.challenge-desc img{max-width:100%} 2 | -------------------------------------------------------------------------------- /CTFd/themes/core/static/css/core.min.css: -------------------------------------------------------------------------------- 1 | .jumbotron{background-color:#343a40;color:#fff}select.form-control{height:auto!important}.custom-select{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right .75rem center/8px 10px!important}.card{border-radius:0!important}#score-graph{min-height:400px;display:block;clear:both}#solves-graph{display:block;height:350px}#categories-pie-graph,#keys-pie-graph{min-height:400px;display:block}.form-control{position:relative;display:block;padding:.8em!important;border-radius:0;background:#f0f0f0;color:#aaa;font-weight:400;font-family:Avenir Next,Helvetica Neue,Helvetica,Arial,sans-serif;-webkit-appearance:none;height:auto!important}.challenge-desc{overflow-wrap:anywhere}.challenge-desc img{max-width:100%} -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/fa-brands-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/fa-brands-400.eot -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/fa-brands-400.ttf -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/fa-brands-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/fa-brands-400.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/fa-brands-400.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/fa-regular-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/fa-regular-400.eot -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/fa-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/fa-regular-400.ttf -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/fa-regular-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/fa-regular-400.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/fa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/fa-regular-400.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/fa-solid-900.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/fa-solid-900.eot -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/fa-solid-900.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/fa-solid-900.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/fa-solid-900.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/lato-latin-100.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/lato-latin-100.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/lato-latin-100.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/lato-latin-100.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/lato-latin-100italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/lato-latin-100italic.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/lato-latin-100italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/lato-latin-100italic.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/lato-latin-300.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/lato-latin-300.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/lato-latin-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/lato-latin-300.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/lato-latin-300italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/lato-latin-300italic.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/lato-latin-300italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/lato-latin-300italic.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/lato-latin-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/lato-latin-400.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/lato-latin-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/lato-latin-400.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/lato-latin-400italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/lato-latin-400italic.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/lato-latin-400italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/lato-latin-400italic.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/lato-latin-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/lato-latin-700.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/lato-latin-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/lato-latin-700.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/lato-latin-700italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/lato-latin-700italic.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/lato-latin-700italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/lato-latin-700italic.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/lato-latin-900.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/lato-latin-900.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/lato-latin-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/lato-latin-900.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/lato-latin-900italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/lato-latin-900italic.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/lato-latin-900italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/lato-latin-900italic.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-100.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-100.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-100.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-100.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-100italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-100italic.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-100italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-100italic.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-200.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-200.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-200.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-200.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-200italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-200italic.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-200italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-200italic.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-300.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-300.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-300.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-300italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-300italic.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-300italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-300italic.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-400.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-400.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-400italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-400italic.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-400italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-400italic.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-500.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-500.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-500italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-500italic.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-500italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-500italic.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-600.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-600.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-600.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-600.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-600italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-600italic.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-600italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-600italic.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-700.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-700.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-700italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-700italic.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-700italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-700italic.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-800.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-800.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-800.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-800.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-800italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-800italic.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-800italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-800italic.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-900.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-900.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-900.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-900italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-900italic.woff -------------------------------------------------------------------------------- /CTFd/themes/core/static/fonts/raleway-latin-900italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/fonts/raleway-latin-900italic.woff2 -------------------------------------------------------------------------------- /CTFd/themes/core/static/img/ctfd.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/img/ctfd.ai -------------------------------------------------------------------------------- /CTFd/themes/core/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/img/favicon.ico -------------------------------------------------------------------------------- /CTFd/themes/core/static/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/img/logo.png -------------------------------------------------------------------------------- /CTFd/themes/core/static/img/logo_old.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/img/logo_old.png -------------------------------------------------------------------------------- /CTFd/themes/core/static/img/scoreboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/img/scoreboard.png -------------------------------------------------------------------------------- /CTFd/themes/core/static/js/core.min.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/js/core.min.js -------------------------------------------------------------------------------- /CTFd/themes/core/static/sounds/README.md: -------------------------------------------------------------------------------- 1 | # Build uncompressed webm 2 | 3 | ``` 4 | ffmpeg -i notification.mp3 -c:a libopus notification.webm 5 | ``` 6 | 7 | ## Build compressed webm 8 | 9 | ``` 10 | ffmpeg -i notification.mp3 -c:a libopus -vn -b:a 48K notification.webm 11 | ``` 12 | 13 | ## To create a base64 blob of the sound file 14 | 15 | ``` 16 | echo "data:audio/webm;base64,`base64 -b 80 notification.webm`" 17 | ``` 18 | -------------------------------------------------------------------------------- /CTFd/themes/core/static/sounds/notification.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/sounds/notification.mp3 -------------------------------------------------------------------------------- /CTFd/themes/core/static/sounds/notification.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/themes/core/static/sounds/notification.webm -------------------------------------------------------------------------------- /CTFd/themes/core/templates/components/errors.html: -------------------------------------------------------------------------------- 1 |
2 | {% for info in infos %} 3 | 9 | {% endfor %} 10 | {% for error in errors %} 11 | 17 | {% endfor %} 18 |
-------------------------------------------------------------------------------- /CTFd/themes/core/templates/config.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | 10 |
11 | 12 |
-------------------------------------------------------------------------------- /CTFd/themes/core/templates/errors/403.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | 5 |
6 |
7 |
8 |
9 |

Forbidden

10 |
11 |

{{ error }}

12 |
13 |
14 |
15 |
16 | 17 | {% endblock %} 18 | 19 | {% block scripts %} 20 | {% endblock %} 21 | -------------------------------------------------------------------------------- /CTFd/themes/core/templates/errors/404.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | 5 |
6 |
7 |
8 |
9 |

404

10 |
11 |

File not found

12 |

Sorry about that

13 |
14 |
15 |
16 |
17 | 18 | 19 | {% endblock %} 20 | 21 | {% block scripts %} 22 | {% endblock %} 23 | -------------------------------------------------------------------------------- /CTFd/themes/core/templates/errors/429.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | 5 |
6 |
7 |
8 |
9 |

429

10 |
11 |

Too many requests

12 |

Please slow down!

13 |
14 |
15 |
16 |
17 | 18 | 19 | {% endblock %} 20 | 21 | {% block scripts %} 22 | {% endblock %} 23 | -------------------------------------------------------------------------------- /CTFd/themes/core/templates/errors/500.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | 5 |
6 |
7 |
8 |
9 |

500

10 |
11 |

{{ error }}

12 |
13 |
14 |
15 |
16 | 17 | 18 | {% endblock %} 19 | 20 | {% block scripts %} 21 | {% endblock %} 22 | -------------------------------------------------------------------------------- /CTFd/themes/core/templates/errors/502.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | 5 |
6 |
7 |
8 |
9 |

502

10 |
11 |

Bad Gateway

12 |
13 |
14 |
15 |
16 | 17 | 18 | {% endblock %} 19 | 20 | {% block scripts %} 21 | {% endblock %} 22 | -------------------------------------------------------------------------------- /CTFd/themes/core/templates/notifications.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 |
5 |
6 |

Notifications

7 |
8 |
9 |
10 | {% if not notifications %} 11 |

There are no notifications yet

12 | {% endif %} 13 | {% for notification in notifications %} 14 |
15 |
16 |

{{ notification.title }}

17 |
18 |

{{ notification.html }}

19 | 20 |
21 |
22 |
23 | {% endfor %} 24 |
25 | {% endblock %} 26 | 27 | {% block entrypoint %} 28 | 29 | {% endblock %} 30 | -------------------------------------------------------------------------------- /CTFd/themes/core/templates/page.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 |
5 | {{ content | safe }} 6 |
7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /CTFd/translations/ar/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/translations/ar/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /CTFd/translations/ca/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/translations/ca/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /CTFd/translations/de/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/translations/de/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /CTFd/translations/es/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/translations/es/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /CTFd/translations/fr/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/translations/fr/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /CTFd/translations/it/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/translations/it/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /CTFd/translations/ja/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/translations/ja/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /CTFd/translations/ko/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/translations/ko/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /CTFd/translations/pl/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/translations/pl/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /CTFd/translations/pt_BR/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/translations/pt_BR/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /CTFd/translations/ru/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/translations/ru/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /CTFd/translations/sk/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/translations/sk/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /CTFd/translations/uz/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/translations/uz/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /CTFd/translations/vi/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/translations/vi/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /CTFd/translations/zh_Hans_CN/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/translations/zh_Hans_CN/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /CTFd/translations/zh_Hant_TW/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/translations/zh_Hant_TW/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /CTFd/uploads/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/uploads/.gitkeep -------------------------------------------------------------------------------- /CTFd/utils/config/integrations.py: -------------------------------------------------------------------------------- 1 | from CTFd.utils import get_app_config, get_config 2 | 3 | 4 | def mlc(): 5 | admin_config = get_config("oauth_client_id") and get_config("oauth_client_secret") 6 | main_config = get_app_config("OAUTH_CLIENT_ID") and get_app_config( 7 | "OAUTH_CLIENT_SECRET" 8 | ) 9 | return admin_config or main_config 10 | 11 | 12 | def mlc_registration(): 13 | v = get_config("registration_visibility") 14 | return v == "mlc" 15 | -------------------------------------------------------------------------------- /CTFd/utils/countries/geoip.py: -------------------------------------------------------------------------------- 1 | import geoacumen_city 2 | import maxminddb 3 | from flask import current_app 4 | 5 | IP_ADDR_LOOKUP = maxminddb.open_database( 6 | current_app.config.get("GEOIP_DATABASE_PATH", geoacumen_city.db_path) 7 | ) 8 | 9 | 10 | def lookup_ip_address(addr): 11 | try: 12 | response = IP_ADDR_LOOKUP.get(addr) 13 | return response["country"]["iso_code"] 14 | except (KeyError, ValueError, TypeError): 15 | return None 16 | 17 | 18 | def lookup_ip_address_city(addr): 19 | try: 20 | response = IP_ADDR_LOOKUP.get(addr) 21 | return response["city"]["names"]["en"] 22 | except (KeyError, ValueError, TypeError): 23 | return None 24 | -------------------------------------------------------------------------------- /CTFd/utils/crypto/__init__.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | 3 | from passlib.hash import bcrypt_sha256 4 | 5 | from CTFd.utils import string_types 6 | 7 | 8 | def hash_password(plaintext): 9 | return bcrypt_sha256.hash(str(plaintext)) 10 | 11 | 12 | def verify_password(plaintext, ciphertext): 13 | return bcrypt_sha256.verify(plaintext, ciphertext) 14 | 15 | 16 | def sha256(p): 17 | if isinstance(p, string_types): 18 | p = p.encode("utf-8") 19 | return hashlib.sha256(p).hexdigest() 20 | -------------------------------------------------------------------------------- /CTFd/utils/decorators/modes.py: -------------------------------------------------------------------------------- 1 | import functools 2 | 3 | from flask import abort 4 | 5 | from CTFd.utils import get_config 6 | from CTFd.utils.modes import TEAMS_MODE, USERS_MODE 7 | 8 | 9 | def require_team_mode(f): 10 | @functools.wraps(f) 11 | def _require_team_mode(*args, **kwargs): 12 | if get_config("user_mode") == USERS_MODE: 13 | abort(404) 14 | return f(*args, **kwargs) 15 | 16 | return _require_team_mode 17 | 18 | 19 | def require_user_mode(f): 20 | @functools.wraps(f) 21 | def _require_user_mode(*args, **kwargs): 22 | if get_config("user_mode") == TEAMS_MODE: 23 | abort(404) 24 | return f(*args, **kwargs) 25 | 26 | return _require_user_mode 27 | -------------------------------------------------------------------------------- /CTFd/utils/email/mailgun.py: -------------------------------------------------------------------------------- 1 | from CTFd.utils.email.providers.mailgun import MailgunEmailProvider 2 | 3 | 4 | def sendmail(addr, text, subject): 5 | print( 6 | "CTFd.utils.email.mailgun.sendmail will raise an exception in a future minor release of CTFd and then be removed in CTFd v4.0" 7 | ) 8 | return MailgunEmailProvider.sendmail(addr, text, subject) 9 | -------------------------------------------------------------------------------- /CTFd/utils/email/providers/__init__.py: -------------------------------------------------------------------------------- 1 | class EmailProvider: 2 | @staticmethod 3 | def sendmail(addr, text, subject): 4 | raise NotImplementedError 5 | -------------------------------------------------------------------------------- /CTFd/utils/email/smtp.py: -------------------------------------------------------------------------------- 1 | from CTFd.utils.email.providers.smtp import SMTPEmailProvider 2 | 3 | 4 | def sendmail(addr, text, subject): 5 | print( 6 | "CTFd.utils.email.smtp.sendmail will raise an exception in a future minor release of CTFd and then be removed in CTFd v4.0" 7 | ) 8 | return SMTPEmailProvider.sendmail(addr, text, subject) 9 | -------------------------------------------------------------------------------- /CTFd/utils/exports/databases.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy.exc import OperationalError 2 | 3 | from CTFd.models import db 4 | 5 | 6 | def is_database_mariadb(): 7 | try: 8 | result = db.session.execute("SELECT version()").fetchone()[0] 9 | mariadb = "mariadb" in result.lower() 10 | except OperationalError: 11 | mariadb = False 12 | return mariadb 13 | -------------------------------------------------------------------------------- /CTFd/utils/exports/freeze.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy.exc import OperationalError, ProgrammingError 2 | 3 | from CTFd.utils.exports.serializers import JSONSerializer 4 | 5 | 6 | def freeze_export(result, fileobj): 7 | try: 8 | query = result 9 | serializer = JSONSerializer(query, fileobj) 10 | serializer.serialize() 11 | except (OperationalError, ProgrammingError) as e: 12 | raise OperationalError("Invalid query: %s" % e) 13 | -------------------------------------------------------------------------------- /CTFd/utils/formatters/__init__.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from markupsafe import escape_silent 4 | 5 | 6 | def safe_format(fmt, **kwargs): 7 | """ 8 | Function that safely formats strings with arbitrary potentially user-supplied format strings 9 | Looks for interpolation placeholders like {target} or {{ target }} 10 | """ 11 | # TODO: CTFd 4.0 - This function should probably be renamed to `safe_text_format` 12 | return re.sub( 13 | r"\{?\{([^{}]*)\}\}?", lambda m: kwargs.get(m.group(1).strip(), m.group(0)), fmt 14 | ) 15 | 16 | 17 | def safe_html_format(template, **kwargs): 18 | """ 19 | Function that safely HTML escapes strings before safely formatting it into a HTML template 20 | """ 21 | for k, v in kwargs.items(): 22 | kwargs[k] = escape_silent(v) 23 | return safe_format(template, **kwargs) 24 | -------------------------------------------------------------------------------- /CTFd/utils/health/__init__.py: -------------------------------------------------------------------------------- 1 | from time import time 2 | 3 | from flask import current_app 4 | from sqlalchemy_utils import database_exists 5 | 6 | from CTFd.cache import cache, timed_lru_cache 7 | 8 | 9 | @timed_lru_cache(timeout=30) 10 | def check_database(): 11 | return database_exists(current_app.config["SQLALCHEMY_DATABASE_URI"]) 12 | 13 | 14 | @timed_lru_cache(timeout=30) 15 | def check_config(): 16 | key = "healthcheck" 17 | value = round(time() / 5) * 5 18 | cache.set(key, value) 19 | return cache.get(key) == value 20 | -------------------------------------------------------------------------------- /CTFd/utils/helpers/models.py: -------------------------------------------------------------------------------- 1 | import sqlalchemy 2 | 3 | 4 | def build_model_filters(model, query, field, extra_columns=None): 5 | if extra_columns is None: 6 | extra_columns = {} 7 | filters = [] 8 | if query: 9 | # The field exists as an exposed column 10 | if model.__mapper__.has_property(field): 11 | column = getattr(model, field) 12 | 13 | if type(column.type) == sqlalchemy.sql.sqltypes.Integer: 14 | _filter = column.op("=")(query) 15 | else: 16 | _filter = column.like(f"%{query}%") 17 | filters.append(_filter) 18 | else: 19 | if field in extra_columns: 20 | column = extra_columns[field] 21 | if type(column.type) == sqlalchemy.sql.sqltypes.Integer: 22 | _filter = column.op("=")(query) 23 | else: 24 | _filter = column.like(f"%{query}%") 25 | filters.append(_filter) 26 | return filters 27 | -------------------------------------------------------------------------------- /CTFd/utils/humanize/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/utils/humanize/__init__.py -------------------------------------------------------------------------------- /CTFd/utils/humanize/numbers.py: -------------------------------------------------------------------------------- 1 | def ordinalize(n): 2 | """ 3 | http://codegolf.stackexchange.com/a/4712 4 | """ 5 | k = n % 10 6 | return "%d%s" % (n, "tsnrhtdd"[(n // 10 % 10 != 1) * (k < 4) * k :: 4]) 7 | -------------------------------------------------------------------------------- /CTFd/utils/humanize/words.py: -------------------------------------------------------------------------------- 1 | def pluralize(number, singular="", plural="s"): 2 | if number == 1: 3 | return singular 4 | else: 5 | return plural 6 | -------------------------------------------------------------------------------- /CTFd/utils/logging/__init__.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import logging.handlers 3 | import time 4 | 5 | from flask import session 6 | 7 | from CTFd.utils.user import get_ip 8 | 9 | 10 | def log(logger, format, **kwargs): 11 | logger = logging.getLogger(logger) 12 | props = { 13 | "id": session.get("id"), 14 | "date": time.strftime("%m/%d/%Y %X"), 15 | "ip": get_ip(), 16 | } 17 | props.update(kwargs) 18 | msg = format.format(**props) 19 | logger.info(msg) 20 | -------------------------------------------------------------------------------- /CTFd/utils/notifications/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/utils/notifications/__init__.py -------------------------------------------------------------------------------- /CTFd/utils/security/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/CTFd/utils/security/__init__.py -------------------------------------------------------------------------------- /CTFd/utils/security/csrf.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from CTFd.utils.encoding import hexencode 4 | 5 | 6 | def generate_nonce(): 7 | return hexencode(os.urandom(32)) 8 | -------------------------------------------------------------------------------- /CTFd/utils/security/passwords.py: -------------------------------------------------------------------------------- 1 | from CTFd.utils.crypto import hash_password as hp 2 | from CTFd.utils.crypto import sha256 as sha 3 | from CTFd.utils.crypto import verify_password as vp 4 | 5 | 6 | def hash_password(p): 7 | print( 8 | "This function will be deprecated in a future release. Please update to CTFd.utils.crypto.hash_password" 9 | ) 10 | return hp(p) 11 | 12 | 13 | def check_password(p, hash): 14 | print( 15 | "This function will be deprecated in a future release. Please update to CTFd.utils.crypto.verify_password" 16 | ) 17 | return vp(p, hash) 18 | 19 | 20 | def sha256(p): 21 | print( 22 | "This function will be deprecated in a future release. Please update to CTFd.utils.crypto.sha256" 23 | ) 24 | return sha(p) 25 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | **Do not open up a GitHub issue if the bug is a security vulnerability in CTFd**. Instead [email the details to us at support@ctfd.io](mailto:support@ctfd.io). 6 | -------------------------------------------------------------------------------- /babel.cfg: -------------------------------------------------------------------------------- 1 | [python: CTFd/**/*.py] 2 | [jinja2: CTFd/themes/core-beta/templates/**.html] 3 | -------------------------------------------------------------------------------- /crowdin.yml: -------------------------------------------------------------------------------- 1 | files: [ 2 | { 3 | "source" : "messages.pot", 4 | "translation" : "/CTFd/translations/%two_letters_code%/LC_MESSAGES/messages.po", 5 | } 6 | ] 7 | -------------------------------------------------------------------------------- /development.txt: -------------------------------------------------------------------------------- 1 | -r requirements.txt 2 | pip-tools==5.4.0 3 | pytest==7.3.1 4 | pytest-randomly==3.12.0 5 | coverage==7.2.3 6 | psycopg2-binary==2.9.6 7 | moto==4.1.11 8 | bandit==1.6.2 9 | flask_profiler==1.8.1 10 | pytest-xdist==3.2.1 11 | pytest-cov==4.0.0 12 | sphinx_rtd_theme==0.4.3 13 | flask-debugtoolbar==0.11.0 14 | Faker==4.1.0 15 | pipdeptree==2.2.0 16 | pytest-sugar==0.9.7 17 | -------------------------------------------------------------------------------- /export.py: -------------------------------------------------------------------------------- 1 | from CTFd import create_app 2 | from CTFd.utils import config 3 | from CTFd.utils.exports import export_ctf 4 | 5 | import datetime 6 | import sys 7 | import shutil 8 | 9 | 10 | app = create_app() 11 | with app.app_context(): 12 | print( 13 | "This file will be deleted in CTFd v4.0. Switch to using `python manage.py export_ctf`" 14 | ) 15 | backup = export_ctf() 16 | 17 | if len(sys.argv) > 1: 18 | with open(sys.argv[1], "wb") as target: 19 | shutil.copyfileobj(backup, target) 20 | else: 21 | ctf_name = config.ctf_name() 22 | day = datetime.datetime.now().strftime("%Y-%m-%d_%T") 23 | full_name = "{}.{}.zip".format(ctf_name, day) 24 | 25 | with open(full_name, "wb") as target: 26 | shutil.copyfileobj(backup, target) 27 | 28 | print("Exported {filename}".format(filename=full_name)) 29 | -------------------------------------------------------------------------------- /frpc/frpc.ini: -------------------------------------------------------------------------------- 1 | [common] 2 | token = YOUR_TOKEN 3 | server_addr = frps 4 | server_port = 7000 5 | admin_addr = 0.0.0.0 6 | admin_port = 7400 7 | -------------------------------------------------------------------------------- /frps/frps.ini: -------------------------------------------------------------------------------- 1 | [common] 2 | bind_addr = 0.0.0.0 3 | bind_port = 7000 4 | token = YOUR_TOKEN 5 | subdomain_host = dynamic.test.com 6 | vhost_http_port = 8009 7 | custom_404_page = /etc/frp/404.html 8 | -------------------------------------------------------------------------------- /import.py: -------------------------------------------------------------------------------- 1 | """ 2 | python import.py export.zip 3 | """ 4 | from CTFd import create_app 5 | from CTFd.utils.exports import import_ctf 6 | 7 | import sys 8 | 9 | app = create_app() 10 | with app.app_context(): 11 | print( 12 | "This file will be deleted in CTFd v4.0. Switch to using `python manage.py import_ctf`" 13 | ) 14 | import_ctf(sys.argv[1]) 15 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | apt-get install docker docker-compose -y 3 | docker swarm init --advertise-addr 127.0.0.1 4 | docker node update --label-add='name=linux-1' $(docker node ls -q) 5 | docker-compose -f CTFd/docker-compose.yml up -d 6 | #docker-compose -f CTFd/docker-compose.yml exec ctfd python manage.py set_config whale auto_connect_network 7 | -------------------------------------------------------------------------------- /linting.txt: -------------------------------------------------------------------------------- 1 | black==22.3.0 2 | isort==5.13.2 3 | ruff==0.0.260 4 | dennis==1.1.0 5 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | from flask.cli import FlaskGroup 2 | 3 | from CTFd import create_app 4 | 5 | app = create_app() 6 | 7 | cli = FlaskGroup(app) 8 | 9 | 10 | if __name__ == "__main__": 11 | cli() 12 | -------------------------------------------------------------------------------- /migrations/alembic.ini: -------------------------------------------------------------------------------- 1 | # A generic, single database configuration. 2 | 3 | [alembic] 4 | # template used to generate migration files 5 | # file_template = %%(rev)s_%%(slug)s 6 | 7 | # set to 'true' to run the environment during 8 | # the 'revision' command, regardless of autogenerate 9 | # revision_environment = false 10 | 11 | 12 | # Logging configuration 13 | [loggers] 14 | keys = root,sqlalchemy,alembic 15 | 16 | [handlers] 17 | keys = console 18 | 19 | [formatters] 20 | keys = generic 21 | 22 | [logger_root] 23 | level = WARN 24 | handlers = console 25 | qualname = 26 | 27 | [logger_sqlalchemy] 28 | level = WARN 29 | handlers = 30 | qualname = sqlalchemy.engine 31 | 32 | [logger_alembic] 33 | level = INFO 34 | handlers = 35 | qualname = alembic 36 | 37 | [handler_console] 38 | class = StreamHandler 39 | args = (sys.stderr,) 40 | level = NOTSET 41 | formatter = generic 42 | 43 | [formatter_generic] 44 | format = %(levelname)-5.5s [%(name)s] %(message)s 45 | datefmt = %H:%M:%S 46 | -------------------------------------------------------------------------------- /migrations/script.py.mako: -------------------------------------------------------------------------------- 1 | """${message} 2 | 3 | Revision ID: ${up_revision} 4 | Revises: ${down_revision | comma,n} 5 | Create Date: ${create_date} 6 | 7 | """ 8 | from alembic import op 9 | import sqlalchemy as sa 10 | ${imports if imports else ""} 11 | 12 | # revision identifiers, used by Alembic. 13 | revision = ${repr(up_revision)} 14 | down_revision = ${repr(down_revision)} 15 | branch_labels = ${repr(branch_labels)} 16 | depends_on = ${repr(depends_on)} 17 | 18 | 19 | def upgrade(): 20 | ${upgrades if upgrades else "pass"} 21 | 22 | 23 | def downgrade(): 24 | ${downgrades if downgrades else "pass"} 25 | -------------------------------------------------------------------------------- /migrations/versions/07dfbe5e1edc_add_format_to_pages.py: -------------------------------------------------------------------------------- 1 | """Add format to Pages 2 | 3 | Revision ID: 07dfbe5e1edc 4 | Revises: 75e8ab9a0014 5 | Create Date: 2021-06-15 19:57:37.410152 6 | 7 | """ 8 | from alembic import op # noqa: I001 9 | import sqlalchemy as sa 10 | 11 | 12 | # revision identifiers, used by Alembic. 13 | revision = "07dfbe5e1edc" 14 | down_revision = "75e8ab9a0014" 15 | branch_labels = None 16 | depends_on = None 17 | 18 | 19 | def upgrade(): 20 | # ### commands auto generated by Alembic - please adjust! ### 21 | op.add_column("pages", sa.Column("format", sa.String(length=80), nullable=True)) 22 | # ### end Alembic commands ### 23 | 24 | 25 | def downgrade(): 26 | # ### commands auto generated by Alembic - please adjust! ### 27 | op.drop_column("pages", "format") 28 | # ### end Alembic commands ### 29 | -------------------------------------------------------------------------------- /migrations/versions/0def790057c1_add_language_column_to_users_table.py: -------------------------------------------------------------------------------- 1 | """Add language column to Users table 2 | 3 | Revision ID: 0def790057c1 4 | Revises: 46a278193a94 5 | Create Date: 2023-04-19 00:56:54.592584 6 | 7 | """ 8 | import sqlalchemy as sa 9 | from alembic import op 10 | 11 | # revision identifiers, used by Alembic. 12 | revision = "0def790057c1" 13 | down_revision = "46a278193a94" 14 | branch_labels = None 15 | depends_on = None 16 | 17 | 18 | def upgrade(): 19 | op.add_column("users", sa.Column("language", sa.String(length=32), nullable=True)) 20 | 21 | 22 | def downgrade(): 23 | op.drop_column("users", "language") 24 | -------------------------------------------------------------------------------- /migrations/versions/4d3c1b59d011_add_next_id_to_challenges_table.py: -------------------------------------------------------------------------------- 1 | """Add next_id to Challenges table 2 | 3 | Revision ID: 4d3c1b59d011 4 | Revises: 6012fe8de495 5 | Create Date: 2022-04-07 03:53:27.554190 6 | 7 | """ 8 | from alembic import op # noqa: I001 9 | import sqlalchemy as sa 10 | 11 | 12 | # revision identifiers, used by Alembic. 13 | revision = "4d3c1b59d011" 14 | down_revision = "6012fe8de495" 15 | branch_labels = None 16 | depends_on = None 17 | 18 | 19 | def upgrade(): 20 | # ### commands auto generated by Alembic - please adjust! ### 21 | op.add_column("challenges", sa.Column("next_id", sa.Integer(), nullable=True)) 22 | op.create_foreign_key( 23 | None, "challenges", "challenges", ["next_id"], ["id"], ondelete="SET NULL" 24 | ) 25 | # ### end Alembic commands ### 26 | 27 | 28 | def downgrade(): 29 | # ### commands auto generated by Alembic - please adjust! ### 30 | op.drop_constraint(None, "challenges", type_="foreignkey") 31 | op.drop_column("challenges", "next_id") 32 | # ### end Alembic commands ### 33 | -------------------------------------------------------------------------------- /migrations/versions/4e4d5a9ea000_add_type_to_awards.py: -------------------------------------------------------------------------------- 1 | """Add type to awards 2 | 3 | Revision ID: 4e4d5a9ea000 4 | Revises: 8369118943a1 5 | Create Date: 2019-04-07 19:37:17.872128 6 | 7 | """ 8 | import sqlalchemy as sa 9 | from alembic import op 10 | 11 | # revision identifiers, used by Alembic. 12 | revision = "4e4d5a9ea000" 13 | down_revision = "8369118943a1" 14 | branch_labels = None 15 | depends_on = None 16 | 17 | 18 | def upgrade(): 19 | # ### commands auto generated by Alembic - please adjust! ### 20 | op.add_column( 21 | "awards", 22 | sa.Column( 23 | "type", sa.String(length=80), nullable=True, server_default="standard" 24 | ), 25 | ) 26 | # ### end Alembic commands ### 27 | 28 | 29 | def downgrade(): 30 | # ### commands auto generated by Alembic - please adjust! ### 31 | op.drop_column("awards", "type") 32 | # ### end Alembic commands ### 33 | -------------------------------------------------------------------------------- /migrations/versions/4fe3eeed9a9d_add_attribution_to_challenges.py: -------------------------------------------------------------------------------- 1 | """Add attribution to Challenges 2 | 3 | Revision ID: 4fe3eeed9a9d 4 | Revises: a02c5bf43407 5 | Create Date: 2024-09-07 01:02:28.997761 6 | 7 | """ 8 | from alembic import op 9 | import sqlalchemy as sa 10 | 11 | 12 | # revision identifiers, used by Alembic. 13 | revision = "4fe3eeed9a9d" 14 | down_revision = "a02c5bf43407" 15 | branch_labels = None 16 | depends_on = None 17 | 18 | 19 | def upgrade(): 20 | op.add_column("challenges", sa.Column("attribution", sa.Text(), nullable=True)) 21 | 22 | 23 | def downgrade(): 24 | op.drop_column("challenges", "attribution") 25 | -------------------------------------------------------------------------------- /migrations/versions/5c4996aeb2cb_add_sha1sum_field_to_files_require_.py: -------------------------------------------------------------------------------- 1 | """Add sha1sum field to Files 2 | 3 | Revision ID: 5c4996aeb2cb 4 | Revises: 9e6f6578ca84 5 | Create Date: 2024-01-07 13:09:08.843903 6 | 7 | """ 8 | import sqlalchemy as sa 9 | from alembic import op 10 | 11 | # revision identifiers, used by Alembic. 12 | revision = "5c4996aeb2cb" 13 | down_revision = "9e6f6578ca84" 14 | branch_labels = None 15 | depends_on = None 16 | 17 | 18 | def upgrade(): 19 | op.add_column("files", sa.Column("sha1sum", sa.String(length=40), nullable=True)) 20 | 21 | 22 | def downgrade(): 23 | op.drop_column("files", "sha1sum") 24 | -------------------------------------------------------------------------------- /migrations/versions/6012fe8de495_add_connection_info_column_to_challenges.py: -------------------------------------------------------------------------------- 1 | """Add connection_info column to Challenges 2 | 3 | Revision ID: 6012fe8de495 4 | Revises: ef87d69ec29a 5 | Create Date: 2021-07-30 03:50:54.219124 6 | 7 | """ 8 | from alembic import op # noqa: I001 9 | import sqlalchemy as sa 10 | 11 | 12 | # revision identifiers, used by Alembic. 13 | revision = "6012fe8de495" 14 | down_revision = "ef87d69ec29a" 15 | branch_labels = None 16 | depends_on = None 17 | 18 | 19 | def upgrade(): 20 | # ### commands auto generated by Alembic - please adjust! ### 21 | op.add_column("challenges", sa.Column("connection_info", sa.Text(), nullable=True)) 22 | # ### end Alembic commands ### 23 | 24 | 25 | def downgrade(): 26 | # ### commands auto generated by Alembic - please adjust! ### 27 | op.drop_column("challenges", "connection_info") 28 | # ### end Alembic commands ### 29 | -------------------------------------------------------------------------------- /migrations/versions/9e6f6578ca84_add_description_column_to_tokens_table.py: -------------------------------------------------------------------------------- 1 | """Add description column to tokens table 2 | 3 | Revision ID: 9e6f6578ca84 4 | Revises: 0def790057c1 5 | Create Date: 2023-06-21 23:22:34.179636 6 | 7 | """ 8 | import sqlalchemy as sa 9 | from alembic import op 10 | 11 | # revision identifiers, used by Alembic. 12 | revision = "9e6f6578ca84" 13 | down_revision = "0def790057c1" 14 | branch_labels = None 15 | depends_on = None 16 | 17 | 18 | def upgrade(): 19 | op.add_column("tokens", sa.Column("description", sa.Text(), nullable=True)) 20 | 21 | 22 | def downgrade(): 23 | op.drop_column("tokens", "description") 24 | -------------------------------------------------------------------------------- /migrations/versions/a02c5bf43407_add_link_target_to_pages.py: -------------------------------------------------------------------------------- 1 | """Add link_target to Pages 2 | 3 | Revision ID: a02c5bf43407 4 | Revises: 9889b8c53673 5 | Create Date: 2024-02-01 13:11:53.076825 6 | 7 | """ 8 | from alembic import op 9 | import sqlalchemy as sa 10 | 11 | 12 | # revision identifiers, used by Alembic. 13 | revision = "a02c5bf43407" 14 | down_revision = "9889b8c53673" 15 | branch_labels = None 16 | depends_on = None 17 | 18 | 19 | def upgrade(): 20 | op.add_column( 21 | "pages", sa.Column("link_target", sa.String(length=80), nullable=True) 22 | ) 23 | 24 | 25 | def downgrade(): 26 | op.drop_column("pages", "link_target") 27 | -------------------------------------------------------------------------------- /ping.py: -------------------------------------------------------------------------------- 1 | """ 2 | Script for checking that a database server is available. 3 | Essentially a cross-platform, database agnostic mysqladmin. 4 | """ 5 | import time 6 | 7 | from sqlalchemy import create_engine 8 | from sqlalchemy.engine.url import make_url 9 | 10 | from CTFd.config import Config 11 | 12 | url = make_url(Config.DATABASE_URL) 13 | 14 | # Ignore sqlite databases 15 | if url.drivername.startswith("sqlite"): 16 | exit(0) 17 | 18 | # Null out the database so raw_connection doesnt error if it doesnt exist 19 | # CTFd will create the database if it doesnt exist 20 | url = url._replace(database=None) 21 | 22 | # Wait for the database server to be available 23 | engine = create_engine(url) 24 | print(f"Waiting for {url.host} to be ready") 25 | while True: 26 | try: 27 | engine.raw_connection() 28 | break 29 | except Exception: 30 | print(".", end="", flush=True) 31 | time.sleep(1) 32 | 33 | print(f"{url.host} is ready") 34 | time.sleep(1) 35 | -------------------------------------------------------------------------------- /prepare.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | sudo apt-get update 3 | sudo DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential python-dev python-pip libffi-dev 4 | pip install -r requirements.txt 5 | -------------------------------------------------------------------------------- /requirements.in: -------------------------------------------------------------------------------- 1 | Flask==2.0.3 2 | Werkzeug==2.0.3 3 | Flask-SQLAlchemy==2.5.1 4 | Flask-Caching==2.0.2 5 | Flask-Migrate==2.5.3 6 | Flask-Script==2.0.6 7 | SQLAlchemy==1.4.48 8 | SQLAlchemy-Utils==0.41.1 9 | passlib==1.7.4 10 | bcrypt==4.0.1 11 | requests==2.32.3 12 | PyMySQL[rsa]==1.0.2 13 | gunicorn==20.1.0 14 | dataset==1.6.2 15 | cmarkgfm==2022.10.27 16 | redis==4.5.5 17 | gevent==23.9.1 18 | python-dotenv==0.13.0 19 | flask-restx==1.1.0 20 | flask-marshmallow==0.10.1 21 | marshmallow-sqlalchemy==0.17.0 22 | boto3==1.35.27 23 | marshmallow==2.20.2 24 | pydantic==1.6.2 25 | WTForms==2.3.1 26 | python-geoacumen-city==2023.4.15 27 | maxminddb==1.5.4 28 | tenacity==6.2.0 29 | pybluemonday==0.0.14 30 | freezegun==1.2.2 31 | Flask-Babel==2.0.0 32 | Pillow==10.1.0 33 | -------------------------------------------------------------------------------- /scripts/pip-compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Script to pin Python requirements in a Docker container 3 | ROOTDIR=`pwd -P` 4 | docker run \ 5 | --rm \ 6 | --entrypoint bash \ 7 | -v $ROOTDIR:/mnt/CTFd \ 8 | -e CUSTOM_COMPILE_COMMAND='./scripts/pip-compile.sh' \ 9 | -it python:3.11-slim-bookworm \ 10 | -c 'cd /mnt/CTFd && pip install pip-tools==7.4.1 && pip-compile' 11 | -------------------------------------------------------------------------------- /sed.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | UUID=$(cat /proc/sys/kernel/random/uuid) 3 | #UUID=YOUR_TOKEN 4 | 5 | sed -i "s/dynamic.test.com/$DYNAMIC_URL/g" /opt/CTFd/CTFd/plugins/ctfd_whale/utils/setup.py 6 | sed -i "s/direct.test.com/$DIRECT_URL/g" /opt/CTFd/CTFd/plugins/ctfd_whale/utils/setup.py 7 | sed -i "s/YOUR_TOKEN/$UUID/g" /opt/CTFd/CTFd/plugins/ctfd_whale/utils/setup.py 8 | 9 | sed -i "s/dynamic.test.com/$DYNAMIC_URL/g" /opt/CTFd/CTFd/plugins/ctfd_owl/setup.py 10 | sed -i "s/direct.test.com/$DIRECT_URL/g" /opt/CTFd/CTFd/plugins/ctfd_owl/setup.py 11 | sed -i "s/YOUR_TOKEN/$UUID/g" /opt/CTFd/CTFd/plugins/ctfd_owl/setup.py 12 | 13 | sed -i "s/ctfd.test.com/$CTFD_URL/g" /opt/CTFd/conf/nginx/http.conf 14 | sed -i "s/dynamic.test.com/$DYNAMIC_URL/g" /opt/CTFd/conf/nginx/http.conf 15 | sed -i "s/direct.test.com/$DIRECT_URL/g" /opt/CTFd/conf/nginx/http.conf 16 | 17 | sed -i "s/dynamic.test.com/$DYNAMIC_URL/g" /opt/CTFd/frps/frps.ini 18 | sed -i "s/YOUR_TOKEN/$UUID/g" /opt/CTFd/frps/frps.ini 19 | 20 | sed -i "s/YOUR_TOKEN/$UUID/g" /opt/CTFd/frpc/frpc.ini 21 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [nosetests] 2 | stop=1 3 | verbosity=2 4 | with-coverage=1 5 | cover-package=CTFd -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/tests/__init__.py -------------------------------------------------------------------------------- /tests/admin/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/tests/admin/__init__.py -------------------------------------------------------------------------------- /tests/admin/test_notifications.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/tests/admin/test_notifications.py -------------------------------------------------------------------------------- /tests/admin/test_statistics.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/tests/admin/test_statistics.py -------------------------------------------------------------------------------- /tests/admin/test_teams.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/tests/admin/test_teams.py -------------------------------------------------------------------------------- /tests/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/tests/api/__init__.py -------------------------------------------------------------------------------- /tests/api/v1/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/tests/api/v1/__init__.py -------------------------------------------------------------------------------- /tests/api/v1/statistics/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/tests/api/v1/statistics/__init__.py -------------------------------------------------------------------------------- /tests/api/v1/teams/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/tests/api/v1/teams/__init__.py -------------------------------------------------------------------------------- /tests/api/v1/user/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/tests/api/v1/user/__init__.py -------------------------------------------------------------------------------- /tests/api/v1/users/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/tests/api/v1/users/__init__.py -------------------------------------------------------------------------------- /tests/cache/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/tests/cache/__init__.py -------------------------------------------------------------------------------- /tests/challenges/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/tests/challenges/__init__.py -------------------------------------------------------------------------------- /tests/constants/time.py: -------------------------------------------------------------------------------- 1 | from CTFd.constants import RawEnum 2 | 3 | 4 | class FreezeTimes(str, RawEnum): 5 | NOT_STARTED = "2017-10-3" # Tuesday, October 3, 2017 6 | STARTED = "2017-10-5" # Thursday, October 5, 2017 7 | ENDED = "2017-10-7" # Saturday, October 7, 2017 8 | START = "1507089600" # Wednesday, October 4, 2017 12:00:00 AM GMT-04:00 DST 9 | END = "1507262400" # Friday, October 6, 2017 12:00:00 AM GMT-04:00 DST 10 | -------------------------------------------------------------------------------- /tests/models/test_model_utils.py: -------------------------------------------------------------------------------- 1 | from CTFd.models import ( 2 | Challenges, 3 | Comments, 4 | Files, 5 | Solves, 6 | Submissions, 7 | get_class_by_tablename, 8 | ) 9 | from tests.helpers import create_ctfd, destroy_ctfd 10 | 11 | 12 | def test_get_class_by_tablename(): 13 | """ 14 | Test that get_class_by_tablename() returns the correct table 15 | """ 16 | app = create_ctfd() 17 | with app.app_context(): 18 | assert get_class_by_tablename("solves") == Solves 19 | assert get_class_by_tablename("comments") == Comments 20 | assert get_class_by_tablename("files") == Files 21 | assert get_class_by_tablename("submissions") == Submissions 22 | assert get_class_by_tablename("challenges") == Challenges 23 | destroy_ctfd(app) 24 | -------------------------------------------------------------------------------- /tests/oauth/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/tests/oauth/__init__.py -------------------------------------------------------------------------------- /tests/teams/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/tests/teams/__init__.py -------------------------------------------------------------------------------- /tests/test_legal.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from CTFd.utils import set_config 5 | from tests.helpers import create_ctfd, destroy_ctfd 6 | 7 | 8 | def test_legal_settings(): 9 | app = create_ctfd() 10 | with app.app_context(): 11 | set_config("tos_text", "Terms of Service") 12 | set_config("privacy_text", "Privacy Policy") 13 | 14 | with app.test_client() as client: 15 | r = client.get("/register") 16 | assert r.status_code == 200 17 | assert "privacy policy" in r.get_data(as_text=True) 18 | assert "terms of service" in r.get_data(as_text=True) 19 | 20 | r = client.get("/tos") 21 | assert r.status_code == 200 22 | assert "Terms of Service" in r.get_data(as_text=True) 23 | 24 | r = client.get("/privacy") 25 | assert r.status_code == 200 26 | assert "Privacy Policy" in r.get_data(as_text=True) 27 | destroy_ctfd(app) 28 | -------------------------------------------------------------------------------- /tests/users/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangzheng2016/CTFd-docker/59fd7aad2ab978c96fbfbca80aa929f991964dd1/tests/users/__init__.py -------------------------------------------------------------------------------- /tests/utils/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from CTFd.utils import get_config, set_config 5 | from tests.helpers import create_ctfd, destroy_ctfd 6 | 7 | 8 | def test_ctf_version_is_set(): 9 | """Does ctf_version get set correctly""" 10 | app = create_ctfd() 11 | with app.app_context(): 12 | assert get_config("ctf_version") == app.VERSION 13 | destroy_ctfd(app) 14 | 15 | 16 | def test_get_config_and_set_config(): 17 | """Does get_config and set_config work properly""" 18 | app = create_ctfd() 19 | with app.app_context(): 20 | assert get_config("setup") == True 21 | config = set_config("TEST_CONFIG_ENTRY", "test_config_entry") 22 | assert config.value == "test_config_entry" 23 | assert get_config("TEST_CONFIG_ENTRY") == "test_config_entry" 24 | destroy_ctfd(app) 25 | -------------------------------------------------------------------------------- /tests/utils/test_formatters.py: -------------------------------------------------------------------------------- 1 | from CTFd.utils.formatters import safe_format 2 | 3 | 4 | def test_safe_format(): 5 | assert safe_format("Message from {ctf_name}", ctf_name="CTF") == "Message from CTF" 6 | assert ( 7 | safe_format("Message from {{ ctf_name }}", ctf_name="CTF") == "Message from CTF" 8 | ) 9 | assert safe_format("{{ ctf_name }} {{ctf_name}}", ctf_name="CTF") == "CTF CTF" 10 | assert ( 11 | safe_format("{ ctf_name } {ctf_name} {asdf}", ctf_name="CTF") 12 | == "CTF CTF {asdf}" 13 | ) 14 | -------------------------------------------------------------------------------- /tests/utils/test_humanize.py: -------------------------------------------------------------------------------- 1 | from CTFd.utils.humanize.numbers import ordinalize 2 | 3 | 4 | def test_ordinalize(): 5 | tests = { 6 | 1: "1st", 7 | 2: "2nd", 8 | 3: "3rd", 9 | 4: "4th", 10 | 11: "11th", 11 | 12: "12th", 12 | 13: "13th", 13 | 101: "101st", 14 | 102: "102nd", 15 | 103: "103rd", 16 | 111: "111th", 17 | } 18 | for t, v in tests.items(): 19 | assert ordinalize(t) == v 20 | -------------------------------------------------------------------------------- /tests/utils/test_markdown.py: -------------------------------------------------------------------------------- 1 | from CTFd.utils import markdown 2 | 3 | 4 | def test_markdown(): 5 | """ 6 | Test that our markdown function renders properly 7 | """ 8 | # Allow raw HTML / potentially unsafe HTML 9 | assert ( 10 | markdown("").strip() 11 | == "" 12 | ) 13 | -------------------------------------------------------------------------------- /tests/utils/test_passwords.py: -------------------------------------------------------------------------------- 1 | from CTFd.utils.crypto import hash_password, sha256, verify_password 2 | 3 | 4 | def test_hash_password(): 5 | assert hash_password("asdf").startswith("$bcrypt-sha256") 6 | 7 | 8 | def test_verify_password(): 9 | assert verify_password( 10 | "asdf", 11 | "$bcrypt-sha256$2b,12$I0CNXRkGD2Bi/lbC4vZ7Y.$1WoilsadKpOjXa/be9x3dyu7p.mslZ6", 12 | ) 13 | 14 | 15 | def test_sha256(): 16 | assert ( 17 | sha256("asdf") 18 | == "f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b" 19 | ) 20 | -------------------------------------------------------------------------------- /tests/utils/test_ratelimit.py: -------------------------------------------------------------------------------- 1 | from tests.helpers import create_ctfd, destroy_ctfd, register_user 2 | 3 | 4 | def test_ratelimit_on_auth(): 5 | """Test that ratelimiting function works properly""" 6 | app = create_ctfd() 7 | with app.app_context(): 8 | register_user(app) 9 | with app.test_client() as client: 10 | r = client.get("/login") 11 | with client.session_transaction() as sess: 12 | data = { 13 | "name": "user", 14 | "password": "wrong_password", 15 | "nonce": sess.get("nonce"), 16 | } 17 | for _ in range(10): 18 | r = client.post("/login", data=data) 19 | assert r.status_code == 200 20 | 21 | for _ in range(5): 22 | r = client.post("/login", data=data) 23 | assert r.status_code == 429 24 | destroy_ctfd(app) 25 | -------------------------------------------------------------------------------- /wsgi.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | # Detect if we're running via `flask run` and don't monkey patch 4 | if not os.getenv("FLASK_RUN_FROM_CLI"): 5 | from gevent import monkey 6 | 7 | monkey.patch_all() 8 | 9 | from CTFd import create_app 10 | 11 | app = create_app() 12 | 13 | if __name__ == "__main__": 14 | app.run(debug=True, threaded=True, host="127.0.0.1", port=4000) 15 | --------------------------------------------------------------------------------