package railo.commons.net; import java.io.IOException; import java.io.Serializable; import java.net.Inet6Address; import java.net.InetAddress; import java.net.UnknownHostException; import railo.commons.lang.StringUtil; import railo.runtime.type.util.ListUtil; public class IPRange implements Serializable { /** * */ private static final long serialVersionUID = 4427999443422764L; private static final short N256 = 256; private static final int SIZE = 4; private Range[] ranges=new Range[SIZE]; int max=0; private static class Range { private final short[] from; private final short[] to; private final boolean equality; private Range(short[] from, short[] to) throws IOException{ if(from.length!=to.length) throw new IOException("both ip address must be from same type, IPv4 or IPv6"); this.from=from; this.to=to; this.equality=equal(from,to); } private Range(short[] from){ this.from=from; this.to=from; this.equality=true; } private boolean inRange(short[] sarr) { if(from.length!=sarr.length) return false; if(equality) return equal(from, sarr); for(int i=0;i<from.length;i++){ if(from[i]>sarr[i] || to[i]<sarr[i]) return false; } return true; } public String toString(){ if(equality) return toString(from); return toString(from)+"-"+toString(to); } private String toString(short[] sarr) { if(sarr.length==4) return new StringBuilder().append(sarr[0]).append(".").append(sarr[1]).append(".").append(sarr[2]).append(".").append(sarr[3]).toString(); return new StringBuilder() .append(toHex(sarr[0],sarr[1],false)).append(":") .append(toHex(sarr[2],sarr[3],true)).append(":") .append(toHex(sarr[4],sarr[5],true)).append(":") .append(toHex(sarr[6],sarr[7],true)).append(":") .append(toHex(sarr[8],sarr[9],true)).append(":") .append(toHex(sarr[10],sarr[11],true)).append(":") .append(toHex(sarr[12],sarr[13],true)).append(":") .append(toHex(sarr[14],sarr[15],false)).toString(); } private String toHex(int first, int second, boolean allowEmpty) { String str1=Integer.toString(first,16); while(str1.length()<2)str1="0"+str1; String str2=Integer.toString(second,16); while(str2.length()<2)str2="0"+str2; str1+=str2; if(allowEmpty && str1.equals("0000")) return ""; while(str1.length()>1 && str1.charAt(0)=='0')str1=str1.substring(1); return str1; } private boolean equal(short[] left, short[] right) { for(int i=0;i<left.length;i++){ if(left[i]!=right[i]) return false; } return true; } } private void add(String ip) throws IOException { ip=ip.trim(); // no wildcard defined if(ip.indexOf('*')==-1) { add(new Range(toShortArray(toInetAddress(ip)))); return; } if("*".equals(ip)) { add("*.*.*.*"); add("*:*:*:*:*:*:*:*"); return; } String from = ip.replace('*', '0'); String to; InetAddress addr1 = toInetAddress(from); if(addr1 instanceof Inet6Address) to=StringUtil.replace(ip, "*","ffff",false); else to=StringUtil.replace(ip, "*","255",false); add(new Range(toShortArray(addr1),toShortArray(toInetAddress(to)))); } private void add(String ip1,String ip2) throws IOException { add(new Range(toShortArray(toInetAddress(ip1)),toShortArray(toInetAddress(ip2)))); } public static IPRange getInstance(String raw) throws IOException { return getInstance(ListUtil.listToStringArray(raw, ',')); } public static IPRange getInstance(String[] raw) throws IOException { IPRange range=new IPRange(); String[] arr = ListUtil.trimItems(ListUtil.trim(raw)); String str; int index; for(int i=0;i<arr.length;i++){ str=arr[i]; if(str.length()>0) { index=str.indexOf('-'); if(index!=-1) range.add(str.substring(0,index), str.substring(index+1)); else range.add(str); } } return range; } private synchronized void add(Range range) { if(max>=ranges.length) { Range[] tmp=new Range[ranges.length+SIZE]; for(int i=0;i<ranges.length;i++){ tmp[i]=ranges[i]; } ranges=tmp; } ranges[max++]=range; } public boolean inRange(String ip) throws IOException { return inRange(toShortArray(ip)); } public boolean inRange(short[] ip) { for(int i=0;i<max;i++){ if(ranges[i].inRange(ip)) return true; } return false; } public String toString(){ StringBuilder sb=new StringBuilder(); for(int i=0;i<max;i++){ if(i>0)sb.append(","); sb.append(ranges[i].toString()); } return sb.toString(); } public static short[] toShortArray(String ip) throws IOException { return toShortArray(toInetAddress(ip)); } private static InetAddress toInetAddress(String ip) throws IOException { // TODO Auto-generated method stub try { return InetAddress.getByName(ip); } catch (UnknownHostException e) { throw new IOException("cannot parse the ip ["+ip+"]"); } } private static short[] toShortArray(InetAddress ia){ byte[] addr = ia.getAddress(); short[] sarr=new short[addr.length]; for(int i=0;i<addr.length;i++){ sarr[i]=byte2short(addr[i]); } return sarr; } private static short byte2short(byte b){ if(b<0) return (short)(b+N256); return b; } }