whois/whois.py
changeset 62 fc06c601b875
parent 60 7801a420f679
child 64 2ed54e885571
equal deleted inserted replaced
60:7801a420f679 62:fc06c601b875
    21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    25 THE SOFTWARE.
    25 THE SOFTWARE.
    26 
       
    27 """
    26 """
       
    27 import re
    28 import sys
    28 import sys
    29 import socket
    29 import socket
    30 import optparse
    30 import optparse
    31 
    31 
    32 
    32 
    60     BNICHOST = "whois.registro.br"
    60     BNICHOST = "whois.registro.br"
    61     NORIDHOST = "whois.norid.no"
    61     NORIDHOST = "whois.norid.no"
    62     IANAHOST = "whois.iana.org"
    62     IANAHOST = "whois.iana.org"
    63     DENICHOST = "de.whois-servers.net"
    63     DENICHOST = "de.whois-servers.net"
    64     DEFAULT_PORT = "nicname"
    64     DEFAULT_PORT = "nicname"
    65     WHOIS_SERVER_ID = "Whois Server:"
       
    66     WHOIS_ORG_SERVER_ID = "Registrant Street1:Whois Server:"
       
    67 
    65 
    68     WHOIS_RECURSE = 0x01
    66     WHOIS_RECURSE = 0x01
    69     WHOIS_QUICK = 0x02
    67     WHOIS_QUICK = 0x02
    70 
    68 
    71     ip_whois = [LNICHOST, RNICHOST, PNICHOST, BNICHOST]
    69     ip_whois = [LNICHOST, RNICHOST, PNICHOST, BNICHOST]
    72 
    70 
    73     def __init__(self):
    71     def __init__(self):
    74         self.use_qnichost = False
    72         self.use_qnichost = False
    75 
    73 
    76     def findwhois_server(self, buf, hostname):
    74     def findwhois_server(self, buf, hostname, query):
    77         """Search the initial TLD lookup results for the regional-specifc
    75         """Search the initial TLD lookup results for the regional-specifc
    78         whois server for getting contact details.
    76         whois server for getting contact details.
    79         """
    77         """
    80         nhost = None
    78         nhost = None
    81         parts_index = 1
    79         match = re.compile('Domain Name: ' + query + '\s*.*?Whois Server: (.*?)\s', flags=re.IGNORECASE|re.DOTALL).search(buf)
    82         start = buf.find(NICClient.WHOIS_SERVER_ID)
    80         if match:
    83         if (start == -1):
    81             nhost = match.groups()[0]
    84             start = buf.find(NICClient.WHOIS_ORG_SERVER_ID)
       
    85             parts_index = 2
       
    86 
       
    87         if (start > -1):
       
    88             end = buf[start:].find('\n')
       
    89             whois_line = buf[start:end+start]
       
    90             nhost = whois_line.split(NICClient.WHOIS_SERVER_ID+' ').pop()
       
    91             nhost = nhost.split('http://').pop()
       
    92             # if the whois address is domain.tld/something then
    82             # if the whois address is domain.tld/something then
    93             # s.connect((hostname, 43)) does not work
    83             # s.connect((hostname, 43)) does not work
    94             if nhost.count('/') > 0:
    84             if nhost.count('/') > 0:
    95                 nhost = None
    85                 nhost = None
    96         elif (hostname == NICClient.ANICHOST):
    86         elif hostname == NICClient.ANICHOST:
    97             for nichost in NICClient.ip_whois:
    87             for nichost in NICClient.ip_whois:
    98                 if (buf.find(nichost) != -1):
    88                 if buf.find(nichost) != -1:
    99                     nhost = nichost
    89                     nhost = nichost
   100                     break
    90                     break
   101         return nhost
    91         return nhost
   102 
    92 
   103     def whois(self, query, hostname, flags):
    93     def whois(self, query, hostname, flags):
   105         then, if the quick flag is false, search that result
    95         then, if the quick flag is false, search that result
   106         for the region-specifc whois server and do a lookup
    96         for the region-specifc whois server and do a lookup
   107         there for contact details
    97         there for contact details
   108         """
    98         """
   109         try:
    99         try:
   110           s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   100             s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   111           s.settimeout(2)
   101             s.settimeout(10)
   112           s.connect((hostname, 43))
   102             s.connect((hostname, 43))
   113           """send takes bytes as an input
   103             # end takes bytes as an input
   114           """
   104             queryBytes = None
   115           queryBytes = None
   105             if type(query) is not unicode:
   116           if type(query) is not unicode:
   106                 query = query.decode('utf-8')
   117               query = query.decode('utf-8')
   107 
   118 
   108             if hostname == NICClient.DENICHOST:
   119           if hostname == NICClient.DENICHOST:
   109                 queryBytes = "-T dn,ace -C UTF-8 " + query
   120               queryBytes = ("-T dn,ace -C UTF-8 " + query + "\r\n").encode('idna')
   110             elif hostname.endswith(NICClient.QNICHOST_TAIL):
   121           elif hostname == 'com.whois-servers.net':
   111                 queryBytes = '=' + query
   122               queryBytes = ('=' + query + "\r\n").encode('idna')
   112             else:
   123           else:
   113                 queryBytes = query
   124               queryBytes = (query + "\r\n").encode('idna')
   114             s.send((queryBytes + "\r\n").encode('idna'))
   125           s.send(queryBytes)
   115             # recv returns bytes
   126           """recv returns bytes
   116             response = b''
   127           """
   117             while True:
   128           response = b''
   118                 d = s.recv(4096)
   129           while True:
   119                 response += d
   130               d = s.recv(4096)
   120                 if not d:
   131               response += d
   121                     break
   132               if not d:
   122             s.close()
   133                   break
       
   134           s.close()
       
   135         except socket.error as socketerror:
   123         except socket.error as socketerror:
   136           print "Error: ", socketerror
   124             print 'Error: ', socketerror
   137         nhost = None
   125         nhost = None
   138         response = enforce_ascii(response)
   126         response = enforce_ascii(response)
   139         if (flags & NICClient.WHOIS_RECURSE and nhost is None):
   127         if flags & NICClient.WHOIS_RECURSE and nhost is None:
   140             nhost = self.findwhois_server(response.decode(), hostname)
   128             nhost = self.findwhois_server(response.decode(), hostname, query)
   141         if (nhost is not None):
   129         if nhost is not None:
   142             response += self.whois(query, nhost, 0)
   130             response += self.whois(query, nhost, 0)
   143         return response.decode()
   131         return response.decode()
   144 
   132 
   145     def choose_server(self, domain):
   133     def choose_server(self, domain):
   146         """Choose initial lookup NIC host"""
   134         """Choose initial lookup NIC host"""
   147         if type(domain) is not unicode:
   135         if type(domain) is not unicode:
   148             domain = domain.decode('utf-8').encode('idna')
   136             domain = domain.decode('utf-8').encode('idna')
   149         if (domain.endswith("-NORID")):
   137         if domain.endswith("-NORID"):
   150             return NICClient.NORIDHOST
   138             return NICClient.NORIDHOST
   151         pos = domain.rfind('.')
   139         pos = domain.rfind('.')
   152         if (pos == -1):
   140         if pos == -1:
   153             return None
   141             return None
   154         tld = domain[pos+1:]
   142         tld = domain[pos+1:]
   155         if (tld[0].isdigit()):
   143         if tld[0].isdigit():
   156             return NICClient.ANICHOST
   144             return NICClient.ANICHOST
   157 
       
   158         return tld + NICClient.QNICHOST_TAIL
   145         return tld + NICClient.QNICHOST_TAIL
   159 
   146 
   160     def whois_lookup(self, options, query_arg, flags):
   147     def whois_lookup(self, options, query_arg, flags):
   161         """Main entry point: Perform initial lookup on TLD whois server,
   148         """Main entry point: Perform initial lookup on TLD whois server,
   162         or other server to get region-specific whois server, then if quick
   149         or other server to get region-specific whois server, then if quick
   165         nichost = None
   152         nichost = None
   166         # whoud happen when this function is called by other than main
   153         # whoud happen when this function is called by other than main
   167         if options is None:
   154         if options is None:
   168             options = {}
   155             options = {}
   169 
   156 
   170         if (('whoishost' not in options or options['whoishost'] is None)
   157         if ('whoishost' not in options or options['whoishost'] is None) \
   171                 and ('country' not in options or options['country'] is None)):
   158                 and ('country' not in options or options['country'] is None):
   172             self.use_qnichost = True
   159             self.use_qnichost = True
   173             options['whoishost'] = NICClient.NICHOST
   160             options['whoishost'] = NICClient.NICHOST
   174             if (not (flags & NICClient.WHOIS_QUICK)):
   161             if not (flags & NICClient.WHOIS_QUICK):
   175                 flags |= NICClient.WHOIS_RECURSE
   162                 flags |= NICClient.WHOIS_RECURSE
   176 
   163 
   177         if 'country' in options and options['country'] is not None:
   164         if 'country' in options and options['country'] is not None:
   178             result = self.whois(
   165             result = self.whois(
   179                 query_arg,
   166                 query_arg,
   180                 options['country'] + NICClient.QNICHOST_TAIL,
   167                 options['country'] + NICClient.QNICHOST_TAIL,
   181                 flags
   168                 flags
   182             )
   169             )
   183         elif self.use_qnichost:
   170         elif self.use_qnichost:
   184             nichost = self.choose_server(query_arg)
   171             nichost = self.choose_server(query_arg)
   185             if (nichost is not None):
   172             if nichost is not None:
   186                 result = self.whois(query_arg, nichost, flags)
   173                 result = self.whois(query_arg, nichost, flags)
   187             else:
   174             else:
   188                 result = ''
   175                 result = ''
   189         else:
   176         else:
   190             result = self.whois(query_arg, options['whoishost'], flags)
   177             result = self.whois(query_arg, options['whoishost'], flags)
   250                       help="Lookup using host " + NICClient.SNICHOST)
   237                       help="Lookup using host " + NICClient.SNICHOST)
   251     parser.add_option("-?", "--help", action="help")
   238     parser.add_option("-?", "--help", action="help")
   252 
   239 
   253     return parser.parse_args(argv)
   240     return parser.parse_args(argv)
   254 
   241 
       
   242 
   255 if __name__ == "__main__":
   243 if __name__ == "__main__":
   256     flags = 0
   244     flags = 0
   257     nic_client = NICClient()
   245     nic_client = NICClient()
   258     (options, args) = parse_command_line(sys.argv)
   246     options, args = parse_command_line(sys.argv)
   259     if (options.b_quicklookup is True):
   247     if options.b_quicklookup:
   260         flags = flags | NICClient.WHOIS_QUICK
   248         flags = flags | NICClient.WHOIS_QUICK
   261     print nic_client.whois_lookup(options.__dict__, args[1], flags)
   249     print nic_client.whois_lookup(options.__dict__, args[1], flags)