home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pyth_os2.zip / python-1.0.2 / Lib / gopherlib.py < prev    next >
Text File  |  1994-02-21  |  4KB  |  196 lines

  1. # Gopher protocol client interface
  2.  
  3. import string
  4.  
  5. # Default selector, host and port
  6. DEF_SELECTOR = '1/'
  7. DEF_HOST     = 'gopher.micro.umn.edu'
  8. DEF_PORT     = 70
  9.  
  10. # Recognized file types
  11. A_TEXT       = '0'
  12. A_MENU       = '1'
  13. A_CSO        = '2'
  14. A_ERROR      = '3'
  15. A_MACBINHEX  = '4'
  16. A_PCBINHEX   = '5'
  17. A_UUENCODED  = '6'
  18. A_INDEX      = '7'
  19. A_TELNET     = '8'
  20. A_BINARY     = '9'
  21. A_DUPLICATE  = '+'
  22. A_SOUND      = 's'
  23. A_EVENT      = 'e'
  24. A_CALENDAR   = 'c'
  25. A_HTML       = 'h'
  26. A_TN3270     = 'T'
  27. A_MIME       = 'M'
  28. A_IMAGE      = 'I'
  29. A_WHOIS      = 'w'
  30. A_QUERY      = 'q'
  31. A_GIF        = 'g'
  32. A_HTML       = 'h'            # HTML file
  33. A_WWW        = 'w'            # WWW address
  34. A_PLUS_IMAGE = ':'
  35. A_PLUS_MOVIE = ';'
  36. A_PLUS_SOUND = '<'
  37.  
  38.  
  39. # Function mapping all file types to strings; unknown types become TYPE='x'
  40. _names = dir()
  41. _type_to_name_map = None
  42. def type_to_name(gtype):
  43.     global _type_to_name_map
  44.     if not _type_to_name_map:
  45.         for name in _names:
  46.             if name[:2] == 'A_':
  47.                 _type_to_name_map[eval(name)] = name[2:]
  48.     if _type_to_name_map.has_key(gtype):
  49.         return _type_to_name_map[gtype]
  50.     return 'TYPE=' + `gtype`
  51.  
  52. # Names for characters and strings
  53. CRLF = '\r\n'
  54. TAB = '\t'
  55.  
  56. # Send a selector to a given host and port, return a file with the reply
  57. def send_selector(selector, host, *args):
  58.     import socket
  59.     import string
  60.     if args:
  61.         if args[1:]: raise TypeError, 'too many args'
  62.         port = args[0]
  63.     else:
  64.         port = None
  65.         i = string.find(host, ':')
  66.         if i >= 0:
  67.             host, port = host[:i], string.atoi(host[i+1:])
  68.     if not port:
  69.         port = DEF_PORT
  70.     elif type(port) == type(''):
  71.         port = string.atoi(port)
  72.     s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  73.     s.connect(host, port)
  74.     s.send(selector + CRLF)
  75.     s.shutdown(1)
  76.     return s.makefile('r')
  77.  
  78. # Send a selector and a query string
  79. def send_query(selector, query, host, *args):
  80.     return apply(send_selector, (selector + '\t' + query, host) + args)
  81.  
  82. # The following functions interpret the data returned by the gopher
  83. # server according to the expected type, e.g. textfile or directory
  84.  
  85. # Get a directory in the form of a list of entries
  86. def get_directory(f):
  87.     import string
  88.     list = []
  89.     while 1:
  90.         line = f.readline()
  91.         if not line:
  92.             print '(Unexpected EOF from server)'
  93.             break
  94.         if line[-2:] == CRLF:
  95.             line = line[:-2]
  96.         elif line[-1:] in CRLF:
  97.             line = line[:-1]
  98.         if line == '.':
  99.             break
  100.         if not line:
  101.             print '(Empty line from server)'
  102.             continue
  103.         gtype = line[0]
  104.         parts = string.splitfields(line[1:], TAB)
  105.         if len(parts) < 4:
  106.             print '(Bad line from server:', `line`, ')'
  107.             continue
  108.         if len(parts) > 4:
  109.             if parts[4:] != ['+']:
  110.                 print '(Extra info from server:', parts[4:], ')'
  111.         else:
  112.             parts.append('')
  113.         parts.insert(0, gtype)
  114.         list.append(parts)
  115.     return list
  116.  
  117. # Get a text file as a list of lines, with trailing CRLF stripped
  118. def get_textfile(f):
  119.     list = []
  120.     get_alt_textfile(f, list.append)
  121.     return list
  122.  
  123. # Get a text file and pass each line to a function, with trailing CRLF stripped
  124. def get_alt_textfile(f, func):
  125.     while 1:
  126.         line = f.readline()
  127.         if not line:
  128.             print '(Unexpected EOF from server)'
  129.             break
  130.         if line[-2:] == CRLF:
  131.             line = line[:-2]
  132.         elif line[-1:] in CRLF:
  133.             line = line[:-1]
  134.         if line == '.':
  135.             break
  136.         if line[:2] == '..':
  137.             line = line[1:]
  138.         func(line)
  139.  
  140. # Get a binary file as one solid data block
  141. def get_binary(f):
  142.     data = f.read()
  143.     return data
  144.  
  145. # Get a binary file and pass each block to a function
  146. def get_alt_binary(f, func, blocksize):
  147.     while 1:
  148.         data = f.read(blocksize)
  149.         if not data:
  150.             break
  151.         func(data)
  152.  
  153. # Trivial test program
  154. def test():
  155.     import sys
  156.     import getopt
  157.     opts, args = getopt.getopt(sys.argv[1:], '')
  158.     selector = DEF_SELECTOR
  159.     type = selector[0]
  160.     host = DEF_HOST
  161.     port = DEF_PORT
  162.     if args:
  163.         host = args[0]
  164.         args = args[1:]
  165.     if args:
  166.         type = args[0]
  167.         args = args[1:]
  168.         if len(type) > 1:
  169.             type, selector = type[0], type
  170.         else:
  171.             selector = ''
  172.             if args:
  173.                 selector = args[0]
  174.                 args = args[1:]
  175.         query = ''
  176.         if args:
  177.             query = args[0]
  178.             args = args[1:]
  179.     if type == A_INDEX:
  180.         f = send_query(selector, query, host)
  181.     else:
  182.         f = send_selector(selector, host)
  183.     if type == A_TEXT:
  184.         list = get_textfile(f)
  185.         for item in list: print item
  186.     elif type in (A_MENU, A_INDEX):
  187.         list = get_directory(f)
  188.         for item in list: print item
  189.     else:
  190.         data = get_binary(f)
  191.         print 'binary data:', len(data), 'bytes:', `data[:100]`[:40]
  192.  
  193. # Run the test when run as script
  194. if __name__ == '__main__':
  195.     test()
  196.