001package votorola.g.net; // Copyright 2011-2012, Michael Allan.  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Votorola Software"), to deal in the Votorola Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of the Votorola Software, and to permit persons to whom the Votorola Software is furnished to do so, subject to the following conditions: The preceding copyright notice and this permission notice shall be included in all copies or substantial portions of the Votorola Software. THE VOTOROLA SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE VOTOROLA SOFTWARE OR THE USE OR OTHER DEALINGS IN THE VOTOROLA SOFTWARE.
002
003import java.util.regex.*;
004import votorola.g.lang.*;
005
006
007/** Networking utilities.
008  */
009public @ThreadSafe final class Net
010{
011
012    private Net() {}
013
014    // changing?  change also in g/web/gwt/super/
015
016
017
018    /** Converts a country code from ISO 3166-1 alpha-2 to top-level domain (ccTLD).
019      *
020      *     @param cc the ISO 3166-1 alpha-2 country code in upper case.
021      *     @return the country code top-level domain (ccTLD) in lower case.
022      *
023      *     @see <a href='http://en.wikipedia.org/wiki/CcTLD'>ccTLD</a>
024      *     @see <a href='http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2'>ISO 3166-1 alpha-2</a>
025      */
026    public static final String ccTLD( final String cc )
027    {
028        if( cc.equals( "GB" )) return "uk";
029
030        return cc.toLowerCase();
031    }
032
033
034
035    /** Matches the specified string against the pattern of a dotted decimal IPV4 address
036      * such as "127.0.0.1".  Sets goups 1 through 4 to the numeric components.
037      *
038      *     @return the match, or null if there is none.
039      */
040    public static MatchResult matchIPAddress( final String s )
041    {
042        // exposing a MatchResult rather than Pattern for sake of GWT
043        final Matcher m = IP_ADDRESS_PATTERN.matcher( s );
044        return m.matches()? m: null;
045    }
046
047
048        private static final Pattern IP_ADDRESS_PATTERN = Pattern.compile(
049          "^([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})$" );
050
051
052
053    /** Returns the widest possible cookie domain (e.g. ".mydomain.dom") for the host, or
054      * null if no domain can be determined from the host specification.
055      *
056      *     @param host the host specification.  This is normally the fully qualified
057      *       domain name of the page host, as for example "hostname.mydomain.dom" or
058      *       "mydomain.dom".  It can also be an Internet address ("206.248.142.181") or
059      *       "localhost".  The value can also be null, in which case the result is null.
060      */
061    public static String widestCookieDomain( final String host )
062    {
063        String domain = null; // till proven otherwise
064        domain: if( host != null )
065        {
066            final int hN = host.length();
067            if( hN == 0 ) break domain;
068
069            if( matchIPAddress(host) != null )
070            {
071                domain = host;
072                break domain;
073            }
074
075            int c = host.lastIndexOf( '.' ); // host.domain[.]tld | domain[.]tld
076            if( c < 0 ) // host | localhost
077            {
078                domain = ".local"; // per http://www.ietf.org/rfc/rfc2965.txt
079                break domain; // not expected
080            }
081
082            c = host.lastIndexOf( '.', c - 1 ); // host[.]domain.tld | []domain.tld
083            if( c >= 0 ) // host[.]domain.tld
084            {
085                domain = host.substring( c ); // .domain.tld, meaning all hosts of domain
086                break domain;
087            }
088            // else []domain.tld
089
090            domain = "." + host; // again .domain.tld
091        }
092        return domain;
093    }
094
095
096}