home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pytho152.zip / emx / lib / python1.5 / gopherlib.py < prev    next >
Text File  |  2000-08-10  |  5KB  |  209 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 = {}
  42. def type_to_name(gtype):
  43.     global _type_to_name_map
  44.     if _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, port = 0):
  58.     import socket
  59.     import string
  60.     if not port:
  61.         i = string.find(host, ':')
  62.         if i >= 0:
  63.             host, port = host[:i], string.atoi(host[i+1:])
  64.     if not port:
  65.         port = DEF_PORT
  66.     elif type(port) == type(''):
  67.         port = string.atoi(port)
  68.     s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  69.     s.connect(host, port)
  70.     s.send(selector + CRLF)
  71.     s.shutdown(1)
  72.     return s.makefile('rb')
  73.  
  74. # Send a selector and a query string
  75. def send_query(selector, query, host, port = 0):
  76.     return send_selector(selector + '\t' + query, host, port)
  77.  
  78. # Takes a path as returned by urlparse and returns the appropriate selector
  79. def path_to_selector(path):
  80.     if path=="/":
  81.         return "/"
  82.     else:
  83.         return path[2:] # Cuts initial slash and data type identifier
  84.  
  85. # Takes a path as returned by urlparse and maps it to a string
  86. # See section 3.4 of RFC 1738 for details
  87. def path_to_datatype_name(path):
  88.     if path=="/":
  89.         # No way to tell, although "INDEX" is likely
  90.         return "TYPE='unknown'"
  91.     else:
  92.         return type_to_name(path[1])
  93.  
  94. # The following functions interpret the data returned by the gopher
  95. # server according to the expected type, e.g. textfile or directory
  96.  
  97. # Get a directory in the form of a list of entries
  98. def get_directory(f):
  99.     import string
  100.     list = []
  101.     while 1:
  102.         line = f.readline()
  103.         if not line:
  104.             print '(Unexpected EOF from server)'
  105.             break
  106.         if line[-2:] == CRLF:
  107.             line = line[:-2]
  108.         elif line[-1:] in CRLF:
  109.             line = line[:-1]
  110.         if line == '.':
  111.             break
  112.         if not line:
  113.             print '(Empty line from server)'
  114.             continue
  115.         gtype = line[0]
  116.         parts = string.splitfields(line[1:], TAB)
  117.         if len(parts) < 4:
  118.             print '(Bad line from server:', `line`, ')'
  119.             continue
  120.         if len(parts) > 4:
  121.             if parts[4:] != ['+']:
  122.                 print '(Extra info from server:',
  123.                 print parts[4:], ')'
  124.         else:
  125.             parts.append('')
  126.         parts.insert(0, gtype)
  127.         list.append(parts)
  128.     return list
  129.  
  130. # Get a text file as a list of lines, with trailing CRLF stripped
  131. def get_textfile(f):
  132.     list = []
  133.     get_alt_textfile(f, list.append)
  134.     return list
  135.  
  136. # Get a text file and pass each line to a function, with trailing CRLF stripped
  137. def get_alt_textfile(f, func):
  138.     while 1:
  139.         line = f.readline()
  140.         if not line:
  141.             print '(Unexpected EOF from server)'
  142.             break
  143.         if line[-2:] == CRLF:
  144.             line = line[:-2]
  145.         elif line[-1:] in CRLF:
  146.             line = line[:-1]
  147.         if line == '.':
  148.             break
  149.         if line[:2] == '..':
  150.             line = line[1:]
  151.         func(line)
  152.  
  153. # Get a binary file as one solid data block
  154. def get_binary(f):
  155.     data = f.read()
  156.     return data
  157.  
  158. # Get a binary file and pass each block to a function
  159. def get_alt_binary(f, func, blocksize):
  160.     while 1:
  161.         data = f.read(blocksize)
  162.         if not data:
  163.             break
  164.         func(data)
  165.  
  166. # Trivial test program
  167. def test():
  168.     import sys
  169.     import getopt
  170.     opts, args = getopt.getopt(sys.argv[1:], '')
  171.     selector = DEF_SELECTOR
  172.     type = selector[0]
  173.     host = DEF_HOST
  174.     port = DEF_PORT
  175.     if args:
  176.         host = args[0]
  177.         args = args[1:]
  178.     if args:
  179.         type = args[0]
  180.         args = args[1:]
  181.         if len(type) > 1:
  182.             type, selector = type[0], type
  183.         else:
  184.             selector = ''
  185.             if args:
  186.                 selector = args[0]
  187.                 args = args[1:]
  188.         query = ''
  189.         if args:
  190.             query = args[0]
  191.             args = args[1:]
  192.     if type == A_INDEX:
  193.         f = send_query(selector, query, host)
  194.     else:
  195.         f = send_selector(selector, host)
  196.     if type == A_TEXT:
  197.         list = get_textfile(f)
  198.         for item in list: print item
  199.     elif type in (A_MENU, A_INDEX):
  200.         list = get_directory(f)
  201.         for item in list: print item
  202.     else:
  203.         data = get_binary(f)
  204.         print 'binary data:', len(data), 'bytes:', `data[:100]`[:40]
  205.  
  206. # Run the test when run as script
  207. if __name__ == '__main__':
  208.     test()
  209.