Remove old frontend ui
|
@ -1 +1 @@
|
|||
../../../frontend/static/css/fic.css
|
||||
../../../qa/static/css/fic.css
|
|
@ -1 +1 @@
|
|||
../../../frontend/static/css/glyphicon.css
|
||||
../../../admin/static/css/glyphicon.css
|
|
@ -1 +1 @@
|
|||
../../frontend/static/favicon.ico
|
||||
../../frontend/ui/static/favicon.ico
|
|
@ -1 +1 @@
|
|||
../../../frontend/static/img/comcyber.png
|
||||
../../../frontend/ui/static/img/comcyber.png
|
|
@ -1 +1 @@
|
|||
../../../frontend/static/img/epita.png
|
||||
../../../admin/static/img/epita.png
|
|
@ -1 +1 @@
|
|||
../../../frontend/static/img/fic.png
|
||||
../../../admin/static/img/fic.png
|
|
@ -1 +1 @@
|
|||
../../../frontend/static/img/srs.png
|
||||
../../../frontend/ui/static/img/srs.png
|
2
dashboard/static/js/angular-route.min.js
vendored
|
@ -1 +1 @@
|
|||
../../../frontend/static/js/angular-route.min.js
|
||||
../../../admin/static/js/angular-route.min.js
|
2
dashboard/static/js/angular-sanitize.min.js
vendored
|
@ -1 +1 @@
|
|||
../../../frontend/static/js/angular-sanitize.min.js
|
||||
../../../admin/static/js/angular-sanitize.min.js
|
2
dashboard/static/js/angular.min.js
vendored
|
@ -1 +1 @@
|
|||
../../../frontend/static/js/angular.min.js
|
||||
../../../admin/static/js/angular.min.js
|
2
dashboard/static/js/bootstrap.min.js
vendored
|
@ -1 +1 @@
|
|||
../../../frontend/static/js/bootstrap.min.js
|
||||
../../../admin/static/js/bootstrap.min.js
|
|
@ -1 +1 @@
|
|||
../../../frontend/static/js/common.js
|
||||
../../../admin/static/js/common.js
|
2
dashboard/static/js/d3.v3.min.js
vendored
|
@ -1 +1 @@
|
|||
../../../frontend/static/js/d3.v3.min.js
|
||||
../../../admin/static/js/d3.v3.min.js
|
|
@ -1 +1 @@
|
|||
../../../frontend/static/js/i18n/
|
||||
../../../admin/static/js/i18n/
|
2
dashboard/static/js/jquery.min.js
vendored
|
@ -1 +1 @@
|
|||
../../../frontend/static/js/jquery.min.js
|
||||
../../../admin/static/js/jquery.min.js
|
12
frontend/static/css/bootstrap.min.css
vendored
|
@ -1,387 +0,0 @@
|
|||
@font-face {
|
||||
font-family: "Linux Biolinum";
|
||||
src: url('../fonts/LinBiolinum_R.woff') format('woff');
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Linux Biolinum";
|
||||
src: url('../fonts/LinBiolinum_RB.woff') format('woff');
|
||||
font-weight: bold;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Linux Biolinum";
|
||||
src: url('../fonts/LinBiolinum_RI.woff') format('woff');
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'FantasqueSansMonoRegular';
|
||||
src: url('../fonts/FantasqueSansMono-Regular.woff') format('woff');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
b, strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
[ng-cloak] {
|
||||
display:none !important;
|
||||
}
|
||||
|
||||
.popover.bs-popover-left .arrow::after {
|
||||
border-left-color: #7A8288;
|
||||
}
|
||||
|
||||
body {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.bg-public {
|
||||
background-image: url('../img/logo-epita-bw.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.bg-public .carousel h3 {
|
||||
font-size: 1.5rem;
|
||||
line-height: 1.1rem;
|
||||
}
|
||||
|
||||
.flag {
|
||||
font-family: 'FantasqueSansMonoRegular', monospace;
|
||||
}
|
||||
|
||||
.card-img-top {
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
.theme-card {
|
||||
height: 10rem;
|
||||
}
|
||||
|
||||
.beautiful {
|
||||
font-family: "Linux Biolinum",Helvetica,Arial,sans-serif;
|
||||
}
|
||||
.beautiful ol {
|
||||
font-size: 133%;
|
||||
}
|
||||
.beautiful ol ol {
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
.text-bold {
|
||||
font-weight: bolder;
|
||||
}
|
||||
.text-indent p {
|
||||
text-indent: 1em;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.niceborder {
|
||||
border-bottom: 5px #4eaee6 solid;
|
||||
}
|
||||
.navbar img {
|
||||
margin: 3px auto;
|
||||
height: 100px;
|
||||
}
|
||||
.navbar .clock {
|
||||
font-size: 70px;
|
||||
}
|
||||
.clock:not(.expired):not(.wait) .point, .clock.expired {
|
||||
transition: color text-shadow 1s;
|
||||
position: relative;
|
||||
animation: clockanim 1s ease infinite;
|
||||
-moz-animation: clockanim 1s ease infinite;
|
||||
-webkit-animation: clockanim 1s ease infinite;
|
||||
}
|
||||
.clock.wait .point {
|
||||
transition: color text-shadow 1s;
|
||||
position: relative;
|
||||
animation: clockwait 1s ease infinite;
|
||||
-moz-animation: clockwait 1s ease infinite;
|
||||
-webkit-animation: clockwait 1s ease infinite;
|
||||
}
|
||||
.end {
|
||||
color: #e64143;
|
||||
}
|
||||
.point {
|
||||
text-shadow: 0 0 20px #4eaee6;
|
||||
}
|
||||
.end .point {
|
||||
text-shadow: 0 0 20px #e64143;
|
||||
}
|
||||
@-webkit-keyframes clockanim {
|
||||
0% { opacity: 1.0; }
|
||||
50% { opacity: 0; }
|
||||
100% { opacity: 1.0; };
|
||||
}
|
||||
@-moz-keyframes clockanim {
|
||||
0% { opacity: 1.0; }
|
||||
50% { opacity: 0; }
|
||||
100% { opacity: 1.0; };
|
||||
}
|
||||
keyframes clockanim {
|
||||
0% { opacity: 1.0; }
|
||||
50% { opacity: 0; }
|
||||
100% { opacity: 1.0; };
|
||||
}
|
||||
@-webkit-keyframes clockwait {
|
||||
0% { text-shadow: 0 0 20px #A6D6F2; }
|
||||
50% { text-shadow: 0 0 2px #A6D6F2; }
|
||||
100% { text-shadow: 0 0 20px #A6D6F2; }
|
||||
}
|
||||
@-moz-keyframes clockwait {
|
||||
0% { text-shadow: 0 0 20px #A6D6F2; }
|
||||
50% { text-shadow: 0 0 2px #A6D6F2; }
|
||||
100% { text-shadow: 0 0 20px #A6D6F2; }
|
||||
}
|
||||
keyframes clockwait {
|
||||
0% { text-shadow: 0 0 20px #A6D6F2; }
|
||||
50% { text-shadow: 0 0 2px #A6D6F2; }
|
||||
100% { text-shadow: 0 0 20px #A6D6F2; }
|
||||
}
|
||||
|
||||
samp.cksum {
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 16vw;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
word-wrap: normal;
|
||||
}
|
||||
|
||||
h1 small.authors {
|
||||
float: right;
|
||||
font-style: italic;
|
||||
font-size: 42%;
|
||||
}
|
||||
.lead small.authors {
|
||||
color: #7a8288;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
a.badge:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
.teamname {
|
||||
-webkit-filter: invert(100%);
|
||||
filter: invert(100%);
|
||||
}
|
||||
a:hover .teamname {
|
||||
text-shadow: 0px 0px 10px #888888;
|
||||
}
|
||||
|
||||
.authors a {
|
||||
color: #3A3F44;
|
||||
}
|
||||
|
||||
.heading {
|
||||
font-style: italic;
|
||||
margin-top: -7px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#eventsList {
|
||||
overflow:hidden;
|
||||
max-height: 90vh;
|
||||
}
|
||||
|
||||
.swap-animation .alert {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.swap-animation {
|
||||
margin-bottom: 0.5rem;
|
||||
max-height: 30vh;
|
||||
transition: max-height 1.0s linear,opacity 1.0s linear,transform 0.5s linear;
|
||||
}
|
||||
.swap-animation.ng-enter {
|
||||
transform: translateY(-25vh);
|
||||
max-height: 0vh;
|
||||
}
|
||||
.swap-animation.ng-enter-active {
|
||||
opacity: 1;
|
||||
transform: translateY(0px);
|
||||
max-height: 30vh;
|
||||
}
|
||||
.swap-animation.ng-leave {
|
||||
opacity: 1;
|
||||
max-height: 30vh;
|
||||
transform: translateY(0px);
|
||||
}
|
||||
.swap-animation.ng-leave-active {
|
||||
opacity: 0;
|
||||
transform: translateX(120vw);
|
||||
max-height: 0vh;
|
||||
}
|
||||
|
||||
.carousel-indicators {
|
||||
bottom: -10px;
|
||||
}
|
||||
.carousel-caption {
|
||||
padding: 0;
|
||||
position: static;
|
||||
}
|
||||
.carousel .table {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.carousel .table-sm td {
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.table th.frotated {
|
||||
border: 0;
|
||||
}
|
||||
.table th.rotated {
|
||||
height: 100px;
|
||||
width: 40px;
|
||||
min-width: 40px;
|
||||
max-width: 40px;
|
||||
position: relative;
|
||||
vertical-align: bottom;
|
||||
padding: 0;
|
||||
font-size: 12px;
|
||||
line-height: 0.9;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
th.rotated > div {
|
||||
position: relative;
|
||||
top: 0px;
|
||||
left: -50px;
|
||||
height: 100%;
|
||||
transform: skew(45deg,0deg);
|
||||
overflow: hidden;
|
||||
border: 1px solid #000;
|
||||
}
|
||||
th.rotated div span {
|
||||
transform: skew(-45deg,0deg) rotate(45deg);
|
||||
position: absolute;
|
||||
bottom: 40px;
|
||||
left: -35px;
|
||||
display: inline-block;
|
||||
width: 110px;
|
||||
text-align: left;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
ul.list-inline li {
|
||||
display: inline;
|
||||
}
|
||||
ul.list-inline li:not(:last-child)::after {
|
||||
content: " ● "
|
||||
}
|
||||
|
||||
.breadcrumb-item + .breadcrumb-item::before {
|
||||
content: ">"
|
||||
}
|
||||
|
||||
.excard {
|
||||
transition: transform 250ms;
|
||||
}
|
||||
.excard:hover {
|
||||
transform: scale(1.07);
|
||||
}
|
||||
|
||||
#tagsMenu + .dropdown-menu div {
|
||||
overflow-y: auto;
|
||||
max-height: calc(66vh - 100px);
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-left: solid 2px;
|
||||
margin-left: 1em;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.jumbotron img {
|
||||
margin-left: -1em;
|
||||
padding-left: 2em;
|
||||
padding-right: 2em;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
#eventsList .card {
|
||||
border-left-color: rgba(0,0,0,.125) !important;
|
||||
border-right-color: rgba(0,0,0,.125) !important;
|
||||
border-top-color: rgba(0,0,0,.125) !important;
|
||||
}
|
||||
|
||||
.bg-public .card-body {
|
||||
padding:1rem;
|
||||
padding-bottom:0;
|
||||
}
|
||||
|
||||
#themesSummary .card-body {
|
||||
padding:0;
|
||||
}
|
||||
#themesSummary h3 {
|
||||
background: rgba(64,64,64,0.66);
|
||||
border-radius: 2px;
|
||||
padding: 0.5rem;
|
||||
margin-left: 0.5rem;
|
||||
margin-right: 0.5rem;
|
||||
margin-top: -40px;
|
||||
}
|
||||
#themesSummary p {
|
||||
font-size: 90%;
|
||||
margin: 0.2rem;
|
||||
text-indent: 0.6em;
|
||||
}
|
||||
|
||||
.card-sm .card-header, .card-sm .card-footer {
|
||||
padding: 0.2rem 0.75rem;
|
||||
}
|
||||
.card-sm .card-body {
|
||||
padding: 0.4rem 0.75rem;
|
||||
}
|
||||
.card-sm .card-body.text-indent p {
|
||||
text-indent: 0.4rem;
|
||||
}
|
||||
|
||||
.carousel-item, .carousel-caption {
|
||||
height: inherit;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
margin-bottom: -15rem;
|
||||
}
|
||||
.page-header h1 {
|
||||
text-shadow: 0 0 15px rgba(255,255,255,0.95), 0 0 5px rgb(255,255,255)
|
||||
}
|
||||
.page-header h1, .page-header h1 a {
|
||||
color: black;
|
||||
}
|
||||
.page-header h1 a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
.page-header h2 {
|
||||
font-size: 100%;
|
||||
text-shadow: 1px 1px 1px rgba(0,0,0,0.9)
|
||||
}
|
||||
.page-header h2, .page-header h2 a {
|
||||
color: #4eaee6;
|
||||
}
|
||||
.page-header h1 {
|
||||
padding-top: 4rem;
|
||||
text-align: center;
|
||||
}
|
||||
.page-header h2 {
|
||||
padding-bottom: 14rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.page-header .headerfade {
|
||||
background: linear-gradient(transparent 0%, rgb(233,236,239) 100%);
|
||||
height: 3rem;
|
||||
}
|
||||
|
||||
a.list-group-item:hover {
|
||||
text-decoration: none;
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
../../../admin/static/css/glyphicon.css
|
|
@ -1,51 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Challenge Forensic</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
|
||||
<meta name="author" content="EPITA Laboratoire SRS">
|
||||
<meta name="robots" content="all">
|
||||
<link href="/css/bootstrap.min.css" type="text/css" rel="stylesheet" media="screen">
|
||||
<link href="/css/fic.css" type="text/css" rel="stylesheet" media="screen">
|
||||
<style>
|
||||
.niceborder {
|
||||
border-bottom-color: #ee5f5b;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-light">
|
||||
|
||||
<div class="navbar navbar-expand-lg navbar-dark bg-dark text-light niceborder">
|
||||
<div class="container">
|
||||
<div class="col-md-auto">
|
||||
<a href="/">
|
||||
<img src="/img/fic.png" alt="Forum International de la Cybersécurité">
|
||||
</a>
|
||||
</div>
|
||||
<div class="clock col-md-auto text-center">Challenge Forensic</div>
|
||||
<div class="col-md-auto">
|
||||
<a href="http://www.epita.fr/">
|
||||
<img src="/img/epita.png" alt="Epita">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container" style="margin-top:20px;">
|
||||
<div class="jumbotron niceborder">
|
||||
<h1>Page introuvable <small>Erreur 404</small></h1>
|
||||
<hr>
|
||||
<p class="lead">
|
||||
La page à laquelle vous tentez d'accéder n'existe pas ou l'adresse que vous avez tapée est incorrecte.
|
||||
</p>
|
||||
<p>
|
||||
Si le problème persiste, <a href="mailto:root@srs.epita.fr">contactez un administrateur</a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1 +0,0 @@
|
|||
{"errmsg": "La page à laquelle vous tentez d'accéder n'existe pas ou l'adresse que vous avez tapée est incorrecte."}
|
|
@ -1,48 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Challenge Forensic</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
|
||||
<meta name="author" content="EPITA Laboratoire SRS">
|
||||
<meta name="robots" content="all">
|
||||
<link href="/css/bootstrap.min.css" type="text/css" rel="stylesheet" media="screen">
|
||||
<link href="/css/fic.css" type="text/css" rel="stylesheet" media="screen">
|
||||
<style>
|
||||
.niceborder {
|
||||
border-bottom-color: #ee5f5b;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-light">
|
||||
|
||||
<div class="navbar navbar-expand-lg navbar-dark bg-dark text-light niceborder">
|
||||
<div class="container">
|
||||
<div class="col-md-auto">
|
||||
<a href="/">
|
||||
<img src="/img/fic.png" alt="Forum International de la Cybersécurité">
|
||||
</a>
|
||||
</div>
|
||||
<div class="clock col-md-auto text-center">Challenge Forensic</div>
|
||||
<div class="col-md-auto">
|
||||
<a href="http://www.epita.fr/">
|
||||
<img src="/img/epita.png" alt="Epita">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container" style="margin-top:20px;">
|
||||
<div class="jumbotron niceborder">
|
||||
<h1>Requête trop grosse <small>Erreur 413</small></h1>
|
||||
<hr>
|
||||
<p class="lead">
|
||||
La quantité de données que vous souhaitez envoyer au serveur est trop importante pour qu'il accepte de la traiter.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1 +0,0 @@
|
|||
{"errmsg": "La quantité de données que vous souhaitez envoyer au serveur est trop importante pour qu'il accepte de la traiter."}
|
|
@ -1,51 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Challenge Forensic</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
|
||||
<meta name="author" content="EPITA Laboratoire SRS">
|
||||
<meta name="robots" content="all">
|
||||
<link href="/css/bootstrap.min.css" type="text/css" rel="stylesheet" media="screen">
|
||||
<link href="/css/fic.css" type="text/css" rel="stylesheet" media="screen">
|
||||
<style>
|
||||
.niceborder {
|
||||
border-bottom-color: #ee5f5b;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-light">
|
||||
|
||||
<div class="navbar navbar-expand-lg navbar-dark bg-dark text-light niceborder">
|
||||
<div class="container">
|
||||
<div class="col-md-auto">
|
||||
<a href="/">
|
||||
<img src="/img/fic.png" alt="Forum International de la Cybersécurité">
|
||||
</a>
|
||||
</div>
|
||||
<div class="clock col-md-auto text-center">Challenge Forensic</div>
|
||||
<div class="col-md-auto">
|
||||
<a href="http://www.epita.fr/">
|
||||
<img src="/img/epita.png" alt="Epita">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container" style="margin-top:20px;">
|
||||
<div class="jumbotron niceborder">
|
||||
<h1>Erreur interne <small>Erreur 500</small></h1>
|
||||
<hr>
|
||||
<p class="lead">
|
||||
Notre serveur est actuellement dans l'incapacité de répondre à votre requête.<br>Veuillez recommencer dans quelques instants.
|
||||
</p>
|
||||
<p>
|
||||
Si le problème persiste, <a href="mailto:root@srs.epita.fr">contactez un administrateur</a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1 +0,0 @@
|
|||
{"errmsg": "Notre serveur est actuellement dans l'incapacité de répondre à votre requête. \nVeuillez recommencer dans quelques instants."}
|
Before Width: | Height: | Size: 2.2 KiB |
|
@ -1 +0,0 @@
|
|||
../../admin/static/fonts/
|
Before Width: | Height: | Size: 152 KiB |
Before Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 157 KiB |
|
@ -1,165 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" ng-app="FICApp">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title ng-bind="'Challenge Forensic' + ($root.title?' - '+$root.title:'')">Challenge Forensic</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
|
||||
<meta name="author" content="EPITA Laboratoire SRS">
|
||||
<meta name="robots" content="all">
|
||||
<base href="/">
|
||||
<link href="/css/bootstrap.min.css" type="text/css" rel="stylesheet" media="screen">
|
||||
<link href="/css/glyphicon.css" type="text/css" rel="stylesheet" media="screen">
|
||||
<link href="/css/fic.css" type="text/css" rel="stylesheet" media="screen">
|
||||
<script src="/js/angular.min.js"></script>
|
||||
</head>
|
||||
<body class="bg-light">
|
||||
|
||||
<div class="navbar navbar-expand-lg navbar-dark bg-dark text-light" ng-controller="CountdownController">
|
||||
<div class="container">
|
||||
<div class="col-auto d-none d-sm-block">
|
||||
<a ng-href="{{ (time.remaining === undefined || my.team_id)?'https://www.forum-fic.com/':'/' }}">
|
||||
<img src="/img/fic.png" alt="Forum International de la Cybersécurité" class="center-block">
|
||||
</a>
|
||||
</div>
|
||||
<div class="clock col-auto text-center" ng-hide="1">Chargement...</div>
|
||||
<div class="clock col text-center" ng-class="{expired: time.expired, end: time.end, wait: startIn}" ng-if="time.remaining !== undefined && settings.end - settings.start > 0" ng-cloak>
|
||||
<span ng-class="{'d-none': !time.hours, 'd-sm-inline': !time.hours}">
|
||||
<span id="hours">{{ time.hours | time }}</span>
|
||||
<span class="point">:</span>
|
||||
</span>
|
||||
<span id="min">{{ time.minutes | time }}</span>
|
||||
<span ng-class="{'d-none': time.hours, 'd-sm-inline': time.hours}">
|
||||
<span class="point">:</span>
|
||||
<span id="sec">{{ time.seconds | time }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="clock col-auto btn-group btn-group-lg" ng-if="time.remaining === undefined || settings.end - settings.start <= 0" ng-cloak>
|
||||
<a class="btn btn-light" href="/">
|
||||
<span class="glyphicon glyphicon-home"></span> Accueil
|
||||
</a>
|
||||
<a class="btn btn-light" href="/rank">
|
||||
<span class="glyphicon glyphicon-list"></span> Classement
|
||||
</a>
|
||||
<a class="btn btn-light" ng-class="{'disabled': settings.videoslink == ''}" href="{{ settings.videoslink }}">
|
||||
<span class="glyphicon glyphicon-blackboard"></span> Vidéos
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-auto d-none d-md-block">
|
||||
<div class="carousel slide" data-ride="carousel" data-interval="30000" style="width: 150px">
|
||||
<div class="carousel-inner text-center">
|
||||
<div class="carousel-item active">
|
||||
<a href="http://www.epita.fr/">
|
||||
<img src="/img/epita.png" alt="Epita">
|
||||
</a>
|
||||
</div>
|
||||
<div class="carousel-item">
|
||||
<a href="https://srs.epita.fr/">
|
||||
<img src="/img/srs.png" alt="Laboratoire SRS Épita">
|
||||
</a>
|
||||
</div>
|
||||
<div class="carousel-item">
|
||||
<img src="/img/comcyber.png" alt="Réserves de cyberdéfense">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-controller="DataController">
|
||||
|
||||
<div class="sticky-top">
|
||||
<nav class="navbar navbar-expand-sm bg-primary" style="border-bottom: none;" ng-cloak>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navMenu" aria-controls="navMenu" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navMenu">
|
||||
<ul class="navbar-nav mr-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/">Accueil</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown" ng-class="{active: current_theme}">
|
||||
<a class="nav-link dropdown-toogle" href="#" id="themesMenu" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Scénarii
|
||||
</a>
|
||||
<div class="dropdown-menu niceborder">
|
||||
<a ng-repeat="(k,theme) in themes" ng-class="{active: k == current_theme}" class="dropdown-item" ng-href="/{{ theme.urlid }}">{{ theme.name }} <span class="badge badge-light"><span class="glyphicon glyphicon-fire" aria-hidden="true" ng-if="max_solved > 1 && theme.solved == max_solved" title="Déjà {{ theme.solved }} défis ont été résolus dans ce thème"></span> <span class="glyphicon glyphicon-gift" aria-hidden="true" ng-if="theme.exercice_coeff_max > 1" title="Des bonus existent pour au moins un défi de ce thème"></span> <span ng-if="(my.team_id)">{{ theme.exercice_solved }}/</span>{{ theme.exercice_count }}</span></a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item dropdown" ng-class="{active: current_tag}">
|
||||
<a class="nav-link dropdown-toogle" href="#" id="tagsMenu" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Tags
|
||||
</a>
|
||||
<div class="dropdown-menu niceborder">
|
||||
<input type="search" class="dropdown-item" placeholder="Filtrer" id="filtertag" ng-model="filtertag">
|
||||
<div>
|
||||
<a ng-repeat="tname in tagsl | filter: filtertag" ng-class="{active: tname == current_tag}" class="dropdown-item" ng-href="/tags/{{ tname }}">#{{ tname }} <span class="badge badge-light"><span ng-if="(my.team_id)">{{ tags[tname].solved }}/</span>{{ tags[tname].count }}</span></a>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/rank">Classement</a>
|
||||
</li>
|
||||
<li class="nav-item" ng-if="issues.length > 0">
|
||||
<a class="nav-link" href="/issues">
|
||||
Problèmes <span class="badge" ng-class="{'badge-danger': issues_need_info && issues_known_responses != issues_nb_responses,'badge-warning': !issues_need_info && issues_known_responses != issues_nb_responses,'badge-light': issues_known_responses == issues_nb_responses}">{{ issues_nb_responses }}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/rules">Aide</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<span class="navbar-text text-light" ng-show="(my.team_id)" ng-cloak>
|
||||
{{ my.score | number }} <ng-pluralize count="my.score" when="{'0': 'point', '-1': 'point', 'one': 'point', 'other': 'points'}"></ng-pluralize> <span ng-show="teams[my.team_id].rank">– {{ teams[my.team_id].rank }}<sup>e</sup> sur {{ teams_count }}</span>
|
||||
<h4 style="display: inline">
|
||||
<a tabindex="0" href="/edit" class="badge" role="button" style="background-color: {{ teams[my.team_id].color }}; color: {{ teams[my.team_id].color }};">
|
||||
<span class="teamname">{{ my.name }}</span>
|
||||
</a>
|
||||
</h4>
|
||||
</span>
|
||||
<span class="navbar-text text-light" ng-show="!my.team_id && settings.allowRegistration" ng-cloak>
|
||||
<a ng-href="/register" class="badge badge-warning" role="button">
|
||||
Inscription
|
||||
</a>
|
||||
</span>
|
||||
</nav>
|
||||
|
||||
<div class="progress" style="background-color: #4eaee6; height: 5px; border-radius: 0;">
|
||||
<div class="progress-bar bg-secondary" role="progressbar" style="width: {{timeProgression * 100}}%"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="background-image: url({{ themes[current_theme].image }})" ng-if="(current_theme)" class="page-header">
|
||||
<div class="container text-primary" ng-cloak>
|
||||
<h1 class="display-2"><a ng-href="{{ themes[current_theme].urlid }}" ng-bind="themes[current_theme].name"></a></h1>
|
||||
<h2 ng-bind-html="themes[current_theme].authors"></h2>
|
||||
</div>
|
||||
<div class="headerfade"></div>
|
||||
</div>
|
||||
|
||||
<div class="container text-primary clearfix" ng-if="!current_theme" ng-cloak>
|
||||
<h1 ng-if="title" ng-cloak>{{ title }} <small class="authors" ng-if="authors">{{ authors }}</small></h1>
|
||||
<h1 ng-if="!title">{{ settings.title }} <small class="authors">{{ settings.authors }}</small></h1>
|
||||
</div>
|
||||
|
||||
<div class="container" ng-view>
|
||||
<noscript>
|
||||
<div class="alert alert-danger mt-4">
|
||||
<strong>Veuillez activer le JavaScript.</strong> Ce site requiert un navigateur interprêtant le JavaScript pour fonctionner. Veuillez l'activer ou en télécharger un supportant cette technologie.
|
||||
</div>
|
||||
</noscript>
|
||||
</div>
|
||||
|
||||
<script src="/js/jquery.min.js"></script>
|
||||
<script src="/js/bootstrap.min.js"></script>
|
||||
<script src="/js/angular-route.min.js"></script>
|
||||
<script src="/js/angular-sanitize.min.js"></script>
|
||||
<script src="/js/i18n/angular-locale_fr-fr.js"></script>
|
||||
<script src="/js/challenge.js"></script>
|
||||
<script src="/js/common.js"></script>
|
||||
<script src="/js/blake2b.js" defer></script>
|
||||
</body>
|
||||
</html>
|
1
frontend/static/js/angular-route.min.js
vendored
|
@ -1 +0,0 @@
|
|||
../../../admin/static/js/angular-route.min.js
|
1
frontend/static/js/angular-sanitize.min.js
vendored
|
@ -1 +0,0 @@
|
|||
../../../admin/static/js/angular-sanitize.min.js
|
1
frontend/static/js/angular.min.js
vendored
|
@ -1 +0,0 @@
|
|||
../../../admin/static/js/angular.min.js
|
1
frontend/static/js/bootstrap.min.js
vendored
|
@ -1 +0,0 @@
|
|||
../../../admin/static/js/bootstrap.min.js
|
|
@ -1,887 +0,0 @@
|
|||
angular.module("FICApp", ["ngRoute", "ngSanitize"])
|
||||
.config(function($routeProvider, $locationProvider) {
|
||||
$routeProvider
|
||||
.when("/rules", {
|
||||
controller: "HomeController",
|
||||
templateUrl: "views/rules.html"
|
||||
})
|
||||
.when("/edit", {
|
||||
controller: "MyTeamController",
|
||||
templateUrl: "views/team-edit.html"
|
||||
})
|
||||
.when("/issue/:eid", {
|
||||
controller: "IssueController",
|
||||
templateUrl: "views/issue.html"
|
||||
})
|
||||
.when("/issues", {
|
||||
controller: "IssueController",
|
||||
templateUrl: "views/issue.html"
|
||||
})
|
||||
.when("/issues/:iid", {
|
||||
controller: "IssueController",
|
||||
templateUrl: "views/issue.html"
|
||||
})
|
||||
.when("/rank", {
|
||||
controller: "RankController",
|
||||
templateUrl: "views/rank.html"
|
||||
})
|
||||
.when("/register", {
|
||||
controller: "RegisterController",
|
||||
templateUrl: "views/register.html"
|
||||
})
|
||||
.when("/videos", {
|
||||
controller: "VideosController",
|
||||
templateUrl: "views/videos.html"
|
||||
})
|
||||
.when("/tags/:tag", {
|
||||
controller: "TagController",
|
||||
templateUrl: "views/tag.html"
|
||||
})
|
||||
.when("/:theme", {
|
||||
controller: "ExerciceController",
|
||||
templateUrl: "views/theme.html"
|
||||
})
|
||||
.when("/:theme/:exercice", {
|
||||
controller: "ExerciceController",
|
||||
templateUrl: function(e) {
|
||||
if (e.theme == "BlueMoney" && e.exercice == "JackSpearrow")
|
||||
return "views/defi-SE.html"
|
||||
else
|
||||
return "views/defi.html";
|
||||
}
|
||||
})
|
||||
.when("/", {
|
||||
controller: "HomeController",
|
||||
templateUrl: "views/home.html"
|
||||
})
|
||||
.otherwise({
|
||||
redirectTo: "/"
|
||||
});
|
||||
$locationProvider.html5Mode(true);
|
||||
})
|
||||
.run(function($rootScope) {
|
||||
$rootScope.current_theme = 0;
|
||||
$rootScope.current_exercice = 0;
|
||||
$rootScope.current_tag = undefined;
|
||||
$rootScope.notify_field = 0;
|
||||
$rootScope.issues_known_responses = 0;
|
||||
|
||||
if ('Notification' in window)
|
||||
Notification.requestPermission(function(result) {
|
||||
if (result == "granted") {
|
||||
if (localStorage && localStorage.notification)
|
||||
$rootScope.notify_field = localStorage.notification;
|
||||
else
|
||||
$rootScope.notify_field = 63;
|
||||
}
|
||||
else
|
||||
$rootScope.notify_field = 0;
|
||||
});
|
||||
})
|
||||
.controller("DataController", function($sce, $scope, $http, $rootScope, $interval, $location) {
|
||||
var actMenu = function() {
|
||||
if ($scope.my && $scope.themes) {
|
||||
var tags = {};
|
||||
angular.forEach($scope.themes, function(theme, key) {
|
||||
$scope.themes[key].exercice_solved = 0;
|
||||
var last_exercice = null;
|
||||
angular.forEach(theme.exercices, function(exercice, k) {
|
||||
if (last_exercice != null)
|
||||
last_exercice.next = k;
|
||||
last_exercice = exercice;
|
||||
|
||||
if ($scope.my.exercices && $scope.my.exercices[k] && $scope.my.exercices[k].solved) {
|
||||
$scope.themes[key].exercice_solved++;
|
||||
}
|
||||
angular.forEach(exercice.tags, function(tag) {
|
||||
if (!tags[tag])
|
||||
tags[tag] = {count: 1, solved: 0};
|
||||
else
|
||||
tags[tag].count += 1;
|
||||
if ($scope.my.exercices && $scope.my.exercices[k] && $scope.my.exercices[k].solved)
|
||||
tags[tag].solved += 1;
|
||||
});
|
||||
});
|
||||
});
|
||||
$scope.tags = tags;
|
||||
$scope.tagsl = Object.keys(tags).sort();
|
||||
}
|
||||
}
|
||||
|
||||
var refreshSettingsInterval
|
||||
var refreshSettings = function() {
|
||||
if (refreshSettingsInterval)
|
||||
$interval.cancel(refreshSettingsInterval);
|
||||
refreshSettingsInterval = $interval(refreshSettings, Math.floor(Math.random() * 24000) + 32000);
|
||||
|
||||
$http.get("settings.json").then(function(response) {
|
||||
var time = $rootScope.recvTime(response);
|
||||
if (response.data.start)
|
||||
response.data.start = new Date(response.data.start);
|
||||
if (response.data.end)
|
||||
response.data.end = new Date(response.data.end);
|
||||
if (response.data.generation)
|
||||
response.data.generation = new Date(response.data.generation);
|
||||
if (response.data.activateTime)
|
||||
response.data.activateTime = new Date(response.data.activateTime);
|
||||
if ($rootScope.settings === undefined || response.data.activateTime === undefined || response.data.activateTime <= new Date(Date.now() + (time.cu - time.he))) {
|
||||
$rootScope.settings = response.data;
|
||||
if (response.data.eventKindness && refreshEventsInterval) {
|
||||
$interval.cancel(refreshEventsInterval);
|
||||
refreshEventsInterval = null;
|
||||
}
|
||||
else if (!response.data.eventKindness && !refreshEventsInterval) {
|
||||
refreshEvents();
|
||||
}
|
||||
}
|
||||
else
|
||||
$rootScope.settings.activateTime = response.data.activateTime;
|
||||
});
|
||||
}
|
||||
|
||||
var refreshIssuesInterval
|
||||
var refreshIssues = function() {
|
||||
if (refreshIssuesInterval)
|
||||
$interval.cancel(refreshIssuesInterval);
|
||||
refreshIssuesInterval = $interval(refreshIssues, Math.floor(Math.random() * 24000) + 32000);
|
||||
|
||||
$http.get("issues.json").then(function(response) {
|
||||
$rootScope.issues_idx = {};
|
||||
$rootScope.issues_nb_responses = 0;
|
||||
$rootScope.issues_need_info = 0;
|
||||
$rootScope.issues = response.data;
|
||||
$rootScope.issues.forEach(function(issue) {
|
||||
$rootScope.issues_idx[issue.id] = issue;
|
||||
$rootScope.issues_nb_responses += issue.texts.length;
|
||||
if (issue.state == 'need-info') $rootScope.issues_need_info++;
|
||||
})
|
||||
}, function(error) {});
|
||||
}
|
||||
|
||||
var refreshThemesInterval
|
||||
var refreshThemes = function() {
|
||||
if (refreshThemesInterval)
|
||||
$interval.cancel(refreshThemesInterval);
|
||||
refreshThemesInterval = $interval(refreshThemes, Math.floor(Math.random() * 24000) + 32000);
|
||||
|
||||
$http.get("themes.json").then(function(response) {
|
||||
$scope.themes = response.data;
|
||||
$scope.max_gain = 0;
|
||||
$scope.max_solved = 0;
|
||||
$scope.themesUrl = {};
|
||||
$scope.exercicesUrl = {};
|
||||
angular.forEach(response.data, function(theme, key) {
|
||||
$scope.themesUrl[theme.urlid] = key;
|
||||
this[key].exercice_count = Object.keys(theme.exercices).length;
|
||||
this[key].exercice_coeff_max = 0;
|
||||
this[key].gain = 0;
|
||||
this[key].solved = 0;
|
||||
angular.forEach(theme.exercices, function(ex, k) {
|
||||
$scope.exercicesUrl[theme.urlid + "/" + ex.urlid] = k;
|
||||
this.gain += ex.gain;
|
||||
this.solved += ex.solved;
|
||||
this.exercice_coeff_max = Math.max(this.exercice_coeff_max, ex.curcoeff);
|
||||
}, theme);
|
||||
$scope.max_gain += theme.gain;
|
||||
$scope.max_solved = Math.max($scope.max_solved, theme.solved);
|
||||
}, response.data);
|
||||
actMenu();
|
||||
});
|
||||
}
|
||||
|
||||
var refreshTeamsInterval;
|
||||
$rootScope.refreshTeams = function() {
|
||||
if (refreshTeamsInterval)
|
||||
$interval.cancel(refreshTeamsInterval);
|
||||
refreshTeamsInterval = $interval($rootScope.refreshTeams, Math.floor(Math.random() * 24000) + 32000);
|
||||
|
||||
$http.get("teams.json").then(function(response) {
|
||||
var teams = response.data;
|
||||
$scope.teams_count = Object.keys(teams).length
|
||||
$scope.teams = teams;
|
||||
|
||||
$scope.rank = [];
|
||||
angular.forEach($scope.teams, function(team, tid) {
|
||||
team.id = tid;
|
||||
this.push(team);
|
||||
}, $scope.rank);
|
||||
});
|
||||
}
|
||||
|
||||
var refreshEventsInterval;
|
||||
var eventsLastRefresh;
|
||||
var eventsLastTreated;
|
||||
var refreshEvents = function() {
|
||||
if (refreshEventsInterval)
|
||||
$interval.cancel(refreshEventsInterval);
|
||||
var refreshRate = 1200;
|
||||
if ($rootScope.notify_field == 0 && eventsLastTreated)
|
||||
refreshRate = 30000;
|
||||
if ($scope.my && !$scope.my.team_id)
|
||||
return;
|
||||
refreshEventsInterval = $interval(refreshEvents, Math.floor(Math.random() * refreshRate * 2) + refreshRate);
|
||||
|
||||
if (!eventsLastTreated) {
|
||||
eventsLastTreated = $rootScope.getSrvTime();
|
||||
if (!eventsLastTreated)
|
||||
return;
|
||||
}
|
||||
|
||||
$http.get("events.json").then(function(response) {
|
||||
if (eventsLastRefresh != undefined && eventsLastRefresh == response.headers()["last-modified"])
|
||||
return;
|
||||
eventsLastRefresh = response.headers()["last-modified"];
|
||||
|
||||
var maxTimeSeen = eventsLastTreated;
|
||||
for (var i = response.data.length - 1; i >= 0; i--) {
|
||||
var event = response.data[i];
|
||||
|
||||
event.time = new Date(event.time);
|
||||
if (event.time <= eventsLastTreated)
|
||||
continue;
|
||||
else if (event.time > maxTimeSeen)
|
||||
maxTimeSeen = event.time;
|
||||
|
||||
// Determine the kind of event
|
||||
var kind = 1;
|
||||
|
||||
if (event.txt.match(/<\/strong> qui vient de nous rejoindre/)) {
|
||||
kind = 64;
|
||||
} else {
|
||||
var res = event.txt.match(/(\w+) le <strong>\d+<sup>e<\/sup><\/strong> défi [^&]+/)
|
||||
if (res) {
|
||||
if (res[1] == "résolu")
|
||||
kind = 8;
|
||||
else if (res[1] == "pour")
|
||||
kind = 16;
|
||||
else if (res[1] == "tente")
|
||||
kind = 32;
|
||||
}
|
||||
}
|
||||
if (kind != 1) {
|
||||
if ($scope.my && $scope.my.name && event.txt.indexOf($scope.my.name) >= 0)
|
||||
kind |= 2;
|
||||
else
|
||||
kind |= 4;
|
||||
}
|
||||
|
||||
if ((kind & $rootScope.notify_field) == kind) {
|
||||
var notification = new Notification("Challenge forensic", {body: event.txt.replace(/&#(\d+);/g, function(match, dec) {return String.fromCharCode(dec);}).replace(/(<([^>]+)>)/ig,""), badge: "/img/icon-" + event.kind + ".ico", icon: "/img/icon-" + event.kind + ".ico"});
|
||||
notification.onclick = function(ev) {
|
||||
$location.url("edit");
|
||||
};
|
||||
setTimeout(notification.close.bind(notification), 4000);
|
||||
}
|
||||
};
|
||||
|
||||
if (maxTimeSeen > eventsLastTreated)
|
||||
eventsLastTreated = maxTimeSeen;
|
||||
});
|
||||
}
|
||||
|
||||
var refreshMyInterval;
|
||||
var refreshMy = function() {
|
||||
if (refreshMyInterval)
|
||||
$interval.cancel(refreshMyInterval);
|
||||
refreshMyInterval = $interval(refreshMy, Math.floor(Math.random() * 24000) + 24000);
|
||||
|
||||
$http.get("my.json").then(function(response) {
|
||||
$rootScope.recvMy(response.data);
|
||||
}, function(response) {
|
||||
if (!$scope.my && response.status == 404) {
|
||||
$location.url("register");
|
||||
}
|
||||
});
|
||||
}
|
||||
$rootScope.recvMy = function(data) {
|
||||
if (data.team_id == 0) {
|
||||
angular.forEach(data.exercices, function(exercice, eid) {
|
||||
angular.forEach(exercice.hints, function(hint, hid) {
|
||||
if ($scope.my && $scope.my.exercices[eid] && $scope.my.exercices[eid].hints[hid] && $scope.my.exercices[eid].hints[hid].hidden !== undefined)
|
||||
data.exercices[eid].hints[hid].hidden = $scope.my.exercices[eid].hints[hid].hidden;
|
||||
else
|
||||
data.exercices[eid].hints[hid].hidden = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
angular.forEach(data.exercices, function(exercice, eid) {
|
||||
if ($scope.my && $scope.my.exercices[eid] && $scope.my.exercices[eid].submitted)
|
||||
data.exercices[eid].timeouted = true;
|
||||
if ($scope.my && $scope.my.exercices[eid] && $scope.my.exercices[eid].solved !== undefined)
|
||||
data.exercices[eid].solved = $scope.my.exercices[eid].solved;
|
||||
if ($scope.my && $scope.my.exercices[eid] && $scope.my.exercices[eid].solved_time !== undefined && data.exercices[eid].solved_time === undefined)
|
||||
data.exercices[eid].solved_time = $scope.my.exercices[eid].solved_time;
|
||||
if ($scope.my && $scope.my.exercices[eid] && $scope.my.exercices[eid].tries !== undefined && data.exercices[eid].tries === undefined)
|
||||
data.exercices[eid].tries = $scope.my.exercices[eid].tries;
|
||||
angular.forEach(exercice.flags, function(flag, fid) {
|
||||
if ($scope.my && $scope.my.exercices[eid] && $scope.my.exercices[eid].flags && $scope.my.exercices[eid].flags[fid] && $scope.my.exercices[eid].flags[fid].found !== undefined)
|
||||
data.exercices[eid].flags[fid].found = $scope.my.exercices[eid].flags[fid].found;
|
||||
if ($scope.my && $scope.my.exercices[eid] && $scope.my.exercices[eid].flags && $scope.my.exercices[eid].flags[fid] && $scope.my.exercices[eid].flags[fid].value !== undefined)
|
||||
data.exercices[eid].flags[fid].value = $scope.my.exercices[eid].flags[fid].value;
|
||||
if ($scope.my && $scope.my.exercices[eid] && $scope.my.exercices[eid].flags && $scope.my.exercices[eid].flags[fid] && $scope.my.exercices[eid].flags[fid].values !== undefined)
|
||||
data.exercices[eid].flags[fid].values = $scope.my.exercices[eid].flags[fid].values;
|
||||
else if (data.exercices[eid].flags[fid].nb_lines)
|
||||
data.exercices[eid].flags[fid].values = Array(data.exercices[eid].flags[fid].nb_lines);
|
||||
else
|
||||
data.exercices[eid].flags[fid].values = [""];
|
||||
});
|
||||
angular.forEach(exercice.mcqs, function(mcq, mid) {
|
||||
if ($scope.my && $scope.my.exercices[eid] && $scope.my.exercices[eid].mcqs && $scope.my.exercices[eid].mcqs[mid] && $scope.my.exercices[eid].mcqs[mid].solved !== undefined)
|
||||
data.exercices[eid].mcqs[mid].solved = $scope.my.exercices[eid].mcqs[mid].solved;
|
||||
});
|
||||
});
|
||||
angular.forEach(data.exercices, function(exercice, eid) {
|
||||
angular.forEach(exercice.mcqs, function(mcq, mid) {
|
||||
angular.forEach(mcq.choices, function(choice, cid) {
|
||||
if (!(choice instanceof Object))
|
||||
this[cid] = {
|
||||
label: choice,
|
||||
};
|
||||
|
||||
this[cid].disabled = mcq.solved || mcq.part_solved || (this[cid].justification && this[cid].justification.solved);
|
||||
|
||||
if (!this[cid].disabled)
|
||||
this[cid].value = $scope.my && $scope.my.exercices[eid] && $scope.my.exercices[eid].mcqs && $scope.my.exercices[eid].mcqs[mid] && $scope.my.exercices[eid].mcqs[mid].choices[cid] && $scope.my.exercices[eid].mcqs[mid].choices[cid].value
|
||||
|
||||
if (mcq.justify) {
|
||||
if (!this[cid].justification)
|
||||
this[cid].justification = {};
|
||||
|
||||
if (!this[cid].justification.label) {
|
||||
this[cid].justification.label = "Flag correspondant";
|
||||
this[cid].justification.help = "Trouvez et validez les choix du QCM pour avoir des indications supplémentaires";
|
||||
}
|
||||
|
||||
if ($scope.my && $scope.my.exercices[eid] && $scope.my.exercices[eid].mcqs[mid] && $scope.my.exercices[eid].mcqs[mid].choices[cid] && $scope.my.exercices[eid].mcqs[mid].choices[cid].justification) {
|
||||
if ($scope.my.exercices[eid].mcqs[mid].choices[cid].justification.value !== undefined)
|
||||
data.exercices[eid].mcqs[mid].choices[cid].justification.value = $scope.my.exercices[eid].mcqs[mid].choices[cid].justification.value;
|
||||
if ($scope.my.exercices[eid].mcqs[mid].choices[cid].justification.values !== undefined)
|
||||
data.exercices[eid].mcqs[mid].choices[cid].justification.values = $scope.my.exercices[eid].mcqs[mid].choices[cid].justification.values;
|
||||
else
|
||||
data.exercices[eid].mcqs[mid].choices[cid].justification.values = [""];
|
||||
}
|
||||
else
|
||||
data.exercices[eid].mcqs[mid].choices[cid].justification.values = [""];
|
||||
}
|
||||
}, mcq.choices);
|
||||
});
|
||||
});
|
||||
$scope.my = data;
|
||||
angular.forEach($scope.my.exercices, function(exercice, eid) {
|
||||
exercice.solved = exercice.solved_rank > 0;
|
||||
if (exercice.video_uri) {
|
||||
exercice.video_uri = $sce.trustAsResourceUrl(exercice.video_uri);
|
||||
}
|
||||
});
|
||||
actMenu();
|
||||
}
|
||||
|
||||
$rootScope.refresh = function(justMy, justSettings) {
|
||||
if (!justMy) {
|
||||
refreshSettings();
|
||||
refreshThemes();
|
||||
$rootScope.refreshTeams();
|
||||
refreshEvents();
|
||||
refreshIssues();
|
||||
}
|
||||
else if (justSettings) {
|
||||
refreshSettings();
|
||||
}
|
||||
refreshMy();
|
||||
}
|
||||
$rootScope.refreshIssues = refreshIssues;
|
||||
$rootScope.refresh();
|
||||
})
|
||||
.controller("ExerciceController", function($scope, $routeParams, $http, $rootScope, $timeout) {
|
||||
if (window.scrollY > 112)
|
||||
window.scrollTo(window.scrollX, 112);
|
||||
|
||||
$rootScope.current_tag = undefined;
|
||||
|
||||
$scope.$watch("themesUrl", function(themesUrl) {
|
||||
if (themesUrl != undefined)
|
||||
$rootScope.current_theme = themesUrl[$routeParams.theme];
|
||||
})
|
||||
|
||||
if ($routeParams.exercice) {
|
||||
$scope.$watch("exercicesUrl", function(exercicesUrl) {
|
||||
if (exercicesUrl != undefined)
|
||||
$rootScope.current_exercice = exercicesUrl[$routeParams.theme + "/" + $routeParams.exercice];
|
||||
})
|
||||
$scope.$watchGroup(["themes", "current_theme", "current_exercice"], function(newValues) {
|
||||
var themes = newValues[0];
|
||||
var current_theme = newValues[1];
|
||||
var current_exercice = newValues[2];
|
||||
if (themes != undefined && themes[current_theme] != undefined && themes[current_theme].exercices != undefined && themes[current_theme].exercices[current_exercice] != undefined)
|
||||
$rootScope.title = themes[current_theme].name + " > " + themes[current_theme].exercices[current_exercice].title;
|
||||
});
|
||||
} else {
|
||||
$rootScope.current_exercice = 0;
|
||||
$scope.$watchGroup(["themes", "current_theme"], function(newValues) {
|
||||
var themes = newValues[0];
|
||||
var current_theme = newValues[1];
|
||||
if (themes != undefined && themes[current_theme] != undefined)
|
||||
$rootScope.title = themes[current_theme].name;
|
||||
});
|
||||
}
|
||||
|
||||
var cbh;
|
||||
$scope.hsubmit = function(hint) {
|
||||
hint.submitted = true;
|
||||
$scope.hinterror = null;
|
||||
$http({ url: "openhint/" + $rootScope.current_exercice, method: "POST", data: { id: hint.id } }).then(function(response) {
|
||||
var checkDiffHint = function() {
|
||||
$http.get("my.json").then(function(response) {
|
||||
var my = response.data;
|
||||
angular.forEach(my.exercices[$rootScope.current_exercice].hints, function(h,hid){
|
||||
if (hint.id == h.id) {
|
||||
if (hint.content != h.content) {
|
||||
$rootScope.recvMy(my);
|
||||
} else {
|
||||
if (cbh)
|
||||
$timeout.cancel(cbh);
|
||||
cbh = $timeout(checkDiffHint, 750);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
checkDiffHint();
|
||||
}, function(response) {
|
||||
$scope.hinterror = response.data.errmsg;
|
||||
hint.submitted = false;
|
||||
});
|
||||
};
|
||||
})
|
||||
.controller("SubmissionController", function($scope, $http, $rootScope, $timeout) {
|
||||
$scope.sberr = null;
|
||||
|
||||
var cbs;
|
||||
var cbd;
|
||||
|
||||
$scope.ssubmit = function() {
|
||||
var resp = {}
|
||||
var check = undefined
|
||||
$scope.sberr = null;
|
||||
|
||||
if ($scope.my.exercices[$rootScope.current_exercice].flags && Object.keys($scope.my.exercices[$rootScope.current_exercice].flags).length)
|
||||
{
|
||||
resp["flags"] = {};
|
||||
angular.forEach($scope.my.exercices[$rootScope.current_exercice].flags, function(flag,kid) {
|
||||
if (check === undefined) check = true;
|
||||
|
||||
check &= treatFlagKey(flag) || flag.found;
|
||||
if (flag.soluce === undefined) {
|
||||
check = undefined;
|
||||
if (flag.found == null) {
|
||||
resp["flags"][kid] = flag.value;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if ($scope.my.exercices[$rootScope.current_exercice].mcqs && Object.keys($scope.my.exercices[$rootScope.current_exercice].mcqs).length)
|
||||
{
|
||||
resp["mcqs"] = {};
|
||||
angular.forEach($scope.my.exercices[$rootScope.current_exercice].mcqs, function(mcq) {
|
||||
var soluce = "";
|
||||
if (mcq.solved == null) {
|
||||
angular.forEach(mcq.choices, function(choice, cid) {
|
||||
if (mcq.soluce !== undefined) {
|
||||
if (check === undefined) check = true;
|
||||
|
||||
soluce += choice.value ? "t" : "f";
|
||||
} else {
|
||||
if (choice.value) {
|
||||
resp["mcqs"][cid] = choice.value;
|
||||
if (choice.justification !== undefined) {
|
||||
if (resp["justifications"] == undefined)
|
||||
resp["justifications"] = {};
|
||||
treatFlagKey(choice.justification);
|
||||
resp["justifications"][cid] = choice.justification.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (mcq.soluce !== undefined) {
|
||||
if (mcq.soluce == b2sum(soluce))
|
||||
mcq.solved = new Date();
|
||||
check &= mcq.solved;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (check !== undefined)
|
||||
{
|
||||
if (!$scope.my.exercices[$rootScope.current_exercice].tries)
|
||||
$scope.my.exercices[$rootScope.current_exercice].tries = 0;
|
||||
$scope.my.exercices[$rootScope.current_exercice].tries += 1;
|
||||
$scope.my.exercices[$rootScope.current_exercice].solved_time = new Date();
|
||||
|
||||
if (check) {
|
||||
$scope.my.exercices[$rootScope.current_exercice].solved = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$http({ url: "submit/" + $rootScope.current_exercice, method: "POST", data: resp }).then(function(response) {
|
||||
$scope.messageClass = {"text-success": true};
|
||||
$scope.message = response.data.errmsg;
|
||||
$scope.sberr = null;
|
||||
|
||||
angular.forEach($scope.flags, function(flag,kid) {
|
||||
flag.value = "";
|
||||
});
|
||||
|
||||
var checkDiff = function() {
|
||||
$http.get("my.json").then(function(response) {
|
||||
var my = response.data;
|
||||
if ($scope.my.exercices[$rootScope.current_exercice].tries != my.exercices[$rootScope.current_exercice].tries || $scope.my.exercices[$rootScope.current_exercice].solved_time != my.exercices[$rootScope.current_exercice].solved_time) {
|
||||
$scope.my.exercices[$rootScope.current_exercice].submitted = false;
|
||||
$rootScope.recvMy(my);
|
||||
$rootScope.refreshTeams();
|
||||
} else {
|
||||
if (cbd)
|
||||
$timeout.cancel(cbd);
|
||||
cbd = $timeout(checkDiff, 750);
|
||||
}
|
||||
});
|
||||
};
|
||||
checkDiff();
|
||||
}, function(response) {
|
||||
if (response.status >= 500) {
|
||||
$scope.my.exercices[$rootScope.current_exercice].submitted = false;
|
||||
}
|
||||
$scope.messageClass = {"text-danger": true};
|
||||
$scope.sberr = "Oups !";
|
||||
$scope.message = response.data.errmsg;
|
||||
});
|
||||
$scope.my.exercices[$rootScope.current_exercice].timeouted = false;
|
||||
$scope.my.exercices[$rootScope.current_exercice].submitted = true;
|
||||
};
|
||||
|
||||
$scope.wantchoices = function(kid) {
|
||||
$scope.my.exercices[$rootScope.current_exercice].flags[kid].wcsubmitted = true;
|
||||
$http({ url: "wantchoices/" + $rootScope.current_exercice, method: "POST", data: { id: Math.floor(kid) } }).then(function(response) {
|
||||
var checkDiffWC = function() {
|
||||
$http.get("my.json").then(function(response) {
|
||||
var my = response.data;
|
||||
if (my.exercices[$rootScope.current_exercice].flags[kid].choices)
|
||||
$rootScope.recvMy(my);
|
||||
else {
|
||||
if (cbd)
|
||||
$timeout.cancel(cbd);
|
||||
cbd = $timeout(checkDiffWC, 750);
|
||||
}
|
||||
});
|
||||
};
|
||||
checkDiffWC();
|
||||
}, function(response) {
|
||||
$scope.messageClass = {"text-danger": true};
|
||||
$scope.sberr = "Oups !";
|
||||
$scope.message = response.data.errmsg;
|
||||
$scope.my.exercices[$rootScope.current_exercice].flags[kid].wcsubmitted = false;
|
||||
});
|
||||
}
|
||||
})
|
||||
.controller("IssueController", function($scope, $http, $rootScope, $routeParams) {
|
||||
$rootScope.current_tag = undefined;
|
||||
$rootScope.current_exercice = $routeParams.eid;
|
||||
$rootScope.issues_known_responses = $rootScope.issues_nb_responses;
|
||||
|
||||
$scope.issue = {
|
||||
id: parseInt($routeParams.iid, 10),
|
||||
id_exercice: parseInt($routeParams.eid, 10),
|
||||
subject: "",
|
||||
description: "",
|
||||
}
|
||||
|
||||
$scope.isubmit = function() {
|
||||
$rootScope.sberr = "";
|
||||
if (!$scope.issue.id && $scope.issue.subject.length < 3) {
|
||||
$rootScope.messageClass = {"text-danger": true};
|
||||
$rootScope.sberr = "L'objet de votre rapport d'anomalie est trop court !";
|
||||
return false;
|
||||
}
|
||||
|
||||
$http({
|
||||
url: "submit/issue",
|
||||
method: "POST",
|
||||
data: $scope.issue
|
||||
}).then(function(response) {
|
||||
$rootScope.messageClass = {"text-success": true};
|
||||
$rootScope.message = response.data.errmsg;
|
||||
$scope.issue.subject = "";
|
||||
$scope.issue.description = "";
|
||||
setTimeout($rootScope.refreshIssues, 1750);
|
||||
}, function(response) {
|
||||
$rootScope.messageClass = {"text-danger": true};
|
||||
$rootScope.message = response.data.errmsg;
|
||||
if (response.status != 402) {
|
||||
$rootScope.sberr = "Une erreur est survenue lors de l'envoi. Veuillez réessayer dans quelques instants.";
|
||||
}
|
||||
});
|
||||
};
|
||||
})
|
||||
.controller("MyTeamController", function($scope, $http, $rootScope, $timeout, $location) {
|
||||
$rootScope.current_theme = 0;
|
||||
$rootScope.current_exercice = 0;
|
||||
$rootScope.current_tag = undefined;
|
||||
if ($scope.my) {
|
||||
$rootScope.title = $scope.my.name;
|
||||
$rootScope.authors = $scope.my.members.map(function (cur) {
|
||||
return cur.firstname.capitalize() + " " + cur.lastname.capitalize();
|
||||
}).join(", ");
|
||||
}
|
||||
$rootScope.message = "";
|
||||
$rootScope.sberr = "";
|
||||
|
||||
$scope.notify = {
|
||||
info: ($rootScope.notify_field & 1) != 1,
|
||||
team: ($rootScope.notify_field & 2) != 2,
|
||||
others: ($rootScope.notify_field & 4) != 4,
|
||||
solve: ($rootScope.notify_field & 8) != 8,
|
||||
hint: ($rootScope.notify_field & 16) != 16,
|
||||
tries: ($rootScope.notify_field & 32) != 32,
|
||||
rename: ($rootScope.notify_field & 64) != 64,
|
||||
}
|
||||
|
||||
$scope.alternotify = function() {
|
||||
$rootScope.notify_field =
|
||||
($scope.notify.info?0:1) |
|
||||
($scope.notify.team?0:2) |
|
||||
($scope.notify.others?0:4) |
|
||||
($scope.notify.solve?0:8) |
|
||||
($scope.notify.hint?0:16) |
|
||||
($scope.notify.tries?0:32) |
|
||||
($scope.notify.rename?0:64);
|
||||
if ($rootScope.notify_field != 0)
|
||||
localStorage.notification = $rootScope.notify_field;
|
||||
else
|
||||
delete localStorage.notification;
|
||||
$location.url(".");
|
||||
}
|
||||
|
||||
var cbt;
|
||||
|
||||
$scope.tsubmit = function() {
|
||||
$rootScope.sberr = "";
|
||||
if ($scope.my.newName.length < 1) {
|
||||
$rootScope.messageClass = {"text-danger": true};
|
||||
$rootScope.sberr = "Nom d'équipe invalide: pas d'entrée.";
|
||||
return false;
|
||||
}
|
||||
else if ($scope.my.newName.length > 32) {
|
||||
$rootScope.messageClass = {"text-danger": true};
|
||||
$rootScope.sberr = "Nom d'équipe invalide: pas plus de 32 caractères.";
|
||||
return false;
|
||||
}
|
||||
else if (!$scope.my.newName.match(/^[A-Za-z0-9 àéèêëîïôùûü_-]+$/)) {
|
||||
$rootScope.messageClass = {"text-danger": true};
|
||||
$rootScope.sberr = "Nom d'équipe invalide: seuls les caractères alpha-numériques sont autorisés.";
|
||||
return false;
|
||||
}
|
||||
|
||||
$http({
|
||||
url: "submit/name",
|
||||
method: "POST",
|
||||
data: {newName: $scope.my.newName}
|
||||
}).then(function(response) {
|
||||
$rootScope.messageClass = {"text-success": true};
|
||||
$rootScope.message = response.data.errmsg;
|
||||
|
||||
var checkDiff = function() {
|
||||
$http.get("my.json").then(function(response) {
|
||||
if ($scope.my.name != response.data.name) {
|
||||
$scope.my.newName = undefined;
|
||||
$rootScope.message = "";
|
||||
$rootScope.recvMy(response.data);
|
||||
$rootScope.refreshTeams();
|
||||
} else {
|
||||
if (cbt)
|
||||
$timeout.cancel(cbt);
|
||||
cbt = $timeout(checkDiff, 750);
|
||||
}
|
||||
});
|
||||
};
|
||||
checkDiff();
|
||||
}, function(response) {
|
||||
$rootScope.messageClass = {"text-danger": true};
|
||||
$rootScope.message = response.data.errmsg;
|
||||
if (response.status != 402) {
|
||||
$rootScope.sberr = "Une erreur est survenue lors de l'envoi. Veuillez réessayer dans quelques instants.";
|
||||
}
|
||||
});
|
||||
};
|
||||
})
|
||||
.controller("RegisterController", function($scope, $rootScope, $location, $http, $interval) {
|
||||
$rootScope.current_theme = 0;
|
||||
$rootScope.current_exercice = 0;
|
||||
$rootScope.current_tag = undefined;
|
||||
$rootScope.title = "Bienvenue au challenge forensic !";
|
||||
$rootScope.authors = null;
|
||||
|
||||
$scope.form = {"teamName": "", "jTeam": 0, "members": [{}]};
|
||||
|
||||
$scope.AddMember = function() {
|
||||
$scope.form.members.push({});
|
||||
}
|
||||
$scope.RemoveMember = function(k) {
|
||||
$scope.form.members.splice(k, 1);
|
||||
}
|
||||
$scope.Validate = function() {
|
||||
if ($scope.form.teamName.length <= 3) {
|
||||
$('#teamName').addClass("is-invalid")
|
||||
return;
|
||||
} else {
|
||||
$('#teamName').removeClass("is-invalid")
|
||||
$('#vldBtn').removeClass("input-group-btn");
|
||||
$('#vldBtn').css("display", "none");
|
||||
$('#jvldBtn').css("display", "none");
|
||||
$scope.partR = true;
|
||||
$scope.partJ = false;
|
||||
}
|
||||
}
|
||||
$scope.JValidate = function() {
|
||||
if (!$scope.teams[$scope.form.jTeam]) {
|
||||
$('#jTeam').addClass("is-invalid")
|
||||
return;
|
||||
} else {
|
||||
$('#jTeam').removeClass("is-invalid")
|
||||
$('#jvldBtn').removeClass("input-group-btn");
|
||||
$('#jvldBtn').css("display", "none");
|
||||
$('#vldBtn').css("display", "none");
|
||||
$scope.partR = false;
|
||||
$scope.partJ = true;
|
||||
}
|
||||
}
|
||||
|
||||
var commonsubmit = function(registration) {
|
||||
// Remove empty members
|
||||
$scope.form.members = $scope.form.members.filter(function(m) {
|
||||
return ((m.lastname != undefined && m.lastname != "") || (m.firstname != undefined && m.firstname != "") || (m.nickname != undefined && m.nickname != ""));
|
||||
});
|
||||
|
||||
if ($scope.form.members.length == 0) {
|
||||
$scope.messageClass = {"text-danger": true};
|
||||
$scope.message = "Veuillez ajouter au moins un membre dans votre équipe !";
|
||||
|
||||
$scope.form.members.push({});
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.form.jTeam = parseInt($scope.form.jTeam);
|
||||
|
||||
$http({
|
||||
url: "registration",
|
||||
method: "POST",
|
||||
data: $scope.form
|
||||
}).then(function(response) {
|
||||
$scope.messageClass = {"text-success": true};
|
||||
$scope.message = response.data.errmsg;
|
||||
|
||||
$interval(function(){
|
||||
$http.get("my.json").then(function(response) {
|
||||
$rootScope.refresh();
|
||||
});
|
||||
}, 1500);
|
||||
|
||||
}, function(response) {
|
||||
$scope.messageClass = {"text-danger": true};
|
||||
if (response.data && response.data.errmsg)
|
||||
$scope.message = response.data.errmsg;
|
||||
else
|
||||
$scope.message = "Une erreur est survenue lors de l'inscription de l'équipe. Veuillez réessayer dans quelques instants.";
|
||||
});
|
||||
}
|
||||
|
||||
$scope.rsubmit = function() {
|
||||
if (!$scope.partR)
|
||||
return $scope.Validate();
|
||||
else
|
||||
return commonsubmit(true);
|
||||
}
|
||||
|
||||
$scope.jsubmit = function() {
|
||||
if (!$scope.partJ)
|
||||
return $scope.JValidate();
|
||||
else
|
||||
return commonsubmit(false);
|
||||
}
|
||||
|
||||
$scope.$watch("my", function(my){
|
||||
if (my)
|
||||
$location.url("/");
|
||||
});
|
||||
})
|
||||
.controller("TagController", function($scope, $rootScope, $routeParams, $location) {
|
||||
$rootScope.current_theme = 0;
|
||||
$rootScope.current_exercice = 0;
|
||||
$rootScope.current_tag = $routeParams.tag;
|
||||
$rootScope.title = "Challenges " + $routeParams.tag;
|
||||
$rootScope.authors = "";
|
||||
|
||||
$scope.tag = $routeParams.tag;
|
||||
$scope.exercices = [];
|
||||
|
||||
$scope.$watch("themes", function(themes) {
|
||||
$scope.exercices = [];
|
||||
angular.forEach(themes, function(theme, tid) {
|
||||
angular.forEach(theme.exercices, function(exercice, eid) {
|
||||
if (exercice.tags.indexOf($scope.tag) >= 0)
|
||||
$scope.exercices.push({"exercice": exercice, "theme": theme, "eid": eid, "tid": tid});
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
$scope.goDefi = function() {
|
||||
$location.url(this.ex.theme.urlid + "/" + this.ex.exercice.urlid);
|
||||
}
|
||||
|
||||
})
|
||||
.controller("RankController", function($scope, $rootScope) {
|
||||
$rootScope.current_theme = 0;
|
||||
$rootScope.current_exercice = 0;
|
||||
$rootScope.current_tag = undefined;
|
||||
$rootScope.title = "Classement général";
|
||||
$rootScope.authors = "";
|
||||
|
||||
$scope.fields = ["rank", "name", "score"];
|
||||
$scope.rankOrder = "rank";
|
||||
$scope.reverse = false;
|
||||
$scope.order = function(fld) {
|
||||
if ($scope.rankOrder == fld) {
|
||||
$scope.reverse = !$scope.reverse;
|
||||
} else {
|
||||
$scope.rankOrder = fld;
|
||||
$scope.reverse = (fld == "score");
|
||||
}
|
||||
};
|
||||
})
|
||||
.controller("VideosController", function($scope, $rootScope) {
|
||||
$rootScope.current_theme = 0;
|
||||
$rootScope.current_exercice = 0;
|
||||
$rootScope.current_tag = undefined;
|
||||
$rootScope.title = "Vidéos de résolution";
|
||||
$rootScope.authors = "";
|
||||
})
|
||||
.controller("HomeController", function($scope, $rootScope, $location) {
|
||||
$rootScope.current_theme = 0;
|
||||
$rootScope.current_exercice = 0;
|
||||
$rootScope.current_tag = undefined;
|
||||
$rootScope.title = "Bienvenue au challenge forensic de l'ÉPITA !";
|
||||
$rootScope.authors = "";
|
||||
|
||||
$scope.goTheme = function() {
|
||||
$location.url(this.theme.urlid);
|
||||
}
|
||||
});
|
||||
|
||||
function sready() {
|
||||
if ($("#solution").val().length) {
|
||||
$("#sbmt").removeClass("disabled");
|
||||
} else {
|
||||
$("#sbmt").addClass("disabled");
|
||||
}
|
||||
};
|
|
@ -1 +0,0 @@
|
|||
../../../admin/static/js/common.js
|
1
frontend/static/js/d3.v3.min.js
vendored
|
@ -1 +0,0 @@
|
|||
../../../admin/static/js/d3.v3.min.js
|
|
@ -1 +0,0 @@
|
|||
../../../admin/static/js/i18n/
|
1
frontend/static/js/jquery.min.js
vendored
|
@ -1 +0,0 @@
|
|||
../../../admin/static/js/jquery.min.js
|
|
@ -1,2 +0,0 @@
|
|||
User-agent: *
|
||||
Disallow: /
|
|
@ -1,130 +0,0 @@
|
|||
<nav role="navigation">
|
||||
<ol class="breadcrumb">
|
||||
<li ng-repeat="(k,exercice) in themes[current_theme].exercices" class="breadcrumb-item" ng-class="{active: k == current_exercice}">
|
||||
<a class="text-muted" ng-if="(k != current_exercice && !my.exercices[k])">{{ exercice.title }}</a>
|
||||
<a ng-href="{{ themes[current_theme].urlid }}/{{ themes[current_theme].exercices[k].urlid }}" ng-if="(k != current_exercice && my.exercices[k])" ng-class="{'text-success': my.exercices[k].solved}">
|
||||
{{ exercice.title }}
|
||||
<span class="glyphicon glyphicon-gift" aria-hidden="true" ng-if="themes[current_theme].exercices[k].curcoeff > 1.0"></span>
|
||||
<span class="glyphicon glyphicon-ok text-success" aria-hidden="true" ng-if="(my.team_id && my.exercices[k].solved)"></span>
|
||||
</a>
|
||||
<strong ng-if="k == current_exercice" class="text-info">
|
||||
{{ exercice.title }}
|
||||
<span class="glyphicon glyphicon-gift" aria-hidden="true" ng-if="themes[current_theme].exercices[k].curcoeff > 1.0"></span>
|
||||
<span class="glyphicon glyphicon-ok text-success" aria-hidden="true" ng-if="(my.team_id && my.exercices[k].solved)"></span>
|
||||
</strong>
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<div class="alert alert-warning mt-3" ng-if="!(my.exercices[current_exercice])">
|
||||
Vous n'avez pas encore accès à cet exercice.
|
||||
</div>
|
||||
<div class="jumbotron niceborder text-indent mt-3" ng-if="!(my.exercices[current_exercice])">
|
||||
<p class="lead text-justify" ng-bind-html="themes[current_theme].headline"></p>
|
||||
<p class="text-justify" ng-bind-html="themes[current_theme].intro"></p>
|
||||
</div>
|
||||
<div class="jumbotron niceborder text-indent mt-3" ng-if="(my.exercices[current_exercice])">
|
||||
<a ng-if="settings.acceptNewIssue" class="float-right btn btn-sm btn-warning" ng-href="issue/{{ current_exercice }}"><span class="glyphicon glyphicon-warning-sign" aria-hidden="true"></span> Rapporter une anomalie sur cet exercice</a>
|
||||
<h3 class="display-4">{{ themes[current_theme].exercices[current_exercice].title }}</h3>
|
||||
<a ng-href="tags/{{tag}}" class="badge badge-pill badge-secondary mr-2 mb-2" ng-repeat="tag in themes[current_theme].exercices[current_exercice].tags">#{{ tag }}</a>
|
||||
<p class="lead text-justify" ng-bind-html="my.exercices[current_exercice].statement"></p>
|
||||
<div class="alert alert-{{my.exercices[current_exercice].issuekind}}" ng-if="my.exercices[current_exercice].issue" ng-bind-html="my.exercices[current_exercice].issue"></div>
|
||||
<div ng-if="(my.exercices[current_exercice] && my.exercices[current_exercice].hints.length)">
|
||||
<p class="text-danger" ng-if="hinterror" ng-bind="hinterror"></p>
|
||||
<p ng-repeat="hint in my.exercices[current_exercice].hints">
|
||||
<span class="glyphicon glyphicon-lamp" aria-hidden="true"></span>
|
||||
<strong ng-bind="hint.title"></strong>
|
||||
<span ng-if="!hint.file && hint.content && !hint.hidden" ng-bind-html="hint.content"></span>
|
||||
<a ng-href="{{ hint.file }}" ng-if="hint.file">b2sum : <samp class="cksum" title="Somme de contrôle BLAKE2b : {{ hint.content }}">{{ hint.content }}</samp></a>
|
||||
<span ng-if="!hint.file && ((!hint.content && hint.hidden === undefined) || hint.hidden === true)">Débloquer cet indice vous fera perdre <ng-pluralize count="hint.cost * settings.hintCurrentCoefficient" when="{'one': '{} point', 'other': '{} points'}"></ng-pluralize>.</span>
|
||||
<button type="button" ng-click="hsubmit(hint)" class="btn btn-sm btn-info" ng-if="!(hint.content || hint.file)" ng-class="{disabled: hint.submitted}"><span class="glyphicon glyphicon-lock" aria-hidden="true"></span> Débloquer</button>
|
||||
<button type="button" ng-click="hint.hidden = false;" class="btn btn-sm btn-info" ng-if="!hint.file && hint.hidden"><span class="glyphicon glyphicon-lock" aria-hidden="true"></span> Afficher</button>
|
||||
</p>
|
||||
</div>
|
||||
<hr class="my-3">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<ul>
|
||||
<li><strong>Gain :</strong> <ng-pluralize count="themes[current_theme].exercices[current_exercice].gain" when="{'one': '{} point', 'other': '{} points'}"></ng-pluralize> <em ng-if="settings.firstBlood && themes[current_theme].exercices[current_exercice].solved < 1">{{ 1 + settings.firstBlood | coeff }} prem's</em> <em ng-if="themes[current_theme].exercices[current_exercice].curcoeff != 1.0 || settings.exerciceCurrentCoefficient != 1.0">{{ themes[current_theme].exercices[current_exercice].curcoeff * settings.exerciceCurrentCoefficient | coeff }} bonus</em></li>
|
||||
<li ng-if="themes[current_theme].exercices[current_exercice].tried"><strong>Tenté par :</strong> <ng-pluralize count="themes[current_theme].exercices[current_exercice].tried" when="{'0': 'aucune équipe', 'one': '{} équipe', 'other': '{} équipes'}"></ng-pluralize> <span ng-if="my.exercices[current_exercice].total_tries">(cumulant <ng-pluralize count="my.exercices[current_exercice].total_tries" when="{'one': '{} tentative', 'other': '{} tentatives'}"></ng-pluralize>)</span></li>
|
||||
<li><strong>Résolu par :</strong> <ng-pluralize count="themes[current_theme].exercices[current_exercice].solved" when="{'0': 'aucune équipe', 'one': '{} équipe', 'other': '{} équipes'}"></ng-pluralize></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col list-group">
|
||||
<a ng-href="{{ file.path }}" target="_self" class="list-group-item" ng-repeat="file in my.exercices[current_exercice].files">
|
||||
<h1 class="float-left" style="margin: 7px 7px 5px -5px"><span class="glyphicon glyphicon-download" aria-hidden="true"></span></h1>
|
||||
<h4 class="list-group-item-heading"><strong><samp>{{ file.name }}</samp></strong></h4>
|
||||
<p class="list-group-item-text"><nobr>Taille : <span title="{{ file.size }} octets">{{ file.size | size }}</span></nobr> – <nobr><span title="blake2.net">b2sum</span> : <samp class="cksum" title="{{ file.checksum }}">{{ file.checksum }}</samp></nobr></p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2" ng-controller="SubmissionController">
|
||||
<div class="card border-info" ng-if="my.exercices[current_exercice] && !(my.exercices[current_exercice].solved)">
|
||||
<div class="card-header bg-info text-white">
|
||||
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> NSEC – Réinitialisation de mot de passe
|
||||
</div>
|
||||
<ul class="list-group" ng-if="(my.exercices[current_exercice].tries || my.exercices[current_exercice].submitted || sberr)">
|
||||
<li class="list-group-item text-warning" ng-if="my.exercices[current_exercice].solved_time && my.exercices[current_exercice].tries"><ng-pluralize count="my.exercices[current_exercice].tries" when="{'one': '{} tentative effectuée', 'other': '{} tentatives effectuées'}"></ng-pluralize>. Dernière tentative envoyée à {{ my.exercices[current_exercice].solved_time | date:"mediumTime" }}. <span ng-if="my.exercices[current_exercice].solve_dist"><ng-pluralize count="my.exercices[current_exercice].solve_dist" when="{'one': '{} réponse erronée', 'other': '{} réponses erronées'}"></ng-pluralize>.</span></li>
|
||||
<li class="list-group-item" ng-class="messageClass" ng-if="my.exercices[current_exercice].submitted || sberr"><strong ng-if="!sberr">Votre demande de réinitialisation de mot de passe a bien été envoyée !</strong><strong ng-if="sberr">{{ sberr }}</strong> {{ message }}</li>
|
||||
<li class="list-group-item text-danger" ng-if="my.exercices[current_exercice].timeouted"><strong>Oops</strong> La requête a dépassé le délai d'attente. Vous devriez réessayer dans quelques instant…</li>
|
||||
</ul>
|
||||
<div class="card-body" ng-if="!my.exercices[current_exercice].submitted || sberr">
|
||||
<form ng-submit="ssubmit()">
|
||||
<flag-key ng-repeat="(kid,key) in my.exercices[current_exercice].flags" kid="kid" key="key" settings="settings" wantchoices="wantchoices"></flag-key>
|
||||
|
||||
<div class="form-group" ng-repeat="(k,mcq) in my.exercices[current_exercice].mcqs">
|
||||
<p ng-if="mcq.title"><span ng-class="{'text-light': !mcq.found}">{{ mcq.title }}</span> <span class="glyphicon glyphicon-ok form-control-feedback text-success" aria-hidden="true" ng-if="mcq.solved" title="QCM réussi à {{ mcq.solved | date:'mediumTime'}}"></span></p>
|
||||
<div class="form-check">
|
||||
<div class="custom-control custom-checkbox" ng-repeat="(cid,choice) in mcq.choices" ng-if="!mcq.solved || mcq.justify">
|
||||
<input class="custom-control-input" type="checkbox" id="mcq_{{k}}_{{cid}}" name="mcq_{{k}}_{{cid}}" ng-model="choice.value" ng-disabled="choice.disabled">
|
||||
<label class="custom-control-label" for="mcq_{{k}}_{{cid}}" ng-bind="choice.label"></label>
|
||||
<flag-key kid="cid" key="choice.justification" settings="settings" wantchoices="wantchoices" ng-if="choice.value && mcq.justify && (!choice.justification || !choice.justification.solved)"></flag-key>
|
||||
<span ng-if="choice.value && mcq.justify && choice.solved" ng-bind="choice.justify"></span>
|
||||
<span class="glyphicon glyphicon-ok form-control-feedback text-success" aria-hidden="true" ng-if="choice.solved" title="Flag trouvé !"></span>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<div class="form-group text-right">
|
||||
<button type="submit" class="btn btn-info" id="sbmt">Réinitialiser le mot de passe</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card border-success" ng-if="my.exercices[current_exercice].solved">
|
||||
<div class="card-header bg-success text-white">
|
||||
<span class="glyphicon glyphicon-flag" aria-hidden="true"></span> NSEC – Réinitialisation de mot de passe
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="card-text" ng-if="my.exercices[current_exercice].finished" ng-bind-html="my.exercices[current_exercice].finished"></p>
|
||||
<hr ng-if="my.exercices[current_exercice].finished">
|
||||
<p class="card-text font-italic" ng-if="my.exercices[current_exercice].solved_rank">
|
||||
Vous êtes la {{ my.exercices[current_exercice].solved_rank }}<sup><ng-pluralize count="my.exercices[current_exercice].solved_rank" when="{'one': 're', 'other': 'e'}"></ng-pluralize></sup> équipe à avoir résolu ce défi à {{ my.exercices[current_exercice].solved_time | date:"mediumTime" }}. Vous avez marqué <ng-pluralize count="my.exercices[current_exercice].gain" when="{'one': '{} point', 'other': '{} points'}"></ng-pluralize> !
|
||||
</p>
|
||||
<p class="card-text font-italic" ng-if="!my.exercices[current_exercice].solved_rank">
|
||||
Bravo, vous avez résolu ce défi à {{ my.exercices[current_exercice].solved_time | date:"mediumTime" }}. Vous marquez <ng-pluralize count="my.exercices[current_exercice].gain" when="{'one': '{} point', 'other': '{} points'}"></ng-pluralize> !
|
||||
</p>
|
||||
<hr ng-if="my.exercices[current_exercice].finished && themes[current_theme].exercices[current_exercice].next">
|
||||
<a href="{{ themes[current_theme].urlid }}/{{ themes[current_theme].exercices[themes[current_theme].exercices[current_exercice].next].urlid }}" class="btn btn-success" ng-if="themes[current_theme].exercices[current_exercice].next">Se connecter</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card border-success mt-2" ng-if="my.exercices[current_exercice].video_uri">
|
||||
<div class="card-header bg-success text-white">
|
||||
<span class="glyphicon glyphicon-blackboard" aria-hidden="true"></span> Solution du défi
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="embed-responsive embed-responsive-16by9">
|
||||
<iframe type="text/html" ng-src="{{ my.exercices[current_exercice].video_uri }}" class="embed-responsive-item">
|
||||
Regardez la vidéo de résolution de ce défi : <a ng-href="{{ my.exercices[current_exercice].video_uri }}">{{ my.exercices[current_exercice].video_uri }}</a>.
|
||||
</iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,149 +0,0 @@
|
|||
<nav role="navigation">
|
||||
<ol class="breadcrumb">
|
||||
<li ng-repeat="(k,exercice) in themes[current_theme].exercices" class="breadcrumb-item" ng-class="{active: k == current_exercice}">
|
||||
<a class="text-muted" ng-if="(k != current_exercice && !my.exercices[k])">{{ exercice.title }}</a>
|
||||
<a ng-href="{{ themes[current_theme].urlid }}/{{ themes[current_theme].exercices[k].urlid }}" ng-if="(k != current_exercice && my.exercices[k])" ng-class="{'text-success': my.exercices[k].solved}">
|
||||
{{ exercice.title }}
|
||||
<span class="glyphicon glyphicon-gift" aria-hidden="true" ng-if="themes[current_theme].exercices[k].curcoeff > 1.0"></span>
|
||||
<span class="glyphicon glyphicon-ok text-success" aria-hidden="true" ng-if="(my.team_id && my.exercices[k].solved)"></span>
|
||||
</a>
|
||||
<strong ng-if="k == current_exercice" class="text-info">
|
||||
{{ exercice.title }}
|
||||
<span class="glyphicon glyphicon-gift" aria-hidden="true" ng-if="themes[current_theme].exercices[k].curcoeff > 1.0"></span>
|
||||
<span class="glyphicon glyphicon-ok text-success" aria-hidden="true" ng-if="(my.team_id && my.exercices[k].solved)"></span>
|
||||
</strong>
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<div class="alert alert-warning mt-3" ng-if="!(my.exercices[current_exercice])">
|
||||
Vous n'avez pas encore accès à cet exercice.
|
||||
</div>
|
||||
<div class="jumbotron niceborder text-indent mt-3" ng-if="!(my.exercices[current_exercice])">
|
||||
<p class="lead text-justify" ng-bind-html="themes[current_theme].headline"></p>
|
||||
<p class="text-justify" ng-bind-html="themes[current_theme].intro"></p>
|
||||
</div>
|
||||
<div class="jumbotron niceborder text-indent mt-3" ng-if="(my.exercices[current_exercice])">
|
||||
<h3 class="display-4">{{ themes[current_theme].exercices[current_exercice].title }}</h3>
|
||||
<a ng-href="tags/{{tag}}" class="badge badge-pill badge-secondary mr-2 mb-2" ng-repeat="tag in themes[current_theme].exercices[current_exercice].tags">#{{ tag }}</a>
|
||||
<p class="lead text-justify" ng-bind-html="my.exercices[current_exercice].statement"></p>
|
||||
<div class="alert alert-{{my.exercices[current_exercice].issuekind}}" ng-if="my.exercices[current_exercice].issue" ng-bind-html="my.exercices[current_exercice].issue"></div>
|
||||
<hr class="my-3">
|
||||
<a ng-if="settings.acceptNewIssue" class="float-right btn btn-sm btn-warning" ng-href="issue/{{ current_exercice }}"><span class="glyphicon glyphicon-warning-sign" aria-hidden="true"></span> Rapporter une anomalie sur cet exercice</a>
|
||||
<a ng-if="settings.QAenabled" class="float-right btn btn-sm btn-info" ng-href="/qa/exercices/{{ current_exercice }}" target="_self"><span class="glyphicon glyphicon-warning-sign" aria-hidden="true"></span> Voir les éléments QA sur cet exercice</a>
|
||||
<ul>
|
||||
<li><strong>Gain :</strong> <ng-pluralize count="themes[current_theme].exercices[current_exercice].gain" when="{'one': '{} point', 'other': '{} points'}"></ng-pluralize> <em ng-if="settings.firstBlood && themes[current_theme].exercices[current_exercice].solved < 1">{{ 1 + settings.firstBlood | coeff }} prem's</em> <em ng-if="themes[current_theme].exercices[current_exercice].curcoeff != 1.0 || settings.exerciceCurrentCoefficient != 1.0">{{ themes[current_theme].exercices[current_exercice].curcoeff * settings.exerciceCurrentCoefficient | coeff }} bonus</em></li>
|
||||
<li ng-if="themes[current_theme].exercices[current_exercice].tried"><strong>Tenté par :</strong> <ng-pluralize count="themes[current_theme].exercices[current_exercice].tried" when="{'0': 'aucune équipe', 'one': '{} équipe', 'other': '{} équipes'}"></ng-pluralize> <span ng-if="my.exercices[current_exercice].total_tries">(cumulant <ng-pluralize count="my.exercices[current_exercice].total_tries" when="{'one': '{} tentative', 'other': '{} tentatives'}"></ng-pluralize>)</span></li>
|
||||
<li><strong>Résolu par :</strong> <ng-pluralize count="themes[current_theme].exercices[current_exercice].solved" when="{'0': 'aucune équipe', 'one': '{} équipe', 'other': '{} équipes'}"></ng-pluralize></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-xl mb-5" ng-if="(my.exercices[current_exercice] && (my.exercices[current_exercice].files.length || my.exercices[current_exercice].hints.length))">
|
||||
<div class="card mb-2" ng-if="my.exercices[current_exercice].files.length">
|
||||
<div class="card-header text-white">
|
||||
<span class="glyphicon glyphicon-download-alt" aria-hidden="true"></span> Téléchargements
|
||||
</div>
|
||||
<div class="card-body text-indent">
|
||||
<p class="card-text text-danger text-justify">
|
||||
<strong>Attention :</strong> puisqu'il s'agit de captures effectuées dans le but de découvrir si des actes malveillants ont été commis, les contenus qui sont téléchargeables <em>peuvent</em> contenir du contenu malveillant !
|
||||
</p>
|
||||
</div>
|
||||
<div class="list-group">
|
||||
<a ng-href="{{ file.path }}" target="_self" class="list-group-item" ng-repeat="file in my.exercices[current_exercice].files">
|
||||
<h1 class="float-left" style="margin: 7px 7px 5px -5px"><span class="glyphicon glyphicon-download" aria-hidden="true"></span></h1>
|
||||
<h4 class="list-group-item-heading"><strong><samp>{{ file.name }}</samp></strong></h4>
|
||||
<p class="list-group-item-text"><nobr>Taille : <span title="{{ file.size }} octets">{{ file.size | size }}</span></nobr> – <nobr><span title="blake2.net">b2sum</span> : <samp class="cksum" title="{{ file.checksum }}">{{ file.checksum }}</samp></nobr></p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card border-info mb-2" ng-if="my.exercices[current_exercice].hints.length">
|
||||
<div class="card-header bg-info text-white">
|
||||
<span class="glyphicon glyphicon-lamp" aria-hidden="true"></span> Indices
|
||||
</div>
|
||||
<div class="card-body" ng-if="hinterror">
|
||||
<div class="card-text text-danger" ng-bind="hinterror"></div>
|
||||
</div>
|
||||
<div class="list-group">
|
||||
<a target="_self" class="list-group-item text-light" ng-repeat="hint in my.exercices[current_exercice].hints" ng-href="{{ hint.file }}">
|
||||
<button type="button" ng-click="hsubmit(hint)" class="float-right btn btn-info" ng-if="!(hint.content || hint.file)" ng-class="{disabled: hint.submitted}"><span class="glyphicon glyphicon-lock" aria-hidden="true"></span> Débloquer</button>
|
||||
<button type="button" ng-click="hint.hidden = false;" class="float-right btn btn-info" ng-if="!hint.file && hint.hidden"><span class="glyphicon glyphicon-lock" aria-hidden="true"></span> Afficher</button>
|
||||
<h1 class="float-left" style="margin: 5px 7px 5px -5px" ng-if="hint.file"><span class="glyphicon glyphicon-download" aria-hidden="true"></span></h1>
|
||||
<h4 class="list-group-item-heading">{{ hint.title }}</h4>
|
||||
<p class="list-group-item-text" ng-if="!hint.file && hint.content && !hint.hidden" ng-bind-html="hint.content"></p>
|
||||
<p class="list-group-item-text" ng-if="hint.file">Cliquez ici pour télécharger l'indice.<br>b2sum : <samp class="cksum" title="Somme de contrôle BLAKE2b : {{ hint.content }}">{{ hint.content }}</samp></p>
|
||||
<p class="list-group-item-text" ng-if="!hint.file && ((!hint.content && hint.hidden === undefined) || hint.hidden === true)">Débloquer cet indice vous fera perdre <ng-pluralize count="hint.cost * settings.hintCurrentCoefficient" when="{'one': '{} point', 'other': '{} points'}"></ng-pluralize>.</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-xl mb-5" ng-controller="SubmissionController">
|
||||
<div class="card border-danger" ng-if="my.exercices[current_exercice] && !(my.exercices[current_exercice].solved)">
|
||||
<div class="card-header bg-danger text-white">
|
||||
<span class="glyphicon glyphicon-flag" aria-hidden="true"></span> Faire son rapport
|
||||
</div>
|
||||
<ul class="list-group" ng-if="(my.exercices[current_exercice].tries || my.exercices[current_exercice].submitted || sberr)">
|
||||
<li class="list-group-item text-warning" ng-if="my.exercices[current_exercice].solved_time && my.exercices[current_exercice].tries"><ng-pluralize count="my.exercices[current_exercice].tries" when="{'one': '{} tentative effectuée', 'other': '{} tentatives effectuées'}"></ng-pluralize>. Dernière solution envoyée à {{ my.exercices[current_exercice].solved_time | date:"mediumTime" }}. <span ng-if="my.exercices[current_exercice].solve_dist"><ng-pluralize count="my.exercices[current_exercice].solve_dist" when="{'one': '{} réponse erronée', 'other': '{} réponses erronées'}"></ng-pluralize>.</span></li>
|
||||
<li class="list-group-item" ng-class="messageClass" ng-if="my.exercices[current_exercice].submitted || sberr"><strong ng-if="!sberr">Votre solution a bien été envoyée !</strong><strong ng-if="sberr">{{ sberr }}</strong> {{ message }}</li>
|
||||
<li class="list-group-item text-danger" ng-if="my.exercices[current_exercice].timeouted"><strong>Oops</strong> La requête a dépassé le délai d'attente. Vous devriez réessayer dans quelques instant…</li>
|
||||
</ul>
|
||||
<div class="card-body" ng-if="!my.exercices[current_exercice].submitted || sberr">
|
||||
<form ng-submit="ssubmit()">
|
||||
<flag-key ng-repeat="(kid,key) in my.exercices[current_exercice].flags" kid="kid" key="key" settings="settings" wantchoices="wantchoices"></flag-key>
|
||||
|
||||
<div class="form-group" ng-repeat="(k,mcq) in my.exercices[current_exercice].mcqs">
|
||||
<p ng-if="mcq.title"><span ng-class="{'text-light': !mcq.found}">{{ mcq.title }}</span> <span class="glyphicon glyphicon-ok form-control-feedback text-success" aria-hidden="true" ng-if="mcq.solved" title="QCM réussi à {{ mcq.solved | date:'mediumTime'}}"></span></p>
|
||||
<div class="form-check">
|
||||
<div class="custom-control custom-checkbox" ng-repeat="(cid,choice) in mcq.choices" ng-if="!mcq.solved || mcq.justify">
|
||||
<input class="custom-control-input" type="checkbox" id="mcq_{{k}}_{{cid}}" name="mcq_{{k}}_{{cid}}" ng-model="choice.value" ng-disabled="choice.disabled">
|
||||
<label class="custom-control-label" for="mcq_{{k}}_{{cid}}" ng-bind="choice.label"></label>
|
||||
<flag-key kid="cid" key="choice.justification" settings="settings" wantchoices="wantchoices" ng-if="choice.value && mcq.justify && (!choice.justification || !choice.justification.solved)"></flag-key>
|
||||
<span ng-if="choice.value && mcq.justify && choice.solved" ng-bind="choice.justify"></span>
|
||||
<span class="glyphicon glyphicon-ok form-control-feedback text-success" aria-hidden="true" ng-if="choice.solved" title="Flag trouvé !"></span>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<div class="form-group text-right">
|
||||
<button type="submit" class="btn btn-danger" id="sbmt">Soumettre</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card border-success" ng-if="my.exercices[current_exercice].solved">
|
||||
<div class="card-header bg-success text-white">
|
||||
<span class="glyphicon glyphicon-flag" aria-hidden="true"></span> Défi réussi !
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="card-text" ng-if="my.exercices[current_exercice].solved_rank">
|
||||
Vous êtes la {{ my.exercices[current_exercice].solved_rank }}<sup><ng-pluralize count="my.exercices[current_exercice].solved_rank" when="{'one': 're', 'other': 'e'}"></ng-pluralize></sup> équipe à avoir résolu ce défi à {{ my.exercices[current_exercice].solved_time | date:"mediumTime" }}. Vous avez marqué <ng-pluralize count="my.exercices[current_exercice].gain" when="{'one': '{} point', 'other': '{} points'}"></ng-pluralize> !
|
||||
</p>
|
||||
<p class="card-text" ng-if="!my.exercices[current_exercice].solved_rank">
|
||||
Bravo, vous avez résolu ce défi à {{ my.exercices[current_exercice].solved_time | date:"mediumTime" }}. Vous marquez <ng-pluralize count="my.exercices[current_exercice].gain" when="{'one': '{} point', 'other': '{} points'}"></ng-pluralize> !
|
||||
</p>
|
||||
<hr ng-if="my.exercices[current_exercice].finished">
|
||||
<p class="card-text" ng-if="my.exercices[current_exercice].finished" ng-bind-html="my.exercices[current_exercice].finished"></p>
|
||||
<hr ng-if="my.exercices[current_exercice].finished && themes[current_theme].exercices[current_exercice].next">
|
||||
<a href="{{ themes[current_theme].urlid }}/{{ themes[current_theme].exercices[themes[current_theme].exercices[current_exercice].next].urlid }}" class="btn btn-success" ng-if="themes[current_theme].exercices[current_exercice].next">Passer au défi suivant</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card border-success mt-2" ng-if="my.exercices[current_exercice].video_uri">
|
||||
<div class="card-header bg-success text-white">
|
||||
<span class="glyphicon glyphicon-blackboard" aria-hidden="true"></span> Solution du défi
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="embed-responsive embed-responsive-16by9">
|
||||
<iframe type="text/html" ng-src="{{ my.exercices[current_exercice].video_uri }}" class="embed-responsive-item">
|
||||
Regardez la vidéo de résolution de ce défi : <a ng-href="{{ my.exercices[current_exercice].video_uri }}">{{ my.exercices[current_exercice].video_uri }}</a>.
|
||||
</iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,27 +0,0 @@
|
|||
<div class="alert alert-danger" ng-if="my && !(my.team_id)">
|
||||
<strong>Attention :</strong> puisqu'il s'agit de captures effectuées dans le but de découvrir si des actes malveillants ont été commis sur différents systèmes d'information, les contenus qui sont téléchargeables <em>peuvent</em> contenir du contenu malveillant !
|
||||
</div>
|
||||
<div class="alert text-justify" ng-if="(my.team_id)" style="background-color: #4eaee6;">
|
||||
<strong>Félicitations <span ng-repeat="member in my.members"><span ng-if="$last && !$first"> et </span><span ng-if="$middle">, </span>{{ member.firstname | capitalize }} {{ member.lastname | capitalize }}</span> !</strong> vous êtes maintenant connecté à l'espace de votre équipe <em>{{ teams[my.team_id].name }}</em>. Vous pouvez changer ce nom dès maintenant en vous rendant sur la page de <a href="edit">votre équipe</a>.
|
||||
</div>
|
||||
<div class="alert alert-warning text-justify" ng-if="(my.team_id && !my.members.length)">
|
||||
<strong>Les membres de votre équipe ne sont pas encore enregistrés.</strong> Passez voir l'équipe serveur pour corriger cela.
|
||||
</div>
|
||||
<div class="alert alert-warning text-justify" ng-if="!my && settings.allowRegistration">
|
||||
<strong>Votre équipe n'est pas encore enregistrée.</strong> Rendez-vous sur <a href="register">cette page</a> pour procéder à votre inscription.
|
||||
</div>
|
||||
<div class="alert alert-danger text-justify" ng-if="!my && !settings.allowRegistration">
|
||||
<strong>Il semblerait qu'il y ait eu un problème lors de l'attribution de votre certificat.</strong> Veuillez vous signaler auprès de notre équipe afin de corriger ce problème.
|
||||
</div>
|
||||
|
||||
<div class="card-columns">
|
||||
<div class="card niceborder excard" ng-repeat="(k,theme) in themes" ng-click="goTheme()" ng-class="{'border-success': my.team_id && theme.solved > 0, 'border-warning': theme.exercice_coeff_max > 1}">
|
||||
<div class="card-img-top theme-card" ng-show="theme.image" style="background-image: url({{ theme.image.substr(0, theme.image.length-3) }}thumb.jpg)"></div>
|
||||
<div class="card-body text-indent">
|
||||
<h5 class="card-title">
|
||||
<a ng-href="{{ theme.urlid }}">{{ theme.name }}</a>
|
||||
</h5>
|
||||
<p class="card-text text-justify" ng-bind-html="theme.headline"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,80 +0,0 @@
|
|||
|
||||
<div class="card niceborder border-warning bg-primary text-light" ng-if="issues.length > 0">
|
||||
<table class="table table-hover table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Objet</th>
|
||||
<th>État / Priorité</th>
|
||||
<th>Géré par</th>
|
||||
<th>Messages</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="issue in issues">
|
||||
<td>{{ issue.subject }} <span ng-if="issue.exercice">(challenge {{ issue.exercice }})</span></td>
|
||||
<td>{{ issue.state }} / {{ issue.priority }}</td>
|
||||
<td>{{ issue.assignee }}</td>
|
||||
<td>
|
||||
<p ng-repeat="text in issue.texts | orderBy:'date':'reverse'" style="margin-left: 15px; text-indent: -15px">
|
||||
<span ng-if="text.assignee == null || text.assignee == '$team'">Vous</span>
|
||||
<span ng-if="text.assignee != null && text.assignee != '$team'" ng-bind="text.assignee"></span> à {{ text.date | date:"mediumTime" }} :
|
||||
<span style="white-space: pre-line">{{ text.cnt }}</span>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<a ng-href="/issues/{{ issue.id }}#myIssue" class="btn btn-sm" ng-class="{'btn-danger': issue.state == 'need-info', 'btn-light': issue.state != 'need-info'}"><span class="glyphicon glyphicon-envelope"></span></a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="card border-warning mt-3" ng-if="!settings.acceptNewIssue">
|
||||
<div class="card-header bg-warning text-light">Rapporter une anomalie sur un exercice</div>
|
||||
<div class="card-body">
|
||||
<p class="card-text">Rapprochez-vous d'un membre de l'équipe serveur afin d'obtenir de l'aide.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card border-warning mt-3 mb-4" ng-if="settings.acceptNewIssue" id="myIssue">
|
||||
<div class="card-header bg-warning text-light" ng-if="!issue.id">Rapporter une anomalie <span ng-if="issue.id_exercice">sur un exercice</span></div>
|
||||
<div class="card-header bg-warning text-light" ng-if="issue.id">Répondre à un rapport d'anomalie</div>
|
||||
<div class="card-body">
|
||||
<p ng-class="messageClass" ng-if="message || sberr"><strong ng-if="!sberr">Votre rapport a bien été envoyé !</strong><strong ng-if="sberr">{{ sberr }}</strong> {{ message }}</p>
|
||||
<form ng-submit="isubmit()">
|
||||
|
||||
<div class="form-group row" ng-if="issue.id_exercice">
|
||||
<label for="idExercice" class="col-sm-2 col-form-label">Exercice</label>
|
||||
<div class="col-sm-10" ng-if="current_theme">
|
||||
<input type="text" readonly class="form-control-plaintext" id="idExercice" value="{{ themes[current_theme].exercices[issue.id_exercice].title }}">
|
||||
</div>
|
||||
<div class="col-sm-10" ng-if="!current_theme">
|
||||
<input type="text" readonly class="form-control-plaintext" id="idExercice" value="{{ issue.id_exercice }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row" ng-if="issue.id && issues_idx[issue.id]">
|
||||
<label for="subject" class="col col-form-label">Objet</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" readonly class="form-control-plaintext" id="subject" value="Re: {{ issues_idx[issue.id].subject }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row" ng-if="!issue.id || !issues_idx[issue.id]">
|
||||
<label for="subject" class="col col-form-label">Objet</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="subject" ng-model="issue.subject" placeholder="Intitulé succinct">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label for="description" class="col col-form-label">Description</label>
|
||||
<div class="col-sm-10">
|
||||
<textarea class="form-control" id="description" ng-model="issue.description" placeholder="Décrivez en détail votre problème ici. Si nécessaire, incluez un lien vers une capture d'écran montrant votre problème."></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="float-right btn btn-warning">Envoyer le rapport</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
|
@ -1,22 +0,0 @@
|
|||
<div class="card niceborder bg-primary text-light">
|
||||
<div class="card-body">
|
||||
<input type="search" class="form-control" placeholder="Rechercher" ng-model="query">
|
||||
</div>
|
||||
<table class="table table-hover table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th ng-repeat="field in fields" ng-click="order(field)" width="33%">
|
||||
{{ field | rankTitle }}
|
||||
<span class="glyphicon" ng-if="rankOrder === field" ng-class="{'glyphicon-chevron-up': reverse, 'glyphicon-chevron-down': !reverse}"></span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="team in rank | filter: query | orderBy:rankOrder:reverse" ng-click="show(team.id)" ng-if="team.rank" ng-class="{'bg-info': my.team_id == team.id}">
|
||||
<td>{{ team.rank }}</td>
|
||||
<td>{{ team.name }}</td>
|
||||
<td>{{ team.score | number:0 }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
|
@ -1,135 +0,0 @@
|
|||
<div class="jumbotron niceborder" style="text-indent: 1em" ng-if="!settings.allowRegistration">
|
||||
<p>
|
||||
Félicitations ! vous êtes maintenant authentifié auprès de notre
|
||||
serveur !
|
||||
</p>
|
||||
<div class="alert alert-danger">
|
||||
<strong>Oups, il semblerait qu'il y ait eu un problème lors de l'attribution de votre certificat.</strong>
|
||||
Veuillez vous signaler auprès de notre équipe afin de corriger ce problème.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="jumbotron niceborder" style="text-indent: 1em" ng-if="settings.allowRegistration && !settings.denyTeamCreation">
|
||||
<p>
|
||||
<strong>Félicitations ! vous êtes maintenant authentifié·e auprès de
|
||||
notre serveur !</strong>
|
||||
</p>
|
||||
<p>
|
||||
Votre équipe n'est pas encore enregistrée sur notre serveur. Afin de
|
||||
pouvoir participer au challenge, nous vous remercions de bien vouloir
|
||||
remplir le formulaire d'inscription suivant :
|
||||
</p>
|
||||
<form ng-submit="rsubmit()">
|
||||
|
||||
<div class="row">
|
||||
<label for="teamName" class="col col-form-label">Nom d'équipe</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" id="teamName" ng-model="form.teamName" placeholder="" autofocus required>
|
||||
<span class="input-group-append" id="vldBtn">
|
||||
<button class="btn btn-info" type="button" ng-click="Validate()" ng-disabled="form.jTeam">Valider</button>
|
||||
</span>
|
||||
<div class="invalid-feedback">
|
||||
Veuillez indiquer un nom d'équipe valide.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="partR">
|
||||
<h4 style="text-indent: 0; margin-top: 20px" ng-if="!settings.canJoinTeam">
|
||||
Membres d'équipe
|
||||
<button class="btn btn-sm btn-success" type="button" ng-click="AddMember()">
|
||||
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Ajouter un membre
|
||||
</button>
|
||||
</h4>
|
||||
<h4 style="text-indent: 0; margin-top: 20px" ng-if="settings.canJoinTeam">
|
||||
Chef d'équipe
|
||||
</h4>
|
||||
<p ng-if="message" ng-class="messageClass" ng-bind="message"></p>
|
||||
<div class="row form-group" ng-repeat="(mid, member) in form.members">
|
||||
<div class="col-sm">
|
||||
<input type="text" class="form-control" ng-model="member.lastname" placeholder="Nom" autofocus>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<input type="text" class="form-control" ng-model="member.firstname" placeholder="Prénom">
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<input type="text" class="form-control" ng-model="member.nickname" placeholder="Pseudo">
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<input type="text" class="form-control" ng-model="member.company" placeholder="Entreprise">
|
||||
</div>
|
||||
<div class="col-sm-auto" ng-if="!settings.canJoinTeam">
|
||||
<button class="btn btn-danger" type="button" ng-click="RemoveMember(mid)">
|
||||
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-info" style="margin-left: 40%;" type="submit" ng-disabled="form.jTeam">
|
||||
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
|
||||
S'inscrire
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="jumbotron niceborder" style="text-indent: 1em" ng-if="settings.canJoinTeam">
|
||||
<p ng-if="settings.denyTeamCreation">
|
||||
<strong>Félicitations ! vous êtes maintenant authentifié·e auprès de
|
||||
notre serveur !</strong>
|
||||
</p>
|
||||
<p ng-if="!settings.denyTeamCreation">
|
||||
Si votre équipe est déjà créée, rejoignez-là !
|
||||
</p>
|
||||
<p ng-if="settings.denyTeamCreation">
|
||||
Vous n'êtes pas encore enregistré·e sur notre serveur. Afin de
|
||||
pouvoir participer au challenge, nous vous remercions de bien vouloir
|
||||
rejoindre votre équipe :
|
||||
</p>
|
||||
<form ng-submit="jsubmit()">
|
||||
|
||||
<div class="row">
|
||||
<label for="jTeam" class="col col-form-label">Nom d'équipe</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group">
|
||||
<select class="custom-select" id="jTeam" ng-model="form.jTeam" ng-options="tid as t.name for (tid,t) in teams" required ng-disabled="partJ">
|
||||
</select>
|
||||
<span class="input-group-append" id="jvldBtn">
|
||||
<button class="btn btn-info" type="button" ng-click="JValidate()" ng-disabled="form.teamName">Valider</button>
|
||||
</span>
|
||||
<div class="invalid-feedback">
|
||||
Veuillez sélectionner une équipe valide.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="partJ">
|
||||
<h4 style="text-indent: 0; margin-top: 20px">
|
||||
Vos informations
|
||||
</h4>
|
||||
<p ng-if="message" ng-class="messageClass" ng-bind="message"></p>
|
||||
<div class="row form-group" ng-repeat="(mid, member) in form.members">
|
||||
<div class="col-sm">
|
||||
<input type="text" class="form-control" ng-model="member.lastname" placeholder="Nom" autofocus>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<input type="text" class="form-control" ng-model="member.firstname" placeholder="Prénom">
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<input type="text" class="form-control" ng-model="member.nickname" placeholder="Pseudo">
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<input type="text" class="form-control" ng-model="member.company" placeholder="Entreprise">
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-info" style="margin-left: 40%;" type="submit" ng-disabled="form.teamName">
|
||||
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
|
||||
Rejoindre
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
|
@ -1,128 +0,0 @@
|
|||
<div class="card-group text-justify mb-5">
|
||||
<div class="card niceborder">
|
||||
<div class="card-body text-indent">
|
||||
<h2>Débloquage des challenges</h2>
|
||||
<p>
|
||||
Au début, seul le premier défi de chaque scénario est
|
||||
accessible. Les défis de niveau supérieur sont débloqués en
|
||||
validant celui du niveau qui le précéde.
|
||||
</p>
|
||||
<hr>
|
||||
|
||||
<h2>Le classement</h2>
|
||||
<p>
|
||||
Pour figurer dans le classement, il faut avoir réalisé au moins une
|
||||
action : qu'elle ajoute ou retire des points.
|
||||
</p>
|
||||
<p>
|
||||
En cas d'égalité au score, les équipes sont départagées selon leur
|
||||
ordre d'arrivée à ce score.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<h2>Calcul des points</h2>
|
||||
<p>
|
||||
Pour gagner des points, vous devez résoudre les défis qui vous sont
|
||||
proposés. Plus le challenge est compliqué, plus il rapporte de points.
|
||||
</p>
|
||||
|
||||
<h3>Coût des tentatives</h3>
|
||||
<p>
|
||||
Vous disposez de 10 tentatives pour trouver la/les solutions d'un
|
||||
challenge. Au delà, chaque tentative vous fait perdre une petite quantité
|
||||
de points comme suit :
|
||||
</p>
|
||||
<table class="table table-sm table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nombre de tentatives</th>
|
||||
<th>Coût par tentative</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>0 à 10</td>
|
||||
<td>0 point</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>11 à 20</td>
|
||||
<td><ng-pluralize count="settings.submissionCostBase" when="{'one': '{} point', 'other': '{} points'}"></ng-pluralize></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>21 à 30</td>
|
||||
<td><ng-pluralize count="settings.submissionCostBase * 2" when="{'one': '{} point', 'other': '{} points'}"></ng-pluralize></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>31 à 40</td>
|
||||
<td><ng-pluralize count="settings.submissionCostBase * 3" when="{'one': '{} point', 'other': '{} points'}"></ng-pluralize></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>41 à 50</td>
|
||||
<td><ng-pluralize count="settings.submissionCostBase * 4" when="{'one': '{} point', 'other': '{} points'}"></ng-pluralize></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>...</td>
|
||||
<td>...</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card niceborder">
|
||||
<div class="card-body text-indent">
|
||||
<p>
|
||||
Par exemple :
|
||||
</p>
|
||||
<ul>
|
||||
<li>À 10 tentatives, vous aurez perdu <ng-pluralize count="settings.submissionCostBase * 0" when="{'one': '{} point', 'other': '{} points'}"></ng-pluralize>.</li>
|
||||
<li>À 15 tentatives, vous aurez perdu en tout <ng-pluralize count="settings.submissionCostBase * 5" when="{'one': '{} point', 'other': '{} points'}"></ng-pluralize> : <samp>{{ settings.submissionCostBase }} * 5</samp>.</li>
|
||||
<li>25 tentatives vous coûteront en tout <ng-pluralize count="settings.submissionCostBase * 20" when="{'one': '{} point', 'other': '{} points'}"></ng-pluralize> : <samp>{{ settings.submissionCostBase }} * 10 + {{ settings.submissionCostBase * 2}} * 5</samp>.</li>
|
||||
<li>50 tentatives vous coûteront en tout <ng-pluralize count="settings.submissionCostBase * 100" when="{'one': '{} point', 'other': '{} points'}"></ng-pluralize> : <samp>{{ settings.submissionCostBase }} * 10 + {{ settings.submissionCostBase * 2 }} * 10 + {{ settings.submissionCostBase * 3 }} * 10 + {{ settings.submissionCostBase * 4 }} * 10</samp>.</li>
|
||||
</ul>
|
||||
<p>
|
||||
La dernière tentative (lorsque tous les flags sont bons) est comptabilisée
|
||||
parmi ce nombre de tentatives.
|
||||
</p>
|
||||
<hr>
|
||||
|
||||
<h3>Coût des indices</h3>
|
||||
<p>
|
||||
Pour vous aider, certains défis vous proposent un ou
|
||||
plusieurs <strong>indices</strong>. Ces indices vous font perdre des
|
||||
points, la valeur de points perdus est indiquée pour chaque indice.
|
||||
</p>
|
||||
<p>
|
||||
Ces points sont perdus, que vous réussissiez ou non le défi.
|
||||
</p>
|
||||
<p>
|
||||
Vous pouvez débloquer des indices même si vous ne disposez pas de
|
||||
suffisamment de points (ou même si vous n'en avez pas encore) ; dans ce
|
||||
cas, votre score sera négatif.
|
||||
</p>
|
||||
<hr>
|
||||
|
||||
<h3>Bonus</h3>
|
||||
<p>
|
||||
Plusieurs bonus peuvent s'appliquer en même temps, dans ce cas, le calcul
|
||||
du bonus est toujours effectué à partir du nombre de points initiaux du
|
||||
défi.
|
||||
</p>
|
||||
|
||||
<h4>Prem's</h4>
|
||||
<p>
|
||||
Un bonus de +{{ settings.firstBlood * 100 }} % est attribué à la première équipe qui résout un défi.
|
||||
</p>
|
||||
|
||||
<h4>Bonus temporaires <small><span class="glyphicon glyphicon-gift" aria-hidden="true" title="Des
|
||||
bonus existent pour au moins un challenge de ce thème"></span></small></h4>
|
||||
<p>
|
||||
Au cours du challenge, afin de booster les équipes ou certains challenges,
|
||||
un bonus peut-être attribué si une tentative valide est envoyée durant la
|
||||
période d'activité du bonus. Restez à l'écoute et observez les challenges
|
||||
portant cette icône : <span class="glyphicon glyphicon-gift"
|
||||
aria-hidden="true" title="Des bonus existent pour au moins un challenge de ce
|
||||
thème"></span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,16 +0,0 @@
|
|||
<div class="card-columns">
|
||||
<div class="card niceborder excard" ng-repeat="ex in exercices" ng-click="goDefi()" ng-class="{'border-success': my.team_id && ex.exercice.solved, 'border-secondary': !my.exercices[ex.eid], 'border-warning': ex.exercice.curcoeff > 1.0}">
|
||||
<div class="card-img-top theme-card" ng-show="ex.theme.image" style="background-image: url({{ ex.theme.image }})"></div>
|
||||
<div class="card-body">
|
||||
<h6 class="card-title">
|
||||
<a ng-href="{{ex.theme.urlid}}">{{ex.theme.name}}</a> >
|
||||
<a ng-href="{{ex.theme.urlid}}/{{ex.exercice.urlid}}">{{ex.exercice.title}}</a>
|
||||
<span class="glyphicon glyphicon-gift" aria-hidden="true" ng-if="ex.exercice.curcoeff > 1.0" title="Un bonus est actuellement appliqué lors de la résolution de ce défi"></span>
|
||||
</h6>
|
||||
<div class="clearfix mb-2">
|
||||
<a ng-href="tags/{{tag}}" class="badge badge-pill badge-secondary mr-2 float-right" ng-repeat="tag in themes[ex.tid].exercices[ex.eid].tags">#{{ tag }}</a>
|
||||
</div>
|
||||
<p class="card-text text-justify text-indent" ng-bind-html="ex.exercice.headline"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,103 +0,0 @@
|
|||
<div class="row mb-4">
|
||||
<div class="col-md">
|
||||
|
||||
<div class="card niceborder">
|
||||
<div class="card-header">Votre équipe est composée de :</div>
|
||||
<div class="card-body" ng-if="!my.members.length">
|
||||
Passez voir l'équipe serveur pour compléter ces informations.
|
||||
</div>
|
||||
<ul class="list-group" ng-if="my.members.length">
|
||||
<li class="list-group-item" ng-repeat="member in my.members">
|
||||
{{ member.firstname | capitalize }}
|
||||
<span style="font-style: italic" ng-if="member.nickname">{{ member.nickname }}</span>
|
||||
<span style="font-variant: small-caps;">{{ member.lastname | capitalize }}</span>
|
||||
<span ng-if="member.company">- {{ member.company}}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="card border-info mt-3" ng-if="!settings.denyNameChange">
|
||||
<div class="card-header bg-info text-light">Changer de nom d'équipe</div>
|
||||
<div class="card-body">
|
||||
<p ng-class="messageClass" ng-if="message || sberr"><strong ng-if="!sberr">Votre demande a bien été envoyée !</strong><strong ng-if="sberr">{{ sberr }}</strong> {{ message }}</p>
|
||||
<form ng-submit="tsubmit()">
|
||||
<div class="form-group row">
|
||||
<label for="newName" class="col col-form-label">Nouveau nom</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" id="newName" ng-model="my.newName" placeholder="{{ my.name }}">
|
||||
<div class="input-group-append">
|
||||
<button type="submit" class="btn btn-info">Valider</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="col-md-5" ng-if="notify_field != 0">
|
||||
|
||||
<div class="card border-success niceborder">
|
||||
<div class="card-header bg-success text-light">Gestion des notifications</div>
|
||||
<form class="card-body" ng-submit="alternotify()">
|
||||
<p>
|
||||
Ces paramètres ne seront valable que pour votre navigateur.
|
||||
</p>
|
||||
|
||||
<div class="form-check">
|
||||
<label class="custom-control custom-checkbox">
|
||||
<input class="custom-control-input" type="checkbox" disabled ng-model="notify.info">
|
||||
<span class="custom-control-label">Ne pas recevoir les notifications de l'équipe serveur.</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<label class="custom-control custom-checkbox">
|
||||
<input class="custom-control-input" type="checkbox" ng-model="notify.team">
|
||||
<span class="custom-control-label">Ne pas recevoir les notifications de mon équipe.</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<label class="custom-control custom-checkbox">
|
||||
<input class="custom-control-input" type="checkbox" ng-model="notify.others">
|
||||
<span class="custom-control-label">Ne pas recevoir les notifications des autres équipes.</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<label class="custom-control custom-checkbox">
|
||||
<input class="custom-control-input" type="checkbox" ng-model="notify.solve">
|
||||
<span class="custom-control-label">Ne pas recevoir les notifications de résolution.</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<label class="custom-control custom-checkbox">
|
||||
<input class="custom-control-input" type="checkbox" ng-model="notify.hint">
|
||||
<span class="custom-control-label">Ne pas recevoir les notifications de découverte d'indice.</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<label class="custom-control custom-checkbox">
|
||||
<input class="custom-control-input" type="checkbox" ng-model="notify.tries">
|
||||
<span class="custom-control-label">Ne pas recevoir les notifications de tentatives.</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<label class="custom-control custom-checkbox">
|
||||
<input class="custom-control-input" type="checkbox" ng-model="notify.rename">
|
||||
<span class="custom-control-label">Ne pas recevoir les notifications de nouvelle équipe.</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-success float-right">Enregistrer</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
|
@ -1,49 +0,0 @@
|
|||
<div class="card niceborder text-indent mt-2 mb-4">
|
||||
<div class="card-body bg-dark">
|
||||
<p class="mt-4 mr-3 ml-3 card-text lead text-justify" ng-bind-html="themes[current_theme].headline"></p>
|
||||
<p class="mb-4 mr-3 ml-3 card-text text-justify" ng-bind-html="themes[current_theme].intro"></p>
|
||||
</div>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item" ng-repeat="(k,exercice) in themes[current_theme].exercices">
|
||||
<div class="row">
|
||||
<div class="col-1" style="margin-top: -0.75rem; margin-bottom: -0.75rem; text-align: right">
|
||||
<svg style="height: 120px; max-height: 100%; width: 23px;">
|
||||
<rect
|
||||
style="fill:#{{ my.exercices[k].solved ? '62c462' : 'aaa' }}"
|
||||
width="5"
|
||||
height="200"
|
||||
x="10"
|
||||
y="0" />
|
||||
<rect
|
||||
style="fill:#{{ my.exercices[k] ? '62c462' : 'aaa' }}"
|
||||
width="5"
|
||||
height="30"
|
||||
x="10"
|
||||
y="0" />
|
||||
<path
|
||||
style="fill:#{{ my.exercices[k] ? (my.exercices[k].solved ? '62c462' : (themes[current_theme].exercices[k].curcoeff > 1.0 ? 'f89406' : '5bc0de')) : 'aaa' }}"
|
||||
d="m 22,24 a 9.5700617,9.5700617 0 0 1 -9.5690181,9.57006 9.5700617,9.5700617 0 0 1 -9.57110534,-9.56797 9.5700617,9.5700617 0 0 1 9.56692984,-9.57215 9.5700617,9.5700617 0 0 1 9.5731926,9.56588" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="col-10">
|
||||
<a ng-href="tags/{{tag}}" class="badge badge-pill badge-secondary ml-1 float-right" ng-repeat="tag in themes[current_theme].exercices[k].tags">#{{tag}}</a>
|
||||
<h5>
|
||||
<a ng-href="{{ themes[current_theme].urlid }}/{{ themes[current_theme].exercices[k].urlid }}" ng-if="my.exercices[k]">
|
||||
{{ exercice.title }}
|
||||
</a>
|
||||
<span ng-if="!my.exercices[k]" style="white-space: nowrap">
|
||||
<span class="glyphicon glyphicon-lock" aria-hidden="true" title="Vous n'avez pas encore accès à ce défi"></span>
|
||||
{{ exercice.title }}
|
||||
</span>
|
||||
<span class="glyphicon glyphicon-gift" aria-hidden="true" ng-if="themes[current_theme].exercices[k].curcoeff > 1.0" title="Un bonus est actuellement appliqué lors de la résolution de ce défi"></span>
|
||||
</h5>
|
||||
<p ng-bind-html="exercice.headline"></p>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<a ng-if="my.exercices[k]" class="float-right" ng-href="{{ themes[current_theme].urlid }}/{{ themes[current_theme].exercices[k].urlid }}" style="font-size: 3rem"><span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span></a>
|
||||
<span ng-if="!my.exercices[k]" class="float-right" style="font-size: 3rem"><span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span></span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
|
@ -1,10 +0,0 @@
|
|||
<div class="list-group">
|
||||
<ng-repeat ng-repeat="theme in themes">
|
||||
<h4 class="list-group-item">
|
||||
{{ theme.name }}
|
||||
</h4>
|
||||
<ng-repeat ng-repeat="(eid,exercice) in theme.exercices">
|
||||
<a class="list-group-item" href="{{ my.exercices[eid].video_uri }}">{{ exercice.title }}</a>
|
||||
</ng-repeat>
|
||||
</ng-repeat>
|
||||
</div>
|
|
@ -1,185 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Challenge Forensic</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
|
||||
<meta name="author" content="EPITA Laboratoire SRS">
|
||||
<meta name="robots" content="all">
|
||||
<link href="/css/bootstrap.min.css" type="text/css" rel="stylesheet" media="screen">
|
||||
<link href="/css/fic.css" type="text/css" rel="stylesheet" media="screen">
|
||||
</head>
|
||||
<body class="bg-light beautiful">
|
||||
|
||||
<div class="navbar navbar-expand-lg navbar-dark bg-dark text-light">
|
||||
<div class="container">
|
||||
<div class="col-md-auto">
|
||||
<a href="/">
|
||||
<img src="/img/fic.png" alt="Forum International de la Cybersécurité">
|
||||
</a>
|
||||
</div>
|
||||
<div class="clock col-md-auto text-center">Challenge Forensic</div>
|
||||
<div class="col-md-auto">
|
||||
<a href="http://www.epita.fr/">
|
||||
<img src="/img/epita.png" alt="Epita">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container text-justify" style="margin-top:20px; text-indent: 1.5em">
|
||||
<div class="jumbotron niceborder">
|
||||
<h1 style="text-indent: 0">Bienvenue !</h1>
|
||||
<p style="text-indent: 0" class="alert alert-primary">
|
||||
<strong>
|
||||
Vous n'êtes pas encore connecté en tant qu'équipe sur notre serveur.
|
||||
</strong>
|
||||
</p><hr>
|
||||
<p class="lead">
|
||||
Bienvenue dans cette première épreuve du challenge forensic !
|
||||
Votre première activité consiste à accéder au site dédié à cet
|
||||
événement ; ce guide est là pour vous y aider.
|
||||
</p>
|
||||
<br>
|
||||
<p>
|
||||
<strong>Important :</strong> La clef USB qui vous a été donnée
|
||||
contient des fichiers permettant votre authentification auprès de
|
||||
nos serveurs. Ne la laissez pas sans surveillance !
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="card niceborder" style="margin-bottom:20px;">
|
||||
<div class="card-header bg-dark">
|
||||
<h2 style="margin: 0">Installation du certificat client</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>
|
||||
Le certificat <em>client</em> est envoyé à notre serveur pour vous
|
||||
identifier et vous authentifier. Votre certificat et votre clef
|
||||
privée sont contenus sur la clef USB que nous vous avons donnée, dans
|
||||
un fichier <samp>.p12</samp>, protégé avec le mot de passe qui vous a
|
||||
été fourni sur papier.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Choisissez la procédure correspondant à votre navigateur ou système
|
||||
d'exploitation :
|
||||
</p>
|
||||
<ol>
|
||||
<li><a href="#cert-client-mozilla-firefox">Mozilla Firefox</a></li>
|
||||
<li><a href="#cert-client-chromium">Chromium/Google Chrome</a></li>
|
||||
<ol>
|
||||
<li><a href="#cert-client-chromium-windows">Sous Microsoft Windows</a></li>
|
||||
<li><a href="#cert-client-chromium-macos">Sous Mac OS</a></li>
|
||||
<li><a href="#cert-client-gnu-linux">Sous GNU/Linux, FreeBSD ou OpenBSD</a></li>
|
||||
</ol>
|
||||
<li><a href="#cert-client-ie">Internet Explorer/Edge</a></li>
|
||||
<li><a href="#cert-client-safari">Safari</a></li>
|
||||
</ol>
|
||||
<hr>
|
||||
|
||||
<p>
|
||||
Si malgré tout, vous n'arrivez pas à accéder à l'espace de votre
|
||||
équipe ou si votre clef USB est illisible, n'hésitez pas à nous
|
||||
solliciter !
|
||||
</p>
|
||||
<p>
|
||||
Bon courage !
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card niceborder" style="margin-bottom:20px;">
|
||||
<div class="card-header bg-dark">
|
||||
<h2 id="cert-client-mozilla-firefox" style="margin: 0">Mozilla Firefox</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ol>
|
||||
<li>Ouvrez la fenêtre des préférences du navigateur.</li>
|
||||
<li>Choisissez la catégorie <strong>Vie privée et sécurité</strong> (<strong>Avancé</strong> dans les versions plus anciennes).</li>
|
||||
<li>Sélectionnez l'onglet <strong>Certificats</strong>.</li>
|
||||
<li>Cliquez sur <strong>Afficher les certificats</strong>.</li>
|
||||
<li>Sélectionnez l'onglet <strong>Vos certificats</strong>.</li>
|
||||
<li>Cliquez sur <strong>Importer…</strong> et sélectionnez votre certificat client.</li>
|
||||
</ol>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card niceborder" style="margin-bottom:20px;">
|
||||
<div class="card-header bg-dark">
|
||||
<h2 id="cert-client-chromium" style="margin: 0">Chromium/Google Chrome</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h3 class="card-title" id="cert-client-chromium-windows">Sous Microsoft Windows</h3>
|
||||
<p>
|
||||
Le navigateur utilise les paramètres du système ; suivez les
|
||||
instructions concernant <a href="#cert-client-ie">Internet
|
||||
Explorer</a>.
|
||||
</p>
|
||||
|
||||
<h3 class="card-title" id="cert-client-chromium-macos">Sous Mac OS</h3>
|
||||
<ol>
|
||||
<li>Ouvrez le menu des préférences du navigateur.</li>
|
||||
<li>Cliquez sur <strong>Afficher les paramètres avancés</strong>.</li>
|
||||
<li>Dans la section <strong>HTTPS/SSL</strong>, cliquez sur <strong>Gérer les certificats</strong>. Le trousseau d'accès se lance.</li>
|
||||
<li>Dans le menu <strong>Fichier</strong>, sélectionnez <strong>Importer des éléments…</strong> et sélectionnez votre certificat client.</li>
|
||||
<li>Choisissez un trousseau.</li>
|
||||
</ol>
|
||||
|
||||
<h3 class="card-title" id="cert-client-chromium-gnu-linux">Sous GNU/Linux, FreeBSD ou OpenBSD</h3>
|
||||
<ol>
|
||||
<li>Ouvrez le menu des préférences du navigateur.</li>
|
||||
<li>Cliquez sur <strong>Afficher les paramètres avancés</strong>.</li>
|
||||
<li>Dans la section <strong>HTTPS/SSL</strong>, cliquez sur <strong>Gérer les certificats</strong>.</li>
|
||||
<li>Sélectionnez l'onglet <strong>Vos certificats</strong>.</li>
|
||||
<li>Cliquez sur <strong>Importer…</strong> et sélectionnez votre certificat client.</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card niceborder" style="margin-bottom:20px;">
|
||||
<div class="card-header bg-dark">
|
||||
<h2 id="cert-client-ie" style="margin: 0">Internet Explorer</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ol>
|
||||
<li>Double-cliquez sur le fichier <samp>.p12</samp> présent sur votre clef USB. L'<em>assistant d'importation du certificat</em> apparaît.</li>
|
||||
<li>Cliquez sur <strong>Suivant</strong>.</li>
|
||||
<li>Cliquez sur <strong>Suivant</strong>.</li>
|
||||
<li>Entrez le mot de passe fourni sur papier puis cliquez sur <strong>Suivant</strong>.</li>
|
||||
<li>Cliquez sur <strong>Suivant</strong> (le certificat sera automatiquement placé dans le magasin <em>Personnel</em>).</li>
|
||||
<li>Cliquez sur <strong>Terminer</strong>.</li>
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
Selon votre version de Windows, votre système peut ensuite vous
|
||||
demander de définir un mot de passe pour protéger ce certificat.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<strong>Microsoft Internet Explorer :</strong> Aucune version
|
||||
de <em>Microsoft Internet Explorer</em> (nom d'« Internet Explorer »
|
||||
jusqu'à sa version 9 comprise) n'est supportée par notre serveur.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card niceborder" style="margin-bottom:20px;">
|
||||
<div class="card-header bg-dark">
|
||||
<h2 id="cert-client-safari" style="margin: 0">Safari</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ol>
|
||||
<li><strong>Double-cliquez</strong> sur le fichier <samp>.p12</samp> présent sur votre clef USB.</li>
|
||||
<li>Entrez le mot de passe fourni sur papier puis cliquez sur <strong>Suivant</strong>.</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1 +0,0 @@
|
|||
{"errmsg": "Vous n'avez pas les droits nécessaires pour effectuer cette action."}
|
|
@ -1 +0,0 @@
|
|||
frontend/static/
|
|
@ -1 +0,0 @@
|
|||
../../../frontend/static/css/fic.css
|
387
qa/static/css/fic.css
Normal file
|
@ -0,0 +1,387 @@
|
|||
@font-face {
|
||||
font-family: "Linux Biolinum";
|
||||
src: url('../fonts/LinBiolinum_R.woff') format('woff');
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Linux Biolinum";
|
||||
src: url('../fonts/LinBiolinum_RB.woff') format('woff');
|
||||
font-weight: bold;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Linux Biolinum";
|
||||
src: url('../fonts/LinBiolinum_RI.woff') format('woff');
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'FantasqueSansMonoRegular';
|
||||
src: url('../fonts/FantasqueSansMono-Regular.woff') format('woff');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
b, strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
[ng-cloak] {
|
||||
display:none !important;
|
||||
}
|
||||
|
||||
.popover.bs-popover-left .arrow::after {
|
||||
border-left-color: #7A8288;
|
||||
}
|
||||
|
||||
body {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.bg-public {
|
||||
background-image: url('../img/logo-epita-bw.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.bg-public .carousel h3 {
|
||||
font-size: 1.5rem;
|
||||
line-height: 1.1rem;
|
||||
}
|
||||
|
||||
.flag {
|
||||
font-family: 'FantasqueSansMonoRegular', monospace;
|
||||
}
|
||||
|
||||
.card-img-top {
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
.theme-card {
|
||||
height: 10rem;
|
||||
}
|
||||
|
||||
.beautiful {
|
||||
font-family: "Linux Biolinum",Helvetica,Arial,sans-serif;
|
||||
}
|
||||
.beautiful ol {
|
||||
font-size: 133%;
|
||||
}
|
||||
.beautiful ol ol {
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
.text-bold {
|
||||
font-weight: bolder;
|
||||
}
|
||||
.text-indent p {
|
||||
text-indent: 1em;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.niceborder {
|
||||
border-bottom: 5px #4eaee6 solid;
|
||||
}
|
||||
.navbar img {
|
||||
margin: 3px auto;
|
||||
height: 100px;
|
||||
}
|
||||
.navbar .clock {
|
||||
font-size: 70px;
|
||||
}
|
||||
.clock:not(.expired):not(.wait) .point, .clock.expired {
|
||||
transition: color text-shadow 1s;
|
||||
position: relative;
|
||||
animation: clockanim 1s ease infinite;
|
||||
-moz-animation: clockanim 1s ease infinite;
|
||||
-webkit-animation: clockanim 1s ease infinite;
|
||||
}
|
||||
.clock.wait .point {
|
||||
transition: color text-shadow 1s;
|
||||
position: relative;
|
||||
animation: clockwait 1s ease infinite;
|
||||
-moz-animation: clockwait 1s ease infinite;
|
||||
-webkit-animation: clockwait 1s ease infinite;
|
||||
}
|
||||
.end {
|
||||
color: #e64143;
|
||||
}
|
||||
.point {
|
||||
text-shadow: 0 0 20px #4eaee6;
|
||||
}
|
||||
.end .point {
|
||||
text-shadow: 0 0 20px #e64143;
|
||||
}
|
||||
@-webkit-keyframes clockanim {
|
||||
0% { opacity: 1.0; }
|
||||
50% { opacity: 0; }
|
||||
100% { opacity: 1.0; };
|
||||
}
|
||||
@-moz-keyframes clockanim {
|
||||
0% { opacity: 1.0; }
|
||||
50% { opacity: 0; }
|
||||
100% { opacity: 1.0; };
|
||||
}
|
||||
keyframes clockanim {
|
||||
0% { opacity: 1.0; }
|
||||
50% { opacity: 0; }
|
||||
100% { opacity: 1.0; };
|
||||
}
|
||||
@-webkit-keyframes clockwait {
|
||||
0% { text-shadow: 0 0 20px #A6D6F2; }
|
||||
50% { text-shadow: 0 0 2px #A6D6F2; }
|
||||
100% { text-shadow: 0 0 20px #A6D6F2; }
|
||||
}
|
||||
@-moz-keyframes clockwait {
|
||||
0% { text-shadow: 0 0 20px #A6D6F2; }
|
||||
50% { text-shadow: 0 0 2px #A6D6F2; }
|
||||
100% { text-shadow: 0 0 20px #A6D6F2; }
|
||||
}
|
||||
keyframes clockwait {
|
||||
0% { text-shadow: 0 0 20px #A6D6F2; }
|
||||
50% { text-shadow: 0 0 2px #A6D6F2; }
|
||||
100% { text-shadow: 0 0 20px #A6D6F2; }
|
||||
}
|
||||
|
||||
samp.cksum {
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 16vw;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
word-wrap: normal;
|
||||
}
|
||||
|
||||
h1 small.authors {
|
||||
float: right;
|
||||
font-style: italic;
|
||||
font-size: 42%;
|
||||
}
|
||||
.lead small.authors {
|
||||
color: #7a8288;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
a.badge:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
.teamname {
|
||||
-webkit-filter: invert(100%);
|
||||
filter: invert(100%);
|
||||
}
|
||||
a:hover .teamname {
|
||||
text-shadow: 0px 0px 10px #888888;
|
||||
}
|
||||
|
||||
.authors a {
|
||||
color: #3A3F44;
|
||||
}
|
||||
|
||||
.heading {
|
||||
font-style: italic;
|
||||
margin-top: -7px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#eventsList {
|
||||
overflow:hidden;
|
||||
max-height: 90vh;
|
||||
}
|
||||
|
||||
.swap-animation .alert {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.swap-animation {
|
||||
margin-bottom: 0.5rem;
|
||||
max-height: 30vh;
|
||||
transition: max-height 1.0s linear,opacity 1.0s linear,transform 0.5s linear;
|
||||
}
|
||||
.swap-animation.ng-enter {
|
||||
transform: translateY(-25vh);
|
||||
max-height: 0vh;
|
||||
}
|
||||
.swap-animation.ng-enter-active {
|
||||
opacity: 1;
|
||||
transform: translateY(0px);
|
||||
max-height: 30vh;
|
||||
}
|
||||
.swap-animation.ng-leave {
|
||||
opacity: 1;
|
||||
max-height: 30vh;
|
||||
transform: translateY(0px);
|
||||
}
|
||||
.swap-animation.ng-leave-active {
|
||||
opacity: 0;
|
||||
transform: translateX(120vw);
|
||||
max-height: 0vh;
|
||||
}
|
||||
|
||||
.carousel-indicators {
|
||||
bottom: -10px;
|
||||
}
|
||||
.carousel-caption {
|
||||
padding: 0;
|
||||
position: static;
|
||||
}
|
||||
.carousel .table {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.carousel .table-sm td {
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.table th.frotated {
|
||||
border: 0;
|
||||
}
|
||||
.table th.rotated {
|
||||
height: 100px;
|
||||
width: 40px;
|
||||
min-width: 40px;
|
||||
max-width: 40px;
|
||||
position: relative;
|
||||
vertical-align: bottom;
|
||||
padding: 0;
|
||||
font-size: 12px;
|
||||
line-height: 0.9;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
th.rotated > div {
|
||||
position: relative;
|
||||
top: 0px;
|
||||
left: -50px;
|
||||
height: 100%;
|
||||
transform: skew(45deg,0deg);
|
||||
overflow: hidden;
|
||||
border: 1px solid #000;
|
||||
}
|
||||
th.rotated div span {
|
||||
transform: skew(-45deg,0deg) rotate(45deg);
|
||||
position: absolute;
|
||||
bottom: 40px;
|
||||
left: -35px;
|
||||
display: inline-block;
|
||||
width: 110px;
|
||||
text-align: left;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
ul.list-inline li {
|
||||
display: inline;
|
||||
}
|
||||
ul.list-inline li:not(:last-child)::after {
|
||||
content: " ● "
|
||||
}
|
||||
|
||||
.breadcrumb-item + .breadcrumb-item::before {
|
||||
content: ">"
|
||||
}
|
||||
|
||||
.excard {
|
||||
transition: transform 250ms;
|
||||
}
|
||||
.excard:hover {
|
||||
transform: scale(1.07);
|
||||
}
|
||||
|
||||
#tagsMenu + .dropdown-menu div {
|
||||
overflow-y: auto;
|
||||
max-height: calc(66vh - 100px);
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-left: solid 2px;
|
||||
margin-left: 1em;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.jumbotron img {
|
||||
margin-left: -1em;
|
||||
padding-left: 2em;
|
||||
padding-right: 2em;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
#eventsList .card {
|
||||
border-left-color: rgba(0,0,0,.125) !important;
|
||||
border-right-color: rgba(0,0,0,.125) !important;
|
||||
border-top-color: rgba(0,0,0,.125) !important;
|
||||
}
|
||||
|
||||
.bg-public .card-body {
|
||||
padding:1rem;
|
||||
padding-bottom:0;
|
||||
}
|
||||
|
||||
#themesSummary .card-body {
|
||||
padding:0;
|
||||
}
|
||||
#themesSummary h3 {
|
||||
background: rgba(64,64,64,0.66);
|
||||
border-radius: 2px;
|
||||
padding: 0.5rem;
|
||||
margin-left: 0.5rem;
|
||||
margin-right: 0.5rem;
|
||||
margin-top: -40px;
|
||||
}
|
||||
#themesSummary p {
|
||||
font-size: 90%;
|
||||
margin: 0.2rem;
|
||||
text-indent: 0.6em;
|
||||
}
|
||||
|
||||
.card-sm .card-header, .card-sm .card-footer {
|
||||
padding: 0.2rem 0.75rem;
|
||||
}
|
||||
.card-sm .card-body {
|
||||
padding: 0.4rem 0.75rem;
|
||||
}
|
||||
.card-sm .card-body.text-indent p {
|
||||
text-indent: 0.4rem;
|
||||
}
|
||||
|
||||
.carousel-item, .carousel-caption {
|
||||
height: inherit;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
margin-bottom: -15rem;
|
||||
}
|
||||
.page-header h1 {
|
||||
text-shadow: 0 0 15px rgba(255,255,255,0.95), 0 0 5px rgb(255,255,255)
|
||||
}
|
||||
.page-header h1, .page-header h1 a {
|
||||
color: black;
|
||||
}
|
||||
.page-header h1 a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
.page-header h2 {
|
||||
font-size: 100%;
|
||||
text-shadow: 1px 1px 1px rgba(0,0,0,0.9)
|
||||
}
|
||||
.page-header h2, .page-header h2 a {
|
||||
color: #4eaee6;
|
||||
}
|
||||
.page-header h1 {
|
||||
padding-top: 4rem;
|
||||
text-align: center;
|
||||
}
|
||||
.page-header h2 {
|
||||
padding-bottom: 14rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.page-header .headerfade {
|
||||
background: linear-gradient(transparent 0%, rgb(233,236,239) 100%);
|
||||
height: 3rem;
|
||||
}
|
||||
|
||||
a.list-group-item:hover {
|
||||
text-decoration: none;
|
||||
}
|
|
@ -1 +1 @@
|
|||
../../../frontend/static/css/glyphicon.css
|
||||
../../../admin/static/css/glyphicon.css
|
|
@ -1 +1 @@
|
|||
../../frontend/static/favicon.ico
|
||||
../../frontend/ui/static/favicon.ico
|
|
@ -1 +1 @@
|
|||
../../frontend/static/fonts/
|
||||
../../admin/static/fonts/
|
|
@ -1 +0,0 @@
|
|||
../../../frontend/static/img/comcyber.png
|
|
@ -1 +0,0 @@
|
|||
../../../frontend/static/img/epita.png
|
|
@ -1 +1 @@
|
|||
../../../frontend/static/img/fic.png
|
||||
../../../frontend/ui/static/img/fic.png
|
|
@ -1 +0,0 @@
|
|||
../../../frontend/static/img/srs.png
|
2
qa/static/js/angular-route.min.js
vendored
|
@ -1 +1 @@
|
|||
../../../frontend/static/js/angular-route.min.js
|
||||
../../../admin/static/js/angular-route.min.js
|
2
qa/static/js/angular-sanitize.min.js
vendored
|
@ -1 +1 @@
|
|||
../../../frontend/static/js/angular-sanitize.min.js
|
||||
../../../admin/static/js/angular-sanitize.min.js
|
2
qa/static/js/angular.min.js
vendored
|
@ -1 +1 @@
|
|||
../../../frontend/static/js/angular.min.js
|
||||
../../../admin/static/js/angular.min.js
|
2
qa/static/js/bootstrap.min.js
vendored
|
@ -1 +1 @@
|
|||
../../../frontend/static/js/bootstrap.min.js
|
||||
../../../admin/static/js/bootstrap.min.js
|
|
@ -1 +1 @@
|
|||
../../../frontend/static/js/common.js
|
||||
../../../admin/static/js/common.js
|
2
qa/static/js/d3.v3.min.js
vendored
|
@ -1 +1 @@
|
|||
../../../frontend/static/js/d3.v3.min.js
|
||||
../../../admin/static/js/d3.v3.min.js
|
|
@ -1 +1 @@
|
|||
../../../frontend/static/js/i18n/
|
||||
../../../admin/static/js/i18n/
|
2
qa/static/js/jquery.min.js
vendored
|
@ -1 +1 @@
|
|||
../../../frontend/static/js/jquery.min.js
|
||||
../../../admin/static/js/jquery.min.js
|