Remove old frontend ui

This commit is contained in:
nemunaire 2021-09-09 15:18:42 +02:00
parent 2875d3eb59
commit d010b86fa0
80 changed files with 414 additions and 5277 deletions

View file

@ -1 +1 @@
../../../frontend/static/css/fic.css
../../../qa/static/css/fic.css

View file

@ -1 +1 @@
../../../frontend/static/css/glyphicon.css
../../../admin/static/css/glyphicon.css

View file

@ -1 +1 @@
../../frontend/static/favicon.ico
../../frontend/ui/static/favicon.ico

View file

@ -1 +1 @@
../../../frontend/static/img/comcyber.png
../../../frontend/ui/static/img/comcyber.png

View file

@ -1 +1 @@
../../../frontend/static/img/epita.png
../../../admin/static/img/epita.png

View file

@ -1 +1 @@
../../../frontend/static/img/fic.png
../../../admin/static/img/fic.png

View file

@ -1 +1 @@
../../../frontend/static/img/srs.png
../../../frontend/ui/static/img/srs.png

View file

@ -1 +1 @@
../../../frontend/static/js/angular-route.min.js
../../../admin/static/js/angular-route.min.js

View file

@ -1 +1 @@
../../../frontend/static/js/angular-sanitize.min.js
../../../admin/static/js/angular-sanitize.min.js

View file

@ -1 +1 @@
../../../frontend/static/js/angular.min.js
../../../admin/static/js/angular.min.js

View file

@ -1 +1 @@
../../../frontend/static/js/bootstrap.min.js
../../../admin/static/js/bootstrap.min.js

View file

@ -1 +1 @@
../../../frontend/static/js/common.js
../../../admin/static/js/common.js

View file

@ -1 +1 @@
../../../frontend/static/js/d3.v3.min.js
../../../admin/static/js/d3.v3.min.js

View file

@ -1 +1 @@
../../../frontend/static/js/i18n/
../../../admin/static/js/i18n/

View file

@ -1 +1 @@
../../../frontend/static/js/jquery.min.js
../../../admin/static/js/jquery.min.js

File diff suppressed because one or more lines are too long

View file

@ -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;
}

View file

@ -1 +0,0 @@
../../../admin/static/css/glyphicon.css

View file

@ -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 &agrave; laquelle vous tentez d'acc&eacute;der n'existe pas ou l'adresse que vous avez tap&eacute;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>

View file

@ -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."}

View file

@ -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>

View file

@ -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."}

View file

@ -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&eacute; de r&eacute;pondre &agrave; votre requ&ecirc;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>

View file

@ -1 +0,0 @@
{"errmsg": "Notre serveur est actuellement dans l'incapacité de répondre à votre requête. \nVeuillez recommencer dans quelques instants."}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -1 +0,0 @@
../../admin/static/fonts/

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 157 KiB

View file

@ -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">&ndash; {{ 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>

View file

@ -1 +0,0 @@
../../../admin/static/js/angular-route.min.js

View file

@ -1 +0,0 @@
../../../admin/static/js/angular-sanitize.min.js

View file

@ -1 +0,0 @@
../../../admin/static/js/angular.min.js

File diff suppressed because it is too large Load diff

View file

@ -1 +0,0 @@
../../../admin/static/js/bootstrap.min.js

View file

@ -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");
}
};

View file

@ -1 +0,0 @@
../../../admin/static/js/common.js

View file

@ -1 +0,0 @@
../../../admin/static/js/d3.v3.min.js

View file

@ -1 +0,0 @@
../../../admin/static/js/i18n/

View file

@ -1 +0,0 @@
../../../admin/static/js/jquery.min.js

View file

@ -1,2 +0,0 @@
User-agent: *
Disallow: /

View file

@ -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&nbsp;: <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&nbsp;:</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&nbsp;:</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&nbsp;:</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&nbsp;: <span title="{{ file.size }} octets">{{ file.size | size }}</span></nobr> &ndash; <nobr><span title="blake2.net">b2sum</span>&nbsp;: <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 &ndash; 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&hellip;</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 &ndash; 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&nbsp;: <a ng-href="{{ my.exercices[current_exercice].video_uri }}">{{ my.exercices[current_exercice].video_uri }}</a>.
</iframe>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

View file

@ -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&nbsp;:</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&nbsp;:</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&nbsp;:</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&nbsp;:</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&nbsp;!
</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&nbsp;: <span title="{{ file.size }} octets">{{ file.size | size }}</span></nobr> &ndash; <nobr><span title="blake2.net">b2sum</span>&nbsp;: <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&nbsp;: <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&hellip;</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&nbsp;: <a ng-href="{{ my.exercices[current_exercice].video_uri }}">{{ my.exercices[current_exercice].video_uri }}</a>.
</iframe>
</div>
</div>
</div>
</div>
</div>

View file

@ -1,27 +0,0 @@
<div class="alert alert-danger" ng-if="my && !(my.team_id)">
<strong>Attention&nbsp;:</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&nbsp;!
</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>

View file

@ -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>&nbsp;à {{ text.date | date:"mediumTime" }}&nbsp;:
<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>

View file

@ -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>

View file

@ -1,135 +0,0 @@
<div class="jumbotron niceborder" style="text-indent: 1em" ng-if="!settings.allowRegistration">
<p>
Félicitations&nbsp;! vous êtes maintenant authentifié auprès de notre
serveur&nbsp;!
</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&nbsp;! vous êtes maintenant authentifié&middot;e auprès de
notre serveur&nbsp;!</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&nbsp;:
</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&nbsp;! vous êtes maintenant authentifié&middot;e auprès de
notre serveur&nbsp;!</strong>
</p>
<p ng-if="!settings.denyTeamCreation">
Si votre équipe est déjà créée, rejoignez-là&nbsp;!
</p>
<p ng-if="settings.denyTeamCreation">
Vous n'êtes pas encore enregistré&middot;e sur notre serveur. Afin de
pouvoir participer au challenge, nous vous remercions de bien vouloir
rejoindre votre équipe&nbsp;:
</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>

View file

@ -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&nbsp;: 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&nbsp;tentatives pour trouver la/les solutions d'un
challenge. Au delà, chaque tentative vous fait perdre une petite quantité
de points comme suit&nbsp;:
</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&nbsp;point</td>
</tr>
<tr>
<td>11 à 20</td>
<td><ng-pluralize count="settings.submissionCostBase" when="{'one': '{}&nbsp;point', 'other': '{}&nbsp;points'}"></ng-pluralize></td>
</tr>
<tr>
<td>21 à 30</td>
<td><ng-pluralize count="settings.submissionCostBase * 2" when="{'one': '{}&nbsp;point', 'other': '{}&nbsp;points'}"></ng-pluralize></td>
</tr>
<tr>
<td>31 à 40</td>
<td><ng-pluralize count="settings.submissionCostBase * 3" when="{'one': '{}&nbsp;point', 'other': '{}&nbsp;points'}"></ng-pluralize></td>
</tr>
<tr>
<td>41 à 50</td>
<td><ng-pluralize count="settings.submissionCostBase * 4" when="{'one': '{}&nbsp;point', 'other': '{}&nbsp;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&nbsp;:
</p>
<ul>
<li>À&nbsp;10 tentatives, vous aurez perdu <ng-pluralize count="settings.submissionCostBase * 0" when="{'one': '{}&nbsp;point', 'other': '{}&nbsp;points'}"></ng-pluralize>.</li>
<li>À&nbsp;15 tentatives, vous aurez perdu en tout <ng-pluralize count="settings.submissionCostBase * 5" when="{'one': '{}&nbsp;point', 'other': '{}&nbsp;points'}"></ng-pluralize>&nbsp;: <samp>{{ settings.submissionCostBase }} * 5</samp>.</li>
<li>25 tentatives vous coûteront en tout <ng-pluralize count="settings.submissionCostBase * 20" when="{'one': '{}&nbsp;point', 'other': '{}&nbsp;points'}"></ng-pluralize>&nbsp;: <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': '{}&nbsp;point', 'other': '{}&nbsp;points'}"></ng-pluralize>&nbsp;: <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 }}&nbsp;% 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&nbsp;: <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>

View file

@ -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> &gt;
<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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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&nbsp;!
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&nbsp;:</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&nbsp;!
</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&nbsp;:</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>

View file

@ -1 +0,0 @@
{"errmsg": "Vous n'avez pas les droits nécessaires pour effectuer cette action."}

View file

@ -1 +0,0 @@
frontend/static/

View file

@ -1 +0,0 @@
../../../frontend/static/css/fic.css

387
qa/static/css/fic.css Normal file
View 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;
}

View file

@ -1 +1 @@
../../../frontend/static/css/glyphicon.css
../../../admin/static/css/glyphicon.css

View file

@ -1 +1 @@
../../frontend/static/favicon.ico
../../frontend/ui/static/favicon.ico

View file

@ -1 +1 @@
../../frontend/static/fonts/
../../admin/static/fonts/

View file

@ -1 +0,0 @@
../../../frontend/static/img/comcyber.png

View file

@ -1 +0,0 @@
../../../frontend/static/img/epita.png

View file

@ -1 +1 @@
../../../frontend/static/img/fic.png
../../../frontend/ui/static/img/fic.png

View file

@ -1 +0,0 @@
../../../frontend/static/img/srs.png

View file

@ -1 +1 @@
../../../frontend/static/js/angular-route.min.js
../../../admin/static/js/angular-route.min.js

View file

@ -1 +1 @@
../../../frontend/static/js/angular-sanitize.min.js
../../../admin/static/js/angular-sanitize.min.js

View file

@ -1 +1 @@
../../../frontend/static/js/angular.min.js
../../../admin/static/js/angular.min.js

View file

@ -1 +1 @@
../../../frontend/static/js/bootstrap.min.js
../../../admin/static/js/bootstrap.min.js

View file

@ -1 +1 @@
../../../frontend/static/js/common.js
../../../admin/static/js/common.js

View file

@ -1 +1 @@
../../../frontend/static/js/d3.v3.min.js
../../../admin/static/js/d3.v3.min.js

View file

@ -1 +1 @@
../../../frontend/static/js/i18n/
../../../admin/static/js/i18n/

View file

@ -1 +1 @@
../../../frontend/static/js/jquery.min.js
../../../admin/static/js/jquery.min.js