component/src/piracyshield_component/validation/rules/ipv6.py
2024-02-07 14:55:23 +01:00

89 lines
2.5 KiB
Python

from piracyshield_component.validation.rule import Rule
class IPv6(Rule):
"""
Rule that checks for a valid IPv6.
"""
hextets_syntax_message = 'IPv6 not valid, more than one `::` found'
hextets_message = 'IPv6 not valid, expecting eight hextets, got {}'
hextets_digits_message = 'IPv6 not valid, expecting eight hextets of hexadecimal digits'
hextets_maximum_length = 'IPv6 not valid, too many hextets'
hextets_length_message = 'IPv6 not valid, one or more hextet(s) too long'
hextets_digits_size_message = 'IPv6 not valid, expecting hexadecimal digits from 0 to FFFF'
def __init__(self):
"""
Initialize parent __init__.
"""
super().__init__()
def __call__(self, value: str) -> None:
"""
Checks the validity of the passed string.
Instead of relying on regular expression, it's better to check the individual hextets.
This also allows for better error reporting.
:param value: a valid string.
"""
# short syntax
if '::' in value:
parts = value.split('::')
if len(parts) > 2:
self.register_error(self.hextets_syntax_message)
return False
left_side = parts[0].split(':') if parts[0] else []
right_side = parts[1].split(':') if parts[1] else []
zeros_needed = 8 - len(left_side) - len(right_side)
if zeros_needed < 0:
self.register_error(self.hextets_maximum_length)
return False
hextets = left_side + ['0'] * zeros_needed + right_side
# common syntax
else:
hextets = value.split(':')
if len(hextets) != 8:
self.register_error(self.hextets_message.format(self.hextets_digits_message))
return False
for hextet in hextets:
if not all(c in '0123456789ABCDEFabcdef' for c in hextet):
self.register_error(self.hextets_digits_message)
return False
if len(hextet) > 4:
self.register_error(self.hextets_length_message)
return False
try:
int_value = int(hextet, 16)
if not (0 <= int_value <= 0xFFFF):
self.register_error(self.hextets_digits_size_message)
return False
except ValueError:
self.register_error(self.hextets_digits_size_message)
return False