diff --git a/netbox/extras/forms.py b/netbox/extras/forms.py index 06c5403c6..3d14cd000 100644 --- a/netbox/extras/forms.py +++ b/netbox/extras/forms.py @@ -3,6 +3,7 @@ from collections import OrderedDict from django import forms from django.contrib.contenttypes.models import ContentType +from utilities.forms import LaxURLField from .models import ( CF_TYPE_BOOLEAN, CF_TYPE_DATE, CF_TYPE_INTEGER, CF_TYPE_SELECT, CF_TYPE_URL, CustomField, CustomFieldValue ) @@ -56,7 +57,7 @@ def get_custom_fields_for_model(content_type, filterable_only=False, bulk_edit=F # URL elif cf.type == CF_TYPE_URL: - field = forms.URLField(required=cf.required, initial=cf.default) + field = LaxURLField(required=cf.required, initial=cf.default) # Text else: diff --git a/netbox/utilities/forms.py b/netbox/utilities/forms.py index 1df25891b..2fe8c2d23 100644 --- a/netbox/utilities/forms.py +++ b/netbox/utilities/forms.py @@ -4,6 +4,7 @@ import re from django import forms from django.core.urlresolvers import reverse_lazy +from django.core.validators import URLValidator from django.utils.encoding import force_text from django.utils.html import format_html from django.utils.safestring import mark_safe @@ -253,6 +254,21 @@ class FilterChoiceField(forms.ModelMultipleChoiceField): choices = property(_get_choices, forms.ChoiceField._set_choices) +class LaxURLField(forms.URLField): + """ + Custom URLField which allows any valid URL scheme + """ + + class AnyURLScheme(object): + # A fake URL list which "contains" all scheme names abiding by the syntax defined in RFC 3986 section 3.1 + def __contains__(self, item): + if not item or not re.match('^[a-z][0-9a-z+\-.]*$', item.lower()): + return False + return True + + default_validators = [URLValidator(schemes=AnyURLScheme())] + + # # Forms #