Last active
January 26, 2023 19:12
-
-
Save JamoCA/27cf5307d7b8854c62539fdeebbea51f to your computer and use it in GitHub Desktop.
ColdFusion isIPInRange() UDF to support IPv4, IPv6, CIDR & Regex
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!--- Blog Entry: https://dev.to/gamesover/coldfusion-isipinrange-udf-to-support-ipv4-ipv6-cidr-regex-212h ---> | |
<!--- 20200109 getIPVersionACF() | |
Inspired by https://www.anujgakhar.com/2008/02/21/validate-ip-address-natively-with-coldfusion/ | |
Uses built-in undocumented coldfusion.util.IPAddressUtils, so this may not work on Lucee without this function being rewritten ---> | |
<!--- 20230126 getIPVersion() | |
Inspired by https://docs.lucee.org/reference/functions/isipinrange.html | |
Requires JAR https://github.com/jgonian/commons-ip-math (Add to existing java path (recommended) or modify to use javaloader) ---> | |
<!--- 20200109 isIPInRange() | |
Inspired by https://www.bennadel.com/blog/3503-using-commons-ip-math-to-check-if-an-ip-address-exists-in-an-ipv4-or-ipv6-cidr-range-in-coldfusion.htm | |
Inspired by https://cflib.org/udf/isIPInRange | |
Inspired by https://docs.lucee.org/reference/functions/isipinrange.html | |
Requires JAR https://github.com/jgonian/commons-ip-math (Add to existing java path (recommended) or modify to use javaloader) ---> | |
<cfscript> | |
numeric function getIPVersionACF(required string ip) hint="identifies whether string represents an IPv4 or IPv6 address; returns 0 if invalid (Adobe ColdFusion Only)" { | |
local.response = 0; | |
if (!structkeyexists(request, "getIPVersion_IPAddressUtils")){ | |
request.getIPVersion_IPAddressUtils = createobject("java","coldfusion.util.IPAddressUtils"); | |
} | |
if (request.getIPVersion_IPAddressUtils.validateIPv4Address( javacast("string", trim(arguments.ip)) )){ | |
local.response = 4; | |
} else if (request.getIPVersion_IPAddressUtils.validateIPv6Address( javacast("string", trim(arguments.ip)) )){ | |
local.response = 6; | |
} | |
return javacast("int", local.response); | |
} | |
numeric function getIPVersion(required string ip) hint="identifies whether string represents an IPv4 or IPv6 address; returns 0 if invalid" { | |
local.response = 0; | |
arguments.ip = javacast("string", arguments.ip); | |
if (find(".", arguments.ip) && listlen(arguments.ip,".") eq 4){ | |
if (!structkeyexists(request, "isIPInRange_Ipv4")){ | |
request.isIPInRange_Ipv4 = createobject("java","com.github.jgonian.ipmath.Ipv4"); | |
} | |
try { | |
local.test = request.isIPInRange_Ipv4.parse(arguments.ip); | |
local.response = 4; | |
} catch (any e) {} | |
} else if (find(":", arguments.ip)){ | |
if (!structkeyexists(request, "isIPInRange_Ipv6")){ | |
request.isIPInRange_Ipv6 = createobject("java","com.github.jgonian.ipmath.Ipv6"); | |
} | |
try { | |
local.test = request.isIPInRange_Ipv6.parse(arguments.ip); | |
local.response = 6; | |
} catch (any e) {} | |
} | |
return javacast("int", local.response); | |
} | |
boolean function isIPInRange(any ips, required ip) hint="Checks if an ip is within the range of a list or array of ips; supports regex & CIDR notation for ranges" { | |
local.ipVersion = getIPVersion(arguments.ip); | |
local.response = javacast("boolean", false); | |
if (!val(local.ipVersion)){ | |
return local.response; | |
} else if (isarray(arguments.ips)){ | |
local.ipRange = arguments.ips; | |
} else if (issimplevalue(arguments.ips)){ | |
local.ipRange = listtoarray(arguments.ips); | |
} else { | |
throw(type="Custom", message="ips must be comma-delimited list or array"); | |
} | |
if (!structkeyexists(request, "isIPInRange_Ipv4")){ | |
request.isIPInRange_Ipv4 = createobject("java","com.github.jgonian.ipmath.Ipv4"); | |
} | |
if (!structkeyexists(request, "isIPInRange_Ipv6")){ | |
request.isIPInRange_Ipv6 = createobject("java","com.github.jgonian.ipmath.Ipv6"); | |
} | |
if (local.ipVersion eq 6){ | |
local.parsedIP = request.isIPInRange_Ipv6.parse( javacast("string", trim(arguments.ip)) ); | |
} else if (local.ipVersion eq 4){ | |
local.parsedIP = request.isIPInRange_Ipv4.parse( javacast("string", trim(arguments.ip)) ); | |
} else { | |
return local.response; | |
} | |
if (!structkeyexists(request, "isIPInRange_Ipv4Range")){ | |
request.isIPInRange_Ipv4Range = createobject("java","com.github.jgonian.ipmath.Ipv4Range"); | |
request.isIPInRange_Ipv6Range = createobject("java","com.github.jgonian.ipmath.Ipv6Range"); | |
} | |
for (local.thisRange in local.ipRange) { | |
if (trim(local.thisRange).replaceall("/32$","") eq trim(arguments.ip)) { /* single IP */ | |
local.response = true; | |
break; | |
/* regex */ | |
} else if (refind("(?:\^|\[|\+|\*|\(|\$|\\\.)", local.thisRange)){ | |
try { | |
if (refindnocase(local.thisRange, arguments.ip)){ | |
local.response = true; | |
break; | |
} | |
} catch (any e){} | |
/* compare w/IPv4 dash-delimited range */ | |
} else if (local.ipVersion eq 4 && !find("/",local.thisRange) && listlen(local.thisRange,"-") eq 2 && getIPVersion(listfirst(local.thisRange,"-")) eq 4 && getIPVersion(listlast(local.thisRange,"-")) eq 4){ | |
local.start = request.isIPInRange_Ipv4.of( javacast("string", trim(listfirst(local.thisRange,"-"))) ); | |
local.end = request.isIPInRange_Ipv4.of( javacast("string", trim(listlast(local.thisRange,"-"))) ); | |
local.range = request.isIPInRange_Ipv4Range.from(local.start).to(local.end); | |
if (local.range.contains(local.parsedIP)){ | |
local.response = true; | |
break; | |
} | |
/* compare w/IPv6 dash-delimited range */ | |
} else if (local.ipVersion eq 6 && !find("/",local.thisRange) && listlen(local.thisRange,"-") eq 2 && getIPVersion(listfirst(local.thisRange,"-")) eq 6 && getIPVersion(listlast(local.thisRange,"-")) eq 6){ | |
local.start = request.isIPInRange_Ipv6.of( javacast("string", trim(listfirst(local.thisRange,"-"))) ); | |
local.end = request.isIPInRange_Ipv6.of( javacast("string", trim(listlast(local.thisRange,"-"))) ); | |
local.range = request.isIPInRange_Ipv6Range.from(local.start).to(local.end); | |
if (local.range.contains(local.parsedIP)){ | |
local.response = true; | |
break; | |
} | |
/* compare w/CIDR range */ | |
} else if (find("/", local.thisRange)){ | |
structdelete(local, "CIDR"); | |
if (local.ipVersion eq 4 && !find(":", local.thisRange)){ | |
local.CIDR = request.isIPInRange_Ipv4Range.parse(local.thisRange); | |
} else if (local.ipVersion eq 6 && find(":", local.thisRange)){ | |
local.CIDR = request.isIPInRange_Ipv6Range.parse(local.thisRange); | |
} | |
if (structkeyexists(local, "CIDR")){ | |
if (local.CIDR.contains(local.parsedIP)){ | |
local.response = true; | |
break; | |
} | |
} | |
} | |
} | |
return javacast("boolean", local.response); | |
} | |
testRanges = [ | |
"2a0a:e200:1600::/40" | |
,"209.197.31.0/25" | |
,"81.171.68.64/26" | |
,"95.138.175.4/32" | |
,"127\.0\.1\.*" | |
,"127.0.0.1-127.0.0.5" | |
]; | |
testIPs = [ | |
"209.197.31.25" | |
,"95.138.175.4" | |
,"81.171.68.124" | |
,"2a0a:e200:16ff:ffff:ffff:ffff:ffff:ffff" | |
,"127.0.1.4" | |
,"127.0.0.6" | |
,"127.0.0.15" | |
,"127.1.1.4" | |
,CGI.REMOTE_ADDR | |
,getLocalHostIP() | |
]; | |
writedump(var=testRanges, label="Test Ranges"); | |
writeoutput("<h2>isIPInRange() Results</h2>"); | |
for (thisIP in testIPs){ | |
writeoutput("<div><b>#thisIP# (v#getIPVersion(thisIP)#):</b> #yesnoformat(isIPInRange(TestRanges, thisIP))#</div>"); | |
} | |
</cfscript> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment