001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.commons.net;
020
021import java.net.InetAddress;
022import java.net.NetworkInterface;
023import java.net.SocketException;
024import java.util.ArrayList;
025import java.util.Enumeration;
026import java.util.List;
027
028import lucee.commons.lang.ExceptionUtil;
029import lucee.commons.lang.StringUtil;
030import lucee.runtime.op.Caster;
031import lucee.runtime.type.util.ListUtil;
032
033public class IPUtil {
034
035        private static boolean isCacheEnabled = false;
036        private static boolean isCacheValid = false;
037        private static List<String> cachedLocalIPs = null;
038
039        static {
040
041                long tc = System.currentTimeMillis();
042
043                List<String> localIPs = getLocalIPs( true );
044
045                isCacheEnabled = System.currentTimeMillis() > tc;
046
047                if ( isCacheEnabled ) {
048
049                        cachedLocalIPs = localIPs;
050                        isCacheValid = true;
051                }
052        }
053
054
055        public static boolean isIPv4(String ip) {
056                String[] arr = ListUtil.trimItems(ListUtil.trim(ListUtil.listToStringArray(ip, '.')));
057                if(arr.length!=4) return false;
058
059                int tmp;
060                for(int i=0;i<arr.length;i++){
061                        tmp=Caster.toIntValue(arr[i],-1);
062                        if(tmp<0 || tmp>255) return false;
063                }
064                return true;
065        }
066
067        public static boolean isIPv62(String ip)        {
068                if(ip.indexOf(':') == -1) return false;
069                String[] arr = ListUtil.trimItems(ListUtil.trim(ListUtil.listToStringArray(ip, ':')));
070                if(arr.length!=8) return false;
071                String str;
072                int _int;
073                for(int i=0;i<arr.length;i++){
074                        str=arr[i];
075                        if(!StringUtil.isEmpty(str)) {
076                                try{
077                                        _int=Integer.parseInt(str,16);
078                                }
079                                catch(Throwable t){
080                        ExceptionUtil.rethrowIfNecessary(t);
081                                        _int=-1;
082                                }
083                                if(_int<0 || _int> 65535)
084                                        return false;
085                        }
086                }
087                return true;
088        }
089
090        public static boolean isIPv4(InetAddress addr)  {
091                return addr.getAddress().length==4;
092        }
093        public static boolean isIPv6(InetAddress addr)  {
094                return !isIPv4(addr);
095        }
096
097
098        public static List<String> getLocalIPs( boolean refresh ) {
099
100                if ( isCacheEnabled && isCacheValid && !refresh ) {
101
102                        return new ArrayList<String>( cachedLocalIPs );
103                }
104
105                List<String> result = new ArrayList();
106
107                try {
108
109                        Enumeration<NetworkInterface> eNics = NetworkInterface.getNetworkInterfaces();
110
111                        while ( eNics.hasMoreElements() ) {
112
113                                NetworkInterface nic = eNics.nextElement();
114
115                                if ( nic.isUp() ) {
116
117                                        Enumeration<InetAddress> eAddr = nic.getInetAddresses();
118
119                                        while ( eAddr.hasMoreElements() ) {
120
121                                                InetAddress inaddr = eAddr.nextElement();
122
123                                                String addr = inaddr.toString();
124
125                                                if ( addr.startsWith( "/" ) )
126                                                        addr = addr.substring( 1 );
127
128                                                if ( addr.indexOf( '%' ) > -1 )
129                                                        addr = addr.substring( 0, addr.indexOf( '%' ) );    // internal zone in some IPv6; http://en.wikipedia.org/wiki/IPv6_Addresses#Link-local%5Faddresses%5Fand%5Fzone%5Findices
130
131                                                result.add( addr );
132                                        }
133                                }
134                        }
135                }
136                catch ( SocketException e ) {
137
138                        result.add( "127.0.0.1" );
139                        result.add( "0:0:0:0:0:0:0:1" );
140                }
141
142                if ( isCacheEnabled ) {
143
144                        cachedLocalIPs = result;
145                        isCacheValid = true;
146                }
147
148                return result;
149        }
150
151
152        /** this method can be called from Controller periodically, or from Admin if user clicks to invalidate the cache */
153        public void invalidateCache() {
154
155                isCacheValid = false;
156        }
157
158
159        /** returns true if cache is used */
160        public boolean isCacheEnabled() {
161
162                return isCacheEnabled;
163        }
164
165}