function binaryvalidate(binv) {
	b2ii=0
	validbinary=1
	while (b2ii<binv.length) {
		if (binv.substr(b2ii,1)!='0' & binv.substr(b2ii,1)!='1') {
			validbinary=0
		}
		b2ii++
	}

	if (validbinary==0) {alert('Your binary argument contains characters other than 0 and 1.')}

	if (validbinary==1) {
		return binv
	} else {return 'undefined'}
}
function ipv4validate(ipaddr) {
	ipvi=0
	validip=1
	ipvperiodcount=0
	var ipvperiodarray = new Array()
	ipvperiodconsecutive=0
	ipvperiodlast=0
	if (ipaddr.length<7) {
		alert('An IP address must be at least 7 characters long.')
		return 'undefined'
	} else if (ipaddr.length>15) {
		alert('An IP address must be no more than 15 characters long.')
		return 'undefined'
	} else {
		while (ipvi<ipaddr.length) {
			if (ipaddr.substr(ipvi,1)=='.') {
				ipvperiodarray[ipvperiodcount]=ipvi
				if (ipvperiodlast==1) {
					ipvperiodconsecutive=1
				}
				ipvperiodlast=1
				ipvperiodcount++
			} else {
				ipvperiodlast=0
			}
			ipvi++
		}
		if (ipvperiodconsecutive==1) {
			alert('There should be at least one number between each dot.')
			return 'undefined'
		} else if (ipvperiodcount<3) {
			alert('There should be at least three dots in a valid IP address.')
			return 'undefined'
		} else if (ipvperiodcount>3) {
			alert('There can be no more than 3 dots in a valid IP address.')
			return 'undefined'
		} else if (ipaddr.substr(ipaddr.length-1,1)=='.') {
			alert('There should be at least one number after the last dot.')
			return 'undefined'
		} else if (ipaddr.substr(0,1)=='.') {
			alert('There should be at least one number before the first dot.')
			return 'undefined'
		} else {
			q1=ipaddr.substr(0,ipvperiodarray[0])
			q2=ipaddr.substr(ipvperiodarray[0]+1,ipvperiodarray[1]-ipvperiodarray[0]-1)
			q3=ipaddr.substr(ipvperiodarray[1]+1,ipvperiodarray[2]-ipvperiodarray[1]-1)
			q4=ipaddr.substr(ipvperiodarray[2]+1,ipaddr.length-ipvperiodarray[2])
			if (isnumber(q1) & isnumber(q2) & isnumber(q3) & isnumber(q4)) {
				if (parseInt(q1)<256 & parseInt(q1)>-1 & parseInt(q2)<256 & parseInt(q2)>-1 & parseInt(q3)<256 & parseInt(q3)>-1 & parseInt(q4)<256 & parseInt(q4)>-1) {
					return ipaddr
				} else {
					alert('Each octet should be a number between 0 and 255.')
					return 'undefined'
				}
			} else {
				alert('One or more of the octets was/were not a number.')
				return 'undefined'
			}
		}
	}
}
function binfixed(bf,numdigits) {
	bf=bf.toString()
	excessones=0
	excessstring=""
	bfi=0
	numdigits=parseInt(numdigits)
	if (numdigits<1) {
		alert('The reqested number of digits must be at least 1.')
		return 'undefined'
	} else {
		if (bf.length>numdigits) {
			excessstring=bf.substr(0,bf.length-numdigits)
			while (bfi<excessstring.length) {
				if (excessstring.substr(bfi,1)=='1') {
					excessones=1
				}
				bfi++
			}
		}
		if (excessones==1) {
			alert('Your binary input string is too long for the number of digits you requested.')
			return 'undefined'
		} else {
			bfi=0
			bfj=bf.length
			while (bfi<numdigits-bfj) {
				bf="0"+bf
				bfi++
			}
			return bf
		}
	}
}
function hexfixed(hf,numdigits) {
	hf=hf.toString()
	excessones=0
	excessstring=""
	hfi=0
	numdigits=parseInt(numdigits)
	if (numdigits<1) {
		alert('The reqested number of digits must be at least 1.')
		return 'undefined'
	} else {
		if (hf.length>numdigits) {
			excessstring=hf.substr(0,hf.length-numdigits)
			while (hfi<excessstring.length) {
				if (excessstring.substr(hfi,1)=='1') {
					excessones=1
				}
				hfi++
			}
		}
		if (excessones==1) {
			alert('Your binary input string is too long for the number of digits you requested.')
			return 'undefined'
		} else {
			hfi=0
			hfj=hf.length
			while (hfi<numdigits-hfj) {
				hf="0"+hf
				hfi++
			}
			return hf
		}
	}	
}
function bin2dec(bin2d) {
	bin2d=binaryvalidate(bin2d)
	b2di=bin2d.length-1
	b2dj=0
	b2dsum=0
	while (b2di>-1) {
		b2dsum=b2dsum+parseInt(bin2d.substr(b2di,1))*(Math.pow(2,b2dj))
//		alert(Math.pow(2,b2dj))
//		alert(parseInt(bin2d.substr(b2di,1)))
//		alert(b2di)
		b2di--
		b2dj++
	}
	return b2dsum
}
function dec2bin(d2b) {
	d2bi=0
	d2bj=0
	d2brmndr=d2b
	var d2barray=new Array()
	while (Math.pow(2,d2bi)<=d2b) {d2bi++}
	if (d2bi>0) {
		d2bi--
		d2bj=d2bi
		d2barray[d2bj-d2bi]="1"
		d2brmndr=d2brmndr-Math.pow(2,d2bi)
		d2bi--
		while (d2bi>-1) {
			if (d2brmndr>=Math.pow(2,d2bi)) {
				d2brmndr=d2brmndr-Math.pow(2,d2bi)
				d2barray[d2bj-d2bi]="1"
			} else {d2barray[d2bj-d2bi]="0"}
			d2bi--
		}
	} else {d2barray[0]="0"}
	d2bi=0
	var d2bstring=""
	while (d2bi<d2barray.length) {
		d2bstring=d2bstring+d2barray[d2bi]
		d2bi++
	}
	return d2bstring
}
function bin2ip(binip) {
	binip=binaryvalidate(binip)
	validlength=1
	if (binip.length!=32) {alert('Your binary argument should be 32 bits in length.');validlength=0}
	if (validlength==1) {
		b2i1=bin2dec(binip.substr(0,8))
		b2i2=bin2dec(binip.substr(8,8))
		b2i3=bin2dec(binip.substr(16,8))
		b2i4=bin2dec(binip.substr(24,8))
		return b2i1+'.'+b2i2+'.'+b2i3+'.'+b2i4
	} else {alert('Invalid binary argument.');return 'undefined'}
}
function ip2bin(ipbin) {
	ipbin=ipv4validate(ipbin)
	if (ipbin=='undefined') {
		return 'undefined'
	} else {
		ip2bi=0
		quad1=""
		quad2=""
		quad3=""
		quad4=""
		while (ipbin.substr(ip2bi,1)!='.') {
			quad1=quad1+ipbin.substr(ip2bi,1)
			ip2bi++
		}
		ip2bi++
		while (ipbin.substr(ip2bi,1)!='.') {
			quad2=quad2+ipbin.substr(ip2bi,1)
			ip2bi++
		}
		ip2bi++
		while (ipbin.substr(ip2bi,1)!='.') {
			quad3=quad3+ipbin.substr(ip2bi,1)
			ip2bi++
		}
		ip2bi++
		while (ip2bi<ipbin.length) {
			quad4=quad4+ipbin.substr(ip2bi,1)
			ip2bi++
		}
		quad1=parseInt(quad1)
		quad2=parseInt(quad2)
		quad3=parseInt(quad3)
		quad4=parseInt(quad4)
		quad1=dec2bin(quad1)
		quad2=dec2bin(quad2)
		quad3=dec2bin(quad3)
		quad4=dec2bin(quad4)
		return binfixed(quad1,8)+' '+binfixed(quad2,8)+' '+binfixed(quad3,8)+' '+binfixed(quad4,8)
	}	
}
function nibble2hex(n2h) {
	var n2hdecnum=0
	if (n2h.length<4) {
		alert('Not enough characters for a valid nibble.')
		return 'undefined'
	} else if (n2h.length>4) {
		alert('Too many characters for a valid nibble.')
		return 'undefined'
	} else {
		n2h=binaryvalidate(n2h)
		if (n2h!='undefined') {
			n2hdecnum=bin2dec(n2h)
			if (n2hdecnum<10) {
				return n2hdecnum.toString()
			} else if (n2hdecnum==10) {
				return 'A'
			} else if (n2hdecnum==11) {
				return 'B'
			} else if (n2hdecnum==12) {
				return 'C'
			} else if (n2hdecnum==13) {
				return 'D'
			} else if (n2hdecnum==14) {
				return 'E'
			} else if (n2hdecnum==15) {
				return 'F'
			} else {
			
			}
		} else {
			return 'undefined'
		}
	}
}
function isnumber(instr) {
	ini=0
	isnumeric=1
	while (ini<instr.length) {
		if (instr.substr(ini,1)=='0' || instr.substr(ini,1)=='1' || instr.substr(ini,1)=='2' || instr.substr(ini,1)=='3' || instr.substr(ini,1)=='4' || instr.substr(ini,1)=='5' || instr.substr(ini,1)=='6' || instr.substr(ini,1)=='7' || instr.substr(ini,1)=='8' || instr.substr(ini,1)=='9') {
			
		} else {
			isnumeric=0
		}
		ini++
	}
	return isnumeric
}
function bin2hex(b2hbin) {
	b2hi=0
	b2hans=''
	b2h4mod=b2hbin.length % 4
	if (b2h4mod!=0) {
		if (b2h4mod==1) {
			b2hbin='000'+b2hbin
		} else if (b2h4mod==2) {
			b2hbin='00'+b2hbin
		} else {
			b2hbin='0'+b2hbin
		}
	}
	while (b2hi<b2hbin.length) {
		b2hans=b2hans+nibble2hex(b2hbin.substr(b2hi,4))
		b2hi=b2hi+4
	}
	return b2hans
}
function hex2bin(h2bhex) {
	h2bi=0
	h2bbin=''
	validhex=1
	while (h2bi<h2bhex.length) {
		if (isnumber(h2bhex.substr(h2bi,1))==1) {
			h2bbin=h2bbin+binfixed(dec2bin(h2bhex.substr(h2bi,1)),4)
		} else if (h2bhex.substr(h2bi,1)=='A') {
			h2bbin=h2bbin+'1010'
		} else if (h2bhex.substr(h2bi,1)=='B') {
			h2bbin=h2bbin+'1011'
		} else if (h2bhex.substr(h2bi,1)=='C') {
			h2bbin=h2bbin+'1100'
		} else if (h2bhex.substr(h2bi,1)=='D') {
			h2bbin=h2bbin+'1101'
		} else if (h2bhex.substr(h2bi,1)=='E') {
			h2bbin=h2bbin+'1110'
		} else if (h2bhex.substr(h2bi,1)=='F') {
			h2bbin=h2bbin+'1111'
		} else {
			validhex=0
			return 'undefined'
		}
		h2bi++
	}
	if (validhex==1) {
		return h2bbin
	} else {
		return 'undefined'
	}
}
function hex2dec(h2dhex) {
	return bin2dec(hex2bin(h2dhex))
}
function dec2hex(d2hdec) {
	return bin2hex(dec2bin(d2hdec))
}
function ipv6bin2hex(ipv6b2h) {
	ipv6b2h=binaryvalidate(ipv6b2h)
	ipv6b2hcontinue=true
	if (ipv6b2h=='undefined') {
		ipv6b2hcontinue=false
		return 'undefined'
	}
	if (ipv6b2hcontinue==true) {
		if (ipv6b2h.length!=128) {
			alert('ipv6bin2hex: An IPV6 address in binary form should be 128 characters in length.')
			return 'undefined'
		} else {
			ipv6b2hi=0
			ipv6b2h2i=0
			ipv6b2hans=''
			while (ipv6b2h2i<8) {
					ipv6b2hans=ipv6b2hans+bin2hex(ipv6b2h.substr(ipv6b2h2i*16,16))
					if (ipv6b2h2i!=7) {
						ipv6b2hans=ipv6b2hans+':'
					}
				ipv6b2hi=0
				ipv6b2h2i++
			}
			return ipv6b2hans
		}
	}
}
function hexvalidate(hvhex) {
	hvi=0
	hvvalidhex=true
	while (hvi<hvhex.length) {
		if (hvhex.substr(hvi,1)=='A' || hvhex.substr(hvi,1)=='B' || hvhex.substr(hvi,1)=='C' || hvhex.substr(hvi,1)=='D' || hvhex.substr(hvi,1)=='E' || hvhex.substr(hvi,1)=='F' || isnumber(hvhex.substr(hvi,1))==1) {
			
		} else {
			hvvalidhex=false
		}
		hvi++
	}
	return hvvalidhex
}
function ipv6hexvalidate(ipv6hv) {
	var ipv6hvcolonarray = new Array()
	var ipv6hvhexarray = new Array()
	ipv6hvnumberofcolons=0
	ipv6hvi=0
	ipv6hvvalid=true
	while (ipv6hvi<ipv6hv.length) {
		if (ipv6hv.substr(ipv6hvi,1)==':') {
			ipv6hvnumberofcolons++
			ipv6hvcolonarray[ipv6hvcolonarray.length]=ipv6hvi
		}
		ipv6hvi++
	}
	ipv6hvi=0
	if (ipv6hvnumberofcolons>7 || ipv6hv.substr(0,1)==':' || ipv6hv.substr(ipv6hv.length,1)==':') {
		ipv6hvvalid=false
		alert('ipv6hexvalidate: invalid argument.')
		return 'undefined'
	}
	if (ipv6hvvalid==true) {
		ipv6hvhexarray[ipv6hvhexarray.length]=ipv6hv.substr(0,ipv6hvcolonarray[0])
		while (ipv6hvi<ipv6hvcolonarray.length-1) {
			ipv6hvhexarray[ipv6hvhexarray.length]=ipv6hv.substr(ipv6hvcolonarray[ipv6hvi]+1,ipv6hvcolonarray[ipv6hvi+1]-ipv6hvcolonarray[ipv6hvi]-1)
			ipv6hvi++
		}
		ipv6hvhexarray[ipv6hvhexarray.length]=ipv6hv.substr(ipv6hvcolonarray[ipv6hvi]+1,ipv6hv.length-ipv6hvcolonarray[ipv6hvi])
		ipv6hvi=0
		while (ipv6hvi<ipv6hvhexarray.length) {
			if (hexvalidate(ipv6hvhexarray[ipv6hvi])!=true) {

				ipv6hvvalid=false
			}
			ipv6hvi++
		}
		if (ipv6hvvalid==true) {
			return ipv6hv
		} else {
			return 'undefined'
		}
	}
}
function ipv6hexabbr(ipv6ha) {
	ipv6havalid=true
	ipv6hai=0
	ipv6haconsecutivecoloncount=0
	ipv6hamaxconsecutivecoloncount=0
	ipv6hahextemp=''
	ipv6haansstring=''
	var ipv6hacolonarray = new Array()
	var ipv6hahexarray = new Array()
	if (ipv6hexvalidate(ipv6ha)=='undefined') {
		ipv6havalid=false
	}
	if (ipv6havalid==true) {
		while (ipv6hai<ipv6ha.length) {
			if (ipv6ha.substr(ipv6hai,1)==':') {
				ipv6hacolonarray[ipv6hacolonarray.length]=ipv6hai
			}
			ipv6hai++
		}
		ipv6hai=0
		ipv6hahexarray[0]=ipv6ha.substr(0,ipv6hacolonarray[0])
		while (ipv6hai<ipv6hacolonarray.length-1) {
			ipv6hahexarray[ipv6hahexarray.length]=ipv6ha.substr(ipv6hacolonarray[ipv6hai]+1,ipv6hacolonarray[ipv6hai+1]-ipv6hacolonarray[ipv6hai]-1)
			ipv6hai++
		}
		ipv6hahexarray[ipv6hahexarray.length]=ipv6ha.substr(ipv6hacolonarray[ipv6hai]+1,ipv6ha.length-ipv6hacolonarray[ipv6hai])
		ipv6hai=0
		ipv6ha2i=0
		while (ipv6hai<ipv6hahexarray.length) {
			ipv6hanumberofinitzeroes=0
			ipv6hainitzero=true
			while (ipv6ha2i<ipv6hahexarray[ipv6hai].length) {
				ipv6hahextemp=ipv6hahexarray[ipv6hai]
				if (ipv6hahexarray[ipv6hai].substr(ipv6ha2i,1)=='0' & ipv6hainitzero==true) {
					ipv6hanumberofinitzeroes++
				} else {
					ipv6hainitzero=false
				}
				ipv6ha2i++
			}
			if (ipv6hanumberofinitzeroes==4) {
				ipv6hahextemp='0'
			} else {
				ipv6hahextemp=ipv6hahexarray[ipv6hai].substr(ipv6hanumberofinitzeroes,4-ipv6hanumberofinitzeroes)
			}
			ipv6hahexarray[ipv6hai]=ipv6hahextemp
			ipv6hai++
			ipv6ha2i=0
		}
		ipv6hai=0
		ipv6hanumberofconsecutivezeroes=0
		ipv6hamaxnumberofconsecutivezeroes=0
		ipv6haconsecutivezeroendsegment=-1
		ipv6hainitzero=true
		while (ipv6hai<ipv6hahexarray.length) {
			if (ipv6hahexarray[ipv6hai]=='0') {
				ipv6hanumberofconsecutivezeroes++
				if (ipv6hanumberofconsecutivezeroes>ipv6hamaxnumberofconsecutivezeroes) {
					ipv6hamaxnumberofconsecutivezeroes=ipv6hanumberofconsecutivezeroes
					ipv6haconsecutivezeroendsegment=ipv6hai
				}
			} else {
				ipv6hanumberofconsecutivezeroes=0
			}
			ipv6hai++
		}
		ipv6hai=0
		if (ipv6haconsecutivezeroendsegment==-1) {

		} else if (ipv6haconsecutivezeroendsegment==0) {
			ipv6hahexarray[0]='::'
		} else if (ipv6haconsecutivezeroendsegment==ipv6hahexarray.length-1) {
			if (ipv6hamaxnumberofconsecutivezeroes==8) {
				while (ipv6hai<ipv6hahexarray.length-1) {
					ipv6hahexarray[ipv6hai]=''
					ipv6hai++
				}
				ipv6hai=0
				ipv6hahexarray[ipv6hahexarray.length-1]='::'
			} else {
				ipv6hai=ipv6hahexarray.length-ipv6hamaxnumberofconsecutivezeroes
				while (ipv6hai<ipv6hahexarray.length-1) {
					ipv6hahexarray[ipv6hai]=''
					ipv6hai++
				}
				ipv6hai=0
				ipv6hahexarray[ipv6hahexarray.length-1]=':'
			}
		} else {
			ipv6hai=ipv6haconsecutivezeroendsegment-ipv6hamaxnumberofconsecutivezeroes+1
			while (ipv6hai<=ipv6haconsecutivezeroendsegment) {
				ipv6hahexarray[ipv6hai]=''
				ipv6hai++
			}
			if (ipv6haconsecutivezeroendsegment!=ipv6hamaxnumberofconsecutivezeroes-1) {
				ipv6hahexarray[ipv6hai-1]=':'
			} else {
				ipv6hahexarray[ipv6hai-1]='::'
			}
			ipv6hai=0
		}
		while (ipv6hai<ipv6hahexarray.length) {
			if (ipv6hahexarray[ipv6hai]!=':' & ipv6hahexarray[ipv6hai]!='::' & ipv6hai!=ipv6hahexarray.length-1 & ipv6hahexarray[ipv6hai].length!=0) {
				ipv6hahexarray[ipv6hai]=ipv6hahexarray[ipv6hai]+':'
			}
			ipv6hai++
		}
		ipv6hai=0
		while (ipv6hai<ipv6hahexarray.length) {
			ipv6haansstring=ipv6haansstring+ipv6hahexarray[ipv6hai]
			ipv6hai++
		}
		return ipv6haansstring
	}
}
function subnet(snarg) {
	ba=ip2bin(snarg)
	binaddress=ba.substr(0,8)+ba.substr(9,8)+ba.substr(18,8)+ba.substr(27,8)
	i=0
	if (binaddress.substr(i,1)=='1') {
		zeroencountered=false
		zerooneinversion=false
		zeroi=-1
		if (binaddress.length==32) {
			while (i<binaddress.length) {
				if (binaddress.substr(i,1)=='0' & zeroencountered==false) {
					zeroencountered=true
					zeroi=i
				}
				if (zeroencountered==true & binaddress.substr(i,1)=='1') {
					zerooneinversion=true
				}
				i++
			}
		} else {
			document.write('Invalid subnet mask.  Binary equivalent must be 32 digits in length.')
		}
	} else {
		document.write('Invalid subnet mask.  First digit of binary equivalent not equal to 1.')
	}
	return {
		hosts: function() {
			return Math.pow(2,32-zeroi)-2
		},
		subnets: function() {
			return Math.pow(2,zeroi)-2
		}
	}
}
function cidr(slashnum) {
	return {
		hosts: function() {
			return Math.pow(2,32-slashnum)-2
		},
		subnets: function() {
			return Math.pow(2,slashnum)-2
		}
	}
}