Ticket #811: ipv6-9781.diff
File ipv6-9781.diff, 12.4 KB (added by , 16 years ago) |
---|
-
django/db/models/fields/__init__.py
710 710 defaults.update(kwargs) 711 711 return super(IPAddressField, self).formfield(**defaults) 712 712 713 class IP6AddressField(Field): 714 empty_strings_allowed = False 715 def __init__(self, *args, **kwargs): 716 kwargs['max_length'] = 39 717 Field.__init__(self, *args, **kwargs) 718 719 def get_internal_type(self): 720 return "IP6AddressField" 721 722 def formfield(self, **kwargs): 723 defaults = {'form_class': forms.IP6AddressField} 724 defaults.update(kwargs) 725 return super(IP6AddressField, self).formfield(**defaults) 726 727 713 728 class NullBooleanField(Field): 714 729 empty_strings_allowed = False 715 730 def __init__(self, *args, **kwargs): -
django/db/backends/postgresql/introspection.py
8 8 23: 'IntegerField', 9 9 25: 'TextField', 10 10 701: 'FloatField', 11 869: 'IP AddressField',11 869: 'IP6AddressField', 12 12 1043: 'CharField', 13 13 1082: 'DateField', 14 14 1083: 'TimeField', -
django/db/backends/postgresql/creation.py
19 19 'FloatField': 'double precision', 20 20 'IntegerField': 'integer', 21 21 'IPAddressField': 'inet', 22 'IP6AddressField': '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 'FloatField': 'real', 21 21 'IntegerField': 'integer', 22 22 'IPAddressField': 'char(15)', 23 'IP6AddressField': 'char(39)', 23 24 'NullBooleanField': 'bool', 24 25 'OneToOneField': 'integer', 25 26 'PositiveIntegerField': 'integer unsigned', -
django/db/backends/mysql/creation.py
19 19 'FloatField': 'double precision', 20 20 'IntegerField': 'integer', 21 21 'IPAddressField': 'char(15)', 22 'IP6AddressField': 'char(39)', 22 23 'NullBooleanField': 'bool', 23 24 'OneToOneField': 'integer', 24 25 'PositiveIntegerField': 'integer UNSIGNED', … … 63 64 field.rel.to._meta.db_table, field.rel.to._meta.pk.column) 64 65 ] 65 66 return table_output, deferred 66 67 Pas de fin de ligne à la fin du fichier 67 -
django/db/backends/oracle/creation.py
28 28 'FloatField': 'DOUBLE PRECISION', 29 29 'IntegerField': 'NUMBER(11)', 30 30 'IPAddressField': 'VARCHAR2(15)', 31 'IP6AddressField': '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
26 26 import django.core.exceptions 27 27 from django.utils.translation import ugettext_lazy as _ 28 28 from django.utils.encoding import smart_unicode, smart_str 29 from django.utils.http import ip6_normalize 29 30 30 31 from util import ErrorList, ValidationError 31 32 from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, FileInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple, DateTimeInput, TimeInput, SplitDateTimeWidget, SplitHiddenDateTimeWidget … … 40 41 'BooleanField', 'NullBooleanField', 'ChoiceField', 'MultipleChoiceField', 41 42 'ComboField', 'MultiValueField', 'FloatField', 'DecimalField', 42 43 'SplitDateTimeField', 'IPAddressField', 'FilePathField', 'SlugField', 43 'TypedChoiceField' 44 'TypedChoiceField', 'IP6AddressField' 44 45 ) 45 46 46 47 # These values, if given to to_python(), will trigger the self.required check. … … 881 882 def __init__(self, *args, **kwargs): 882 883 super(IPAddressField, self).__init__(ipv4_re, *args, **kwargs) 883 884 885 ipv6_re = re.compile(r'^[0-9a-fA-F]{1,4}(:[0-9a-fA-F]{1,4}){7}$') 886 887 class IP6AddressField(CharField): 888 def __init__(self, *args, **kwargs): 889 super(IP6AddressField, self).__init__(39, 3, *args, **kwargs) 890 891 def clean(self, value): 892 value = super(IP6AddressField, self).clean(value) 893 if value == u'': 894 return value 895 if not ipv4_re.search(value): 896 try: 897 ip = ip6_normalize(value) 898 if not ipv6_re.search(ip): 899 raise ValidationError(_(u'Enter a valid IP address.')) 900 except ValueError: 901 raise ValidationError(_(u'Enter a valid IP address.')) 902 return value 903 884 904 slug_re = re.compile(r'^[-\w]+$') 885 905 886 906 class SlugField(RegexField): -
django/utils/http.py
94 94 i = i % j 95 95 factor -= 1 96 96 return ''.join(base36) 97 98 99 def ip6_normalize(addr): 100 """ 101 Normalize an IPv6 address to allow easy regexp validation 102 mostly checks the length, and gets ride of tricky things 103 like IPv4 mapped addresses and :: shortcuts 104 105 Outputs a string 106 """ 107 # Some basic error checking 108 if addr.count('::') > 2 or ':::' in addr: 109 raise ValueError 110 111 ip = addr.split(':') 112 nbfull = len([elem for elem in ip if elem != '']) 113 nb = len(ip) 114 115 if nbfull >= 1 and '.' in ip[-1]: 116 # Convert IPv4 mapped addresses to full hexa 117 ipv4 = ip[-1].split('.') 118 hex1 = (int(ipv4[0]) << 8) + int(ipv4[1]) 119 hex2 = (int(ipv4[2]) << 8) + int(ipv4[3]) 120 ip[-1:] = [hex(hex1)[2:], hex(hex2)[2:]] 121 nbfull = nbfull + 1 122 nb = nb + 1 123 124 if nbfull == 8 or nbfull == nb: 125 # No need to bother 126 return addr 127 elif nbfull > 8: 128 # Has to be invalid anyway 129 raise ValueError 130 131 # Begin normalization 132 start, end, index = (None, None, 0) 133 for elem in ip: 134 if elem == '': 135 if start is None: 136 start = index 137 end = index 138 else: 139 end = index 140 index += 1 141 pad = 8 - nbfull 142 if end != start: 143 ip[start:end-start+1] = ['0'] * pad 144 else: 145 ip[start] = '0' 146 if pad > 1: 147 ip[start:1] = ['0'] * (pad - 1) 148 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/topics/forms/modelforms.txt
60 60 ``ImageField`` ``ImageField`` 61 61 ``IntegerField`` ``IntegerField`` 62 62 ``IPAddressField`` ``IPAddressField`` 63 ``IP6AddressField`` ``IP6AddressField`` 63 64 ``ManyToManyField`` ``ModelMultipleChoiceField`` (see 64 65 below) 65 66 ``NullBooleanField`` ``CharField`` -
docs/ref/models/fields.txt
626 626 627 627 .. class:: IPAddressField([**options]) 628 628 629 An IP address, in string format (e.g. "192.0.2.30"). The admin represents this629 An IPv4 address, in string format (e.g. "192.0.2.30"). The admin represents this 630 630 as an ``<input type="text">`` (a single-line input). 631 631 632 ``IP6AddressField`` 633 ------------------ 634 635 .. class:: IP6AddressField([**options]) 636 637 An IPv4 or IPv6 address, in string format (e.g. "192.0.2.30" or 638 "2a01:5d8:25ae:9451:20d:39bc:1e6:cab:b2c"). The admin represents this as an 639 ``<input type="text">`` (a single-line input). 640 632 641 ``NullBooleanField`` 633 642 -------------------- 634 643 -
docs/ref/forms/fields.txt
623 623 expression. 624 624 * Error message keys: ``required``, ``invalid`` 625 625 626 ``IP6AddressField`` 627 ~~~~~~~~~~~~~~~~~~ 628 629 .. class:: IP6AddressField(**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