diff --git a/content/_index.md b/content/_index.md new file mode 100644 index 0000000..c301ce4 --- /dev/null +++ b/content/_index.md @@ -0,0 +1,9 @@ +--- +date: 2019-04-04T15:59:52+02:00 +title: Préparation du challenge forensic +chapter: true +--- + +# Préparation du challenge forensic + +![Le challenge au FIC](home.jpg) diff --git a/content/files/_index.md b/content/files/_index.md new file mode 100644 index 0000000..9e3997d --- /dev/null +++ b/content/files/_index.md @@ -0,0 +1,180 @@ +--- +date: 2019-04-04T15:59:52+02:00 +title: Arborescence et fichiers +weight: 10 +--- + +Afin de pouvoir être importé automatiquement sur la plate-forme, vos scénarios +doivent respecter une certaine arborescence que voici : + +
+    .
+    ├── AUTHORS.txt
+    ├── overview.txt
+    ├── heading.jpg
+    ├── CHID-Titre du défi/
+    │   ├── challenge.txt
+    │   ├── finished.txt    (opt.)
+    │   ├── links.txt
+    │   ├── overview.txt
+    │   ├── resolution.mp4
+    │   ├── statement.txt
+    │   ├── hints/          (opt.)
+    │   │   ├── DIGESTS.txt
+    │   │   └── ...
+    │   ├── files/
+    │   │   ├── DIGESTS.txt
+    │   │   └── ...
+    │   └── ressources/
+    │       └── ...
+    │
+    ├── CHID-Titre du défi/
+    │   └── ...
+    └── ...
+
+ +N'ajoutez pas inutilement de dossiers ou fichiers vides. Ceux-ci doivent sans +doute être optionnels. + + +## Fichiers pour un scénario + +### `AUTHORS.txt` + +Voir la [page dédiée]({{}}). + + +### `heading.jpg` + +Chaque scénario devrait avoir une image/photo représentative. Je vous invite +donc à trouver votre bonheur sur : [Unsplash](https://unsplash.com/) ou à +partager un travail personnel. Mais attention aux licences et contraintes +(notamment l'obligation de citer la source ou le photographe) si vous utilisez +un autre service qu'unsplash. + +La taille et l'orientation de l'image n'a pas d'importance, mais gardez en tête +que c'est son centre qui sera affiché, si la hauteur dépasse la taille prévue. + + +### `overview.txt` + +Une présentation rapide du scenario (~2-3 phrases d'accroche pour lecture +rapide), compréhensible par un décideur, petit schéma à l'appui. + +Le fichier **doit** comporter une phrase d'accroche (qui sera affichée plus +grosse que les suivantes). Celle-ci correspond à la première ligne de votre +fichier. + +Comme l'ensemble des textes importés, vous pouvez utiliser du +[Markdown](https://daringfireball.net/projects/markdown/) pour mettre en forme +vos textes. + +Vous pouvez insérer des images dans tous les textes : + + ![alt](path title) + +Le chemin *doit* être un chemin _absolu_ vers l'image, considérant la racine +comme étant le dossier du scémario (pour l'overview du thème) ou de l'exercice +(pour les autres textes). + + +## Fichiers pour un défi + +### `challenge.txt` + +Voir la [page dédiée]({{}}). + + +### `finished.txt` + +Remplissez ce fichier optionnel, lorsque vous souhaitez apporter une +information aux participants une fois qu'ils ont validé votre défi. + +Comme l'ensemble des textes importés, vous pouvez utiliser du +[Markdown](https://daringfireball.net/projects/markdown/) pour mettre en forme +vos textes. + + +### `links.txt` + +Voir la [page dédiée]({{}}). + + +### `overview.txt` + +Une présentation rapide du défi (~1-2 phrases), compréhensible par un décideur, +petit schéma à l'appui si besoin. + +Le fichier **doit** comporter une phrase d'accroche (qui sera affichée plus +grosse que les suivantes). Celle-ci correspond à la première ligne de votre +fichier. + +Comme l'ensemble des textes importés, vous pouvez utiliser du +[Markdown](https://daringfireball.net/projects/markdown/) pour mettre en forme +vos textes. + +Gardez en tête que les *overview*, que ce soit scénario ou exercices, sont +affichées au public : il s'agit à la fois d'aguicher le participant pour qu'il +fasse votre scénario plutôt que celui d'un autre groupe, mais aussi de donner +envie au public de lire plus en détail. + + +### `resolution.mp4` + +Voir la [page dédiée]({{}}). + + +### `statement.txt` + +contenant le scénario du challenge, tel qu'il sera affiché sur le site, à destination des participants +Une présentation rapide du défi (~1-2 phrases), compréhensible par un décideur, +petit schéma à l'appui si besoin. + +Le fichier **doit** comporter une phrase d'accroche (qui sera affichée plus +grosse que les suivantes). Celle-ci correspond à la première ligne de votre +fichier. + +Comme l'ensemble des textes importés, vous pouvez utiliser du +[Markdown](https://daringfireball.net/projects/markdown/) pour mettre en forme +vos textes. + + +### `files/` + +Utilisez ce dossier pour y placer les fichiers que vous mettez à disposition +des participants. + +Chaque fichier doit avoir une entrée correspondante dans le fichier +`DIGESTS.txt` ; plus d'infos sur la page [`DIGESTS.txt`]({{}}). + +- Pas plus 4GB à télécharger **par challenge** (ie. tous les fichiers de ce challenge) +- Archives `.tar.bz2`, `.tar.gz`, `.tar.xz` ou `.zip` lorsque nécessaire. **PAS** de `.rar`, ... +- Compresser (sans tarball, juste via **gzip**[^gz]) les fichiers lorsque c'est utile (memory dump, images BMP, disques, fichiers textes, ...) +- Utiliser `$(split -b 240M -d BIG_FILE BIG_FILE.)` pour uploader les gros fichiers sur owncloud. + Ces fichiers seront concaténés au moment de leur import sur l'interface. + Seul le hash du fichier entier est requis dans le fichier `DIGESTS.txt`. + +[^gz]: l'intérêt de `gzip` est que le serveur web sera capable de distribuer le fichier sans faire apparaître la compression. Voir le [module nginx utilisé](https://nginx.org/en/docs/http/ngx_http_gzip_static_module.html). + + +### `hints/` + +Utilisez ce dossier pour y placer les fichiers que vous mettez à disposition, +dans le cadre d'indices. + +Chaque fichier doit avoir une entrée correspondante dans le fichier +`DIGESTS.txt` ; plus d'infos sur la page [`DIGESTS.txt`]({{}}). + +De plus, chaque fichier doit également posséder une entrée dans le fichier +[`challenge.txt`]({{}}), afin de lui attribuer son coût, +titre, ... + + +### `ressources/` + +Rangez dans ce dossier toutes les ressources et scripts que vous avez réalisés +pour le challenge : pour sa construction ou sa résolution, les schémas du SI au +premier challenge concerné, éventuellement un `README.txt` avec les liens des +outils externes. diff --git a/content/files/authors.md b/content/files/authors.md new file mode 100644 index 0000000..9dca7fc --- /dev/null +++ b/content/files/authors.md @@ -0,0 +1,27 @@ +--- +date: 2019-04-04T15:59:52+02:00 +title: AUTHORS.txt +weight: 10 +--- + +Le fichier `AUTHORS.txt`, à la racine de chaque thème, contient vos noms, tels +qu'ils apparraîtront sur la plate-forme. + +## Format du fichier + +Chaque ligne contient le nom qui apparaîtra sur le site, suivi, éventuellement +d'un [lien hypertexte complet](https://tools.ietf.org/html/rfc2396), placé +entre chevrons. Ce lien peut être, par exemple, l'adresse du blog de l'auteur +correspondant ou son adresse électronique. + +### Exemple + +```text +Courtois J. +Bombal S. +Mercier P-O. +``` + +### Rendu + +![Rendu AUTHORS.txt](screenshoot.png) diff --git a/content/files/challenge.md b/content/files/challenge.md new file mode 100644 index 0000000..e909e0c --- /dev/null +++ b/content/files/challenge.md @@ -0,0 +1,129 @@ +--- +date: 2019-04-04T15:59:52+02:00 +title: challenge.txt +weight: 20 +--- + ++ `challenge.txt` définitions des paramètres de votre challenge (au format [toml](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md)) : + - `gain = 42` : nombre de points que rapporte cet exercice ; + - `tags = ["Android", "RAT", "ROM"]` : mots-clefs de l'exercice ; + - `[[depend]]` : dépendance à un autre exercice : + * `id = CHID` : identifiant du challenge ; + * `theme = "NomDuTheme"` : (facultatif) nom du thème dans lequel aller chercher l'identifiant (par défaut, on prend le thème courant) ; + - `[[flag]]` : drapeau classique à valider pour résoudre le challenge : + * `id = 42` : (facultatif) identifiant du flag au sein de l'exercice, pour définir des dépendances ; + * `label = "Intitulé"` : (facultatif, par défaut : `Flag`) intitulé du drapeau ; + * `raw = 'MieH2athxuPhai6u'` ou `raw = ['part1', 'part2']` : drapeau exact à trouver ; sous forme de tableau, le participant n'aura pas connaissaance du nombre d'éléments ; + * `validator_regexp = "^(?:sudo +)?(.*)$"` : (facultatif) expression rationnelle dont les groupes capturés serviront comme chaîne à valider (notez que `?:` au début d'un groupe ne le capturera pas) ; + * `ordered = false` : (facultatif, par défaut : `false`) ignore l'ordre dans lequels les éléments du tableau sont passés ; + * `ignorecase = true` : (facultatif, par défaut : `false`) ignore la case de ce drapeau ; + * `help = "Indication"` : (facultatif) chaîne de caractères placée sous le champ du formulaire, idéale pour donner une indication de format ; + * `[[flag.unlock_file]]` : bloque l'accès à un fichier tant que le flag n'est pas obtenu : + + `filename = "toto.txt"` : nom du fichier tel qu'il apparaît dans le dossier `files` ; + * `[[flag.need_flag]]` : liste des flags devant être validés avant de débloquer celui-ci : + + `id = 23` : identifiant du flag tel qu'il a été défini plus tôt dans le fichier ; + - `[[flag_mcq]]` : drapeau sous forme de question à choix multiple (cases à cocher) : + * `label = "Intitulé du groupe"` : (facultatif) intitulé du groupe de choix ; + * `[[flag_mcq.choice]]` : représente un choix, répétez autant de fois qu'il y a de choix : + + `label = "Intitulé de la réponse"`, + + `value = true` : (facultatif, par défaut `false`) valeur attendue pour ce choix ; pour un QCM justifié, utilisez une chaîne de caractères (notez qu'il n'est pas possible de combiner des réponses vraies justifiées et justifiées), + + `help = "Flag correspondant"` : (facultatif) indication affichée dans le champ de texte des QCM justifiés ; + - `[[flag_ucq]]` : drapeau sous forme de question à choix unique : + * `id = 42` : (facultatif) identifiant du flag au sein de l'exercice, pour définir des dépendances ; + * `label = "Intitulé du groupe"` : (facultatif) intitulé du groupe de choix ; + * `raw = 'MieH2athxuPhai6u'` : drapeau attendu parmi les propositions ; + * `validator_regexp = "^(?:sudo +)?(.*)$"` : (facultatif) expression rationnelle dont les groupes capturés serviront comme chaîne à valider (notez que `?:` au début d'un groupe ne le capturera pas) ; + * `help = "Indication"` : (facultatif, uniquement si `displayAs = select`) chaîne de caractères placée sous le champ du formulaire ; + * `displayAs = "select|radio"` : (facultatif, par défaut `radio`) manière dont est affichée le choix : `select` pour une liste de choix, `radio` pour des boutons radios ; + * `choices_cost = 20` : (facultatif, par défaut `0`) coût pour afficher les choix, avant l'affichage, se comporte comme un `flag` classique (à 0, les choix sont affichés directement) ; + * `[[flag_ucq.choice]]` : représente un choix, répétez autant de fois qu'il y a de choix : + + `value = "response"` : valeur qui sera retournée pour comparaison avec la valeur `raw` du ucq, + + `label = "Intitulé de la réponse"` : (facultatif, par défaut identique à `value`) ; + * `[[flag_ucq.unlock_file]]` : bloque l'accès à un fichier tant que le flag n'est pas obtenu : + + `filename = "toto.txt"` : nom du fichier tel qu'il apparaît dans le dossier `files` ; + * `[[flag_ucq.need_flag]]` : liste des flags devant être validés avant de débloquer celui-ci : + + `id = 23` : identifiant du flag tel qu'il a été défini plus tôt dans le fichier ; + - `[[hint]]` : paramètres pour un indice : + * `filename = "toto.txt"` : (mutuellement exclusif avec `content`) nom du fichier tel qu'il apparaît dans le dossier `hints` ; + * `content = "Contenu de l'indice"` : (mutuellement exclusif avec `filename`) contenu de l'indice affiché, en markdown ; + * `cost = 10` : (facultatif, par défaut 1/4 des gains du challenge) coût de l'indice ; + * `title = "Foo Bar"` : (facultatif, par défaut "Astuce $id") titre de l'astuce dans l'interface ; + +Voir aussi [la section sur les flags]({{< relref "/responses" >}}). + +## Exemple + +``` +gain = 42 + +[[depend]] +id = 2 + +[[flag]] +label = "Date d'exfiltration" +help= "Format : yyyy-mm" +raw = '2015-12' + +[[flag]] +label = "IPv6 d'exfiltration" +raw = 'fe80::319c:1002:7c60:68fa' +ignorecase = true + +[[flag_ucq]] +label = "Conditions générales de validation de challenge" +raw = 'conscent' + + [[flag_ucq.choice]] + label = "J'accepte les conditions" + value = 'conscent' + +[[flag_ucq]] +label = "Quelle est la couleur du cheval blanc d'Henri IV ?" +raw = 'blanc' +ignorecase = true +displayAs = "select" + + [[flag_ucq.choice]] + value = 'Noir' + + [[flag_ucq.choice]] + label = 'Roux' + value = 'Alezan' + + [[flag_ucq.choice]] + label = 'Brun' + value = 'Alezan' + + [[flag_ucq.choice]] + label = "Crème" + value = 'Blanc' + +[[flag_mcq]] +label = "Quels sont les films réalisés par C. Nolan ?" + + [[flag_mcq.choice]] + label = "Memento" + value = true + + [[flag_mcq.choice]] + label = "Inception" + value = true + + [[flag_mcq.choice]] + label = "Transcendance" + +[[hint]] +filename = 'enocean-specs.pdf' +title = "Spécifications du protocole utilisé" + +[[hint]] +content = """ +Le TOML c'est magique. +Je peux avoir des chaînes de caractères sur plusieurs lignes ! +""" +title = "L'astuce du siècle" +cost = 30 +``` + + +## Rendu diff --git a/content/files/digests.md b/content/files/digests.md new file mode 100644 index 0000000..bd57e3d --- /dev/null +++ b/content/files/digests.md @@ -0,0 +1,45 @@ +--- +date: 2019-04-04T15:59:52+02:00 +title: DIGESTS.txt +weight: 15 +--- + +Le fichier `DIGESTS.txt` se trouve dans le répertoire `files/` ou `hints/` d'un +défi. Il contient les condensats des fichiers se trouvant dans le dossier +respectif. + +Il génére avec la commande : + +```sh +b2sum * > DIGESTS.txt +``` + +{{% notice warning %}} +Ce fichier est à générer **avant** l'upload. Son utilité est d'avoir un moyen +de vérifier, une fois sur place, sans connexion Internet, que l'intégralité de +l'arborescence n'a pas été altérée et que les fichiers servis sont bien les +mêmes que sur vos dépôts Git. +{{% /notice %}} + +La commande `b2sum` fait parti des *GNU Core Utilities* depuis la [version +8.26](https://github.com/coreutils/coreutils/commit/ea94589e9ef02624a3837f97f80efd7d3dcf56bf). + +L'algorithme [blake2b](https://blake2.net/) est utilisé à la place d'un SHA-1 +ou MD5 car il est plus rapide que ces derniers et est encore considéré comme +sûr. + + +## Cas des fichiers en plusieurs parties + +Dans le cas où vous êtes contraint de découper vos fichiers avant de les +uploader, seule la somme de contrôle du fichier entier, avant découpage, est +nécessaire. + + +## Exemple + +``` +3222734c6c8782682a9c36135a3518e8f4d1facabf76e702cf50da0037a4ed0a425e51266c2914fb83828573e397f96c2a95d419bd85919055479d028f51dba5 fic2016.jpg +023939b0c52b0dfce66954318ab82f7a8c10af4c79c8d5781612b58c74f3ace056067d7b15967e612b176a186b46d3d900c4db8881ba47202521eec33e5bb87b fic.org +7c91450239cf9b0717642c55c3429dd7326db26e87d4ca198758053333f0640ee89d2dd9b2f1919598f89644b06aa8fc2085648e3d1e542a6db324c9b16a0bdf header.tex +``` diff --git a/content/files/links.md b/content/files/links.md new file mode 100644 index 0000000..308f0f4 --- /dev/null +++ b/content/files/links.md @@ -0,0 +1,27 @@ +--- +date: 2019-04-04T15:59:52+02:00 +title: links.txt +weight: 30 +--- + ++ `links.txt` : webographie publiée avec les solutions + - un lien par ligne + - format d'une ligne : `https://lien Description` + le premier ' ' est utilisé comme séparateur entre le lien et sa description + - liens vers les CVE concernées, metasploit/exploitDB, article qui vous a aidé, extrait/dépôt de code, ... + + +## Exemple + +``` +https://media.ccc.de/... Vidéo d'inspiration +https://metasplo.it/ Exploit utilisé +https://nist.gov/ CVE-2016-4242 +``` + + +## Rendu + +{{% notice info %}} +Le contenu du fichier `links.txt` n'est pas encore rendu sur la plate-forme. +{{% /notice %}} diff --git a/content/files/resolution.md b/content/files/resolution.md new file mode 100644 index 0000000..f64606f --- /dev/null +++ b/content/files/resolution.md @@ -0,0 +1,14 @@ +--- +date: 2019-04-04T15:59:52+02:00 +title: resolution.mp4 +weight: 35 +--- + ++ `resolution.mp4` : la vidéo de résolution, montée : + - format MP4 (H.264 + AAC + 3GPP Timed Text) + - utiliser les sous-titres pour commenter les étapes ; pas de commentaires audio + - environ 2' par vidéo : maxi 1'30" pour les challenges simples, 3-4' maxi + - `ffmpeg -video_size 1920x1080 -framerate 25 -f x11grab -i :0.0 -f alsa -ac 2 -i hw:0 -strict experimental resolution.mp4` + - [recordMyDesktop](http://recordmydesktop.sourceforge.net/) sous Linux + - [Screencast Capture Lite](http://cesarsouza.github.io/screencast-capture/) pour Windows (pas de logiciel de « démonstration » => il faut payer la licence pour publier une vidéo) + - [Aegisub](http://www.aegisub.org/), [Gnome Subtitle](http://gnomesubtitles.org/), emacs/vim, ... pour les sous-titres diff --git a/content/intro/_index.md b/content/intro/_index.md new file mode 100644 index 0000000..42984cd --- /dev/null +++ b/content/intro/_index.md @@ -0,0 +1,8 @@ +--- +date: 2019-04-04T15:59:52+02:00 +title: Présentation +weight: 5 +--- + +{{% notice note %}}Ébauche à compléter +{{% /notice %}} diff --git a/content/responses/_index.md b/content/responses/_index.md new file mode 100644 index 0000000..eed7371 --- /dev/null +++ b/content/responses/_index.md @@ -0,0 +1,5 @@ +--- +date: 2019-04-04T15:59:52+02:00 +title: Flags +weight: 15 +--- diff --git a/content/responses/mcq.md b/content/responses/mcq.md new file mode 100644 index 0000000..b093d57 --- /dev/null +++ b/content/responses/mcq.md @@ -0,0 +1,23 @@ +--- +date: 2019-04-05T15:59:52+02:00 +title: QCM +weight: 10 +--- + +{{% notice note %}}Ébauche à compléter +{{% /notice %}} + + +# Propriétés + +id +: (facultatif) identifiant du flag au sein de l'exercice, pour définir des dépendances ; + +label +: (facultatif, par défaut : `Flag`) intitulé du questionnaire ; + +noshuffle +: (facultatif, par défaut : `false`) conserve l'ordre des propositions, au lieu de les mélanger ; + +help +: (facultatif) chaîne de caractères placée sous le champ du formulaire, idéale pour donner une indication de format ; diff --git a/content/responses/mcq_justified.md b/content/responses/mcq_justified.md new file mode 100644 index 0000000..87c5149 --- /dev/null +++ b/content/responses/mcq_justified.md @@ -0,0 +1,23 @@ +--- +date: 2019-04-05T15:59:52+02:00 +title: QCM justifiés +weight: 15 +--- + +{{% notice note %}}Ébauche à compléter +{{% /notice %}} + + +# Propriétés + +id +: (facultatif) identifiant du flag au sein de l'exercice, pour définir des dépendances ; + +label +: (facultatif, par défaut : `Flag`) intitulé du questionnaire ; + +noshuffle +: (facultatif, par défaut : `false`) conserve l'ordre des propositions, au lieu de les mélanger ; + +help +: (facultatif) chaîne de caractères placée sous le champ du formulaire, idéale pour donner une indication de format ; diff --git a/content/responses/simple.md b/content/responses/simple.md new file mode 100644 index 0000000..8fbeb93 --- /dev/null +++ b/content/responses/simple.md @@ -0,0 +1,87 @@ +--- +date: 2019-04-05T15:59:52+02:00 +title: Flag simple +weight: 5 +--- + +Ce type de flag s'utilise pour valider toute chaîne de caractère que l'on +retrouve brute dans les fichiers donnés (ou après un traitement +_déterministe_). + +Attention, par défaut, les propositions ne sont pas sensible à la +casse[^gocase]. + +[^gocase]: Casse selon les classes Unicode de charactères, ce ne concerne pas + que l'alphabet traditionnel. Pour plus d'infos, consultez la [documentation + de la fonction utilisée](https://golang.org/pkg/bytes/#ToLower). + +### Exemple + +``` +[[flag]] +label = "IPv6 d'exfiltration" +raw = 'fe80::319c:1002:7c60:68fa' +``` + +Dans cet exemple, l'importance de la casse de l'IPv6 n'est pas importante, on +laissera donc le participant entrer l'IPv6 comme il le désire, même si elle +peut être copiée/collée. + + +## Flag strict, sensible à la casse + +On utilise la propriété `casesensitive` pour forcer la prise en compte de la +casse lors de la vérification du flag. + + +### Exemple + +``` +[[flag]] +label = "Mot de passe du compte" +raw = 'rech1aichoh2Tei1ohHe' +casesensitive = true +``` + +Pour un mot de passe, ou une chaîne de caractère comme un token, ... qui sera +forcément recopiée par les participants, on impose le respect strict de la +casse. + + +## Flag modulable + + +### Exemple + +Si par exemple, on estime que plusieurs réponses sont correctes (ici, plusieurs secondes) : + +``` +[[flag]] +label = "Heure de l'exfiltration" +raw = '11:22:33+02:00' +validator_regexp = "([0-9]{1,2}):([0-9]{1,2}):[0-9]{1,2}" +``` + + +# Propriétés + +id +: (facultatif) identifiant du flag au sein de l'exercice, pour définir des dépendances ; + +label +: (facultatif, par défaut : `Flag`) intitulé du drapeau ; + +raw +: drapeau exact à trouver ; sous forme de tableau, le participant n'aura pas connaissaance du nombre d'éléments ; + +validator_regexp +: (facultatif) expression rationnelle dont les groupes capturés serviront comme chaîne à valider (notez que `?:` au début d'un groupe ne le capturera pas) ; + +ordered +: (facultatif, par défaut : `false`) ignore l'ordre dans lequels les éléments du tableau sont passés ; + +casesensitive +: (facultatif, par défaut : `false`) prend en compte la la casse de ce drapeau lors de la validation ; + +help +: (facultatif) chaîne de caractères placée sous le champ du formulaire, idéale pour donner une indication de format ; diff --git a/content/responses/ucq.md b/content/responses/ucq.md new file mode 100644 index 0000000..0a5cf95 --- /dev/null +++ b/content/responses/ucq.md @@ -0,0 +1,35 @@ +--- +date: 2019-04-05T15:59:52+02:00 +title: Liste de choix +weight: 20 +--- + +{{% notice note %}}Ébauche à compléter +{{% /notice %}} + + +# Propriétés + +id +: (facultatif) identifiant du flag au sein de l'exercice, pour définir des dépendances ; + +label +: (facultatif, par défaut : `Flag`) intitulé du drapeau ; + +raw +: drapeau exact à trouver ; sous forme de tableau, le participant n'aura pas connaissaance du nombre d'éléments ; + +validator_regexp +: (facultatif) expression rationnelle dont les groupes capturés serviront comme chaîne à valider (notez que `?:` au début d'un groupe ne le capturera pas) ; + +ordered +: (facultatif, par défaut : `false`) ignore l'ordre dans lequels les éléments du tableau sont passés ; + +casesensitive +: (facultatif, par défaut : `false`) prend en compte la la casse de ce drapeau lors de la validation ; + +help +: (facultatif) chaîne de caractères placée sous le champ du formulaire, idéale pour donner une indication de format ; + +choice_cost +: (facultatif) coût pour afficher les choix : avant l'affichage, se comporte comme un `flag` classique (à 0, les choix sont affichés directement) ; diff --git a/static/files/authors/screenshoot.png b/static/files/authors/screenshoot.png new file mode 100644 index 0000000..33fa1e4 Binary files /dev/null and b/static/files/authors/screenshoot.png differ diff --git a/static/home.jpg b/static/home.jpg new file mode 100644 index 0000000..7dd1b05 Binary files /dev/null and b/static/home.jpg differ