From ce5af572cc27d1b82b94b95075e27fafe5660768 Mon Sep 17 00:00:00 2001 From: Richard Schreiber Date: Tue, 19 May 2026 15:23:30 +0200 Subject: [PATCH] Improve error messages for name-parts inputs (Z#23234440) (#6187) * Improve error messages for name-parts inputs (Z#23234440) * fix isort after flake8 * correct spelling of .med in user-provided title/name * fix search instead of match --- src/pretix/base/forms/questions.py | 52 +++++++++++++++++++----------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/src/pretix/base/forms/questions.py b/src/pretix/base/forms/questions.py index 488e684b7a..a4184fa522 100644 --- a/src/pretix/base/forms/questions.py +++ b/src/pretix/base/forms/questions.py @@ -35,6 +35,7 @@ import copy import json import logging +import re from datetime import timedelta from decimal import Decimal from io import BytesIO @@ -47,9 +48,7 @@ from django.conf import settings from django.contrib import messages from django.core.exceptions import ValidationError from django.core.files.uploadedfile import SimpleUploadedFile -from django.core.validators import ( - MaxValueValidator, MinValueValidator, RegexValidator, -) +from django.core.validators import MaxValueValidator, MinValueValidator from django.db.models import QuerySet from django.forms import Select, widgets from django.forms.widgets import FILE_INPUT_CONTRADICTION @@ -220,20 +219,6 @@ class NamePartsFormField(forms.MultiValueField): defaults = { 'widget': self.widget, 'max_length': kwargs.pop('max_length', None), - 'validators': [ - RegexValidator( - # The following characters should never appear in a name anywhere of - # the world. However, they commonly appear in inputs generated by spam - # bots. - r'^[^$€/%§{}<>~]*$', - message=_('Please do not use special characters in names.') - ), - RegexValidator( - URL_RE, - inverse_match=True, - message=_('Please do not use special characters in names.') - ) - ] } self.max_length = defaults['max_length'] self.scheme_name = kwargs.pop('scheme') @@ -255,7 +240,6 @@ class NamePartsFormField(forms.MultiValueField): if fname == 'title' and self.scheme_titles: d = dict(defaults) d.pop('max_length', None) - d.pop('validators', None) field = forms.ChoiceField( **d, choices=[('', '')] + [(d, d) for d in self.scheme_titles[1]] @@ -264,7 +248,6 @@ class NamePartsFormField(forms.MultiValueField): elif fname == 'salutation': d = dict(defaults) d.pop('max_length', None) - d.pop('validators', None) field = forms.ChoiceField( **d, choices=[ @@ -296,6 +279,37 @@ class NamePartsFormField(forms.MultiValueField): if sum(len(v) for v in value.values() if v) > (self.max_length or 250): raise forms.ValidationError(_('Please enter a shorter name.'), code='max_length') + for fname, label, size in self.scheme['fields']: + if fname == 'salutation' or (fname == 'title' and self.scheme_titles): + continue + v = value.get(fname) + if not v: + continue + special_chars = re.findall('[$€/%§{}<>~]', v) + if special_chars: + raise forms.ValidationError( + _('The field "%(label)s" may not contain special characters such as "%(chars)s".'), + code='name_special_chars', + params={ + "label": label, + "chars": "".join(special_chars), + }, + ) + # URL_RE checks for valid domain names, including one special TLD med, which can be part of a title + if ".med" in v: + v = v.replace(".med", ". med") + value[fname] = v + url_matched = URL_RE.search(v) + if url_matched: + raise forms.ValidationError( + _('The field "%(label)s" may not contain an URL (%(url)s).'), + code='url_in_title', + params={ + "label": label, + "url": url_matched.group(0), + } + ) + if value.get("salutation") == "empty": value["salutation"] = ""