├── CTFd-Theme-StormCTF.png ├── README.md ├── plugins ├── challenges │ └── assets │ │ ├── view.html │ │ └── view.js └── dynamic_challenges │ └── assets │ ├── view.html │ └── view.js ├── screenshots ├── challenge_modal.png ├── challenge_modal_solves.png ├── challenges.png ├── login.png ├── profile.png ├── register.png ├── scoreboard.png ├── team.png └── teams.png └── stormctf ├── README.md ├── static ├── css │ ├── base.css │ ├── challenge-board.css │ ├── jumbotron.css │ ├── sticky-footer.css │ ├── style.css │ └── vendor │ │ ├── font-awesome │ │ ├── fontawesome-all.css │ │ ├── fontawesome-all.min.css │ │ ├── fontawesome-fonts.css │ │ └── webfonts │ │ │ ├── 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 │ │ ├── font.css │ │ ├── lato │ │ ├── Lato_400.eot │ │ ├── Lato_400.svg │ │ ├── Lato_400.ttf │ │ ├── Lato_400.woff │ │ ├── Lato_400.woff2 │ │ ├── Lato_400i.eot │ │ ├── Lato_400i.svg │ │ ├── Lato_400i.ttf │ │ ├── Lato_400i.woff │ │ ├── Lato_400i.woff2 │ │ ├── Lato_700.eot │ │ ├── Lato_700.svg │ │ ├── Lato_700.ttf │ │ ├── Lato_700.woff │ │ ├── Lato_700.woff2 │ │ ├── Lato_700i.eot │ │ ├── Lato_700i.svg │ │ ├── Lato_700i.ttf │ │ ├── Lato_700i.woff │ │ └── Lato_700i.woff2 │ │ ├── raleway │ │ ├── Raleway_400.eot │ │ ├── Raleway_400.svg │ │ ├── Raleway_400.ttf │ │ ├── Raleway_400.woff │ │ ├── Raleway_400.woff2 │ │ ├── Raleway_400i.eot │ │ ├── Raleway_400i.svg │ │ ├── Raleway_400i.ttf │ │ ├── Raleway_400i.woff │ │ ├── Raleway_400i.woff2 │ │ ├── Raleway_700.eot │ │ ├── Raleway_700.svg │ │ ├── Raleway_700.ttf │ │ ├── Raleway_700.woff │ │ ├── Raleway_700.woff2 │ │ ├── Raleway_700i.eot │ │ ├── Raleway_700i.svg │ │ ├── Raleway_700i.ttf │ │ ├── Raleway_700i.woff │ │ └── Raleway_700i.woff2 │ │ ├── uikit.css │ │ └── uikit.min.css ├── fonts │ ├── IcoMoon.eot │ ├── font-08a5b663.woff │ ├── font-360dafd3.woff │ ├── font-38d64ba3.woff │ ├── font-3d31737a.woff2 │ ├── font-6482a3ff.woff2 │ ├── font-6c7b3554.woff │ ├── font-a3913573.woff2 │ ├── font-a4a03eac.woff │ ├── font-a6c1c4ca.woff2 │ ├── font-b7eb26b8.woff │ ├── font-c2ad8b3d.woff2 │ ├── font-e0d6f976.woff2 │ ├── font-ec67e4a8.woff │ ├── font-ec84201c.woff2 │ ├── font-f2de05d4.woff │ ├── font-fd3a65d0.woff2 │ └── section-background-image-noise.png ├── img │ ├── challenges.jpg │ ├── confirmation.png │ ├── ctfd.ai │ ├── ctfd.svg │ ├── ctfd_transfer.svg │ ├── favicon.ico │ ├── login.jpg │ ├── logo.png │ ├── logo_old.png │ ├── notifications.png │ ├── scoreboard.png │ └── team.png └── js │ ├── CTFd.js │ ├── chalboard.js │ ├── challenges.js │ ├── events.js │ ├── ezq.js │ ├── hints.js │ ├── multi-modal.js │ ├── scoreboard.js │ ├── settings.js │ ├── style.js │ ├── team.js │ ├── user.js │ ├── utils.js │ └── vendor │ ├── bootstrap.bundle.min.js │ ├── codemirror.min.js │ ├── eventsource.min.js │ ├── fetch.min.js │ ├── fontawesome-all.min.js │ ├── howler.min.js │ ├── jquery.min.js │ ├── markdown-it.min.js │ ├── marked.min.js │ ├── moment-timezone-with-data.min.js │ ├── moment.min.js │ ├── nunjucks.min.js │ ├── plotly.min.js │ ├── promise-polyfill.min.js │ ├── uikit-icons.min.js │ ├── uikit.min.js │ └── window-controller.js └── templates ├── base.html ├── challenges.html ├── confirm.html ├── errors ├── 403.html ├── 404.html ├── 429.html ├── 500.html └── 502.html ├── login.html ├── notifications.html ├── page.html ├── register.html ├── reset_password.html ├── scoreboard.html ├── settings.html ├── setup.html ├── teams ├── join_team.html ├── new_team.html ├── private.html ├── public.html ├── team_enrollment.html └── teams.html └── users ├── private.html ├── public.html └── users.html /CTFd-Theme-StormCTF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/CTFd-Theme-StormCTF.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CTFd-Theme-StormCTF 2 | CTFd Theme for StormCTF (Updated a little bit for the newest version of CTFd) 3 | 4 | ### For Version 2.1.1 5 | 6 | ## Info 7 | Redesigned CTFd template for [UIKit](https://getuikit.com). Colors are based off of StormCTF's Website. Mobile ready. Written by [Alex](https://twitter.com/offsec_ginger) for StormCTF 2019 at InfoSeCon 2019. 8 | 9 | ## Installation 10 | * Copy `stormctf/` into your `CTFd/CTFd/themes` folder. 11 | * Copy `plugins/challenges/assets/view.html` to `CTFd/CTFd/plugins/challenges/assets/view.html` 12 | * Copy `plugins/challenges/assets/view.js` to `CTFd/CTFd/plugins/challenges/assets/view.js` 13 | * **THIS WILL OVERWRITE THE ORIGINAL. MAKE A BACKUP.** 14 | 15 | ### TO DO: 16 | - [ ] Maybe redo the Graphs? 17 | - [x] Wait for @ColdHeat to update to 3.0 so I can fix this all over again :stuck_out_tongue: 18 | 19 | ![Theme Image](https://github.com/stormctf/CTFd-Theme-StormCTF/blob/master/CTFd-Theme-StormCTF.png) 20 | -------------------------------------------------------------------------------- /plugins/challenges/assets/view.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 |

{{ name }} - {{ value }}

6 |
{% for tag in tags %} 7 | {{tag}} {% endfor %}
8 |
9 |
10 | 20 | 81 |
82 | 96 |
97 | -------------------------------------------------------------------------------- /plugins/challenges/assets/view.js: -------------------------------------------------------------------------------- 1 | window.challenge.data = undefined; 2 | 3 | window.challenge.renderer = new markdownit({ 4 | html: true, 5 | linkify: true, 6 | }); 7 | 8 | window.challenge.preRender = function () { 9 | 10 | }; 11 | 12 | window.challenge.render = function (markdown) { 13 | return window.challenge.renderer.render(markdown); 14 | }; 15 | 16 | 17 | window.challenge.postRender = function () { 18 | 19 | }; 20 | 21 | 22 | window.challenge.submit = function (cb, preview) { 23 | var challenge_id = parseInt($('#challenge-id').val()); 24 | var submission = $('#submission-input').val(); 25 | var url = "/api/v1/challenges/attempt"; 26 | 27 | if (preview) { 28 | url += "?preview=true"; 29 | } 30 | 31 | var params = { 32 | 'challenge_id': challenge_id, 33 | 'submission': submission 34 | }; 35 | 36 | CTFd.fetch(url, { 37 | method: 'POST', 38 | credentials: 'same-origin', 39 | headers: { 40 | 'Accept': 'application/json', 41 | 'Content-Type': 'application/json' 42 | }, 43 | body: JSON.stringify(params) 44 | }).then(function (response) { 45 | if (response.status === 429) { 46 | // User was ratelimited but process response 47 | return response.json(); 48 | } 49 | if (response.status === 403) { 50 | // User is not logged in or CTF is paused. 51 | return response.json(); 52 | } 53 | return response.json(); 54 | }).then(function (response) { 55 | cb(response); 56 | }); 57 | }; -------------------------------------------------------------------------------- /plugins/dynamic_challenges/assets/view.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 |

{{ name }} - {{ value }}

6 |
{% for tag in tags %} 7 | {{tag}} {% endfor %}
8 |
9 |
10 | 20 | 81 |
82 | 96 |
97 | -------------------------------------------------------------------------------- /plugins/dynamic_challenges/assets/view.js: -------------------------------------------------------------------------------- 1 | window.challenge.data = undefined; 2 | 3 | window.challenge.renderer = new markdownit({ 4 | html: true, 5 | linkify: true, 6 | }); 7 | 8 | window.challenge.preRender = function () { 9 | 10 | }; 11 | 12 | window.challenge.render = function (markdown) { 13 | return window.challenge.renderer.render(markdown); 14 | }; 15 | 16 | 17 | window.challenge.postRender = function () { 18 | 19 | }; 20 | 21 | 22 | window.challenge.submit = function (cb, preview) { 23 | var challenge_id = parseInt($('#challenge-id').val()); 24 | var submission = $('#submission-input').val(); 25 | var url = "/api/v1/challenges/attempt"; 26 | 27 | if (preview) { 28 | url += "?preview=true"; 29 | } 30 | 31 | var params = { 32 | 'challenge_id': challenge_id, 33 | 'submission': submission 34 | }; 35 | 36 | CTFd.fetch(url, { 37 | method: 'POST', 38 | credentials: 'same-origin', 39 | headers: { 40 | 'Accept': 'application/json', 41 | 'Content-Type': 'application/json' 42 | }, 43 | body: JSON.stringify(params) 44 | }).then(function (response) { 45 | if (response.status === 429) { 46 | // User was ratelimited but process response 47 | return response.json(); 48 | } 49 | if (response.status === 403) { 50 | // User is not logged in or CTF is paused. 51 | return response.json(); 52 | } 53 | return response.json(); 54 | }).then(function (response) { 55 | cb(response); 56 | }); 57 | }; -------------------------------------------------------------------------------- /screenshots/challenge_modal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/screenshots/challenge_modal.png -------------------------------------------------------------------------------- /screenshots/challenge_modal_solves.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/screenshots/challenge_modal_solves.png -------------------------------------------------------------------------------- /screenshots/challenges.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/screenshots/challenges.png -------------------------------------------------------------------------------- /screenshots/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/screenshots/login.png -------------------------------------------------------------------------------- /screenshots/profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/screenshots/profile.png -------------------------------------------------------------------------------- /screenshots/register.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/screenshots/register.png -------------------------------------------------------------------------------- /screenshots/scoreboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/screenshots/scoreboard.png -------------------------------------------------------------------------------- /screenshots/team.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/screenshots/team.png -------------------------------------------------------------------------------- /screenshots/teams.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/screenshots/teams.png -------------------------------------------------------------------------------- /stormctf/README.md: -------------------------------------------------------------------------------- 1 | # CTFd-Theme-StormCTF 2 | CTFd Theme for StormCTF (Updated a little bit for the newest version of CTFd) 3 | 4 | ### For Version 1.2.0 5 | 6 | ## Info 7 | Redesigned CTFd template for [UIKit](https://getuikit.com). Colors are based off of StormCTF's Website. Mobile ready. Written by [Alex](https://twitter.com/offsec_ginger) for StormCTF 2018 at InfoSeCon 2018. 8 | 9 | ## Installation 10 | * Copy `stormctf/` into your `CTFd/CTFd/themes` folder. 11 | * Copy `plugins/challenges/assets/standard-challenge-modal.njk` to `CTFd/CTFd/plugins/challenges/assets/standard-challenge-modal.njk` 12 | * **THIS WILL OVERWRITE THE ORIGINAL. MAKE A BACKUP.** 13 | 14 | ### TO DO: 15 | - [ ] Create njk's for different challenge types. 16 | - [ ] Maybe redo the Graphs? 17 | - [x] Wait for @ColdHeat to update to 2.0 so I can fix this all over again :stuck_out_tongue: 18 | 19 | ![Theme Image](https://github.com/stormctf/CTFd-Theme-StormCTF/blob/master/CTFd-Theme-StormCTF.png) 20 | -------------------------------------------------------------------------------- /stormctf/static/css/base.css: -------------------------------------------------------------------------------- 1 | html, body, .container { 2 | font-family: 'Lato', 'LatoOffline', sans-serif; 3 | } 4 | 5 | h1, h2 { 6 | font-family: 'Raleway', 'RalewayOffline', sans-serif; 7 | font-weight: 500; 8 | letter-spacing: 2px; 9 | } 10 | 11 | a { 12 | color: #337ab7; 13 | text-decoration: none; 14 | } 15 | 16 | table > thead > tr > td { 17 | /* Remove border line from thead of all tables */ 18 | /* It can overlap with other element styles */ 19 | border-top: none !important; 20 | } 21 | 22 | #score-graph { 23 | height: 450px; 24 | display: block; 25 | clear: both; 26 | } 27 | 28 | .fa-spin.spinner { 29 | margin-top: 225px; 30 | text-align: center; 31 | opacity: 0.5; 32 | } 33 | 34 | .spinner-error { 35 | padding-top: 20vh; 36 | text-align: center; 37 | opacity: 0.5; 38 | } 39 | 40 | .jumbotron { 41 | background-color: #343a40; 42 | color: #FFF; 43 | border-radius: 0; 44 | text-align: center; 45 | } 46 | 47 | .form-control { 48 | position: relative; 49 | display: block; 50 | padding: 0.8em; 51 | border-radius: 0; 52 | background: #f0f0f0; 53 | color: #aaa; 54 | font-weight: 400; 55 | font-family: "Avenir Next", "Helvetica Neue", Helvetica, Arial, sans-serif; 56 | -webkit-appearance: none; 57 | } 58 | 59 | .form-control:focus { 60 | background-color: transparent; 61 | border-color: #a3d39c; 62 | box-shadow: 0 0 0 0.2rem #a3d39c; 63 | transition: background-color 0.3s, border-color 0.3s; 64 | } 65 | 66 | .input-filled-valid { 67 | background-color: transparent; 68 | border-color: #a3d39c; 69 | box-shadow: 0 0 0 0.2rem #a3d39c; 70 | transition: background-color 0.3s, border-color 0.3s; 71 | } 72 | 73 | .btn-outlined.btn-theme { 74 | background: none; 75 | color: #545454; 76 | border-color: #545454; 77 | border: 3px solid; 78 | } 79 | 80 | .btn-outlined { 81 | border-radius: 0; 82 | -webkit-transition: all 0.3s; 83 | -moz-transition: all 0.3s; 84 | transition: all 0.3s; 85 | } 86 | 87 | .btn { 88 | letter-spacing: 1px; 89 | text-decoration: none; 90 | -moz-user-select: none; 91 | border-radius: 0; 92 | cursor: pointer; 93 | display: inline-block; 94 | margin-bottom: 0; 95 | vertical-align: middle; 96 | white-space: nowrap; 97 | font-size: 14px; 98 | line-height: 20px; 99 | font-weight: 700; 100 | padding: 8px 20px; 101 | } 102 | 103 | .btn-info { 104 | background-color: #5B7290 !important; 105 | border-color: #5B7290 !important; 106 | } 107 | 108 | .badge-info { 109 | background-color: #5B7290 !important; 110 | } 111 | 112 | .alert { 113 | border-radius: 0 !important; 114 | padding: 0.8em; 115 | } 116 | 117 | .btn-fa { 118 | cursor: pointer; 119 | } 120 | 121 | .close { 122 | cursor: pointer; 123 | } 124 | 125 | .cursor-pointer { 126 | cursor: pointer; 127 | } 128 | 129 | .cursor-help { 130 | cursor: help; 131 | } -------------------------------------------------------------------------------- /stormctf/static/css/challenge-board.css: -------------------------------------------------------------------------------- 1 | .chal-desc { 2 | padding-left: 30px; 3 | padding-right: 30px; 4 | font-size: 14px; 5 | } 6 | 7 | .modal-content { 8 | border-radius: 0px; 9 | max-width: 1000px; 10 | padding: 1em; 11 | margin: 0 auto; 12 | } 13 | 14 | .btn-info { 15 | background-color: #5B7290 !important; 16 | } 17 | 18 | .badge-info { 19 | background-color: #5B7290 !important; 20 | } 21 | 22 | .challenge-button { 23 | box-shadow: 3px 3px 3px grey; 24 | } 25 | 26 | .solved-challenge { 27 | background-color: #37d63e !important; 28 | opacity: 0.4; 29 | border: none; 30 | } 31 | 32 | .corner-button-check { 33 | margin-top: -10px; 34 | margin-right: 25px; 35 | position: absolute; 36 | right: 0; 37 | } 38 | 39 | .key-submit .btn { 40 | height: 51px; 41 | } -------------------------------------------------------------------------------- /stormctf/static/css/jumbotron.css: -------------------------------------------------------------------------------- 1 | /* Move down content because we have a fixed navbar that is 3.5rem tall */ 2 | body { 3 | padding-top: 3.5rem; 4 | } -------------------------------------------------------------------------------- /stormctf/static/css/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 | bottom: 0; 15 | width: 100%; 16 | height: 60px; /* Set the fixed height of the footer here */ 17 | line-height: 60px; /* Vertically center the text there */ 18 | /*background-color: #f5f5f5;*/ 19 | } -------------------------------------------------------------------------------- /stormctf/static/css/style.css: -------------------------------------------------------------------------------- 1 | 2 | html, body, .container { 3 | height: 100% !important; 4 | font-family: 'Lato', 'LatoOffline', sans-serif; 5 | } 6 | 7 | h1, h2 { 8 | font-family: 'Raleway', 'RalewayOffline', sans-serif; 9 | font-weight: 500; 10 | letter-spacing: 2px; 11 | } 12 | 13 | td { 14 | padding: 15px !important; 15 | } 16 | 17 | a { 18 | outline: 0; 19 | } 20 | 21 | img { 22 | max-width: 100%; 23 | } 24 | 25 | .body-container { 26 | min-height: 100%; 27 | position: relative; 28 | } 29 | 30 | .no-margin-right { 31 | margin-right: 0px !important; 32 | } 33 | 34 | .no-margin-left { 35 | margin-left: -3px !important; 36 | } 37 | 38 | .navbar > .container { 39 | padding-top: 30px; 40 | } 41 | 42 | .navbar .navbar-brand { 43 | font-size: 24px; 44 | letter-spacing: -0.04rem; 45 | line-height: 15px; 46 | color: #FFF; 47 | } 48 | 49 | .navbar-inverse .navbar-nav > li > a { 50 | color: #FFF !important; 51 | } 52 | 53 | .navbar li > a { 54 | opacity: 0.5; 55 | transition: opacity 0.08s ease-in 0s; 56 | cursor: pointer; 57 | } 58 | 59 | .navbar li > a:hover { 60 | opacity: 0.8; 61 | } 62 | 63 | .align-text-to-button { 64 | padding-top: 16px; 65 | } 66 | 67 | .padded-container { 68 | margin-top: 50px; 69 | padding-left: 50px; 70 | padding-right: 50px; 71 | } 72 | 73 | .main-container { 74 | margin-top: 35px; 75 | margin-bottom: 25px; 76 | padding-bottom: 100px; 77 | } 78 | 79 | #login-container { 80 | padding-left: 70px; 81 | padding-right: 70px; 82 | } 83 | 84 | #chal > form{ 85 | width: 400px; 86 | margin: 0 auto; 87 | } 88 | 89 | .reveal-modal{ 90 | text-align: center; 91 | } 92 | 93 | .chal-desc{ 94 | text-align: left; 95 | } 96 | 97 | table{ 98 | width: 100%; 99 | } 100 | 101 | #challenges button{ 102 | margin: 8px; 103 | } 104 | 105 | .row > h1{ 106 | text-align: center; 107 | } 108 | 109 | #challenges{ 110 | line-height: 66px; 111 | } 112 | 113 | #score-graph{ 114 | height: 450px; 115 | display: block; 116 | clear: both; 117 | } 118 | 119 | .fa.spinner { 120 | margin-top: 225px; 121 | text-align: center; 122 | opacity: 0.5; 123 | } 124 | 125 | .spinner-error { 126 | padding-top: 20vh; 127 | text-align: center; 128 | opacity: 0.5; 129 | } 130 | 131 | #keys-pie-graph{ 132 | width: 50%; 133 | float: left; 134 | } 135 | 136 | #categories-pie-graph{ 137 | width: 50%; 138 | float: left; 139 | } 140 | 141 | .logo{ 142 | margin: 0 auto; 143 | width: 100%; 144 | max-width: 500px; 145 | padding: 50px; 146 | display: block; 147 | } 148 | 149 | @media only screen and (min-width: 40.063em){ 150 | .top-bar .dropdown{ 151 | display: block; 152 | padding: 0 15px 5px; 153 | width: 200% !important; 154 | } 155 | } 156 | 157 | .btn { 158 | letter-spacing: 1px; 159 | text-decoration: none; 160 | -moz-user-select: none; 161 | border-radius: 0; 162 | cursor: pointer; 163 | display: inline-block; 164 | margin-bottom: 0; 165 | vertical-align: middle; 166 | white-space: nowrap; 167 | font-size:14px; 168 | line-height:20px; 169 | font-weight:700; 170 | text-transform:uppercase; 171 | padding:8px 20px; 172 | } 173 | 174 | .btn-outlined { 175 | border-radius: 0; 176 | -webkit-transition: all 0.3s; 177 | -moz-transition: all 0.3s; 178 | transition: all 0.3s; 179 | } 180 | 181 | .file-wrapper { 182 | background-color: #5B7290; 183 | } 184 | 185 | .file-wrapper:hover { 186 | background-color: #747474; 187 | } 188 | 189 | .theme-background { 190 | background-color: #545454 !important; 191 | 192 | } 193 | 194 | .solved-challenge { 195 | background-color: #8EDC9D !important; 196 | } 197 | 198 | .panel-theme { 199 | border-color: #545454; 200 | } 201 | 202 | .panel-theme > .panel-heading { 203 | border-color: #545454; 204 | background-color: #545454; 205 | opacity: 1; 206 | color: #FFF; 207 | text-align: center; 208 | } 209 | 210 | .btn-outlined.btn-theme { 211 | background: none; 212 | color: #545454; 213 | border-color: #545454; 214 | background-image: none; 215 | border: 3px solid; 216 | } 217 | 218 | .btn-outlined.btn-theme:hover, 219 | .btn-outlined.btn-theme:active { 220 | color: #FFF; 221 | background: #545454; 222 | border-color: #545454; 223 | } 224 | 225 | .navbar-inverse { 226 | background: none repeat scroll 0% 0% #545454; 227 | border: medium none; 228 | margin-bottom: 0px; 229 | } 230 | 231 | .jumbotron { 232 | background-color: #545454; 233 | color: #FFF; 234 | padding: 0px 0px 25px; 235 | } 236 | 237 | .jumbotron.home { 238 | text-align: center; 239 | margin-bottom: 0px; 240 | } 241 | 242 | .home h1 { 243 | font-size: 48px !important; 244 | } 245 | 246 | .navbar { 247 | border-radius: 0px; 248 | } 249 | 250 | .modal-content { 251 | border-radius: 0px; 252 | } 253 | 254 | .chal-tag { 255 | margin: 0 5px 0 5px; 256 | } 257 | 258 | .alert { 259 | border-radius: 0px; 260 | } 261 | 262 | /* INPUT CSS */ 263 | 264 | .submit-row { 265 | padding-left: 15px; 266 | padding-right: 30px; 267 | } 268 | 269 | .input { 270 | width: 100%; 271 | position: relative; 272 | z-index: 1; 273 | display: inline-block; 274 | margin: 1em 0em; 275 | vertical-align: top; 276 | } 277 | 278 | .input-field { 279 | position: relative; 280 | display: block; 281 | float: right; 282 | padding: 0.8em; 283 | width: 60%; 284 | border: none; 285 | border-radius: 0; 286 | background: #f0f0f0; 287 | color: #aaa; 288 | font-weight: 400; 289 | font-family: "Avenir Next", "Helvetica Neue", Helvetica, Arial, sans-serif; 290 | -webkit-appearance: none; /* for box shadows to show on iOS */ 291 | } 292 | 293 | .input-field:focus { 294 | outline: none; 295 | } 296 | 297 | .input-label { 298 | display: inline-block; 299 | float: right; 300 | padding: 0 1em; 301 | width: 40%; 302 | color: #6a7989; 303 | font-weight: bold; 304 | font-size: 100%; 305 | -webkit-font-smoothing: antialiased; 306 | -moz-osx-font-smoothing: grayscale; 307 | -webkit-touch-callout: none; 308 | -webkit-user-select: none; 309 | -khtml-user-select: none; 310 | -moz-user-select: none; 311 | -ms-user-select: none; 312 | user-select: none; 313 | margin: 0 0 0 0 !important; 314 | } 315 | 316 | .label-content { 317 | position: relative; 318 | display: block; 319 | padding: 1.6em 0; 320 | width: 100%; 321 | } 322 | 323 | .graphic { 324 | position: absolute; 325 | top: 0; 326 | left: 0; 327 | fill: none; 328 | } 329 | 330 | .icon { 331 | color: #ddd; 332 | font-size: 150%; 333 | } 334 | 335 | .input-field { 336 | width: 100%; 337 | background-color: #eee; 338 | border: 2px solid transparent; 339 | -webkit-transition: background-color 0.3s, border-color 0.3s; 340 | transition: background-color 0.3s, border-color 0.3s; 341 | } 342 | 343 | .input-label { 344 | width: 100%; 345 | text-align: left; 346 | position: absolute; 347 | bottom: 100%; 348 | pointer-events: none; 349 | overflow: hidden; 350 | padding: 0 1.25em; 351 | } 352 | 353 | .label-content { 354 | color: #8B8C8B; 355 | padding: 0.25em 0; 356 | -webkit-transition: -webkit-transform 0.3s; 357 | transition: transform 0.3s; 358 | } 359 | 360 | .label-content::after { 361 | content: attr(data-content); 362 | position: absolute; 363 | font-weight: 800; 364 | bottom: 100%; 365 | left: 0; 366 | height: 100%; 367 | width: 100%; 368 | color: #a3d39c; 369 | padding: 0.25em 0; 370 | letter-spacing: 1px; 371 | font-size: 0.85em; 372 | } 373 | 374 | .input-field:focus + .input-field, 375 | .input--filled .input-field { 376 | background-color: transparent; 377 | border-color: #a3d39c; 378 | } 379 | 380 | .input--hide { 381 | display: none; 382 | } 383 | 384 | #submit { 385 | position: relative; 386 | right: -15px; 387 | } 388 | 389 | .done-row { 390 | margin: 0px; 391 | } 392 | 393 | .footer { 394 | position: absolute; 395 | left: 0; 396 | bottom: 0; 397 | padding: 0; 398 | margin: 0; 399 | width: 100%; 400 | } 401 | 402 | /* END OF INPUT CSS */ 403 | -------------------------------------------------------------------------------- /stormctf/static/css/vendor/font-awesome/fontawesome-fonts.css: -------------------------------------------------------------------------------- 1 | @import url('https://use.fontawesome.com/releases/v5.4.1/css/all.css'); 2 | 3 | @font-face { 4 | font-family: 'Font Awesome 5 Brands Offline'; 5 | font-style: normal; 6 | font-weight: normal; 7 | src: url("webfonts/fa-brands-400.eot"); 8 | src: url("webfonts/fa-brands-400.eot?#iefix") format("embedded-opentype"), url("webfonts/fa-brands-400.woff2") format("woff2"), url("webfonts/fa-brands-400.woff") format("woff"), url("webfonts/fa-brands-400.ttf") format("truetype"), url("webfonts/fa-brands-400.svg#fontawesome") format("svg"); } 9 | 10 | @font-face { 11 | font-family: 'Font Awesome 5 Free Offline'; 12 | font-style: normal; 13 | font-weight: 400; 14 | src: url("webfonts/fa-regular-400.eot"); 15 | src: url("webfonts/fa-regular-400.eot?#iefix") format("embedded-opentype"), url("webfonts/fa-regular-400.woff2") format("woff2"), url("webfonts/fa-regular-400.woff") format("woff"), url("webfonts/fa-regular-400.ttf") format("truetype"), url("webfonts/fa-regular-400.svg#fontawesome") format("svg"); } 16 | 17 | @font-face { 18 | font-family: 'Font Awesome 5 Free Offline'; 19 | font-style: normal; 20 | font-weight: 900; 21 | src: url("webfonts/fa-solid-900.eot"); 22 | src: url("webfonts/fa-solid-900.eot?#iefix") format("embedded-opentype"), url("webfonts/fa-solid-900.woff2") format("woff2"), url("webfonts/fa-solid-900.woff") format("woff"), url("webfonts/fa-solid-900.ttf") format("truetype"), url("webfonts/fa-solid-900.svg#fontawesome") format("svg"); } -------------------------------------------------------------------------------- /stormctf/static/css/vendor/font-awesome/webfonts/fa-brands-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/font-awesome/webfonts/fa-brands-400.eot -------------------------------------------------------------------------------- /stormctf/static/css/vendor/font-awesome/webfonts/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/font-awesome/webfonts/fa-brands-400.ttf -------------------------------------------------------------------------------- /stormctf/static/css/vendor/font-awesome/webfonts/fa-brands-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/font-awesome/webfonts/fa-brands-400.woff -------------------------------------------------------------------------------- /stormctf/static/css/vendor/font-awesome/webfonts/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/font-awesome/webfonts/fa-brands-400.woff2 -------------------------------------------------------------------------------- /stormctf/static/css/vendor/font-awesome/webfonts/fa-regular-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/font-awesome/webfonts/fa-regular-400.eot -------------------------------------------------------------------------------- /stormctf/static/css/vendor/font-awesome/webfonts/fa-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/font-awesome/webfonts/fa-regular-400.ttf -------------------------------------------------------------------------------- /stormctf/static/css/vendor/font-awesome/webfonts/fa-regular-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/font-awesome/webfonts/fa-regular-400.woff -------------------------------------------------------------------------------- /stormctf/static/css/vendor/font-awesome/webfonts/fa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/font-awesome/webfonts/fa-regular-400.woff2 -------------------------------------------------------------------------------- /stormctf/static/css/vendor/font-awesome/webfonts/fa-solid-900.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/font-awesome/webfonts/fa-solid-900.eot -------------------------------------------------------------------------------- /stormctf/static/css/vendor/font-awesome/webfonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/font-awesome/webfonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /stormctf/static/css/vendor/font-awesome/webfonts/fa-solid-900.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/font-awesome/webfonts/fa-solid-900.woff -------------------------------------------------------------------------------- /stormctf/static/css/vendor/font-awesome/webfonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/font-awesome/webfonts/fa-solid-900.woff2 -------------------------------------------------------------------------------- /stormctf/static/css/vendor/font.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Lato:400,400i,700,700i|Raleway:400,400i,700,700i&subset=latin-ext'); 2 | 3 | @font-face { 4 | font-family: 'LatoOffline'; 5 | font-style: normal; 6 | font-weight: 400; 7 | src: 8 | local('Lato Regular'), 9 | local('Lato-Regular'), 10 | /* from https://fonts.gstatic.com/s/lato/v14/nQhiC-wSiJx0pvEuJl8d8A.eot */ 11 | url('lato/Lato_400.eot?#iefix') format('embedded-opentype'), 12 | /* from https://fonts.gstatic.com/s/lato/v14/9k-RPmcnxYEPm8CNFsH2gg.woff */ 13 | url('lato/Lato_400.woff') format('woff'), 14 | /* from https://fonts.gstatic.com/s/lato/v14/1YwB1sO8YE1Lyjf12WNiUA.woff2 */ 15 | url('lato/Lato_400.woff2') format('woff2'), 16 | /* from https://fonts.gstatic.com/l/font?kit=hLECvlEj3pKlnS4NFs8NQw&skey=2d58b92a99e1c086&v=v14#Lato */ 17 | url('lato/Lato_400.svg#Lato') format('svg'), 18 | /* from https://fonts.gstatic.com/s/lato/v14/v0SdcGFAl2aezM9Vq_aFTQ.ttf */ 19 | url('lato/Lato_400.ttf') format('truetype'); 20 | } 21 | @font-face { 22 | font-family: 'LatoOffline'; 23 | font-style: italic; 24 | font-weight: 400; 25 | src: 26 | local('Lato Italic'), 27 | local('Lato-Italic'), 28 | /* from https://fonts.gstatic.com/s/lato/v14/bjaQ6jyWa8A2XFrSKceJyA.eot */ 29 | url('lato/Lato_400i.eot?#iefix') format('embedded-opentype'), 30 | /* from https://fonts.gstatic.com/s/lato/v14/oUan5VrEkpzIazlUe5ieaA.woff */ 31 | url('lato/Lato_400i.woff') format('woff'), 32 | /* from https://fonts.gstatic.com/s/lato/v14/PLygLKRVCQnA5fhu3qk5fQ.woff2 */ 33 | url('lato/Lato_400i.woff2') format('woff2'), 34 | /* from https://fonts.gstatic.com/l/font?kit=sbmVKhXgM5wMsElf_vy3Iw&skey=51512958f8cff7a8&v=v14#Lato */ 35 | url('lato/Lato_400i.svg#Lato') format('svg'), 36 | /* from https://fonts.gstatic.com/s/lato/v14/LqowQDslGv4DmUBAfWa2Vw.ttf */ 37 | url('lato/Lato_400i.ttf') format('truetype'); 38 | } 39 | @font-face { 40 | font-family: 'LatoOffline'; 41 | font-style: normal; 42 | font-weight: 700; 43 | src: 44 | local('Lato Bold'), 45 | local('Lato-Bold'), 46 | /* from https://fonts.gstatic.com/s/lato/v14/sBtfDPlEIwvKKU53nAG7AQ.eot */ 47 | url('lato/Lato_700.eot?#iefix') format('embedded-opentype'), 48 | /* from https://fonts.gstatic.com/s/lato/v14/wkfQbvfT_02e2IWO3yYueQ.woff */ 49 | url('lato/Lato_700.woff') format('woff'), 50 | /* from https://fonts.gstatic.com/s/lato/v14/H2DMvhDLycM56KNuAtbJYA.woff2 */ 51 | url('lato/Lato_700.woff2') format('woff2'), 52 | /* from https://fonts.gstatic.com/l/font?kit=H4oiIt_Ug9TU5ast0nUT-w&skey=3480a19627739c0d&v=v14#Lato */ 53 | url('lato/Lato_700.svg#Lato') format('svg'), 54 | /* from https://fonts.gstatic.com/s/lato/v14/DvlFBScY1r-FMtZSYIYoYw.ttf */ 55 | url('lato/Lato_700.ttf') format('truetype'); 56 | } 57 | @font-face { 58 | font-family: 'LatoOffline'; 59 | font-style: italic; 60 | font-weight: 700; 61 | src: 62 | local('Lato Bold Italic'), 63 | local('Lato-BoldItalic'), 64 | /* from https://fonts.gstatic.com/s/lato/v14/HkF_qI1x_noxlxhrhMQYEPY6323mHUZFJMgTvxaG2iE.eot */ 65 | url('lato/Lato_700i.eot?#iefix') format('embedded-opentype'), 66 | /* from https://fonts.gstatic.com/s/lato/v14/HkF_qI1x_noxlxhrhMQYED8E0i7KZn-EPnyo3HZu7kw.woff */ 67 | url('lato/Lato_700i.woff') format('woff'), 68 | /* from https://fonts.gstatic.com/s/lato/v14/HkF_qI1x_noxlxhrhMQYEFtXRa8TVwTICgirnJhmVJw.woff2 */ 69 | url('lato/Lato_700i.woff2') format('woff2'), 70 | /* from https://fonts.gstatic.com/l/font?kit=HkF_qI1x_noxlxhrhMQYEJbd9NUM7myrQQz30yPaGQ4&skey=5334e9c0b67702e2&v=v14#Lato */ 71 | url('lato/Lato_700i.svg#Lato') format('svg'), 72 | /* from https://fonts.gstatic.com/s/lato/v14/HkF_qI1x_noxlxhrhMQYEKCWcynf_cDxXwCLxiixG1c.ttf */ 73 | url('lato/Lato_700i.ttf') format('truetype'); 74 | } 75 | @font-face { 76 | font-family: 'RalewayOffline'; 77 | font-style: normal; 78 | font-weight: 400; 79 | src: 80 | local('Raleway'), 81 | local('Raleway-Regular'), 82 | /* from https://fonts.gstatic.com/s/raleway/v12/JDau3G46nqY5-B-S9E_nwg.eot */ 83 | url('raleway/Raleway_400.eot?#iefix') format('embedded-opentype'), 84 | /* from https://fonts.gstatic.com/s/raleway/v12/IczWvq5y_Cwwv_rBjOtT0w.woff */ 85 | url('raleway/Raleway_400.woff') format('woff'), 86 | /* from https://fonts.gstatic.com/s/raleway/v12/0dTEPzkLWceF7z0koJaX1A.woff2 */ 87 | url('raleway/Raleway_400.woff2') format('woff2'), 88 | /* from https://fonts.gstatic.com/l/font?kit=IP_NSg73bUZGuyb3zF6qcQ&skey=30a27f2564731c64&v=v12#Raleway */ 89 | url('raleway/Raleway_400.svg#Raleway') format('svg'), 90 | /* from https://fonts.gstatic.com/s/raleway/v12/bIcY3_3JNqUVRAQQRNVteQ.ttf */ 91 | url('raleway/Raleway_400.ttf') format('truetype'); 92 | } 93 | @font-face { 94 | font-family: 'RalewayOffline'; 95 | font-style: italic; 96 | font-weight: 400; 97 | src: 98 | local('Raleway Italic'), 99 | local('Raleway-Italic'), 100 | /* from https://fonts.gstatic.com/s/raleway/v12/IIm-lPOtfVKQy0GMiczF__Y6323mHUZFJMgTvxaG2iE.eot */ 101 | url('raleway/Raleway_400i.eot?#iefix') format('embedded-opentype'), 102 | /* from https://fonts.gstatic.com/s/raleway/v12/IIm-lPOtfVKQy0GMiczF_z8E0i7KZn-EPnyo3HZu7kw.woff */ 103 | url('raleway/Raleway_400i.woff') format('woff'), 104 | /* from https://fonts.gstatic.com/s/raleway/v12/IIm-lPOtfVKQy0GMiczF_1tXRa8TVwTICgirnJhmVJw.woff2 */ 105 | url('raleway/Raleway_400i.woff2') format('woff2'), 106 | /* from https://fonts.gstatic.com/l/font?kit=IIm-lPOtfVKQy0GMiczF_5bd9NUM7myrQQz30yPaGQ4&skey=bf44ee29381a37b0&v=v12#Raleway */ 107 | url('raleway/Raleway_400i.svg#Raleway') format('svg'), 108 | /* from https://fonts.gstatic.com/s/raleway/v12/IIm-lPOtfVKQy0GMiczF_6CWcynf_cDxXwCLxiixG1c.ttf */ 109 | url('raleway/Raleway_400i.ttf') format('truetype'); 110 | } 111 | @font-face { 112 | font-family: 'RalewayOffline'; 113 | font-style: normal; 114 | font-weight: 700; 115 | src: 116 | local('Raleway Bold'), 117 | local('Raleway-Bold'), 118 | /* from https://fonts.gstatic.com/s/raleway/v12/JbtMzqLaYbbbCL9X6EvaI1QlYEbsez9cZjKsNMjLOwM.eot */ 119 | url('raleway/Raleway_700.eot?#iefix') format('embedded-opentype'), 120 | /* from https://fonts.gstatic.com/s/raleway/v12/JbtMzqLaYbbbCL9X6EvaIxsxEYwM7FgeyaSgU71cLG0.woff */ 121 | url('raleway/Raleway_700.woff') format('woff'), 122 | /* from https://fonts.gstatic.com/s/raleway/v12/JbtMzqLaYbbbCL9X6EvaI_k_vArhqVIZ0nv9q090hN8.woff2 */ 123 | url('raleway/Raleway_700.woff2') format('woff2'), 124 | /* from https://fonts.gstatic.com/l/font?kit=JbtMzqLaYbbbCL9X6EvaI6WUboTb-jS2tyCOQMtm97g&skey=e507c3e2b7915ad1&v=v12#Raleway */ 125 | url('raleway/Raleway_700.svg#Raleway') format('svg'), 126 | /* from https://fonts.gstatic.com/s/raleway/v12/JbtMzqLaYbbbCL9X6EvaIy3USBnSvpkopQaUR-2r7iU.ttf */ 127 | url('raleway/Raleway_700.ttf') format('truetype'); 128 | } 129 | @font-face { 130 | font-family: 'RalewayOffline'; 131 | font-style: italic; 132 | font-weight: 700; 133 | src: 134 | local('Raleway Bold Italic'), 135 | local('Raleway-BoldItalic'), 136 | /* from https://fonts.gstatic.com/s/raleway/v12/lFxvRPuGFG5ktd7P0WRwKnZ2MAKAc2x4R1uOSeegc5U.eot */ 137 | url('raleway/Raleway_700i.eot?#iefix') format('embedded-opentype'), 138 | /* from https://fonts.gstatic.com/s/raleway/v12/lFxvRPuGFG5ktd7P0WRwKnhCUOGz7vYGh680lGh-uXM.woff */ 139 | url('raleway/Raleway_700i.woff') format('woff'), 140 | /* from https://fonts.gstatic.com/s/raleway/v12/lFxvRPuGFG5ktd7P0WRwKugdm0LZdjqr5-oayXSOefg.woff2 */ 141 | url('raleway/Raleway_700i.woff2') format('woff2'), 142 | /* from https://fonts.gstatic.com/l/font?kit=lFxvRPuGFG5ktd7P0WRwKllIn5tFQcqMuf-jhyJP0ps&skey=9ecf9384a6d643b6&v=v12#Raleway */ 143 | url('raleway/Raleway_700i.svg#Raleway') format('svg'), 144 | /* from https://fonts.gstatic.com/s/raleway/v12/lFxvRPuGFG5ktd7P0WRwKonF5uFdDttMLvmWuJdhhgs.ttf */ 145 | url('raleway/Raleway_700i.ttf') format('truetype'); 146 | } 147 | -------------------------------------------------------------------------------- /stormctf/static/css/vendor/lato/Lato_400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/lato/Lato_400.eot -------------------------------------------------------------------------------- /stormctf/static/css/vendor/lato/Lato_400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/lato/Lato_400.ttf -------------------------------------------------------------------------------- /stormctf/static/css/vendor/lato/Lato_400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/lato/Lato_400.woff -------------------------------------------------------------------------------- /stormctf/static/css/vendor/lato/Lato_400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/lato/Lato_400.woff2 -------------------------------------------------------------------------------- /stormctf/static/css/vendor/lato/Lato_400i.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/lato/Lato_400i.eot -------------------------------------------------------------------------------- /stormctf/static/css/vendor/lato/Lato_400i.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/lato/Lato_400i.ttf -------------------------------------------------------------------------------- /stormctf/static/css/vendor/lato/Lato_400i.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/lato/Lato_400i.woff -------------------------------------------------------------------------------- /stormctf/static/css/vendor/lato/Lato_400i.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/lato/Lato_400i.woff2 -------------------------------------------------------------------------------- /stormctf/static/css/vendor/lato/Lato_700.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/lato/Lato_700.eot -------------------------------------------------------------------------------- /stormctf/static/css/vendor/lato/Lato_700.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/lato/Lato_700.ttf -------------------------------------------------------------------------------- /stormctf/static/css/vendor/lato/Lato_700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/lato/Lato_700.woff -------------------------------------------------------------------------------- /stormctf/static/css/vendor/lato/Lato_700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/lato/Lato_700.woff2 -------------------------------------------------------------------------------- /stormctf/static/css/vendor/lato/Lato_700i.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/lato/Lato_700i.eot -------------------------------------------------------------------------------- /stormctf/static/css/vendor/lato/Lato_700i.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/lato/Lato_700i.ttf -------------------------------------------------------------------------------- /stormctf/static/css/vendor/lato/Lato_700i.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/lato/Lato_700i.woff -------------------------------------------------------------------------------- /stormctf/static/css/vendor/lato/Lato_700i.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/lato/Lato_700i.woff2 -------------------------------------------------------------------------------- /stormctf/static/css/vendor/raleway/Raleway_400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/raleway/Raleway_400.eot -------------------------------------------------------------------------------- /stormctf/static/css/vendor/raleway/Raleway_400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/raleway/Raleway_400.ttf -------------------------------------------------------------------------------- /stormctf/static/css/vendor/raleway/Raleway_400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/raleway/Raleway_400.woff -------------------------------------------------------------------------------- /stormctf/static/css/vendor/raleway/Raleway_400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/raleway/Raleway_400.woff2 -------------------------------------------------------------------------------- /stormctf/static/css/vendor/raleway/Raleway_400i.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/raleway/Raleway_400i.eot -------------------------------------------------------------------------------- /stormctf/static/css/vendor/raleway/Raleway_400i.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/raleway/Raleway_400i.ttf -------------------------------------------------------------------------------- /stormctf/static/css/vendor/raleway/Raleway_400i.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/raleway/Raleway_400i.woff -------------------------------------------------------------------------------- /stormctf/static/css/vendor/raleway/Raleway_400i.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/raleway/Raleway_400i.woff2 -------------------------------------------------------------------------------- /stormctf/static/css/vendor/raleway/Raleway_700.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/raleway/Raleway_700.eot -------------------------------------------------------------------------------- /stormctf/static/css/vendor/raleway/Raleway_700.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/raleway/Raleway_700.ttf -------------------------------------------------------------------------------- /stormctf/static/css/vendor/raleway/Raleway_700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/raleway/Raleway_700.woff -------------------------------------------------------------------------------- /stormctf/static/css/vendor/raleway/Raleway_700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/raleway/Raleway_700.woff2 -------------------------------------------------------------------------------- /stormctf/static/css/vendor/raleway/Raleway_700i.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/raleway/Raleway_700i.eot -------------------------------------------------------------------------------- /stormctf/static/css/vendor/raleway/Raleway_700i.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/raleway/Raleway_700i.ttf -------------------------------------------------------------------------------- /stormctf/static/css/vendor/raleway/Raleway_700i.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/raleway/Raleway_700i.woff -------------------------------------------------------------------------------- /stormctf/static/css/vendor/raleway/Raleway_700i.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/css/vendor/raleway/Raleway_700i.woff2 -------------------------------------------------------------------------------- /stormctf/static/fonts/IcoMoon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/fonts/IcoMoon.eot -------------------------------------------------------------------------------- /stormctf/static/fonts/font-08a5b663.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/fonts/font-08a5b663.woff -------------------------------------------------------------------------------- /stormctf/static/fonts/font-360dafd3.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/fonts/font-360dafd3.woff -------------------------------------------------------------------------------- /stormctf/static/fonts/font-38d64ba3.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/fonts/font-38d64ba3.woff -------------------------------------------------------------------------------- /stormctf/static/fonts/font-3d31737a.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/fonts/font-3d31737a.woff2 -------------------------------------------------------------------------------- /stormctf/static/fonts/font-6482a3ff.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/fonts/font-6482a3ff.woff2 -------------------------------------------------------------------------------- /stormctf/static/fonts/font-6c7b3554.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/fonts/font-6c7b3554.woff -------------------------------------------------------------------------------- /stormctf/static/fonts/font-a3913573.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/fonts/font-a3913573.woff2 -------------------------------------------------------------------------------- /stormctf/static/fonts/font-a4a03eac.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/fonts/font-a4a03eac.woff -------------------------------------------------------------------------------- /stormctf/static/fonts/font-a6c1c4ca.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/fonts/font-a6c1c4ca.woff2 -------------------------------------------------------------------------------- /stormctf/static/fonts/font-b7eb26b8.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/fonts/font-b7eb26b8.woff -------------------------------------------------------------------------------- /stormctf/static/fonts/font-c2ad8b3d.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/fonts/font-c2ad8b3d.woff2 -------------------------------------------------------------------------------- /stormctf/static/fonts/font-e0d6f976.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/fonts/font-e0d6f976.woff2 -------------------------------------------------------------------------------- /stormctf/static/fonts/font-ec67e4a8.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/fonts/font-ec67e4a8.woff -------------------------------------------------------------------------------- /stormctf/static/fonts/font-ec84201c.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/fonts/font-ec84201c.woff2 -------------------------------------------------------------------------------- /stormctf/static/fonts/font-f2de05d4.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/fonts/font-f2de05d4.woff -------------------------------------------------------------------------------- /stormctf/static/fonts/font-fd3a65d0.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/fonts/font-fd3a65d0.woff2 -------------------------------------------------------------------------------- /stormctf/static/fonts/section-background-image-noise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/fonts/section-background-image-noise.png -------------------------------------------------------------------------------- /stormctf/static/img/challenges.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/img/challenges.jpg -------------------------------------------------------------------------------- /stormctf/static/img/confirmation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/img/confirmation.png -------------------------------------------------------------------------------- /stormctf/static/img/ctfd.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/img/ctfd.ai -------------------------------------------------------------------------------- /stormctf/static/img/ctfd.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 9 | 10 | 13 | 14 | 15 | 19 | 20 | 22 | 24 | 26 | 27 | -------------------------------------------------------------------------------- /stormctf/static/img/ctfd_transfer.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 10 | 11 | 14 | 15 | 16 | 20 | 21 | 23 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /stormctf/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/img/favicon.ico -------------------------------------------------------------------------------- /stormctf/static/img/login.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/img/login.jpg -------------------------------------------------------------------------------- /stormctf/static/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/img/logo.png -------------------------------------------------------------------------------- /stormctf/static/img/logo_old.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/img/logo_old.png -------------------------------------------------------------------------------- /stormctf/static/img/notifications.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/img/notifications.png -------------------------------------------------------------------------------- /stormctf/static/img/scoreboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/img/scoreboard.png -------------------------------------------------------------------------------- /stormctf/static/img/team.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sctf2020/CTFd-Theme-StormCTF/10a9f0bae810aaaca98e746b2c015638ff623742/stormctf/static/img/team.png -------------------------------------------------------------------------------- /stormctf/static/js/CTFd.js: -------------------------------------------------------------------------------- 1 | var CTFd = (function () { 2 | 3 | var options = { 4 | urlRoot: '', 5 | csrfNonce: '', 6 | start: null, 7 | end: null, 8 | }; 9 | 10 | var challenges = {}; 11 | 12 | var scoreboard = function() {}; 13 | 14 | var teams = {}; 15 | 16 | var users = {}; 17 | 18 | var fetch = function(url, options) { 19 | if (options === undefined) { 20 | options = { 21 | method: "GET", 22 | credentials: "same-origin", 23 | headers: {}, 24 | }; 25 | } 26 | url = this.options.urlRoot + url; 27 | 28 | 29 | if (options.headers === undefined) { 30 | options.headers = {}; 31 | } 32 | options.credentials = 'same-origin'; 33 | options.headers['Accept'] = 'application/json'; 34 | options.headers['Content-Type'] = 'application/json'; 35 | options.headers['CSRF-Token'] = this.options.csrfNonce; 36 | 37 | return window.fetch(url, options); 38 | }; 39 | 40 | return { 41 | challenges: challenges, 42 | scoreboard: scoreboard, 43 | teams: teams, 44 | users: users, 45 | fetch: fetch, 46 | options: options 47 | }; 48 | })(); -------------------------------------------------------------------------------- /stormctf/static/js/challenges.js: -------------------------------------------------------------------------------- 1 | var challenges; 2 | var user_solves = []; 3 | var templates = {}; 4 | 5 | window.challenge = new Object(); 6 | 7 | function loadchal(id) { 8 | var obj = $.grep(challenges, function (e) { 9 | return e.id == id; 10 | })[0]; 11 | 12 | if (obj.type === 'hidden') { 13 | ezal({ 14 | title: "Challenge Hidden!", 15 | body: "You haven't unlocked this challenge yet!", 16 | button: "Got it!" 17 | }); 18 | return; 19 | } 20 | 21 | updateChalWindow(obj); 22 | } 23 | 24 | function loadchalbyname(chalname) { 25 | var obj = $.grep(challenges, function (e) { 26 | return e.name == chalname; 27 | })[0]; 28 | 29 | updateChalWindow(obj); 30 | } 31 | 32 | function updateChalWindow(obj) { 33 | $.get(script_root + "/api/v1/challenges/" + obj.id, function (response) { 34 | var challenge_data = response.data; 35 | 36 | $.getScript(script_root + obj.script, function () { 37 | $.get(script_root + obj.template, function (template_data) { 38 | $('#challenge-window').empty(); 39 | var template = nunjucks.compile(template_data); 40 | window.challenge.data = challenge_data; 41 | window.challenge.preRender(); 42 | 43 | challenge_data['description'] = window.challenge.render(challenge_data['description']); 44 | challenge_data['script_root'] = script_root; 45 | 46 | $('#challenge-window').append(template.render(challenge_data)); 47 | 48 | $('.challenge-solves').click(function (e) { 49 | getsolves($('#challenge-id').val()) 50 | }); 51 | $('.nav-tabs a').click(function (e) { 52 | e.preventDefault(); 53 | $(this).tab('show') 54 | }); 55 | 56 | // Handle modal toggling 57 | $('#challenge-window').on('hide.uk.modal', function (event) { 58 | $("#submission-input").removeClass("uk-form-danger"); 59 | $("#submission-input").removeClass("uk-form-success"); 60 | $("#incorrect-key").slideUp(); 61 | $("#correct-key").slideUp(); 62 | $("#already-solved").slideUp(); 63 | $("#too-fast").slideUp(); 64 | }); 65 | 66 | $('#submit-key').click(function (e) { 67 | e.preventDefault(); 68 | //$('#submit-key').addClass("disabled-button"); 69 | $('#submit-key').prop('disabled', true); 70 | window.challenge.submit(function (data) { 71 | renderSubmissionResponse(data); 72 | loadchals(function () { 73 | marksolves(); 74 | }); 75 | }); 76 | }); 77 | 78 | // $("#submission-input").keyup(function (event) { 79 | // if (event.keyCode == 13) { 80 | // $("#submit-key").click(); 81 | // } 82 | // }); 83 | 84 | $(".input-field").bind({ 85 | focus: function () { 86 | $(this).parent().addClass('input--filled'); 87 | $label = $(this).siblings(".input-label"); 88 | }, 89 | blur: function () { 90 | if ($(this).val() === '') { 91 | $(this).parent().removeClass('input--filled'); 92 | $label = $(this).siblings(".input-label"); 93 | $label.removeClass('input--hide'); 94 | } 95 | } 96 | }); 97 | 98 | window.challenge.postRender(); 99 | 100 | window.location.replace(window.location.href.split('#')[0] + '#' + obj.name); 101 | //$('#challenge-window').modal(); 102 | UIkit.modal('#challenge-window', { bgclose: true, center: true }).show(); 103 | }); 104 | }); 105 | }); 106 | } 107 | 108 | $("#submission-input").keyup(function (event) { 109 | if (event.keyCode == 13) { 110 | $("#submit-key").click(); 111 | } 112 | }); 113 | 114 | 115 | function renderSubmissionResponse(response, cb) { 116 | var result = response.data; 117 | 118 | var result_message = $('#result-message'); 119 | var result_notification = $('#result-notification'); 120 | var answer_input = $("#submission-input"); 121 | result_notification.removeClass('uk-alert-warning'); 122 | result_notification.removeClass('uk-alert-success'); 123 | result_notification.removeClass('uk-alert-danger'); 124 | result_message.text(result.message); 125 | 126 | if (result.status === "authentication_required") { 127 | window.location = script_root + "/login?next=" + script_root + window.location.pathname + window.location.hash; 128 | return 129 | } 130 | else if (result.status === "incorrect") { // Incorrect key 131 | result_notification.addClass('uk-alert-danger'); 132 | result_notification.slideDown(); 133 | 134 | answer_input.removeClass("uk-form-success"); 135 | answer_input.addClass("uk-form-danger"); 136 | setTimeout(function () { 137 | answer_input.removeClass("uk-form-danger"); 138 | }, 3000); 139 | } 140 | else if (result.status === "correct") { // Challenge Solved 141 | result_notification.addClass('uk-alert-success'); 142 | result_notification.slideDown(); 143 | 144 | $('.challenge-solves').text((parseInt($('.challenge-solves').text().split(" ")[0]) + 1 + " Solves")); 145 | 146 | answer_input.val(""); 147 | answer_input.removeClass("uk-form-danger"); 148 | answer_input.addClass("uk-form-success"); 149 | setTimeout(function () { 150 | UIkit.modal('#challenge-window').hide(); 151 | update(); 152 | }, 3000); 153 | } 154 | else if (result.status === "already_solved") { // Challenge already solved 155 | result_notification.addClass('uk-alert-primary'); 156 | result_notification.slideDown(); 157 | setTimeout(function () { 158 | UIkit.modal('#challenge-window').hide(); 159 | update(); 160 | }, 3000); 161 | 162 | //answer_input.addClass("uk-form-danger"); 163 | } 164 | else if (result.status === "paused") { // CTF is paused 165 | result_notification.addClass('uk-alert-warning'); 166 | result_notification.slideDown(); 167 | } 168 | else if (result.status === "ratelimited") { // Keys per minute too high 169 | result_notification.addClass('uk-alert-warning'); 170 | result_notification.slideDown(); 171 | 172 | answer_input.addClass("uk-form-danger"); 173 | setTimeout(function () { 174 | answer_input.removeClass("uk-form-danger"); 175 | }, 3000); 176 | } 177 | setTimeout(function () { 178 | $('.alert').slideUp(); 179 | //$('#submit-key').removeClass("disabled-button"); 180 | $('#submit-key').prop('disabled', false); 181 | }, 3000); 182 | 183 | if (cb) { 184 | cb(result); 185 | } 186 | } 187 | 188 | function marksolves(cb) { 189 | $.get(script_root + '/api/v1/' + user_mode + '/me/solves', function (response) { 190 | var solves = response.data; 191 | for (var i = solves.length - 1; i >= 0; i--) { 192 | var id = solves[i].challenge_id; 193 | var btn = $('button[value="' + id + '"]'); 194 | btn.addClass('solved-challenge'); 195 | btn.prepend("") 196 | } 197 | if (cb) { 198 | cb(); 199 | } 200 | }); 201 | } 202 | 203 | function load_user_solves(cb) { 204 | if (authed) { 205 | $.get(script_root + '/api/v1/' + user_mode + '/me/solves', function (response) { 206 | var solves = response.data; 207 | 208 | for (var i = solves.length - 1; i >= 0; i--) { 209 | var chal_id = solves[i].challenge_id; 210 | user_solves.push(chal_id); 211 | 212 | } 213 | if (cb) { 214 | cb(); 215 | } 216 | }); 217 | } else { 218 | cb(); 219 | } 220 | } 221 | 222 | function getsolves(id) { 223 | $.get(script_root + '/api/v1/challenges/' + id + '/solves', function (response) { 224 | var data = response.data; 225 | $('.challenge-solves').text( 226 | (parseInt(data.length) + " Solves") 227 | ); 228 | var box = $('#challenge-solves-names'); 229 | box.empty(); 230 | for (var i = 0; i < data.length; i++) { 231 | var id = data[i].account_id; 232 | var name = data[i].name; 233 | var date = moment(data[i].date).local().fromNow(); 234 | var account_url = data[i].account_url 235 | box.append('{2}{3}'.format(account_url, id, htmlentities(name), date)); 236 | } 237 | }); 238 | } 239 | 240 | function loadchals(cb) { 241 | $.get(script_root + "/api/v1/challenges", function (response) { 242 | var categories = []; 243 | challenges = response.data; 244 | 245 | $('#challenges-board').empty(); 246 | 247 | for (var i = challenges.length - 1; i >= 0; i--) { 248 | challenges[i].solves = 0; 249 | if ($.inArray(challenges[i].category, categories) == -1) { 250 | var category = challenges[i].category; 251 | categories.push(category); 252 | 253 | var categoryid = category.replace(/ /g, "-").hashCode(); 254 | var categoryrow = $('' + 255 | '
'.format(categoryid) + 256 | '
' + 257 | '
' + 258 | '
' + 259 | '
' + 260 | '
' + 261 | '
'); 262 | categoryrow.find(".category-header").append($("

" + category + "

")); 263 | 264 | $('#challenges-board').append(categoryrow); 265 | } 266 | } 267 | 268 | for (var i = 0; i <= challenges.length - 1; i++) { 269 | var chalinfo = challenges[i]; 270 | var challenge = chalinfo.category.replace(/ /g, "-").hashCode(); 271 | var chalid = chalinfo.name.replace(/ /g, "-").hashCode(); 272 | var catid = chalinfo.category.replace(/ /g, "-").hashCode(); 273 | var chalwrap = $("
".format(chalid)); 274 | 275 | if (user_solves.indexOf(chalinfo.id) == -1) { 276 | var chalbutton = $("".format(chalinfo.id)); 277 | var chalcard = $('
'); 278 | 279 | } else { 280 | var chalbutton = $("".format(chalinfo.id)); 281 | var chalcard = $('
Solved
'); 282 | } 283 | 284 | var chalheader = $("

{0}

".format(chalinfo.name)); 285 | var chalscore = $("

{0}

".format(chalinfo.value)); 286 | for (var j = 0; j < chalinfo.tags.length; j++) { 287 | var tag = 'tag-' + chalinfo.tags[j].value.replace(/ /g, '-'); 288 | chalwrap.addClass(tag); 289 | } 290 | 291 | chalcard.prepend(chalheader); 292 | chalcard.append(chalscore); 293 | chalcard.append(chalbutton); 294 | chalwrap.append(chalcard); 295 | 296 | // chalbutton.append(chalheader); 297 | // chalbutton.append(chalscore); 298 | // chalwrap.append(chalbutton); 299 | 300 | $("#" + catid + "-row").find(".category-challenges > .challenges-row").append(chalwrap); 301 | } 302 | 303 | $('.challenge-button').click(function (e) { 304 | loadchal(this.value); 305 | getsolves(this.value); 306 | }); 307 | 308 | if (cb) { 309 | cb(); 310 | } 311 | }); 312 | } 313 | 314 | 315 | 316 | $('#submit-key').click(function (e) { 317 | submitkey($('#challenge-id').val(), $('#submission-input').val(), $('#nonce').val()) 318 | }); 319 | 320 | $('.challenge-solves').click(function (e) { 321 | getsolves($('#challenge-id').val()) 322 | }); 323 | 324 | $('#challenge-window').on('hide.uk.modal', function (event) { 325 | $("#submission-input").removeClass("uk-form-danger"); 326 | $("#submission-input").removeClass("uk-form-success"); 327 | $("#incorrect-key").slideUp(); 328 | $("#correct-key").slideUp(); 329 | $("#already-solved").slideUp(); 330 | $("#too-fast").slideUp(); 331 | }); 332 | 333 | var load_location_hash = function () { 334 | if (window.location.hash.length > 0) { 335 | loadchalbyname(decodeURIComponent(window.location.hash.substring(1))); 336 | } 337 | }; 338 | 339 | function update(cb) { 340 | load_user_solves(function () { // Load the user's solved challenge ids 341 | loadchals(function () { // Load the full list of challenges 342 | if (cb) { 343 | cb(); 344 | } 345 | }); 346 | }); 347 | } 348 | 349 | $(function () { 350 | update(function () { 351 | load_location_hash(); 352 | }); 353 | }); 354 | 355 | $('.nav-tabs a').click(function (e) { 356 | e.preventDefault(); 357 | $(this).tab('show') 358 | }); 359 | 360 | $('#challenge-window').on('hidden.uk.modal', function () { 361 | //$('.nav-tabs a:first').tab('show'); 362 | history.replaceState('', document.title, window.location.pathname); 363 | }); 364 | 365 | setInterval(update, 300000); 366 | -------------------------------------------------------------------------------- /stormctf/static/js/events.js: -------------------------------------------------------------------------------- 1 | var wc = new WindowController(); 2 | 3 | var sound = new Howl({ 4 | src: [ 5 | script_root + "/themes/core/static/sounds/notification.webm", 6 | script_root + "/themes/core/static/sounds/notification.mp3", 7 | ] 8 | }); 9 | 10 | function connect() { 11 | window.ctfEventSource = new EventSource(script_root + "/events"); 12 | 13 | window.ctfEventSource.addEventListener('notification', function (event) { 14 | var data = JSON.parse(event.data); 15 | wc.broadcast('notification', data); 16 | render(data); 17 | }, false); 18 | } 19 | 20 | function disconnect() { 21 | if (window.ctfEventSource) { 22 | window.ctfEventSource.close(); 23 | } 24 | } 25 | 26 | function render(data) { 27 | ezal({ 28 | title: data.title, 29 | body: data.content, 30 | button: "Got it!" 31 | }); 32 | sound.play(); 33 | } 34 | 35 | wc.notification = function(data) { 36 | render(data); 37 | }; 38 | 39 | wc.masterDidChange = function () { 40 | if (this.isMaster) { 41 | connect(); 42 | } else { 43 | disconnect(); 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /stormctf/static/js/ezq.js: -------------------------------------------------------------------------------- 1 | var modal = '
' + 2 | '
' + 3 | ' ' + 4 | '
' + 5 | '
\{0\}
' + 6 | '
' + 7 | '
' + 8 | '

\{1\}

' + 9 | '
' + 10 | ' ' + 12 | '
' + 13 | '
'; 14 | 15 | var progress = '' + 16 | ''; 17 | 18 | var error_template = "
\n" + 19 | " " + 20 | "

\{0\}

\n" + 21 | "
"; 22 | 23 | 24 | var success_template = "
\n" + 25 | " " + 26 | " Success!\n" + 27 | " \{0\}\n" + 28 | "
"; 29 | 30 | 31 | function ezal(args){ 32 | var res = modal.format(args.title, args.body); 33 | var obj = $(res); 34 | var button = ''.format(args.button); 35 | 36 | obj.find('.uk-modal-footer').append(button); 37 | $('main').append(obj); 38 | 39 | UIkit.modal(obj).show(); 40 | // obj.modal('show'); 41 | 42 | $(obj).on('hidden.uk.modal', function (e) { 43 | // $(this).modal('dispose'); 44 | UIkit.modal(this).hide(); 45 | }); 46 | 47 | return obj; 48 | } 49 | 50 | function ezq(args){ 51 | var res = modal.format(args.title, args.body); 52 | var obj = $(res); 53 | var deny = ''; 54 | var confirm = $(''); 55 | 56 | obj.find('.uk-modal-footer').append(deny); 57 | obj.find('.uk-modal-footer').append(confirm); 58 | 59 | $('main').append(obj); 60 | 61 | $(obj).on('hidden.uk.modal', function (e) { 62 | UIkit.modal(this).hide(); 63 | // $(this).modal('dispose'); 64 | }); 65 | 66 | $(confirm).click(function(){ 67 | args.success(); 68 | }); 69 | UIkit.modal(obj).show(); 70 | // obj.modal('show'); 71 | 72 | return obj; 73 | } 74 | 75 | function ezpg(args){ 76 | if (args.target){ 77 | var obj = $(args.target); 78 | var pbar = obj.find('.uk-progress'); 79 | pbar.css('width', args.width + '%'); 80 | return obj; 81 | } 82 | var bar = progress.format(args.width); 83 | var res = modal.format(args.title, bar); 84 | 85 | var obj = $(res); 86 | $('main').append(obj); 87 | obj.modal('show'); 88 | 89 | return obj; 90 | } 91 | 92 | function ezbadge(args) { 93 | var type = args.type; 94 | var body = args.body; 95 | var tpl = undefined; 96 | if (type === 'success') { 97 | tpl = success_template; 98 | } else if (type === 'error') { 99 | tpl = error_template; 100 | } 101 | 102 | tpl = tpl.format(body); 103 | var obj = $(tpl); 104 | return obj; 105 | } -------------------------------------------------------------------------------- /stormctf/static/js/hints.js: -------------------------------------------------------------------------------- 1 | function hint(id) { 2 | return CTFd.fetch('/api/v1/hints/' + id, { 3 | method: 'GET', 4 | credentials: 'same-origin', 5 | headers: { 6 | 'Accept': 'application/json', 7 | 'Content-Type': 'application/json' 8 | } 9 | }).then(function (response) { 10 | return response.json(); 11 | }); 12 | } 13 | 14 | 15 | function unlock(params){ 16 | return CTFd.fetch('/api/v1/unlocks', { 17 | method: 'POST', 18 | credentials: 'same-origin', 19 | headers: { 20 | 'Accept': 'application/json', 21 | 'Content-Type': 'application/json' 22 | }, 23 | body: JSON.stringify(params) 24 | }).then(function (response) { 25 | return response.json(); 26 | }); 27 | } 28 | 29 | function loadhint(hintid) { 30 | var md = window.markdownit({ 31 | html: true, 32 | linkify: true, 33 | }); 34 | 35 | hint(hintid).then(function (response) { 36 | if (response.data.content) { 37 | ezal({ 38 | title: "Hint", 39 | body: md.render(response.data.content), 40 | button: "Got it!" 41 | }); 42 | } else { 43 | ezq({ 44 | title: "Unlock Hint?", 45 | body: "Are you sure you want to open this hint?", 46 | success: function () { 47 | var params = { 48 | target: hintid, 49 | type: "hints" 50 | }; 51 | unlock(params).then(function (response) { 52 | if (response.success) { 53 | hint(hintid).then(function(response) { 54 | ezal({ 55 | title: "Hint", 56 | body: md.render(response.data.content), 57 | button: "Got it!" 58 | }); 59 | }); 60 | } else { 61 | ezal({ 62 | title: "Error", 63 | body: md.render(response.errors.score), 64 | button: "Got it!" 65 | }); 66 | } 67 | }); 68 | } 69 | }); 70 | } 71 | }); 72 | } -------------------------------------------------------------------------------- /stormctf/static/js/multi-modal.js: -------------------------------------------------------------------------------- 1 | (function($, window) { 2 | 'use strict'; 3 | 4 | var MultiModal = function(element) { 5 | this.$element = $(element); 6 | }; 7 | 8 | MultiModal.BASE_ZINDEX = 1040; 9 | 10 | MultiModal.prototype.show = function(target) { 11 | var that = this; 12 | var $target = $(target); 13 | var modalCount = $('.modal:visible').length; 14 | 15 | $target.css('z-index', MultiModal.BASE_ZINDEX + (modalCount * 20) + 10); 16 | 17 | window.setTimeout(function() { 18 | var modalCount = $('.modal:visible').length; 19 | if(modalCount > 0) 20 | $('.modal-backdrop').not(':first').addClass('hidden'); 21 | 22 | that.adjustBackdrop(modalCount); 23 | }); 24 | }; 25 | 26 | MultiModal.prototype.hidden = function(target) { 27 | var modalCount = $('.modal:visible').length; 28 | 29 | var $target = $(target); 30 | 31 | if(modalCount) { 32 | this.adjustBackdrop(modalCount - 1); 33 | $('body').addClass('modal-open'); 34 | } 35 | }; 36 | 37 | MultiModal.prototype.adjustBackdrop = function(modalCount) { 38 | $('.modal-backdrop:first').css('z-index', MultiModal.BASE_ZINDEX + ((modalCount)* 20)); 39 | }; 40 | 41 | function Plugin(method, target) { 42 | return this.each(function() { 43 | var $this = $(this); 44 | var data = $this.data('multi-modal-plugin'); 45 | 46 | if(!data) 47 | $this.data('multi-modal-plugin', (data = new MultiModal(this))); 48 | 49 | if(method) 50 | data[method](target); 51 | }); 52 | } 53 | 54 | $.fn.multiModal = Plugin; 55 | $.fn.multiModal.Constructor = MultiModal; 56 | 57 | $(document).on('show.bs.modal', function(e) { 58 | $(document).multiModal('show', e.target); 59 | }); 60 | 61 | $(document).on('hidden.bs.modal', function(e) { 62 | $(document).multiModal('hidden', e.target); 63 | }); 64 | }(jQuery, window)); 65 | -------------------------------------------------------------------------------- /stormctf/static/js/scoreboard.js: -------------------------------------------------------------------------------- 1 | function updatescores() { 2 | $.get(script_root + '/api/v1/scoreboard', function(response) { 3 | var teams = response.data; 4 | var table = $('#scoreboard tbody'); 5 | table.empty(); 6 | for (var i = 0; i < teams.length; i++) { 7 | var row = "\n" + 8 | '{0}'.format(teams[i]['pos']) + 9 | '{2}'.format(script_root,teams[i]['id'],htmlentities(teams[i]['name'])) + 10 | "{0}".format(teams[i]['score']) + 11 | ""; 12 | table.append(row); 13 | } 14 | }); 15 | } 16 | 17 | function cumulativesum(arr) { 18 | var result = arr.concat(); 19 | for (var i = 0; i < arr.length; i++) { 20 | result[i] = arr.slice(0, i + 1).reduce(function(p, i) { return p + i; }); 21 | } 22 | return result 23 | } 24 | 25 | function UTCtoDate(utc) { 26 | var d = new Date(0); 27 | d.setUTCSeconds(utc); 28 | return d; 29 | } 30 | 31 | function scoregraph() { 32 | $.get(script_root + '/api/v1/scoreboard/top/10', function(response) { 33 | var places = response.data; 34 | 35 | if (Object.keys(places).length === 0) { 36 | // Replace spinner 37 | $('#score-graph').html( 38 | '

No solves yet

' 39 | ); 40 | return; 41 | } 42 | 43 | var teams = Object.keys(places); 44 | var traces = []; 45 | for (var i = 0; i < teams.length; i++) { 46 | var team_score = []; 47 | var times = []; 48 | for (var j = 0; j < places[teams[i]]['solves'].length; j++) { 49 | team_score.push(places[teams[i]]['solves'][j].value); 50 | var date = moment(places[teams[i]]['solves'][j].date); 51 | times.push(date.toDate()); 52 | } 53 | team_score = cumulativesum(team_score); 54 | var trace = { 55 | x: times, 56 | y: team_score, 57 | mode: 'lines+markers', 58 | name: places[teams[i]]['name'], 59 | marker: { 60 | color: colorhash(places[teams[i]]['name'] + places[teams[i]]['id']), 61 | }, 62 | line: { 63 | color: colorhash(places[teams[i]]['name'] + places[teams[i]]['id']), 64 | } 65 | }; 66 | traces.push(trace); 67 | } 68 | 69 | traces.sort(function(a, b) { 70 | var scorediff = b['y'][b['y'].length - 1] - a['y'][a['y'].length - 1]; 71 | if (!scorediff) { 72 | return a['x'][a['x'].length - 1] - b['x'][b['x'].length - 1]; 73 | } 74 | return scorediff; 75 | }); 76 | 77 | var layout = { 78 | title: 'Top 10 Teams', 79 | paper_bgcolor: 'rgba(0,0,0,0)', 80 | plot_bgcolor: 'rgba(0,0,0,0)', 81 | hovermode: 'closest', 82 | titlefont: { 83 | family: 'Raleway', 84 | size: '36', 85 | color: 'white' 86 | }, 87 | xaxis: { 88 | showgrid: false, 89 | showspikes: true, 90 | color: 'white', 91 | }, 92 | yaxis: { 93 | showgrid: false, 94 | showspikes: true, 95 | color: 'white', 96 | }, 97 | legend: { 98 | orientation: "h", 99 | family: 'Raleway', 100 | font: { 101 | color: "white", 102 | size: "14" 103 | } 104 | }, 105 | marker: { 106 | symbol: "diamond-dot" 107 | }, 108 | hoverlabel: { 109 | bgcolor: "black", 110 | font: { 111 | family: "Raleway", 112 | size: "20" 113 | } 114 | } 115 | }; 116 | 117 | $('#score-graph').empty(); // Remove spinners 118 | document.getElementById('score-graph').fn = 'CTFd_scoreboard_' + (new Date).toISOString().slice(0, 19); 119 | Plotly.newPlot('score-graph', traces, layout, { 120 | // displayModeBar: false, 121 | displaylogo: false 122 | }); 123 | }); 124 | } 125 | 126 | function update() { 127 | updatescores(); 128 | scoregraph(); 129 | } 130 | setInterval(update, 300000); // Update every 30 min 131 | scoregraph(); 132 | 133 | window.onresize = function() { 134 | Plotly.Plots.resize(document.getElementById('score-graph')); 135 | }; -------------------------------------------------------------------------------- /stormctf/static/js/settings.js: -------------------------------------------------------------------------------- 1 | var error_template = "
\n" + 2 | " " + 3 | "

\{0\}

\n" + 4 | "
"; 5 | 6 | 7 | var success_template = "
\n" + 8 | " " + 9 | " Success!\n" + 10 | " Your profile has been updated\n" + 11 | "
"; 12 | 13 | 14 | $(function () { 15 | var form = $('#user-settings-form'); 16 | form.submit(function(e){ 17 | e.preventDefault(); 18 | $('#results').empty(); 19 | var params = $('#user-settings-form').serializeJSON(); 20 | 21 | CTFd.fetch('/api/v1/users/me', { 22 | method: 'PATCH', 23 | credentials: 'same-origin', 24 | headers: { 25 | 'Accept': 'application/json', 26 | 'Content-Type': 'application/json' 27 | }, 28 | body: JSON.stringify(params) 29 | }).then(function (response) { 30 | if (response.status === 400) { 31 | response.json().then(function (object) { 32 | if (!object.success){ 33 | Object.keys(object.errors).map(function(error){ 34 | var i = form.find('input[name={0}]'.format(error)); 35 | var input = $(i); 36 | input.addClass('uk-form-danger'); 37 | input.removeClass('uk-form-success'); 38 | var error_msg = object.errors[error]; 39 | var alert = error_template.format(error_msg); 40 | console.log(error_template); 41 | $('#results').append( 42 | alert 43 | ); 44 | }); 45 | } 46 | }); 47 | } else if (response.status === 200) { 48 | response.json().then(function (object) { 49 | if (object.success) { 50 | $('#results').html( 51 | success_template 52 | ); 53 | } 54 | }); 55 | } 56 | }); 57 | }); 58 | }); -------------------------------------------------------------------------------- /stormctf/static/js/style.js: -------------------------------------------------------------------------------- 1 | $(".form-control").bind({ 2 | focus: function() { 3 | $(this).removeClass('input-filled-invalid'); 4 | $(this).addClass('input-filled-valid' ); 5 | }, 6 | blur: function() { 7 | if ($(this).val() === '') { 8 | $(this).removeClass('input-filled-invalid'); 9 | $(this).removeClass('input-filled-valid'); 10 | } 11 | } 12 | }); 13 | 14 | $(function () { 15 | $('.form-control').each(function () { 16 | if ($(this).val()) { 17 | $(this).addClass("input-filled-valid"); 18 | } 19 | }); 20 | 21 | $('[data-toggle="tooltip"]').tooltip(); 22 | }); 23 | -------------------------------------------------------------------------------- /stormctf/static/js/team.js: -------------------------------------------------------------------------------- 1 | 2 | function scoregraph() { 3 | var times = []; 4 | var scores = []; 5 | if (self) 6 | $.get(script_root + '/api/v1/teams/' + team_account_id + '/solves', function (solve_data) { 7 | $.get(script_root + '/api/v1/teams/' + team_account_id + '/awards', function (award_data) { 8 | var solves = solve_data.data; 9 | var awards = award_data.data; 10 | 11 | var total = solves.concat(awards); 12 | 13 | total.sort(function (a, b) { 14 | return new Date(a.date) - new Date(b.date); 15 | }); 16 | 17 | for (var i = 0; i < total.length; i++) { 18 | var date = moment(total[i].date); 19 | times.push(date.toDate()); 20 | try { 21 | scores.push(total[i].challenge.value); 22 | } catch (e) { 23 | scores.push(total[i].value); 24 | } 25 | } 26 | scores = cumulativesum(scores); 27 | 28 | var data = [ 29 | { 30 | x: times, 31 | y: scores, 32 | type: 'scatter', 33 | marker: { 34 | color: colorhash(team_name + team_id), 35 | }, 36 | line: { 37 | color: colorhash(team_name + team_id), 38 | }, 39 | fill: 'tozeroy' 40 | } 41 | ]; 42 | 43 | var layout = { 44 | title: 'Score over Time', 45 | paper_bgcolor: 'rgba(0,0,0,0)', 46 | plot_bgcolor: 'rgba(0,0,0,0)', 47 | hovermode: 'closest', 48 | xaxis: { 49 | showgrid: false, 50 | showspikes: true, 51 | }, 52 | yaxis: { 53 | showgrid: false, 54 | showspikes: true, 55 | }, 56 | legend: { 57 | "orientation": "h" 58 | } 59 | }; 60 | 61 | $('#score-graph').empty(); 62 | document.getElementById('score-graph').fn = 'CTFd_score_team_' + team_id + '_' + (new Date).toISOString().slice(0, 19); 63 | Plotly.newPlot('score-graph', data, layout); 64 | }); 65 | }); 66 | } 67 | 68 | function keys_percentage_graph() { 69 | var base_url = script_root + '/api/v1/teams/' + team_account_id; 70 | $.get(base_url + '/fails', function (fails) { 71 | $.get(base_url + '/solves', function (solves) { 72 | var solves_count = solves.data.length; 73 | var fails_count = fails.meta.count; 74 | 75 | var graph_data = [{ 76 | values: [solves_count, fails_count], 77 | labels: ['Solves', 'Fails'], 78 | marker: { 79 | colors: [ 80 | "rgb(0, 209, 64)", 81 | "rgb(207, 38, 0)" 82 | ] 83 | }, 84 | hole: .4, 85 | type: 'pie' 86 | }]; 87 | 88 | var layout = { 89 | title: 'Solve Percentages', 90 | paper_bgcolor: 'rgba(0,0,0,0)', 91 | plot_bgcolor: 'rgba(0,0,0,0)', 92 | legend: { 93 | "orientation": "h" 94 | } 95 | }; 96 | 97 | $('#keys-pie-graph').empty(); 98 | document.getElementById('keys-pie-graph').fn = 'CTFd_submissions_team_' + team_id + '_' + (new Date).toISOString().slice(0, 19); 99 | Plotly.newPlot('keys-pie-graph', graph_data, layout); 100 | }); 101 | }); 102 | } 103 | 104 | function category_breakdown_graph() { 105 | // TODO: This graph isn't taking awards into account 106 | // This should be based off of value instead of count. 107 | $.get(script_root + '/api/v1/teams/' + team_account_id + '/solves', function (response) { 108 | var solves = response.data; 109 | 110 | var categories = []; 111 | for (var i = 0; i < solves.length; i++) { 112 | categories.push(solves[i].challenge.category) 113 | } 114 | 115 | var keys = categories.filter(function (elem, pos) { 116 | return categories.indexOf(elem) == pos; 117 | }); 118 | 119 | var counts = []; 120 | for (var i = 0; i < keys.length; i++) { 121 | var count = 0; 122 | for (var x = 0; x < categories.length; x++) { 123 | if (categories[x] == keys[i]) { 124 | count++; 125 | } 126 | } 127 | counts.push(count) 128 | } 129 | 130 | var data = [{ 131 | values: counts, 132 | labels: keys, 133 | hole: .4, 134 | type: 'pie' 135 | }]; 136 | 137 | var layout = { 138 | title: 'Category Breakdown', 139 | paper_bgcolor: 'rgba(0,0,0,0)', 140 | plot_bgcolor: 'rgba(0,0,0,0)', 141 | legend: { 142 | "orientation": "v" 143 | } 144 | }; 145 | 146 | $('#categories-pie-graph').empty(); 147 | document.getElementById('categories-pie-graph').fn = 'CTFd_categories_team_' +team_id + '_' + (new Date).toISOString().slice(0,19); 148 | Plotly.newPlot('categories-pie-graph', data, layout); 149 | }); 150 | } 151 | 152 | category_breakdown_graph(); 153 | keys_percentage_graph(); 154 | scoregraph(); 155 | 156 | 157 | window.onresize = function () { 158 | Plotly.Plots.resize(document.getElementById('keys-pie-graph')); 159 | Plotly.Plots.resize(document.getElementById('categories-pie-graph')); 160 | Plotly.Plots.resize(document.getElementById('score-graph')); 161 | }; 162 | -------------------------------------------------------------------------------- /stormctf/static/js/user.js: -------------------------------------------------------------------------------- 1 | 2 | function scoregraph() { 3 | var times = []; 4 | var scores = []; 5 | $.get(script_root + '/api/v1/users/' + user_account_id + '/solves', function (solve_data) { 6 | $.get(script_root + '/api/v1/users/' + user_account_id + '/awards', function (award_data) { 7 | var solves = solve_data.data; 8 | var awards = award_data.data; 9 | 10 | var total = solves.concat(awards); 11 | 12 | total.sort(function (a, b) { 13 | return new Date(a.date) - new Date(b.date); 14 | }); 15 | 16 | for (var i = 0; i < total.length; i++) { 17 | var date = moment(total[i].date); 18 | times.push(date.toDate()); 19 | try { 20 | scores.push(total[i].challenge.value); 21 | } catch (e) { 22 | scores.push(total[i].value); 23 | } 24 | } 25 | 26 | scores = cumulativesum(scores); 27 | 28 | var data = [ 29 | { 30 | x: times, 31 | y: scores, 32 | type: 'scatter', 33 | marker: { 34 | color: colorhash(user_name + user_id), 35 | }, 36 | line: { 37 | color: colorhash(user_name + user_id), 38 | }, 39 | fill: 'tozeroy' 40 | } 41 | ]; 42 | 43 | var layout = { 44 | title: 'Score over Time', 45 | paper_bgcolor: 'rgba(0,0,0,0)', 46 | plot_bgcolor: 'rgba(0,0,0,0)', 47 | hovermode: 'closest', 48 | xaxis: { 49 | showgrid: false, 50 | showspikes: true, 51 | }, 52 | yaxis: { 53 | showgrid: false, 54 | showspikes: true, 55 | }, 56 | legend: { 57 | "orientation": "h" 58 | } 59 | }; 60 | 61 | $('#score-graph').empty(); 62 | document.getElementById('score-graph').fn = 'CTFd_score_user_' + user_id + '_' + (new Date).toISOString().slice(0, 19); 63 | Plotly.newPlot('score-graph', data, layout); 64 | }); 65 | }); 66 | } 67 | 68 | function keys_percentage_graph() { 69 | // Solves and Fails pie chart 70 | var base_url = script_root + '/api/v1/users/' + user_account_id; 71 | $.get(base_url + '/fails', function (fails) { 72 | $.get(base_url + '/solves', function(solves) { 73 | var solves_count = solves.data.length; 74 | var fails_count = fails.meta.count; 75 | 76 | var graph_data = [{ 77 | values: [solves_count, fails_count], 78 | labels: ['Solves', 'Fails'], 79 | marker: { 80 | colors: [ 81 | "rgb(0, 209, 64)", 82 | "rgb(207, 38, 0)" 83 | ] 84 | }, 85 | hole: .4, 86 | type: 'pie' 87 | }]; 88 | 89 | var layout = { 90 | title: 'Solve Percentages', 91 | paper_bgcolor: 'rgba(0,0,0,0)', 92 | plot_bgcolor: 'rgba(0,0,0,0)', 93 | legend: { 94 | "orientation": "h" 95 | } 96 | }; 97 | 98 | $('#keys-pie-graph').empty(); 99 | document.getElementById('keys-pie-graph').fn = 'CTFd_submissions_user_' + user_id + '_' + (new Date).toISOString().slice(0, 19); 100 | Plotly.newPlot('keys-pie-graph', graph_data, layout); 101 | }); 102 | }); 103 | } 104 | 105 | function category_breakdown_graph() { 106 | // TODO: This graph isn't taking awards into account 107 | // This should be based off of value instead of count. 108 | $.get(script_root + '/api/v1/users/' + user_account_id + '/solves', function (response) { 109 | var solves = response.data; 110 | 111 | var categories = []; 112 | for (var i = 0; i < solves.length; i++) { 113 | categories.push(solves[i].challenge.category) 114 | } 115 | 116 | var keys = categories.filter(function (elem, pos) { 117 | return categories.indexOf(elem) == pos; 118 | }); 119 | 120 | var counts = []; 121 | for (var i = 0; i < keys.length; i++) { 122 | var count = 0; 123 | for (var x = 0; x < categories.length; x++) { 124 | if (categories[x] == keys[i]) { 125 | count++; 126 | } 127 | } 128 | counts.push(count) 129 | } 130 | 131 | var data = [{ 132 | values: counts, 133 | labels: keys, 134 | hole: .4, 135 | type: 'pie' 136 | }]; 137 | 138 | var layout = { 139 | title: 'Category Breakdown', 140 | paper_bgcolor: 'rgba(0,0,0,0)', 141 | plot_bgcolor: 'rgba(0,0,0,0)', 142 | legend: { 143 | "orientation": "v" 144 | } 145 | }; 146 | 147 | $('#categories-pie-graph').empty(); 148 | document.getElementById('categories-pie-graph').fn = 'CTFd_categories_team_' + user_id + '_' + (new Date).toISOString().slice(0, 19); 149 | Plotly.newPlot('categories-pie-graph', data, layout); 150 | }); 151 | } 152 | 153 | category_breakdown_graph(); 154 | keys_percentage_graph(); 155 | scoregraph(); 156 | 157 | window.onresize = function () { 158 | Plotly.Plots.resize(document.getElementById('keys-pie-graph')); 159 | Plotly.Plots.resize(document.getElementById('categories-pie-graph')); 160 | Plotly.Plots.resize(document.getElementById('score-graph')); 161 | }; 162 | -------------------------------------------------------------------------------- /stormctf/static/js/utils.js: -------------------------------------------------------------------------------- 1 | //http://stackoverflow.com/a/1186309 2 | $.fn.serializeObject = function() 3 | { 4 | var o = {}; 5 | var a = this.serializeArray(); 6 | $.each(a, function() { 7 | if (o[this.name] !== undefined) { 8 | if (!o[this.name].push) { 9 | o[this.name] = [o[this.name]]; 10 | } 11 | o[this.name].push(this.value || ''); 12 | } else { 13 | o[this.name] = this.value || ''; 14 | } 15 | }); 16 | return o; 17 | }; 18 | 19 | $.fn.serializeJSON = function (omit_nulls) { 20 | var params = {}; 21 | var form = $(this); 22 | var values = form.serializeArray(); 23 | 24 | values = values.concat( 25 | form.find('input[type=checkbox]:checked').map( 26 | function () { 27 | return {"name": this.name, "value": true} 28 | }).get() 29 | ); 30 | values = values.concat( 31 | form.find('input[type=checkbox]:not(:checked)').map( 32 | function () { 33 | return {"name": this.name, "value": false} 34 | }).get() 35 | ); 36 | values.map(function (x) { 37 | if (omit_nulls) { 38 | if (x.value !== null && x.value !== "") { 39 | params[x.name] = x.value; 40 | } 41 | } else { 42 | params[x.name] = x.value; 43 | } 44 | }); 45 | return params; 46 | }; 47 | 48 | //http://stackoverflow.com/a/2648463 - wizardry! 49 | String.prototype.format = String.prototype.f = function() { 50 | var s = this, 51 | i = arguments.length; 52 | 53 | while (i--) { 54 | s = s.replace(new RegExp('\\{' + i + '\\}', 'gm'), arguments[i]); 55 | } 56 | return s; 57 | }; 58 | 59 | //http://stackoverflow.com/a/7616484 60 | String.prototype.hashCode = function() { 61 | var hash = 0, i, chr, len; 62 | if (this.length == 0) return hash; 63 | for (i = 0, len = this.length; i < len; i++) { 64 | chr = this.charCodeAt(i); 65 | hash = ((hash << 5) - hash) + chr; 66 | hash |= 0; // Convert to 32bit integer 67 | } 68 | return hash; 69 | }; 70 | 71 | function colorhash(str) { 72 | var hash = 0; 73 | for (var i = 0; i < str.length; i++) { 74 | hash = str.charCodeAt(i) + ((hash << 5) - hash); 75 | } 76 | var colour = '#'; 77 | for (var i = 0; i < 3; i++) { 78 | var value = (hash >> (i * 8)) & 0xFF; 79 | colour += ('00' + value.toString(16)).substr(-2); 80 | } 81 | return colour; 82 | } 83 | 84 | function htmlentities(string) { 85 | return $('
').text(string).html(); 86 | } 87 | 88 | function cumulativesum(arr) { 89 | var result = arr.concat(); 90 | for (var i = 0; i < arr.length; i++) { 91 | result[i] = arr.slice(0, i + 1).reduce(function (p, i) { 92 | return p + i; 93 | }); 94 | } 95 | return result 96 | } 97 | 98 | // http://stepansuvorov.com/blog/2014/04/jquery-put-and-delete/ 99 | jQuery.each(["patch", "put", "delete"], function(i, method) { 100 | jQuery[method] = function(url, data, callback, type) { 101 | if (jQuery.isFunction(data)) { 102 | type = type || callback; 103 | callback = data; 104 | data = undefined; 105 | } 106 | 107 | return jQuery.ajax({ 108 | url: url, 109 | type: method, 110 | dataType: type, 111 | data: data, 112 | success: callback 113 | }); 114 | }; 115 | }); 116 | -------------------------------------------------------------------------------- /stormctf/static/js/vendor/eventsource.min.js: -------------------------------------------------------------------------------- 1 | /** @license 2 | * eventsource.js 3 | * Available under MIT License (MIT) 4 | * https://github.com/Yaffle/EventSource/ 5 | */ 6 | !function(a){"use strict";function b(){this.bitsNeeded=0,this.codePoint=0}function c(a){this.withCredentials=!1,this.responseType="",this.readyState=0,this.status=0,this.statusText="",this.responseText="",this.onprogress=E,this.onreadystatechange=E,this._contentType="",this._xhr=a,this._sendTimeout=0,this._abort=E}function d(a){return a.replace(/[A-Z]/g,function(a){return String.fromCharCode(a.charCodeAt(0)+32)})}function e(a){for(var b=Object.create(null),c=a.split("\r\n"),e=0;eQ&&f.charCodeAt(Q)===" ".charCodeAt(0)?1:0),h);"data"===j?(A+="\n",A+=k):"id"===j?B=k:"event"===j?C=k:"retry"===j?(g=R(k,g),p=g):"heartbeatTimeout"===j&&(i=R(k,i),0!==y&&(r(y),y=q(function(){Z()},i)))}if(E===K){if(""!==A){n=B,""===C&&(C="message");var m=new l(C,{data:A.slice(1),lastEventId:B});if(a.dispatchEvent(m),"message"===C&&T(a,a.onmessage,m),z===I)return}A="",C=""}E=e==="\r".charCodeAt(0)?J:K}else E===K&&(P=h,E=L),E===L?e===":".charCodeAt(0)&&(Q=h+1,E=M):E===M&&(E=N)}}},X=function(){if(z===H||z===G){z=F,0!==y&&(r(y),y=0),y=q(function(){Z()},p),p=S(Math.min(16*g,2*p)),a.readyState=G;var b=new k("error");a.dispatchEvent(b),T(a,a.onerror,b)}},Y=function(){z=I,void 0!=x&&(x(),x=void 0),0!==y&&(r(y),y=0),a.readyState=I},Z=function(){if(y=0,z!==F)return void(s||void 0==x?(s=!1,y=q(function(){Z()},i)):(j(new Error("No activity within "+i+" milliseconds. Reconnecting.")),x(),x=void 0));s=!1,y=q(function(){Z()},i),z=G,A="",C="",B=n,D="",P=0,Q=0,E=K;var a=b;"data:"!==b.slice(0,5)&&"blob:"!==b.slice(0,5)&&""!==n&&(a+=(-1===b.indexOf("?")?"?":"&")+"lastEventId="+encodeURIComponent(n));var c={};if(c.Accept="text/event-stream",void 0!=t)for(var d in t)Object.prototype.hasOwnProperty.call(t,d)&&(c[d]=t[d]);try{w.open(v,V,W,X,a,e,c)}catch(f){throw Y(),f}};a.url=b,a.readyState=G,a.withCredentials=e,a._close=Y,Z()}var q=a.setTimeout,r=a.clearTimeout,s=a.XMLHttpRequest,t=a.XDomainRequest,u=a.EventSource,v=a.document,w=a.Promise,x=a.fetch,y=a.Response,z=a.TextDecoder,A=a.TextEncoder,B=a.AbortController;if(void 0==Object.create&&(Object.create=function(a){function b(){}return b.prototype=a,new b}),void 0!=w&&void 0==w.prototype["finally"]&&(w.prototype["finally"]=function(a){return this.then(function(b){return w.resolve(a()).then(function(){return b})},function(b){return w.resolve(a()).then(function(){throw b})})}),void 0!=x){var C=x;x=function(a,b){return w.resolve(C(a,b))}}void 0==B&&(B=function(){this.signal=null,this.abort=function(){}}),b.prototype.decode=function(a){function b(a,b,c){if(1===c)return a>=128>>b&&2047>=a<=2048>>b&&55295>=a<=57344>>b&&65535>=a<=65536>>b&&1114111>=a<>6>15?3:b>31?2:1;if(12===a)return b>15?3:2;if(18===a)return 3;throw new Error}for(var d=65533,e="",f=this.bitsNeeded,g=this.codePoint,h=0;hi||i>191||!b(g<<6|63&i,f-6,c(f,g)))&&(f=0,g=d,e+=String.fromCharCode(g)),0===f?(i>=0&&127>=i?(f=0,g=i):i>=192&&223>=i?(f=6,g=31&i):i>=224&&239>=i?(f=12,g=15&i):i>=240&&247>=i?(f=18,g=7&i):(f=0,g=d),0===f||b(g,f,c(f,g))||(f=0,g=d)):(f-=6,g=g<<6|63&i),0===f&&(65535>=g?e+=String.fromCharCode(g):(e+=String.fromCharCode(55296+(g-65535-1>>10)),e+=String.fromCharCode(56320+(g-65535-1&1023))))}return this.bitsNeeded=f,this.codePoint=g,e};var D=function(){try{return"test"===(new z).decode((new A).encode("test"),{stream:!0})}catch(a){}return!1};void 0!=z&&void 0!=A&&D()||(z=b);var E=function(){};c.prototype.open=function(a,b){this._abort(!0);var c=this,d=this._xhr,e=1,f=0;this._abort=function(a){0!==c._sendTimeout&&(r(c._sendTimeout),c._sendTimeout=0),(1===e||2===e||3===e)&&(e=4,d.onload=E,d.onerror=E,d.onabort=E,d.onprogress=E,d.onreadystatechange=E,d.abort(),0!==f&&(r(f),f=0),a||(c.readyState=4,c.onreadystatechange())),e=0};var g=function(){if(1===e){var a=0,b="",f=void 0;if("contentType"in d)a=200,b="OK",f=d.contentType;else try{a=d.status,b=d.statusText,f=d.getResponseHeader("Content-Type")}catch(g){a=0,b="",f=void 0}0!==a&&(e=2,c.readyState=2,c.status=a,c.statusText=b,c._contentType=f,c.onreadystatechange())}},h=function(){if(g(),2===e||3===e){e=3;var a="";try{a=d.responseText}catch(b){}c.readyState=3,c.responseText=a,c.onprogress()}},i=function(){h(),(1===e||2===e||3===e)&&(e=4,0!==f&&(r(f),f=0),c.readyState=4,c.onreadystatechange())},j=function(){void 0!=d&&(4===d.readyState?i():3===d.readyState?h():2===d.readyState&&g())},k=function(){f=q(function(){k()},500),3===d.readyState&&h()};d.onload=i,d.onerror=i,d.onabort=i,"sendAsBinary"in s.prototype||"mozAnon"in s.prototype||(d.onprogress=h),d.onreadystatechange=j,"contentType"in d&&(b+=(-1===b.indexOf("?")?"?":"&")+"padding=true"),d.open(a,b,!0),"readyState"in d&&(f=q(function(){k()},0))},c.prototype.abort=function(){this._abort(!1)},c.prototype.getResponseHeader=function(a){return this._contentType},c.prototype.setRequestHeader=function(a,b){var c=this._xhr;"setRequestHeader"in c&&c.setRequestHeader(a,b)},c.prototype.getAllResponseHeaders=function(){return void 0!=this._xhr.getAllResponseHeaders?this._xhr.getAllResponseHeaders():""},c.prototype.send=function(){if(!("ontimeout"in s.prototype)&&void 0!=v&&void 0!=v.readyState&&"complete"!==v.readyState){var a=this;return void(a._sendTimeout=q(function(){a._sendTimeout=0,a.send()},4))}var b=this._xhr;b.withCredentials=this.withCredentials,b.responseType=this.responseType;try{b.send(void 0)}catch(c){throw c}},e.prototype.get=function(a){return this._map[d(a)]},f.prototype.open=function(a,b,c,d,f,g,h){a.open("GET",f);var i=0;a.onprogress=function(){var b=a.responseText,d=b.slice(i);i+=d.length,c(d)},a.onreadystatechange=function(){if(2===a.readyState){var c=a.status,f=a.statusText,g=a.getResponseHeader("Content-Type"),h=a.getAllResponseHeaders();b(c,f,g,new e(h),function(){a.abort()})}else 4===a.readyState&&d()},a.withCredentials=g,a.responseType="text";for(var j in h)Object.prototype.hasOwnProperty.call(h,j)&&a.setRequestHeader(j,h[j]);a.send()},g.prototype.get=function(a){return this._headers.get(a)},h.prototype.open=function(a,b,c,d,e,f,h){var i=new B,j=i.signal,k=new z;x(e,{headers:h,credentials:f?"include":"same-origin",signal:j,cache:"no-store"}).then(function(a){var d=a.body.getReader();return b(a.status,a.statusText,a.headers.get("Content-Type"),new g(a.headers),function(){i.abort(),d.cancel()}),new w(function(a,b){var e=function(){d.read().then(function(b){if(b.done)a(void 0);else{var d=k.decode(b.value,{stream:!0});c(d),e()}})["catch"](function(a){b(a)})};e()})})["finally"](function(){d()})},i.prototype.dispatchEvent=function(a){a.target=this;var b=this._listeners[a.type];if(void 0!=b)for(var c=b.length,d=0;c>d;d+=1){var e=b[d];try{"function"==typeof e.handleEvent?e.handleEvent(a):e.call(this,a)}catch(f){j(f)}}},i.prototype.addEventListener=function(a,b){a=String(a);var c=this._listeners,d=c[a];void 0==d&&(d=[],c[a]=d);for(var e=!1,f=0;f-1;};}function f(a){if(typeof a!=='string')a=String(a);if(/[^a-z0-9\-#$%&'*+.^_`|~]/i.test(a))throw new TypeError('Invalid character in header field name');return a.toLowerCase();}function g(a){if(typeof a!=='string')a=String(a);return a;}function h(a){var c={next:function(){var b=a.shift();return{done:b===undefined,value:b};}};if(b.iterable)c[Symbol.iterator]=function(){return c;};return c;}function i(a){this.map={};if(a instanceof i)a.forEach(function(a,b){this.append(b,a);},this);else if(Array.isArray(a))a.forEach(function(a){this.append(a[0],a[1]);},this);else if(a)Object.getOwnPropertyNames(a).forEach(function(b){this.append(b,a[b]);},this);}i.prototype.append=function(a,b){a=f(a);b=g(b);var c=this.map[a];this.map[a]=c?c+', '+b:b;};i.prototype['delete']=function(a){delete this.map[f(a)];};i.prototype.get=function(a){a=f(a);return this.has(a)?this.map[a]:null;};i.prototype.has=function(a){return this.map.hasOwnProperty(f(a));};i.prototype.set=function(a,b){this.map[f(a)]=g(b);};i.prototype.forEach=function(a,b){for(var c in this.map)if(this.map.hasOwnProperty(c))a.call(b,this.map[c],c,this);};i.prototype.keys=function(){var a=[];this.forEach(function(b,c){a.push(c);});return h(a);};i.prototype.values=function(){var a=[];this.forEach(function(b){a.push(b);});return h(a);};i.prototype.entries=function(){var a=[];this.forEach(function(b,c){a.push([c,b]);});return h(a);};if(b.iterable)i.prototype[Symbol.iterator]=i.prototype.entries;function j(a){if(a.bodyUsed)return Promise.reject(new TypeError('Already read'));a.bodyUsed=true;}function k(a){return new Promise(function(b,c){a.onload=function(){b(a.result);};a.onerror=function(){c(a.error);};});}function l(a){var b=new FileReader();var c=k(b);b.readAsArrayBuffer(a);return c;}function m(a){var b=new FileReader();var c=k(b);b.readAsText(a);return c;}function n(a){var b=new Uint8Array(a);var c=new Array(b.length);for(var d=0;d-1?b:a;}function s(a,b){b=b||{};var c=b.body;if(a instanceof s){if(a.bodyUsed)throw new TypeError('Already read');this.url=a.url;this.credentials=a.credentials;if(!b.headers)this.headers=new i(a.headers);this.method=a.method;this.mode=a.mode;this.signal=a.signal;if(!c&&a._bodyInit!=null){c=a._bodyInit;a.bodyUsed=true;}}else this.url=String(a);this.credentials=b.credentials||this.credentials||'same-origin';if(b.headers||!this.headers)this.headers=new i(b.headers);this.method=r(b.method||this.method||'GET');this.mode=b.mode||this.mode||null;this.signal=b.signal||this.signal;this.referrer=null;if((this.method==='GET'||this.method==='HEAD')&&c)throw new TypeError('Body not allowed for GET or HEAD requests');this._initBody(c);}s.prototype.clone=function(){return new s(this,{body:this._bodyInit});};function t(a){var b=new FormData();a.trim().split('&').forEach(function(a){if(a){var c=a.split('=');var d=c.shift().replace(/\+/g,' ');var e=c.join('=').replace(/\+/g,' ');b.append(decodeURIComponent(d),decodeURIComponent(e));}});return b;}function u(a){var b=new i();var c=a.replace(/\r?\n[\t ]+/g,' ');c.split(/\r?\n/).forEach(function(a){var c=a.split(':');var d=c.shift().trim();if(d){var e=c.join(':').trim();b.append(d,e);}});return b;}p.call(s.prototype);function v(a,b){if(!b)b={};this.type='default';this.status=b.status===undefined?200:b.status;this.ok=this.status>=200&&this.status<300;this.statusText='statusText' in b?b.statusText:'OK';this.headers=new i(b.headers);this.url=b.url||'';this._initBody(a);}p.call(v.prototype);v.prototype.clone=function(){return new v(this._bodyInit,{status:this.status,statusText:this.statusText,headers:new i(this.headers),url:this.url});};v.error=function(){var a=new v(null,{status:0,statusText:''});a.type='error';return a;};var w=[301,302,303,307,308];v.redirect=function(a,b){if(w.indexOf(b)===-1)throw new RangeError('Invalid status code');return new v(null,{status:b,headers:{location:a}});};a.DOMException=self.DOMException;try{new a.DOMException();}catch(x){a.DOMException=function(a,b){this.message=a;this.name=b;var c=Error(a);this.stack=c.stack;};a.DOMException.prototype=Object.create(Error.prototype);a.DOMException.prototype.constructor=a.DOMException;}function y(c,d){return new Promise(function(e,f){var g=new s(c,d);if(g.signal&&g.signal.aborted)return f(new a.DOMException('Aborted','AbortError'));var h=new XMLHttpRequest();function i(){h.abort();}h.onload=function(){var a={status:h.status,statusText:h.statusText,headers:u(h.getAllResponseHeaders()||'')};a.url='responseURL' in h?h.responseURL:a.headers.get('X-Request-URL');var b='response' in h?h.response:h.responseText;e(new v(b,a));};h.onerror=function(){f(new TypeError('Network request failed'));};h.ontimeout=function(){f(new TypeError('Network request failed'));};h.onabort=function(){f(new a.DOMException('Aborted','AbortError'));};h.open(g.method,g.url,true);if(g.credentials==='include')h.withCredentials=true;else if(g.credentials==='omit')h.withCredentials=false;if('responseType' in h&&b.blob)h.responseType='blob';g.headers.forEach(function(a,b){h.setRequestHeader(b,a);});if(g.signal){g.signal.addEventListener('abort',i);h.onreadystatechange=function(){if(h.readyState===4)g.signal.removeEventListener('abort',i);};}h.send(typeof g._bodyInit==='undefined'?null:g._bodyInit);});}y.polyfill=true;if(!self.fetch){self.fetch=y;self.Headers=i;self.Request=s;self.Response=v;}a.Headers=i;a.Request=s;a.Response=v;a.fetch=y;Object.defineProperty(a,'__esModule',{value:true});}))); -------------------------------------------------------------------------------- /stormctf/static/js/vendor/promise-polyfill.min.js: -------------------------------------------------------------------------------- 1 | !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n():"function"==typeof define&&define.amd?define(n):n()}(0,function(){"use strict";function e(n){var t=this.constructor;return this.then(function(e){return t.resolve(n()).then(function(){return e})},function(e){return t.resolve(n()).then(function(){return t.reject(e)})})}var n=setTimeout;function o(){}function f(e){if(!(this instanceof f))throw new TypeError("Promises must be constructed via new");if("function"!=typeof e)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=undefined,this._deferreds=[],l(e,this)}function r(o,r){for(;3===o._state;)o=o._value;0!==o._state?(o._handled=!0,f._immediateFn(function(){var e=1===o._state?r.onFulfilled:r.onRejected;if(null!==e){var n;try{n=e(o._value)}catch(t){return void u(r.promise,t)}i(r.promise,n)}else(1===o._state?i:u)(r.promise,o._value)})):o._deferreds.push(r)}function i(e,n){try{if(n===e)throw new TypeError("A promise cannot be resolved with itself.");if(n&&("object"==typeof n||"function"==typeof n)){var t=n.then;if(n instanceof f)return e._state=3,e._value=n,void c(e);if("function"==typeof t)return void l((o=t,r=n,function(){o.apply(r,arguments)}),e)}e._state=1,e._value=n,c(e)}catch(i){u(e,i)}var o,r}function u(e,n){e._state=2,e._value=n,c(e)}function c(e){2===e._state&&0===e._deferreds.length&&f._immediateFn(function(){e._handled||f._unhandledRejectionFn(e._value)});for(var n=0,t=e._deferreds.length;n --> 5 | {% endblock %} 6 | 7 | {% block content %} 8 | 9 |
10 |
11 |
12 |

Challenges

13 |
14 |
15 |
16 | 17 | {% if infos %} 18 |
19 |
20 |
21 | {% for info in infos %} 22 |
23 | 24 |

{{ info }}

25 |
26 | {% endfor %} 27 |
28 |
29 |
30 | {% endif %} 31 | 32 | {% if errors %} 33 |
34 |
35 |
36 | {% for error in errors %} 37 |
38 | 39 |

{{ error }}

40 |
41 | {% endfor %} 42 |
43 |
44 |
45 | {% endif %} 46 | 47 | {% if admin or not errors %} 48 | 49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | 57 |
58 |
59 |
60 |
61 | 62 | 63 | 75 | {% endif %} 76 | {% endblock %} 77 | 78 | {% block scripts %} 79 | 82 | 83 | 84 | {% if admin or not errors %} 85 | 86 | 87 | {% endif %} 88 | 89 | {% endblock %} 90 | -------------------------------------------------------------------------------- /stormctf/templates/confirm.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block stylesheets %} 3 | {% endblock %} 4 | {% block content %} 5 |
6 |
7 |
8 |

Email Confirmation

9 |
10 |
11 |
12 | {% if infos %} 13 |
14 |
15 |
16 | {% for info in infos %} 17 |
18 | 19 |

{{ info }}

20 |
21 | {% endfor %} 22 |
23 |
24 |
25 | {% endif %} {% if errors %} 26 |
27 |
28 |
29 | {% for error in errors %} 30 |
31 | 32 |

{{ error }}

33 |
34 | {% endfor %} 35 |
36 |
37 |
38 | {% endif %} 39 |
40 |
41 | {% if user %} 42 |

We've sent a confirmation email to {{ user.email }}

43 |

44 | Please click the link in that email to confirm your account. 45 |

46 | {% endif %} 47 |
48 | {% if name %} 49 |
50 |

51 | Need to resend the confirmation email? 52 |

53 |
54 | 55 |
56 | 57 |
58 | {% endif %} 59 |
60 |
61 | {% endblock %} 62 | {% block scripts %} 63 | 64 | 71 | {% endblock %} -------------------------------------------------------------------------------- /stormctf/templates/errors/403.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block content %} 3 |
4 |
5 |

403

6 |

Forbidden

7 |

{{ error }}

8 |
9 |
10 | {% endblock %} 11 | {% block scripts %} 12 | {% endblock %} -------------------------------------------------------------------------------- /stormctf/templates/errors/404.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block content %} 3 |
4 |
5 |

404

6 |

Whoops, looks like we can't find that.

7 |

Sorry about that

8 |
9 |
10 | {% endblock %} 11 | {% block scripts %} 12 | {% endblock %} -------------------------------------------------------------------------------- /stormctf/templates/errors/429.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block content %} 3 |
4 |
5 |

429

6 |

Too many requests

7 |

Please slow down!

8 |
9 |
10 | {% endblock %} 11 | {% block scripts %} 12 | {% endblock %} -------------------------------------------------------------------------------- /stormctf/templates/errors/500.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block content %} 3 |
4 |
5 |

500

6 |

An Internal Server Error has occurred

7 |
8 |
9 | {% endblock %} 10 | {% block scripts %} 11 | {% endblock %} -------------------------------------------------------------------------------- /stormctf/templates/errors/502.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block content %} 3 |
4 |
5 |

502

6 |

Bad Gateway

7 |
8 |
9 | {% endblock %} 10 | {% block scripts %} 11 | {% endblock %} -------------------------------------------------------------------------------- /stormctf/templates/login.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block stylesheets %} 3 | {% endblock %} 4 | {% block content %} 5 |
6 |
7 |

Login

8 |
9 |
10 | {% if errors %} 11 |
12 |
13 |
14 | {% for error in errors %} 15 |
16 | 17 |

{{ error }}

18 |
19 | {% endfor %} 20 |
21 |
22 |
23 | {% endif %} 24 |
25 | 26 | 33 |
34 |
35 |
36 |
37 |
38 |
39 | 40 | 41 |
42 |
43 |
44 |
45 | 46 | 47 |
48 |
49 |
50 | 51 |
52 | 53 |
54 |
55 |
56 | 59 |
60 |
61 | {% endblock %} 62 | {% block scripts %} 63 | 70 | {% endblock %} -------------------------------------------------------------------------------- /stormctf/templates/notifications.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block content %} 3 |
4 |
5 |
6 |

Notifications

7 |
8 |
9 |
10 |
11 |
12 | {% if notifications %} 13 | {% for notification in notifications %} 14 |
15 |
16 |

{{ notification.title }}

17 |
18 |

{{ notification.content | safe }}

19 | 22 |
23 |
24 |
25 | {% endfor %} 26 | {% else %} 27 |

No Notifications Yet

28 | {% endif %} 29 |
30 |
31 | {% endblock %} 32 | {% block scripts %} 33 | 34 | 35 | {% endblock %} -------------------------------------------------------------------------------- /stormctf/templates/page.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block content %} 3 |
4 |
5 | {{ content | safe }} 6 |
7 |
8 | {% endblock %} -------------------------------------------------------------------------------- /stormctf/templates/register.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block stylesheets %} 3 | {% endblock %} 4 | {% block content %} 5 |
6 |
7 |

Register

8 |
9 |
10 | {% if errors %} 11 |
12 |
13 |
14 | {% for error in errors %} 15 |
16 | 17 |

{{ error }}

18 |
19 | {% endfor %} 20 |
21 |
22 |
23 | {% endif %} 24 |
25 | 26 | 33 |
34 |
35 |
36 |
37 |
38 |
39 | 40 | 41 |
42 |
43 |
44 |
45 | 46 | 47 |
48 |
49 |
50 |
51 | 52 | 53 |
54 |
55 |
56 | 57 |
58 | 59 |
60 |
61 |
62 | 65 |
66 |
67 | {% endblock %} 68 | {% block scripts %} 69 | 76 | {% endblock %} -------------------------------------------------------------------------------- /stormctf/templates/reset_password.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} {% block stylesheets %} {% endblock %} {% block content %} 2 |
3 |
4 |

Reset Password

5 |
6 |
7 | {% if errors %} 8 |
9 |
10 |
11 | {% for error in errors %} 12 |
13 | 14 |

{{ error }}

15 |
16 | {% endfor %} 17 |
18 |
19 |
20 | {% endif %} 21 |
22 |
23 |
24 | {% if can_send_mail() %} 25 |
26 |
27 | {% if mode %} 28 |
29 |
30 | 31 | 32 |
33 |
34 | {% else %} 35 |
36 |
37 | 38 | 39 |
40 |
41 | {% endif %} 42 |
43 | 44 |
45 | 46 |
47 |
48 | {% else %} 49 |
50 |

Contact a CTF organizer

51 |

This CTF is not configured to send email.

52 |

Please contact an organizer to have your password reset

53 |
54 | {% endif %} 55 |
56 |
57 |
58 | {% endblock %} {% block scripts %} 59 | 60 | {% endblock %} -------------------------------------------------------------------------------- /stormctf/templates/scoreboard.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block content %} 3 |
4 |
5 |

Scoreboard

6 |
7 |
8 | {% if errors %} 9 |
10 |
11 |
12 | {% for error in errors %} 13 |
14 | 15 |

{{ error }}

16 |
17 | {% endfor %} 18 |
19 |
20 |
21 | {% else %} 22 | {% if score_frozen %} 23 |
24 |
25 |
26 |

Scoreboard has been frozen.

27 |
28 |
29 |
30 | {% endif %} 31 | {% endif %} 32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | {% if standings %} 42 |
43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | {% for standing in standings %} 53 | 54 | 55 | 71 | 72 | 73 | {% endfor %} 74 | 75 |
PlaceTeamScore
{{ loop.index }} 56 | 57 | {{ standing.name | truncate(50) }} 58 | {% if standing.oauth_id %} 59 | {% if get_config('user_mode') == 'teams' %} 60 | 61 | Official 62 | 63 | {% elif get_config('user_mode') == 'users' %} 64 | 65 | Official 66 | 67 | {% endif %} 68 | {% endif %} 69 | 70 | {{ standing.score }}
76 |
77 |
78 | {% endif %} 79 |
80 | {% endblock %} 81 | {% block scripts %} 82 | 83 | 84 | 85 | {% endblock %} -------------------------------------------------------------------------------- /stormctf/templates/settings.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block stylesheets %} 3 | {% endblock %} 4 | {% block content %} 5 |
6 |
7 |

Settings

8 |
9 |
10 |
11 |
12 | {% if confirm_email %} 13 |
14 | Your email address isn't confirmed! Please check your email to confirm your email address. 15 |
16 |
To have the confirmation email resent please click 17 | here. 18 |
19 | {% endif %} 20 |
21 |
22 |
23 |
24 | 27 | 28 |
29 |
30 | 33 | 34 |
35 |
36 |
37 | 38 |
39 |
40 | 41 |
42 |
43 |
44 | 47 | 48 |
49 |
50 | 53 | 54 |
55 |
56 | 59 | 66 |
67 |
68 |
69 | 70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | {% endblock %} 78 | {% block scripts %} 79 | 80 | 81 | {% endblock %} -------------------------------------------------------------------------------- /stormctf/templates/setup.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block stylesheets %} 4 | {% endblock %} 5 | 6 | {% block content %} 7 |
8 |
9 |

Setup

10 |
11 |
12 |
13 |
14 |

CTF Settings

15 | {% for error in errors %} 16 |
17 | 23 |
24 | {% endfor %} 25 |
26 | 27 | {# This nonce is implemented specially in the route itself #} 28 |
29 | 35 | 36 |
37 |
38 | 44 | 45 |
46 |
47 | 53 | 54 |
55 |
56 | 62 | 63 |
64 |
65 | 73 | 77 |
78 |
79 |
80 | 82 |
83 |
84 |
85 |
86 | 87 | {% endblock %} 88 | 89 | {% block scripts %} 90 | 91 | {% endblock %} 92 | -------------------------------------------------------------------------------- /stormctf/templates/teams/join_team.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block stylesheets %} 3 | {% endblock %} 4 | {% block content %} 5 |
6 |
7 |
8 |

Join Team

9 |
10 |
11 |
12 | {% if errors %} 13 |
14 |
15 |
16 | {% for error in errors %} 17 |
18 | 19 |

{{ error }}

20 |
21 | {% endfor %} 22 |
23 |
24 |
25 | {% endif %} 26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | 34 | 35 |
36 |
37 |
38 |
39 | 40 | 41 |
42 |
43 |
44 | 45 |
46 | 47 |
48 |
49 |
50 |
51 |
52 | {% endblock %} 53 | {% block scripts %} 54 | 61 | {% endblock %} -------------------------------------------------------------------------------- /stormctf/templates/teams/new_team.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block stylesheets %} 3 | {% endblock %} 4 | {% block content %} 5 |
6 |
7 |
8 |

Create Team

9 |
10 |
11 |
12 | {% if errors %} 13 |
14 |
15 |
16 | {% for error in errors %} 17 |
18 | 19 |

{{ error }}

20 |
21 | {% endfor %} 22 |
23 |
24 |
25 | {% endif %} 26 |
27 |
28 |

After creating your team, share the team name and password with your teammates so they can join your team!

29 |
30 |
31 |
32 |
33 |
34 | 35 | 36 |
37 |
38 |
39 |
40 | 41 | 42 |
43 |
44 |
45 | 46 |
47 | 48 |
49 |
50 |
51 |
52 |
53 | {% endblock %} 54 | {% block scripts %} 55 | 62 | {% endblock %} -------------------------------------------------------------------------------- /stormctf/templates/teams/public.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block stylesheets %} 3 | {% endblock %} 4 | {% block content %} 5 |
6 |
7 |

{{ team.name }}

8 | {% if team.oauth_id %} 9 | 10 |

Official

11 |
12 | {% endif %} 13 | {% if team.affiliation %} 14 |

{{ team.affiliation }}

15 | {% endif %} 16 |
17 |

18 | {# This intentionally hides the team's place because this can be their internal profile. #} 19 | {# Public page hiding is done at the route level #} 20 | {% if scores_visible() %} 21 | {% if team.place != 0 %} 22 | {{ team.place }} 23 | place 24 | {% endif %} 25 | {% endif %} 26 |

27 |

28 | {% if score %} 29 | {{ team.score }} 30 | points 31 | {% endif %} 32 |

33 |
34 |
35 | {% if team.website and (team.website.startswith('http://') or team.website.startswith('https://')) %} 36 | {{ team.website }} 37 | {% endif %} 38 |
39 |
40 |
41 | {% if errors %} 42 |
43 |
44 |
45 | {% for error in errors %} 46 |
47 | 48 |

{{ error }}

49 |
50 | {% endfor %} 51 |
52 |
53 |
54 | {% else %} {% if score_frozen %} 55 |
56 |
57 |
58 |

Scoreboard has been frozen.

59 |
60 |
61 |
62 | {% endif %} 63 |
64 |
65 |

Members

66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | {% for member in team.members %} 75 | 76 | 81 | 82 | 83 | {% endfor %} 84 | 85 |
User NameScore
77 | 78 | {{ member.name }} 79 | 80 | {{ member.score }}
86 | {% if solves %} 87 |
88 |

Details

89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 | {% endif %} 118 |
119 |
120 |
121 |
122 | {% if solves %} 123 | {% if awards %} 124 |

Awards

125 |
126 | {% for award in awards %} 127 |
128 |
129 |
130 |

{{ award.name }}
{{ award.value }} Points

131 |
132 |
133 | {% if award.category %} 134 |

Award Category: {{ award.category }}

{% else %} 135 |

Award Category: None

{% endif %} {% if award.description %} 136 |

Description: {{ award.description }}

{% else %} 137 |

Description: None

{% endif %} {% if award.icon %}{{award.icon}}{% endif %} 138 |
139 |
140 |
141 | {% endfor %} 142 |
143 | {% endif %} 144 |

Solves

145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | {% for solve in solves %} 156 | 157 | 158 | 159 | 160 | 165 | 166 | {% endfor %} 167 | 168 |
ChallengeCategoryValueTime
{{ solve.challenge.name }}{{ solve.challenge.category }}{{ solve.challenge.value }} 161 | 164 |
169 | {% else %} 170 |
171 |

No solves yet

172 |
173 | {% endif %} 174 | {% endif %} 175 |
176 |
177 | {% endblock %} 178 | {% block scripts %} 179 | 188 | 189 | 190 | {% if solves %} 191 | 192 | {% endif %} 193 | {% endblock %} -------------------------------------------------------------------------------- /stormctf/templates/teams/team_enrollment.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block stylesheets %} 3 | {% endblock %} 4 | {% block content %} 5 |
6 |
7 |
8 |

Team

9 |
10 |
11 |
12 |
13 |
14 |
15 |

Welcome to {{ get_ctf_name() }}!

16 |

In order to participate you must either join or create a team. Check with your teammates before you continue!

17 |
18 |
19 | 20 | 23 |
24 | Join Team 25 |
26 |
27 | Create Team 28 |
29 |
30 |
31 |
32 | {% endblock %} 33 | {% block scripts %} 34 | 36 | {% if solves %} 37 | {% endif %} 39 | {% endblock %} -------------------------------------------------------------------------------- /stormctf/templates/teams/teams.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block stylesheets %} 3 | {% endblock %} 4 | {% block content %} 5 |
6 |
7 |

Teams

8 |
9 |
10 |
11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | {% for team in teams %} 23 | 24 | 38 | 51 | 58 | 61 | 62 | {% endfor %} 63 | 64 |
TeamAffiliationWebsiteCountry
25 | {% if scores_visible() %} 26 | 27 | {{ team.name | truncate(50) }} 28 | 29 | {% else %} 30 | {{ team.name | truncate(50) }} 31 | {% endif %} 32 | {% if team.oauth_id %} 33 | 34 | Official 35 | 36 | {% endif %} 37 | 39 | {% if team.affiliation %} 40 | {% if team.affiliation | length > 50 %} 41 | 42 | {% if team.affiliation %}{{ team.affiliation | truncate(50) }}{% endif %} 43 | 44 | {% else %} 45 | 46 | {% if team.affiliation %}{{ team.affiliation | truncate(50) }}{% endif %} 47 | 48 | {% endif %} 49 | {% endif %} 50 | 52 | {% if team.website and (team.website.startswith('http://') or team.website.startswith('https://')) %} 53 | 54 | {{ team.website | truncate(20) }} 55 | 56 | {% endif %} 57 | 59 | {% if team.country %}{{ lookup_country_code(team.country) }}{% endif %} 60 |
65 | {% if pages > 1 %} 66 |
67 |
68 |

Page

69 |
    70 | {% if curr_page != 1 %} 71 |
  • 72 | {% endif %} 73 | {% for page in range(1, pages + 1) %} 74 | {% if curr_page != page %} 75 | {{ page }} 76 | {% else %} 77 |
  • {{page}}
  • 78 | {% endif %} 79 | {% endfor %} 80 | {% if curr_page != pages %} 81 | > 82 |
83 |
84 | {% endif %} 85 |
86 | {% endif %} 87 |
88 | {% endblock %} 89 | {% block scripts %} 90 | 128 | {% endblock %} -------------------------------------------------------------------------------- /stormctf/templates/users/private.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block stylesheets %} 3 | {% endblock %} 4 | {% block content %} 5 |
6 |
7 |

{{ user.name }}

8 | {% if user.oauth_id %} 9 | 10 |

Official

11 |
12 | {% endif %} 13 | {% if user.affiliation %} 14 |

{{ user.affiliation }}

15 | {% endif %} 16 |
17 |

18 | {# This intentionally hides the user's place because this can be their internal profile. #} 19 | {# Public page hiding is done at the route level #} 20 | {% if scores_visible() %} 21 | {% if user.place != 0 %} 22 | {{ user.place }} 23 | place 24 | {% endif %} 25 | {% endif %} 26 |

27 |

28 | {% if score %} 29 | {{ user.score }} 30 | points 31 | {% endif %} 32 |

33 |
34 |
35 | {% if user.website and (user.website.startswith('http://') or user.website.startswith('https://')) %} 36 | {{ user.website }} 37 | {% endif %} 38 |
39 |
40 |
41 | {% if errors %} 42 |
43 |
44 |
45 | {% for error in errors %} 46 |
47 | 48 |

{{ error }}

49 |
50 | {% endfor %} 51 |
52 |
53 |
54 | {% else %} {% if score_frozen %} 55 |
56 |
57 |
58 |

Scoreboard has been frozen.

59 |
60 |
61 |
62 | {% endif %} 63 |
64 |
65 |
66 | {% set solves = user.solves %} 67 | {% set awards = user.awards %} 68 | {% if solves %} 69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | {% endif %} 100 |
101 |
102 | {% if solves %} 103 | {% if awards %} 104 |

Awards

105 |
106 | {% for award in awards %} 107 |
108 |
109 |
110 |

{{ award.name }}
{{ award.value }} Points

111 |
112 |
113 | {% if award.category %} 114 |

Award Category: {{ award.category }}

{% else %} 115 |

Award Category: None

{% endif %} {% if award.description %} 116 |

Description: {{ award.description }}

{% else %} 117 |

Description: None

{% endif %} {% if award.icon %}{{award.icon}}{% endif %} 118 |
119 |
120 |
121 | {% endfor %} 122 |
123 | {% endif %} 124 |

Solves

125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | {% for solve in solves %} 136 | 137 | 138 | 139 | 140 | 145 | 146 | {% endfor %} 147 | 148 |
ChallengeCategoryValueTime
{{ solve.challenge.name }}{{ solve.challenge.category }}{{ solve.challenge.value }} 141 | 144 |
149 | {% else %} 150 |
151 |

No solves yet

152 |
153 | {% endif %} 154 | {% endif %} 155 |
156 |
157 | {% endblock %} 158 | {% block scripts %} 159 | 166 | 167 | 168 | 169 | {% endblock %} -------------------------------------------------------------------------------- /stormctf/templates/users/public.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block stylesheets %} 3 | {% endblock %} 4 | {% block content %} 5 |
6 |
7 |

{{ user.name }}

8 | {% if user.oauth_id %} 9 | 10 |

Official

11 |
12 | {% endif %} 13 | {% if user.affiliation %} 14 |

{{ user.affiliation }}

15 | {% endif %} 16 |
17 |

18 | {# This intentionally hides the user's place because this can be their internal profile. #} 19 | {# Public page hiding is done at the route level #} 20 | {% if scores_visible() %} 21 | {% if user.place != 0 %} 22 | {{ user.place }} 23 | place 24 | {% endif %} 25 | {% endif %} 26 |

27 |

28 | {% if score %} 29 | {{ user.score }} 30 | points 31 | {% endif %} 32 |

33 |
34 |
35 | {% if user.website and (user.website.startswith('http://') or user.website.startswith('https://')) %} 36 | {{ user.website }} 37 | {% endif %} 38 |
39 |
40 |
41 | {% if errors %} 42 |
43 |
44 |
45 | {% for error in errors %} 46 |
47 | 48 |

{{ error }}

49 |
50 | {% endfor %} 51 |
52 |
53 |
54 | {% else %} {% if score_frozen %} 55 |
56 |
57 |
58 |

Scoreboard has been frozen.

59 |
60 |
61 |
62 | {% endif %} 63 |
64 |
65 |
66 | {% set solves = user.solves %} 67 | {% set awards = user.awards %} 68 | {% if solves %} 69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | {% endif %} 100 |
101 |
102 | {% if solves %} 103 | {% if awards %} 104 |

Awards

105 |
106 | {% for award in awards %} 107 |
108 |
109 |
110 |

{{ award.name }}
{{ award.value }} Points

111 |
112 |
113 | {% if award.category %} 114 |

Award Category: {{ award.category }}

{% else %} 115 |

Award Category: None

{% endif %} {% if award.description %} 116 |

Description: {{ award.description }}

{% else %} 117 |

Description: None

{% endif %} {% if award.icon %}{{award.icon}}{% endif %} 118 |
119 |
120 |
121 | {% endfor %} 122 |
123 | {% endif %} 124 |

Solves

125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | {% for solve in solves %} 136 | 137 | 138 | 139 | 140 | 145 | 146 | {% endfor %} 147 | 148 |
ChallengeCategoryValueTime
{{ solve.challenge.name }}{{ solve.challenge.category }}{{ solve.challenge.value }} 141 | 144 |
149 | {% else %} 150 |
151 |

No solves yet

152 |
153 | {% endif %} 154 | {% endif %} 155 |
156 |
157 | {% endblock %} 158 | {% block scripts %} 159 | 166 | 167 | 168 | 169 | {% endblock %} -------------------------------------------------------------------------------- /stormctf/templates/users/users.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block stylesheets %} 3 | {% endblock %} 4 | {% block content %} 5 |
6 |
7 |

Users

8 |
9 |
10 |
11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | {% for user in users %} 23 | 24 | 38 | 51 | 58 | 61 | 62 | {% endfor %} 63 | 64 |
UserAffiliationWebsiteCountry
25 | {% if scores_visible() %} 26 | 27 | {{ user.name | truncate(50) }} 28 | 29 | {% else %} 30 | {{ user.name | truncate(50) }} 31 | {% endif %} 32 | {% if user.oauth_id %} 33 | 34 | Official 35 | 36 | {% endif %} 37 | 39 | {% if user.affiliation %} 40 | {% if user.affiliation | length > 50 %} 41 | 42 | {% if user.affiliation %}{{ user.affiliation | truncate(50) }}{% endif %} 43 | 44 | {% else %} 45 | 46 | {% if user.affiliation %}{{ user.affiliation | truncate(50) }}{% endif %} 47 | 48 | {% endif %} 49 | {% endif %} 50 | 52 | {% if user.website and (user.website.startswith('http://') or user.website.startswith('https://')) %} 53 | 54 | {{ user.website | truncate(20) }} 55 | 56 | {% endif %} 57 | 59 | {% if user.country %}{{ lookup_country_code(user.country) }}{% endif %} 60 |
65 | {% if pages > 1 %} 66 |
67 |
68 |

Page

69 |
    70 | {% if curr_page != 1 %} 71 |
  • 72 | {% endif %} 73 | {% for page in range(1, pages + 1) %} 74 | {% if curr_page != page %} 75 | {{ page }} 76 | {% else %} 77 |
  • {{page}}
  • 78 | {% endif %} 79 | {% endfor %} 80 | {% if curr_page != pages %} 81 | > 82 |
83 |
84 | {% endif %} 85 |
86 | {% endif %} 87 |
88 | {% endblock %} 89 | {% block scripts %} 90 | 128 | {% endblock %} --------------------------------------------------------------------------------