validate ip address (user input)

hi all,

i’ve got a script i’m working on that needs the user to input two ip addresses (for DNS servers). here is part of the code:


global myDNS1
global myDNS2

on getDns()
	set firstQ to "You will need to enter two valid ip addresses to your DNS servers for this to work." & return & "Please enter the first DNS server's ip address:  "
	set secondQ to "Please enter the second DNS server's ip address:  "
	set myDNS1 to text returned of (display dialog firstQ default answer "")
	set myDNS2 to text returned of (display dialog secondQ default answer "")
end getDns

on checkDns(a)
	--not sure how to do this
end checkDns

getDns()

i’d like to call my getDns() and get the user input (done), and then call checkDns(a) for each entry and check to make sure it in a valid ip address form, then give an error if it’s not and recall getDns().

sound simple? i’m not really sure how to do this. i did search, using terms like, “user input” and “‘user input’ validate” but i’m still scratching my head on this one.

thanks.

WaltR;

Why aren’t you just checking to see what they are (or is this a setup script for a machine that’s not configured)

do shell script "cat /etc/resolv.conf"

hi adam,

that’s not a bad idea at all. however, i’m thinking that the user should be able to override these if they needed to for some reason.

to get a better idea of the project, i’m trying to script this hint from macosxhints:

http://www.macosxhints.com/article.php?story=20050420025219402

i’ve got most of it done but i was thinking that the user might have DNS entries they’d like to use. perhaps that is wrong though.

here’s a bit of progress:


global myDNS1
global myDNS2

on getDns()
	set firstQ to "You will need to enter two valid ip addresses to your DNS servers for this to work." & return & "Please enter the first DNS server's ip address:  "
	set secondQ to "Please enter the second DNS server's ip address:  "
	set myDNS1 to text returned of (display dialog firstQ default answer "")
	set myDNS2 to text returned of (display dialog secondQ default answer "")
	checkDNS(myDNS1)
	checkDNS(myDNS2)
end getDns

on checkDNS(a)
	set badAns to a & " is not a valid DNS entry.  Please try again."
	set ASTD to AppleScript's text item delimiters
	set AppleScript's text item delimiters to "."
	set howMany to (count text items of a)
	set x to 1
	repeat while x ≤ howMany
		display dialog text item x of a
		if text item x of a > 0 and text item x of a < 256 then
			set x to (x + 1)
		else
			display dialog badAns
			getDns()
		end if
	end repeat
end checkDNS

getDns()

however, if the number between the dot’s is less than 3 digits it fails. for example:

123.123.123.123 – works fine!
123.12.312.312 – fails on the ‘12’ → DOAH! 312 is not a valid number. see below.

do i need to pad the numbers with 0’s or is there a better way to do this?

cheers.

EDITED: because i need to slow down a bit.

There’s also whois:

do shell script "whois 72.14.207.104" -- happens to be Google.ca

and parse something out of that confirm that it’s a reachable address.

ok, i just realized that 312 is bigger than 256.

more coffee please! :confused:

ok, my function seems not to work when the first number is over ‘2’. so:

123.123.123.223 – works!
123.123.123.5 – doesn’t work! fails on the ‘5’

does anyone know what i’m doing wrong? i feel it must be obvious, but i am too close to see it.

on checkDNS(a)
	set badAns to a & " is not a valid DNS entry. Please try again."
	set ASTD to AppleScript's text item delimiters
	set AppleScript's text item delimiters to "."
	set howMany to count (text items of a)
	if howMany < 4 then
		display dialog "Whoops"
		return
	end if
	set TI to text items of a
	set AppleScript's text item delimiters to ASTD
	set x to 1
	repeat while x ≤ howMany
		--display dialog text item x of a
		tell (text item x of TI) as number
			if it ≥ 0 and it < 256 then
				set x to (x + 1)
				set msg to "Yay"
			else
				set msg to badAns
				exit repeat
				--getDns()
			end if
		end tell
	end repeat
	display dialog msg
end checkDNS

checkDNS("123.12.0.123")

nice adam,

i’ve got to digest that.

by the way, another way of finding the DNS names on the local machine is with a utility called, ‘scutil’. try:

scutil --dns

for an interesting look at how OS X handles DNS.

cheers.

The problem with whois, is that if there are only three: 72.14.104, say, this is interpreted as if the last was 0: 72.14.104.0 actually resolves.

ok, here is the final answer for this component of the program:


global myDNS1
global myDNS2

on getDns()
	set firstQ to "You will need to enter two valid ip addresses to your DNS servers for this to work." & return & "Please enter the first DNS server's ip address:  "
	set secondQ to "Please enter the second DNS server's ip address:  "
	set myDNS1 to text returned of (display dialog firstQ default answer "")
	set myDNS2 to text returned of (display dialog secondQ default answer "")
	checkDNS(myDNS1)
	checkDNS(myDNS2)
end getDns

on checkDNS(a)
	set badAns to a & " is not a valid DNS entry.  Please try again."
	set ASTD to AppleScript's text item delimiters
	set AppleScript's text item delimiters to "."
	set howMany to (count text items of a)
	if howMany is not 4 then
		display dialog badAns
		getDns()
		return
	end if
	set TI to text items of a
	set AppleScript's text item delimiters to ASTD
	set x to 1
	repeat while x ≤ howMany
		tell (text item x of TI) as number
			if it ≥ 0 and it < 256 then
				set x to (x + 1)
			else
				display dialog badAns
				getDns()
				exit repeat
			end if
		end tell
	end repeat
end checkDNS

getDns()

i’ll work in getting some DNS numbers from /etc/resolv.conf or from scutil also–that’s a really good idea.

A bit cleaner, Waltr:


on checkDNS(a)
	set badAns to a & " is not a valid DNS entry."
	set ASTD to AppleScript's text item delimiters
	set AppleScript's text item delimiters to "."
	set blocks to text items of a
	set howMany to count blocks
	if howMany < 4 then
		display dialog a & " is not valid." & return & return & "IP addresses must have four groups"
		return
	end if
	set AppleScript's text item delimiters to ASTD
	repeat with k from 1 to 4
		tell item k of blocks as number to if it ≥ 0 and it < 256 then
			set msg to "Yay"
		else
			set msg to badAns & return & return & "Block #" & k & " is out of range" & return & return & "Using numbers between 0 and 255, try again"
			exit repeat
		end if
	end repeat
	display dialog msg
end checkDNS

set IPs to (choose from list {"123.233.4.1", "43.33.99", "27.49.259.0"}) as string
checkDNS(IPs)

hi adam,

i changed this:

if howMany < 4 then
       display dialog a & " is not valid." & return & return & "IP addresses must have four groups"
       return
   end if

to this:

if howMany is not 4 then
       display dialog badAns
       getDns()
       return

so that it would catch numbers that had more entries than 4 also. do you think that’s wise?

i’ve added this all to the big script. i have one more question, but i’ll start another thread–after lunch!

Might want to reset the delimiters before you return. :wink:

Edit:

on checkValidIPAddress(address)
	local address, octets, i
	
	set ASTID to AppleScript's text item delimiters
	set AppleScript's text item delimiters to {"."}
	set octets to text items of address
	set AppleScript's text item delimiters to ASTID
	
	if (count octets) is not 4 then error "An IP address must have four groups." number 5 -- or return false
	
	repeat with i from 1 to 4
		tell (item i of octets as integer) to if not (it ≥ 0 and it ≤ 255) then
			error "Group " & i & " is out of range. Each group must be between 0 and 255." number i -- or return false
			exit repeat
		end if
	end repeat
	--return true
end checkValidIPAddress

try
	choose from list {"123.233.4.1", "43.33.99", "27.49.259.0"}
	checkValidIPAddress("" & result)
on error errMsg number errNum
	display dialog "Error " & errNum & ":" & return & return & errMsg buttons {"Ok"} default button 1 with icon note
end try

Nice and clean, Bruce