from urllib.parse import urlsplit from flask import current_app from wtforms import ValidationError from ..url_security import ( AddressResolutionError, NonPublicAddressError, ensure_public_url, ) class NotEqualTo: """ Compares the values of two fields. :param fieldname: The name of the other field to compare to. :param message: Error message to raise in case of a validation error. Can be interpolated with `%(other_label)s` and `%(other_name)s` to provide a more helpful error. """ def __init__(self, fieldname, message=None): self.fieldname = fieldname self.message = message def __call__(self, form, field): try: other = form[self.fieldname] except KeyError as exc: raise ValidationError( field.gettext("Invalid field name '%s'.") % self.fieldname ) from exc if field.data != other.data: return d = { "other_label": hasattr(other, "label") and other.label.text or self.fieldname, "other_name": self.fieldname, } message = self.message if message is None: message = field.gettext("Field must not be equal to %(other_name)s.") raise ValidationError(message % d) class AllowedHostname: def __init__(self, message=None): self.message = message def __call__(self, form, field): if ( urlsplit(field.data).hostname in current_app.config["WEBMENTIONS_SSG_ALLOWED_HOSTNAMES"] ): return message = self.message if self.message is None: message = field.gettext("Invalid input.") raise ValidationError(message) class PublicURL: def __init__(self, message=None): self.message = message def __call__(self, form, field): try: ensure_public_url(field.data) except ( AddressResolutionError, NonPublicAddressError, ) as exc: message = self.message if message is None: message = field.gettext("URL must resolve to a public address.") raise ValidationError(message) from exc