content: /*
  * Conditions Of Use
  *
  * This software was developed by employees of the National Institute of
  * Standards and Technology (NIST), an agency of the Federal Government.
  * Pursuant to title 15 Untied States Code Section 105, works of NIST
  * employees are not subject to copyright protection in the United States
  * and are considered to be in the public domain.  As a result, a formal
  * license is not needed to use the software.
  *
  * This software is provided by NIST as a service and is expressly
  * provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
  * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
  * AND DATA ACCURACY.  NIST does not warrant or make any representations
  * regarding the use of the software or the results thereof, including but
  * not limited to the correctness, accuracy, reliability or usefulness of
  * the software.
  *
  * Permission to use this software is contingent upon your acceptance
  * of the terms of this agreement
  *
  * .
  *
  */
  /***************************************************************************
   * Product of NIST/ITL Advanced Networking Technologies Division(ANTD).   *
   **************************************************************************/
  package gov2.nist.core;
  
  import java.net.*;
  
  /*
   * IPv6 Support added by Emil Ivov (emil_ivov@yahoo.com)<br/>
   * Network Research Team (http://www-r2.u-strasbg.fr))<br/>
   * Louis Pasteur University - Strasbourg - France<br/>
   *
   * Frank Feif reported a bug.
   *
   *
   */
  /**
   * Stores hostname.
   * @version 1.2
   *
   * @author M. Ranganathan
   * @author Emil Ivov <emil_ivov@yahoo.com> IPV6 Support. <br/>
   *
   *
   *
  
   * Marc Bednarek <bednarek@nist.gov> (Bugfixes).<br/>
   *
   */
  public class Host extends GenericObject {
  
      /**
       * Determines whether or not we should tolerate and strip address scope
       * zones from IPv6 addresses. Address scope zones are sometimes returned
       * at the end of IPv6 addresses generated by InetAddress.getHostAddress().
       * They are however not part of the SIP semantics so basically this method
       * determines whether or not the parser should be stripping them (as
       * opposed simply being blunt and throwing an exception).
       */
      private boolean stripAddressScopeZones = false;
  
      private static final long serialVersionUID = -7233564517978323344L;
      protected static final int HOSTNAME = 1;
      protected static final int IPV4ADDRESS = 2;
      protected static final int IPV6ADDRESS = 3;
  
      /** hostName field
       */
      protected String hostname;
  
      /** address field
       */
  
      protected int addressType;
  
      private InetAddress inetAddress;
  
      /** default constructor
       */
      public Host() {
          addressType = HOSTNAME;
  
          stripAddressScopeZones
              = Boolean.getBoolean("gov2.nist.core.STRIP_ADDR_SCOPES");
      }
  
      /** Constructor given host name or IP address.
       */
      public Host(String hostName) throws IllegalArgumentException {
          if (hostName == null)
              throw new IllegalArgumentException("null host name");
  
          stripAddressScopeZones
              = Boolean.getBoolean("gov2.nist.core.STRIP_ADDR_SCOPES");
  
          setHost(hostName, IPV4ADDRESS);
      }
  
      /** constructor
       * @param name String to set
       * @param addrType int to set
       */
      public Host(String name, int addrType) {
          stripAddressScopeZones
              = Boolean.getBoolean("gov2.nist.core.STRIP_ADDR_SCOPES");
  
          setHost(name, addrType);
      }
  
      /**
       * Return the host name in encoded form.
       * @return String
       */
      public String encode() {
          return encode(new StringBuffer()).toString();
      }
  
      public StringBuffer encode(StringBuffer buffer) {
          if (addressType == IPV6ADDRESS && !isIPv6Reference(hostname)) {
              buffer.append('[').append(hostname).append(']');
          } else {
              buffer.append(hostname);
          }
          return buffer;
      }
  
      /**
       * Compare for equality of hosts.
       * Host names are compared by textual equality. No dns lookup
       * is performed.
       * @param obj Object to set
       * @return boolean
       */
      public boolean equals(Object obj) {
          if ( obj == null ) return false;
          if (!this.getClass().equals(obj.getClass())) {
              return false;
          }
          Host otherHost = (Host) obj;
          return otherHost.hostname.equals(hostname);
  
      }
  
      /** get the HostName field
       * @return String
       */
      public String getHostname() {
          return hostname;
      }
  
      /** get the Address field
       * @return String
       */
      public String getAddress() {
          return hostname;
      }
  
      /**
       * Convenience function to get the raw IP destination address
       * of a SIP message as a String.
       * @return String
       */
      public String getIpAddress() {
          String rawIpAddress = null;
          if (hostname == null)
              return null;
          if (addressType == HOSTNAME) {
              try {
                  if (inetAddress == null)
                      inetAddress = InetAddress.getByName(hostname);
                  rawIpAddress = inetAddress.getHostAddress();
              } catch (UnknownHostException ex) {
                  dbgPrint("Could not resolve hostname " + ex);
              }
          } else {
              rawIpAddress = hostname;
          }
          return rawIpAddress;
      }
  
      /**
       * Set the hostname member.
       * @param h String to set
       */
      public void setHostname(String h) {
          setHost(h, HOSTNAME);
      }
  
      /** Set the IP Address.
       *@param address is the address string to set.
       */
      public void setHostAddress(String address) {
          setHost(address, IPV4ADDRESS);
      }
  
      /**
       * Sets the host address or name of this object.
       *
       * @param host that host address/name value
       * @param type determines whether host is an address or a host name
       */
      private void setHost(String host, int type){
          //set inetAddress to null so that it would be reinited
          //upon next call to getInetAddress()
          inetAddress = null;
  
          if (isIPv6Address(host))
              addressType = IPV6ADDRESS;
          else
              addressType = type;
  
          // Null check bug fix sent in by jpaulo@ipb.pt
          if (host != null){
              hostname = host.trim();
  
              //if this is an FQDN, make it lowercase to simplify processing
              if(addressType == HOSTNAME)
                  hostname = hostname.toLowerCase();
  
              //remove address scope zones if this is an IPv6 address as they
              //are not allowed by the RFC
              int zoneStart = -1;
              if(addressType == IPV6ADDRESS
                  && stripAddressScopeZones
                  && (zoneStart = hostname.indexOf('%'))!= -1){
  
                  hostname = hostname.substring(0, zoneStart);
              }
          }
      }
  
      /**
       * Set the address member
       * @param address address String to set
       */
      public void setAddress(String address) {
          this.setHostAddress(address);
      }
  
      /** Return true if the address is a DNS host name
       *  (and not an IPV4 address)
       *@return true if the hostname is a DNS name
       */
      public boolean isHostname() {
          return addressType == HOSTNAME;
      }
  
      /** Return true if the address is a DNS host name
       *  (and not an IPV4 address)
       *@return true if the hostname is host address.
       */
      public boolean isIPAddress() {
          return addressType != HOSTNAME;
      }
  
      /** Get the inet address from this host.
       * Caches the inet address returned from dns lookup to avoid
       * lookup delays.
       *
       *@throws UnkownHostexception when the host name cannot be resolved.
       */
      public InetAddress getInetAddress() throws java.net.UnknownHostException {
          if (hostname == null)
              return null;
          if (inetAddress != null)
              return inetAddress;
          inetAddress = InetAddress.getByName(hostname);
          return inetAddress;
  
      }
  
      //----- IPv6
      /**
       * Verifies whether the <code>address</code> could
       * be an IPv6 address
       */
      private boolean isIPv6Address(String address) {
          return (address != null && address.indexOf(':') != -1);
      }
  
      /**
       * Verifies whether the ipv6reference, i.e. whether it enclosed in
       * square brackets
       */
      public static boolean isIPv6Reference(String address) {
          return address.charAt(0) == '['
              && address.charAt(address.length() - 1) == ']';
      }
      
      @Override
      public int hashCode() {
          return this.getHostname().hashCode();
          
      }
  }
  