diff --git a/app/__init__.py b/app/__init__.py index e430742..461c546 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -85,6 +85,8 @@ def create_app(config_path=None, config=None): def inject_globals(): from flask import session from app.models.user import user_get_unread_notifications + from app.services.crackme_fields import ( + DIFFICULTY_CHOICES, LANG_CHOICES, ARCH_CHOICES, PLATFORM_CHOICES) username = session.get('name', '') unread_notifs = 0 @@ -96,7 +98,11 @@ def inject_globals(): 'AuthLevel': 'auth' if username else 'anon', 'usersess': username, 'unread_notifications': unread_notifs, - 'RECAPTCHA_SITEKEY': config['Recaptcha'].get('SiteKey', '') if config['Recaptcha'].get('Enabled') else '' + 'RECAPTCHA_SITEKEY': config['Recaptcha'].get('SiteKey', '') if config['Recaptcha'].get('Enabled') else '', + 'DIFFICULTY_CHOICES': DIFFICULTY_CHOICES, + 'LANG_CHOICES': LANG_CHOICES, + 'ARCH_CHOICES': ARCH_CHOICES, + 'PLATFORM_CHOICES': PLATFORM_CHOICES, } # Register template filters diff --git a/app/services/crackme_fields.py b/app/services/crackme_fields.py new file mode 100644 index 0000000..b288611 --- /dev/null +++ b/app/services/crackme_fields.py @@ -0,0 +1,53 @@ +"""Controlled vocabularies for a crackme's single-value classification fields. + +Language, architecture and platform are each a single value chosen on the +upload and edit forms. Keeping the option lists here (instead of hardcoding +them into each template) means the upload form, the edit form and any future +consumer all agree on the exact same choices. +""" + +# (submitted value, display label) pairs — the value is the stored integer. +DIFFICULTY_CHOICES = [ + ('1', '1. Very Easy'), + ('2', '2. Easy'), + ('3', '3. Medium'), + ('4', '4. Hard'), + ('5', '5. Very Hard'), + ('6', '6. Insane'), +] + +LANG_CHOICES = [ + 'C/C++', + 'Assembler', + 'Java', + 'Go', + 'Rust', + 'WebAssembly', + 'Python', + 'AutoIt', + '(Visual) Basic', + 'Borland Delphi', + 'Turbo Pascal', + '.NET', + 'Unspecified/other', +] + +ARCH_CHOICES = [ + 'x86', + 'x86-64', + 'java', + 'ARM', + 'MIPS', + 'RISC-V', + 'other', +] + +PLATFORM_CHOICES = [ + 'Mac OS X', + 'Multiplatform', + 'Unix/linux etc.', + 'Windows', + 'Android', + 'iOS', + 'Unspecified/other', +] diff --git a/static/css/custom.css b/static/css/custom.css index b6cbb16..5545fbb 100644 --- a/static/css/custom.css +++ b/static/css/custom.css @@ -37,6 +37,19 @@ a:active { color: #9acc14;} .form-select:focus { border-color: #9acc14; } +/* Boxed inline radio/checkbox group (templates/partial/choice_inputs.html). + Keeps each metadata field (difficulty/lang/arch/platform) visually + separated instead of blending into the fields around it. */ +.choice-box { + border: .05rem solid #444; + border-radius: .1rem; + padding: 8px 10px 4px; +} +.choice-box .form-radio, +.choice-box .form-checkbox { + margin-bottom: 4px; +} + button, select { text-transform: none; } diff --git a/templates/crackme/create.html b/templates/crackme/create.html index 6b32371..9bfd1c3 100644 --- a/templates/crackme/create.html +++ b/templates/crackme/create.html @@ -38,14 +38,11 @@

Quick Rules

- + {% set choice_type = 'radio' %} + {% set choice_name = 'difficulty' %} + {% set choice_options = DIFFICULTY_CHOICES %} + {% set choice_selected = '' %} + {% include 'partial/choice_inputs.html' %}
@@ -53,21 +50,11 @@

Quick Rules

- + {% set choice_type = 'radio' %} + {% set choice_name = 'lang' %} + {% set choice_options = LANG_CHOICES %} + {% set choice_selected = '' %} + {% include 'partial/choice_inputs.html' %}
@@ -75,15 +62,11 @@

Quick Rules

- + {% set choice_type = 'radio' %} + {% set choice_name = 'arch' %} + {% set choice_options = ARCH_CHOICES %} + {% set choice_selected = '' %} + {% include 'partial/choice_inputs.html' %}
@@ -91,15 +74,11 @@

Quick Rules

- + {% set choice_type = 'radio' %} + {% set choice_name = 'platform' %} + {% set choice_options = PLATFORM_CHOICES %} + {% set choice_selected = '' %} + {% include 'partial/choice_inputs.html' %}
@@ -113,9 +92,11 @@

Quick Rules

applies, the specific technique underneath — ticking a technique ticks its category automatically. Reviewers may adjust these later.

- {% set label_input_name = 'labels' %} - {% set checked_labels = [] %} - {% include 'partial/labels_checkboxes.html' %} +
+ {% set label_input_name = 'labels' %} + {% set checked_labels = [] %} + {% include 'partial/labels_checkboxes.html' %} +
diff --git a/templates/crackme/edit.html b/templates/crackme/edit.html index 226dc7f..6974bc2 100644 --- a/templates/crackme/edit.html +++ b/templates/crackme/edit.html @@ -16,21 +16,11 @@

Edit crackme: {{ crackme.name }}

- + {% set choice_type = 'radio' %} + {% set choice_name = 'lang' %} + {% set choice_options = LANG_CHOICES %} + {% set choice_selected = crackme.lang %} + {% include 'partial/choice_inputs.html' %}
@@ -38,15 +28,11 @@

Edit crackme: {{ crackme.name }}

- + {% set choice_type = 'radio' %} + {% set choice_name = 'arch' %} + {% set choice_options = ARCH_CHOICES %} + {% set choice_selected = crackme.arch %} + {% include 'partial/choice_inputs.html' %}
@@ -54,15 +40,11 @@

Edit crackme: {{ crackme.name }}

- + {% set choice_type = 'radio' %} + {% set choice_name = 'platform' %} + {% set choice_options = PLATFORM_CHOICES %} + {% set choice_selected = crackme.platform %} + {% include 'partial/choice_inputs.html' %}
diff --git a/templates/partial/choice_inputs.html b/templates/partial/choice_inputs.html new file mode 100644 index 0000000..3123f18 --- /dev/null +++ b/templates/partial/choice_inputs.html @@ -0,0 +1,22 @@ +{# Inline radio/checkbox group, boxed and laid out like the label checkboxes + (templates/partial/labels_checkboxes.html) instead of an ugly multi-line + select list box. + + Expects: + choice_type - 'radio' (single-select) or 'checkbox' (multi-select) + choice_name - form field name (e.g. 'lang') + choice_options - list of options; each item is either a plain string + (value == label) or a (value, label) pair + choice_selected - radio: the selected value string ('' when none) + checkbox: a list of the selected values #} +
+{% for opt in choice_options %} + {% set val = opt if opt is string else opt[0] %} + {% set text = opt if opt is string else opt[1] %} + {% set is_checked = (val in choice_selected) if choice_type == 'checkbox' else (choice_selected == val) %} + +{% endfor %} +
diff --git a/templates/search/search.html b/templates/search/search.html index 50b260f..7b6c979 100644 --- a/templates/search/search.html +++ b/templates/search/search.html @@ -114,21 +114,11 @@

Crackme search

- + {% set choice_type = 'checkbox' %} + {% set choice_name = 'lang' %} + {% set choice_options = LANG_CHOICES %} + {% set choice_selected = search_params.get('lang', []) %} + {% include 'partial/choice_inputs.html' %}
@@ -136,15 +126,11 @@

Crackme search

- + {% set choice_type = 'checkbox' %} + {% set choice_name = 'arch' %} + {% set choice_options = ARCH_CHOICES %} + {% set choice_selected = search_params.get('arch', []) %} + {% include 'partial/choice_inputs.html' %}
@@ -152,19 +138,11 @@

Crackme search

- + {% set choice_type = 'checkbox' %} + {% set choice_name = 'platform' %} + {% set choice_options = PLATFORM_CHOICES %} + {% set choice_selected = search_params.get('platform', []) %} + {% include 'partial/choice_inputs.html' %}