whois client was using the first whois server in list rather than the whois server associated with the domain we are querying issue #74
authorRichard Penman
Tue, 08 Sep 2015 11:09:02 +0800
changeset 62 fc06c601b875
parent 60 7801a420f679
child 63 56499470d942
whois client was using the first whois server in list rather than the whois server associated with the domain we are querying issue #74
setup.py
whois/whois.py
--- a/setup.py	Sat Sep 05 23:01:44 2015 +0800
+++ b/setup.py	Tue Sep 08 11:09:02 2015 +0800
@@ -1,7 +1,7 @@
 import sys, os
 import setuptools
 
-version = '0.4'
+version = '0.5'
 
 setuptools.setup(
     name='python-whois',
--- a/whois/whois.py	Sat Sep 05 23:01:44 2015 +0800
+++ b/whois/whois.py	Tue Sep 08 11:09:02 2015 +0800
@@ -23,8 +23,8 @@
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
-
 """
+import re
 import sys
 import socket
 import optparse
@@ -62,8 +62,6 @@
     IANAHOST = "whois.iana.org"
     DENICHOST = "de.whois-servers.net"
     DEFAULT_PORT = "nicname"
-    WHOIS_SERVER_ID = "Whois Server:"
-    WHOIS_ORG_SERVER_ID = "Registrant Street1:Whois Server:"
 
     WHOIS_RECURSE = 0x01
     WHOIS_QUICK = 0x02
@@ -73,29 +71,21 @@
     def __init__(self):
         self.use_qnichost = False
 
-    def findwhois_server(self, buf, hostname):
+    def findwhois_server(self, buf, hostname, query):
         """Search the initial TLD lookup results for the regional-specifc
         whois server for getting contact details.
         """
         nhost = None
-        parts_index = 1
-        start = buf.find(NICClient.WHOIS_SERVER_ID)
-        if (start == -1):
-            start = buf.find(NICClient.WHOIS_ORG_SERVER_ID)
-            parts_index = 2
-
-        if (start > -1):
-            end = buf[start:].find('\n')
-            whois_line = buf[start:end+start]
-            nhost = whois_line.split(NICClient.WHOIS_SERVER_ID+' ').pop()
-            nhost = nhost.split('http://').pop()
+        match = re.compile('Domain Name: ' + query + '\s*.*?Whois Server: (.*?)\s', flags=re.IGNORECASE|re.DOTALL).search(buf)
+        if match:
+            nhost = match.groups()[0]
             # if the whois address is domain.tld/something then
             # s.connect((hostname, 43)) does not work
             if nhost.count('/') > 0:
                 nhost = None
-        elif (hostname == NICClient.ANICHOST):
+        elif hostname == NICClient.ANICHOST:
             for nichost in NICClient.ip_whois:
-                if (buf.find(nichost) != -1):
+                if buf.find(nichost) != -1:
                     nhost = nichost
                     break
         return nhost
@@ -107,38 +97,36 @@
         there for contact details
         """
         try:
-          s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-          s.settimeout(2)
-          s.connect((hostname, 43))
-          """send takes bytes as an input
-          """
-          queryBytes = None
-          if type(query) is not unicode:
-              query = query.decode('utf-8')
+            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+            s.settimeout(10)
+            s.connect((hostname, 43))
+            # end takes bytes as an input
+            queryBytes = None
+            if type(query) is not unicode:
+                query = query.decode('utf-8')
 
-          if hostname == NICClient.DENICHOST:
-              queryBytes = ("-T dn,ace -C UTF-8 " + query + "\r\n").encode('idna')
-          elif hostname == 'com.whois-servers.net':
-              queryBytes = ('=' + query + "\r\n").encode('idna')
-          else:
-              queryBytes = (query + "\r\n").encode('idna')
-          s.send(queryBytes)
-          """recv returns bytes
-          """
-          response = b''
-          while True:
-              d = s.recv(4096)
-              response += d
-              if not d:
-                  break
-          s.close()
+            if hostname == NICClient.DENICHOST:
+                queryBytes = "-T dn,ace -C UTF-8 " + query
+            elif hostname.endswith(NICClient.QNICHOST_TAIL):
+                queryBytes = '=' + query
+            else:
+                queryBytes = query
+            s.send((queryBytes + "\r\n").encode('idna'))
+            # recv returns bytes
+            response = b''
+            while True:
+                d = s.recv(4096)
+                response += d
+                if not d:
+                    break
+            s.close()
         except socket.error as socketerror:
-          print "Error: ", socketerror
+            print 'Error: ', socketerror
         nhost = None
         response = enforce_ascii(response)
-        if (flags & NICClient.WHOIS_RECURSE and nhost is None):
-            nhost = self.findwhois_server(response.decode(), hostname)
-        if (nhost is not None):
+        if flags & NICClient.WHOIS_RECURSE and nhost is None:
+            nhost = self.findwhois_server(response.decode(), hostname, query)
+        if nhost is not None:
             response += self.whois(query, nhost, 0)
         return response.decode()
 
@@ -146,15 +134,14 @@
         """Choose initial lookup NIC host"""
         if type(domain) is not unicode:
             domain = domain.decode('utf-8').encode('idna')
-        if (domain.endswith("-NORID")):
+        if domain.endswith("-NORID"):
             return NICClient.NORIDHOST
         pos = domain.rfind('.')
-        if (pos == -1):
+        if pos == -1:
             return None
         tld = domain[pos+1:]
-        if (tld[0].isdigit()):
+        if tld[0].isdigit():
             return NICClient.ANICHOST
-
         return tld + NICClient.QNICHOST_TAIL
 
     def whois_lookup(self, options, query_arg, flags):
@@ -167,11 +154,11 @@
         if options is None:
             options = {}
 
-        if (('whoishost' not in options or options['whoishost'] is None)
-                and ('country' not in options or options['country'] is None)):
+        if ('whoishost' not in options or options['whoishost'] is None) \
+                and ('country' not in options or options['country'] is None):
             self.use_qnichost = True
             options['whoishost'] = NICClient.NICHOST
-            if (not (flags & NICClient.WHOIS_QUICK)):
+            if not (flags & NICClient.WHOIS_QUICK):
                 flags |= NICClient.WHOIS_RECURSE
 
         if 'country' in options and options['country'] is not None:
@@ -182,7 +169,7 @@
             )
         elif self.use_qnichost:
             nichost = self.choose_server(query_arg)
-            if (nichost is not None):
+            if nichost is not None:
                 result = self.whois(query_arg, nichost, flags)
             else:
                 result = ''
@@ -252,10 +239,11 @@
 
     return parser.parse_args(argv)
 
+
 if __name__ == "__main__":
     flags = 0
     nic_client = NICClient()
-    (options, args) = parse_command_line(sys.argv)
-    if (options.b_quicklookup is True):
+    options, args = parse_command_line(sys.argv)
+    if options.b_quicklookup:
         flags = flags | NICClient.WHOIS_QUICK
     print nic_client.whois_lookup(options.__dict__, args[1], flags)