|
Whois Client in Visual Basic .NET
Written by Tony Bhimani
September 5, 2004
Requirements
Microsoft Windows 98/ME/NT4/2000/XP
Microsoft
.NET Framework Version 1.1
Download the source code: Whois_VB.NET.zip
I frequently use the Whois Client on my RedHat server and wanted to add
the same tool to my Windows system. I figured it would be a good opportunity
to start learning VB.NET and a tool of this type incorporates a few important
features. By features I mean the use of regular expressions, file I/O,
hash tables, and tcp/ip sockets. So there is a little bit of everything
for those reading this tutorial. As I wrote the client, there was one
thing about multiline text boxes that Microsoft changed I was unaware
of. In VB when you put a multiline string in a multiline text box you
use newline characters (vbCrLf or vbNewLine) to mark lines in text. In
VB.NET the multiline text box has a property called Lines that expects
an array of strings. This makes more sense and I thought was kind of cool.

The Whois Client is GUI based. Later I will write a console based version
and post the source code.You can do queries for domain names as well as
IP addresses. As the program is loaded it reads in a text file containing
whois servers and the TLD's (Top Level Domains) they service. The text
file was borrowed from a PHP whois script called mwhois which is available
from Matt's Script
Archive (why reinvent the wheel when you don't have to.) A hash table
is created as the servers and TLD's are read in. A hash table is similar
to a PHP associative array. When you do a query the TLD (i.e. com, net,
co.uk, etc) is parsed from the domain name and passed to the hash table.
The hash table returns the whois server to contact for the query. The
domain name and the server are passed to a function which contacts the
whois server to retrieve the domain's information. That information is
then parsed using regular expressions to check for the whois server of
the registrar for the domain. If it is found an additional query is performed
to retrieve more detailed information about the domain. Finally all the
information is placed in the multiline text box and shown to the user.
Now we will look at some code segments. We start with the servers.lst
file which contains all the TLD and whois servers.
com|whois.crsnic.net|No match for|whois.networksolutions.com|whois.internic.net|Whois Server:
net|whois.crsnic.net|No match for|whois.networksolutions.com|whois.internic.net|Whois Server:
...
Each line has several fields but we are interested in only the first
and second ones. The first field is the TLD and the second one is the
whois server that handles its requests. We read these lines in and create
a hash table containing the TLD and whois server with the LoadWhoisServers
function.
Private Shared Function LoadWhoisServers(ByVal filename As String) As Hashtable
Dim tmpArray() As String
Dim whoisTable As New Hashtable()
Try
Dim MyStreamReader As StreamReader = IO.File.OpenText(filename)
Do While MyStreamReader.Peek() >= 0
tmpArray = MyStreamReader.ReadLine().Split("|")
If (tmpArray.GetLength(0) = 6 And tmpArray(0).StartsWith("#") = False) Then
whoisTable.Add(tmpArray(0), tmpArray(1))
End If
Loop
MyStreamReader.Close()
Catch e As Exception
MsgBox(e.Message + vbLf + "The application will now exit.", MsgBoxStyle.Critical)
End
End Try
Return whoisTable
End Function
...
Private Sub Whois_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
whoisTable = LoadWhoisServers("servers.lst")
End Sub
LoadWhoisServers takes the whois servers list file name as a parameter
and returns a hash table. Each line of the file is read in until end of
file is reached. The file allows for comments on lines beginning with
a #. With the line read in it is split by the | (pipe) character and the
pieces are stored in a string array called tmpArray. Next the size of
the array is tested to see if it has six elements and if it does not begin
with a # character. If this is the case then the TLD and whois server
is added to the hash table. If the array does not have six elements and
starts with a # character, then it is a comment line and the line is skipped.
Once the lines have all been read in and processed, the file is closed
and the hash table is returned. If at any point there is an error the
Catch section is executed. A message box is displayed with the error message
and the application ends. LoadWhoisServers is called from the form's Load
event and the resulting hash table is stored in a global variable called
whoisTable.
The action of the client rests upon the Lookup button's Click event.
Private Sub btnLookup_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLookup.Click
Dim i As Int32
Dim lines As String
Dim server As String
Dim domain As String = txtDomain.Text
Dim tld As String
If (isIP(domain.Trim)) Then
server = "whois.arin.net"
ElseIf (isDomain(domain.Trim)) Then
tld = domain.Substring(domain.IndexOf(".") + 1)
server = whoisTable.Item(tld)
Else
MsgBox("It appears you entered something other than a Domain Name or IP Address.")
txtDomain.Focus()
txtDomain.SelectAll()
Exit Sub
End If
' display our working status
txtResults.Lines = New String() {"Querying whois server(s)...Please wait"}
txtResults.Refresh()
' do the whois query
Dim whoisResult As String = doWhoisQuery(domain, server)
' send the output to the results textbox
lines += "[" + server + "]" + vbLf
lines += whoisResult + vbLf
' check for a redirect whois server
Dim infoServer As String = GetInfoServer(whoisResult)
If (infoServer <> "") Then
whoisResult = doWhoisQuery(domain, infoServer)
lines += "[" + infoServer + "]" + vbLf
lines += whoisResult
End If
txtResults.Lines = lines.Split(vbLf)
End Sub
The domain or IP address is read from the text box and stored in the
domain variable. First it is tested whether it is an IP address, a domain
name, or something that we don't understand (empty strings, malformed
domain names, etc.) If it is an IP then we set the server to whois.arin.net
which is used to query the IP and see who it belongs to. If it is a domain
name then we extract the TLD (everything after the first period encountered)
and pass it to the hash table to get the whois server. If it is not an
IP or domain name then we display an error and set focus to the domain/IP
text box, highlight the contents, and exit the function.
Now with our server set we call the doWhoisQuery function (which we will
go over soon) and pass it the domain name and whois server. The results
are passed back and stored in a string called whoisResult. We append our
results to a string called lines which we will later use for our multiline
text box to show our results. With the whois results we currently have
we then call another function called GetInfoServer. GetInfoServer parses
the results looking for the domain name registrar's whois server so we
can query it for additional details about the domain. If it is found it
is stored in the infoServer variable and we perform another query. More
lines are appended to our result and it is finally stored in our multiline
text box. Now earlier I mentioned multiline text boxes in VB.NET have
a property called Lines that expects a string array. So all we have to
do is convert our lines variable into an array using the Split method
and assign it to the Lines property. We do the split on new line characters
or vbLf.
Private Function isDomain(ByVal domain As String) As Boolean
Dim regex As New RegularExpressions.Regex("^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}$")
Return regex.IsMatch(domain)
End Function
Private Function isIP(ByVal ip As String) As Boolean
Dim regex As New RegularExpressions.Regex("^(?:(?:25[0-5]|2[0-4]\d|[01]\d\d|\d?\d)(?(\.?\d)\.)){4}$")
Return regex.IsMatch(ip)
End Function
For testing whether the user input is either a domain name or IP address
we create two functions that use regular expressions. They test whether
the data matches the expression. They both return boolean values of either
True or False.
Private Shared Function GetInfoServer(ByVal queryTxt As String) As String
Dim regex As New RegularExpressions.Regex("Whois Server:\s+(.+)", RegularExpressions.RegexOptions.IgnoreCase)
Dim match As RegularExpressions.Match = regex.Match(queryTxt)
If (match.Value <> "") Then
Return match.Value.Substring(14)
Else
Return ""
End If
End Function
GetInfoServer also uses regular expressions to see if the domain's registrar
whois server is listed. If it is listed we get the expression text and
take the substring after "Whois Server: " which will be the
server name and return it. If it is not found we return a null string.
Finally we will look at the tcp/ip sockets code portion.
Private Function doWhoisQuery(ByVal domain As String, ByVal server As String) As String
Dim returnData As String = ""
Dim tcpClient As New TcpClient()
tcpClient.Connect(server, 43)
Dim networkStream As NetworkStream = tcpClient.GetStream()
If networkStream.CanWrite And networkStream.CanRead Then
Dim sendBytes As [Byte]() = Encoding.ASCII.GetBytes(domain + vbCrLf)
networkStream.Write(sendBytes, 0, sendBytes.Length)
Dim bytes(tcpClient.ReceiveBufferSize) As Byte
Dim recvSize As Int32
recvSize = networkStream.Read(bytes, 0, CInt(tcpClient.ReceiveBufferSize))
While (recvSize <> 0)
returnData += Encoding.ASCII.GetString(bytes, 0, recvSize)
recvSize = networkStream.Read(bytes, 0, CInt(tcpClient.ReceiveBufferSize))
End While
Else
If Not networkStream.CanWrite Then
returnData = "Cannot write data to this stream."
Else
If Not networkStream.CanRead Then
returnData = "Cannot read data from this stream."
End If
End If
End If
tcpClient.Close()
Return returnData
End Function
doWhoisQuery accepts the domain name and the whois server to query as
parameters. The results of the query are returned as a string. The first
thing we do is create a new TcpClient object and connect to the whois
server on port 43. If the connection is successful the TcpClient object
creates a new NetworkStream which we get access to using with the GetStream
method. With this stream we can send as well as receive data on our connection.
The data must be sent/received in the form of a byte array. We convert
the domain name followed by a newline into an array of bytes using Encoding.ASCII.GetBytes.
We then send these bytes using the NetworkStream's Write method. Now we
wait for the whois server sends us a response (if any). We enter a loop
and continue to read the bytes received from the server, convert them
back into an ASCII string, and append them to the returnData string variable.
Once we have finished reading all the data we close the connection and
return the data string.
I have found VB.NET much more friendly in the socket area (as well as
others) than prior versions of VB that used the Winsock control. With
the old VB if you wanted anything extra you most likely had to use COM
objects. But now with the .NET Framework you have everything at your disposal.
Next on my list is to write a console version of this program and a C#
port. Stay tuned for this page to update with that source code.
|
This page has been viewed 12,535 times |
|