Ticket #811: ipv6-13294.diff
File ipv6-13294.diff, 12.9 KB (added by , 15 years ago) |
---|
-
django/db/models/fields/__init__.py
906 906 defaults.update(kwargs) 907 907 return super(IPAddressField, self).formfield(**defaults) 908 908 909 class IPv6AddressField(Field): 910 empty_strings_allowed = False 911 description = _("IPv6/IPv4 address") 912 def __init__(self, *args, **kwargs): 913 kwargs['max_length'] = 39 914 Field.__init__(self, *args, **kwargs) 915 916 def get_internal_type(self): 917 return "IPv6AddressField" 918 919 def formfield(self, **kwargs): 920 defaults = {'form_class': forms.IPv6AddressField} 921 defaults.update(kwargs) 922 return super(IPv6AddressField, self).formfield(**defaults) 923 924 909 925 class NullBooleanField(Field): 910 926 empty_strings_allowed = False 911 927 default_error_messages = { -
django/db/backends/postgresql/introspection.py
10 10 25: 'TextField', 11 11 700: 'FloatField', 12 12 701: 'FloatField', 13 869: 'IP AddressField',13 869: 'IPv6AddressField', 14 14 1043: 'CharField', 15 15 1082: 'DateField', 16 16 1083: 'TimeField', -
django/db/backends/postgresql/creation.py
19 19 'IntegerField': 'integer', 20 20 'BigIntegerField': 'bigint', 21 21 'IPAddressField': 'inet', 22 'IPv6AddressField': 'inet', 22 23 'NullBooleanField': 'boolean', 23 24 'OneToOneField': 'integer', 24 25 'PositiveIntegerField': 'integer CHECK ("%(column)s" >= 0)', -
django/db/backends/sqlite3/creation.py
20 20 'IntegerField': 'integer', 21 21 'BigIntegerField': 'bigint', 22 22 'IPAddressField': 'char(15)', 23 'IPv6AddressField': 'char(39)', 23 24 'NullBooleanField': 'bool', 24 25 'OneToOneField': 'integer', 25 26 'PositiveIntegerField': 'integer unsigned', -
django/db/backends/mysql/creation.py
19 19 'IntegerField': 'integer', 20 20 'BigIntegerField': 'bigint', 21 21 'IPAddressField': 'char(15)', 22 'IPv6AddressField': 'char(39)', 22 23 'NullBooleanField': 'bool', 23 24 'OneToOneField': 'integer', 24 25 'PositiveIntegerField': 'integer UNSIGNED', -
django/db/backends/oracle/creation.py
28 28 'IntegerField': 'NUMBER(11)', 29 29 'BigIntegerField': 'NUMBER(19)', 30 30 'IPAddressField': 'VARCHAR2(15)', 31 'IPv6AddressField': 'VARCHAR2(39)', 31 32 'NullBooleanField': 'NUMBER(1) CHECK ((%(qn_column)s IN (0,1)) OR (%(qn_column)s IS NULL))', 32 33 'OneToOneField': 'NUMBER(11)', 33 34 'PositiveIntegerField': 'NUMBER(11) CHECK (%(qn_column)s >= 0)', -
django/forms/fields.py
39 39 'BooleanField', 'NullBooleanField', 'ChoiceField', 'MultipleChoiceField', 40 40 'ComboField', 'MultiValueField', 'FloatField', 'DecimalField', 41 41 'SplitDateTimeField', 'IPAddressField', 'FilePathField', 'SlugField', 42 'TypedChoiceField' 42 'TypedChoiceField', 'IPv6AddressField' 43 43 ) 44 44 45 45 def en_format(name): … … 868 868 default_validators = [validators.validate_ipv4_address] 869 869 870 870 871 ipv6_re = re.compile(r'^[0-9a-fA-F]{1,4}(:[0-9a-fA-F]{1,4}){7}$') 872 873 class IPv6AddressField(CharField): 874 default_error_messages = { 875 'invalid': _(u'Enter a valid IP address.'), 876 } 877 default_validators = [validators.validate_ipv6_address] 878 879 871 880 class SlugField(CharField): 872 881 default_error_messages = { 873 882 'invalid': _(u"Enter a valid 'slug' consisting of letters, numbers," -
django/core/validators.py
38 38 if not self.regex.search(smart_unicode(value)): 39 39 raise ValidationError(self.message, code=self.code) 40 40 41 ipv6_re = re.compile(r'^[0-9a-fA-F]{1,4}(:[0-9a-fA-F]{1,4}){7}$') 42 43 class IPv6Validator(object): 44 message = _(u'Enter a valid IP address.') 45 code = 'invalid' 46 47 def __init__(self, message=None, code=None): 48 if message is not None: 49 self.message = message 50 if code is not None: 51 self.code = code 52 53 def __call__(self, value): 54 """ 55 Validates that the input matches an IPv4/IPv6 address 56 """ 57 ip = smart_unicode(value) 58 if not ipv4_re.search(ip): 59 from django.utils.http import ipv6_normalize 60 try: 61 ipv6 = ipv6_normalize(ip) 62 if not ipv6_re.search(ipv6): 63 raise ValidationError(self.message, code=self.code) 64 except ValueError: 65 raise ValidationError(self.message, code=self.code) 66 41 67 class URLValidator(RegexValidator): 42 68 regex = re.compile( 43 69 r'^https?://' # http:// or https:// … … 124 150 125 151 ipv4_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}$') 126 152 validate_ipv4_address = RegexValidator(ipv4_re, _(u'Enter a valid IPv4 address.'), 'invalid') 153 validate_ipv6_address = IPv6Validator(_(u'Enter a valid IPv4 address.'), 'invalid') 127 154 128 155 comma_separated_int_list_re = re.compile('^[\d,]+$') 129 156 validate_comma_separated_integer_list = RegexValidator(comma_separated_int_list_re, _(u'Enter only digits separated by commas.'), 'invalid') -
django/utils/http.py
117 117 """ 118 118 return '"%s"' % etag.replace('\\', '\\\\').replace('"', '\\"') 119 119 120 def ipv6_normalize(addr): 121 """ 122 Normalize an IPv6 address to allow easy regexp validation 123 mostly checks the length, and gets ride of tricky things 124 like IPv4 mapped addresses and :: shortcuts 125 126 Outputs a string 127 """ 128 # Some basic error checking 129 if addr.count('::') > 2 or ':::' in addr: 130 raise ValueError 131 132 ip = addr.split(':') 133 nbfull = len([elem for elem in ip if elem != '']) 134 nb = len(ip) 135 136 if nbfull >= 1 and '.' in ip[-1]: 137 # Convert IPv4 mapped addresses to full hexa 138 ipv4 = ip[-1].split('.') 139 hex1 = (int(ipv4[0]) << 8) + int(ipv4[1]) 140 hex2 = (int(ipv4[2]) << 8) + int(ipv4[3]) 141 ip[-1:] = [hex(hex1)[2:], hex(hex2)[2:]] 142 nbfull = nbfull + 1 143 nb = nb + 1 144 145 if nbfull == 8 or nbfull == nb: 146 # No need to bother 147 return addr 148 elif nbfull > 8: 149 # Has to be invalid anyway 150 raise ValueError 151 152 # Begin normalization 153 start, end, index = (None, None, 0) 154 for elem in ip: 155 if elem == '': 156 if start is None: 157 start = index 158 end = index 159 else: 160 end = index 161 index += 1 162 pad = 8 - nbfull 163 if end != start: 164 ip[start:end-start+1] = ['0'] * pad 165 else: 166 ip[start] = '0' 167 if pad > 1: 168 ip[start:1] = ['0'] * (pad - 1) 169 return ':'.join([item for item in ip if len(item) > 0]) -
tests/regressiontests/forms/extra.py
580 580 ... 581 581 ValidationError: [u'Enter a valid IPv4 address.'] 582 582 583 # IPv6AddressField ################################################################## 584 585 >>> f = IPv6AddressField() 586 >>> f.clean('') 587 Traceback (most recent call last): 588 ... 589 ValidationError: [u'This field is required.'] 590 >>> f.clean(None) 591 Traceback (most recent call last): 592 ... 593 ValidationError: [u'This field is required.'] 594 >>> f.clean('127.0.0.1') 595 u'127.0.0.1' 596 >>> f.clean('2a01:05d8:25ae:9451:020d:39bc:21e6:8cab') 597 u'2a01:05d8:25ae:9451:020d:39bc:21e6:8cab' 598 >>> f.clean('2a01:5d8:25ae:9451:20d:39bc:21e6:8cab') 599 u'2a01:5d8:25ae:9451:20d:39bc:21e6:8cab' 600 >>> f.clean('::1') 601 u'::1' 602 >>> f.clean('::ffff:88.191.32.1') 603 u'::ffff:88.191.32.1' 604 >>> f.clean('foo') 605 Traceback (most recent call last): 606 ... 607 ValidationError: [u'Enter a valid IP address.'] 608 >>> f.clean('127.0.0.') 609 Traceback (most recent call last): 610 ... 611 ValidationError: [u'Enter a valid IP address.'] 612 >>> f.clean('::1:') 613 Traceback (most recent call last): 614 ... 615 ValidationError: [u'Enter a valid IP address.'] 616 >>> f.clean('1.2.3.4.5') 617 Traceback (most recent call last): 618 ... 619 ValidationError: [u'Enter a valid IP address.'] 620 >>> f.clean('2a01:5d8:25ae:9451:20d:39bc:21e6:8cab:fb2c') 621 Traceback (most recent call last): 622 ... 623 ValidationError: [u'Enter a valid IP address.'] 624 >>> f.clean('2a01:5d8:25ae:9451:20d:39bc:1e6:cab:b2c') 625 Traceback (most recent call last): 626 ... 627 ValidationError: [u'Enter a valid IP address.'] 628 >>> f.clean('256.125.1.5') 629 Traceback (most recent call last): 630 ... 631 ValidationError: [u'Enter a valid IP address.'] 632 >>> f.clean('::12345') 633 Traceback (most recent call last): 634 ... 635 ValidationError: [u'Enter a valid IP address.'] 636 637 >>> f = IPv6AddressField(required=False) 638 >>> f.clean('') 639 u'' 640 >>> f.clean(None) 641 u'' 642 >>> f.clean('127.0.0.1') 643 u'127.0.0.1' 644 >>> f.clean('foo') 645 Traceback (most recent call last): 646 ... 647 ValidationError: [u'Enter a valid IP address.'] 648 >>> f.clean('127.0.0.') 649 Traceback (most recent call last): 650 ... 651 ValidationError: [u'Enter a valid IP address.'] 652 >>> f.clean('1.2.3.4.5') 653 Traceback (most recent call last): 654 ... 655 ValidationError: [u'Enter a valid IP address.'] 656 >>> f.clean('256.125.1.5') 657 Traceback (most recent call last): 658 ... 659 ValidationError: [u'Enter a valid IP address.'] 660 661 583 662 ################################# 584 663 # Tests of underlying functions # 585 664 ################################# -
docs/topics/forms/modelforms.txt
79 79 80 80 ``IPAddressField`` ``IPAddressField`` 81 81 82 ``IPv6AddressField`` ``IPv6AddressField`` 83 82 84 ``ManyToManyField`` ``ModelMultipleChoiceField`` (see 83 85 below) 84 86 -
docs/ref/models/fields.txt
715 715 716 716 .. class:: IPAddressField([**options]) 717 717 718 An IP address, in string format (e.g. "192.0.2.30"). The admin represents this718 An IPv4 address, in string format (e.g. "192.0.2.30"). The admin represents this 719 719 as an ``<input type="text">`` (a single-line input). 720 720 721 ``IPv6AddressField`` 722 ------------------ 723 724 .. class:: IPv6AddressField([**options]) 725 726 An IPv4 or IPv6 address, in string format (e.g. "192.0.2.30" or 727 "2a01:5d8:25ae:9451:20d:39bc:1e6:cab:b2c"). The admin represents this as an 728 ``<input type="text">`` (a single-line input). 729 721 730 ``NullBooleanField`` 722 731 -------------------- 723 732 -
docs/ref/forms/fields.txt
623 623 expression. 624 624 * Error message keys: ``required``, ``invalid`` 625 625 626 ``IPv6AddressField`` 627 ~~~~~~~~~~~~~~~~~~ 628 629 .. class:: IPv6AddressField(**kwargs) 630 631 * Default widget: ``TextInput`` 632 * Empty value: ``''`` (an empty string) 633 * Normalizes to: A Unicode object. 634 * Validates that the given value is a valid IPv4 or IPv6 address, using 635 a regular expression. 636 * Error message keys: ``required``, ``invalid`` 637 638 626 639 ``MultipleChoiceField`` 627 640 ~~~~~~~~~~~~~~~~~~~~~~~ 628 641