//------------------------------------------------------------------------------
// Dotless IP Calculator
// Copyright (c) 1999-2001, Root Solutions
//------------------------------------------------------------------------------

  // Constants
  var MAX_DECIMAL_VALUE = 4294967295  // 2^32 - 1
  var LEFTMOST_HEX_PLACE = 268435456  // 16^7
  
  //----------------------------------------------------------------------------
  // Check validity of a base 10 or 16 number.
  //----------------------------------------------------------------------------
  function isNumeric(strNumber, radix)
  {
    var validChars = "0123456789"
    var validNumber = true
    var i = 0
    
    if (radix == 16)
      validChars += "ABCDEF"
      
    // Check for valid digits.
    for (i = 0; i < strNumber.length; i++)
      if (validChars.indexOf(strNumber.charAt(i).toUpperCase()) == -1)
        validNumber = false
        
    return validNumber
  }
  
  //----------------------------------------------------------------------------
  // Given a decimal number, convert it to a hexidecimal string.
  //----------------------------------------------------------------------------
  function toHex(dec_number)
  {
    // These 2 lines don't work in Netscape 4.7 when the dec_number 
    // is 2^31 or larger. How do you specify unsigned?  It works fine in IE.
    /*hex_value = dec_number.toString(16)
    return hex_value.toUpperCase()*/
    
    // Do it by hand :(
    var hexNumbers = new Array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F')
    var hexValueArray = new Array('0','0','0','0','0','0','0','0')
    var hex_value = ""
    var temp = dec_number
    var i = 0, j = 0, k = 0

    for (i = LEFTMOST_HEX_PLACE; i >= 1; i /= 16, j++)
    {
      hexValueArray[j] = Math.floor(temp / i)
      temp %= i
      
      // Carry over if necessary.
      k = j;
      while (hexValueArray[k] == 16 && k > 0)
      {
        hexValueArray[k] = 0
        hexValueArray[--k]++
      }
    }

    // Convert the decimal numbers to hex digits.
    i = 0
    while (hexValueArray[i++] == 0);
    for (--i; i < hexValueArray.length; i++)
      hex_value += hexNumbers[hexValueArray[i]]
    
    delete hexNumbers
    delete hexValueArray
    return hex_value
  }
  
  //----------------------------------------------------------------------------
  // Given the form containing fields oct[0], oct[1], oct[2], oct[3], and a 32-bit
  // decimal number, assign the appropriate octets to the form fields.
  //----------------------------------------------------------------------------
  function assignOctets(calc, dec_number)
  {
    var temp = dec_number
    var i = Math.pow(2, 24), j = 0
    for (i; i >= 1, j < 4; i /= 256, j++)
    {
      calc.oct[j].value = Math.floor(temp / i)
      temp %= i
    }
  }

  //----------------------------------------------------------------------------
  // Process the calculation given a "normal" octet-based IP address.
  //----------------------------------------------------------------------------
  function calculateDotless(calc)
  {
    var i = 0
    
    // Validate the octets.
    for (i = 0; i < 4; i++)
    {
      if (isEmpty(calc.oct[i].value))
        return warnEmpty(calc.oct[i], "Please enter octet #" + eval(i + 1) + 
        " of the IP address\n" + "before clicking the \"Get Dotless IPs\" button.")
  
      if (!isNumeric(calc.oct[i].value) || 
          eval(calc.oct[i].value) > 255 || 
          eval(calc.oct[i].value) < 0)
        return warnInvalid(calc.oct[i], "Please enter a valid number in decimal format,\n"
               + "from 0 - 255, for octet #" + eval(i + 1) + ".")
    }

    // Calculate the 32-bit decimal equivalent.
    var dec_value = 0
    var j = 0
    for (i = Math.pow(2, 24); i >= 1, j < 4; i /= 256, j++)
      dec_value += eval(calc.oct[j].value) * i

    calc.dotless.value = dec_value
    
    // Calculate the 32-bit hexidecimal equivalent.
    calc.hex.value = toHex(eval(calc.dotless.value))

    return true
  }

  //----------------------------------------------------------------------------
  // Process the calculation given a 32-bit decimal IP address.
  //----------------------------------------------------------------------------
  function calculateOrigAndHex(calc)
  {
    // Validate the 32-bit decimal number.
    if (isEmpty(calc.dotless.value))
      return warnEmpty(calc.dotless, "You must enter a dotless IP in decimal\n"
             + "format before clicking the button.")

    if (!isNumeric(calc.dotless.value) ||
        eval(calc.dotless.value) > MAX_DECIMAL_VALUE ||
        eval(calc.dotless.value) < 0)
  	  return warnInvalid(calc.dotless, "You must enter a VALID 32-bit number\n"
  	         + "in decimal format in the range 0 - " + MAX_DECIMAL_VALUE + ".")
    
    // Calculate the octet-based equivalent.
    assignOctets(calc, eval(calc.dotless.value))

    // Calculate the 32-bit hexidecimal equivalent.
    calc.hex.value = toHex(eval(calc.dotless.value))

    return true
  }

  //----------------------------------------------------------------------------
  // Process the calculation given a 32-bit hexidecimal IP address.
  //----------------------------------------------------------------------------
  function calculateOrigAndDec(calc)
  {
    // Validate the 32-bit hexidecimal number.
    if (isEmpty(calc.hex.value))
      return warnEmpty(calc.hex, "You must enter a dotless IP in hexidecimal\n"
             + "format before clicking the button.")

    if (!isNumeric(calc.hex.value, 16) ||
        parseInt(calc.hex.value, 16) > MAX_DECIMAL_VALUE || 
        parseInt(calc.hex.value, 16) < 0)
	    return warnInvalid(calc.hex, "You must enter a VALID 32-bit hexidecimal number\n"
	         + "in the range 0 - FFFFFFFF.")
			 
    // Calculate the 32-bit decimal equivalent.
    calc.dotless.value = parseInt(calc.hex.value, 16)
    
    // Calculate the octet-based equivalent.
    assignOctets(calc, eval(calc.dotless.value))
    
    return true
  }

