| | 43 | |
| | 44 | 2006-02-24-23:14-ish |
| | 45 | |
| | 46 | While watching Firefly I've come up with this: |
| | 47 | |
| | 48 | {{{ |
| | 49 | class FormPortField(formfields.TextField): |
| | 50 | |
| | 51 | requires_data_list = True |
| | 52 | |
| | 53 | def __init__(self, **kw): |
| | 54 | formfields.TextField.__init__(self, **kw) |
| | 55 | self.validator_list.append(self.isValidList) |
| | 56 | |
| | 57 | def isValidList(self, field_data, all_data): |
| | 58 | for datum in field_data: |
| | 59 | for port in datum.split(','): |
| | 60 | if port.lower().strip() != 'icmp': |
| | 61 | try: |
| | 62 | no, proto = port.split(':') |
| | 63 | except ValueError: |
| | 64 | raise validators.ValidationError, _("Ports should be specified in the form 'number:protocol'. E.g. '80:tcp'") |
| | 65 | try: |
| | 66 | if int(no) < 1 or int(no) > 65355: |
| | 67 | raise validators.ValidationError, _("Port number must be between 1 and 65355") |
| | 68 | except ValueError: |
| | 69 | raise validators.ValidationError, _("Port number must be between 1 and 65355") |
| | 70 | if proto.lower().strip() not in ['tcp', 'udp']: |
| | 71 | raise validators.ValidationError, _("Protocol must be either 'TCP' or 'UDP'") |
| | 72 | |
| | 73 | def render(self, data): |
| | 74 | if data is None: |
| | 75 | data = '' |
| | 76 | if isinstance(data, unicode): |
| | 77 | data = data.encode(DEFAULT_CHARSET) |
| | 78 | tmp = [] |
| | 79 | for datum in data: |
| | 80 | try: |
| | 81 | port = ports.get_object(id__exact=int(datum)) |
| | 82 | if port.number: |
| | 83 | tmp.append("%s:%s" % (port.number, port.protocol)) |
| | 84 | else: |
| | 85 | tmp.append("%s" % (port.protocol, )) |
| | 86 | except ValueError: |
| | 87 | # By catching this error we now assume that it's invalid data entered by the user and |
| | 88 | # so should simply be returned in the 'raw' |
| | 89 | return '<input type="text" id="%s" class="v%s%s" name="%s" size="%s" value="%s" />' % \ |
| | 90 | (self.get_id(), self.__class__.__name__, self.is_required and ' required' or '', |
| | 91 | data = ', '.join(tmp) |
| | 92 | return '<input type="text" id="%s" class="v%s%s" name="%s" size="%s" value="%s" />' % \ |
| | 93 | (self.get_id(), self.__class__.__name__, self.is_required and ' required' or '', |
| | 94 | self.field_name, 40, escape(data)) |
| | 95 | |
| | 96 | def convert_post_data(self, new_data): |
| | 97 | name = self.get_member_name() |
| | 98 | if new_data.has_key(self.field_name): |
| | 99 | d = new_data.getlist(self.field_name) |
| | 100 | try: |
| | 101 | self.isValidList(d, new_data) |
| | 102 | except validators.ValidationError: |
| | 103 | return |
| | 104 | portlist=[] |
| | 105 | for datum in d: |
| | 106 | for n in datum.split(','): |
| | 107 | n = n.strip() |
| | 108 | if n: |
| | 109 | if n.lower() == 'icmp': |
| | 110 | portlist.append(ports.get_object(protocol__exact="icmp").id) |
| | 111 | else: |
| | 112 | port, proto = n.split(':') |
| | 113 | port_ref = ports.get_object(number__exact=int(port), protocol__exact=proto.lower()) |
| | 114 | portlist.append(port_ref.id) |
| | 115 | new_data.setlist( name, portlist) |
| | 116 | }}} |
| | 117 | |
| | 118 | Wow. What a mess. We end up validating the data three times over. What a pain. But it works. |