<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous"> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.11/handlebars.min.js"></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script type="text/javascript" src="/files/logout.js"></script> <style type="text/css"> body { overflow-y: scroll; } </style> </head> <script id="nav-template" type="text/x-handlebars-template"> <ul class="nav nav-pills" id="navigation-pills"> <li class="nav-item"> <a class="nav-link active" href="#" onclick="filterChallenges()" circus-category="ALL"> All </a> </li> {{#each categories as |count name|}} <li class="nav-item"> <a class="nav-link" href="#" onclick="filterChallenges('{{ name }}')" circus-category="{{ name }}"> {{ name }} <span class="badge badge-light">{{ count }}</span> </a> </li> {{/each}} </ul> </script> <script id="challenge-template" type="text/x-handlebars-template"> <div id="challenge-container"> {{#each challenges}} <div class="card {{#if foundFlag}}border-success{{/if}}" style="margin-bottom: 20px" circus-category="{{ category }}"> <div class="card-header"> {{ name }} <span class="badge badge-light"> {{ category }} </span> </div> <div class="card-body"> <p> {{{ description }}} </p> {{#if ContainsLaunchable}} {{#if IPAddress}} <p class="text-primary"> Container running IPv4: <kbd>{{IPAddress}}</kbd> </p> <button class="btn btn-primary" onclick="stopContainer('{{ name }}');$(this).prop('disabled', true)">Stop Container</button> {{else}} <button class="btn btn-primary" onclick="startContainer('{{ name }}');$(this).prop('disabled', true)">Launch Container</button> {{/if}} {{/if}} <hr> {{#if foundFlag}} <p class="text-success">Flag found!</p> {{else}} <form class="input-group mb-3" onsubmit="event.preventDefault();submitThis(this);"> <input type="hidden" name="challengeName" value="{{ name }}"> <input type="text" class="form-control" aria-label="Flag" aria-describedby="button-submit" name="flag"> <div class="input-group-append"> <button class="btn btn-outline-primary" type="submit" id="button-submit">Submit flag</button> </div> </form> {{/if}} </div> </div> {{/each}} </script> <body> <nav class="navbar navbar-expand-md navbar-dark bg-dark mb-4"> <a class="navbar-brand" href="/">Companion</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarCollapse"> <ul class="navbar-nav mr-auto"> <li class="nav-item"> <a class="nav-link" href="/">Home <span class="sr-only">(current)</span></a> </li> <li class="nav-item"> <a class="nav-link" href="/access">Access</a> </li> <li class="nav-item active"> <a class="nav-link" href="/challenges">Challenges</a> </li> </ul> <button class="btn btn-outline-danger my-2 my-sm-0" onclick="logoutThenRedirect()">Logout</button> </div> </nav> <main class="container" role="main"> <div id="nav-list"> </div> <br> <div id="challenge-list"> <div class="alert alert-info" role="alert"> Loading challenges... </div> </div> </main> </body> <script type="text/javascript"> var navTemplate = Handlebars.compile($("#nav-template").html()); var challengeTemplate = Handlebars.compile($("#challenge-template").html()); var renderedNav = false; function loadChallengesAndRender() { $.ajax({ url: "/api/getChallenges", success: function(result) { if(!renderedNav) { $("#nav-list").html(navTemplate(jQuery.parseJSON(result))); renderedNav = true; } $("#challenge-list").html(challengeTemplate(jQuery.parseJSON(result))); filterChallenges($('#navigation-pills > li > a.active').attr("circus-category")); } }); } function submitThis(t) { submitFlag($(t).find('[name=challengeName]').val(), $(t).find('[name=flag]')); } function submitFlag(challengeName, flagObject) { $.post("/api/submitFlag", { "challengeName": challengeName, "flag": flagObject.val() }).done(function(data) { var result = jQuery.parseJSON(data); if(result["correctFlag"] == "true") { // yay! loadChallengesAndRender(); } else { // nay! flagObject.addClass("alert-danger").blur(); } }); } function startContainer(name) { $.post("/api/startContainer", { "challengeName": name }).done(function() { loadChallengesAndRender(); }); } function stopContainer(name) { $.post("/api/stopContainer", { "challengeName": name }).done(function() { loadChallengesAndRender(); }); } function filterChallenges(category) { $("#navigation-pills > li > a").removeClass("active"); if(category && category != "ALL") { $("#challenge-container > div").hide(); $("#challenge-container > div[circus-category=" + category + "]").show(); $("#navigation-pills > li > a[circus-category=" + category + "]").addClass("active"); } else { // Show ALL $("#challenge-container > div").show(); $("#navigation-pills > li > a[circus-category=ALL]").addClass("active"); } } $(document).ready(function() { loadChallengesAndRender(); }); </script> </html>