Make the IP address exceptions more detailed

This commit is contained in:
Matthias Einwag 2014-03-14 22:17:44 +01:00
commit 95e4ab99e7

View file

@ -139,20 +139,21 @@ proc parseIPv4Address(address_str: string): TIpAddress =
for i in 0 .. high(address_str): for i in 0 .. high(address_str):
if address_str[i] in strutils.Digits: # Character is a number if address_str[i] in strutils.Digits: # Character is a number
currentByte = currentByte * 10 + cast[uint16](ord(address_str[i]) - ord('0')) currentByte = currentByte * 10 + cast[uint16](ord(address_str[i]) - ord('0'))
if currentByte > 255'u16: raise newException(EInvalidValue, "Invalid IP Address") if currentByte > 255'u16:
raise newException(EInvalidValue, "Invalid IP Address. Value is out of range")
seperatorValid = true seperatorValid = true
elif address_str[i] == '.': # IPv4 address separator elif address_str[i] == '.': # IPv4 address separator
if not seperatorValid or byteCount >= 3: if not seperatorValid or byteCount >= 3:
raise new EInvalidValue raise newException(EInvalidValue, "Invalid IP Address. The address consists of too many groups")
result.address_v4[byteCount] = cast[uint8](currentByte) result.address_v4[byteCount] = cast[uint8](currentByte)
currentByte = 0 currentByte = 0
byteCount.inc byteCount.inc
seperatorValid = false seperatorValid = false
else: else:
raise newException(EInvalidValue, "Invalid IP Address") # Invalid character raise newException(EInvalidValue, "Invalid IP Address. Address contains an invalid character")
if byteCount != 3 or not seperatorValid: if byteCount != 3 or not seperatorValid:
raise new EInvalidValue raise newException(EInvalidValue, "Invalid IP Address")
result.address_v4[byteCount] = cast[uint8](currentByte) result.address_v4[byteCount] = cast[uint8](currentByte)
proc parseIPv6Address(address_str: string): TIpAddress = proc parseIPv6Address(address_str: string): TIpAddress =
@ -173,22 +174,24 @@ proc parseIPv6Address(address_str: string): TIpAddress =
for i,c in address_str: for i,c in address_str:
if c == ':': if c == ':':
if not seperatorValid: raise newException(EInvalidValue, "Invalid IP Address") if not seperatorValid: raise newException(EInvalidValue, "Invalid IP Address. Address contains an invalid seperator")
if lastWasColon: if lastWasColon:
if dualColonGroup != -1: raise newException(EInvalidValue, "Invalid IP Address") if dualColonGroup != -1: raise newException(EInvalidValue, "Invalid IP Address. Address contains more than one \"::\" seperator")
dualColonGroup = groupCount dualColonGroup = groupCount
seperatorValid = false seperatorValid = false
elif i != 0 and i != high(address_str): elif i != 0 and i != high(address_str):
if groupCount >= 8: raise newException(EInvalidValue, "Invalid IP Address") if groupCount >= 8: raise newException(EInvalidValue, "Invalid IP Address. The address consists of too many groups")
result.address_v6[groupCount*2] = cast[uint8](currentShort shr 8) result.address_v6[groupCount*2] = cast[uint8](currentShort shr 8)
result.address_v6[groupCount*2+1] = cast[uint8](currentShort and 0xFF) result.address_v6[groupCount*2+1] = cast[uint8](currentShort and 0xFF)
currentShort = 0 currentShort = 0
groupCount.inc() groupCount.inc()
if dualColonGroup != -1: seperatorValid = false if dualColonGroup != -1: seperatorValid = false
elif i == 0: # only valid if address starts with :: elif i == 0: # only valid if address starts with ::
if address_str[1] != ':': raise newException(EInvalidValue, "Invalid IP Address") if address_str[1] != ':':
raise newException(EInvalidValue, "Invalid IP Address. Address may not start with \":\"")
else: # i == high(address_str) - only valid if address ends with :: else: # i == high(address_str) - only valid if address ends with ::
if address_str[high(address_str)-1] != ':': raise newException(EInvalidValue, "Invalid IP Address") if address_str[high(address_str)-1] != ':':
raise newException(EInvalidValue, "Invalid IP Address. Address may not end with \":\"")
lastWasColon = true lastWasColon = true
currentGroupStart = i + 1 currentGroupStart = i + 1
elif c == '.': # Switch to parse IPv4 mode elif c == '.': # Switch to parse IPv4 mode
@ -204,16 +207,17 @@ proc parseIPv6Address(address_str: string): TIpAddress =
currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('a')) + 10 currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('a')) + 10
else: # Upper case hex else: # Upper case hex
currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('A')) + 10 currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('A')) + 10
if currentShort > 65535'u32: raise newException(EInvalidValue, "Invalid IP Address") if currentShort > 65535'u32:
raise newException(EInvalidValue, "Invalid IP Address. Value is out of range")
lastWasColon = false lastWasColon = false
seperatorValid = true seperatorValid = true
else: else:
raise newException(EInvalidValue, "Invalid IP Address") raise newException(EInvalidValue, "Invalid IP Address. Address contains an invalid character")
if v4StartPos == -1: # Don't parse v4. Copy the remaining v6 stuff if v4StartPos == -1: # Don't parse v4. Copy the remaining v6 stuff
if seperatorValid: # Copy remaining data if seperatorValid: # Copy remaining data
if groupCount >= 8: raise newException(EInvalidValue, "Invalid IP Address") if groupCount >= 8: raise newException(EInvalidValue, "Invalid IP Address. The address consists of too many groups")
result.address_v6[groupCount*2] = cast[uint8](currentShort shr 8) result.address_v6[groupCount*2] = cast[uint8](currentShort shr 8)
result.address_v6[groupCount*2+1] = cast[uint8](currentShort and 0xFF) result.address_v6[groupCount*2+1] = cast[uint8](currentShort and 0xFF)
groupCount.inc() groupCount.inc()
@ -221,35 +225,36 @@ proc parseIPv6Address(address_str: string): TIpAddress =
for i,c in address_str[v4StartPos..high(address_str)]: for i,c in address_str[v4StartPos..high(address_str)]:
if c in strutils.Digits: # Character is a number if c in strutils.Digits: # Character is a number
currentShort = currentShort * 10 + cast[uint32](ord(c) - ord('0')) currentShort = currentShort * 10 + cast[uint32](ord(c) - ord('0'))
if currentShort > 255'u32: raise newException(EInvalidValue, "Invalid IP Address") if currentShort > 255'u32:
raise newException(EInvalidValue, "Invalid IP Address. Value is out of range")
seperatorValid = true seperatorValid = true
elif c == '.': # IPv4 address separator elif c == '.': # IPv4 address separator
if not seperatorValid or byteCount >= 3: if not seperatorValid or byteCount >= 3:
raise new EInvalidValue raise newException(EInvalidValue, "Invalid IP Address")
result.address_v6[groupCount*2 + byteCount] = cast[uint8](currentShort) result.address_v6[groupCount*2 + byteCount] = cast[uint8](currentShort)
currentShort = 0 currentShort = 0
byteCount.inc() byteCount.inc()
seperatorValid = false seperatorValid = false
else: # Invalid character else: # Invalid character
raise newException(EInvalidValue, "Invalid IP Address") raise newException(EInvalidValue, "Invalid IP Address. Address contains an invalid character")
if byteCount != 3 or not seperatorValid: if byteCount != 3 or not seperatorValid:
raise new EInvalidValue raise newException(EInvalidValue, "Invalid IP Address")
result.address_v6[groupCount*2 + byteCount] = cast[uint8](currentShort) result.address_v6[groupCount*2 + byteCount] = cast[uint8](currentShort)
groupCount += 2 groupCount += 2
# Shift and fill zeros in case of :: # Shift and fill zeros in case of ::
if groupCount > 8: if groupCount > 8:
raise newException(EInvalidValue, "Invalid IP Address") raise newException(EInvalidValue, "Invalid IP Address. The address consists of too many groups")
elif groupCount < 8: # must fill elif groupCount < 8: # must fill
if dualColonGroup == -1: raise newException(EInvalidValue, "Invalid IP Address") if dualColonGroup == -1: raise newException(EInvalidValue, "Invalid IP Address. The address consists of too few groups")
var toFill = 8 - groupCount # The number of groups to fill var toFill = 8 - groupCount # The number of groups to fill
var toShift = groupCount - dualColonGroup # Nr of known groups after :: var toShift = groupCount - dualColonGroup # Nr of known groups after ::
for i in 0..2*toShift-1: # shift for i in 0..2*toShift-1: # shift
result.address_v6[15-i] = result.address_v6[groupCount*2-i-1] result.address_v6[15-i] = result.address_v6[groupCount*2-i-1]
for i in 0..2*toFill-1: # fill with 0s for i in 0..2*toFill-1: # fill with 0s
result.address_v6[dualColonGroup*2+i] = 0 result.address_v6[dualColonGroup*2+i] = 0
elif dualColonGroup != -1: raise newException(EInvalidValue, "Invalid IP Address") elif dualColonGroup != -1: raise newException(EInvalidValue, "Invalid IP Address. The address consists of too many groups")
proc parseIpAddress*(address_str: string): TIpAddress = proc parseIpAddress*(address_str: string): TIpAddress =