bug fix / isipv6 complete rewrite

This commit is contained in:
fatalerrors
2026-07-09 14:58:01 +02:00
parent e328199618
commit db7dcb6f03

View File

@@ -206,20 +206,21 @@ isipv4()
for oct in "${ip_arr[@]}"; do
# Reject leading plus/minus or empty entries
if [[ -z $oct || $oct =~ [^0-9] ]]; then
[[ -t 1 ]] && disp "The given parameter is NOT a valid IPv4."
[[ -t 1 ]] && disp E "The given parameter is NOT a valid IPv4."
return 1
fi
if (( oct > 255 )); then
[[ -t 1 ]] && disp "The given parameter is NOT a valid IPv4."
# 10# forces base-10 so leading-zero octets (08, 09) are not read as octal
if (( 10#$oct > 255 )); then
[[ -t 1 ]] && disp E "The given parameter is NOT a valid IPv4."
return 1
fi
done
[[ -t 1 ]] && disp "The given IPv4 is valid."
[[ -t 1 ]] && disp I "The given IPv4 is valid."
return 0
fi
[[ -t 1 ]] && disp "The given parameter is NOT a valid IPv4."
[[ -t 1 ]] && disp E "The given parameter is NOT a valid IPv4."
return 1
}
export -f isipv4
@@ -229,19 +230,94 @@ export -f isipv4
# ------------------------------------------------------------------------------
# Determine if parameter is a valid IPv6 address
# Usage: isipv6 <ip_address>
# Accepts full and "::"-compressed forms, an embedded IPv4 suffix
# (e.g. ::ffff:192.0.2.1) and an optional RFC 4007 zone id (e.g. fe80::1%eth0).
isipv6()
{
local ip="$1"
local regex='^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}$'
if [[ $ip =~ $regex ]]; then
if [[ -t 1 ]]; then
disp "The given IPv6 is valid."
local valid=0
# A single-pass validation; any failing check breaks out with valid=0.
while true; do
[[ -z $ip ]] && break
# Strip an optional zone identifier (fe80::1%eth0); reject empty/multiple.
if [[ $ip == *%* ]]; then
[[ $ip == *%*%* ]] && break
[[ -z ${ip#*%} ]] && break
ip="${ip%%[%]*}"
fi
# Reject ':::' and more than one '::' compression.
[[ $ip == *:::* ]] && break
local compressed=0
if [[ $ip == *::* ]]; then
[[ ${ip#*::} == *::* ]] && break
compressed=1
fi
# A lone leading/trailing ':' that is not part of a '::' is invalid.
[[ $ip == :* && $ip != ::* ]] && break
[[ $ip == *: && $ip != *:: ]] && break
# An embedded IPv4 is allowed only as the trailing 32 bits. Validate it,
# then replace it with two zero hextets so the rest is a clean hextet list.
if [[ $ip == *.* ]]; then
local v4="${ip##*:}"
[[ $v4 == *.*.*.* ]] || break
local -a oct=()
IFS='.' read -ra oct <<< "$v4"
[[ ${#oct[@]} -eq 4 ]] || break
local o v4ok=1
for o in "${oct[@]}"; do
if [[ ! $o =~ ^[0-9]{1,3}$ ]] || (( 10#$o > 255 )); then
v4ok=0
break
fi
done
(( v4ok )) || break
ip="${ip%"$v4"}0:0"
fi
# Count the hextets on each side of an optional '::'.
local left right seg part total=0 ok=1
if (( compressed )); then
left="${ip%%::*}"
right="${ip#*::}"
else
left="$ip"
right=""
fi
for seg in "$left" "$right"; do
[[ -z $seg ]] && continue
local -a parts=()
IFS=':' read -ra parts <<< "$seg"
for part in "${parts[@]}"; do
[[ $part =~ ^[0-9a-fA-F]{1,4}$ ]] || { ok=0; break; }
(( total++ ))
done
(( ok )) || break
done
(( ok )) || break
# Without '::' there must be exactly 8 hextets; with it, fewer than 8
# (the '::' expands to at least one zero hextet).
if (( compressed )); then
(( total <= 7 )) || break
else
(( total == 8 )) || break
fi
valid=1
break
done
if (( valid )); then
[[ -t 1 ]] && disp I "The given IPv6 is valid."
return 0
fi
if [[ -t 1 ]]; then
disp "The given parameter is not a valid IPv6."
fi
[[ -t 1 ]] && disp E "The given parameter is not a valid IPv6."
return 1
}
export -f isipv6
@@ -256,12 +332,13 @@ urlencode()
local LANG=C
local str="$*"
local length="${#str}"
local i
for (( i = 0; i < length; i++ )); do
local c="${str:i:1}"
case "$c" in
[a-zA-Z0-9.~_-]) printf '%s' "$c" ;;
' ') printf '+' ;;
*) printf '%%%02X' "'$c" #| cut -d' ' -f2 ;;
*) printf '%%%02X' "'$c" ;;
esac
done
}