001    /*
002     * Copyright 2010 the original author or authors.
003     * 
004     *  Licensed under the Apache License, Version 2.0 (the "License");
005     *  you may not use this file except in compliance with the License.
006     *  You may obtain a copy of the License at
007     *
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     *
010     *  Unless required by applicable law or agreed to in writing, software
011     *  distributed under the License is distributed on an "AS IS" BASIS,
012     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     *  See the License for the specific language governing permissions and
014     *  limitations under the License.
015     */
016    package com.hs.mail.util;
017    
018    import java.net.InetAddress;
019    import java.util.ArrayList;
020    import java.util.List;
021    import java.util.StringTokenizer;
022    
023    public class InetAddressMatcher {
024            
025            private List<Integer> addresses = new ArrayList<Integer>();
026            private List<Integer> netmasks = new ArrayList<Integer>();
027            
028            public InetAddressMatcher(String networks) {
029                    StringTokenizer st = new StringTokenizer(networks, ", ");
030                    while (st.hasMoreElements()) {
031                            String s = st.nextToken().trim();
032                            int i = s.indexOf('/');
033                            if (i != -1) {
034                                    addresses.add(toByte(s.substring(0, i)));
035                                    String mask = s.substring(i + 1);
036                                    if (mask.indexOf('.') == -1) {
037                                            int nm = Integer.parseInt(mask);
038                                            netmasks.add((nm == 0) ? 0 : 0xffffffff << (32 - nm));
039                                    } else {
040                                            netmasks.add(toByte(mask));
041                                    }
042                            } else {
043                                    addresses.add(toByte(s));
044                                    netmasks.add(0xffffffff);
045                            }
046                    }
047            }
048            
049            public static int toByte(String address) {
050                    StringTokenizer st = new StringTokenizer(address, ".");
051                    int bytes = Integer.parseInt(st.nextToken()) << 24
052                                    | Integer.parseInt(st.nextToken()) << 16
053                                    | Integer.parseInt(st.nextToken()) << 8
054                                    | Integer.parseInt(st.nextToken());
055                    return bytes;
056            }
057            
058            public boolean matches(InetAddress address) {
059                    int ipaddr = toByte(address.getHostAddress());
060                    for (int i = 0; i < addresses.size(); i++) {
061                            int nm = netmasks.get(i);
062                            if ((ipaddr & nm) == (addresses.get(i) & nm)) {
063                                    return true;
064                            }
065                    }
066                    return false;
067            }
068    
069            public static boolean matches(String networks, InetAddress address) {
070                    return new InetAddressMatcher(networks).matches(address);
071            }
072            
073            private String toString(int addr) {
074                    StringBuffer sb = new StringBuffer();
075                    for (int i = 0; i < 4; i++) {
076                            int x = addr >>> 24;
077                            addr = addr << 8;
078                            if (i != 0)
079                                    sb.append('.');
080                            sb.append(x);
081                    }
082                    return sb.toString();
083            }
084            
085            private String toString(int address, int netmask) {
086                    if (netmask == -1)
087                            return toString(address);
088                    else
089                            return toString(address) + '/' + toString(netmask);
090            }
091            
092            public String toString() {
093                    StringBuilder sb = new StringBuilder();
094                    for (int i = 0; i < addresses.size(); i++) {
095                            if (i != 0)
096                                    sb.append(' ');
097                            sb.append(toString(addresses.get(i), netmasks.get(i)));
098                    }
099                    return sb.toString();
100            }
101    
102    }