Commit 9ed6e08f authored by Aymeric Augustin's avatar Aymeric Augustin
Browse files

Removed deprecated URLField.verify_exists.

The deprecation schedule was slightly accelerated because of possible security ramifications.



git-svn-id: http://code.djangoproject.com/svn/django/trunk@17847 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent 800e3941
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -403,11 +403,6 @@ THOUSAND_SEPARATOR = ','
# Hint: you really don't!
TRANSACTIONS_MANAGED = False

# The User-Agent string to use when checking for URL validity through the
# isExistingURL validator.
from django import get_version
URL_VALIDATOR_USER_AGENT = "Django/%s (https://www.djangoproject.com)" % get_version()

# The tablespaces to use for each model when not specified otherwise.
DEFAULT_TABLESPACE = ''
DEFAULT_INDEX_TABLESPACE = ''
+1 −65
Original line number Diff line number Diff line
import re
import urllib
import urllib2
import urlparse

from django.core.exceptions import ValidationError
@@ -11,13 +9,6 @@ from django.utils.ipv6 import is_valid_ipv6_address
# These values, if given to validate(), will trigger the self.required check.
EMPTY_VALUES = (None, '', [], (), {})

try:
    from django.conf import settings
    URL_VALIDATOR_USER_AGENT = settings.URL_VALIDATOR_USER_AGENT
except ImportError:
    # It's OK if Django settings aren't configured.
    URL_VALIDATOR_USER_AGENT = 'Django (http://www.djangoproject.com/)'

class RegexValidator(object):
    regex = ''
    message = _(u'Enter a valid value.')
@@ -51,11 +42,8 @@ class URLValidator(RegexValidator):
        r'(?::\d+)?' # optional port
        r'(?:/?|[/?]\S+)$', re.IGNORECASE)

    def __init__(self, verify_exists=False,
                 validator_user_agent=URL_VALIDATOR_USER_AGENT):
    def __init__(self):
        super(URLValidator, self).__init__()
        self.verify_exists = verify_exists
        self.user_agent = validator_user_agent

    def __call__(self, value):
        try:
@@ -76,58 +64,6 @@ class URLValidator(RegexValidator):
        else:
            url = value

        if self.verify_exists:
            import warnings
            warnings.warn(
                "The URLField verify_exists argument has intractable security "
                "and performance issues. Accordingly, it has been deprecated.",
                DeprecationWarning
                )

            headers = {
                "Accept": "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5",
                "Accept-Language": "en-us,en;q=0.5",
                "Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
                "Connection": "close",
                "User-Agent": self.user_agent,
            }
            url = url.encode('utf-8')
            # Quote characters from the unreserved set, refs #16812
            url = urllib.quote(url, "!*'();:@&=+$,/?#[]")
            broken_error = ValidationError(
                _(u'This URL appears to be a broken link.'), code='invalid_link')
            try:
                req = urllib2.Request(url, None, headers)
                req.get_method = lambda: 'HEAD'
                #Create an opener that does not support local file access
                opener = urllib2.OpenerDirector()

                #Don't follow redirects, but don't treat them as errors either
                error_nop = lambda *args, **kwargs: True
                http_error_processor = urllib2.HTTPErrorProcessor()
                http_error_processor.http_error_301 = error_nop
                http_error_processor.http_error_302 = error_nop
                http_error_processor.http_error_307 = error_nop

                handlers = [urllib2.UnknownHandler(),
                            urllib2.HTTPHandler(),
                            urllib2.HTTPDefaultErrorHandler(),
                            urllib2.FTPHandler(),
                            http_error_processor]
                try:
                    import ssl
                except ImportError:
                    # Python isn't compiled with SSL support
                    pass
                else:
                    handlers.append(urllib2.HTTPSHandler())
                map(opener.add_handler, handlers)
                opener.open(req, timeout=10)
            except ValueError:
                raise ValidationError(_(u'Enter a valid URL.'), code='invalid')
            except: # urllib2.URLError, httplib.InvalidURL, etc.
                raise broken_error


def validate_integer(value):
    try:
+3 −5
Original line number Diff line number Diff line
@@ -1251,12 +1251,10 @@ class TimeField(Field):
class URLField(CharField):
    description = _("URL")

    def __init__(self, verbose_name=None, name=None, verify_exists=False,
                 **kwargs):
    def __init__(self, verbose_name=None, name=None, **kwargs):
        kwargs['max_length'] = kwargs.get('max_length', 200)
        CharField.__init__(self, verbose_name, name, **kwargs)
        self.validators.append(
            validators.URLValidator(verify_exists=verify_exists))
        self.validators.append(validators.URLValidator())

    def formfield(self, **kwargs):
        # As with CharField, this will cause URL validation to be performed
+3 −6
Original line number Diff line number Diff line
@@ -598,14 +598,11 @@ class ImageField(FileField):
class URLField(CharField):
    default_error_messages = {
        'invalid': _(u'Enter a valid URL.'),
        'invalid_link': _(u'This URL appears to be a broken link.'),
    }

    def __init__(self, max_length=None, min_length=None, verify_exists=False,
            validator_user_agent=validators.URL_VALIDATOR_USER_AGENT, *args, **kwargs):
        super(URLField, self).__init__(max_length, min_length, *args,
                                       **kwargs)
        self.validators.append(validators.URLValidator(verify_exists=verify_exists, validator_user_agent=validator_user_agent))
    def __init__(self, max_length=None, min_length=None, *args, **kwargs):
        super(URLField, self).__init__(max_length, min_length, *args, **kwargs)
        self.validators.append(validators.URLValidator())

    def to_python(self, value):

+1 −15
Original line number Diff line number Diff line
@@ -789,7 +789,7 @@ For each field, we describe the default widget used if you don't specify
    * Empty value: ``''`` (an empty string)
    * Normalizes to: A Unicode object.
    * Validates that the given value is a valid URL.
    * Error message keys: ``required``, ``invalid``, ``invalid_link``
    * Error message keys: ``required``, ``invalid``

    Takes the following optional arguments:

@@ -798,20 +798,6 @@ For each field, we describe the default widget used if you don't specify

    These are the same as ``CharField.max_length`` and ``CharField.min_length``.

    .. attribute:: verify_exists

        If ``True``, the validator will attempt to load the given URL, raising
        ``ValidationError`` if the page gives a 404. Defaults to ``False``.

        .. deprecated:: 1.4
            ``verify_exists`` was deprecated for security reasons and will be removed in
            Django 1.5. This deprecation also removes ``validator_user_agent``.

    .. attribute:: validator_user_agent

        String used as the user-agent used when checking for a URL's existence.
        Defaults to the value of the :setting:`URL_VALIDATOR_USER_AGENT` setting.

.. versionchanged:: 1.2
   The URLField previously did not recognize URLs as valid that contained an IDN
   (Internationalized Domain Name; a domain name containing unicode characters)
Loading