001 package railo.commons.net; 002 003 import java.io.IOException; 004 import java.io.Serializable; 005 import java.net.Inet6Address; 006 import java.net.InetAddress; 007 import java.net.UnknownHostException; 008 009 import railo.commons.lang.StringUtil; 010 import railo.runtime.type.util.ListUtil; 011 012 public class IPRange implements Serializable { 013 014 /** 015 * 016 */ 017 private static final long serialVersionUID = 4427999443422764L; 018 private static final short N256 = 256; 019 private static final int SIZE = 4; 020 021 private Range[] ranges=new Range[SIZE]; 022 int max=0; 023 024 025 private static class Range { 026 private final short[] from; 027 private final short[] to; 028 private final boolean equality; 029 030 private Range(short[] from, short[] to) throws IOException{ 031 if(from.length!=to.length) 032 throw new IOException("both ip address must be from same type, IPv4 or IPv6"); 033 034 this.from=from; 035 this.to=to; 036 this.equality=equal(from,to); 037 } 038 private Range(short[] from){ 039 this.from=from; 040 this.to=from; 041 this.equality=true; 042 } 043 private boolean inRange(short[] sarr) { 044 if(from.length!=sarr.length) return false; 045 046 if(equality) return equal(from, sarr); 047 048 for(int i=0;i<from.length;i++){ 049 if(from[i]>sarr[i] || to[i]<sarr[i]) 050 return false; 051 } 052 return true; 053 } 054 055 public String toString(){ 056 if(equality) return toString(from); 057 return toString(from)+"-"+toString(to); 058 } 059 060 private String toString(short[] sarr) { 061 if(sarr.length==4) 062 return new StringBuilder().append(sarr[0]).append(".").append(sarr[1]).append(".").append(sarr[2]).append(".").append(sarr[3]).toString(); 063 064 return new StringBuilder() 065 .append(toHex(sarr[0],sarr[1],false)).append(":") 066 .append(toHex(sarr[2],sarr[3],true)).append(":") 067 .append(toHex(sarr[4],sarr[5],true)).append(":") 068 .append(toHex(sarr[6],sarr[7],true)).append(":") 069 .append(toHex(sarr[8],sarr[9],true)).append(":") 070 .append(toHex(sarr[10],sarr[11],true)).append(":") 071 .append(toHex(sarr[12],sarr[13],true)).append(":") 072 .append(toHex(sarr[14],sarr[15],false)).toString(); 073 074 075 } 076 077 078 079 private String toHex(int first, int second, boolean allowEmpty) { 080 String str1=Integer.toString(first,16); 081 while(str1.length()<2)str1="0"+str1; 082 String str2=Integer.toString(second,16); 083 while(str2.length()<2)str2="0"+str2; 084 str1+=str2; 085 if(allowEmpty && str1.equals("0000")) return ""; 086 087 while(str1.length()>1 && str1.charAt(0)=='0')str1=str1.substring(1); 088 089 090 091 return str1; 092 } 093 private boolean equal(short[] left, short[] right) { 094 for(int i=0;i<left.length;i++){ 095 if(left[i]!=right[i]) return false; 096 } 097 return true; 098 } 099 100 101 } 102 103 104 private void add(String ip) throws IOException { 105 ip=ip.trim(); 106 // no wildcard defined 107 if(ip.indexOf('*')==-1) { 108 add(new Range(toShortArray(toInetAddress(ip)))); 109 return; 110 } 111 112 if("*".equals(ip)) { 113 add("*.*.*.*"); 114 add("*:*:*:*:*:*:*:*"); 115 return; 116 } 117 118 String from = ip.replace('*', '0'); 119 String to; 120 InetAddress addr1 = toInetAddress(from); 121 if(addr1 instanceof Inet6Address) 122 to=StringUtil.replace(ip, "*","ffff",false); 123 else 124 to=StringUtil.replace(ip, "*","255",false); 125 add(new Range(toShortArray(addr1),toShortArray(toInetAddress(to)))); 126 } 127 128 private void add(String ip1,String ip2) throws IOException { 129 add(new Range(toShortArray(toInetAddress(ip1)),toShortArray(toInetAddress(ip2)))); 130 } 131 public static IPRange getInstance(String raw) throws IOException { 132 return getInstance(ListUtil.listToStringArray(raw, ',')); 133 } 134 135 public static IPRange getInstance(String[] raw) throws IOException { 136 IPRange range=new IPRange(); 137 String[] arr = ListUtil.trimItems(ListUtil.trim(raw)); 138 String str; 139 int index; 140 for(int i=0;i<arr.length;i++){ 141 str=arr[i]; 142 if(str.length()>0) { 143 index=str.indexOf('-'); 144 if(index!=-1) range.add(str.substring(0,index), str.substring(index+1)); 145 else range.add(str); 146 } 147 } 148 return range; 149 150 } 151 152 153 private synchronized void add(Range range) { 154 if(max>=ranges.length) { 155 Range[] tmp=new Range[ranges.length+SIZE]; 156 for(int i=0;i<ranges.length;i++){ 157 tmp[i]=ranges[i]; 158 } 159 ranges=tmp; 160 } 161 ranges[max++]=range; 162 } 163 164 public boolean inRange(String ip) throws IOException { 165 return inRange(toShortArray(ip)); 166 } 167 168 public boolean inRange(short[] ip) { 169 for(int i=0;i<max;i++){ 170 if(ranges[i].inRange(ip)) return true; 171 } 172 return false; 173 } 174 175 176 public String toString(){ 177 StringBuilder sb=new StringBuilder(); 178 for(int i=0;i<max;i++){ 179 if(i>0)sb.append(","); 180 sb.append(ranges[i].toString()); 181 } 182 return sb.toString(); 183 } 184 185 public static short[] toShortArray(String ip) throws IOException { 186 return toShortArray(toInetAddress(ip)); 187 } 188 189 private static InetAddress toInetAddress(String ip) throws IOException { 190 // TODO Auto-generated method stub 191 try { 192 return InetAddress.getByName(ip); 193 } catch (UnknownHostException e) { 194 throw new IOException("cannot parse the ip ["+ip+"]"); 195 } 196 } 197 198 private static short[] toShortArray(InetAddress ia){ 199 byte[] addr = ia.getAddress(); 200 short[] sarr=new short[addr.length]; 201 for(int i=0;i<addr.length;i++){ 202 sarr[i]=byte2short(addr[i]); 203 } 204 return sarr; 205 } 206 207 private static short byte2short(byte b){ 208 if(b<0) return (short)(b+N256); 209 return b; 210 } 211 }