Ticket #811: ipv6-standalone.diff
File ipv6-standalone.diff, 16.5 KB (added by , 17 years ago) |
---|
-
django/oldforms/__init__.py
933 933 934 934 def isValidIPAddress(self, field_data, all_data): 935 935 try: 936 validators.isValidIP Address4(field_data, all_data)936 validators.isValidIP4Address(field_data, all_data) 937 937 except validators.ValidationError, e: 938 938 raise validators.CriticalValidationError, e.messages 939 939 … … 941 941 return data or None 942 942 html2python = staticmethod(html2python) 943 943 944 class IP6AddressField(IPAddressField): 945 def __init__(self, field_name, length=39, max_length=39, is_required=False, validator_list=None): 946 if validator_list is None: validator_list = [] 947 validator_list = [self.isValidIPAddress] + validator_list 948 TextField.__init__(self, field_name, length=length, max_length=max_length, 949 is_required=is_required, validator_list=validator_list) 950 951 def isValidIPAddress(self, field_data, all_data): 952 try: 953 validators.isValidIPAddress(field_data, all_data) 954 except validators.ValidationError, e: 955 raise validators.CriticalValidationError, e.messages 956 957 def html2python(data): 958 return data or None 959 html2python = staticmethod(html2python) 960 944 961 #################### 945 962 # MISCELLANEOUS # 946 963 #################### -
django/db/models/fields/__init__.py
943 943 defaults.update(kwargs) 944 944 return super(IPAddressField, self).formfield(**defaults) 945 945 946 class IP6AddressField(Field): 947 empty_strings_allowed = False 948 def __init__(self, *args, **kwargs): 949 kwargs['max_length'] = 39 950 Field.__init__(self, *args, **kwargs) 951 952 def get_manipulator_field_objs(self): 953 return [oldforms.IP6AddressField] 954 955 def validate(self, field_data, all_data): 956 validators.isValidIPAddress(field_data, None) 957 958 def formfield(self, **kwargs): 959 defaults = {'form_class': forms.IP6AddressField} 960 defaults.update(kwargs) 961 return super(IP6AddressField, self).formfield(**defaults) 962 963 946 964 class NullBooleanField(Field): 947 965 empty_strings_allowed = False 948 966 def __init__(self, *args, **kwargs): -
django/db/backends/postgresql/introspection.py
75 75 23: 'IntegerField', 76 76 25: 'TextField', 77 77 701: 'FloatField', 78 869: 'IP AddressField',78 869: 'IP6AddressField', 79 79 1043: 'CharField', 80 80 1082: 'DateField', 81 81 1083: 'TimeField', -
django/db/backends/postgresql/creation.py
16 16 'ImageField': 'varchar(%(max_length)s)', 17 17 'IntegerField': 'integer', 18 18 'IPAddressField': 'inet', 19 'IP6AddressField': 'inet', 19 20 'NullBooleanField': 'boolean', 20 21 'OneToOneField': 'integer', 21 22 'PhoneNumberField': 'varchar(20)', -
django/db/backends/mysql_old/creation.py
16 16 'ImageField': 'varchar(%(max_length)s)', 17 17 'IntegerField': 'integer', 18 18 'IPAddressField': 'char(15)', 19 'IP6AddressField': 'char(39)', 19 20 'NullBooleanField': 'bool', 20 21 'OneToOneField': 'integer', 21 22 'PhoneNumberField': 'varchar(20)', -
django/db/backends/sqlite3/creation.py
15 15 'ImageField': 'varchar(%(max_length)s)', 16 16 'IntegerField': 'integer', 17 17 'IPAddressField': 'char(15)', 18 'IP6AddressField': 'char(39)', 18 19 'NullBooleanField': 'bool', 19 20 'OneToOneField': 'integer', 20 21 'PhoneNumberField': 'varchar(20)', -
django/db/backends/mysql/creation.py
16 16 'ImageField': 'varchar(%(max_length)s)', 17 17 'IntegerField': 'integer', 18 18 'IPAddressField': 'char(15)', 19 'IPAddressField': 'char(39)', 19 20 'NullBooleanField': 'bool', 20 21 'OneToOneField': 'integer', 21 22 'PhoneNumberField': 'varchar(20)', -
django/db/backends/oracle/creation.py
19 19 'ImageField': 'NVARCHAR2(%(max_length)s)', 20 20 'IntegerField': 'NUMBER(11)', 21 21 'IPAddressField': 'VARCHAR2(15)', 22 'IP6AddressField': 'VARCHAR2(39)', 22 23 'NullBooleanField': 'NUMBER(1) CHECK ((%(column)s IN (0,1)) OR (%(column)s IS NULL))', 23 24 'OneToOneField': 'NUMBER(11)', 24 25 'PhoneNumberField': 'VARCHAR2(20)', -
django/db/backends/postgresql_psycopg2/introspection.py
72 72 23: 'IntegerField', 73 73 25: 'TextField', 74 74 701: 'FloatField', 75 869: 'IP AddressField',75 869: 'IP6AddressField', 76 76 1043: 'CharField', 77 77 1082: 'DateField', 78 78 1083: 'TimeField', -
django/core/validators.py
19 19 from django.utils.translation import ugettext as _, ugettext_lazy, ungettext 20 20 from django.utils.functional import Promise, lazy 21 21 from django.utils.encoding import force_unicode, smart_str 22 from django.utils.http import ip6_normalize 22 23 23 24 _datere = r'\d{4}-\d{1,2}-\d{1,2}' 24 25 _timere = r'(?:[01]?[0-9]|2[0-3]):[0-5][0-9](?::[0-5][0-9])?' … … 33 34 r')@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$', re.IGNORECASE) # domain 34 35 integer_re = re.compile(r'^-?\d+$') 35 36 ip4_re = re.compile(r'^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$') 37 ip6_re = re.compile(r'^[0-9a-fA-F]{1,4}(:[0-9a-fA-F]{1,4}){7}$') 36 38 phone_re = re.compile(r'^[A-PR-Y0-9]{3}-[A-PR-Y0-9]{3}-[A-PR-Y0-9]{4}$', re.IGNORECASE) 37 39 slug_re = re.compile(r'^[-\w]+$') 38 40 url_re = re.compile(r'^https?://\S+$') … … 106 108 except ValidationError: 107 109 raise ValidationError, _("Enter valid e-mail addresses separated by commas.") 108 110 109 def isValidIP Address4(field_data, all_data):111 def isValidIP4Address(field_data, all_data): 110 112 if not ip4_re.search(field_data): 111 raise ValidationError, _("Please enter a valid IP address.")113 raise ValidationError, _("Please enter a valid IPv4 address.") 112 114 115 def isValidIPAddress(field_data, all_data): 116 if not ip4_re.search(field_data): 117 try: 118 ip = ip6_normalize(field_data) 119 if not ip6_re.search(ip): 120 raise ValidationError, _("Please enter a valid IP address.") 121 except ValueError: 122 raise ValidationError, _("Please enter a valid IP address.") 123 113 124 def isNotEmpty(field_data, all_data): 114 125 if field_data.strip() == '': 115 126 raise ValidationError, _("Empty values are not allowed here.") -
django/newforms/fields.py
19 19 20 20 from django.utils.translation import ugettext_lazy as _ 21 21 from django.utils.encoding import StrAndUnicode, smart_unicode, smart_str 22 from django.utils.http import ip6_normalize 22 23 23 24 from util import ErrorList, ValidationError 24 25 from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, FileInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple, DateTimeInput … … 32 33 'RegexField', 'EmailField', 'FileField', 'ImageField', 'URLField', 33 34 'BooleanField', 'NullBooleanField', 'ChoiceField', 'MultipleChoiceField', 34 35 'ComboField', 'MultiValueField', 'FloatField', 'DecimalField', 35 'SplitDateTimeField', 'IPAddressField', 'FilePathField', 36 'SplitDateTimeField', 'IPAddressField', 'FilePathField', 'IP6AddressField', 36 37 ) 37 38 38 39 # These values, if given to to_python(), will trigger the self.required check. … … 782 783 783 784 def __init__(self, *args, **kwargs): 784 785 super(IPAddressField, self).__init__(ipv4_re, *args, **kwargs) 786 787 ipv6_re = re.compile(r'^[0-9a-fA-F]{1,4}(:[0-9a-fA-F]{1,4}){7}$') 788 789 class IP6AddressField(CharField): 790 def __init__(self, *args, **kwargs): 791 super(IP6AddressField, self).__init__(39, 3, *args, **kwargs) 792 793 def clean(self, value): 794 value = super(IP6AddressField, self).clean(value) 795 if value == u'': 796 return value 797 if not ipv4_re.search(value): 798 try: 799 ip = ip6_normalize(value) 800 if not ipv6_re.search(ip): 801 raise ValidationError(_(u'Enter a valid IP address.')) 802 except ValueError: 803 raise ValidationError(_(u'Enter a valid IP address.')) 804 return value -
django/utils/http.py
65 65 """ 66 66 rfcdate = formatdate(epoch_seconds) 67 67 return '%s GMT' % rfcdate[:25] 68 69 def ip6_normalize(addr): 70 """ 71 Normalize an IPv6 address to allow easy regexp validation 72 mostly checks the length, and gets ride of tricky things 73 like IPv4 mapped addresses and :: shortcuts 74 75 Outputs a string 76 """ 77 # Some basic error checking 78 if addr.count('::') > 2 or ':::' in addr: 79 raise ValueError 80 81 ip = addr.split(':') 82 nbfull = len([elem for elem in ip if elem != '']) 83 nb = len(ip) 84 85 if nbfull >= 1 and '.' in ip[-1]: 86 # Convert IPv4 mapped addresses to full hexa 87 ipv4 = ip[-1].split('.') 88 hex1 = (int(ipv4[0]) << 8) + int(ipv4[1]) 89 hex2 = (int(ipv4[2]) << 8) + int(ipv4[3]) 90 ip[-1:] = [hex(hex1)[2:], hex(hex2)[2:]] 91 nbfull = nbfull + 1 92 nb = nb + 1 93 94 if nbfull == 8 or nbfull == nb: 95 # No need to bother 96 return addr 97 elif nbfull > 8: 98 # Has to be invalid anyway 99 raise ValueError 100 101 # Begin normalization 102 start, end, index = (None, None, 0) 103 for elem in ip: 104 if elem == '': 105 if start is None: 106 start = index 107 end = index 108 else: 109 end = index 110 index += 1 111 pad = 8 - nbfull 112 if end != start: 113 ip[start:end-start+1] = ['0'] * pad 114 else: 115 ip[start] = '0' 116 if pad > 1: 117 ip[start:1] = ['0'] * (pad - 1) 118 return ':'.join([item for item in ip if len(item) > 0]) -
tests/regressiontests/forms/extra.py
377 377 ... 378 378 ValidationError: [u'Enter a valid IPv4 address.'] 379 379 380 # IP6AddressField ################################################################## 381 382 >>> f = IP6AddressField() 383 >>> f.clean('') 384 Traceback (most recent call last): 385 ... 386 ValidationError: [u'This field is required.'] 387 >>> f.clean(None) 388 Traceback (most recent call last): 389 ... 390 ValidationError: [u'This field is required.'] 391 >>> f.clean('127.0.0.1') 392 u'127.0.0.1' 393 >>> f.clean('2a01:05d8:25ae:9451:020d:39bc:21e6:8cab') 394 u'2a01:05d8:25ae:9451:020d:39bc:21e6:8cab' 395 >>> f.clean('2a01:5d8:25ae:9451:20d:39bc:21e6:8cab') 396 u'2a01:5d8:25ae:9451:20d:39bc:21e6:8cab' 397 >>> f.clean('::1') 398 u'::1' 399 >>> f.clean('::ffff:88.191.32.1') 400 u'::ffff:88.191.32.1' 401 >>> f.clean('foo') 402 Traceback (most recent call last): 403 ... 404 ValidationError: [u'Enter a valid IP address.'] 405 >>> f.clean('127.0.0.') 406 Traceback (most recent call last): 407 ... 408 ValidationError: [u'Enter a valid IP address.'] 409 >>> f.clean('::1:') 410 Traceback (most recent call last): 411 ... 412 ValidationError: [u'Enter a valid IP address.'] 413 >>> f.clean('1.2.3.4.5') 414 Traceback (most recent call last): 415 ... 416 ValidationError: [u'Enter a valid IP address.'] 417 >>> f.clean('2a01:5d8:25ae:9451:20d:39bc:21e6:8cab:fb2c') 418 Traceback (most recent call last): 419 ... 420 ValidationError: [u'Ensure this value has at most 39 characters (it has 42).'] 421 >>> f.clean('2a01:5d8:25ae:9451:20d:39bc:1e6:cab:b2c') 422 Traceback (most recent call last): 423 ... 424 ValidationError: [u'Enter a valid IP address.'] 425 >>> f.clean('256.125.1.5') 426 Traceback (most recent call last): 427 ... 428 ValidationError: [u'Enter a valid IP address.'] 429 >>> f.clean('::12345') 430 Traceback (most recent call last): 431 ... 432 ValidationError: [u'Enter a valid IP address.'] 433 434 >>> f = IP6AddressField(required=False) 435 >>> f.clean('') 436 u'' 437 >>> f.clean(None) 438 u'' 439 >>> f.clean('127.0.0.1') 440 u'127.0.0.1' 441 >>> f.clean('foo') 442 Traceback (most recent call last): 443 ... 444 ValidationError: [u'Enter a valid IP address.'] 445 >>> f.clean('127.0.0.') 446 Traceback (most recent call last): 447 ... 448 ValidationError: [u'Enter a valid IP address.'] 449 >>> f.clean('1.2.3.4.5') 450 Traceback (most recent call last): 451 ... 452 ValidationError: [u'Enter a valid IP address.'] 453 >>> f.clean('256.125.1.5') 454 Traceback (most recent call last): 455 ... 456 ValidationError: [u'Enter a valid IP address.'] 457 458 380 459 ################################# 381 460 # Tests of underlying functions # 382 461 ################################# -
docs/modelforms.txt
58 58 ``ImageField`` ``ImageField`` 59 59 ``IntegerField`` ``IntegerField`` 60 60 ``IPAddressField`` ``IPAddressField`` 61 ``IP6AddressField`` ``IP6AddressField`` 61 62 ``ManyToManyField`` ``ModelMultipleChoiceField`` (see 62 63 below) 63 64 ``NullBooleanField`` ``CharField`` -
docs/model-api.txt
388 388 389 389 The admin represents this as an ``<input type="text">`` (a single-line input). 390 390 391 ``IP6AddressField`` 392 ~~~~~~~~~~~~~~~~~~ 393 394 An IPv6 or IPv4 address, in string format (i.e. "24.124.1.30", 395 "2002:58bf:278c::1", "::ffff:88.191.52.1"). 396 397 The admin represents this as an ``<input type="text">`` (a single-line input). 398 391 399 ``NullBooleanField`` 392 400 ~~~~~~~~~~~~~~~~~~~~ 393 401 -
docs/newforms.txt
1427 1427 expression. 1428 1428 * Error message keys: ``required``, ``invalid`` 1429 1429 1430 ``IP6AddressField`` 1431 ~~~~~~~~~~~~~~~~~~ 1432 1433 * Default widget: ``TextInput`` 1434 * Empty value: ``''`` (an empty string) 1435 * Normalizes to: A Unicode object. 1436 * Validates that the given value is a valid IPv4 or IPv6 address 1437 * Error message keys: ``required``, ``invalid`` 1438 1430 1439 ``MultipleChoiceField`` 1431 1440 ~~~~~~~~~~~~~~~~~~~~~~~ 1432 1441 -
docs/form_for_model.txt
65 65 ``ImageField`` ``ImageField`` 66 66 ``IntegerField`` ``IntegerField`` 67 67 ``IPAddressField`` ``IPAddressField`` 68 ``IP6AddressField`` ``IP6AddressField`` 68 69 ``ManyToManyField`` ``ModelMultipleChoiceField`` (see 69 70 below) 70 71 ``NullBooleanField`` ``CharField``