Skip to content

Instantly share code, notes, and snippets.

@JamoCA
Last active January 26, 2023 19:12
Show Gist options
  • Save JamoCA/27cf5307d7b8854c62539fdeebbea51f to your computer and use it in GitHub Desktop.
Save JamoCA/27cf5307d7b8854c62539fdeebbea51f to your computer and use it in GitHub Desktop.
ColdFusion isIPInRange() UDF to support IPv4, IPv6, CIDR & Regex
<!--- 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