~ubuntu-branches/ubuntu/raring/horizon/raring

« back to all changes in this revision

Viewing changes to horizon/utils/fields.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2012-05-24 14:33:20 UTC
  • mfrom: (1.1.14)
  • Revision ID: package-import@ubuntu.com-20120524143320-i7eswfq6ecxlvh5a
Tags: 2012.2~f1-0ubuntu1
* New usptream release. 
* Prepare for quantal:
  - debian/patches/fix-coverage-binary-name.patch: Refreshed.
* Temporarily pass the testsuite.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import re
 
2
import netaddr
 
3
from django.core.exceptions import ValidationError
 
4
from django.forms import forms
 
5
from django.utils.translation import ugettext as _
 
6
 
 
7
ip_allowed_symbols_re = re.compile(r'^[a-fA-F0-9:/\.]+$')
 
8
IPv4 = 1
 
9
IPv6 = 2
 
10
 
 
11
 
 
12
class IPField(forms.Field):
 
13
    """
 
14
    Form field for entering IP/range values, with validation.
 
15
    Supports IPv4/IPv6 in the format:
 
16
    .. xxx.xxx.xxx.xxx
 
17
    .. xxx.xxx.xxx.xxx/zz
 
18
    .. ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
 
19
    .. ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/zz
 
20
    and all compressed forms. Also the short forms
 
21
    are supported:
 
22
    xxx/yy
 
23
    xxx.xxx/yy
 
24
 
 
25
    .. attribute:: version
 
26
 
 
27
        Specifies which IP version to validate,
 
28
        valid values are 1 (fields.IPv4), 2 (fields.IPv6) or
 
29
        both - 3 (fields.IPv4 | fields.IPv6).
 
30
        Defaults to IPv4 (1)
 
31
 
 
32
    .. attribute:: mask
 
33
 
 
34
        Boolean flag to validate subnet masks along with IP address.
 
35
        E.g: 10.0.0.1/32
 
36
 
 
37
    .. attribute:: mask_range_from
 
38
        Subnet range limitation, e.g. 16
 
39
        That means the input mask will be checked to be in the range
 
40
        16:max_value. Useful to limit the subnet ranges
 
41
        to A/B/C-class networks.
 
42
    """
 
43
    invalid_format_message = _("Incorrect format for IP address")
 
44
    invalid_version_message = _("Invalid version for IP address")
 
45
    invalid_mask_message = _("Invalid subnet mask")
 
46
    max_v4_mask = 32
 
47
    max_v6_mask = 128
 
48
 
 
49
    def __init__(self, *args, **kwargs):
 
50
        self.mask = kwargs.pop("mask", None)
 
51
        self.min_mask = kwargs.pop("mask_range_from", 0)
 
52
        self.version = kwargs.pop('version', IPv4)
 
53
 
 
54
        super(IPField, self).__init__(*args, **kwargs)
 
55
 
 
56
    def validate(self, value):
 
57
        super(IPField, self).validate(value)
 
58
        if not value and not self.required:
 
59
            return
 
60
 
 
61
        try:
 
62
            if self.mask:
 
63
                self.ip = netaddr.IPNetwork(value)
 
64
            else:
 
65
                self.ip = netaddr.IPAddress(value)
 
66
        except:
 
67
            raise ValidationError(self.invalid_format_message)
 
68
 
 
69
        if not any([self.version & IPv4 > 0 and self.ip.version == 4,
 
70
                    self.version & IPv6 > 0 and self.ip.version == 6]):
 
71
            raise ValidationError(self.invalid_version_message)
 
72
 
 
73
        if self.mask:
 
74
            if self.ip.version == 4 and \
 
75
                    not self.min_mask <= self.ip.prefixlen <= self.max_v4_mask:
 
76
                raise ValidationError(self.invalid_mask_message)
 
77
 
 
78
            if self.ip.version == 6 and \
 
79
                    not self.min_mask <= self.ip.prefixlen <= self.max_v6_mask:
 
80
                raise ValidationError(self.invalid_mask_message)
 
81
 
 
82
    def clean(self, value):
 
83
        super(IPField, self).clean(value)
 
84
        return str(getattr(self, "ip", ""))